From f011fded7f992aea9adf2e85805304187bee1f4f Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Sun, 5 Nov 2023 22:59:00 +0900 Subject: [PATCH 01/24] =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aff2c46597..363417fd1e 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ class Lotto { #validate(numbers) { if (numbers.length !== 6) { - throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); + throw new Error('[ERROR] 로또 번호는 6개여야 합니다.'); } } @@ -237,3 +237,30 @@ class Lotto { - **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가한다. - [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고해 커밋 메시지를 작성한다. - 과제 진행 및 제출 방법은 [프리코스 과제 제출](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 문서를 참고한다. + +## 구현 기능 목록 + +### 1. 도메인 로직 + +- 로또번호 생성 기능 + - 지정 범위 내에서 원하는 개수의 숫자를 무작위로 생성하는 기능 + - 무작위로 생성된 숫자가 중복되지 않는 기능 + - 생성된 번호 오름차순 정렬 기능 +- 수익률 계산 및 소수점 둘째 자리 반올림 + +### 2. UI 담당 + +- 입력 + - 구입금액 + - 당첨 번호 + - 보너스 번호 +- 출력 + - 발행한 로또 수량 및 번호 + - 수익률 및 당첨 내역 + - 에러 문구 `예시) [ERROR] 숫자가 잘못된 형식입니다.` + +### 3. 기타 + +- 에러 처리 + - 구입 금액 입력 시 천원 단위 확인 + - 당첨 번호와 보너스 번호 입력 시, 중복 입력 체크 From cb61623549ef57d17808b92810791d8273c5a427 Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Sun, 5 Nov 2023 23:40:10 +0900 Subject: [PATCH 02/24] =?UTF-8?q?=EB=A1=9C=EB=98=90=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20-=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=20=EB=B2=94=EC=9C=84=20=EB=82=B4=20=EC=9B=90=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B0=9C=EC=88=98=EC=9D=98=20=EC=88=AB=EC=9E=90=20?= =?UTF-8?q?=EB=AC=B4=EC=9E=91=EC=9C=84=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EB=B6=88=EA=B0=80=20=EA=B8=B0=EB=8A=A5=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/Lotto.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Lotto.js b/src/Lotto.js index cb0b1527e9..313a9b2a4f 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -1,3 +1,5 @@ +import { Console, Random } from '@woowacourse/mission-utils'; + class Lotto { #numbers; @@ -8,11 +10,18 @@ class Lotto { #validate(numbers) { if (numbers.length !== 6) { - throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); + throw new Error('[ERROR] 로또 번호는 6개여야 합니다.'); } } // TODO: 추가 기능 구현 + createLotto() { + const lottoNumberList = []; + while (lottoNumberList.length < 6) { + pick = Random.pickUniqueNumbersInRange(1, 45); + if (!lottoNumberList.includes(pick)) lottoNumberList.push(pick); + } + } } export default Lotto; From a68afe74f15cb5cd23f8a5f1bc43a5f16d21afd4 Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Sun, 5 Nov 2023 23:49:46 +0900 Subject: [PATCH 03/24] =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=B2=88=ED=98=B8?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5-=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EB=90=9C=20=EB=B2=88=ED=98=B8=20=EC=98=A4=EB=A6=84?= =?UTF-8?q?=EC=B0=A8=EC=88=9C=20=EC=A0=95=EB=A0=AC=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Lotto.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Lotto.js b/src/Lotto.js index 313a9b2a4f..e25e415dac 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -21,6 +21,14 @@ class Lotto { pick = Random.pickUniqueNumbersInRange(1, 45); if (!lottoNumberList.includes(pick)) lottoNumberList.push(pick); } + return lottoNumberList; + } + + sortAscending(numList) { + const result = [...numList]; + return result.sort((a, b) => { + return a - b; + }); } } From df7cb4b370a29eb8c9b3a5246968fcfe7467c08d Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 00:15:39 +0900 Subject: [PATCH 04/24] =?UTF-8?q?=EC=88=98=EC=9D=B5=EB=A5=A0=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EB=B0=8F=20=EC=86=8C=EC=88=98=EC=A0=90=20=EB=91=98?= =?UTF-8?q?=EC=A7=B8=20=EC=9E=90=EB=A6=AC=20=EB=B0=98=EC=98=AC=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Lotto.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Lotto.js b/src/Lotto.js index e25e415dac..876654112e 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -30,6 +30,10 @@ class Lotto { return a - b; }); } + + rateReturn(purchase, revenue) { + return parseFloat((revenue / purchase) * 100).toFixed(1); + } } export default Lotto; From 2303c851880cf4563e6b88690570fedb734edffe Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 00:18:02 +0900 Subject: [PATCH 05/24] =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 363417fd1e..bb754eb29c 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,7 @@ class Lotto { - 무작위로 생성된 숫자가 중복되지 않는 기능 - 생성된 번호 오름차순 정렬 기능 - 수익률 계산 및 소수점 둘째 자리 반올림 +- 로또 번호 당첨 및 수익금 통계 ### 2. UI 담당 From 2bea852ef509c31f439f6cd9dec8fe5694ff2f3c Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 00:23:54 +0900 Subject: [PATCH 06/24] =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=B2=88=ED=98=B8?= =?UTF-8?q?=20=EB=8B=B9=EC=B2=A8=20=EA=B0=AF=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Lotto.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Lotto.js b/src/Lotto.js index 876654112e..1ae0b83eb7 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -34,6 +34,13 @@ class Lotto { rateReturn(purchase, revenue) { return parseFloat((revenue / purchase) * 100).toFixed(1); } + + winningRate(userNumList, winningNumList) { + const same = userNumList.filter((num) => + winningNumList.includes(num), + ).length; + return same; + } } export default Lotto; From 90fae62fc827831f1dd44a8237f3c5e5806e020d Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 00:57:58 +0900 Subject: [PATCH 07/24] =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20=EC=83=81=EC=88=98=ED=99=94=20=EB=B0=8F=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/input/Input.js | 19 +++++++++++++++++++ src/input/message.js | 6 ++++++ 2 files changed, 25 insertions(+) create mode 100644 src/input/Input.js create mode 100644 src/input/message.js diff --git a/src/input/Input.js b/src/input/Input.js new file mode 100644 index 0000000000..6616e77cde --- /dev/null +++ b/src/input/Input.js @@ -0,0 +1,19 @@ +import { Console, Random } from '@woowacourse/mission-utils'; +import { MESSAGES } from './message.js'; + +class Input { + async inputPurchase() { + const purchase = await Console.readLineAsync(MESSAGES.PURCHASE_INPUT); + return purchase; + } + + async inputWinningNum() { + const winning = await Console.readLineAsync(MESSAGES.WINNING_INPUT); + return winning; + } + + async inputBonus() { + const bonus = await Console.readLineAsync(MESSAGES.BONUS_INPUT); + return bonus; + } +} diff --git a/src/input/message.js b/src/input/message.js new file mode 100644 index 0000000000..5bc0426fe1 --- /dev/null +++ b/src/input/message.js @@ -0,0 +1,6 @@ +export const MESSAGES = { + PURCHASE_INPUT: '구입금액을 입력해 주세요.\n', + WINNING_INPUT: '당첨 번호를 입력해 주세요.\n', + BONUS_INPUT: '보너스 번호를 입력해 주세요.\n', + WINNING_STATISTICS: '당첨 통계', +}; From 914bc47dd8509aea75ed6ddca1023d04107bd88a Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 01:36:41 +0900 Subject: [PATCH 08/24] =?UTF-8?q?=EC=B6=9C=EB=A0=A5=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20=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/message.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/message.js diff --git a/src/message.js b/src/message.js new file mode 100644 index 0000000000..e431b4f3bb --- /dev/null +++ b/src/message.js @@ -0,0 +1,13 @@ +export const MESSAGES = { + PURCHASE_INPUT: '구입금액을 입력해 주세요.\n', + WINNING_INPUT: '당첨 번호를 입력해 주세요.\n', + BONUS_INPUT: '보너스 번호를 입력해 주세요.\n', +}; + +export const PRIZE_MESSAGES = [ + '3개 일치 (5,000원)', + '4개 일치 (50,000원)', + '5개 일치 (1,500,000원)', + '5개 일치, 보너스 볼 일치 (30,000,000원)', + '6개 일치 (2,000,000,000원)', +]; From 78bc78b4e6725bfcf575e88b111182b6fd34a58f Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 01:39:06 +0900 Subject: [PATCH 09/24] =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Input.js | 21 +++++++++++++++++++++ src/Output.js | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/Input.js create mode 100644 src/Output.js diff --git a/src/Input.js b/src/Input.js new file mode 100644 index 0000000000..0cf61945c1 --- /dev/null +++ b/src/Input.js @@ -0,0 +1,21 @@ +import { Console } from '@woowacourse/mission-utils'; +import { MESSAGES } from './message.js'; + +class Input { + async inputPurchase() { + const purchase = await Console.readLineAsync(MESSAGES.PURCHASE_INPUT); + return purchase; + } + + async inputWinningNum() { + const winning = await Console.readLineAsync(MESSAGES.WINNING_INPUT); + return winning; + } + + async inputBonus() { + const bonus = await Console.readLineAsync(MESSAGES.BONUS_INPUT); + return bonus; + } +} + +export default Input; diff --git a/src/Output.js b/src/Output.js new file mode 100644 index 0000000000..1432f17494 --- /dev/null +++ b/src/Output.js @@ -0,0 +1,19 @@ +import { Console } from '@woowacourse/mission-utils'; + +class Output { + purchaseHistory(purchaseList) { + Console.print(`${purchaseList.length}개 구매했습니다.`); + for (const lotto in purchaseList) { + Console.print(purchaseList[lotto]); + } + } + + winningDetails(matchNum, rateReturn) { + for (let i = 0; i < matchNum.length; i++) { + Console.print(`${PRIZE_MESSAGES[i]} - ${matchNum[i]}개`); + } + Console.print(`총 수익률은 ${rateReturn}입니다.`); + } +} + +export default Output; From 1d13256fd53e6288e6db9b28debc8b8398776d4b Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 01:40:14 +0900 Subject: [PATCH 10/24] =?UTF-8?q?c=EC=B6=9C=EB=A0=A5=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84=20-=20=EB=B0=9C=ED=96=89?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EB=98=90=20=EC=88=98=EB=9F=89=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B2=88=ED=98=B8=EB=A6=AC=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Output.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Output.js b/src/Output.js index 1432f17494..b56287e5a8 100644 --- a/src/Output.js +++ b/src/Output.js @@ -7,13 +7,6 @@ class Output { Console.print(purchaseList[lotto]); } } - - winningDetails(matchNum, rateReturn) { - for (let i = 0; i < matchNum.length; i++) { - Console.print(`${PRIZE_MESSAGES[i]} - ${matchNum[i]}개`); - } - Console.print(`총 수익률은 ${rateReturn}입니다.`); - } } export default Output; From ecbbbbf5de6413a78bffae033faa80e670d9d118 Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Mon, 6 Nov 2023 01:40:54 +0900 Subject: [PATCH 11/24] =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84=20-=20=EC=88=98=EC=9D=B5?= =?UTF-8?q?=EB=A5=A0=20=EB=B0=8F=20=EB=8B=B9=EC=B2=A8=20=EB=82=B4=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Output.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Output.js b/src/Output.js index b56287e5a8..1432f17494 100644 --- a/src/Output.js +++ b/src/Output.js @@ -7,6 +7,13 @@ class Output { Console.print(purchaseList[lotto]); } } + + winningDetails(matchNum, rateReturn) { + for (let i = 0; i < matchNum.length; i++) { + Console.print(`${PRIZE_MESSAGES[i]} - ${matchNum[i]}개`); + } + Console.print(`총 수익률은 ${rateReturn}입니다.`); + } } export default Output; From 793bd9a55c5d6c3e6626842181f04cd54334c1b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Tue, 7 Nov 2023 10:12:12 +0900 Subject: [PATCH 12/24] =?UTF-8?q?style:=20view=20=EA=B5=AC=ED=98=84(input,?= =?UTF-8?q?output)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{ => View}/Input.js | 0 src/{ => View}/Output.js | 0 src/{ => View}/message.js | 0 src/input/Input.js | 19 ------------------- src/input/message.js | 6 ------ 5 files changed, 25 deletions(-) rename src/{ => View}/Input.js (100%) rename src/{ => View}/Output.js (100%) rename src/{ => View}/message.js (100%) delete mode 100644 src/input/Input.js delete mode 100644 src/input/message.js diff --git a/src/Input.js b/src/View/Input.js similarity index 100% rename from src/Input.js rename to src/View/Input.js diff --git a/src/Output.js b/src/View/Output.js similarity index 100% rename from src/Output.js rename to src/View/Output.js diff --git a/src/message.js b/src/View/message.js similarity index 100% rename from src/message.js rename to src/View/message.js diff --git a/src/input/Input.js b/src/input/Input.js deleted file mode 100644 index 6616e77cde..0000000000 --- a/src/input/Input.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Console, Random } from '@woowacourse/mission-utils'; -import { MESSAGES } from './message.js'; - -class Input { - async inputPurchase() { - const purchase = await Console.readLineAsync(MESSAGES.PURCHASE_INPUT); - return purchase; - } - - async inputWinningNum() { - const winning = await Console.readLineAsync(MESSAGES.WINNING_INPUT); - return winning; - } - - async inputBonus() { - const bonus = await Console.readLineAsync(MESSAGES.BONUS_INPUT); - return bonus; - } -} diff --git a/src/input/message.js b/src/input/message.js deleted file mode 100644 index 5bc0426fe1..0000000000 --- a/src/input/message.js +++ /dev/null @@ -1,6 +0,0 @@ -export const MESSAGES = { - PURCHASE_INPUT: '구입금액을 입력해 주세요.\n', - WINNING_INPUT: '당첨 번호를 입력해 주세요.\n', - BONUS_INPUT: '보너스 번호를 입력해 주세요.\n', - WINNING_STATISTICS: '당첨 통계', -}; From 3005ba880d6e213cd0943e0a2a106fc9e2d22f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Tue, 7 Nov 2023 10:49:20 +0900 Subject: [PATCH 13/24] =?UTF-8?q?style:=20eslint=20=EB=B0=8F=20prettier=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Lotto.js | 4 ++-- src/View/Input.js | 2 +- src/View/Output.js | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Lotto.js b/src/Lotto.js index 1ae0b83eb7..8ebe401617 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -1,4 +1,4 @@ -import { Console, Random } from '@woowacourse/mission-utils'; +import { Random } from '@woowacourse/mission-utils'; class Lotto { #numbers; @@ -18,7 +18,7 @@ class Lotto { createLotto() { const lottoNumberList = []; while (lottoNumberList.length < 6) { - pick = Random.pickUniqueNumbersInRange(1, 45); + const pick = Random.pickUniqueNumbersInRange(1, 45); if (!lottoNumberList.includes(pick)) lottoNumberList.push(pick); } return lottoNumberList; diff --git a/src/View/Input.js b/src/View/Input.js index 0cf61945c1..b955c41107 100644 --- a/src/View/Input.js +++ b/src/View/Input.js @@ -1,5 +1,5 @@ import { Console } from '@woowacourse/mission-utils'; -import { MESSAGES } from './message.js'; +import MESSAGES from './message'; class Input { async inputPurchase() { diff --git a/src/View/Output.js b/src/View/Output.js index 1432f17494..9abf495677 100644 --- a/src/View/Output.js +++ b/src/View/Output.js @@ -1,4 +1,5 @@ import { Console } from '@woowacourse/mission-utils'; +import { PRIZE_MESSAGES } from './message'; class Output { purchaseHistory(purchaseList) { @@ -9,7 +10,7 @@ class Output { } winningDetails(matchNum, rateReturn) { - for (let i = 0; i < matchNum.length; i++) { + for (let i = 0; i < matchNum.length; i += 1) { Console.print(`${PRIZE_MESSAGES[i]} - ${matchNum[i]}개`); } Console.print(`총 수익률은 ${rateReturn}입니다.`); From 473d9009322c2b8fbf2fec59674504301a290c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Tue, 7 Nov 2023 13:15:18 +0900 Subject: [PATCH 14/24] =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC?= =?UTF-8?q?=EC=97=90=20=EC=9E=85=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=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/Controller/Controller.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/Controller/Controller.js diff --git a/src/Controller/Controller.js b/src/Controller/Controller.js new file mode 100644 index 0000000000..ecca59b4dd --- /dev/null +++ b/src/Controller/Controller.js @@ -0,0 +1,28 @@ +import Input from '../View/Input'; +import Output from '../View/Output'; + +class Controller { + #amount; + + #winnginNum; + + #bonusNum; + + constructor() { + this.input = new Input(); + this.output = new Output(); + } + + async buyLotto() { + this.#amount = await this.input.inputPurchase(); + // 구입금액만큼 로또사기 + // 로또 출력 + } + + async inputWinningNum() { + this.#winnginNum = await this.input.inputWinningNum(); + this.#bonusNum = await this.input.inputBonus(); + } +} + +export default Controller; From 91b44631d04ba933995bded51c88b57799f6fb03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Tue, 7 Nov 2023 14:38:04 +0900 Subject: [PATCH 15/24] =?UTF-8?q?Lotto=20class=EC=9D=98=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5(=EB=B2=88=ED=98=B8=20=EC=83=9D=EC=84=B1,=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC,=20=EC=88=98=EC=9D=B5=EB=A5=A0)=20model=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Model/LottoService.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/Model/LottoService.js diff --git a/src/Model/LottoService.js b/src/Model/LottoService.js new file mode 100644 index 0000000000..88a5d9a2c3 --- /dev/null +++ b/src/Model/LottoService.js @@ -0,0 +1,32 @@ +import { Random } from '@woowacourse/mission-utils'; + +class LottoService { + createLotto() { + const lottoNumberList = []; + while (lottoNumberList.length < 6) { + const pick = Random.pickUniqueNumbersInRange(1, 45); + if (!lottoNumberList.includes(pick)) lottoNumberList.push(pick); + } + return lottoNumberList; + } + + sortAscending(numList) { + const result = [...numList]; + return result.sort((a, b) => { + return a - b; + }); + } + + rateReturn(purchase, revenue) { + return parseFloat((revenue / purchase) * 100).toFixed(1); + } + + winningRate(userNumList, winningNumList) { + const same = userNumList.filter((num) => + winningNumList.includes(num), + ).length; + return same; + } +} + +export default LottoService; From 48da45e00317a2f1efbb3169b581425cbfa9b1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Tue, 7 Nov 2023 15:44:59 +0900 Subject: [PATCH 16/24] =?UTF-8?q?createLotto=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Model/LottoService.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Model/LottoService.js b/src/Model/LottoService.js index 88a5d9a2c3..207f6f207d 100644 --- a/src/Model/LottoService.js +++ b/src/Model/LottoService.js @@ -2,12 +2,12 @@ import { Random } from '@woowacourse/mission-utils'; class LottoService { createLotto() { - const lottoNumberList = []; - while (lottoNumberList.length < 6) { - const pick = Random.pickUniqueNumbersInRange(1, 45); - if (!lottoNumberList.includes(pick)) lottoNumberList.push(pick); - } - return lottoNumberList; + let randomList; + do { + randomList = Random.pickUniqueNumbersInRange(1, 45, 6); + } while (randomList.some((num, index, arr) => arr.indexOf(num) !== index)); + + return randomList; } sortAscending(numList) { From 83d373cb626c566d3a8287d36b3bb5a939b32439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Tue, 7 Nov 2023 15:49:04 +0900 Subject: [PATCH 17/24] =?UTF-8?q?createLotto=20=ED=95=A8=EC=88=98=EC=97=90?= =?UTF-8?q?=20=EC=A0=95=EB=A0=AC=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80,?= =?UTF-8?q?=20sortAscending=ED=95=A8=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Model/LottoService.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Model/LottoService.js b/src/Model/LottoService.js index 207f6f207d..0cd9963bc3 100644 --- a/src/Model/LottoService.js +++ b/src/Model/LottoService.js @@ -6,15 +6,10 @@ class LottoService { do { randomList = Random.pickUniqueNumbersInRange(1, 45, 6); } while (randomList.some((num, index, arr) => arr.indexOf(num) !== index)); - - return randomList; - } - - sortAscending(numList) { - const result = [...numList]; - return result.sort((a, b) => { + const sortRandomList = randomList.sort((a, b) => { return a - b; }); + return sortRandomList; } rateReturn(purchase, revenue) { From f4b19a23d694d9ac823425ebce61abdf8ea13e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Wed, 8 Nov 2023 02:31:27 +0900 Subject: [PATCH 18/24] fix: Resolve Error module not found by modifying import statements --- src/View/Input.js | 2 +- src/View/Output.js | 7 ++++--- src/View/message.js | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/View/Input.js b/src/View/Input.js index b955c41107..0cf61945c1 100644 --- a/src/View/Input.js +++ b/src/View/Input.js @@ -1,5 +1,5 @@ import { Console } from '@woowacourse/mission-utils'; -import MESSAGES from './message'; +import { MESSAGES } from './message.js'; class Input { async inputPurchase() { diff --git a/src/View/Output.js b/src/View/Output.js index 9abf495677..f91816579b 100644 --- a/src/View/Output.js +++ b/src/View/Output.js @@ -1,11 +1,12 @@ import { Console } from '@woowacourse/mission-utils'; -import { PRIZE_MESSAGES } from './message'; +import { PRIZE_MESSAGES } from './message.js'; class Output { purchaseHistory(purchaseList) { - Console.print(`${purchaseList.length}개 구매했습니다.`); + Console.print(`\n${purchaseList.length}개 구매했습니다.`); for (const lotto in purchaseList) { - Console.print(purchaseList[lotto]); + const msg = purchaseList[lotto].join(', '); + Console.print(`[${msg}]`); } } diff --git a/src/View/message.js b/src/View/message.js index e431b4f3bb..4cef58bbab 100644 --- a/src/View/message.js +++ b/src/View/message.js @@ -1,7 +1,7 @@ export const MESSAGES = { PURCHASE_INPUT: '구입금액을 입력해 주세요.\n', - WINNING_INPUT: '당첨 번호를 입력해 주세요.\n', - BONUS_INPUT: '보너스 번호를 입력해 주세요.\n', + WINNING_INPUT: '\n당첨 번호를 입력해 주세요.\n', + BONUS_INPUT: '\n보너스 번호를 입력해 주세요.\n', }; export const PRIZE_MESSAGES = [ From be85ddd543bdcbd4bc3c51dc61c2e58ef789a4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Wed, 8 Nov 2023 02:36:31 +0900 Subject: [PATCH 19/24] feat: Implement controller functionality for MVC --- src/Controller/Controller.js | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Controller/Controller.js b/src/Controller/Controller.js index ecca59b4dd..9b91b59ac9 100644 --- a/src/Controller/Controller.js +++ b/src/Controller/Controller.js @@ -1,28 +1,51 @@ -import Input from '../View/Input'; -import Output from '../View/Output'; +import Input from '../View/Input.js'; +import Output from '../View/Output.js'; +import LottoService from '../Model/LottoService.js'; class Controller { #amount; - + #lottoList = []; #winnginNum; - #bonusNum; + #matchHistory; + #rateOfReturn; constructor() { this.input = new Input(); this.output = new Output(); + this.lottoService = new LottoService(); } async buyLotto() { this.#amount = await this.input.inputPurchase(); - // 구입금액만큼 로또사기 - // 로또 출력 + while (this.#amount > 0) { + this.#lottoList.push(this.lottoService.createLotto()); + this.#amount -= 1000; + } + this.output.purchaseHistory(this.#lottoList); } async inputWinningNum() { this.#winnginNum = await this.input.inputWinningNum(); this.#bonusNum = await this.input.inputBonus(); } + + winningStatement() { + this.#matchHistory = this.lottoService.getWinningList( + this.#lottoList, + this.#winnginNum, + this.#bonusNum, + ); + this.output.winningDetails( + this.#matchHistory, + this.#winnginNum, + this.#bonusNum, + ); + } + + rateReturn() { + this.#rateOfReturn = this.lottoService.getrateReturn(this.#amount); + } } export default Controller; From 0acf3ecd4788637b99b81f16929d0aa00a22f678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Wed, 8 Nov 2023 02:46:52 +0900 Subject: [PATCH 20/24] refactor: Refactor LottoService class --- src/Model/LottoService.js | 43 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/Model/LottoService.js b/src/Model/LottoService.js index 0cd9963bc3..147f50f74c 100644 --- a/src/Model/LottoService.js +++ b/src/Model/LottoService.js @@ -1,26 +1,47 @@ import { Random } from '@woowacourse/mission-utils'; class LottoService { + #MIN_NUM = 1; + #MAX_NUM = 45; + #CNT = 6; + #winningList = { + '3개 일치': 0, + '4개 일치': 0, + '5개 일치': 0, + '보너스 일치': 0, + '6개 일치': 0, + }; + #revenue = 0; + createLotto() { - let randomList; - do { - randomList = Random.pickUniqueNumbersInRange(1, 45, 6); - } while (randomList.some((num, index, arr) => arr.indexOf(num) !== index)); + const randomList = Random.pickUniqueNumbersInRange( + this.#MIN_NUM, + this.#MAX_NUM, + this.#CNT, + ); const sortRandomList = randomList.sort((a, b) => { return a - b; }); return sortRandomList; } - rateReturn(purchase, revenue) { - return parseFloat((revenue / purchase) * 100).toFixed(1); + getrateReturn(purchase) { + for (const result in this.#winningList) { + this.#revenue += this.#winningList[result]; + } + return parseFloat((this.#revenue / purchase) * 100).toFixed(1); } - winningRate(userNumList, winningNumList) { - const same = userNumList.filter((num) => - winningNumList.includes(num), - ).length; - return same; + getWinningList(userNumList, winningNumList, bonus) { + for (let i = 0; i < userNumList.length; i += 1) { + const matchNums = userNumList.filter((num) => + winningNumList.includes(num), + ); + if (userNumList[i].includes(bonus) && matchNums.length === 5) + this.#winningList[`보너스 일치`] += 1; + else this.#winningList[`${matchNums.length}개 일치`] += 1; + } + return this.#winningList; } } From 1389c4bc10dca3685a5de26fe8584c305f359651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Wed, 8 Nov 2023 02:50:42 +0900 Subject: [PATCH 21/24] chore: Remove all functions from lotto class --- src/Lotto.js | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 src/Lotto.js diff --git a/src/Lotto.js b/src/Lotto.js deleted file mode 100644 index 8ebe401617..0000000000 --- a/src/Lotto.js +++ /dev/null @@ -1,46 +0,0 @@ -import { Random } from '@woowacourse/mission-utils'; - -class Lotto { - #numbers; - - constructor(numbers) { - this.#validate(numbers); - this.#numbers = numbers; - } - - #validate(numbers) { - if (numbers.length !== 6) { - throw new Error('[ERROR] 로또 번호는 6개여야 합니다.'); - } - } - - // TODO: 추가 기능 구현 - createLotto() { - const lottoNumberList = []; - while (lottoNumberList.length < 6) { - const pick = Random.pickUniqueNumbersInRange(1, 45); - if (!lottoNumberList.includes(pick)) lottoNumberList.push(pick); - } - return lottoNumberList; - } - - sortAscending(numList) { - const result = [...numList]; - return result.sort((a, b) => { - return a - b; - }); - } - - rateReturn(purchase, revenue) { - return parseFloat((revenue / purchase) * 100).toFixed(1); - } - - winningRate(userNumList, winningNumList) { - const same = userNumList.filter((num) => - winningNumList.includes(num), - ).length; - return same; - } -} - -export default Lotto; From 2d5fbb33b5e94972a09d1c05175a5001cf3204d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Wed, 8 Nov 2023 02:54:08 +0900 Subject: [PATCH 22/24] refactor: Move existing Lotto class to the model --- src/Model/Lotto.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/Model/Lotto.js diff --git a/src/Model/Lotto.js b/src/Model/Lotto.js new file mode 100644 index 0000000000..1164a3f810 --- /dev/null +++ b/src/Model/Lotto.js @@ -0,0 +1,18 @@ +class Lotto { + #numbers; + + constructor(numbers) { + this.#validate(numbers); + this.#numbers = numbers; + } + + #validate(numbers) { + if (numbers.length !== 6) { + throw new Error('[ERROR] 로또 번호는 6개여야 합니다.'); + } + } + + // TODO: 추가 기능 구현 +} + +export default Lotto; From 26aa9f53e70b51e6cd842431f3172360622256f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A1=EC=A2=85=ED=98=B8?= Date: Wed, 8 Nov 2023 03:04:48 +0900 Subject: [PATCH 23/24] feat: Add funct buylotto & inputwinningNum to controller --- src/App.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index c38b30d5b2..97998a9539 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,18 @@ +import Controller from './Controller/Controller.js'; + class App { - async play() {} + constructor() { + this.controller = new Controller(); + // this.play(); + } + + async play() { + await this.controller.buyLotto(); + await this.controller.inputWinningNum(); + } } +const app = new App(); +await app.play(); + export default App; From 254f7d24f8353f994be16ccb6e154b2a3e90997d Mon Sep 17 00:00:00 2001 From: yook-jongho Date: Wed, 8 Nov 2023 23:51:02 +0900 Subject: [PATCH 24/24] refactor: app class --- __tests__/LottoTest.js | 17 +++++++++------ src/App.js | 7 ++++--- src/Controller/Controller.js | 22 +++++++++----------- src/Model/Lotto.js | 18 ++++++++++++++++ src/Model/LottoService.js | 40 ++++++++++++++++++------------------ src/View/Input.js | 30 +++++++++++++++++++++++++-- src/View/Output.js | 5 +++-- 7 files changed, 94 insertions(+), 45 deletions(-) diff --git a/__tests__/LottoTest.js b/__tests__/LottoTest.js index 97bd457659..13494d8468 100644 --- a/__tests__/LottoTest.js +++ b/__tests__/LottoTest.js @@ -1,18 +1,23 @@ -import Lotto from "../src/Lotto.js"; +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]'); }); // 아래에 추가 테스트 작성 가능 + test('로또 번호에 1~45가 아닌 숫자가 있으면 예외가 발생한다.', () => { + expect(() => { + new Lotto([1, 2, 3, 46, 57, 58]); + }).toThrow('[ERROR]'); + }); }); diff --git a/src/App.js b/src/App.js index 97998a9539..79e6e6ebb2 100644 --- a/src/App.js +++ b/src/App.js @@ -9,10 +9,11 @@ class App { async play() { await this.controller.buyLotto(); await this.controller.inputWinningNum(); + this.controller.winningStatement(); } } -const app = new App(); -await app.play(); - export default App; + +const app = new App(); +app.play(); diff --git a/src/Controller/Controller.js b/src/Controller/Controller.js index 9b91b59ac9..ed508e9c9f 100644 --- a/src/Controller/Controller.js +++ b/src/Controller/Controller.js @@ -1,5 +1,7 @@ +import { Console } from '@woowacourse/mission-utils'; import Input from '../View/Input.js'; import Output from '../View/Output.js'; +import Lotto from '../Model/Lotto.js'; import LottoService from '../Model/LottoService.js'; class Controller { @@ -18,15 +20,18 @@ class Controller { async buyLotto() { this.#amount = await this.input.inputPurchase(); - while (this.#amount > 0) { + let buy = this.#amount; + while (buy > 0) { this.#lottoList.push(this.lottoService.createLotto()); - this.#amount -= 1000; + buy -= 1000; } this.output.purchaseHistory(this.#lottoList); } async inputWinningNum() { - this.#winnginNum = await this.input.inputWinningNum(); + const userInput = await this.input.inputWinningNum(); + this.#winnginNum = userInput.split(','); + const lotto = new Lotto(this.#winnginNum); this.#bonusNum = await this.input.inputBonus(); } @@ -36,15 +41,8 @@ class Controller { this.#winnginNum, this.#bonusNum, ); - this.output.winningDetails( - this.#matchHistory, - this.#winnginNum, - this.#bonusNum, - ); - } - - rateReturn() { - this.#rateOfReturn = this.lottoService.getrateReturn(this.#amount); + this.#rateOfReturn = this.lottoService.getRateReturn(this.#amount); + this.output.winningDetails(this.#matchHistory, this.#rateOfReturn); } } diff --git a/src/Model/Lotto.js b/src/Model/Lotto.js index 1164a3f810..cfb1690f44 100644 --- a/src/Model/Lotto.js +++ b/src/Model/Lotto.js @@ -3,6 +3,8 @@ class Lotto { constructor(numbers) { this.#validate(numbers); + this.#winningNumValid(numbers); + this.#isDuplicate(numbers); this.#numbers = numbers; } @@ -13,6 +15,22 @@ class Lotto { } // TODO: 추가 기능 구현 + #winningNumValid(numbers) { + for (let i = 0; i < numbers.length; i++) { + if (numbers[i] > 45 || numbers[i] < 1) { + throw new Error( + '[ERROR] 로또 번호는 1~45 사이의 숫자만 있어야 합니다.', + ); + } + } + } + + #isDuplicate(numbers) { + const set = new Set(numbers); + if (set.length !== 6) { + throw new Error('[ERROR] 로또 번호에 중복된 숫자가 있으면 안됩니다.'); + } + } } export default Lotto; diff --git a/src/Model/LottoService.js b/src/Model/LottoService.js index 147f50f74c..a26da8b300 100644 --- a/src/Model/LottoService.js +++ b/src/Model/LottoService.js @@ -1,17 +1,10 @@ -import { Random } from '@woowacourse/mission-utils'; +import { Console, Random } from '@woowacourse/mission-utils'; class LottoService { #MIN_NUM = 1; #MAX_NUM = 45; #CNT = 6; - #winningList = { - '3개 일치': 0, - '4개 일치': 0, - '5개 일치': 0, - '보너스 일치': 0, - '6개 일치': 0, - }; - #revenue = 0; + #winningList = [0, 0, 0, 0, 0]; createLotto() { const randomList = Random.pickUniqueNumbersInRange( @@ -25,24 +18,31 @@ class LottoService { return sortRandomList; } - getrateReturn(purchase) { - for (const result in this.#winningList) { - this.#revenue += this.#winningList[result]; + getRateReturn(purchase) { + let revenue = 0; + const money = [5000, 50000, 1500000, 30000000, 2000000000]; + for (let i = 0; i < this.#winningList.length; i++) { + revenue += money[i] * this.#winningList[i]; } - return parseFloat((this.#revenue / purchase) * 100).toFixed(1); + return parseFloat((revenue / purchase) * 100).toFixed(1); } getWinningList(userNumList, winningNumList, bonus) { - for (let i = 0; i < userNumList.length; i += 1) { - const matchNums = userNumList.filter((num) => - winningNumList.includes(num), - ); - if (userNumList[i].includes(bonus) && matchNums.length === 5) - this.#winningList[`보너스 일치`] += 1; - else this.#winningList[`${matchNums.length}개 일치`] += 1; + for (const lotto of userNumList) { + let match = this.matchNums(lotto, winningNumList); + const hasBonus = lotto.includes(bonus - '0'); + if (match === 6 || (match === 5 && hasBonus)) { + match++; + } + this.#winningList[match - 3]++; } return this.#winningList; } + + matchNums(numList, winningNumList) { + const result = numList.filter((num) => winningNumList.includes(`${num}`)); + return result.length; + } } export default LottoService; diff --git a/src/View/Input.js b/src/View/Input.js index 0cf61945c1..196599804e 100644 --- a/src/View/Input.js +++ b/src/View/Input.js @@ -2,9 +2,35 @@ import { Console } from '@woowacourse/mission-utils'; import { MESSAGES } from './message.js'; class Input { + #purchase; + #isValid; async inputPurchase() { - const purchase = await Console.readLineAsync(MESSAGES.PURCHASE_INPUT); - return purchase; + while (true) { + try { + this.#purchase = await Console.readLineAsync(MESSAGES.PURCHASE_INPUT); + this.#isValid = this.purchaseValid(this.#purchase); + if (this.#isValid) { + return this.#purchase; + } + } catch (e) { + Console.print(e.message); + } + } + } + + purchaseValid(purchase) { + let valid = true; + if (isNaN(purchase)) { + valid = false; + throw new Error('[ERROR] 숫자를 입력해 주세요.'); + } else if (parseInt(purchase) < 1000) { + valid = false; + throw new Error('[ERROR] 1000원 이상 입력해 주세요.'); + } else if (parseInt(purchase) % 1000 !== 0) { + valid = false; + throw new Error('[ERROR] 1000원단위로 입력해주세요'); + } + return valid; } async inputWinningNum() { diff --git a/src/View/Output.js b/src/View/Output.js index f91816579b..e3b55e9491 100644 --- a/src/View/Output.js +++ b/src/View/Output.js @@ -3,7 +3,7 @@ import { PRIZE_MESSAGES } from './message.js'; class Output { purchaseHistory(purchaseList) { - Console.print(`\n${purchaseList.length}개 구매했습니다.`); + Console.print(`\n${purchaseList.length}개를 구매했습니다.`); for (const lotto in purchaseList) { const msg = purchaseList[lotto].join(', '); Console.print(`[${msg}]`); @@ -11,10 +11,11 @@ class Output { } winningDetails(matchNum, rateReturn) { + Console.print('\n당첨통계\n---'); for (let i = 0; i < matchNum.length; i += 1) { Console.print(`${PRIZE_MESSAGES[i]} - ${matchNum[i]}개`); } - Console.print(`총 수익률은 ${rateReturn}입니다.`); + Console.print(`총 수익률은 ${rateReturn}%입니다.`); } }