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
diff --git a/README.md b/README.md
index 4fc0ae874..031c22b20 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,230 @@
-# kotlin-lotto-precourse
+# [3์ฃผ์ฐจ] ๋ก๋ (kotlin-lotto-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` ๋ฑ๊ณผ ๊ฐ์ ๋ช
ํํ ์ ํ์ ์ฒ๋ฆฌํ๋ค.
+
+---
+- [ ] ๋ก๋ ๊ตฌ์
๊ธ์ก ์
๋ ฅ ๋ฐ๊ธฐ (1000์ ๋จ์)
+- [ ] ๋ก๋ ๋น์ฒจ ๋ฒํธ + ๋ณด๋์ค ๋ฒํธ ์
๋ ฅ ๋ฐ๊ธฐ (์ผํ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ตฌ๋ถ)
+- [ ] ๋ก๋ ๊ตฌ์
๊ธ์ก์ ํด๋นํ๋ ๋งํผ ๋ก๋๋ฅผ ๋ฐํ (๋ก๋ 1์ฅ ๊ฐ๊ฒฉ : 1000์)
+- [ ] 1~45๊น์ง์ ์ซ์ ์ค ์ค๋ณต๋์ง ์๋ 6๊ฐ์ ์ซ์์ ๋ณด๋์ค ๋ฒํธ 1๊ฐ ์ซ์ ์ถ์ถ
+- [ ] ์ฌ์ฉ์๊ฐ ๊ตฌ๋งคํ ๋ก๋ ๋ฒํธ์ ๋น์ฒจ ๋ฒํธ๋ฅผ ๋น๊ต โ ๋น์ฒจ ๋ด์ญ ๋ฐ ์์ต๋ฅ (์์์ ๋์งธ ์๋ฆฌ์์ ๋ฐ์ฌ๋ฆผ) ์ถ๋ ฅ ํ ๋ก๋ ๊ฒ์ ์ข
๋ฃ
+- [ ] ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฐ์ ์
๋ ฅํ ๊ฒฝ์ฐ `IllegalArgumentException`์ ๋ฐ์(`[ERROR]`๋ก ์์ํ๋ ์๋ฌ ๋ฉ์์ง)์ํจ ํ ์ ํ๋ฆฌ์ผ์ด์
์ ์ข
๋ฃ
+ - [ ] ๋ก๋ ๊ตฌ์
๊ธ์ก์ด 1,000์์ผ๋ก ๋๋์ด ๋จ์ด์ง์ง ์๋ ๊ฒฝ์ฐ
+ - [ ] ๋ก๋ ๊ตฌ์
๊ธ์ก์ด ๊ณต๋ฐฑ์ธ ๊ฒฝ์ฐ
+ - [ ] ๋น์ฒจ ๋ฒํธ๊ฐ ๊ณต๋ฐฑ์ธ ๊ฒฝ์ฐ
+ - [ ] ๋น์ฒจ ๋ฒํธ์ ์ซ์๊ฐ ์๋ ๋ค๋ฅธ ๋ฌธ์์ด์ด ํฌํจ๋ ๊ฒฝ์ฐ
+ - [ ] ๋น์ฒจ ๋ฒํธ๊ฐ 1~45๊น์ง์ ์ซ์์ ํฌํจ๋์ง ์๋ ๊ฒฝ์ฐ
+ - [ ] ๋ณด๋์ค ๋ฒํธ๊ฐ ๊ณต๋ฐฑ์ธ ๊ฒฝ์ฐ
+ - [ ] ๋ณด๋์ค ๋ฒํธ๊ฐ ์ซ์๊ฐ ์๋ ๋ค๋ฅธ ๋ฌธ์์ด์ธ ๊ฒฝ์ฐ
+ - [ ] ๋ณด๋์ค ๋ฒํธ๊ฐ 1~45๊น์ง์ ์ซ์์ ํฌํจ๋์ง ์๋ ๊ฒฝ์ฐ
+ - [ ] ๋น์ฒจ ๋ฒํธ ๋ฐ ๋ณด๋์ค ๋ฒํธ์ ์ค๋ณต๋ ์ซ์๊ฐ ์๋ ๊ฒฝ์ฐ
+---
+
+
+#### ๐ฌ ์
์ถ๋ ฅ ์๊ตฌ ์ฌํญ
+- ์
๋ ฅ :
+ - ๋ก๋ ๊ตฌ์
๊ธ์ก์ ์
๋ ฅ ๋ฐ๋๋ค. ๊ตฌ์
๊ธ์ก์ 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: ์ถ๊ฐ ๊ธฐ๋ฅ ๊ตฌํ
+}
+```
+
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()
}
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/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt
index b97abc385..d7946451b 100644
--- a/src/main/kotlin/lotto/Lotto.kt
+++ b/src/main/kotlin/lotto/Lotto.kt
@@ -1,9 +1,37 @@
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๊ฐ์ ์ซ์์ฌ์ผ ํฉ๋๋ค."}
+ }
+
+ 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
+ }
+ }
}
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
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
diff --git a/src/main/kotlin/lotto/View/InputView.kt b/src/main/kotlin/lotto/View/InputView.kt
new file mode 100644
index 000000000..51ae733a3
--- /dev/null
+++ b/src/main/kotlin/lotto/View/InputView.kt
@@ -0,0 +1,60 @@
+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] ๊ตฌ์
๊ธ์ก์ ์ซ์๋ก ์
๋ ฅํด์ผ ํฉ๋๋ค.")
+
+ val lottoAmount = LottoResult().checkAmount(lottoPayment)
+
+ return lottoAmount
+ } catch (e: IllegalArgumentException) {
+ println(e.message)
+ }
+ }
+
+ }
+
+ fun inputLottoNum(): List {
+ println("๋น์ฒจ ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.")
+
+ while (true) {
+ try {
+ val lottoNum = Console.readLine().split(",")
+
+ InputValidation().checkLottoNum(lottoNum)
+
+ 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] ๊ตฌ์
๊ธ์ก์ ์ซ์๋ก ์
๋ ฅํด์ผ ํฉ๋๋ค.")
+
+ InputValidation().checkBonusLottoNum(bonusLottoNum)
+ InputValidation().checkDuplicate(lottoNum, bonusLottoNum)
+
+ return bonusLottoNum
+ } catch (e: IllegalArgumentException) {
+ // ์์ธ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๊ณ ์ฌ์
๋ ฅ์ ๋ฐ๋๋ก ํ๋ค.
+ println(e.message)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/lotto/View/OutputView.kt b/src/main/kotlin/lotto/View/OutputView.kt
new file mode 100644
index 000000000..ac86d18b2
--- /dev/null
+++ b/src/main/kotlin/lotto/View/OutputView.kt
@@ -0,0 +1,52 @@
+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
+ }
+
+ 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
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)
+ }
+ }
}