From e64694987edffafbef24f9698f495641d51f3fb7 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 13:38:55 +0900 Subject: [PATCH 01/24] =?UTF-8?q?docs(REAME.md):=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=85=EC=84=B8=EC=84=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/README.md b/README.md index b168a180..dd71ea3b 100644 --- a/README.md +++ b/README.md @@ -1 +1,112 @@ # javascript-planetlotto-precourse + +# javascript-planetlotto-precourse + +## ๐Ÿ“‹ ์š”๊ตฌ์‚ฌํ•ญ ๋ช…์„ธ์„œ + +- ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์‹œ `"๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."` ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ `๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก`์„ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. `๋‹จ์œ„๋Š” 1,000์›`์ด๋ฉฐ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•œ๋‹ค. +- 500์› ๋‹จ์œ„๋กœ ์ž๋ฅธ ๊ฐœ์ˆ˜์ธ n์— ๋Œ€ํ•ด `"n๊ฐœ๋ฅผ ๊ตฌ๋งคํ–ˆ์Šต๋‹ˆ๋‹ค."` ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- ์ดํ›„ `"๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."` ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ `๋‹น์ฒจ ๋ฒˆํ˜ธ`๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” `์‰ผํ‘œ(,)`๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค. +- ์ดํ›„ `"๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."` ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ `๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ`๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. +- ์ž…๋ ฅ์ด ์™„๋ฃŒ๋˜๋ฉด `"๋‹น์ฒจํ†ต๊ณ„"` ๋ฉ”์„ธ์ง€์™€ `"---"`๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, `๋‹น์ฒจ ๋‚ด์—ญ`์„ ์ถœ๋ ฅํ•œ๋‹ค. +- ๋‹น์ฒจ ๋‚ด์—ญ์€ 2๊ฐœ~5๊ฐœ ์ผ์น˜ ํ•ญ๋ชฉ์„ ์ˆœ์„œ๋Œ€๋กœ ๋‹ค์Œ ํ˜•์‹์— ๋งž์ถฐ ์ถœ๋ ฅํ•œ๋‹ค. (n์€ ์‹ค์ œ ๋‹น์ฒจ๋œ ๊ฐœ์ˆ˜) + - 5๊ฐœ ๋ฒˆํ˜ธ ์ผ์น˜ (100,000,000์›) - n๊ฐœ + - 4๊ฐœ ๋ฒˆํ˜ธ, ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ผ์น˜ (10,000,000์›) - n๊ฐœ + - 4๊ฐœ ๋ฒˆํ˜ธ ์ผ์น˜ (1,500,000์›) - n๊ฐœ + - 3๊ฐœ ๋ฒˆํ˜ธ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ผ์น˜ (500,000์›) - n๊ฐœ + - 2๊ฐœ ๋ฒˆํ˜ธ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ผ์น˜ (5,000์›) - n๊ฐœ + - 0๊ฐœ ๋ฒˆํ˜ธ ์ผ์น˜ (0์›) - n๊ฐœ +- ์˜ˆ์™ธ ์ƒํ™ฉ ์‹œ `[ERROR]`๋กœ ์‹œ์ž‘ํ•˜๋Š” ์—๋Ÿฌ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, ํ•ด๋‹น ์ง€์ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +## โš™๏ธ ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ ๋ชฉ๋ก + +### LottoGameController.js + +#### 1๏ธโƒฃ ํ–‰์„ฑ๋กœ๋˜ ๊ฒŒ์ž„ ์ง„ํ–‰ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ + +- [ ] ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๊ฐ’๋“ค์€ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ๋‹ค์‹œ ๋ฐ˜๋ณตํ•ด์„œ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. + +### Lotto.js + +#### 1๏ธโƒฃ ๋กœ๋˜ ๋ฒˆํ˜ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ + +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ ๊ฐœ์ˆ˜๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๊ฐ€ ์ •์ˆ˜๊ฐ€ ์•„๋‹ ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๊ฐ€ ์ค‘๋ณต๋  ์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž๊ฐ€ ์•„๋‹ ์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. + +#### 2๏ธโƒฃ ๋กœ๋˜ ๋ฒˆํ˜ธ ๋ฐ ๋ฌธ์ž์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ + +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +### LottoGame.js + +#### 1๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ์ƒ์„ฑ ๊ธฐ๋Šฅ + +- [ ] ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์— ๋”ฐ๋ฅธ ๋กœ๋˜ ๊ฐœ์ˆ˜๋งŒํผ ๋กœ๋˜ ๊ฐ์ฒด์„ ๋งŒ๋“ค์–ด ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +#### 2๏ธโƒฃ ๋กœ๋˜ ๊ฐ์ฒด ์ƒ์„ฑ ๊ธฐ๋Šฅ + +- [ ] ํ•˜๋‚˜์˜ ๋กœ๋˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +#### 3๏ธโƒฃ ํ†ต๊ณ„ ์ƒ์„ฑ ๊ธฐ๋Šฅ + +- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ํ†ต๊ณ„ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +#### 4๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ + +- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +### WinningLotto.js + +#### 1๏ธโƒฃ ๋“ฑ์ˆ˜ ํ™•์ธ ๊ธฐ๋Šฅ + +- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋น„๊ตํ•˜์—ฌ ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +#### 2๏ธโƒฃ ๋“ฑ์ˆ˜ ์ถ”์ถœ ๊ธฐ๋Šฅ + +- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๊ฒน์น˜๋Š” ๋ฒˆํ˜ธ ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ๋ฐ›์•„ ๋“ฑ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + +### InputView + +#### 1๏ธโƒฃ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก ์ž…๋ ฅ ๊ธฐ๋Šฅ + +- [ ] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์„ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. + +#### 2๏ธโƒฃ ๋‹น์ฒจ ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ + +- [ ] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. + +#### 3๏ธโƒฃ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ + +- [ ] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. + +### OutputView + +#### 1๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ์ถœ๋ ฅ ๊ธฐ๋Šฅ + +- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋ชจ๋“  ๋กœ๋˜๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + +#### 2๏ธโƒฃ ๋‹น์ฒจ ํ†ต๊ณ„ ์ถœ๋ ฅ ๊ธฐ๋Šฅ + +- [ ] ์ „์ฒด ๋“ฑ์ˆ˜๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + +### ๐Ÿšซ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ + +- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ์ฝค๋งˆ(,) ์‚ฌ์ด์˜ ๊ณต๋ฐฑ์€ ๋ฌด์‹œํ•œ๋‹ค. +- [ ] ์˜ˆ์™ธ ์ƒํ™ฉ ์‹œ `[ERROR]`๋กœ ์‹œ์ž‘ํ•˜๋Š” ์—๋Ÿฌ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, ํ•ด๋‹น ์ง€์ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +#### โŒ [ERROR] ์ฒ˜๋ฆฌ + +- [ ] ๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์—ฌ์•ผ ํ•œ๋‹ค. + +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. +- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. + +- [ ] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. From 929007a849cda416bb2d849372d1e385b23fb784 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 13:45:33 +0900 Subject: [PATCH 02/24] =?UTF-8?q?feat(Lotto.js):=20Lotto=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=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 --- README.md | 12 ++++++------ src/model/Lotto.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/model/Lotto.js diff --git a/README.md b/README.md index dd71ea3b..8011a555 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,15 @@ #### 1๏ธโƒฃ ๋กœ๋˜ ๋ฒˆํ˜ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ ๊ฐœ์ˆ˜๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๊ฐ€ ์ •์ˆ˜๊ฐ€ ์•„๋‹ ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๊ฐ€ ์ค‘๋ณต๋  ์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž๊ฐ€ ์•„๋‹ ์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ ๊ฐœ์ˆ˜๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๊ฐ€ ์ •์ˆ˜๊ฐ€ ์•„๋‹ ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๊ฐ€ ์ค‘๋ณต๋  ์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž๊ฐ€ ์•„๋‹ ์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. #### 2๏ธโƒฃ ๋กœ๋˜ ๋ฒˆํ˜ธ ๋ฐ ๋ฌธ์ž์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ### LottoGame.js diff --git a/src/model/Lotto.js b/src/model/Lotto.js new file mode 100644 index 00000000..21dc9671 --- /dev/null +++ b/src/model/Lotto.js @@ -0,0 +1,34 @@ +class Lotto { + #numbers; // ๋กœ๋˜ ํ•œ ์žฅ์€ 5๊ฐœ์˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๊ฐ€์ง + + // ๋กœ๋˜๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” ์ž๋™์œผ๋กœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ & ์ •๋ ฌ ์ˆ˜ํ–‰ + constructor(numbers) { + this.#validate(numbers); + numbers.sort((a, b) => a - b); + this.#numbers = numbers; + } + + #validate(numbers) { + if (numbers.length !== 5) { + throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + if (numbers.some((number) => !Number.isInteger(number))) { + throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + } + if (new Set(numbers).size !== 5) { + throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.'); + } + if (numbers.some((n) => n < 1 || n > 30)) { + throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + } + + // ์ถœ๋ ฅ์„ ์œ„ํ•œ ๋ฉ”์„œ๋“œ + toString() { + return `[${this.#numbers.join(', ')}]`; + } + // ๋ฒˆํ˜ธ๋ฅผ ๋ฐฐ์—ด๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ + getNumbers() { + return [...this.#numbers]; + } +} From 560e649514088d2c7e3c5b701d6784e18c3d77fb Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 13:52:28 +0900 Subject: [PATCH 03/24] =?UTF-8?q?feat(LottoGameController.js):=20LottoGame?= =?UTF-8?q?Controller=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EB=B0=8F=20=EB=8B=B9=EC=B2=A8=EB=B2=88=ED=98=B8=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=20=EC=9E=85=EB=A0=A5=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 --- README.md | 2 +- src/App.js | 7 ++++++- src/controller/LottoGameController.js | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/controller/LottoGameController.js diff --git a/README.md b/README.md index 8011a555..89612210 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ #### 1๏ธโƒฃ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก ์ž…๋ ฅ ๊ธฐ๋Šฅ -- [ ] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์„ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. +- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์„ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. #### 2๏ธโƒฃ ๋‹น์ฒจ ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ diff --git a/src/App.js b/src/App.js index 091aa0a5..2697473c 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,10 @@ +import LottoGameController from './controller/LottoGameController.js'; + class App { - async run() {} + async run() { + const lottoGameController = new LottoGameController(); + lottoGameController.play(); + } } export default App; diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js new file mode 100644 index 00000000..b1800ca6 --- /dev/null +++ b/src/controller/LottoGameController.js @@ -0,0 +1,20 @@ +import { InputView, OutputView } from './../view.js'; + +class LottoGameController { + async play() { + let purchaseAmount; + + while (true) { + try { + purchaseAmount = await InputView.askAmount(); + // this.#validator.validatePurchaseAmount(purchaseAmount); + + break; + } catch (error) { + OutputView.printErrorMessage(error); + } + } + } +} + +export default LottoGameController; From acd427f184ad759783413e1fd14ec45cf552083d Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 14:07:31 +0900 Subject: [PATCH 04/24] =?UTF-8?q?feat(LottoGame.js):=20LottoGame=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20?= =?UTF-8?q?=EB=9E=9C=EB=8D=A4=20=EB=B2=88=ED=98=B8=EC=9D=98=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EC=83=9D=EC=84=B1=20=ED=9B=84=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++-- src/constants/lottoConstants.js | 8 +++++ src/controller/LottoGameController.js | 6 ++++ src/model/Lotto.js | 2 ++ src/model/LottoGame.js | 45 +++++++++++++++++++++++++++ src/view.js | 16 +++++++--- 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 src/constants/lottoConstants.js create mode 100644 src/model/LottoGame.js diff --git a/README.md b/README.md index 89612210..5c296b7e 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,11 @@ #### 1๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ์ƒ์„ฑ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์— ๋”ฐ๋ฅธ ๋กœ๋˜ ๊ฐœ์ˆ˜๋งŒํผ ๋กœ๋˜ ๊ฐ์ฒด์„ ๋งŒ๋“ค์–ด ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์— ๋”ฐ๋ฅธ ๋กœ๋˜ ๊ฐœ์ˆ˜๋งŒํผ ๋กœ๋˜ ๊ฐ์ฒด์„ ๋งŒ๋“ค์–ด ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 2๏ธโƒฃ ๋กœ๋˜ ๊ฐ์ฒด ์ƒ์„ฑ ๊ธฐ๋Šฅ -- [ ] ํ•˜๋‚˜์˜ ๋กœ๋˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ํ•˜๋‚˜์˜ ๋กœ๋˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 3๏ธโƒฃ ํ†ต๊ณ„ ์ƒ์„ฑ ๊ธฐ๋Šฅ @@ -57,7 +57,7 @@ #### 4๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ### WinningLotto.js diff --git a/src/constants/lottoConstants.js b/src/constants/lottoConstants.js new file mode 100644 index 00000000..f2e2dfba --- /dev/null +++ b/src/constants/lottoConstants.js @@ -0,0 +1,8 @@ +export const RANK = Object.freeze({ + FIRST: 1, + SECOND: 2, + THIRD: 3, + FOURTH: 4, + FIFTH: 5, + NO_PRIZE: 0, +}); diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js index b1800ca6..833b296c 100644 --- a/src/controller/LottoGameController.js +++ b/src/controller/LottoGameController.js @@ -1,3 +1,5 @@ +import { Console } from '@woowacourse/mission-utils'; +import LottoGame from '../model/LottoGame.js'; import { InputView, OutputView } from './../view.js'; class LottoGameController { @@ -14,6 +16,10 @@ class LottoGameController { OutputView.printErrorMessage(error); } } + // ๊ตฌ์ž… ๊ธˆ์•ก๋งŒํผ ๋กœ๋˜๋ฅผ ์ƒ์„ฑํ•œ LottoGame ๊ฐ์ฒด ์ƒ์„ฑ + const lottoGame = new LottoGame(purchaseAmount); + // ๊ตฌ์ž…ํ•œ ๋กœ๋˜๋“ค ๋ชจ๋‘ ์ถœ๋ ฅ + OutputView.printPurchasedLottos(lottoGame.getLottoNumbers()); } } diff --git a/src/model/Lotto.js b/src/model/Lotto.js index 21dc9671..2a68c1aa 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -32,3 +32,5 @@ class Lotto { return [...this.#numbers]; } } + +export default Lotto; diff --git a/src/model/LottoGame.js b/src/model/LottoGame.js new file mode 100644 index 00000000..10b710fc --- /dev/null +++ b/src/model/LottoGame.js @@ -0,0 +1,45 @@ +import { Random } from '@woowacourse/mission-utils'; + +import Lotto from './Lotto.js'; +import { RANK } from '../constants/lottoConstants.js'; + +class LottoGame { + #purchaseAmount; // ๊ตฌ์ž… ๊ธˆ์•ก + #lottos; // ๋กœ๋˜ ๋ฐฐ์—ด + + constructor(purchaseAmount) { + this.#purchaseAmount = purchaseAmount; + this.#lottos = this.#createLottos(); + } + + // ๊ตฌ์ž… ๊ธˆ์•ก๋งŒํผ ๋กœ๋˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ + #createLottos() { + const gameCount = this.#purchaseAmount / 500; + const lottos = []; + for (let i = 0; i < gameCount; i++) { + lottos.push(this.#createOneLotto()); + } + return lottos; + } + + // ๋กœ๋˜ ํ•œ ์žฅ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ + #createOneLotto() { + // 1~30 ์‚ฌ์ด์˜ ๊ฐ’ ์ค‘ 5๊ฐœ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑ + const numbers = Random.pickUniqueNumbersInRange(1, 30, 5); + numbers.sort((a, b) => a - b); // ์ •๋ ฌ + return new Lotto(numbers); // ์ •๋ ฌ๋œ ์ˆซ์ž ๋ฐฐ์—ด๋กœ ์ƒˆ ๋กœ๋˜ ์ƒ์„ฑ + } + + getLottos() { + return [...this.#lottos]; + } + getLottoNumbers() { + let line = []; + this.#lottos.forEach((lotto) => { + line.push(lotto.getNumbers()); + }); + return line; + } +} + +export default LottoGame; diff --git a/src/view.js b/src/view.js index ae6afd9c..708f8eb9 100644 --- a/src/view.js +++ b/src/view.js @@ -1,11 +1,13 @@ -import { MissionUtils } from "@woowacourse/mission-utils"; +import { MissionUtils } from '@woowacourse/mission-utils'; const InputView = { /** * @returns {number} */ async askAmount() { - const input = await MissionUtils.Console.readLineAsync('๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n'); + const input = await MissionUtils.Console.readLineAsync( + '๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n', + ); const num = parseInt(input, 10); if (Number.isNaN(num)) { throw new Error('๊ตฌ๋งค๊ธˆ์•ก์€ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); @@ -17,7 +19,9 @@ const InputView = { * @returns {number[]} */ async askWinningLotto() { - const input = await MissionUtils.Console.readLineAsync('์ง€๋‚œ ์ฃผ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n'); + const input = await MissionUtils.Console.readLineAsync( + '์ง€๋‚œ ์ฃผ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n', + ); return input .replaceAll(' ', '') @@ -35,7 +39,9 @@ const InputView = { * @returns {number} */ async askBonusNumber() { - const input = await MissionUtils.Console.readLineAsync('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n'); + const input = await MissionUtils.Console.readLineAsync( + '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n', + ); const num = parseInt(input, 10); if (Number.isNaN(num)) { throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); @@ -51,7 +57,7 @@ const OutputView = { printPurchasedLottos(lottos) { const lines = [ `${lottos.length}๊ฐœ๋ฅผ ๊ตฌ๋งคํ–ˆ์Šต๋‹ˆ๋‹ค.`, - ...lottos.map(lotto => `[${lotto.join(', ')}]`), + ...lottos.map((lotto) => `[${lotto.join(', ')}]`), ]; MissionUtils.Console.print(lines.join('\n')); }, From a1de7116318af569d6cbaec6a55dd7c7929e551e Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 14:18:45 +0900 Subject: [PATCH 05/24] =?UTF-8?q?feat(WinningLotto.js):=20WinningLotto=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20?= =?UTF-8?q?=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8=20&=20=EB=B3=B4?= =?UTF-8?q?=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=20=EB=B0=98=EB=B3=B5=20?= =?UTF-8?q?=EC=9E=85=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 --- README.md | 14 +++++----- src/controller/LottoGameController.js | 34 +++++++++++++++++++++++ src/model/WinningLotto.js | 40 +++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 src/model/WinningLotto.js diff --git a/README.md b/README.md index 5c296b7e..e68f7e99 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ #### 1๏ธโƒฃ ํ–‰์„ฑ๋กœ๋˜ ๊ฒŒ์ž„ ์ง„ํ–‰ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ -- [ ] ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๊ฐ’๋“ค์€ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ๋‹ค์‹œ ๋ฐ˜๋ณตํ•ด์„œ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. +- [x] ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๊ฐ’๋“ค์€ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ๋‹ค์‹œ ๋ฐ˜๋ณตํ•ด์„œ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. ### Lotto.js @@ -53,7 +53,7 @@ #### 3๏ธโƒฃ ํ†ต๊ณ„ ์ƒ์„ฑ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ํ†ต๊ณ„ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 4๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ @@ -63,11 +63,11 @@ #### 1๏ธโƒฃ ๋“ฑ์ˆ˜ ํ™•์ธ ๊ธฐ๋Šฅ -- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋น„๊ตํ•˜์—ฌ ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋น„๊ตํ•˜์—ฌ ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 2๏ธโƒฃ ๋“ฑ์ˆ˜ ์ถ”์ถœ ๊ธฐ๋Šฅ -- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๊ฒน์น˜๋Š” ๋ฒˆํ˜ธ ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ๋ฐ›์•„ ๋“ฑ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๊ฒน์น˜๋Š” ๋ฒˆํ˜ธ ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ๋ฐ›์•„ ๋“ฑ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ### InputView @@ -77,17 +77,17 @@ #### 2๏ธโƒฃ ๋‹น์ฒจ ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ -- [ ] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. +- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. #### 3๏ธโƒฃ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ -- [ ] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. +- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. ### OutputView #### 1๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ์ถœ๋ ฅ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋ชจ๋“  ๋กœ๋˜๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋ชจ๋“  ๋กœ๋˜๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅํ•œ๋‹ค. #### 2๏ธโƒฃ ๋‹น์ฒจ ํ†ต๊ณ„ ์ถœ๋ ฅ ๊ธฐ๋Šฅ diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js index 833b296c..143e76bc 100644 --- a/src/controller/LottoGameController.js +++ b/src/controller/LottoGameController.js @@ -1,10 +1,14 @@ import { Console } from '@woowacourse/mission-utils'; import LottoGame from '../model/LottoGame.js'; import { InputView, OutputView } from './../view.js'; +import Lotto from '../model/Lotto.js'; +import WinningLotto from '../model/WinningLotto.js'; class LottoGameController { async play() { let purchaseAmount; + let winningNumberLotto; + let bonusNumber; while (true) { try { @@ -20,6 +24,36 @@ class LottoGameController { const lottoGame = new LottoGame(purchaseAmount); // ๊ตฌ์ž…ํ•œ ๋กœ๋˜๋“ค ๋ชจ๋‘ ์ถœ๋ ฅ OutputView.printPurchasedLottos(lottoGame.getLottoNumbers()); + + while (true) { + try { + let winningNumbers = await InputView.askWinningLotto(); + // ๋‹น์ฒจ ๋ฒˆํ˜ธ์ธ Lotto ๊ฐ์ฒด ํ•˜๋‚˜ ์ƒ์„ฑ + winningNumberLotto = new Lotto(winningNumbers); + + break; + } catch (error) { + OutputView.printErrorMessage(error); + } + } + + while (true) { + try { + bonusNumber = await InputView.askBonusNumber(); + // this.#validator.validateBonusNumber(bonusNumber); + // this.#validator.validateWinningNumbersAndBonusNumber( + // winningNumberLotto, + // bonusNumber, + // ); + + break; + } catch (error) { + OutputView.printErrorMessage(error); + } + } + + // ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋กœ WinningLotto ๊ฐ์ฒด ์ƒ์„ฑ + const winningLotto = new WinningLotto(winningNumberLotto, bonusNumber); } } diff --git a/src/model/WinningLotto.js b/src/model/WinningLotto.js new file mode 100644 index 00000000..73f7e031 --- /dev/null +++ b/src/model/WinningLotto.js @@ -0,0 +1,40 @@ +import { RANK } from '../constants/lottoConstants.js'; + +class WinningLotto { + // ๋‹น์ฒจ ๋ฒˆํ˜ธ ๋กœ๋˜ + #winningNumberLotto; + // ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ + #bonusNumber; + + constructor(winningNumberLotto, bonusNumber) { + this.#winningNumberLotto = winningNumberLotto; + this.#bonusNumber = bonusNumber; + } + + // ๋กœ๋˜ ํ•œ ์žฅ์„ ์ธ์ž๋กœ ๋ฐ›์•„ ๋‹น์ฒจ ๋กœ๋˜์™€ ๋น„๊ตํ•˜์—ฌ rank๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ + match(lotto) { + const lottoNumbers = lotto.getNumbers(); + const winningNumbersSet = new Set(this.#winningNumberLotto.getNumbers()); + + // 1. ๋‹น์ฒจ ๋ฒˆํ˜ธ set์ด ์ธ์ž๋กœ ๋ฐ›์€ ๋กœ๋˜ ๋ฒˆํ˜ธ๋ฅผ ๋น„๊ตํ•œ ๋ฐฐ์—ด์˜ ๊ธธ์ด = ๋งค์น˜๋œ ๊ฐœ์ˆ˜ + const matchCount = lottoNumbers.filter((number) => + winningNumbersSet.has(number), + ).length; + // 2. ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€ + const hasBonus = lottoNumbers.includes(this.#bonusNumber); + + return this.#extractRank(matchCount, hasBonus); + } + + // ๋งค์น˜๋œ ๊ฐœ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ rank๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ + #extractRank(matchCount, hasBonus) { + if (matchCount === 6) return RANK.FIRST; + if (matchCount === 5 && hasBonus) return RANK.SECOND; + if (matchCount === 5) return RANK.THIRD; + if (matchCount === 4) return RANK.FOURTH; + if (matchCount === 3) return RANK.FIFTH; + return RANK.NO_PRIZE; + } +} + +export default WinningLotto; From ed546037d111170a819f7b5bf43da78ab4972af0 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 14:44:44 +0900 Subject: [PATCH 06/24] =?UTF-8?q?feat(LottoGame.js):=20=ED=86=B5=EA=B3=84?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EB=B0=8F=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/constants/lottoConstants.js | 2 +- src/controller/LottoGameController.js | 11 +++++++++++ src/model/LottoGame.js | 25 +++++++++++++++++++++++++ src/model/WinningLotto.js | 12 ++++++------ 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e68f7e99..8d5661f3 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ #### 3๏ธโƒฃ ํ†ต๊ณ„ ์ƒ์„ฑ ๊ธฐ๋Šฅ -- [ ] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 4๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ @@ -91,7 +91,7 @@ #### 2๏ธโƒฃ ๋‹น์ฒจ ํ†ต๊ณ„ ์ถœ๋ ฅ ๊ธฐ๋Šฅ -- [ ] ์ „์ฒด ๋“ฑ์ˆ˜๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ „์ฒด ๋“ฑ์ˆ˜๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. ### ๐Ÿšซ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ diff --git a/src/constants/lottoConstants.js b/src/constants/lottoConstants.js index f2e2dfba..82400831 100644 --- a/src/constants/lottoConstants.js +++ b/src/constants/lottoConstants.js @@ -4,5 +4,5 @@ export const RANK = Object.freeze({ THIRD: 3, FOURTH: 4, FIFTH: 5, - NO_PRIZE: 0, + ZERO: 0, }); diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js index 143e76bc..26f3e5f3 100644 --- a/src/controller/LottoGameController.js +++ b/src/controller/LottoGameController.js @@ -54,6 +54,17 @@ class LottoGameController { // ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋กœ WinningLotto ๊ฐ์ฒด ์ƒ์„ฑ const winningLotto = new WinningLotto(winningNumberLotto, bonusNumber); + // ๋“ฑ์ˆ˜ ํ†ต๊ณ„ ๊ฐ์ฒด + const winningStatistics = lottoGame.createWinningStatistics(winningLotto); + + // ์ƒ์„ฑ๋œ ํ†ต๊ณ„ ๊ฐ์ฒด๋ฅผ Map์œผ๋กœ ํ‚ค๊ฐ’๋งˆ๋‹ค ์‚ฝ์ž… + const priceMap = new Map(); + for (const [key, value] of Object.entries(winningStatistics)) { + priceMap.set(Number(key), value); + } + + // ์ตœ์ข… ๊ณ„์‚ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅ + OutputView.printResult(priceMap); } } diff --git a/src/model/LottoGame.js b/src/model/LottoGame.js index 10b710fc..95f2735c 100644 --- a/src/model/LottoGame.js +++ b/src/model/LottoGame.js @@ -30,6 +30,31 @@ class LottoGame { return new Lotto(numbers); // ์ •๋ ฌ๋œ ์ˆซ์ž ๋ฐฐ์—ด๋กœ ์ƒˆ ๋กœ๋˜ ์ƒ์„ฑ } + // ๋‹น์ฒจ ํ†ต๊ณ„๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  ๋‹น์ฒจ ํ†ต๊ณ„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ + createWinningStatistics(winningLotto) { + // ์ดˆ๊ธฐ rankCounts ๊ฐ์ฒด ์ƒ์„ฑ + const rankCounts = { + [RANK.FIRST]: 0, + [RANK.SECOND]: 0, + [RANK.THIRD]: 0, + [RANK.FOURTH]: 0, + [RANK.FIFTH]: 0, + [RANK.ZERO]: 0, + }; + + // ๋กœ๋˜ ๋ฐฐ์—ด์„ ๊ฐ๊ฐ ๊ฒ€์‚ฌํ•˜์—ฌ + this.#lottos.forEach((lotto) => { + // ํ•˜๋‚˜์˜ ๋กœ๋˜์— ๋Œ€ํ•ด winningLotto์™€ ๋น„๊ตํ•˜์—ฌ ๋งค์น˜๋œ ์ˆซ์ž์˜ ๊ฐœ์ˆ˜(rank)๋ฅผ ๊ณ„์‚ฐ + const rank = winningLotto.match(lotto); + // ๋งค์น˜๋œ ์ˆ˜๊ฐ€ NO_PRIZE๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ทธ ๋žญํฌ์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์„ +1 + + rankCounts[rank] += 1; + }); + + // ๋ชจ๋“  ๋กœ๋˜ ๋ฐฐ์—ด์„ ๊ฒ€์‚ฌํ•œ ๋’ค ์ƒˆ ๋‹น์ฒจ ํ†ต๊ณ„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ + return rankCounts; + } + getLottos() { return [...this.#lottos]; } diff --git a/src/model/WinningLotto.js b/src/model/WinningLotto.js index 73f7e031..7214e629 100644 --- a/src/model/WinningLotto.js +++ b/src/model/WinningLotto.js @@ -28,12 +28,12 @@ class WinningLotto { // ๋งค์น˜๋œ ๊ฐœ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ rank๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ #extractRank(matchCount, hasBonus) { - if (matchCount === 6) return RANK.FIRST; - if (matchCount === 5 && hasBonus) return RANK.SECOND; - if (matchCount === 5) return RANK.THIRD; - if (matchCount === 4) return RANK.FOURTH; - if (matchCount === 3) return RANK.FIFTH; - return RANK.NO_PRIZE; + if (matchCount === 5) return 1; + if (matchCount === 4 && hasBonus) return 2; + if (matchCount === 4) return 3; + if (matchCount === 3 && hasBonus) return 4; + if (matchCount === 2 && hasBonus) return 5; + return 0; } } From b894b46b5c9bc627a73a10f0680899cf8a2baaed Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 15:27:09 +0900 Subject: [PATCH 07/24] =?UTF-8?q?feat(validate.js):=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EA=B0=9D=EC=B2=B4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++++++++---------- src/controller/LottoGameController.js | 13 +++++++------ src/utils/validate.js | 20 ++++++++++++++++++++ src/view.js | 8 ++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 src/utils/validate.js diff --git a/README.md b/README.md index 8d5661f3..83d41959 100644 --- a/README.md +++ b/README.md @@ -95,18 +95,18 @@ ### ๐Ÿšซ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ -- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ์ฝค๋งˆ(,) ์‚ฌ์ด์˜ ๊ณต๋ฐฑ์€ ๋ฌด์‹œํ•œ๋‹ค. -- [ ] ์˜ˆ์™ธ ์ƒํ™ฉ ์‹œ `[ERROR]`๋กœ ์‹œ์ž‘ํ•˜๋Š” ์—๋Ÿฌ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, ํ•ด๋‹น ์ง€์ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ์ฝค๋งˆ(,) ์‚ฌ์ด์˜ ๊ณต๋ฐฑ์€ ๋ฌด์‹œํ•œ๋‹ค. +- [x] ์˜ˆ์™ธ ์ƒํ™ฉ ์‹œ `[ERROR]`๋กœ ์‹œ์ž‘ํ•˜๋Š” ์—๋Ÿฌ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ ํ›„, ํ•ด๋‹น ์ง€์ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. #### โŒ [ERROR] ์ฒ˜๋ฆฌ -- [ ] ๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. -- [ ] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. +- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. +- [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js index 26f3e5f3..bafd362c 100644 --- a/src/controller/LottoGameController.js +++ b/src/controller/LottoGameController.js @@ -3,6 +3,7 @@ import LottoGame from '../model/LottoGame.js'; import { InputView, OutputView } from './../view.js'; import Lotto from '../model/Lotto.js'; import WinningLotto from '../model/WinningLotto.js'; +import Validate from '../utils/validate.js'; class LottoGameController { async play() { @@ -13,7 +14,6 @@ class LottoGameController { while (true) { try { purchaseAmount = await InputView.askAmount(); - // this.#validator.validatePurchaseAmount(purchaseAmount); break; } catch (error) { @@ -40,11 +40,12 @@ class LottoGameController { while (true) { try { bonusNumber = await InputView.askBonusNumber(); - // this.#validator.validateBonusNumber(bonusNumber); - // this.#validator.validateWinningNumbersAndBonusNumber( - // winningNumberLotto, - // bonusNumber, - // ); + + // ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ถ”๊ฐ€ + Validate.validateWinningNumbersAndBonusNumber( + winningNumberLotto, + bonusNumber, + ); break; } catch (error) { diff --git a/src/utils/validate.js b/src/utils/validate.js new file mode 100644 index 00000000..f136e187 --- /dev/null +++ b/src/utils/validate.js @@ -0,0 +1,20 @@ +const Validate = { + validatePurchaseAmount(amount) { + if (isNaN(amount) || amount % 500 !== 0 || amount === 0) { + throw new Error('๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + }, + validateBonusNumber(number) { + if (isNaN(number)) throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + if (number < 1 || number > 30) { + throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + }, + + validateWinningNumbersAndBonusNumber(winningNumberLotto, bonusNumber) { + if (winningNumberLotto.getNumbers().includes(bonusNumber)) + throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); + }, +}; + +export default Validate; diff --git a/src/view.js b/src/view.js index 708f8eb9..b1da7138 100644 --- a/src/view.js +++ b/src/view.js @@ -1,4 +1,5 @@ import { MissionUtils } from '@woowacourse/mission-utils'; +import Validate from './utils/validate.js'; const InputView = { /** @@ -8,10 +9,14 @@ const InputView = { const input = await MissionUtils.Console.readLineAsync( '๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n', ); + + Validate.validatePurchaseAmount(input); // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ถ”๊ฐ€ + const num = parseInt(input, 10); if (Number.isNaN(num)) { throw new Error('๊ตฌ๋งค๊ธˆ์•ก์€ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } + return num; }, @@ -42,6 +47,9 @@ const InputView = { const input = await MissionUtils.Console.readLineAsync( '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n', ); + + Validate.validateBonusNumber(input); // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ถ”๊ฐ€ + const num = parseInt(input, 10); if (Number.isNaN(num)) { throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); From 56ab2bca287516363bb95546f5d17a9765144f2a Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 15:33:54 +0900 Subject: [PATCH 08/24] =?UTF-8?q?fix(App.js):=20=EB=B9=84=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=EB=A1=9C=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC?= =?UTF-8?q?=EB=A5=BC=20=EC=8B=A4=ED=96=89=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EC=95=84=20test=EB=A5=BC=20=ED=86=B5=EA=B3=BC=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EB=AA=BB=ED=95=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index 2697473c..7cbc317b 100644 --- a/src/App.js +++ b/src/App.js @@ -3,7 +3,7 @@ import LottoGameController from './controller/LottoGameController.js'; class App { async run() { const lottoGameController = new LottoGameController(); - lottoGameController.play(); + await lottoGameController.play(); } } From dfa8276b6e98093031b77cfd720a23ace59c2044 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 15:39:46 +0900 Subject: [PATCH 09/24] =?UTF-8?q?feat(LottoTest.js):=20Lotto=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/model/LottoTest.js | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 __tests__/model/LottoTest.js diff --git a/__tests__/model/LottoTest.js b/__tests__/model/LottoTest.js new file mode 100644 index 00000000..0e5f1460 --- /dev/null +++ b/__tests__/model/LottoTest.js @@ -0,0 +1,60 @@ +import Lotto from '../../src/model/Lotto.js'; + +describe('Lotto ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ', () => { + describe('๋กœ๋˜ ๋ฒˆํ˜ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ', () => { + test.each([ + { + description: '๋ฒˆํ˜ธ๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ ๋•Œ (6๊ฐœ)', + input: [1, 2, 3, 4, 5, 6], + expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + }, + { + description: '๋ฒˆํ˜ธ๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ ๋•Œ (4๊ฐœ)', + input: [1, 2, 3, 4], + expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + }, + { + description: '๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์„ ๋•Œ', + input: [1, 2, 3, 4, 4], + expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.', + }, + { + description: '๋ฒˆํ˜ธ์— ๋ฌธ์ž๊ฐ€ ์žˆ์„ ๋•Œ', + input: [1, 2, 3, 4, 'a'], + expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', + }, + { + description: '๋ฒˆํ˜ธ์— ์‹ค์ˆ˜๊ฐ€ ์žˆ์„ ๋•Œ', + input: [1, 2, 3, 4, 5.5], + expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', + }, + { + description: '๋ฒˆํ˜ธ๊ฐ€ 1~30 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ (0)', + input: [0, 1, 2, 3, 4], + expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + }, + + [ + '๋ฒˆํ˜ธ๊ฐ€ 1~45 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ (31)', + [1, 2, 3, 4, 31], + '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + ], + ])('%s, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', ({ input, expectedError }) => { + expect(() => new Lotto(input)).toThrow(expectedError); + }); + }); + + describe('๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ', () => { + test('Lotto ๊ฐ์ฒด๋Š” ๋ฒˆํ˜ธ๋ฅผ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ ์ €์žฅํ•œ๋‹ค.', () => { + const numbers = [5, 4, 3, 2, 1]; + const lotto = new Lotto(numbers); + expect(lotto.getNumbers()).toEqual([1, 2, 3, 4, 5]); + }); + + test("toString ๋ฉ”์„œ๋“œ๋Š” '[1, 2, 3, 4, 5]' ํ˜•์‹์˜ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.", () => { + const numbers = [1, 2, 3, 4, 5]; + const lotto = new Lotto(numbers); + expect(lotto.toString()).toEqual('[1, 2, 3, 4, 5]'); + }); + }); +}); From 431943d0706cdb4732faf51d7b37b0e68d925889 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 15:45:56 +0900 Subject: [PATCH 10/24] =?UTF-8?q?feat(LottoGameTest.js):=20LottoGame=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/model/LottoGameTest.js | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 __tests__/model/LottoGameTest.js diff --git a/__tests__/model/LottoGameTest.js b/__tests__/model/LottoGameTest.js new file mode 100644 index 00000000..62250fe9 --- /dev/null +++ b/__tests__/model/LottoGameTest.js @@ -0,0 +1,57 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; + +import LottoGame from '../../src/model/LottoGame.js'; +import WinningLotto from '../../src/model/WinningLotto.js'; +import Lotto from '../../src/model/Lotto.js'; +import { RANK } from '../../src/constants/lottoConstants.js'; + +const mockRandoms = (numbers) => { + MissionUtils.Random.pickUniqueNumbersInRange = jest.fn(); + numbers.reduce((acc, number) => { + return acc.mockReturnValueOnce(number); + }, MissionUtils.Random.pickUniqueNumbersInRange); +}; + +describe('LottoGame ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ', () => { + beforeEach(() => { + jest.restoreAllMocks(); + }); + + test('๊ตฌ๋งค ๊ธˆ์•ก์— ํ•ด๋‹นํ•˜๋Š” ๊ฐœ์ˆ˜๋งŒํผ ๋กœ๋˜๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.', () => { + const purchaseAmount = 3000; + const game = new LottoGame(purchaseAmount); + const lottos = game.getLottos(); + + expect(lottos.length).toBe(6); + }); + + test('createWinningStatistics๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋‹น์ฒจ ํ†ต๊ณ„๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.', () => { + // given + const mockNumbers = [ + [1, 2, 3, 4, 5], // 1๋“ฑ (5๊ฐœ ์ผ์น˜) + [1, 2, 3, 4, 6], // 2๋“ฑ (4๊ฐœ ์ผ์น˜ + ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ผ์น˜ O) + [1, 2, 3, 4, 7], // 3๋“ฑ (4๊ฐœ ์ผ์น˜ + ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ผ์น˜ X) + ]; + mockRandoms(mockNumbers); + + const purchaseAmount = 1500; + const lottoGame = new LottoGame(purchaseAmount); + + const winningNumbers = [1, 2, 3, 4, 5]; + const bonusNumber = 6; + const winningLotto = new WinningLotto( + new Lotto(winningNumbers), + bonusNumber, + ); + + // when + const winningStatistics = lottoGame.createWinningStatistics(winningLotto); + + // then + expect(winningStatistics[RANK.FIRST]).toBe(1); + expect(winningStatistics[RANK.SECOND]).toBe(1); + expect(winningStatistics[RANK.THIRD]).toBe(1); + expect(winningStatistics[RANK.FOURTH]).toBe(0); + expect(winningStatistics[RANK.FIFTH]).toBe(0); + }); +}); From 2fcb21fa25fb010b35edf8d12a5ae706d9ad7763 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 15:48:36 +0900 Subject: [PATCH 11/24] =?UTF-8?q?feat(WinningLottoTest.js):=20WinningLotto?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/model/WinningLottoTest.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 __tests__/model/WinningLottoTest.js diff --git a/__tests__/model/WinningLottoTest.js b/__tests__/model/WinningLottoTest.js new file mode 100644 index 00000000..7b60ac83 --- /dev/null +++ b/__tests__/model/WinningLottoTest.js @@ -0,0 +1,24 @@ +import Lotto from '../../src/model/Lotto.js'; +import WinningLotto from '../../src/model/WinningLotto.js'; +import { RANK } from '../../src/constants/lottoConstants.js'; + +describe('WinningLotto ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ', () => { + const winningNumbers = [1, 2, 3, 4, 5]; + const bonusNumber = 6; + const winningLotto = new WinningLotto(new Lotto(winningNumbers), bonusNumber); + + test.each([ + ['1๋“ฑ(5๊ฐœ ์ผ์น˜)', new Lotto([1, 2, 3, 4, 5]), RANK.FIRST], + ['2๋“ฑ(4๊ฐœ + ๋ณด๋„ˆ์Šค ์ผ์น˜)', new Lotto([1, 2, 3, 4, 6]), RANK.SECOND], + ['3๋“ฑ(4๊ฐœ ์ผ์น˜)', new Lotto([1, 2, 3, 4, 7]), RANK.THIRD], + ['4๋“ฑ(3๊ฐœ + ๋ณด๋„ˆ์Šค ์ผ์น˜)', new Lotto([1, 2, 3, 6, 7]), RANK.FOURTH], + ['5๋“ฑ(2๊ฐœ + ๋ณด๋„ˆ์Šค ์ผ์น˜)', new Lotto([1, 2, 6, 7, 8]), RANK.FIFTH], + ['๊ฝ(0๊ฐœ ์ผ์น˜)', new Lotto([7, 8, 9, 10, 11]), RANK.ZERO], + ])( + '%s์ผ๋•Œ, ์˜ฌ๋ฐ”๋ฅธ ๋“ฑ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.', + (description, userLotto, expectedRank) => { + const rank = winningLotto.match(userLotto); + expect(rank).toBe(expectedRank); + }, + ); +}); From 06faf6a2d45c1c4155bdeeeb5416840a743f1ede Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:00:52 +0900 Subject: [PATCH 12/24] =?UTF-8?q?feat(validateTest.js):=20Validate=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EC=9D=98=20=ED=95=A8=EC=88=98=EB=93=A4?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EB=8F=99=EC=9D=BC?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/utils/validateTest.js | 66 +++++++++++++++++++++++++++++++++ src/utils/validate.js | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 __tests__/utils/validateTest.js diff --git a/__tests__/utils/validateTest.js b/__tests__/utils/validateTest.js new file mode 100644 index 00000000..2ba4b446 --- /dev/null +++ b/__tests__/utils/validateTest.js @@ -0,0 +1,66 @@ +import Validate from '../../src/utils/validate.js'; +import Lotto from '../../src/model/Lotto.js'; + +describe('Validate ํ…Œ์ŠคํŠธ', () => { + describe('validatePurchaseAmount ํ…Œ์ŠคํŠธ', () => { + test.each([ + ['์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ(abc)', 'abc'], + ['500์› ๋‹จ์œ„๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ(750์›)', 750], + ['์ˆซ์ž์™€ ๋ฌธ์ž๊ฐ€ ์„ž์—ฌ์žˆ๋Š” ๊ฒฝ์šฐ(500j)', '500j'], + ])('%s, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', (description, amount) => { + expect(() => Validate.validatePurchaseAmount(amount)).toThrow( + '๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + ); + }); + + test('์œ ํšจํ•œ ๊ตฌ๋งค ๊ธˆ์•ก์ธ ๊ฒฝ์šฐ, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.', () => { + expect(() => Validate.validatePurchaseAmount(3000)).not.toThrow(); + }); + }); + + describe('validateBonusNumber ํ…Œ์ŠคํŠธ', () => { + test.each([ + ['์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ', 'a', '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'], + [ + '๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ (0)', + 0, + '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + ], + [ + '๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ (31)', + 31, + '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + ], + ])('%s, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', (description, number, expectedError) => { + expect(() => Validate.validateBonusNumber(number)).toThrow(expectedError); + }); + + test('์œ ํšจํ•œ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ์ธ ๊ฒฝ์šฐ, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.', () => { + expect(() => Validate.validateBonusNumber(6)).not.toThrow(); + }); + }); + + describe('validateWinningNumbersAndBonusNumber ํ…Œ์ŠคํŠธ', () => { + test('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๊ฐ€ ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ๊ฒฝ์šฐ, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', () => { + const winningNumberLotto = new Lotto([1, 2, 3, 4, 5]); + const bonusNumber = 5; + expect(() => + Validate.validateWinningNumbersAndBonusNumber( + winningNumberLotto, + bonusNumber, + ), + ).toThrow('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); + }); + + test('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๊ฐ€ ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.', () => { + const winningNumberLotto = new Lotto([1, 2, 3, 4, 5]); + const bonusNumber = 6; + expect(() => + Validate.validateWinningNumbersAndBonusNumber( + winningNumberLotto, + bonusNumber, + ), + ).not.toThrow(); + }); + }); +}); diff --git a/src/utils/validate.js b/src/utils/validate.js index f136e187..f444d4d3 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -5,7 +5,7 @@ const Validate = { } }, validateBonusNumber(number) { - if (isNaN(number)) throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + if (isNaN(number)) throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); if (number < 1 || number > 30) { throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } From ee95a1e203ffb825575fc23679bbd237317bb5f1 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:08:09 +0900 Subject: [PATCH 13/24] =?UTF-8?q?docs(README.md):=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=85=EC=84=B8=EC=84=9C=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=20=EB=82=B4=EC=9A=A9=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?&=20=ED=95=84=EC=9A=94=20=EA=B8=B0=EB=8A=A5=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=20=EC=9D=BC=EB=B6=80=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=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 | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 83d41959..0cc545c6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # javascript-planetlotto-precourse -# javascript-planetlotto-precourse - ## ๐Ÿ“‹ ์š”๊ตฌ์‚ฌํ•ญ ๋ช…์„ธ์„œ - ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์‹œ `"๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."` ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. @@ -53,7 +51,7 @@ #### 3๏ธโƒฃ ํ†ต๊ณ„ ์ƒ์„ฑ ๊ธฐ๋Šฅ -- [x] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ Map์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 4๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ @@ -69,30 +67,6 @@ - [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๊ฒน์น˜๋Š” ๋ฒˆํ˜ธ ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ๋ฐ›์•„ ๋“ฑ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. -### InputView - -#### 1๏ธโƒฃ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก ์ž…๋ ฅ ๊ธฐ๋Šฅ - -- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋กœ๋˜ ๊ตฌ์ž… ๊ธˆ์•ก์„ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. - -#### 2๏ธโƒฃ ๋‹น์ฒจ ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ - -- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. - -#### 3๏ธโƒฃ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ ์ž…๋ ฅ ๊ธฐ๋Šฅ - -- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. - -### OutputView - -#### 1๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ์ถœ๋ ฅ ๊ธฐ๋Šฅ - -- [x] ๋กœ๋˜ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋ชจ๋“  ๋กœ๋˜๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅํ•œ๋‹ค. - -#### 2๏ธโƒฃ ๋‹น์ฒจ ํ†ต๊ณ„ ์ถœ๋ ฅ ๊ธฐ๋Šฅ - -- [x] ์ „์ฒด ๋“ฑ์ˆ˜๋ฅผ ์ •ํ•ด์ง„ ํ˜•ํƒœ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. - ### ๐Ÿšซ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ - [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ์ฝค๋งˆ(,) ์‚ฌ์ด์˜ ๊ณต๋ฐฑ์€ ๋ฌด์‹œํ•œ๋‹ค. @@ -100,12 +74,11 @@ #### โŒ [ERROR] ์ฒ˜๋ฆฌ -- [x] ๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. -- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. -- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. -- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. -- [x] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. +- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ์ฝค๋งˆ(,)๋กœ ์—ฐ๊ฒฐ๋œ 5๊ฐœ์˜ ์ค‘๋ณต๋˜์ง€ ์•Š์€ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. - [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. - [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. From 2b940883ad2d02297eb03fdbac7077190945acd9 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:15:30 +0900 Subject: [PATCH 14/24] =?UTF-8?q?feat(validate.js):=20=EB=8B=B9=EC=B2=A8?= =?UTF-8?q?=20=EB=B2=88=ED=98=B8=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=9C=A0?= =?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=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 --- src/utils/validate.js | 17 ++++++++++++++++- src/view.js | 3 +++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/utils/validate.js b/src/utils/validate.js index f444d4d3..8727dbf3 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -4,8 +4,23 @@ const Validate = { throw new Error('๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } }, + validateWinningNumbers(numbers) { + if (numbers.length !== 5) { + throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + if (numbers.some((number) => !Number.isInteger(number))) { + throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + } + if (new Set(numbers).size !== 5) { + throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.'); + } + if (numbers.some((n) => n < 1 || n > 30)) { + throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + }, validateBonusNumber(number) { - if (isNaN(number)) throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + if (isNaN(number) || !Number.isInteger(Number(number))) + throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์ธ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); if (number < 1 || number > 30) { throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } diff --git a/src/view.js b/src/view.js index b1da7138..c89c4ce3 100644 --- a/src/view.js +++ b/src/view.js @@ -28,6 +28,9 @@ const InputView = { '์ง€๋‚œ ์ฃผ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n', ); + const numbers = input.split(',').map(Number); + Validate.validateWinningNumbers(numbers); // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ถ”๊ฐ€ + return input .replaceAll(' ', '') .split(',') From 8004493b651b2fc91372a67c5ce41bea4182df48 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:33:43 +0900 Subject: [PATCH 15/24] =?UTF-8?q?refactor(errorMessages.js):=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=A9=94=EC=84=B8=EC=A7=80=EB=A5=BC=20=EC=83=81?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EB=B6=84=EB=A6=AC,=20=EB=AC=B8=EC=9E=90?= =?UTF-8?q?=EC=97=B4=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EB=A1=9C=EB=98=90=20=EA=B7=9C=EC=B9=99=EC=9D=B8=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=EB=93=A4=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=83=81?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/errorMessages.js | 23 +++++++++++++++++++++++ src/constants/lottoConstants.js | 7 +++++++ src/utils/validate.js | 10 +++++----- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 src/constants/errorMessages.js diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js new file mode 100644 index 00000000..51ad165a --- /dev/null +++ b/src/constants/errorMessages.js @@ -0,0 +1,23 @@ +import { LOTTO_RULES } from './lottoConstants.js'; + +const ERROR_MESSAGES = Object.freeze({ + DUPLICATE_WINNING_NUMBERS_AND_BONUS_NUMBER: + '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', + + INVALID_PURCHASE_AMOUNT: `๊ตฌ์ž… ๊ธˆ์•ก์€ ${LOTTO_RULES.PRICE}์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, + + INVALID_NUMBERS_COUNT: `๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.NUMBER_COUNT}๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, + NUMBERS_MUST_BE_INTEGER: '๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', + DUPLICATE_NUMBERS: '๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', + OUT_OF_RANGE_NUMBERS: `๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.MIN_NUMBER}๋ถ€ํ„ฐ ${LOTTO_RULES.MAX_NUMBER} ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, + + INVALID_WINNING_NUMBERS_COUNT: `๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.NUMBER_COUNT}๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, + WINNING_NUMBERS_MUST_BE_INTEGER: '๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', + DUPLICATE_WINNING_NUMBERS: '๋‹น์ฒจ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.', + OUT_OF_RANGE_WINNING_NUMBERS: `๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.MIN_NUMBER}๋ถ€ํ„ฐ ${LOTTO_RULES.MAX_NUMBER} ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, + + BONUS_NUMBER_MUST_BE_INTEGER: '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + OUT_OF_RANGE_BONUS_NUMBER: `๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.MIN_NUMBER}๋ถ€ํ„ฐ ${LOTTO_RULES.MAX_NUMBER} ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, +}); + +export default ERROR_MESSAGES; diff --git a/src/constants/lottoConstants.js b/src/constants/lottoConstants.js index 82400831..9da0410f 100644 --- a/src/constants/lottoConstants.js +++ b/src/constants/lottoConstants.js @@ -6,3 +6,10 @@ export const RANK = Object.freeze({ FIFTH: 5, ZERO: 0, }); + +export const LOTTO_RULES = Object.freeze({ + MIN_NUMBER: 1, + MAX_NUMBER: 30, + NUMBER_COUNT: 5, + PRICE: 500, +}); diff --git a/src/utils/validate.js b/src/utils/validate.js index 8727dbf3..f3ea2fee 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -6,21 +6,21 @@ const Validate = { }, validateWinningNumbers(numbers) { if (numbers.length !== 5) { - throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } if (numbers.some((number) => !Number.isInteger(number))) { - throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); } if (new Set(numbers).size !== 5) { - throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.'); + throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.'); } if (numbers.some((n) => n < 1 || n > 30)) { - throw new Error('๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } }, validateBonusNumber(number) { if (isNaN(number) || !Number.isInteger(Number(number))) - throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์ธ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); if (number < 1 || number > 30) { throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); } From b7a8b7c1a488a3096c613a77521c58e9ca5795cd Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:36:51 +0900 Subject: [PATCH 16/24] =?UTF-8?q?refactor(Lotto.js,=20LottoTest.js):=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=99=80=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=EB=A5=BC=20=EC=83=81=EC=88=98?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/model/LottoTest.js | 15 ++++++++------- src/constants/errorMessages.js | 2 +- src/model/Lotto.js | 10 ++++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/__tests__/model/LottoTest.js b/__tests__/model/LottoTest.js index 0e5f1460..d274cd20 100644 --- a/__tests__/model/LottoTest.js +++ b/__tests__/model/LottoTest.js @@ -1,3 +1,4 @@ +import ERROR_MESSAGES from '../../src/constants/errorMessages.js'; import Lotto from '../../src/model/Lotto.js'; describe('Lotto ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ', () => { @@ -6,38 +7,38 @@ describe('Lotto ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ', () => { { description: '๋ฒˆํ˜ธ๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ ๋•Œ (6๊ฐœ)', input: [1, 2, 3, 4, 5, 6], - expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + expectedError: ERROR_MESSAGES.INVALID_NUMBERS_COUNT, }, { description: '๋ฒˆํ˜ธ๊ฐ€ 5๊ฐœ๊ฐ€ ์•„๋‹ ๋•Œ (4๊ฐœ)', input: [1, 2, 3, 4], - expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + expectedError: ERROR_MESSAGES.INVALID_NUMBERS_COUNT, }, { description: '๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์„ ๋•Œ', input: [1, 2, 3, 4, 4], - expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.', + expectedError: ERROR_MESSAGES.DUPLICATE_NUMBERS, }, { description: '๋ฒˆํ˜ธ์— ๋ฌธ์ž๊ฐ€ ์žˆ์„ ๋•Œ', input: [1, 2, 3, 4, 'a'], - expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', + expectedError: ERROR_MESSAGES.NUMBERS_MUST_BE_INTEGER, }, { description: '๋ฒˆํ˜ธ์— ์‹ค์ˆ˜๊ฐ€ ์žˆ์„ ๋•Œ', input: [1, 2, 3, 4, 5.5], - expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', + expectedError: ERROR_MESSAGES.NUMBERS_MUST_BE_INTEGER, }, { description: '๋ฒˆํ˜ธ๊ฐ€ 1~30 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ (0)', input: [0, 1, 2, 3, 4], - expectedError: '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + expectedError: ERROR_MESSAGES.OUT_OF_RANGE_NUMBERS, }, [ '๋ฒˆํ˜ธ๊ฐ€ 1~45 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ (31)', [1, 2, 3, 4, 31], - '[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + ERROR_MESSAGES.OUT_OF_RANGE_NUMBERS, ], ])('%s, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', ({ input, expectedError }) => { expect(() => new Lotto(input)).toThrow(expectedError); diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index 51ad165a..c626a90f 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -13,7 +13,7 @@ const ERROR_MESSAGES = Object.freeze({ INVALID_WINNING_NUMBERS_COUNT: `๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.NUMBER_COUNT}๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, WINNING_NUMBERS_MUST_BE_INTEGER: '๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', - DUPLICATE_WINNING_NUMBERS: '๋‹น์ฒจ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.', + DUPLICATE_WINNING_NUMBERS: '๋‹น์ฒจ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', OUT_OF_RANGE_WINNING_NUMBERS: `๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.MIN_NUMBER}๋ถ€ํ„ฐ ${LOTTO_RULES.MAX_NUMBER} ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, BONUS_NUMBER_MUST_BE_INTEGER: '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', diff --git a/src/model/Lotto.js b/src/model/Lotto.js index 2a68c1aa..b5845c62 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -1,3 +1,5 @@ +import ERROR_MESSAGES from '../constants/errorMessages'; + class Lotto { #numbers; // ๋กœ๋˜ ํ•œ ์žฅ์€ 5๊ฐœ์˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๊ฐ€์ง @@ -10,16 +12,16 @@ class Lotto { #validate(numbers) { if (numbers.length !== 5) { - throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.INVALID_NUMBERS_COUNT); } if (numbers.some((number) => !Number.isInteger(number))) { - throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + throw new Error(ERROR_MESSAGES.NUMBERS_MUST_BE_INTEGER); } if (new Set(numbers).size !== 5) { - throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.DUPLICATE_NUMBERS); } if (numbers.some((n) => n < 1 || n > 30)) { - throw new Error('[ERROR] ๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.OUT_OF_RANGE_NUMBERS); } } From d108ef4eb9c73bb7e41f60556d60b88678289132 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:40:23 +0900 Subject: [PATCH 17/24] =?UTF-8?q?refactor(validate.js,=20validateTest.js):?= =?UTF-8?q?=20Validate=20=EA=B0=9D=EC=B2=B4=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=93=A4=EA=B3=BC=20Validate=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EC=83=81=EC=88=98=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/utils/validateTest.js | 19 ++++++------------- src/utils/validate.js | 20 ++++++++++++-------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/__tests__/utils/validateTest.js b/__tests__/utils/validateTest.js index 2ba4b446..da51e130 100644 --- a/__tests__/utils/validateTest.js +++ b/__tests__/utils/validateTest.js @@ -1,5 +1,6 @@ import Validate from '../../src/utils/validate.js'; import Lotto from '../../src/model/Lotto.js'; +import ERROR_MESSAGES from '../../src/constants/errorMessages.js'; describe('Validate ํ…Œ์ŠคํŠธ', () => { describe('validatePurchaseAmount ํ…Œ์ŠคํŠธ', () => { @@ -9,7 +10,7 @@ describe('Validate ํ…Œ์ŠคํŠธ', () => { ['์ˆซ์ž์™€ ๋ฌธ์ž๊ฐ€ ์„ž์—ฌ์žˆ๋Š” ๊ฒฝ์šฐ(500j)', '500j'], ])('%s, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', (description, amount) => { expect(() => Validate.validatePurchaseAmount(amount)).toThrow( - '๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + ERROR_MESSAGES.INVALID_PURCHASE_AMOUNT, ); }); @@ -20,17 +21,9 @@ describe('Validate ํ…Œ์ŠคํŠธ', () => { describe('validateBonusNumber ํ…Œ์ŠคํŠธ', () => { test.each([ - ['์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ', 'a', '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'], - [ - '๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ (0)', - 0, - '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', - ], - [ - '๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ (31)', - 31, - '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', - ], + ['์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ', 'a', ERROR_MESSAGES.BONUS_NUMBER_MUST_BE_INTEGER], + ['๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ (0)', 0, ERROR_MESSAGES.OUT_OF_RANGE_BONUS_NUMBER], + ['๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ (31)', 31, ERROR_MESSAGES.OUT_OF_RANGE_BONUS_NUMBER], ])('%s, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.', (description, number, expectedError) => { expect(() => Validate.validateBonusNumber(number)).toThrow(expectedError); }); @@ -49,7 +42,7 @@ describe('Validate ํ…Œ์ŠคํŠธ', () => { winningNumberLotto, bonusNumber, ), - ).toThrow('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); + ).toThrow(ERROR_MESSAGES.DUPLICATE_WINNING_NUMBERS_AND_BONUS_NUMBER); }); test('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๊ฐ€ ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.', () => { diff --git a/src/utils/validate.js b/src/utils/validate.js index f3ea2fee..d6259f44 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -1,34 +1,38 @@ +import ERROR_MESSAGES from '../constants/errorMessages.js'; + const Validate = { validatePurchaseAmount(amount) { if (isNaN(amount) || amount % 500 !== 0 || amount === 0) { - throw new Error('๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.INVALID_PURCHASE_AMOUNT); } }, validateWinningNumbers(numbers) { if (numbers.length !== 5) { - throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.INVALID_WINNING_NUMBERS_COUNT); } if (numbers.some((number) => !Number.isInteger(number))) { - throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค'); + throw new Error(ERROR_MESSAGES.WINNING_NUMBERS_MUST_BE_INTEGER); } if (new Set(numbers).size !== 5) { - throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.DUPLICATE_WINNING_NUMBERS); } if (numbers.some((n) => n < 1 || n > 30)) { - throw new Error('๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.OUT_OF_RANGE_WINNING_NUMBERS); } }, validateBonusNumber(number) { if (isNaN(number) || !Number.isInteger(Number(number))) - throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.BONUS_NUMBER_MUST_BE_INTEGER); if (number < 1 || number > 30) { - throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1๋ถ€ํ„ฐ 30์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + throw new Error(ERROR_MESSAGES.OUT_OF_RANGE_BONUS_NUMBER); } }, validateWinningNumbersAndBonusNumber(winningNumberLotto, bonusNumber) { if (winningNumberLotto.getNumbers().includes(bonusNumber)) - throw new Error('๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); + throw new Error( + ERROR_MESSAGES.DUPLICATE_WINNING_NUMBERS_AND_BONUS_NUMBER, + ); }, }; From b598eaa891f0e6c94da1a5f73e66aa6a8293402c Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:42:45 +0900 Subject: [PATCH 18/24] =?UTF-8?q?docs(README.md):=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=85=EC=84=B8=EC=84=9C=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B0=8F=20=EB=AC=B8=EC=9E=90?= =?UTF-8?q?=EC=97=B4=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++--- src/constants/errorMessages.js | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0cc545c6..6be3071b 100644 --- a/README.md +++ b/README.md @@ -76,9 +76,10 @@ - [x] ๊ตฌ์ž… ๊ธˆ์•ก์€ 500์› ๋‹จ์œ„์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. -- [ ] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ์ฝค๋งˆ(,)๋กœ ์—ฐ๊ฒฐ๋œ 5๊ฐœ์˜ ์ค‘๋ณต๋˜์ง€ ์•Š์€ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” 5๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค. +- [x] ๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. - [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. - [x] ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” 1~30 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค. diff --git a/src/constants/errorMessages.js b/src/constants/errorMessages.js index c626a90f..5eebe2b0 100644 --- a/src/constants/errorMessages.js +++ b/src/constants/errorMessages.js @@ -13,7 +13,7 @@ const ERROR_MESSAGES = Object.freeze({ INVALID_WINNING_NUMBERS_COUNT: `๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.NUMBER_COUNT}๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, WINNING_NUMBERS_MUST_BE_INTEGER: '๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ๋ชจ๋‘ ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค', - DUPLICATE_WINNING_NUMBERS: '๋‹น์ฒจ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', + DUPLICATE_WINNING_NUMBERS: '๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', OUT_OF_RANGE_WINNING_NUMBERS: `๋‹น์ฒจ ๋ฒˆํ˜ธ๋Š” ${LOTTO_RULES.MIN_NUMBER}๋ถ€ํ„ฐ ${LOTTO_RULES.MAX_NUMBER} ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.`, BONUS_NUMBER_MUST_BE_INTEGER: '๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', From 295ec4ab38d9973062a0d288bedc35f38eea7157 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:43:38 +0900 Subject: [PATCH 19/24] =?UTF-8?q?refactor(Lotto.js):=20Lotto=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=81=EC=88=98=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 --- src/model/Lotto.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/model/Lotto.js b/src/model/Lotto.js index b5845c62..0b58f888 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -1,4 +1,5 @@ import ERROR_MESSAGES from '../constants/errorMessages'; +import { LOTTO_RULES } from '../constants/lottoConstants'; class Lotto { #numbers; // ๋กœ๋˜ ํ•œ ์žฅ์€ 5๊ฐœ์˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๊ฐ€์ง @@ -11,16 +12,20 @@ class Lotto { } #validate(numbers) { - if (numbers.length !== 5) { + if (numbers.length !== LOTTO_RULES.NUMBER_COUNT) { throw new Error(ERROR_MESSAGES.INVALID_NUMBERS_COUNT); } if (numbers.some((number) => !Number.isInteger(number))) { throw new Error(ERROR_MESSAGES.NUMBERS_MUST_BE_INTEGER); } - if (new Set(numbers).size !== 5) { + if (new Set(numbers).size !== LOTTO_RULES.NUMBER_COUNT) { throw new Error(ERROR_MESSAGES.DUPLICATE_NUMBERS); } - if (numbers.some((n) => n < 1 || n > 30)) { + if ( + numbers.some( + (n) => n < LOTTO_RULES.MIN_NUMBER || n > LOTTO_RULES.MAX_NUMBER, + ) + ) { throw new Error(ERROR_MESSAGES.OUT_OF_RANGE_NUMBERS); } } From 0c181a3af5bb7dbd0868369171921e16dfa9aaf7 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:44:39 +0900 Subject: [PATCH 20/24] =?UTF-8?q?refactor(LottoGame.js):=20LottoGame=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=81=EC=88=98=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 --- src/model/LottoGame.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/model/LottoGame.js b/src/model/LottoGame.js index 95f2735c..071cec24 100644 --- a/src/model/LottoGame.js +++ b/src/model/LottoGame.js @@ -1,7 +1,7 @@ import { Random } from '@woowacourse/mission-utils'; import Lotto from './Lotto.js'; -import { RANK } from '../constants/lottoConstants.js'; +import { LOTTO_RULES, RANK } from '../constants/lottoConstants.js'; class LottoGame { #purchaseAmount; // ๊ตฌ์ž… ๊ธˆ์•ก @@ -14,7 +14,7 @@ class LottoGame { // ๊ตฌ์ž… ๊ธˆ์•ก๋งŒํผ ๋กœ๋˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ #createLottos() { - const gameCount = this.#purchaseAmount / 500; + const gameCount = this.#purchaseAmount / LOTTO_RULES.PRICE; const lottos = []; for (let i = 0; i < gameCount; i++) { lottos.push(this.#createOneLotto()); @@ -25,7 +25,11 @@ class LottoGame { // ๋กœ๋˜ ํ•œ ์žฅ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ #createOneLotto() { // 1~30 ์‚ฌ์ด์˜ ๊ฐ’ ์ค‘ 5๊ฐœ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑ - const numbers = Random.pickUniqueNumbersInRange(1, 30, 5); + const numbers = Random.pickUniqueNumbersInRange( + LOTTO_RULES.MIN_NUMBER, + LOTTO_RULES.MAX_NUMBER, + LOTTO_RULES.NUMBER_COUNT, + ); numbers.sort((a, b) => a - b); // ์ •๋ ฌ return new Lotto(numbers); // ์ •๋ ฌ๋œ ์ˆซ์ž ๋ฐฐ์—ด๋กœ ์ƒˆ ๋กœ๋˜ ์ƒ์„ฑ } From 347419832c3bd9650ef1480ab405b665f06f7707 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:45:31 +0900 Subject: [PATCH 21/24] =?UTF-8?q?refactor(WinningLotto.js):=20WinningLotto?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=81=EC=88=98=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 --- src/model/WinningLotto.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/model/WinningLotto.js b/src/model/WinningLotto.js index 7214e629..e7570395 100644 --- a/src/model/WinningLotto.js +++ b/src/model/WinningLotto.js @@ -28,12 +28,12 @@ class WinningLotto { // ๋งค์น˜๋œ ๊ฐœ์ˆ˜์™€ ๋ณด๋„ˆ์Šค ์—ฌ๋ถ€๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ rank๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ #extractRank(matchCount, hasBonus) { - if (matchCount === 5) return 1; - if (matchCount === 4 && hasBonus) return 2; - if (matchCount === 4) return 3; - if (matchCount === 3 && hasBonus) return 4; - if (matchCount === 2 && hasBonus) return 5; - return 0; + if (matchCount === 5) return RANK.FIRST; + if (matchCount === 4 && hasBonus) return RANK.SECOND; + if (matchCount === 4) return RANK.THIRD; + if (matchCount === 3 && hasBonus) return RANK.FOURTH; + if (matchCount === 2 && hasBonus) return RANK.FIFTH; + return RANK.ZERO; } } From e19383eb45fa9e55e24d51f449f9558a6e8b15df Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:46:58 +0900 Subject: [PATCH 22/24] =?UTF-8?q?fix(LottoGame.js):=20LottoGame=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=82=B4=EB=B6=80=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/LottoGame.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/model/LottoGame.js b/src/model/LottoGame.js index 071cec24..f92b7ce2 100644 --- a/src/model/LottoGame.js +++ b/src/model/LottoGame.js @@ -34,9 +34,7 @@ class LottoGame { return new Lotto(numbers); // ์ •๋ ฌ๋œ ์ˆซ์ž ๋ฐฐ์—ด๋กœ ์ƒˆ ๋กœ๋˜ ์ƒ์„ฑ } - // ๋‹น์ฒจ ํ†ต๊ณ„๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  ๋‹น์ฒจ ํ†ต๊ณ„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ createWinningStatistics(winningLotto) { - // ์ดˆ๊ธฐ rankCounts ๊ฐ์ฒด ์ƒ์„ฑ const rankCounts = { [RANK.FIRST]: 0, [RANK.SECOND]: 0, @@ -46,16 +44,11 @@ class LottoGame { [RANK.ZERO]: 0, }; - // ๋กœ๋˜ ๋ฐฐ์—ด์„ ๊ฐ๊ฐ ๊ฒ€์‚ฌํ•˜์—ฌ this.#lottos.forEach((lotto) => { - // ํ•˜๋‚˜์˜ ๋กœ๋˜์— ๋Œ€ํ•ด winningLotto์™€ ๋น„๊ตํ•˜์—ฌ ๋งค์น˜๋œ ์ˆซ์ž์˜ ๊ฐœ์ˆ˜(rank)๋ฅผ ๊ณ„์‚ฐ const rank = winningLotto.match(lotto); - // ๋งค์น˜๋œ ์ˆ˜๊ฐ€ NO_PRIZE๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ทธ ๋žญํฌ์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์„ +1 - rankCounts[rank] += 1; }); - // ๋ชจ๋“  ๋กœ๋˜ ๋ฐฐ์—ด์„ ๊ฒ€์‚ฌํ•œ ๋’ค ์ƒˆ ๋‹น์ฒจ ํ†ต๊ณ„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ return rankCounts; } From a683860911d2f8d49b9d384fe1f2b3dc0e15bf00 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:49:56 +0900 Subject: [PATCH 23/24] =?UTF-8?q?refactor(LottoGame.js):=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=EC=97=90=EC=84=9C=20=EC=88=98?= =?UTF-8?q?=ED=96=89=ED=95=98=EB=8D=98=20Map=20=EB=A1=9C=EC=A7=81=EC=9D=84?= =?UTF-8?q?=20LottoGame=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EA=B0=80=EB=8F=85=EC=84=B1=20=ED=96=A5?= =?UTF-8?q?=EC=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/LottoGameController.js | 10 ++-------- src/model/LottoGame.js | 9 +++++++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js index bafd362c..bb31ab43 100644 --- a/src/controller/LottoGameController.js +++ b/src/controller/LottoGameController.js @@ -56,16 +56,10 @@ class LottoGameController { // ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋กœ WinningLotto ๊ฐ์ฒด ์ƒ์„ฑ const winningLotto = new WinningLotto(winningNumberLotto, bonusNumber); // ๋“ฑ์ˆ˜ ํ†ต๊ณ„ ๊ฐ์ฒด - const winningStatistics = lottoGame.createWinningStatistics(winningLotto); - - // ์ƒ์„ฑ๋œ ํ†ต๊ณ„ ๊ฐ์ฒด๋ฅผ Map์œผ๋กœ ํ‚ค๊ฐ’๋งˆ๋‹ค ์‚ฝ์ž… - const priceMap = new Map(); - for (const [key, value] of Object.entries(winningStatistics)) { - priceMap.set(Number(key), value); - } + const rankCounts = lottoGame.createWinningStatistics(winningLotto); // ์ตœ์ข… ๊ณ„์‚ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅ - OutputView.printResult(priceMap); + await OutputView.printResult(lottoGame.createPriceMap(rankCounts)); } } diff --git a/src/model/LottoGame.js b/src/model/LottoGame.js index f92b7ce2..0e36010f 100644 --- a/src/model/LottoGame.js +++ b/src/model/LottoGame.js @@ -52,6 +52,15 @@ class LottoGame { return rankCounts; } + createPriceMap(rankCounts) { + const priceMap = new Map(); + for (const [key, value] of Object.entries(rankCounts)) { + priceMap.set(Number(key), value); + } + + return priceMap; + } + getLottos() { return [...this.#lottos]; } From c9b02dbb1f6ea7d71394a5f8afa9c37d6efd7af9 Mon Sep 17 00:00:00 2001 From: GGGGGangSub Date: Sat, 10 Jan 2026 16:52:51 +0900 Subject: [PATCH 24/24] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20?= =?UTF-8?q?import=20=EA=B2=BD=EB=A1=9C=20=EB=B2=84=EA=B7=B8=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 --- README.md | 2 +- src/controller/LottoGameController.js | 1 - src/model/Lotto.js | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6be3071b..fcb68492 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ #### 3๏ธโƒฃ ํ†ต๊ณ„ ์ƒ์„ฑ ๊ธฐ๋Šฅ -- [x] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ Map์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. +- [x] ๋กœ๋˜ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋กœ๋˜์— ๋Œ€ํ•ด ๋“ฑ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. #### 4๏ธโƒฃ ๋กœ๋˜ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ ๊ธฐ๋Šฅ diff --git a/src/controller/LottoGameController.js b/src/controller/LottoGameController.js index bb31ab43..5bf29507 100644 --- a/src/controller/LottoGameController.js +++ b/src/controller/LottoGameController.js @@ -1,4 +1,3 @@ -import { Console } from '@woowacourse/mission-utils'; import LottoGame from '../model/LottoGame.js'; import { InputView, OutputView } from './../view.js'; import Lotto from '../model/Lotto.js'; diff --git a/src/model/Lotto.js b/src/model/Lotto.js index 0b58f888..830d6d15 100644 --- a/src/model/Lotto.js +++ b/src/model/Lotto.js @@ -1,5 +1,5 @@ -import ERROR_MESSAGES from '../constants/errorMessages'; -import { LOTTO_RULES } from '../constants/lottoConstants'; +import ERROR_MESSAGES from '../constants/errorMessages.js'; +import { LOTTO_RULES } from '../constants/lottoConstants.js'; class Lotto { #numbers; // ๋กœ๋˜ ํ•œ ์žฅ์€ 5๊ฐœ์˜ ๋ฒˆํ˜ธ ๋ฐฐ์—ด์„ ๊ฐ€์ง