From e9e195e3e8763902b190a20892b4341b803dcf5d Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Thu, 30 Oct 2025 13:28:39 +0900 Subject: [PATCH 01/30] =?UTF-8?q?feat(Controller)=20:=20=EA=B8=88=EC=95=A1?= =?UTF-8?q?,=20=EC=9C=84=EB=8B=9D=EB=84=98=EB=B2=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/input.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/controller/input.js diff --git a/src/controller/input.js b/src/controller/input.js new file mode 100644 index 000000000..d8ea680be --- /dev/null +++ b/src/controller/input.js @@ -0,0 +1,16 @@ +import { Console } from "@woowacourse/mission-utils"; + +class Controller { + static async getWinningNumber() { + const INPUT = await Console.readLineAsync("당첨 번호를 입력해 주세요. : "); + const WINNING_NUMBER = INPUT.replaceAll(" ", ""); + + return WINNING_NUMBER; + } + + static async getMoney() { + const MONEY_INPUT = await Console.readLineAsync("금액을 입력해 주세요. : "); + + return MONEY_INPUT; + } +} From 20e0eb2135d39faa3b515bc7cddf90f3a3e63b1a Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Thu, 30 Oct 2025 13:32:41 +0900 Subject: [PATCH 02/30] =?UTF-8?q?feat(controller)=20:=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EB=84=98=EB=B2=84=20=EC=9E=85=EB=A0=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/input.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/controller/input.js b/src/controller/input.js index d8ea680be..bcc0fbf7d 100644 --- a/src/controller/input.js +++ b/src/controller/input.js @@ -8,6 +8,14 @@ class Controller { return WINNING_NUMBER; } + static async getBonusNumber() { + const BONUS_NUMBER = await Console.readLineAsync( + "금액을 입력해 주세요. : " + ); + + return MONEY_INPUT; + } + static async getMoney() { const MONEY_INPUT = await Console.readLineAsync("금액을 입력해 주세요. : "); From 9ab57737969bded1611adcc3b556c28d1be3ce4f Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Thu, 30 Oct 2025 15:08:00 +0900 Subject: [PATCH 03/30] =?UTF-8?q?refactor(input)=20:=20=EA=B0=80=EB=8F=85?= =?UTF-8?q?=EC=84=B1=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/input.js b/src/controller/input.js index bcc0fbf7d..29eeb0801 100644 --- a/src/controller/input.js +++ b/src/controller/input.js @@ -1,6 +1,6 @@ import { Console } from "@woowacourse/mission-utils"; -class Controller { +export default class Inputs { static async getWinningNumber() { const INPUT = await Console.readLineAsync("당첨 번호를 입력해 주세요. : "); const WINNING_NUMBER = INPUT.replaceAll(" ", ""); From 1d7d1c7a35933d27167a71b104b5bb8be594292b Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Thu, 30 Oct 2025 17:04:26 +0900 Subject: [PATCH 04/30] =?UTF-8?q?fix(input):=20=EB=A9=94=EC=84=B8=EC=A7=80?= =?UTF-8?q?=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/input.js b/src/controller/input.js index 29eeb0801..40426de0a 100644 --- a/src/controller/input.js +++ b/src/controller/input.js @@ -10,7 +10,7 @@ export default class Inputs { static async getBonusNumber() { const BONUS_NUMBER = await Console.readLineAsync( - "금액을 입력해 주세요. : " + "보너스 번호를 입력해 주세요. : " ); return MONEY_INPUT; From 51234d4504fb47fd021559d39e64dee26bc7d8af Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 00:05:13 +0900 Subject: [PATCH 05/30] =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20Pc=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=9E=91=EC=97=85=EC=9D=84=20=ED=95=98=EA=B8=B0=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=9E=84=EC=8B=9C=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/money.js | 29 +++++++++++++++++++++++++++++ src/model/numbers.js | 5 +++++ 2 files changed, 34 insertions(+) create mode 100644 src/model/money.js create mode 100644 src/model/numbers.js diff --git a/src/model/money.js b/src/model/money.js new file mode 100644 index 000000000..65c5d77ed --- /dev/null +++ b/src/model/money.js @@ -0,0 +1,29 @@ +import Inputs from "../controller/input"; + +export default class Money { + #money; + #count; + // 입력받은 금액의 유효성 검사 + // 나머지의 몫이 그럼 전부 로또로 + // 로또는 사용자가 입력한 수 만큼 구매 + // 세터 지양의 이유 + constructor(money, count) { + this.#money = money; + this.#count = count; + } + + #modulo(money, count) { + if (money % 1000 != 0) { + throw new Error("[ERROR] 로또의 금액 투입은 1,000원 단위 입니다."); + } + const GAME_MONEY = money / (count * 1000); + + return GAME_MONEY; + } + + #restMoney(money, GAME_MONEY) { + const REST_MONEY = money - GAME_MONEY; + + return REST_MONEY; + } +} diff --git a/src/model/numbers.js b/src/model/numbers.js new file mode 100644 index 000000000..8fbefbc3d --- /dev/null +++ b/src/model/numbers.js @@ -0,0 +1,5 @@ +import Inputs from "../controller/input"; + +export default class Numbers { + // 입력받은 문자열을 숫자로 변환 +} From fa390ad862224913947edb72ef122c11984a7a11 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 00:05:17 +0900 Subject: [PATCH 06/30] =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20Pc=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=9E=91=EC=97=85=EC=9D=84=20=ED=95=98=EA=B8=B0=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=9E=84=EC=8B=9C=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/input.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/controller/input.js b/src/controller/input.js index 40426de0a..25637f141 100644 --- a/src/controller/input.js +++ b/src/controller/input.js @@ -3,7 +3,8 @@ import { Console } from "@woowacourse/mission-utils"; export default class Inputs { static async getWinningNumber() { const INPUT = await Console.readLineAsync("당첨 번호를 입력해 주세요. : "); - const WINNING_NUMBER = INPUT.replaceAll(" ", ""); + const TRIMED_INPUT = INPUT.replaceAll(" ", ""); + const WINNING_NUMBER = TRIMED_INPUT.split(","); return WINNING_NUMBER; } @@ -13,7 +14,7 @@ export default class Inputs { "보너스 번호를 입력해 주세요. : " ); - return MONEY_INPUT; + return BONUS_NUMBER; } static async getMoney() { @@ -21,4 +22,10 @@ export default class Inputs { return MONEY_INPUT; } + + static async getGameCount() { + const COUNT_INPUT = await Console.readLineAsync("금액을 입력해 주세요. : "); + + return COUNT_INPUT; + } } From 0ef66fc3abdce27dde85479c148ba0f364c1eb68 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 09:20:51 +0900 Subject: [PATCH 07/30] =?UTF-8?q?docs(README.md)=20:=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=ED=8C=8C=EC=9D=BC=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++ src/model/money.js | 6 ++-- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 15bb106b5..50bd68acf 100644 --- a/README.md +++ b/README.md @@ -1 +1,85 @@ # javascript-lotto-precourse + +# 프리코스-로또 + +## 이번 미션에서는 도전하고 싶은 부분 + +1. MVC 패턴 숙지 +2. Airbnb js 코드 컨벤션 적용 +3. 메서드의 책임 최소화 +4. 테스트 코드 원칙에 의거한 테스트 코드 구현 + +--- + +### **1. 모델 (Model): 데이터 관리의 핵심** + +- **모델의 역할:** + - **데이터 저장 및 관리:** 애플리케이션에서 사용하는 데이터를 데이터베이스에 저장하고, 필요할 때 데이터를 가져오거나 수정, 삭제하는 역할을 합니다. + - **데이터베이스와 상호작용:** 데이터베이스와 직접 통신하여 데이터를 처리합니다. (예: 테이블 생성, 데이터 검색, 데이터 삽입 등) + - **데이터 유효성 검증:** 데이터가 올바른 형식인지 확인하고, 잘못된 데이터가 저장되지 않도록 합니다. (예: 이메일 형식 검사, 필수 입력 필드 확인) + - **비즈니스 로직 처리:** 데이터와 관련된 복잡한 규칙이나 계산을 처리합니다. (예: 할인율 계산, 사용자 등급 계산 등) + +### **2. 뷰 (View): 사용자 인터페이스 담당** + +- **뷰의 역할:** + - **사용자 인터페이스 생성:** 웹 페이지를 구성하는 HTML, CSS, JavaScript 코드를 작성하여 사용자에게 보여지는 화면을 만듭니다. + - **데이터 출력:** 모델에서 가져온 데이터를 사용자에게 보기 좋게 출력합니다. + - **템플릿 사용:** HTML에 Ruby 코드를 추가하여 동적인 웹 페이지를 만듭니다. (ERB, Haml 등의 템플릿 엔진 사용) + - **사용자 입력 처리:** 사용자가 입력한 데이터를 화면에서 처리하고, 컨트롤러에 전달합니다. +- **뷰의 예시 (Rails):** + - `app/views` 폴더에 있는 파일 (예: `users/index.html.erb`, `posts/show.html.erb`) + - ERB(Embedded Ruby) 문법을 사용하여 HTML 코드 안에 Ruby 코드를 작성할 수 있습니다. +- **뷰의 특징:** + - 웹 브라우저에 보여지는 HTML, CSS, JavaScript 코드를 포함합니다. + - 모델에서 가져온 데이터를 예쁘게 표현합니다. + - 사용자의 입력에 따라 동적으로 웹 페이지를 변경합니다. + +**뷰를 쉽게 이해하는 방법:** + +- **무대 디자이너:** 뷰는 마치 무대 디자이너와 같습니다. 사용자에게 보여지는 화면을 디자인하고 꾸밉니다. +- **프레젠테이션 전문가:** 뷰는 데이터를 프레젠테이션하는 전문가입니다. 데이터를 보기 좋게 정리하여 보여줍니다. + +### **3. 컨트롤러 (Controller): 모델과 뷰 연결 담당** + +- **컨트롤러의 역할:** + - **사용자 요청 처리:** 웹 브라우저에서 온 사용자 요청을 분석하고, 어떤 모델을 사용해야 하는지, 어떤 뷰를 보여줘야 하는지 결정합니다. + - **모델 호출:** 모델을 사용하여 데이터를 가져오거나 변경합니다. + - **뷰 호출:** 데이터를 뷰에 전달하고, 뷰를 실행하여 사용자에게 웹 페이지를 보여줍니다. + - **흐름 제어:** 웹 애플리케이션의 흐름을 제어합니다. (예: 로그인 여부 확인, 사용 권한 확인 등) + - **데이터 전달:** 모델에서 가져온 데이터를 뷰에 전달합니다. +- **컨트롤러의 예시 (Rails):** + - `app/controllers` 폴더에 있는 파일 (예: `UsersController.rb`, `PostsController.rb`) + - 액션(action)이라고 불리는 메서드를 사용하여 요청을 처리합니다. +- **컨트롤러의 특징:** + - 모델과 뷰 사이의 중개자 역할을 합니다. + - 사용자의 요청에 따라 적절한 모델과 뷰를 선택합니다. + - 웹 애플리케이션의 논리적인 흐름을 제어합니다. + +**컨트롤러를 쉽게 이해하는 방법:** + +- **교통 경찰관:** 컨트롤러는 마치 교통 경찰관과 같습니다. 교통 흐름을 제어하고, 필요에 따라 차량(데이터)을 목적지(뷰)로 안내합니다. +- **매니저:** 컨트롤러는 웹 애플리케이션의 매니저와 같습니다. 사용자의 요청을 처리하고, 필요한 작업을 수행합니다. + +--- + +미션에 따른 역할 구분 + +- 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. + 중복되지 않는 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원 + 등수에 대한 데이터는 상수화 번호를 확인한 다음 일치하는 번호에 따른 값을 출력 +- 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. + 입력된 값에 따라 데이터를 뷰로 보내기 때문에 있으므로 컨트롤러에 해당 +- 로또 1장의 가격은 1,000원이다. + 이건 상수로 묶어서 처리 +- 당첨 번호와 보너스 번호를 입력받는다. + 입력된 값에 따라 데이터를 뷰로 보내기 때문에 있으므로 컨트롤러에 해당 +- 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. +- 사용자가 잘못된 값을 입력할 경우 "[ERROR]"로 시작하는 메시지와 함께 `Error`를 발생시키고 해당 메시지를 출력한 다음 해당 지점부터 다시 입력을 받는다. diff --git a/src/model/money.js b/src/model/money.js index 65c5d77ed..43c66ac62 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -13,10 +13,12 @@ export default class Money { } #modulo(money, count) { - if (money % 1000 != 0) { + const GAME_PRICE = 1000; + + if (money % GAME_PRICE != 0) { throw new Error("[ERROR] 로또의 금액 투입은 1,000원 단위 입니다."); } - const GAME_MONEY = money / (count * 1000); + const GAME_MONEY = money / (count * GAME_PRICE); return GAME_MONEY; } From 4145f83270558cd36b920f5296302752e87b9524 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 09:51:02 +0900 Subject: [PATCH 08/30] =?UTF-8?q?fix(fileName)=20:=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=9D=B4=EB=A6=84=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ src/App.js | 6 +++++- src/controller/{input.js => Inputs.js} | 0 src/model/money.js | 2 +- src/model/numbers.js | 9 ++++++++- 5 files changed, 16 insertions(+), 3 deletions(-) rename src/controller/{input.js => Inputs.js} (100%) diff --git a/README.md b/README.md index 50bd68acf..04652f037 100644 --- a/README.md +++ b/README.md @@ -83,3 +83,5 @@ 입력된 값에 따라 데이터를 뷰로 보내기 때문에 있으므로 컨트롤러에 해당 - 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. - 사용자가 잘못된 값을 입력할 경우 "[ERROR]"로 시작하는 메시지와 함께 `Error`를 발생시키고 해당 메시지를 출력한 다음 해당 지점부터 다시 입력을 받는다. + +- 입력값 숫자로 변경 diff --git a/src/App.js b/src/App.js index 091aa0a5d..d0b1bab28 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,9 @@ +import Inputs from "./controller/inputs"; + class App { - async run() {} + async run() { + let a = Inputs.getWinningNumber(); + } } export default App; diff --git a/src/controller/input.js b/src/controller/Inputs.js similarity index 100% rename from src/controller/input.js rename to src/controller/Inputs.js diff --git a/src/model/money.js b/src/model/money.js index 43c66ac62..7c781d7e9 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -1,4 +1,4 @@ -import Inputs from "../controller/input"; +import Inputs from "./controller/inputs"; export default class Money { #money; diff --git a/src/model/numbers.js b/src/model/numbers.js index 8fbefbc3d..6daf17e41 100644 --- a/src/model/numbers.js +++ b/src/model/numbers.js @@ -1,5 +1,12 @@ -import Inputs from "../controller/input"; +import Inputs from "./controller/inputs"; export default class Numbers { // 입력받은 문자열을 숫자로 변환 + changeToNumber(winningNumber) { + const fetchWinningNumber = winningNumber.map((index) => { + Number(index); + }); + + return fetchWinningNumber; + } } From af7b589867687bfa6bbc527064a6e2bed59f31d2 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 10:25:00 +0900 Subject: [PATCH 09/30] =?UTF-8?q?refactor=20:=20=EA=B2=80=EC=A6=9D?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EA=B0=92=20=EC=88=AB=EC=9E=90=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/money.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/model/money.js b/src/model/money.js index 7c781d7e9..a4b7b72a5 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -3,21 +3,38 @@ import Inputs from "./controller/inputs"; export default class Money { #money; #count; + #GAME_PRICE = 1000; // 입력받은 금액의 유효성 검사 // 나머지의 몫이 그럼 전부 로또로 // 로또는 사용자가 입력한 수 만큼 구매 // 세터 지양의 이유 + constructor(money, count) { - this.#money = money; + const CHANGED_MONEY = this.#changeMoney(money); + this.#money = CHANGED_MONEY; this.#count = count; } - #modulo(money, count) { - const GAME_PRICE = 1000; + #changeMoney(money) { + const CHANGE_NUM = Number(money); + if (isNaN(CHANGE_NUM)) { + throw new Error("[ERROR] 금액이 숫자가 아닙니다."); + } + + return CHANGE_NUM; + } - if (money % GAME_PRICE != 0) { + #validateMoney(money) { + if (money % 1000 !== 0) { throw new Error("[ERROR] 로또의 금액 투입은 1,000원 단위 입니다."); } + if (money < 1000) { + throw new Error("[ERROR] 로또의 금액 투입은 1,000원 이상 입니다."); + } + return money; + } + + #modulo(money, count) { const GAME_MONEY = money / (count * GAME_PRICE); return GAME_MONEY; From 8a7c748d677ecd38146af62437a29d1003b2e5f6 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 10:54:27 +0900 Subject: [PATCH 10/30] =?UTF-8?q?refactor(Numbers)=20:=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=EA=B0=92=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=EC=A0=84=ED=99=98=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 로또 번호 입력하는 기능이 필요없는것으로 판단해서 제거하였습니다 --- src/model/numbers.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/model/numbers.js b/src/model/numbers.js index 6daf17e41..ceb121a4a 100644 --- a/src/model/numbers.js +++ b/src/model/numbers.js @@ -1,12 +1,3 @@ import Inputs from "./controller/inputs"; -export default class Numbers { - // 입력받은 문자열을 숫자로 변환 - changeToNumber(winningNumber) { - const fetchWinningNumber = winningNumber.map((index) => { - Number(index); - }); - - return fetchWinningNumber; - } -} +export default class Numbers {} From 1d21b03168d23b091b715fdaa59b332d9097abdf Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 11:10:17 +0900 Subject: [PATCH 11/30] =?UTF-8?q?fix:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 시행횟수를 받는 부분에서 금액을 입력하라고 있던 오타를 기능에 맞게 수정하였습니다. --- src/controller/Inputs.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controller/Inputs.js b/src/controller/Inputs.js index 25637f141..4f986a653 100644 --- a/src/controller/Inputs.js +++ b/src/controller/Inputs.js @@ -24,7 +24,9 @@ export default class Inputs { } static async getGameCount() { - const COUNT_INPUT = await Console.readLineAsync("금액을 입력해 주세요. : "); + const COUNT_INPUT = await Console.readLineAsync( + "시행횟수를 입력해 주세요. : " + ); return COUNT_INPUT; } From 7a3539c3ccd12e909c555a8a968ad9a5da755e47 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 11:52:33 +0900 Subject: [PATCH 12/30] =?UTF-8?q?feat(Money)=20:=20=EC=8B=9C=ED=96=89?= =?UTF-8?q?=ED=9A=9F=EC=88=98=20=EA=B2=80=EC=A6=9D=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 시행횟수가 0이거나 0보다 작을경우 예외처리를 했습니다. 추가적으로 게임 금액이 투입 금액보다 클 경우 예외처리 했습니다 --- README.md | 2 ++ src/model/money.js | 14 +++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04652f037..38ba9163d 100644 --- a/README.md +++ b/README.md @@ -85,3 +85,5 @@ - 사용자가 잘못된 값을 입력할 경우 "[ERROR]"로 시작하는 메시지와 함께 `Error`를 발생시키고 해당 메시지를 출력한 다음 해당 지점부터 다시 입력을 받는다. - 입력값 숫자로 변경 +- 시행횟수가 0보다 작을경우 또는 0일경우 예외처리 +- 입력금액보다 게임 하는 금액이 클 경우 예외처리 diff --git a/src/model/money.js b/src/model/money.js index a4b7b72a5..34244aae4 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -4,9 +4,6 @@ export default class Money { #money; #count; #GAME_PRICE = 1000; - // 입력받은 금액의 유효성 검사 - // 나머지의 몫이 그럼 전부 로또로 - // 로또는 사용자가 입력한 수 만큼 구매 // 세터 지양의 이유 constructor(money, count) { @@ -31,11 +28,18 @@ export default class Money { if (money < 1000) { throw new Error("[ERROR] 로또의 금액 투입은 1,000원 이상 입니다."); } + if (count <= 0) { + throw new Error("[ERROR] 시행횟수가 0보다 작을수 없습니다."); + } + if (count * this.#GAME_PRICE > money) { + throw new Error("[ERROR] 구매 개수가 금액을 초과할 수 없습니다."); + } + return money; } - #modulo(money, count) { - const GAME_MONEY = money / (count * GAME_PRICE); + #availableMoney(money, count) { + const GAME_MONEY = this.#money / count; return GAME_MONEY; } From cc7c067938f2bd8589230b0031ce9ff44a5bed9e Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 13:04:03 +0900 Subject: [PATCH 13/30] =?UTF-8?q?refactor(Money):=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EA=B0=84=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 에러 메세지를 상수화 시켜서 에러 메세지를 더 간소하고 수정을 더 용이하게할 수 있도록 정리했습니다 --- README.md | 2 ++ src/constants/errorMessages.js | 10 ++++++++++ src/model/money.js | 12 ++++++------ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 src/constants/errorMessages.js diff --git a/README.md b/README.md index 38ba9163d..986e1181b 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,8 @@ - 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. - 사용자가 잘못된 값을 입력할 경우 "[ERROR]"로 시작하는 메시지와 함께 `Error`를 발생시키고 해당 메시지를 출력한 다음 해당 지점부터 다시 입력을 받는다. +--- + - 입력값 숫자로 변경 - 시행횟수가 0보다 작을경우 또는 0일경우 예외처리 - 입력금액보다 게임 하는 금액이 클 경우 예외처리 diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js new file mode 100644 index 000000000..dc66c912b --- /dev/null +++ b/src/constants/errorMessages.js @@ -0,0 +1,10 @@ +const ERROR_MESSAGES = { + NOT_NUMBER: "[ERROR] 금액은 숫자여야 합니다.", + BELOW_MINIMUM: "[ERROR] 최소 금액은 1,000원 이상이어야 합니다.", + INVALID_UNIT: "[ERROR] 금액은 1,000원 단위로 입력해야 합니다.", + INVALID_COUNT: "[ERROR] 구매 개수는 1개 이상이어야 합니다.", + EXCEED_LIMIT: "[ERROR] 구매 개수가 금액을 초과할 수 없습니다.", + LOTTO_NUMBER_COUNT: "[ERROR] 로또 번호는 6개여야 합니다.", +}; + +export default ERROR_MESSAGES; diff --git a/src/model/money.js b/src/model/money.js index 34244aae4..c16d1751f 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -1,10 +1,10 @@ import Inputs from "./controller/inputs"; +import ERROR_MESSAGES from "../constants/errorMessages"; export default class Money { #money; #count; #GAME_PRICE = 1000; - // 세터 지양의 이유 constructor(money, count) { const CHANGED_MONEY = this.#changeMoney(money); @@ -15,7 +15,7 @@ export default class Money { #changeMoney(money) { const CHANGE_NUM = Number(money); if (isNaN(CHANGE_NUM)) { - throw new Error("[ERROR] 금액이 숫자가 아닙니다."); + throw new Error(ERROR_MESSAGES.NOT_NUMBER); } return CHANGE_NUM; @@ -23,16 +23,16 @@ export default class Money { #validateMoney(money) { if (money % 1000 !== 0) { - throw new Error("[ERROR] 로또의 금액 투입은 1,000원 단위 입니다."); + throw new Error(ERROR_MESSAGES.INVALID_UNIT); } if (money < 1000) { - throw new Error("[ERROR] 로또의 금액 투입은 1,000원 이상 입니다."); + throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); } if (count <= 0) { - throw new Error("[ERROR] 시행횟수가 0보다 작을수 없습니다."); + throw new Error(ERROR_MESSAGES.INVALID_COUNT); } if (count * this.#GAME_PRICE > money) { - throw new Error("[ERROR] 구매 개수가 금액을 초과할 수 없습니다."); + throw new Error(ERROR_MESSAGES.EXCEED_LIMIT); } return money; From 32d22ad2ec9fe9df2984631f4a06baa7bd2c2e97 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 13:05:17 +0900 Subject: [PATCH 14/30] =?UTF-8?q?docs(README.md):=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=EB=82=B4=EC=9A=A9=20=EC=88=98=EC=A0=95?= 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 986e1181b..f5a4656de 100644 --- a/README.md +++ b/README.md @@ -89,3 +89,4 @@ - 입력값 숫자로 변경 - 시행횟수가 0보다 작을경우 또는 0일경우 예외처리 - 입력금액보다 게임 하는 금액이 클 경우 예외처리 +- 에러 메시지 상수화 From 43776ba3848d8849d7938f19e21fa3ec4ad8b8ce Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 13:30:04 +0900 Subject: [PATCH 15/30] =?UTF-8?q?feat(Money):=20=EC=B5=9C=EB=8C=80=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=20=EA=B0=80=EB=8A=A5=ED=9A=8C=EC=88=98=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 입력받은 금액과 게임하는게 필요한 금액을 계산하여 최대로 가능한 게임 횟수를 알려줍니다 --- README.md | 8 ++++++++ src/model/money.js | 27 +++++++++------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f5a4656de..c8d746042 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,11 @@ - 시행횟수가 0보다 작을경우 또는 0일경우 예외처리 - 입력금액보다 게임 하는 금액이 클 경우 예외처리 - 에러 메시지 상수화 + +### Money 클래스에서 해야할일 + +- 입력받은 금액을 문자열에서 숫자로 변경 +- 일어날 수 있는 문제에 대한 예외처리 +- 최대 가능 횟수 계산 +- 거스름돈 계산 +- diff --git a/src/model/money.js b/src/model/money.js index c16d1751f..fa8bf4f93 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -22,29 +22,20 @@ export default class Money { } #validateMoney(money) { - if (money % 1000 !== 0) { - throw new Error(ERROR_MESSAGES.INVALID_UNIT); - } - if (money < 1000) { - throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); - } - if (count <= 0) { - throw new Error(ERROR_MESSAGES.INVALID_COUNT); - } - if (count * this.#GAME_PRICE > money) { + if (money % 1000 !== 0) throw new Error(ERROR_MESSAGES.INVALID_UNIT); + if (money < 1000) throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); + if (count <= 0) throw new Error(ERROR_MESSAGES.INVALID_COUNT); + if (count * this.#GAME_PRICE > money) throw new Error(ERROR_MESSAGES.EXCEED_LIMIT); - } - - return money; } - #availableMoney(money, count) { - const GAME_MONEY = this.#money / count; - - return GAME_MONEY; + #getMaxPurchaseCount() { + return this.#money / this.#GAME_PRICE; } - #restMoney(money, GAME_MONEY) { + #restMoney(money, count) { + const GAME_MONEY = this.#GAME_PRICE * this.#count; + const REST_MONEY = money - GAME_MONEY; return REST_MONEY; From 4dcfc8ef19ff1970e16d95089f7da6f828994b83 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 13:50:46 +0900 Subject: [PATCH 16/30] =?UTF-8?q?refactor(Money):=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=9E=85=EB=A0=A5=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 해당 객체의 생성자로 이미 금액을 입력받기 때문에 따로 파라미터를 받는게 아닌 해당 객체의 값을 그대로 가져오는 방식을 선택했습니다 --- src/model/money.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/model/money.js b/src/model/money.js index fa8bf4f93..f82de2512 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -21,11 +21,11 @@ export default class Money { return CHANGE_NUM; } - #validateMoney(money) { - if (money % 1000 !== 0) throw new Error(ERROR_MESSAGES.INVALID_UNIT); - if (money < 1000) throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); - if (count <= 0) throw new Error(ERROR_MESSAGES.INVALID_COUNT); - if (count * this.#GAME_PRICE > money) + #validateMoney() { + if (this.#money % 1000 !== 0) throw new Error(ERROR_MESSAGES.INVALID_UNIT); + if (this.#money < 1000) throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); + if (this.#count <= 0) throw new Error(ERROR_MESSAGES.INVALID_COUNT); + if (this.#count * this.#GAME_PRICE > money) throw new Error(ERROR_MESSAGES.EXCEED_LIMIT); } From 8d9ea52274050cd9a4c2be1f5899bf80437d0acd Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 13:58:02 +0900 Subject: [PATCH 17/30] =?UTF-8?q?feat(Inputs):=20=EA=B5=AC=EB=A7=A4=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=EC=9E=85=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/Inputs.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/controller/Inputs.js b/src/controller/Inputs.js index 4f986a653..ee597bac5 100644 --- a/src/controller/Inputs.js +++ b/src/controller/Inputs.js @@ -30,4 +30,12 @@ export default class Inputs { return COUNT_INPUT; } + + static async getPurchaseMoney() { + const PURCHASE_MONEY = await Console.readLineAsync( + "구매 금액을 입력해 주세요. : " + ); + + return PURCHASE_MONEY; + } } From eb39e81231848eb5a757ba3796afb2d09964017f Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 14:00:56 +0900 Subject: [PATCH 18/30] =?UTF-8?q?refactor(Money)=20:=20=EA=B2=8C=EC=9E=84?= =?UTF-8?q?=20=EA=B5=AC=EB=A7=A4=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게임 구매 입력에 따른 거스름돈 반환함수 (restMoney) 수정 --- src/model/money.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/model/money.js b/src/model/money.js index f82de2512..bd4eed6d0 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -1,4 +1,4 @@ -import Inputs from "./controller/inputs"; +import Inputs from "./controller/inputs.js"; import ERROR_MESSAGES from "../constants/errorMessages"; export default class Money { @@ -12,8 +12,8 @@ export default class Money { this.#count = count; } - #changeMoney(money) { - const CHANGE_NUM = Number(money); + #changeMoney() { + const CHANGE_NUM = Number(this.#money); if (isNaN(CHANGE_NUM)) { throw new Error(ERROR_MESSAGES.NOT_NUMBER); } @@ -33,9 +33,8 @@ export default class Money { return this.#money / this.#GAME_PRICE; } - #restMoney(money, count) { - const GAME_MONEY = this.#GAME_PRICE * this.#count; - + #restMoney() { + const GAME_MONEY = Inputs.getPurchaseMoney(); const REST_MONEY = money - GAME_MONEY; return REST_MONEY; From a1aaaf2f2f5c265120978206b8c52298d5d385cb Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 14:05:53 +0900 Subject: [PATCH 19/30] =?UTF-8?q?feat(prizeRank):=20=EB=93=B1=EC=88=98=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=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/constants/prizeRank.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/constants/prizeRank.js diff --git a/src/constants/prizeRank.js b/src/constants/prizeRank.js new file mode 100644 index 000000000..72d4ed548 --- /dev/null +++ b/src/constants/prizeRank.js @@ -0,0 +1,9 @@ +const PRIZE_RANK = { + NO_1: "6개 번호 일치 / 2,000,000,000원", + NO_2: "5개 번호 + 보너스 번호 일치 / 30,000,000원", + NO_3: "5개 번호 일치 / 1,500,000원", + NO_4: "4개 번호 일치 / 50,000원", + NO_5: "3개 번호 일치 / 5,000원", +}; + +export default PRIZE_RANK; From be8c66249fa6f29670c895dd720b511805c11b78 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 15:53:40 +0900 Subject: [PATCH 20/30] =?UTF-8?q?feat(Lotto):=20=ED=8B=B0=EC=BC=93=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 좀더 안전성을 확보하기 위해 객체를 통한 상수화를 거쳐 매직넘버를 표현했습니다 --- src/Lotto.js | 10 ++++++++++ src/constants/game.js | 7 +++++++ 2 files changed, 17 insertions(+) create mode 100644 src/constants/game.js diff --git a/src/Lotto.js b/src/Lotto.js index cb0b1527e..09393b19b 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -1,3 +1,6 @@ +import { Random } from "@woowacourse/mission-utils"; +import GAME_RULES from "./constants/game"; + class Lotto { #numbers; @@ -13,6 +16,13 @@ class Lotto { } // TODO: 추가 기능 구현 + #generateTicket() { + MissionUtils.Random.pickUniqueNumbersInRange( + GAME_RULES.MIN_NUMBER, + GAME_RULES.MAX_NUMBER, + GAME_RULES.LOTTO_NUMBER_COUNT + ); + } } export default Lotto; diff --git a/src/constants/game.js b/src/constants/game.js new file mode 100644 index 000000000..57c513ded --- /dev/null +++ b/src/constants/game.js @@ -0,0 +1,7 @@ +const GAME_RULES = { + LOTTO_NUMBER_COUNT: 6, + MIN_NUMBER: 1, + MAX_NUMBER: 45, +}; + +export default GAME_RULES; From 4c44b42f4f3692579dfe83407025f7405fd4c4a3 Mon Sep 17 00:00:00 2001 From: yehoon00 Date: Mon, 3 Nov 2025 20:29:42 +0900 Subject: [PATCH 21/30] =?UTF-8?q?feat(Lotto)=20:=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EA=B0=92=EA=B3=BC=20=EB=B9=84=EA=B5=90=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 랜덤으로 생성한 번호를 정렬시키고 정렬시킨 값과 입력값을 비교하는 기능을 구현했습니다 --- README.md | 8 +++++++- src/App.js | 6 ++---- src/{ => model}/Lotto.js | 21 ++++++++++++++++++--- 3 files changed, 27 insertions(+), 8 deletions(-) rename src/{ => model}/Lotto.js (50%) diff --git a/README.md b/README.md index c8d746042..03b2a9e29 100644 --- a/README.md +++ b/README.md @@ -97,4 +97,10 @@ - 일어날 수 있는 문제에 대한 예외처리 - 최대 가능 횟수 계산 - 거스름돈 계산 -- + +### Lotto 클래스 해야할일 + +- 랜덤 번호 생성 +- 생성된 번호 정렬 +- 매직넘버와 생성된 번호를 비교후 불리언 값으로 비교 +- 입력받은 배열을 숫자 배열로 변경 diff --git a/src/App.js b/src/App.js index d0b1bab28..ddb9390a0 100644 --- a/src/App.js +++ b/src/App.js @@ -1,9 +1,7 @@ -import Inputs from "./controller/inputs"; +import { Console } from "@woowacourse/mission-utils"; class App { - async run() { - let a = Inputs.getWinningNumber(); - } + async run() {} } export default App; diff --git a/src/Lotto.js b/src/model/Lotto.js similarity index 50% rename from src/Lotto.js rename to src/model/Lotto.js index 09393b19b..a4f757926 100644 --- a/src/Lotto.js +++ b/src/model/Lotto.js @@ -1,5 +1,5 @@ import { Random } from "@woowacourse/mission-utils"; -import GAME_RULES from "./constants/game"; +import GAME_RULES from "../constants/game"; class Lotto { #numbers; @@ -15,13 +15,28 @@ class Lotto { } } - // TODO: 추가 기능 구현 #generateTicket() { - MissionUtils.Random.pickUniqueNumbersInRange( + const GET_TICKET = MissionUtils.Random.pickUniqueNumbersInRange( GAME_RULES.MIN_NUMBER, GAME_RULES.MAX_NUMBER, GAME_RULES.LOTTO_NUMBER_COUNT ); + const SORTED_TICKET = GET_TICKET.sort((a, b) => a - b); + + return SORTED_TICKET; + } + + #compareTicket(numArr) { + SORTED_TICKET.map((index) => { + return index === numbers; + }); + } + + #changeToNumber(numbers) { + const CHECK_NUM = numbers.map((index) => { + return Number(index); + }); + return CHECK_NUM; } } From 403b87f16e327a0630ec4afb33c59ebcb9871f37 Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 22:01:55 +0900 Subject: [PATCH 22/30] =?UTF-8?q?refactor(Lotto):=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=83=9D=EC=84=B1=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 로또 클래스에서 너무 많은 책임을 가지고 있는것 같아 따로 클래스를 분리했습니다 --- src/model/Lotto.js | 11 ----------- src/model/LottoGenerator.js | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 src/model/LottoGenerator.js diff --git a/src/model/Lotto.js b/src/model/Lotto.js index a4f757926..5227b9e87 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -15,17 +15,6 @@ class Lotto { } } - #generateTicket() { - const GET_TICKET = MissionUtils.Random.pickUniqueNumbersInRange( - GAME_RULES.MIN_NUMBER, - GAME_RULES.MAX_NUMBER, - GAME_RULES.LOTTO_NUMBER_COUNT - ); - const SORTED_TICKET = GET_TICKET.sort((a, b) => a - b); - - return SORTED_TICKET; - } - #compareTicket(numArr) { SORTED_TICKET.map((index) => { return index === numbers; diff --git a/src/model/LottoGenerator.js b/src/model/LottoGenerator.js new file mode 100644 index 000000000..5ee4dfac8 --- /dev/null +++ b/src/model/LottoGenerator.js @@ -0,0 +1,18 @@ +import { Random } from "@woowacourse/mission-utils"; +import GAME_RULES from "../constants/game.js"; +import Lotto from "./Lotto.js"; + +class LottoGenerator { + #generateTicket() { + const GET_TICKET = MissionUtils.Random.pickUniqueNumbersInRange( + GAME_RULES.MIN_NUMBER, + GAME_RULES.MAX_NUMBER, + GAME_RULES.LOTTO_NUMBER_COUNT + ); + const SORTED_TICKET = GET_TICKET.sort((a, b) => a - b); + + return new Lotto(SORTED_TICKET); + } +} + +export default LottoGenerator; From bcec133dbccc69d3c2ba9309c2c8793dfc460cd3 Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 22:15:53 +0900 Subject: [PATCH 23/30] =?UTF-8?q?refactor(Input,=20Lotto,=20LottoGenerator?= =?UTF-8?q?):=20mvc=ED=8C=A8=ED=84=B4=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mvc패턴에 맞게 데이터의 흐름을 변경했습니다 또한 위반가능성이 있는 부분은 클래스를 새롭게 만들어서 처리했습니다 --- src/controller/Inputs.js | 11 +++++++++-- src/model/Lotto.js | 18 ++---------------- src/model/LottoGenerator.js | 6 ++++++ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/controller/Inputs.js b/src/controller/Inputs.js index ee597bac5..02a285622 100644 --- a/src/controller/Inputs.js +++ b/src/controller/Inputs.js @@ -6,7 +6,7 @@ export default class Inputs { const TRIMED_INPUT = INPUT.replaceAll(" ", ""); const WINNING_NUMBER = TRIMED_INPUT.split(","); - return WINNING_NUMBER; + return changeToNumber(WINNING_NUMBER).sort((a, b) => a - b); } static async getBonusNumber() { @@ -14,7 +14,7 @@ export default class Inputs { "보너스 번호를 입력해 주세요. : " ); - return BONUS_NUMBER; + return Number(BONUS_NUMBER); } static async getMoney() { @@ -38,4 +38,11 @@ export default class Inputs { return PURCHASE_MONEY; } + + static #changeToNumber(numbers) { + const CHECK_NUM = numbers.map((index) => { + return Number(index); + }); + return CHECK_NUM; + } } diff --git a/src/model/Lotto.js b/src/model/Lotto.js index 5227b9e87..f35bcac66 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -1,5 +1,4 @@ -import { Random } from "@woowacourse/mission-utils"; -import GAME_RULES from "../constants/game"; +import GAME_RULES from "../constants/game.js"; class Lotto { #numbers; @@ -10,23 +9,10 @@ class Lotto { } #validate(numbers) { - if (numbers.length !== 6) { + if (numbers.length !== GAME_RULES.LOTTO_NUMBER_COUNT) { throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); } } - - #compareTicket(numArr) { - SORTED_TICKET.map((index) => { - return index === numbers; - }); - } - - #changeToNumber(numbers) { - const CHECK_NUM = numbers.map((index) => { - return Number(index); - }); - return CHECK_NUM; - } } export default Lotto; diff --git a/src/model/LottoGenerator.js b/src/model/LottoGenerator.js index 5ee4dfac8..d0f623934 100644 --- a/src/model/LottoGenerator.js +++ b/src/model/LottoGenerator.js @@ -13,6 +13,12 @@ class LottoGenerator { return new Lotto(SORTED_TICKET); } + + #sortNumber(numArr) { + SORTED_TICKET.map((index) => { + return index === numbers; + }); + } } export default LottoGenerator; From 77742e60d47738a4baee87852162b5fb24f4bebc Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 22:27:40 +0900 Subject: [PATCH 24/30] =?UTF-8?q?refactor(LottoGenerator):=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=9D=98=20=EC=B1=85=EC=9E=84=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generateTicket 함수가 단일 책임을 위반하여 따로 메서드를 분리했습니다 --- src/model/Lotto.js | 12 +++++++++++- src/model/LottoGenerator.js | 5 ++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/model/Lotto.js b/src/model/Lotto.js index f35bcac66..f164da027 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -5,7 +5,7 @@ class Lotto { constructor(numbers) { this.#validate(numbers); - this.#numbers = numbers; + this.#numbers = this.#sortNumbers(numbers); } #validate(numbers) { @@ -13,6 +13,16 @@ class Lotto { throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); } } + + #getNumbers() { + return this.#numbers; + } + + #sortNumbers(numbers) { + const SORTED_TICKET = [...numbers].sort((a, b) => a - b); + + return SORTED_TICKET; + } } export default Lotto; diff --git a/src/model/LottoGenerator.js b/src/model/LottoGenerator.js index d0f623934..1e75725b2 100644 --- a/src/model/LottoGenerator.js +++ b/src/model/LottoGenerator.js @@ -9,12 +9,11 @@ class LottoGenerator { GAME_RULES.MAX_NUMBER, GAME_RULES.LOTTO_NUMBER_COUNT ); - const SORTED_TICKET = GET_TICKET.sort((a, b) => a - b); - return new Lotto(SORTED_TICKET); + return new Lotto(GET_TICKET); } - #sortNumber(numArr) { + #compareTicket(numArr) { SORTED_TICKET.map((index) => { return index === numbers; }); From cdac3c684da0dd0f09e70c657576d2e4372b3ca1 Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 22:46:48 +0900 Subject: [PATCH 25/30] =?UTF-8?q?feat:(Lotto)=20:=20=EA=B2=8C=ED=84=B0=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/model/Lotto.js | 8 ++++---- src/model/LottoGenerator.js | 13 ++++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/model/Lotto.js b/src/model/Lotto.js index f164da027..03eba866b 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -14,15 +14,15 @@ class Lotto { } } - #getNumbers() { - return this.#numbers; - } - #sortNumbers(numbers) { const SORTED_TICKET = [...numbers].sort((a, b) => a - b); return SORTED_TICKET; } + + getNumbers() { + return [...this.#numbers]; + } } export default Lotto; diff --git a/src/model/LottoGenerator.js b/src/model/LottoGenerator.js index 1e75725b2..46bc77c45 100644 --- a/src/model/LottoGenerator.js +++ b/src/model/LottoGenerator.js @@ -3,7 +3,12 @@ import GAME_RULES from "../constants/game.js"; import Lotto from "./Lotto.js"; class LottoGenerator { - #generateTicket() { + #ticket; + constructor() { + this.#ticket = this.generateTicket(); + } + + static generateTicket() { const GET_TICKET = MissionUtils.Random.pickUniqueNumbersInRange( GAME_RULES.MIN_NUMBER, GAME_RULES.MAX_NUMBER, @@ -13,10 +18,8 @@ class LottoGenerator { return new Lotto(GET_TICKET); } - #compareTicket(numArr) { - SORTED_TICKET.map((index) => { - return index === numbers; - }); + getGenerated() { + return [...this.#ticket]; } } From 6e08a4b7f8386c0ec4673a1ed2c5b962b1322288 Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 22:48:24 +0900 Subject: [PATCH 26/30] =?UTF-8?q?feat(Calculator)=20:=20=EB=B6=88=EB=A6=B0?= =?UTF-8?q?=20=EB=B0=B0=EC=97=B4=20=EC=A0=84=EB=8B=AC=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 등수를 구별하기 위해서 불린값을 가지는 배열을 리턴하는 메서드를 구햔하였습니다 --- src/model/Calculator.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/model/Calculator.js diff --git a/src/model/Calculator.js b/src/model/Calculator.js new file mode 100644 index 000000000..7d1e24543 --- /dev/null +++ b/src/model/Calculator.js @@ -0,0 +1,8 @@ +class Calculator { + #compareTicket(numArr) { + const BOOLEAN_ARR = numArr.map((index) => { + return index === numbers; + }); + return BOOLEAN_ARR; + } +} From 8e8ef4b90a376cbb82ca047ab6514d63e2fe852e Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 23:50:56 +0900 Subject: [PATCH 27/30] =?UTF-8?q?feat(Calculator)=20:=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 배열에 입력값에 맞게 등수를 확인시키는 기능을 추가하였습니다 --- src/model/Calculator.js | 74 +++++++++++++++++++++++++++++++++++++---- src/model/Lotto.js | 28 ---------------- 2 files changed, 68 insertions(+), 34 deletions(-) delete mode 100644 src/model/Lotto.js diff --git a/src/model/Calculator.js b/src/model/Calculator.js index 7d1e24543..8edecb6d5 100644 --- a/src/model/Calculator.js +++ b/src/model/Calculator.js @@ -1,8 +1,70 @@ -class Calculator { - #compareTicket(numArr) { - const BOOLEAN_ARR = numArr.map((index) => { - return index === numbers; - }); - return BOOLEAN_ARR; +import PRIZE_RANK from "../constants/prizeRank.js"; + +const PRIZE ={ + RANK_1: 2000000000, + RANK_2: 30000000, + RANK_3: 1500000, + RANK_4: 50000, + RANK_5: 5000, +}; + +export default class Calculator { + static countMatch(ticketNumbers, winningNumbers) { + const set = new Set(winningNumbers); + return ticketNumbers.filter((n) => set.has(n)).length; + } + + static isBonusMatch(ticketNumbers, bonus) { + return ticketNumbers.includes(bonus); + } + + static getRank(ticketNumbers, winningNumbers, bonus) { + const match = Calculator.countMatch(ticketNumbers, winningNumbers); + if (match === 6) return "rank1"; + if (match === 5 && Calculator.isBonusMatch(ticketNumbers, bonus)) return "rank2"; + if (match === 5) return "rank3"; + if (match === 4) return "rank4"; + if (match === 3) return "rank5"; + return null; + } + + static tallyResults(tickets, winningNumbers, bonus) { + return tickets.reduce( + (tally, ticket) => { + const rank = Calculator.getRank( + ticket.getNumbers(), + winningNumbers, + bonus + ); + if (rank) tally[rank] += 1; + return tally; + }, + { rank5: 0, rank4: 0, rank3: 0, rank2: 0, rank1: 0 } + ); + } + + static totalPrize(tally) { + return ( + tally.rank1 * PRIZE.RANK_1 + + tally.rank2 * PRIZE.RANK_2 + + tally.rank3 * PRIZE.RANK_3 + + tally.rank4 * PRIZE.RANK_4 + + tally.rank5 * PRIZE.RANK_5 + ); + } + + static rate(totalPrize, purchaseAmount) { + const percent = (totalPrize / purchaseAmount) * 100; + return Math.round(percent * 10) / 10; + } + + static rankDescriptions() { + return { + rank1: PRIZE_RANK.NO_1, + rank2: PRIZE_RANK.NO_2, + rank3: PRIZE_RANK.NO_3, + rank4: PRIZE_RANK.NO_4, + rank5: PRIZE_RANK.NO_5, + }; } } diff --git a/src/model/Lotto.js b/src/model/Lotto.js deleted file mode 100644 index 03eba866b..000000000 --- a/src/model/Lotto.js +++ /dev/null @@ -1,28 +0,0 @@ -import GAME_RULES from "../constants/game.js"; - -class Lotto { - #numbers; - - constructor(numbers) { - this.#validate(numbers); - this.#numbers = this.#sortNumbers(numbers); - } - - #validate(numbers) { - if (numbers.length !== GAME_RULES.LOTTO_NUMBER_COUNT) { - throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); - } - } - - #sortNumbers(numbers) { - const SORTED_TICKET = [...numbers].sort((a, b) => a - b); - - return SORTED_TICKET; - } - - getNumbers() { - return [...this.#numbers]; - } -} - -export default Lotto; From e7269596048f85a94a253486688956b881aee1ac Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 23:52:04 +0900 Subject: [PATCH 28/30] =?UTF-8?q?docs(README)=20:=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=97=90=20=EB=A7=9E=EB=8A=90=20=EB=A6=AC?= =?UTF-8?q?=EB=93=9C=EB=AF=B8=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 | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 03b2a9e29..f332ea987 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,16 @@ ### Lotto 클래스 해야할일 +- 생성된 번호 정렬 -> 컨트롤러에서 제공 +- 매직넘버와 생성된 번호를 비교후 불리언 값으로 비교 -> 계산기에서 비교 +- 입력받은 배열을 숫자 배열로 변경 -> + +### LottoGenerator 클래스의 역할 + - 랜덤 번호 생성 -- 생성된 번호 정렬 -- 매직넘버와 생성된 번호를 비교후 불리언 값으로 비교 -- 입력받은 배열을 숫자 배열로 변경 +- 티켓 구매 수 만큼 랜덤 번호 시행 회수 + + +### Calculator 클래스의 역할 + +- 배열수를 확인 From 02bb6d47edcc2da42d47c1ce49affa6b3f9aa97c Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 23:53:30 +0900 Subject: [PATCH 29/30] =?UTF-8?q?refactor=20:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EB=AA=85=EC=84=B8=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 테스트 코드가 요구하는 사항에 맞게 코드를 수정하였습니다 잘못된 참조 수정 및 잘못된 유틸리티 호출 수정, money 생성자 파라미터 1개로 변경 --- README.md | 3 +- src/App.js | 62 ++++++++++++++++++++++++++++++++++++- src/Lotto.js | 34 ++++++++++++++++++++ src/controller/Inputs.js | 2 +- src/model/LottoGenerator.js | 18 +++++------ src/model/money.js | 47 ++++++++++++---------------- src/model/numbers.js | 3 -- 7 files changed, 127 insertions(+), 42 deletions(-) create mode 100644 src/Lotto.js delete mode 100644 src/model/numbers.js diff --git a/README.md b/README.md index f332ea987..611ccd7fa 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,8 @@ - 랜덤 번호 생성 - 티켓 구매 수 만큼 랜덤 번호 시행 회수 - ### Calculator 클래스의 역할 - 배열수를 확인 +- 배열에 맞게 맞는 수가 있다면 카운트 증가 +- 카운트를 배경으로 등수를 매김 diff --git a/src/App.js b/src/App.js index ddb9390a0..c8eb1e427 100644 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,67 @@ import { Console } from "@woowacourse/mission-utils"; +import Inputs from "./controller/Inputs.js"; +import Money from "./model/money.js"; +import LottoGenerator from "./model/LottoGenerator.js"; +import Calculator from "./model/Calculator.js"; +import PRIZE_RANK from "./constants/prizeRank.js"; class App { - async run() {} + async run() { + const money = await this.#readValidMoney(); + const count = money.getPurchaseCount(); + Console.print(`${count}개를 구매했습니다.`); + + const tickets = LottoGenerator.generateTickets(count); + tickets.forEach((ticket) => { + const formatted = `[${ticket.getNumbers().join(", ")}]`; + Console.print(formatted); + }); + + const winningNumbers = await Inputs.getWinningNumber(); + const bonusNumber = await Inputs.getBonusNumber(); + + const tally = Calculator.tallyResults( + tickets, + winningNumbers, + bonusNumber + ); + + this.#printStatistics(tally); + const totalPrize = Calculator.totalPrize(tally); + const rate = Calculator.rate(totalPrize, money.getAmount()); + Console.print(`총 수익률은 ${rate}%입니다.`); + } + + async #readValidMoney() { + while (true) { + try { + const input = await Inputs.getMoney(); + return new Money(input); + } catch (e) { + Console.print(e?.message); + } + } + } + + #printStatistics(tally) { + const format = (key, desc) => { + const amount = desc.split(" / ")[1]; + const labelMap = { + NO_5: "3개 일치", + NO_4: "4개 일치", + NO_3: "5개 일치", + NO_2: "5개 일치, 보너스 볼 일치", + NO_1: "6개 일치", + }; + return `${labelMap[key]} (${amount})`; + }; + + Console.print(`${format("NO_5", PRIZE_RANK.NO_5)} - ${tally.rank5}개`); + Console.print(`${format("NO_4", PRIZE_RANK.NO_4)} - ${tally.rank4}개`); + Console.print(`${format("NO_3", PRIZE_RANK.NO_3)} - ${tally.rank3}개`); + Console.print(`${format("NO_2", PRIZE_RANK.NO_2)} - ${tally.rank2}개`); + Console.print(`${format("NO_1", PRIZE_RANK.NO_1)} - ${tally.rank1}개`); + } } export default App; diff --git a/src/Lotto.js b/src/Lotto.js new file mode 100644 index 000000000..d37d90f34 --- /dev/null +++ b/src/Lotto.js @@ -0,0 +1,34 @@ +import GAME_RULES from "./constants/game.js"; + +class Lotto { + #numbers; + + constructor(numbers) { + this.#validate(numbers); + this.#numbers = this.#sortNumbers(numbers); + } + + #validate(numbers) { + if (numbers.length !== GAME_RULES.LOTTO_NUMBER_COUNT) { + throw new Error("[ERROR] 로또 번호는 6개여야 합니다."); + } + const uniqueCount = new Set(numbers).size; + if (uniqueCount !== numbers.length) { + throw new Error("[ERROR] 중복된 번호가 있습니다."); + } + } + + #sortNumbers(numbers) { + const SORTED_TICKET = [...numbers].sort((a, b) => a - b); + + return SORTED_TICKET; + } + + getNumbers() { + return [...this.#numbers]; + } +} + +export default Lotto; + + diff --git a/src/controller/Inputs.js b/src/controller/Inputs.js index 02a285622..fc598a35e 100644 --- a/src/controller/Inputs.js +++ b/src/controller/Inputs.js @@ -6,7 +6,7 @@ export default class Inputs { const TRIMED_INPUT = INPUT.replaceAll(" ", ""); const WINNING_NUMBER = TRIMED_INPUT.split(","); - return changeToNumber(WINNING_NUMBER).sort((a, b) => a - b); + return this.#changeToNumber(WINNING_NUMBER).sort((a, b) => a - b); } static async getBonusNumber() { diff --git a/src/model/LottoGenerator.js b/src/model/LottoGenerator.js index 46bc77c45..ecd689c32 100644 --- a/src/model/LottoGenerator.js +++ b/src/model/LottoGenerator.js @@ -1,15 +1,10 @@ import { Random } from "@woowacourse/mission-utils"; import GAME_RULES from "../constants/game.js"; -import Lotto from "./Lotto.js"; +import Lotto from "../Lotto.js"; class LottoGenerator { - #ticket; - constructor() { - this.#ticket = this.generateTicket(); - } - static generateTicket() { - const GET_TICKET = MissionUtils.Random.pickUniqueNumbersInRange( + const GET_TICKET = Random.pickUniqueNumbersInRange( GAME_RULES.MIN_NUMBER, GAME_RULES.MAX_NUMBER, GAME_RULES.LOTTO_NUMBER_COUNT @@ -18,9 +13,14 @@ class LottoGenerator { return new Lotto(GET_TICKET); } - getGenerated() { - return [...this.#ticket]; + static generateTickets(count) { + const tickets = []; + for (let i = 0; i < count; i += 1) { + tickets.push(this.generateTicket()); + } + return tickets; } + } export default LottoGenerator; diff --git a/src/model/money.js b/src/model/money.js index bd4eed6d0..e2f734345 100644 --- a/src/model/money.js +++ b/src/model/money.js @@ -1,42 +1,35 @@ -import Inputs from "./controller/inputs.js"; -import ERROR_MESSAGES from "../constants/errorMessages"; +import ERROR_MESSAGES from "../constants/errorMessages.js"; export default class Money { - #money; - #count; - #GAME_PRICE = 1000; + #amount; + static #GAME_PRICE = 1000; - constructor(money, count) { - const CHANGED_MONEY = this.#changeMoney(money); - this.#money = CHANGED_MONEY; - this.#count = count; + constructor(input) { + const parsed = Money.#parseAmount(input); + Money.#validateAmount(parsed); + this.#amount = parsed; } - #changeMoney() { - const CHANGE_NUM = Number(this.#money); - if (isNaN(CHANGE_NUM)) { + static #parseAmount(input) { + const num = Number(input); + if (Number.isNaN(num)) { throw new Error(ERROR_MESSAGES.NOT_NUMBER); } - - return CHANGE_NUM; + return num; } - #validateMoney() { - if (this.#money % 1000 !== 0) throw new Error(ERROR_MESSAGES.INVALID_UNIT); - if (this.#money < 1000) throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); - if (this.#count <= 0) throw new Error(ERROR_MESSAGES.INVALID_COUNT); - if (this.#count * this.#GAME_PRICE > money) - throw new Error(ERROR_MESSAGES.EXCEED_LIMIT); + static #validateAmount(amount) { + if (amount < Money.#GAME_PRICE) + throw new Error(ERROR_MESSAGES.BELOW_MINIMUM); + if (amount % Money.#GAME_PRICE !== 0) + throw new Error(ERROR_MESSAGES.INVALID_UNIT); } - #getMaxPurchaseCount() { - return this.#money / this.#GAME_PRICE; + getAmount() { + return this.#amount; } - #restMoney() { - const GAME_MONEY = Inputs.getPurchaseMoney(); - const REST_MONEY = money - GAME_MONEY; - - return REST_MONEY; + getPurchaseCount() { + return this.#amount / Money.#GAME_PRICE; } } diff --git a/src/model/numbers.js b/src/model/numbers.js deleted file mode 100644 index ceb121a4a..000000000 --- a/src/model/numbers.js +++ /dev/null @@ -1,3 +0,0 @@ -import Inputs from "./controller/inputs"; - -export default class Numbers {} From ebf601ecfba79d5e98b5e5996b4a95d6aa277509 Mon Sep 17 00:00:00 2001 From: JangYEhoon00 Date: Mon, 3 Nov 2025 23:54:09 +0900 Subject: [PATCH 30/30] =?UTF-8?q?feat(CalculatorTest)=20:=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=EA=B8=B0=EB=8A=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 계산 기능의 테스트 코드를 작성하였습니다 --- __tests__/CalculatorTest.js | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 __tests__/CalculatorTest.js diff --git a/__tests__/CalculatorTest.js b/__tests__/CalculatorTest.js new file mode 100644 index 000000000..45d2886d9 --- /dev/null +++ b/__tests__/CalculatorTest.js @@ -0,0 +1,39 @@ +import Calculator from "../src/model/Calculator.js"; + +const makeTicket = (numbers) => ({ + getNumbers: () => numbers, +}); + +describe("Calculator - tallyResults", () => { + test("6개 일치 -> rank1 1개", () => { + const tickets = [makeTicket([1, 2, 3, 4, 5, 6])]; + const tally = Calculator.tallyResults(tickets, [1, 2, 3, 4, 5, 6], 7); + expect(tally).toEqual({ rank5: 0, rank4: 0, rank3: 0, rank2: 0, rank1: 1 }); + }); + + test("5개+보너스 -> rank2 1개", () => { + const tickets = [makeTicket([1, 2, 3, 4, 5, 7])]; + const tally = Calculator.tallyResults(tickets, [1, 2, 3, 4, 5, 6], 7); + expect(tally).toEqual({ rank5: 0, rank4: 0, rank3: 0, rank2: 1, rank1: 0 }); + }); + + test("5개 -> rank3 1개", () => { + const tickets = [makeTicket([1, 2, 3, 4, 5, 8])]; + const tally = Calculator.tallyResults(tickets, [1, 2, 3, 4, 5, 6], 7); + expect(tally).toEqual({ rank5: 0, rank4: 0, rank3: 1, rank2: 0, rank1: 0 }); + }); + + test("4개 -> rank4 1개", () => { + const tickets = [makeTicket([1, 2, 3, 4, 9, 10])]; + const tally = Calculator.tallyResults(tickets, [1, 2, 3, 4, 5, 6], 7); + expect(tally).toEqual({ rank5: 0, rank4: 1, rank3: 0, rank2: 0, rank1: 0 }); + }); + + test("3개 -> rank5 1개", () => { + const tickets = [makeTicket([1, 2, 3, 9, 10, 11])]; + const tally = Calculator.tallyResults(tickets, [1, 2, 3, 4, 5, 6], 7); + expect(tally).toEqual({ rank5: 1, rank4: 0, rank3: 0, rank2: 0, rank1: 0 }); + }); +}); + +