Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[로또] 남소은 과제 제출합니다. #630

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
18 changes: 18 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## 기능 구현 목록
---

1. 로또 게임
- [ ] 로또 금액을 입력하면 그에 해당하는 로또를 발행하기
- [ ] 당첨 번호와 보너스 번호 입력 받기
- [ ] 로또 번호를 오름차순으로 정렬
- [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하기
- [ ] 당첨 내역과 수익률을 출력하기


2. 예외 처리
- [ ] 입력한 로또 금액이 천원 단위인지 확인
- [ ] 입력한 로또 금액이 숫자인지 확인
- [ ] 입력 받은 당첨 번호가 쉼표로 구분되는지 확인
- [ ] 입력 번호의 로또 범위가 1~45 사이인지 확인
- [ ] 로또 번호를 발행할 때, 중복되는지 확인
- [ ] 보너스 번호가 6개의 로또 번호와 중복되는지 확인
18 changes: 17 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
import LottoController from "./Controller/LottoController";
import { Console } from "@woowacourse/mission-utils";

class App {
async play() {}
#lotto;
constructor() {
this.#lotto = new LottoController();
}

async play() {
try {
await this.#lotto.LottoStart();
} catch(error) {
Console.print(error.message);
}

}

}

export default App;
20 changes: 20 additions & 0 deletions src/Constant/ErrorMessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const ERROR_MESSAGE = Object.freeze({
PURCHASE_AMOUNT_NUMBER: "[ERROR] 구입 금액은 숫자만 입력 가능합니다.",
PURCHASE_AMOUNT_UNDER:
"[ERROR] 구입 금액은 1000원 이상부터 로또 구입이 구입 가능합니다.",
PURCHASE_AMOUNT_UNIT:
"[ERROR] 구입 금액은 1000원 단위로 로또를 구입해야 합니다.",
PURCHASE_AMOUNT_ZERO: "[ERROR] 구입 금액은 0원이 될 수 없습니다.",

LOTTO_NUMBER: "[ERROR] 로또 번호는 숫자로만 구성되어야 합니다.",
LOTTO_DUPLICATE: "[ERROR] 로또 번호는 서로 중복될 수 없습니다.",
LOTTO_COUNT: "[ERROR] 로또 번호는 6개로 구성되어야 합니다.",
LOTTO_RANGE: "[ERROR] 로또 번호는 1과 45 사이의 값이어야 합니다",

WINNING_NUMBER: "[ERROR] 당첨 번호는 숫자만 입력 가능합니다.",
WINNING_DUPLICATE: "[ERROR] 당첨 번호는 서로 중복될 수 없습니다.",
WINNING_COUNT: "[ERROR] 당첨 번호는 6개로 구성되어야 합니다.",
WINNING_RANGE: "[ERROR] 당첨 번호는 1과 45 사이의 값이어야 합니다.",
});

export default ERROR_MESSAGE;
8 changes: 8 additions & 0 deletions src/Constant/PrintMessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const PRINT_MESSAGE = Object.freeze({
REQUEST_PURCHASE_AMOUNT: "구입금액을 입력해 주세요.\n",
LOTTO_COUNT: "개를 구매했습니다.",
REQUEST_WINNING_NUMBERS: "\n당첨 번호를 입력해 주세요.\n",
REQUEST_BONUS_NUMBER: "\n보너스 번호를 입력해 주세요.\n",
});

export default PRINT_MESSAGE;
8 changes: 8 additions & 0 deletions src/Constant/StaticNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const STATIC_NUMBER = Object.freeze({
PURCHASE_AMOUNT_SPLIT: 1_000,
LOTTO_START_NUMBER: 1,
LOTTO_END_NUMBER: 45,
LOTTO_COUNT: 6,
});

export default STATIC_NUMBER;
49 changes: 49 additions & 0 deletions src/Controller/LottoController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Console } from "@woowacourse/mission-utils";
import Input from "../Input/Input";
import LottoCount from "../Main/LottoCount";
import Output from "../Output/Output";
import Lottos from "../Main/Lottos";
import WinningNumber from "../Main/WinningNumber";
import BonusNumber from "../domain/BonusNumber";

