From 5ddf201d3e233f8591696bde2c6d60ad8ef37d78 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 15:07:35 +0900
Subject: [PATCH 01/19] =?UTF-8?q?docs:=20=EA=B5=AC=ED=98=84=20=EC=A0=84=20?=
=?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=9E=91=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 docs/README.md
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000000..47564e5b55
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,54 @@
+로또 게임 기능 목록
+--------------------
+
+
+- 로또 구입 금액 입력받기
+ - 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
+
+
+- 로또 발행
+ - 구입 금액에 해당하는 만큼 로또를 발행한다
+ - 로또 1장의 가격은 1000원이다
+
+
+- 구매한 로또 수량 및 번호 출력
+ - 로또 번호는 오름차순으로 정렬하여 보여준다.
+
+
+- 당첨 번호를 입력 받는다
+ - 번호는 쉼표(,)를 기준으로 구분한다.
+- 보너스 번호를 입력 받는다
+
+
+- 잘못된 입력에 대한 예외처리 (각 입력마다)
+ - 사용자가 잘못된 값을 입력할 경우 throw문을 사용해 예외를 발생시킨다. 그런 다음, "[ERROR]"로 시작하는 에러 메시지를 출력하고 해당 부분부터 입력을 다시 받는다.
+
+
+- 당첨 번호 추첨
+ - 1~45범위의 중복되지 않는 6개의 숫자를 뽑는다
+ - 보너스 번호를 뽑는다
+
+
+- 당첨금 계산
+ - 당첨은 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원
+
+
+- 당첨 내역 출력
+ - 일치한 번호 개수, 당첨금, 로또 개수
+ 3개 일치 (5,000원) - ?개
+ 4개 일치 (50,000원) - ?개
+ 5개 일치 (1,500,000원) - ?개
+ 5개 일치, 보너스 볼 일치 (30,000,000원) - ?개
+ 6개 일치 (2,000,000,000원) - ?개
+
+
+- 수익률 계산
+ - 수익률은 소수점 둘째 자리에서 반올림한다
+
+
+- 수익률 출력
From 299d6318bdffce36e62fb384a7ff36cbf09d4971 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 15:49:20 +0900
Subject: [PATCH 02/19] =?UTF-8?q?feat:=20=EA=B5=AC=EC=9E=85=20=EA=B8=88?=
=?UTF-8?q?=EC=95=A1=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EA=B8=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/App.js b/src/App.js
index c38b30d5b2..efbda63b4f 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,5 +1,14 @@
+import { MissionUtils } from "@woowacourse/mission-utils";
+import Lotto from "./Lotto.js";
class App {
- async play() {}
+ // 구입 금액 입력받기
+ async inputMoney() {
+ const money = await MissionUtils.Console.readLineAsync("구입금액을 입력해 주세요.\n");
+ if (money % 1000 !== 0) {
+ throw new Error("[ERROR] 1000원 단위로 입력해 주세요.");
+ }
+ return money;
+ }
}
export default App;
From 9c40731d22a34b8dca98dcba9bba1fe486bd1df8 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 15:49:39 +0900
Subject: [PATCH 03/19] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B0=9C?=
=?UTF-8?q?=ED=96=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/App.js b/src/App.js
index efbda63b4f..adec9ce4b7 100644
--- a/src/App.js
+++ b/src/App.js
@@ -9,6 +9,16 @@ class App {
}
return money;
}
+ // 로또 발행
+ publishLotto(money) {
+ const lottoCount = money / 1000;
+ const lottos = [];
+ for (let i = 0; i < lottoCount; i++) {
+ const randomNumbers = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6)
+ lottos.push(randomNumbers);
+ }
+ return lottos;
+ }
}
export default App;
From c7308f18033757a8daf1c1863031112ced20c5fb Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 15:49:55 +0900
Subject: [PATCH 04/19] =?UTF-8?q?feat:=20=EA=B5=AC=EB=A7=A4=ED=95=9C=20?=
=?UTF-8?q?=EB=A1=9C=EB=98=90=20=EC=88=98=EB=9F=89=20=EB=B0=8F=20=EB=B2=88?=
=?UTF-8?q?=ED=98=B8=20=EC=B6=9C=EB=A0=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/App.js b/src/App.js
index adec9ce4b7..ec387652e6 100644
--- a/src/App.js
+++ b/src/App.js
@@ -19,6 +19,13 @@ class App {
}
return lottos;
}
+ // 구매한 로또 수량 및 번호 출력
+ printLottos(lottos) {
+ MissionUtils.Console.print(`\n${lottos.length}개를 구매했습니다.`);
+ for (let i=0; i
Date: Wed, 8 Nov 2023 19:32:54 +0900
Subject: [PATCH 05/19] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?=
=?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EA=B8=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/App.js b/src/App.js
index ec387652e6..f2e72f7735 100644
--- a/src/App.js
+++ b/src/App.js
@@ -22,9 +22,16 @@ class App {
// 구매한 로또 수량 및 번호 출력
printLottos(lottos) {
MissionUtils.Console.print(`\n${lottos.length}개를 구매했습니다.`);
- for (let i=0; i Number(number.trim()));
+ return numbers;
+ }
}
}
From b2e1fea2e03ba52778b28bb4935b2c0cfe39f648 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 19:33:07 +0900
Subject: [PATCH 06/19] =?UTF-8?q?feat:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?=
=?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EA=B8=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/App.js b/src/App.js
index f2e72f7735..b36ff6de52 100644
--- a/src/App.js
+++ b/src/App.js
@@ -32,6 +32,16 @@ class App {
.map((number) => Number(number.trim()));
return numbers;
}
+
+ // 보너스 번호 입력받기
+ async inputBonusNumber() {
+ const inputString = await MissionUtils.Console.readLineAsync(
+ "보너스 번호를 입력해주세요.\n"
+ );
+ const bonusNumber = Number(inputString.trim());
+ return bonusNumber;
+ }
+
}
}
From bcb55e3ee6c528671deed9eb00d860a8cd4f66f8 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 19:33:35 +0900
Subject: [PATCH 07/19] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B3=84=20=EB=A1=9C?=
=?UTF-8?q?=EB=98=90=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=B0=EA=B3=BC=20?=
=?UTF-8?q?=EA=B3=84=EC=82=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/src/App.js b/src/App.js
index b36ff6de52..39b9fad1f3 100644
--- a/src/App.js
+++ b/src/App.js
@@ -42,6 +42,36 @@ class App {
return bonusNumber;
}
+ // 로또 하나에 대한 결과(등수) 계산
+
+ // 일치하는 번호 개수
+ countMatchingNumbers(lotto, winningNumbers) {
+ let count = 0;
+ lotto.forEach((number) => {
+ if (winningNumbers.includes(number)) {
+ count++;
+ }
+ });
+ return count;
+ }
+ // 등수 계산
+ computeRank(lotto, winningNumbers, bonusNumber) {
+ const count = this.countMatchingNumbers(lotto, winningNumbers);
+ switch (count) {
+ case 6:
+ return "1등";
+ case 5:
+ if (winningNumbers.includes(bonusNumber)) {
+ return "2등";
+ } else return "3등";
+ case 4:
+ return "4등";
+ case 3:
+ return "5등";
+ default:
+ return "꽝";
+ }
+ }
}
}
From 4bd1085809b9007b432a17d136606d794dc87613 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 19:35:25 +0900
Subject: [PATCH 08/19] =?UTF-8?q?feat:=20=EC=B4=9D=20=EB=8B=B9=EC=B2=A8=20?=
=?UTF-8?q?=EB=82=B4=EC=97=AD=20=EC=B6=9C=EB=A0=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/App.js b/src/App.js
index 39b9fad1f3..fd8fa279ed 100644
--- a/src/App.js
+++ b/src/App.js
@@ -72,6 +72,28 @@ class App {
return "꽝";
}
}
+
+ // 총 당첨 내역 출력
+ // 결과 합산
+ computeTotalResult(lottos, winningNumbers, bonusNubmer) {
+ const result = { "1등": 0, "2등": 0, "3등": 0, "4등": 0, "5등": 0, "꽝": 0};
+ for (const lotto of lottos) {
+ const rank = this.computeRank(lotto, winningNumbers, bonusNubmer);
+ result[rank]++;
+ }
+ return result;
+ }
+
+ // 출력
+ printResult(result) {
+ MissionUtils.Console.print(`
+당첨 통계\n---
+3개 일치 (5,000원) - ${result["5등"]}개
+4개 일치 (50,000원) - ${result["4등"]}개
+5개 일치 (1,500,000원) - ${result["3등"]}개
+5개 일치, 보너스 볼 일치 (30,000,000원) - ${result["2등"]}개
+6개 일치 (2,000,000,000원) - ${result["1등"]}개`);
+ }
}
}
From ae1227ab1982cfa29425046cb122fbab2161dbe5 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 20:08:19 +0900
Subject: [PATCH 09/19] =?UTF-8?q?feat:=20=EC=88=98=EC=9D=B5=EB=A5=A0=20?=
=?UTF-8?q?=EA=B3=84=EC=82=B0=20=EB=B0=8F=20=EC=B6=9C=EB=A0=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/App.js b/src/App.js
index fd8fa279ed..e31870c476 100644
--- a/src/App.js
+++ b/src/App.js
@@ -94,6 +94,18 @@ class App {
5개 일치, 보너스 볼 일치 (30,000,000원) - ${result["2등"]}개
6개 일치 (2,000,000,000원) - ${result["1등"]}개`);
}
+
+ // 수익률 계산
+
+ computeProfit(result,money){
+ const totalPrize = result["5등"]*5000 + result["4등"]*50000 + result["3등"]*1500000 + result["2등"]*30000000 + result["1등"]*2000000000;
+ const profit = (totalPrize/money*100).toFixed(1);
+ return profit;
+ }
+
+ printProfit(profit){
+ MissionUtils.Console.print(`총 수익률은 ${profit}%입니다.`);
+ }
}
}
From 1aaae94f87b4661667057be6a2401c5fc3a2a109 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:04:10 +0900
Subject: [PATCH 10/19] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=EC=B2=98?=
=?UTF-8?q?=EB=A6=AC=20-=20=EC=9E=85=EB=A0=A5=EC=97=90=20=EB=8C=80?=
=?UTF-8?q?=ED=95=9C=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?=
=?UTF-8?q?=ED=95=A8=EC=88=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 78 +++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 63 insertions(+), 15 deletions(-)
diff --git a/src/App.js b/src/App.js
index e31870c476..8b3eeedd1e 100644
--- a/src/App.js
+++ b/src/App.js
@@ -3,12 +3,27 @@ import Lotto from "./Lotto.js";
class App {
// 구입 금액 입력받기
async inputMoney() {
- const money = await MissionUtils.Console.readLineAsync("구입금액을 입력해 주세요.\n");
- if (money % 1000 !== 0) {
- throw new Error("[ERROR] 1000원 단위로 입력해 주세요.");
+ let money;
+ let isValidated = false;
+ while (!isValidated) {
+ const inputString = await MissionUtils.Console.readLineAsync(
+ "구입금액을 입력해 주세요.\n"
+ );
+ money = Number(inputString.trim());
+ isValidated = this.validateMoney(money);
}
return money;
}
+
+ // 예외처리
+ validateMoney(money) {
+ if (isNaN(money)) {
+ MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
+ } else if (money % 1000 !== 0) {
+ MissionUtils.Console.print("[ERROR] 1000원 단위로 입력해주세요.\n");
+ } else return true;
+ }
+
// 로또 발행
publishLotto(money) {
const lottoCount = money / 1000;
@@ -24,22 +39,55 @@ class App {
MissionUtils.Console.print(`\n${lottos.length}개를 구매했습니다.`);
// 당첨 번호 입력받기
async inputNumbers() {
- const inputString = await MissionUtils.Console.readLineAsync(
- "당첨 번호를 입력해주세요.\n"
- );
- const numbers = inputString
- .split(",")
- .map((number) => Number(number.trim()));
- return numbers;
+ let numbers;
+ let isValidated = false;
+ while (!isValidated) {
+ const inputString = await MissionUtils.Console.readLineAsync(
+ "\n당첨 번호를 입력해주세요.\n"
+ );
+ numbers = inputString.split(",").map((number) => Number(number.trim()));
+ isValidated = this.validateNumbers(numbers);
+ }
+ this.winningNumbers = numbers;
+ }
+
+ // 당첨 번호 예외처리
+ validateNumbers(numbers) {
+ if (numbers.length !== 6) {
+ MissionUtils.Console.print("[ERROR] 6개의 숫자를 입력해주세요.\n");
+ } else if (numbers.some((number) => isNaN(number))) {
+ MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
+ } else if (numbers.some((number) => number < 1 || number > 45)) {
+ MissionUtils.Console.print("[ERROR] 1~45 사이의 숫자를 입력해주세요.\n");
+ } else if (new Set(numbers).size !== 6) {
+ MissionUtils.Console.print("[ERROR] 중복된 숫자를 입력할 수 없습니다.\n");
+ } else return true;
}
// 보너스 번호 입력받기
async inputBonusNumber() {
- const inputString = await MissionUtils.Console.readLineAsync(
- "보너스 번호를 입력해주세요.\n"
- );
- const bonusNumber = Number(inputString.trim());
- return bonusNumber;
+ let bonusNumber;
+ let isValidated = false;
+ while (!isValidated) {
+ const inputString = await MissionUtils.Console.readLineAsync(
+ "\n보너스 번호를 입력해주세요.\n"
+ );
+ bonusNumber = Number(inputString.trim());
+ isValidated = this.validateBonusNumber(bonusNumber);
+ }
+ this.bonusNumber = bonusNumber;
+ }
+
+ validateBonusNumber(bonusNumber) {
+ const winningNumbers = this.winningNumbers;
+ if (isNaN(bonusNumber)) {
+ MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
+ } else if (bonusNumber < 1 || bonusNumber > 45) {
+ MissionUtils.Console.print("[ERROR] 1~45 사이의 숫자를 입력해주세요.\n");
+ } else if (winningNumbers.includes(bonusNumber)) {
+ MissionUtils.Console.print("[ERROR] 당첨 번호와 중복될 수 없습니다.\n");
+ }
+ else return true;
}
// 로또 하나에 대한 결과(등수) 계산
From 1ce7ac58ef05599fa2008ca541283a20bb7697c3 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:07:18 +0900
Subject: [PATCH 11/19] style: code formatting
---
src/App.js | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/App.js b/src/App.js
index 8b3eeedd1e..c5966db300 100644
--- a/src/App.js
+++ b/src/App.js
@@ -29,7 +29,11 @@ class App {
const lottoCount = money / 1000;
const lottos = [];
for (let i = 0; i < lottoCount; i++) {
- const randomNumbers = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6)
+ const randomNumbers = MissionUtils.Random.pickUniqueNumbersInRange(
+ 1,
+ 45,
+ 6
+ );
lottos.push(randomNumbers);
}
return lottos;
@@ -123,8 +127,8 @@ class App {
// 총 당첨 내역 출력
// 결과 합산
- computeTotalResult(lottos, winningNumbers, bonusNubmer) {
- const result = { "1등": 0, "2등": 0, "3등": 0, "4등": 0, "5등": 0, "꽝": 0};
+ computeTotalResult(lottos) {
+ const result = { "1등": 0, "2등": 0, "3등": 0, "4등": 0, "5등": 0, 꽝: 0 };
for (const lotto of lottos) {
const rank = this.computeRank(lotto, winningNumbers, bonusNubmer);
result[rank]++;
@@ -144,14 +148,19 @@ class App {
}
// 수익률 계산
-
- computeProfit(result,money){
- const totalPrize = result["5등"]*5000 + result["4등"]*50000 + result["3등"]*1500000 + result["2등"]*30000000 + result["1등"]*2000000000;
- const profit = (totalPrize/money*100).toFixed(1);
- return profit;
+
+ computeProfit(result, money) {
+ const totalPrize =
+ result["5등"] * 5000 +
+ result["4등"] * 50000 +
+ result["3등"] * 1500000 +
+ result["2등"] * 30000000 +
+ result["1등"] * 2000000000;
+ const profit = ((totalPrize / money) * 100).toFixed(1);
+ return profit;
}
-
- printProfit(profit){
+
+ printProfit(profit) {
MissionUtils.Console.print(`총 수익률은 ${profit}%입니다.`);
}
}
From f0d1277bf2bd1e1841be36aa6d470b22054d33a7 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:09:47 +0900
Subject: [PATCH 12/19] =?UTF-8?q?refactor:=20=EB=B0=98=EB=B3=B5=20?=
=?UTF-8?q?=EC=82=AC=EC=9A=A9=EB=90=98=EB=8A=94=20=ED=8C=8C=EB=9D=BC?=
=?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EB=A9=A4=EB=B2=84=20=EB=B3=80=EC=88=98?=
=?UTF-8?q?=EB=A1=9C=20=EC=A0=80=EC=9E=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/src/App.js b/src/App.js
index c5966db300..0525b0604b 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,7 +1,11 @@
import { MissionUtils } from "@woowacourse/mission-utils";
import Lotto from "./Lotto.js";
class App {
- // 구입 금액 입력받기
+ constructor() {
+ this.winningNumbers = [];
+ this.bonusNumber = 0;
+ }
+
async inputMoney() {
let money;
let isValidated = false;
@@ -94,26 +98,23 @@ class App {
else return true;
}
- // 로또 하나에 대한 결과(등수) 계산
-
- // 일치하는 번호 개수
- countMatchingNumbers(lotto, winningNumbers) {
+ countMatchingNumbers(lotto) {
let count = 0;
lotto.forEach((number) => {
- if (winningNumbers.includes(number)) {
+ if (this.winningNumbers.includes(number)) {
count++;
}
});
return count;
}
- // 등수 계산
- computeRank(lotto, winningNumbers, bonusNumber) {
- const count = this.countMatchingNumbers(lotto, winningNumbers);
+
+ computeRank(lotto) {
+ const count = this.countMatchingNumbers(lotto, this.winningNumbers);
switch (count) {
case 6:
return "1등";
case 5:
- if (winningNumbers.includes(bonusNumber)) {
+ if (this.winningNumbers.includes(this.bonusNumber)) {
return "2등";
} else return "3등";
case 4:
@@ -130,7 +131,11 @@ class App {
computeTotalResult(lottos) {
const result = { "1등": 0, "2등": 0, "3등": 0, "4등": 0, "5등": 0, 꽝: 0 };
for (const lotto of lottos) {
- const rank = this.computeRank(lotto, winningNumbers, bonusNubmer);
+ const rank = this.computeRank(
+ lotto,
+ this.winningNumbers,
+ this.bonusNumber
+ );
result[rank]++;
}
return result;
From 5884b5781b75ea446c6b592320d6e6f8e4aa5720 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:10:12 +0900
Subject: [PATCH 13/19] =?UTF-8?q?feat:=20play=ED=95=A8=EC=88=98=20?=
=?UTF-8?q?=EC=9E=91=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/App.js b/src/App.js
index 0525b0604b..5a056bc38d 100644
--- a/src/App.js
+++ b/src/App.js
@@ -168,6 +168,21 @@ class App {
printProfit(profit) {
MissionUtils.Console.print(`총 수익률은 ${profit}%입니다.`);
}
+
+ async play() {
+ const money = await this.inputMoney();
+ const lottos = this.publishLotto(money);
+ this.printLottos(lottos);
+ await this.inputNumbers();
+ await this.inputBonusNumber();
+ const result = this.computeTotalResult(
+ lottos,
+ this.winningNumbers,
+ this.mber
+ );
+ this.printResult(result);
+ const profit = this.computeProfit(result, money);
+ this.printProfit(profit);
}
}
From d8ae5726c95e8439d4823db37d97662ec1313851 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:11:01 +0900
Subject: [PATCH 14/19] style: code formatting
---
src/App.js | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/src/App.js b/src/App.js
index 5a056bc38d..67afd78c71 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,5 +1,6 @@
import { MissionUtils } from "@woowacourse/mission-utils";
import Lotto from "./Lotto.js";
+
class App {
constructor() {
this.winningNumbers = [];
@@ -19,7 +20,6 @@ class App {
return money;
}
- // 예외처리
validateMoney(money) {
if (isNaN(money)) {
MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
@@ -28,7 +28,6 @@ class App {
} else return true;
}
- // 로또 발행
publishLotto(money) {
const lottoCount = money / 1000;
const lottos = [];
@@ -42,10 +41,14 @@ class App {
}
return lottos;
}
- // 구매한 로또 수량 및 번호 출력
+
printLottos(lottos) {
MissionUtils.Console.print(`\n${lottos.length}개를 구매했습니다.`);
- // 당첨 번호 입력받기
+ for (const lotto of lottos) {
+ MissionUtils.Console.print(`[${lotto.join(", ")}]`);
+ }
+ }
+
async inputNumbers() {
let numbers;
let isValidated = false;
@@ -59,7 +62,6 @@ class App {
this.winningNumbers = numbers;
}
- // 당첨 번호 예외처리
validateNumbers(numbers) {
if (numbers.length !== 6) {
MissionUtils.Console.print("[ERROR] 6개의 숫자를 입력해주세요.\n");
@@ -72,7 +74,6 @@ class App {
} else return true;
}
- // 보너스 번호 입력받기
async inputBonusNumber() {
let bonusNumber;
let isValidated = false;
@@ -94,8 +95,7 @@ class App {
MissionUtils.Console.print("[ERROR] 1~45 사이의 숫자를 입력해주세요.\n");
} else if (winningNumbers.includes(bonusNumber)) {
MissionUtils.Console.print("[ERROR] 당첨 번호와 중복될 수 없습니다.\n");
- }
- else return true;
+ } else return true;
}
countMatchingNumbers(lotto) {
@@ -126,8 +126,6 @@ class App {
}
}
- // 총 당첨 내역 출력
- // 결과 합산
computeTotalResult(lottos) {
const result = { "1등": 0, "2등": 0, "3등": 0, "4등": 0, "5등": 0, 꽝: 0 };
for (const lotto of lottos) {
@@ -141,7 +139,6 @@ class App {
return result;
}
- // 출력
printResult(result) {
MissionUtils.Console.print(`
당첨 통계\n---
@@ -152,8 +149,6 @@ class App {
6개 일치 (2,000,000,000원) - ${result["1등"]}개`);
}
- // 수익률 계산
-
computeProfit(result, money) {
const totalPrize =
result["5등"] * 5000 +
From 37095aa8f96f211dbd13d4ef86ff3db6af17cfcc Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:11:37 +0900
Subject: [PATCH 15/19] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?=
=?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/README.md | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/docs/README.md b/docs/README.md
index 47564e5b55..243458ecad 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -3,34 +3,33 @@
- 로또 구입 금액 입력받기
- - 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
+ - 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다
- 로또 발행
- 구입 금액에 해당하는 만큼 로또를 발행한다
+ - 1~45범위의 중복되지 않는 6개의 숫자를 뽑는다
- 로또 1장의 가격은 1000원이다
- 구매한 로또 수량 및 번호 출력
- - 로또 번호는 오름차순으로 정렬하여 보여준다.
+ - 로또 번호는 오름차순으로 정렬하여 보여준다
- 당첨 번호를 입력 받는다
+ - 1~45범위의 중복되지 않는 6개의 숫자를 입력받는다
- 번호는 쉼표(,)를 기준으로 구분한다.
- 보너스 번호를 입력 받는다
+ - 보너스 번호는 당첨 번호와 중복될 수 없다
- 잘못된 입력에 대한 예외처리 (각 입력마다)
- 사용자가 잘못된 값을 입력할 경우 throw문을 사용해 예외를 발생시킨다. 그런 다음, "[ERROR]"로 시작하는 에러 메시지를 출력하고 해당 부분부터 입력을 다시 받는다.
-- 당첨 번호 추첨
- - 1~45범위의 중복되지 않는 6개의 숫자를 뽑는다
- - 보너스 번호를 뽑는다
-
-
-- 당첨금 계산
- - 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다.
+- 로또 하나에 대한 결과(등수) 계산
+ - 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다
+ - 5개가 일치할 시 틀린 1개가 보너스 번호와 일치하는지 확인하여 2등과 3등을 나눈다
1등: 6개 번호 일치 / 2,000,000,000원
2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원
3등: 5개 번호 일치 / 1,500,000원
@@ -38,11 +37,12 @@
5등: 3개 번호 일치 / 5,000원
-- 당첨 내역 출력
- - 일치한 번호 개수, 당첨금, 로또 개수
+- 총 당첨 내역 출력
+ - 각 로또의 결과를 합산한다
+ - 아래와 같은 형식으로 출력한다
3개 일치 (5,000원) - ?개
4개 일치 (50,000원) - ?개
- 5개 일치 (1,500,000원) - ?개
+ 5개 일치 (1,500,000원) - ?개
5개 일치, 보너스 볼 일치 (30,000,000원) - ?개
6개 일치 (2,000,000,000원) - ?개
From d06d7395af27837cbf3920b73364dcbfce3a9fa6 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:19:00 +0900
Subject: [PATCH 16/19] =?UTF-8?q?fix:=202=EB=93=B1=20=ED=8C=90=EB=8B=A8=20?=
=?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/App.js b/src/App.js
index 67afd78c71..a2f041bfb0 100644
--- a/src/App.js
+++ b/src/App.js
@@ -93,7 +93,7 @@ class App {
MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
} else if (bonusNumber < 1 || bonusNumber > 45) {
MissionUtils.Console.print("[ERROR] 1~45 사이의 숫자를 입력해주세요.\n");
- } else if (winningNumbers.includes(bonusNumber)) {
+ } else if (this.winningNumbers.includes(bonusNumber)) {
MissionUtils.Console.print("[ERROR] 당첨 번호와 중복될 수 없습니다.\n");
} else return true;
}
@@ -114,7 +114,7 @@ class App {
case 6:
return "1등";
case 5:
- if (this.winningNumbers.includes(this.bonusNumber)) {
+ if (lotto.includes(this.bonusNumber)) {
return "2등";
} else return "3등";
case 4:
From 21fa15873577bdce78ee946afceacc7bf494ebe4 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:20:54 +0900
Subject: [PATCH 17/19] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?=
=?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=B0=8F=20?=
=?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=A0=9C=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/src/App.js b/src/App.js
index a2f041bfb0..b71e3e5979 100644
--- a/src/App.js
+++ b/src/App.js
@@ -88,7 +88,6 @@ class App {
}
validateBonusNumber(bonusNumber) {
- const winningNumbers = this.winningNumbers;
if (isNaN(bonusNumber)) {
MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
} else if (bonusNumber < 1 || bonusNumber > 45) {
@@ -129,11 +128,7 @@ class App {
computeTotalResult(lottos) {
const result = { "1등": 0, "2등": 0, "3등": 0, "4등": 0, "5등": 0, 꽝: 0 };
for (const lotto of lottos) {
- const rank = this.computeRank(
- lotto,
- this.winningNumbers,
- this.bonusNumber
- );
+ const rank = this.computeRank(lotto);
result[rank]++;
}
return result;
@@ -170,11 +165,7 @@ class App {
this.printLottos(lottos);
await this.inputNumbers();
await this.inputBonusNumber();
- const result = this.computeTotalResult(
- lottos,
- this.winningNumbers,
- this.mber
- );
+ const result = this.computeTotalResult(lottos);
this.printResult(result);
const profit = this.computeProfit(result, money);
this.printProfit(profit);
From 6f7362df74bd1926f885c783430c2cb746641d30 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 22:50:51 +0900
Subject: [PATCH 18/19] =?UTF-8?q?refactor:=20Lotto=20=ED=81=B4=EB=9E=98?=
=?UTF-8?q?=EC=8A=A4=20=ED=99=9C=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.js | 19 ++++++++++++-------
src/Lotto.js | 17 +++++++++++++++++
2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/src/App.js b/src/App.js
index b71e3e5979..8a5af334da 100644
--- a/src/App.js
+++ b/src/App.js
@@ -37,7 +37,13 @@ class App {
45,
6
);
- lottos.push(randomNumbers);
+ try {
+ const lotto = new Lotto(randomNumbers);
+ lottos.push(lotto);
+ } catch (error) {
+ MissionUtils.Console.print(error.message);
+ i--;
+ }
}
return lottos;
}
@@ -45,7 +51,7 @@ class App {
printLottos(lottos) {
MissionUtils.Console.print(`\n${lottos.length}개를 구매했습니다.`);
for (const lotto of lottos) {
- MissionUtils.Console.print(`[${lotto.join(", ")}]`);
+ MissionUtils.Console.print(lotto.toString());
}
}
@@ -99,7 +105,7 @@ class App {
countMatchingNumbers(lotto) {
let count = 0;
- lotto.forEach((number) => {
+ lotto.getNumbers().forEach((number) => {
if (this.winningNumbers.includes(number)) {
count++;
}
@@ -108,14 +114,13 @@ class App {
}
computeRank(lotto) {
- const count = this.countMatchingNumbers(lotto, this.winningNumbers);
+ const count = this.countMatchingNumbers(lotto);
+ const isBonusMatched = lotto.hasNumber(this.bonusNumber);
switch (count) {
case 6:
return "1등";
case 5:
- if (lotto.includes(this.bonusNumber)) {
- return "2등";
- } else return "3등";
+ return isBonusMatched ? "2등" : "3등";
case 4:
return "4등";
case 3:
diff --git a/src/Lotto.js b/src/Lotto.js
index cb0b1527e9..1e6e61c3bd 100644
--- a/src/Lotto.js
+++ b/src/Lotto.js
@@ -10,8 +10,25 @@ class Lotto {
if (numbers.length !== 6) {
throw new Error("[ERROR] 로또 번호는 6개여야 합니다.");
}
+ if (new Set(numbers).size !== 6) {
+ throw new Error("[ERROR] 중복된 숫자가 있습니다.");
+ }
+ if (numbers.some(num => num < 1 || num > 45)) {
+ throw new Error("[ERROR] 번호는 1과 45 사이여야 합니다.");
+ }
+ }
+
+ getNumbers() {
+ return this.#numbers;
}
+ hasNumber(number) {
+ return this.#numbers.includes(number);
+ }
+
+ toString() {
+ return `[${this.#numbers.join(", ")}]`;
+ }
// TODO: 추가 기능 구현
}
From 5ba0b1fdf2eea01b86447b8197cf4efc7d13e5a1 Mon Sep 17 00:00:00 2001
From: Eunhak Lee <112919689+Ag-crane@users.noreply.github.com>
Date: Wed, 8 Nov 2023 23:58:01 +0900
Subject: [PATCH 19/19] =?UTF-8?q?test:=20=EB=8B=A8=EC=9C=84=ED=85=8C?=
=?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
__tests__/LottoTest.js | 81 ++++++++++++++++++++++++++++++++++++++++--
src/App.js | 5 ++-
2 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/__tests__/LottoTest.js b/__tests__/LottoTest.js
index 97bd457659..070344468e 100644
--- a/__tests__/LottoTest.js
+++ b/__tests__/LottoTest.js
@@ -1,4 +1,5 @@
import Lotto from "../src/Lotto.js";
+import App from "../src/App.js";
describe("로또 클래스 테스트", () => {
test("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.", () => {
@@ -7,12 +8,88 @@ describe("로또 클래스 테스트", () => {
}).toThrow("[ERROR]");
});
- // TODO: 이 테스트가 통과할 수 있게 구현 코드 작성
test("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.", () => {
expect(() => {
new Lotto([1, 2, 3, 4, 5, 5]);
}).toThrow("[ERROR]");
});
- // 아래에 추가 테스트 작성 가능
+ test("로또 번호에 1보다 작은 숫자가 있으면 예외가 발생한다.", () => {
+ expect(() => {
+ new Lotto([1, 2, 3, 4, 5, 0]);
+ }).toThrow("[ERROR]");
+ });
+
+ test("로또 번호에 45보다 큰 숫자가 있으면 예외가 발생한다.", () => {
+ expect(() => {
+ new Lotto([1, 2, 3, 4, 5, 46]);
+ }).toThrow("[ERROR]");
+ });
+
+ test("hasNumber 테스트",()=>{
+ const lotto = new Lotto([1,2,3,4,5,6]);
+ expect(lotto.hasNumber(1)).toEqual(true);
+ expect(lotto.hasNumber(7)).toEqual(false);
+ })
});
+
+describe("App.js 메서드 단위 테스트",()=>{
+ test("constructor 테스트",()=>{
+ const app = new App();
+ expect(app.winningNumbers).toEqual([]);
+ expect(app.bonusNumber).toEqual(0);
+ })
+ test("validateMoney 테스트",()=>{
+ const app = new App();
+ expect(app.validateMoney(1000)).toEqual(true);
+ expect(app.validateMoney(1001)).toEqual(undefined);
+ expect(app.validateMoney(0)).toEqual(undefined);
+ expect(app.validateMoney(-1)).toEqual(undefined);
+ })
+ test("publishLotto 테스트",()=>{
+ const app = new App();
+ const lottos = app.publishLotto(1000);
+ expect(lottos.length).toEqual(1);
+ expect(lottos[0].getNumbers().length).toEqual(6);
+ })
+ test("validateNumbers 테스트",()=>{
+ const app = new App();
+ expect(app.validateNumbers([1,2,3,4,5,6])).toEqual(true);
+ expect(app.validateNumbers([1,2,3,4,5,5])).toEqual(undefined);
+ expect(app.validateNumbers([1,2,3,4,5,0])).toEqual(undefined);
+ expect(app.validateNumbers([1,2,3,4,5,46])).toEqual(undefined);
+ })
+ test("validateBonusNumber 테스트",()=>{
+ const app = new App();
+ app.winningNumbers = [1,2,3,4,5,6];
+ expect(app.validateBonusNumber(7)).toEqual(true);
+ expect(app.validateBonusNumber(6)).toEqual(undefined);
+ expect(app.validateBonusNumber(0)).toEqual(undefined);
+ expect(app.validateBonusNumber(46)).toEqual(undefined);
+ })
+ test("countMatchingNumbers 테스트",()=>{
+ const app = new App();
+ app.winningNumbers = [1,2,3,4,5,6];
+ const lotto = new Lotto([1,2,3,4,5,6]);
+ expect(app.countMatchingNumbers(lotto)).toEqual(6);
+ app.winningNumbers = [1,2,3,4,5,7];
+ expect(app.countMatchingNumbers(lotto)).toEqual(5);
+ })
+ test("computeRank 테스트",()=>{
+ const app = new App();
+ app.bonusNumber = 7;
+ const lotto = new Lotto([1,2,3,4,5,6]);
+ app.winningNumbers = [1,2,3,4,5,6];
+ expect(app.computeRank(lotto)).toEqual("1등");
+ // app.winningNumbers = [1,2,3,4,5,7];
+ // expect(app.computeRank(lotto)).toEqual("2등");
+ app.winningNumbers = [1,2,3,4,5,8];
+ expect(app.computeRank(lotto)).toEqual("3등");
+ app.winningNumbers = [1,2,3,4,7,8];
+ expect(app.computeRank(lotto)).toEqual("4등");
+ app.winningNumbers = [1,2,3,7,8,9];
+ expect(app.computeRank(lotto)).toEqual("5등");
+ app.winningNumbers = [1,2,7,8,9,10];
+ expect(app.computeRank(lotto)).toEqual("꽝");
+ });
+})
diff --git a/src/App.js b/src/App.js
index 8a5af334da..4214ffb105 100644
--- a/src/App.js
+++ b/src/App.js
@@ -23,7 +23,10 @@ class App {
validateMoney(money) {
if (isNaN(money)) {
MissionUtils.Console.print("[ERROR] 숫자만 입력해주세요.\n");
- } else if (money % 1000 !== 0) {
+ }else if(money < 1000){
+ MissionUtils.Console.print("[ERROR] 최소 1000 이상을 입력해야 합니다.\n");
+ }
+ else if (money % 1000 !== 0) {
MissionUtils.Console.print("[ERROR] 1000원 단위로 입력해주세요.\n");
} else return true;
}