From f6024db81cda085643fd847bc5cbf88d822f8c27 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=ED=94=BC=EC=9C=A0=EC=A7=84?=
<86800087+PIYUJIN@users.noreply.github.com>
Date: Mon, 4 Nov 2024 12:05:40 +0900
Subject: [PATCH 01/15] =?UTF-8?q?docs($README.md):=20=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A0=95=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 215 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4fc0ae874..751493426 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,215 @@
-# kotlin-lotto-precourse
+# [2주차] 자동차 경주(kotlin-racingcar-precourse)
+
+### 🔍 진행 방식
+- 미션은 과제 진행 요구 사항, 기능 요구 사항, 프로그래밍 요구 사항 세 가지로 구성되어 있다.
+- 세 개의 요구 사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.
+- 기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.
+
+
+
+### 📮 미션 제출 방법
+- 미션 구현을 완료한 후 GitHub을 통해 제출해야 한다.
+ - GitHub을 활용한 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/main/precourse)를 참고해 제출한다.
+- GitHub에 미션을 제출한 후 우아한테크코스 지원 플랫폼에 **PR 링크를 포함하여 최종 제출**한다.
+ - 자세한 안내는 [제출 가이드](https://github.com/woowacourse/woowacourse-docs/tree/main/precourse#%EC%A0%9C%EC%B6%9C-%EA%B0%80%EC%9D%B4%EB%93%9C)를 참고한다.
+ - 과제를 수행하면서 느낀 점, 배운 점, 많은 시간을 투자한 부분 등 자유롭게 작성한다.
+
+
+
+### ✔️ 과제 제출 전 체크 리스트
+- 기능을 올바르게 구현했더라도 요구 사항에 명시된 출력 형식을 따르지 않으면 0점을 받게 된다.
+- 기능 구현을 완료한 후 아래 가이드에 따라 모든 테스트가 성공적으로 실행되는지 확인한다.
+- 테스트가 실패하면 점수가 0점이 되므로 제출하기 전에 반드시 확인한다.
+
+#### 테스트 실행 가이드
+- IntelliJ IDEA 또는 Android Studio와 같은 IDE에서 ```Kotlin 1.9.24```로 실행되는지 확인한다.
+- 터미널에서 Mac 또는 Linux 사용자의 경우 ```./gradlew clean test``` 명령을 실행하고, Windows 사용자의 경우 ```gradlew.bat clean test``` 또는 ```.\gradlew.bat clean test``` 명령을 실행할 때 모든 테스트가 아래와 같이 통과하는지 확인한다.
+
+```
+BUILD SUCCESSFUL in 0s
+```
+
+
+
+-------------
+### 📝 과제 진행 요구 사항
+- 미션은 [로또 저장소](https://github.com/woowacourse-precourse/kotlin-lotto-7)를 포크하고 클론하는 것으로 시작한다.
+- 기능을 구현하기 전 README.md에 구현할 기능 목록을 정리해 추가한다.
+- Git의 커밋 단위는 앞 단계에서 README.md에 정리한 기능 목록 단위로 추가한다.
+ - [AngularJS Git Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153)을 참고해 커밋 메시지를 작성한다.
+- 자세한 과제 진행 방법은 프리코스 진행 가이드 문서를 참고한다.
+
+
+
+### 🚀 기능 요구 사항
+간단한 로또 발매기를 구현한다.
+
+- 로또 번호의 숫자 범위는 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` 등과 같은 명확한 유형을 처리한다.
+
+
+
+
+#### 💬 입출력 요구 사항
+- 입력 :
+ - 로또 구입 금액을 입력 받는다. 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
+
+ ```
+ 14000
+ ```
+
+ - 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다.
+
+ ```
+ 1,2,3,4,5,6
+ ```
+
+ - 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다.
+
+ ```
+ 7
+ ```
+
+
+- 출력 :
+ - 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다.
+ ```
+ 8개를 구매했습니다.
+ [8, 21, 23, 41, 42, 43]
+ [3, 5, 11, 16, 32, 38]
+ [7, 11, 16, 35, 36, 44]
+ [1, 8, 11, 31, 41, 42]
+ [13, 14, 16, 38, 42, 45]
+ [7, 11, 30, 40, 42, 43]
+ [2, 13, 22, 32, 38, 45]
+ [1, 3, 5, 14, 22, 45]
+ ```
+ - 당첨 내역을 출력한다.
+ ```
+ 3개 일치 (5,000원) - 1개
+ 4개 일치 (50,000원) - 0개
+ 5개 일치 (1,500,000원) - 0개
+ 5개 일치, 보너스 볼 일치 (30,000,000원) - 0개
+ 6개 일치 (2,000,000,000원) - 0개
+ ```
+ - 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%)
+ ```
+ 총 수익률은 62.5%입니다.
+ ```
+
+ - 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.
+ ```
+ [ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.
+ ```
+
+> 실행 결과 예시
+
+ ```
+구입금액을 입력해 주세요.
+8000
+
+8개를 구매했습니다.
+[8, 21, 23, 41, 42, 43]
+[3, 5, 11, 16, 32, 38]
+[7, 11, 16, 35, 36, 44]
+[1, 8, 11, 31, 41, 42]
+[13, 14, 16, 38, 42, 45]
+[7, 11, 30, 40, 42, 43]
+[2, 13, 22, 32, 38, 45]
+[1, 3, 5, 14, 22, 45]
+
+당첨 번호를 입력해 주세요.
+1,2,3,4,5,6
+
+보너스 번호를 입력해 주세요.
+7
+
+당첨 통계
+---
+3개 일치 (5,000원) - 1개
+4개 일치 (50,000원) - 0개
+5개 일치 (1,500,000원) - 0개
+5개 일치, 보너스 볼 일치 (30,000,000원) - 0개
+6개 일치 (2,000,000,000원) - 0개
+총 수익률은 62.5%입니다.
+ ```
+
+
+
+### 🖥️ 프로그래밍 요구 사항
+- Kotlin **1.9.24**에서 실행 가능해야 한다.
+- Java 코드가 아닌 **Kotlin 코드**로만 구현해야 한다.
+- 프로그램 실행의 시작점은 ```Application의 main()```이다.
+- build.gradle.kts 파일은 변경할 수 없으며, 제공된 라이브러리 이외의 외부 라이브러리는 사용하지 않는다.
+- 프로그램 종료 시 ```System.exit()``` 또는 ```exitProcess()```를 호출하지 않는다.
+- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 등의 이름을 바꾸거나 이동하지 않는다.
+- 코틀린 코드 컨벤션을 지키면서 프로그래밍한다.
+- 기본적으로 [Kotlin Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/kotlin)를 원칙으로 한다.
+
+### 🖥️ 프로그래밍 요구 사항2
+- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
+ - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
+ - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
+- 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
+- JUnit 5와 AssertJ를 이용하여 정리한 기능 목록이 정상적으로 작동하는지 테스트 코드로 확인한다.
+ - 테스트 도구 사용법이 익숙하지 않다면 아래 문서를 참고하여 학습한 후 테스트를 구현한다.
+ - [JUnit 5 User Guide](https://junit.org/junit5/docs/current/user-guide/)
+ - [AssertJ User Guide](https://assertj.github.io/doc/)
+ - [AssertJ Exception Assertions](https://www.baeldung.com/assertj-exception-assertion)
+ - [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)
+
+### 🖥️ 프로그래밍 요구 사항3
+- 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다.
+ - 함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다.
+- else를 지양한다.
+ - 때로는 if/else, when문을 사용하는 것이 더 깔끔해 보일 수 있다. 어느 경우에 쓰는 것이 적절할지 스스로 고민해 본다.
+ - 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
+- Enum 클래스를 적용하여 프로그램을 구현한다.
+- 구현한 기능에 대한 단위 테스트를 작성한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다.
+ - 단위 테스트 작성이 익숙하지 않다면 `LottoTest`를 참고하여 학습한 후 테스트를 작성한다.
+
+
+
+#### 라이브러리
+- ```camp.nextstep.edu.missionutils```에서 제공하는 ```Randoms 및 Console API```를 사용하여 구현해야 한다.
+ - Random 값 추출은 ```camp.nextstep.edu.missionutils.Randoms의 pickUniqueNumbersInRange()```를 활용한다.
+ - 사용자가 입력하는 값은 ```camp.nextstep.edu.missionutils.Console의 readLine()```을 활용한다.
+
+> 사용 예시 : 1에서 45 사이의 중복되지 않은 정수 6개 반환
+
+```
+Randoms.pickUniqueNumbersInRange(1, 45, 6)
+```
+
+#### Lotto 클래스
+- 제공된 `Lotto 클래스`를 사용하여 구현해야 한다.
+- `Lotto`에 `numbers` 이외의 필드(인스턴스 변수)를 추가할 수 없다.
+- `numbers`의 접근 제어자인 `private`은 변경할 수 없다.
+- `Lotto`의 패키지를 변경할 수 있다.
+
+```
+package lotto
+
+class Lotto(private val numbers: List) {
+ init {
+ require(numbers.size == 6) { "[ERROR] 로또 번호는 6개여야 합니다." }
+ }
+
+ // TODO: 추가 기능 구현
+}
+```
+
From dbedb04f2b1a446a3ccd009345fa322a226d0e0d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=ED=94=BC=EC=9C=A0=EC=A7=84?=
<86800087+PIYUJIN@users.noreply.github.com>
Date: Mon, 4 Nov 2024 12:25:18 +0900
Subject: [PATCH 02/15] =?UTF-8?q?docs($README.md):=20=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=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 751493426..0c2836882 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# [2주차] 자동차 경주(kotlin-racingcar-precourse)
+# [3주차] 로또 (kotlin-lotto-precourse)
### 🔍 진행 방식
- 미션은 과제 진행 요구 사항, 기능 요구 사항, 프로그래밍 요구 사항 세 가지로 구성되어 있다.
From bf4bae9b12b4c71e278ea2a1b30f65285e15662e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=ED=94=BC=EC=9C=A0=EC=A7=84?=
<86800087+PIYUJIN@users.noreply.github.com>
Date: Mon, 4 Nov 2024 16:11:17 +0900
Subject: [PATCH 03/15] =?UTF-8?q?docs($README.md):=20=EA=B5=AC=ED=98=84?=
=?UTF-8?q?=ED=95=A0=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=A0=95?=
=?UTF-8?q?=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 0c2836882..f8aba7e92 100644
--- a/README.md
+++ b/README.md
@@ -60,8 +60,14 @@ BUILD SUCCESSFUL in 0s
- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시키고, `[ERROR]`로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
- `Exception`이 아닌 `IllegalArgumentException`, `IllegalStateException` 등과 같은 명확한 유형을 처리한다.
-
+---
+- [ ] 로또 구입 금액 입력 받기 (1000원 단위)
+- [ ] 로또 당첨 번호 + 보너스 번호 입력 받기 (쉼표를 기준으로 구분)
+- [ ] 로또 구입 금액에 해당하는 만큼 로또를 발행 (로또 1장 가격 : 1000원)
+- [ ] 1~45까지의 숫자 중 중복되지 않는 6개의 숫자와 보너스 번호 1개 숫자 추출
+- [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교 → 당첨 내역 및 수익률(소수점 둘째 자리에서 반올림) 출력 후 로또 게임 종료
+- [ ] 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생(`[ERROR]`로 시작하는 에러 메시지)시킨 후 애플리케이션은 종료
+---
#### 💬 입출력 요구 사항
@@ -78,7 +84,7 @@ BUILD SUCCESSFUL in 0s
1,2,3,4,5,6
```
- - 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다.
+ - 보너스 번호를 입력 받는다.
```
7
From a87bb89dee915e8d3802620508b3b77bcb71c075 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=ED=94=BC=EC=9C=A0=EC=A7=84?=
<86800087+PIYUJIN@users.noreply.github.com>
Date: Mon, 4 Nov 2024 16:14:56 +0900
Subject: [PATCH 04/15] =?UTF-8?q?docs($README.md):=20=EA=B5=AC=ED=98=84?=
=?UTF-8?q?=ED=95=A0=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EB=AA=A9?=
=?UTF-8?q?=EB=A1=9D=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, 10 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index f8aba7e92..031c22b20 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,16 @@ BUILD SUCCESSFUL in 0s
- [ ] 로또 구입 금액에 해당하는 만큼 로또를 발행 (로또 1장 가격 : 1000원)
- [ ] 1~45까지의 숫자 중 중복되지 않는 6개의 숫자와 보너스 번호 1개 숫자 추출
- [ ] 사용자가 구매한 로또 번호와 당첨 번호를 비교 → 당첨 내역 및 수익률(소수점 둘째 자리에서 반올림) 출력 후 로또 게임 종료
-- [ ] 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생(`[ERROR]`로 시작하는 에러 메시지)시킨 후 애플리케이션은 종료
+- [ ] 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생(`[ERROR]`로 시작하는 에러 메시지)시킨 후 애플리케이션은 종료
+ - [ ] 로또 구입 금액이 1,000원으로 나누어 떨어지지 않는 경우
+ - [ ] 로또 구입 금액이 공백인 경우
+ - [ ] 당첨 번호가 공백인 경우
+ - [ ] 당첨 번호에 숫자가 아닌 다른 문자열이 포함된 경우
+ - [ ] 당첨 번호가 1~45까지의 숫자에 포함되지 않는 경우
+ - [ ] 보너스 번호가 공백인 경우
+ - [ ] 보너스 번호가 숫자가 아닌 다른 문자열인 경우
+ - [ ] 보너스 번호가 1~45까지의 숫자에 포함되지 않는 경우
+ - [ ] 당첨 번호 및 보너스 번호에 중복된 숫자가 있는 경우
---
From 10d03da10d99ef7c6c32bb58592e72a5cc4fb871 Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 16:40:16 +0900
Subject: [PATCH 05/15] =?UTF-8?q?docs($.gitignore):=20gitignore=20?=
=?UTF-8?q?=EC=84=A4=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git으로 관리할 자원 설정
---
.gitignore | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 5dca701a7..9d23512ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,36 @@ build/
.springBeans
.sts4-cache
+# User-specific configurations
+.idea/caches/
+.idea/libraries/
+.idea/shelf/
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/.name
+.idea/compiler.xml
+.idea/copyright/profiles_settings.xml
+.idea/encodings.xml
+.idea/misc.xml
+.idea/modules.xml
+.idea/scopes/scope_settings.xml
+.idea/dictionaries
+.idea/vcs.xml
+.idea/jsLibraryMappings.xml
+.idea/datasources.xml
+.idea/dataSources.ids
+.idea/sqlDataSources.xml
+.idea/dynamic.xml
+.idea/uiDesigner.xml
+.idea/assetWizardSettings.xml
+.idea/gradle.xml
+.idea/jarRepositories.xml
+.idea/navEditor.xml
+
+### Kotlin ###
+# Compiled class file
+*.class
+
### IntelliJ IDEA ###
.idea
*.iws
@@ -31,5 +61,11 @@ out/
### VS Code ###
.vscode/
-### Mac OS ###
+### macOS ###
+# General
.DS_Store
+.AppleDouble
+.LSOverride
+
+# Local configuration file (sdk path, etc)
+local.properties
From 049e9132553c1a4710053cc2534704ee3785393f Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:05:58 +0900
Subject: [PATCH 06/15] =?UTF-8?q?feat($InputView):=20=EC=82=AC=EC=9A=A9?=
=?UTF-8?q?=EC=9E=90=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=9E=85=EB=A0=A5=20?=
=?UTF-8?q?=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/View/InputView.kt | 53 +++++++++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 src/main/kotlin/lotto/View/InputView.kt
diff --git a/src/main/kotlin/lotto/View/InputView.kt b/src/main/kotlin/lotto/View/InputView.kt
new file mode 100644
index 000000000..18da57e50
--- /dev/null
+++ b/src/main/kotlin/lotto/View/InputView.kt
@@ -0,0 +1,53 @@
+package lotto.View
+
+import camp.nextstep.edu.missionutils.Console
+import lotto.InputValidation
+import lotto.Lotto
+import lotto.LottoResult
+
+class InputView {
+ fun inputPurchaseLotto(): Int {
+ println("구입금액을 입력해 주세요.")
+
+ while (true) {
+ try {
+ val lottoPayment = Console.readLine().toIntOrNull()
+ ?: throw IllegalArgumentException("[ERROR] 구입 금액은 숫자로 입력해야 합니다.")
+
+ return lottoAmount
+ } catch (e: IllegalArgumentException) {
+ println(e.message)
+ }
+ }
+
+ }
+
+ fun inputLottoNum(): List {
+ println("당첨 번호를 입력해 주세요.")
+
+ while (true) {
+ try {
+ val lottoNum = Console.readLine().split(",")
+
+ return lottoNum
+ } catch (e: IllegalArgumentException) {
+ println(e.message)
+ }
+ }
+ }
+
+ fun inputBonusLottoNum(lottoNum: List): Int {
+ println("보너스 번호를 입력해 주세요.")
+ while (true) {
+ try {
+ val bonusLottoNum = Console.readLine().toIntOrNull()
+ ?: throw IllegalArgumentException("[ERROR] 구입 금액은 숫자로 입력해야 합니다.")
+
+ return bonusLottoNum
+ } catch (e: IllegalArgumentException) {
+ // 예외 메시지를 출력하고 재입력을 받도록 한다.
+ println(e.message)
+ }
+ }
+ }
+}
\ No newline at end of file
From 85f2d52addf236e79c9c16b252740cda0f7f6d61 Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:06:39 +0900
Subject: [PATCH 07/15] =?UTF-8?q?feat($InputValidation):=20=EC=82=AC?=
=?UTF-8?q?=EC=9A=A9=EC=9E=90=EA=B0=80=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?=
=?UTF-8?q?=EA=B0=92=EC=9D=84=20=EC=9E=85=EB=A0=A5=ED=95=A0=20=EA=B2=BD?=
=?UTF-8?q?=EC=9A=B0=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EA=B8=B0?=
=?UTF-8?q?=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/InputValidation.kt | 40 ++++++++++++++++++++++++
src/main/kotlin/lotto/View/InputView.kt | 7 +++++
2 files changed, 47 insertions(+)
create mode 100644 src/main/kotlin/lotto/InputValidation.kt
diff --git a/src/main/kotlin/lotto/InputValidation.kt b/src/main/kotlin/lotto/InputValidation.kt
new file mode 100644
index 000000000..94f0aa719
--- /dev/null
+++ b/src/main/kotlin/lotto/InputValidation.kt
@@ -0,0 +1,40 @@
+package lotto
+
+class InputValidation {
+
+ fun checkPayment(payment: Int) {
+ if(payment <= 0) {
+ throw IllegalArgumentException("[ERROR] 구입 금액은 1000원 이상 입력해야 합니다.")
+ }
+
+ if((payment%1000) != 0) {
+ throw IllegalArgumentException("[ERROR] 구입 금액은 1000원 단위로 입력해야 합니다.")
+ }
+ }
+
+ fun checkLottoNum(lottoNum: List) {
+ lottoNum.forEach { num ->
+ val lottoNumber = num.toIntOrNull() ?: throw IllegalArgumentException("[ERROR] 당첨 번호는 정수로 입력해야 합니다.")
+
+ if (lottoNumber !in 1..45) {
+ throw IllegalArgumentException("[ERROR] 당첨 번호는 1~45까지의 숫자로만 입력해야 합니다. : $num")
+ }
+ }
+
+ if(lottoNum.size != 6) {
+ throw IllegalArgumentException("[ERROR] 당첨 번호는 6개 입력해야 합니다.")
+ }
+ }
+
+ fun checkBonusLottoNum(bonusLottoNum: Int) {
+ if(bonusLottoNum !in 1..45) {
+ throw IllegalArgumentException("[ERROR] 보너스 번호는 1~45까지의 숫자로만 입력해야 합니다. : $bonusLottoNum")
+ }
+ }
+
+ fun checkDuplicate(lottoNum: List, bonusLottoNum: Int) {
+ if(lottoNum.contains(bonusLottoNum)) {
+ throw IllegalArgumentException("[ERROR] 로또 당첨 번호는 중복이 아닌 6개의 숫자여야 합니다.")
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/lotto/View/InputView.kt b/src/main/kotlin/lotto/View/InputView.kt
index 18da57e50..51ae733a3 100644
--- a/src/main/kotlin/lotto/View/InputView.kt
+++ b/src/main/kotlin/lotto/View/InputView.kt
@@ -14,6 +14,8 @@ class InputView {
val lottoPayment = Console.readLine().toIntOrNull()
?: throw IllegalArgumentException("[ERROR] 구입 금액은 숫자로 입력해야 합니다.")
+ val lottoAmount = LottoResult().checkAmount(lottoPayment)
+
return lottoAmount
} catch (e: IllegalArgumentException) {
println(e.message)
@@ -29,6 +31,8 @@ class InputView {
try {
val lottoNum = Console.readLine().split(",")
+ InputValidation().checkLottoNum(lottoNum)
+
return lottoNum
} catch (e: IllegalArgumentException) {
println(e.message)
@@ -43,6 +47,9 @@ class InputView {
val bonusLottoNum = Console.readLine().toIntOrNull()
?: throw IllegalArgumentException("[ERROR] 구입 금액은 숫자로 입력해야 합니다.")
+ InputValidation().checkBonusLottoNum(bonusLottoNum)
+ InputValidation().checkDuplicate(lottoNum, bonusLottoNum)
+
return bonusLottoNum
} catch (e: IllegalArgumentException) {
// 예외 메시지를 출력하고 재입력을 받도록 한다.
From baff899f31d338910d22b9afdeefa74b48f6b9cb Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:08:14 +0900
Subject: [PATCH 08/15] =?UTF-8?q?feat($Lotto):=20=EC=82=AC=EC=9A=A9?=
=?UTF-8?q?=EC=9E=90=EA=B0=80=20=EB=A1=9C=EB=98=90=20=EB=8B=B9=EC=B2=A8=20?=
=?UTF-8?q?=EB=B2=88=ED=98=B8=EB=A5=BC=20=EC=9E=98=EB=AA=BB=20=EC=9E=85?=
=?UTF-8?q?=EB=A0=A5=ED=95=A0=20=EA=B2=BD=EC=9A=B0=20=EC=98=88=EC=99=B8?=
=?UTF-8?q?=EC=B2=98=EB=A6=AC=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
- 로또 당첨 번호가 중복되는 경우
- 로또 당첨 번호가 1~45까지의 숫자에 포함되지 않는 경우
- 로또 당첨 번호가 공백인 경우
---
src/main/kotlin/lotto/Lotto.kt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt
index b97abc385..a9ce36f6b 100644
--- a/src/main/kotlin/lotto/Lotto.kt
+++ b/src/main/kotlin/lotto/Lotto.kt
@@ -1,8 +1,13 @@
package lotto
class Lotto(private val numbers: List) {
+
init {
require(numbers.size == 6) { "[ERROR] 로또 번호는 6개여야 합니다." }
+ require(numbers.size == numbers.distinct().size) { "[ERROR] 로또 당첨 번호는 중복이 아닌 6개의 숫자여야 합니다." }
+ require(numbers.all { it in 1..45}) {"[ERROR] 로또 당첨 번호는 1~45까지의 숫자로만 입력해야 합니다."}
+ require(numbers.isNotEmpty()) {"[ERROR] 로또 당첨 번호는 중복이 아닌 6개의 숫자여야 합니다."}
+ }
}
// TODO: 추가 기능 구현
From 865bf59fac007c6f4a0b8569b9fdb5c641ddb5bf Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:10:38 +0900
Subject: [PATCH 09/15] =?UTF-8?q?feat($OutputView):=20=EB=A1=9C=EB=98=90?=
=?UTF-8?q?=20=EA=B5=AC=EC=9E=85=20=EA=B8=88=EC=95=A1=EC=97=90=20=ED=95=B4?=
=?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EB=A1=9C=EB=98=90=20=EB=B0=9C?=
=?UTF-8?q?=ED=96=89=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/View/OutputView.kt | 25 ++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 src/main/kotlin/lotto/View/OutputView.kt
diff --git a/src/main/kotlin/lotto/View/OutputView.kt b/src/main/kotlin/lotto/View/OutputView.kt
new file mode 100644
index 000000000..96093b500
--- /dev/null
+++ b/src/main/kotlin/lotto/View/OutputView.kt
@@ -0,0 +1,25 @@
+package lotto.View
+
+import camp.nextstep.edu.missionutils.Randoms
+import lotto.Lotto
+import lotto.LottoResult
+
+class OutputView {
+
+ fun outputLottoNum(amount: Int): MutableList> {
+
+ println("${amount}개를 구매했습니다.")
+
+ var outputLotto = mutableListOf>()
+
+ for (num in 0 until amount) {
+ outputLotto.add(Randoms.pickUniqueNumbersInRange(1, 45, 6).sorted())
+ }
+
+ outputLotto.forEach { lottoNumbers ->
+ println(lottoNumbers)
+ }
+
+ return outputLotto
+ }
+}
\ No newline at end of file
From a77f55cb5846201691689f1291aa9cb907a2d8d3 Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:11:55 +0900
Subject: [PATCH 10/15] =?UTF-8?q?feat($Lotto):=20=EB=A1=9C=EB=98=90=20?=
=?UTF-8?q?=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8=20=EB=B0=8F=20=EB=B3=B4?=
=?UTF-8?q?=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=20=EB=B9=84=EA=B5=90=20?=
=?UTF-8?q?=EB=B0=8F=20=EB=8B=B9=EC=B2=A8=20=EA=B2=B0=EA=B3=BC=20=EC=B6=94?=
=?UTF-8?q?=EC=B6=9C=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/Lotto.kt | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt
index a9ce36f6b..d7946451b 100644
--- a/src/main/kotlin/lotto/Lotto.kt
+++ b/src/main/kotlin/lotto/Lotto.kt
@@ -1,5 +1,6 @@
package lotto
+
class Lotto(private val numbers: List) {
init {
@@ -8,7 +9,29 @@ class Lotto(private val numbers: List) {
require(numbers.all { it in 1..45}) {"[ERROR] 로또 당첨 번호는 1~45까지의 숫자로만 입력해야 합니다."}
require(numbers.isNotEmpty()) {"[ERROR] 로또 당첨 번호는 중복이 아닌 6개의 숫자여야 합니다."}
}
+
+ fun checkMatch(outputLottoNumbers: MutableList>, bonusLottoNum: Int): MutableList {
+ val results = MutableList(5) { 0 }
+
+ outputLottoNumbers.forEach { outputNum ->
+ val count = outputNum.count { it in numbers }
+ val isBonusMatch = bonusLottoNum in outputNum
+ val rank = checkWinning(count, isBonusMatch)
+
+ rank?.let { results[it] += 1 }
+ }
+
+ return results
}
- // TODO: 추가 기능 구현
+ fun checkWinning(count: Int, bonusMatch: Boolean): Int? {
+ return when {
+ count == 6 -> 4 // 1등
+ count == 5 && bonusMatch -> 3 // 2등
+ count == 5 -> 2 // 3등
+ count == 4 -> 1 // 4등
+ count == 3 -> 0 // 5등
+ else -> null
+ }
+ }
}
From 4fb1766f8d12d2716a91576a477b557e989c085e Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:14:33 +0900
Subject: [PATCH 11/15] =?UTF-8?q?feat($LottoResult):=20=EB=A1=9C=EB=98=90?=
=?UTF-8?q?=20=EC=88=98=EC=9D=B5=EB=A5=A0=20=EA=B3=84=EC=82=B0=20=EA=B8=B0?=
=?UTF-8?q?=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/LottoResult.kt | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 src/main/kotlin/lotto/LottoResult.kt
diff --git a/src/main/kotlin/lotto/LottoResult.kt b/src/main/kotlin/lotto/LottoResult.kt
new file mode 100644
index 000000000..8420c1b1f
--- /dev/null
+++ b/src/main/kotlin/lotto/LottoResult.kt
@@ -0,0 +1,24 @@
+package lotto
+
+class LottoResult {
+
+ fun checkAmount(payment: Int): Int {
+ InputValidation().checkPayment(payment)
+
+ return (payment / 1000)
+ }
+
+ fun calculateRevenueRate(payment: Int, results: List): Double {
+ val revenue = calculateRevenue(results)
+
+ return if (payment == 0) 0.00 else String.format("%.2f", (revenue / payment) * 100).toDouble()
+ }
+
+ fun calculateRevenue(results: List): Double {
+ val earningPerRank = listOf(5000, 50000, 1500000, 30000000, 2000000000)
+
+ val totalEarnings = results.zip(earningPerRank).sumOf { (count, earning) -> count * earning }
+
+ return totalEarnings.toDouble()
+ }
+}
\ No newline at end of file
From fa90a26102c4cfaae4882417619ed3b9b9942c52 Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:15:12 +0900
Subject: [PATCH 12/15] =?UTF-8?q?feat($OutputView):=20=EB=A1=9C=EB=98=90?=
=?UTF-8?q?=20=EB=8B=B9=EC=B2=A8=20=EB=82=B4=EC=97=AD=20=EB=B0=8F=20?=
=?UTF-8?q?=EC=88=98=EC=9D=B5=EB=A5=A0=20=EA=B2=B0=EA=B3=BC=20=EC=B6=9C?=
=?UTF-8?q?=EB=A0=A5=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/View/OutputView.kt | 27 ++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/src/main/kotlin/lotto/View/OutputView.kt b/src/main/kotlin/lotto/View/OutputView.kt
index 96093b500..ac86d18b2 100644
--- a/src/main/kotlin/lotto/View/OutputView.kt
+++ b/src/main/kotlin/lotto/View/OutputView.kt
@@ -22,4 +22,31 @@ class OutputView {
return outputLotto
}
+
+ fun outputResult(
+ payment: Int,
+ outputLottoNum: MutableList>,
+ lottoNum: List,
+ bonusLottoNum: Int
+ ) {
+ println("당첨 통계\n---")
+
+ val matchResult = Lotto(lottoNum).checkMatch(outputLottoNum, bonusLottoNum)
+
+ val matchCountLabels = listOf(
+ "3개 일치 (5,000원) -",
+ "4개 일치 (50,000원) -",
+ "5개 일치 (1,500,000원) -",
+ "5개 일치, 보너스 볼 일치 (30,000,000원) -",
+ "6개 일치 (2,000,000,000원) -"
+ )
+
+ matchResult.forEachIndexed { index, count ->
+ println("${matchCountLabels[index]} ${count}개")
+ }
+
+ val revenue = LottoResult().calculateRevenueRate(payment, matchResult)
+
+ println("총 수익률은 ${revenue}%입니다.")
+ }
}
\ No newline at end of file
From f0657ec1c8e4e60c7a887f0906fcb8e50ae395de Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:15:46 +0900
Subject: [PATCH 13/15] =?UTF-8?q?feat($LottoController):=20=EB=A1=9C?=
=?UTF-8?q?=EB=98=90=20=EB=B0=9C=EB=A7=A4=EA=B8=B0=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
---
src/main/kotlin/lotto/LottoController.kt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 src/main/kotlin/lotto/LottoController.kt
diff --git a/src/main/kotlin/lotto/LottoController.kt b/src/main/kotlin/lotto/LottoController.kt
new file mode 100644
index 000000000..0bedf5928
--- /dev/null
+++ b/src/main/kotlin/lotto/LottoController.kt
@@ -0,0 +1,20 @@
+package lotto
+
+import lotto.View.InputView
+import lotto.View.OutputView
+
+class LottoController {
+
+ private var inputView = InputView()
+ private var outputView = OutputView()
+
+
+ fun run() {
+ val lottoAmount = inputView.inputPurchaseLotto()
+ val outputLottoNum = outputView.outputLottoNum(lottoAmount)
+ val lottoNum = inputView.inputLottoNum().map { it.toIntOrNull() ?: throw IllegalArgumentException("[ERROR] 당첨 번호는 정수로 입력해야 합니다.")}
+ val bonusLottoNum = inputView.inputBonusLottoNum(lottoNum)
+
+ outputView.outputResult(lottoAmount*1000, outputLottoNum, lottoNum, bonusLottoNum)
+ }
+}
\ No newline at end of file
From 1e7de4259a67e14c1ca234f4477f1b6ffe827bcd Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:16:10 +0900
Subject: [PATCH 14/15] =?UTF-8?q?feat($Application.kt):=20=EB=A1=9C?=
=?UTF-8?q?=EB=98=90=20=EB=B0=9C=EB=A7=A4=EA=B8=B0=20=EC=8B=A4=ED=96=89=20?=
=?UTF-8?q?=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 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt
index 151821c9c..c0477a6af 100644
--- a/src/main/kotlin/lotto/Application.kt
+++ b/src/main/kotlin/lotto/Application.kt
@@ -1,5 +1,5 @@
package lotto
fun main() {
- // TODO: 프로그램 구현
+ LottoController().run()
}
From c0dd6feefa0ef5a6103a02970a5e89cdd3cdc164 Mon Sep 17 00:00:00 2001
From: PIYUJIN
Date: Mon, 4 Nov 2024 23:16:44 +0900
Subject: [PATCH 15/15] =?UTF-8?q?feat($LottoTest):=20=EC=82=AC=EC=9A=A9?=
=?UTF-8?q?=EC=9E=90=EA=B0=80=20=EC=9E=98=EB=AA=BB=EB=90=9C=20=EA=B0=92?=
=?UTF-8?q?=EC=9D=84=20=EC=9E=85=EB=A0=A5=ED=95=A0=20=EA=B2=BD=EC=9A=B0=20?=
=?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=ED=85=8C=EC=8A=A4?=
=?UTF-8?q?=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=9E=91=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/test/kotlin/lotto/LottoTest.kt | 50 ++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/src/test/kotlin/lotto/LottoTest.kt b/src/test/kotlin/lotto/LottoTest.kt
index 122fae572..080cfdead 100644
--- a/src/test/kotlin/lotto/LottoTest.kt
+++ b/src/test/kotlin/lotto/LottoTest.kt
@@ -20,4 +20,54 @@ class LottoTest {
}
// TODO: 추가 기능 구현에 따른 테스트 코드 작성
+ @Test
+ fun `로또 번호의 개수가 6개 이하면 예외가 발생한다`() {
+ assertThrows {
+ Lotto(listOf(1, 2, 3, 4, 5))
+ }
+ }
+
+ @Test
+ fun `로또 번호가 1~45까지의 숫자가 아닌 경우 예외가 발생한다`() {
+ assertThrows {
+ Lotto(listOf(1, 2, 3, 4, 5, 55))
+ }
+
+ assertThrows {
+ Lotto(listOf(1, 2, 3, 4, 5, 0))
+ }
+ }
+
+ @Test
+ fun `보너스 번호가 1~45까지의 숫자가 아닌 경우 예외가 발생한다`() {
+
+ assertThrows {
+ val bonusLottoNum = 46
+ InputValidation().checkBonusLottoNum(bonusLottoNum)
+ }
+
+ assertThrows {
+ val bonusLottoNum = 0
+ InputValidation().checkBonusLottoNum(bonusLottoNum)
+ }
+ }
+
+ @Test
+ fun `당첨 번호 및 보너스 번호에 중복된 숫자가 있으면 예외가 발생한다`() {
+ val lottoNum = listOf(1, 2, 3, 4, 5, 6)
+ val bonusLottoNum = 1
+
+ assertThrows {
+ InputValidation().checkDuplicate(lottoNum, bonusLottoNum)
+ }
+ }
+
+ @Test
+ fun `로또 구입 금액이 1,000원으로 나누어 떨어지지 않으면 예외가 발생한다`() {
+ val lottoPayment = 1500
+
+ assertThrows {
+ InputValidation().checkPayment(lottoPayment)
+ }
+ }
}