diff --git a/docs/README.md b/docs/README.md index e69de29..336b510 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,614 @@ +# ๐ŸŽ… ํฌ๋ฆฌ์Šค๋งˆ์Šค ํ”„๋กœ๋ชจ์…˜ + +### [ ๋ชฉ์ฐจ ] + +#### 1. [ ๋น„์ฆˆ๋‹ˆ์ŠคํŒ€ ์ „๋‹ฌ์‚ฌํ•ญ ](#๋น„์ฆˆ๋‹ˆ์Šค-ํŒ€-์ „๋‹ฌ์‚ฌํ•ญ) + +- [ํ”„๋กœ๊ทธ๋žจ ๊ธฐ๋Šฅ ์„ค๋ช…](#ํ”„๋กœ๊ทธ๋žจ-๊ธฐ๋Šฅ-์„ค๋ช…) + - [์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ](#์˜ˆ์•ฝ-๋‚ ์งœ-์ž…๋ ฅ) + - [์ฃผ๋ฌธ ๋‚ด์—ญ ์ž…๋ ฅ](#์ฃผ๋ฌธ-๋‚ด์—ญ-์ž…๋ ฅ) + - [์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ](#์‹คํ–‰-๊ฒฐ๊ณผ-์˜ˆ์‹œ) + +#### 2. [ ๊ฐœ๋ฐœํŒ€ ์ „๋‹ฌ์‚ฌํ•ญ ](#๊ฐœ๋ฐœํŒ€-์ „๋‹ฌ์‚ฌํ•ญ) + +- [๊ธฐ๋Šฅ ๋ชฉ๋ก](#๊ธฐ๋Šฅ-๋ชฉ๋ก) +- [ํ”„๋กœ๊ทธ๋žจ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ](#ํŒจํ‚ค์ง€-๊ตฌ์กฐ) +- [ํ”„๋กœ์ ํŠธ ์•„ํ‚คํ…์ฒ˜](#ํ”„๋กœ์ ํŠธ-์•„ํ‚คํ…์ฒ˜) +- [์ถ”ํ›„ ํ™•์žฅ ๋ฐ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ ์‹œ ์ฐธ๊ณ ์‚ฌํ•ญ](#์ถ”ํ›„-ํ™•์žฅ-๋ฐ-์ฝ”๋“œ-์žฌ์‚ฌ์šฉ-์‹œ-์ฐธ๊ณ ์‚ฌํ•ญ) + +#### 3. [ ๊ณตํ†ต ์ „๋‹ฌ ์‚ฌํ•ญ ] + +- [1์ฃผ์ผ ๋’ค ๊ฐœ๋ฐœ ํšŒ์˜์—์„œ ๋…ผ์˜ํ•˜๋ฉด ์ข‹์„ ์‚ฌํ•ญ](#1์ฃผ์ผ-๋’ค-๊ฐœ๋ฐœ-ํšŒ์˜์—์„œ-๋…ผ์˜ํ•˜๋ฉด-์ข‹์„-์‚ฌํ•ญ) + +--- + +## ๋น„์ฆˆ๋‹ˆ์Šค ํŒ€ ์ „๋‹ฌ์‚ฌํ•ญ + +> ### ํ”„๋กœ๊ทธ๋žจ ๊ธฐ๋Šฅ ์„ค๋ช… + +#### ์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ + +#### 1-1. ์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ ( ์œ ํšจํ•˜์ง€ ์•Š์€ ์ž…๋ ฅ๊ฐ’ ) + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +> +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>a +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>40 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>-5 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +``` + +#### ์œ ํšจํ•˜์ง€ ์•Š์€ ์˜ˆ์•ฝ๋‚ ์งœ ์ž…๋ ฅ ๊ธฐ์ค€ + +- ์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ’์„ ์ž…๋ ฅํ•  ์‹œ, +
์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์˜ˆ์•ฝ ๋‚ ์งœ๋ฅผ ๋‹ค์‹œ ์ž…๋ ฅ๋ฐ›์Šต๋‹ˆ๋‹ค. + - ๋น„์–ด์žˆ๋Š” ๊ฐ’ + - ์ˆซ์ž ํ˜•์‹์ด ์•„๋‹Œ ์ž…๋ ฅ ๊ฐ’ + - 1๋ถ€ํ„ฐ 31 ์‚ฌ์ด๊ฐ€ ์•„๋‹Œ ๊ฐ’ + - 0๋ณด๋‹ค ์ž‘์€ ์ˆซ์ž ๊ฐ’ + - ๊ณต๋ฐฑ ํฌํ•จ 2000๊ธ€์ž ์ด์ƒ์ธ ๊ฐ’ + - ๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ 3๊ธ€์ž ์ด์ƒ์ธ ๊ฐ’ + +#### 1-2. ์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ ( ์˜ฌ๋ฐ”๋ฅธ ์ž…๋ ฅ ๊ฐ’ + ๊ณต๋ฐฑ์„ ํฌํ•จํ•œ ์ž…๋ ฅ ๊ฐ’ ) + +```bash +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>24 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> +``` + +```bash +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>31 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> +``` + +```bash +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>2 1 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> +``` + +```bash +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +> 3 1 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> +``` + +- ์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ์ด ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜๋”๋ผ๋„
+ [์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฐ’](#์œ ํšจํ•˜์ง€-์•Š์€-์˜ˆ์•ฝ๋‚ ์งœ-์ž…๋ ฅ-๊ธฐ์ค€)์ด ์•„๋‹Œ ํ˜•์‹์˜ ์ž…๋ ฅ์ด๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +#### ์ฃผ๋ฌธ ๋‚ด์—ญ ์ž…๋ ฅ + +#### 2-1. ์ฃผ๋ฌธ ๋‚ด์—ญ ์ž…๋ ฅ ( ์œ ํšจํ•˜์ง€ ์•Š์€ ์ž…๋ ฅ๊ฐ’ ) + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>1 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค- +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>-3 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค-a +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํ—ˆ๋‹ˆ๊ฐˆ๋ฆญ์น˜ํ‚จ-1 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>์‹œ์ €์ƒ๋Ÿฌ๋“œ-2,ํƒ€ํŒŒ์Šค-3,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-5,์ œ๋กœ์ฝœ๋ผ-10,ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-5 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>์ œ๋กœ์ฝœ๋ผ-3,๋ ˆ๋“œ์™€์ธ-2,์ƒดํŽ˜์ธ-1 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> ํƒ€ํŒŒ์Šค-1,์‹œ์ €์ƒ๋Ÿฌ๋“œ-,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-3 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> ์•„์ด์Šคํฌ๋ฆผ-1,-3,์ดˆ์ฝ”์ผ€์ดํฌ-1 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> ์‹œ์ €์ƒ๋Ÿฌ๋“œ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์‹œ์ €์ƒ๋Ÿฌ๋“œ-1 +[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”. +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +> +``` + +#### ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ๋‚ด์—ญ ์ž…๋ ฅ ๊ธฐ์ค€ + +- ์ฃผ๋ฌธ ๋‚ด์—ญ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ’์„ ์ž…๋ ฅํ•  ์‹œ, +
์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์ฃผ๋ฌธ ๋‚ด์—ญ์„ ๋‹ค์‹œ ์ž…๋ ฅ๋ฐ›์Šต๋‹ˆ๋‹ค. + - ๋น„์–ด์žˆ๋Š” ๊ฐ’ + - ๋ฉ”๋‰ด ์ด๋ฆ„์ด ๋น„์–ด์žˆ๋Š” ๊ฐ’ + - ๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฐ’ + - ๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ ์ˆซ์ž ํ˜•์‹์ด ์•„๋‹Œ ๊ฐ’ + - ๋ฉ”๋‰ด ์ด๋ฆ„์ด 30๊ธ€์ž ์ดˆ๊ณผ์ธ ๊ฐ’ + - ๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ 3๊ธ€์ž ์ดˆ๊ณผ์ธ ๊ฐ’ + - ํŒ๋งค์ค‘์ธ ๋ฉ”๋‰ด๊ฐ€ ์•„๋‹Œ ๋ฉ”๋‰ด ์ด๋ฆ„์„ ํฌํ•จํ•œ ๊ฐ’ + - ๊ฐ ์ฃผ๋ฌธ์˜ ๋ฉ”๋‰ด ๊ฐœ์ˆ˜ ํ•ฉ์ด 20๊ฐœ๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๊ฐ’ + - ๋ฉ”๋‰ด ์ด๋ฆ„์ด ์Œ๋ฃŒ๋งŒ์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ฐ’ + - ๋ฉ”๋‰ด ์ด๋ฆ„๊ณผ ๋ฉ”๋‰ด ๊ฐœ์ˆ˜๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ตฌ๋ถ„์ž(-)๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š๋Š” ๊ฐ’ + - ๊ตฌ๋ถ„์ž(-)๋กœ ๋๋‚˜๋Š” ๊ฐ’ + - ๊ณต๋ฐฑ ํฌํ•จ 2000๊ธ€์ž ์ดˆ๊ณผ์ธ ๊ฐ’ + - ๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ 1000๊ธ€์ž ์ดˆ๊ณผ์ธ ๊ฐ’ + +#### 2-2. ์ฃผ๋ฌธ ๋‚ด์—ญ ์ž…๋ ฅ ( ์˜ฌ๋ฐ”๋ฅธ ์ž…๋ ฅ๊ฐ’ + ๊ณต๋ฐฑ์„ ํฌํ•จํ•œ ์ž…๋ ฅ๊ฐ’ ) + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>31 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค-1,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-1,๋ฐ”๋น„ํ๋ฆฝ-1,์•„์ด์Šคํฌ๋ฆผ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์ƒดํŽ˜์ธ-1,๋ ˆ๋“œ์™€์ธ-1 +12์›” 31์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ! +... +``` + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>25 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>์–‘ ์†ก์ด ์ˆ˜ ํ”„ - 1, ํ‹ฐ ๋ณธ์Šคํ…Œ์ดํฌ-1,๋ฐ”๋น„ํ ๋ฆฝ-1, ์ดˆ์ฝ” ์ผ€์ดํฌ-1, ํฌ๋ฆฌ์Šค๋งˆ์Šค ํŒŒ์Šคํƒ€ -1, ๋ ˆ๋“œ ์™€์ธ-1 +12์›” 25์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ! +... +``` + +- ์ฃผ๋ฌธ ๋‚ด์—ญ ์ž…๋ ฅ์ด ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜๋”๋ผ๋„
+ [์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฐ’](#์œ ํšจํ•˜์ง€-์•Š์€-์ฃผ๋ฌธ๋‚ด์—ญ-์ž…๋ ฅ-๊ธฐ์ค€)์ด ์•„๋‹Œ ํ˜•์‹์˜ ์ž…๋ ฅ์ด๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +#### ์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ + +- ๋‹ค์Œ์€ ์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•œ ๋ช‡๊ฐ€์ง€ ์˜ˆ์‹œ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. + +#### 3-1. ์ฃผ๋ฌธ ๊ธˆ์•ก์ด 10000์› ๋ฏธ๋งŒ, ์ด๋ฒคํŠธ ์ ์šฉ ๋Œ€์ƒ์ด ์•„๋‹Œ ์ฃผ๋ฌธ + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>1 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค-1,์ œ๋กœ์ฝœ๋ผ-1 +12์›” 1์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ! + +<์ฃผ๋ฌธ ๋ฉ”๋‰ด> +์ œ๋กœ์ฝœ๋ผ 1๊ฐœ +ํƒ€ํŒŒ์Šค 1๊ฐœ + +<ํ• ์ธ ์ „ ์ด์ฃผ๋ฌธ ๊ธˆ์•ก> +8,500์› + +<์ฆ์ • ๋ฉ”๋‰ด> +์—†์Œ + +<ํ˜œํƒ ๋‚ด์—ญ> +์—†์Œ + +<์ดํ˜œํƒ ๊ธˆ์•ก> +0์› + +<ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก> +8,500์› + +<12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€> +์—†์Œ +``` + +#### 3-2. ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ, ํ‰์ผ ํ• ์ธ ์ ์šฉ ์ฃผ๋ฌธ ์˜ˆ์‹œ + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>13 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค-1,์‹œ์ €์ƒ๋Ÿฌ๋“œ-1,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์ œ๋กœ์ฝœ๋ผ-1 +12์›” 13์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ! + +<์ฃผ๋ฌธ ๋ฉ”๋‰ด> +์ดˆ์ฝ”์ผ€์ดํฌ 1๊ฐœ +์ œ๋กœ์ฝœ๋ผ 1๊ฐœ +ํƒ€ํŒŒ์Šค 1๊ฐœ +ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ 1๊ฐœ +์‹œ์ €์ƒ๋Ÿฌ๋“œ 1๊ฐœ + +<ํ• ์ธ ์ „ ์ด์ฃผ๋ฌธ ๊ธˆ์•ก> +86,500์› + +<์ฆ์ • ๋ฉ”๋‰ด> +์—†์Œ + +<ํ˜œํƒ ๋‚ด์—ญ> +ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ: -2,200์› +ํ‰์ผ ํ• ์ธ: -2,023์› + +<์ดํ˜œํƒ ๊ธˆ์•ก> +-4,223์› + +<ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก> +82,277์› + +<12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€> +์—†์Œ +``` + +#### 3-3. ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ, ์ฃผ๋ง ํ• ์ธ, ์ฆ์ • ์ด๋ฒคํŠธ ์ ์šฉ ์ฃผ๋ฌธ ์˜ˆ์‹œ + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>23 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค-2,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-1,ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1 +12์›” 23์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ! + +<์ฃผ๋ฌธ ๋ฉ”๋‰ด> +ํƒ€ํŒŒ์Šค 2๊ฐœ +ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ 1๊ฐœ +ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€ 2๊ฐœ +๋ ˆ๋“œ์™€์ธ 1๊ฐœ + +<ํ• ์ธ ์ „ ์ด์ฃผ๋ฌธ ๊ธˆ์•ก> +196,000์› + +<์ฆ์ • ๋ฉ”๋‰ด> +์ƒดํŽ˜์ธ 1๊ฐœ + +<ํ˜œํƒ ๋‚ด์—ญ> +ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ: -3,200์› +์ฃผ๋ง ํ• ์ธ: -6,069์› +์ฆ์ • ์ด๋ฒคํŠธ: -25,000์› + +<์ดํ˜œํƒ ๊ธˆ์•ก> +-34,269์› + +<ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก> +186,731์› + +<12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€> +์‚ฐํƒ€ +``` + +#### 3-4. ํ‰์ผ ํ• ์ธ๋งŒ ์ ์šฉ๋œ ์ฃผ๋ฌธ ์˜ˆ์‹œ + +```bash +์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น 12์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค. +12์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!) +>28 +์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1) +>ํƒ€ํŒŒ์Šค-1,์•„์ด์Šคํฌ๋ฆผ-3,์ œ๋กœ์ฝœ๋ผ-1 +12์›” 28์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ! + +<์ฃผ๋ฌธ ๋ฉ”๋‰ด> +์ œ๋กœ์ฝœ๋ผ 1๊ฐœ +ํƒ€ํŒŒ์Šค 1๊ฐœ +์•„์ด์Šคํฌ๋ฆผ 3๊ฐœ + +<ํ• ์ธ ์ „ ์ด์ฃผ๋ฌธ ๊ธˆ์•ก> +23,500์› + +<์ฆ์ • ๋ฉ”๋‰ด> +์—†์Œ + +<ํ˜œํƒ ๋‚ด์—ญ> +ํ‰์ผ ํ• ์ธ: -6,069์› + +<์ดํ˜œํƒ ๊ธˆ์•ก> +-6,069์› + +<ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก> +17,431์› + +<12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€> +๋ณ„ +``` + +--- + +## ๊ฐœ๋ฐœํŒ€ ์ „๋‹ฌ์‚ฌํ•ญ + +## ๐Ÿ‘จโ€๐Ÿ’ป๊ธฐ๋Šฅ ๋ชฉ๋ก + +## ๐Ÿ’ป [ ์ž…๋ ฅ ๋ฐ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ ๊ธฐ๋Šฅ ] + +> ### ๐ŸŽฏ ๋ชจ๋“  ์ข…๋ฅ˜ ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•œ ๊ฒ€์ฆ + +- [x] ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’์€ ๊ณต๋ฐฑ ํฌํ•จ ๊ธธ์ด 2000๊ธ€์ž ์ดํ•˜๋กœ ํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `BasicInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ ์ž…๋ ฅ ์ข…๋ฅ˜์— ๋”ฐ๋ผ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." ๋˜๋Š”
"[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ + ํ•ด๋‹น ์ž…๋ ฅ + ์ข…๋ฅ˜(๋‚ ์งœ ํ˜น์€ ์ฃผ๋ฌธ)์„ ๋ฐ›๋Š”๋‹ค. + +> ### ๐Ÿ—“ ์˜ˆ์•ฝ ๋‚ ์งœ ์ž…๋ ฅ ๋ฐ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ + +- [x] `์˜ˆ์•ฝ ๋‚ ์งœ` ์ž…๋ ฅ ์š”์ฒญ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์‚ฌ์šฉ์ž์—๊ฒŒ `์˜ˆ์•ฝ ๋‚ ์งœ`๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. + - [x] ๋‚ ์งœ๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฐ’์ด ์•„๋‹˜์„ ํ™•์ธํ•œ๋‹ค. + - [x] ๋‚ ์งœ์— ๊ณต๋ฐฑ์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ๊ณต๋ฐฑ์ด ์•ž ๋’ค์— ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ๋‹ค. + - [x] ๊ณต๋ฐฑ์ด ๊ธ€์ž ์ค‘๊ฐ„์— ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•ด ๊ณต๋ฐฑ ์‚ฌ์ด๋ฅผ ์ด์–ด์ค€๋‹ค. + - [x] ๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ ๊ธ€์ž ๊ธธ์ด๊ฐ€ 2 ์ดํ•˜์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์˜ˆ์•ฝ ๋‚ ์งœ๊ฐ€ ์ˆซ์ž ํ˜•์‹์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์˜ˆ์•ฝ ๋‚ ์งœ๊ฐ€ ์–‘์ˆ˜์ธ์ง€ ํ™•์ธํ•œ๋‹ค. +- [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `DayInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์˜ˆ์•ฝ ๋‚ ์งœ` ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +> ### ๐Ÿ”– ์ฃผ๋ฌธ ๋‚ด์—ญ ์ž…๋ ฅ ๋ฐ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ + +- [x] `์ฃผ๋ฌธ ๋‚ด์—ญ` ์ž…๋ ฅ ์š”์ฒญ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์‚ฌ์šฉ์ž์—๊ฒŒ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. + - [x] `์ฃผ๋ฌธ ๋‚ด์—ญ`์ด ๋น„์–ด์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] `์ฃผ๋ฌธ ๋‚ด์—ญ`์ด 1000๊ธ€์ž ์ดํ•˜์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `BasicInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + - [x] ์ฃผ๋ฌธ ๋‚ด์—ญ์— ๊ณต๋ฐฑ์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ๊ณต๋ฐฑ์ด ์•ž ๋’ค์— ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ๋‹ค. + - [x] ๊ณต๋ฐฑ์ด ๊ธ€์ž ์ค‘๊ฐ„์— ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•ด ๊ณต๋ฐฑ ์‚ฌ์ด๋ฅผ ์ด์–ด์ค€๋‹ค. + - [x] `์ฃผ๋ฌธ`์€ `๋ฉ”๋‰ด ์ด๋ฆ„`๊ณผ `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค. + - [x] `์ฃผ๋ฌธ`์€ ์‰ผํ‘œ(,)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค. + - [x] `๋ฉ”๋‰ด ์ด๋ฆ„`์™€ `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๋Š” ๋Œ€์‹œ(-)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค. + +> #### i) ๐Ÿ™‹`์ฃผ๋ฌธ`์— ๋Œ€ํ•œ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ + +- [x] `์ฃผ๋ฌธ`์ด ๋น„์–ด์žˆ๋Š” ๊ฐ’์ด ์•„๋‹˜์„ ํ™•์ธํ•œ๋‹ค. +- [x] `์ฃผ๋ฌธ`์ด 50๊ธ€์ž ์ดํ•˜์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `BasicInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. +- [x] `์ฃผ๋ฌธ`์ด ๋Œ€์‹œ(-)๋ฅผ ํฌํ•จํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. +- [x] `์ฃผ๋ฌธ` ์•ž ๋’ค์— ๊ณต๋ฐฑ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ๊ณต๋ฐฑ์ด ์•ž๋’ค์— ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ๋‹ค. + - [x] ๊ณต๋ฐฑ์ด ๊ธ€์ž ์ค‘๊ฐ„์— ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•ด ๊ณต๋ฐฑ ์‚ฌ์ด๋ฅผ ์ด์–ด์ค€๋‹ค. +- [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `OrdersInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +> #### ii) โœ‰๏ธ`๋ฉ”๋‰ด ์ด๋ฆ„`์— ๋Œ€ํ•œ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ + +- [x] `๋ฉ”๋‰ด ์ด๋ฆ„`์ด ๋น„์–ด์žˆ๋Š” ๊ฐ’์ด ์•„๋‹˜์„ ํ™•์ธํ•œ๋‹ค. +- [x] `๋ฉ”๋‰ด ์ด๋ฆ„`์ด 30๊ธ€์ž ์ดํ•˜์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `BasicInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. +- [x] `๋ฉ”๋‰ด ์ด๋ฆ„`์ด ๋ฉ”๋‰ดํŒ์— ์žˆ๋Š” ๋ฉ”๋‰ด์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `InvalidOrdersException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." ๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +> #### iii) `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`์— ๋Œ€ํ•œ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ + +- [x] `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฐ’์ด ์•„๋‹˜์„ ํ™•์ธํ•œ๋‹ค. +- [x] `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๊ฐ€ 2๊ธ€์ž ์ดํ•˜์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `BasicInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. +- [x] `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๊ฐ€ ์ˆซ์ž ํ˜•์‹์ธ์ง€ ํ™•์ธํ•œ๋‹ค. +- [x] `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๊ฐ€ 1 ์ด์ƒ ์ •์ˆ˜ ์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `OrdersInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +> #### ๐Ÿ”– iv) `์ฃผ๋ฌธ ๋‚ด์—ญ` ์ž…๋ ฅ๊ฐ’ ์žฌ๊ฒ€์ฆ + +- [x] `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ค‘๋ณต ๋ฉ”๋‰ด๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `OrdersInputException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +## ๐Ÿงฉ [ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ด€๋ จ ๊ธฐ๋Šฅ ] + +> ### ๐Ÿ—“ ๋‚ ์งœ์— ๋Œ€ํ•œ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฒคํŠธ ํŒ๋‹จ ๋„๋ฉ”์ธ ๋กœ์ง + +- ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž…๋ ฅ๋ฐ›์€ ๋‚ ์งœ์— ๋Œ€ํ•ด + - [x] ๋‚ ์งœ๊ฐ€ 1 ์ด์ƒ 31 ์ดํ•˜์˜ ์ˆซ์ž์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] 1 ์ด์ƒ 31 ์ดํ•˜์˜ ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ, `InvalidDayException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
"[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ + ์ถœ๋ ฅํ•œ๋‹ค. + - [x] ํ•ด๋‹น ๋‚ ์งœ๊ฐ€ ํฌ๋ฆฌ์Šค๋งˆ์Šค D-Day ํ”„๋กœ๋ชจ์…˜ ๋Œ€์ƒ ๋‚ ์งœ์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ํ‰์ผ ํ• ์ธ ๋Œ€์ƒ ๋‚ ์งœ์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์ฃผ๋ง ํ• ์ธ ๋Œ€์ƒ ๋‚ ์งœ์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ํŠน๋ณ„ ํ• ์ธ ๋Œ€์ƒ ๋‚ ์งœ์ธ์ง€ ํ™•์ธํ•œ๋‹ค. + +> ### ๐Ÿ”– ์ฃผ๋ฌธ ๋‚ด์—ญ์— ๋”ฐ๋ฅธ ์ด๋ฒคํŠธ ์ ์šฉ ์—ฌ๋ถ€ ํŒ๋‹จ ๋„๋ฉ”์ธ ๋กœ์ง + +- ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž…๋ ฅ๋ฐ›์€ ์ฃผ๋ฌธ ๋‚ด์—ญ( ๋ฉ”๋‰ด ์ด๋ฆ„๊ณผ ์ˆ˜๋Ÿ‰ )์— ๋Œ€ํ•ด + - [x] `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, `๋ฉ”๋‰ด ๊ฐœ์ˆ˜`๊ฐ€ `20๊ฐœ`๊ฐ€ ๋„˜์–ด๊ฐ€๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, `์ฃผ๋ฌธ ๋‚ด์—ญ`์— ์Œ๋ฃŒ์ˆ˜๋งŒ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. + - [x] ์œ„ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ `InvalidOrdersException`์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
+ "[ERROR] ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค.
์ดํ›„ ๋‹ค์‹œ `์ฃผ๋ฌธ ๋‚ด์—ญ`์„ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + - [x] ์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๊ธˆ์•ก์ด `10000์›` ์ดํ•˜์ด๋ฉด, ํ• ์ธ ์ด๋ฒคํŠธ ์ ์šฉ ๋Œ€์ƒ์—์„œ ์ œ์™ธ์‹œํ‚จ๋‹ค. + - [x] ์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๊ธˆ์•ก์ด `12๋งŒ์› ์ด์ƒ`์ผ ์‹œ, `์ƒดํŽ˜์ธ 1๊ฐœ` ๋ฅผ ์ฆ์ •ํ•œ๋‹ค. + - [x] ์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ด์šฉํ•ด์„œ `ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก`์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. + +> ### ๐ŸŽ„ ์ฃผ๋ฌธ ๋‚ด์—ญ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ ์ ์šฉ ๊ฒฐ๊ณผ ์‚ฐ์ถœ ๋„๋ฉ”์ธ ๋กœ์ง + +- [x] ์ฃผ๋ฌธ ๋‚ด์—ญ๊ณผ ๋‚ ์งœ๋ฅผ ๋น„๊ตํ•ด์„œ, `ํ˜œํƒ ๋‚ด์—ญ`์„ ์ƒ์‚ฐํ•œ๋‹ค. + - [x] ์ฃผ๋ฌธ ๋‚ด์—ญ์— ๋‚ ์งœ์— ๋”ฐ๋ฅธ ํ• ์ธ ์—ฌ๋ถ€๋ฅผ ์ ์šฉํ•ด์„œ, `ํ• ์ธ ๊ธˆ์•ก`์„ ๊ณ„์‚ฐํ•œ๋‹ค. + - [x] ํ˜œํƒ ๋‚ด์—ญ์˜ ๊ธˆ์•ก์„ ํ•ฉ์ณ์„œ, `์ด ํ˜œํƒ ๊ธˆ์•ก`์„ ๊ณ„์‚ฐํ•œ๋‹ค. + - [x] ์ฃผ๋ฌธ ๋‚ด์—ญ์— ์ฆ์ • ์ด๋ฒคํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์„ ์‹œ, ์ฆ์ •ํ’ˆ์˜ ๊ฐ€๊ฒฉ๊นŒ์ง€ `์ด ํ˜œํƒ ๊ธˆ์•ก`์— ํฌํ•จ์‹œํ‚จ๋‹ค. + - [x] ์ด ํ˜œํƒ ๊ธˆ์•ก์„ ๊ธฐ๋ฐ˜์œผ๋กœ 12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€๋ฅผ ๋ฐœ๊ธ‰ํ•œ๋‹ค. + - [x] ํ˜œํƒ ๊ธˆ์•ก์ด `5000์›` ์ด์ƒ์ผ ์‹œ, `๋ณ„` +
ํ˜œํƒ ๊ธˆ์•ก์ด `1๋งŒ์›` ์ด์ƒ์ผ ์‹œ, `ํŠธ๋ฆฌ` +
ํ˜œํƒ ๊ธˆ์•ก์ด `2๋งŒ์›` ์ด์ƒ์ผ ์‹œ, `์‚ฐํƒ€` + - [x] `ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก` ์—์„œ `ํ• ์ธ ๊ธˆ์•ก`์„ ๋นผ์„œ `ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก`์„ ๊ณ„์‚ฐํ•œ๋‹ค. + +## ๐Ÿ–จ [ ์ถœ๋ ฅ ๊ธฐ๋Šฅ ] + +> ### ๐ŸŽ™๏ธ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ ์•Œ๋ฆผ ์ถœ๋ ฅ + +- [x] ์ž…๋ ฅ๋ฐ›์€ ๋‚ ์งœ์— ํ•ด๋‹นํ•˜๋Š” ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์•Œ๋ฆผ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. + +> ### ๐Ÿ™‹โ€โ™‚๏ธ ์ฃผ๋ฌธ ๋ฉ”๋‰ด ์ถœ๋ ฅ + +- [x] ์ฃผ๋ฌธ ๋ฉ”๋‰ด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ฃผ๋ฌธ ๋ฉ”๋‰ด๋Š” `${๋ฉ”๋‰ด์ด๋ฆ„} ${๋ฉ”๋‰ด๊ฐœ์ˆ˜} ๊ฐœ` ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ฃผ๋ฌธํ•œ ๋ฉ”๋‰ด ์ „์ฒด๋ฅผ ์œ„์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ถœ๋ ฅ ์ˆœ์„œ๋Š” ์ž์œ ๋กญ๊ฒŒ ํ•œ๋‹ค. + +> ### ๐Ÿ’ฐ ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก ์ถœ๋ ฅ + +- [x] ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] `ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก`์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. + - [x] ๊ธˆ์•ก์˜ ์„ธ์ž๋ฆฌ ์ˆ˜๋งˆ๋‹ค `,`์„ ๋ถ™์ด๋Š” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + +> ### ๐ŸŽ ์ฆ์ • ๋ฉ”๋‰ด ์ถœ๋ ฅ + +- [x] ์ฆ์ • ๋ฉ”๋‰ด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ฆ์ • ๋ฉ”๋‰ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ `${์ฆ์ • ๋ฉ”๋‰ด ์ด๋ฆ„} ${์ฆ์ • ๋ฉ”๋‰ด ๊ฐœ์ˆ˜}๊ฐœ` ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ฆ์ • ๋ฉ”๋‰ด๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ `์—†์Œ`์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + +> ### ๐Ÿ‘ ํ˜œํƒ ๋‚ด์—ญ ์ถœ๋ ฅ + +- [x] ํ˜œํƒ ๋‚ด์—ญ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ ์šฉ๋˜๋Š” ํ• ์ธ ์ด๋ฒคํŠธ๋ณ„ ์ด๋ฆ„ ๋ฐ ํ˜œํƒ ๊ธˆ์•ก์„ ์ •๋ฆฌํ•ด์„œ ๋‚˜ํƒ€๋‚ธ๋‹ค. + - [x] `${์ ์šฉ ํ˜œํƒ ์ด๋ฒคํŠธ ์ด๋ฆ„}: -${ํ˜œํƒ ๊ธˆ์•ก}์›` ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] `ํ˜œํƒ ๊ธˆ์•ก`์˜ ์„ธ์ž๋ฆฌ ์ˆ˜๋งˆ๋‹ค `,`์„ ๋ถ™์ด๋Š” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] ์ ์šฉ๋œ ํ˜œํƒ์ด ์—†์œผ๋ฉด `์—†์Œ`์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ด๋ฒคํŠธ๊ฐ€ ์ ์šฉ๋˜์—ˆ์œผ๋ฉด, ์ถœ๋ ฅ ์ˆœ์„œ๋Š” ์ž์œ ๋กญ๊ฒŒ ํ•œ๋‹ค. + +> ### ๐Ÿ“‰ ์ด ํ˜œํƒ ๊ธˆ์•ก ์ถœ๋ ฅ + +- [x] ์ด ํ˜œํƒ ๊ธˆ์•ก์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] `์ด ํ˜œํƒ ๊ธˆ์•ก`์€ `ํ˜œํƒ ๋‚ด์—ญ`์— ์ ์šฉ๋œ ํ˜œํƒ ๊ธˆ์•ก์„ ๋ชจ๋‘ ๋”ํ•œ ๊ฐ’์„ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] `-${ํ˜œํƒ ๊ธˆ์•ก}์›` ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] `ํ˜œํƒ ๊ธˆ์•ก`์˜ ์„ธ์ž๋ฆฌ ์ˆ˜๋งˆ๋‹ค `,`๋ฅผ ๋ถ™์ด๋Š” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] `์ด ํ˜œํƒ ๊ธˆ์•ก`์ด 0์›์ด๋ฉด `0์›`์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + +> ### ๐Ÿ’ต ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก ์ถœ๋ ฅ + +- [x] ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] `ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก`์€ `ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก`์—์„œ `์ด ํ˜œํƒ ๊ธˆ์•ก`์„ ๋บ€ ๊ฐ’์„ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] `${ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก}์›` ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] `ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก`์˜ ์„ธ์ž๋ฆฌ ์ˆ˜๋งˆ๋‹ค `,`๋ฅผ ๋ถ™์ด๋Š” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + +> ### โญ๐ŸŽ„๐ŸŽ… 12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€ ์ถœ๋ ฅ + +- [x] 12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] `๋ฐฐ์ง€ ์ด๋ฆ„` ์˜ ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] `12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€`๋Š” `์ด ํ˜œํƒ ๊ธˆ์•ก`์˜ ๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ๊ฐ’์„ ๋‹ค๋ฅด๊ฒŒ ์ถœ๋ ฅํ•œ๋‹ค. + - [x] 5000์› ์ด์ƒ์€ `๋ณ„`, 10000์› ์ด์ƒ์€ `ํŠธ๋ฆฌ`, 20000์› ์ด์ƒ์€ `์‚ฐํƒ€`๋กœ ์ถœ๋ ฅํ•œ๋‹ค. +- [x] ์ด๋ฒคํŠธ ๋ฐฐ์ง€๊ฐ€ ๋ถ€์—ฌ๋˜์ง€ ์•Š์œผ๋ฉด `์—†์Œ`์„ ์ถœ๋ ฅํ•œ๋‹ค. + +--- + +## ๐ŸŽ’ํŒจํ‚ค์ง€ ๊ตฌ์กฐ + +```bash +christmas + โ”œโ”€โ”€ Application.java + โ”œโ”€โ”€ EventPlanner.java + โ”œโ”€โ”€ controller + โ”‚ย ย  โ”œโ”€โ”€ OrdersController.java + โ”‚ย ย  โ””โ”€โ”€ ReservationDayController.java + โ”œโ”€โ”€ domain + โ”‚ย ย  โ”œโ”€โ”€ DayPerMonth.java + โ”‚ย ย  โ”œโ”€โ”€ EventManager.java + โ”‚ย ย  โ”œโ”€โ”€ Order.java + โ”‚ย ย  โ”œโ”€โ”€ Orders.java + โ”‚ย ย  โ”œโ”€โ”€ ReservationDay.java + โ”‚ย ย  โ”œโ”€โ”€ constant + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ event + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ ChristmasPromotion.java + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ EventBadge.java + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ EventNumberConstant.java + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ EventSymbolConstant.java + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Promotion.java + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ orders + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ FoodType.java + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ Menu.java + โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ OrdersConstant.java + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ reservationday + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ ReservationDayConstant.java + โ”‚ย ย  โ””โ”€โ”€ exception + โ”‚ย ย  โ”œโ”€โ”€ InvalidOrdersException.java + โ”‚ย ย  โ”œโ”€โ”€ InvalidReservationDayException.java + โ”‚ย ย  โ””โ”€โ”€ message + โ”‚ย ย  โ”œโ”€โ”€ InvalidOrdersExceptionMessage.java + โ”‚ย ย  โ””โ”€โ”€ InvalidReservationDayExceptionMessage.java + โ”œโ”€โ”€ dto + โ”‚ย ย  โ”œโ”€โ”€ BenefitsDetailsDto.java + โ”‚ย ย  โ”œโ”€โ”€ EstimatedAmountWithDiscountDto.java + โ”‚ย ย  โ”œโ”€โ”€ EventBadgeDto.java + โ”‚ย ย  โ”œโ”€โ”€ EventBenefitsPreviewDto.java + โ”‚ย ย  โ”œโ”€โ”€ GiftDto.java + โ”‚ย ย  โ”œโ”€โ”€ OrderedMenusDto.java + โ”‚ย ย  โ”œโ”€โ”€ TotalAmountWithNoDiscountDto.java + โ”‚ย ย  โ””โ”€โ”€ TotalBenefitedAmountDto.java + โ”œโ”€โ”€ global + โ”‚ย ย  โ””โ”€โ”€ ApplicationConstant.java + โ”œโ”€โ”€ service + โ”‚ย ย  โ”œโ”€โ”€ EventManagerService.java + โ”‚ย ย  โ”œโ”€โ”€ OrdersService.java + โ”‚ย ย  โ””โ”€โ”€ ReservationDayService.java + โ””โ”€โ”€ view + โ”œโ”€โ”€ input + โ”‚ย ย  โ”œโ”€โ”€ InputView.java + โ”‚ย ย  โ”œโ”€โ”€ constant + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ InputNumberConstant.java + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ InputSymbolConstant.java + โ”‚ย ย  โ”œโ”€โ”€ exception + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ BasicInputException.java + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ DayInputException.java + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ OrdersInputException.java + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ message + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ BasicInputExceptionMessageFormat.java + โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ DayInputExceptionMessage.java + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ OrdersInputExceptionMessage.java + โ”‚ย ย  โ”œโ”€โ”€ parser + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ InputParser.java + โ”‚ย ย  โ””โ”€โ”€ validator + โ”‚ย ย  โ”œโ”€โ”€ BasicValidator.java + โ”‚ย ย  โ”œโ”€โ”€ DayInputValidator.java + โ”‚ย ย  โ”œโ”€โ”€ MenuCountInputValidator.java + โ”‚ย ย  โ”œโ”€โ”€ MenuNameInputValidator.java + โ”‚ย ย  โ”œโ”€โ”€ OrderInputValidator.java + โ”‚ย ย  โ”œโ”€โ”€ OrdersInputValidator.java + โ”‚ย ย  โ””โ”€โ”€ PositiveIntegerCheckable.java + โ””โ”€โ”€ output + โ”œโ”€โ”€ OutputView.java + โ””โ”€โ”€ constant + โ”œโ”€โ”€ OutputFormatConstant.java + โ”œโ”€โ”€ OutputMessageConstant.java + โ””โ”€โ”€ OutputSymbolConstant.java +``` + +## ํ”„๋กœ์ ํŠธ ์•„ํ‚คํ…์ฒ˜ + + + +## ์ถ”ํ›„ ํ™•์žฅ ๋ฐ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ ์‹œ ์ฐธ๊ณ ์‚ฌํ•ญ + +- `global/ApplicationConstant` ํด๋ž˜์Šค์˜
+ `CURRENT_PROMOTION_MONTH`๋Š” ์ด๋ฒคํŠธ๊ฐ€ ์‹œํ–‰๋˜๋Š” ์›”(month)์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +

+- `ReservationDay` ํด๋ž˜์Šค๋Š” 12์›”์˜ ๋‚ ์งœ ๊ฐ’๊ณผ 12์›” ์ด๋ฒคํŠธ ๋„๋ฉ”์ธ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
+ ํ•ด๋‹น ํด๋ž˜์Šค๋Š” `DayPerMonth`๋ผ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์œผ๋ฉฐ, ์ด ํด๋ž˜์Šค๋Š” ์œ ํšจ ๋‚ ์งœ ๊ฒ€์ฆ ๋กœ์ง์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
+ ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ๋‹ฌ 1์›” ์ด๋ฒคํŠธ๋ฅผ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉ ํ•˜์‹ ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ง„ํ–‰ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

+ 1. `domain.constant.reservationday.ReservationDayConstant` ํด๋ž˜์Šค์—์„œ,
+ `JANUARY_FIRST_DAY`, `JANUARY_LAST_DAY` ๊ฐ’์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

+ 2. `ReservationDay` ํด๋ž˜์Šค์˜ `isInAppropriateRange`๋ฉ”์„œ๋“œ์˜ DECEMBER ๊ด€๋ จ ์ƒ์ˆ˜ ๊ฐ’์„ 1์—์„œ ์ƒ์„ฑํ•œ ์ƒ์ˆ˜ ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•ด์ค๋‹ˆ๋‹ค.

+ 3. `ReservationDay` ํด๋ž˜์Šค์˜ 12์›” ๊ด€๋ จ ๋„๋ฉ”์ธ ๋กœ์ง์„ ์ œ๊ฑฐํ•˜๊ณ ,
1์›” ์ด๋ฒคํŠธ์— ๋งž๋Š” ๋„๋ฉ”์ธ ๋กœ์ง์œผ๋กœ ํด๋ž˜์Šค๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

+ 4. `EventManager` ํด๋ž˜์Šค๋Š” ์ด๋ฒคํŠธ ๊ด€๋ จ ๋„๋ฉ”์ธ ๋กœ์ง์„
์˜ˆ์•ฝ ๋‚ ์งœ์™€ ์ฃผ๋ฌธ ๋‚ด์—ญ์„ ํ†ตํ•ด ํ•ด๊ฒฐํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

+ 5. `ReservationDay`ํด๋ž˜์Šค์˜ ๋„๋ฉ”์ธ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ `EventManager`๋„๋ฉ”์ธ ๋กœ์ง์„ ์ˆ˜์ •ํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.์ด ๋•Œ, `christmas.domain.constant.event` ํด๋”์˜ + ์ด๋ฒคํŠธ ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณ€๊ฒฝ ๋˜๋Š” ํ™œ์šฉํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. + +--- + +### 1์ฃผ์ผ ๋’ค ๊ฐœ๋ฐœ ํšŒ์˜์—์„œ ๋…ผ์˜ํ•˜๋ฉด ์ข‹์„ ์‚ฌํ•ญ + +- ํ‰์ผ ํ• ์ธ ๋‚ ์— ์•„์ด์Šคํฌ๋ฆผ๋งŒ ๋งŽ์ด ์‹œ์ผœ๋จน๋Š” ์†๋‹˜์ด ์˜ค๋ฉด ๋งค์ถœ์— ๋ถˆ๋ฆฌํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
+ ์ด์— ๋Œ€ํ•œ ๋Œ€์‘์ฑ…์ด ํ•„์š”ํ•˜์ง€ ์•Š์„๊นŒ์š”?

+- 30์ผ๊ณผ 31์ผ์€ ์—ฐ๋ง์ด๋ผ ์†๋‹˜์ด ๋งŽ์ด ๋ชฐ๋ฆด ์‹œ๊ธฐ์ธ๋ฐ, ์ด๋ฅผ ์œ ์ธํ• ๋งŒํ•œ ์ด๋ฒคํŠธ๊ฐ€ ๋‹ค์†Œ ๋ถ€์กฑํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
+ ์—ฐ๋ง ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์•ˆ์€ ์–ด๋–จ๊นŒ์š”?

+- ์ฆ์ • ์ด๋ฒคํŠธ๊ฐ€ ์ƒดํŽ˜์ธ๋งŒ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ฒƒ ๊ฐ™์•„, ์•„์ด๋“ค๊ณผ ํ•จ๊ป˜ ์˜ค๋Š” ๋ถ€๋ชจ๋‹˜๋“ค์—๊ฒŒ๋Š” ๊ทธ๋‹ค์ง€ ์œ ์ธ์ฑ…์ด ๋˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. +
๊ณ ๊ฐ์„ ์œ ์ธํ•˜๊ธฐ ์œ„ํ•ด ์ƒดํŽ˜์ธ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์˜คํžˆ๋ ค ์•„์ด๋“ค ์•ž์—์„œ ์Œ์ฃผ ์žฅ๋ ค(?)๋ฅผ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์•„ ์ €ํฌ ์‹๋‹น์„ ์ด์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์„ ๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค.์ฆ์ •ํ’ˆ์„ ๋‹ค์–‘ํ™”ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”? \ No newline at end of file diff --git a/src/main/java/christmas/Application.java b/src/main/java/christmas/Application.java index b9ba6a2..579e42e 100644 --- a/src/main/java/christmas/Application.java +++ b/src/main/java/christmas/Application.java @@ -1,7 +1,11 @@ package christmas; +import christmas.view.input.InputView; +import christmas.view.output.OutputView; + public class Application { public static void main(String[] args) { - // TODO: ํ”„๋กœ๊ทธ๋žจ ๊ตฌํ˜„ + EventPlanner eventPlanner = new EventPlanner(new InputView(), new OutputView()); + eventPlanner.execute(); } -} +} \ No newline at end of file diff --git a/src/main/java/christmas/EventPlanner.java b/src/main/java/christmas/EventPlanner.java new file mode 100644 index 0000000..d5b1d48 --- /dev/null +++ b/src/main/java/christmas/EventPlanner.java @@ -0,0 +1,82 @@ +package christmas; + +import camp.nextstep.edu.missionutils.Console; +import christmas.controller.OrdersController; +import christmas.controller.ReservationDayController; +import christmas.domain.EventManager; +import christmas.domain.Orders; +import christmas.domain.ReservationDay; +import christmas.service.EventManagerService; +import christmas.view.input.InputView; +import christmas.view.output.OutputView; + +public class EventPlanner { + private final OutputView outputView; + private final ReservationDayController reservationDayController; + private final OrdersController ordersController; + private final EventManagerService eventManagerService; + + public EventPlanner(InputView inputView, OutputView outputView) { + this.outputView = outputView; + reservationDayController = new ReservationDayController(inputView, outputView); + ordersController = new OrdersController(inputView, outputView); + eventManagerService = new EventManagerService(); + outputView.printGreetingMessage(); + } + + public void execute() { + ReservationDay reservationDay = reservationDayController.insertReservationDay(); + Orders orders = ordersController.insertOrders(); + EventManager eventManager = EventManager.of(reservationDay, orders); + printResult(reservationDay, orders, eventManager); + terminatePlanner(); + } + + private void printResult(ReservationDay reservationDay, Orders orders, EventManager eventManager) { + printIntroMessage(reservationDay); + printOrderedMenus(orders); + printTotalAmountWithNoDiscount(orders); + printGiftMenu(orders); + printBenefitsDetails(eventManager); + printTotalBenefitedAmount(eventManager); + printEstimatedAmountWithDiscount(eventManager); + printEventBadge(eventManager); + } + + private void printIntroMessage(ReservationDay reservationDay) { + outputView.printIntroMessage(reservationDayController.createEventBenefitsPreviousDto(reservationDay)); + } + + private void printOrderedMenus(Orders orders) { + outputView.printOrderedMenus(ordersController.createOrderedMenusDto(orders)); + } + + private void printTotalAmountWithNoDiscount(Orders orders) { + outputView.printTotalAmountWithNoDiscount(ordersController.createTotalAmountWithNoDiscountDto(orders)); + } + + private void printGiftMenu(Orders orders) { + outputView.printGiftMenu(eventManagerService.createGiftDto(orders)); + } + + private void printBenefitsDetails(EventManager eventManager) { + outputView.printBenefitsDetails(eventManagerService.createBenefitsDetailsDto(eventManager)); + } + + private void printTotalBenefitedAmount(EventManager eventManager) { + outputView.printTotalBenefitedAmount(eventManagerService.createTotalBenefitedAmountDto(eventManager)); + } + + private void printEstimatedAmountWithDiscount(EventManager eventManager) { + outputView.printEstimatedAmountWithDiscount( + eventManagerService.createEstimatedAmountWithDiscountDto(eventManager)); + } + + private void printEventBadge(EventManager eventManager) { + outputView.printEventBadge(eventManagerService.createEventBadgeDto(eventManager)); + } + + private void terminatePlanner() { + Console.close(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/controller/OrdersController.java b/src/main/java/christmas/controller/OrdersController.java new file mode 100644 index 0000000..fa8a313 --- /dev/null +++ b/src/main/java/christmas/controller/OrdersController.java @@ -0,0 +1,47 @@ +package christmas.controller; + +import christmas.domain.Orders; +import christmas.domain.exception.InvalidOrdersException; +import christmas.dto.OrderedMenusDto; +import christmas.dto.TotalAmountWithNoDiscountDto; +import christmas.service.OrdersService; +import christmas.view.input.InputView; +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.OrdersInputException; +import christmas.view.output.OutputView; +import java.util.Map; + +public class OrdersController { + private final InputView inputView; + private final OutputView outputView; + private final OrdersService ordersService; + + public OrdersController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + ordersService = new OrdersService(); + } + + public Orders insertOrders() { + try { + Map orders = askToInsertOrders(); + return ordersService.createOrders(orders); + } catch (BasicInputException | OrdersInputException | InvalidOrdersException e) { + outputView.printErrorMessage(e.getMessage()); + return insertOrders(); + } + } + + private Map askToInsertOrders() throws BasicInputException, OrdersInputException { + outputView.askToInsertOrders(); + return inputView.getOrders(); + } + + public OrderedMenusDto createOrderedMenusDto(Orders orders) { + return ordersService.createOrdersHistoryDto(orders); + } + + public TotalAmountWithNoDiscountDto createTotalAmountWithNoDiscountDto(Orders orders) { + return ordersService.createTotalAmountWithNoDiscountDto(orders); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/controller/ReservationDayController.java b/src/main/java/christmas/controller/ReservationDayController.java new file mode 100644 index 0000000..f10378c --- /dev/null +++ b/src/main/java/christmas/controller/ReservationDayController.java @@ -0,0 +1,41 @@ +package christmas.controller; + +import christmas.domain.ReservationDay; +import christmas.domain.exception.InvalidReservationDayException; +import christmas.dto.EventBenefitsPreviewDto; +import christmas.service.ReservationDayService; +import christmas.view.input.InputView; +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.DayInputException; +import christmas.view.output.OutputView; + +public class ReservationDayController { + private final InputView inputView; + private final OutputView outputView; + private final ReservationDayService reservationDayService; + + public ReservationDayController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + reservationDayService = new ReservationDayService(); + } + + public ReservationDay insertReservationDay() { + try { + int reservationDay = askToInsertReservationDay(); + return reservationDayService.createReservationDay(reservationDay); + } catch (BasicInputException | DayInputException | InvalidReservationDayException e) { + outputView.printErrorMessage(e.getMessage()); + return insertReservationDay(); + } + } + + private int askToInsertReservationDay() throws BasicInputException, DayInputException { + outputView.askToInsertReservationDay(); + return inputView.getReservationDay(); + } + + public EventBenefitsPreviewDto createEventBenefitsPreviousDto(ReservationDay reservationDay) { + return reservationDayService.createEventBenefitsPreviewDto(reservationDay); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/DayPerMonth.java b/src/main/java/christmas/domain/DayPerMonth.java new file mode 100644 index 0000000..28e4d7a --- /dev/null +++ b/src/main/java/christmas/domain/DayPerMonth.java @@ -0,0 +1,22 @@ +package christmas.domain; + +import static christmas.domain.constant.reservationday.ReservationDayConstant.DECEMBER_LAST_DAY; +import static christmas.domain.constant.reservationday.ReservationDayConstant.DEFAULT_FIRST_DAY; +import static christmas.domain.exception.message.InvalidReservationDayExceptionMessage.NOT_IN_APPROPRIATE_RANGE; + +import christmas.domain.exception.InvalidReservationDayException; + +public abstract class DayPerMonth { + public DayPerMonth() { + } + + protected void validate(final int day) { + if (!isInAppropriateRange(day)) { + throw InvalidReservationDayException.of(NOT_IN_APPROPRIATE_RANGE.getMessage()); + } + } + + protected boolean isInAppropriateRange(final int day) { + return day >= DEFAULT_FIRST_DAY.getValue() && day <= DECEMBER_LAST_DAY.getValue(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/EventManager.java b/src/main/java/christmas/domain/EventManager.java new file mode 100644 index 0000000..faccf98 --- /dev/null +++ b/src/main/java/christmas/domain/EventManager.java @@ -0,0 +1,138 @@ +package christmas.domain; + +import static christmas.domain.constant.event.ChristmasPromotion.CHRISTMAS_D_DAY_PROMOTION; +import static christmas.domain.constant.event.EventNumberConstant.NONE_PROMOTION_APPLIED_AMOUNT; +import static christmas.domain.constant.event.Promotion.GIFT_PROMOTION; +import static christmas.domain.constant.event.Promotion.SPECIAL_PROMOTION; +import static christmas.domain.constant.event.Promotion.WEEKDAY_PROMOTION; +import static christmas.domain.constant.event.Promotion.WEEKEND_PROMOTION; + +import christmas.domain.constant.event.EventBadge; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +public class EventManager { + private final ReservationDay reservationDay; + private final Orders orders; + + private EventManager(ReservationDay reservationDay, Orders orders) { + this.reservationDay = reservationDay; + this.orders = orders; + } + + public static EventManager of(ReservationDay reservationDay, Orders orders) { + return new EventManager(reservationDay, orders); + } + + public Map createBenefitsDetails() { + Map benefitsDetails = new LinkedHashMap<>(); + if (orders.isEventApplicable()) { + return makeBenefitsDetails(benefitsDetails); + } + return Collections.unmodifiableMap(benefitsDetails); + } + + private Map makeBenefitsDetails(Map benefitsDetails) { + addChristmasPromotionDetails(benefitsDetails); + addWeekdayPromotionDetails(benefitsDetails); + addWeekendPromotionDetails(benefitsDetails); + addSpecialPromotionDetails(benefitsDetails); + addGiftPromotionDetails(benefitsDetails); + return Collections.unmodifiableMap(benefitsDetails); + } + + private void addChristmasPromotionDetails(Map benefitsDetails) { + if (reservationDay.isChristmasPromotionApplicable()) { + benefitsDetails.put(CHRISTMAS_D_DAY_PROMOTION.getName(), + calculateChristmasPromotionBenefitAmount()); + } + } + + private int calculateChristmasPromotionBenefitAmount() { + return CHRISTMAS_D_DAY_PROMOTION.getBenefitAmount(reservationDay.getDay()); + } + + private void addWeekdayPromotionDetails(Map benefitsDetails) { + if (canAddWeekdayPromotion()) { + benefitsDetails.put(WEEKDAY_PROMOTION.getName(), + calculateWeekdayPromotionBenefitAmount()); + } + } + + private boolean canAddWeekdayPromotion() { + return reservationDay.isWeekdayPromotionApplicable() + && calculateWeekdayPromotionBenefitAmount() + > NONE_PROMOTION_APPLIED_AMOUNT.getValue(); + } + + private int calculateWeekdayPromotionBenefitAmount() { + int count = orders.getOrders().stream() + .filter(Order::isWeekdayPromotionApplicable) + .mapToInt(Order::getMenuCount) + .sum(); + return WEEKDAY_PROMOTION.getBenefitAmount() * count; + } + + private void addWeekendPromotionDetails(Map benefitsDetails) { + if (canAddWeekendPromotion()) { + benefitsDetails.put(WEEKEND_PROMOTION.getName(), + calculateWeekendPromotionBenefitAmount()); + } + } + + private boolean canAddWeekendPromotion() { + return reservationDay.isWeekendPromotionApplicable() + && calculateWeekendPromotionBenefitAmount() + > NONE_PROMOTION_APPLIED_AMOUNT.getValue(); + } + + private int calculateWeekendPromotionBenefitAmount() { + int count = orders.getOrders().stream() + .filter(Order::isWeekendPromotionApplicable) + .mapToInt(Order::getMenuCount) + .sum(); + return WEEKEND_PROMOTION.getBenefitAmount() * count; + } + + private void addSpecialPromotionDetails(Map benefitsDetails) { + if (reservationDay.isSpecialPromotionApplicable()) { + benefitsDetails.put(SPECIAL_PROMOTION.getName(), calculateSpecialPromotionBenefitAmount()); + } + } + + private int calculateSpecialPromotionBenefitAmount() { + return SPECIAL_PROMOTION.getBenefitAmount(); + } + + private void addGiftPromotionDetails(Map benefitsDetails) { + if (orders.isGiftEventApplicable()) { + benefitsDetails.put(GIFT_PROMOTION.getName(), calculateGiftPromotionBenefitAmount()); + } + } + + private int calculateGiftPromotionBenefitAmount() { + return GIFT_PROMOTION.getBenefitAmount(); + } + + public int calculateTotalBenefitedAmount() { + return createBenefitsDetails().values().stream() + .mapToInt(Integer::intValue) + .sum(); + } + + public int calculateEstimatedOrdersAmountWithDiscount() { + return orders.calculateTotalAmountWithNoDiscount() - calculateTotalDiscountedAmount(); + } + + private int calculateTotalDiscountedAmount() { + if (orders.isGiftEventApplicable()) { + return calculateTotalBenefitedAmount() - calculateGiftPromotionBenefitAmount(); + } + return calculateTotalBenefitedAmount(); + } + + public String issueEventBadge() { + return EventBadge.getBadgeNameByBenefitedPrice(calculateTotalBenefitedAmount()); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/Order.java b/src/main/java/christmas/domain/Order.java new file mode 100644 index 0000000..0d1b0b5 --- /dev/null +++ b/src/main/java/christmas/domain/Order.java @@ -0,0 +1,43 @@ +package christmas.domain; + +import christmas.domain.constant.orders.FoodType; +import christmas.domain.constant.orders.Menu; +import christmas.domain.exception.InvalidOrdersException; + +public class Order { + private final Menu menu; + private final int count; + + private Order(Menu menu, final int count) { + this.menu = menu; + this.count = count; + } + + public static Order of(final String menuName, final int count) throws InvalidOrdersException { + return new Order(Menu.searchByName(menuName), count); + } + + public String getMenuName() { + return menu.getName(); + } + + public int getMenuCount() { + return count; + } + + public FoodType getFoodType() { + return menu.getFoodType(); + } + + public boolean isWeekdayPromotionApplicable() { + return menu.isWeekDayPromotionApplicable(); + } + + public boolean isWeekendPromotionApplicable() { + return menu.isWeekendPromotionApplicable(); + } + + public int getTotalPrice() { + return menu.getPrice() * count; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/Orders.java b/src/main/java/christmas/domain/Orders.java new file mode 100644 index 0000000..5aa333e --- /dev/null +++ b/src/main/java/christmas/domain/Orders.java @@ -0,0 +1,71 @@ +package christmas.domain; + +import static christmas.domain.constant.event.EventNumberConstant.EVENT_APPLICABLE_AMOUNT; +import static christmas.domain.constant.event.EventNumberConstant.GIFT_EVENT_APPLICABLE_AMOUNT; +import static christmas.domain.constant.orders.OrdersConstant.MAX_MENU_COUNTS; +import static christmas.domain.exception.message.InvalidOrdersExceptionMessage.EXCEED_MENU_COUNTS_UPPER_LIMIT; +import static christmas.domain.exception.message.InvalidOrdersExceptionMessage.MENUS_ONLY_CONTAIN_BEVERAGE; + +import christmas.domain.constant.orders.FoodType; +import christmas.domain.exception.InvalidOrdersException; +import java.util.Collections; +import java.util.List; + +public class Orders { + private final List orders; + + private Orders(List orders) { + this.orders = orders; + } + + public static Orders from(List orders) { + validate(orders); + return new Orders(orders); + } + + private static void validate(List orders) { + validateSumOfMenuCountsNotExceedUpperLimit(orders); + validateOrderedMenusNotOnlyContainBeverage(orders); + } + + private static void validateSumOfMenuCountsNotExceedUpperLimit(List orders) { + if (sumOfMenuCountsExceedUpperLimit(orders)) { + throw InvalidOrdersException.of(EXCEED_MENU_COUNTS_UPPER_LIMIT.getMessage()); + } + } + + private static boolean sumOfMenuCountsExceedUpperLimit(List orders) { + return orders.stream() + .mapToInt(Order::getMenuCount) + .sum() > MAX_MENU_COUNTS.getValue(); + } + + private static void validateOrderedMenusNotOnlyContainBeverage(List orders) { + if (orderedMenusOnlyContainBeverage(orders)) { + throw InvalidOrdersException.of(MENUS_ONLY_CONTAIN_BEVERAGE.getMessage()); + } + } + + private static boolean orderedMenusOnlyContainBeverage(List orders) { + return orders.stream() + .allMatch(order -> order.getFoodType() == FoodType.BEVERAGE); + } + + public int calculateTotalAmountWithNoDiscount() { + return orders.stream() + .mapToInt(Order::getTotalPrice) + .sum(); + } + + public boolean isEventApplicable() { + return calculateTotalAmountWithNoDiscount() >= EVENT_APPLICABLE_AMOUNT.getValue(); + } + + public boolean isGiftEventApplicable() { + return calculateTotalAmountWithNoDiscount() >= GIFT_EVENT_APPLICABLE_AMOUNT.getValue(); + } + + public List getOrders() { + return Collections.unmodifiableList(orders); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/ReservationDay.java b/src/main/java/christmas/domain/ReservationDay.java new file mode 100644 index 0000000..1888dc0 --- /dev/null +++ b/src/main/java/christmas/domain/ReservationDay.java @@ -0,0 +1,54 @@ +package christmas.domain; + +import static christmas.domain.constant.reservationday.ReservationDayConstant.DECEMBER_CHRISTMAS_DAY; +import static christmas.domain.constant.reservationday.ReservationDayConstant.DECEMBER_FIRST_DAY; +import static christmas.domain.constant.reservationday.ReservationDayConstant.DECEMBER_LAST_DAY; +import static christmas.domain.constant.reservationday.ReservationDayConstant.FRIDAY_VALUE; +import static christmas.domain.constant.reservationday.ReservationDayConstant.SATURDAY_VALUE; +import static christmas.domain.constant.reservationday.ReservationDayConstant.SUNDAY_VALUE; +import static christmas.domain.constant.reservationday.ReservationDayConstant.WEEKDAY_LENGTH; + +import christmas.domain.exception.InvalidReservationDayException; + +public class ReservationDay extends DayPerMonth { + private final int day; + + private ReservationDay(final int day) throws InvalidReservationDayException { + validate(day); + this.day = day; + } + + public static ReservationDay from(final int day) throws InvalidReservationDayException { + return new ReservationDay(day); + } + + public boolean isChristmasPromotionApplicable() { + return day >= DECEMBER_FIRST_DAY.getValue() && day <= DECEMBER_CHRISTMAS_DAY.getValue(); + } + + public boolean isWeekdayPromotionApplicable() { + return !isWeekend(); + } + + public boolean isWeekendPromotionApplicable() { + return isWeekend(); + } + + private boolean isWeekend() { + return day % WEEKDAY_LENGTH.getValue() == FRIDAY_VALUE.getValue() + || day % WEEKDAY_LENGTH.getValue() == SATURDAY_VALUE.getValue(); + } + + public boolean isSpecialPromotionApplicable() { + return day % WEEKDAY_LENGTH.getValue() == SUNDAY_VALUE.getValue() || day == DECEMBER_CHRISTMAS_DAY.getValue(); + } + + public int getDay() { + return day; + } + + @Override + protected boolean isInAppropriateRange(final int day) { + return day >= DECEMBER_FIRST_DAY.getValue() && day <= DECEMBER_LAST_DAY.getValue(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/event/ChristmasPromotion.java b/src/main/java/christmas/domain/constant/event/ChristmasPromotion.java new file mode 100644 index 0000000..3e50d44 --- /dev/null +++ b/src/main/java/christmas/domain/constant/event/ChristmasPromotion.java @@ -0,0 +1,23 @@ +package christmas.domain.constant.event; + +import static christmas.domain.constant.event.EventNumberConstant.CHRISTMAS_PROMOTION_INCREASING_AMOUNT; + +public enum ChristmasPromotion { + CHRISTMAS_D_DAY_PROMOTION("ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ", 900); + + private final String name; + private final int startBenefitAmount; + + ChristmasPromotion(final String name, final int startBenefitAmount) { + this.name = name; + this.startBenefitAmount = startBenefitAmount; + } + + public String getName() { + return name; + } + + public int getBenefitAmount(final int day) { + return startBenefitAmount + day * CHRISTMAS_PROMOTION_INCREASING_AMOUNT.getValue(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/event/EventBadge.java b/src/main/java/christmas/domain/constant/event/EventBadge.java new file mode 100644 index 0000000..bac6c4c --- /dev/null +++ b/src/main/java/christmas/domain/constant/event/EventBadge.java @@ -0,0 +1,44 @@ +package christmas.domain.constant.event; + +import static christmas.domain.constant.event.EventSymbolConstant.NO_BADGE_SYMBOL; + +public enum EventBadge { + STAR("๋ณ„", 5_000), + TREE("ํŠธ๋ฆฌ", 10_000), + SANTA("์‚ฐํƒ€", 20_000); + + private final String name; + private final int minimumTotalBenefitedPrice; + + EventBadge(final String name, final int minimumTotalBenefitedPrice) { + this.name = name; + this.minimumTotalBenefitedPrice = minimumTotalBenefitedPrice; + } + + public static String getBadgeNameByBenefitedPrice(final int totalBenefitedPrice) { + if (isStar(totalBenefitedPrice)) { + return STAR.name; + } + if (isTree(totalBenefitedPrice)) { + return TREE.name; + } + if (isSanta(totalBenefitedPrice)) { + return SANTA.name; + } + return NO_BADGE_SYMBOL.getSymbol(); + } + + private static boolean isStar(final int totalBenefitedPrice) { + return totalBenefitedPrice >= STAR.minimumTotalBenefitedPrice + && totalBenefitedPrice < TREE.minimumTotalBenefitedPrice; + } + + private static boolean isTree(final int totalBenefitedPrice) { + return totalBenefitedPrice >= TREE.minimumTotalBenefitedPrice + && totalBenefitedPrice < SANTA.minimumTotalBenefitedPrice; + } + + private static boolean isSanta(final int totalBenefitedPrice) { + return totalBenefitedPrice >= SANTA.minimumTotalBenefitedPrice; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/event/EventNumberConstant.java b/src/main/java/christmas/domain/constant/event/EventNumberConstant.java new file mode 100644 index 0000000..12cecd3 --- /dev/null +++ b/src/main/java/christmas/domain/constant/event/EventNumberConstant.java @@ -0,0 +1,19 @@ +package christmas.domain.constant.event; + +public enum EventNumberConstant { + EVENT_APPLICABLE_AMOUNT(10_000), + GIFT_EVENT_APPLICABLE_AMOUNT(120_000), + GIFT_CHAMPAGNE_COUNT(1), + CHRISTMAS_PROMOTION_INCREASING_AMOUNT(100), + NONE_PROMOTION_APPLIED_AMOUNT(0); + + private final int value; + + EventNumberConstant(final int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/event/EventSymbolConstant.java b/src/main/java/christmas/domain/constant/event/EventSymbolConstant.java new file mode 100644 index 0000000..e7fc013 --- /dev/null +++ b/src/main/java/christmas/domain/constant/event/EventSymbolConstant.java @@ -0,0 +1,14 @@ +package christmas.domain.constant.event; + +public enum EventSymbolConstant { + NO_BADGE_SYMBOL(""); + private final String symbol; + + EventSymbolConstant(final String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/event/Promotion.java b/src/main/java/christmas/domain/constant/event/Promotion.java new file mode 100644 index 0000000..898c630 --- /dev/null +++ b/src/main/java/christmas/domain/constant/event/Promotion.java @@ -0,0 +1,24 @@ +package christmas.domain.constant.event; + +public enum Promotion { + WEEKDAY_PROMOTION("ํ‰์ผ ํ• ์ธ", 2_023), + WEEKEND_PROMOTION("์ฃผ๋ง ํ• ์ธ", 2_023), + SPECIAL_PROMOTION("ํŠน๋ณ„ ํ• ์ธ", 1_000), + GIFT_PROMOTION("์ฆ์ • ์ด๋ฒคํŠธ", 25_000); + + private final String name; + private final int benefitAmount; + + Promotion(final String name, final int benefitAmount) { + this.name = name; + this.benefitAmount = benefitAmount; + } + + public String getName() { + return name; + } + + public int getBenefitAmount() { + return benefitAmount; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/orders/FoodType.java b/src/main/java/christmas/domain/constant/orders/FoodType.java new file mode 100644 index 0000000..4679658 --- /dev/null +++ b/src/main/java/christmas/domain/constant/orders/FoodType.java @@ -0,0 +1,25 @@ +package christmas.domain.constant.orders; + +public enum FoodType { + + APPETIZER(false, false), + MAIN(false, true), + DESSERT(true, false), + BEVERAGE(false, false); + + private final boolean isWeekdayPromotionApplicable; + private final boolean isWeekendPromotionApplicable; + + FoodType(final boolean isWeekdayPromotionApplicable, final boolean isWeekendPromotionApplicable) { + this.isWeekdayPromotionApplicable = isWeekdayPromotionApplicable; + this.isWeekendPromotionApplicable = isWeekendPromotionApplicable; + } + + public boolean isWeekdayPromotionApplicable() { + return isWeekdayPromotionApplicable; + } + + public boolean isWeekendPromotionApplicable() { + return isWeekendPromotionApplicable; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/orders/Menu.java b/src/main/java/christmas/domain/constant/orders/Menu.java new file mode 100644 index 0000000..223997c --- /dev/null +++ b/src/main/java/christmas/domain/constant/orders/Menu.java @@ -0,0 +1,65 @@ +package christmas.domain.constant.orders; + +import static christmas.domain.constant.orders.FoodType.APPETIZER; +import static christmas.domain.constant.orders.FoodType.BEVERAGE; +import static christmas.domain.constant.orders.FoodType.DESSERT; +import static christmas.domain.constant.orders.FoodType.MAIN; +import static christmas.domain.exception.message.InvalidOrdersExceptionMessage.NOT_EXISTING_MENU; + +import christmas.domain.exception.InvalidOrdersException; +import java.util.Arrays; + +public enum Menu { + MUSHROOM_SOUP("์–‘์†ก์ด์ˆ˜ํ”„", 6_000, APPETIZER), + TAPAS("ํƒ€ํŒŒ์Šค", 5_500, APPETIZER), + CAESAR_SALAD("์‹œ์ €์ƒ๋Ÿฌ๋“œ", 8_000, APPETIZER), + + T_BONE_STAKE("ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ", 55_000, MAIN), + BARBECUE_RIB("๋ฐ”๋น„ํ๋ฆฝ", 54_000, MAIN), + SEAFOOD_PASTA("ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€", 35_000, MAIN), + CHRISTMAS_PASTA("ํฌ๋ฆฌ์Šค๋งˆ์ŠคํŒŒ์Šคํƒ€", 25_000, MAIN), + + CHOCOLATE_CAKE("์ดˆ์ฝ”์ผ€์ดํฌ", 15_000, DESSERT), + ICE_CREAM("์•„์ด์Šคํฌ๋ฆผ", 5_000, DESSERT), + + ZERO_COKE("์ œ๋กœ์ฝœ๋ผ", 3_000, BEVERAGE), + RED_WINE("๋ ˆ๋“œ์™€์ธ", 60_000, BEVERAGE), + CHAMPAGNE("์ƒดํŽ˜์ธ", 25_000, BEVERAGE); + + private final String name; + private final int price; + private final FoodType foodType; + + Menu(final String name, final int price, final FoodType foodType) { + this.name = name; + this.price = price; + this.foodType = foodType; + } + + public String getName() { + return name; + } + + public int getPrice() { + return price; + } + + public FoodType getFoodType() { + return foodType; + } + + public boolean isWeekDayPromotionApplicable() { + return foodType.isWeekdayPromotionApplicable(); + } + + public boolean isWeekendPromotionApplicable() { + return foodType.isWeekendPromotionApplicable(); + } + + public static Menu searchByName(final String name) { + return Arrays.stream(Menu.values()) + .filter(menu -> menu.name.equalsIgnoreCase(name)) + .findFirst() + .orElseThrow(() -> InvalidOrdersException.of(NOT_EXISTING_MENU.getMessage())); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/orders/OrdersConstant.java b/src/main/java/christmas/domain/constant/orders/OrdersConstant.java new file mode 100644 index 0000000..df44a44 --- /dev/null +++ b/src/main/java/christmas/domain/constant/orders/OrdersConstant.java @@ -0,0 +1,15 @@ +package christmas.domain.constant.orders; + +public enum OrdersConstant { + MAX_MENU_COUNTS(20); + + private final int value; + + OrdersConstant(final int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/constant/reservationday/ReservationDayConstant.java b/src/main/java/christmas/domain/constant/reservationday/ReservationDayConstant.java new file mode 100644 index 0000000..66e9fbc --- /dev/null +++ b/src/main/java/christmas/domain/constant/reservationday/ReservationDayConstant.java @@ -0,0 +1,23 @@ +package christmas.domain.constant.reservationday; + +public enum ReservationDayConstant { + DEFAULT_FIRST_DAY(1), + DEFAULT_LAST_DAY(30), + DECEMBER_FIRST_DAY(1), + DECEMBER_LAST_DAY(31), + DECEMBER_CHRISTMAS_DAY(25), + WEEKDAY_LENGTH(7), + FRIDAY_VALUE(1), + SATURDAY_VALUE(2), + SUNDAY_VALUE(3); + + private final int value; + + ReservationDayConstant(final int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/exception/InvalidOrdersException.java b/src/main/java/christmas/domain/exception/InvalidOrdersException.java new file mode 100644 index 0000000..e0e25ae --- /dev/null +++ b/src/main/java/christmas/domain/exception/InvalidOrdersException.java @@ -0,0 +1,11 @@ +package christmas.domain.exception; + +public class InvalidOrdersException extends IllegalArgumentException { + private InvalidOrdersException(final String invalidMenuExceptionMessage) { + super(invalidMenuExceptionMessage); + } + + public static InvalidOrdersException of(final String invalidMenuExceptionMessage) { + return new InvalidOrdersException(invalidMenuExceptionMessage); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/exception/InvalidReservationDayException.java b/src/main/java/christmas/domain/exception/InvalidReservationDayException.java new file mode 100644 index 0000000..e4ff894 --- /dev/null +++ b/src/main/java/christmas/domain/exception/InvalidReservationDayException.java @@ -0,0 +1,11 @@ +package christmas.domain.exception; + +public class InvalidReservationDayException extends IllegalArgumentException { + private InvalidReservationDayException(final String invalidDayExceptionMessage) { + super(invalidDayExceptionMessage); + } + + public static InvalidReservationDayException of(final String invalidDayExceptionMessage) { + return new InvalidReservationDayException(invalidDayExceptionMessage); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/exception/message/InvalidOrdersExceptionMessage.java b/src/main/java/christmas/domain/exception/message/InvalidOrdersExceptionMessage.java new file mode 100644 index 0000000..b479cb4 --- /dev/null +++ b/src/main/java/christmas/domain/exception/message/InvalidOrdersExceptionMessage.java @@ -0,0 +1,19 @@ +package christmas.domain.exception.message; + +import static christmas.global.ApplicationConstant.ERROR_PREFIX; + +public enum InvalidOrdersExceptionMessage { + NOT_EXISTING_MENU("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + EXCEED_MENU_COUNTS_UPPER_LIMIT("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + MENUS_ONLY_CONTAIN_BEVERAGE("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + + private final String message; + + InvalidOrdersExceptionMessage(final String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_PREFIX + message; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/domain/exception/message/InvalidReservationDayExceptionMessage.java b/src/main/java/christmas/domain/exception/message/InvalidReservationDayExceptionMessage.java new file mode 100644 index 0000000..23b0f05 --- /dev/null +++ b/src/main/java/christmas/domain/exception/message/InvalidReservationDayExceptionMessage.java @@ -0,0 +1,17 @@ +package christmas.domain.exception.message; + +import static christmas.global.ApplicationConstant.ERROR_PREFIX; + +public enum InvalidReservationDayExceptionMessage { + NOT_IN_APPROPRIATE_RANGE("์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + + private final String message; + + InvalidReservationDayExceptionMessage(final String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_PREFIX + message; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/BenefitsDetailsDto.java b/src/main/java/christmas/dto/BenefitsDetailsDto.java new file mode 100644 index 0000000..44d606f --- /dev/null +++ b/src/main/java/christmas/dto/BenefitsDetailsDto.java @@ -0,0 +1,24 @@ +package christmas.dto; + +import java.util.Collections; +import java.util.Map; + +public class BenefitsDetailsDto { + private final Map benefitsDetails; + + private BenefitsDetailsDto(Map benefitsDetails) { + this.benefitsDetails = benefitsDetails; + } + + public static BenefitsDetailsDto from(Map benefitsDetails) { + return new BenefitsDetailsDto(benefitsDetails); + } + + public Map getBenefitsDetails() { + return Collections.unmodifiableMap(benefitsDetails); + } + + public boolean isEmpty() { + return benefitsDetails.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/EstimatedAmountWithDiscountDto.java b/src/main/java/christmas/dto/EstimatedAmountWithDiscountDto.java new file mode 100644 index 0000000..6e459e7 --- /dev/null +++ b/src/main/java/christmas/dto/EstimatedAmountWithDiscountDto.java @@ -0,0 +1,17 @@ +package christmas.dto; + +public class EstimatedAmountWithDiscountDto { + private final int amount; + + public EstimatedAmountWithDiscountDto(final int amount) { + this.amount = amount; + } + + public static EstimatedAmountWithDiscountDto from(final int amount) { + return new EstimatedAmountWithDiscountDto(amount); + } + + public int getAmount() { + return amount; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/EventBadgeDto.java b/src/main/java/christmas/dto/EventBadgeDto.java new file mode 100644 index 0000000..038140b --- /dev/null +++ b/src/main/java/christmas/dto/EventBadgeDto.java @@ -0,0 +1,21 @@ +package christmas.dto; + +public class EventBadgeDto { + private final String badgeName; + + public EventBadgeDto(final String badgeName) { + this.badgeName = badgeName; + } + + public static EventBadgeDto from(final String badgeName) { + return new EventBadgeDto(badgeName); + } + + public String getBadgeName() { + return badgeName; + } + + public boolean isEmpty() { + return badgeName.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/EventBenefitsPreviewDto.java b/src/main/java/christmas/dto/EventBenefitsPreviewDto.java new file mode 100644 index 0000000..9fc1315 --- /dev/null +++ b/src/main/java/christmas/dto/EventBenefitsPreviewDto.java @@ -0,0 +1,17 @@ +package christmas.dto; + +public class EventBenefitsPreviewDto { + private final int day; + + public EventBenefitsPreviewDto(final int day) { + this.day = day; + } + + public static EventBenefitsPreviewDto from(final int day) { + return new EventBenefitsPreviewDto(day); + } + + public int getDay() { + return day; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/GiftDto.java b/src/main/java/christmas/dto/GiftDto.java new file mode 100644 index 0000000..6ffd78a --- /dev/null +++ b/src/main/java/christmas/dto/GiftDto.java @@ -0,0 +1,24 @@ +package christmas.dto; + +import java.util.Collections; +import java.util.Map; + +public class GiftDto { + private final Map gift; + + private GiftDto(Map gift) { + this.gift = gift; + } + + public static GiftDto from(Map gift) { + return new GiftDto(gift); + } + + public Map getGift() { + return Collections.unmodifiableMap(gift); + } + + public boolean isEmpty() { + return gift.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/OrderedMenusDto.java b/src/main/java/christmas/dto/OrderedMenusDto.java new file mode 100644 index 0000000..4b79253 --- /dev/null +++ b/src/main/java/christmas/dto/OrderedMenusDto.java @@ -0,0 +1,20 @@ +package christmas.dto; + +import java.util.Collections; +import java.util.Map; + +public class OrderedMenusDto { + private final Map orders; + + public OrderedMenusDto(Map orders) { + this.orders = orders; + } + + public static OrderedMenusDto from(Map orders) { + return new OrderedMenusDto(orders); + } + + public Map getOrders() { + return Collections.unmodifiableMap(orders); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/TotalAmountWithNoDiscountDto.java b/src/main/java/christmas/dto/TotalAmountWithNoDiscountDto.java new file mode 100644 index 0000000..5cabde5 --- /dev/null +++ b/src/main/java/christmas/dto/TotalAmountWithNoDiscountDto.java @@ -0,0 +1,17 @@ +package christmas.dto; + +public class TotalAmountWithNoDiscountDto { + private final int amount; + + public TotalAmountWithNoDiscountDto(final int amount) { + this.amount = amount; + } + + public static TotalAmountWithNoDiscountDto from(final int amount) { + return new TotalAmountWithNoDiscountDto(amount); + } + + public int getAmount() { + return amount; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/dto/TotalBenefitedAmountDto.java b/src/main/java/christmas/dto/TotalBenefitedAmountDto.java new file mode 100644 index 0000000..5cbbbbd --- /dev/null +++ b/src/main/java/christmas/dto/TotalBenefitedAmountDto.java @@ -0,0 +1,17 @@ +package christmas.dto; + +public class TotalBenefitedAmountDto { + private final int amount; + + public TotalBenefitedAmountDto(final int amount) { + this.amount = amount; + } + + public static TotalBenefitedAmountDto from(final int amount) { + return new TotalBenefitedAmountDto(amount); + } + + public int getAmount() { + return amount; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/global/ApplicationConstant.java b/src/main/java/christmas/global/ApplicationConstant.java new file mode 100644 index 0000000..d544ca2 --- /dev/null +++ b/src/main/java/christmas/global/ApplicationConstant.java @@ -0,0 +1,9 @@ +package christmas.global; + +public class ApplicationConstant { + public static final int CURRENT_PROMOTION_MONTH = 12; + public static final String ERROR_PREFIX = "[ERROR] "; + + private ApplicationConstant() { + } +} \ No newline at end of file diff --git a/src/main/java/christmas/service/EventManagerService.java b/src/main/java/christmas/service/EventManagerService.java new file mode 100644 index 0000000..b3e3808 --- /dev/null +++ b/src/main/java/christmas/service/EventManagerService.java @@ -0,0 +1,45 @@ +package christmas.service; + + +import static christmas.domain.constant.event.EventNumberConstant.GIFT_CHAMPAGNE_COUNT; + +import christmas.domain.EventManager; +import christmas.domain.Orders; +import christmas.domain.constant.orders.Menu; +import christmas.dto.BenefitsDetailsDto; +import christmas.dto.EstimatedAmountWithDiscountDto; +import christmas.dto.EventBadgeDto; +import christmas.dto.GiftDto; +import christmas.dto.TotalBenefitedAmountDto; +import java.util.LinkedHashMap; +import java.util.Map; + +public class EventManagerService { + public GiftDto createGiftDto(Orders orders) { + Map gifts = new LinkedHashMap<>(); + if (orders.isGiftEventApplicable()) { + makeGifts(gifts); + } + return GiftDto.from(gifts); + } + + private void makeGifts(Map gifts) { + gifts.put(Menu.CHAMPAGNE.getName(), GIFT_CHAMPAGNE_COUNT.getValue()); + } + + public BenefitsDetailsDto createBenefitsDetailsDto(EventManager eventManager) { + return BenefitsDetailsDto.from(eventManager.createBenefitsDetails()); + } + + public TotalBenefitedAmountDto createTotalBenefitedAmountDto(EventManager eventManager) { + return TotalBenefitedAmountDto.from(eventManager.calculateTotalBenefitedAmount()); + } + + public EstimatedAmountWithDiscountDto createEstimatedAmountWithDiscountDto(EventManager eventManager) { + return EstimatedAmountWithDiscountDto.from(eventManager.calculateEstimatedOrdersAmountWithDiscount()); + } + + public EventBadgeDto createEventBadgeDto(EventManager eventManager) { + return EventBadgeDto.from(eventManager.issueEventBadge()); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/service/OrdersService.java b/src/main/java/christmas/service/OrdersService.java new file mode 100644 index 0000000..447ce0f --- /dev/null +++ b/src/main/java/christmas/service/OrdersService.java @@ -0,0 +1,42 @@ +package christmas.service; + +import christmas.domain.Order; +import christmas.domain.Orders; +import christmas.domain.exception.InvalidOrdersException; +import christmas.dto.OrderedMenusDto; +import christmas.dto.TotalAmountWithNoDiscountDto; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class OrdersService { + public Orders createOrders(Map orders) throws InvalidOrdersException { + return Orders.from(makeOrders(orders)); + } + + private List makeOrders(Map orders) throws InvalidOrdersException { + return orders.entrySet().stream() + .map(order -> createOrder(order.getKey(), order.getValue())) + .toList(); + } + + private Order createOrder(final String menuName, final int menuCount) throws InvalidOrdersException { + return Order.of(menuName, menuCount); + } + + public OrderedMenusDto createOrdersHistoryDto(Orders orders) { + return OrderedMenusDto.from(makeOrdersHistory(orders)); + } + + private Map makeOrdersHistory(Orders orders) { + return orders.getOrders().stream() + .collect(Collectors.toUnmodifiableMap( + Order::getMenuName, + Order::getMenuCount + )); + } + + public TotalAmountWithNoDiscountDto createTotalAmountWithNoDiscountDto(Orders orders) { + return TotalAmountWithNoDiscountDto.from(orders.calculateTotalAmountWithNoDiscount()); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/service/ReservationDayService.java b/src/main/java/christmas/service/ReservationDayService.java new file mode 100644 index 0000000..c2a7cf7 --- /dev/null +++ b/src/main/java/christmas/service/ReservationDayService.java @@ -0,0 +1,15 @@ +package christmas.service; + +import christmas.domain.ReservationDay; +import christmas.domain.exception.InvalidReservationDayException; +import christmas.dto.EventBenefitsPreviewDto; + +public class ReservationDayService { + public ReservationDay createReservationDay(final int day) throws InvalidReservationDayException { + return ReservationDay.from(day); + } + + public EventBenefitsPreviewDto createEventBenefitsPreviewDto(ReservationDay day) { + return EventBenefitsPreviewDto.from(day.getDay()); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/InputView.java b/src/main/java/christmas/view/input/InputView.java new file mode 100644 index 0000000..9901e42 --- /dev/null +++ b/src/main/java/christmas/view/input/InputView.java @@ -0,0 +1,28 @@ +package christmas.view.input; + +import camp.nextstep.edu.missionutils.Console; +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.DayInputException; +import christmas.view.input.exception.OrdersInputException; +import christmas.view.input.parser.InputParser; +import java.util.Map; + +public class InputView { + private final InputParser inputParser; + + public InputView() { + inputParser = new InputParser(); + } + + public int getReservationDay() throws BasicInputException, DayInputException { + return inputParser.parseReservationDay(readLine()); + } + + public Map getOrders() throws BasicInputException, OrdersInputException { + return inputParser.parseOrders(readLine()); + } + + private String readLine() { + return Console.readLine(); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/constant/InputNumberConstant.java b/src/main/java/christmas/view/input/constant/InputNumberConstant.java new file mode 100644 index 0000000..d9d8df0 --- /dev/null +++ b/src/main/java/christmas/view/input/constant/InputNumberConstant.java @@ -0,0 +1,23 @@ +package christmas.view.input.constant; + +public enum InputNumberConstant { + APPLICATION_MAX_INPUT_LENGTH(2000), + ORDERS_MAX_INPUT_LENGTH(1000), + ORDER_MAX_INPUT_LENGTH(33), + MENU_NAME_MAX_INPUT_LENGTH(30), + MENU_COUNT_MAX_INPUT_LENGTH(2), + DAY_MAX_INPUT_LENGTH(2), + MENU_NAME_INDEX(0), + MENU_COUNT_INDEX(1), + POSITIVE_BOUNDARY_VALUE(0); + + private final int value; + + InputNumberConstant(final int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/constant/InputSymbolConstant.java b/src/main/java/christmas/view/input/constant/InputSymbolConstant.java new file mode 100644 index 0000000..f7b9bee --- /dev/null +++ b/src/main/java/christmas/view/input/constant/InputSymbolConstant.java @@ -0,0 +1,20 @@ +package christmas.view.input.constant; + +public enum InputSymbolConstant { + BLANK(" "), + VOID(""), + ORDERS_DELIMITER(","), + ORDER_DELIMITER("-"), + DAY_SYMBOL("๋‚ ์งœ"), + ORDER_SYMBOL("์ฃผ๋ฌธ"); + + private final String symbol; + + InputSymbolConstant(final String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/exception/BasicInputException.java b/src/main/java/christmas/view/input/exception/BasicInputException.java new file mode 100644 index 0000000..23d5a58 --- /dev/null +++ b/src/main/java/christmas/view/input/exception/BasicInputException.java @@ -0,0 +1,11 @@ +package christmas.view.input.exception; + +public class BasicInputException extends IllegalArgumentException { + private BasicInputException(final String invalidDayExceptionMessage) { + super(invalidDayExceptionMessage); + } + + public static BasicInputException of(final String basicInputExceptionMessage) { + return new BasicInputException(basicInputExceptionMessage); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/exception/DayInputException.java b/src/main/java/christmas/view/input/exception/DayInputException.java new file mode 100644 index 0000000..6820be7 --- /dev/null +++ b/src/main/java/christmas/view/input/exception/DayInputException.java @@ -0,0 +1,11 @@ +package christmas.view.input.exception; + +public class DayInputException extends IllegalArgumentException { + private DayInputException(final String dayInputExceptionMessage) { + super(dayInputExceptionMessage); + } + + public static DayInputException of(final String dayInputExceptionMessage) { + return new DayInputException(dayInputExceptionMessage); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/exception/OrdersInputException.java b/src/main/java/christmas/view/input/exception/OrdersInputException.java new file mode 100644 index 0000000..3c94983 --- /dev/null +++ b/src/main/java/christmas/view/input/exception/OrdersInputException.java @@ -0,0 +1,11 @@ +package christmas.view.input.exception; + +public class OrdersInputException extends IllegalArgumentException { + private OrdersInputException(final String ordersInputExceptionMessage) { + super(ordersInputExceptionMessage); + } + + public static OrdersInputException of(final String ordersInputExceptionMessage) { + return new OrdersInputException(ordersInputExceptionMessage); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/exception/message/BasicInputExceptionMessageFormat.java b/src/main/java/christmas/view/input/exception/message/BasicInputExceptionMessageFormat.java new file mode 100644 index 0000000..26444fc --- /dev/null +++ b/src/main/java/christmas/view/input/exception/message/BasicInputExceptionMessageFormat.java @@ -0,0 +1,19 @@ +package christmas.view.input.exception.message; + +import static christmas.global.ApplicationConstant.ERROR_PREFIX; + +public enum BasicInputExceptionMessageFormat { + TOO_LONG_WITH_BLANKS_FORMAT("์œ ํšจํ•˜์ง€ ์•Š์€ %s์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + EMPTY_FORMAT("์œ ํšจํ•˜์ง€ ์•Š์€ %s์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + TOO_LONG_FORMAT("์œ ํšจํ•˜์ง€ ์•Š์€ %s์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + + private final String format; + + BasicInputExceptionMessageFormat(final String format) { + this.format = format; + } + + public String getFormat() { + return ERROR_PREFIX + format; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/exception/message/DayInputExceptionMessage.java b/src/main/java/christmas/view/input/exception/message/DayInputExceptionMessage.java new file mode 100644 index 0000000..cb12a99 --- /dev/null +++ b/src/main/java/christmas/view/input/exception/message/DayInputExceptionMessage.java @@ -0,0 +1,18 @@ +package christmas.view.input.exception.message; + +import static christmas.global.ApplicationConstant.ERROR_PREFIX; + +public enum DayInputExceptionMessage { + NOT_NUMERIC_TYPE("์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + NOT_POSITIVE("์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + + private final String message; + + DayInputExceptionMessage(final String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_PREFIX + message; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/exception/message/OrdersInputExceptionMessage.java b/src/main/java/christmas/view/input/exception/message/OrdersInputExceptionMessage.java new file mode 100644 index 0000000..322b140 --- /dev/null +++ b/src/main/java/christmas/view/input/exception/message/OrdersInputExceptionMessage.java @@ -0,0 +1,21 @@ +package christmas.view.input.exception.message; + +import static christmas.global.ApplicationConstant.ERROR_PREFIX; + +public enum OrdersInputExceptionMessage { + INVALID_ORDER_FORMAT("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + EMPTY_MENU_COUNT("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + NOT_NUMERIC_TYPE("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + NOT_POSITIVE("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."), + DUPLICATED_MENUS("์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”."); + + private final String message; + + OrdersInputExceptionMessage(final String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_PREFIX + message; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/parser/InputParser.java b/src/main/java/christmas/view/input/parser/InputParser.java new file mode 100644 index 0000000..75e925a --- /dev/null +++ b/src/main/java/christmas/view/input/parser/InputParser.java @@ -0,0 +1,89 @@ +package christmas.view.input.parser; + +import static christmas.view.input.constant.InputNumberConstant.APPLICATION_MAX_INPUT_LENGTH; +import static christmas.view.input.constant.InputNumberConstant.MENU_COUNT_INDEX; +import static christmas.view.input.constant.InputNumberConstant.MENU_NAME_INDEX; +import static christmas.view.input.constant.InputSymbolConstant.BLANK; +import static christmas.view.input.constant.InputSymbolConstant.DAY_SYMBOL; +import static christmas.view.input.constant.InputSymbolConstant.ORDERS_DELIMITER; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_DELIMITER; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static christmas.view.input.constant.InputSymbolConstant.VOID; +import static christmas.view.input.exception.message.BasicInputExceptionMessageFormat.TOO_LONG_WITH_BLANKS_FORMAT; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.DayInputException; +import christmas.view.input.exception.OrdersInputException; +import christmas.view.input.validator.DayInputValidator; +import christmas.view.input.validator.OrderInputValidator; +import christmas.view.input.validator.OrdersInputValidator; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +public class InputParser { + private final DayInputValidator dayInputValidator; + private final OrdersInputValidator ordersInputValidator; + private final OrderInputValidator orderInputValidator; + + public InputParser() { + this.dayInputValidator = new DayInputValidator(); + this.ordersInputValidator = new OrdersInputValidator(); + this.orderInputValidator = new OrderInputValidator(); + } + + public int parseReservationDay(String userInput) throws BasicInputException, DayInputException { + checkDayLengthIsUnderUpperLimit(userInput); + userInput = removeBlank(userInput); + dayInputValidator.validate(userInput); + return parseToInt(userInput); + } + + public Map parseOrders(String userInput) throws BasicInputException, OrdersInputException { + checkOrdersLengthIsUnderUpperLimit(userInput); + userInput = removeBlank(userInput); + ordersInputValidator.preValidate(userInput); + validateEachOrder(userInput); + ordersInputValidator.postValidate(userInput); + return parseToOrderMap(userInput); + } + + private void checkDayLengthIsUnderUpperLimit(final String userInput) { + if (userInput.length() > APPLICATION_MAX_INPUT_LENGTH.getValue()) { + throw BasicInputException.of( + String.format(TOO_LONG_WITH_BLANKS_FORMAT.getFormat(), DAY_SYMBOL.getSymbol())); + } + } + + private void checkOrdersLengthIsUnderUpperLimit(final String userInput) { + if (userInput.length() > APPLICATION_MAX_INPUT_LENGTH.getValue()) { + throw BasicInputException.of( + String.format(TOO_LONG_WITH_BLANKS_FORMAT.getFormat(), ORDER_SYMBOL.getSymbol())); + } + } + + private int parseToInt(String userInput) { + return Integer.parseInt(userInput); + } + + private String removeBlank(String userInput) { + if (userInput.contains(BLANK.getSymbol())) { + userInput = userInput.replace(BLANK.getSymbol(), VOID.getSymbol()); + } + return userInput; + } + + private void validateEachOrder(final String userInput) throws BasicInputException, OrdersInputException { + Arrays.stream(userInput.split(ORDERS_DELIMITER.getSymbol())) + .forEach(orderInputValidator::validate); + } + + private Map parseToOrderMap(final String userInput) { + return Arrays.stream(userInput.split(ORDERS_DELIMITER.getSymbol())) + .map(orders -> orders.split(ORDER_DELIMITER.getSymbol())) + .collect(Collectors.toUnmodifiableMap( + order -> order[MENU_NAME_INDEX.getValue()], + order -> parseToInt(order[MENU_COUNT_INDEX.getValue()]) + )); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/BasicValidator.java b/src/main/java/christmas/view/input/validator/BasicValidator.java new file mode 100644 index 0000000..16d834d --- /dev/null +++ b/src/main/java/christmas/view/input/validator/BasicValidator.java @@ -0,0 +1,27 @@ +package christmas.view.input.validator; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; + +public abstract class BasicValidator { + + protected void validate(final String userInput, final String inputType, final int maxLength) + throws BasicInputException { + validateNotEmpty(userInput, inputType); + validateLengthUnderMaxLength(userInput, inputType, maxLength); + } + + protected void validateNotEmpty(final String userInput, final String inputType) { + if (userInput.isEmpty()) { + throw BasicInputException.of( + String.format(BasicInputExceptionMessageFormat.EMPTY_FORMAT.getFormat(), inputType)); + } + } + + protected void validateLengthUnderMaxLength(final String userInput, final String inputType, final int maxLength) { + if (userInput.length() > maxLength) { + throw BasicInputException.of( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_FORMAT.getFormat(), inputType)); + } + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/DayInputValidator.java b/src/main/java/christmas/view/input/validator/DayInputValidator.java new file mode 100644 index 0000000..a5b2f30 --- /dev/null +++ b/src/main/java/christmas/view/input/validator/DayInputValidator.java @@ -0,0 +1,39 @@ +package christmas.view.input.validator; + +import static christmas.view.input.constant.InputNumberConstant.DAY_MAX_INPUT_LENGTH; +import static christmas.view.input.constant.InputNumberConstant.POSITIVE_BOUNDARY_VALUE; +import static christmas.view.input.constant.InputSymbolConstant.DAY_SYMBOL; +import static christmas.view.input.exception.message.DayInputExceptionMessage.NOT_NUMERIC_TYPE; +import static christmas.view.input.exception.message.DayInputExceptionMessage.NOT_POSITIVE; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.DayInputException; + +public class DayInputValidator extends BasicValidator implements PositiveIntegerCheckable { + public void validate(final String dayInput) throws BasicInputException, DayInputException { + super.validate(dayInput, DAY_SYMBOL.getSymbol(), DAY_MAX_INPUT_LENGTH.getValue()); + validateNumeric(dayInput); + validatePositive(dayInput); + } + + @Override + public void validateNumeric(final String dayInput) { + try { + parseToInt(dayInput); + } catch (NumberFormatException e) { + throw DayInputException.of(NOT_NUMERIC_TYPE.getMessage()); + } + } + + @Override + public void validatePositive(final String dayInput) { + int day = parseToInt(dayInput); + if (day < POSITIVE_BOUNDARY_VALUE.getValue()) { + throw DayInputException.of(NOT_POSITIVE.getMessage()); + } + } + + private int parseToInt(final String dayInput) { + return Integer.parseInt(dayInput); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/MenuCountInputValidator.java b/src/main/java/christmas/view/input/validator/MenuCountInputValidator.java new file mode 100644 index 0000000..cee80cf --- /dev/null +++ b/src/main/java/christmas/view/input/validator/MenuCountInputValidator.java @@ -0,0 +1,38 @@ +package christmas.view.input.validator; + +import static christmas.view.input.constant.InputNumberConstant.MENU_COUNT_MAX_INPUT_LENGTH; +import static christmas.view.input.constant.InputNumberConstant.POSITIVE_BOUNDARY_VALUE; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static christmas.view.input.exception.message.OrdersInputExceptionMessage.NOT_NUMERIC_TYPE; +import static christmas.view.input.exception.message.OrdersInputExceptionMessage.NOT_POSITIVE; + +import christmas.view.input.exception.OrdersInputException; + +public class MenuCountInputValidator extends BasicValidator implements PositiveIntegerCheckable { + public void validate(final String menuCountInput) throws OrdersInputException { + super.validate(menuCountInput, ORDER_SYMBOL.getSymbol(), MENU_COUNT_MAX_INPUT_LENGTH.getValue()); + validateNumeric(menuCountInput); + validatePositive(menuCountInput); + } + + @Override + public void validateNumeric(final String menuCountInput) { + try { + parseToInt(menuCountInput); + } catch (NumberFormatException e) { + throw OrdersInputException.of(NOT_NUMERIC_TYPE.getMessage()); + } + } + + @Override + public void validatePositive(final String menuCountInput) { + int menuCount = parseToInt(menuCountInput); + if (menuCount < POSITIVE_BOUNDARY_VALUE.getValue()) { + throw OrdersInputException.of(NOT_POSITIVE.getMessage()); + } + } + + private int parseToInt(final String menuCountInput) { + return Integer.parseInt(menuCountInput); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/MenuNameInputValidator.java b/src/main/java/christmas/view/input/validator/MenuNameInputValidator.java new file mode 100644 index 0000000..9f7e071 --- /dev/null +++ b/src/main/java/christmas/view/input/validator/MenuNameInputValidator.java @@ -0,0 +1,12 @@ +package christmas.view.input.validator; + +import static christmas.view.input.constant.InputNumberConstant.MENU_NAME_MAX_INPUT_LENGTH; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; + +import christmas.view.input.exception.BasicInputException; + +public class MenuNameInputValidator extends BasicValidator { + public void validate(final String menuNameInput) throws BasicInputException { + super.validate(menuNameInput, ORDER_SYMBOL.getSymbol(), MENU_NAME_MAX_INPUT_LENGTH.getValue()); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/OrderInputValidator.java b/src/main/java/christmas/view/input/validator/OrderInputValidator.java new file mode 100644 index 0000000..684bcdd --- /dev/null +++ b/src/main/java/christmas/view/input/validator/OrderInputValidator.java @@ -0,0 +1,61 @@ +package christmas.view.input.validator; + +import static christmas.view.input.constant.InputNumberConstant.MENU_COUNT_INDEX; +import static christmas.view.input.constant.InputNumberConstant.MENU_NAME_INDEX; +import static christmas.view.input.constant.InputNumberConstant.ORDER_MAX_INPUT_LENGTH; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_DELIMITER; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static christmas.view.input.exception.message.OrdersInputExceptionMessage.EMPTY_MENU_COUNT; +import static christmas.view.input.exception.message.OrdersInputExceptionMessage.INVALID_ORDER_FORMAT; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.OrdersInputException; +import java.util.Arrays; +import java.util.List; + +public class OrderInputValidator extends BasicValidator { + private final MenuNameInputValidator menuNameInputValidator; + private final MenuCountInputValidator menuCountInputValidator; + + public OrderInputValidator() { + this.menuNameInputValidator = new MenuNameInputValidator(); + this.menuCountInputValidator = new MenuCountInputValidator(); + } + + public void validate(final String orderInput) throws BasicInputException, OrdersInputException { + super.validate(orderInput, ORDER_SYMBOL.getSymbol(), ORDER_MAX_INPUT_LENGTH.getValue()); + validateContainingDelimiter(orderInput); + validateNotEndsWithDelimiter(orderInput); + validateMenu(splitToMenuInput(orderInput)); + } + + private void validateContainingDelimiter(final String orderInput) { + if (!containsDelimiter(orderInput)) { + throw OrdersInputException.of(INVALID_ORDER_FORMAT.getMessage()); + } + } + + private boolean containsDelimiter(final String orderInput) { + return orderInput.contains(ORDER_DELIMITER.getSymbol()); + } + + private void validateNotEndsWithDelimiter(final String orderInput) { + if (endsWithDelimiter(orderInput)) { + throw OrdersInputException.of(EMPTY_MENU_COUNT.getMessage()); + } + } + + private boolean endsWithDelimiter(final String orderInput) { + return orderInput.endsWith(ORDER_DELIMITER.getSymbol()); + } + + private List splitToMenuInput(final String orderInput) { + return Arrays.stream(orderInput.split(ORDER_DELIMITER.getSymbol())) + .toList(); + } + + private void validateMenu(List menuInput) throws BasicInputException, OrdersInputException { + menuNameInputValidator.validate(menuInput.get(MENU_NAME_INDEX.getValue())); + menuCountInputValidator.validate(menuInput.get(MENU_COUNT_INDEX.getValue())); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/OrdersInputValidator.java b/src/main/java/christmas/view/input/validator/OrdersInputValidator.java new file mode 100644 index 0000000..31c3054 --- /dev/null +++ b/src/main/java/christmas/view/input/validator/OrdersInputValidator.java @@ -0,0 +1,41 @@ +package christmas.view.input.validator; + +import static christmas.view.input.constant.InputNumberConstant.MENU_NAME_INDEX; +import static christmas.view.input.constant.InputNumberConstant.ORDERS_MAX_INPUT_LENGTH; +import static christmas.view.input.constant.InputSymbolConstant.ORDERS_DELIMITER; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_DELIMITER; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static christmas.view.input.exception.message.OrdersInputExceptionMessage.DUPLICATED_MENUS; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.OrdersInputException; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public class OrdersInputValidator extends BasicValidator { + public void preValidate(final String ordersInput) throws BasicInputException { + super.validate(ordersInput, ORDER_SYMBOL.getSymbol(), ORDERS_MAX_INPUT_LENGTH.getValue()); + } + + public void postValidate(final String ordersInput) throws OrdersInputException { + validateNotExistDuplicatedMenus(ordersInput); + } + + private void validateNotExistDuplicatedMenus(final String ordersInput) { + Set uniqueMenuNames = makeUniqueMenuNames(ordersInput); + if (haveDuplicatedMenus(ordersInput, uniqueMenuNames)) { + throw OrdersInputException.of(DUPLICATED_MENUS.getMessage()); + } + } + + private Set makeUniqueMenuNames(final String ordersInput) { + return Arrays.stream(ordersInput.split(ORDERS_DELIMITER.getSymbol())) + .map(order -> order.split(ORDER_DELIMITER.getSymbol())[MENU_NAME_INDEX.getValue()]) + .collect(Collectors.toUnmodifiableSet()); + } + + private boolean haveDuplicatedMenus(final String ordersInput, Set uniqueMenuNames) { + return uniqueMenuNames.size() < ordersInput.split(ORDERS_DELIMITER.getSymbol()).length; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/input/validator/PositiveIntegerCheckable.java b/src/main/java/christmas/view/input/validator/PositiveIntegerCheckable.java new file mode 100644 index 0000000..e203f43 --- /dev/null +++ b/src/main/java/christmas/view/input/validator/PositiveIntegerCheckable.java @@ -0,0 +1,7 @@ +package christmas.view.input.validator; + +public interface PositiveIntegerCheckable { + void validateNumeric(final String userInput); + + void validatePositive(final String userInput); +} \ No newline at end of file diff --git a/src/main/java/christmas/view/output/OutputView.java b/src/main/java/christmas/view/output/OutputView.java new file mode 100644 index 0000000..c3313ee --- /dev/null +++ b/src/main/java/christmas/view/output/OutputView.java @@ -0,0 +1,171 @@ +package christmas.view.output; + +import static christmas.view.output.constant.OutputFormatConstant.BENEFITS_DETAILS_PRINT_FORMAT; +import static christmas.view.output.constant.OutputFormatConstant.ESTIMATED_AMOUNT_WITH_DISCOUNT_PRINT_FORMAT; +import static christmas.view.output.constant.OutputFormatConstant.GIFT_PRINT_FORMAT; +import static christmas.view.output.constant.OutputFormatConstant.ORDERED_MENUS_PRINT_FORMAT; +import static christmas.view.output.constant.OutputFormatConstant.PRICE_FORMAT_STYLE; +import static christmas.view.output.constant.OutputFormatConstant.SHOW_RESULT_INTRO_FORMAT; +import static christmas.view.output.constant.OutputFormatConstant.TOTAL_AMOUNT_WITH_NO_DISCOUNT_PRINT_FORMAT; +import static christmas.view.output.constant.OutputFormatConstant.TOTAL_BENEFITED_AMOUNT_PRINT_FORMAT; +import static christmas.view.output.constant.OutputMessageConstant.GREETING; +import static christmas.view.output.constant.OutputMessageConstant.INSERT_ORDERS; +import static christmas.view.output.constant.OutputMessageConstant.INSERT_RESERVATION_DAY; +import static christmas.view.output.constant.OutputSymbolConstant.BENEFITS_DETAILS; +import static christmas.view.output.constant.OutputSymbolConstant.ESTIMATED_AMOUNT_WITH_DISCOUNT; +import static christmas.view.output.constant.OutputSymbolConstant.EVENT_BADGE; +import static christmas.view.output.constant.OutputSymbolConstant.GIFT_MENU; +import static christmas.view.output.constant.OutputSymbolConstant.NEW_LINE; +import static christmas.view.output.constant.OutputSymbolConstant.NO_BENEFITS; +import static christmas.view.output.constant.OutputSymbolConstant.NO_EVENT_BADGE; +import static christmas.view.output.constant.OutputSymbolConstant.NO_GIFT; +import static christmas.view.output.constant.OutputSymbolConstant.ORDERED_MENUS; +import static christmas.view.output.constant.OutputSymbolConstant.TOTAL_AMOUNT_WITH_NO_DISCOUNT; +import static christmas.view.output.constant.OutputSymbolConstant.TOTAL_BENEFITED_AMOUNT; + +import christmas.dto.BenefitsDetailsDto; +import christmas.dto.EstimatedAmountWithDiscountDto; +import christmas.dto.EventBadgeDto; +import christmas.dto.EventBenefitsPreviewDto; +import christmas.dto.GiftDto; +import christmas.dto.OrderedMenusDto; +import christmas.dto.TotalAmountWithNoDiscountDto; +import christmas.dto.TotalBenefitedAmountDto; +import java.text.DecimalFormat; + +public class OutputView { + public void printGreetingMessage() { + print(GREETING.getMessage()); + printLine(); + } + + public void askToInsertReservationDay() { + print(INSERT_RESERVATION_DAY.getMessage()); + printLine(); + } + + public void askToInsertOrders() { + print(INSERT_ORDERS.getMessage()); + printLine(); + } + + public void printIntroMessage(EventBenefitsPreviewDto eventBenefitsPreviewDto) { + printFormatted(SHOW_RESULT_INTRO_FORMAT.getFormat(), eventBenefitsPreviewDto.getDay()); + printLine(); + printLine(); + } + + public void printOrderedMenus(OrderedMenusDto orderedMenusDto) { + print(ORDERED_MENUS.getSymbol()); + printLine(); + orderedMenusDto.getOrders().forEach(this::printOrderedMenu); + } + + private void printOrderedMenu(final String menuName, final int menuCount) { + printFormatted(ORDERED_MENUS_PRINT_FORMAT.getFormat(), menuName, menuCount); + printLine(); + } + + public void printTotalAmountWithNoDiscount(TotalAmountWithNoDiscountDto totalAmountWithNoDiscountDto) { + printLine(); + print(TOTAL_AMOUNT_WITH_NO_DISCOUNT.getSymbol()); + printLine(); + printFormatted(TOTAL_AMOUNT_WITH_NO_DISCOUNT_PRINT_FORMAT.getFormat(), + formatPrice(totalAmountWithNoDiscountDto.getAmount())); + printLine(); + } + + public void printGiftMenu(GiftDto giftDto) { + printLine(); + print(GIFT_MENU.getSymbol()); + printLine(); + printGift(giftDto); + } + + private void printGift(GiftDto giftDto) { + if (giftDto.isEmpty()) { + print(NO_GIFT.getSymbol()); + printLine(); + } + giftDto.getGift().forEach((giftName, giftCount) -> { + printFormatted(GIFT_PRINT_FORMAT.getFormat(), giftName, giftCount); + printLine(); + } + ); + } + + public void printBenefitsDetails(BenefitsDetailsDto benefitsDetailsDto) { + printLine(); + print(BENEFITS_DETAILS.getSymbol()); + printLine(); + printBenefitNamesAndAmount(benefitsDetailsDto); + } + + private void printBenefitNamesAndAmount(BenefitsDetailsDto benefitsDetailsDto) { + if (benefitsDetailsDto.isEmpty()) { + print(NO_BENEFITS.getSymbol()); + printLine(); + } + benefitsDetailsDto.getBenefitsDetails().forEach((benefitName, benefitAmount) -> { + printFormatted(BENEFITS_DETAILS_PRINT_FORMAT.getFormat(), benefitName, formatPrice(benefitAmount)); + printLine(); + } + ); + } + + public void printTotalBenefitedAmount(TotalBenefitedAmountDto totalBenefitedAmountDto) { + printLine(); + print(TOTAL_BENEFITED_AMOUNT.getSymbol()); + printLine(); + printFormatted(TOTAL_BENEFITED_AMOUNT_PRINT_FORMAT.getFormat(), + formatPrice(-totalBenefitedAmountDto.getAmount())); + printLine(); + } + + public void printEstimatedAmountWithDiscount(EstimatedAmountWithDiscountDto estimatedAmountWithDiscountDto) { + printLine(); + print(ESTIMATED_AMOUNT_WITH_DISCOUNT.getSymbol()); + printLine(); + printFormatted(ESTIMATED_AMOUNT_WITH_DISCOUNT_PRINT_FORMAT.getFormat(), + formatPrice(estimatedAmountWithDiscountDto.getAmount())); + printLine(); + } + + public void printEventBadge(EventBadgeDto eventBadgeDto) { + printLine(); + print(EVENT_BADGE.getSymbol()); + printLine(); + printEventBadgeName(eventBadgeDto); + } + + private void printEventBadgeName(EventBadgeDto eventBadgeDto) { + if (eventBadgeDto.isEmpty()) { + print(NO_EVENT_BADGE.getSymbol()); + } + if (!eventBadgeDto.isEmpty()) { + print(eventBadgeDto.getBadgeName()); + } + } + + public void printErrorMessage(final String message) { + print(message); + printLine(); + } + + private void print(final String message) { + System.out.print(message); + } + + private void printLine() { + System.out.print(NEW_LINE.getSymbol()); + } + + private void printFormatted(final String format, final Object... args) { + print(String.format(format, args)); + } + + private String formatPrice(final int price) { + return new DecimalFormat(PRICE_FORMAT_STYLE.getFormat()) + .format(price); + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/output/constant/OutputFormatConstant.java b/src/main/java/christmas/view/output/constant/OutputFormatConstant.java new file mode 100644 index 0000000..47d4b07 --- /dev/null +++ b/src/main/java/christmas/view/output/constant/OutputFormatConstant.java @@ -0,0 +1,24 @@ +package christmas.view.output.constant; + +import static christmas.global.ApplicationConstant.CURRENT_PROMOTION_MONTH; + +public enum OutputFormatConstant { + SHOW_RESULT_INTRO_FORMAT(CURRENT_PROMOTION_MONTH + "์›” %d์ผ์— ์šฐํ…Œ์ฝ” ์‹๋‹น์—์„œ ๋ฐ›์„ ์ด๋ฒคํŠธ ํ˜œํƒ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ!"), + ORDERED_MENUS_PRINT_FORMAT("%s %d๊ฐœ"), + TOTAL_AMOUNT_WITH_NO_DISCOUNT_PRINT_FORMAT("%s์›"), + PRICE_FORMAT_STYLE("###,###"), + GIFT_PRINT_FORMAT("%s %d๊ฐœ"), + BENEFITS_DETAILS_PRINT_FORMAT("%s: -%s์›"), + TOTAL_BENEFITED_AMOUNT_PRINT_FORMAT("%s์›"), + ESTIMATED_AMOUNT_WITH_DISCOUNT_PRINT_FORMAT("%s์›"); + + private final String format; + + OutputFormatConstant(final String format) { + this.format = format; + } + + public String getFormat() { + return format; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/output/constant/OutputMessageConstant.java b/src/main/java/christmas/view/output/constant/OutputMessageConstant.java new file mode 100644 index 0000000..5c825ba --- /dev/null +++ b/src/main/java/christmas/view/output/constant/OutputMessageConstant.java @@ -0,0 +1,19 @@ +package christmas.view.output.constant; + +import static christmas.global.ApplicationConstant.CURRENT_PROMOTION_MONTH; + +public enum OutputMessageConstant { + GREETING("์•ˆ๋…•ํ•˜์„ธ์š”! ์šฐํ…Œ์ฝ” ์‹๋‹น " + CURRENT_PROMOTION_MONTH + "์›” ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค."), + INSERT_RESERVATION_DAY(CURRENT_PROMOTION_MONTH + "์›” ์ค‘ ์‹๋‹น ๋ฐฉ๋ฌธ ๋‚ ์งœ๋Š” ์–ธ์ œ์ธ๊ฐ€์š”? (์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”!)"), + INSERT_ORDERS("์ฃผ๋ฌธํ•˜์‹ค ๋ฉ”๋‰ด๋ฅผ ๋ฉ”๋‰ด์™€ ๊ฐœ์ˆ˜๋ฅผ ์•Œ๋ ค ์ฃผ์„ธ์š”. (e.g. ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-2,๋ ˆ๋“œ์™€์ธ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1)"); + + private final String message; + + OutputMessageConstant(final String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} \ No newline at end of file diff --git a/src/main/java/christmas/view/output/constant/OutputSymbolConstant.java b/src/main/java/christmas/view/output/constant/OutputSymbolConstant.java new file mode 100644 index 0000000..5849c15 --- /dev/null +++ b/src/main/java/christmas/view/output/constant/OutputSymbolConstant.java @@ -0,0 +1,24 @@ +package christmas.view.output.constant; + +public enum OutputSymbolConstant { + NEW_LINE(System.lineSeparator()), + ORDERED_MENUS("<์ฃผ๋ฌธ ๋ฉ”๋‰ด>"), + TOTAL_AMOUNT_WITH_NO_DISCOUNT("<ํ• ์ธ ์ „ ์ด์ฃผ๋ฌธ ๊ธˆ์•ก>"), + GIFT_MENU("<์ฆ์ • ๋ฉ”๋‰ด>"), + BENEFITS_DETAILS("<ํ˜œํƒ ๋‚ด์—ญ>"), + TOTAL_BENEFITED_AMOUNT("<์ดํ˜œํƒ ๊ธˆ์•ก>"), + ESTIMATED_AMOUNT_WITH_DISCOUNT("<ํ• ์ธ ํ›„ ์˜ˆ์ƒ ๊ฒฐ์ œ ๊ธˆ์•ก>"), + EVENT_BADGE("<12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€>"), + NO_GIFT("์—†์Œ"), + NO_BENEFITS("์—†์Œ"), + NO_EVENT_BADGE("์—†์Œ"); + private final String symbol; + + OutputSymbolConstant(final String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/ChristmasPromotionTest.java b/src/test/java/christmas/domain/ChristmasPromotionTest.java new file mode 100644 index 0000000..08a6da6 --- /dev/null +++ b/src/test/java/christmas/domain/ChristmasPromotionTest.java @@ -0,0 +1,21 @@ +package christmas.domain; + +import static christmas.domain.constant.event.ChristmasPromotion.CHRISTMAS_D_DAY_PROMOTION; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class ChristmasPromotionTest { + @DisplayName("25์ผ ์ด์ „์˜ ๋‚ ์งœ๊ฐ€ ์ž…๋ ฅ๋˜๋ฉด, ํ•ด๋‹นํ•˜๋Š” ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ”„๋กœ๋ชจ์…˜ ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = { + "1:1000", "2:1100", "3:1200", "25:3400", "24:3300", "23:3200", + "15:2400", "16:2500", "19:2800", "7:1600", "11:2000", "13:2200" + }, delimiter = ':') + void ๋‚ ์งœ๊ฐ€_์ž…๋ ฅ๋˜๋ฉด_ํ•ด๋‹นํ•˜๋Š”_ํฌ๋ฆฌ์Šค๋งˆ์Šค_๋””๋ฐ์ด_ํ”„๋กœ๋ชจ์…˜_๊ธˆ์•ก์„_๊ณ„์‚ฐ(int day, int expectedBenefitAmount) { + assertThat(CHRISTMAS_D_DAY_PROMOTION.getBenefitAmount(day)) + .isEqualTo(expectedBenefitAmount); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/EventBadgeTest.java b/src/test/java/christmas/domain/EventBadgeTest.java new file mode 100644 index 0000000..40f9d14 --- /dev/null +++ b/src/test/java/christmas/domain/EventBadgeTest.java @@ -0,0 +1,21 @@ +package christmas.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import christmas.domain.constant.event.EventBadge; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class EventBadgeTest { + @DisplayName("ํ˜œํƒ ๊ธˆ์•ก์— ๋”ฐ๋ผ ์ด๋ฒคํŠธ ๋ฐฐ์ง€๋ฅผ ๋ฐœ๊ธ‰ํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = { + "1000:''", "4999:''", "5000:๋ณ„", "8230:๋ณ„", "9999:๋ณ„", "10000:ํŠธ๋ฆฌ", "13200:ํŠธ๋ฆฌ", + "14999:ํŠธ๋ฆฌ", "15000:ํŠธ๋ฆฌ", "19999:ํŠธ๋ฆฌ", "20000:์‚ฐํƒ€", "20001:์‚ฐํƒ€", "83000:์‚ฐํƒ€" + }, delimiter = ':') + void ํ˜œํƒ_๊ธˆ์•ก์—_๋”ฐ๋ผ_์ด๋ฒคํŠธ_๋ฐฐ์ง€_๋ฐœ๊ธ‰(int totalBenefitedAmount, String eventBadgeName) { + assertThat(EventBadge.getBadgeNameByBenefitedPrice(totalBenefitedAmount)) + .isEqualTo(eventBadgeName); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/EventManagerTest.java b/src/test/java/christmas/domain/EventManagerTest.java new file mode 100644 index 0000000..b45fd57 --- /dev/null +++ b/src/test/java/christmas/domain/EventManagerTest.java @@ -0,0 +1,101 @@ +package christmas.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class EventManagerTest { + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ๊ณผ ๋‚ ์งœ๋ฅผ ๋น„๊ตํ•ด์„œ, ํ˜œํƒ ๋‚ด์—ญ์„ ์ƒ์‚ฐํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource({ + "4, '์‹œ์ €์ƒ๋Ÿฌ๋“œ,3|์ œ๋กœ์ฝœ๋ผ,2|๋ ˆ๋“œ์™€์ธ,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,3|์ดˆ์ฝ”์ผ€์ดํฌ,4','ํ‰์ผ ํ• ์ธ,8092|ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ,1300|์ฆ์ • ์ด๋ฒคํŠธ,25000'", + "3,'ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|๋ฐ”๋น„ํ๋ฆฝ,1|์ดˆ์ฝ”์ผ€์ดํฌ,2|์ œ๋กœ์ฝœ๋ผ,1','ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ,1200|ํ‰์ผ ํ• ์ธ,4046|ํŠน๋ณ„ ํ• ์ธ,1000|์ฆ์ • ์ด๋ฒคํŠธ,25000'", + "25,'ํƒ€ํŒŒ์Šค,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|์•„์ด์Šคํฌ๋ฆผ,3|์ œ๋กœ์ฝœ๋ผ,3','ํฌ๋ฆฌ์Šค๋งˆ์Šค ๋””๋ฐ์ด ํ• ์ธ,3400|ํ‰์ผ ํ• ์ธ,6069|ํŠน๋ณ„ ํ• ์ธ,1000'" + }) + void ์ฃผ๋ฌธ_๋‚ด์—ญ๊ณผ_๋‚ ์งœ๋ฅผ_๋น„๊ตํ•ด์„œ_ํ˜œํƒ_๋‚ด์—ญ์„_์ƒ์‚ฐ(int day, String menuAndCounts, String expectedBenefitDetails) { + // given + EventManager eventManager = createEventManager(day, menuAndCounts); + // when + Map benefitsDetails = eventManager.createBenefitsDetails(); + // then + for (String benefit : expectedBenefitDetails.split("\\|")) { + String[] parts = benefit.split(","); + String benefitName = parts[0]; + int expectedAmount = Integer.parseInt(parts[1]); + assertThat(benefitsDetails.get(benefitName)).isEqualTo(expectedAmount); + } + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์— ๋‚ ์งœ์— ๋”ฐ๋ฅธ ํ• ์ธ ์—ฌ๋ถ€๋ฅผ ์ ์šฉํ•ด์„œ, ํ• ์ธ ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource({ + "4, '์‹œ์ €์ƒ๋Ÿฌ๋“œ,3|์ œ๋กœ์ฝœ๋ผ,2|๋ ˆ๋“œ์™€์ธ,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,3|์ดˆ์ฝ”์ผ€์ดํฌ,4','9392'", + "3,'ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|๋ฐ”๋น„ํ๋ฆฝ,1|์ดˆ์ฝ”์ผ€์ดํฌ,2|์ œ๋กœ์ฝœ๋ผ,1','6246'", + "25,'ํƒ€ํŒŒ์Šค,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|์•„์ด์Šคํฌ๋ฆผ,3|์ œ๋กœ์ฝœ๋ผ,3','10469'" + }) + void ์ฃผ๋ฌธ_๋‚ด์—ญ์—_๋‚ ์งœ์—_๋”ฐ๋ฅธ_ํ• ์ธ_์—ฌ๋ถ€๋ฅผ_์ ์šฉํ•ด์„œ_ํ• ์ธ_๊ธˆ์•ก_๊ณ„์‚ฐ(int day, String menuAndCounts, int expectedDiscountAmount) { + // given + Orders orders = Orders.from(parseMenuAndCounts(menuAndCounts)); + EventManager eventManager = createEventManager(day, menuAndCounts); + // when + int discountAmount = + orders.calculateTotalAmountWithNoDiscount() - eventManager.calculateEstimatedOrdersAmountWithDiscount(); + // then + assertThat(discountAmount).isEqualTo(expectedDiscountAmount); + } + + @DisplayName("ํ˜œํƒ ๋‚ด์—ญ์˜ ๊ธˆ์•ก์„ ํ•ฉ์ณ์„œ, ์ด ํ˜œํƒ ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource({ + "4, '์‹œ์ €์ƒ๋Ÿฌ๋“œ,3|์ œ๋กœ์ฝœ๋ผ,2|๋ ˆ๋“œ์™€์ธ,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,3|์ดˆ์ฝ”์ผ€์ดํฌ,4','34392'", + "3,'ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|๋ฐ”๋น„ํ๋ฆฝ,1|์ดˆ์ฝ”์ผ€์ดํฌ,2|์ œ๋กœ์ฝœ๋ผ,1','31246'", + "25,'ํƒ€ํŒŒ์Šค,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|์•„์ด์Šคํฌ๋ฆผ,3|์ œ๋กœ์ฝœ๋ผ,3','10469'" + }) + void ํ˜œํƒ_๋‚ด์—ญ์˜_๊ธˆ์•ก์„_ํ•ฉ์ณ์„œ_์ด_ํ˜œํƒ_๊ธˆ์•ก์„_๊ณ„์‚ฐ(int day, String menuAndCounts, int expectedDiscountAmount) { + // given + EventManager eventManager = createEventManager(day, menuAndCounts); + // when + int discountAmount = eventManager.calculateTotalBenefitedAmount(); + // then + assertThat(discountAmount).isEqualTo(expectedDiscountAmount); + } + + @DisplayName("์ด ํ˜œํƒ ๊ธˆ์•ก์„ ๊ธฐ๋ฐ˜์œผ๋กœ 12์›” ์ด๋ฒคํŠธ ๋ฐฐ์ง€๋ฅผ ๋ฐœ๊ธ‰ํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource({ + "4, '์‹œ์ €์ƒ๋Ÿฌ๋“œ,3|์ œ๋กœ์ฝœ๋ผ,2|๋ ˆ๋“œ์™€์ธ,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,3|์ดˆ์ฝ”์ผ€์ดํฌ,4','์‚ฐํƒ€'", + "3,'ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|๋ฐ”๋น„ํ๋ฆฝ,1|์ดˆ์ฝ”์ผ€์ดํฌ,2|์ œ๋กœ์ฝœ๋ผ,1','์‚ฐํƒ€'", + "25,'ํƒ€ํŒŒ์Šค,1|ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,1|์•„์ด์Šคํฌ๋ฆผ,3|์ œ๋กœ์ฝœ๋ผ,3','ํŠธ๋ฆฌ'", + "26,'ํƒ€ํŒŒ์Šค,1|ํฌ๋ฆฌ์Šค๋งˆ์ŠคํŒŒ์Šคํƒ€,1|์•„์ด์Šคํฌ๋ฆผ,3|','๋ณ„'", + "26,'์–‘์†ก์ด์ˆ˜ํ”„,3|ํฌ๋ฆฌ์Šค๋งˆ์ŠคํŒŒ์Šคํƒ€,1|์•„์ด์Šคํฌ๋ฆผ,1|',''" + }) + void ์ด_ํ˜œํƒ_๊ธˆ์•ก์„_๊ธฐ๋ฐ˜์œผ๋กœ_12์›”_์ด๋ฒคํŠธ_๋ฐฐ์ง€๋ฅผ_๋ฐœ๊ธ‰(int day, String menuAndCounts, String expectedEventBadge) { + // given + EventManager eventManager = createEventManager(day, menuAndCounts); + // when + String eventBadge = eventManager.issueEventBadge(); + // then + assertThat(eventBadge).isEqualTo(expectedEventBadge); + } + + private EventManager createEventManager(int day, String menuAndCounts) { + ReservationDay reservationDay = ReservationDay.from(day); + Orders orders = Orders.from(parseMenuAndCounts(menuAndCounts)); + return EventManager.of(reservationDay, orders); + } + + private List parseMenuAndCounts(String menuAndCounts) { + List orders = new ArrayList<>(); + String[] splitedMenusAndCounts = menuAndCounts.split("\\|"); + for (String splitedMenusAndCount : splitedMenusAndCounts) { + String[] menuNameAndCount = splitedMenusAndCount.split(","); + orders.add(Order.of(menuNameAndCount[0], Integer.parseInt(menuNameAndCount[1]))); + } + return orders; + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/MenuTest.java b/src/test/java/christmas/domain/MenuTest.java new file mode 100644 index 0000000..05b602d --- /dev/null +++ b/src/test/java/christmas/domain/MenuTest.java @@ -0,0 +1,34 @@ +package christmas.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.domain.constant.orders.Menu; +import christmas.domain.exception.InvalidOrdersException; +import christmas.domain.exception.message.InvalidOrdersExceptionMessage; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class MenuTest { + @DisplayName("๋ฉ”๋‰ด ์ด๋ฆ„์ด ๋ฉ”๋‰ดํŒ์— ์—†์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"์‹œ์ธ„์ƒ๋Ÿฌ๋“œ", "๋™์–‘์†ก์ด์ˆ˜ํ”„", "๋ฌผํŒŒ์Šค", "๋ฐฑํผ์ฝœ๋ผ", "์™€์ด๋ณธ์Šคํ…Œ์ดํฌ", "๋ฐ”๋น„ํ์น˜ํ‚จ", "ํฌ๋ฆผ", "๋‹น๊ทผ์ผ€์ดํฌ"}) + void ๋ฉ”๋‰ด_์ด๋ฆ„์ด_๋ฉ”๋‰ดํŒ์—_์—†์œผ๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String menuName) { + assertThatThrownBy(() -> Menu.searchByName(menuName)) + .isInstanceOf(InvalidOrdersException.class) + .hasMessageContaining(InvalidOrdersExceptionMessage.NOT_EXISTING_MENU.getMessage()); + } + + @DisplayName("๋ฉ”๋‰ด ์ด๋ฆ„์ด ๋ฉ”๋‰ดํŒ์— ์žˆ์œผ๋ฉด, ๋ฉ”๋‰ด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ฐ˜ํ™˜๋œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"์‹œ์ €์ƒ๋Ÿฌ๋“œ", "ํƒ€ํŒŒ์Šค", "์–‘์†ก์ด์ˆ˜ํ”„", "ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ", "๋ฐ”๋น„ํ๋ฆฝ", "ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€", "ํฌ๋ฆฌ์Šค๋งˆ์ŠคํŒŒ์Šคํƒ€", "์ดˆ์ฝ”์ผ€์ดํฌ", "์•„์ด์Šคํฌ๋ฆผ", "์ œ๋กœ์ฝœ๋ผ", + "๋ ˆ๋“œ์™€์ธ", "์ƒดํŽ˜์ธ"}) + void ๋ฉ”๋‰ด_์ด๋ฆ„์ด_๋ฉ”๋‰ดํŒ์—_์žˆ์œผ๋ฉด_๋ฉ”๋‰ด๋ฅผ_์˜ฌ๋ฐ”๋ฅด๊ฒŒ_๋ฐ˜ํ™˜(String menuName) { + // given, when + Menu menu = Menu.searchByName(menuName); + // then + assertThat(menu).isInstanceOf(Menu.class); + assertThat(menu.getName()).isEqualTo(menuName); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/OrderTest.java b/src/test/java/christmas/domain/OrderTest.java new file mode 100644 index 0000000..88f000e --- /dev/null +++ b/src/test/java/christmas/domain/OrderTest.java @@ -0,0 +1,31 @@ +package christmas.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.domain.exception.InvalidOrdersException; +import christmas.domain.exception.message.InvalidOrdersExceptionMessage; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class OrderTest { + @DisplayName("๋ฉ”๋‰ดํŒ์— ์žˆ๋Š” ๋ฉ”๋‰ด ์ด๋ฆ„๊ณผ ์ˆ˜๋Ÿ‰์„ ์ฃผ๋ฌธํ•˜๋ฉด ์ฃผ๋ฌธ์ด ์ƒ์„ฑ๋œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"์–‘์†ก์ด์ˆ˜ํ”„-10", "ํƒ€ํŒŒ์Šค-3", "๋ ˆ๋“œ์™€์ธ-5", "์ œ๋กœ์ฝœ๋ผ-3", "์ƒดํŽ˜์ธ-7", "๋ฐ”๋น„ํ๋ฆฝ-10"}, delimiter = '-') + void ๋ฉ”๋‰ดํŒ์—_์žˆ๋Š”_๋ฉ”๋‰ด_์ด๋ฆ„๊ณผ_์ˆ˜๋Ÿ‰์„_์ฃผ๋ฌธ์‹œ_์ฃผ๋ฌธ_์ƒ์„ฑ(String menuName, int count) { + // given, when + Order order = Order.of(menuName, count); + // then + assertThat(order).isInstanceOf(Order.class); + } + + @DisplayName("๋ฉ”๋‰ดํŒ์— ์—†๋Š” ๋ฉ”๋‰ด๋ฅผ ์ฃผ๋ฌธํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"์‹œ์ ธ์ƒ๋Ÿฌ๋“œ-10", "ํ‹ฐ์Šคํ…Œ์ดํฌ-3", "์‚ฐ๋‚˜๋ฌผํŒŒ์Šคํƒ€-2", "๋…ผ์•Œ์ฝœ์ฝœ๋ผ-3", "๋‹จ์˜คํŒŒ์Šคํƒ€-7", "์—ฐ๊ทผ์ผ€์ดํฌ-10"}, delimiter = '-') + void ๋ฉ”๋‰ดํŒ์—_์—†๋Š”_๋ฉ”๋‰ด์ด๋ฆ„์œผ๋กœ_์ฃผ๋ฌธ์‹œ_์˜ˆ์™ธ_๋ฐœ์ƒ(String menuName, int count) { + assertThatThrownBy(() -> Order.of(menuName, count)) + .isInstanceOf(InvalidOrdersException.class) + .hasMessageContaining(InvalidOrdersExceptionMessage.NOT_EXISTING_MENU.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/OrdersTest.java b/src/test/java/christmas/domain/OrdersTest.java new file mode 100644 index 0000000..9f77ad6 --- /dev/null +++ b/src/test/java/christmas/domain/OrdersTest.java @@ -0,0 +1,114 @@ +package christmas.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.domain.exception.InvalidOrdersException; +import christmas.domain.exception.message.InvalidOrdersExceptionMessage; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class OrdersTest { + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ 20๊ฐœ๊ฐ€ ๋„˜์–ด๊ฐ€๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ทจํ•ฉํ–ˆ์„๋•Œ_๋ฉ”๋‰ด_๊ฐœ์ˆ˜๊ฐ€_20๊ฐœ๊ฐ€_๋„˜์–ด๊ฐ€๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ() { + // given + List orders = List.of( + Order.of("์‹œ์ €์ƒ๋Ÿฌ๋“œ", 3), + Order.of("์ œ๋กœ์ฝœ๋ผ", 10), + Order.of("ํƒ€ํŒŒ์Šค", 2), + Order.of("ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ", 3), + Order.of("์ดˆ์ฝ”์ผ€์ดํฌ", 4) + ); + // when, then + assertThatThrownBy(() -> Orders.from(orders)) + .isInstanceOf(InvalidOrdersException.class) + .hasMessageContaining(InvalidOrdersExceptionMessage.EXCEED_MENU_COUNTS_UPPER_LIMIT.getMessage()); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๋‚ด์—ญ์— ์Œ๋ฃŒ์ˆ˜๋งŒ ์žˆ์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ทจํ•ฉํ–ˆ์„๋•Œ_์ฃผ๋ฌธ_๋‚ด์—ญ์—_์Œ๋ฃŒ์ˆ˜๋งŒ_์žˆ์œผ๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ() { + // given + List orders = List.of( + Order.of("๋ ˆ๋“œ์™€์ธ", 3), + Order.of("์ œ๋กœ์ฝœ๋ผ", 4), + Order.of("์ƒดํŽ˜์ธ", 5) + ); + // when, then + assertThatThrownBy(() -> Orders.from(orders)) + .isInstanceOf(InvalidOrdersException.class) + .hasMessageContaining(InvalidOrdersExceptionMessage.MENUS_ONLY_CONTAIN_BEVERAGE.getMessage()); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๊ธˆ์•ก์ด 10000์› ์ดํ•˜๋ฉด ๋ชจ๋“  ์ด๋ฒคํŠธ ์ ์šฉ ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ทจํ•ฉํ–ˆ์„๋•Œ_์ฃผ๋ฌธ_๊ธˆ์•ก์ด_10000์›_์ดํ•˜๋ฉด_๋ชจ๋“ _์ด๋ฒคํŠธ_์ ์šฉ_๋Œ€์ƒ์—์„œ_์ œ์™ธ() { + // given + List orders = List.of( + Order.of("์–‘์†ก์ด์ˆ˜ํ”„", 1), + Order.of("์ œ๋กœ์ฝœ๋ผ", 1) + ); + // when, then + assertThat(Orders.from(orders).isEventApplicable()).isEqualTo(false); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๊ธˆ์•ก์ด 10000์› ์ดˆ๊ณผ๋ฉด ์ด๋ฒคํŠธ ์ ์šฉ ๋Œ€์ƒ์— ํฌํ•จํ•œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ทจํ•ฉํ–ˆ์„๋•Œ_์ฃผ๋ฌธ_๊ธˆ์•ก์ด_10000์›_์ดˆ๊ณผ๋ฉด_์ด๋ฒคํŠธ_์ ์šฉ_๋Œ€์ƒ์—_ํฌํ•จ() { + // given + List orders = List.of( + Order.of("์‹œ์ €์ƒ๋Ÿฌ๋“œ", 2), + Order.of("ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ", 3) + ); + // when, then + assertThat(Orders.from(orders).isEventApplicable()).isEqualTo(true); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๊ธˆ์•ก์ด 12๋งŒ์› ๋ฏธ๋งŒ์ด๋ฉด ์ฆ์ • ์ด๋ฒคํŠธ ์ ์šฉ ๋Œ€์ƒ์— ์ œ์™ธ๋œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ทจํ•ฉํ–ˆ์„๋•Œ_์ฃผ๋ฌธ_๊ธˆ์•ก์ด_12๋งŒ์›_๋ฏธ๋งŒ์ด๋ฉด_์ฆ์ •_์ด๋ฒคํŠธ_์ ์šฉ_๋Œ€์ƒ์—_ํฌํ•จ() { + // given + List orders = List.of( + Order.of("์‹œ์ €์ƒ๋Ÿฌ๋“œ", 1), + Order.of("ํฌ๋ฆฌ์Šค๋งˆ์ŠคํŒŒ์Šคํƒ€", 1), + Order.of("์•„์ด์Šคํฌ๋ฆผ", 1), + Order.of("์ œ๋กœ์ฝœ๋ผ", 1) + ); + // when, then + assertThat(Orders.from(orders).isGiftEventApplicable()).isEqualTo(false); + } + + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ฃผ๋ฌธ ๊ธˆ์•ก์ด 12๋งŒ์› ์ด์ƒ์ด๋ฉด ์ฆ์ • ์ด๋ฒคํŠธ ์ ์šฉ ๋Œ€์ƒ์— ํฌํ•จํ•œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ทจํ•ฉํ–ˆ์„๋•Œ_์ฃผ๋ฌธ_๊ธˆ์•ก์ด_12๋งŒ์›_์ด์ƒ์ด๋ฉด_์ฆ์ •_์ด๋ฒคํŠธ_์ ์šฉ_๋Œ€์ƒ์—_ํฌํ•จ() { + // given + List orders = List.of( + Order.of("์‹œ์ €์ƒ๋Ÿฌ๋“œ", 2), + Order.of("๋ฐ”๋น„ํ๋ฆฝ", 2), + Order.of("ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ", 1), + Order.of("์ดˆ์ฝ”์ผ€์ดํฌ", 1), + Order.of("๋ ˆ๋“œ์™€์ธ", 1) + ); + // when, then + assertThat(Orders.from(orders).isGiftEventApplicable()).isEqualTo(true); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ด์šฉํ•ด์„œ ํ• ์ธ ์ „ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•œ๋‹ค.") + @Test + public void ์ฃผ๋ฌธ_๋‚ด์—ญ์„_์ด์šฉํ•ด์„œ_ํ• ์ธ_์ „_์ด_์ฃผ๋ฌธ_๊ธˆ์•ก์„_๊ณ„์‚ฐ() { + // given + List orders = List.of( + Order.of("์‹œ์ €์ƒ๋Ÿฌ๋“œ", 1), + Order.of("ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ", 1), + Order.of("์•„์ด์Šคํฌ๋ฆผ", 1), + Order.of("์ดˆ์ฝ”์ผ€์ดํฌ", 1), + Order.of("๋ ˆ๋“œ์™€์ธ", 1) + ); + // when, then + assertThat(Orders.from(orders).calculateTotalAmountWithNoDiscount()).isEqualTo(143000); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/domain/ReservationDayTest.java b/src/test/java/christmas/domain/ReservationDayTest.java new file mode 100644 index 0000000..275520a --- /dev/null +++ b/src/test/java/christmas/domain/ReservationDayTest.java @@ -0,0 +1,65 @@ +package christmas.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.domain.exception.InvalidReservationDayException; +import christmas.domain.exception.message.InvalidReservationDayExceptionMessage; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +public class ReservationDayTest { + @DisplayName("์œ ํšจํ•˜์ง€ ์•Š์€ ๋‚ ์งœ ( 1 ~ 31 ์‚ฌ์ด์˜ ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ์ˆซ์ž )๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.") + @ParameterizedTest + @ValueSource(ints = {0, -1, -10, 300, 350, 500, 32}) + void ์œ ํšจํ•˜์ง€_์•Š์€_๋‚ ์งœ_์ž…๋ ฅ์‹œ_์˜ˆ์™ธ_๋ฐœ์ƒ(int day) { + assertThatThrownBy(() -> ReservationDay.from(day)) + .isInstanceOf(InvalidReservationDayException.class) + .hasMessageContaining(InvalidReservationDayExceptionMessage.NOT_IN_APPROPRIATE_RANGE.getMessage()); + } + + @DisplayName("๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํฌ๋ฆฌ์Šค๋งˆ์Šค D-Day ํ”„๋กœ๋ชจ์…˜์ด ์ ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จ ๊ฐ€๋Šฅํ•˜๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"1:true", "10:true", "24:true", "31:false", "25:true", "26:false"}, delimiter = ':') + void ๋‚ ์งœ_์ž…๋ ฅ์‹œ_ํฌ๋ฆฌ์Šค๋งˆ์Šค_๋””๋ฐ์ด_ํ”„๋กœ๋ชจ์…˜_์ ์šฉ_๊ฐ€๋Šฅ_์—ฌ๋ถ€_ํŒ๋‹จ_๊ฐ€๋Šฅ(int day, boolean expected) { + // given, when + ReservationDay reservationDay = ReservationDay.from(day); + // then + assertThat(reservationDay.isChristmasPromotionApplicable()).isEqualTo(expected); + } + + @DisplayName("๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํ‰์ผ ํ• ์ธ์ด ์ ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จ ๊ฐ€๋Šฅํ•˜๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"5:true", "6:true", "7:true", "8:false", "25:true", "29:false", "30:false", + "31:true"}, delimiter = ':') + void ๋‚ ์งœ_์ž…๋ ฅ์‹œ_ํ‰์ผ_ํ• ์ธ_์ ์šฉ_๊ฐ€๋Šฅ_์—ฌ๋ถ€_ํŒ๋‹จ_๊ฐ€๋Šฅ(int day, boolean expected) { + // given, when + ReservationDay reservationDay = ReservationDay.from(day); + // then + assertThat(reservationDay.isWeekdayPromotionApplicable()).isEqualTo(expected); + } + + @DisplayName("๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์ฃผ๋ง ํ• ์ธ์ด ์ ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จ ๊ฐ€๋Šฅํ•˜๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"1:true", "9:true", "15:true", "24:false", "30:true", "28:false", "31:false", + "23:true"}, delimiter = ':') + void ๋‚ ์งœ_์ž…๋ ฅ์‹œ_์ฃผ๋ง_ํ• ์ธ_์ ์šฉ_๊ฐ€๋Šฅ_์—ฌ๋ถ€_ํŒ๋‹จ_๊ฐ€๋Šฅ(int day, boolean expected) { + // given, when + ReservationDay reservationDay = ReservationDay.from(day); + // then + assertThat(reservationDay.isWeekendPromotionApplicable()).isEqualTo(expected); + } + + @DisplayName("๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํŠน๋ณ„ ํ• ์ธ์ด ์ ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จ ๊ฐ€๋Šฅํ•˜๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"3:true", "10:true", "24:true", "26:false", "25:true", "27:false", "14:false", + "17:true", "31:true"}, delimiter = ':') + void ๋‚ ์งœ_์ž…๋ ฅ์‹œ_ํŠน๋ณ„_ํ• ์ธ_์ ์šฉ_๊ฐ€๋Šฅ_์—ฌ๋ถ€_ํŒ๋‹จ_๊ฐ€๋Šฅ(int day, boolean expected) { + // given, when + ReservationDay reservationDay = ReservationDay.from(day); + // then + assertThat(reservationDay.isSpecialPromotionApplicable()).isEqualTo(expected); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/parser/InputParserTest.java b/src/test/java/christmas/parser/InputParserTest.java new file mode 100644 index 0000000..6a6d205 --- /dev/null +++ b/src/test/java/christmas/parser/InputParserTest.java @@ -0,0 +1,65 @@ +package christmas.parser; + +import static christmas.view.input.constant.InputSymbolConstant.DAY_SYMBOL; +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; +import christmas.view.input.parser.InputParser; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class InputParserTest { + private InputParser inputParser; + + @BeforeEach + void setUp() { + inputParser = new InputParser(); + } + + @DisplayName("์˜ˆ์•ฝ ๋‚ ์งœ์— ๊ณต๋ฐฑ์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ๊ฐ’์„ ์ˆซ์ž ํ˜•์‹์œผ๋กœ ๋ฐ”๊พธ์–ด ๋Œ๋ ค์ค€๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"1 0:10", "2 3:23", " 1 7:17", "3 1:31", " 1 :1", + " 3 0 :30"}, delimiter = ':') + void ์˜ˆ์•ฝ_๋‚ ์งœ์—_๊ณต๋ฐฑ์ด_ํฌํ•จ๋œ_๊ฒฝ์šฐ_๊ณต๋ฐฑ์„_์ œ๊ฑฐํ•œ_์ˆซ์ž๋กœ_๋ฐ˜ํ™˜(String userInput, int expected) { + assertThat(inputParser.parseReservationDay(userInput)).isEqualTo(expected); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์— ๊ณต๋ฐฑ์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ, ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ๊ฐ’์„ Mapํ˜•์‹์œผ๋กœ ๋ฐ”๊พธ์–ด ๋Œ๋ ค์ค€๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"ํƒ€ ํŒŒ ์Šค - 1,ํƒ€ํŒŒ์Šค,1", " ํ‹ฐ ๋ณธ ์Šคํ…Œ ์ด ํฌ - 2,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ,2", "์ œ๋กœ ์ฝœ ๋ผ-10,์ œ๋กœ์ฝœ๋ผ,10"}, delimiter = ',') + void ์ฃผ๋ฌธ_๋‚ด์—ญ์—_๊ณต๋ฐฑ์ด_ํฌํ•จ๋œ_๊ฒฝ์šฐ_๊ณต๋ฐฑ์„_์ œ๊ฑฐํ•œ_๊ฐ’์„_๋งต์œผ๋กœ_๋ฐ˜ํ™˜(String userInput, String menuName, int menuCount) { + assertThat(inputParser.parseOrders(userInput)) + .isEqualTo(Collections.singletonMap(menuName, menuCount)); + } + + @DisplayName("๊ณต๋ฐฑ ํฌํ•จ ๋‚ ์งœ ์ž…๋ ฅ๊ฐ’์˜ ๊ธธ์ด๊ฐ€ 2000๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ๊ณต๋ฐฑ_ํฌํ•จ_๋‚ ์งœ_์ž…๋ ฅ๊ฐ’์ด_2000๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ() { + String safeDayInput = "1" + " ".repeat(1000); + String illegalDayInput = "1" + " ".repeat(2000); + assertThat(inputParser.parseReservationDay(safeDayInput)).isEqualTo(1); + assertThatThrownBy(() -> inputParser.parseReservationDay(illegalDayInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_WITH_BLANKS_FORMAT.getFormat(), + DAY_SYMBOL.getSymbol())); + } + + @DisplayName("๊ณต๋ฐฑ ํฌํ•จ ์ฃผ๋ฌธ๋‚ด์—ญ ์ž…๋ ฅ๊ฐ’์˜ ๊ธธ์ด๊ฐ€ 2000๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ๊ณต๋ฐฑ_ํฌํ•จ_์ฃผ๋ฌธ๋‚ด์—ญ_์ž…๋ ฅ๊ฐ’์ด_2000๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ() { + String userInput = "ํƒ€ํŒŒ์Šค-1" + " ".repeat(2000); + assertThatThrownBy(() -> inputParser.parseOrders(userInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_WITH_BLANKS_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/validator/DayInputValidatorTest.java b/src/test/java/christmas/validator/DayInputValidatorTest.java new file mode 100644 index 0000000..b61452d --- /dev/null +++ b/src/test/java/christmas/validator/DayInputValidatorTest.java @@ -0,0 +1,62 @@ +package christmas.validator; + +import static christmas.view.input.constant.InputSymbolConstant.DAY_SYMBOL; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.DayInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; +import christmas.view.input.exception.message.DayInputExceptionMessage; +import christmas.view.input.validator.DayInputValidator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class DayInputValidatorTest { + private DayInputValidator dayInputValidator; + + @BeforeEach + void setUp() { + dayInputValidator = new DayInputValidator(); + } + + @DisplayName("์˜ˆ์•ฝ ๋‚ ์งœ๊ฐ€ ๋น„์–ด์žˆ๋Š” ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ์˜ˆ์•ฝ_๋‚ ์งœ๊ฐ€_๋น„์–ด์žˆ๋Š”_๊ฐ’์ผ๋•Œ_์˜ˆ์™ธ_๋ฐœ์ƒ() { + assertThatThrownBy(() -> dayInputValidator.validate("")) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining(String.format(BasicInputExceptionMessageFormat.EMPTY_FORMAT.getFormat(), + DAY_SYMBOL.getSymbol())); + } + + @DisplayName("๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ ๋‚ ์งœ ๊ธธ์ด๊ฐ€ 3๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {" 0 3 0 ", "0 0 2", "0 0 0 0 4"}) + void ๊ณต๋ฐฑ_์ œ๊ฑฐ_ํ›„_์˜ˆ์•ฝ_๋‚ ์งœ_์ž…๋ ฅ๊ฐ’์ด_3๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> dayInputValidator.validate(userInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_FORMAT.getFormat(), + DAY_SYMBOL.getSymbol())); + } + + @DisplayName("์˜ˆ์•ฝ ๋‚ ์งœ๊ฐ€ ์ˆซ์žํ˜•์‹์ด ์•„๋‹Œ ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"1a", "1s", "kw", "@!", "-", "a-", "dy", "!a"}) + void ์˜ˆ์•ฝ_๋‚ ์งœ๊ฐ€_์ˆซ์ž_ํ˜•์‹์ด_์•„๋‹Œ_์ž…๋ ฅ๊ฐ’์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> dayInputValidator.validate(userInput)) + .isInstanceOf(DayInputException.class) + .hasMessageContaining(DayInputExceptionMessage.NOT_NUMERIC_TYPE.getMessage()); + } + + @DisplayName("์˜ˆ์•ฝ ๋‚ ์งœ๊ฐ€ ์–‘์ˆ˜๊ฐ€ ์•„๋‹Œ ์ˆซ์ž์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"-1", "-2", "-5", "-7", "-9", "-8", "-3", "-4"}) + void ์˜ˆ์•ฝ_๋‚ ์งœ๊ฐ€_์–‘์ˆ˜๊ฐ€_์•„๋‹Œ_์ˆซ์ž์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> dayInputValidator.validate(userInput)) + .isInstanceOf(DayInputException.class) + .hasMessageContaining(DayInputExceptionMessage.NOT_POSITIVE.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/validator/MenuCountInputValidatorTest.java b/src/test/java/christmas/validator/MenuCountInputValidatorTest.java new file mode 100644 index 0000000..3d6c818 --- /dev/null +++ b/src/test/java/christmas/validator/MenuCountInputValidatorTest.java @@ -0,0 +1,62 @@ +package christmas.validator; + +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.OrdersInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; +import christmas.view.input.exception.message.OrdersInputExceptionMessage; +import christmas.view.input.validator.MenuCountInputValidator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class MenuCountInputValidatorTest { + private MenuCountInputValidator menuCountInputValidator; + + @BeforeEach + void setUp() { + menuCountInputValidator = new MenuCountInputValidator(); + } + + @DisplayName("๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ ๋น„์–ด์žˆ๋Š” ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ๋ฉ”๋‰ด_๊ฐœ์ˆ˜๊ฐ€_๋น„์–ด์žˆ๋Š”_๊ฐ’์ผ๋•Œ_์˜ˆ์™ธ_๋ฐœ์ƒ() { + assertThatThrownBy(() -> menuCountInputValidator.validate("")) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining(String.format(BasicInputExceptionMessageFormat.EMPTY_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } + + @DisplayName("๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ ๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ 3๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {" 1 3 2 ", "4 3 2", "2 5 3 7 4"}) + void ๊ณต๋ฐฑ_์ œ๊ฑฐ_ํ›„_๋ฉ”๋‰ด_๊ฐœ์ˆ˜_์ž…๋ ฅ๊ฐ’์ด_3๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> menuCountInputValidator.validate(userInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } + + @DisplayName("๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ ์ˆซ์žํ˜•์‹์ด ์•„๋‹Œ ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"a1", "s1", "wk", "!@", "-/", "-a", "yd", "a!"}) + void ๋ฉ”๋‰ด_๊ฐœ์ˆ˜๊ฐ€_์ˆซ์ž_ํ˜•์‹์ด_์•„๋‹Œ_์ž…๋ ฅ๊ฐ’์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> menuCountInputValidator.validate(userInput)) + .isInstanceOf(OrdersInputException.class) + .hasMessageContaining(OrdersInputExceptionMessage.NOT_NUMERIC_TYPE.getMessage()); + } + + @DisplayName("๋ฉ”๋‰ด ๊ฐœ์ˆ˜๊ฐ€ ์–‘์ˆ˜๊ฐ€ ์•„๋‹Œ ์ˆซ์ž์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"-1", "-2", "-5", "-7", "-9", "-8", "-3", "-4"}) + void ๋ฉ”๋‰ด_๊ฐœ์ˆ˜๊ฐ€_์–‘์ˆ˜๊ฐ€_์•„๋‹Œ_์ˆซ์ž์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> menuCountInputValidator.validate(userInput)) + .isInstanceOf(OrdersInputException.class) + .hasMessageContaining(OrdersInputExceptionMessage.NOT_POSITIVE.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/validator/MenuNameInputValidatorTest.java b/src/test/java/christmas/validator/MenuNameInputValidatorTest.java new file mode 100644 index 0000000..ee7878a --- /dev/null +++ b/src/test/java/christmas/validator/MenuNameInputValidatorTest.java @@ -0,0 +1,44 @@ +package christmas.validator; + +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; +import christmas.view.input.validator.MenuNameInputValidator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class MenuNameInputValidatorTest { + private MenuNameInputValidator menuNameInputValidator; + + @BeforeEach + void setUp() { + menuNameInputValidator = new MenuNameInputValidator(); + } + + @DisplayName("๋ฉ”๋‰ด ์ด๋ฆ„์ด ๋น„์–ด์žˆ๋Š” ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ๋ฉ”๋‰ด_์ด๋ฆ„์ด_๋น„์–ด์žˆ๋Š”_๊ฐ’์ผ๋•Œ_์˜ˆ์™ธ_๋ฐœ์ƒ() { + assertThatThrownBy(() -> menuNameInputValidator.validate("")) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining(String.format(BasicInputExceptionMessageFormat.EMPTY_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } + + @DisplayName("๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ ๋ฉ”๋‰ด ์ด๋ฆ„ ๊ธธ์ด๊ฐ€ 31๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ํƒ€ํŒŒ์Šค ", + "ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ " + , "๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ ๋ ˆ๋“œ์™€์ธ "}) + void ๊ณต๋ฐฑ_์ œ๊ฑฐ_ํ›„_๋ฉ”๋‰ด_์ด๋ฆ„_๊ธธ์ด๊ฐ€_31๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> menuNameInputValidator.validate(userInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/validator/OrderInputValidatorTest.java b/src/test/java/christmas/validator/OrderInputValidatorTest.java new file mode 100644 index 0000000..19c1d3a --- /dev/null +++ b/src/test/java/christmas/validator/OrderInputValidatorTest.java @@ -0,0 +1,65 @@ +package christmas.validator; + +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.OrdersInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; +import christmas.view.input.exception.message.OrdersInputExceptionMessage; +import christmas.view.input.validator.OrderInputValidator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +public class OrderInputValidatorTest { + private OrderInputValidator orderInputValidator; + + @BeforeEach + void setUp() { + orderInputValidator = new OrderInputValidator(); + } + + @DisplayName("์ฃผ๋ฌธ์ด ๋น„์–ด์žˆ๋Š” ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ์ฃผ๋ฌธ์ด_๋น„์–ด์žˆ๋Š”_๊ฐ’์ผ๋•Œ_์˜ˆ์™ธ_๋ฐœ์ƒ() { + assertThatThrownBy(() -> orderInputValidator.validate("")) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining(String.format(BasicInputExceptionMessageFormat.EMPTY_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } + + @DisplayName("๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ ์ฃผ๋ฌธ ๊ธธ์ด๊ฐ€ 34๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @CsvSource(value = {"ํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šคํƒ€ํŒŒ์Šค-13", + "ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-14", + "์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ์•„์ด์Šคํฌ๋ฆผ-11"}) + void ๊ณต๋ฐฑ_์ œ๊ฑฐ_ํ›„_์ฃผ๋ฌธ_์ž…๋ ฅ๊ฐ’์ด_34๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> orderInputValidator.validate(userInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + String.format(BasicInputExceptionMessageFormat.TOO_LONG_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } + + @DisplayName("์ฃผ๋ฌธ์— ๊ตฌ๋ถ„์ž(-)๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์—์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"ํƒ€ํŒŒ์Šค1", "ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ~2", "๋ฐ”๋น„ํ๋ฆฝ@12", "์•„์ด์Šคํฌ๋ฆผ", "์‹œ์ €์ƒ๋Ÿฌ๋“œ#3", "์ดˆ์ฝ”์ผ€์ดํฌ*4", "์ œ๋กœ์ฝœ๋ผ!!", "๋ ˆ๋“œ์™€์ธ$3"}) + void ์ฃผ๋ฌธ_์ž…๋ ฅ๊ฐ’์—_๊ตฌ๋ถ„์ž๊ฐ€_ํฌํ•จ๋˜์–ด_์žˆ์ง€_์•Š์œผ๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> orderInputValidator.validate(userInput)) + .isInstanceOf(OrdersInputException.class) + .hasMessageContaining(OrdersInputExceptionMessage.INVALID_ORDER_FORMAT.getMessage()); + } + + @DisplayName("์ฃผ๋ฌธ์˜ ๋งˆ์ง€๋ง‰ ๋‹จ์–ด๊ฐ€ ๊ตฌ๋ถ„์ž(-)์ธ ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"ํƒ€ํŒŒ์Šค1-", "ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-", "ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-1-", "์‹œ์ €์ƒ๋Ÿฌ๋“œ-", "์ดˆ์ฝ”-์ผ€์ดํฌ-"}) + void ์ฃผ๋ฌธ_์ž…๋ ฅ๊ฐ’์˜_๋งˆ์ง€๋ง‰_๋‹จ์–ด๊ฐ€_๊ตฌ๋ถ„์ž_์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> orderInputValidator.validate(userInput)) + .isInstanceOf(OrdersInputException.class) + .hasMessageContaining(OrdersInputExceptionMessage.EMPTY_MENU_COUNT.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/christmas/validator/OrdersInputValidatorTest.java b/src/test/java/christmas/validator/OrdersInputValidatorTest.java new file mode 100644 index 0000000..c24df9d --- /dev/null +++ b/src/test/java/christmas/validator/OrdersInputValidatorTest.java @@ -0,0 +1,57 @@ +package christmas.validator; + +import static christmas.view.input.constant.InputSymbolConstant.ORDER_SYMBOL; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import christmas.view.input.exception.BasicInputException; +import christmas.view.input.exception.OrdersInputException; +import christmas.view.input.exception.message.BasicInputExceptionMessageFormat; +import christmas.view.input.exception.message.OrdersInputExceptionMessage; +import christmas.view.input.validator.OrdersInputValidator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class OrdersInputValidatorTest { + private OrdersInputValidator ordersInputValidator; + + @BeforeEach + void setUp() { + ordersInputValidator = new OrdersInputValidator(); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์ด ๋น„์–ด์žˆ๋Š” ์ž…๋ ฅ๊ฐ’์ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ์ฃผ๋ฌธ_๋‚ด์—ญ์ด_๋น„์–ด์žˆ๋Š”_๊ฐ’์ผ๋•Œ_์˜ˆ์™ธ_๋ฐœ์ƒ() { + assertThatThrownBy(() -> ordersInputValidator.preValidate("")) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining(String.format(BasicInputExceptionMessageFormat.EMPTY_FORMAT.getFormat(), + ORDER_SYMBOL.getSymbol())); + } + + @DisplayName("๊ณต๋ฐฑ ์ œ๊ฑฐ ํ›„ ์ฃผ๋ฌธ ๋‚ด์—ญ ๊ธธ์ด๊ฐ€ 1000๊ธ€์ž ์ด์ƒ์ด๋ฉด, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void ๊ณต๋ฐฑ_์ œ๊ฑฐ_ํ›„_์ฃผ๋ฌธ๋‚ด์—ญ_์ž…๋ ฅ๊ฐ’์ด_1000๊ธ€์ž_์ด์ƒ์ด๋ฉด_์˜ˆ์™ธ_๋ฐœ์ƒ() { + String illegalOrdersInput = "์‹œ์ €์ƒ๋Ÿฌ๋“œ-1,".repeat(200); + assertThatThrownBy(() -> ordersInputValidator.preValidate(illegalOrdersInput)) + .isInstanceOf(BasicInputException.class) + .hasMessageContaining( + BasicInputExceptionMessageFormat.TOO_LONG_FORMAT.getFormat(), ORDER_SYMBOL.getSymbol()); + } + + @DisplayName("์ฃผ๋ฌธ ๋‚ด์—ญ์„ ์ทจํ•ฉํ–ˆ์„ ๋•Œ, ์ค‘๋ณต๋œ ์ฃผ๋ฌธ ๋ฉ”๋‰ด๊ฐ€ ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = { + "ํƒ€ํŒŒ์Šค-1,ํƒ€ํŒŒ์Šค-4", + "ํƒ€ํŒŒ์Šค-1,์ดˆ์ฝ”์ผ€์ดํฌ-2,๋ ˆ๋“œ์™€์ธ-1,์ƒดํŽ˜์ธ-1,์•„์ด์Šคํฌ๋ฆผ-2,ํ‹ฐ๋ณธ์Šคํ…Œ์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1", + "์ดˆ์ฝ”์ผ€์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1,์ดˆ์ฝ”์ผ€์ดํฌ-1", + "์‹œ์ €์ƒ๋Ÿฌ๋“œ-1,์–‘์†ก์ด์ˆ˜ํ”„-1,์ œ๋กœ์ฝœ๋ผ-1,์ƒดํŽ˜์ธ-1,ํฌ๋ฆฌ์Šค๋งˆ์ŠคํŒŒ์Šคํƒ€-2,ํ•ด์‚ฐ๋ฌผํŒŒ์Šคํƒ€-1,์‹œ์ €์ƒ๋Ÿฌ๋“œ-4" + }) + void ์ค‘๋ณต_์ฃผ๋ฌธ_๋ฉ”๋‰ด_์กด์žฌ_์‹œ_์˜ˆ์™ธ_๋ฐœ์ƒ(String userInput) { + assertThatThrownBy(() -> ordersInputValidator.postValidate(userInput)) + .isInstanceOf(OrdersInputException.class) + .hasMessageContaining(OrdersInputExceptionMessage.DUPLICATED_MENUS.getMessage()); + } +} \ No newline at end of file