From f89addeecb3def694a37ed0d0cd67d230def0b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EA=B8=B0=ED=99=98?= Date: Wed, 8 Nov 2023 23:49:06 +0900 Subject: [PATCH] . --- __tests__/ApplicationTest.js | 64 ++++++++++++++++++------------------ __tests__/LottoTest.js | 12 +++---- docs/README.md | 24 ++++++++++++++ src/App.js | 16 ++++++++- src/Console.js | 19 +++++++++++ src/Lotto.js | 11 +++++-- src/index.js | 2 +- src/utility.js | 36 ++++++++++++++++++++ src/validate.js | 0 9 files changed, 142 insertions(+), 42 deletions(-) create mode 100644 docs/README.md create mode 100644 src/Console.js create mode 100644 src/utility.js create mode 100644 src/validate.js diff --git a/__tests__/ApplicationTest.js b/__tests__/ApplicationTest.js index 227bd03864..180fc9b7ef 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 { MissionUtils } from '@woowacourse/mission-utils'; +import App from '../src/App'; const mockQuestions = (inputs) => { MissionUtils.Console.readLineAsync = jest.fn(); @@ -13,13 +13,14 @@ const mockQuestions = (inputs) => { const mockRandoms = (numbers) => { MissionUtils.Random.pickUniqueNumbersInRange = jest.fn(); - numbers.reduce((acc, number) => { - return acc.mockReturnValueOnce(number); - }, MissionUtils.Random.pickUniqueNumbersInRange); + numbers.reduce( + (acc, number) => acc.mockReturnValueOnce(number), + MissionUtils.Random.pickUniqueNumbersInRange, + ); }; const getLogSpy = () => { - const logSpy = jest.spyOn(MissionUtils.Console, "print"); + const logSpy = jest.spyOn(MissionUtils.Console, 'print'); logSpy.mockClear(); return logSpy; }; @@ -28,8 +29,8 @@ const runException = async (input) => { // given 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 RANDOM_NUMBERS_TO_END = [1, 2, 3, 4, 5, 6]; + 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 +40,15 @@ const runException = async (input) => { await app.play(); // 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 +62,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 +70,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,8 +92,7 @@ describe("로또 테스트", () => { }); }); - test("예외 테스트", async () => { - await runException("1000j"); + test('예외 테스트', async () => { + await runException('1000j'); }); }); - diff --git a/__tests__/LottoTest.js b/__tests__/LottoTest.js index 97bd457659..822e9e2782 100644 --- a/__tests__/LottoTest.js +++ b/__tests__/LottoTest.js @@ -1,17 +1,17 @@ -import Lotto from "../src/Lotto.js"; +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]'); }); // 아래에 추가 테스트 작성 가능 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..b18e0cfc4a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,24 @@ +## 필요 기능 + +- 구매 금액 입력 받는 함수 +- 금액에 따라 복권 갯수 출력 +- 갯수 만큼의 로또 번호 생성 및 출력 + - 로또 번호는 오름차순으로 출력 +- 당첨번호 입력 +- 보너스 번호 입력 +- 당첨 통계 출력 +- 수익률 출력 + +## 로또 당첨 기준 + +``` +- 로또 번호의 숫자 범위는 1~45까지이다. +- 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. +- 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다. +- 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다. + - 1등: 6개 번호 일치 / 2,000,000,000원 + - 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원 + - 3등: 5개 번호 일치 / 1,500,000원 + - 4등: 4개 번호 일치 / 50,000원 + - 5등: 3개 번호 일치 / 5,000원 +``` diff --git a/src/App.js b/src/App.js index c38b30d5b2..7cf629bb4e 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,19 @@ +import MyConsole from './Console.js'; +import utility from './utility.js'; + class App { - async play() {} + constructor() { + this.console = new MyConsole(); + } + + async play() { + const input = await this.console.readLineAsync('구입금액을 입력해 주세요.'); + utility.validateInput(input); + const money = utility.changeStringToNumber(input); + const amount = utility.getLottoAmount(money); + this.console.log(`${amount}개를 구매했습니다.`); + const lottos = utility.generateLottos(amount); + } } export default App; diff --git a/src/Console.js b/src/Console.js new file mode 100644 index 0000000000..b7a86eabd5 --- /dev/null +++ b/src/Console.js @@ -0,0 +1,19 @@ +import { Console } from '@woowacourse/mission-utils'; + +export default class MyConsole { + log(value) { + Console.print(value); + return this; + } + + async read(value = '') { + const input = await Console.readLineAsync(value); + return input; + } + + async readLineAsync(value = '') { + Console.print(value); + await Console.readLineAsync(''); + return this; + } +} diff --git a/src/Lotto.js b/src/Lotto.js index cb0b1527e9..bc29a89174 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -1,18 +1,25 @@ +import MyConsole from './Console.js'; + class Lotto { #numbers; constructor(numbers) { + this.console = new MyConsole(); this.#validate(numbers); - this.#numbers = numbers; + this.#numbers = [...numbers].sort((a, b) => a - b); } #validate(numbers) { if (numbers.length !== 6) { - throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); + throw new Error('[ERROR] 로또 번호는 6개여야 합니다.'); } + return this; } // TODO: 추가 기능 구현 + printLotto() { + this.console.log(this.#numbers); + } } export default Lotto; diff --git a/src/index.js b/src/index.js index 93eda3237a..0a3bc50015 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.play(); diff --git a/src/utility.js b/src/utility.js new file mode 100644 index 0000000000..900fb6831d --- /dev/null +++ b/src/utility.js @@ -0,0 +1,36 @@ +import { Random } from '@woowacourse/mission-utils'; +import Lotto from './Lotto.js'; + +const utility = { + changeStringToNumber: (str) => Number(str), + validateInput: (input) => { + const number = Number(input); + if (Number.isNaN(number)) { + throw new Error('[ERROR] 숫자를 입력해주세요.'); + } + }, + getLottoAmount: (money) => money / 1000, + + generateLottos: (amount) => { + const lottos = []; + for (let i = 0; i < amount; i += 1) { + lottos.push(utility.generateLotto()); + } + return lottos; + }, + + generateLotto: () => { + const numbers = []; + while (numbers.length < 6) { + const number = Random.pickUniqueNumbersInRange(1, 45, 6); + if (!numbers.includes(number)) { + numbers.push(number); + } + } + const lotto = new Lotto(numbers); + lotto.printLotto(); + return lotto; + }, +}; + +export default utility; diff --git a/src/validate.js b/src/validate.js new file mode 100644 index 0000000000..e69de29bb2