class LottoController {
#lottoCount;
#lottos;
#winningNumber;

constructor() {}

async LottoStart() {
await this.getLottoPrice();
}

async getLottoPrice() {
const LOTTO_PRICE = await Input.lottoPrice();
await this.getLottoCount(LOTTO_PRICE);
}

async getLottoCount(input) {
this.#lottoCount = new LottoCount(input);

Output.printLottoCount(this.#lottoCount.getLottoCount());

this.#lottos = new Lottos(this.#lottoCount.getLottoCount());
Output.printLottos(this.#lottos.getLottos());

await this.requestWinningNumber();
}

async requestWinningNumber() {
const winningNumber = await Input.lottoWinningNumber();
this.#winningNumber = new WinningNumber(winningNumber);
Console.print(this.#winningNumber.getWinningNumber());
}

async requestBonusNumber() {
const bonusNumber = await Input.lottoBonusNumber();
this.#winningNumber = new BonusNumber(bonusNumber);
Console.print(this.#winningNumber.getBonusNumber());
}
}

export default LottoController;
30 changes: 30 additions & 0 deletions src/Input/Input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Console } from "@woowacourse/mission-utils";
import PRINT_MESSAGE from "../Constant/PrintMessage";

const Input = {
async lottoPrice() {
const purchaseAmount = await Console.readLineAsync(
PRINT_MESSAGE.REQUEST_PURCHASE_AMOUNT
);

Validator.InputPurchaseAmount(purchaseAmount);
return purchaseAmount;
},

async lottoWinningNumber() {
const winningNumber = await Console.readLineAsync(
PRINT_MESSAGE.REQUEST_WINNING_NUMBERS
);
Validator.InputWinningNumber(winningNumber);
return winningNumber;
},

async lottoBonusNumber(winningNumber) {
const bonusNumber = await Console.readLineAsync(
PRINT_MESSAGE.REQUEST_BONUS_NUMBER
);
return bonusNumber;
},
};

export default Input;
18 changes: 0 additions & 18 deletions src/Lotto.js

This file was deleted.

13 changes: 13 additions & 0 deletions src/Main/BonusNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class BonusNumber {
#bonusNumber;

constructor(bonusNumber) {
this.#bonusNumber = bonusNumber;
}

getBonusNumber() {
return this.#bonusNumber;
}
}

export default BonusNumber;
20 changes: 20 additions & 0 deletions src/Main/Lotto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Validator from "../utils/Validator";

class Lotto {
#numbers;

constructor(numbers) {
this.#validate(numbers);
this.#numbers = numbers.sort((a, b) => a - b);
}

#validate(numbers) {
Validator.lottoNumber(numbers);
}

getLotto() {
return this.#numbers;
}
}

export default Lotto;
15 changes: 15 additions & 0 deletions src/Main/LottoCount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import STATIC_NUMBER from "../Constant/StaticNumber";

class LottoCount {
#lottoCount;

constructor(inputPurchaseAmount) {
this.#lottoCount = Number(inputPurchaseAmount) / STATIC_NUMBER.PURCHASE_AMOUNT_SPLIT;
}

getLottoCount() {
return this.#lottoCount;
}
}

export default LottoCount;
21 changes: 21 additions & 0 deletions src/Main/Lottos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Lotto from "./Lotto";
import LottoRandomNumberGenerator from "../utils/LottoRandomNumberGenerator";

class Lottos {
#lottos = [];

/** 로또 번호 생성 **/
constructor(lottoCount) {
for (let i = 0; i < lottoCount; i += 1) {
this.#lottos.push(
new Lotto(LottoRandomNumberGenerator.generate()).getLotto()
);
}
}

getLottos() {
return this.#lottos;
}
}

export default Lottos;
13 changes: 13 additions & 0 deletions src/Main/WinningNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class WinningNumber {
#winningNumber;

constructor(winningNumber) {
this.#winningNumber = winningNumber.split(",");
}

getWinningNumber() {
return this.#winningNumber;
}
}

export default WinningNumber;
16 changes: 16 additions & 0 deletions src/Output/Output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Console } from "@woowacourse/mission-utils";
import PRINT_MESSAGE from "../Constant/PrintMessage";

