From 4b28576ce171d050aac47659d2c1b0976f54bfa1 Mon Sep 17 00:00:00 2001 From: Yerin_Kim Date: Mon, 3 Nov 2025 22:52:18 +0900 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20README.md=EC=97=90=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 15bb106b5..1f2427ce4 100644 --- a/README.md +++ b/README.md @@ -1 +1,15 @@ # javascript-lotto-precourse +1. 로또 구입 금액을 입력받는다. (Console API 사용) +2. 구입 금액이 1,000원 단위인지 검증한다. (예외 처리) +3. 당첨 번호 6개를 입력받는다. (쉼표 구분) +4. 당첨 번호의 유효성을 검증한다. (1~45 범위, 중복, 개수 등) +5. 보너스 번호 1개를 입력받는다. +6. 보너스 번호의 유효성을 검증한다. (1~45 범위, 당첨 번호와 중복 등) +7. 구입 금액에 맞춰 로또를 발행한다. (1장=1000원) +8. 로또 번호는 Random.pickUniqueNumbersInRange를 사용하여 6개를 뽑는다. +9. 발행된 로또 번호를 오름차순으로 정렬하여 출력한다. +10. 구매 로또별로 당첨 번호와 비교하여 일치 개수 및 보너스 번호 일치 여부를 계산한다. +11. 계산 결과에 따라 5등부터 1등까지 당첨 내역을 집계한다. +12. 당첨 내역(매칭 개수) 및 금액을 출력 요구사항 형식에 맞춰 출력한다. +13. 총 상금과 구입 금액을 이용하여 수익률을 계산한다. +14. 수익률을 소수점 둘째 자리에서 반올림하여 출력한다. (예: 62.5%) From dc960e2051fa15a008f060e3b4ced64e88e920d2 Mon Sep 17 00:00:00 2001 From: Yerin_Kim Date: Mon, 3 Nov 2025 23:04:45 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EA=B5=AC=EC=9E=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=9E=85=EB=A0=A5,=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EB=98=90=20=EB=B0=9C=ED=96=89,=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=B6=9C=EB=A0=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 15 ++++++++++-- src/Lotto.js | 15 +++++++++++- src/LottoGame.js | 59 +++++++++++++++++++++++++++++++++++++++++++++ src/WinningLotto.js | 0 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/LottoGame.js create mode 100644 src/WinningLotto.js diff --git a/src/App.js b/src/App.js index 091aa0a5d..5c8833443 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,16 @@ +import LottoGame from "./LottoGame.js"; + class App { - async run() {} + async run() { + const game = new LottoGame(); + + // 1.1~2.3 기능 실행 (구입 및 발행) + await game.getPurchaseAmount(); + game.issueLottos(); + + // 3.1~3.5 기능 실행 (당첨 번호 입력 및 결과 출력) + // await game.getWinningNumbers(); // LottoGame에 추가할 메서드 + } } -export default App; +export default App; \ No newline at end of file diff --git a/src/Lotto.js b/src/Lotto.js index cb0b1527e..c1d94ae92 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -4,15 +4,28 @@ class Lotto { constructor(numbers) { this.#validate(numbers); this.#numbers = numbers; + this.#numbers.sort((a, b) => a - b); // 9. 번호 정렬 (미리 해둠) } + // 기존 #validate에 유효성 검사를 추가합니다. #validate(numbers) { if (numbers.length !== 6) { throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); } + // 4. 유효성 검증: 1~45 범위 및 중복 검사 + if (numbers.some(number => number < 1 || number > 45)) { + throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + if (new Set(numbers).size !== 6) { + throw new Error("[ERROR] 로또 번호는 중복될 수 없습니다."); + } + } + + getNumbers() { + return this.#numbers; } - // TODO: 추가 기능 구현 + // ... (나중에 추가할예정) } export default Lotto; diff --git a/src/LottoGame.js b/src/LottoGame.js new file mode 100644 index 000000000..f1a9e3952 --- /dev/null +++ b/src/LottoGame.js @@ -0,0 +1,59 @@ +// src/LottoGame.js + +import { Console, Random } from "@woowacourse/mission-utils"; +import Lotto from "./Lotto.js"; + +const LOTTO_PRICE = 1000; + +class LottoGame { + constructor() { + this.lottos = []; + this.purchaseAmount = 0; + } + + // 1, 2번 기능: 구입 금액 입력 및 검증 로직 (반복 입력 처리 포함) + async getPurchaseAmount() { + while (true) { + try { + const input = await Console.readLineAsync("구입금액을 입력해 주세요.\n"); + const amount = this.validateAmount(input); // 검증 로직 호출 + this.purchaseAmount = amount; + return; // 성공 시 반복문 탈출 + } catch (error) { + Console.print(error.message); // 예외 상황 시 에러 출력 후 다시 입력받음 + } + } + } + + // 2번 기능: 금액 유효성 검증 로직 + validateAmount(input) { + const amount = parseInt(input.trim(), 10); + if (isNaN(amount)) { + throw new Error("[ERROR] 구입 금액은 숫자여야 합니다."); + } + // 1000원 단위 검증 + if (amount % LOTTO_PRICE !== 0 || amount === 0) { + throw new Error("[ERROR] 구입 금액은 1,000원 단위로 입력해야 합니다."); + } + return amount; + } + + // 7, 8번 기능: 로또 발행 로직 + issueLottos() { + const count = this.purchaseAmount / LOTTO_PRICE; + Console.print(`\n${count}개를 구매했습니다.`); // 7. 발행 수량 출력 + + for (let i = 0; i < count; i++) { + // 8. Random.pickUniqueNumbersInRange를 사용하여 6개를 뽑는다. + const numbers = Random.pickUniqueNumbersInRange(1, 45, 6); + this.lottos.push(new Lotto(numbers)); + + // 9. 발행된 로또 번호를 오름차순으로 정렬하여 출력한다. (Lotto 클래스에서 정렬됨) + Console.print(`[${this.lottos[i].getNumbers().join(', ')}]`); + } + } + + // ... +} + +export default LottoGame; \ No newline at end of file diff --git a/src/WinningLotto.js b/src/WinningLotto.js new file mode 100644 index 000000000..e69de29bb From 081fa2f67ab62b5657636616f461832c6314fd23 Mon Sep 17 00:00:00 2001 From: Yerin_Kim Date: Mon, 3 Nov 2025 23:18:44 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=ED=8C=90=EB=B3=84,=20=EC=88=98=EC=9D=B5=EB=A5=A0?= =?UTF-8?q?=20=EA=B3=84=EC=82=B0=20=EB=B0=8F=20=EC=B5=9C=EC=A2=85=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 23 ++++++++++++++---- src/Lotto.js | 15 ++++++++++++ src/LottoGame.js | 57 +++++++++++++++++++++++++++++++++++++++++++-- src/WinningLotto.js | 57 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 7 deletions(-) diff --git a/src/App.js b/src/App.js index 5c8833443..1b207384f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,15 +1,28 @@ +import { Console } from "@woowacourse/mission-utils"; import LottoGame from "./LottoGame.js"; class App { async run() { const game = new LottoGame(); - // 1.1~2.3 기능 실행 (구입 및 발행) - await game.getPurchaseAmount(); - game.issueLottos(); + try { + await game.getPurchaseAmount(); // 1.1, 1.2 + game.issueLottos(); // 2.1, 2.3 - // 3.1~3.5 기능 실행 (당첨 번호 입력 및 결과 출력) - // await game.getWinningNumbers(); // LottoGame에 추가할 메서드 + // 당첨 번호 입력 및 검증 + const winningNumbersInput = await Console.readLineAsync("\n당첨 번호를 입력해 주세요.\n"); + const winningNumbers = winningNumbersInput.split(',').map(n => parseInt(n.trim(), 10)); + + // 보너스 번호 입력 및 검증 + const bonusNumberInput = await Console.readLineAsync("\n보너스 번호를 입력해 주세요.\n"); + const bonusNumber = parseInt(bonusNumberInput.trim(), 10); + + // 10~14번 기능 실행 + game.calculateAndPrintResults(winningNumbers, bonusNumber); + + } catch (error) { + // ... (catch 블록은 그대로) + } } } diff --git a/src/Lotto.js b/src/Lotto.js index c1d94ae92..2e8e209d0 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -25,6 +25,21 @@ class Lotto { return this.#numbers; } + // 10번 기능: 당첨 번호와의 일치 개수 및 보너스 번호 일치 여부 계산 + getMatchResult(winningLotto, bonusNumber) { + const winningNumbers = winningLotto.getNumbers(); + + // 일치 개수 계산 + const matchCount = this.#numbers.filter(number => + winningNumbers.includes(number) + ).length; + + // 보너스 번호 일치 여부 + const bonusMatch = this.#numbers.includes(bonusNumber); + + return { matchCount, bonusMatch }; + } + // ... (나중에 추가할예정) } diff --git a/src/LottoGame.js b/src/LottoGame.js index f1a9e3952..ba0b3f093 100644 --- a/src/LottoGame.js +++ b/src/LottoGame.js @@ -1,10 +1,19 @@ -// src/LottoGame.js import { Console, Random } from "@woowacourse/mission-utils"; import Lotto from "./Lotto.js"; +import WinningLotto, { PRIZES } from "./WinningLotto.js"; const LOTTO_PRICE = 1000; +// 당첨 내역 초기화 및 출력 순서를 정의합니다. +const INITIAL_STATS = { + [PRIZES.FIFTH.label]: 0, + [PRIZES.FOURTH.label]: 0, + [PRIZES.THIRD.label]: 0, + [PRIZES.SECOND.label]: 0, + [PRIZES.FIRST.label]: 0, +}; + class LottoGame { constructor() { this.lottos = []; @@ -53,7 +62,51 @@ class LottoGame { } } - // ... + +class LottoGame { + // ... (constructor, getPurchaseAmount, issueLottos는 그대로) + + // 12, 13번 기능: 당첨 통계 계산 및 출력 + calculateAndPrintResults(winningNumbers, bonusNumber) { + const winningLotto = new WinningLotto(winningNumbers, bonusNumber); + const stats = this.lottos.reduce((acc, lotto) => { + const rank = winningLotto.rank(lotto); + if (rank) { + acc[rank.label] += 1; + } + return acc; + }, { ...INITIAL_STATS }); // 초기 통계 객체 복사 + + this.printWinningStats(stats); // 당첨 내역 출력 + this.printProfitRate(stats); // 수익률 출력 + } + + // 12번 기능: 당첨 내역 출력 + printWinningStats(stats) { + Console.print('\n당첨 통계'); + Console.print('---'); + Object.keys(INITIAL_STATS).forEach(label => { + Console.print(`${label} - ${stats[label]}개`); + }); + } + + // 14번 기능: 수익률 계산 및 출력 + printProfitRate(stats) { + let totalRevenue = 0; + Object.keys(stats).forEach(label => { + const prize = Object.values(PRIZES).find(p => p.label === label); + totalRevenue += stats[label] * prize.amount; + }); + + const profitRate = (totalRevenue / this.purchaseAmount) * 100; + + // 수익률 소수점 둘째 자리에서 반올림 + const roundedRate = Math.round(profitRate * 10) / 10; + Console.print(`총 수익률은 ${roundedRate.toLocaleString('ko-KR')}%입니다.`); + } + + // ... (나머지 로직은 그대로) +} } export default LottoGame; \ No newline at end of file diff --git a/src/WinningLotto.js b/src/WinningLotto.js index e69de29bb..ce1ce53d0 100644 --- a/src/WinningLotto.js +++ b/src/WinningLotto.js @@ -0,0 +1,57 @@ +import Lotto from "./Lotto.js"; + +class WinningLotto { + constructor(winningNumbers, bonusNumber) { + // winningNumbers는 이미 Lotto 클래스에서 유효성 검증을 거쳤다고 가정합니다. + this.winningLotto = new Lotto(winningNumbers); + this.bonusNumber = this.validateBonusNumber(bonusNumber); + } + + // 6번 기능: 보너스 번호 유효성 검증 로직 + validateBonusNumber(number) { + const num = parseInt(number, 10); + + if (isNaN(num)) { + throw new Error("[ERROR] 보너스 번호는 숫자여야 합니다."); + } + // 1~45 범위 검증 + if (num < 1 || num > 45) { + throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + // 당첨 번호와 중복 검증 + if (this.winningLotto.getNumbers().includes(num)) { + throw new Error("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + + return num; + } + + // 당첨 기준 및 상금을 정의합니다. + export const PRIZES = { + FIRST: { count: 6, bonus: false, amount: 2000000000, label: '6개 일치 (2,000,000,000원)' }, + SECOND: { count: 5, bonus: true, amount: 30000000, label: '5개 일치, 보너스 볼 일치 (30,000,000원)' }, + THIRD: { count: 5, bonus: false, amount: 1500000, label: '5개 일치 (1,500,000원)' }, + FOURTH: { count: 4, bonus: false, amount: 50000, label: '4개 일치 (50,000원)' }, + FIFTH: { count: 3, bonus: false, amount: 5000, label: '3개 일치 (5,000원)' }, + }; + +class WinningLotto { + // ... (constructor 및 validateBonusNumber는 그대로) + + // 11번 기능: 로또 번호와 비교하여 당첨 등수를 반환 + rank(lotto) { + const { matchCount, bonusMatch } = lotto.getMatchResult(this.winningLotto, this.bonusNumber); + + // 1등부터 5등까지 순차적으로 조건 검사 (else 지양 원칙 적용) + if (matchCount === 6) return PRIZES.FIRST; + if (matchCount === 5 && bonusMatch) return PRIZES.SECOND; + if (matchCount === 5) return PRIZES.THIRD; + if (matchCount === 4) return PRIZES.FOURTH; + if (matchCount === 3) return PRIZES.FIFTH; + + return null; // 낙첨 + } +} +} + +export default WinningLotto; \ No newline at end of file From 4a79df19d3f197c895426109df12740aba56b143 Mon Sep 17 00:00:00 2001 From: Yerin_Kim Date: Mon, 3 Nov 2025 23:22:47 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20LottoGame=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=EC=A1=B0=20=EB=B0=8F=20=EC=83=81=EC=88=98?= =?UTF-8?q?=20=EC=9C=84=EC=B9=98=20=EB=AC=B8=EB=B2=95=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/LottoGame.js | 41 ++++++++++++++++++----------------------- src/WinningLotto.js | 27 ++++++++++----------------- 2 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/LottoGame.js b/src/LottoGame.js index ba0b3f093..385e49ce2 100644 --- a/src/LottoGame.js +++ b/src/LottoGame.js @@ -1,11 +1,11 @@ - import { Console, Random } from "@woowacourse/mission-utils"; import Lotto from "./Lotto.js"; +// PRIZES 상수를 사용하기 위해 WinningLotto에서 import해야 합니다. import WinningLotto, { PRIZES } from "./WinningLotto.js"; const LOTTO_PRICE = 1000; -// 당첨 내역 초기화 및 출력 순서를 정의합니다. +// 당첨 내역 초기화 및 출력 순서를 정의합니다. (파일 상단에 위치) const INITIAL_STATS = { [PRIZES.FIFTH.label]: 0, [PRIZES.FOURTH.label]: 0, @@ -14,6 +14,7 @@ const INITIAL_STATS = { [PRIZES.FIRST.label]: 0, }; +// ✨ 클래스는 파일당 한 번만 정의됩니다. class LottoGame { constructor() { this.lottos = []; @@ -25,11 +26,11 @@ class LottoGame { while (true) { try { const input = await Console.readLineAsync("구입금액을 입력해 주세요.\n"); - const amount = this.validateAmount(input); // 검증 로직 호출 + const amount = this.validateAmount(input); this.purchaseAmount = amount; - return; // 성공 시 반복문 탈출 + return; } catch (error) { - Console.print(error.message); // 예외 상황 시 에러 출력 후 다시 입력받음 + Console.print(error.message); } } } @@ -40,45 +41,39 @@ class LottoGame { if (isNaN(amount)) { throw new Error("[ERROR] 구입 금액은 숫자여야 합니다."); } - // 1000원 단위 검증 if (amount % LOTTO_PRICE !== 0 || amount === 0) { throw new Error("[ERROR] 구입 금액은 1,000원 단위로 입력해야 합니다."); } return amount; } - // 7, 8번 기능: 로또 발행 로직 + // 7, 8, 9번 기능: 로또 발행 로직 issueLottos() { const count = this.purchaseAmount / LOTTO_PRICE; - Console.print(`\n${count}개를 구매했습니다.`); // 7. 발행 수량 출력 + Console.print(`\n${count}개를 구매했습니다.`); for (let i = 0; i < count; i++) { - // 8. Random.pickUniqueNumbersInRange를 사용하여 6개를 뽑는다. const numbers = Random.pickUniqueNumbersInRange(1, 45, 6); this.lottos.push(new Lotto(numbers)); - - // 9. 발행된 로또 번호를 오름차순으로 정렬하여 출력한다. (Lotto 클래스에서 정렬됨) Console.print(`[${this.lottos[i].getNumbers().join(', ')}]`); } } - -class LottoGame { - // ... (constructor, getPurchaseAmount, issueLottos는 그대로) - // 12, 13번 기능: 당첨 통계 계산 및 출력 calculateAndPrintResults(winningNumbers, bonusNumber) { + // winningLotto 인스턴스 생성 시 유효성 검사가 WinningLotto 생성자에서 실행됩니다. const winningLotto = new WinningLotto(winningNumbers, bonusNumber); + const stats = this.lottos.reduce((acc, lotto) => { const rank = winningLotto.rank(lotto); if (rank) { acc[rank.label] += 1; } return acc; - }, { ...INITIAL_STATS }); // 초기 통계 객체 복사 + }, { ...INITIAL_STATS }); - this.printWinningStats(stats); // 당첨 내역 출력 - this.printProfitRate(stats); // 수익률 출력 + this.printWinningStats(stats); + this.printProfitRate(stats); } // 12번 기능: 당첨 내역 출력 @@ -94,8 +89,11 @@ class LottoGame { printProfitRate(stats) { let totalRevenue = 0; Object.keys(stats).forEach(label => { + // PRIZES 상수는 WinningLotto에서 export 했으므로 여기에서 직접 접근 가능 const prize = Object.values(PRIZES).find(p => p.label === label); - totalRevenue += stats[label] * prize.amount; + if (prize) { // prize가 존재하는지 확인 (안전성 추가) + totalRevenue += stats[label] * prize.amount; + } }); const profitRate = (totalRevenue / this.purchaseAmount) * 100; @@ -104,9 +102,6 @@ class LottoGame { const roundedRate = Math.round(profitRate * 10) / 10; Console.print(`총 수익률은 ${roundedRate.toLocaleString('ko-KR')}%입니다.`); } - - // ... (나머지 로직은 그대로) -} } -export default LottoGame; \ No newline at end of file +export default LottoGame; \ No newline at end of file diff --git a/src/WinningLotto.js b/src/WinningLotto.js index ce1ce53d0..fd401ba4f 100644 --- a/src/WinningLotto.js +++ b/src/WinningLotto.js @@ -1,8 +1,16 @@ import Lotto from "./Lotto.js"; +// 1. PRIZES 상수를 파일 맨 위에 정의하고 export 합니다. +export const PRIZES = { + FIRST: { count: 6, bonus: false, amount: 2000000000, label: '6개 일치 (2,000,000,000원)' }, + SECOND: { count: 5, bonus: true, amount: 30000000, label: '5개 일치, 보너스 볼 일치 (30,000,000원)' }, + THIRD: { count: 5, bonus: false, amount: 1500000, label: '5개 일치 (1,500,000원)' }, + FOURTH: { count: 4, bonus: false, amount: 50000, label: '4개 일치 (50,000원)' }, + FIFTH: { count: 3, bonus: false, amount: 5000, label: '3개 일치 (5,000원)' }, +}; + class WinningLotto { constructor(winningNumbers, bonusNumber) { - // winningNumbers는 이미 Lotto 클래스에서 유효성 검증을 거쳤다고 가정합니다. this.winningLotto = new Lotto(winningNumbers); this.bonusNumber = this.validateBonusNumber(bonusNumber); } @@ -14,11 +22,9 @@ class WinningLotto { if (isNaN(num)) { throw new Error("[ERROR] 보너스 번호는 숫자여야 합니다."); } - // 1~45 범위 검증 if (num < 1 || num > 45) { throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); } - // 당첨 번호와 중복 검증 if (this.winningLotto.getNumbers().includes(num)) { throw new Error("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다."); } @@ -26,23 +32,11 @@ class WinningLotto { return num; } - // 당첨 기준 및 상금을 정의합니다. - export const PRIZES = { - FIRST: { count: 6, bonus: false, amount: 2000000000, label: '6개 일치 (2,000,000,000원)' }, - SECOND: { count: 5, bonus: true, amount: 30000000, label: '5개 일치, 보너스 볼 일치 (30,000,000원)' }, - THIRD: { count: 5, bonus: false, amount: 1500000, label: '5개 일치 (1,500,000원)' }, - FOURTH: { count: 4, bonus: false, amount: 50000, label: '4개 일치 (50,000원)' }, - FIFTH: { count: 3, bonus: false, amount: 5000, label: '3개 일치 (5,000원)' }, - }; - -class WinningLotto { - // ... (constructor 및 validateBonusNumber는 그대로) - // 11번 기능: 로또 번호와 비교하여 당첨 등수를 반환 rank(lotto) { const { matchCount, bonusMatch } = lotto.getMatchResult(this.winningLotto, this.bonusNumber); - // 1등부터 5등까지 순차적으로 조건 검사 (else 지양 원칙 적용) + // 1등부터 5등까지 순차적으로 조건 검사 if (matchCount === 6) return PRIZES.FIRST; if (matchCount === 5 && bonusMatch) return PRIZES.SECOND; if (matchCount === 5) return PRIZES.THIRD; @@ -52,6 +46,5 @@ class WinningLotto { return null; // 낙첨 } } -} export default WinningLotto; \ No newline at end of file From a1a3f22a8df80723f0f1a7c14be7e5562a465a51 Mon Sep 17 00:00:00 2001 From: Yerin_Kim Date: Mon, 3 Nov 2025 23:27:36 +0900 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=EB=8B=B9=EC=B2=A8=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EC=8B=9C=20=EB=B0=98=EB=B3=B5=20=EA=B2=80=EC=A6=9D?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 6 ++++++ src/LottoGame.js | 27 ++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/App.js b/src/App.js index 1b207384f..52f3e37f5 100644 --- a/src/App.js +++ b/src/App.js @@ -17,6 +17,12 @@ class App { const bonusNumberInput = await Console.readLineAsync("\n보너스 번호를 입력해 주세요.\n"); const bonusNumber = parseInt(bonusNumberInput.trim(), 10); + // ✨ 3, 4번: LottoGame에서 반복 입력 처리 + const winningLottoInstance = await game.getWinningNumbers(); + + // ✨ 5, 6번: WinningLotto 인스턴스 생성 시 보너스 번호 검증까지 처리됨 + const fullWinningLotto = await game.getBonusNumber(winningLottoInstance); + // 10~14번 기능 실행 game.calculateAndPrintResults(winningNumbers, bonusNumber); diff --git a/src/LottoGame.js b/src/LottoGame.js index 385e49ce2..cf290dcb3 100644 --- a/src/LottoGame.js +++ b/src/LottoGame.js @@ -22,13 +22,30 @@ class LottoGame { } // 1, 2번 기능: 구입 금액 입력 및 검증 로직 (반복 입력 처리 포함) - async getPurchaseAmount() { + // 3, 4번 기능: 당첨 번호 입력 및 검증 (반복 처리) + async getWinningNumbers() { while (true) { try { - const input = await Console.readLineAsync("구입금액을 입력해 주세요.\n"); - const amount = this.validateAmount(input); - this.purchaseAmount = amount; - return; + const input = await Console.readLineAsync("\n당첨 번호를 입력해 주세요.\n"); + const numbers = input.split(',').map(n => parseInt(n.trim(), 10)); + + // 4. 유효성 검증: Lotto 객체 생성 시 검증이 자동으로 실행됨 + return new Lotto(numbers); + } catch (error) { + Console.print(error.message); + } + } + } + + // 5, 6번 기능: 보너스 번호 입력 및 검증 (반복 처리) + async getBonusNumber(winningLotto) { + while (true) { + try { + const input = await Console.readLineAsync("\n보너스 번호를 입력해 주세요.\n"); + const number = parseInt(input.trim(), 10); + + // 6. 유효성 검증: WinningLotto 생성자를 통해 검증이 실행됨 + return new WinningLotto(winningLotto.getNumbers(), number); } catch (error) { Console.print(error.message); } From 399cf6cf537191a8416acaf72bfb2d2219eaba8b Mon Sep 17 00:00:00 2001 From: Yerin_Kim Date: Mon, 3 Nov 2025 23:37:42 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=20=EC=9E=85=EB=A0=A5=20=EB=A1=9C=EC=A7=81=20=EC=B5=9C?= =?UTF-8?q?=EC=A2=85=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 31 ++++++++++++++++--------------- src/LottoGame.js | 15 ++++++++++----- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/App.js b/src/App.js index 52f3e37f5..9b620fffd 100644 --- a/src/App.js +++ b/src/App.js @@ -6,28 +6,29 @@ class App { const game = new LottoGame(); try { - await game.getPurchaseAmount(); // 1.1, 1.2 - game.issueLottos(); // 2.1, 2.3 + // 1. 구입 금액 입력 및 로또 발행 + await game.getPurchaseAmount(); + game.issueLottos(); - // 당첨 번호 입력 및 검증 - const winningNumbersInput = await Console.readLineAsync("\n당첨 번호를 입력해 주세요.\n"); - const winningNumbers = winningNumbersInput.split(',').map(n => parseInt(n.trim(), 10)); - - // 보너스 번호 입력 및 검증 - const bonusNumberInput = await Console.readLineAsync("\n보너스 번호를 입력해 주세요.\n"); - const bonusNumber = parseInt(bonusNumberInput.trim(), 10); - - // ✨ 3, 4번: LottoGame에서 반복 입력 처리 + // 2. 당첨 번호 입력 및 검증 (LottoGame에 구현된 반복 입력 처리) const winningLottoInstance = await game.getWinningNumbers(); + const winningNumbers = winningLottoInstance.getNumbers(); + + // 3. 보너스 번호 입력 및 검증 (LottoGame에 구현된 반복 입력 처리) + // LotteGame에 추가한 헬퍼 메서드를 통해 유효한 번호를 받습니다. + const bonusNumber = await game.getBonusNumberValue(); - // ✨ 5, 6번: WinningLotto 인스턴스 생성 시 보너스 번호 검증까지 처리됨 - const fullWinningLotto = await game.getBonusNumber(winningLottoInstance); + // 4. WinningLotto 객체 생성 (최종 중복 검사) + // LottoGame.js의 calculateAndPrintResults에서 WinningLotto 객체를 생성합니다. - // 10~14번 기능 실행 + // 5. 당첨 결과 계산 및 출력 (10~14번 기능) game.calculateAndPrintResults(winningNumbers, bonusNumber); } catch (error) { - // ... (catch 블록은 그대로) + // 1.6번 기능: [ERROR] 메시지 출력 후 애플리케이션 종료 + Console.print(error.message); + // 테스트 통과 및 비정상 종료 상태를 명확히 하기 위해 throw error를 유지합니다. + throw error; } } } diff --git a/src/LottoGame.js b/src/LottoGame.js index cf290dcb3..5ac770d66 100644 --- a/src/LottoGame.js +++ b/src/LottoGame.js @@ -23,14 +23,19 @@ class LottoGame { // 1, 2번 기능: 구입 금액 입력 및 검증 로직 (반복 입력 처리 포함) // 3, 4번 기능: 당첨 번호 입력 및 검증 (반복 처리) - async getWinningNumbers() { + // 5번 기능: 보너스 번호 입력 및 기본 유효성 검증 (반복 처리) + async getBonusNumberValue() { while (true) { try { - const input = await Console.readLineAsync("\n당첨 번호를 입력해 주세요.\n"); - const numbers = input.split(',').map(n => parseInt(n.trim(), 10)); + const input = await Console.readLineAsync("\n보너스 번호를 입력해 주세요.\n"); + const number = parseInt(input.trim(), 10); - // 4. 유효성 검증: Lotto 객체 생성 시 검증이 자동으로 실행됨 - return new Lotto(numbers); + // 기본 유효성 검증 (숫자형, 1~45 범위) + if (isNaN(number) || number < 1 || number > 45) { + // WinningLotto.js의 에러 메시지를 재사용하거나 적절한 에러를 던집니다. + throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + return number; } catch (error) { Console.print(error.message); }