Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
# javascript-lotto-precourse

우아한 테크코스 3주차

## 기능 요구 사항

### 1. 사용자 입력

- [x] 로또 구입 금액을 입력받는다.
- [ ] 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
- [x] 당첨 번호를 쉼표(,)를 기준으로 구분하여 입력 받는다.
- [x] 보너스 번호를 입력 받는다.

### 2. 로또 실행

- [x] 로또 번호의 숫자 범위는 1~45까지이다.
- [ ] 로또 범위의 숫자 범위 내에서 중복되지 않는 6개의 숫자를 뽑는다.
- [x] 보너스 번호 1개의 숫자를 뽑는다.
- [x] 구입 금액에 해당하는 만큼 로또를 발행한다.

### 3. 출력

- [x] 발행한 로또 수량 및 번호를 출력한다.
- [x] 로또 번호는 오름차순으로 정렬하여 보여준다.
- [x] 당첨 내역을 출력한다.
- [x] 수익률을 계산하여 출력한다. 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%)
- [ ] 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.
6 changes: 5 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { startLotto } from "./LottoProgram.js";

class App {
async run() {}
async run() {
await startLotto();
}
}

export default App;
16 changes: 16 additions & 0 deletions src/Constant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const PROGRAM_MESSAGES = {
PRICE_PROMPT: "구입금액을 입력해 주세요.",
TRY_NUM_PROMPT: "개를 구매했습니다.",
WINNING_NUMBER_PROMPT: "\n" + "당첨 번호를 입력해 주세요.",
BONUS_NUMBER_PROMPT: "\n" + "보너스 번호를 입력해 주세요.",
};

export const STATICS_MESSAGE = {
RESULT_MESSAGE: "\n" + "당첨 통계" + "\n" + "---" + "\n",
THREE_MATCHES: "3개 일치 (5,000원) - ",
FOUR_MATCHES: "4개 일치 (50,000원) - ",
FIVE_MATCHES: "5개 일치 (1,500,000원) - ",
BONUS_MATCHES: "5개 일치, 보너스 볼 일치 (30,000,000원) - ",
SIX_MATCHES: "6개 일치 (2,000,000,000원) - ",
RATE_OF_RETURN: (rate) => `총 수익률은 ${rate}%입니다.`,
};
14 changes: 14 additions & 0 deletions src/InputHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Console } from "@woowacourse/mission-utils";

class InputHandler {
static async input(message) {
const price = await this.#readInput(message + "\n");
return price;
}

static #readInput(message) {
return Console.readLineAsync(message);
}
}

export default InputHandler;
15 changes: 14 additions & 1 deletion src/Lotto.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import OutputHandler from "./OutputHandler.js";

class Lotto {
#numbers;

Expand All @@ -13,6 +15,17 @@ class Lotto {
}

// TODO: 추가 기능 구현
}

// 로또 출력 함수
displayNumbers() {
OutputHandler.output("[" + this.#numbers.join(", ") + "]");
}

countMatchNumber(winningNumbers) {
const matchNum = this.#numbers.filter((num) =>
winningNumbers.includes(num)
);
return matchNum.length;
}
}
export default Lotto;
109 changes: 109 additions & 0 deletions src/LottoProgram.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import InputHandler from "./InputHandler.js";
import OutputHandler from "./OutputHandler.js";
import { PROGRAM_MESSAGES, STATICS_MESSAGE } from "./Constant.js";
import { validatePrice } from "./Validation.js";
import { MissionUtils } from "@woowacourse/mission-utils";

import Lotto from "./Lotto.js";

export const startLotto = async () => {
//로또 구입 금액을 입력받는다.
const price = await InputHandler.input(PROGRAM_MESSAGES.PRICE_PROMPT);
const tryNum = price / 1000;
// 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
validatePrice(tryNum);

// 로또 몇장인지 출력
OutputHandler.output("\n" + tryNum + PROGRAM_MESSAGES.TRY_NUM_PROMPT);
//tryNum 만큼의 로또를 발행
const lottoNumbers = getLottoNumbers(tryNum);

// 당첨 번호를 쉼표(,)를 기준으로 구분하여 입력 받는다.
let winningNumbers = await InputHandler.input(
PROGRAM_MESSAGES.WINNING_NUMBER_PROMPT
);
winningNumbers = winningNumbers.split(",").map((num) => num.trim());

//로또 번호 검증 ( 6개인지 )
const validateLotto = new Lotto(winningNumbers);

//보너스 번호 입력
const bonusNumber = await InputHandler.input(
PROGRAM_MESSAGES.BONUS_NUMBER_PROMPT
);

//당첨통계
OutputHandler.output(STATICS_MESSAGE.RESULT_MESSAGE);
getStatics(lottoNumbers, winningNumbers, bonusNumber, price);
};

export const getLottoNumbers = (tryNum) => {
const lottoNumbersArray = [];
for (let i = 0; i < tryNum; i++) {
const numbers = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6);
//오름차순 정렬
const lotto = new Lotto(numbers.sort((a, b) => a - b));
lotto.displayNumbers();
lottoNumbersArray.push(lotto);
}
return lottoNumbersArray;
};

export const getStatics = (
lottoNumbers,
winningNumbers,
bonusNumber,
price
) => {
const result = {
threeMatches: 0,
fourMatches: 0,
fiveMatches: 0,
fiveBonusMatches: 0,
sixMatches: 0,
};
let income = 0;
let rate = 0;
lottoNumbers.forEach((num) => {
const matchCount = num.countMatchNumber(winningNumbers);

if (matchCount === 3) {
result.threeMatches += 1;
income += 5000;
} else if (matchCount === 4) {
result.fourMatches += 1;
income += 50000;
} else if (matchCount === 5) {
if (num.numbers.includes(bonusNumber)) {
result.fiveBonusMatches += 1;
income += 30000000;
} else {
result.fiveMatches += 1;
income += 1500000;
}
} else if (matchCount === 6) {
result.sixMatches += 1;
income += 2000000000;
}
});

OutputHandler.output(
`${STATICS_MESSAGE.THREE_MATCHES} ${result.threeMatches}개`
);
OutputHandler.output(
`${STATICS_MESSAGE.FOUR_MATCHES} ${result.fourMatches}개`
);
OutputHandler.output(
`${STATICS_MESSAGE.FIVE_MATCHES} ${result.fiveMatches}개`
);
OutputHandler.output(
`${STATICS_MESSAGE.BONUS_MATCHES} ${result.fiveBonusMatches}개`
);
OutputHandler.output(`${STATICS_MESSAGE.SIX_MATCHES} ${result.sixMatches}개`);

if (income !== 0) {
rate = (income / price) * 100;
}

OutputHandler.output(STATICS_MESSAGE.RATE_OF_RETURN(rate.toFixed(2)));
};
12 changes: 12 additions & 0 deletions src/OutputHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Console } from "@woowacourse/mission-utils";

class OutputHandler {
static async output(message) {
Console.print(message);
}
static async staticOutput(matchNum, winners, message) {
Console.print(matchNum + message + winners);
}
}

export default OutputHandler;
5 changes: 5 additions & 0 deletions src/Validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const validatePrice = (try_num) => {
if (!Number.isInteger(try_num)) {
throw Error("[ERROR] 입력 금액이 1,000원 단위가 아닙니다.");
}
};