From cbe1c2a2250ccc69f884af4d48063b131279588a Mon Sep 17 00:00:00 2001 From: DDangDin Date: Tue, 29 Oct 2024 18:23:29 +0900 Subject: [PATCH 01/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4fc0ae874..a73d1bb6f 100644 --- a/README.md +++ b/README.md @@ -1 +1,39 @@ -# kotlin-lotto-precourse +# 우테코 프리코스 3주차 - 로또 + +**간단한 로또 발매기**를 구현 + +
+ +## ⚙️ 기능 목록 정리 + +- **입출력 기능** + - **입력** + - [ ] 로또 구입 금액을 1,000원 단위로 입력받는다 + - [ ] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. + - [ ] 보너스 번호를 입력 받는다. + - **입력 예외 처리** + - [ ] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 예외 처리 + - **출력** + - [ ] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. + - [ ] 당첨 내역을 출력한다. + - [ ] 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%) + - [ ] **예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.** + +
+ +- **로또** + - [ ] 로또 번호의 숫자 범위는 1~45까지이다. + - [ ] 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. + - [ ] 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다. + - [ ] 당첨은 1등부터 5등까지 있다. + - 당첨 기준과 금액 + - 1등: 6개 번호 일치 / 2,000,000,000원 + - 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원 + - 3등: 5개 번호 일치 / 1,500,000원 + - 4등: 4개 번호 일치 / 50,000원 + - 5등: 3개 번호 일치 / 5,000원 + - [ ] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. + - [ ] 로또 1장의 가격은 1,000원이다. + - [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. + - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. + - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From b374aa10d6b41fa2588fc2ee72816b11f0f947f2 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 17:39:40 +0900 Subject: [PATCH 02/59] =?UTF-8?q?docs:=20README.md=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a73d1bb6f..033d8e2d3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,10 @@ - [ ] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. - [ ] 보너스 번호를 입력 받는다. - **입력 예외 처리** - - [ ] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 예외 처리 + - [ ] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 + - [ ] 구입 금액이 1,000원 보다 적은 금액일 경우 + - [ ] 숫자가 아닐 경우 + - [ ] 공백일 경우 - **출력** - [ ] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - [ ] 당첨 내역을 출력한다. From edbc8afc16d759fd7495b6538c3ef1aa61b33ac6 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:07:17 +0900 Subject: [PATCH 03/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EC=9E=85=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구입 금액을 입력할 때 출력되는 텍스트는 LottoOutputText에서 통합적으로 관리 --- src/main/kotlin/lotto/Application.kt | 8 +++++++- src/main/kotlin/lotto/util/LottoOutputText.kt | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/lotto/util/LottoOutputText.kt diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 151821c9c..956719440 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -1,5 +1,11 @@ package lotto +import camp.nextstep.edu.missionutils.Console +import lotto.util.LottoOutputText + fun main() { - // TODO: 프로그램 구현 + // TODO: 예외 발생 후에도 항상 해당 부분 부터 다시 입력을 받는다. + println(LottoOutputText.INPUT_PURCHASE_PRICE_TEXT) + val purchasePrice = Console.readLine().toInt() // TODO: 입력 예외 처리 필요 + println() } diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/util/LottoOutputText.kt new file mode 100644 index 000000000..39dfdd56c --- /dev/null +++ b/src/main/kotlin/lotto/util/LottoOutputText.kt @@ -0,0 +1,5 @@ +package lotto.util + +object LottoOutputText { + const val INPUT_PURCHASE_PRICE_TEXT = "구입금액을 입력해 주세요." +} \ No newline at end of file From ddbc8e34acb7fce9464389cef9c84a28d6ee3b7e Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:09:03 +0900 Subject: [PATCH 04/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=20=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 033d8e2d3..72f1a3239 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - **입출력 기능** - **입력** - - [ ] 로또 구입 금액을 1,000원 단위로 입력받는다 + - [x] 로또 구입 금액을 1,000원 단위로 입력받는다 - [ ] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. - [ ] 보너스 번호를 입력 받는다. - **입력 예외 처리** From e62260c9857bf3b8cbbf54d40cea53e84e24ea4c Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:10:50 +0900 Subject: [PATCH 05/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EC=9E=85=20=EA=B8=88=EC=95=A1=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 예외 메시지는 ErrorMessage에서 통합 관리 --- src/main/kotlin/lotto/LottoMachine.kt | 12 ++++++++++++ src/main/kotlin/lotto/util/ErrorMessage.kt | 10 ++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/main/kotlin/lotto/LottoMachine.kt create mode 100644 src/main/kotlin/lotto/util/ErrorMessage.kt diff --git a/src/main/kotlin/lotto/LottoMachine.kt b/src/main/kotlin/lotto/LottoMachine.kt new file mode 100644 index 000000000..04ba6e837 --- /dev/null +++ b/src/main/kotlin/lotto/LottoMachine.kt @@ -0,0 +1,12 @@ +package lotto + +import lotto.util.ErrorMessage + +class LottoMachine(private val purchasePrice: Int) { + init { + require(purchasePrice >= 1000) { ErrorMessage.PURCHASE_PRICE_MORE_THAN_THOUSAND.getMessage() } + require(purchasePrice % 1000 == 0) { ErrorMessage.INVALID_PURCHASE_PRICE.getMessage() } + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/ErrorMessage.kt b/src/main/kotlin/lotto/util/ErrorMessage.kt new file mode 100644 index 000000000..e416a7502 --- /dev/null +++ b/src/main/kotlin/lotto/util/ErrorMessage.kt @@ -0,0 +1,10 @@ +package lotto.util + +enum class ErrorMessage(private val message: String) { + PURCHASE_PRICE_MORE_THAN_THOUSAND("구입 금액은 최소 1,000원 부터 입니다."), + INVALID_PURCHASE_PRICE("구입 금액은 1,000원 단위 입니다."), + PURCHASE_PRICE_MUST_BE_NUMBER("구입 금액은 숫자만 입력 가능 합니다."), + PURCHASE_PRICE_EMPTY("구입 금액은 비어있을 수 없습니다."); + + fun getMessage(): String = "[ERROR] $message" +} \ No newline at end of file From 5c46e12db13731cbed5872ed5bcd5cc00d5def43 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:11:15 +0900 Subject: [PATCH 06/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 72f1a3239..ec140a9da 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ - [ ] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. - [ ] 보너스 번호를 입력 받는다. - **입력 예외 처리** - - [ ] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 - - [ ] 구입 금액이 1,000원 보다 적은 금액일 경우 + - [x] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 + - [x] 구입 금액이 1,000원 보다 적은 금액일 경우 - [ ] 숫자가 아닐 경우 - [ ] 공백일 경우 - **출력** From cecd60349cde0cecb0888e8c4b97b0b7e17eb34b Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:23:54 +0900 Subject: [PATCH 07/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B0=9C?= =?UTF-8?q?=EB=A7=A4=EA=B8=B0=EC=97=90=EC=84=9C=20=EB=A1=9C=EB=98=90?= =?UTF-8?q?=EB=A5=BC=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 로또 발매기(LottoMachine)에서 1개의 로또를 생성하는 기능 추가 - 가격에 따른 로또 개수 계산 기능 추가 --- src/main/kotlin/lotto/LottoMachine.kt | 13 +++++++++++++ src/main/kotlin/lotto/util/LottoConstants.kt | 5 +++++ 2 files changed, 18 insertions(+) create mode 100644 src/main/kotlin/lotto/util/LottoConstants.kt diff --git a/src/main/kotlin/lotto/LottoMachine.kt b/src/main/kotlin/lotto/LottoMachine.kt index 04ba6e837..5ea22e9e7 100644 --- a/src/main/kotlin/lotto/LottoMachine.kt +++ b/src/main/kotlin/lotto/LottoMachine.kt @@ -1,6 +1,8 @@ package lotto +import camp.nextstep.edu.missionutils.Randoms.pickUniqueNumbersInRange import lotto.util.ErrorMessage +import lotto.util.LottoConstants class LottoMachine(private val purchasePrice: Int) { init { @@ -8,5 +10,16 @@ class LottoMachine(private val purchasePrice: Int) { require(purchasePrice % 1000 == 0) { ErrorMessage.INVALID_PURCHASE_PRICE.getMessage() } } + private fun getLottoCount(): Int = purchasePrice / LottoConstants.PRICE + private fun generateOneLotto(): Lotto { + val randomUniqueNumbers = pickUniqueNumbersInRange(START_NUMBER, END_NUMBER, PICK_COUNT) + return Lotto(randomUniqueNumbers) + } + + companion object { + private const val START_NUMBER = 0 + private const val END_NUMBER = 45 + private const val PICK_COUNT = 6 + } } \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/LottoConstants.kt b/src/main/kotlin/lotto/util/LottoConstants.kt new file mode 100644 index 000000000..0b1d705cc --- /dev/null +++ b/src/main/kotlin/lotto/util/LottoConstants.kt @@ -0,0 +1,5 @@ +package lotto.util + +object LottoConstants { + const val PRICE = 1000 +} \ No newline at end of file From d0115aa269d1399cc67737c5815673285ecdc35b Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:24:11 +0900 Subject: [PATCH 08/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ec140a9da..f8a79523d 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@
- **로또** - - [ ] 로또 번호의 숫자 범위는 1~45까지이다. - - [ ] 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. + - [x] 로또 번호의 숫자 범위는 1~45까지이다. + - [x] 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. - [ ] 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다. - [ ] 당첨은 1등부터 5등까지 있다. - 당첨 기준과 금액 @@ -36,7 +36,7 @@ - 4등: 4개 번호 일치 / 50,000원 - 5등: 3개 번호 일치 / 5,000원 - [ ] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - - [ ] 로또 1장의 가격은 1,000원이다. + - [x] 로또 1장의 가격은 1,000원이다. - [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From 849f2285888425261d9974ceb89604c08efe4d3b Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:26:54 +0900 Subject: [PATCH 09/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EC=9E=85=20=EA=B8=88=EC=95=A1=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=B0=9C=ED=96=89=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/main/kotlin/lotto/Application.kt | 3 +++ src/main/kotlin/lotto/LottoMachine.kt | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 956719440..60565720e 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -8,4 +8,7 @@ fun main() { println(LottoOutputText.INPUT_PURCHASE_PRICE_TEXT) val purchasePrice = Console.readLine().toInt() // TODO: 입력 예외 처리 필요 println() + + val lottoMachine = LottoMachine(purchasePrice) + lottoMachine.generate() } diff --git a/src/main/kotlin/lotto/LottoMachine.kt b/src/main/kotlin/lotto/LottoMachine.kt index 5ea22e9e7..86157847d 100644 --- a/src/main/kotlin/lotto/LottoMachine.kt +++ b/src/main/kotlin/lotto/LottoMachine.kt @@ -10,6 +10,14 @@ class LottoMachine(private val purchasePrice: Int) { require(purchasePrice % 1000 == 0) { ErrorMessage.INVALID_PURCHASE_PRICE.getMessage() } } + fun generate(): List { + val lottoCount = getLottoCount() + val lottoList = List(lottoCount) { + generateOneLotto() + } + return lottoList + } + private fun getLottoCount(): Int = purchasePrice / LottoConstants.PRICE private fun generateOneLotto(): Lotto { From 7b43241111744669800e6a678baed404df3ca543 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:27:29 +0900 Subject: [PATCH 10/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8a79523d..6a5f81203 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ - 3등: 5개 번호 일치 / 1,500,000원 - 4등: 4개 번호 일치 / 50,000원 - 5등: 3개 번호 일치 / 5,000원 - - [ ] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. + - [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - [x] 로또 1장의 가격은 1,000원이다. - [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. From e1f4fc1487c6295efaebb777086ad323ab87c6dc Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:28:59 +0900 Subject: [PATCH 11/59] =?UTF-8?q?refactor:=20LottoMachine=20->=20LottoGene?= =?UTF-8?q?rator=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LottoGenerator 라는 이름이 더 적합하다고 생각해서 클래스명 수정 --- src/main/kotlin/lotto/Application.kt | 4 ++-- src/main/kotlin/lotto/{LottoMachine.kt => LottoGenerator.kt} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/main/kotlin/lotto/{LottoMachine.kt => LottoGenerator.kt} (94%) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 60565720e..c84264c1b 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -9,6 +9,6 @@ fun main() { val purchasePrice = Console.readLine().toInt() // TODO: 입력 예외 처리 필요 println() - val lottoMachine = LottoMachine(purchasePrice) - lottoMachine.generate() + val lottoGenerator = LottoGenerator(purchasePrice) + lottoGenerator.generate() } diff --git a/src/main/kotlin/lotto/LottoMachine.kt b/src/main/kotlin/lotto/LottoGenerator.kt similarity index 94% rename from src/main/kotlin/lotto/LottoMachine.kt rename to src/main/kotlin/lotto/LottoGenerator.kt index 86157847d..c1e936cd4 100644 --- a/src/main/kotlin/lotto/LottoMachine.kt +++ b/src/main/kotlin/lotto/LottoGenerator.kt @@ -4,7 +4,7 @@ import camp.nextstep.edu.missionutils.Randoms.pickUniqueNumbersInRange import lotto.util.ErrorMessage import lotto.util.LottoConstants -class LottoMachine(private val purchasePrice: Int) { +class LottoGenerator(private val purchasePrice: Int) { init { require(purchasePrice >= 1000) { ErrorMessage.PURCHASE_PRICE_MORE_THAN_THOUSAND.getMessage() } require(purchasePrice % 1000 == 0) { ErrorMessage.INVALID_PURCHASE_PRICE.getMessage() } From df80913e6d7c8e59b7f5f0f1d2426c0190a5aad5 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:38:10 +0900 Subject: [PATCH 12/59] =?UTF-8?q?feat:=20=EB=B0=9C=ED=96=89=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=EC=98=A4?= =?UTF-8?q?=EB=A6=84=EC=B0=A8=EC=88=9C=20=EC=A0=95=EB=A0=AC=EB=90=9C=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=B6=9C=EB=A0=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 발행한 로또 수량을 출력 텍스트와 함께 출력 - Lotto 클래스에서 정렬된 숫자를 반환하는 메서드 추가 --- src/main/kotlin/lotto/Application.kt | 7 ++++++- src/main/kotlin/lotto/Lotto.kt | 2 +- src/main/kotlin/lotto/util/LottoOutputText.kt | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index c84264c1b..563b2a6e4 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -10,5 +10,10 @@ fun main() { println() val lottoGenerator = LottoGenerator(purchasePrice) - lottoGenerator.generate() + val lottoList = lottoGenerator.generate() + val lottoListSize = lottoList.size + println("${lottoListSize}${LottoOutputText.LOTTO_GENERATE_FINISH_TEXT}") + lottoList.forEach { lotto -> + println(lotto.getSortedNumbers()) + } } diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt index b97abc385..916b9ddbe 100644 --- a/src/main/kotlin/lotto/Lotto.kt +++ b/src/main/kotlin/lotto/Lotto.kt @@ -5,5 +5,5 @@ class Lotto(private val numbers: List) { require(numbers.size == 6) { "[ERROR] 로또 번호는 6개여야 합니다." } } - // TODO: 추가 기능 구현 + fun getSortedNumbers(): List = numbers.sorted() } diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/util/LottoOutputText.kt index 39dfdd56c..29bea9d37 100644 --- a/src/main/kotlin/lotto/util/LottoOutputText.kt +++ b/src/main/kotlin/lotto/util/LottoOutputText.kt @@ -2,4 +2,5 @@ package lotto.util object LottoOutputText { const val INPUT_PURCHASE_PRICE_TEXT = "구입금액을 입력해 주세요." + const val LOTTO_GENERATE_FINISH_TEXT = "개 구매했습니다." } \ No newline at end of file From 5e8a5dd76f53a0e7bcf4acbfe774917f8efbd7ea Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:38:25 +0900 Subject: [PATCH 13/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a5f81203..779842c3b 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - [ ] 숫자가 아닐 경우 - [ ] 공백일 경우 - **출력** - - [ ] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. + - [x] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - [ ] 당첨 내역을 출력한다. - [ ] 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%) - [ ] **예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.** From 13f311ca244923549a731340021f10f56b1ad876 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 19:41:12 +0900 Subject: [PATCH 14/59] =?UTF-8?q?fix:=20=EB=A1=9C=EB=98=90=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=20=EB=B0=9C=ED=96=89=20=EC=8B=9C=EC=9E=91=20=EB=B2=94?= =?UTF-8?q?=EC=9C=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 로또 숫자 발행 시작 범위 0으로 잘못 명시 되어 있어서 1로 수정 --- src/main/kotlin/lotto/LottoGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/lotto/LottoGenerator.kt b/src/main/kotlin/lotto/LottoGenerator.kt index c1e936cd4..de711fd61 100644 --- a/src/main/kotlin/lotto/LottoGenerator.kt +++ b/src/main/kotlin/lotto/LottoGenerator.kt @@ -26,7 +26,7 @@ class LottoGenerator(private val purchasePrice: Int) { } companion object { - private const val START_NUMBER = 0 + private const val START_NUMBER = 1 private const val END_NUMBER = 45 private const val PICK_COUNT = 6 } From d958ddb6ececdba79bdb85f600c6e7d383a685a9 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 22:02:49 +0900 Subject: [PATCH 15/59] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8,=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=9E=85=EB=A0=A5=20=EB=B0=9B=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 당첨 번호, 보너스 번호를 입력만 받아 놓은 상태 --- src/main/kotlin/lotto/Application.kt | 6 ++++++ src/main/kotlin/lotto/util/LottoConstants.kt | 1 + src/main/kotlin/lotto/util/LottoOutputText.kt | 1 + 3 files changed, 8 insertions(+) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 563b2a6e4..5438709e4 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -1,6 +1,7 @@ package lotto import camp.nextstep.edu.missionutils.Console +import lotto.util.LottoConstants import lotto.util.LottoOutputText fun main() { @@ -16,4 +17,9 @@ fun main() { lottoList.forEach { lotto -> println(lotto.getSortedNumbers()) } + + println(LottoOutputText.INPUT_WINNING_NUMBERS) + val winningNumbers = Console.readLine().split(LottoConstants.WINNING_NUMBERS_DELIMITER) + val trimBonusNumber = Console.readLine().trim() // TODO: 입력 예외 처리 필요 + val bonusNumber = trimBonusNumber.toInt() } diff --git a/src/main/kotlin/lotto/util/LottoConstants.kt b/src/main/kotlin/lotto/util/LottoConstants.kt index 0b1d705cc..ba3afa2a2 100644 --- a/src/main/kotlin/lotto/util/LottoConstants.kt +++ b/src/main/kotlin/lotto/util/LottoConstants.kt @@ -2,4 +2,5 @@ package lotto.util object LottoConstants { const val PRICE = 1000 + const val WINNING_NUMBERS_DELIMITER = "," } \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/util/LottoOutputText.kt index 29bea9d37..7cc38b2dc 100644 --- a/src/main/kotlin/lotto/util/LottoOutputText.kt +++ b/src/main/kotlin/lotto/util/LottoOutputText.kt @@ -3,4 +3,5 @@ package lotto.util object LottoOutputText { const val INPUT_PURCHASE_PRICE_TEXT = "구입금액을 입력해 주세요." const val LOTTO_GENERATE_FINISH_TEXT = "개 구매했습니다." + const val INPUT_WINNING_NUMBERS = "당첨 번호를 입력해 주세요." } \ No newline at end of file From f432db74ec228afec165aacfabfbfed0f83f3654 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 22:03:16 +0900 Subject: [PATCH 16/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 779842c3b..e6dba0986 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ - **입출력 기능** - **입력** - [x] 로또 구입 금액을 1,000원 단위로 입력받는다 - - [ ] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. - - [ ] 보너스 번호를 입력 받는다. + - [x] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. + - [x] 보너스 번호를 입력 받는다. - **입력 예외 처리** - [x] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 - [x] 구입 금액이 1,000원 보다 적은 금액일 경우 From 6021e915ebc02c513f3e0da189691bc73be61655 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 22:11:32 +0900 Subject: [PATCH 17/59] =?UTF-8?q?docs:=20README.md=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 입력 예외 처리와 입력 공통 예외 처리를 분리 - 입력 예외 처리에 몇 가지 항목 추가 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e6dba0986..2b12a6ab2 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ - **입력 예외 처리** - [x] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 - [x] 구입 금액이 1,000원 보다 적은 금액일 경우 + - [ ] 당첨 번호가 쉼표로 구분되어 있지 않은 경우 + - [ ] 당첨 번호가 중복되는 경우 + - [ ] 보너스 번호가 당첨 번호와 중복되는 경우 + - **입력 공통 예외 처리** - [ ] 숫자가 아닐 경우 - [ ] 공백일 경우 - **출력** From 8a17141ec6ad56dedd6cc948b061271ee971820e Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 22:21:58 +0900 Subject: [PATCH 18/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 당첨 내역과 수익률 기능을 분리하여 작성 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b12a6ab2..7125f8719 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ - 5등: 3개 번호 일치 / 5,000원 - [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - [x] 로또 1장의 가격은 1,000원이다. - - [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다. + - [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역을 출력 + - [ ] 수익률을 출력하고 로또 게임을 종료한다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From d8661274ffba687d497e2c4188c869dbec7efc7d Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 23:18:04 +0900 Subject: [PATCH 19/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EC=99=80=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8?= =?UTF-8?q?=EB=A5=BC=20=EB=B9=84=EA=B5=90=ED=95=98=EC=97=AC=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 당첨 번호 정수형으로 매핑 - 보너스 번호 입력 텍스트 추가 - 로또 리스트 -> 숫자 리스트로 매핑해주는 메서드 추가 - LottoResult에서 당첨 번호, 보너스 번호를 통해 당첨 카운트 출력 --- src/main/kotlin/lotto/Application.kt | 13 ++++++- src/main/kotlin/lotto/Lotto.kt | 2 + src/main/kotlin/lotto/LottoResult.kt | 37 +++++++++++++++++++ src/main/kotlin/lotto/util/LottoOutputText.kt | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/lotto/LottoResult.kt diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 5438709e4..77160e7ed 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -17,9 +17,20 @@ fun main() { lottoList.forEach { lotto -> println(lotto.getSortedNumbers()) } + println() println(LottoOutputText.INPUT_WINNING_NUMBERS) - val winningNumbers = Console.readLine().split(LottoConstants.WINNING_NUMBERS_DELIMITER) + val winningNumbers = Console.readLine() + .split(LottoConstants.WINNING_NUMBERS_DELIMITER) + .map { it.toInt() } + println() + + println(LottoOutputText.INPUT_BONUS_NUMBER) val trimBonusNumber = Console.readLine().trim() // TODO: 입력 예외 처리 필요 val bonusNumber = trimBonusNumber.toInt() + println() + + val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) + val matchingCount = lottoResult.getMatchingCount() + println(matchingCount) } diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt index 916b9ddbe..b197e99ae 100644 --- a/src/main/kotlin/lotto/Lotto.kt +++ b/src/main/kotlin/lotto/Lotto.kt @@ -7,3 +7,5 @@ class Lotto(private val numbers: List) { fun getSortedNumbers(): List = numbers.sorted() } + +fun List.toNumberList(): List> = this.map { it.getSortedNumbers() } diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt new file mode 100644 index 000000000..a8828ab49 --- /dev/null +++ b/src/main/kotlin/lotto/LottoResult.kt @@ -0,0 +1,37 @@ +package lotto + +class LottoResult( + private val lottoList: List, + private val winningNumbers: List, + private val bonusNumber: Int, +) { + + fun getMatchingCount(): List { + val lottoResults = mutableListOf() + val lottoNumberList = lottoList.toNumberList() + lottoNumberList.forEach { numbers -> + // TODO: 리팩토링 필요 + val intersectCount = numbers.intersect(winningNumbers).size + val bonusCount = numbers.getBonusCount(intersectCount) + val count = intersectCount + bonusCount + lottoResults.add(count) + } + return lottoResults + } + + private fun List.getBonusCount(intersectionCount: Int): Int { + val isContainBonusNumber = this.contains(bonusNumber) + if (isContainBonusNumber && + intersectionCount == FIVE_MATCHES + ) { + return BONUS_NUMBER + } + return NOT_BONUS_NUMBER + } + + companion object { + private const val FIVE_MATCHES = 5 + private const val BONUS_NUMBER = 1 + private const val NOT_BONUS_NUMBER = 0 + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/util/LottoOutputText.kt index 7cc38b2dc..ba754852c 100644 --- a/src/main/kotlin/lotto/util/LottoOutputText.kt +++ b/src/main/kotlin/lotto/util/LottoOutputText.kt @@ -4,4 +4,5 @@ object LottoOutputText { const val INPUT_PURCHASE_PRICE_TEXT = "구입금액을 입력해 주세요." const val LOTTO_GENERATE_FINISH_TEXT = "개 구매했습니다." const val INPUT_WINNING_NUMBERS = "당첨 번호를 입력해 주세요." + const val INPUT_BONUS_NUMBER = "보너스 번호를 입력해 주세요." } \ No newline at end of file From 8e5834a51c5f42402bea959ef10a37b413b40a3b Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 23:20:31 +0900 Subject: [PATCH 20/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7125f8719..bbbdbbea4 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - **로또** - [x] 로또 번호의 숫자 범위는 1~45까지이다. - [x] 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. - - [ ] 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다. + - [x] 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다. - [ ] 당첨은 1등부터 5등까지 있다. - 당첨 기준과 금액 - 1등: 6개 번호 일치 / 2,000,000,000원 From 838045ac1e5fd9886463ca68e1aa718c317abce6 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Thu, 31 Oct 2024 23:25:12 +0900 Subject: [PATCH 21/59] =?UTF-8?q?test:=20Lotto=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 오름차순 정렬 테스트 추가 --- src/test/kotlin/lotto/LottoTest.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/kotlin/lotto/LottoTest.kt b/src/test/kotlin/lotto/LottoTest.kt index 122fae572..7d6c7b0f4 100644 --- a/src/test/kotlin/lotto/LottoTest.kt +++ b/src/test/kotlin/lotto/LottoTest.kt @@ -1,5 +1,6 @@ package lotto +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows @@ -19,5 +20,13 @@ class LottoTest { } } - // TODO: 추가 기능 구현에 따른 테스트 코드 작성 + @Test + fun `로또 번호 오름차순으로 정렬`() { + val testList = listOf(6,5,4,3,2,1) + val lotto = Lotto(testList) + val expectedList = testList.sorted() + val actualList = lotto.getSortedNumbers() + + assertEquals(expectedList, actualList) + } } From 762f891bdeead53d4ae012d5a1e0894cfddcfe19 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 01:53:31 +0900 Subject: [PATCH 22/59] =?UTF-8?q?test:=20LottoGeneratorTest=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/lotto/LottoGeneratorTest.kt | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/kotlin/lotto/LottoGeneratorTest.kt diff --git a/src/test/kotlin/lotto/LottoGeneratorTest.kt b/src/test/kotlin/lotto/LottoGeneratorTest.kt new file mode 100644 index 000000000..1eef6f5df --- /dev/null +++ b/src/test/kotlin/lotto/LottoGeneratorTest.kt @@ -0,0 +1,33 @@ +package lotto + +import lotto.util.LottoConstants +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class LottoGeneratorTest { + @Test + fun `구입 금액이 1,000원 미만이면 예외가 발생한다`() { + assertThrows { + LottoGenerator(500) + } + } + + @Test + fun `구입 금액이 1,000원으로 나누어 떨어지지 않으면 예외가 발생한다`() { + assertThrows { + LottoGenerator(1500) + } + } + + @Test + fun `구입 금액에 따라 정확한 개수의 로또를 반환한다`() { + val purchasePrice = 2000 + val expectedSize = purchasePrice / LottoConstants.PRICE + val lottoGenerator = LottoGenerator(purchasePrice) + val lottoList = lottoGenerator.generate() + val actualSize = lottoList.size + + assertEquals(expectedSize, actualSize) + } +} \ No newline at end of file From 6f115ce62c6cd36188bbce424fb0b18852dfdeb1 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 18:43:58 +0900 Subject: [PATCH 23/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bbbdbbea4..1fcaf1491 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ - 5등: 3개 번호 일치 / 5,000원 - [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - [x] 로또 1장의 가격은 1,000원이다. - - [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역을 출력 + - [ ] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - [ ] 수익률을 출력하고 로또 게임을 종료한다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From d59fee22584386b83840da3b2841543c30d73fdb Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 19:18:26 +0900 Subject: [PATCH 24/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EC=99=80=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8,?= =?UTF-8?q?=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=EC=99=80=20?= =?UTF-8?q?=EB=B9=84=EA=B5=90=ED=95=98=EB=8A=94=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 - LottoCounter를 통해 로또 번호를 당첨 번호와 보너스 번호와 비교 - Lotto 클래스에 numbers 반환하는 메서드 추가 --- src/main/kotlin/lotto/Lotto.kt | 2 ++ src/main/kotlin/lotto/LottoCounter.kt | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/main/kotlin/lotto/LottoCounter.kt diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt index b197e99ae..bf6e7b428 100644 --- a/src/main/kotlin/lotto/Lotto.kt +++ b/src/main/kotlin/lotto/Lotto.kt @@ -5,6 +5,8 @@ class Lotto(private val numbers: List) { require(numbers.size == 6) { "[ERROR] 로또 번호는 6개여야 합니다." } } + fun getNumbers(): List = numbers + fun getSortedNumbers(): List = numbers.sorted() } diff --git a/src/main/kotlin/lotto/LottoCounter.kt b/src/main/kotlin/lotto/LottoCounter.kt new file mode 100644 index 000000000..831b5c0c6 --- /dev/null +++ b/src/main/kotlin/lotto/LottoCounter.kt @@ -0,0 +1,16 @@ +package lotto + +class LottoCounter(private val lotto: Lotto) { + // TODO: 두 개의 리스트가 모두 Set 이라면 intersect 메서드가 더 효율적일 것으로 예상 + fun countWithWinningNumbers(winningNumbers: List): Int { + val lottoNumbers = lotto.getNumbers() + val matchCount = lottoNumbers.count { it in winningNumbers } + return matchCount + } + + fun countWithBonusNumber(bonusNumber: Int): Int { + val lottoNumbers = lotto.getNumbers() + val bonusNumberCount = lottoNumbers.count { it == bonusNumber } + return bonusNumberCount + } +} \ No newline at end of file From c83442d466344ac8489b9ef12cf49dcd8136b90f Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 19:21:08 +0900 Subject: [PATCH 25/59] =?UTF-8?q?refactor:=20LottoCounter=20=EC=99=80=20Lo?= =?UTF-8?q?tto=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LottoCounter는 유틸리티 클래스로서 생성자 파라미터 제거 - Lotto 클래스에서 불필요한 확장함수 제거 --- src/main/kotlin/lotto/Lotto.kt | 2 -- src/main/kotlin/lotto/LottoCounter.kt | 12 +++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt index bf6e7b428..f1f9be762 100644 --- a/src/main/kotlin/lotto/Lotto.kt +++ b/src/main/kotlin/lotto/Lotto.kt @@ -9,5 +9,3 @@ class Lotto(private val numbers: List) { fun getSortedNumbers(): List = numbers.sorted() } - -fun List.toNumberList(): List> = this.map { it.getSortedNumbers() } diff --git a/src/main/kotlin/lotto/LottoCounter.kt b/src/main/kotlin/lotto/LottoCounter.kt index 831b5c0c6..2dbe88f2f 100644 --- a/src/main/kotlin/lotto/LottoCounter.kt +++ b/src/main/kotlin/lotto/LottoCounter.kt @@ -1,14 +1,20 @@ package lotto -class LottoCounter(private val lotto: Lotto) { +class LottoCounter { // TODO: 두 개의 리스트가 모두 Set 이라면 intersect 메서드가 더 효율적일 것으로 예상 - fun countWithWinningNumbers(winningNumbers: List): Int { + fun countWithWinningNumbers( + lotto: Lotto, + winningNumbers: List, + ): Int { val lottoNumbers = lotto.getNumbers() val matchCount = lottoNumbers.count { it in winningNumbers } return matchCount } - fun countWithBonusNumber(bonusNumber: Int): Int { + fun countWithBonusNumber( + lotto: Lotto, + bonusNumber: Int, + ): Int { val lottoNumbers = lotto.getNumbers() val bonusNumberCount = lottoNumbers.count { it == bonusNumber } return bonusNumberCount From 31afe320ef5de53c8bb8f7ad43d5eb9a503ec58a Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 19:21:54 +0900 Subject: [PATCH 26/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fcaf1491..2d67ff92d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ - 5등: 3개 번호 일치 / 5,000원 - [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - [x] 로또 1장의 가격은 1,000원이다. - - [ ] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. + - [x] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - [ ] 수익률을 출력하고 로또 게임을 종료한다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From dd738f3f4dcd5e9db49702054b60ed616d43d909 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 19:34:42 +0900 Subject: [PATCH 27/59] =?UTF-8?q?refactor:=20LottoCounter=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=AA=85=20=EC=88=98=EC=A0=95=20&=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LottoCounter -> LottoMatcher 클래스 명 수정 - LottoMatcher의 countWithBonusNumber -> hasBonusNumber 메서드 명 수정 - hasBonusNumber 로직 수정 --- .../kotlin/lotto/{LottoCounter.kt => LottoMatcher.kt} | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) rename src/main/kotlin/lotto/{LottoCounter.kt => LottoMatcher.kt} (69%) diff --git a/src/main/kotlin/lotto/LottoCounter.kt b/src/main/kotlin/lotto/LottoMatcher.kt similarity index 69% rename from src/main/kotlin/lotto/LottoCounter.kt rename to src/main/kotlin/lotto/LottoMatcher.kt index 2dbe88f2f..1cd937b67 100644 --- a/src/main/kotlin/lotto/LottoCounter.kt +++ b/src/main/kotlin/lotto/LottoMatcher.kt @@ -1,8 +1,8 @@ package lotto -class LottoCounter { +class LottoMatcher { // TODO: 두 개의 리스트가 모두 Set 이라면 intersect 메서드가 더 효율적일 것으로 예상 - fun countWithWinningNumbers( + fun matchWithWinningNumbers( lotto: Lotto, winningNumbers: List, ): Int { @@ -11,12 +11,11 @@ class LottoCounter { return matchCount } - fun countWithBonusNumber( + fun hasBonusNumber( lotto: Lotto, bonusNumber: Int, - ): Int { + ): Boolean { val lottoNumbers = lotto.getNumbers() - val bonusNumberCount = lottoNumbers.count { it == bonusNumber } - return bonusNumberCount + return lottoNumbers.contains(bonusNumber) } } \ No newline at end of file From aaf8b6d7716c41383123e2627cb8b2bf1f680119 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 19:36:41 +0900 Subject: [PATCH 28/59] =?UTF-8?q?test:=20LottoMatcherTest=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/lotto/LottoMatcherTest.kt | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/kotlin/lotto/LottoMatcherTest.kt diff --git a/src/test/kotlin/lotto/LottoMatcherTest.kt b/src/test/kotlin/lotto/LottoMatcherTest.kt new file mode 100644 index 000000000..2c328e16e --- /dev/null +++ b/src/test/kotlin/lotto/LottoMatcherTest.kt @@ -0,0 +1,29 @@ +package lotto + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class LottoMatcherTest { + + private val lottoMatcher = LottoMatcher() + + @Test + fun `로또 번호 당첨 번호와 비교했을 때 3개 일치`() { + val count = lottoMatcher.matchWithWinningNumbers(lottoTestData, winningNumbersTestData) + assertEquals(THREE_MATCHES, count) + } + + @Test + fun `로또 번호에 보너스 번호 포함`() { + val hasBonusNumber = lottoMatcher.hasBonusNumber(lottoTestData, BONUS_NUMBER) + assertEquals(HAS_BONUS_NUMBER, hasBonusNumber) + } + + companion object { + private val lottoTestData = Lotto(listOf(1,2,3,4,5,6)) + private val winningNumbersTestData = listOf(1,2,3,10,11,12) + private const val THREE_MATCHES = 3 + private const val BONUS_NUMBER = 6 + private const val HAS_BONUS_NUMBER = true + } +} \ No newline at end of file From 56aa11d46f2d2e541a30ed0f89b90a9c882cfa9b Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 19:51:40 +0900 Subject: [PATCH 29/59] =?UTF-8?q?refactor:=20LottoMatch=20->=20LottoNumber?= =?UTF-8?q?Matcher=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 클래스 명 수정에 따른 테스트 코드 수정 --- .../lotto/{LottoMatcher.kt => LottoNumberMatcher.kt} | 2 +- .../{LottoMatcherTest.kt => LottoNumberMatcherTest.kt} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/main/kotlin/lotto/{LottoMatcher.kt => LottoNumberMatcher.kt} (95%) rename src/test/kotlin/lotto/{LottoMatcherTest.kt => LottoNumberMatcherTest.kt} (70%) diff --git a/src/main/kotlin/lotto/LottoMatcher.kt b/src/main/kotlin/lotto/LottoNumberMatcher.kt similarity index 95% rename from src/main/kotlin/lotto/LottoMatcher.kt rename to src/main/kotlin/lotto/LottoNumberMatcher.kt index 1cd937b67..44d26852a 100644 --- a/src/main/kotlin/lotto/LottoMatcher.kt +++ b/src/main/kotlin/lotto/LottoNumberMatcher.kt @@ -1,6 +1,6 @@ package lotto -class LottoMatcher { +class LottoNumberMatcher { // TODO: 두 개의 리스트가 모두 Set 이라면 intersect 메서드가 더 효율적일 것으로 예상 fun matchWithWinningNumbers( lotto: Lotto, diff --git a/src/test/kotlin/lotto/LottoMatcherTest.kt b/src/test/kotlin/lotto/LottoNumberMatcherTest.kt similarity index 70% rename from src/test/kotlin/lotto/LottoMatcherTest.kt rename to src/test/kotlin/lotto/LottoNumberMatcherTest.kt index 2c328e16e..386962301 100644 --- a/src/test/kotlin/lotto/LottoMatcherTest.kt +++ b/src/test/kotlin/lotto/LottoNumberMatcherTest.kt @@ -3,19 +3,19 @@ package lotto import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -class LottoMatcherTest { +class LottoNumberMatcherTest { - private val lottoMatcher = LottoMatcher() + private val lottoNumberMatcher = LottoNumberMatcher() @Test fun `로또 번호 당첨 번호와 비교했을 때 3개 일치`() { - val count = lottoMatcher.matchWithWinningNumbers(lottoTestData, winningNumbersTestData) + val count = lottoNumberMatcher.matchWithWinningNumbers(lottoTestData, winningNumbersTestData) assertEquals(THREE_MATCHES, count) } @Test fun `로또 번호에 보너스 번호 포함`() { - val hasBonusNumber = lottoMatcher.hasBonusNumber(lottoTestData, BONUS_NUMBER) + val hasBonusNumber = lottoNumberMatcher.hasBonusNumber(lottoTestData, BONUS_NUMBER) assertEquals(HAS_BONUS_NUMBER, hasBonusNumber) } From 32fb64f218ce784906410c5b34696cc16e38c3cb Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 23:37:34 +0900 Subject: [PATCH 30/59] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EC=99=80=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8,?= =?UTF-8?q?=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=EB=A5=BC=20?= =?UTF-8?q?=EB=B9=84=EA=B5=90=ED=95=98=EC=97=AC=20=EC=88=9C=EC=9C=84?= =?UTF-8?q?=EB=A5=BC=20=EB=A7=A4=EA=B8=B0=EB=8A=94=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 - LottoNumberMatcher 메서드 명 수정 - LottoRank 를 통해 순위 지정 - LottoResult 에서 당첨 통계 계산 (현재는 로또 순위 매기는 기능만 존재) --- src/main/kotlin/lotto/LottoNumberMatcher.kt | 2 +- src/main/kotlin/lotto/LottoRank.kt | 20 ++++++++++ src/main/kotlin/lotto/LottoResult.kt | 39 ++++++++++--------- .../kotlin/lotto/LottoNumberMatcherTest.kt | 2 +- 4 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 src/main/kotlin/lotto/LottoRank.kt diff --git a/src/main/kotlin/lotto/LottoNumberMatcher.kt b/src/main/kotlin/lotto/LottoNumberMatcher.kt index 44d26852a..c1df0e777 100644 --- a/src/main/kotlin/lotto/LottoNumberMatcher.kt +++ b/src/main/kotlin/lotto/LottoNumberMatcher.kt @@ -11,7 +11,7 @@ class LottoNumberMatcher { return matchCount } - fun hasBonusNumber( + fun matchWithBonusNumber( lotto: Lotto, bonusNumber: Int, ): Boolean { diff --git a/src/main/kotlin/lotto/LottoRank.kt b/src/main/kotlin/lotto/LottoRank.kt new file mode 100644 index 000000000..49c7857c1 --- /dev/null +++ b/src/main/kotlin/lotto/LottoRank.kt @@ -0,0 +1,20 @@ +package lotto + +enum class LottoRank(val price: Int) { + NOTHING(0), + THREE_MATCHES(5000), + FOUR_MATCHES(50000), + FIVE_MATCHES(1500000), + FIVE_AND_BONUS_MATCHES(30000000), + SIX_MATCHES(2000000000) +} + +fun Int.toLottoRank(): LottoRank = + when (this) { + 3 -> LottoRank.THREE_MATCHES + 4 -> LottoRank.FOUR_MATCHES + 5 -> LottoRank.FIVE_MATCHES + 55 -> LottoRank.FIVE_AND_BONUS_MATCHES + 6 -> LottoRank.SIX_MATCHES + else -> LottoRank.NOTHING + } \ No newline at end of file diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt index a8828ab49..3e15b9a7f 100644 --- a/src/main/kotlin/lotto/LottoResult.kt +++ b/src/main/kotlin/lotto/LottoResult.kt @@ -5,33 +5,34 @@ class LottoResult( private val winningNumbers: List, private val bonusNumber: Int, ) { + private val lottoMatcher = LottoNumberMatcher() - fun getMatchingCount(): List { - val lottoResults = mutableListOf() - val lottoNumberList = lottoList.toNumberList() - lottoNumberList.forEach { numbers -> - // TODO: 리팩토링 필요 - val intersectCount = numbers.intersect(winningNumbers).size - val bonusCount = numbers.getBonusCount(intersectCount) - val count = intersectCount + bonusCount - lottoResults.add(count) + private fun getLottoRankList(): List { + val lottoRankList = mutableListOf() + lottoList.forEach { lotto -> + val winningCount = lottoMatcher.matchWithWinningNumbers(lotto, winningNumbers) + val hasBonusNumber = hasBonusNumber(winningCount, lotto) + if (hasBonusNumber) { + lottoRankList.add(LottoRank.FIVE_AND_BONUS_MATCHES) + } + val winningLottoRank = winningCount.toLottoRank() + lottoRankList.add(winningLottoRank) } - return lottoResults + return lottoRankList } - private fun List.getBonusCount(intersectionCount: Int): Int { - val isContainBonusNumber = this.contains(bonusNumber) - if (isContainBonusNumber && - intersectionCount == FIVE_MATCHES - ) { - return BONUS_NUMBER + private fun hasBonusNumber( + winningCount: Int, + lotto: Lotto, + ): Boolean { + if (winningCount == FIVE_MATCHES) { + val hasBonusNumber = lottoMatcher.matchWithBonusNumber(lotto, bonusNumber) + return hasBonusNumber } - return NOT_BONUS_NUMBER + return false } companion object { private const val FIVE_MATCHES = 5 - private const val BONUS_NUMBER = 1 - private const val NOT_BONUS_NUMBER = 0 } } \ No newline at end of file diff --git a/src/test/kotlin/lotto/LottoNumberMatcherTest.kt b/src/test/kotlin/lotto/LottoNumberMatcherTest.kt index 386962301..60562248c 100644 --- a/src/test/kotlin/lotto/LottoNumberMatcherTest.kt +++ b/src/test/kotlin/lotto/LottoNumberMatcherTest.kt @@ -15,7 +15,7 @@ class LottoNumberMatcherTest { @Test fun `로또 번호에 보너스 번호 포함`() { - val hasBonusNumber = lottoNumberMatcher.hasBonusNumber(lottoTestData, BONUS_NUMBER) + val hasBonusNumber = lottoNumberMatcher.matchWithBonusNumber(lottoTestData, BONUS_NUMBER) assertEquals(HAS_BONUS_NUMBER, hasBonusNumber) } From cfdbde9964ca767791b83c6ce01a9e0aedfb08a8 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 23:38:11 +0900 Subject: [PATCH 31/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d67ff92d..08d4b6e35 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ - [x] 로또 번호의 숫자 범위는 1~45까지이다. - [x] 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. - [x] 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다. - - [ ] 당첨은 1등부터 5등까지 있다. + - [x] 당첨은 1등부터 5등까지 있다. - 당첨 기준과 금액 - 1등: 6개 번호 일치 / 2,000,000,000원 - 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원 From 4d32272fe14c773f491f782fa54ec01ab4f5dea6 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Fri, 1 Nov 2024 23:41:01 +0900 Subject: [PATCH 32/59] =?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=ED=9B=84=20=EB=8B=B9=EC=B2=A8=20=ED=86=B5?= =?UTF-8?q?=EA=B3=84=20=EB=82=B4=EB=8A=94=20=EA=B8=B0=EB=8A=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 - LottoResult 에서 수익률 계산하는 기능 추가 - 당첨 통계 내역을 가지고 있는 데이터 클래스 LottoResultDetail 추가 --- src/main/kotlin/lotto/LottoResult.kt | 18 ++++++++++++++++++ src/main/kotlin/lotto/LottoResultDetail.kt | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 src/main/kotlin/lotto/LottoResultDetail.kt diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt index 3e15b9a7f..2d35b56e4 100644 --- a/src/main/kotlin/lotto/LottoResult.kt +++ b/src/main/kotlin/lotto/LottoResult.kt @@ -1,5 +1,7 @@ package lotto +import lotto.util.LottoConstants + class LottoResult( private val lottoList: List, private val winningNumbers: List, @@ -7,6 +9,13 @@ class LottoResult( ) { private val lottoMatcher = LottoNumberMatcher() + fun getResult(): LottoResultDetail { + val lottoRankList = getLottoRankList() + val rateOfReturn = getRateOfReturn(lottoRankList) + val lottoResultDetail = LottoResultDetail(lottoRankList, rateOfReturn) + return lottoResultDetail + } + private fun getLottoRankList(): List { val lottoRankList = mutableListOf() lottoList.forEach { lotto -> @@ -32,7 +41,16 @@ class LottoResult( return false } + private fun getRateOfReturn(lottoRankList: List): Float { + // (최종 수익 / 구입 금액) * 100 + val purchasePrice = lottoList.size * LottoConstants.PRICE + val finalProfit = lottoRankList.sumOf { it.price } + val rateOfReturn = (finalProfit / purchasePrice).toFloat() * PERCENTAGE_MULTIPLIER + return rateOfReturn + } + companion object { private const val FIVE_MATCHES = 5 + private const val PERCENTAGE_MULTIPLIER = 100 } } \ No newline at end of file diff --git a/src/main/kotlin/lotto/LottoResultDetail.kt b/src/main/kotlin/lotto/LottoResultDetail.kt new file mode 100644 index 000000000..912750c0c --- /dev/null +++ b/src/main/kotlin/lotto/LottoResultDetail.kt @@ -0,0 +1,6 @@ +package lotto + +data class LottoResultDetail( + val lottoRankList: List, + val rateOfReturn: Float +) From 6ce2cca2b085e726336e897cc61c49b4611e9e75 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Sat, 2 Nov 2024 19:35:35 +0900 Subject: [PATCH 33/59] =?UTF-8?q?refactor:=20=EC=88=98=EC=9D=B5=EB=A5=A0?= =?UTF-8?q?=20=EA=B3=84=EC=82=B0=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 - 수익률 소수점 둘째 자리에서 반올림 - 수익률 Double 로 수정 - LottoResultDetail에 소수점 둘째자리에서 반올림한 수익률 프로퍼티 추가 (Application 에서 임시 출력 코드 추가) --- src/main/kotlin/lotto/Application.kt | 5 +++-- src/main/kotlin/lotto/LottoResult.kt | 6 +++--- src/main/kotlin/lotto/LottoResultDetail.kt | 7 +++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 77160e7ed..4233580d5 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -31,6 +31,7 @@ fun main() { println() val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) - val matchingCount = lottoResult.getMatchingCount() - println(matchingCount) + val lottoResultDetail = lottoResult.getResult() + println("lottoResultDetail.lottoRankList: ${lottoResultDetail.lottoRankList}") + println("lottoResultDetail.rateOfReturn: ${lottoResultDetail.roundedRateOfReturn}") } diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt index 2d35b56e4..227aefa5e 100644 --- a/src/main/kotlin/lotto/LottoResult.kt +++ b/src/main/kotlin/lotto/LottoResult.kt @@ -41,11 +41,11 @@ class LottoResult( return false } - private fun getRateOfReturn(lottoRankList: List): Float { - // (최종 수익 / 구입 금액) * 100 + // 최종 수익률: (최종 수익 / 구입 금액) * 100 + private fun getRateOfReturn(lottoRankList: List): Double { val purchasePrice = lottoList.size * LottoConstants.PRICE val finalProfit = lottoRankList.sumOf { it.price } - val rateOfReturn = (finalProfit / purchasePrice).toFloat() * PERCENTAGE_MULTIPLIER + val rateOfReturn = (finalProfit / purchasePrice).toDouble() * PERCENTAGE_MULTIPLIER return rateOfReturn } diff --git a/src/main/kotlin/lotto/LottoResultDetail.kt b/src/main/kotlin/lotto/LottoResultDetail.kt index 912750c0c..fa15281ab 100644 --- a/src/main/kotlin/lotto/LottoResultDetail.kt +++ b/src/main/kotlin/lotto/LottoResultDetail.kt @@ -2,5 +2,8 @@ package lotto data class LottoResultDetail( val lottoRankList: List, - val rateOfReturn: Float -) + val rateOfReturn: Double +) { + val roundedRateOfReturn: String + get() = String.format("%.1f", rateOfReturn) +} From f54b13178197a1f7ef270e625a72f3facaf5ce21 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Sat, 2 Nov 2024 19:49:54 +0900 Subject: [PATCH 34/59] =?UTF-8?q?test:=20LottoResultTest=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/lotto/LottoResultTest.kt | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/kotlin/lotto/LottoResultTest.kt diff --git a/src/test/kotlin/lotto/LottoResultTest.kt b/src/test/kotlin/lotto/LottoResultTest.kt new file mode 100644 index 000000000..4eb94bf6b --- /dev/null +++ b/src/test/kotlin/lotto/LottoResultTest.kt @@ -0,0 +1,34 @@ +package lotto + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class LottoResultTest { + + private lateinit var lottoResult: LottoResult + private lateinit var expectedLottoList: List + private lateinit var expectedWinningNumbers: List + private lateinit var expectedLottoRankList: List + private var expectedRateOfReturn: Double = 0.0 + + @BeforeEach + fun setUp() { + expectedLottoList = listOf(Lotto(listOf(1,2,3,4,5,6))) + expectedWinningNumbers = listOf(1,2,3,30,31,32) + expectedLottoRankList = listOf(LottoRank.THREE_MATCHES) + expectedRateOfReturn = (LottoRank.THREE_MATCHES.price / 1000).toDouble() * 100 + lottoResult = LottoResult(expectedLottoList, expectedWinningNumbers, BONUS_NUMBER) + } + + @Test + fun `로또 당첨 통계 테스트`() { + val actual = lottoResult.getResult() + assertEquals(expectedRateOfReturn, actual.rateOfReturn) + assertEquals(expectedLottoRankList, actual.lottoRankList) + } + + companion object { + private const val BONUS_NUMBER = 35 + } +} \ No newline at end of file From 6bcb6f9b868bc967fe35e29e2fcad5f67b7b8cea Mon Sep 17 00:00:00 2001 From: DDangDin Date: Sat, 2 Nov 2024 23:17:19 +0900 Subject: [PATCH 35/59] =?UTF-8?q?fix:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EC=99=80=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EB=B9=84=EA=B5=90=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 - getLottoLank 메서드 추가 - 보너스 번호가 포함되어 있을 때 확실하게 처리하도록 수정 --- src/main/kotlin/lotto/LottoResult.kt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt index 227aefa5e..842a6f855 100644 --- a/src/main/kotlin/lotto/LottoResult.kt +++ b/src/main/kotlin/lotto/LottoResult.kt @@ -21,15 +21,23 @@ class LottoResult( lottoList.forEach { lotto -> val winningCount = lottoMatcher.matchWithWinningNumbers(lotto, winningNumbers) val hasBonusNumber = hasBonusNumber(winningCount, lotto) - if (hasBonusNumber) { - lottoRankList.add(LottoRank.FIVE_AND_BONUS_MATCHES) - } - val winningLottoRank = winningCount.toLottoRank() - lottoRankList.add(winningLottoRank) + val lottoLank = getLottoLank(winningCount, hasBonusNumber) + lottoRankList.add(lottoLank) } return lottoRankList } + private fun getLottoLank( + winningCount: Int, + hasBonusNumber: Boolean, + ): LottoRank { + if (hasBonusNumber) { + return LottoRank.FIVE_AND_BONUS_MATCHES + } + val winningLottoRank = winningCount.toLottoRank() + return winningLottoRank + } + private fun hasBonusNumber( winningCount: Int, lotto: Lotto, From 6f09c2653e6d96143baf1166ab5f44ba962fdd78 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Sat, 2 Nov 2024 23:17:50 +0900 Subject: [PATCH 36/59] =?UTF-8?q?test:=20LottoResultTest=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LottoResult 수정에 따른 테스트 코드 수정 --- src/test/kotlin/lotto/LottoResultTest.kt | 31 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/test/kotlin/lotto/LottoResultTest.kt b/src/test/kotlin/lotto/LottoResultTest.kt index 4eb94bf6b..7fe5c2923 100644 --- a/src/test/kotlin/lotto/LottoResultTest.kt +++ b/src/test/kotlin/lotto/LottoResultTest.kt @@ -8,27 +8,44 @@ class LottoResultTest { private lateinit var lottoResult: LottoResult private lateinit var expectedLottoList: List - private lateinit var expectedWinningNumbers: List + private lateinit var expectedWinningNumbersWithThreeMatches: List + private lateinit var expectedWinningNumbersWithBonusNumber: List private lateinit var expectedLottoRankList: List private var expectedRateOfReturn: Double = 0.0 @BeforeEach fun setUp() { - expectedLottoList = listOf(Lotto(listOf(1,2,3,4,5,6))) - expectedWinningNumbers = listOf(1,2,3,30,31,32) - expectedLottoRankList = listOf(LottoRank.THREE_MATCHES) + expectedLottoList = listOf(Lotto(listOf(1, 2, 3, 4, 5, 6))) + expectedWinningNumbersWithThreeMatches = listOf(1, 2, 3, 30, 31, 32) + expectedWinningNumbersWithBonusNumber = listOf(1, 2, 3, 4, 5, 10) + } + + @Test + fun `로또번호와 당첨번호 비교 후 당첨 통계 테스트`() { + lottoResult = LottoResult(expectedLottoList, expectedWinningNumbersWithThreeMatches, BONUS_NUMBER) expectedRateOfReturn = (LottoRank.THREE_MATCHES.price / 1000).toDouble() * 100 - lottoResult = LottoResult(expectedLottoList, expectedWinningNumbers, BONUS_NUMBER) + expectedLottoRankList = listOf(LottoRank.THREE_MATCHES) + + val actual = lottoResult.getResult() + + assertEquals(expectedRateOfReturn, actual.rateOfReturn) + assertEquals(expectedLottoRankList, actual.lottoRankList) } @Test - fun `로또 당첨 통계 테스트`() { + fun `로또번호와 보너스 번호 당첨 통계 테스트`() { + lottoResult = + LottoResult(expectedLottoList, expectedWinningNumbersWithBonusNumber, BONUS_NUMBER) + expectedRateOfReturn = (LottoRank.FIVE_AND_BONUS_MATCHES.price / 1000).toDouble() * 100 + expectedLottoRankList = listOf(LottoRank.FIVE_AND_BONUS_MATCHES) + val actual = lottoResult.getResult() + assertEquals(expectedRateOfReturn, actual.rateOfReturn) assertEquals(expectedLottoRankList, actual.lottoRankList) } companion object { - private const val BONUS_NUMBER = 35 + private const val BONUS_NUMBER = 6 } } \ No newline at end of file From 919cff1461574da7135d7378142f40f04e65931d Mon Sep 17 00:00:00 2001 From: DDangDin Date: Sat, 2 Nov 2024 23:18:35 +0900 Subject: [PATCH 37/59] =?UTF-8?q?test:=20LottoResultTest=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/lotto/LottoResultTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/kotlin/lotto/LottoResultTest.kt b/src/test/kotlin/lotto/LottoResultTest.kt index 7fe5c2923..235209a3d 100644 --- a/src/test/kotlin/lotto/LottoResultTest.kt +++ b/src/test/kotlin/lotto/LottoResultTest.kt @@ -21,7 +21,7 @@ class LottoResultTest { } @Test - fun `로또번호와 당첨번호 비교 후 당첨 통계 테스트`() { + fun `로또 번호와 당첨 번호 비교 후 당첨 통계 테스트`() { lottoResult = LottoResult(expectedLottoList, expectedWinningNumbersWithThreeMatches, BONUS_NUMBER) expectedRateOfReturn = (LottoRank.THREE_MATCHES.price / 1000).toDouble() * 100 expectedLottoRankList = listOf(LottoRank.THREE_MATCHES) @@ -33,7 +33,7 @@ class LottoResultTest { } @Test - fun `로또번호와 보너스 번호 당첨 통계 테스트`() { + fun `로또 번호와 보너스 번호 당첨 통계 테스트`() { lottoResult = LottoResult(expectedLottoList, expectedWinningNumbersWithBonusNumber, BONUS_NUMBER) expectedRateOfReturn = (LottoRank.FIVE_AND_BONUS_MATCHES.price / 1000).toDouble() * 100 From b0e9584e50459258ad389639290505aa47f26b09 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Sat, 2 Nov 2024 23:31:28 +0900 Subject: [PATCH 38/59] =?UTF-8?q?refactor:=20LottoResult=20=EC=88=98?= =?UTF-8?q?=EC=9D=B5=EB=A5=A0=20=EC=88=98=EC=A0=95=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=ED=99=95=EC=9E=A5=ED=95=A8=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 수익률 수식 아주 약간 변경 - 반올림 하는 확장함수 추가 --- src/main/kotlin/lotto/LottoResult.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt index 842a6f855..8b5516086 100644 --- a/src/main/kotlin/lotto/LottoResult.kt +++ b/src/main/kotlin/lotto/LottoResult.kt @@ -53,12 +53,14 @@ class LottoResult( private fun getRateOfReturn(lottoRankList: List): Double { val purchasePrice = lottoList.size * LottoConstants.PRICE val finalProfit = lottoRankList.sumOf { it.price } - val rateOfReturn = (finalProfit / purchasePrice).toDouble() * PERCENTAGE_MULTIPLIER + val rateOfReturn = + ((finalProfit.toDouble() / purchasePrice) * PERCENTAGE_MULTIPLIER).round(2) return rateOfReturn } companion object { private const val FIVE_MATCHES = 5 private const val PERCENTAGE_MULTIPLIER = 100 + private fun Double.round(decimals: Int): Double = "%.${decimals}f".format(this).toDouble() } } \ No newline at end of file From 92c3db4cccb0ba3a8c2ceafb57ac71345c0e5f06 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 16:27:39 +0900 Subject: [PATCH 39/59] =?UTF-8?q?docs:=20README.md=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 | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 08d4b6e35..f29bb6d88 100644 --- a/README.md +++ b/README.md @@ -43,5 +43,6 @@ - [x] 로또 1장의 가격은 1,000원이다. - [x] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - [ ] 수익률을 출력하고 로또 게임을 종료한다. + - [ ] 입력 부분에서 예외가 발생해도 예외 출력 후 계속해서 입력을 받는다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From 5250349b58e40f5cbd02cbadccba48b40ef24451 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 16:31:48 +0900 Subject: [PATCH 40/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f29bb6d88..bc3dbb129 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ - **출력** - [x] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - [ ] 당첨 내역을 출력한다. - - [ ] 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%) - [ ] **예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.** + - [ ] 수익률을 출력하고 로또 게임을 종료한다. 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%)
@@ -42,7 +42,7 @@ - [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - [x] 로또 1장의 가격은 1,000원이다. - [x] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - - [ ] 수익률을 출력하고 로또 게임을 종료한다. + - [ ] 당첨 내역을 출력할 때 금액을 천 단위 당 쉼표로 구분한다. - [ ] 입력 부분에서 예외가 발생해도 예외 출력 후 계속해서 입력을 받는다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From 394143c551eac078ee22a41147ca155e4860609d Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 17:22:26 +0900 Subject: [PATCH 41/59] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=EA=B3=BC=20=EC=88=98=EC=9D=B5=EB=A5=A0=EC=9D=84=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 당첨 내역을 출력하는 기능 추가 - 수익률을 출력하는 기능 추가 - 당첨 내역 출력 시 금액을 천단위 쉼표로 구분하는 확장함수 추가 - LottoRank를 출력용 문자열로 바꿔주는 함수 추가 --- src/main/kotlin/lotto/Application.kt | 11 ++++++-- src/main/kotlin/lotto/LottoRank.kt | 27 ++++++++++++++++--- src/main/kotlin/lotto/util/LottoOutputText.kt | 6 +++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 4233580d5..eb122656e 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -32,6 +32,13 @@ fun main() { val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) val lottoResultDetail = lottoResult.getResult() - println("lottoResultDetail.lottoRankList: ${lottoResultDetail.lottoRankList}") - println("lottoResultDetail.rateOfReturn: ${lottoResultDetail.roundedRateOfReturn}") + println("당첨 통계") + println("---") + LottoRank.entries.forEach { rank-> + if (rank != LottoRank.NOTHING) { + val rankCount = lottoResultDetail.lottoRankList.count { it == rank } + println("${rank.print()} - ${rankCount}개") + } + } + println("총 수익률은 ${lottoResultDetail.roundedRateOfReturn}%입니다.") } diff --git a/src/main/kotlin/lotto/LottoRank.kt b/src/main/kotlin/lotto/LottoRank.kt index 49c7857c1..9a6c33880 100644 --- a/src/main/kotlin/lotto/LottoRank.kt +++ b/src/main/kotlin/lotto/LottoRank.kt @@ -1,12 +1,32 @@ package lotto +import lotto.util.LottoOutputText +import java.text.DecimalFormat + enum class LottoRank(val price: Int) { NOTHING(0), THREE_MATCHES(5000), FOUR_MATCHES(50000), FIVE_MATCHES(1500000), FIVE_AND_BONUS_MATCHES(30000000), - SIX_MATCHES(2000000000) + SIX_MATCHES(2000000000); + + fun print(): String = "${this.toDisplayName()} (${this.price.formatCurrency()})" + + private fun toDisplayName(): String = + when (this) { + THREE_MATCHES -> LottoOutputText.THREE_MATCHES + FOUR_MATCHES -> LottoOutputText.FOUR_MATCHES + FIVE_MATCHES -> LottoOutputText.FIVE_MATCHES + FIVE_AND_BONUS_MATCHES -> LottoOutputText.FIVE_AND_BONUS_MATCHES + SIX_MATCHES -> LottoOutputText.SIX_MATCHES + NOTHING -> LottoOutputText.EMPTY + } + + private fun Int.formatCurrency(): String { + val decimalFormat = DecimalFormat(THOUSAND_COMMA) + return decimalFormat.format(this) + } } fun Int.toLottoRank(): LottoRank = @@ -14,7 +34,8 @@ fun Int.toLottoRank(): LottoRank = 3 -> LottoRank.THREE_MATCHES 4 -> LottoRank.FOUR_MATCHES 5 -> LottoRank.FIVE_MATCHES - 55 -> LottoRank.FIVE_AND_BONUS_MATCHES 6 -> LottoRank.SIX_MATCHES else -> LottoRank.NOTHING - } \ No newline at end of file + } + +private const val THOUSAND_COMMA = "#,###" \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/util/LottoOutputText.kt index ba754852c..d3e5aa1d2 100644 --- a/src/main/kotlin/lotto/util/LottoOutputText.kt +++ b/src/main/kotlin/lotto/util/LottoOutputText.kt @@ -5,4 +5,10 @@ object LottoOutputText { const val LOTTO_GENERATE_FINISH_TEXT = "개 구매했습니다." const val INPUT_WINNING_NUMBERS = "당첨 번호를 입력해 주세요." const val INPUT_BONUS_NUMBER = "보너스 번호를 입력해 주세요." + const val THREE_MATCHES = "3개 일치" + const val FOUR_MATCHES = "4개 일치" + const val FIVE_MATCHES = "5개 일치" + const val FIVE_AND_BONUS_MATCHES = "5개 일치, 보너스 볼 일치" + const val SIX_MATCHES = "6개 일치" + const val EMPTY = "" } \ No newline at end of file From fbef5716613f61c06b019d07a9cfe249e34e84a0 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 17:22:50 +0900 Subject: [PATCH 42/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc3dbb129..fc3a17cf6 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ - [ ] 공백일 경우 - **출력** - [x] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - - [ ] 당첨 내역을 출력한다. + - [x] 당첨 내역을 출력한다. - [ ] **예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.** - - [ ] 수익률을 출력하고 로또 게임을 종료한다. 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%) + - [x] 수익률을 출력하고 로또 게임을 종료한다. 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%)
@@ -42,7 +42,7 @@ - [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. - [x] 로또 1장의 가격은 1,000원이다. - [x] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - - [ ] 당첨 내역을 출력할 때 금액을 천 단위 당 쉼표로 구분한다. + - [x] 당첨 내역을 출력할 때 금액을 천 단위 당 쉼표로 구분한다. - [ ] 입력 부분에서 예외가 발생해도 예외 출력 후 계속해서 입력을 받는다. - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. From 6b2714e01ee5cc8d7bd94b95dc17c75a5534d7eb Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 17:40:36 +0900 Subject: [PATCH 43/59] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=B5=9C=EC=86=8C,=20=EC=B5=9C=EB=8C=80=20=EB=B2=88=ED=98=B8?= =?UTF-8?q?=20=EC=83=81=EC=88=98=20=EA=B0=92=EC=9D=84=20LottoConstants?= =?UTF-8?q?=EC=97=90=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효성 검사를 위해서 로또 최소, 최대 번호 상수 값을 전역적으로 관리 --- src/main/kotlin/lotto/LottoGenerator.kt | 8 +++++--- src/main/kotlin/lotto/util/LottoConstants.kt | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/lotto/LottoGenerator.kt b/src/main/kotlin/lotto/LottoGenerator.kt index de711fd61..5635b0b83 100644 --- a/src/main/kotlin/lotto/LottoGenerator.kt +++ b/src/main/kotlin/lotto/LottoGenerator.kt @@ -21,13 +21,15 @@ class LottoGenerator(private val purchasePrice: Int) { private fun getLottoCount(): Int = purchasePrice / LottoConstants.PRICE private fun generateOneLotto(): Lotto { - val randomUniqueNumbers = pickUniqueNumbersInRange(START_NUMBER, END_NUMBER, PICK_COUNT) + val randomUniqueNumbers = pickUniqueNumbersInRange( + LottoConstants.MIN_NUMBER, + LottoConstants.MAX_NUMBER, + PICK_COUNT + ) return Lotto(randomUniqueNumbers) } companion object { - private const val START_NUMBER = 1 - private const val END_NUMBER = 45 private const val PICK_COUNT = 6 } } \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/LottoConstants.kt b/src/main/kotlin/lotto/util/LottoConstants.kt index ba3afa2a2..2bd46264b 100644 --- a/src/main/kotlin/lotto/util/LottoConstants.kt +++ b/src/main/kotlin/lotto/util/LottoConstants.kt @@ -3,4 +3,6 @@ package lotto.util object LottoConstants { const val PRICE = 1000 const val WINNING_NUMBERS_DELIMITER = "," + const val MIN_NUMBER = 1 + const val MAX_NUMBER = 45 } \ No newline at end of file From ddddedbe3fae5dd84d34a26b48e7adfb50e2a72b Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 17:49:27 +0900 Subject: [PATCH 44/59] =?UTF-8?q?feat:=20Lotto=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 중복되는 숫자가 없는지 검사 - 로또 최대 번호인 45를 초과하는 번호가 없는지 검사 --- src/main/kotlin/lotto/Lotto.kt | 7 ++++++- src/main/kotlin/lotto/util/ErrorMessage.kt | 6 +++++- src/main/kotlin/lotto/util/Validator.kt | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/lotto/util/Validator.kt diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt index f1f9be762..5265784a5 100644 --- a/src/main/kotlin/lotto/Lotto.kt +++ b/src/main/kotlin/lotto/Lotto.kt @@ -1,8 +1,13 @@ package lotto +import lotto.util.ErrorMessage +import lotto.util.Validator + class Lotto(private val numbers: List) { init { - require(numbers.size == 6) { "[ERROR] 로또 번호는 6개여야 합니다." } + require(numbers.size == 6) { ErrorMessage.LOTTO_NUMBERS_MUST_SIX_LETTERS.getMessage() } + require(Validator.isUniqueNumbers(numbers)) { ErrorMessage.LOTTO_NUMBERS_MUST_UNIQUE.getMessage() } + require(Validator.validateNumberLimit(numbers)) { ErrorMessage.LOTTO_NUMBER_EXCEEDS_MAX.getMessage() } } fun getNumbers(): List = numbers diff --git a/src/main/kotlin/lotto/util/ErrorMessage.kt b/src/main/kotlin/lotto/util/ErrorMessage.kt index e416a7502..a50e3e76d 100644 --- a/src/main/kotlin/lotto/util/ErrorMessage.kt +++ b/src/main/kotlin/lotto/util/ErrorMessage.kt @@ -4,7 +4,11 @@ enum class ErrorMessage(private val message: String) { PURCHASE_PRICE_MORE_THAN_THOUSAND("구입 금액은 최소 1,000원 부터 입니다."), INVALID_PURCHASE_PRICE("구입 금액은 1,000원 단위 입니다."), PURCHASE_PRICE_MUST_BE_NUMBER("구입 금액은 숫자만 입력 가능 합니다."), - PURCHASE_PRICE_EMPTY("구입 금액은 비어있을 수 없습니다."); + PURCHASE_PRICE_EMPTY("구입 금액은 비어있을 수 없습니다."), + LOTTO_NUMBERS_MUST_SIX_LETTERS("로또 번호는 6개여야 합니다."), + LOTTO_NUMBERS_MUST_UNIQUE("로또 번호는 중복 되면 안됩니다."), + LOTTO_NUMBER_EXCEEDS_MAX("로또 번호는 45보다 클 수 없습니다."), + INPUT_VALUE_MUST_NUMBER("입력 값은 숫자 여야 합니다."); fun getMessage(): String = "[ERROR] $message" } \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/Validator.kt b/src/main/kotlin/lotto/util/Validator.kt new file mode 100644 index 000000000..f35bb24ae --- /dev/null +++ b/src/main/kotlin/lotto/util/Validator.kt @@ -0,0 +1,20 @@ +package lotto.util + +object Validator { + /** 숫자 리스트에서 중복이 없는지 검사 한다. */ + fun isUniqueNumbers(numbers: List): Boolean { + val uniqueNumbers = numbers.toSet() + val isUnique = uniqueNumbers.size == numbers.size + return isUnique + } + + /** 로또 최대 번호를 초과 하는지 검사 한다. */ + fun validateNumberLimit(numbers: List): Boolean { + numbers.forEach { number -> + if (number > LottoConstants.MAX_NUMBER) { + return false + } + } + return true + } +} \ No newline at end of file From a01a6135dde05fe41607b38ea787893587f0ef95 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 17:49:56 +0900 Subject: [PATCH 45/59] =?UTF-8?q?test:=20LottoTest=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/lotto/LottoTest.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/kotlin/lotto/LottoTest.kt b/src/test/kotlin/lotto/LottoTest.kt index 7d6c7b0f4..fc29111b3 100644 --- a/src/test/kotlin/lotto/LottoTest.kt +++ b/src/test/kotlin/lotto/LottoTest.kt @@ -12,7 +12,6 @@ class LottoTest { } } - // TODO: 테스트가 통과하도록 프로덕션 코드 구현 @Test fun `로또 번호에 중복된 숫자가 있으면 예외가 발생한다`() { assertThrows { @@ -21,7 +20,14 @@ class LottoTest { } @Test - fun `로또 번호 오름차순으로 정렬`() { + fun `로또 번호가 최대 번호인 45를 초과하면 예외가 발생한다`() { + assertThrows { + Lotto(listOf(1, 2, 3, 4, 5, 46)) + } + } + + @Test + fun `로또 번호가 오름차순으로 올바르게 정렬 됐는지 테스트`() { val testList = listOf(6,5,4,3,2,1) val lotto = Lotto(testList) val expectedList = testList.sorted() From 5795d35d2b3ab903f8336dbf70731c83feca2115 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 17:53:10 +0900 Subject: [PATCH 46/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20&=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 로또 예외 처리 영역 생성 - 로또 예외 처리 추가 - 완료된 예외 처리 진행상황 업데이트 --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fc3a17cf6..c97516cea 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ - [x] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 - [x] 구입 금액이 1,000원 보다 적은 금액일 경우 - [ ] 당첨 번호가 쉼표로 구분되어 있지 않은 경우 - - [ ] 당첨 번호가 중복되는 경우 + - [x] 당첨 번호가 중복되는 경우 - [ ] 보너스 번호가 당첨 번호와 중복되는 경우 - **입력 공통 예외 처리** - [ ] 숫자가 아닐 경우 @@ -23,7 +23,7 @@ - **출력** - [x] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - [x] 당첨 내역을 출력한다. - - [ ] **예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.** + - [x] **예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.** - [x] 수익률을 출력하고 로또 게임을 종료한다. 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%)
@@ -44,5 +44,8 @@ - [x] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - [x] 당첨 내역을 출력할 때 금액을 천 단위 당 쉼표로 구분한다. - [ ] 입력 부분에서 예외가 발생해도 예외 출력 후 계속해서 입력을 받는다. - - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. + +- **로또 예외 처리** + - [x] 로또 번호는 최대 번호인 45를 초과하면 예외가 발생한다. + - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. + - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. \ No newline at end of file From 35c650c28973ff2333435394303e08cfdbe8914a Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 18:39:51 +0900 Subject: [PATCH 47/59] =?UTF-8?q?refactor:=20MVC=20=ED=8C=A8=ED=84=B4?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MVC 구조 생성 --- src/main/kotlin/lotto/Application.kt | 3 +++ src/main/kotlin/lotto/controller/LottoController.kt | 3 +++ src/main/kotlin/lotto/{ => model}/Lotto.kt | 2 +- src/main/kotlin/lotto/{ => model}/LottoGenerator.kt | 2 +- src/main/kotlin/lotto/{ => model}/LottoNumberMatcher.kt | 2 +- src/main/kotlin/lotto/{ => model}/LottoRank.kt | 2 +- src/main/kotlin/lotto/{ => model}/LottoResult.kt | 2 +- src/main/kotlin/lotto/{ => model}/LottoResultDetail.kt | 2 +- src/main/kotlin/lotto/view/LottoInputView.kt | 3 +++ src/main/kotlin/lotto/view/LottoOutputView.kt | 3 +++ src/test/kotlin/lotto/LottoGeneratorTest.kt | 1 + src/test/kotlin/lotto/LottoNumberMatcherTest.kt | 2 ++ src/test/kotlin/lotto/LottoResultTest.kt | 3 +++ src/test/kotlin/lotto/LottoTest.kt | 1 + 14 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/lotto/controller/LottoController.kt rename src/main/kotlin/lotto/{ => model}/Lotto.kt (96%) rename src/main/kotlin/lotto/{ => model}/LottoGenerator.kt (98%) rename src/main/kotlin/lotto/{ => model}/LottoNumberMatcher.kt (96%) rename src/main/kotlin/lotto/{ => model}/LottoRank.kt (98%) rename src/main/kotlin/lotto/{ => model}/LottoResult.kt (99%) rename src/main/kotlin/lotto/{ => model}/LottoResultDetail.kt (90%) create mode 100644 src/main/kotlin/lotto/view/LottoInputView.kt create mode 100644 src/main/kotlin/lotto/view/LottoOutputView.kt diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index eb122656e..15fd5217d 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -1,6 +1,9 @@ package lotto import camp.nextstep.edu.missionutils.Console +import lotto.model.LottoGenerator +import lotto.model.LottoRank +import lotto.model.LottoResult import lotto.util.LottoConstants import lotto.util.LottoOutputText diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt new file mode 100644 index 000000000..9fa4182ef --- /dev/null +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -0,0 +1,3 @@ +package lotto.controller + +class LottoController \ No newline at end of file diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/model/Lotto.kt similarity index 96% rename from src/main/kotlin/lotto/Lotto.kt rename to src/main/kotlin/lotto/model/Lotto.kt index 5265784a5..099ab2cd1 100644 --- a/src/main/kotlin/lotto/Lotto.kt +++ b/src/main/kotlin/lotto/model/Lotto.kt @@ -1,4 +1,4 @@ -package lotto +package lotto.model import lotto.util.ErrorMessage import lotto.util.Validator diff --git a/src/main/kotlin/lotto/LottoGenerator.kt b/src/main/kotlin/lotto/model/LottoGenerator.kt similarity index 98% rename from src/main/kotlin/lotto/LottoGenerator.kt rename to src/main/kotlin/lotto/model/LottoGenerator.kt index 5635b0b83..6fec8b4d6 100644 --- a/src/main/kotlin/lotto/LottoGenerator.kt +++ b/src/main/kotlin/lotto/model/LottoGenerator.kt @@ -1,4 +1,4 @@ -package lotto +package lotto.model import camp.nextstep.edu.missionutils.Randoms.pickUniqueNumbersInRange import lotto.util.ErrorMessage diff --git a/src/main/kotlin/lotto/LottoNumberMatcher.kt b/src/main/kotlin/lotto/model/LottoNumberMatcher.kt similarity index 96% rename from src/main/kotlin/lotto/LottoNumberMatcher.kt rename to src/main/kotlin/lotto/model/LottoNumberMatcher.kt index c1df0e777..3549077a5 100644 --- a/src/main/kotlin/lotto/LottoNumberMatcher.kt +++ b/src/main/kotlin/lotto/model/LottoNumberMatcher.kt @@ -1,4 +1,4 @@ -package lotto +package lotto.model class LottoNumberMatcher { // TODO: 두 개의 리스트가 모두 Set 이라면 intersect 메서드가 더 효율적일 것으로 예상 diff --git a/src/main/kotlin/lotto/LottoRank.kt b/src/main/kotlin/lotto/model/LottoRank.kt similarity index 98% rename from src/main/kotlin/lotto/LottoRank.kt rename to src/main/kotlin/lotto/model/LottoRank.kt index 9a6c33880..a68384432 100644 --- a/src/main/kotlin/lotto/LottoRank.kt +++ b/src/main/kotlin/lotto/model/LottoRank.kt @@ -1,4 +1,4 @@ -package lotto +package lotto.model import lotto.util.LottoOutputText import java.text.DecimalFormat diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/model/LottoResult.kt similarity index 99% rename from src/main/kotlin/lotto/LottoResult.kt rename to src/main/kotlin/lotto/model/LottoResult.kt index 8b5516086..80d71137f 100644 --- a/src/main/kotlin/lotto/LottoResult.kt +++ b/src/main/kotlin/lotto/model/LottoResult.kt @@ -1,4 +1,4 @@ -package lotto +package lotto.model import lotto.util.LottoConstants diff --git a/src/main/kotlin/lotto/LottoResultDetail.kt b/src/main/kotlin/lotto/model/LottoResultDetail.kt similarity index 90% rename from src/main/kotlin/lotto/LottoResultDetail.kt rename to src/main/kotlin/lotto/model/LottoResultDetail.kt index fa15281ab..759e38d93 100644 --- a/src/main/kotlin/lotto/LottoResultDetail.kt +++ b/src/main/kotlin/lotto/model/LottoResultDetail.kt @@ -1,4 +1,4 @@ -package lotto +package lotto.model data class LottoResultDetail( val lottoRankList: List, diff --git a/src/main/kotlin/lotto/view/LottoInputView.kt b/src/main/kotlin/lotto/view/LottoInputView.kt new file mode 100644 index 000000000..d13177885 --- /dev/null +++ b/src/main/kotlin/lotto/view/LottoInputView.kt @@ -0,0 +1,3 @@ +package lotto.view + +class LottoInputView \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/LottoOutputView.kt b/src/main/kotlin/lotto/view/LottoOutputView.kt new file mode 100644 index 000000000..ae5054077 --- /dev/null +++ b/src/main/kotlin/lotto/view/LottoOutputView.kt @@ -0,0 +1,3 @@ +package lotto.view + +class LottoOutputView \ No newline at end of file diff --git a/src/test/kotlin/lotto/LottoGeneratorTest.kt b/src/test/kotlin/lotto/LottoGeneratorTest.kt index 1eef6f5df..50e4ff05d 100644 --- a/src/test/kotlin/lotto/LottoGeneratorTest.kt +++ b/src/test/kotlin/lotto/LottoGeneratorTest.kt @@ -1,5 +1,6 @@ package lotto +import lotto.model.LottoGenerator import lotto.util.LottoConstants import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/lotto/LottoNumberMatcherTest.kt b/src/test/kotlin/lotto/LottoNumberMatcherTest.kt index 60562248c..bb770b88b 100644 --- a/src/test/kotlin/lotto/LottoNumberMatcherTest.kt +++ b/src/test/kotlin/lotto/LottoNumberMatcherTest.kt @@ -1,5 +1,7 @@ package lotto +import lotto.model.Lotto +import lotto.model.LottoNumberMatcher import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/lotto/LottoResultTest.kt b/src/test/kotlin/lotto/LottoResultTest.kt index 235209a3d..9c1a9dc65 100644 --- a/src/test/kotlin/lotto/LottoResultTest.kt +++ b/src/test/kotlin/lotto/LottoResultTest.kt @@ -1,5 +1,8 @@ package lotto +import lotto.model.Lotto +import lotto.model.LottoRank +import lotto.model.LottoResult import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/lotto/LottoTest.kt b/src/test/kotlin/lotto/LottoTest.kt index fc29111b3..34ee8669a 100644 --- a/src/test/kotlin/lotto/LottoTest.kt +++ b/src/test/kotlin/lotto/LottoTest.kt @@ -1,5 +1,6 @@ package lotto +import lotto.model.Lotto import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows From 97becde1fc6a45e0623764dfdf0f191407337e8a Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 18:40:53 +0900 Subject: [PATCH 48/59] =?UTF-8?q?chore:=20MVC=20=ED=8C=A8=ED=84=B4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/lotto/{ => model}/LottoGeneratorTest.kt | 3 +-- src/test/kotlin/lotto/{ => model}/LottoNumberMatcherTest.kt | 4 +--- src/test/kotlin/lotto/{ => model}/LottoResultTest.kt | 5 +---- src/test/kotlin/lotto/{ => model}/LottoTest.kt | 3 +-- 4 files changed, 4 insertions(+), 11 deletions(-) rename src/test/kotlin/lotto/{ => model}/LottoGeneratorTest.kt (95%) rename src/test/kotlin/lotto/{ => model}/LottoNumberMatcherTest.kt (92%) rename src/test/kotlin/lotto/{ => model}/LottoResultTest.kt (95%) rename src/test/kotlin/lotto/{ => model}/LottoTest.kt (96%) diff --git a/src/test/kotlin/lotto/LottoGeneratorTest.kt b/src/test/kotlin/lotto/model/LottoGeneratorTest.kt similarity index 95% rename from src/test/kotlin/lotto/LottoGeneratorTest.kt rename to src/test/kotlin/lotto/model/LottoGeneratorTest.kt index 50e4ff05d..b1dd70993 100644 --- a/src/test/kotlin/lotto/LottoGeneratorTest.kt +++ b/src/test/kotlin/lotto/model/LottoGeneratorTest.kt @@ -1,6 +1,5 @@ -package lotto +package lotto.model -import lotto.model.LottoGenerator import lotto.util.LottoConstants import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/lotto/LottoNumberMatcherTest.kt b/src/test/kotlin/lotto/model/LottoNumberMatcherTest.kt similarity index 92% rename from src/test/kotlin/lotto/LottoNumberMatcherTest.kt rename to src/test/kotlin/lotto/model/LottoNumberMatcherTest.kt index bb770b88b..c71161941 100644 --- a/src/test/kotlin/lotto/LottoNumberMatcherTest.kt +++ b/src/test/kotlin/lotto/model/LottoNumberMatcherTest.kt @@ -1,7 +1,5 @@ -package lotto +package lotto.model -import lotto.model.Lotto -import lotto.model.LottoNumberMatcher import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/lotto/LottoResultTest.kt b/src/test/kotlin/lotto/model/LottoResultTest.kt similarity index 95% rename from src/test/kotlin/lotto/LottoResultTest.kt rename to src/test/kotlin/lotto/model/LottoResultTest.kt index 9c1a9dc65..8a53ce8c5 100644 --- a/src/test/kotlin/lotto/LottoResultTest.kt +++ b/src/test/kotlin/lotto/model/LottoResultTest.kt @@ -1,8 +1,5 @@ -package lotto +package lotto.model -import lotto.model.Lotto -import lotto.model.LottoRank -import lotto.model.LottoResult import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/lotto/LottoTest.kt b/src/test/kotlin/lotto/model/LottoTest.kt similarity index 96% rename from src/test/kotlin/lotto/LottoTest.kt rename to src/test/kotlin/lotto/model/LottoTest.kt index 34ee8669a..d018347cf 100644 --- a/src/test/kotlin/lotto/LottoTest.kt +++ b/src/test/kotlin/lotto/model/LottoTest.kt @@ -1,6 +1,5 @@ -package lotto +package lotto.model -import lotto.model.Lotto import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows From c7180cbf3785d7ff3d336e173022571db4ce72f7 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 20:42:42 +0900 Subject: [PATCH 49/59] =?UTF-8?q?refactor:=20MVC=20=ED=8C=A8=ED=84=B4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MVC 패턴에 맞춰 리팩토링 --- src/main/kotlin/lotto/Application.kt | 51 ++++--------------- .../lotto/controller/LottoController.kt | 45 +++++++++++++++- src/main/kotlin/lotto/model/Lotto.kt | 2 + src/main/kotlin/lotto/view/LottoInputView.kt | 23 ++++++++- src/main/kotlin/lotto/view/LottoOutputView.kt | 40 ++++++++++++++- 5 files changed, 118 insertions(+), 43 deletions(-) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 15fd5217d..852fc9493 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -1,47 +1,18 @@ package lotto -import camp.nextstep.edu.missionutils.Console -import lotto.model.LottoGenerator -import lotto.model.LottoRank -import lotto.model.LottoResult -import lotto.util.LottoConstants -import lotto.util.LottoOutputText +import lotto.controller.LottoController +import lotto.view.LottoInputView +import lotto.view.LottoOutputView fun main() { // TODO: 예외 발생 후에도 항상 해당 부분 부터 다시 입력을 받는다. - println(LottoOutputText.INPUT_PURCHASE_PRICE_TEXT) - val purchasePrice = Console.readLine().toInt() // TODO: 입력 예외 처리 필요 - println() + val inputView = LottoInputView() + val outputView = LottoOutputView() + val lottoController = LottoController(inputView, outputView) - val lottoGenerator = LottoGenerator(purchasePrice) - val lottoList = lottoGenerator.generate() - val lottoListSize = lottoList.size - println("${lottoListSize}${LottoOutputText.LOTTO_GENERATE_FINISH_TEXT}") - lottoList.forEach { lotto -> - println(lotto.getSortedNumbers()) - } - println() - - println(LottoOutputText.INPUT_WINNING_NUMBERS) - val winningNumbers = Console.readLine() - .split(LottoConstants.WINNING_NUMBERS_DELIMITER) - .map { it.toInt() } - println() - - println(LottoOutputText.INPUT_BONUS_NUMBER) - val trimBonusNumber = Console.readLine().trim() // TODO: 입력 예외 처리 필요 - val bonusNumber = trimBonusNumber.toInt() - println() - - val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) - val lottoResultDetail = lottoResult.getResult() - println("당첨 통계") - println("---") - LottoRank.entries.forEach { rank-> - if (rank != LottoRank.NOTHING) { - val rankCount = lottoResultDetail.lottoRankList.count { it == rank } - println("${rank.print()} - ${rankCount}개") - } - } - println("총 수익률은 ${lottoResultDetail.roundedRateOfReturn}%입니다.") + lottoController.purchaseLotto() + lottoController.showPurchasedLotto() + lottoController.inputWinningNumbers() + lottoController.inputBonusNumber() + lottoController.showLottoResult() } diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt index 9fa4182ef..929faf1ab 100644 --- a/src/main/kotlin/lotto/controller/LottoController.kt +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -1,3 +1,46 @@ package lotto.controller -class LottoController \ No newline at end of file +import lotto.model.Lotto +import lotto.model.LottoGenerator +import lotto.model.LottoResult +import lotto.model.toViewData +import lotto.view.LottoInputView +import lotto.view.LottoOutputView + +class LottoController( + private val inputView: LottoInputView, + private val outputView: LottoOutputView, +) { + private var purchasePrice = 0 + private var lottoList = listOf() + private var winningNumbers = listOf() + private var bonusNumber = 0 + + fun purchaseLotto() { + outputView.outputPurchasePrice() + purchasePrice = inputView.getPurchasePrice() + } + + fun showPurchasedLotto() { + val lottoGenerator = LottoGenerator(purchasePrice) + lottoList = lottoGenerator.generate() + val lottoListViewData = lottoList.toViewData() + outputView.outputLottoList(lottoListViewData) + } + + fun inputWinningNumbers() { + outputView.outputWinningNumber() + winningNumbers = inputView.getWinningNumbers() + } + + fun inputBonusNumber() { + outputView.outputBonusNumber() + bonusNumber = inputView.getBonusNumber() + } + + fun showLottoResult() { + val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) + val lottoResultDetail = lottoResult.getResult() + outputView.outputLottoResult(lottoResultDetail) + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/model/Lotto.kt b/src/main/kotlin/lotto/model/Lotto.kt index 099ab2cd1..395a386e0 100644 --- a/src/main/kotlin/lotto/model/Lotto.kt +++ b/src/main/kotlin/lotto/model/Lotto.kt @@ -14,3 +14,5 @@ class Lotto(private val numbers: List) { fun getSortedNumbers(): List = numbers.sorted() } + +fun List.toViewData(): List> = this.map { it.getNumbers() } diff --git a/src/main/kotlin/lotto/view/LottoInputView.kt b/src/main/kotlin/lotto/view/LottoInputView.kt index d13177885..6094ad6ba 100644 --- a/src/main/kotlin/lotto/view/LottoInputView.kt +++ b/src/main/kotlin/lotto/view/LottoInputView.kt @@ -1,3 +1,24 @@ package lotto.view -class LottoInputView \ No newline at end of file +import camp.nextstep.edu.missionutils.Console +import lotto.util.LottoConstants + +class LottoInputView { + fun getPurchasePrice(): Int { + val purchasePrice = Console.readLine().toInt() // TODO: 입력 예외 처리 필요 + return purchasePrice + } + + fun getWinningNumbers(): List { + val winningNumbers = Console.readLine() + .split(LottoConstants.WINNING_NUMBERS_DELIMITER) + .map { it.toInt() } + return winningNumbers + } + + fun getBonusNumber(): Int { + val trimBonusNumber = Console.readLine().trim() // TODO: 입력 예외 처리 필요 + val bonusNumber = trimBonusNumber.toInt() + return bonusNumber + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/LottoOutputView.kt b/src/main/kotlin/lotto/view/LottoOutputView.kt index ae5054077..c77d2e2c6 100644 --- a/src/main/kotlin/lotto/view/LottoOutputView.kt +++ b/src/main/kotlin/lotto/view/LottoOutputView.kt @@ -1,3 +1,41 @@ package lotto.view -class LottoOutputView \ No newline at end of file +import lotto.model.LottoRank +import lotto.model.LottoResultDetail +import lotto.util.LottoOutputText + +class LottoOutputView { + fun outputPurchasePrice() { + println(LottoOutputText.INPUT_PURCHASE_PRICE_TEXT) + } + + fun outputLottoList(lottoList: List>) { + println("${lottoList.size}${LottoOutputText.LOTTO_GENERATE_FINISH_TEXT}") + lottoList.forEach { lotto -> + println(lotto) + } + } + + fun outputWinningNumber() { + println() + println(LottoOutputText.INPUT_WINNING_NUMBERS) + } + + fun outputBonusNumber() { + println() + println(LottoOutputText.INPUT_BONUS_NUMBER) + } + + fun outputLottoResult(lottoResultDetail: LottoResultDetail) { + println() + println("당첨 통계") + println("---") + LottoRank.entries.forEach { rank-> + if (rank != LottoRank.NOTHING) { + val rankCount = lottoResultDetail.lottoRankList.count { it == rank } + println("${rank.print()} - ${rankCount}개") + } + } + println("총 수익률은 ${lottoResultDetail.roundedRateOfReturn}%입니다.") + } +} \ No newline at end of file From ef19f993a229bd3a4cfca7984ae87797f016d58a Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 21:34:03 +0900 Subject: [PATCH 50/59] =?UTF-8?q?refactor:=20MVC=20=ED=8C=A8=ED=84=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EA=B0=81=20=EA=B3=84=EC=B8=B5=20=EC=97=AD?= =?UTF-8?q?=ED=95=A0=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - View 계층이 Model 계층을 의존하지 않게 수정 - 최대한 Controller 계층이 View, Model 계층의 다리 역할을 하게끔 수정 --- .../lotto/controller/LottoController.kt | 24 ++++++++++++++++- .../kotlin/lotto/model/LottoResultDetail.kt | 4 +-- src/main/kotlin/lotto/util/LottoOutputText.kt | 4 +++ src/main/kotlin/lotto/view/LottoOutputView.kt | 26 +++++++++++-------- .../kotlin/lotto/model/LottoResultTest.kt | 4 +-- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt index 929faf1ab..7a3efaaa4 100644 --- a/src/main/kotlin/lotto/controller/LottoController.kt +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -2,7 +2,9 @@ package lotto.controller import lotto.model.Lotto import lotto.model.LottoGenerator +import lotto.model.LottoRank import lotto.model.LottoResult +import lotto.model.LottoResultDetail import lotto.model.toViewData import lotto.view.LottoInputView import lotto.view.LottoOutputView @@ -15,6 +17,8 @@ class LottoController( private var lottoList = listOf() private var winningNumbers = listOf() private var bonusNumber = 0 + private val printableRankList = mutableListOf() + private val winningRankCountList = mutableListOf() fun purchaseLotto() { outputView.outputPurchasePrice() @@ -41,6 +45,24 @@ class LottoController( fun showLottoResult() { val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) val lottoResultDetail = lottoResult.getResult() - outputView.outputLottoResult(lottoResultDetail) + val roundedRateOfReturn = lottoResultDetail.roundedRateOfReturnText + + calculateRankList(lottoResultDetail) + + outputView.outputLottoResult( + printableRankList = printableRankList, + winningRankCountList = winningRankCountList, + rateOfReturn = roundedRateOfReturn + ) + } + + private fun calculateRankList(lottoResultDetail: LottoResultDetail) { + LottoRank.entries.forEach { rank -> + if (rank != LottoRank.NOTHING) { + val rankCount = lottoResultDetail.winningRankList.count { it == rank } + winningRankCountList.add(rankCount) + printableRankList.add(rank.print()) + } + } } } \ No newline at end of file diff --git a/src/main/kotlin/lotto/model/LottoResultDetail.kt b/src/main/kotlin/lotto/model/LottoResultDetail.kt index 759e38d93..bd944e0eb 100644 --- a/src/main/kotlin/lotto/model/LottoResultDetail.kt +++ b/src/main/kotlin/lotto/model/LottoResultDetail.kt @@ -1,9 +1,9 @@ package lotto.model data class LottoResultDetail( - val lottoRankList: List, + val winningRankList: List, val rateOfReturn: Double ) { - val roundedRateOfReturn: String + val roundedRateOfReturnText: String get() = String.format("%.1f", rateOfReturn) } diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/util/LottoOutputText.kt index d3e5aa1d2..bac7055d0 100644 --- a/src/main/kotlin/lotto/util/LottoOutputText.kt +++ b/src/main/kotlin/lotto/util/LottoOutputText.kt @@ -11,4 +11,8 @@ object LottoOutputText { const val FIVE_AND_BONUS_MATCHES = "5개 일치, 보너스 볼 일치" const val SIX_MATCHES = "6개 일치" const val EMPTY = "" + const val LOTTO_WINNING_RESULT_TITLE = "당첨 통계" + const val LOTTO_WINNING_RESULT_SEPARATE_LINE = "---" + const val LOTTO_WINNING_RESULT_TOTAL_RATE_OF_RETURN = "총 수익률은" + const val LOTTO_WINNING_RESULT_TOTAL_RATE_OF_RETURN_2 = "%입니다." } \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/LottoOutputView.kt b/src/main/kotlin/lotto/view/LottoOutputView.kt index c77d2e2c6..1529eb953 100644 --- a/src/main/kotlin/lotto/view/LottoOutputView.kt +++ b/src/main/kotlin/lotto/view/LottoOutputView.kt @@ -1,7 +1,5 @@ package lotto.view -import lotto.model.LottoRank -import lotto.model.LottoResultDetail import lotto.util.LottoOutputText class LottoOutputView { @@ -26,16 +24,22 @@ class LottoOutputView { println(LottoOutputText.INPUT_BONUS_NUMBER) } - fun outputLottoResult(lottoResultDetail: LottoResultDetail) { + fun outputLottoResult( + printableRankList: List, + winningRankCountList: List, + rateOfReturn: String, + ) { println() - println("당첨 통계") - println("---") - LottoRank.entries.forEach { rank-> - if (rank != LottoRank.NOTHING) { - val rankCount = lottoResultDetail.lottoRankList.count { it == rank } - println("${rank.print()} - ${rankCount}개") - } + println(LottoOutputText.LOTTO_WINNING_RESULT_TITLE) + println(LottoOutputText.LOTTO_WINNING_RESULT_SEPARATE_LINE) + + printableRankList.forEachIndexed { index, printableRank -> + println("$printableRank - ${winningRankCountList[index]}개") } - println("총 수익률은 ${lottoResultDetail.roundedRateOfReturn}%입니다.") + + println( + "${LottoOutputText.LOTTO_WINNING_RESULT_TOTAL_RATE_OF_RETURN} " + + "$rateOfReturn${LottoOutputText.LOTTO_WINNING_RESULT_TOTAL_RATE_OF_RETURN_2}" + ) } } \ No newline at end of file diff --git a/src/test/kotlin/lotto/model/LottoResultTest.kt b/src/test/kotlin/lotto/model/LottoResultTest.kt index 8a53ce8c5..6ac7a2c2c 100644 --- a/src/test/kotlin/lotto/model/LottoResultTest.kt +++ b/src/test/kotlin/lotto/model/LottoResultTest.kt @@ -29,7 +29,7 @@ class LottoResultTest { val actual = lottoResult.getResult() assertEquals(expectedRateOfReturn, actual.rateOfReturn) - assertEquals(expectedLottoRankList, actual.lottoRankList) + assertEquals(expectedLottoRankList, actual.winningRankList) } @Test @@ -42,7 +42,7 @@ class LottoResultTest { val actual = lottoResult.getResult() assertEquals(expectedRateOfReturn, actual.rateOfReturn) - assertEquals(expectedLottoRankList, actual.lottoRankList) + assertEquals(expectedLottoRankList, actual.winningRankList) } companion object { From 7b60ae4e397f570f234ca30ae9106de77c9a0810 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 22:58:56 +0900 Subject: [PATCH 51/59] =?UTF-8?q?refactor:=20Validator=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 역할 별로 Validator를 생성 - 새로 생성한 Validator 적용 - 그 외 자잘한 수정 --- .../lotto/controller/LottoController.kt | 5 +++ src/main/kotlin/lotto/model/Lotto.kt | 8 ++--- src/main/kotlin/lotto/model/LottoGenerator.kt | 9 +++-- src/main/kotlin/lotto/util/ErrorMessage.kt | 5 +-- src/main/kotlin/lotto/util/LottoConstants.kt | 2 +- .../lotto/util/validator/InputValidator.kt | 23 ++++++++++++ .../util/validator/LottoGeneratorValidator.kt | 9 +++++ .../LottoValidator.kt} | 13 ++++--- src/main/kotlin/lotto/view/LottoInputView.kt | 36 ++++++++++++++++--- 9 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 src/main/kotlin/lotto/util/validator/InputValidator.kt create mode 100644 src/main/kotlin/lotto/util/validator/LottoGeneratorValidator.kt rename src/main/kotlin/lotto/util/{Validator.kt => validator/LottoValidator.kt} (55%) diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt index 7a3efaaa4..9d108bcbb 100644 --- a/src/main/kotlin/lotto/controller/LottoController.kt +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -6,6 +6,8 @@ import lotto.model.LottoRank import lotto.model.LottoResult import lotto.model.LottoResultDetail import lotto.model.toViewData +import lotto.util.ErrorMessage +import lotto.util.validator.InputValidator import lotto.view.LottoInputView import lotto.view.LottoOutputView @@ -40,6 +42,9 @@ class LottoController( fun inputBonusNumber() { outputView.outputBonusNumber() bonusNumber = inputView.getBonusNumber() + require(InputValidator.isBonusNumberUnique(winningNumbers, bonusNumber)) { + ErrorMessage.LOTTO_NUMBERS_CONTAIN_BONUS_NUMBER.getMessage() + } } fun showLottoResult() { diff --git a/src/main/kotlin/lotto/model/Lotto.kt b/src/main/kotlin/lotto/model/Lotto.kt index 395a386e0..8bb7e9d2b 100644 --- a/src/main/kotlin/lotto/model/Lotto.kt +++ b/src/main/kotlin/lotto/model/Lotto.kt @@ -1,13 +1,13 @@ package lotto.model import lotto.util.ErrorMessage -import lotto.util.Validator +import lotto.util.validator.LottoValidator class Lotto(private val numbers: List) { init { - require(numbers.size == 6) { ErrorMessage.LOTTO_NUMBERS_MUST_SIX_LETTERS.getMessage() } - require(Validator.isUniqueNumbers(numbers)) { ErrorMessage.LOTTO_NUMBERS_MUST_UNIQUE.getMessage() } - require(Validator.validateNumberLimit(numbers)) { ErrorMessage.LOTTO_NUMBER_EXCEEDS_MAX.getMessage() } + require(LottoValidator.isNumbersLengthSix(numbers)) { ErrorMessage.LOTTO_NUMBERS_MUST_SIX_LETTERS.getMessage() } + require(LottoValidator.isNumbersUnique(numbers)) { ErrorMessage.LOTTO_NUMBERS_MUST_UNIQUE.getMessage() } + require(LottoValidator.isMaximumNumberExceeded(numbers)) { ErrorMessage.LOTTO_NUMBER_EXCEEDS_MAX.getMessage() } } fun getNumbers(): List = numbers diff --git a/src/main/kotlin/lotto/model/LottoGenerator.kt b/src/main/kotlin/lotto/model/LottoGenerator.kt index 6fec8b4d6..c218da15c 100644 --- a/src/main/kotlin/lotto/model/LottoGenerator.kt +++ b/src/main/kotlin/lotto/model/LottoGenerator.kt @@ -3,11 +3,16 @@ package lotto.model import camp.nextstep.edu.missionutils.Randoms.pickUniqueNumbersInRange import lotto.util.ErrorMessage import lotto.util.LottoConstants +import lotto.util.validator.LottoGeneratorValidator class LottoGenerator(private val purchasePrice: Int) { init { - require(purchasePrice >= 1000) { ErrorMessage.PURCHASE_PRICE_MORE_THAN_THOUSAND.getMessage() } - require(purchasePrice % 1000 == 0) { ErrorMessage.INVALID_PURCHASE_PRICE.getMessage() } + require(LottoGeneratorValidator.isMoreThanOneThousand(purchasePrice)) { + ErrorMessage.PURCHASE_PRICE_MORE_THAN_THOUSAND.getMessage() + } + require(LottoGeneratorValidator.isThousandUnit(purchasePrice)) { + ErrorMessage.INVALID_PURCHASE_PRICE.getMessage() + } } fun generate(): List { diff --git a/src/main/kotlin/lotto/util/ErrorMessage.kt b/src/main/kotlin/lotto/util/ErrorMessage.kt index a50e3e76d..eca35159a 100644 --- a/src/main/kotlin/lotto/util/ErrorMessage.kt +++ b/src/main/kotlin/lotto/util/ErrorMessage.kt @@ -1,10 +1,11 @@ package lotto.util enum class ErrorMessage(private val message: String) { + NO_WHITESPACE_ALLOWED("입력 값이 비어 있습니다."), + MUST_SEPARATE_COMMA("쉼표(,)로 구분해 주세요."), + LOTTO_NUMBERS_CONTAIN_BONUS_NUMBER("보너스 번호를 로또 번호에 포함 시킬 수 없습니다."), PURCHASE_PRICE_MORE_THAN_THOUSAND("구입 금액은 최소 1,000원 부터 입니다."), INVALID_PURCHASE_PRICE("구입 금액은 1,000원 단위 입니다."), - PURCHASE_PRICE_MUST_BE_NUMBER("구입 금액은 숫자만 입력 가능 합니다."), - PURCHASE_PRICE_EMPTY("구입 금액은 비어있을 수 없습니다."), LOTTO_NUMBERS_MUST_SIX_LETTERS("로또 번호는 6개여야 합니다."), LOTTO_NUMBERS_MUST_UNIQUE("로또 번호는 중복 되면 안됩니다."), LOTTO_NUMBER_EXCEEDS_MAX("로또 번호는 45보다 클 수 없습니다."), diff --git a/src/main/kotlin/lotto/util/LottoConstants.kt b/src/main/kotlin/lotto/util/LottoConstants.kt index 2bd46264b..b84eafb37 100644 --- a/src/main/kotlin/lotto/util/LottoConstants.kt +++ b/src/main/kotlin/lotto/util/LottoConstants.kt @@ -2,7 +2,7 @@ package lotto.util object LottoConstants { const val PRICE = 1000 - const val WINNING_NUMBERS_DELIMITER = "," + const val WINNING_NUMBERS_DELIMITER = ',' const val MIN_NUMBER = 1 const val MAX_NUMBER = 45 } \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/validator/InputValidator.kt b/src/main/kotlin/lotto/util/validator/InputValidator.kt new file mode 100644 index 000000000..2967407d7 --- /dev/null +++ b/src/main/kotlin/lotto/util/validator/InputValidator.kt @@ -0,0 +1,23 @@ +package lotto.util.validator + +object InputValidator { + /** 숫자 인지 검사 한다. */ + fun isNumber(input: String): Boolean = input.toIntOrNull() != null + + /** 비어 있는지 검사 한다. */ + fun isNotEmpty(input: String): Boolean = input.isNotEmpty() + + /** 쉼표로 구분 했는지 검사 한다. */ + fun isDelimiterValid(input: String, delimiter: Char): Boolean { + return input.split(delimiter) + .all { + it.trim().toIntOrNull() != null + } + } + + /** 로또 번호와 보너스 번호가 중복 되지 않는지 검사 한다. */ + fun isBonusNumberUnique( + numbers: List, + bonusNumber: Int, + ): Boolean = !numbers.contains(bonusNumber) +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/validator/LottoGeneratorValidator.kt b/src/main/kotlin/lotto/util/validator/LottoGeneratorValidator.kt new file mode 100644 index 000000000..3a80374e3 --- /dev/null +++ b/src/main/kotlin/lotto/util/validator/LottoGeneratorValidator.kt @@ -0,0 +1,9 @@ +package lotto.util.validator + +object LottoGeneratorValidator { + /** 구입 금액이 1,000원 이상 인지 검사 한다. */ + fun isMoreThanOneThousand(purchasePrice: Int): Boolean = purchasePrice >= 1000 + + /** 구입 금액이 1,000원 단위 인지 검사 한다. */ + fun isThousandUnit(purchasePrice: Int): Boolean = purchasePrice % 1000 == 0 +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/Validator.kt b/src/main/kotlin/lotto/util/validator/LottoValidator.kt similarity index 55% rename from src/main/kotlin/lotto/util/Validator.kt rename to src/main/kotlin/lotto/util/validator/LottoValidator.kt index f35bb24ae..0d48edb29 100644 --- a/src/main/kotlin/lotto/util/Validator.kt +++ b/src/main/kotlin/lotto/util/validator/LottoValidator.kt @@ -1,15 +1,20 @@ -package lotto.util +package lotto.util.validator + +import lotto.util.LottoConstants + +object LottoValidator { + /** 숫자 리스트 사이즈가 6개인지 검사 한다. */ + fun isNumbersLengthSix(numbers: List): Boolean = numbers.size == 6 -object Validator { /** 숫자 리스트에서 중복이 없는지 검사 한다. */ - fun isUniqueNumbers(numbers: List): Boolean { + fun isNumbersUnique(numbers: List): Boolean { val uniqueNumbers = numbers.toSet() val isUnique = uniqueNumbers.size == numbers.size return isUnique } /** 로또 최대 번호를 초과 하는지 검사 한다. */ - fun validateNumberLimit(numbers: List): Boolean { + fun isMaximumNumberExceeded(numbers: List): Boolean { numbers.forEach { number -> if (number > LottoConstants.MAX_NUMBER) { return false diff --git a/src/main/kotlin/lotto/view/LottoInputView.kt b/src/main/kotlin/lotto/view/LottoInputView.kt index 6094ad6ba..be9268790 100644 --- a/src/main/kotlin/lotto/view/LottoInputView.kt +++ b/src/main/kotlin/lotto/view/LottoInputView.kt @@ -1,23 +1,49 @@ package lotto.view import camp.nextstep.edu.missionutils.Console +import lotto.util.ErrorMessage import lotto.util.LottoConstants +import lotto.util.validator.InputValidator class LottoInputView { fun getPurchasePrice(): Int { - val purchasePrice = Console.readLine().toInt() // TODO: 입력 예외 처리 필요 + val trimPurchasePrice = Console.readLine().trim() + + require(InputValidator.isNumber(trimPurchasePrice)) { + ErrorMessage.INPUT_VALUE_MUST_NUMBER.getMessage() + } + require(InputValidator.isNotEmpty(trimPurchasePrice)) { + ErrorMessage.NO_WHITESPACE_ALLOWED.getMessage() + } + + val purchasePrice = trimPurchasePrice.toInt() return purchasePrice } fun getWinningNumbers(): List { - val winningNumbers = Console.readLine() - .split(LottoConstants.WINNING_NUMBERS_DELIMITER) - .map { it.toInt() } + val trimWinningNumbers = Console.readLine().trim() + + require(InputValidator.isDelimiterValid(trimWinningNumbers, LottoConstants.WINNING_NUMBERS_DELIMITER)) { + ErrorMessage.MUST_SEPARATE_COMMA.getMessage() + } + require(InputValidator.isNotEmpty(trimWinningNumbers)) { + ErrorMessage.NO_WHITESPACE_ALLOWED.getMessage() + } + + val winningNumbers = + trimWinningNumbers + .split(LottoConstants.WINNING_NUMBERS_DELIMITER) + .map { it.toInt() } return winningNumbers } fun getBonusNumber(): Int { - val trimBonusNumber = Console.readLine().trim() // TODO: 입력 예외 처리 필요 + val trimBonusNumber = Console.readLine().trim() + + require(InputValidator.isNotEmpty(trimBonusNumber)) { + ErrorMessage.NO_WHITESPACE_ALLOWED.getMessage() + } + val bonusNumber = trimBonusNumber.toInt() return bonusNumber } From ff9d8414d2da243b71de0c78ef69d4fc612cc9b6 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 22:59:27 +0900 Subject: [PATCH 52/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c97516cea..6e000e608 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,12 @@ - **입력 예외 처리** - [x] 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우 - [x] 구입 금액이 1,000원 보다 적은 금액일 경우 - - [ ] 당첨 번호가 쉼표로 구분되어 있지 않은 경우 + - [x] 당첨 번호가 쉼표로 구분되어 있지 않은 경우 - [x] 당첨 번호가 중복되는 경우 - - [ ] 보너스 번호가 당첨 번호와 중복되는 경우 + - [x] 보너스 번호가 당첨 번호와 중복되는 경우 - **입력 공통 예외 처리** - - [ ] 숫자가 아닐 경우 - - [ ] 공백일 경우 + - [x] 숫자가 아닐 경우 + - [x] 공백일 경우 - **출력** - [x] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다. - [x] 당첨 내역을 출력한다. From 2d5f1809f6b745d3da00008ff0f3651ff033df2e Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:00:12 +0900 Subject: [PATCH 53/59] =?UTF-8?q?test:=20=EC=97=AD=ED=95=A0=20=EB=B3=84=20?= =?UTF-8?q?Validator=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=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 --- ...Test.kt => LottoGeneratorValidatorTest.kt} | 2 +- .../util/validator/InputValidatorTest.kt | 67 +++++++++++++++++++ .../validator/LottoGeneratorValidatorTest.kt | 35 ++++++++++ .../util/validator/LottoValidatorTest.kt | 66 ++++++++++++++++++ 4 files changed, 169 insertions(+), 1 deletion(-) rename src/test/kotlin/lotto/model/{LottoGeneratorTest.kt => LottoGeneratorValidatorTest.kt} (96%) create mode 100644 src/test/kotlin/lotto/util/validator/InputValidatorTest.kt create mode 100644 src/test/kotlin/lotto/util/validator/LottoGeneratorValidatorTest.kt create mode 100644 src/test/kotlin/lotto/util/validator/LottoValidatorTest.kt diff --git a/src/test/kotlin/lotto/model/LottoGeneratorTest.kt b/src/test/kotlin/lotto/model/LottoGeneratorValidatorTest.kt similarity index 96% rename from src/test/kotlin/lotto/model/LottoGeneratorTest.kt rename to src/test/kotlin/lotto/model/LottoGeneratorValidatorTest.kt index b1dd70993..a3bb2f07e 100644 --- a/src/test/kotlin/lotto/model/LottoGeneratorTest.kt +++ b/src/test/kotlin/lotto/model/LottoGeneratorValidatorTest.kt @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -class LottoGeneratorTest { +class LottoGeneratorValidatorTest { @Test fun `구입 금액이 1,000원 미만이면 예외가 발생한다`() { assertThrows { diff --git a/src/test/kotlin/lotto/util/validator/InputValidatorTest.kt b/src/test/kotlin/lotto/util/validator/InputValidatorTest.kt new file mode 100644 index 000000000..1550a56c5 --- /dev/null +++ b/src/test/kotlin/lotto/util/validator/InputValidatorTest.kt @@ -0,0 +1,67 @@ +package lotto.util.validator + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows + +class InputValidatorTest { + @Test + fun `입력 값이 숫자가 아닐 때 예외 테스트`() { + assertThrows { + require(InputValidator.isNumber("a")) + } + } + + @Test + fun `입력 값이 숫자일 때 성공 테스트`() { + assertDoesNotThrow { + require(InputValidator.isNumber("1")) + } + } + + @Test + fun `입력 값이 비어 있을 때 예외 테스트`() { + assertThrows { + require(InputValidator.isNotEmpty("")) + } + } + + @Test + fun `입력 값이 비어 있지 않을 때 성공 테스트`() { + assertDoesNotThrow { + require(InputValidator.isNotEmpty("11")) + } + } + + @Test + fun `입력 값을 쉼표로 구분하지 않았을 때 예외 테스트`() { + assertThrows { + require(InputValidator.isDelimiterValid("1/1/1/1/1/1", COMMA)) + } + } + + @Test + fun `입력 값을 쉼표로 구분 했을 때 성공 테스트`() { + assertDoesNotThrow { + require(InputValidator.isDelimiterValid("1,1,1,1,1,1", COMMA)) + } + } + + @Test + fun `로또 번호와 보너스 번호가 중복일 때 예외 테스트`() { + assertThrows { + require(InputValidator.isBonusNumberUnique(listOf(1,2), 1)) + } + } + + @Test + fun `로또 번호와 보너스 번호가 중복이 아닐 때 성공 테스트`() { + assertDoesNotThrow { + require(InputValidator.isBonusNumberUnique(listOf(1,2), 3)) + } + } + + companion object { + private const val COMMA = ',' + } +} \ No newline at end of file diff --git a/src/test/kotlin/lotto/util/validator/LottoGeneratorValidatorTest.kt b/src/test/kotlin/lotto/util/validator/LottoGeneratorValidatorTest.kt new file mode 100644 index 000000000..98ed11a9d --- /dev/null +++ b/src/test/kotlin/lotto/util/validator/LottoGeneratorValidatorTest.kt @@ -0,0 +1,35 @@ +package lotto.util.validator + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows + +class LottoGeneratorValidatorTest { + @Test + fun `구입 금액이 1,000원 미만일 때 예외 테스트`() { + assertThrows { + require(LottoGeneratorValidator.isMoreThanOneThousand(900)) + } + } + + @Test + fun `구입 금액이 1,000단위가 아닐 때 예외 테스트`() { + assertThrows { + require(LottoGeneratorValidator.isThousandUnit(1500)) + } + } + + @Test + fun `구입 금액이 1,000원 이상일 때 성공 테스트`() { + assertDoesNotThrow { + require(LottoGeneratorValidator.isMoreThanOneThousand(1000)) + } + } + + @Test + fun `구입 금액이 1,000단위일 때 성공 테스트`() { + assertDoesNotThrow { + require(LottoGeneratorValidator.isThousandUnit(2000)) + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/lotto/util/validator/LottoValidatorTest.kt b/src/test/kotlin/lotto/util/validator/LottoValidatorTest.kt new file mode 100644 index 000000000..7dcf10479 --- /dev/null +++ b/src/test/kotlin/lotto/util/validator/LottoValidatorTest.kt @@ -0,0 +1,66 @@ +package lotto.util.validator + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows + +class LottoValidatorTest { + @Test + fun `숫자 리스트 사이즈가 6개 미만일 때 예외 테스트`() { + assertThrows { + require(LottoValidator.isNumbersLengthSix(LIST_OF_FIVE_LENGTH)) + } + } + + @Test + fun `숫자 리스트 사이즈가 6개일 때 성공 테스트`() { + assertDoesNotThrow { + require(LottoValidator.isNumbersLengthSix(LIST_OF_SIX_LENGTH)) + } + } + + @Test + fun `숫자 리스트 사이즈가 6개 초과일 때 예외 테스트`() { + assertThrows { + require(LottoValidator.isNumbersLengthSix(LIST_OF_SEVEN_LENGTH)) + } + } + + @Test + fun `숫자 리스트에 중복 값이 있을 때 예외 테스트`() { + assertThrows { + require(LottoValidator.isNumbersUnique(NOT_UNIQUE_NUMBERS)) + } + } + + @Test + fun `숫자 리스트에 중복 값이 없을 때 성공 테스트`() { + assertDoesNotThrow { + require(LottoValidator.isNumbersUnique(UNIQUE_NUMBERS)) + } + } + + @Test + fun `로또 최대 번호를 초과할 때 예외 테스트`() { + assertThrows { + require(LottoValidator.isMaximumNumberExceeded(LIST_CONTAIN_MAX_NUMBER)) + } + } + + @Test + fun `로또 최대 번호를 초과하지 않았을 때 성공 테스트`() { + assertDoesNotThrow { + require(LottoValidator.isMaximumNumberExceeded(LIST_NOT_CONTAIN_MAX_NUMBER)) + } + } + + companion object { + private val LIST_OF_FIVE_LENGTH = listOf(1,2,3,4,5) + private val LIST_OF_SIX_LENGTH = listOf(1,2,3,4,5,6) + private val LIST_OF_SEVEN_LENGTH = listOf(1,2,3,4,5,6,7) + private val NOT_UNIQUE_NUMBERS = listOf(1,1) + private val UNIQUE_NUMBERS = listOf(1,2) + private val LIST_CONTAIN_MAX_NUMBER = listOf(1,2,3,46) + private val LIST_NOT_CONTAIN_MAX_NUMBER = listOf(1,2,3,5) + } +} \ No newline at end of file From 276cb23bd8461f3c5152f97d1b0eb9a8c9799c59 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:14:56 +0900 Subject: [PATCH 54/59] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=ED=9B=84=20=EB=8B=A4=EC=8B=9C=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20=EB=B0=9B=EB=8A=94=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/main/kotlin/lotto/Application.kt | 7 +--- .../lotto/controller/LottoController.kt | 33 ++++++++++++++++--- src/main/kotlin/lotto/view/LottoOutputView.kt | 7 ++++ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 852fc9493..1cf0a2ed2 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -5,14 +5,9 @@ import lotto.view.LottoInputView import lotto.view.LottoOutputView fun main() { - // TODO: 예외 발생 후에도 항상 해당 부분 부터 다시 입력을 받는다. val inputView = LottoInputView() val outputView = LottoOutputView() val lottoController = LottoController(inputView, outputView) - lottoController.purchaseLotto() - lottoController.showPurchasedLotto() - lottoController.inputWinningNumbers() - lottoController.inputBonusNumber() - lottoController.showLottoResult() + lottoController.start() } diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt index 9d108bcbb..e5ced4f2b 100644 --- a/src/main/kotlin/lotto/controller/LottoController.kt +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -22,24 +22,32 @@ class LottoController( private val printableRankList = mutableListOf() private val winningRankCountList = mutableListOf() - fun purchaseLotto() { + fun start() { + continueAfterException(outputView) { purchaseLotto() } + continueAfterException(outputView) { showPurchasedLotto() } + continueAfterException(outputView) { inputWinningNumbers() } + continueAfterException(outputView) { inputBonusNumber() } + continueAfterException(outputView) { showLottoResult() } + } + + private fun purchaseLotto() { outputView.outputPurchasePrice() purchasePrice = inputView.getPurchasePrice() } - fun showPurchasedLotto() { + private fun showPurchasedLotto() { val lottoGenerator = LottoGenerator(purchasePrice) lottoList = lottoGenerator.generate() val lottoListViewData = lottoList.toViewData() outputView.outputLottoList(lottoListViewData) } - fun inputWinningNumbers() { + private fun inputWinningNumbers() { outputView.outputWinningNumber() winningNumbers = inputView.getWinningNumbers() } - fun inputBonusNumber() { + private fun inputBonusNumber() { outputView.outputBonusNumber() bonusNumber = inputView.getBonusNumber() require(InputValidator.isBonusNumberUnique(winningNumbers, bonusNumber)) { @@ -47,7 +55,7 @@ class LottoController( } } - fun showLottoResult() { + private fun showLottoResult() { val lottoResult = LottoResult(lottoList, winningNumbers, bonusNumber) val lottoResultDetail = lottoResult.getResult() val roundedRateOfReturn = lottoResultDetail.roundedRateOfReturnText @@ -70,4 +78,19 @@ class LottoController( } } } +} + +private fun continueAfterException( + outputView: LottoOutputView, + block: () -> Unit, +) { + while (true) { + try { + block() + break + } catch (e: Exception) { + val errorMessage = e.localizedMessage + outputView.printErrorMessage(errorMessage) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/LottoOutputView.kt b/src/main/kotlin/lotto/view/LottoOutputView.kt index 1529eb953..aede73d7b 100644 --- a/src/main/kotlin/lotto/view/LottoOutputView.kt +++ b/src/main/kotlin/lotto/view/LottoOutputView.kt @@ -8,6 +8,7 @@ class LottoOutputView { } fun outputLottoList(lottoList: List>) { + println() println("${lottoList.size}${LottoOutputText.LOTTO_GENERATE_FINISH_TEXT}") lottoList.forEach { lotto -> println(lotto) @@ -42,4 +43,10 @@ class LottoOutputView { "$rateOfReturn${LottoOutputText.LOTTO_WINNING_RESULT_TOTAL_RATE_OF_RETURN_2}" ) } + + fun printErrorMessage(message: String) { + println() + println(message) + println() + } } \ No newline at end of file From 5d386a2620a3fb6a4398f770ec57b4baacc6ca54 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:15:12 +0900 Subject: [PATCH 55/59] =?UTF-8?q?docs:=20README.md=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=83=81=ED=99=A9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6e000e608..a22c766c1 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,9 @@ - [x] 로또 1장의 가격은 1,000원이다. - [x] 사용자가 구매한 로또 번호와 당첨 번호(, 보너스 번호)를 비교한다. - [x] 당첨 내역을 출력할 때 금액을 천 단위 당 쉼표로 구분한다. - - [ ] 입력 부분에서 예외가 발생해도 예외 출력 후 계속해서 입력을 받는다. + - [x] 입력 부분에서 예외가 발생해도 예외 출력 후 계속해서 입력을 받는다. - **로또 예외 처리** - [x] 로또 번호는 최대 번호인 45를 초과하면 예외가 발생한다. - - [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. + - [x] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. - Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다. \ No newline at end of file From 2aa9d0aef8268401b6378722b9bc991232bf57c8 Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:19:53 +0900 Subject: [PATCH 56/59] =?UTF-8?q?chore:=20=EC=9E=91=EC=9D=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트 코드 파일 명 수정 - LottoOutputText 패키지 위치 수정 --- src/main/kotlin/lotto/model/LottoRank.kt | 2 +- src/main/kotlin/lotto/{util => view}/LottoOutputText.kt | 2 +- src/main/kotlin/lotto/view/LottoOutputView.kt | 2 -- .../{LottoGeneratorValidatorTest.kt => LottoGeneratorTest.kt} | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) rename src/main/kotlin/lotto/{util => view}/LottoOutputText.kt (97%) rename src/test/kotlin/lotto/model/{LottoGeneratorValidatorTest.kt => LottoGeneratorTest.kt} (96%) diff --git a/src/main/kotlin/lotto/model/LottoRank.kt b/src/main/kotlin/lotto/model/LottoRank.kt index a68384432..479409cd3 100644 --- a/src/main/kotlin/lotto/model/LottoRank.kt +++ b/src/main/kotlin/lotto/model/LottoRank.kt @@ -1,6 +1,6 @@ package lotto.model -import lotto.util.LottoOutputText +import lotto.view.LottoOutputText import java.text.DecimalFormat enum class LottoRank(val price: Int) { diff --git a/src/main/kotlin/lotto/util/LottoOutputText.kt b/src/main/kotlin/lotto/view/LottoOutputText.kt similarity index 97% rename from src/main/kotlin/lotto/util/LottoOutputText.kt rename to src/main/kotlin/lotto/view/LottoOutputText.kt index bac7055d0..e018f2921 100644 --- a/src/main/kotlin/lotto/util/LottoOutputText.kt +++ b/src/main/kotlin/lotto/view/LottoOutputText.kt @@ -1,4 +1,4 @@ -package lotto.util +package lotto.view object LottoOutputText { const val INPUT_PURCHASE_PRICE_TEXT = "구입금액을 입력해 주세요." diff --git a/src/main/kotlin/lotto/view/LottoOutputView.kt b/src/main/kotlin/lotto/view/LottoOutputView.kt index aede73d7b..9aa22502f 100644 --- a/src/main/kotlin/lotto/view/LottoOutputView.kt +++ b/src/main/kotlin/lotto/view/LottoOutputView.kt @@ -1,7 +1,5 @@ package lotto.view -import lotto.util.LottoOutputText - class LottoOutputView { fun outputPurchasePrice() { println(LottoOutputText.INPUT_PURCHASE_PRICE_TEXT) diff --git a/src/test/kotlin/lotto/model/LottoGeneratorValidatorTest.kt b/src/test/kotlin/lotto/model/LottoGeneratorTest.kt similarity index 96% rename from src/test/kotlin/lotto/model/LottoGeneratorValidatorTest.kt rename to src/test/kotlin/lotto/model/LottoGeneratorTest.kt index a3bb2f07e..b1dd70993 100644 --- a/src/test/kotlin/lotto/model/LottoGeneratorValidatorTest.kt +++ b/src/test/kotlin/lotto/model/LottoGeneratorTest.kt @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -class LottoGeneratorValidatorTest { +class LottoGeneratorTest { @Test fun `구입 금액이 1,000원 미만이면 예외가 발생한다`() { assertThrows { From 2e0fcefa76ed0e3dd2f29eee29c9f8b88de7c2ae Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:38:05 +0900 Subject: [PATCH 57/59] =?UTF-8?q?fix:=20=EB=AC=B4=ED=95=9C=20=EB=A3=A8?= =?UTF-8?q?=ED=94=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효성 검사 수정 - 무한 루프 수정 --- src/main/kotlin/lotto/controller/LottoController.kt | 8 +++++--- src/main/kotlin/lotto/view/LottoInputView.kt | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt index e5ced4f2b..2f966c654 100644 --- a/src/main/kotlin/lotto/controller/LottoController.kt +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -8,6 +8,7 @@ import lotto.model.LottoResultDetail import lotto.model.toViewData import lotto.util.ErrorMessage import lotto.util.validator.InputValidator +import lotto.util.validator.LottoValidator import lotto.view.LottoInputView import lotto.view.LottoOutputView @@ -24,7 +25,6 @@ class LottoController( fun start() { continueAfterException(outputView) { purchaseLotto() } - continueAfterException(outputView) { showPurchasedLotto() } continueAfterException(outputView) { inputWinningNumbers() } continueAfterException(outputView) { inputBonusNumber() } continueAfterException(outputView) { showLottoResult() } @@ -33,11 +33,10 @@ class LottoController( private fun purchaseLotto() { outputView.outputPurchasePrice() purchasePrice = inputView.getPurchasePrice() - } - private fun showPurchasedLotto() { val lottoGenerator = LottoGenerator(purchasePrice) lottoList = lottoGenerator.generate() + val lottoListViewData = lottoList.toViewData() outputView.outputLottoList(lottoListViewData) } @@ -45,6 +44,9 @@ class LottoController( private fun inputWinningNumbers() { outputView.outputWinningNumber() winningNumbers = inputView.getWinningNumbers() + require(LottoValidator.isNumbersLengthSix(winningNumbers)) { + ErrorMessage.LOTTO_NUMBERS_MUST_SIX_LETTERS.getMessage() + } } private fun inputBonusNumber() { diff --git a/src/main/kotlin/lotto/view/LottoInputView.kt b/src/main/kotlin/lotto/view/LottoInputView.kt index be9268790..ff0335b3e 100644 --- a/src/main/kotlin/lotto/view/LottoInputView.kt +++ b/src/main/kotlin/lotto/view/LottoInputView.kt @@ -9,12 +9,12 @@ class LottoInputView { fun getPurchasePrice(): Int { val trimPurchasePrice = Console.readLine().trim() - require(InputValidator.isNumber(trimPurchasePrice)) { - ErrorMessage.INPUT_VALUE_MUST_NUMBER.getMessage() - } require(InputValidator.isNotEmpty(trimPurchasePrice)) { ErrorMessage.NO_WHITESPACE_ALLOWED.getMessage() } + require(InputValidator.isNumber(trimPurchasePrice)) { + ErrorMessage.INPUT_VALUE_MUST_NUMBER.getMessage() + } val purchasePrice = trimPurchasePrice.toInt() return purchasePrice @@ -40,6 +40,9 @@ class LottoInputView { fun getBonusNumber(): Int { val trimBonusNumber = Console.readLine().trim() + require(InputValidator.isNotEmpty(trimBonusNumber)) { + ErrorMessage.INPUT_VALUE_MUST_NUMBER.getMessage() + } require(InputValidator.isNotEmpty(trimBonusNumber)) { ErrorMessage.NO_WHITESPACE_ALLOWED.getMessage() } From e2261383e712f221d9762664a90439214f6b9bfb Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:46:36 +0900 Subject: [PATCH 58/59] =?UTF-8?q?fix:=20=EB=AC=B4=ED=95=9C=20=EB=A3=A8?= =?UTF-8?q?=ED=94=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 무한 루프 수정 - LottoOutputView NewLine 메서드 추가 --- src/main/kotlin/lotto/controller/LottoController.kt | 13 ++++++++++--- src/main/kotlin/lotto/view/LottoOutputView.kt | 10 ++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/lotto/controller/LottoController.kt b/src/main/kotlin/lotto/controller/LottoController.kt index 2f966c654..1949a395c 100644 --- a/src/main/kotlin/lotto/controller/LottoController.kt +++ b/src/main/kotlin/lotto/controller/LottoController.kt @@ -38,7 +38,9 @@ class LottoController( lottoList = lottoGenerator.generate() val lottoListViewData = lottoList.toViewData() + outputView.newLine() outputView.outputLottoList(lottoListViewData) + outputView.newLine() } private fun inputWinningNumbers() { @@ -47,6 +49,7 @@ class LottoController( require(LottoValidator.isNumbersLengthSix(winningNumbers)) { ErrorMessage.LOTTO_NUMBERS_MUST_SIX_LETTERS.getMessage() } + outputView.newLine() } private fun inputBonusNumber() { @@ -55,6 +58,7 @@ class LottoController( require(InputValidator.isBonusNumberUnique(winningNumbers, bonusNumber)) { ErrorMessage.LOTTO_NUMBERS_CONTAIN_BONUS_NUMBER.getMessage() } + outputView.newLine() } private fun showLottoResult() { @@ -69,6 +73,7 @@ class LottoController( winningRankCountList = winningRankCountList, rateOfReturn = roundedRateOfReturn ) + outputView.newLine() } private fun calculateRankList(lottoResultDetail: LottoResultDetail) { @@ -86,13 +91,15 @@ private fun continueAfterException( outputView: LottoOutputView, block: () -> Unit, ) { - while (true) { + var hasException = true + while (hasException) { + hasException = false try { block() - break - } catch (e: Exception) { + } catch (e: IllegalArgumentException) { val errorMessage = e.localizedMessage outputView.printErrorMessage(errorMessage) + hasException = true } } } \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/LottoOutputView.kt b/src/main/kotlin/lotto/view/LottoOutputView.kt index 9aa22502f..438dfd78f 100644 --- a/src/main/kotlin/lotto/view/LottoOutputView.kt +++ b/src/main/kotlin/lotto/view/LottoOutputView.kt @@ -6,7 +6,6 @@ class LottoOutputView { } fun outputLottoList(lottoList: List>) { - println() println("${lottoList.size}${LottoOutputText.LOTTO_GENERATE_FINISH_TEXT}") lottoList.forEach { lotto -> println(lotto) @@ -14,12 +13,10 @@ class LottoOutputView { } fun outputWinningNumber() { - println() println(LottoOutputText.INPUT_WINNING_NUMBERS) } fun outputBonusNumber() { - println() println(LottoOutputText.INPUT_BONUS_NUMBER) } @@ -28,7 +25,6 @@ class LottoOutputView { winningRankCountList: List, rateOfReturn: String, ) { - println() println(LottoOutputText.LOTTO_WINNING_RESULT_TITLE) println(LottoOutputText.LOTTO_WINNING_RESULT_SEPARATE_LINE) @@ -43,8 +39,10 @@ class LottoOutputView { } fun printErrorMessage(message: String) { - println() + newLine() println(message) - println() + newLine() } + + fun newLine() = println() } \ No newline at end of file From 5ed3c3d3fd80c6b7cbbd8fa1844a847800ecbf9e Mon Sep 17 00:00:00 2001 From: DDangDin Date: Mon, 4 Nov 2024 23:49:00 +0900 Subject: [PATCH 59/59] =?UTF-8?q?fix:=20=EC=B6=9C=EB=A0=A5=20=ED=85=8D?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 출력 텍스트 일부 수정 --- src/main/kotlin/lotto/model/LottoRank.kt | 2 +- src/main/kotlin/lotto/view/LottoOutputText.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/lotto/model/LottoRank.kt b/src/main/kotlin/lotto/model/LottoRank.kt index 479409cd3..b6d3a7ae7 100644 --- a/src/main/kotlin/lotto/model/LottoRank.kt +++ b/src/main/kotlin/lotto/model/LottoRank.kt @@ -11,7 +11,7 @@ enum class LottoRank(val price: Int) { FIVE_AND_BONUS_MATCHES(30000000), SIX_MATCHES(2000000000); - fun print(): String = "${this.toDisplayName()} (${this.price.formatCurrency()})" + fun print(): String = "${this.toDisplayName()} (${this.price.formatCurrency()}원)" private fun toDisplayName(): String = when (this) { diff --git a/src/main/kotlin/lotto/view/LottoOutputText.kt b/src/main/kotlin/lotto/view/LottoOutputText.kt index e018f2921..7c9764a75 100644 --- a/src/main/kotlin/lotto/view/LottoOutputText.kt +++ b/src/main/kotlin/lotto/view/LottoOutputText.kt @@ -2,7 +2,7 @@ package lotto.view object LottoOutputText { const val INPUT_PURCHASE_PRICE_TEXT = "구입금액을 입력해 주세요." - const val LOTTO_GENERATE_FINISH_TEXT = "개 구매했습니다." + const val LOTTO_GENERATE_FINISH_TEXT = "개를 구매했습니다." const val INPUT_WINNING_NUMBERS = "당첨 번호를 입력해 주세요." const val INPUT_BONUS_NUMBER = "보너스 번호를 입력해 주세요." const val THREE_MATCHES = "3개 일치"