const Output = {
printLottoCount(lottoCount) {
Console.print(`\n${lottoCount}${PRINT_MESSAGE.LOTTO_COUNT}`);
},

printLottos(lottos) {
for (let i = 0; i < lottos.length; i++) {
Console.print(`[${lottos[i].join(", ")}]`);
}
},
};

export default Output;
14 changes: 14 additions & 0 deletions src/utils/LottoRandomNumberGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Random } from "@woowacourse/mission-utils";
import STATIC_NUMBER from "../Constant/StaticNumber";

const LottoRandomNumberGenerator = {
generate() {
return Random.pickUniqueNumbersInRange(
STATIC_NUMBER.LOTTO_START_NUMBER,
STATIC_NUMBER.LOTTO_END_NUMBER,
STATIC_NUMBER.LOTTO_COUNT
);
},
};

export default LottoRandomNumberGenerator;
12 changes: 12 additions & 0 deletions src/utils/RangeTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import STATIC_NUMBER from "../Constant/StaticNumber";

function RangeTest(inputNumbers) {
return inputNumbers.some((number) => {
return (
number < STATIC_NUMBER.LOTTO_START_NUMBER ||
number > STATIC_NUMBER.LOTTO_END_NUMBER
);
});
}

export default RangeTest;
48 changes: 48 additions & 0 deletions src/utils/Validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import ERROR_MESSAGE from "../Constant/ErrorMessage";
import RangeTest from "./RangeTest";

const Validator = {
InputPurchaseAmount(purchaseAmount) {
if (purchaseAmount.replace(/\d/g, "").length > 0)
throw new Error(ERROR_MESSAGE.PURCHASE_AMOUNT_NUMBER);

if (purchaseAmount < 1000)
throw new Error(ERROR_MESSAGE.PURCHASE_AMOUNT_UNDER);

if (purchaseAmount % 1000 !== 0)
throw new Error(ERROR_MESSAGE.PURCHASE_AMOUNT_UNIT);

if (purchaseAmount.replace(/0/g, "").length === 0)
throw new Error(ERROR_MESSAGE.PURCHASE_AMOUNT_ZERO);

},

lottoNumber(numbers) {
const number = numbers.join("");
if (number.replace(/\d/g, "").length > 0)
throw new Error(ERROR_MESSAGE.LOTTO_NUMBER);
if (numbers.length !== new Set(numbers).size)
throw new Error(ERROR_MESSAGE.LOTTO_DUPLICATE);
if (numbers.length !== 6)
throw new Error(ERROR_MESSAGE.LOTTO_COUNT);
if (RangeTest(numbers))
throw new Error(ERROR_MESSAGE.LOTTO_RANGE);
},

InputWinningNumber(input) {
const inputWinninNumbers = input.split(",");
if (input.replace(/\d|\,/g, "").length > 0)
throw new Error(ERROR_MESSAGE.WINNING_NUMBER);

if (inputWinninNumbers.length !== new Set(inputWinninNumbers).size)
throw new Error(ERROR_MESSAGE.LOTTO_DUPLICATE);

if (inputWinninNumbers.length !== 6)
throw new Error(ERROR_MESSAGE.WINNING_COUNT);

if (RangeTest(inputWinninNumbers))
throw new Error(ERROR_MESSAGE.WINNING_RANGE);
},
};

export default Validator;