diff --git a/README.md b/README.md index 5fa2560b46..f77def8eee 100644 --- a/README.md +++ b/README.md @@ -1 +1,138 @@ -# java-lotto-precourse +# ๋กœ๋˜ (Lotto) + +## ๐Ÿ“Œ ๊ฐœ์š” +- ๋กœ๋˜ ๋ฐœ๋งค๊ธฐ ์ฝ˜์†” ํ”„๋กœ๊ทธ๋žจ์„ **TDD**๋กœ ๊ตฌํ˜„ํ•œ๋‹ค. +- ์ž…๋ ฅ: ๊ตฌ์ž… ๊ธˆ์•ก, ๋‹น์ฒจ ๋ฒˆํ˜ธ(์‰ผํ‘œ ๊ตฌ๋ถ„ 6๊ฐœ), ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ(1๊ฐœ) +- ์ถœ๋ ฅ: ๋ฐœํ–‰๋œ ๋กœ๋˜ ๋ชฉ๋ก(์˜ค๋ฆ„์ฐจ์ˆœ), ๋‹น์ฒจ ํ†ต๊ณ„(๋“ฑ์ˆ˜๋ณ„ ๊ฐœ์ˆ˜), ์ด ์ˆ˜์ต๋ฅ (์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ ๋ฐ˜์˜ฌ๋ฆผ) + +> ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ์•ฝ, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ทœ์น™, ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ(๋“ค์—ฌ์“ฐ๊ธฐ/๋ผ์ธ ๊ธธ์ด/๋ฉ”์„œ๋“œ ๊ธธ์ด/elseยทswitch ๊ธˆ์ง€)๋ฅผ ์ค€์ˆ˜ํ•œ๋‹ค. + +--- + +## โœ… ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ ์ •๋ฆฌ (๋ฌด์—‡์„) +- ๋กœ๋˜ ๋ฒˆํ˜ธ์˜ ๋ฒ”์œ„๋Š” **1~45**. +- **1์žฅ๋‹น 6๊ฐœ**์˜ **์ค‘๋ณต ์—†๋Š”** ๋ฒˆํ˜ธ๋กœ ๊ตฌ์„ฑ. +- ๊ตฌ์ž… ๊ธˆ์•ก ์ž…๋ ฅ ์‹œ, **1,000์› ๋‹จ์œ„**์ธ์ง€ ํ™•์ธํ•˜๊ณ  ๊ธˆ์•ก์— ๋น„๋ก€ํ•ด **์žฅ ์ˆ˜**๋ฅผ ๊ณ„์‚ฐํ•ด ๋ฐœํ–‰ํ•œ๋‹ค. (1์žฅ ๊ฐ€๊ฒฉ: 1,000์›) +- ๋‹น์ฒจ ๋ฒˆํ˜ธ 6๊ฐœ(์ค‘๋ณต ์—†์Œ, ๋ฒ”์œ„ ๋‚ด)๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. +- ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ 1๊ฐœ(๋ฒ”์œ„ ๋‚ด, ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ **์ค‘๋ณต ๋ถˆ๊ฐ€**)๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. +- ๊ตฌ๋งคํ•œ ๊ฐ ๋กœ๋˜๋ฅผ ๋‹น์ฒจ ๋ฒˆํ˜ธ/๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ์™€ ๋น„๊ตํ•ด **๋‹น์ฒจ ๋“ฑ์ˆ˜**๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค. +- ๋“ฑ์ˆ˜/์ƒ๊ธˆ + - 1๋“ฑ: 6๊ฐœ ์ผ์น˜ / 2,000,000,000์› + - 2๋“ฑ: 5๊ฐœ ์ผ์น˜ + ๋ณด๋„ˆ์Šค ์ผ์น˜ / 30,000,000์› + - 3๋“ฑ: 5๊ฐœ ์ผ์น˜ / 1,500,000์› + - 4๋“ฑ: 4๊ฐœ ์ผ์น˜ / 50,000์› + - 5๋“ฑ: 3๊ฐœ ์ผ์น˜ / 5,000์› +- ๋‹น์ฒจ ํ†ต๊ณ„(๋“ฑ์ˆ˜๋ณ„ ๊ฐœ์ˆ˜)์™€ **์ด ์ˆ˜์ต๋ฅ **์„ ์ถœ๋ ฅํ•œ๋‹ค. + ์ˆ˜์ต๋ฅ  = (์ด ๋‹น์ฒจ๊ธˆ ํ•ฉ / ์ด ๊ตฌ์ž… ๊ธˆ์•ก) ร— 100, **์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ์—์„œ ๋ฐ˜์˜ฌ๋ฆผ** (์˜ˆ: `100.0%`, `51.5%`) +- **์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ**: ๋ฐ˜๋“œ์‹œ `IllegalArgumentException` ๋˜๋Š” `IllegalStateException` ๋“ฑ์˜ **๋ช…ํ™•ํ•œ ์œ ํ˜•**์œผ๋กœ ๋˜์ง€๊ณ , + ๋ฉ”์‹œ์ง€๋Š” **"[ERROR]"๋กœ ์‹œ์ž‘**ํ•ด์•ผ ํ•˜๋ฉฐ, **๊ทธ ๋ถ€๋ถ„๋ถ€ํ„ฐ ์ž…๋ ฅ์„ ๋‹ค์‹œ ๋ฐ›๋Š”๋‹ค**. + +--- + +## ๐Ÿงพ ์ž…์ถœ๋ ฅ ๋ช…์„ธ + +### ์ž…๋ ฅ +1. ๊ตฌ์ž… ๊ธˆ์•ก: ์ •์ˆ˜, **1,000์› ๋‹จ์œ„**, 1,000์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ + ์˜ˆ) `14000` +2. ๋‹น์ฒจ ๋ฒˆํ˜ธ: ์‰ผํ‘œ(`,`)๋กœ ๊ตฌ๋ถ„๋œ 6๊ฐœ ์ •์ˆ˜, **์ค‘๋ณต ์—†์Œ**, ๋ฒ”์œ„ 1~45 + ์˜ˆ) `1,2,3,4,5,6` +3. ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ: ์ •์ˆ˜ 1๊ฐœ, ๋ฒ”์œ„ 1~45, **๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต ๋ถˆ๊ฐ€** + ์˜ˆ) `7` + +### ์ถœ๋ ฅ +- ๋ฐœํ–‰ ๊ฐœ์ˆ˜ ๋ฐ ๊ฐ ๋กœ๋˜ ๋ฒˆํ˜ธ(์˜ค๋ฆ„์ฐจ์ˆœ) + 8๊ฐœ๋ฅผ ๊ตฌ๋งคํ–ˆ์Šต๋‹ˆ๋‹ค.
+ [8, 21, 23, 41, 42, 43]
+ ... +- ๋‹น์ฒจ ํ†ต๊ณ„ ๋ฐ ์ด ์ˆ˜์ต๋ฅ 
+ ๋‹น์ฒจ ํ†ต๊ณ„
+ 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%์ž…๋‹ˆ๋‹ค. + +### ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€ ์˜ˆ์‹œ +- `[ERROR] ๊ตฌ์ž… ๊ธˆ์•ก์€ 1,000์› ๋‹จ์œ„์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.` +- `[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 45 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.` +- `[ERROR] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” 6๊ฐœ์˜ ์ค‘๋ณต๋˜์ง€ ์•Š๋Š” ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.` +- `[ERROR] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.` + +--- + +## ๐Ÿ”ง ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/์ œ์•ฝ +- **Randoms**: `camp.nextstep.edu.missionutils.Randoms` +- ์‚ฌ์šฉ: `Randoms.pickUniqueNumbersInRange(1, 45, 6)` โ†’ **์ค‘๋ณต ์—†๋Š” 6๊ฐœ** ๋ฒˆํ˜ธ +- **Console**: `camp.nextstep.edu.missionutils.Console` +- ์‚ฌ์šฉ: `Console.readLine()` (์ž…๋ ฅ) / ์ข…๋ฃŒ ์‹œ `Console.close()` +- `System.exit()` **์‚ฌ์šฉ ๊ธˆ์ง€** +- **JDK 21**, **build.gradle ์ˆ˜์ • ๋ถˆ๊ฐ€**, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ๊ธˆ์ง€ +- **Java Style Guide**(4 space ๋“ค์—ฌ์“ฐ๊ธฐ, 120์ž ๋ผ์ธ ๋“ฑ) ์ค€์ˆ˜ +- **indent depth โ‰ค 2**, **๋ฉ”์„œ๋“œ ๊ธธ์ด โ‰ค 15๋ผ์ธ**, **์‚ผํ•ญ ์—ฐ์‚ฐ์ž/else/switch ๊ธˆ์ง€** + โ†’ ์กฐ๊ฑด ๋ถ„๊ธฐ: **์กฐ๊ธฐ return**๊ณผ **๋ฉ”์„œ๋“œ ๋ถ„๋ฆฌ**๋กœ ์ฒ˜๋ฆฌ +- **Java Enum ์ ์šฉ**(๋“ฑ์ˆ˜/์ƒ๊ธˆ/ํŒ์ • ๋กœ์ง ๋“ฑ) + +--- + +## ๐Ÿงฑ ์„ค๊ณ„ ๊ฐœ์š” (๋ ˆ์ด์–ด/์˜์กด์„ฑ) +- **domain**: ์ˆœ์ˆ˜ ๋กœ์ง(๋ฐœํ–‰, ๊ฒ€์ฆ, ๋‹น์ฒจ ํŒ์ •, ์ˆ˜์ต๋ฅ  ๊ณ„์‚ฐ) โ€” Random/Console ์˜์กด ์—†์Œ +- `Lotto` (์ œ๊ณต ํด๋ž˜์Šค ์‚ฌ์šฉ, numbers ์™ธ ํ•„๋“œ ์ถ”๊ฐ€ ๊ธˆ์ง€) +- `LottoNumber` (๊ฐ’ ๊ฐ์ฒด, ๋ฒ”์œ„/๋น„๊ต) +- `Lottos` (๊ตฌ๋งคํ•œ ๋กœ๋˜ ์ปฌ๋ ‰์…˜) +- `WinningNumbers` (๋‹น์ฒจ 6๊ฐœ + ๋ณด๋„ˆ์Šค) +- `Rank` (Enum: ์ผ์น˜ ๊ฐœ์ˆ˜/๋ณด๋„ˆ์Šค ์—ฌ๋ถ€ โ†’ ์ƒ๊ธˆ/ํ‘œ์‹œ๋ฌธ๊ตฌ) +- `Result` (๋“ฑ์ˆ˜๋ณ„ ์ง‘๊ณ„, ์ด ์ƒ๊ธˆ, ์ˆ˜์ต๋ฅ  ๊ณ„์‚ฐ) +- `PurchaseAmount` (๊ตฌ์ž… ๊ธˆ์•ก, 1,000์› ๋‹จ์œ„ ๊ฒ€์ฆ, ๊ฐœ์ˆ˜ ๊ณ„์‚ฐ) +- **application**: ํ๋ฆ„ ์ œ์–ด/์กฐ๋ฆฝ +- `LottoMachine` (๋ฐœํ–‰๊ธฐ: Randoms ์‚ฌ์šฉ ์ง€์ ์€ ์—ฌ๊ธฐ ๋˜๋Š” ๋ณ„๋„์˜ ์–ด๋Œ‘ํ„ฐ) +- `GameRunner` (์ž…๋ ฅโ†’๋„๋ฉ”์ธโ†’์ถœ๋ ฅ) +- **view**: ์ž…์ถœ๋ ฅ ์ „๋‹ด +- `InputView` (`Console.readLine()`) +- `OutputView` (๋ฐœํ–‰ ๋ชฉ๋ก/ํ†ต๊ณ„/์ˆ˜์ต๋ฅ /์—๋Ÿฌ ์ถœ๋ ฅ) +- **main**: `Application.main()` โ€” `try/finally`์—์„œ `Console.close()` ์ฒ˜๋ฆฌ + +> `Lotto`๋Š” ์ œ๊ณต๋œ ํ˜•ํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๊ฒ€์ฆ/์ •๋ ฌ์€ ์™ธ๋ถ€์—์„œ ์™„๋ฃŒ๋œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋„˜๊ฒจ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์„ ์šฐ์„  ๊ณ ๋ คํ•œ๋‹ค. + +--- + +## ๐Ÿงช ํ…Œ์ŠคํŠธ ์ „๋žต (UI ์ œ์™ธ) +- **๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์šฐ์„ **: ๋„๋ฉ”์ธ(๊ฒ€์ฆ/์ง‘๊ณ„/์ˆ˜์ต๋ฅ )๋ถ€ํ„ฐ ์ž‘์€ ๋‹จ์œ„๋กœ +- `PurchaseAmount`: 1000 ๋‹จ์œ„/์–‘์ˆ˜ ๊ฒ€์ฆ, ๊ฐœ์ˆ˜ ๊ณ„์‚ฐ +- `LottoNumber`: ๋ฒ”์œ„/๋™๋“ฑ์„ฑ +- `WinningNumbers`: ์ž…๋ ฅ ํŒŒ์‹ฑ/์ค‘๋ณต/๋ฒ”์œ„/๋ณด๋„ˆ์Šค ์ค‘๋ณต ๊ธˆ์ง€ +- `Rank`: ์ผ์น˜ ๊ฐœ์ˆ˜/๋ณด๋„ˆ์Šค ์—ฌ๋ถ€ โ†’ ๋“ฑ์ˆ˜ ๋งคํ•‘, ์ƒ๊ธˆ +- `Result`: ๋“ฑ์ˆ˜๋ณ„ ๊ฐœ์ˆ˜ ์ง‘๊ณ„/์ด ์ƒ๊ธˆ/์ˆ˜์ต๋ฅ  ๋ฐ˜์˜ฌ๋ฆผ ๊ทœ์น™ +- **๋ฐœํ–‰๊ธฐ(Randoms)**: ๋„๋ฉ”์ธ ํ…Œ์ŠคํŠธ์—์„œ๋Š” **๋‚œ์ˆ˜ ์ง์ ‘ ์‚ฌ์šฉ ๊ธˆ์ง€** + ์ „๋žต/ํฌํŠธ ๋„์ž… ๋˜๋Š” **๊ณ ์ • ๋ฒˆํ˜ธ๋กœ ์ƒ์„ฑ**ํ•ด ๊ฒ€์ฆ. +- **ํ†ตํ•ฉ ํ๋ฆ„**: ์ตœ์ข… ํ•œ ๋ฒˆ๋งŒ(๋˜๋Š” NsTest)๋กœ ์ž…์ถœ๋ ฅ ์‹œ๋‚˜๋ฆฌ์˜ค ํ™•์ธ + +--- + +## ๐Ÿ“ ๊ทœ์น™/์ •์ฑ… ๋ฉ”๋ชจ +- **์ •๋ ฌ**: ๋ฐœํ–‰๋œ ๊ฐ ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” **์˜ค๋ฆ„์ฐจ์ˆœ** ์ •๋ ฌํ•˜์—ฌ ์ถœ๋ ฅ +- **์ˆ˜์ต๋ฅ  ํฌ๋งท**: ์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ์—์„œ ๋ฐ˜์˜ฌ๋ฆผ, `%` ํฌํ•จ (์˜ˆ: `62.5%`) +- **์žฌ์ž…๋ ฅ ๋กœ์ง**: ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ํ•ด๋‹น ์ž…๋ ฅ๋ถ€ํ„ฐ ๋‹ค์‹œ ๋ฐ›๋˜, ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ๋Š” ํ•˜์ง€ ์•Š์Œ +- **์—๋Ÿฌ ํฌ๋งท**: ๋ฉ”์‹œ์ง€๋Š” ๋ฐ˜๋“œ์‹œ `"[ERROR]"`๋กœ ์‹œ์ž‘ + +--- + +## ๐Ÿš€ ์‹คํ–‰ ์˜ˆ์‹œ(์š”์•ฝ) +๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.
+8000 + +8๊ฐœ๋ฅผ ๊ตฌ๋งคํ–ˆ์Šต๋‹ˆ๋‹ค.
+[8, 21, 23, 41, 42, 43] +... + +๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.
+1,2,3,4,5,6 + +๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.
+7 + +๋‹น์ฒจ ํ†ต๊ณ„ + +3๊ฐœ ์ผ์น˜ (5,000์›) - 1๊ฐœ
+...
+์ด ์ˆ˜์ต๋ฅ ์€ 62.5%์ž…๋‹ˆ๋‹ค. \ No newline at end of file diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..f6e7e1681c 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,10 @@ package lotto; + +import camp.nextstep.edu.missionutils.Console; + public class Application { public static void main(String[] args) { - // TODO: ํ”„๋กœ๊ทธ๋žจ ๊ตฌํ˜„ + new GameRunner().run(); } } diff --git a/src/main/java/lotto/GameRunner.java b/src/main/java/lotto/GameRunner.java new file mode 100644 index 0000000000..54ae328968 --- /dev/null +++ b/src/main/java/lotto/GameRunner.java @@ -0,0 +1,26 @@ +package lotto; + +import java.util.List; + +public class GameRunner { + + public void run() { + PurchaseAmount amount = InputView.readPurchaseAmount(); + + LottoMachine machine = new LottoMachine(); + List ticket = machine.issue(amount); + System.out.println(); + OutputView.printTickets(ticket); + + WinningNumbers winning = InputView.readWinningNumbers(); + System.out.println(); + + Result result = new Result(); + for (Lotto t : ticket) { + Rank rank = LottoJudge.judge(t, winning); + result.add(rank); + } + + OutputView.printStatistics(result, amount.value()); + } +} diff --git a/src/main/java/lotto/InputView.java b/src/main/java/lotto/InputView.java new file mode 100644 index 0000000000..01f0d667c8 --- /dev/null +++ b/src/main/java/lotto/InputView.java @@ -0,0 +1,39 @@ +package lotto; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + + private InputView() {} + + public static PurchaseAmount readPurchaseAmount() { + while (true) { + try { + System.out.println("๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + String raw = Console.readLine(); + + return new PurchaseAmount(raw); + } catch (IllegalArgumentException | IllegalStateException e) { + System.out.println(e.getMessage()); + } + } + } + + public static WinningNumbers readWinningNumbers() { + while (true) { + try { + System.out.println(); + System.out.println("๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”"); + String main = Console.readLine(); + + System.out.println(); + System.out.println("๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + String bonus = Console.readLine(); + + return WinningNumbers.of(main, bonus); + } catch (IllegalArgumentException | IllegalStateException e) { + System.out.println(e.getMessage()); + } + } + } +} diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 88fc5cf12b..ee004ece40 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -1,10 +1,16 @@ package lotto; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class Lotto { private final List numbers; + private static final String ERR_PREFIX = "[ERROR] "; + private static final String ERR_SIZE = ERR_PREFIX + "๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 6๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + private static final String ERR_DUP = ERR_PREFIX + "๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."; + public Lotto(List numbers) { validate(numbers); this.numbers = numbers; @@ -12,9 +18,30 @@ public Lotto(List numbers) { private void validate(List numbers) { if (numbers.size() != 6) { - throw new IllegalArgumentException("[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 6๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); + throw new IllegalArgumentException(ERR_SIZE); + } + + Set unique = new HashSet<>(numbers); + if (unique.size() != 6) { + throw new IllegalArgumentException(ERR_DUP); } } - // TODO: ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„ + public boolean contains(int n) { + return numbers.contains(n); + } + + public int countMatchesWith(List main) { + int cnt = 0; + + for (int n : main) { + if (numbers.contains(n)) cnt++; + } + + return cnt; + } + + public List numbers() { + return List.copyOf(numbers); + } } diff --git a/src/main/java/lotto/LottoJudge.java b/src/main/java/lotto/LottoJudge.java new file mode 100644 index 0000000000..6fa31c2fcb --- /dev/null +++ b/src/main/java/lotto/LottoJudge.java @@ -0,0 +1,12 @@ +package lotto; + +public final class LottoJudge { + + private LottoJudge() {} + + public static Rank judge(Lotto ticket, WinningNumbers winning) { + int match = ticket.countMatchesWith(winning.main()); + boolean bonus = (match == 5) && ticket.contains(winning.bonus()); + return Rank.of(match, bonus); + } +} diff --git a/src/main/java/lotto/LottoMachine.java b/src/main/java/lotto/LottoMachine.java new file mode 100644 index 0000000000..98a9fed178 --- /dev/null +++ b/src/main/java/lotto/LottoMachine.java @@ -0,0 +1,23 @@ +package lotto; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class LottoMachine { + + public List issue(PurchaseAmount amount) { + int count = amount.countTickets(); + List tickets = new ArrayList<>(count); + + for (int i = 0; i < count; i++) { + List numbers = new ArrayList<>(Randoms.pickUniqueNumbersInRange(1, 45, 6)); + Collections.sort(numbers); + tickets.add(new Lotto(numbers)); + } + + return tickets; + } +} diff --git a/src/main/java/lotto/LottoNumber.java b/src/main/java/lotto/LottoNumber.java new file mode 100644 index 0000000000..fe613b2529 --- /dev/null +++ b/src/main/java/lotto/LottoNumber.java @@ -0,0 +1,20 @@ +package lotto; + +public class LottoNumber { + public static final int MIN = 1; + public static final int MAX = 45; + private static final String ERR = "[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 45 ์‚ฌ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + + private final int value; + + public LottoNumber(int value) { + if (value < MIN || value > MAX) { + throw new IllegalArgumentException(ERR); + } + this.value = value; + } + + public int value() { + return value; + } +} diff --git a/src/main/java/lotto/LottoTicketFactory.java b/src/main/java/lotto/LottoTicketFactory.java new file mode 100644 index 0000000000..54f54b45a7 --- /dev/null +++ b/src/main/java/lotto/LottoTicketFactory.java @@ -0,0 +1,31 @@ +package lotto; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +public class LottoTicketFactory { + private static final String ERR_PREFIX = "[ERROR] "; + private static final String ERR_SIZE = ERR_PREFIX + "๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 6๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + private static final String ERR_DUP = ERR_PREFIX + "๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."; + + private LottoTicketFactory() {} + + public static List sortedUniqueSix(List src) { + if (src == null || src.size() != 6) { + throw new IllegalArgumentException(ERR_SIZE); + } + if (new HashSet<>(src).size() != 6) { + throw new IllegalArgumentException(ERR_DUP); + } + + for (int n : src) { + new LottoNumber(n); + } + + List copy = new ArrayList<>(src); + Collections.sort(copy); + return copy; + } +} diff --git a/src/main/java/lotto/OutputView.java b/src/main/java/lotto/OutputView.java new file mode 100644 index 0000000000..aef1333099 --- /dev/null +++ b/src/main/java/lotto/OutputView.java @@ -0,0 +1,39 @@ +package lotto; + +import java.util.List; +import java.util.Map; + +public class OutputView { + private static final String PURCHASED_FORMAT = "%d๊ฐœ๋ฅผ ๊ตฌ๋งคํ–ˆ์Šต๋‹ˆ๋‹ค.%n"; + private static final String STATS_TITLE = "๋‹น์ฒจ ํ†ต๊ณ„"; + private static final String STATS_DIVIDER = "---"; + + private OutputView() {} + + public static void printTickets(List tickets) { + System.out.printf(PURCHASED_FORMAT, tickets.size()); + + for (Lotto t : tickets) { + System.out.println(formatTicket(t.numbers())); + } + } + + public static void printStatistics(Result result, long spent) { + System.out.println(STATS_TITLE); + System.out.println(STATS_DIVIDER); + + Map m = result.snapshot(); + System.out.printf("3๊ฐœ ์ผ์น˜ (5,000์›) - %d๊ฐœ%n", m.get(Rank.FIFTH)); + System.out.printf("4๊ฐœ ์ผ์น˜ (50,000์›) - %d๊ฐœ%n", m.get(Rank.FOURTH)); + System.out.printf("5๊ฐœ ์ผ์น˜ (1,500,000์›) - %d๊ฐœ%n", m.get(Rank.THIRD)); + System.out.printf("5๊ฐœ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ณผ ์ผ์น˜ (30,000,000์›) - %d๊ฐœ%n", m.get(Rank.SECOND)); + System.out.printf("6๊ฐœ ์ผ์น˜ (2,000,000,000์›) - %d๊ฐœ%n", m.get(Rank.FIRST)); + + ProfitRate rate = ProfitRate.of(result.totalPrize(), spent); + System.out.printf("์ด ์ˆ˜์ต๋ฅ ์€ %s์ž…๋‹ˆ๋‹ค.%n", rate.format()); + } + + private static String formatTicket(List numbers) { + return numbers.toString(); + } +} diff --git a/src/main/java/lotto/ProfitRate.java b/src/main/java/lotto/ProfitRate.java new file mode 100644 index 0000000000..ef418cb6c6 --- /dev/null +++ b/src/main/java/lotto/ProfitRate.java @@ -0,0 +1,29 @@ +package lotto; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class ProfitRate { + private final BigDecimal percent; + + private ProfitRate(BigDecimal decimal) { + this.percent = decimal; + } + + public static ProfitRate of(long totalPrize, long spent) { + if (spent <= 0) { + return new ProfitRate(BigDecimal.ZERO); + } + + BigDecimal v = BigDecimal.valueOf(totalPrize) + .multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(spent), 10, RoundingMode.HALF_UP) + .setScale(1, RoundingMode.HALF_UP); + + return new ProfitRate(v); + } + + public String format() { + return percent.stripTrailingZeros().toPlainString() + "%"; + } +} diff --git a/src/main/java/lotto/PurchaseAmount.java b/src/main/java/lotto/PurchaseAmount.java new file mode 100644 index 0000000000..ae31f25084 --- /dev/null +++ b/src/main/java/lotto/PurchaseAmount.java @@ -0,0 +1,42 @@ +package lotto; + +public final class PurchaseAmount { + private static final long UNIT = 1_000L; + private static final String ERR_PREFIX = "[ERROR] "; + private static final String ERR_EMPTY = ERR_PREFIX + "๊ตฌ์ž… ๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."; + private static final String ERR_NUMBER = ERR_PREFIX + "๊ตฌ์ž… ๊ธˆ์•ก์€ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + private static final String ERR_POSITIVE = ERR_PREFIX + "๊ตฌ์ž… ๊ธˆ์•ก์€ 1,000์› ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + private static final String ERR_UNIT = ERR_PREFIX + "๊ตฌ์ž… ๊ธˆ์•ก์€ 1,000์› ๋‹จ์œ„์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + + private final long value; + + public PurchaseAmount(String input) { + if (input == null || input.isBlank()) { + throw new IllegalArgumentException(ERR_EMPTY); + } + + final long parsed; + try { + parsed = Long.parseLong(input.trim()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(ERR_NUMBER); + } + + if (parsed <= 0) { + throw new IllegalArgumentException(ERR_POSITIVE); + } + if (parsed % UNIT != 0) { + throw new IllegalArgumentException(ERR_UNIT); + } + + this.value = parsed; + } + + public long value() { + return value; + } + + public int countTickets() { + return (int)(value / UNIT); + } +} diff --git a/src/main/java/lotto/Rank.java b/src/main/java/lotto/Rank.java new file mode 100644 index 0000000000..1f26c371cd --- /dev/null +++ b/src/main/java/lotto/Rank.java @@ -0,0 +1,40 @@ +package lotto; + +public enum Rank { + FIRST(6, false, 2_000_000_000L, "6๊ฐœ ์ผ์น˜ (2,000,000,000์›)"), + SECOND(5, true, 30_000_000L, "5๊ฐœ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ณผ ์ผ์น˜ (30,000,000์›)"), + THIRD(5, false, 1_500_000L, "5๊ฐœ ์ผ์น˜ (1,500,000์›)"), + FOURTH(4, false, 50_000L, "4๊ฐœ ์ผ์น˜ (50,000์›)"), + FIFTH(3, false, 5_000L, "3๊ฐœ ์ผ์น˜ (5,000์›)"), + NONE(0, false, 0L, ""); + + private final int match; + private final boolean bonusRequired; + private final long prize; + private final String label; + + Rank(int match, boolean bonusRequired, long prize, String label) { + this.match = match; + this.bonusRequired = bonusRequired; + this.prize = prize; + this.label = label; + } + + public long prize() { + return prize; + } + + public String label() { + return label; + } + + public static Rank of(int matchCount, boolean bonusMatched) { + if (matchCount == 6) return FIRST; + if (matchCount == 5 && bonusMatched) return SECOND; + if (matchCount == 5) return THIRD; + if (matchCount == 4) return FOURTH; + if (matchCount == 3) return FIFTH; + + return NONE; + } +} diff --git a/src/main/java/lotto/RankResultProfit.java b/src/main/java/lotto/RankResultProfit.java new file mode 100644 index 0000000000..c2d03a88e6 --- /dev/null +++ b/src/main/java/lotto/RankResultProfit.java @@ -0,0 +1,4 @@ +package lotto; + +public class RankResultProfit { +} diff --git a/src/main/java/lotto/Result.java b/src/main/java/lotto/Result.java new file mode 100644 index 0000000000..f27bc2a23e --- /dev/null +++ b/src/main/java/lotto/Result.java @@ -0,0 +1,35 @@ +package lotto; + +import java.util.EnumMap; +import java.util.Map; + +public class Result { + private final Map counts = new EnumMap<>(Rank.class); + + public Result() { + for (Rank r : Rank.values()) { + counts.put(r, 0); + } + } + + public void add(Rank r) { + counts.put(r, counts.get(r) + 1); + } + + public int count(Rank r) { + return counts.get(r); + } + + public long totalPrize() { + long sum = 0; + for (Rank r : Rank.values()) { + sum += (long) counts.get(r) * r.prize(); + } + + return sum; + } + + public Map snapshot() { + return new EnumMap<>(counts); + } +} diff --git a/src/main/java/lotto/WinningNumbers.java b/src/main/java/lotto/WinningNumbers.java new file mode 100644 index 0000000000..209b92f3f4 --- /dev/null +++ b/src/main/java/lotto/WinningNumbers.java @@ -0,0 +1,62 @@ +package lotto; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class WinningNumbers { + private static final String ERR_PREFIX = "[ERROR] "; + private static final String ERR_MAIN_FORMAT = ERR_PREFIX + "๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ์‰ผํ‘œ(,)๋กœ ๊ตฌ๋ถ„๋œ 6๊ฐœ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + private static final String ERR_BONUS_RANGE = ERR_PREFIX + "๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 45 ์‚ฌ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."; + private static final String ERR_BONUS_DUP = ERR_PREFIX + "๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."; + + private final List main; + private final int bonus; + + private WinningNumbers(List main, int bonus) { + this.main = main; + this.bonus = bonus; + } + + public static WinningNumbers of(String mainCsv, String bonusInput) { + List parsed = parseCsv(mainCsv); + List sorted = LottoTicketFactory.sortedUniqueSix(parsed); + int bonus = parseBonus(bonusInput); + + if (sorted.contains(bonus)) { + throw new IllegalArgumentException(ERR_BONUS_DUP); + } + + return new WinningNumbers(sorted, bonus); + } + + private static int parseBonus(String s) { + try { + int v = Integer.parseInt(s.trim()); + new LottoNumber(v); + + return v; + } catch (Exception e) { + throw new IllegalArgumentException(ERR_BONUS_RANGE); + } + } + + private static List parseCsv(String csv) { + try { + return Arrays.stream(csv.split(",")) + .map(String::trim) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalArgumentException(ERR_MAIN_FORMAT); + } + } + + public List main() { + return List.copyOf(main); + } + + public int bonus() { + return bonus; + } +} diff --git a/src/test/java/lotto/LottoMachineTest.java b/src/test/java/lotto/LottoMachineTest.java new file mode 100644 index 0000000000..76fca4ea11 --- /dev/null +++ b/src/test/java/lotto/LottoMachineTest.java @@ -0,0 +1,26 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import java.util.List; +import static org.junit.jupiter.api.Assertions.*; + +class LottoMachineTest { + + @Test + void ๊ธˆ์•ก๋งŒํผ_๋ฐœํ–‰ํ•˜๊ณ _๊ฐ_ํ‹ฐ์ผ“์€_6๊ฐœ_์ •๋ ฌ() { + LottoMachine m = new LottoMachine(); + var tickets = m.issue(new PurchaseAmount("3000")); + assertEquals(3, tickets.size()); + + for (Lotto t : tickets) { + assertEquals(6, tNumbers(t).size()); + List nums = tNumbers(t); + + for (int i = 0; i < 5; i++) assertTrue(nums.get(i) < nums.get(i+1)); + } + } + + private List tNumbers(Lotto t) { + return List.of(1,2,3,4,5,6); + } +} diff --git a/src/test/java/lotto/LottoNumberTest.java b/src/test/java/lotto/LottoNumberTest.java new file mode 100644 index 0000000000..eb2c5ded32 --- /dev/null +++ b/src/test/java/lotto/LottoNumberTest.java @@ -0,0 +1,37 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import java.util.List; +import static org.junit.jupiter.api.Assertions.*; + +class LottoNumberAndFactoryTest { + + @Test + void LottoNumber_๋ฒ”์œ„_1_์—์„œ_45() { + assertDoesNotThrow(() -> new LottoNumber(1)); + assertDoesNotThrow(() -> new LottoNumber(45)); + assertThrows(IllegalArgumentException.class, () -> new LottoNumber(0)); + assertThrows(IllegalArgumentException.class, () -> new LottoNumber(46)); + } + + @Test + void ์ˆซ์ž_6๊ฐœ_์ •๋ ฌ๋˜๊ณ _์ค‘๋ณต์—†์–ด์•ผ() { + List made = LottoTicketFactory.sortedUniqueSix(List.of(8, 21, 23, 41, 42, 43)); + assertEquals(List.of(8,21,23,41,42,43), made); + } + + @Test + void ๊ฐœ์ˆ˜_6๊ฐœ_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> LottoTicketFactory.sortedUniqueSix(List.of(1,2,3,4,5))); + } + + @Test + void ์ค‘๋ณต์ด_์žˆ์œผ๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> LottoTicketFactory.sortedUniqueSix(List.of(1,1,3,4,5,6))); + } + + @Test + void ๋ฒ”์œ„๋ฐ–_์ˆซ์ž_์žˆ์œผ๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> LottoTicketFactory.sortedUniqueSix(List.of(0,2,3,4,5,6))); + } +} diff --git a/src/test/java/lotto/MatchAggregationTest.java b/src/test/java/lotto/MatchAggregationTest.java new file mode 100644 index 0000000000..80cdf14317 --- /dev/null +++ b/src/test/java/lotto/MatchAggregationTest.java @@ -0,0 +1,29 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class MatchAggregationTest { + + @Test + void ์—ฌ๋Ÿฌ์žฅ_์ง‘๊ณ„ํ•ด์„œ_Result์—_๋ˆ„์ ํ•œ๋‹ค() { + WinningNumbers w = WinningNumbers.of("1,2,3,4,5,6","7"); + Result result = new Result(); + + List tickets = List.of( + new Lotto(List.of(1,2,3,4,5,6)), // 1๋“ฑ + new Lotto(List.of(1,2,3,4,5,7)), // 2๋“ฑ + new Lotto(List.of(1,2,3,10,11,12)) // 5๋“ฑ + ); + + for (Lotto t : tickets) result.add(LottoJudge.judge(t, w)); + + assertEquals(1, result.count(Rank.FIRST)); + assertEquals(1, result.count(Rank.SECOND)); + assertEquals(1, result.count(Rank.FIFTH)); + assertEquals(3, result.snapshot().values().stream().mapToInt(i->i).sum()); + } + +} diff --git a/src/test/java/lotto/MatchJudgeTest.java b/src/test/java/lotto/MatchJudgeTest.java new file mode 100644 index 0000000000..fccc4df12e --- /dev/null +++ b/src/test/java/lotto/MatchJudgeTest.java @@ -0,0 +1,43 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class MatchJudgeTest { + + @Test + void ์—ฌ์„ฏ๊ฐœ_์ผ์น˜๋ฉด_1๋“ฑ() { + Lotto lotto = new Lotto(List.of(1,2,3,4,5,6)); + WinningNumbers w = WinningNumbers.of("1,2,3,4,5,6", "7"); + assertEquals(Rank.FIRST, LottoJudge.judge(lotto, w)); + } + + @Test + void ๋‹ค์„ฏ๊ฐœ_์ผ์น˜_๋ณด๋„ˆ์Šค_์ผ์น˜๋ฉด_2๋“ฑ() { + Lotto lotto = new Lotto(List.of(1,2,3,4,5,7)); + WinningNumbers w = WinningNumbers.of("1,2,3,4,5,6", "7"); + assertEquals(Rank.SECOND, LottoJudge.judge(lotto, w)); + } + + @Test + void ๋‹ค์„ฏ๊ฐœ_์ผ์น˜_๋ณด๋„ˆ์Šค_๋ถˆ์ผ์น˜๋ฉด_3๋“ฑ() { + Lotto lotto = new Lotto(List.of(1,2,3,4,5,8)); + WinningNumbers w = WinningNumbers.of("1,2,3,4,5,6", "7"); + assertEquals(Rank.THIRD, LottoJudge.judge(lotto, w)); + } + + @Test + void ๋„ค๊ฐœ_์ผ์น˜๋ฉด_4๋“ฑ_์„ธ๊ฐœ๋ฉด_5๋“ฑ_๊ทธ์™ธ_NONE() { + assertEquals(Rank.FOURTH, + LottoJudge.judge(new Lotto(List.of(1,2,3,4,10,11)), + WinningNumbers.of("1,2,3,4,5,6","7"))); + assertEquals(Rank.FIFTH, + LottoJudge.judge(new Lotto(List.of(1,2,3,10,11,12)), + WinningNumbers.of("1,2,3,4,5,6","7"))); + assertEquals(Rank.NONE, + LottoJudge.judge(new Lotto(List.of(1,9,10,11,12,13)), + WinningNumbers.of("1,2,3,4,5,6","7"))); + } +} diff --git a/src/test/java/lotto/PurchaseAmountTest.java b/src/test/java/lotto/PurchaseAmountTest.java new file mode 100644 index 0000000000..1ac6421c61 --- /dev/null +++ b/src/test/java/lotto/PurchaseAmountTest.java @@ -0,0 +1,37 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class PurchaseAmountTest { + + @Test + void ์ฒœ์›_๋‹จ์œ„๋ฉด_์žฅ์ˆ˜_๊ณ„์‚ฐ๋œ๋‹ค() { + PurchaseAmount amount = new PurchaseAmount("8000"); + assertEquals(8, amount.countTickets()); + assertEquals(8000L, amount.value()); + } + + @Test + void ๋นˆ๊ฐ’_๊ณต๋ฐฑ_null_์ด๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount("")); + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount(" ")); + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount(null)); + } + + @Test + void ์ˆซ์ž๊ฐ€_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount("8a00")); + } + + @Test + void ์Œ์ˆ˜_์˜_์ด๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount("0")); + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount("-1000")); + } + + @Test + void ์ฒœ์›๋‹จ์œ„_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ() { + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount("1500")); + } +} diff --git a/src/test/java/lotto/RankResultProfitTest.java b/src/test/java/lotto/RankResultProfitTest.java new file mode 100644 index 0000000000..b73ed05b84 --- /dev/null +++ b/src/test/java/lotto/RankResultProfitTest.java @@ -0,0 +1,31 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class RankResultProfitTest { + + @Test + void ๋žญํฌ_๋งคํ•‘() { + assertEquals(Rank.FIRST, Rank.of(6, false)); + assertEquals(Rank.SECOND, Rank.of(5, true)); + assertEquals(Rank.THIRD, Rank.of(5, false)); + assertEquals(Rank.FOURTH, Rank.of(4, false)); + assertEquals(Rank.FIFTH, Rank.of(3, false)); + assertEquals(Rank.NONE, Rank.of(2, false)); + } + + @Test + void ์ง‘๊ณ„์™€_์ˆ˜์ต๋ฅ () { + Result r = new Result(); + r.add(Rank.FIFTH); + r.add(Rank.FIRST); + assertEquals(1, r.count(Rank.FIFTH)); + assertEquals(1, r.count(Rank.FIRST)); + long prize = r.totalPrize(); + assertTrue(prize > 0); + + ProfitRate rate = ProfitRate.of(prize, 8_000); + assertNotNull(rate.format()); + } +} diff --git a/src/test/java/lotto/WinningNumbersTest.java b/src/test/java/lotto/WinningNumbersTest.java new file mode 100644 index 0000000000..5b0446570f --- /dev/null +++ b/src/test/java/lotto/WinningNumbersTest.java @@ -0,0 +1,27 @@ +package lotto; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class WinningNumbersTest { + + @Test + void ํŒŒ์‹ฑ_์ •์ƒ() { + WinningNumbers w = WinningNumbers.of("1,2,3,4,5,6", "7"); + assertEquals(6, w.main().size()); + assertEquals(7, w.bonus()); + } + + @Test + void ๋ฉ”์ธ๋ฒˆํ˜ธ_6๊ฐœ_์ค‘๋ณต์—†์Œ_๋ฒ”์œ„() { + assertThrows(IllegalArgumentException.class, () -> WinningNumbers.of("1,2,3,4,5", "7")); // ๊ฐœ์ˆ˜ + assertThrows(IllegalArgumentException.class, () -> WinningNumbers.of("1,2,3,4,5,5", "7")); // ์ค‘๋ณต + assertThrows(IllegalArgumentException.class, () -> WinningNumbers.of("0,2,3,4,5,6", "7")); // ๋ฒ”์œ„ + } + + @Test + void ๋ณด๋„ˆ์Šค_๋ฒ”์œ„๋‚ด_๊ทธ๋ฆฌ๊ณ _๋ฉ”์ธ๊ณผ_์ค‘๋ณต๋ถˆ๊ฐ€() { + assertThrows(IllegalArgumentException.class, () -> WinningNumbers.of("1,2,3,4,5,6", "1")); + assertThrows(IllegalArgumentException.class, () -> WinningNumbers.of("1,2,3,4,5,6", "46")); + } +}