From 272943f0a58cbdca06cb45664663ca0af4b8db30 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 16:55:03 +0900 Subject: [PATCH 01/11] =?UTF-8?q?docs=20:=20README=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EA=B3=BC=20=EC=8B=A4=ED=96=89=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15bb106b5..9aa5aee43 100644 --- a/README.md +++ b/README.md @@ -1 +1,59 @@ -# javascript-lotto-precourse +# 로또 발매기 + +간단한 로또 발매기 +구매한 로또의 금액과 당첨된 로또의 금액을 비교하여 수익률을 알려주는 프로그램 + +## 실행 결과 + +### 입력 + +``` plaintext + 구입금액을 입력해 주세요. + 8000 + + 8개를 구매했습니다. + [8, 21, 23, 41, 42, 43] + [3, 5, 11, 16, 32, 38] + [7, 11, 16, 35, 36, 44] + [1, 8, 11, 31, 41, 42] + [13, 14, 16, 38, 42, 45] + [7, 11, 30, 40, 42, 43] + [2, 13, 22, 32, 38, 45] + [1, 3, 5, 14, 22, 45] + + 당첨 번호를 입력해 주세요. + 1,2,3,4,5,6 + + 보너스 번호를 입력해 주세요. + 7 + + 당첨 통계 + --- + 3개 일치 (5,000원) - 1개 + 4개 일치 (50,000원) - 0개 + 5개 일치 (1,500,000원) - 0개 + 5개 일치, 보너스 볼 일치 (30,000,000원) - 0개 + 6개 일치 (2,000,000,000원) - 0개 + 총 수익률은 62.5%입니다. +``` + +## 구현할 기능 +- [ ] 입력 받기 + - [ ] 로또 구매할 금액 입력 + - [ ] 1000원으로 나누어 떨어지지 않는 경우 ERROR + - [ ] 당첨 번호 입력 + - [ ] 예외 처리 + - ','로 구분 안되는 값 + - 숫자가 아닌 값 + - 중복된 값 + - [ ] 보너스 번호 입력 + - [ ] 예외 처리 + - [ ] 숫자가 아닌 값 + - [ ] 입력 당첨 번호와 중복된 값 + +- [ ] 로또 발행하기 + - [ ] 구매한 로또만큼 번호 발행 + - [ ] 발행한 로또 출력 + - [ ] 발행한 로또 당첨 처리 + - [ ] 당첨 내역 출력 + - [ ] 수익률 출력 From 66d0963451dca6b862baa9c572c655b5d3373794 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 17:25:44 +0900 Subject: [PATCH 02/11] =?UTF-8?q?feat=20:=20input(=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=EA=B8=88=EC=95=A1,=20=EB=A1=9C=EB=98=90=20=EB=B2=88=ED=98=B8)?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/View/InputView.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/View/InputView.js diff --git a/src/View/InputView.js b/src/View/InputView.js new file mode 100644 index 000000000..6edc011b9 --- /dev/null +++ b/src/View/InputView.js @@ -0,0 +1,21 @@ +import { Console } from "@woowacourse/mission-utils"; + + +export default class InputView { + + async readPurchaseAmount() { + const PurchaseAmount = await Console.readLineAsync("구입금액을 입력해 주세요."); + return PurchaseAmount; + } + + async readWinningNumber() { + const winningNumber = await Console.readLineAsync("당첨 번호를 입력해 주세요."); + return winningNumber; + } + + async readBonusNumber() { + const bonusNumber = await Console.readLineAsync("보너스 번호를 입력해 주세요."); + return bonusNumber; + } + +} \ No newline at end of file From 78964bd3b11450d3741e915e186e23ed1c4992d4 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 20:44:40 +0900 Subject: [PATCH 03/11] =?UTF-8?q?feat=20:=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=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 | 16 +++++++++++++- src/validators/LottoValidator.js | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/validators/LottoValidator.js diff --git a/src/App.js b/src/App.js index 091aa0a5d..9a9173243 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,19 @@ +import LottoValidator from "./validators/LottoValidator.js"; +import InputView from "./view/InputView.js"; + class App { - async run() {} + async run() { + const input = new InputView(); + const purchaseAmount = await input.readPurchaseAmount(); + const winningNumbers = await input.readWinningNumbers(); + const bonusNumber = await input.readBonusNumber(); + const allLottoNumbers = [...winningNumbers, bonusNumber]; + LottoValidator.validateDuplicateNumbers(allLottoNumbers); + allLottoNumbers.forEach(LottoValidator.validatorSingleNumber); + + + + } } export default App; diff --git a/src/validators/LottoValidator.js b/src/validators/LottoValidator.js new file mode 100644 index 000000000..279d6a029 --- /dev/null +++ b/src/validators/LottoValidator.js @@ -0,0 +1,37 @@ + +export default class LottoValidator { + static LOTTO_REGEX = /^[0-9]{1,2}(,\s*[0-9]{1,2}){5}$/; + static BONUS_LOTTO_REGEX = /^[0-9]{1,2}\s*$/; + static MIN_LOTTO_NUMBER = 1; + static MAX_LOTTO_NUMBER = 45; + + static validatorPurchaseAmount(purchaseAmount) { + if (purchaseAmount % 1000 !== 0) + throw new Error("[ERROR] 구매금액은 1000원 단위이어야합니다."); + } + + static validatorLottoNumbers(numbers) { + if (! LottoValidator.LOTTO_REGEX.test(numbers)) { + throw new Error("[ERROR] 당첨 번호는 총 6개의 최대 2자리 숫자로 ','로 구분되어있어야 합니다."); + } + } + + static validatorBonusNumber(bonusNumber) { + if (! LottoValidator.BONUS_LOTTO_REGEX.test(bonusNumber)) { + throw new Error("[ERROR] 보너스 번호는 하나의 숫자만 입력되어야 합니다."); + } + } + + static validatorSingleNumber(number) { + if (number < LottoValidator.MIN_LOTTO_NUMBER || number > LottoValidator.MAX_LOTTO_NUMBER) { + throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + } + + static validateDuplicateNumbers(winningLottoNumbers) { + const uniqueNumbers = new Set(winningLottoNumbers); + if (uniqueNumbers.size !== winningLottoNumbers.length) { + throw new Error("[ERROR] 로또 당첨 번호는 중복된 값을 가질 수 없습니다."); + } + } +} \ No newline at end of file From 171e92b6a26f85acdedb484fd4c086078ff45833 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 20:51:25 +0900 Subject: [PATCH 04/11] =?UTF-8?q?refactor=20:=20inputView=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20split=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 ++++++++++++------------ src/App.js | 3 +++ src/View/InputView.js | 25 ++++++++++++++++++------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 9aa5aee43..b11c3d428 100644 --- a/README.md +++ b/README.md @@ -38,18 +38,18 @@ ``` ## 구현할 기능 -- [ ] 입력 받기 - - [ ] 로또 구매할 금액 입력 - - [ ] 1000원으로 나누어 떨어지지 않는 경우 ERROR - - [ ] 당첨 번호 입력 - - [ ] 예외 처리 - - ','로 구분 안되는 값 - - 숫자가 아닌 값 - - 중복된 값 - - [ ] 보너스 번호 입력 - - [ ] 예외 처리 - - [ ] 숫자가 아닌 값 - - [ ] 입력 당첨 번호와 중복된 값 +- [x] 입력 받기 + - [x] 로또 구매할 금액 입력 + - [x] 1000원으로 나누어 떨어지지 않는 경우 ERROR + - [x] 당첨 번호 입력 + - [x] 예외 처리 + - [x] ','로 구분 안되는 값 + - [x] 숫자가 아닌 값 + - [x] 중복된 값 + - [x] 보너스 번호 입력 + - [x] 예외 처리 + - [x] 숫자가 아닌 값 + - [x] 입력 당첨 번호와 중복된 값 - [ ] 로또 발행하기 - [ ] 구매한 로또만큼 번호 발행 diff --git a/src/App.js b/src/App.js index 9a9173243..2cc80c1fe 100644 --- a/src/App.js +++ b/src/App.js @@ -4,6 +4,7 @@ import InputView from "./view/InputView.js"; class App { async run() { const input = new InputView(); + const purchaseAmount = await input.readPurchaseAmount(); const winningNumbers = await input.readWinningNumbers(); const bonusNumber = await input.readBonusNumber(); @@ -11,6 +12,8 @@ class App { LottoValidator.validateDuplicateNumbers(allLottoNumbers); allLottoNumbers.forEach(LottoValidator.validatorSingleNumber); + + } diff --git a/src/View/InputView.js b/src/View/InputView.js index 6edc011b9..eff4895de 100644 --- a/src/View/InputView.js +++ b/src/View/InputView.js @@ -1,21 +1,32 @@ import { Console } from "@woowacourse/mission-utils"; - +import LottoValidator from "../validators/LottoValidator.js"; export default class InputView { async readPurchaseAmount() { - const PurchaseAmount = await Console.readLineAsync("구입금액을 입력해 주세요."); - return PurchaseAmount; + const purchaseAmountStr = await Console.readLineAsync("구입금액을 입력해 주세요.\n"); + const purchaseAmount = Number(purchaseAmountStr); + LottoValidator.validatorPurchaseAmount(purchaseAmount); + return purchaseAmount; } - async readWinningNumber() { - const winningNumber = await Console.readLineAsync("당첨 번호를 입력해 주세요."); - return winningNumber; + async readWinningNumbers() { + const winningNumbers = await Console.readLineAsync("당첨 번호를 입력해 주세요.\n"); + LottoValidator.validatorLottoNumbers(winningNumbers); + const winningNumbersArr = this.splitNumbers(winningNumbers); + return winningNumbersArr; } async readBonusNumber() { - const bonusNumber = await Console.readLineAsync("보너스 번호를 입력해 주세요."); + let bonusNumber = await Console.readLineAsync("보너스 번호를 입력해 주세요.\n"); + LottoValidator.validatorBonusNumber(bonusNumber); + bonusNumber = Number(bonusNumber.trim()); return bonusNumber; } + splitNumbers(winningNumbers) { + const numbersArray = winningNumbers.split(',').map(number => Number(number.trim())); + return numbersArray; + } + } \ No newline at end of file From 61ebd7e13e16f5abf7d48e487bdb3da90936e33e Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 21:05:32 +0900 Subject: [PATCH 05/11] =?UTF-8?q?refactor=20:=20inputView=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20split=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index 2cc80c1fe..fe34c1554 100644 --- a/src/App.js +++ b/src/App.js @@ -1,10 +1,13 @@ import LottoValidator from "./validators/LottoValidator.js"; import InputView from "./view/InputView.js"; +import { Random } from "@woowacourse/mission-utils"; class App { async run() { + const a = Random.pickUniqueNumbersInRange(1,2); + console.log(a); const input = new InputView(); - + const purchaseAmount = await input.readPurchaseAmount(); const winningNumbers = await input.readWinningNumbers(); const bonusNumber = await input.readBonusNumber(); From e8fe5960e01a8733a630244da212a03205ab45e3 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 21:19:25 +0900 Subject: [PATCH 06/11] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80.=20=EB=B0=8F=20LottoValidator=EC=9D=98=20MIN,=20MAX?= =?UTF-8?q?=20NUM=20->=20Lotto=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/App.js | 7 ++----- src/model/Customer.js | 20 ++++++++++++++++++++ src/model/Lotto.js | 11 +++++++++++ src/validators/LottoValidator.js | 5 ++--- 5 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 src/model/Customer.js create mode 100644 src/model/Lotto.js diff --git a/README.md b/README.md index b11c3d428..2ccbb2f94 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ - [x] 입력 당첨 번호와 중복된 값 - [ ] 로또 발행하기 - - [ ] 구매한 로또만큼 번호 발행 + - [x] 구매한 로또만큼 번호 발행 - [ ] 발행한 로또 출력 - [ ] 발행한 로또 당첨 처리 - [ ] 당첨 내역 출력 diff --git a/src/App.js b/src/App.js index fe34c1554..7ad75f4b8 100644 --- a/src/App.js +++ b/src/App.js @@ -1,13 +1,10 @@ import LottoValidator from "./validators/LottoValidator.js"; import InputView from "./view/InputView.js"; -import { Random } from "@woowacourse/mission-utils"; class App { async run() { - const a = Random.pickUniqueNumbersInRange(1,2); - console.log(a); const input = new InputView(); - + const purchaseAmount = await input.readPurchaseAmount(); const winningNumbers = await input.readWinningNumbers(); const bonusNumber = await input.readBonusNumber(); @@ -15,7 +12,7 @@ class App { LottoValidator.validateDuplicateNumbers(allLottoNumbers); allLottoNumbers.forEach(LottoValidator.validatorSingleNumber); - + diff --git a/src/model/Customer.js b/src/model/Customer.js new file mode 100644 index 000000000..71a75471d --- /dev/null +++ b/src/model/Customer.js @@ -0,0 +1,20 @@ +import Lotto from "./Lotto"; + +export default class Customer { + #purchaseAmount; + #lottoNumbersList; + #lottoCount; + + constructor(purchaseAmount) { + this.#purchaseAmount = purchaseAmount; + this.#lottoCount = purchaseAmount/1000; + } + + getLottoNumberList() { + Array.from({ length: this.#lottoCount }).forEach(() => { + const lottoNumbers = Lotto.getLottoNumberList(); + this.#lottoNumbersList.push(lottoNumbers); + }) + } + +} \ No newline at end of file diff --git a/src/model/Lotto.js b/src/model/Lotto.js new file mode 100644 index 000000000..3c8b877d6 --- /dev/null +++ b/src/model/Lotto.js @@ -0,0 +1,11 @@ +import { Random } from "@woowacourse/mission-utils"; + +export default class Lotto { + static MIN_LOTTO_NUMBER = 1; + static MAX_LOTTO_NUMBER = 45; + + generateLottoNumbers() { + const lottoNumbers = Random.pickUniqueNumbersInRange(Lotto.MIN_LOTTO_NUMBER, Lotto.MAX_LOTTO_NUMBER, 6); + return lottoNumbers; + } +} \ No newline at end of file diff --git a/src/validators/LottoValidator.js b/src/validators/LottoValidator.js index 279d6a029..07835db6c 100644 --- a/src/validators/LottoValidator.js +++ b/src/validators/LottoValidator.js @@ -1,9 +1,8 @@ +import Lotto from "../model/Lotto"; export default class LottoValidator { static LOTTO_REGEX = /^[0-9]{1,2}(,\s*[0-9]{1,2}){5}$/; static BONUS_LOTTO_REGEX = /^[0-9]{1,2}\s*$/; - static MIN_LOTTO_NUMBER = 1; - static MAX_LOTTO_NUMBER = 45; static validatorPurchaseAmount(purchaseAmount) { if (purchaseAmount % 1000 !== 0) @@ -23,7 +22,7 @@ export default class LottoValidator { } static validatorSingleNumber(number) { - if (number < LottoValidator.MIN_LOTTO_NUMBER || number > LottoValidator.MAX_LOTTO_NUMBER) { + if (number < Lotto.MIN_LOTTO_NUMBER || number > Lotto.MAX_LOTTO_NUMBER) { throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); } } From 98f1b75a9a29b46c313783a5b92ae275a48f555b Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 22:24:54 +0900 Subject: [PATCH 07/11] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 9 +++++++++ src/model/Customer.js | 10 +++++----- src/model/Lotto.js | 2 +- src/validators/LottoValidator.js | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/App.js b/src/App.js index 7ad75f4b8..7e251810b 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,20 @@ +import Customer from "./model/Customer.js"; import LottoValidator from "./validators/LottoValidator.js"; import InputView from "./view/InputView.js"; class App { async run() { const input = new InputView(); + const customer = new Customer(); + + // 로또 구매 및 출력 const purchaseAmount = await input.readPurchaseAmount(); + customer.purchaseLotto(purchaseAmount); + customer.getLottoNumberList(); + customer.lottoPrint(); + + const winningNumbers = await input.readWinningNumbers(); const bonusNumber = await input.readBonusNumber(); const allLottoNumbers = [...winningNumbers, bonusNumber]; diff --git a/src/model/Customer.js b/src/model/Customer.js index 71a75471d..2e9942acd 100644 --- a/src/model/Customer.js +++ b/src/model/Customer.js @@ -1,20 +1,20 @@ -import Lotto from "./Lotto"; +import Lotto from "./Lotto.js"; export default class Customer { #purchaseAmount; - #lottoNumbersList; + #lottoNumbersList = []; #lottoCount; - constructor(purchaseAmount) { + purchaseLotto(purchaseAmount) { this.#purchaseAmount = purchaseAmount; this.#lottoCount = purchaseAmount/1000; } getLottoNumberList() { Array.from({ length: this.#lottoCount }).forEach(() => { - const lottoNumbers = Lotto.getLottoNumberList(); + const lottoNumbers = Lotto.generateLottoNumbers(); this.#lottoNumbersList.push(lottoNumbers); }) } - + } \ No newline at end of file diff --git a/src/model/Lotto.js b/src/model/Lotto.js index 3c8b877d6..a8dbfcb69 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -4,7 +4,7 @@ export default class Lotto { static MIN_LOTTO_NUMBER = 1; static MAX_LOTTO_NUMBER = 45; - generateLottoNumbers() { + static generateLottoNumbers() { const lottoNumbers = Random.pickUniqueNumbersInRange(Lotto.MIN_LOTTO_NUMBER, Lotto.MAX_LOTTO_NUMBER, 6); return lottoNumbers; } diff --git a/src/validators/LottoValidator.js b/src/validators/LottoValidator.js index 07835db6c..cded87b93 100644 --- a/src/validators/LottoValidator.js +++ b/src/validators/LottoValidator.js @@ -1,4 +1,4 @@ -import Lotto from "../model/Lotto"; +import Lotto from "../model/Lotto.js"; export default class LottoValidator { static LOTTO_REGEX = /^[0-9]{1,2}(,\s*[0-9]{1,2}){5}$/; From 0125d714bc79abf3925f713bec2e642dec99548a Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 22:30:38 +0900 Subject: [PATCH 08/11] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 9 +++++++-- src/model/Lotto.js | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/App.js b/src/App.js index 7e251810b..43939c233 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,5 @@ import Customer from "./model/Customer.js"; +import Lotto from "./model/Lotto.js"; import LottoValidator from "./validators/LottoValidator.js"; import InputView from "./view/InputView.js"; @@ -6,14 +7,15 @@ class App { async run() { const input = new InputView(); const customer = new Customer(); + const lotto = new Lotto(); // 로또 구매 및 출력 const purchaseAmount = await input.readPurchaseAmount(); customer.purchaseLotto(purchaseAmount); customer.getLottoNumberList(); - customer.lottoPrint(); - + + // 생성한 번호 출력 const winningNumbers = await input.readWinningNumbers(); const bonusNumber = await input.readBonusNumber(); @@ -21,6 +23,9 @@ class App { LottoValidator.validateDuplicateNumbers(allLottoNumbers); allLottoNumbers.forEach(LottoValidator.validatorSingleNumber); + lotto.setWinningAndBonusNumbers(winningNumbers, bonusNumber); + lotto.print(); + diff --git a/src/model/Lotto.js b/src/model/Lotto.js index a8dbfcb69..ec1337568 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -3,9 +3,24 @@ import { Random } from "@woowacourse/mission-utils"; export default class Lotto { static MIN_LOTTO_NUMBER = 1; static MAX_LOTTO_NUMBER = 45; + #winningNumbers; + #bonusNumber; + + setWinningAndBonusNumbers(winningNumbers, bonusNumber) { + this.#winningNumbers = winningNumbers; + this.#bonusNumber = bonusNumber; + } static generateLottoNumbers() { const lottoNumbers = Random.pickUniqueNumbersInRange(Lotto.MIN_LOTTO_NUMBER, Lotto.MAX_LOTTO_NUMBER, 6); return lottoNumbers; } + + print() { + console.log(this.#winningNumbers, this.#bonusNumber); + } + + static checkWinningNumber(LottoNumbers) { + + } } \ No newline at end of file From 7fffc867b63428136aa2411287434b3bdf950c65 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Mon, 4 Nov 2024 22:53:25 +0900 Subject: [PATCH 09/11] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=20=EB=93=B1=EC=88=98=20=ED=99=95=EC=9D=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/App.js | 2 +- src/model/Customer.js | 8 ++++++++ src/model/Lotto.js | 25 ++++++++++++++++++------- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2ccbb2f94..ef7829878 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,6 @@ - [ ] 로또 발행하기 - [x] 구매한 로또만큼 번호 발행 - [ ] 발행한 로또 출력 - - [ ] 발행한 로또 당첨 처리 + - [x] 발행한 로또 당첨 처리 - [ ] 당첨 내역 출력 - [ ] 수익률 출력 diff --git a/src/App.js b/src/App.js index 43939c233..08277a67e 100644 --- a/src/App.js +++ b/src/App.js @@ -24,7 +24,7 @@ class App { allLottoNumbers.forEach(LottoValidator.validatorSingleNumber); lotto.setWinningAndBonusNumbers(winningNumbers, bonusNumber); - lotto.print(); + customer.getLottoResults(lotto); diff --git a/src/model/Customer.js b/src/model/Customer.js index 2e9942acd..fdcb48f62 100644 --- a/src/model/Customer.js +++ b/src/model/Customer.js @@ -3,6 +3,7 @@ import Lotto from "./Lotto.js"; export default class Customer { #purchaseAmount; #lottoNumbersList = []; + #lottoResults = []; #lottoCount; purchaseLotto(purchaseAmount) { @@ -17,4 +18,11 @@ export default class Customer { }) } + getLottoResults(lotto) { + this.#lottoNumbersList.forEach(lottoNumbers => { + const rank = lotto.getLottoRank(lottoNumbers); + this.#lottoResults.push(rank); + }) + } + } \ No newline at end of file diff --git a/src/model/Lotto.js b/src/model/Lotto.js index ec1337568..a756ef963 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -3,7 +3,7 @@ import { Random } from "@woowacourse/mission-utils"; export default class Lotto { static MIN_LOTTO_NUMBER = 1; static MAX_LOTTO_NUMBER = 45; - #winningNumbers; + #winningNumbers=[]; #bonusNumber; setWinningAndBonusNumbers(winningNumbers, bonusNumber) { @@ -16,11 +16,22 @@ export default class Lotto { return lottoNumbers; } - print() { - console.log(this.#winningNumbers, this.#bonusNumber); - } - - static checkWinningNumber(LottoNumbers) { - + // return : 로또 등수 + getLottoRank(LottoNumbers) { + const winningCount = LottoNumbers.filter(number => this.#winningNumbers.includes(number)) + const actions = { + 3: () => {return 5}, + 4: () => {return 4}, + 5: () => { + if (LottoNumbers.includes(this.#bonusNumber)) + return 2; + return 3; + }, + 6: () => { return 1; }, + default: () => { return 0;} + } + const rank = (actions[winningCount] || actions.default)(); + console.log(rank); + return rank; } } \ No newline at end of file From 5b0ad094ea0b51775ebd173946feda23a7d2d640 Mon Sep 17 00:00:00 2001 From: standard-chan Date: Tue, 5 Nov 2024 00:09:05 +0900 Subject: [PATCH 10/11] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B2=B4=ED=81=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/LottoTest.js | 2 +- src/App.js | 19 ++++++++------ src/Lotto.js | 13 ++++++++- src/View/InputView.js | 4 --- src/model/Customer.js | 45 +++++++++++++++++++++++++++----- src/model/Lotto.js | 37 -------------------------- src/validators/LottoValidator.js | 36 ------------------------- 7 files changed, 63 insertions(+), 93 deletions(-) delete mode 100644 src/model/Lotto.js delete mode 100644 src/validators/LottoValidator.js diff --git a/__tests__/LottoTest.js b/__tests__/LottoTest.js index 409aaf69b..22a9ad58f 100644 --- a/__tests__/LottoTest.js +++ b/__tests__/LottoTest.js @@ -1,4 +1,4 @@ -import Lotto from "../src/Lotto"; +import Lotto from "../src/Lotto.js"; describe("로또 클래스 테스트", () => { test("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.", () => { diff --git a/src/App.js b/src/App.js index 08277a67e..9a2b85a55 100644 --- a/src/App.js +++ b/src/App.js @@ -1,13 +1,13 @@ import Customer from "./model/Customer.js"; -import Lotto from "./model/Lotto.js"; -import LottoValidator from "./validators/LottoValidator.js"; +import Lotto from "./Lotto.js"; +import LottoChecker from "./model/LottoChecker.js"; import InputView from "./view/InputView.js"; class App { async run() { const input = new InputView(); const customer = new Customer(); - const lotto = new Lotto(); + const lottoChecker = new LottoChecker(); // 로또 구매 및 출력 @@ -16,15 +16,18 @@ class App { customer.getLottoNumberList(); // 생성한 번호 출력 + customer.lottoNumbersPrint(); const winningNumbers = await input.readWinningNumbers(); + const lotto = new Lotto(winningNumbers); + const validWinningNumbers = lotto.getNumbers(); const bonusNumber = await input.readBonusNumber(); - const allLottoNumbers = [...winningNumbers, bonusNumber]; - LottoValidator.validateDuplicateNumbers(allLottoNumbers); - allLottoNumbers.forEach(LottoValidator.validatorSingleNumber); - lotto.setWinningAndBonusNumbers(winningNumbers, bonusNumber); - customer.getLottoResults(lotto); + lottoChecker.setWinningAndBonusNumbers(validWinningNumbers, bonusNumber); + customer.getLottoResults(lottoChecker); + + customer.calculateProfit(); + customer.lottoResultPrint(); diff --git a/src/Lotto.js b/src/Lotto.js index cb0b1527e..f054e8c08 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -10,9 +10,20 @@ class Lotto { if (numbers.length !== 6) { throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); } + + if (new Set(numbers).size !== numbers.length) { + throw new Error("[ERROR] 로또 당첨 번호는 중복된 값을 가질 수 없습니다."); + } + + if (numbers.some((number) => number < 1 || number > 45)) { + throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + } + + getNumbers() { + return this.#numbers; } - // TODO: 추가 기능 구현 } export default Lotto; diff --git a/src/View/InputView.js b/src/View/InputView.js index eff4895de..994af50cc 100644 --- a/src/View/InputView.js +++ b/src/View/InputView.js @@ -1,25 +1,21 @@ import { Console } from "@woowacourse/mission-utils"; -import LottoValidator from "../validators/LottoValidator.js"; export default class InputView { async readPurchaseAmount() { const purchaseAmountStr = await Console.readLineAsync("구입금액을 입력해 주세요.\n"); const purchaseAmount = Number(purchaseAmountStr); - LottoValidator.validatorPurchaseAmount(purchaseAmount); return purchaseAmount; } async readWinningNumbers() { const winningNumbers = await Console.readLineAsync("당첨 번호를 입력해 주세요.\n"); - LottoValidator.validatorLottoNumbers(winningNumbers); const winningNumbersArr = this.splitNumbers(winningNumbers); return winningNumbersArr; } async readBonusNumber() { let bonusNumber = await Console.readLineAsync("보너스 번호를 입력해 주세요.\n"); - LottoValidator.validatorBonusNumber(bonusNumber); bonusNumber = Number(bonusNumber.trim()); return bonusNumber; } diff --git a/src/model/Customer.js b/src/model/Customer.js index fdcb48f62..2552c7561 100644 --- a/src/model/Customer.js +++ b/src/model/Customer.js @@ -1,28 +1,61 @@ -import Lotto from "./Lotto.js"; +import Lotto from "../Lotto.js"; +import LottoChecker from "./LottoChecker.js"; +import { Console } from "@woowacourse/mission-utils"; export default class Customer { #purchaseAmount; #lottoNumbersList = []; - #lottoResults = []; + #lottoRankResults = [0, 0, 0, 0, 0, 0]; // index = 결과 등수 #lottoCount; + #profitRate; + #profit = 0; + + #valid(purchaseAmount) { + if (purchaseAmount % 1000 !== 0) + throw new Error("[ERROR] 구매금액은 1000원 단위이어야합니다."); + } purchaseLotto(purchaseAmount) { + this.#valid(purchaseAmount); this.#purchaseAmount = purchaseAmount; this.#lottoCount = purchaseAmount/1000; } getLottoNumberList() { Array.from({ length: this.#lottoCount }).forEach(() => { - const lottoNumbers = Lotto.generateLottoNumbers(); + const lottoNumbers = LottoChecker.generateLottoNumbers(); this.#lottoNumbersList.push(lottoNumbers); }) } - getLottoResults(lotto) { + getLottoResults(lottoChecker) { this.#lottoNumbersList.forEach(lottoNumbers => { - const rank = lotto.getLottoRank(lottoNumbers); - this.#lottoResults.push(rank); + const rank = lottoChecker.getLottoRank(lottoNumbers); + this.#lottoRankResults[rank] += 1; + }) + } + + lottoNumbersPrint() { + Console.print(`${this.#lottoCount}개를 구매했습니다.\n`); + this.#lottoNumbersList.forEach((lottoNumbers) => { + Console.print(`${lottoNumbers}\n`); }) } + calculateProfit() { + const prizeAmounts = [0, 2000000000, 30000000, 1500000, 50000, 5000]; + + this.#lottoRankResults.forEach((count, rank) => { + this.#profit += count * prizeAmounts[rank]; + }); + + this.#profitRate = Math.round((this.#profit / this.#purchaseAmount) * 10000) / 100; + } + + lottoResultPrint() { + Console.print("당첨 통계\n---\n"); + Console.print(`3개 일치 (5,000원) - ${this.#lottoRankResults[5]}개\n4개 일치 (50,000원) - ${this.#lottoRankResults[4]}개\n5개 일치 (1,500,000원) - ${this.#lottoRankResults[3]}개\n5개 일치, 보너스 볼 일치 (30,000,000원) - ${this.#lottoRankResults[2]}개\n6개 일치 (2,000,000,000원) - ${this.#lottoRankResults[1]}개\n총 수익률은 ${this.#profitRate}%입니다.\n + `) + } + } \ No newline at end of file diff --git a/src/model/Lotto.js b/src/model/Lotto.js deleted file mode 100644 index a756ef963..000000000 --- a/src/model/Lotto.js +++ /dev/null @@ -1,37 +0,0 @@ -import { Random } from "@woowacourse/mission-utils"; - -export default class Lotto { - static MIN_LOTTO_NUMBER = 1; - static MAX_LOTTO_NUMBER = 45; - #winningNumbers=[]; - #bonusNumber; - - setWinningAndBonusNumbers(winningNumbers, bonusNumber) { - this.#winningNumbers = winningNumbers; - this.#bonusNumber = bonusNumber; - } - - static generateLottoNumbers() { - const lottoNumbers = Random.pickUniqueNumbersInRange(Lotto.MIN_LOTTO_NUMBER, Lotto.MAX_LOTTO_NUMBER, 6); - return lottoNumbers; - } - - // return : 로또 등수 - getLottoRank(LottoNumbers) { - const winningCount = LottoNumbers.filter(number => this.#winningNumbers.includes(number)) - const actions = { - 3: () => {return 5}, - 4: () => {return 4}, - 5: () => { - if (LottoNumbers.includes(this.#bonusNumber)) - return 2; - return 3; - }, - 6: () => { return 1; }, - default: () => { return 0;} - } - const rank = (actions[winningCount] || actions.default)(); - console.log(rank); - return rank; - } -} \ No newline at end of file diff --git a/src/validators/LottoValidator.js b/src/validators/LottoValidator.js deleted file mode 100644 index cded87b93..000000000 --- a/src/validators/LottoValidator.js +++ /dev/null @@ -1,36 +0,0 @@ -import Lotto from "../model/Lotto.js"; - -export default class LottoValidator { - static LOTTO_REGEX = /^[0-9]{1,2}(,\s*[0-9]{1,2}){5}$/; - static BONUS_LOTTO_REGEX = /^[0-9]{1,2}\s*$/; - - static validatorPurchaseAmount(purchaseAmount) { - if (purchaseAmount % 1000 !== 0) - throw new Error("[ERROR] 구매금액은 1000원 단위이어야합니다."); - } - - static validatorLottoNumbers(numbers) { - if (! LottoValidator.LOTTO_REGEX.test(numbers)) { - throw new Error("[ERROR] 당첨 번호는 총 6개의 최대 2자리 숫자로 ','로 구분되어있어야 합니다."); - } - } - - static validatorBonusNumber(bonusNumber) { - if (! LottoValidator.BONUS_LOTTO_REGEX.test(bonusNumber)) { - throw new Error("[ERROR] 보너스 번호는 하나의 숫자만 입력되어야 합니다."); - } - } - - static validatorSingleNumber(number) { - if (number < Lotto.MIN_LOTTO_NUMBER || number > Lotto.MAX_LOTTO_NUMBER) { - throw new Error("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); - } - } - - static validateDuplicateNumbers(winningLottoNumbers) { - const uniqueNumbers = new Set(winningLottoNumbers); - if (uniqueNumbers.size !== winningLottoNumbers.length) { - throw new Error("[ERROR] 로또 당첨 번호는 중복된 값을 가질 수 없습니다."); - } - } -} \ No newline at end of file From e3b86b30ab89c51695ef3359c4fac7b30cb2249a Mon Sep 17 00:00:00 2001 From: standard-chan Date: Tue, 5 Nov 2024 00:11:14 +0900 Subject: [PATCH 11/11] =?UTF-8?q?docs=20:=20=EB=AC=B8=EC=84=9C=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- src/View/outputView.js | 6 ++++++ src/model/LottoChecker.js | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/View/outputView.js create mode 100644 src/model/LottoChecker.js diff --git a/README.md b/README.md index ef7829878..3103de9eb 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ - [ ] 로또 발행하기 - [x] 구매한 로또만큼 번호 발행 - - [ ] 발행한 로또 출력 + - [x] 발행한 로또 출력 - [x] 발행한 로또 당첨 처리 - - [ ] 당첨 내역 출력 - - [ ] 수익률 출력 + - [x] 당첨 내역 출력 + - [x] 수익률 출력 diff --git a/src/View/outputView.js b/src/View/outputView.js new file mode 100644 index 000000000..4be72301e --- /dev/null +++ b/src/View/outputView.js @@ -0,0 +1,6 @@ +import { Console } from "@woowacourse/mission-utils"; + +export default class outputView { + + static +} \ No newline at end of file diff --git a/src/model/LottoChecker.js b/src/model/LottoChecker.js new file mode 100644 index 000000000..5ebb4a8c7 --- /dev/null +++ b/src/model/LottoChecker.js @@ -0,0 +1,34 @@ +import { Random } from "@woowacourse/mission-utils"; + +export default class LottoChecker { + #winningNumbers=[]; + #bonusNumber; + + setWinningAndBonusNumbers(winningNumbers, bonusNumber) { + this.#winningNumbers = winningNumbers; + this.#bonusNumber = bonusNumber; + } + + static generateLottoNumbers() { + const lottoNumbers = Random.pickUniqueNumbersInRange(1, 45, 6); + return lottoNumbers; + } + + // return : 로또 등수 + getLottoRank(LottoNumbers) { + const winningCount = LottoNumbers.filter(number => this.#winningNumbers.includes(number)) + const actions = { + 3: () => {return 5}, + 4: () => {return 4}, + 5: () => { + if (LottoNumbers.includes(this.#bonusNumber)) + return 2; + return 3; + }, + 6: () => { return 1; }, + default: () => { return 0;} + } + const rank = (actions[winningCount.length] || actions.default)(); + return rank; + } +} \ No newline at end of file