From b4508c26461984def72a0fc84d1515142093d106 Mon Sep 17 00:00:00 2001 From: chichi Date: Thu, 31 Oct 2024 21:46:06 +0900 Subject: [PATCH 1/8] =?UTF-8?q?docs:=20README.md=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15bb106b5..e5c40b08d 100644 --- a/README.md +++ b/README.md @@ -1 +1,27 @@ -# javascript-lotto-precourse +### 로또 발매기 + +간단한 로또 발매기를 구현한다. + +### 구현할 기능 목록 + +**프로그램 실행 시** + +- 로또 구입 금액을 입력 받는다. 구입 금액은 1,000원 단위로 입력 받는다 +- 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다 +- 보너스 번호를 입력 받는다 + +**출력** + +- 발행한 로또 수량 및 번호를 출력한다 +- 로또 번호는 오름차순으로 정렬하여 보여준다 +- 당첨 내역을 출력한다 +- 수익률은 소수점 둘째 자리에서 반올림한다 + +**예외 처리** + +- 구입 금액이 숫자가 아닌 경우 예외 처리한다 +- 구입 금액이 0원인 경우 예외 처리한다 +- 로또 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다 +- 로또 당첨 번호가 중복인 경우 예외 처리한다 +- 로또 당첨 번호의 개수가 6개 초과일 경우 예외 처리한다 +- 로또 번호가 1~45 사이의 숫자가 아닌 경우 예외 처리한다 From 201485de5f63e33bd673864132640ee46f4532e5 Mon Sep 17 00:00:00 2001 From: chichi Date: Fri, 1 Nov 2024 21:27:54 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=EC=8B=A4=ED=96=89=20=EC=8B=9C=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EC=97=90=EA=B2=8C=20=EA=B0=92=EC=9D=84=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=B0=9B=EC=9D=84=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=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/App.js | 7 +++++- src/Controller/Controller.js | 41 ++++++++++++++++++++++++++++++++++++ src/{ => Model}/Lotto.js | 0 src/View/View.js | 25 ++++++++++++++++++++++ src/constants/constants.js | 2 ++ src/constants/messages.js | 12 +++++++++++ 6 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/Controller/Controller.js rename src/{ => Model}/Lotto.js (100%) create mode 100644 src/View/View.js create mode 100644 src/constants/constants.js create mode 100644 src/constants/messages.js diff --git a/src/App.js b/src/App.js index 091aa0a5d..9077f6d3f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,10 @@ +import Controller from './Controller/Controller.js'; + class App { - async run() {} + async run() { + const controller = new Controller(); + controller.execute(); + } } export default App; diff --git a/src/Controller/Controller.js b/src/Controller/Controller.js new file mode 100644 index 000000000..9336ec501 --- /dev/null +++ b/src/Controller/Controller.js @@ -0,0 +1,41 @@ +import { DELIMITER, LOTTO_PRICE } from '../constants/constants.js'; +import { ERROR_MESSAGES } from '../constants/messages.js'; +import View from '../View/View.js'; + +class Controller { + async #validateAmount(amount) { + if (amount % LOTTO_PRICE !== 0) { + throw new Error(ERROR_MESSAGES.INVALID_LOTTO_PRICE); + } + } + + async #validateWinningNumbers(numbers) { + const splittedNumbers = numbers.split(DELIMITER); + + if (!splittedNumbers) { + throw new Error(ERROR_MESSAGES.EMPTY_LOTTO_NUMBERS); + } + + if (!numbers.includes(DELIMITER)) { + throw new Error(ERROR_MESSAGES.INVALID_LOTTO_NUMBERS); + } + + if (splittedNumbers.length !== 6) { + throw new Error(ERROR_MESSAGES.INVALID_LOTTO_COUNT); + } + } + + async execute() { + const view = new View(); + + const amount = await view.getAmount(); + await this.#validateAmount(amount); + + const winningNumbers = await view.getWinningNumbers(); + await this.#validateWinningNumbers(winningNumbers); + + await view.getBonusNumber(); + } +} + +export default Controller; diff --git a/src/Lotto.js b/src/Model/Lotto.js similarity index 100% rename from src/Lotto.js rename to src/Model/Lotto.js diff --git a/src/View/View.js b/src/View/View.js new file mode 100644 index 000000000..f196d0b37 --- /dev/null +++ b/src/View/View.js @@ -0,0 +1,25 @@ +import { Console } from '@woowacourse/mission-utils'; +import { PROMPT_MESSAGES } from '../constants/messages.js'; + +class View { + async getAmount() { + const amount = await Console.readLineAsync(PROMPT_MESSAGES.INPUT_AMOUNT); + return amount; + } + + async getWinningNumbers() { + const winningNumbers = await Console.readLineAsync( + PROMPT_MESSAGES.INPUT_WINNING_NUMBERS + ); + return winningNumbers; + } + + async getBonusNumber() { + const bonusNumber = await Console.readLineAsync( + PROMPT_MESSAGES.INPUT_BONUS_NUMBERS + ); + return bonusNumber; + } +} + +export default View; diff --git a/src/constants/constants.js b/src/constants/constants.js new file mode 100644 index 000000000..080f55cbe --- /dev/null +++ b/src/constants/constants.js @@ -0,0 +1,2 @@ +export const LOTTO_PRICE = 1000; +export const DELIMITER = ','; diff --git a/src/constants/messages.js b/src/constants/messages.js new file mode 100644 index 000000000..cc0a13745 --- /dev/null +++ b/src/constants/messages.js @@ -0,0 +1,12 @@ +export const PROMPT_MESSAGES = Object.freeze({ + INPUT_AMOUNT: '구입금액을 입력해 주세요.\n', + INPUT_WINNING_NUMBERS: '당첨 번호를 입력해 주세요.\n', + INPUT_BONUS_NUMBERS: '보너스 번호를 입력해 주세요.\n', +}); + +export const ERROR_MESSAGES = Object.freeze({ + INVALID_LOTTO_PRICE: '구입 금액은 1,000원 단위로 입력해 주세요.', + INVALID_LOTTO_NUMBERS: '당첨 번호를 쉼표 기준으로 구분해 주세요.', + EMPTY_LOTTO_NUMBERS: '당첨 번호를 입력해 주세요.', + INVALID_LOTTO_COUNT: '당첨 번호를 6개 입력해 주세요.', +}); From 55be552427cbbbbc2f2c6d312490dcb43b509143 Mon Sep 17 00:00:00 2001 From: chichi Date: Mon, 4 Nov 2024 23:52:48 +0900 Subject: [PATCH 3/8] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=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 | 18 ++++++++----- 2 files changed, 36 insertions(+), 32 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..f0e964980 100644 --- a/__tests__/LottoTest.js +++ b/__tests__/LottoTest.js @@ -1,18 +1,22 @@ -import Lotto from "../src/Lotto"; +import Lotto from '../src/Model/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: 추가 기능 구현에 따른 테스트 코드 작성 + test('로또 번호가 6개 미만일 경우 예외가 발생한다.', () => { + expect(() => { + new Lotto([1, 2, 3, 4, 5]); + }).toThrow('[ERROR]'); + }); }); From 7c3804b50dbad26cb2d18645915951f23cbf4de3 Mon Sep 17 00:00:00 2001 From: chichi Date: Mon, 4 Nov 2024 23:57:12 +0900 Subject: [PATCH 4/8] =?UTF-8?q?add:=20constants=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/constants.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/constants/constants.js b/src/constants/constants.js index 080f55cbe..53a929984 100644 --- a/src/constants/constants.js +++ b/src/constants/constants.js @@ -1,2 +1,7 @@ export const LOTTO_PRICE = 1000; -export const DELIMITER = ','; +export const DELIMITER = ', '; +export const FIRST_PRIZE_MONEY = 200000000; +export const SECOND_PRIZE_MONEY = 30000000; +export const THIRD_PRIZE_MONEY = 1500000; +export const FOURTH_PRIZE_MONEY = 50000; +export const FIFTH_PRIZE_MONEY = 5000; From 9b17027eff8d22135743c3c7715b27e147ce0f9a Mon Sep 17 00:00:00 2001 From: chichi Date: Mon, 4 Nov 2024 23:57:36 +0900 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20Lotto=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EB=82=B4=EB=B6=80=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Model/Lotto.js | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Model/Lotto.js b/src/Model/Lotto.js index cb0b1527e..477cc3014 100644 --- a/src/Model/Lotto.js +++ b/src/Model/Lotto.js @@ -1,3 +1,6 @@ +import { DELIMITER } from '../constants/constants.js'; +import { ERROR_MESSAGES } from '../constants/messages.js'; + class Lotto { #numbers; @@ -7,12 +10,31 @@ class Lotto { } #validate(numbers) { + if (!numbers) { + throw new Error(ERROR_MESSAGES.EMPTY_LOTTO_NUMBERS); + } + + if (numbers.some((number) => isNaN(number))) { + throw new Error(ERROR_MESSAGES.INVALID_LOTTO_NUMBERS); + } + if (numbers.length !== 6) { - throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); + throw new Error(ERROR_MESSAGES.INVALID_LOTTO_COUNT); + } + + const uniqueNumbers = new Set(numbers); + if (uniqueNumbers.size !== numbers.length) { + throw new Error(ERROR_MESSAGES.DUPLICATE_LOTTO_NUMBERS); } } - // TODO: 추가 기능 구현 + getLottoNumbers() { + return this.#numbers; + } + + getLottoNumbersToString() { + return `[${this.#numbers.join(DELIMITER)}]`; + } } export default Lotto; From d500a36dee2023e40e563790af6a740d7f0a8760 Mon Sep 17 00:00:00 2001 From: chichi Date: Mon, 4 Nov 2024 23:58:02 +0900 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20Controller=20->=20App.js=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=A9=94=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 3 deletions(-) diff --git a/src/App.js b/src/App.js index 9077f6d3f..87cf0e48f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,9 +1,165 @@ -import Controller from './Controller/Controller.js'; +import { Random } from '@woowacourse/mission-utils'; +import { + DELIMITER, + LOTTO_PRICE, + FIRST_PRIZE_MONEY, + SECOND_PRIZE_MONEY, + THIRD_PRIZE_MONEY, + FOURTH_PRIZE_MONEY, + FIFTH_PRIZE_MONEY, +} from './constants/constants.js'; +import { ERROR_MESSAGES } from './constants/messages.js'; +import Lotto from './Model/Lotto.js'; +import InputView from './View/InputView.js'; +import OutputView from './View/OutputView.js'; class App { + #result; + + constructor() { + this.#result = []; + } + async run() { - const controller = new Controller(); - controller.execute(); + const inputView = new InputView(); + const outputView = new OutputView(); + + const amount = await inputView.getAmount(); + this.validateAmount(amount); + + const lottoCount = amount / LOTTO_PRICE; + const lottos = await this.buyLotto(lottoCount); + + await outputView.printBoughtLottos(lottoCount, lottos); + + const winningNumbers = await inputView.getWinningNumbers(); + const splittedWinningNumbers = winningNumbers + .split(DELIMITER.trim()) + .map((number) => Number(number)); + + const winningLotto = new Lotto(splittedWinningNumbers); + const bonusNumber = await inputView.getBonusNumber(); + + this.#result = this.getLottoMatchResults(lottos, winningLotto, bonusNumber); + const prizeCount = this.prizeCountCalculate(); + const profitRate = this.calculateProfitRate(amount, prizeCount); + + await outputView.printResult(prizeCount, profitRate); + } + + validateAmount(amount) { + if (isNaN(amount)) { + throw new Error(ERROR_MESSAGES.NON_NUMERIC_AMOUNT); + } + if (!amount) { + throw new Error(ERROR_MESSAGES.EMPTY_LOTTO_PRICE); + } + if (amount % LOTTO_PRICE !== 0) { + throw new Error(ERROR_MESSAGES.INVALID_LOTTO_PRICE); + } + } + + async pickLottoNumbers() { + const lottoNumbers = await Random.pickUniqueNumbersInRange(1, 45, 6); + return lottoNumbers; + } + + async buyLotto(lottoCount) { + let lottos = []; + for (let i = 0; i < lottoCount; i++) { + const lottoNumbers = await this.pickLottoNumbers(); + const sortedLotto = lottoNumbers.sort((a, b) => a - b); + + const lotto = new Lotto(sortedLotto); + + lottos.push(lotto); + } + return lottos; + } + + getLottoMatchResults(lottos, winningLotto, bonusNumber) { + const winningLottoNumbers = winningLotto.getLottoNumbers(); + const winningNumberSet = new Set(winningLottoNumbers); + + let result = []; + + for (let i = 0; i < lottos.length; i++) { + const lottoNumbers = lottos[i].getLottoNumbers(); // [1,2,3,8,15,43] + let matchCount = 0; + let bonusMatchCount = 0; + + for (let j = 0; j < lottoNumbers.length; j++) { + if (winningNumberSet.has(lottoNumbers[j])) { + matchCount += 1; + } + + if (bonusNumber === lottoNumbers[j]) { + bonusMatchCount += 1; + } + } + + result.push({ matchCount: matchCount, bonusMatchCount: bonusMatchCount }); + } + + return result; + } + + prizeCountCalculate() { + const prizeCount = { + firstPrizeCount: 0, + secondPrizeCount: 0, + thirdPrizeCount: 0, + fourthPrizeCount: 0, + fifthPrizeCount: 0, + }; + + this.#result.forEach(({ matchCount, bonusMatchCount }) => { + if (matchCount + bonusMatchCount === 3) { + prizeCount.fifthPrizeCount += 1; + } + + if (matchCount + bonusMatchCount === 4) { + prizeCount.fourthPrizeCount += 1; + } + + if (matchCount + bonusMatchCount === 5) { + prizeCount.thirdPrizeCount += 1; + } + + if (matchCount === 5 && bonusMatchCount === 1) { + prizeCount.secondPrizeCount += 1; + } + + if (matchCount === 6) { + prizeCount.firstPrizeCount += 1; + } + }); + return prizeCount; + } + + calculateProfitRate(amount, prizeCount) { + const { + firstPrizeCount, + secondPrizeCount, + thirdPrizeCount, + fourthPrizeCount, + fifthPrizeCount, + } = prizeCount; + + const prizeMoney = + firstPrizeCount * FIRST_PRIZE_MONEY + + secondPrizeCount * SECOND_PRIZE_MONEY + + thirdPrizeCount * THIRD_PRIZE_MONEY + + fourthPrizeCount * FOURTH_PRIZE_MONEY + + fifthPrizeCount * FIFTH_PRIZE_MONEY; + + const profitRate = (prizeMoney / amount) * 100; + + if (!Number.isInteger(profitRate)) { + return profitRate.toFixed(1); + } + + return profitRate; } } From 386a4dcff9a72f7205e7b1ed373e9cabc3da4c55 Mon Sep 17 00:00:00 2001 From: chichi Date: Mon, 4 Nov 2024 23:58:12 +0900 Subject: [PATCH 7/8] =?UTF-8?q?add:=20=EC=83=81=EC=88=98=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/messages.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/constants/messages.js b/src/constants/messages.js index cc0a13745..25885a71a 100644 --- a/src/constants/messages.js +++ b/src/constants/messages.js @@ -2,11 +2,16 @@ export const PROMPT_MESSAGES = Object.freeze({ INPUT_AMOUNT: '구입금액을 입력해 주세요.\n', INPUT_WINNING_NUMBERS: '당첨 번호를 입력해 주세요.\n', INPUT_BONUS_NUMBERS: '보너스 번호를 입력해 주세요.\n', + OUTPUT_LOTTOS: '개를 구매했습니다.', }); export const ERROR_MESSAGES = Object.freeze({ - INVALID_LOTTO_PRICE: '구입 금액은 1,000원 단위로 입력해 주세요.', - INVALID_LOTTO_NUMBERS: '당첨 번호를 쉼표 기준으로 구분해 주세요.', - EMPTY_LOTTO_NUMBERS: '당첨 번호를 입력해 주세요.', - INVALID_LOTTO_COUNT: '당첨 번호를 6개 입력해 주세요.', + NON_NUMERIC_AMOUNT: '[ERROR] 구입 금액은 숫자로 입력해 주세요.', + EMPTY_LOTTO_PRICE: '[ERROR] 구입 금액이 입력되지 않았습니다.', + INVALID_LOTTO_PRICE: '[ERROR] 구입 금액은 1,000원 단위로 입력해 주세요.', + INVALID_LOTTO_NUMBERS: '[ERROR] 당첨 번호를 숫자로 입력해 주세요.', + EMPTY_LOTTO_NUMBERS: '[ERROR] 당첨 번호를 입력해 주세요.', + INVALID_LOTTO_COUNT: '[ERROR] 로또 번호는 6개여야 합니다.', + DUPLICATE_LOTTO_NUMBERS: + '[ERROR] 로또 번호에 중복된 숫자를 사용하실 수 없습니다.', }); From f98219092bb390de5ae5ea9973dae30f15611bc8 Mon Sep 17 00:00:00 2001 From: chichi Date: Mon, 4 Nov 2024 23:59:11 +0900 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20View=20=EB=A1=9C=EC=A7=81=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/{View.js => InputView.js} | 8 +++--- src/View/OutputView.js | 39 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) rename src/View/{View.js => InputView.js} (83%) create mode 100644 src/View/OutputView.js diff --git a/src/View/View.js b/src/View/InputView.js similarity index 83% rename from src/View/View.js rename to src/View/InputView.js index f196d0b37..bc1ba518e 100644 --- a/src/View/View.js +++ b/src/View/InputView.js @@ -1,10 +1,10 @@ import { Console } from '@woowacourse/mission-utils'; import { PROMPT_MESSAGES } from '../constants/messages.js'; -class View { +class InputView { async getAmount() { const amount = await Console.readLineAsync(PROMPT_MESSAGES.INPUT_AMOUNT); - return amount; + return Number(amount); } async getWinningNumbers() { @@ -18,8 +18,8 @@ class View { const bonusNumber = await Console.readLineAsync( PROMPT_MESSAGES.INPUT_BONUS_NUMBERS ); - return bonusNumber; + return Number(bonusNumber); } } -export default View; +export default InputView; diff --git a/src/View/OutputView.js b/src/View/OutputView.js new file mode 100644 index 000000000..6707bd119 --- /dev/null +++ b/src/View/OutputView.js @@ -0,0 +1,39 @@ +import { Console } from '@woowacourse/mission-utils'; +import { PROMPT_MESSAGES } from '../constants/messages.js'; + +class OutputView { + async printBoughtLottos(lottoCount, lottos) { + await Console.print(`${lottoCount}${PROMPT_MESSAGES.OUTPUT_LOTTOS}`); + for (const lotto of lottos) { + const lottoNumbers = lotto.getLottoNumbersToString(); + await Console.print(`${lottoNumbers}`); + } + } + + async printResult(prizeCount, profitRate) { + const { + firstPrizeCount, + secondPrizeCount, + thirdPrizeCount, + fourthPrizeCount, + fifthPrizeCount, + } = prizeCount; + + const printPrompt = [ + '당첨 통계', + '---', + `3개 일치 (5,000원) - ${fifthPrizeCount}개`, + `4개 일치 (50,000원) - ${fourthPrizeCount}개`, + `5개 일치 (1,500,000원) - ${thirdPrizeCount}개`, + `5개 일치, 보너스 볼 일치 (30,000,000원) - ${secondPrizeCount}개`, + `6개 일치 (2,000,000,000원) - ${firstPrizeCount}개`, + `총 수익률은 ${profitRate}%입니다.`, + ]; + + for (const prompt of printPrompt) { + await Console.print(`${prompt}`); + } + } +} + +export default OutputView;