From 6c7a96def281c03794dde10e2eda4676259527cd Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 13:35:22 +0900 Subject: [PATCH 01/59] initial commit --- src/App.js | 9 ++++++++- src/Lotto.js | 2 +- src/index.js | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/App.js b/src/App.js index 091aa0a5d..f85fb6c95 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,12 @@ +import LottoController from './controller/LottoController'; + class App { - async run() {} + constructor() { + this.lottoController = new LottoController(); + } + async run() { + this.lottoController.runLotto(); + } } export default App; diff --git a/src/Lotto.js b/src/Lotto.js index cb0b1527e..1164a3f81 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -8,7 +8,7 @@ class Lotto { #validate(numbers) { if (numbers.length !== 6) { - throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); + throw new Error('[ERROR] 로또 번호는 6개여야 합니다.'); } } diff --git a/src/index.js b/src/index.js index 02a1d389e..9daefc93f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -import App from "./App.js"; +import App from './App.js'; const app = new App(); await app.run(); From 30a006a56ad6852a635f8d0c4dc6fa6ae613e4eb Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 13:35:45 +0900 Subject: [PATCH 02/59] =?UTF-8?q?docs(README):=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=ED=95=A0=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/README.md b/README.md index 15bb106b5..61992893f 100644 --- a/README.md +++ b/README.md @@ -1 +1,65 @@ # javascript-lotto-precourse + +  + +  + +# ✅ 구현할 기능 목록 + +간단한 로또 발매기를 구현한다. + +  + +### 🟢 [입력] 로또 구입 금액을 입력받는다. + +#### ㄴ validation + +- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다. +- 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나우어 떨어지지 않는 경우 예외 처리한다. + +  + +  + +### 🟢 [출력] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. + +  + +  + +### 🟢 [입력] 당첨번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. + +#### ㄴ validation + +- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다. + +  + +  + +### 🟢 [입력] 보너스 번호를 입력 받는다. + +#### ㄴ validation + +- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다. + +  + +  + +### 🟢 [출력] 당첨 내역을 출력한다. + +<출력 예시> +당첨 통계 + +\--- + +3개 일치 (5,000원) - 1개 + +  + +  + +### 🟢 [출력] 총 수익률을 출력한다. + +수익률은 소수점 둘쨰 자리에서 반올림 한다. (ex. 100.0%, 51.5%, 1,000,000.0%) From e3ec6a21d32611e9cc3678963fe7b5a68d2e802e Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:07:30 +0900 Subject: [PATCH 03/59] =?UTF-8?q?feat(constants):=20inputMessages=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/inputMessages.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/constants/inputMessages.js diff --git a/src/constants/inputMessages.js b/src/constants/inputMessages.js new file mode 100644 index 000000000..9b20fa304 --- /dev/null +++ b/src/constants/inputMessages.js @@ -0,0 +1,7 @@ +const INPUT_MESSAGES = { + WHAT_PURCHASE_AMOUNT: '구매금액을 입력해주세요. \n => ', + WINNING_NUMBER: '당첨번호를 입력해주세요. \n => ', + BONUS_NUMBER: '보너스번호를 입력해주세요. \n => ', +}; + +export default INPUT_MESSAGES; From 6464421a10b138e5abafb891d1a83244164eddf8 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:09:01 +0900 Subject: [PATCH 04/59] =?UTF-8?q?feat(InputView):=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EB=B0=9B=EC=9D=84=20=EA=B0=92=20=EB=82=B4=EC=9A=A9=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/InputView.js | 18 ++++++++++++++++++ 1 file changed, 18 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..fbecb1cff --- /dev/null +++ b/src/view/InputView.js @@ -0,0 +1,18 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; +import INPUT_MESSAGES from '../constants/inputMessages.js'; + +const InputView = { + async readPurchaseAmount() { + return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.WHAT_PURCHASE_AMOUNT); + }, + + async readWinningNumber() { + return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.WINNING_NUMBER); + }, + + async readBonusNumber() { + return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.BONUS_NUMBER); + }, +}; + +export default InputView; From 423754823c1832af97ef5a75b2b75f82e4323207 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:09:44 +0900 Subject: [PATCH 05/59] =?UTF-8?q?feat(controller):=20[=EC=9E=85=EB=A0=A5]?= =?UTF-8?q?=20=EB=A1=9C=EB=98=90=20=EA=B5=AC=EC=9E=85=20=EA=B8=88=EC=95=A1?= =?UTF-8?q?=EC=9D=84=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 2 +- src/controller/LottoController.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/controller/LottoController.js diff --git a/src/App.js b/src/App.js index f85fb6c95..40566670d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,4 @@ -import LottoController from './controller/LottoController'; +import LottoController from './controller/LottoController.js'; class App { constructor() { diff --git a/src/controller/LottoController.js b/src/controller/LottoController.js new file mode 100644 index 000000000..3625c411a --- /dev/null +++ b/src/controller/LottoController.js @@ -0,0 +1,12 @@ +import InputPurchaseModule from '../modules/InputPurchaseModule.js'; + +class LottoController { + constructor() { + this.inputPurchaseModule = new InputPurchaseModule(); + } + async runLotto() { + const input = await this.inputPurchaseModule.inputPurchaseAmount(); + } +} + +export default LottoController; From b6b7dd5241ca797972d8358d2b3ff8172dda3540 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:46:45 +0900 Subject: [PATCH 06/59] =?UTF-8?q?feat(module)=20:=20[=EC=9E=85=EB=A0=A5]?= =?UTF-8?q?=20=EB=A1=9C=EB=98=90=20=EA=B5=AC=EC=9E=85=20=EA=B8=88=EC=95=A1?= =?UTF-8?q?=EC=9D=84=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=EB=8B=A4.=20wi?= =?UTF-8?q?th=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputPurchaseModule.js | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/modules/InputPurchaseModule.js diff --git a/src/modules/InputPurchaseModule.js b/src/modules/InputPurchaseModule.js new file mode 100644 index 000000000..9a9a63a87 --- /dev/null +++ b/src/modules/InputPurchaseModule.js @@ -0,0 +1,49 @@ +import ERROR_MESSAGES from '../constants/errorMessages.js'; +import validation from '../validation/validation.js'; +import InputView from '../view/InputView.js'; +import OutputView from '../view/OutputView.js'; + +class InputPurchaseModule { + constructor() { + this.validation = new validation(); + } + + async inputPurchaseAmount() { + return this.repeatInput(); + } + + async inputAndValidation() { + const input = await InputView.readPurchaseAmount(); + this.validatatePrice(input); + return input; + } + + validatatePrice(value) { + this.validation.empty(value); + const regExpPattern = /\d/; + this.validation.regularExpression(value, regExpPattern); + this.validation.nagativeNumber(value); + this.validation.limitDigits(value); + this.validation.thousandUnit(value); + } + + async errorCatch() { + try { + const validatedInput = await this.inputAndValidation(); + return validatedInput; + } catch (error) { + OutputView.printError(error); + return false; + } + } + + async repeatInput() { + for (let i = 0; i < 10; i++) { + const vlaidatedInput = await this.errorCatch(); + if (vlaidatedInput) return vlaidatedInput; + if (i === 5) throw new Error(ERROR_MESSAGES.ENTERED_MORE_FIVE_TIMES); + } + } +} + +export default InputPurchaseModule; From b59e2daa2de430e4468c2cc0a171c6063060c657 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:48:20 +0900 Subject: [PATCH 07/59] =?UTF-8?q?feat(constants):=20errorMessages=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/errorMessages.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/errorMessages.js diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js new file mode 100644 index 000000000..0dc8d6293 --- /dev/null +++ b/src/constants/errorMessages.js @@ -0,0 +1,13 @@ +const ERROR_MESSAGES = { + EMPTY_VALUE: '[ERROR] 값이 존재하지 않습니다. 다시 입력해주세요.', + REGEXP_TEST: '[ERROR] 형식이 잘 못되었습니다. 다시 입력해주세요.', + START_COMMA: '[ERROR] 입력이 콤마(,)부터 시작할 수 없습니다. 다시 입력해주세요.', + END_COMMA: '[ERROR] 입력 끝에 콤마(,)로 끝날 수 없습니다. 다시 입력해주세요.', + ENTERED_MORE_FIVE_TIMES: '[ERROR] 5회 이상 잘못 입력하여 종료되없습니다. 다시 실행해주세요.', + LIMIT_DIGITS: '[ERROR] 최소 4자리 숫자부터 6자리 숫자까지 입력 가능합니다. 다시 입력해주세요.', + THOUSAND_UNIT: + '[ERROR] 로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다. 다시 입력해주세요.', + NAGATIVE_NUMBER: '[ERROR] 음수가 입력될 수 없습니다. 다시 입력해주세요.', +}; + +export default ERROR_MESSAGES; From 6b2b9200e24abde45c17221d7a29af9fab506435 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:49:02 +0900 Subject: [PATCH 08/59] =?UTF-8?q?feat(validation):=20=EC=97=AC=EB=9F=AC?= =?UTF-8?q?=EA=B0=80=EC=A7=80=20=EC=83=81=ED=99=A9=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EB=90=A0=20validtaion=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/validation/validation.js | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/validation/validation.js diff --git a/src/validation/validation.js b/src/validation/validation.js new file mode 100644 index 000000000..9a37dde46 --- /dev/null +++ b/src/validation/validation.js @@ -0,0 +1,52 @@ +import ERROR_MESSAGES from '../constants/errorMessages.js'; + +class validation { + empty(value) { + if (value === '') throw new Error(ERROR_MESSAGES.EMPTY_VALUE); + return true; + } + + regularExpression(value, regExp) { + const regExpTest = regExp.test(value); + if (!regExpTest) throw new Error(ERROR_MESSAGES.REGEXP_TEST); + return true; + } + + startedComma(value) { + const regExp = /^,/; + const regExpTest = regExp.test(value); + if (regExpTest) throw new Error(ERROR_MESSAGES.START_COMMA); + return true; + } + + endedComma(value) { + const regExp = /,$/; + const regExpTest = regExp.test(value); + if (regExpTest) throw new Error(ERROR_MESSAGES.END_COMMA); + return true; + } + + nagativeNumber(value) { + const changeTypeNumber = Number(value); + if (0 > changeTypeNumber) throw new Error(ERROR_MESSAGES.NAGATIVE_NUMBER); + return true; + } + + limitDigits(value) { + const regExp = /\d{4,6}$/; + const regExpTest = regExp.test(value); + if (!regExpTest) throw new Error(ERROR_MESSAGES.LIMIT_DIGITS); + return true; + } + + thousandUnit(value) { + const changeTypeNumber = Number(value); + const target = changeTypeNumber / 1000; + const isInteger = Number.isInteger(target); + if (!isInteger) throw new Error(ERROR_MESSAGES.THOUSAND_UNIT); + if (0 < target && target > 101) throw new Error(ERROR_MESSAGES.THOUSAND_UNIT); + return true; + } +} + +export default validation; From b51406fe0cbdc9fb670bba792418fb411bc1122d Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:49:46 +0900 Subject: [PATCH 09/59] =?UTF-8?q?feat(constants):=20outputMessages=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/outputMessages.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/constants/outputMessages.js diff --git a/src/constants/outputMessages.js b/src/constants/outputMessages.js new file mode 100644 index 000000000..fef8942dc --- /dev/null +++ b/src/constants/outputMessages.js @@ -0,0 +1,7 @@ +const OUTPUT_MESSAGES = { + PURCHASE_NUMBER: '개를 구매했습니다.', + WINNING_STATISTICS: '당첨통계\n--- ', + TOTAL_RETURN: '총 수익률은 ', +}; + +export default OUTPUT_MESSAGES; From b5e1cffd5b780540229697afde41265c0e9c8875 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:51:11 +0900 Subject: [PATCH 10/59] =?UTF-8?q?feat(OutputView):=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EB=90=A0=20=EB=82=B4=EC=9A=A9=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/OutputView.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/view/OutputView.js diff --git a/src/view/OutputView.js b/src/view/OutputView.js new file mode 100644 index 000000000..31ecfc174 --- /dev/null +++ b/src/view/OutputView.js @@ -0,0 +1,26 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; +import OUTPUT_MESSAGES from '../constants/outputMessages.js'; + +const OutputView = { + async printPurchaseNumber() { + return MissionUtils.Console.print(OUTPUT_MESSAGES.PURCHASE_NUMBER); + }, + + async printWinningStatistics() { + return MissionUtils.Console.print(OUTPUT_MESSAGES.WINNING_STATISTICS); + }, + + async printTotalReturn() { + return MissionUtils.Console.print(OUTPUT_MESSAGES.TOTAL_RETURN); + }, + + async printError(error) { + return MissionUtils.Console.print(error); + }, + + async printSpace() { + return MissionUtils.Console.print(''); + }, +}; + +export default OutputView; From 4a3c8db43960b4137eebd0a85bd201490a68f706 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 14:59:24 +0900 Subject: [PATCH 11/59] =?UTF-8?q?fix(module):=20awiat=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputPurchaseModule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/InputPurchaseModule.js b/src/modules/InputPurchaseModule.js index 9a9a63a87..529d002ac 100644 --- a/src/modules/InputPurchaseModule.js +++ b/src/modules/InputPurchaseModule.js @@ -9,7 +9,7 @@ class InputPurchaseModule { } async inputPurchaseAmount() { - return this.repeatInput(); + return await this.repeatInput(); } async inputAndValidation() { From 328ea43dc1093f770926e6d69ee5ae02f1808c0c Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 15:29:47 +0900 Subject: [PATCH 12/59] =?UTF-8?q?fix(module):=20InputPurchaseModule?= =?UTF-8?q?=EC=9D=B4=20=EA=B5=AC=EB=A7=A4=EC=88=98=EB=9F=89=EC=9D=84=20ret?= =?UTF-8?q?urn=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EC=97=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputPurchaseModule.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/InputPurchaseModule.js b/src/modules/InputPurchaseModule.js index 529d002ac..a8540adf1 100644 --- a/src/modules/InputPurchaseModule.js +++ b/src/modules/InputPurchaseModule.js @@ -9,7 +9,10 @@ class InputPurchaseModule { } async inputPurchaseAmount() { - return await this.repeatInput(); + const validatedPurchaseAmount = await this.repeatInput(); + const changgeTypeNumber = Number(validatedPurchaseAmount); + OutputView.printSpace(); + return changgeTypeNumber / 1000; } async inputAndValidation() { From c1f4bf8103caf34d1d1d50a76c5293eca1cce88e Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 15:30:38 +0900 Subject: [PATCH 13/59] =?UTF-8?q?feat(contorller):=20[=EC=B6=9C=EB=A0=A5]?= =?UTF-8?q?=20=EB=B0=9C=ED=96=89=ED=95=9C=20=EB=A1=9C=EB=98=90=20=EC=88=98?= =?UTF-8?q?=EB=9F=89=20=EB=B0=8F=20=EB=B2=88=ED=98=B8=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/LottoController.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/controller/LottoController.js b/src/controller/LottoController.js index 3625c411a..68090c962 100644 --- a/src/controller/LottoController.js +++ b/src/controller/LottoController.js @@ -1,11 +1,25 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; import InputPurchaseModule from '../modules/InputPurchaseModule.js'; +import OutputView from '../view/OutputView.js'; class LottoController { constructor() { this.inputPurchaseModule = new InputPurchaseModule(); } async runLotto() { - const input = await this.inputPurchaseModule.inputPurchaseAmount(); + const purchasQuantity = await this.inputPurchaseModule.inputPurchaseAmount(); + const lottoNumber = this.printRandomNumber(purchasQuantity); + } + + printRandomNumber(purchasQuantity) { + OutputView.printPurchaseNumber(purchasQuantity); + let lottoNumberArrayss = []; + for (let i = 0; i < purchasQuantity; i++) { + const lottoNumber = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6); + OutputView.printLottoNumber(lottoNumber); + lottoNumberArrayss = [...lottoNumberArrayss, lottoNumber]; + } + return lottoNumberArrayss; } } From 6ae00354a424df6d8aa5d574b9d13df8076d6537 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 15:33:30 +0900 Subject: [PATCH 14/59] =?UTF-8?q?feat(OutputView):=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=BC=EB=B6=80=20=EC=BD=94=EB=93=9C=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 - 수정 : printPurchaseNumber(purchasQuantity) 수량을 매개변수로 받아서 출력되도록 만듬. - 추가 : printLottoNumber(value) 로또번호를 그대로 받아 바로 출력해주도록 만듬. --- src/view/OutputView.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/view/OutputView.js b/src/view/OutputView.js index 31ecfc174..1d80fc191 100644 --- a/src/view/OutputView.js +++ b/src/view/OutputView.js @@ -2,8 +2,8 @@ import { MissionUtils } from '@woowacourse/mission-utils'; import OUTPUT_MESSAGES from '../constants/outputMessages.js'; const OutputView = { - async printPurchaseNumber() { - return MissionUtils.Console.print(OUTPUT_MESSAGES.PURCHASE_NUMBER); + async printPurchaseNumber(purchasQuantity) { + return MissionUtils.Console.print(`${purchasQuantity}${OUTPUT_MESSAGES.PURCHASE_NUMBER}`); }, async printWinningStatistics() { @@ -14,6 +14,10 @@ const OutputView = { return MissionUtils.Console.print(OUTPUT_MESSAGES.TOTAL_RETURN); }, + async printLottoNumber(value) { + return MissionUtils.Console.print(value); + }, + async printError(error) { return MissionUtils.Console.print(error); }, From d9cd286cc0f62abeb6a2854994a5496da4b314dd Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 15:39:43 +0900 Subject: [PATCH 15/59] =?UTF-8?q?feat(controller):=20[=EC=B6=9C=EB=A0=A5]?= =?UTF-8?q?=20=EB=B0=9C=ED=96=89=ED=95=9C=20=EB=A1=9C=EB=98=90=20=EC=88=98?= =?UTF-8?q?=EB=9F=89=20=EB=B0=8F=20=EB=B2=88=ED=98=B8=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=9C=EB=8B=A4.=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EB=8A=94=20=EC=98=A4=EB=A6=84=EC=B0=A8=EC=88=9C?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=A0=95=EB=A0=AC=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EB=B3=B4=EC=97=AC=EC=A4=80=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/LottoController.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/controller/LottoController.js b/src/controller/LottoController.js index 68090c962..2f0238d32 100644 --- a/src/controller/LottoController.js +++ b/src/controller/LottoController.js @@ -16,8 +16,9 @@ class LottoController { let lottoNumberArrayss = []; for (let i = 0; i < purchasQuantity; i++) { const lottoNumber = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6); - OutputView.printLottoNumber(lottoNumber); - lottoNumberArrayss = [...lottoNumberArrayss, lottoNumber]; + const ascendingOrder = lottoNumber.sort((a, b) => a - b); + OutputView.printLottoNumber(ascendingOrder); + lottoNumberArrayss = [...lottoNumberArrayss, ascendingOrder]; } return lottoNumberArrayss; } From 03cb4f53a0f690b6d53fbc088b10f62c3ed9b454 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 16:28:45 +0900 Subject: [PATCH 16/59] =?UTF-8?q?feat(module):=20=EA=B2=80=EC=A6=9D?= =?UTF-8?q?=EB=90=9C=20Lotto=EB=B2=88=ED=98=B8=20=EC=B5=9C=EC=A2=85=20retu?= =?UTF-8?q?rn=20=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=A7=8C=EB=93=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputWinningModule.js | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/modules/InputWinningModule.js diff --git a/src/modules/InputWinningModule.js b/src/modules/InputWinningModule.js new file mode 100644 index 000000000..2e938b8c7 --- /dev/null +++ b/src/modules/InputWinningModule.js @@ -0,0 +1,50 @@ +import ERROR_MESSAGES from '../constants/errorMessages.js'; +import validation from '../validation/validation.js'; +import InputView from '../view/InputView.js'; +import OutputView from '../view/OutputView.js'; + +class InputWinningModule { + constructor() { + this.validation = new validation(); + } + async inputWinningNumber() { + const validatedLottoNumber = await this.repeatInput(); + const changgeTypeArray = validatedLottoNumber.split(',').map((string) => Number(string)); + OutputView.printSpace(); + return changgeTypeArray; + } + + async inputAndValidation() { + const input = await InputView.readWinningNumber(); + this.validateWinningNumber(input); + return input; + } + + validateWinningNumber(value) { + this.validation.empty(value); + this.validation.startedComma(value); + this.validation.endedComma(value); + const regExpPattern = /^\d(,\s?\d)*/; + this.validation.regularExpression(value, regExpPattern); + } + + async errorCatch() { + try { + const validatedInput = await this.inputAndValidation(); + return validatedInput; + } catch (error) { + OutputView.printError(error); + return false; + } + } + + async repeatInput() { + for (let i = 0; i < 10; i++) { + const vlaidatedInput = await this.errorCatch(); + if (vlaidatedInput) return vlaidatedInput; + if (i === 5) throw new Error(ERROR_MESSAGES.ENTERED_MORE_FIVE_TIMES); + } + } +} + +export default InputWinningModule; From 25899e57811ee969439677b2923dd86c74603968 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 16:37:04 +0900 Subject: [PATCH 17/59] =?UTF-8?q?feat(module):=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=EB=84=98=EB=B2=84=EB=A5=BC=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EB=B0=9B=EA=B3=A0=20validation=20=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputBonusModule.js | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/modules/InputBonusModule.js diff --git a/src/modules/InputBonusModule.js b/src/modules/InputBonusModule.js new file mode 100644 index 000000000..25635ca81 --- /dev/null +++ b/src/modules/InputBonusModule.js @@ -0,0 +1,49 @@ +import ERROR_MESSAGES from '../constants/errorMessages.js'; +import validation from '../validation/validation.js'; +import InputView from '../view/InputView.js'; +import OutputView from '../view/OutputView.js'; + +class InputBonusModule { + constructor() { + this.validation = new validation(); + } + + async inputBonusNumber() { + const validatedBonusNumber = await this.repeatInput(); + const changgeTypeNumber = Number(validatedPurchaseAmount); + OutputView.printSpace(); + return changgeTypeNumber; + } + + async inputAndValidation() { + const input = await InputView.readBonusNumber(); + this.validateBonusNumber(input); + return input; + } + + validateBonusNumber(value) { + this.validation.empty(value); + const regExpPattern = /\d{1,2}/; + this.validation.regularExpression(value, regExpPattern); + } + + async errorCatch() { + try { + const validatedInput = await this.inputAndValidation(); + return validatedInput; + } catch (error) { + OutputView.printError(error); + return false; + } + } + + async repeatInput() { + for (let i = 0; i < 10; i++) { + const vlaidatedInput = await this.errorCatch(); + if (vlaidatedInput) return vlaidatedInput; + if (i === 5) throw new Error(ERROR_MESSAGES.ENTERED_MORE_FIVE_TIMES); + } + } +} + +export default InputBonusModule; From 1bb4cd7f44a8f990912259158505dcfedf5ef592 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 16:37:37 +0900 Subject: [PATCH 18/59] =?UTF-8?q?feat(controller):=20[=EC=9E=85=EB=A0=A5]?= =?UTF-8?q?=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EB=B0=9B=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/LottoController.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/controller/LottoController.js b/src/controller/LottoController.js index 2f0238d32..1189e7514 100644 --- a/src/controller/LottoController.js +++ b/src/controller/LottoController.js @@ -1,14 +1,22 @@ import { MissionUtils } from '@woowacourse/mission-utils'; -import InputPurchaseModule from '../modules/InputPurchaseModule.js'; import OutputView from '../view/OutputView.js'; +import InputPurchaseModule from '../modules/InputPurchaseModule.js'; +import InputWinningModule from '../modules/InputWinningModule.js'; +import InputBonusModule from '../modules/InputBonusModule.js'; class LottoController { constructor() { this.inputPurchaseModule = new InputPurchaseModule(); + this.inputWinningModule = new InputWinningModule(); + this.inputBonusModule = new InputBonusModule(); } + async runLotto() { const purchasQuantity = await this.inputPurchaseModule.inputPurchaseAmount(); const lottoNumber = this.printRandomNumber(purchasQuantity); + const winningNumber = await this.inputWinningModule.inputWinningNumber(); + const bonusNumber = await this.inputBonusModule.inputBonusNumber(); + console.log(bonusNumber); } printRandomNumber(purchasQuantity) { @@ -20,6 +28,7 @@ class LottoController { OutputView.printLottoNumber(ascendingOrder); lottoNumberArrayss = [...lottoNumberArrayss, ascendingOrder]; } + OutputView.printSpace(); return lottoNumberArrayss; } } From f4943c4d7961402684866a8050cfe6742faf7213 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 16:53:37 +0900 Subject: [PATCH 19/59] =?UTF-8?q?feat(constants):=20outputMessages=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/outputMessages.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/constants/outputMessages.js b/src/constants/outputMessages.js index fef8942dc..87da9702e 100644 --- a/src/constants/outputMessages.js +++ b/src/constants/outputMessages.js @@ -1,7 +1,14 @@ const OUTPUT_MESSAGES = { PURCHASE_NUMBER: '개를 구매했습니다.', WINNING_STATISTICS: '당첨통계\n--- ', + MATCHED_THREE: '3개 일치 (5,000원) - ', + MATCHED_FOUR: '4개 일치 (50,000원) - ', + MATCHED_FIVE: '5개 일치 (1,500,000원) - ', + MATCHED_FIVE_BONUS: '5개 일치 (30,000,000원) - ', + MATCHED_SIX: '6개 일치 (2,000,000,000원) - ', + PRINT_QUANTITY: '개', TOTAL_RETURN: '총 수익률은 ', + TOTAL_RETURN_PERCENTAGE: '% 입니다.', }; export default OUTPUT_MESSAGES; From a286cfcdc3b413b9c4ba6543c5bcbb7982e676a9 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 25 Nov 2024 16:54:12 +0900 Subject: [PATCH 20/59] =?UTF-8?q?feat(OutputView):=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20=EB=82=B4=EC=9A=A9=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/OutputView.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/view/OutputView.js b/src/view/OutputView.js index 1d80fc191..ab6c7e02f 100644 --- a/src/view/OutputView.js +++ b/src/view/OutputView.js @@ -6,12 +6,28 @@ const OutputView = { return MissionUtils.Console.print(`${purchasQuantity}${OUTPUT_MESSAGES.PURCHASE_NUMBER}`); }, - async printWinningStatistics() { - return MissionUtils.Console.print(OUTPUT_MESSAGES.WINNING_STATISTICS); + async printWinningStatistics(three, four, five, fiveAndBonus, six) { + MissionUtils.Console.print( + `${OUTPUT_MESSAGES.MATCHED_THREE}${three}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + ); + MissionUtils.Console.print( + `${OUTPUT_MESSAGES.MATCHED_FOUR}${four}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + ); + MissionUtils.Console.print( + `${OUTPUT_MESSAGES.MATCHED_FIVE}${five}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + ); + MissionUtils.Console.print( + `${OUTPUT_MESSAGES.MATCHED_FIVE_BONUS}${fiveAndBonus}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + ); + MissionUtils.Console.print( + `${OUTPUT_MESSAGES.MATCHED_SIX}${six}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + ); }, - async printTotalReturn() { - return MissionUtils.Console.print(OUTPUT_MESSAGES.TOTAL_RETURN); + async printTotalReturn(percentage) { + return MissionUtils.Console.print( + `${OUTPUT_MESSAGES.TOTAL_RETURN}${percentage}${OUTPUT_MESSAGES.TOTAL_RETURN_PERCENTAGE}` + ); }, async printLottoNumber(value) { From bd8d4b9647228f2dabce1de793b97f9c9e9c1fe1 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Wed, 27 Nov 2024 00:27:52 +0900 Subject: [PATCH 21/59] =?UTF-8?q?=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=205?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EB=82=B4=20=EA=B5=AC=ED=98=84=EC=9D=84=20?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EB=AA=BB=ED=95=A8=20=3D=3D=3D=3D=3D=3D=3D?= =?UTF-8?q?=3D=3D=3D=3D=3D=3D=3D=3D=3D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 61992893f..384410e86 100644 --- a/README.md +++ b/README.md @@ -63,3 +63,5 @@ ### 🟢 [출력] 총 수익률을 출력한다. 수익률은 소수점 둘쨰 자리에서 반올림 한다. (ex. 100.0%, 51.5%, 1,000,000.0%) + +- From 27a258f336724ec90cd6bdb898d44acdf173cc2c Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 22:23:13 +0900 Subject: [PATCH 22/59] =?UTF-8?q?chroe:=20LottoController=20=ED=95=9C?= =?UTF-8?q?=EC=A4=84=EB=A1=9C=20=EB=A7=8C=EB=93=A4=EC=97=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index 40566670d..8b0404c4d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,8 @@ import LottoController from './controller/LottoController.js'; class App { - constructor() { - this.lottoController = new LottoController(); - } async run() { - this.lottoController.runLotto(); + await new LottoController().runLotto(); } } From b771a16e7d9476cf87d06a309edcd9563dda159a Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 23:19:59 +0900 Subject: [PATCH 23/59] =?UTF-8?q?feat(constants):=20errorMessage=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=EC=A0=9C=EA=B1=B0,=20ERROR=5FMESSAGES=20?= =?UTF-8?q?=ED=82=A4=EA=B0=92=20=EC=83=81=EC=88=98=EB=AA=85=EC=B9=AD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=B9=B4=EB=A9=9C=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20Import=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20export=EB=AC=B8=EC=9D=B4=20{}=ED=98=95?= =?UTF-8?q?=ED=83=9C=EB=A1=9C=20=EC=97=AC=EB=9F=AC=EA=B0=80=EC=A7=80?= =?UTF-8?q?=EB=A5=BC=20export=20=ED=95=98=EB=8A=94=20=EA=B2=83=EC=9D=B4?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/errorMessages.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index 0dc8d6293..deb7d0e43 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -1,13 +1,18 @@ +const ERROR_PREFIX = '[ERROR]'; + +const createMsg = (msg) => `${ERROR_PREFIX} ${msg} ${'다시 입력해주세요.'}\n`; + const ERROR_MESSAGES = { - EMPTY_VALUE: '[ERROR] 값이 존재하지 않습니다. 다시 입력해주세요.', - REGEXP_TEST: '[ERROR] 형식이 잘 못되었습니다. 다시 입력해주세요.', - START_COMMA: '[ERROR] 입력이 콤마(,)부터 시작할 수 없습니다. 다시 입력해주세요.', - END_COMMA: '[ERROR] 입력 끝에 콤마(,)로 끝날 수 없습니다. 다시 입력해주세요.', - ENTERED_MORE_FIVE_TIMES: '[ERROR] 5회 이상 잘못 입력하여 종료되없습니다. 다시 실행해주세요.', - LIMIT_DIGITS: '[ERROR] 최소 4자리 숫자부터 6자리 숫자까지 입력 가능합니다. 다시 입력해주세요.', - THOUSAND_UNIT: - '[ERROR] 로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다. 다시 입력해주세요.', - NAGATIVE_NUMBER: '[ERROR] 음수가 입력될 수 없습니다. 다시 입력해주세요.', + emptyValue: createMsg('값이 존재하지 않습니다.'), + regexpTest: createMsg('형식이 잘 못되었습니다.'), + startComma: createMsg('입력이 콤마(,)부터 시작할 수 없습니다.'), + endComma: createMsg('입력 끝에 콤마(,)로 끝날 수 없습니다.'), + enteredMoreFiveTimes: '5회 이상 잘못 입력하여 종료되없습니다. 다시 실행해주세요.', + limitDigits: createMsg('최소 4자리 숫자부터 6자리 숫자까지 입력 가능합니다.'), + THOUSAND_UNIT: createMsg( + '로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다.' + ), + NAGATIVE_NUMBER: createMsg('음수가 입력될 수 없습니다.'), }; -export default ERROR_MESSAGES; +export { ERROR_PREFIX, ERROR_MESSAGES }; From 26ef7b288e2aff84bc7c282fde660abe52481c30 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 23:20:53 +0900 Subject: [PATCH 24/59] =?UTF-8?q?chore:=20errorMessages.js=20export=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=98?= =?UTF-8?q?=EC=97=AC=20import=20{}=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/validation/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation/validation.js b/src/validation/validation.js index 9a37dde46..a51cf238e 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -1,4 +1,4 @@ -import ERROR_MESSAGES from '../constants/errorMessages.js'; +import { ERROR_MESSAGES } from '../constants/errorMessages.js'; class validation { empty(value) { From 6b3b3f9c44116314b6ebd4d78588ace4d5be39bc Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 23:28:27 +0900 Subject: [PATCH 25/59] =?UTF-8?q?chore(constants):=20outputMessages=20?= =?UTF-8?q?=ED=82=A4=EB=AA=85=EC=B9=AD=20=EC=B9=B4=EB=A9=9C=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/outputMessages.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/constants/outputMessages.js b/src/constants/outputMessages.js index 87da9702e..c0e2f01d0 100644 --- a/src/constants/outputMessages.js +++ b/src/constants/outputMessages.js @@ -1,14 +1,14 @@ const OUTPUT_MESSAGES = { - PURCHASE_NUMBER: '개를 구매했습니다.', - WINNING_STATISTICS: '당첨통계\n--- ', - MATCHED_THREE: '3개 일치 (5,000원) - ', - MATCHED_FOUR: '4개 일치 (50,000원) - ', - MATCHED_FIVE: '5개 일치 (1,500,000원) - ', - MATCHED_FIVE_BONUS: '5개 일치 (30,000,000원) - ', - MATCHED_SIX: '6개 일치 (2,000,000,000원) - ', - PRINT_QUANTITY: '개', - TOTAL_RETURN: '총 수익률은 ', - TOTAL_RETURN_PERCENTAGE: '% 입니다.', + purchaseNumber: '개를 구매했습니다.', + winningStatistics: '당첨통계\n--- ', + matchedThree: '3개 일치 (5,000원) - ', + matchedFour: '4개 일치 (50,000원) - ', + matchedFive: '5개 일치 (1,500,000원) - ', + matchedFiveBonus: '5개 일치 (30,000,000원) - ', + matchedSix: '6개 일치 (2,000,000,000원) - ', + printQuantity: '개', + totalReturn: '총 수익률은 ', + totalReturnPercentage: '% 입니다.', }; export default OUTPUT_MESSAGES; From 2e0ea5cc446e33e6f0edf2a4417491a807dc9604 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 23:28:50 +0900 Subject: [PATCH 26/59] =?UTF-8?q?chore(constants):=20outputMessages=20?= =?UTF-8?q?=ED=82=A4=EB=AA=85=EC=B9=AD=20=EC=B9=B4=EB=A9=9C=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20print=20=EB=AA=85=EC=B9=AD=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/OutputView.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/view/OutputView.js b/src/view/OutputView.js index ab6c7e02f..63fec9a16 100644 --- a/src/view/OutputView.js +++ b/src/view/OutputView.js @@ -3,30 +3,34 @@ import OUTPUT_MESSAGES from '../constants/outputMessages.js'; const OutputView = { async printPurchaseNumber(purchasQuantity) { - return MissionUtils.Console.print(`${purchasQuantity}${OUTPUT_MESSAGES.PURCHASE_NUMBER}`); + return MissionUtils.Console.print(`${purchasQuantity}${OUTPUT_MESSAGES.purchaseNumber}`); + }, + + async printWinningMessage() { + return MissionUtils.Console.print(OUTPUT_MESSAGES.winningStatistics); }, async printWinningStatistics(three, four, five, fiveAndBonus, six) { MissionUtils.Console.print( - `${OUTPUT_MESSAGES.MATCHED_THREE}${three}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + `${OUTPUT_MESSAGES.MATCHED_THREE}${three}${OUTPUT_MESSAGES.printQuantity}` ); MissionUtils.Console.print( - `${OUTPUT_MESSAGES.MATCHED_FOUR}${four}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + `${OUTPUT_MESSAGES.matchedFour}${four}${OUTPUT_MESSAGES.printQuantity}` ); MissionUtils.Console.print( - `${OUTPUT_MESSAGES.MATCHED_FIVE}${five}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + `${OUTPUT_MESSAGES.matchedFive}${five}${OUTPUT_MESSAGES.printQuantity}` ); MissionUtils.Console.print( - `${OUTPUT_MESSAGES.MATCHED_FIVE_BONUS}${fiveAndBonus}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + `${OUTPUT_MESSAGES.matchedFiveBonus}${fiveAndBonus}${OUTPUT_MESSAGES.printQuantity}` ); MissionUtils.Console.print( - `${OUTPUT_MESSAGES.MATCHED_SIX}${six}${OUTPUT_MESSAGES.PRINT_QUANTITY}` + `${OUTPUT_MESSAGES.matchedSix}${six}${OUTPUT_MESSAGES.printQuantity}` ); }, async printTotalReturn(percentage) { return MissionUtils.Console.print( - `${OUTPUT_MESSAGES.TOTAL_RETURN}${percentage}${OUTPUT_MESSAGES.TOTAL_RETURN_PERCENTAGE}` + `${OUTPUT_MESSAGES.totalReturn}${percentage}${OUTPUT_MESSAGES.totalReturnPercentage}` ); }, From ad80c86dd8ff7fd4357881c01aac7bb6d6b2596a Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 23:30:18 +0900 Subject: [PATCH 27/59] =?UTF-8?q?chore(constants):=20inputMessages=20?= =?UTF-8?q?=ED=82=A4=EB=AA=85=EC=B9=AD=20=EC=B9=B4=EB=A9=9C=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/inputMessages.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constants/inputMessages.js b/src/constants/inputMessages.js index 9b20fa304..b53bd6112 100644 --- a/src/constants/inputMessages.js +++ b/src/constants/inputMessages.js @@ -1,7 +1,7 @@ const INPUT_MESSAGES = { - WHAT_PURCHASE_AMOUNT: '구매금액을 입력해주세요. \n => ', - WINNING_NUMBER: '당첨번호를 입력해주세요. \n => ', - BONUS_NUMBER: '보너스번호를 입력해주세요. \n => ', + whatPurchaseAmount: '구매금액을 입력해주세요. \n => ', + winningNumber: '당첨번호를 입력해주세요. \n => ', + bonusNumber: '보너스번호를 입력해주세요. \n => ', }; export default INPUT_MESSAGES; From 14650ef8c53935544ef2b3481ec82a95ea257b06 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Fri, 29 Nov 2024 23:30:44 +0900 Subject: [PATCH 28/59] =?UTF-8?q?chore(OInputView):=20inputMessages=20?= =?UTF-8?q?=ED=82=A4=EB=AA=85=EC=B9=AD=20=EC=B9=B4=EB=A9=9C=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20print=20=EB=AA=85=EC=B9=AD=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/InputView.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/view/InputView.js b/src/view/InputView.js index fbecb1cff..23af82e78 100644 --- a/src/view/InputView.js +++ b/src/view/InputView.js @@ -3,15 +3,15 @@ import INPUT_MESSAGES from '../constants/inputMessages.js'; const InputView = { async readPurchaseAmount() { - return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.WHAT_PURCHASE_AMOUNT); + return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.whatPurchaseAmount); }, async readWinningNumber() { - return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.WINNING_NUMBER); + return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.winningNumber); }, async readBonusNumber() { - return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.BONUS_NUMBER); + return await MissionUtils.Console.readLineAsync(INPUT_MESSAGES.bonusNumber); }, }; From 732e159344f0c2a94b1f7b1f04596f1ad1291e86 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:19:20 +0900 Subject: [PATCH 29/59] =?UTF-8?q?chore(constants):=20errorMessages=20?= =?UTF-8?q?=ED=82=A4=EB=AA=85=EC=B9=AD=20=EC=B9=B4=EB=A9=9C=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/errorMessages.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index deb7d0e43..0f41f96b0 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -9,10 +9,10 @@ const ERROR_MESSAGES = { endComma: createMsg('입력 끝에 콤마(,)로 끝날 수 없습니다.'), enteredMoreFiveTimes: '5회 이상 잘못 입력하여 종료되없습니다. 다시 실행해주세요.', limitDigits: createMsg('최소 4자리 숫자부터 6자리 숫자까지 입력 가능합니다.'), - THOUSAND_UNIT: createMsg( + negativeNumber: createMsg('음수가 입력될 수 없습니다.'), + thiusandUnit: createMsg( '로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다.' ), - NAGATIVE_NUMBER: createMsg('음수가 입력될 수 없습니다.'), }; export { ERROR_PREFIX, ERROR_MESSAGES }; From 0f79b8110ea1839ad49e4bc28193065419c96ab7 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:20:03 +0900 Subject: [PATCH 30/59] =?UTF-8?q?feat(util):=20throw=20Error=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=A0=9C=EA=B1=B0=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?util=20=ED=95=A8=EC=88=98=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/createError.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/utils/createError.js diff --git a/src/utils/createError.js b/src/utils/createError.js new file mode 100644 index 000000000..1854052d7 --- /dev/null +++ b/src/utils/createError.js @@ -0,0 +1,5 @@ +const createThrowError = (message) => { + throw new Error(`${message}`); +}; + +export default createThrowError; From e247daab6bec4cc944205750fa2f9e804776aeb8 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:21:18 +0900 Subject: [PATCH 31/59] =?UTF-8?q?feat(validation)=20:=20throw=20new=20Erro?= =?UTF-8?q?r=EB=A5=BC=20createThrowError()=20=ED=95=A8=EC=88=98=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/validation/validation.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/validation/validation.js b/src/validation/validation.js index a51cf238e..fea9813cd 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -1,41 +1,42 @@ import { ERROR_MESSAGES } from '../constants/errorMessages.js'; +import createThrowError from '../utils/createError.js'; class validation { empty(value) { - if (value === '') throw new Error(ERROR_MESSAGES.EMPTY_VALUE); + if (value === '') createThrowError(ERROR_MESSAGES.emptyValue); return true; } regularExpression(value, regExp) { const regExpTest = regExp.test(value); - if (!regExpTest) throw new Error(ERROR_MESSAGES.REGEXP_TEST); + if (!regExpTest) createThrowError(ERROR_MESSAGES.regexpTest); return true; } startedComma(value) { const regExp = /^,/; const regExpTest = regExp.test(value); - if (regExpTest) throw new Error(ERROR_MESSAGES.START_COMMA); + if (regExpTest) createThrowError(ERROR_MESSAGES.startComma); return true; } endedComma(value) { const regExp = /,$/; const regExpTest = regExp.test(value); - if (regExpTest) throw new Error(ERROR_MESSAGES.END_COMMA); + if (regExpTest) createThrowError(ERROR_MESSAGES.endComma); return true; } nagativeNumber(value) { const changeTypeNumber = Number(value); - if (0 > changeTypeNumber) throw new Error(ERROR_MESSAGES.NAGATIVE_NUMBER); + if (0 > changeTypeNumber) createThrowError(ERROR_MESSAGES.negativeNumber); return true; } limitDigits(value) { const regExp = /\d{4,6}$/; const regExpTest = regExp.test(value); - if (!regExpTest) throw new Error(ERROR_MESSAGES.LIMIT_DIGITS); + if (!regExpTest) createThrowError(ERROR_MESSAGES.limitDigits); return true; } @@ -43,8 +44,8 @@ class validation { const changeTypeNumber = Number(value); const target = changeTypeNumber / 1000; const isInteger = Number.isInteger(target); - if (!isInteger) throw new Error(ERROR_MESSAGES.THOUSAND_UNIT); - if (0 < target && target > 101) throw new Error(ERROR_MESSAGES.THOUSAND_UNIT); + if (!isInteger) createThrowError(ERROR_MESSAGES.thiusandUnit); + if (0 < target && target > 101) createThrowError(ERROR_MESSAGES.THOUSAND_UNIT); return true; } } From 07b2974b6d696946714ee547c03340f69d792487 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:36:10 +0900 Subject: [PATCH 32/59] =?UTF-8?q?chore:=20=EC=95=8C=ED=8C=8C=EB=B2=B3=20?= =?UTF-8?q?=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/errorMessages.js | 2 +- src/validation/validation.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index 0f41f96b0..bcbff89c9 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -10,7 +10,7 @@ const ERROR_MESSAGES = { enteredMoreFiveTimes: '5회 이상 잘못 입력하여 종료되없습니다. 다시 실행해주세요.', limitDigits: createMsg('최소 4자리 숫자부터 6자리 숫자까지 입력 가능합니다.'), negativeNumber: createMsg('음수가 입력될 수 없습니다.'), - thiusandUnit: createMsg( + thousandUnit: createMsg( '로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다.' ), }; diff --git a/src/validation/validation.js b/src/validation/validation.js index fea9813cd..fe69be27b 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -44,7 +44,7 @@ class validation { const changeTypeNumber = Number(value); const target = changeTypeNumber / 1000; const isInteger = Number.isInteger(target); - if (!isInteger) createThrowError(ERROR_MESSAGES.thiusandUnit); + if (!isInteger) createThrowError(ERROR_MESSAGES.thousandUnit); if (0 < target && target > 101) createThrowError(ERROR_MESSAGES.THOUSAND_UNIT); return true; } From 9b66531bb5ef141c84c78297d5397fa4ace75d0e Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:45:53 +0900 Subject: [PATCH 33/59] feat(validation): add method winningNumberSixDigit --- src/validation/validation.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/validation/validation.js b/src/validation/validation.js index fe69be27b..bdd7db430 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -48,6 +48,12 @@ class validation { if (0 < target && target > 101) createThrowError(ERROR_MESSAGES.THOUSAND_UNIT); return true; } + + winningNumberSixDigit(value) { + const lottoNumberArray = value.split(','); + if (lottoNumberArray.length !== 6) createThrowError(ERROR_MESSAGES.winningNumberSixDigit); + return true; + } } export default validation; From cd1d4cadd45805285db2f5eb6675da58718c21a6 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:46:11 +0900 Subject: [PATCH 34/59] feat(module): add validation winningNumberSixDigit --- src/modules/InputWinningModule.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/InputWinningModule.js b/src/modules/InputWinningModule.js index 2e938b8c7..57cb9e17c 100644 --- a/src/modules/InputWinningModule.js +++ b/src/modules/InputWinningModule.js @@ -26,6 +26,7 @@ class InputWinningModule { this.validation.endedComma(value); const regExpPattern = /^\d(,\s?\d)*/; this.validation.regularExpression(value, regExpPattern); + this.validation.winningNumberSixDigit(value); } async errorCatch() { From 3d59a8c5869fa7edb4ea45e3dc66d39166420586 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 17:46:28 +0900 Subject: [PATCH 35/59] feat(validation): add Mesaage winningNumberSixDigit --- src/constants/errorMessages.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index bcbff89c9..f4923afc1 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -13,6 +13,7 @@ const ERROR_MESSAGES = { thousandUnit: createMsg( '로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다.' ), + winningNumberSixDigit: createMsg('당첨번호는 6자리를 입력해야합니다.'), }; export { ERROR_PREFIX, ERROR_MESSAGES }; From bc2067775b33ca2be1cfd732dd913d0a1c8f0511 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 18:10:44 +0900 Subject: [PATCH 36/59] =?UTF-8?q?chore:=20=20ERROR=5FMESSAGE=20import=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=ED=82=A4=EB=AA=85=EC=B9=AD=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputPurchaseModule.js | 4 ++-- src/modules/InputWinningModule.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/InputPurchaseModule.js b/src/modules/InputPurchaseModule.js index a8540adf1..0e5925d63 100644 --- a/src/modules/InputPurchaseModule.js +++ b/src/modules/InputPurchaseModule.js @@ -1,4 +1,4 @@ -import ERROR_MESSAGES from '../constants/errorMessages.js'; +import { ERROR_MESSAGES } from '../constants/errorMessages.js'; import validation from '../validation/validation.js'; import InputView from '../view/InputView.js'; import OutputView from '../view/OutputView.js'; @@ -44,7 +44,7 @@ class InputPurchaseModule { for (let i = 0; i < 10; i++) { const vlaidatedInput = await this.errorCatch(); if (vlaidatedInput) return vlaidatedInput; - if (i === 5) throw new Error(ERROR_MESSAGES.ENTERED_MORE_FIVE_TIMES); + if (i === 5) throw new Error(ERROR_MESSAGES.enteredMoreFiveTimes); } } } diff --git a/src/modules/InputWinningModule.js b/src/modules/InputWinningModule.js index 57cb9e17c..2ae1fd382 100644 --- a/src/modules/InputWinningModule.js +++ b/src/modules/InputWinningModule.js @@ -1,4 +1,4 @@ -import ERROR_MESSAGES from '../constants/errorMessages.js'; +import { ERROR_MESSAGES } from '../constants/errorMessages.js'; import validation from '../validation/validation.js'; import InputView from '../view/InputView.js'; import OutputView from '../view/OutputView.js'; @@ -43,7 +43,7 @@ class InputWinningModule { for (let i = 0; i < 10; i++) { const vlaidatedInput = await this.errorCatch(); if (vlaidatedInput) return vlaidatedInput; - if (i === 5) throw new Error(ERROR_MESSAGES.ENTERED_MORE_FIVE_TIMES); + if (i === 5) throw new Error(ERROR_MESSAGES.enteredMoreFiveTimes); } } } From 90c1edfb39660e7b39a8f4c1cafd28d1b14d669b Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 18:36:23 +0900 Subject: [PATCH 37/59] =?UTF-8?q?feat(module):=20=20ERROR=5FMESSAGE=20impo?= =?UTF-8?q?rt=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=ED=82=A4=EB=AA=85?= =?UTF-8?q?=EC=B9=AD=20=EB=B3=80=EA=B2=BD=20/=20construct=EB=A5=BC=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20winningNumber=EB=A5=BC=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EA=B3=A0,=20validation=EC=97=90=EC=84=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EB=90=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputBonusModule.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/modules/InputBonusModule.js b/src/modules/InputBonusModule.js index 25635ca81..7203765e5 100644 --- a/src/modules/InputBonusModule.js +++ b/src/modules/InputBonusModule.js @@ -1,30 +1,35 @@ -import ERROR_MESSAGES from '../constants/errorMessages.js'; +import { ERROR_MESSAGES } from '../constants/errorMessages.js'; import validation from '../validation/validation.js'; import InputView from '../view/InputView.js'; import OutputView from '../view/OutputView.js'; class InputBonusModule { - constructor() { + constructor(winningNumber) { this.validation = new validation(); + this.winningNumber = winningNumber; } async inputBonusNumber() { const validatedBonusNumber = await this.repeatInput(); - const changgeTypeNumber = Number(validatedPurchaseAmount); + const changeTypeNumber = Number(validatedBonusNumber); OutputView.printSpace(); - return changgeTypeNumber; + return changeTypeNumber; } async inputAndValidation() { const input = await InputView.readBonusNumber(); - this.validateBonusNumber(input); + console.log(`?????? 잘 가져오니 ?? - ${input}`); + const winningNumber = this.winningNumber; + console.log(`?????? 잘 가져오니 ?? - ${winningNumber}`); + this.validateBonusNumber(input, winningNumber); return input; } - validateBonusNumber(value) { + validateBonusNumber(value, winningNumber) { this.validation.empty(value); const regExpPattern = /\d{1,2}/; this.validation.regularExpression(value, regExpPattern); + this.validation.isDuplicatedInWinningNumber(value, winningNumber); } async errorCatch() { @@ -41,7 +46,7 @@ class InputBonusModule { for (let i = 0; i < 10; i++) { const vlaidatedInput = await this.errorCatch(); if (vlaidatedInput) return vlaidatedInput; - if (i === 5) throw new Error(ERROR_MESSAGES.ENTERED_MORE_FIVE_TIMES); + if (i === 5) throw new Error(ERROR_MESSAGES.enteredMoreFiveTimes); } } } From db0d3bb20d1f0d6b956ce6aa21bfbdbface2a8eb Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 18:37:15 +0900 Subject: [PATCH 38/59] feat(validation): add new method 'isDuplicatedInWinningNumber' --- src/validation/validation.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/validation/validation.js b/src/validation/validation.js index bdd7db430..05a88f0ba 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -54,6 +54,13 @@ class validation { if (lottoNumberArray.length !== 6) createThrowError(ERROR_MESSAGES.winningNumberSixDigit); return true; } + + isDuplicatedInWinningNumber(bonusNumber, winningNumber) { + const isDuplicated = winningNumber.some( + (winningNumber) => Number(winningNumber) === Number(bonusNumber) + ); + if (isDuplicated) createThrowError(ERROR_MESSAGES.isDuplicatedInWinningNumber); + } } export default validation; From a61eb34a0f4ec71f011090188fd7b94642cd0cc9 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 18:37:46 +0900 Subject: [PATCH 39/59] feat(constants): add ERROR_MESSAGES 'isDuplicatedInWinningNumber' --- src/constants/errorMessages.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index f4923afc1..6ba8406db 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -14,6 +14,7 @@ const ERROR_MESSAGES = { '로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다.' ), winningNumberSixDigit: createMsg('당첨번호는 6자리를 입력해야합니다.'), + isDuplicatedInWinningNumber: createMsg('당첨번호와 중복되는 번호를 입력하셨습니다.'), }; export { ERROR_PREFIX, ERROR_MESSAGES }; From 6c30c610ef5ba51c3dd2bea14c677a1594ee7c3c Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 20:55:12 +0900 Subject: [PATCH 40/59] =?UTF-8?q?chore(module):=20console.log=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputBonusModule.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/InputBonusModule.js b/src/modules/InputBonusModule.js index 7203765e5..20b5d5370 100644 --- a/src/modules/InputBonusModule.js +++ b/src/modules/InputBonusModule.js @@ -18,9 +18,7 @@ class InputBonusModule { async inputAndValidation() { const input = await InputView.readBonusNumber(); - console.log(`?????? 잘 가져오니 ?? - ${input}`); const winningNumber = this.winningNumber; - console.log(`?????? 잘 가져오니 ?? - ${winningNumber}`); this.validateBonusNumber(input, winningNumber); return input; } From c42cb60b300935b7af1d94e0bb78368c2e321d8d Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:23:32 +0900 Subject: [PATCH 41/59] =?UTF-8?q?chore:=20return=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/OutputView.js | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/view/OutputView.js b/src/view/OutputView.js index 63fec9a16..d17849379 100644 --- a/src/view/OutputView.js +++ b/src/view/OutputView.js @@ -3,47 +3,35 @@ import OUTPUT_MESSAGES from '../constants/outputMessages.js'; const OutputView = { async printPurchaseNumber(purchasQuantity) { - return MissionUtils.Console.print(`${purchasQuantity}${OUTPUT_MESSAGES.purchaseNumber}`); + MissionUtils.Console.print(`${purchasQuantity}${OUTPUT_MESSAGES.purchaseNumber}`); }, async printWinningMessage() { - return MissionUtils.Console.print(OUTPUT_MESSAGES.winningStatistics); + MissionUtils.Console.print(OUTPUT_MESSAGES.winningStatistics); }, async printWinningStatistics(three, four, five, fiveAndBonus, six) { - MissionUtils.Console.print( - `${OUTPUT_MESSAGES.MATCHED_THREE}${three}${OUTPUT_MESSAGES.printQuantity}` - ); - MissionUtils.Console.print( - `${OUTPUT_MESSAGES.matchedFour}${four}${OUTPUT_MESSAGES.printQuantity}` - ); - MissionUtils.Console.print( - `${OUTPUT_MESSAGES.matchedFive}${five}${OUTPUT_MESSAGES.printQuantity}` - ); - MissionUtils.Console.print( - `${OUTPUT_MESSAGES.matchedFiveBonus}${fiveAndBonus}${OUTPUT_MESSAGES.printQuantity}` - ); - MissionUtils.Console.print( - `${OUTPUT_MESSAGES.matchedSix}${six}${OUTPUT_MESSAGES.printQuantity}` - ); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.MATCHED_THREE}${three}${OUTPUT_MESSAGES.printQuantity}`); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedFour}${four}${OUTPUT_MESSAGES.printQuantity}`); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedFive}${five}${OUTPUT_MESSAGES.printQuantity}`); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedFiveBonus}${fiveAndBonus}${OUTPUT_MESSAGES.printQuantity}`); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedSix}${six}${OUTPUT_MESSAGES.printQuantity}`); }, async printTotalReturn(percentage) { - return MissionUtils.Console.print( - `${OUTPUT_MESSAGES.totalReturn}${percentage}${OUTPUT_MESSAGES.totalReturnPercentage}` - ); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.totalReturn}${percentage}${OUTPUT_MESSAGES.totalReturnPercentage}`); }, async printLottoNumber(value) { - return MissionUtils.Console.print(value); + MissionUtils.Console.print(value); }, async printError(error) { - return MissionUtils.Console.print(error); + MissionUtils.Console.print(error); }, async printSpace() { - return MissionUtils.Console.print(''); + MissionUtils.Console.print(''); }, }; From b0e07b85efd17dd6679041b9d72ee588ce23c4b8 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:44:11 +0900 Subject: [PATCH 42/59] =?UTF-8?q?feat(module):=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=EC=88=98=EB=9F=89=EC=9D=84=20=EB=A6=AC=ED=84=B4=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EA=B8=88=EC=95=A1=EC=9D=84=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4=ED=95=98=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/InputPurchaseModule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/InputPurchaseModule.js b/src/modules/InputPurchaseModule.js index 0e5925d63..3d13832c8 100644 --- a/src/modules/InputPurchaseModule.js +++ b/src/modules/InputPurchaseModule.js @@ -12,7 +12,7 @@ class InputPurchaseModule { const validatedPurchaseAmount = await this.repeatInput(); const changgeTypeNumber = Number(validatedPurchaseAmount); OutputView.printSpace(); - return changgeTypeNumber / 1000; + return changgeTypeNumber; } async inputAndValidation() { From 1ddce8fbb881a03e726dd0b8e86d4265b9418d5e Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:44:30 +0900 Subject: [PATCH 43/59] =?UTF-8?q?chore:=20=EB=8B=A8=EC=88=9C=20=EB=9D=84?= =?UTF-8?q?=EC=96=B4=EC=93=B0=EA=B8=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/outputMessages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/outputMessages.js b/src/constants/outputMessages.js index c0e2f01d0..f2ec2d3fb 100644 --- a/src/constants/outputMessages.js +++ b/src/constants/outputMessages.js @@ -1,6 +1,6 @@ const OUTPUT_MESSAGES = { purchaseNumber: '개를 구매했습니다.', - winningStatistics: '당첨통계\n--- ', + winningStatistics: '당첨 통계\n--- ', matchedThree: '3개 일치 (5,000원) - ', matchedFour: '4개 일치 (50,000원) - ', matchedFive: '5개 일치 (1,500,000원) - ', From f05b992c7b7913feae6cd29d849535b0cbbb22ff Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:45:10 +0900 Subject: [PATCH 44/59] =?UTF-8?q?chore:=20=EB=8B=A8=EC=88=9C=20outputMessa?= =?UTF-8?q?ge=20=ED=82=A4=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/OutputView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/view/OutputView.js b/src/view/OutputView.js index d17849379..19bf8e2d1 100644 --- a/src/view/OutputView.js +++ b/src/view/OutputView.js @@ -11,7 +11,7 @@ const OutputView = { }, async printWinningStatistics(three, four, five, fiveAndBonus, six) { - MissionUtils.Console.print(`${OUTPUT_MESSAGES.MATCHED_THREE}${three}${OUTPUT_MESSAGES.printQuantity}`); + MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedThree}${three}${OUTPUT_MESSAGES.printQuantity}`); MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedFour}${four}${OUTPUT_MESSAGES.printQuantity}`); MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedFive}${five}${OUTPUT_MESSAGES.printQuantity}`); MissionUtils.Console.print(`${OUTPUT_MESSAGES.matchedFiveBonus}${fiveAndBonus}${OUTPUT_MESSAGES.printQuantity}`); From 2303ec15a06b23a0a135b02da6298170b28ad883 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:48:24 +0900 Subject: [PATCH 45/59] =?UTF-8?q?chore:=20matchedFiveBonus:=20'5=EA=B0=9C?= =?UTF-8?q?=20=EC=9D=BC=EC=B9=98,=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EB=B3=BC=20=EC=9D=BC=EC=B9=98=20(30,000,000=EC=9B=90)=20-=20',?= =?UTF-8?q?=20=EC=97=90=EC=84=9C=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B3=BC?= =?UTF-8?q?=20=EC=9D=BC=EC=B9=98=20=EB=A9=94=EC=84=B8=EC=A7=80=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/constants/outputMessages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/outputMessages.js b/src/constants/outputMessages.js index f2ec2d3fb..ed9e74e1f 100644 --- a/src/constants/outputMessages.js +++ b/src/constants/outputMessages.js @@ -4,7 +4,7 @@ const OUTPUT_MESSAGES = { matchedThree: '3개 일치 (5,000원) - ', matchedFour: '4개 일치 (50,000원) - ', matchedFive: '5개 일치 (1,500,000원) - ', - matchedFiveBonus: '5개 일치 (30,000,000원) - ', + matchedFiveBonus: '5개 일치, 보너스 볼 일치 (30,000,000원) - ', matchedSix: '6개 일치 (2,000,000,000원) - ', printQuantity: '개', totalReturn: '총 수익률은 ', From cae0e80a6c6b31a36ad6e3d28d61979e15228317 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:49:19 +0900 Subject: [PATCH 46/59] =?UTF-8?q?feat(module):=20=EB=8B=B9=EC=B2=A8?= =?UTF-8?q?=EB=82=B4=EC=97=AD=EA=B3=BC=20=EC=B4=9D=20=EC=88=98=EC=9D=B5?= =?UTF-8?q?=EB=A5=A0=EC=9D=84=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EB=AA=A9=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/PrintWinningDetails.js | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/modules/PrintWinningDetails.js diff --git a/src/modules/PrintWinningDetails.js b/src/modules/PrintWinningDetails.js new file mode 100644 index 000000000..ee71dfc4f --- /dev/null +++ b/src/modules/PrintWinningDetails.js @@ -0,0 +1,96 @@ +import OutputView from '../view/OutputView.js'; + +class PrintWinningDetails { + constructor(purchasePrice) { + this.purchasePrice = purchasePrice; + } + + winningDetails(lottoNumber, winningNumber, bonusNumber) { + const commonNumbers = this.checkMatchedNumber(lottoNumber, winningNumber, bonusNumber); + // console.log(commonNumbers); + const winningStatistics = this.getWinningStatistics(commonNumbers); + this.printWinningStatistics(winningStatistics); + const winningAmount = this.getWinningAmount(winningStatistics); + const purchasePrice = this.purchasePrice; + this.printProfitRate(purchasePrice, winningAmount); + } + + // service logic + checkMatchedNumber(lottoNumber, winningNumber, bonusNumber) { + let commonNumbers = []; + lottoNumber.map((lottoArray) => { + const matchedNumbers = lottoArray.filter((array) => winningNumber.includes(array)).length; + const matchedBonus = lottoArray.filter((array) => [bonusNumber].includes(array)).length; + const commonResult = { matchNum: matchedNumbers, matchBonus: matchedBonus }; + return (commonNumbers = [...commonNumbers, commonResult]); + }); + return commonNumbers; + } + + getWinningStatistics(commonNumbers) { + const winningStatistics = [ + { matchThree: commonNumbers.filter((o) => o.matchNum === 3).length }, + { matchFour: commonNumbers.filter((o) => o.matchNum === 4).length }, + { matchFive: commonNumbers.filter((o) => o.matchNum === 5 && o.matchBonus === 0).length }, + { matchFiveAndBonus: commonNumbers.filter((o) => o.matchNum === 5 && o.matchBonus === 1).length }, + { matchSix: commonNumbers.filter((o) => o.matchNum === 6).length }, + ]; + return winningStatistics; + } + + printWinningStatistics(winningStatistics) { + OutputView.printWinningMessage(); + OutputView.printWinningStatistics( + winningStatistics[0].matchThree, + winningStatistics[1].matchFour, + winningStatistics[2].matchFive, + winningStatistics[3].matchFiveAndBonus, + winningStatistics[4].matchSix + ); + } + + getWinningAmount(winningStatistics) { + const calculThree = winningStatistics[0].matchThree * 5000; + const calculFour = winningStatistics[1].matchFour * 50000; + const calculFive = winningStatistics[2].matchFive * 1500000; + const calculFiveAndBonus = winningStatistics[3].matchFiveAndBonus * 30000000; + const calculSix = winningStatistics[4].matchSix * 2000000000; + const sum = calculThree + calculFour + calculFive + calculFiveAndBonus + calculSix; + return sum; + } + + printProfitRate(purchasePrice, getWinningAmount) { + const profitRateCalcul = (((getWinningAmount - purchasePrice) / purchasePrice) * 100).toFixed(2); + OutputView.printTotalReturn(profitRateCalcul); + } +} + +export default PrintWinningDetails; + +//===================================== +// test + +// const lottoNumber = [ +// [2, 10, 20, 29, 43, 44], +// [(7, 15, 16, 20, 28, 40)], +// [(25, 31, 34, 35, 40, 44)], +// [(1, 2, 10, 24, 25, 26)], +// [(2, 4, 11, 27, 32, 37)], +// ]; + +// const winningNumber = [20, 29, 40, 25, 2, 4]; + +// const bonusNumber = 2; + +// const test = new PrintWinningDetails(); +// test.winningDetails(lottoNumber, winningNumber, bonusNumber); + +// const commonNumbers = [ +// { matchNum: 3, matchBonus: 1 }, +// { matchNum: 1, matchBonus: 0 }, +// { matchNum: 0, matchBonus: 0 }, +// { matchNum: 0, matchBonus: 0 }, +// { matchNum: 0, matchBonus: 0 }, +// ]; + +// const From 66426146ff08192808ae0806bce97ad87d1722f7 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:50:26 +0900 Subject: [PATCH 47/59] =?UTF-8?q?feat(controller):=20[=EC=B6=9C=EB=A0=A5]?= =?UTF-8?q?=20=EB=8B=B9=EC=B2=A8=20=EB=82=B4=EC=97=AD=EC=9D=84=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=9C=EB=8B=A4.=20/=20[=EC=B6=9C=EB=A0=A5]=20?= =?UTF-8?q?=EC=B4=9D=20=EC=88=98=EC=9D=B5=EB=A5=A0=EC=9D=84=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/LottoController.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/controller/LottoController.js b/src/controller/LottoController.js index 1189e7514..907567803 100644 --- a/src/controller/LottoController.js +++ b/src/controller/LottoController.js @@ -3,20 +3,29 @@ import OutputView from '../view/OutputView.js'; import InputPurchaseModule from '../modules/InputPurchaseModule.js'; import InputWinningModule from '../modules/InputWinningModule.js'; import InputBonusModule from '../modules/InputBonusModule.js'; +import PrintWinningDetails from '../modules/printWinningDetails.js'; class LottoController { constructor() { this.inputPurchaseModule = new InputPurchaseModule(); this.inputWinningModule = new InputWinningModule(); - this.inputBonusModule = new InputBonusModule(); } async runLotto() { - const purchasQuantity = await this.inputPurchaseModule.inputPurchaseAmount(); + // [module] [입력] 로또 구매 금액 입력 +validation + const purchasPrice = await this.inputPurchaseModule.inputPurchaseAmount(); + const purchasQuantity = purchasPrice / 1000; + // [출력] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. const lottoNumber = this.printRandomNumber(purchasQuantity); + // [module] [입력] 당첨번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. + validation const winningNumber = await this.inputWinningModule.inputWinningNumber(); - const bonusNumber = await this.inputBonusModule.inputBonusNumber(); - console.log(bonusNumber); + // [module] [입력] 보너스 번호를 입력 받는다. + const inputBonusModule = new InputBonusModule(winningNumber); + const bonusNumber = await inputBonusModule.inputBonusNumber(); + // [module] [출력] 당첨 내역을 출력한다. + // [module] [출력] 총 수익률을 출력한다. + const printWinningDetails = new PrintWinningDetails(purchasPrice); + printWinningDetails.winningDetails(lottoNumber, winningNumber, bonusNumber); } printRandomNumber(purchasQuantity) { From 8276e3c34f713692eed541c75d0bcd7c35151d8f Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sat, 30 Nov 2024 23:56:56 +0900 Subject: [PATCH 48/59] =?UTF-8?q?feat(module):=20printRandomNumber=20Modul?= =?UTF-8?q?e=EB=A1=9C=20=EB=A7=8C=EB=93=A4=EA=B3=A0,=20import=EB=A1=9C=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=99=80=EC=84=9C=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/LottoController.js | 25 +++---------------------- src/modules/PrintRandomNumber.js | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 src/modules/PrintRandomNumber.js diff --git a/src/controller/LottoController.js b/src/controller/LottoController.js index 907567803..adf0063d8 100644 --- a/src/controller/LottoController.js +++ b/src/controller/LottoController.js @@ -1,45 +1,26 @@ -import { MissionUtils } from '@woowacourse/mission-utils'; -import OutputView from '../view/OutputView.js'; import InputPurchaseModule from '../modules/InputPurchaseModule.js'; import InputWinningModule from '../modules/InputWinningModule.js'; import InputBonusModule from '../modules/InputBonusModule.js'; import PrintWinningDetails from '../modules/printWinningDetails.js'; +import PrintRandomNumber from '../modules/PrintRandomNumber.js'; class LottoController { constructor() { this.inputPurchaseModule = new InputPurchaseModule(); this.inputWinningModule = new InputWinningModule(); + this.printRandomNumber = new PrintRandomNumber(); } async runLotto() { - // [module] [입력] 로또 구매 금액 입력 +validation const purchasPrice = await this.inputPurchaseModule.inputPurchaseAmount(); const purchasQuantity = purchasPrice / 1000; - // [출력] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - const lottoNumber = this.printRandomNumber(purchasQuantity); - // [module] [입력] 당첨번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. + validation + const lottoNumber = this.printRandomNumber.printRandomNumber(purchasQuantity); const winningNumber = await this.inputWinningModule.inputWinningNumber(); - // [module] [입력] 보너스 번호를 입력 받는다. const inputBonusModule = new InputBonusModule(winningNumber); const bonusNumber = await inputBonusModule.inputBonusNumber(); - // [module] [출력] 당첨 내역을 출력한다. - // [module] [출력] 총 수익률을 출력한다. const printWinningDetails = new PrintWinningDetails(purchasPrice); printWinningDetails.winningDetails(lottoNumber, winningNumber, bonusNumber); } - - printRandomNumber(purchasQuantity) { - OutputView.printPurchaseNumber(purchasQuantity); - let lottoNumberArrayss = []; - for (let i = 0; i < purchasQuantity; i++) { - const lottoNumber = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6); - const ascendingOrder = lottoNumber.sort((a, b) => a - b); - OutputView.printLottoNumber(ascendingOrder); - lottoNumberArrayss = [...lottoNumberArrayss, ascendingOrder]; - } - OutputView.printSpace(); - return lottoNumberArrayss; - } } export default LottoController; diff --git a/src/modules/PrintRandomNumber.js b/src/modules/PrintRandomNumber.js new file mode 100644 index 000000000..9b560ddf8 --- /dev/null +++ b/src/modules/PrintRandomNumber.js @@ -0,0 +1,19 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; +import OutputView from '../view/OutputView.js'; + +class PrintRandomNumber { + printRandomNumber(purchasQuantity) { + OutputView.printPurchaseNumber(purchasQuantity); + let lottoNumberArrayss = []; + for (let i = 0; i < purchasQuantity; i++) { + const lottoNumber = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6); + const ascendingOrder = lottoNumber.sort((a, b) => a - b); + OutputView.printLottoNumber(ascendingOrder); + lottoNumberArrayss = [...lottoNumberArrayss, ascendingOrder]; + } + OutputView.printSpace(); + return lottoNumberArrayss; + } +} + +export default PrintRandomNumber; From bcfc800ee162f771392ed1bb292df1a045166831 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 00:28:19 +0900 Subject: [PATCH 49/59] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/PrintWinningDetails.js | 37 ++++++------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/src/modules/PrintWinningDetails.js b/src/modules/PrintWinningDetails.js index ee71dfc4f..6b2e2eeda 100644 --- a/src/modules/PrintWinningDetails.js +++ b/src/modules/PrintWinningDetails.js @@ -32,7 +32,10 @@ class PrintWinningDetails { { matchThree: commonNumbers.filter((o) => o.matchNum === 3).length }, { matchFour: commonNumbers.filter((o) => o.matchNum === 4).length }, { matchFive: commonNumbers.filter((o) => o.matchNum === 5 && o.matchBonus === 0).length }, - { matchFiveAndBonus: commonNumbers.filter((o) => o.matchNum === 5 && o.matchBonus === 1).length }, + { + matchFiveAndBonus: commonNumbers.filter((o) => o.matchNum === 5 && o.matchBonus === 1) + .length, + }, { matchSix: commonNumbers.filter((o) => o.matchNum === 6).length }, ]; return winningStatistics; @@ -60,37 +63,11 @@ class PrintWinningDetails { } printProfitRate(purchasePrice, getWinningAmount) { - const profitRateCalcul = (((getWinningAmount - purchasePrice) / purchasePrice) * 100).toFixed(2); + const profitRateCalcul = (((getWinningAmount - purchasePrice) / purchasePrice) * 100).toFixed( + 2 + ); OutputView.printTotalReturn(profitRateCalcul); } } export default PrintWinningDetails; - -//===================================== -// test - -// const lottoNumber = [ -// [2, 10, 20, 29, 43, 44], -// [(7, 15, 16, 20, 28, 40)], -// [(25, 31, 34, 35, 40, 44)], -// [(1, 2, 10, 24, 25, 26)], -// [(2, 4, 11, 27, 32, 37)], -// ]; - -// const winningNumber = [20, 29, 40, 25, 2, 4]; - -// const bonusNumber = 2; - -// const test = new PrintWinningDetails(); -// test.winningDetails(lottoNumber, winningNumber, bonusNumber); - -// const commonNumbers = [ -// { matchNum: 3, matchBonus: 1 }, -// { matchNum: 1, matchBonus: 0 }, -// { matchNum: 0, matchBonus: 0 }, -// { matchNum: 0, matchBonus: 0 }, -// { matchNum: 0, matchBonus: 0 }, -// ]; - -// const From ab5ebcaf3257e43eaec4f7323cbdcf633c19d5ce Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 02:32:24 +0900 Subject: [PATCH 50/59] =?UTF-8?q?chore:=20console.log=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=8B=A4=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EC=A7=80=EC=86=8D=EC=A0=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B0=98=EB=B3=B5=ED=95=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/PrintWinningDetails.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/PrintWinningDetails.js b/src/modules/PrintWinningDetails.js index 6b2e2eeda..c234e0aea 100644 --- a/src/modules/PrintWinningDetails.js +++ b/src/modules/PrintWinningDetails.js @@ -7,7 +7,6 @@ class PrintWinningDetails { winningDetails(lottoNumber, winningNumber, bonusNumber) { const commonNumbers = this.checkMatchedNumber(lottoNumber, winningNumber, bonusNumber); - // console.log(commonNumbers); const winningStatistics = this.getWinningStatistics(commonNumbers); this.printWinningStatistics(winningStatistics); const winningAmount = this.getWinningAmount(winningStatistics); From 37b5a4ddb67afa6d763a6bdb92e003b2c9deacb0 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 02:36:18 +0900 Subject: [PATCH 51/59] =?UTF-8?q?chore:=20prettier=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/ApplicationTest.js | 50 ++++++++++++++++++------------------ __tests__/LottoTest.js | 12 ++++----- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/__tests__/ApplicationTest.js b/__tests__/ApplicationTest.js index 872380c9c..b8a446383 100644 --- a/__tests__/ApplicationTest.js +++ b/__tests__/ApplicationTest.js @@ -1,5 +1,5 @@ -import App from "../src/App.js"; -import { MissionUtils } from "@woowacourse/mission-utils"; +import App from '../src/App.js'; +import { MissionUtils } from '@woowacourse/mission-utils'; const mockQuestions = (inputs) => { MissionUtils.Console.readLineAsync = jest.fn(); @@ -19,7 +19,7 @@ const mockRandoms = (numbers) => { }; const getLogSpy = () => { - const logSpy = jest.spyOn(MissionUtils.Console, "print"); + const logSpy = jest.spyOn(MissionUtils.Console, 'print'); logSpy.mockClear(); return logSpy; }; @@ -29,7 +29,7 @@ const runException = async (input) => { const logSpy = getLogSpy(); const RANDOM_NUMBERS_TO_END = [1, 2, 3, 4, 5, 6]; - const INPUT_NUMBERS_TO_END = ["1000", "1,2,3,4,5,6", "7"]; + const INPUT_NUMBERS_TO_END = ['1000', '1,2,3,4,5,6', '7']; mockRandoms([RANDOM_NUMBERS_TO_END]); mockQuestions([input, ...INPUT_NUMBERS_TO_END]); @@ -39,15 +39,15 @@ const runException = async (input) => { await app.run(); // then - expect(logSpy).toHaveBeenCalledWith(expect.stringContaining("[ERROR]")); + expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('[ERROR]')); }; -describe("로또 테스트", () => { +describe('로또 테스트', () => { beforeEach(() => { jest.restoreAllMocks(); }); - test("기능 테스트", async () => { + test('기능 테스트', async () => { // given const logSpy = getLogSpy(); @@ -61,7 +61,7 @@ describe("로또 테스트", () => { [2, 13, 22, 32, 38, 45], [1, 3, 5, 14, 22, 45], ]); - mockQuestions(["8000", "1,2,3,4,5,6", "7"]); + mockQuestions(['8000', '1,2,3,4,5,6', '7']); // when const app = new App(); @@ -69,21 +69,21 @@ describe("로또 테스트", () => { // then const logs = [ - "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]", - "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%입니다.", + '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]', + '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%입니다.', ]; logs.forEach((log) => { @@ -91,7 +91,7 @@ describe("로또 테스트", () => { }); }); - test("예외 테스트", async () => { - await runException("1000j"); + test('예외 테스트', async () => { + await runException('1000j'); }); }); diff --git a/__tests__/LottoTest.js b/__tests__/LottoTest.js index 409aaf69b..19d576106 100644 --- a/__tests__/LottoTest.js +++ b/__tests__/LottoTest.js @@ -1,17 +1,17 @@ -import Lotto from "../src/Lotto"; +import Lotto from '../src/Lotto'; -describe("로또 클래스 테스트", () => { - test("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.", () => { +describe('로또 클래스 테스트', () => { + test('로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.', () => { expect(() => { new Lotto([1, 2, 3, 4, 5, 6, 7]); - }).toThrow("[ERROR]"); + }).toThrow('[ERROR]'); }); // TODO: 테스트가 통과하도록 프로덕션 코드 구현 - test("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.", () => { + test('로또 번호에 중복된 숫자가 있으면 예외가 발생한다.', () => { expect(() => { new Lotto([1, 2, 3, 4, 5, 5]); - }).toThrow("[ERROR]"); + }).toThrow('[ERROR]'); }); // TODO: 추가 기능 구현에 따른 테스트 코드 작성 From 273b81b2dc6c90159c1728afbfb9bd7c398354d3 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 03:54:45 +0900 Subject: [PATCH 52/59] feat(constant): add errorMessage 'isDuplicatedInLottoNumbers' --- src/constants/errorMessages.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index 6ba8406db..8f02a42bc 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -14,6 +14,7 @@ const ERROR_MESSAGES = { '로또 금액인 1000원 단위로만 입력 가능하며, 최대 10만원까지 입력 가능합니다.' ), winningNumberSixDigit: createMsg('당첨번호는 6자리를 입력해야합니다.'), + isDuplicatedInLottoNumbers: createMsg('입력하신 당첨번호에 중복값이 존재합니다.'), isDuplicatedInWinningNumber: createMsg('당첨번호와 중복되는 번호를 입력하셨습니다.'), }; From 67c50ec7ca89b97f2f266e6e84af90aac0664e9b Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 03:55:16 +0900 Subject: [PATCH 53/59] feat(Lotto.js): add validation 'isDuplicatedInLottoNumbers' --- src/Lotto.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Lotto.js b/src/Lotto.js index 1164a3f81..00bee98b9 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -1,8 +1,12 @@ +import { ERROR_MESSAGES } from './constants/errorMessages.js'; +import createThrowError from './utils/createError.js'; + class Lotto { #numbers; constructor(numbers) { this.#validate(numbers); + this.isDuplicatedInLottoNumbers(numbers); this.#numbers = numbers; } @@ -13,6 +17,15 @@ class Lotto { } // TODO: 추가 기능 구현 + // test코드를 확인해보니, 중복 값을 검증하는 코드가 필요합니다. + isDuplicatedInLottoNumbers(number) { + const removeDuplicated = new Set(number); // 🔥 출력이 배열로 나오지 않습니다. + // 🔥 Set은 배열과 다른 특별한 객체 타입입니다. + // 배열로 변환하려면 간단히 스프레드 연산자(...)나 Array.from()을 사용하면 됩니다. + const uniqueArray = [...removeDuplicated]; // 배열로 변환 + if (number.length !== uniqueArray.length) + createThrowError(ERROR_MESSAGES.isDuplicatedInLottoNumbers); + } } export default Lotto; From a0c74812b3aaa158af0b45a3e78dc6fd3232fa9f Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 03:56:20 +0900 Subject: [PATCH 54/59] feat(validation): add validation 'isDuplicatedInLottoNumbers' --- src/validation/validation.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/validation/validation.js b/src/validation/validation.js index 05a88f0ba..6acbb5fa1 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -55,6 +55,13 @@ class validation { return true; } + isDuplicatedInLottoNumbers(number) { + const removeDuplicated = new Set(number); + const uniqueArray = [...removeDuplicated]; + if (number.length !== uniqueArray.length) + createThrowError(ERROR_MESSAGES.isDuplicatedInLottoNumbers); + } + isDuplicatedInWinningNumber(bonusNumber, winningNumber) { const isDuplicated = winningNumber.some( (winningNumber) => Number(winningNumber) === Number(bonusNumber) From e4bb9279733b144e0ef8d299c5929dbf13db92dc Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 03:57:43 +0900 Subject: [PATCH 55/59] feat(module): add validation 'isDuplicatedInLottoNumbers' in InputWinningModule.js --- src/modules/InputWinningModule.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/InputWinningModule.js b/src/modules/InputWinningModule.js index 2ae1fd382..6823744f7 100644 --- a/src/modules/InputWinningModule.js +++ b/src/modules/InputWinningModule.js @@ -27,6 +27,7 @@ class InputWinningModule { const regExpPattern = /^\d(,\s?\d)*/; this.validation.regularExpression(value, regExpPattern); this.validation.winningNumberSixDigit(value); + this.validation.isDuplicatedInLottoNumbers(value); } async errorCatch() { From c726bcd4b1a0b619d9cd77082782577161bb7700 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Sun, 1 Dec 2024 04:00:14 +0900 Subject: [PATCH 56/59] =?UTF-8?q?feat(util):=20const=20ERROR=5FPREFIX=20?= =?UTF-8?q?=3D=20'[ERROR]';=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=20=EC=8B=9C?= =?UTF-8?q?=EC=BC=9C=20test=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=EA=B3=BC=ED=95=98=EB=A0=A4=EA=B3=A0=20=ED=95=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/createError.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/createError.js b/src/utils/createError.js index 1854052d7..849d04a44 100644 --- a/src/utils/createError.js +++ b/src/utils/createError.js @@ -1,5 +1,9 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; +import { ERROR_PREFIX } from '../constants/errorMessages.js'; + const createThrowError = (message) => { - throw new Error(`${message}`); + MissionUtils.Console.print(ERROR_PREFIX); + throw new Error(message); }; export default createThrowError; From 6b8328113ebbeefddc3dff09957f1f7b3708dc0b Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 2 Dec 2024 00:17:14 +0900 Subject: [PATCH 57/59] =?UTF-8?q?feat(util):=20=EB=AC=B8=EC=9E=90=EC=97=B4?= =?UTF-8?q?=EC=9D=84=20=EB=B0=B0=EC=97=B4=EB=A1=9C=20=EB=B0=94=EA=BE=B8?= =?UTF-8?q?=EB=8A=94=20=EB=8F=84=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/makeArrayFromString.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/utils/makeArrayFromString.js diff --git a/src/utils/makeArrayFromString.js b/src/utils/makeArrayFromString.js new file mode 100644 index 000000000..4726c576c --- /dev/null +++ b/src/utils/makeArrayFromString.js @@ -0,0 +1,5 @@ +const makeArrayFromString = (value) => { + return value.split(","); +}; + +export default makeArrayFromString; \ No newline at end of file From 5cec1e2ef7d77ac87a2e8a0b96ef840760dd1359 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 2 Dec 2024 00:20:28 +0900 Subject: [PATCH 58/59] =?UTF-8?q?fix(validation):=20new=20Set()=20?= =?UTF-8?q?=EB=B0=B0=EC=97=B4=EC=9D=B4=20=EB=93=A4=EC=96=B4=EA=B0=80?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EA=B3=A0=20=EC=9E=88=EB=8A=94=20=EC=A0=90?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20in=20isDuplicatedInLottoNumbers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/validation/validation.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/validation/validation.js b/src/validation/validation.js index 6acbb5fa1..9304349bc 100644 --- a/src/validation/validation.js +++ b/src/validation/validation.js @@ -1,5 +1,6 @@ import { ERROR_MESSAGES } from '../constants/errorMessages.js'; import createThrowError from '../utils/createError.js'; +import makeArrayFromString from '../utils/makeArrayFromString.js'; class validation { empty(value) { @@ -45,7 +46,7 @@ class validation { const target = changeTypeNumber / 1000; const isInteger = Number.isInteger(target); if (!isInteger) createThrowError(ERROR_MESSAGES.thousandUnit); - if (0 < target && target > 101) createThrowError(ERROR_MESSAGES.THOUSAND_UNIT); + if (0 < target && target > 101) createThrowError(ERROR_MESSAGES.thousandUnit); return true; } @@ -56,9 +57,9 @@ class validation { } isDuplicatedInLottoNumbers(number) { - const removeDuplicated = new Set(number); - const uniqueArray = [...removeDuplicated]; - if (number.length !== uniqueArray.length) + const changeArray = makeArrayFromString(number); + const removeDuplicated = new Set(changeArray).size; + if (changeArray.length !== removeDuplicated) createThrowError(ERROR_MESSAGES.isDuplicatedInLottoNumbers); } From e9d57523e3db11e8e60194df9b908ada0bb36851 Mon Sep 17 00:00:00 2001 From: BoRamSon Date: Mon, 2 Dec 2024 02:29:39 +0900 Subject: [PATCH 59/59] =?UTF-8?q?test:=20=EA=B8=B0=EB=8A=A5=EB=B3=84=20tes?= =?UTF-8?q?t=20code=20=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/InputBonusModule.test.js | 41 ++++++++++++++++++ __tests__/InputPurchaseModule.test.js | 39 +++++++++++++++++ __tests__/InputWinningModule.test.js | 61 +++++++++++++++++++++++++++ __tests__/PrintRandomNumber.test.js | 54 ++++++++++++++++++++++++ __tests__/PrintWinningDetails.test.js | 48 +++++++++++++++++++++ 5 files changed, 243 insertions(+) create mode 100644 __tests__/InputBonusModule.test.js create mode 100644 __tests__/InputPurchaseModule.test.js create mode 100644 __tests__/InputWinningModule.test.js create mode 100644 __tests__/PrintRandomNumber.test.js create mode 100644 __tests__/PrintWinningDetails.test.js diff --git a/__tests__/InputBonusModule.test.js b/__tests__/InputBonusModule.test.js new file mode 100644 index 000000000..3af424042 --- /dev/null +++ b/__tests__/InputBonusModule.test.js @@ -0,0 +1,41 @@ +import InputBonusModule from '../src/modules/InputBonusModule'; + +describe('로또 구입 금액 검증', () => { + // given + const bonusNumber = new InputBonusModule(); + + // 실패하는 코드 + test('당첨번호에 있는 값이 보너스번호로 입력되면 ERROR가 발생한다.', () => { + // when + const testBonusNumber = '1'; + const winningNumber = [1, 2, 3, 4, 5, 6]; + + // then + expect(() => { + bonusNumber.validateBonusNumber(testBonusNumber, winningNumber); + }).toThrow('[ERROR]'); + }); + + // 성공하는 코드 + test('당첨번호에 있는 값이 보너스번호로 입력될 수 없다.', () => { + // when + const testBonusNumber = '7'; + const winningNumber = [1, 2, 3, 4, 5, 6]; + + // then + expect(() => { + bonusNumber.validateBonusNumber(testBonusNumber, winningNumber); + }).toBeTruthy(); + }); + + // (추가적인 테스트 코드) + test('입력값이 빈값이면 ERROR가 발생한다.', () => { + // when + const testBonusNumber = ''; + + // then + expect(() => { + bonusNumber.validateBonusNumber(testBonusNumber); + }).toThrow('[ERROR]'); + }); +}); diff --git a/__tests__/InputPurchaseModule.test.js b/__tests__/InputPurchaseModule.test.js new file mode 100644 index 000000000..2a14199a3 --- /dev/null +++ b/__tests__/InputPurchaseModule.test.js @@ -0,0 +1,39 @@ +import InputPurchaseModule from '../src/modules/InputPurchaseModule'; + +describe('로또 구입 금액 검증', () => { + // given + const purchaseAmount = new InputPurchaseModule(); + + // 실패하는 코드 + test('1,000원으로 나누어 떨어지지 않으면 에러', () => { + // when + const testInput = '1500'; + + // then + expect(() => { + purchaseAmount.validatatePrice(testInput); + }).toThrow('[ERROR]'); + }); + + // 성공하는 코드 + test('1,000원 단위로 입력 가능해야 한다', () => { + // when + const testInput = '10000'; + + // then + expect(() => { + purchaseAmount.validatatePrice(testInput); + }).toBeTruthy(); + }); + + // (추가적인 테스트 코드) + test('입력값이 빈값이면 ERROR가 발생한다.', () => { + // when + const testInput = ''; + + // then + expect(() => { + purchaseAmount.validatatePrice(testInput); + }).toThrow('[ERROR]'); + }); +}); diff --git a/__tests__/InputWinningModule.test.js b/__tests__/InputWinningModule.test.js new file mode 100644 index 000000000..289f28a5d --- /dev/null +++ b/__tests__/InputWinningModule.test.js @@ -0,0 +1,61 @@ +import InputWinningModule from '../src/modules/InputWinningModule'; + +describe('로또 구입 금액 검증', () => { + // given + const winningNumber = new InputWinningModule(); + + // 실패하는 코드 + test('당첨번호는 6자리를 입력해야한다.', () => { + // when + const testInput = '1,2,3,4,5,6,7'; + + // then + expect(() => { + winningNumber.validateWinningNumber(testInput); + }).toThrow('[ERROR]'); + }); + + // 성공하는 코드 + test('당첨번호는 6자리를 입력해야한다.', () => { + // when + const testInput = '1,2,3,4,5,6'; + + // then + expect(() => { + winningNumber.validateWinningNumber(testInput); + }).toBeTruthy(); + }); + + // 실패하는 코드 + test('6자리 중 중복값은 없어야 한다.', () => { + // when + const testInput = '1,2,3,4,5,5'; + + // then + expect(() => { + winningNumber.validateWinningNumber(testInput); + }).toThrow('[ERROR]'); + }); + + // 성공하는 코드 + test('6자리 중 중복값은 없어야 한다.', () => { + // when + const testInput = '1,2,3,4,5,6'; + + // then + expect(() => { + winningNumber.validateWinningNumber(testInput); + }).toBeTruthy(); + }); + + // (추가적인 테스트 코드) + test('입력값이 빈값이면 ERROR가 발생한다.', () => { + // when + const testInput = ''; + + // then + expect(() => { + winningNumber.validateWinningNumber(testInput); + }).toThrow('[ERROR]'); + }); +}); diff --git a/__tests__/PrintRandomNumber.test.js b/__tests__/PrintRandomNumber.test.js new file mode 100644 index 000000000..fc63fcb8d --- /dev/null +++ b/__tests__/PrintRandomNumber.test.js @@ -0,0 +1,54 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; +import PrintRandomNumber from '../src/modules/PrintRandomNumber'; +import OutputView from '../src/view/OutputView'; + +jest.mock('../src/view/OutputView'); +jest.mock('@woowacourse/mission-utils', () => ({ + MissionUtils: { + Random: { + pickUniqueNumbersInRange: jest.fn(), + }, + }, +})); + +describe('PrintRandomNumber', () => { + // given + beforeEach(() => { + OutputView.printPurchaseNumber.mockClear(); + OutputView.printLottoNumber.mockClear(); + OutputView.printSpace.mockClear(); + MissionUtils.Random.pickUniqueNumbersInRange.mockClear(); + }); + + const printRandomNumber = new PrintRandomNumber(); + const mockPurchaseQuantity = 3; + const mockLottoNumbers = [ + [1, 2, 3, 4, 5, 6], + [7, 8, 9, 10, 11, 12], + [13, 14, 15, 16, 17, 18], + ]; + + test('로또 번호 생성 및 출력 검증', () => { + // when + MissionUtils.Random.pickUniqueNumbersInRange + .mockReturnValueOnce(mockLottoNumbers[0]) + .mockReturnValueOnce(mockLottoNumbers[1]) + .mockReturnValueOnce(mockLottoNumbers[2]); + + // then + expect(printRandomNumber.printRandomNumber(mockPurchaseQuantity)).toEqual([ + [1, 2, 3, 4, 5, 6], + [7, 8, 9, 10, 11, 12], + [13, 14, 15, 16, 17, 18], + ]); + + expect(OutputView.printPurchaseNumber).toHaveBeenCalledWith(mockPurchaseQuantity); + expect(OutputView.printLottoNumber).toHaveBeenCalledTimes(mockPurchaseQuantity); + expect(OutputView.printSpace).toHaveBeenCalledTimes(1); + + expect(MissionUtils.Random.pickUniqueNumbersInRange).toHaveBeenCalledTimes( + mockPurchaseQuantity + ); + expect(MissionUtils.Random.pickUniqueNumbersInRange).toHaveBeenCalledWith(1, 45, 6); + }); +}); diff --git a/__tests__/PrintWinningDetails.test.js b/__tests__/PrintWinningDetails.test.js new file mode 100644 index 000000000..42f415bbe --- /dev/null +++ b/__tests__/PrintWinningDetails.test.js @@ -0,0 +1,48 @@ +import OutputView from '../src/view/OutputView'; +import PrintWinningDetails from '../src/modules/printWinningDetails'; + +jest.mock('../src/view/OutputView'); + +describe('당첨 내역 출력하기', () => { + // given + beforeEach(() => { + OutputView.printWinningMessage.mockClear(); + OutputView.printWinningStatistics.mockClear(); + OutputView.printTotalReturn.mockClear(); + }); + + const printWinningDsetails = new PrintWinningDetails(); + const mockLottoNumbers = [ + [1, 2, 3, 4, 5, 6], + [7, 8, 9, 10, 11, 12], + [13, 14, 15, 16, 17, 18], + ]; + const mockWinningNumber = [13, 14, 15, 16, 17, 18]; + const mockBonusNumber = 12; + + test('당첨 내역 출력이 되었는가?', () => { + // when + printWinningDsetails.winningDetails(mockLottoNumbers, mockWinningNumber, mockBonusNumber); + + // then + expect(OutputView.printWinningMessage).toHaveBeenCalledTimes(1); + expect(OutputView.printWinningStatistics).toHaveBeenCalledTimes(1); + expect(OutputView.printTotalReturn).toHaveBeenCalledTimes(1); + }); + + test('당첨번호 매칭이 잘 되었는가?', () => { + // when + const result = printWinningDsetails.checkMatchedNumber( + mockLottoNumbers, + mockWinningNumber, + mockBonusNumber + ); + + // then + expect(result).toEqual([ + { matchNum: 0, matchBonus: 0 }, + { matchNum: 0, matchBonus: 1 }, + { matchNum: 6, matchBonus: 0 }, + ]); + }); +});