From 190ac26fb90f9bcb845d2038106bc32d9c505e39 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Mon, 11 Apr 2022 23:56:31 +0900 Subject: [PATCH 01/34] =?UTF-8?q?docs=20:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index b4b1377..3b9d66a 100644 --- a/README.md +++ b/README.md @@ -55,3 +55,26 @@ spill ๐ŸŸฉ๐ŸŸฉโฌœ๐ŸŸฉ๐ŸŸฉ ๐ŸŸฉ๐ŸŸฉ๐ŸŸฉ๐ŸŸฉ๐ŸŸฉ ``` + +## ์š”๊ตฌ์‚ฌํ•ญ +- [ ] ํ•˜๋‚˜์˜ Tile์ด ์žˆ๋‹ค. => (Tile) + - [ ] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. + - [ ] Tile์—๋Š” ์ƒํƒœ๊ฐ€ ์กด์žฌํ•œ๋‹ค. + - [ ] ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ + - [ ] ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ + - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ + - [ ] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. +- [ ] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) + - [ ] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. + - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [ ] Tiles๋Š” ๊ฐ๊ฐ์˜ ํƒ€์ผ์—๊ฒŒ ์ƒํƒœ๋ฅผ ๋ฌผ์„ ์ˆ˜ ์žˆ๋‹ค. + - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ์ƒํƒœ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) +- [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) + - [ ] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. + - [ ] ๊ธฐํšŒ๋งˆ๋‹ค 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [ ] ์ •๋‹ต์„ ์ ์œผ๋ฉด ๊ฒŒ์ž„์ด ๋๋‚œ๋‹ค. + - [ ] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. + - [ ] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. + - [ ] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. + - [ ] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. + - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. \ No newline at end of file From 337557e9bdc0c2d02987cc5266f49aa458f8507c Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 08:22:05 +0900 Subject: [PATCH 02/34] =?UTF-8?q?feat(Tile.kt):=20Tile=EC=97=90=EB=8A=94?= =?UTF-8?q?=20=EB=AC=B8=EC=9E=90=EA=B0=80=20=EB=93=A4=EC=96=B4=EA=B0=84?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- src/main/kotlin/domain/Tile.kt | 6 ++++++ src/test/kotlin/domain/TileTest.kt | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/domain/Tile.kt create mode 100644 src/test/kotlin/domain/TileTest.kt diff --git a/README.md b/README.md index 3b9d66a..b20631e 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,8 @@ spill ``` ## ์š”๊ตฌ์‚ฌํ•ญ -- [ ] ํ•˜๋‚˜์˜ Tile์ด ์žˆ๋‹ค. => (Tile) - - [ ] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. +- [X] ํ•˜๋‚˜์˜ Tile์ด ์žˆ๋‹ค. => (Tile) + - [X] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. - [ ] Tile์—๋Š” ์ƒํƒœ๊ฐ€ ์กด์žฌํ•œ๋‹ค. - [ ] ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - [ ] ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ @@ -77,4 +77,4 @@ spill - [ ] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. - [ ] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. - [ ] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. \ No newline at end of file + - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. diff --git a/src/main/kotlin/domain/Tile.kt b/src/main/kotlin/domain/Tile.kt new file mode 100644 index 0000000..49a5f32 --- /dev/null +++ b/src/main/kotlin/domain/Tile.kt @@ -0,0 +1,6 @@ +package domain + +@JvmInline +value class Tile ( + val character: Char +) \ No newline at end of file diff --git a/src/test/kotlin/domain/TileTest.kt b/src/test/kotlin/domain/TileTest.kt new file mode 100644 index 0000000..7210162 --- /dev/null +++ b/src/test/kotlin/domain/TileTest.kt @@ -0,0 +1,15 @@ +package domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TileTest { + @Test + fun `ํƒ€์ผ์€ ํ•˜๋‚˜์˜ ๋ฌธ์ž๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค`() { + // given + val tile = Tile('์ฟ„') + + // then + assertThat(tile.character).isEqualTo('์ฟ„') + } +} \ No newline at end of file From 9e6149d7e983a0444df23dafa673a94fcfe11ebf Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 08:31:23 +0900 Subject: [PATCH 03/34] =?UTF-8?q?feat(Tile.kt):=20=EC=95=8C=ED=8C=8C?= =?UTF-8?q?=EB=B2=B3=EB=A7=8C=20=EC=9E=85=EB=A0=A5=EC=9D=B4=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=98=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/kotlin/domain/Tile.kt | 8 +++++--- src/test/kotlin/domain/TileTest.kt | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b20631e..e7a5074 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,11 @@ spill ## ์š”๊ตฌ์‚ฌํ•ญ - [X] ํ•˜๋‚˜์˜ Tile์ด ์žˆ๋‹ค. => (Tile) - [X] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. + - [X] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - [ ] Tile์—๋Š” ์ƒํƒœ๊ฐ€ ์กด์žฌํ•œ๋‹ค. - [ ] ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - [ ] ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ - - [ ] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - [ ] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) - [ ] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. diff --git a/src/main/kotlin/domain/Tile.kt b/src/main/kotlin/domain/Tile.kt index 49a5f32..c113a39 100644 --- a/src/main/kotlin/domain/Tile.kt +++ b/src/main/kotlin/domain/Tile.kt @@ -1,6 +1,8 @@ package domain @JvmInline -value class Tile ( - val character: Char -) \ No newline at end of file +value class Tile(val character: Char) { + init { + require(character in 'A'..'z') { "๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค." } + } +} \ No newline at end of file diff --git a/src/test/kotlin/domain/TileTest.kt b/src/test/kotlin/domain/TileTest.kt index 7210162..e31198e 100644 --- a/src/test/kotlin/domain/TileTest.kt +++ b/src/test/kotlin/domain/TileTest.kt @@ -1,15 +1,26 @@ package domain import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatIllegalArgumentException import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource internal class TileTest { @Test fun `ํƒ€์ผ์€ ํ•˜๋‚˜์˜ ๋ฌธ์ž๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค`() { // given - val tile = Tile('์ฟ„') + val tile = Tile('a') // then - assertThat(tile.character).isEqualTo('์ฟ„') + assertThat(tile.character).isEqualTo('a') + } + + @ParameterizedTest + @ValueSource(chars = [' ', '0', '1', '5', '9', 'ใ„ฑ', 'โฌœ']) + fun `ํƒ€์ผ์€ ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค`(character: Char) { + assertThatIllegalArgumentException() + .isThrownBy { Tile(character) } + .withMessage("๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.") } } \ No newline at end of file From f697439dfe0747dc158e139f92d35fcf3d7bcb3e Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 08:42:15 +0900 Subject: [PATCH 04/34] =?UTF-8?q?docs=20:=20Tile=EC=9D=98=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A0=95=EC=9D=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e7a5074..484058f 100644 --- a/README.md +++ b/README.md @@ -60,15 +60,15 @@ spill - [X] ํ•˜๋‚˜์˜ Tile์ด ์žˆ๋‹ค. => (Tile) - [X] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. - [X] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - - [ ] Tile์—๋Š” ์ƒํƒœ๊ฐ€ ์กด์žฌํ•œ๋‹ค. - - [ ] ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - - [ ] ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ -- [ ] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) + - [ ] Tile๊ณผ Tile์€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. +- [ ] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - [ ] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - - [ ] Tiles๋Š” ๊ฐ๊ฐ์˜ ํƒ€์ผ์—๊ฒŒ ์ƒํƒœ๋ฅผ ๋ฌผ์„ ์ˆ˜ ์žˆ๋‹ค. - - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ์ƒํƒœ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) + - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [ ] ์ •๋‹ต๊ณผ Tiles๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค + - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ + - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ + - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ + - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ๋น„๊ต ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) - [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - [ ] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. - [ ] ๊ธฐํšŒ๋งˆ๋‹ค 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. From f5d8d6d8c51652595b3cc373b89a1933f4c9e991 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 08:48:04 +0900 Subject: [PATCH 05/34] =?UTF-8?q?feat(Tile.kt)=20:=20Tile=EA=B3=BC=20Tile?= =?UTF-8?q?=EC=9D=80=20=EB=B9=84=EA=B5=90=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/test/kotlin/domain/TileTest.kt | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 484058f..ff27819 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ spill - [X] ํ•˜๋‚˜์˜ Tile์ด ์žˆ๋‹ค. => (Tile) - [X] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. - [X] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - - [ ] Tile๊ณผ Tile์€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. + - [X] Tile๊ณผ Tile์€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. - [ ] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - [ ] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. diff --git a/src/test/kotlin/domain/TileTest.kt b/src/test/kotlin/domain/TileTest.kt index e31198e..e22d856 100644 --- a/src/test/kotlin/domain/TileTest.kt +++ b/src/test/kotlin/domain/TileTest.kt @@ -23,4 +23,24 @@ internal class TileTest { .isThrownBy { Tile(character) } .withMessage("๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.") } -} \ No newline at end of file + + @Test + fun `๋‘๊ฐœ์˜ Tile์ด ์„œ๋กœ ์ผ์น˜ํ•˜๋ฉด ์ฐธ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() { + // given + val tile = Tile('a') + val anotherTile = Tile('a') + + // then + assertThat(tile).isEqualTo(anotherTile) + } + + @Test + fun `๋‘๊ฐœ์˜ Tile์ด ์„œ๋กœ ๋‹ค๋ฅด๋ฉด ๊ฑฐ์ง“์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() { + // given + val tile = Tile('a') + val anotherTile = Tile('b') + + // then + assertThat(tile).isNotEqualTo(anotherTile) + } +} From 8771abc4f14e8bb48760d4b1c2dfb17fad044206 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 09:02:09 +0900 Subject: [PATCH 06/34] =?UTF-8?q?feat(Tiles.kt)=20:=205=EA=B0=9C=EC=9D=98?= =?UTF-8?q?=20Tile=EC=9D=84=20=EA=B5=AC=EC=84=B1=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20Tiles=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/kotlin/domain/Tile.kt | 2 +- src/main/kotlin/domain/Tiles.kt | 7 ++++++ src/test/kotlin/domain/TilesTest.kt | 33 +++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/domain/Tiles.kt create mode 100644 src/test/kotlin/domain/TilesTest.kt diff --git a/README.md b/README.md index ff27819..263a4fe 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,9 @@ spill - [X] Tile์—๋Š” ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. - [X] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - [X] Tile๊ณผ Tile์€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. -- [ ] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - - [ ] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. +- [X] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [X] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [ ] ์ •๋‹ต๊ณผ Tiles๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ diff --git a/src/main/kotlin/domain/Tile.kt b/src/main/kotlin/domain/Tile.kt index c113a39..30d38c0 100644 --- a/src/main/kotlin/domain/Tile.kt +++ b/src/main/kotlin/domain/Tile.kt @@ -5,4 +5,4 @@ value class Tile(val character: Char) { init { require(character in 'A'..'z') { "๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค." } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt new file mode 100644 index 0000000..5b41bd9 --- /dev/null +++ b/src/main/kotlin/domain/Tiles.kt @@ -0,0 +1,7 @@ +package domain + +class Tiles(val tiles: List) { + init { + require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } + } +} diff --git a/src/test/kotlin/domain/TilesTest.kt b/src/test/kotlin/domain/TilesTest.kt new file mode 100644 index 0000000..e8dd4b9 --- /dev/null +++ b/src/test/kotlin/domain/TilesTest.kt @@ -0,0 +1,33 @@ +package domain + +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatIllegalArgumentException +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +internal class TilesTest { + @Test + fun `Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค`() { + // given + val elements = listOf(Tile('a'), Tile('b'), Tile('c'), Tile('d'), Tile('e')) + + // when + val tiles = Tiles(elements) + + // then + assertThat(tiles.tiles).containsExactlyElementsOf(elements) + } + + @ParameterizedTest + @ValueSource(ints = [0, 1, 2, 3, 4, 6, 10]) + fun `Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(size: Int) { + // given + val elements: List = (0 until size).map { Tile('a') } + + // then + assertThatIllegalArgumentException() + .isThrownBy { Tiles(elements) } + .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + } +} From 862eb7e563d0432257d9c12566bc534e44408d68 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 22:18:00 +0900 Subject: [PATCH 07/34] =?UTF-8?q?feat(Tiles.kt)=20:=20Tiles=EB=8A=94=205?= =?UTF-8?q?=EA=B8=80=EC=9E=90=EB=A5=BC=20=EB=B0=9B=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/kotlin/domain/Tiles.kt | 4 ++++ src/test/kotlin/domain/TilesTest.kt | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 263a4fe..f647e84 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ spill - [X] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - [X] Tile๊ณผ Tile์€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. - [X] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - - [ ] Tiles๋Š” 5๊ธ€์ž์˜ ๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [X] Tiles๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [ ] ์ •๋‹ต๊ณผ Tiles๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt index 5b41bd9..278abb7 100644 --- a/src/main/kotlin/domain/Tiles.kt +++ b/src/main/kotlin/domain/Tiles.kt @@ -4,4 +4,8 @@ class Tiles(val tiles: List) { init { require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } } + + companion object { + fun of(words: String): Tiles = Tiles(words.map { Tile(it) }) + } } diff --git a/src/test/kotlin/domain/TilesTest.kt b/src/test/kotlin/domain/TilesTest.kt index e8dd4b9..0a2b5cb 100644 --- a/src/test/kotlin/domain/TilesTest.kt +++ b/src/test/kotlin/domain/TilesTest.kt @@ -30,4 +30,20 @@ internal class TilesTest { .isThrownBy { Tiles(elements) } .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") } + + @Test + fun `Tiles๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค`() { + val tiles = Tiles.of("hello") + + assertThat(tiles.tiles) + .containsExactly(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + } + + @ParameterizedTest + @ValueSource(strings = ["", "h", "hell", "hellow"]) + fun `Tiles๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(words: String) { + assertThatIllegalArgumentException() + .isThrownBy { Tiles.of(words) } + .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + } } From b84dc75f30a03594a62c5f203c19d07de9ca303f Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 22:27:03 +0900 Subject: [PATCH 08/34] =?UTF-8?q?docs=20:=20Answer=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f647e84..910be2a 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,12 @@ spill - [X] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - [X] Tiles๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - - [ ] ์ •๋‹ต๊ณผ Tiles๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค - - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ +- [ ] ์ •๋‹ต์ด ์žˆ๋‹ค. => (Answer) + - [ ] Answer๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [ ] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. + - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ + - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ + - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ๋น„๊ต ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) - [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - [ ] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. From ac876f82d33a68b8ffba695bf6dbe66f375895d3 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 22:30:32 +0900 Subject: [PATCH 09/34] =?UTF-8?q?feat(Answer.kt)=20:=20Answer=EB=8A=94=205?= =?UTF-8?q?=EA=B0=9C=EC=9D=98=20Tile=EB=A1=9C=20=EA=B5=AC=EC=84=B1?= =?UTF-8?q?=EC=9D=B4=20=EB=90=98=EC=96=B4=EC=9E=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/kotlin/domain/Answer.kt | 7 ++++++ src/test/kotlin/domain/AnswerTest.kt | 32 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/domain/Answer.kt create mode 100644 src/test/kotlin/domain/AnswerTest.kt diff --git a/README.md b/README.md index 910be2a..77eeecf 100644 --- a/README.md +++ b/README.md @@ -64,9 +64,9 @@ spill - [X] ์—ฌ๋Ÿฌ๊ฐœ์˜ Tile์„ ๋ฌถ๋Š”๋‹ค. => (Tiles) (์ž…๋ ฅ๋˜์–ด์„œ ์ƒ์„ฑ๋œ Tiles) - [X] Tiles๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. -- [ ] ์ •๋‹ต์ด ์žˆ๋‹ค. => (Answer) +- [X] ์ •๋‹ต์ด ์žˆ๋‹ค. => (Answer) - [ ] Answer๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - - [ ] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. + - [X] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt new file mode 100644 index 0000000..1939c6f --- /dev/null +++ b/src/main/kotlin/domain/Answer.kt @@ -0,0 +1,7 @@ +package domain + +class Answer(val tiles: List) { + init { + require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } + } +} \ No newline at end of file diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt new file mode 100644 index 0000000..f073472 --- /dev/null +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -0,0 +1,32 @@ +package domain + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +internal class AnswerTest { + @Test + fun `Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค`() { + // given + val elements = listOf(Tile('a'), Tile('b'), Tile('c'), Tile('d'), Tile('e')) + + // when + val answer = Answer(elements) + + // then + Assertions.assertThat(answer.tiles).containsExactlyElementsOf(elements) + } + + @ParameterizedTest + @ValueSource(ints = [0, 1, 2, 3, 4, 6, 10]) + fun `Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(size: Int) { + // given + val elements: List = (0 until size).map { Tile('a') } + + // then + Assertions.assertThatIllegalArgumentException() + .isThrownBy { Answer(elements) } + .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + } +} \ No newline at end of file From 8c1daf172b1447809049f09eae47af1de5345b99 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 22:34:23 +0900 Subject: [PATCH 10/34] =?UTF-8?q?feat(Answer.kt)=20:=20Answer=EB=8A=94=205?= =?UTF-8?q?=EA=B8=80=EC=9E=90=EB=A5=BC=20=EB=B0=9B=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/kotlin/domain/Answer.kt | 6 +++++- src/test/kotlin/domain/AnswerTest.kt | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77eeecf..8a9750f 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ spill - [X] Tiles๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Tiles๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [X] ์ •๋‹ต์ด ์žˆ๋‹ค. => (Answer) - - [ ] Answer๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. + - [X] Answer๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index 1939c6f..5b654ed 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -4,4 +4,8 @@ class Answer(val tiles: List) { init { require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } } -} \ No newline at end of file + + companion object { + fun of(words: String): Answer = Answer(words.map { Tile(it) }) + } +} diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index f073472..938c5dd 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -29,4 +29,20 @@ internal class AnswerTest { .isThrownBy { Answer(elements) } .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") } + + @Test + fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค`() { + val answer = Answer.of("hello") + + Assertions.assertThat(answer.tiles) + .containsExactly(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + } + + @ParameterizedTest + @ValueSource(strings = ["", "h", "hell", "hellow"]) + fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(words: String) { + Assertions.assertThatIllegalArgumentException() + .isThrownBy { Answer.of(words) } + .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + } } \ No newline at end of file From 6a252629676d24e7dab452fbcbc74d219be47e39 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 23:07:23 +0900 Subject: [PATCH 11/34] =?UTF-8?q?feat(Answer.kt,=20Tiles.kt):=20=EC=A0=95?= =?UTF-8?q?=EB=8B=B5=EA=B3=BC=20=EB=B9=84=EA=B5=90=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EA=B0=99=EC=9D=80=20=EC=9C=84=EC=B9=98=EC=97=90=20=EC=9E=88?= =?UTF-8?q?=EC=9C=BC=EB=A9=B4=20GREEN=EC=9D=B4=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/kotlin/domain/Answer.kt | 10 ++++++++++ src/main/kotlin/domain/MatchResult.kt | 7 +++++++ src/main/kotlin/domain/Tiles.kt | 2 ++ src/test/kotlin/domain/AnswerTest.kt | 24 +++++++++++++++++++++--- src/test/kotlin/domain/TilesTest.kt | 18 ++++++++++++++++++ 6 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/domain/MatchResult.kt diff --git a/README.md b/README.md index 8a9750f..3747a44 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ spill - [X] ์ •๋‹ต์ด ์žˆ๋‹ค. => (Answer) - [X] Answer๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - - [ ] ์ •๋‹ต์ด ๋œ ๋ฌธ์ž๊ณผ ์ž…๋ ฅ๋œ ํ•ด๋‹น ์œ„์น˜์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ๋งž์œผ๋ฉด ์ดˆ๋ก์ƒ‰ + - [X] ์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ๋น„๊ต ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index 5b654ed..b87d34f 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -5,6 +5,16 @@ class Answer(val tiles: List) { require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } } + fun match(another : Tiles) : List { + return this.tiles.mapIndexed { index, tile -> + if (another.equals(tile, index)) { + MatchResult.GREEN + } else { + MatchResult.GRAY + } + } + } + companion object { fun of(words: String): Answer = Answer(words.map { Tile(it) }) } diff --git a/src/main/kotlin/domain/MatchResult.kt b/src/main/kotlin/domain/MatchResult.kt new file mode 100644 index 0000000..2982370 --- /dev/null +++ b/src/main/kotlin/domain/MatchResult.kt @@ -0,0 +1,7 @@ +package domain + +enum class MatchResult { + GREEN, + YELLOW, + GRAY +} \ No newline at end of file diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt index 278abb7..16cd594 100644 --- a/src/main/kotlin/domain/Tiles.kt +++ b/src/main/kotlin/domain/Tiles.kt @@ -5,6 +5,8 @@ class Tiles(val tiles: List) { require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } } + fun equals(tile: Tile, index: Int): Boolean = this.tiles[index] == tile + companion object { fun of(words: String): Tiles = Tiles(words.map { Tile(it) }) } diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 938c5dd..192a3b1 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -1,6 +1,8 @@ package domain +import domain.MatchResult.* import org.assertj.core.api.Assertions +import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource @@ -15,7 +17,7 @@ internal class AnswerTest { val answer = Answer(elements) // then - Assertions.assertThat(answer.tiles).containsExactlyElementsOf(elements) + assertThat(answer.tiles).containsExactlyElementsOf(elements) } @ParameterizedTest @@ -32,17 +34,33 @@ internal class AnswerTest { @Test fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค`() { + // given val answer = Answer.of("hello") - Assertions.assertThat(answer.tiles) + // then + assertThat(answer.tiles) .containsExactly(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) } @ParameterizedTest @ValueSource(strings = ["", "h", "hell", "hellow"]) fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(words: String) { + // then Assertions.assertThatIllegalArgumentException() .isThrownBy { Answer.of(words) } .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") } -} \ No newline at end of file + + @Test + fun `์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค`() {// given + // given + val answer = Answer.of("hello") + val tiles = Tiles.of("hello") + + // when + val matches: List = answer.match(tiles) + + // then + assertThat(matches).containsOnly(GREEN) + } +} diff --git a/src/test/kotlin/domain/TilesTest.kt b/src/test/kotlin/domain/TilesTest.kt index 0a2b5cb..693c602 100644 --- a/src/test/kotlin/domain/TilesTest.kt +++ b/src/test/kotlin/domain/TilesTest.kt @@ -4,6 +4,7 @@ import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatIllegalArgumentException 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 internal class TilesTest { @@ -33,8 +34,10 @@ internal class TilesTest { @Test fun `Tiles๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค`() { + // given val tiles = Tiles.of("hello") + // then assertThat(tiles.tiles) .containsExactly(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) } @@ -42,8 +45,23 @@ internal class TilesTest { @ParameterizedTest @ValueSource(strings = ["", "h", "hell", "hellow"]) fun `Tiles๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(words: String) { + // then assertThatIllegalArgumentException() .isThrownBy { Tiles.of(words) } .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") } + + @ParameterizedTest + @CsvSource(value = [ + "h,0,true","e,1,true","l,2,true","l,3,true","o,4,true", // ์„ฑ๊ณต์ผ€์ด์Šค + "a,0,false","b,1,false","c,2,false","d,3,false","e,4,false" // ์‹คํŒจ์ผ€์ด์Šค + ]) + fun `Tiles๋Š” ์œ„์น˜์™€ Tile์„ ๋ฐ›์•„์„œ ํ•ด๋‹น ์œ„์น˜์— ๊ฐ™์€ ํƒ€์ผ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค`(tile: Char, index: Int, result: Boolean) { + // given + val tile = Tile(tile) + val tiles = Tiles.of("hello") + + // then + assertThat(tiles.equals(tile, index)).isEqualTo(result) + } } From ee1393663cde7fbb1c3af90530a91e5564746822 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 23:17:22 +0900 Subject: [PATCH 12/34] =?UTF-8?q?feat(Answer.kt,=20Tiles.kt):=20=EC=A0=95?= =?UTF-8?q?=EB=8B=B5=EC=97=90=EB=8A=94=20=EC=9E=88=EC=A7=80=EB=A7=8C=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=EA=B0=80=20=EB=8B=A4=EB=A5=B4=EB=A9=B4=20?= =?UTF-8?q?=EB=85=B8=EB=9E=80=EC=83=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/kotlin/domain/Answer.kt | 2 ++ src/main/kotlin/domain/Tiles.kt | 2 ++ src/test/kotlin/domain/AnswerTest.kt | 15 ++++++++++++++- src/test/kotlin/domain/TilesTest.kt | 11 +++++++++++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3747a44..7bfb7b1 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ spill - [X] Answer๋Š” 5๊ธ€์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [X] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [X] ์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค - - [ ] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ + - [X] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ๋น„๊ต ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) - [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index b87d34f..8bd42f4 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -9,6 +9,8 @@ class Answer(val tiles: List) { return this.tiles.mapIndexed { index, tile -> if (another.equals(tile, index)) { MatchResult.GREEN + } else if (another.countOf(tile) > 0) { + MatchResult.YELLOW } else { MatchResult.GRAY } diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt index 16cd594..32bed16 100644 --- a/src/main/kotlin/domain/Tiles.kt +++ b/src/main/kotlin/domain/Tiles.kt @@ -7,6 +7,8 @@ class Tiles(val tiles: List) { fun equals(tile: Tile, index: Int): Boolean = this.tiles[index] == tile + fun countOf(tile: Tile): Int = this.tiles.count { it == tile } + companion object { fun of(words: String): Tiles = Tiles(words.map { Tile(it) }) } diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 192a3b1..089ca51 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -52,7 +52,7 @@ internal class AnswerTest { } @Test - fun `์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค`() {// given + fun `์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("hello") @@ -63,4 +63,17 @@ internal class AnswerTest { // then assertThat(matches).containsOnly(GREEN) } + + @Test + fun `์ •๋‹ต์€ ์•„๋‹ˆ์ง€๋งŒ Tile์ด ์žˆ์œผ๋ฉด YELLOW์ด๋‹ค`() { + // given + val answer = Answer.of("hello") + val tiles = Tiles.of("olehl") + + // when + val matches: List = answer.match(tiles) + + // then + assertThat(matches).containsOnly(YELLOW) + } } diff --git a/src/test/kotlin/domain/TilesTest.kt b/src/test/kotlin/domain/TilesTest.kt index 693c602..d2491e4 100644 --- a/src/test/kotlin/domain/TilesTest.kt +++ b/src/test/kotlin/domain/TilesTest.kt @@ -64,4 +64,15 @@ internal class TilesTest { // then assertThat(tiles.equals(tile, index)).isEqualTo(result) } + + @ParameterizedTest + @CsvSource(value = ["h,1","e,1","l,2","o,1","z,0"]) + fun `Tiles์— Tile์ด ๋ช‡๊ฐœ ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค`(tile: Char, count: Int) { + // given + val tiles = Tiles.of("hello") + val tile = Tile(tile) + + // then + assertThat(tiles.countOf(tile)).isEqualTo(count) + } } From 18d8b9fd4ca2b84f2050c4f0d0e8462caff9fd85 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Tue, 12 Apr 2022 23:23:01 +0900 Subject: [PATCH 13/34] =?UTF-8?q?feat(Answer.kt,=20Tiles.kt):=20=EC=95=84?= =?UTF-8?q?=EC=98=88=20=EC=97=86=EC=9C=BC=EB=A9=B4=20=ED=9A=8C=EC=83=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- src/test/kotlin/domain/AnswerTest.kt | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7bfb7b1..ce909a6 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,8 @@ spill - [X] Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. - [X] ์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค - [X] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - - [ ] ์—†์œผ๋ฉด ํšŒ์ƒ‰ or ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ + - [X] ์•„์˜ˆ ์—†์œผ๋ฉด ํšŒ์ƒ‰ + - [ ] ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ๋น„๊ต ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) - [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - [ ] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 089ca51..c70cd54 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -76,4 +76,17 @@ internal class AnswerTest { // then assertThat(matches).containsOnly(YELLOW) } + + @Test + fun `์ •๋‹ต์— Tile์ด ์—†์œผ๋ฉด GRAY์ด๋‹ค`() { + // given + val answer = Answer.of("hello") + val tiles = Tiles.of("zzzzz") + + // when + val matches: List = answer.match(tiles) + + // then + assertThat(matches).containsOnly(GRAY) + } } From 8ca253b958890cd53accf4e1a89624b7c31900d0 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 00:38:09 +0900 Subject: [PATCH 14/34] =?UTF-8?q?feat(Answer.kt):=20=EC=A0=95=EB=8B=B5?= =?UTF-8?q?=EC=97=90=20=EC=9E=88=EB=8A=94=20=ED=83=80=EC=9D=BC=EC=9D=80=20?= =?UTF-8?q?n=EA=B0=9C=EC=9D=B4=EC=A7=80=EB=A7=8C,=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=ED=95=9C=20=ED=83=80=EC=9D=BC=EC=9D=80=20n=20+=201=EA=B0=9C=20?= =?UTF-8?q?=EC=9D=B4=EC=83=81=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=EC=B4=88?= =?UTF-8?q?=EB=A1=9D=20->=20=EB=85=B8=EB=9E=80=EC=83=89=20->=20=ED=9A=8C?= =?UTF-8?q?=EC=83=89=EC=88=9C=EC=9C=BC=EB=A1=9C=20=EC=9A=B0=EC=84=A0?= =?UTF-8?q?=EC=88=9C=EC=9C=84=EB=A5=BC=20=EA=B0=80=EC=A7=84=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- src/main/kotlin/domain/Answer.kt | 47 +++++++++++++++++++++++----- src/main/kotlin/domain/Tiles.kt | 2 +- src/test/kotlin/domain/AnswerTest.kt | 39 +++++++++++++++++++++++ 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ce909a6..f998047 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,7 @@ spill - [X] ์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค - [X] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - [X] ์•„์˜ˆ ์—†์œผ๋ฉด ํšŒ์ƒ‰ - - [ ] ์ •๋‹ต์— ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ - - [ ] Tiles๋Š” ๋ชจ๋“  Tile์— ๋Œ€ํ•œ ๋น„๊ต ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค. (๋ช‡๊ฐœ ๋งž์•˜๊ณ , ๋ช‡๊ฐœ ๋ฏธ์‹ฑ์ด๊ณ , ๋ช‡๊ฐœ๊ฐ€ ์—†๋Š”์ง€) + - [X] ์ •๋‹ต์— ์žˆ๋Š” ํƒ€์ผ์€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ ์ดˆ๋ก -> ๋…ธ๋ž€์ƒ‰ -> ํšŒ์ƒ‰์ˆœ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„๋‹ค - [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - [ ] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. - [ ] ๊ธฐํšŒ๋งˆ๋‹ค 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index 8bd42f4..5cfc690 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -1,18 +1,49 @@ package domain +import domain.MatchResult.GRAY +import domain.MatchResult.YELLOW + class Answer(val tiles: List) { init { require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } } - fun match(another : Tiles) : List { - return this.tiles.mapIndexed { index, tile -> - if (another.equals(tile, index)) { - MatchResult.GREEN - } else if (another.countOf(tile) > 0) { - MatchResult.YELLOW - } else { - MatchResult.GRAY + fun match(other: Tiles): List { + val result: Array = arrayOf(GRAY, GRAY, GRAY, GRAY, GRAY) + val countOfTile: MutableMap = tiles.groupingBy { it }.eachCount().toMutableMap() + + fillGreen(result, other, countOfTile) + fillYellow(result, other, countOfTile) + + return result.toList() + } + + private fun fillGreen( + result: Array, + other: Tiles, + countOfTile: MutableMap + ) { + this.tiles.mapIndexed { index, tile -> + if (other.equals(tile, index)) { + result[index] = MatchResult.GREEN + + countOfTile[tile] = countOfTile[tile]!!.dec() + } + } + } + + private fun fillYellow( + result: Array, + other: Tiles, + countOfTile: MutableMap + ) { + other.mapIndexed { index, tile -> + val count = countOfTile[tile] ?: 0 + + if (result[index] == GRAY && count > 0) { + result[index] = YELLOW + + countOfTile[tile] = count.dec() } } } diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt index 32bed16..0d16380 100644 --- a/src/main/kotlin/domain/Tiles.kt +++ b/src/main/kotlin/domain/Tiles.kt @@ -1,6 +1,6 @@ package domain -class Tiles(val tiles: List) { +class Tiles(val tiles: List) : List by tiles { init { require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } } diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index c70cd54..4393e62 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -89,4 +89,43 @@ internal class AnswerTest { // then assertThat(matches).containsOnly(GRAY) } + + @Test + fun `์ •๋‹ต์„ ๋จธ์ € ์ดˆ๋ก์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ์กด์žฌํ•˜๋Š” ๋ถ€๋ถ„์„ ๋…ธ๋ž€์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค`() { + // given + val answer = Answer.of("hello") + val tiles = Tiles.of("olleh") + + // when + val matches: List = answer.match(tiles) + + // then + assertThat(matches).containsExactly(YELLOW, YELLOW, GREEN, YELLOW, YELLOW) + } + + @Test + fun `์ •๋‹ต์ด ๋’ค์— ์žˆ์œผ๋ฉด ์ •๋‹ต๋ถ€ํ„ฐ ์ดˆ๋ก์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { + // given + val answer = Answer.of("hello") + val tiles = Tiles.of("lllll") + + // when + val matches: List = answer.match(tiles) + + // then + assertThat(matches).containsExactly(GRAY, GRAY, GREEN, GREEN, GRAY) + } + + @Test + fun `๋‹ต์— ์žˆ๋Š” ํƒ€์ผ ๊ฐœ์ˆ˜๋ณด๋‹ค ๋งŽ์œผ๋ฉด ํšŒ์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { + // given + val answer = Answer.of("hello") + val tiles = Tiles.of("llool") + + // when + val matches: List = answer.match(tiles) + + // then + assertThat(matches).containsExactly(YELLOW, YELLOW, YELLOW, GRAY, GRAY) + } } From 7f95066293d4f422376d06573dbf34525fee9699 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 00:51:06 +0900 Subject: [PATCH 15/34] =?UTF-8?q?refact=20:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/domain/Answer.kt | 20 +++++++++++-------- src/main/kotlin/domain/MatchResult.kt | 6 +++--- src/main/kotlin/domain/Tile.kt | 7 ++++++- src/main/kotlin/domain/Tiles.kt | 5 ++++- src/test/kotlin/domain/AnswerTest.kt | 28 +++++++++++++-------------- src/test/kotlin/domain/TileTest.kt | 2 +- src/test/kotlin/domain/TilesTest.kt | 4 ++-- 7 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index 5cfc690..ced4308 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -1,15 +1,15 @@ package domain -import domain.MatchResult.GRAY -import domain.MatchResult.YELLOW +import domain.MatchResult.INCORRECT +import domain.MatchResult.MISSING class Answer(val tiles: List) { init { - require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } + require(tiles.size == REQUIRE_TILE_SIZE) { ERROR_TILE_SIZE_MSG } } fun match(other: Tiles): List { - val result: Array = arrayOf(GRAY, GRAY, GRAY, GRAY, GRAY) + val result: Array = arrayOf(INCORRECT, INCORRECT, INCORRECT, INCORRECT, INCORRECT) val countOfTile: MutableMap = tiles.groupingBy { it }.eachCount().toMutableMap() fillGreen(result, other, countOfTile) @@ -25,7 +25,7 @@ class Answer(val tiles: List) { ) { this.tiles.mapIndexed { index, tile -> if (other.equals(tile, index)) { - result[index] = MatchResult.GREEN + result[index] = MatchResult.CORRECT countOfTile[tile] = countOfTile[tile]!!.dec() } @@ -38,10 +38,10 @@ class Answer(val tiles: List) { countOfTile: MutableMap ) { other.mapIndexed { index, tile -> - val count = countOfTile[tile] ?: 0 + val count = countOfTile[tile] ?: EMPTY - if (result[index] == GRAY && count > 0) { - result[index] = YELLOW + if (result[index] == INCORRECT && count > EMPTY) { + result[index] = MISSING countOfTile[tile] = count.dec() } @@ -49,6 +49,10 @@ class Answer(val tiles: List) { } companion object { + const val ERROR_TILE_SIZE_MSG = "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." + const val REQUIRE_TILE_SIZE = 5 + const val EMPTY = 0 + fun of(words: String): Answer = Answer(words.map { Tile(it) }) } } diff --git a/src/main/kotlin/domain/MatchResult.kt b/src/main/kotlin/domain/MatchResult.kt index 2982370..d1f8b83 100644 --- a/src/main/kotlin/domain/MatchResult.kt +++ b/src/main/kotlin/domain/MatchResult.kt @@ -1,7 +1,7 @@ package domain enum class MatchResult { - GREEN, - YELLOW, - GRAY + CORRECT, + MISSING, + INCORRECT } \ No newline at end of file diff --git a/src/main/kotlin/domain/Tile.kt b/src/main/kotlin/domain/Tile.kt index 30d38c0..4d60863 100644 --- a/src/main/kotlin/domain/Tile.kt +++ b/src/main/kotlin/domain/Tile.kt @@ -3,6 +3,11 @@ package domain @JvmInline value class Tile(val character: Char) { init { - require(character in 'A'..'z') { "๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค." } + require(character in ALLOWED_CHARACTER) { ERROR_ALLOWED_CHARACTER_MSG } + } + + companion object { + const val ERROR_ALLOWED_CHARACTER_MSG = "๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค." + val ALLOWED_CHARACTER = 'a'..'z' } } diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt index 0d16380..8305191 100644 --- a/src/main/kotlin/domain/Tiles.kt +++ b/src/main/kotlin/domain/Tiles.kt @@ -2,7 +2,7 @@ package domain class Tiles(val tiles: List) : List by tiles { init { - require(tiles.size == 5) { "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." } + require(tiles.size == REQUIRE_TILE_SIZE) { ERROR_TILE_SIZE_MSG } } fun equals(tile: Tile, index: Int): Boolean = this.tiles[index] == tile @@ -10,6 +10,9 @@ class Tiles(val tiles: List) : List by tiles { fun countOf(tile: Tile): Int = this.tiles.count { it == tile } companion object { + const val ERROR_TILE_SIZE_MSG = "ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." + const val REQUIRE_TILE_SIZE = 5 + fun of(words: String): Tiles = Tiles(words.map { Tile(it) }) } } diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 4393e62..3b147c2 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -29,7 +29,7 @@ internal class AnswerTest { // then Assertions.assertThatIllegalArgumentException() .isThrownBy { Answer(elements) } - .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + .withMessage(Answer.ERROR_TILE_SIZE_MSG) } @Test @@ -48,11 +48,11 @@ internal class AnswerTest { // then Assertions.assertThatIllegalArgumentException() .isThrownBy { Answer.of(words) } - .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + .withMessage(Answer.ERROR_TILE_SIZE_MSG) } @Test - fun `์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด GREEN์ด๋‹ค`() { + fun `์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด CORRECT์ด๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("hello") @@ -61,11 +61,11 @@ internal class AnswerTest { val matches: List = answer.match(tiles) // then - assertThat(matches).containsOnly(GREEN) + assertThat(matches).containsOnly(CORRECT) } @Test - fun `์ •๋‹ต์€ ์•„๋‹ˆ์ง€๋งŒ Tile์ด ์žˆ์œผ๋ฉด YELLOW์ด๋‹ค`() { + fun `์ •๋‹ต์€ ์•„๋‹ˆ์ง€๋งŒ Tile์ด ์žˆ์œผ๋ฉด MISSING์ด๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("olehl") @@ -74,11 +74,11 @@ internal class AnswerTest { val matches: List = answer.match(tiles) // then - assertThat(matches).containsOnly(YELLOW) + assertThat(matches).containsOnly(MISSING) } @Test - fun `์ •๋‹ต์— Tile์ด ์—†์œผ๋ฉด GRAY์ด๋‹ค`() { + fun `์ •๋‹ต์— Tile์ด ์—†์œผ๋ฉด INCORRECT์ด๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("zzzzz") @@ -87,11 +87,11 @@ internal class AnswerTest { val matches: List = answer.match(tiles) // then - assertThat(matches).containsOnly(GRAY) + assertThat(matches).containsOnly(INCORRECT) } @Test - fun `์ •๋‹ต์„ ๋จธ์ € ์ดˆ๋ก์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ์กด์žฌํ•˜๋Š” ๋ถ€๋ถ„์„ ๋…ธ๋ž€์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค`() { + fun `์ •๋‹ต์„ ๋จธ์ € CORRECT์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ์กด์žฌํ•˜๋Š” ๋ถ€๋ถ„์„ MISSING์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("olleh") @@ -100,11 +100,11 @@ internal class AnswerTest { val matches: List = answer.match(tiles) // then - assertThat(matches).containsExactly(YELLOW, YELLOW, GREEN, YELLOW, YELLOW) + assertThat(matches).containsExactly(MISSING, MISSING, CORRECT, MISSING, MISSING) } @Test - fun `์ •๋‹ต์ด ๋’ค์— ์žˆ์œผ๋ฉด ์ •๋‹ต๋ถ€ํ„ฐ ์ดˆ๋ก์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { + fun `์ •๋‹ต์ด ๋’ค์— ์žˆ์œผ๋ฉด ์ •๋‹ต๋ถ€ํ„ฐ CORRECT์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("lllll") @@ -113,11 +113,11 @@ internal class AnswerTest { val matches: List = answer.match(tiles) // then - assertThat(matches).containsExactly(GRAY, GRAY, GREEN, GREEN, GRAY) + assertThat(matches).containsExactly(INCORRECT, INCORRECT, CORRECT, CORRECT, INCORRECT) } @Test - fun `๋‹ต์— ์žˆ๋Š” ํƒ€์ผ ๊ฐœ์ˆ˜๋ณด๋‹ค ๋งŽ์œผ๋ฉด ํšŒ์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { + fun `๋‹ต์— ์žˆ๋Š” ํƒ€์ผ ๊ฐœ์ˆ˜๋ณด๋‹ค ๋งŽ์œผ๋ฉด INCORRECT์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { // given val answer = Answer.of("hello") val tiles = Tiles.of("llool") @@ -126,6 +126,6 @@ internal class AnswerTest { val matches: List = answer.match(tiles) // then - assertThat(matches).containsExactly(YELLOW, YELLOW, YELLOW, GRAY, GRAY) + assertThat(matches).containsExactly(MISSING, MISSING, MISSING, INCORRECT, INCORRECT) } } diff --git a/src/test/kotlin/domain/TileTest.kt b/src/test/kotlin/domain/TileTest.kt index e22d856..115a536 100644 --- a/src/test/kotlin/domain/TileTest.kt +++ b/src/test/kotlin/domain/TileTest.kt @@ -21,7 +21,7 @@ internal class TileTest { fun `ํƒ€์ผ์€ ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค`(character: Char) { assertThatIllegalArgumentException() .isThrownBy { Tile(character) } - .withMessage("๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.") + .withMessage(Tile.ERROR_ALLOWED_CHARACTER_MSG) } @Test diff --git a/src/test/kotlin/domain/TilesTest.kt b/src/test/kotlin/domain/TilesTest.kt index d2491e4..a8f2a76 100644 --- a/src/test/kotlin/domain/TilesTest.kt +++ b/src/test/kotlin/domain/TilesTest.kt @@ -29,7 +29,7 @@ internal class TilesTest { // then assertThatIllegalArgumentException() .isThrownBy { Tiles(elements) } - .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + .withMessage(Tiles.ERROR_TILE_SIZE_MSG) } @Test @@ -48,7 +48,7 @@ internal class TilesTest { // then assertThatIllegalArgumentException() .isThrownBy { Tiles.of(words) } - .withMessage("ํƒ€์ผ์€ 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") + .withMessage(Tiles.ERROR_TILE_SIZE_MSG) } @ParameterizedTest From 44a0e0d002e16afcaace3e3abb8d01639492fd56 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 00:51:18 +0900 Subject: [PATCH 16/34] =?UTF-8?q?refact=20:=20MatchResult=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=AA=85=EC=B9=AD=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/domain/MatchResult.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/domain/MatchResult.kt b/src/main/kotlin/domain/MatchResult.kt index d1f8b83..3328fd8 100644 --- a/src/main/kotlin/domain/MatchResult.kt +++ b/src/main/kotlin/domain/MatchResult.kt @@ -4,4 +4,4 @@ enum class MatchResult { CORRECT, MISSING, INCORRECT -} \ No newline at end of file +} From 56b4cd980a4e271b693dafe8f389a34e7cb8419f Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 00:54:07 +0900 Subject: [PATCH 17/34] =?UTF-8?q?feat(MatchResults.kt)=20:=20MatchResult?= =?UTF-8?q?=20=EC=9D=BC=EA=B8=89=EC=BB=AC=EB=A0=89=EC=85=98=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/domain/Answer.kt | 4 ++-- src/main/kotlin/domain/MatchResults.kt | 3 +++ src/test/kotlin/domain/AnswerTest.kt | 24 ++++++++++++------------ 3 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/domain/MatchResults.kt diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index ced4308..727b35e 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -8,14 +8,14 @@ class Answer(val tiles: List) { require(tiles.size == REQUIRE_TILE_SIZE) { ERROR_TILE_SIZE_MSG } } - fun match(other: Tiles): List { + fun match(other: Tiles): MatchResults { val result: Array = arrayOf(INCORRECT, INCORRECT, INCORRECT, INCORRECT, INCORRECT) val countOfTile: MutableMap = tiles.groupingBy { it }.eachCount().toMutableMap() fillGreen(result, other, countOfTile) fillYellow(result, other, countOfTile) - return result.toList() + return MatchResults(result.toList()) } private fun fillGreen( diff --git a/src/main/kotlin/domain/MatchResults.kt b/src/main/kotlin/domain/MatchResults.kt new file mode 100644 index 0000000..fac0343 --- /dev/null +++ b/src/main/kotlin/domain/MatchResults.kt @@ -0,0 +1,3 @@ +package domain + +class MatchResults(val results: List) diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 3b147c2..be6fbdf 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -58,10 +58,10 @@ internal class AnswerTest { val tiles = Tiles.of("hello") // when - val matches: List = answer.match(tiles) + val matches = answer.match(tiles) // then - assertThat(matches).containsOnly(CORRECT) + assertThat(matches.results).containsOnly(CORRECT) } @Test @@ -71,10 +71,10 @@ internal class AnswerTest { val tiles = Tiles.of("olehl") // when - val matches: List = answer.match(tiles) + val matches = answer.match(tiles) // then - assertThat(matches).containsOnly(MISSING) + assertThat(matches.results).containsOnly(MISSING) } @Test @@ -84,10 +84,10 @@ internal class AnswerTest { val tiles = Tiles.of("zzzzz") // when - val matches: List = answer.match(tiles) + val matches = answer.match(tiles) // then - assertThat(matches).containsOnly(INCORRECT) + assertThat(matches.results).containsOnly(INCORRECT) } @Test @@ -97,10 +97,10 @@ internal class AnswerTest { val tiles = Tiles.of("olleh") // when - val matches: List = answer.match(tiles) + val matches = answer.match(tiles) // then - assertThat(matches).containsExactly(MISSING, MISSING, CORRECT, MISSING, MISSING) + assertThat(matches.results).containsExactly(MISSING, MISSING, CORRECT, MISSING, MISSING) } @Test @@ -110,10 +110,10 @@ internal class AnswerTest { val tiles = Tiles.of("lllll") // when - val matches: List = answer.match(tiles) + val matches = answer.match(tiles) // then - assertThat(matches).containsExactly(INCORRECT, INCORRECT, CORRECT, CORRECT, INCORRECT) + assertThat(matches.results).containsExactly(INCORRECT, INCORRECT, CORRECT, CORRECT, INCORRECT) } @Test @@ -123,9 +123,9 @@ internal class AnswerTest { val tiles = Tiles.of("llool") // when - val matches: List = answer.match(tiles) + val matches = answer.match(tiles) // then - assertThat(matches).containsExactly(MISSING, MISSING, MISSING, INCORRECT, INCORRECT) + assertThat(matches.results).containsExactly(MISSING, MISSING, MISSING, INCORRECT, INCORRECT) } } From d8b6671ff4ff1aa5373856cdcb177bbf0cd87578 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 20:36:46 +0900 Subject: [PATCH 18/34] =?UTF-8?q?feat(Game.kt)=20:=20=EA=B8=B0=ED=9A=8C?= =?UTF-8?q?=EB=8A=94=20=EC=B4=9D=206=EB=B2=88=EC=9D=B4=20=EC=9E=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- src/main/kotlin/domain/Game.kt | 16 ++++++++ src/main/kotlin/domain/Input.kt | 5 +++ src/main/kotlin/presentation/KeyboardInput.kt | 12 ++++++ src/test/kotlin/domain/GameTest.kt | 41 +++++++++++++++++++ 5 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/domain/Game.kt create mode 100644 src/main/kotlin/domain/Input.kt create mode 100644 src/main/kotlin/presentation/KeyboardInput.kt create mode 100644 src/test/kotlin/domain/GameTest.kt diff --git a/README.md b/README.md index f998047..71cc482 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,8 @@ spill - [X] ์ •๋‹ต์—๋Š” ์žˆ์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋…ธ๋ž€์ƒ‰ - [X] ์•„์˜ˆ ์—†์œผ๋ฉด ํšŒ์ƒ‰ - [X] ์ •๋‹ต์— ์žˆ๋Š” ํƒ€์ผ์€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ ์ดˆ๋ก -> ๋…ธ๋ž€์ƒ‰ -> ํšŒ์ƒ‰์ˆœ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„๋‹ค -- [ ] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - - [ ] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. +- [X] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) + - [X] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. - [ ] ๊ธฐํšŒ๋งˆ๋‹ค 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - [ ] ์ •๋‹ต์„ ์ ์œผ๋ฉด ๊ฒŒ์ž„์ด ๋๋‚œ๋‹ค. - [ ] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt new file mode 100644 index 0000000..d208d75 --- /dev/null +++ b/src/main/kotlin/domain/Game.kt @@ -0,0 +1,16 @@ +package domain + +class Game( + private val input: Input +) { + fun start() { + (BEGIN_INDEX..MAX_TRY_COUNT).forEach { index -> + val tiles = input.read() + } + } + + companion object { + const val BEGIN_INDEX = 1 + const val MAX_TRY_COUNT = 6 + } +} diff --git a/src/main/kotlin/domain/Input.kt b/src/main/kotlin/domain/Input.kt new file mode 100644 index 0000000..1430cf6 --- /dev/null +++ b/src/main/kotlin/domain/Input.kt @@ -0,0 +1,5 @@ +package domain + +interface Input { + fun read(): Tiles +} \ No newline at end of file diff --git a/src/main/kotlin/presentation/KeyboardInput.kt b/src/main/kotlin/presentation/KeyboardInput.kt new file mode 100644 index 0000000..05eea8c --- /dev/null +++ b/src/main/kotlin/presentation/KeyboardInput.kt @@ -0,0 +1,12 @@ +package presentation + +import domain.Input +import domain.Tiles + +class KeyboardInput: Input { + override fun read(): Tiles { + val readLine = System.`in`.bufferedReader().readLine() + + return Tiles.of(readLine) + } +} \ No newline at end of file diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt new file mode 100644 index 0000000..8a4cbfa --- /dev/null +++ b/src/test/kotlin/domain/GameTest.kt @@ -0,0 +1,41 @@ +package domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import java.util.* + +class GameTest { + @Test + fun `๊ฒŒ์ž„์€ 6๋ฒˆ์„ ์ž…๋ ฅํ•  ๊ธฐํšŒ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค`() { + // given + val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello"))) + val game = Game(input) + + // when + game.start() + + // then + assertThat(input.result).isEmpty() + } + + @Test + fun `๊ฒŒ์ž„์€ 7๋ฒˆ ์ด์ƒ ์ž…๋ ฅ์‹œ 6๋ฒˆ๋งŒ ์ž…๋ ฅ ๋œ๋‹ค`() { + // given + val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello", "hello"))) + val game = Game(input) + + // when + game.start() + + // then + assertThat(input.result).hasSize(1) + } +} + +class TestInput(val result: Queue): Input { + override fun read(): Tiles { + return Tiles.of(result.poll()) + } +} \ No newline at end of file From d0ffc16058dbd9882c19f463cd0314822b046cbf Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 21:04:11 +0900 Subject: [PATCH 19/34] =?UTF-8?q?feat(Game.kt)=20:=20=EC=A0=95=EB=8B=B5?= =?UTF-8?q?=EC=9D=84=20=EC=A0=81=EC=9C=BC=EB=A9=B4=20=EA=B2=8C=EC=9E=84?= =?UTF-8?q?=EC=9D=B4=20=EB=81=9D=EB=82=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- src/main/kotlin/domain/Game.kt | 13 +++++- src/main/kotlin/domain/MatchResults.kt | 13 +++++- src/main/kotlin/domain/Tiles.kt | 2 +- src/main/kotlin/domain/WordsRepository.kt | 7 +++ src/test/kotlin/domain/GameTest.kt | 52 ++++++++++++++++++---- src/test/kotlin/domain/MatchResultsTest.kt | 52 ++++++++++++++++++++++ 7 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/domain/WordsRepository.kt create mode 100644 src/test/kotlin/domain/MatchResultsTest.kt diff --git a/README.md b/README.md index 71cc482..b520bfa 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,8 @@ spill - [X] ์ •๋‹ต์— ์žˆ๋Š” ํƒ€์ผ์€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ ์ดˆ๋ก -> ๋…ธ๋ž€์ƒ‰ -> ํšŒ์ƒ‰์ˆœ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„๋‹ค - [X] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - [X] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. - - [ ] ๊ธฐํšŒ๋งˆ๋‹ค 5๊ธ€์ž์˜ ๋ฌธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. - - [ ] ์ •๋‹ต์„ ์ ์œผ๋ฉด ๊ฒŒ์ž„์ด ๋๋‚œ๋‹ค. + - [X] ์ •๋‹ต์„ ์ ์œผ๋ฉด ๊ฒŒ์ž„์ด ๋๋‚œ๋‹ค. - [ ] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. - [ ] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. - [ ] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. - - [ ] ์•ŒํŒŒ๋ฒณ๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index d208d75..3d7fe17 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -1,11 +1,22 @@ package domain class Game( - private val input: Input + private val input: Input, + private val wordsRepository: WordsRepository ) { fun start() { + val answer = Answer(wordsRepository.getTodayWords()) + (BEGIN_INDEX..MAX_TRY_COUNT).forEach { index -> val tiles = input.read() + + if (wordsRepository.exists(tiles)) { + val match = answer.match(tiles) + + if (match.isCorrect()) { + return + } + } } } diff --git a/src/main/kotlin/domain/MatchResults.kt b/src/main/kotlin/domain/MatchResults.kt index fac0343..7db46a0 100644 --- a/src/main/kotlin/domain/MatchResults.kt +++ b/src/main/kotlin/domain/MatchResults.kt @@ -1,3 +1,14 @@ package domain -class MatchResults(val results: List) +class MatchResults(val results: List) { + init { + require(results.size == REQUIRE_RESULTS_SIZE) { ERROR_RESULTS_SIZE_MSG } + } + + fun isCorrect(): Boolean = results.all { it == MatchResult.CORRECT } + + companion object { + const val ERROR_RESULTS_SIZE_MSG = "๊ฒฐ๊ณผ๋Š” 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." + const val REQUIRE_RESULTS_SIZE = 5 + } +} \ No newline at end of file diff --git a/src/main/kotlin/domain/Tiles.kt b/src/main/kotlin/domain/Tiles.kt index 8305191..d2a2cbe 100644 --- a/src/main/kotlin/domain/Tiles.kt +++ b/src/main/kotlin/domain/Tiles.kt @@ -1,6 +1,6 @@ package domain -class Tiles(val tiles: List) : List by tiles { +data class Tiles(val tiles: List) : List by tiles { init { require(tiles.size == REQUIRE_TILE_SIZE) { ERROR_TILE_SIZE_MSG } } diff --git a/src/main/kotlin/domain/WordsRepository.kt b/src/main/kotlin/domain/WordsRepository.kt new file mode 100644 index 0000000..1308d29 --- /dev/null +++ b/src/main/kotlin/domain/WordsRepository.kt @@ -0,0 +1,7 @@ +package domain + +interface WordsRepository { + fun exists(tiles: Tiles): Boolean + + fun getTodayWords(): List +} \ No newline at end of file diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index 8a4cbfa..44d73c8 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -2,29 +2,49 @@ package domain import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test - -import org.junit.jupiter.api.Assertions.* import java.util.* class GameTest { @Test - fun `๊ฒŒ์ž„์€ 6๋ฒˆ์„ ์ž…๋ ฅํ•  ๊ธฐํšŒ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค`() { + fun `๋‹ต์•ˆ์— ์ •๋‹ต์ด ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋œ๋‹ค`() { // given + val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello"))) - val game = Game(input) + val repository = TestWordsRepository(answer, setOf(Tiles(answer))) + val game = Game(input, repository) + + // when + game.start() + + // then + assertThat(repository.calledTodayWords).isTrue + assertThat(input.result).hasSize(5) + assertThat(repository.tilesStack).contains(Tiles(answer)) + } + + @Test + fun `๋‹ต์„ ๋ชป๋งž์ถœ ๊ฒฝ์šฐ ์ตœ๋Œ€ 6๋ฒˆ์„ ์ž…๋ ฅํ•  ๊ธฐํšŒ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค`() { + // given + val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) + val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) + val game = Game(input, repository) // when game.start() // then assertThat(input.result).isEmpty() + assertThat(repository.calledTodayWords).isTrue } @Test fun `๊ฒŒ์ž„์€ 7๋ฒˆ ์ด์ƒ ์ž…๋ ฅ์‹œ 6๋ฒˆ๋งŒ ์ž…๋ ฅ ๋œ๋‹ค`() { // given - val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello", "hello"))) - val game = Game(input) + val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) + val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) + val game = Game(input, repository) // when game.start() @@ -34,8 +54,24 @@ class GameTest { } } -class TestInput(val result: Queue): Input { +class TestInput(val result: Queue) : Input { override fun read(): Tiles { return Tiles.of(result.poll()) } -} \ No newline at end of file +} + +class TestWordsRepository(val answer: List, val words: Set) : WordsRepository { + var tilesStack = mutableListOf() + var calledTodayWords = false + + override fun exists(tiles: Tiles): Boolean { + tilesStack.add(tiles) + + return words.contains(tiles) + } + + override fun getTodayWords(): List { + calledTodayWords = true + return answer + } +} diff --git a/src/test/kotlin/domain/MatchResultsTest.kt b/src/test/kotlin/domain/MatchResultsTest.kt new file mode 100644 index 0000000..a0772ab --- /dev/null +++ b/src/test/kotlin/domain/MatchResultsTest.kt @@ -0,0 +1,52 @@ +package domain + +import org.junit.jupiter.api.Test +import domain.MatchResult.* +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatIllegalArgumentException +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource +import org.junit.jupiter.params.provider.ValueSource + +internal class MatchResultsTest { + @Test + fun `5๊ฐœ์˜ ๊ฒฐ๊ณผ๋กœ ์ด๋ค„์ง„๋‹ค`() { + // given + val matchResult = listOf(CORRECT, CORRECT, CORRECT, CORRECT, CORRECT) + val result = MatchResults(matchResult) + + // then + assertThat(result.results).containsExactlyElementsOf(matchResult) + } + + @ParameterizedTest + @ValueSource(ints = [0,1,2,3,4,6,7,8]) + fun `5๊ฐœ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹ˆ๋ฉด ์‹คํŒจํ•œ๋‹ค`(size: Int) { + // given + val matchResult = (0 until size).map { CORRECT } + + // then + assertThatIllegalArgumentException().isThrownBy { + MatchResults(matchResult) + }.withMessage(MatchResults.ERROR_RESULTS_SIZE_MSG) + } + + @Test + fun `๋ชจ๋“  MatchResult๊ฐ€ ์„ฑ๊ณต์ด๋ฉด MatchResults๋„ ์„ฑ๊ณต์ด๋‹ค`() { + // given + val result = MatchResults(listOf(CORRECT, CORRECT, CORRECT, CORRECT, CORRECT)) + + // then + assertThat(result.isCorrect()).isTrue + } + + @ParameterizedTest + @EnumSource(value = MatchResult::class, names = ["MISSING", "INCORRECT"]) + fun `๋ชจ๋“  MatchResult๊ฐ€ ์„ฑ๊ณต์ด ์•„๋‹ˆ๋ฉด MatchResults๋Š” ์„ฑ๊ณต์ด ์•„๋‹ˆ๋‹ค`(result: MatchResult) { + // given + val result = MatchResults(listOf(CORRECT, CORRECT, CORRECT, CORRECT, result)) + + // then + assertThat(result.isCorrect()).isFalse + } +} \ No newline at end of file From f4d6b6103520f9b67caf360aa74f355b591e54b6 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 21:33:25 +0900 Subject: [PATCH 20/34] =?UTF-8?q?feat(Game.kt)=20:=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=84=EB=8B=AC=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++++++--- src/main/kotlin/domain/Game.kt | 3 +++ src/main/kotlin/domain/MatchResults.kt | 2 +- src/main/kotlin/domain/Output.kt | 5 ++++ src/test/kotlin/domain/GameTest.kt | 32 ++++++++++++++++++++++---- 5 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/domain/Output.kt diff --git a/README.md b/README.md index b520bfa..5f3d1c3 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,15 @@ spill - [X] ์•„์˜ˆ ์—†์œผ๋ฉด ํšŒ์ƒ‰ - [X] ์ •๋‹ต์— ์žˆ๋Š” ํƒ€์ผ์€ n๊ฐœ์ด์ง€๋งŒ, ์ž…๋ ฅํ•œ ํƒ€์ผ์€ n + 1๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ ์ดˆ๋ก -> ๋…ธ๋ž€์ƒ‰ -> ํšŒ์ƒ‰์ˆœ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„๋‹ค - [X] ๊ฒŒ์ž„์ด ์žˆ๋‹ค => (Game) - - [X] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์ด ์žˆ๋‹ค. + - [X] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค. - [X] ์ •๋‹ต์„ ์ ์œผ๋ฉด ๊ฒŒ์ž„์ด ๋๋‚œ๋‹ค. + - [X] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ ์ •๋‹ต ์ €์žฅ์†Œ์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. + - [X] ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. + +### PRESENTATION +- [ ] DefaultOutput - [ ] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. - - [ ] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. - - [ ] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. +- [ ] DefaultWordsRepository + - [ ] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. + - [ ] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. \ No newline at end of file diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index 3d7fe17..56b06a7 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -2,6 +2,7 @@ package domain class Game( private val input: Input, + private val output: Output, private val wordsRepository: WordsRepository ) { fun start() { @@ -13,6 +14,8 @@ class Game( if (wordsRepository.exists(tiles)) { val match = answer.match(tiles) + output.write(match) + if (match.isCorrect()) { return } diff --git a/src/main/kotlin/domain/MatchResults.kt b/src/main/kotlin/domain/MatchResults.kt index 7db46a0..636205a 100644 --- a/src/main/kotlin/domain/MatchResults.kt +++ b/src/main/kotlin/domain/MatchResults.kt @@ -1,6 +1,6 @@ package domain -class MatchResults(val results: List) { +data class MatchResults(val results: List) { init { require(results.size == REQUIRE_RESULTS_SIZE) { ERROR_RESULTS_SIZE_MSG } } diff --git a/src/main/kotlin/domain/Output.kt b/src/main/kotlin/domain/Output.kt new file mode 100644 index 0000000..f8a0cf6 --- /dev/null +++ b/src/main/kotlin/domain/Output.kt @@ -0,0 +1,5 @@ +package domain + +interface Output { + fun write(matchResults: MatchResults) +} \ No newline at end of file diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index 44d73c8..09317be 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -1,5 +1,7 @@ package domain +import domain.MatchResult.INCORRECT +import domain.MatchResult.MISSING import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import java.util.* @@ -10,16 +12,19 @@ class GameTest { // given val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello"))) + val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer))) - val game = Game(input, repository) + val game = Game(input, output, repository) // when game.start() // then assertThat(repository.calledTodayWords).isTrue - assertThat(input.result).hasSize(5) assertThat(repository.tilesStack).contains(Tiles(answer)) + assertThat(input.result).hasSize(5) + assertThat(output.resultsStack).hasSize(1) + assertThat(output.resultsStack[0].isCorrect()).isTrue } @Test @@ -27,8 +32,9 @@ class GameTest { // given val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) + val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) - val game = Game(input, repository) + val game = Game(input, output, repository) // when game.start() @@ -36,6 +42,9 @@ class GameTest { // then assertThat(input.result).isEmpty() assertThat(repository.calledTodayWords).isTrue + assertThat(output.resultsStack).hasSize(6) + assertThat(output.resultsStack) + .containsOnly(MatchResults(listOf(INCORRECT, INCORRECT, INCORRECT, INCORRECT, MISSING))) } @Test @@ -43,14 +52,19 @@ class GameTest { // given val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) + val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) - val game = Game(input, repository) + val game = Game(input, output, repository) // when game.start() // then assertThat(input.result).hasSize(1) + assertThat(output.resultsStack).hasSize(6) + assertThat(output.resultsStack) + .flatMap({it.isCorrect()}) + .containsExactly(false, false, false, false, false, false) } } @@ -60,6 +74,14 @@ class TestInput(val result: Queue) : Input { } } +class TestOutput : Output { + val resultsStack = mutableListOf() + + override fun write(matchResults: MatchResults) { + resultsStack.add(matchResults) + } +} + class TestWordsRepository(val answer: List, val words: Set) : WordsRepository { var tilesStack = mutableListOf() var calledTodayWords = false @@ -74,4 +96,4 @@ class TestWordsRepository(val answer: List, val words: Set) : Words calledTodayWords = true return answer } -} +} \ No newline at end of file From 08ee075cdda11d66f25dfd5e67dc46a3f95b9d17 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Wed, 13 Apr 2022 21:38:49 +0900 Subject: [PATCH 21/34] =?UTF-8?q?feat(Game.kt)=20:=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=8B=A8=EC=96=B4?= =?UTF-8?q?=EC=9D=B4=EB=A9=B4=20=EC=9E=AC=EC=9E=85=EB=A0=A5=EC=9D=84=20?= =?UTF-8?q?=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/kotlin/domain/Game.kt | 4 +++- src/test/kotlin/domain/GameTest.kt | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f3d1c3..2f656f1 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ spill - [X] ๊ธฐํšŒ๋Š” ์ด 6๋ฒˆ์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค. - [X] ์ •๋‹ต์„ ์ ์œผ๋ฉด ๊ฒŒ์ž„์ด ๋๋‚œ๋‹ค. - [X] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ ์ •๋‹ต ์ €์žฅ์†Œ์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. + - [X] ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด์ด๋ฉด ์žฌ์ž…๋ ฅ์„ ํ•œ๋‹ค. - [X] ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ### PRESENTATION diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index 56b06a7..e5c238d 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -7,14 +7,16 @@ class Game( ) { fun start() { val answer = Answer(wordsRepository.getTodayWords()) + var inputCount = 0 - (BEGIN_INDEX..MAX_TRY_COUNT).forEach { index -> + while (inputCount < MAX_TRY_COUNT) { val tiles = input.read() if (wordsRepository.exists(tiles)) { val match = answer.match(tiles) output.write(match) + inputCount++ if (match.isCorrect()) { return diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index 09317be..ea08af8 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -66,6 +66,23 @@ class GameTest { .flatMap({it.isCorrect()}) .containsExactly(false, false, false, false, false, false) } + + @Test + fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์žฌ์ž…๋ ฅ ๊ธฐํšŒ๋ฅผ ์ค€๋‹ค`() { + // given + val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "hello"))) + val output = TestOutput() + val repository = TestWordsRepository(answer, setOf(Tiles(answer))) + val game = Game(input, output, repository) + + // when + game.start() + + // then + assertThat(input.result).hasSize(0) + assertThat(output.resultsStack).hasSize(1) + } } class TestInput(val result: Queue) : Input { From f775ac77e2be68060f8de51a8fc6bd9c493de3f6 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Thu, 14 Apr 2022 20:06:42 +0900 Subject: [PATCH 22/34] =?UTF-8?q?feat(Game.kt)=20:=20=EC=A0=95=EB=8B=B5?= =?UTF-8?q?=EA=B3=BC=20=EB=8B=B5=EC=95=88=EC=9D=80=20words.txt=20=EC=97=90?= =?UTF-8?q?=20=EC=9E=88=EA=B3=A0,=20=EB=82=A0=EC=A7=9C=EA=B0=80=20?= =?UTF-8?q?=EB=B0=94=EB=80=94=20=EB=95=8C=20=EB=A7=88=EB=8B=A4=20=EB=8B=B5?= =?UTF-8?q?=EC=9D=B4=20=EB=B0=94=EB=80=90=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++-- src/main/kotlin/Application.kt | 9 ++++++ src/main/kotlin/domain/Game.kt | 1 - .../presentation/DefaultWordsRepository.kt | 31 +++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/Application.kt create mode 100644 src/main/kotlin/presentation/DefaultWordsRepository.kt diff --git a/README.md b/README.md index 2f656f1..69009d9 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,6 @@ spill - [ ] DefaultOutput - [ ] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. -- [ ] DefaultWordsRepository - - [ ] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. - - [ ] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. \ No newline at end of file +- [X] DefaultWordsRepository + - [X] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. + - [X] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. \ No newline at end of file diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt new file mode 100644 index 0000000..4cb96a4 --- /dev/null +++ b/src/main/kotlin/Application.kt @@ -0,0 +1,9 @@ +import domain.Tiles +import presentation.DefaultWordsRepository + +fun main() { + val repository = DefaultWordsRepository() + + println(repository.getTodayWords()) + println(repository.exists(Tiles.of("royal"))) +} \ No newline at end of file diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index e5c238d..444e65e 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -26,7 +26,6 @@ class Game( } companion object { - const val BEGIN_INDEX = 1 const val MAX_TRY_COUNT = 6 } } diff --git a/src/main/kotlin/presentation/DefaultWordsRepository.kt b/src/main/kotlin/presentation/DefaultWordsRepository.kt new file mode 100644 index 0000000..b97091f --- /dev/null +++ b/src/main/kotlin/presentation/DefaultWordsRepository.kt @@ -0,0 +1,31 @@ +package presentation + +import domain.Tile +import domain.Tiles +import domain.WordsRepository +import java.time.LocalDate + +class DefaultWordsRepository: WordsRepository { + private val words: Set + private val today: List + + init { + val now = LocalDate.now() + val standard = LocalDate.of(2021, 6, 19) + + val values: List = this.javaClass.classLoader.getResourceAsStream("words.txt").bufferedReader().readLines() + + val daysFromStandard = (now.toEpochDay() - standard.toEpochDay()).toInt() + + this.words = values.map { Tiles.of(it) }.toSet() + this.today = Tiles.of(values[daysFromStandard % this.words.size]).tiles + } + + override fun exists(tiles: Tiles): Boolean { + return words.contains(tiles) + } + + override fun getTodayWords(): List { + return today + } +} From 8271db1228acbb49213cf2400cf4e083e5f80a04 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Thu, 14 Apr 2022 20:23:52 +0900 Subject: [PATCH 23/34] =?UTF-8?q?feat(DefaultOutput.kt)=20:=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=95=84=EC=9B=83=ED=92=8B=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +-- src/main/kotlin/Application.kt | 13 ++++-- .../DefaultWordsRepository.kt | 2 +- src/main/kotlin/presentation/DefaultInput.kt | 19 +++++++++ src/main/kotlin/presentation/DefaultOutput.kt | 41 +++++++++++++++++++ src/main/kotlin/presentation/KeyboardInput.kt | 12 ------ 6 files changed, 73 insertions(+), 20 deletions(-) rename src/main/kotlin/{presentation => infra}/DefaultWordsRepository.kt (97%) create mode 100644 src/main/kotlin/presentation/DefaultInput.kt create mode 100644 src/main/kotlin/presentation/DefaultOutput.kt delete mode 100644 src/main/kotlin/presentation/KeyboardInput.kt diff --git a/README.md b/README.md index 69009d9..da277b7 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,9 @@ spill - [X] ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ### PRESENTATION -- [ ] DefaultOutput - - [ ] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. - - [ ] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. +- [X] DefaultOutput + - [X] ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ๊ณผ๊ฑฐ์— ์žˆ๋˜ ๊ฒฐ๊ณผ๋„ ๊ฐ™์ด ํ‘œ์ถœ๋œ๋‹ค. + - [X] ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅํ•œ Tiles๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. - [X] DefaultWordsRepository - [X] ์ •๋‹ต๊ณผ ๋‹ต์•ˆ์€ `words.txt`์— ์กด์žฌํ•˜๋Š” ๋‹จ์–ด์—ฌ์•ผ ํ•œ๋‹ค. - [X] ์ •๋‹ต์€ ๋งค์ผ ๋ฐ”๋€Œ๋ฉฐ ((ํ˜„์žฌ ๋‚ ์งœ - 2021๋…„ 6์›” 19์ผ) % ๋ฐฐ์—ด์˜ ํฌ๊ธฐ) ๋ฒˆ์งธ์˜ ๋‹จ์–ด์ด๋‹ค. \ No newline at end of file diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt index 4cb96a4..6a35ef2 100644 --- a/src/main/kotlin/Application.kt +++ b/src/main/kotlin/Application.kt @@ -1,9 +1,14 @@ -import domain.Tiles -import presentation.DefaultWordsRepository +import domain.Game +import infra.DefaultWordsRepository +import presentation.DefaultInput +import presentation.DefaultOutput fun main() { + val input = DefaultInput() + val output = DefaultOutput() val repository = DefaultWordsRepository() - println(repository.getTodayWords()) - println(repository.exists(Tiles.of("royal"))) + val game = Game(input, output, repository) + + game.start() } \ No newline at end of file diff --git a/src/main/kotlin/presentation/DefaultWordsRepository.kt b/src/main/kotlin/infra/DefaultWordsRepository.kt similarity index 97% rename from src/main/kotlin/presentation/DefaultWordsRepository.kt rename to src/main/kotlin/infra/DefaultWordsRepository.kt index b97091f..fca67ee 100644 --- a/src/main/kotlin/presentation/DefaultWordsRepository.kt +++ b/src/main/kotlin/infra/DefaultWordsRepository.kt @@ -1,4 +1,4 @@ -package presentation +package infra import domain.Tile import domain.Tiles diff --git a/src/main/kotlin/presentation/DefaultInput.kt b/src/main/kotlin/presentation/DefaultInput.kt new file mode 100644 index 0000000..86303b3 --- /dev/null +++ b/src/main/kotlin/presentation/DefaultInput.kt @@ -0,0 +1,19 @@ +package presentation + +import domain.Input +import domain.Tiles + +class DefaultInput : Input { + override fun read(): Tiles { + var text = "" + + do { + println("์ •๋‹ต์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.") + + text = System.`in`.bufferedReader().readLine() + + } while (text.length != 5) + + return Tiles.of(text) + } +} \ No newline at end of file diff --git a/src/main/kotlin/presentation/DefaultOutput.kt b/src/main/kotlin/presentation/DefaultOutput.kt new file mode 100644 index 0000000..489dd32 --- /dev/null +++ b/src/main/kotlin/presentation/DefaultOutput.kt @@ -0,0 +1,41 @@ +package presentation + +import domain.Game +import domain.MatchResult +import domain.MatchResults +import domain.Output + +class DefaultOutput : Output { + private val allResults: MutableList = mutableListOf() + + override fun write(matchResults: MatchResults) { + allResults.add(matchResults) + + if (matchResults.isCorrect()) { + println("${allResults.size}/${Game.MAX_TRY_COUNT}") + } + + printAll() + } + + private fun printAll() { + allResults.forEach { + printLine(it) + } + } + + private fun printLine(matchResults: MatchResults) { + println( + matchResults.results.joinToString("") { + blockOf(it) + } + ) + } + + + private fun blockOf(matchResult: MatchResult): String = when (matchResult) { + MatchResult.CORRECT -> "\uD83D\uDFE9" + MatchResult.MISSING -> "\uD83D\uDFE8" + else -> "โฌœ" + } +} \ No newline at end of file diff --git a/src/main/kotlin/presentation/KeyboardInput.kt b/src/main/kotlin/presentation/KeyboardInput.kt deleted file mode 100644 index 05eea8c..0000000 --- a/src/main/kotlin/presentation/KeyboardInput.kt +++ /dev/null @@ -1,12 +0,0 @@ -package presentation - -import domain.Input -import domain.Tiles - -class KeyboardInput: Input { - override fun read(): Tiles { - val readLine = System.`in`.bufferedReader().readLine() - - return Tiles.of(readLine) - } -} \ No newline at end of file From 5f72da95607e1d2bbb7144f9b26f1016f0e84870 Mon Sep 17 00:00:00 2001 From: ohgillwhan Date: Thu, 14 Apr 2022 21:11:34 +0900 Subject: [PATCH 24/34] =?UTF-8?q?refact(ALL)=20:=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EC=A0=81=EC=9D=B8=20=EB=A6=B0=ED=8A=B8=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/Application.kt | 2 +- src/main/kotlin/domain/Answer.kt | 51 ++++++++++++------- src/main/kotlin/domain/Game.kt | 20 ++++---- src/main/kotlin/domain/Input.kt | 2 +- src/main/kotlin/domain/MatchResults.kt | 2 +- src/main/kotlin/domain/Output.kt | 2 +- src/main/kotlin/domain/WordsRepository.kt | 4 +- .../kotlin/infra/DefaultWordsRepository.kt | 11 ++-- src/main/kotlin/presentation/DefaultInput.kt | 27 +++++++--- src/main/kotlin/presentation/DefaultOutput.kt | 9 ++-- src/test/kotlin/domain/AnswerTest.kt | 14 +---- src/test/kotlin/domain/GameTest.kt | 16 +++--- src/test/kotlin/domain/MatchResultsTest.kt | 6 +-- src/test/kotlin/domain/TilesTest.kt | 12 +++-- 14 files changed, 100 insertions(+), 78 deletions(-) diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt index 6a35ef2..5a0f09d 100644 --- a/src/main/kotlin/Application.kt +++ b/src/main/kotlin/Application.kt @@ -11,4 +11,4 @@ fun main() { val game = Game(input, output, repository) game.start() -} \ No newline at end of file +} diff --git a/src/main/kotlin/domain/Answer.kt b/src/main/kotlin/domain/Answer.kt index 727b35e..0fe558b 100644 --- a/src/main/kotlin/domain/Answer.kt +++ b/src/main/kotlin/domain/Answer.kt @@ -3,7 +3,7 @@ package domain import domain.MatchResult.INCORRECT import domain.MatchResult.MISSING -class Answer(val tiles: List) { +class Answer(val tiles: Tiles) { init { require(tiles.size == REQUIRE_TILE_SIZE) { ERROR_TILE_SIZE_MSG } } @@ -12,39 +12,56 @@ class Answer(val tiles: List) { val result: Array = arrayOf(INCORRECT, INCORRECT, INCORRECT, INCORRECT, INCORRECT) val countOfTile: MutableMap = tiles.groupingBy { it }.eachCount().toMutableMap() - fillGreen(result, other, countOfTile) - fillYellow(result, other, countOfTile) + fillGreens(result, other, countOfTile) + fillYellows(result, other, countOfTile) return MatchResults(result.toList()) } - private fun fillGreen( + private fun fillGreens( result: Array, other: Tiles, countOfTile: MutableMap ) { - this.tiles.mapIndexed { index, tile -> - if (other.equals(tile, index)) { - result[index] = MatchResult.CORRECT + other.mapIndexed { index, tile -> + fillGreen(tile, index, result, countOfTile) + } + } + private fun fillYellows( + result: Array, + other: Tiles, + countOfTile: MutableMap + ) { + other.mapIndexed { index, tile -> + fillYellow(tile, index, result, countOfTile) + } + } + + private fun fillGreen( + tile: Tile, + index: Int, + result: Array, + countOfTile: MutableMap + ) { + if (this.tiles.equals(tile, index)) { + result[index] = MatchResult.CORRECT - countOfTile[tile] = countOfTile[tile]!!.dec() - } + countOfTile[tile] = countOfTile[tile]!!.dec() } } private fun fillYellow( + tile: Tile, + index: Int, result: Array, - other: Tiles, countOfTile: MutableMap ) { - other.mapIndexed { index, tile -> - val count = countOfTile[tile] ?: EMPTY + val count = countOfTile[tile] ?: EMPTY - if (result[index] == INCORRECT && count > EMPTY) { - result[index] = MISSING + if (result[index] == INCORRECT && count > EMPTY) { + result[index] = MISSING - countOfTile[tile] = count.dec() - } + countOfTile[tile] = count.dec() } } @@ -53,6 +70,6 @@ class Answer(val tiles: List) { const val REQUIRE_TILE_SIZE = 5 const val EMPTY = 0 - fun of(words: String): Answer = Answer(words.map { Tile(it) }) + fun of(words: String): Answer = Answer(Tiles.of(words)) } } diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index 444e65e..6ca8366 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -7,20 +7,22 @@ class Game( ) { fun start() { val answer = Answer(wordsRepository.getTodayWords()) - var inputCount = 0 + var tryCount = 0 - while (inputCount < MAX_TRY_COUNT) { + while (tryCount < MAX_TRY_COUNT) { val tiles = input.read() - if (wordsRepository.exists(tiles)) { - val match = answer.match(tiles) + if (!wordsRepository.exists(tiles)) { + continue + } + + val match = answer.match(tiles) - output.write(match) - inputCount++ + output.write(match) + tryCount++ - if (match.isCorrect()) { - return - } + if (match.isCorrect()) { + return } } } diff --git a/src/main/kotlin/domain/Input.kt b/src/main/kotlin/domain/Input.kt index 1430cf6..d00b155 100644 --- a/src/main/kotlin/domain/Input.kt +++ b/src/main/kotlin/domain/Input.kt @@ -2,4 +2,4 @@ package domain interface Input { fun read(): Tiles -} \ No newline at end of file +} diff --git a/src/main/kotlin/domain/MatchResults.kt b/src/main/kotlin/domain/MatchResults.kt index 636205a..45d0470 100644 --- a/src/main/kotlin/domain/MatchResults.kt +++ b/src/main/kotlin/domain/MatchResults.kt @@ -11,4 +11,4 @@ data class MatchResults(val results: List) { const val ERROR_RESULTS_SIZE_MSG = "๊ฒฐ๊ณผ๋Š” 5๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." const val REQUIRE_RESULTS_SIZE = 5 } -} \ No newline at end of file +} diff --git a/src/main/kotlin/domain/Output.kt b/src/main/kotlin/domain/Output.kt index f8a0cf6..f216608 100644 --- a/src/main/kotlin/domain/Output.kt +++ b/src/main/kotlin/domain/Output.kt @@ -2,4 +2,4 @@ package domain interface Output { fun write(matchResults: MatchResults) -} \ No newline at end of file +} diff --git a/src/main/kotlin/domain/WordsRepository.kt b/src/main/kotlin/domain/WordsRepository.kt index 1308d29..0e135a4 100644 --- a/src/main/kotlin/domain/WordsRepository.kt +++ b/src/main/kotlin/domain/WordsRepository.kt @@ -3,5 +3,5 @@ package domain interface WordsRepository { fun exists(tiles: Tiles): Boolean - fun getTodayWords(): List -} \ No newline at end of file + fun getTodayWords(): Tiles +} diff --git a/src/main/kotlin/infra/DefaultWordsRepository.kt b/src/main/kotlin/infra/DefaultWordsRepository.kt index fca67ee..509a06e 100644 --- a/src/main/kotlin/infra/DefaultWordsRepository.kt +++ b/src/main/kotlin/infra/DefaultWordsRepository.kt @@ -1,31 +1,30 @@ package infra -import domain.Tile import domain.Tiles import domain.WordsRepository import java.time.LocalDate -class DefaultWordsRepository: WordsRepository { +class DefaultWordsRepository : WordsRepository { private val words: Set - private val today: List + private val today: Tiles init { val now = LocalDate.now() val standard = LocalDate.of(2021, 6, 19) - + val values: List = this.javaClass.classLoader.getResourceAsStream("words.txt").bufferedReader().readLines() val daysFromStandard = (now.toEpochDay() - standard.toEpochDay()).toInt() this.words = values.map { Tiles.of(it) }.toSet() - this.today = Tiles.of(values[daysFromStandard % this.words.size]).tiles + this.today = Tiles.of(values[daysFromStandard % this.words.size]) } override fun exists(tiles: Tiles): Boolean { return words.contains(tiles) } - override fun getTodayWords(): List { + override fun getTodayWords(): Tiles { return today } } diff --git a/src/main/kotlin/presentation/DefaultInput.kt b/src/main/kotlin/presentation/DefaultInput.kt index 86303b3..ed11e88 100644 --- a/src/main/kotlin/presentation/DefaultInput.kt +++ b/src/main/kotlin/presentation/DefaultInput.kt @@ -4,16 +4,27 @@ import domain.Input import domain.Tiles class DefaultInput : Input { - override fun read(): Tiles { - var text = "" + override tailrec fun read(): Tiles { + val tiles = nextTiles() - do { - println("์ •๋‹ต์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.") + return tiles ?: read() + } + + private fun nextTiles(): Tiles? { + try { + println(INPUT_MESSAGE) - text = System.`in`.bufferedReader().readLine() + val text = System.`in`.bufferedReader().readLine() - } while (text.length != 5) + return Tiles.of(text) + } catch (e: Exception) { + println(e.message) + } + + return null + } - return Tiles.of(text) + companion object { + private const val INPUT_MESSAGE = "์ •๋‹ต์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." } -} \ No newline at end of file +} diff --git a/src/main/kotlin/presentation/DefaultOutput.kt b/src/main/kotlin/presentation/DefaultOutput.kt index 489dd32..0a1a03a 100644 --- a/src/main/kotlin/presentation/DefaultOutput.kt +++ b/src/main/kotlin/presentation/DefaultOutput.kt @@ -26,16 +26,19 @@ class DefaultOutput : Output { private fun printLine(matchResults: MatchResults) { println( - matchResults.results.joinToString("") { + matchResults.results.joinToString(BLANK) { blockOf(it) } ) } - private fun blockOf(matchResult: MatchResult): String = when (matchResult) { MatchResult.CORRECT -> "\uD83D\uDFE9" MatchResult.MISSING -> "\uD83D\uDFE8" else -> "โฌœ" } -} \ No newline at end of file + + companion object { + private const val BLANK = "" + } +} diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index be6fbdf..98a597c 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -11,7 +11,7 @@ internal class AnswerTest { @Test fun `Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค`() { // given - val elements = listOf(Tile('a'), Tile('b'), Tile('c'), Tile('d'), Tile('e')) + val elements = Tiles.of("hello") // when val answer = Answer(elements) @@ -20,18 +20,6 @@ internal class AnswerTest { assertThat(answer.tiles).containsExactlyElementsOf(elements) } - @ParameterizedTest - @ValueSource(ints = [0, 1, 2, 3, 4, 6, 10]) - fun `Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(size: Int) { - // given - val elements: List = (0 until size).map { Tile('a') } - - // then - Assertions.assertThatIllegalArgumentException() - .isThrownBy { Answer(elements) } - .withMessage(Answer.ERROR_TILE_SIZE_MSG) - } - @Test fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค`() { // given diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index ea08af8..1d08f19 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -10,7 +10,7 @@ class GameTest { @Test fun `๋‹ต์•ˆ์— ์ •๋‹ต์ด ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋œ๋‹ค`() { // given - val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val answer = Tiles.of("hello") val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello"))) val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer))) @@ -30,7 +30,7 @@ class GameTest { @Test fun `๋‹ต์„ ๋ชป๋งž์ถœ ๊ฒฝ์šฐ ์ตœ๋Œ€ 6๋ฒˆ์„ ์ž…๋ ฅํ•  ๊ธฐํšŒ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค`() { // given - val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val answer = Tiles.of("hello") val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) @@ -50,7 +50,7 @@ class GameTest { @Test fun `๊ฒŒ์ž„์€ 7๋ฒˆ ์ด์ƒ ์ž…๋ ฅ์‹œ 6๋ฒˆ๋งŒ ์ž…๋ ฅ ๋œ๋‹ค`() { // given - val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val answer = Tiles.of("hello") val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) @@ -63,14 +63,14 @@ class GameTest { assertThat(input.result).hasSize(1) assertThat(output.resultsStack).hasSize(6) assertThat(output.resultsStack) - .flatMap({it.isCorrect()}) + .flatMap({ it.isCorrect() }) .containsExactly(false, false, false, false, false, false) } @Test fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์žฌ์ž…๋ ฅ ๊ธฐํšŒ๋ฅผ ์ค€๋‹ค`() { // given - val answer = listOf(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) + val answer = Tiles.of("hello") val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "hello"))) val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer))) @@ -99,7 +99,7 @@ class TestOutput : Output { } } -class TestWordsRepository(val answer: List, val words: Set) : WordsRepository { +class TestWordsRepository(val answer: Tiles, val words: Set) : WordsRepository { var tilesStack = mutableListOf() var calledTodayWords = false @@ -109,8 +109,8 @@ class TestWordsRepository(val answer: List, val words: Set) : Words return words.contains(tiles) } - override fun getTodayWords(): List { + override fun getTodayWords(): Tiles { calledTodayWords = true return answer } -} \ No newline at end of file +} diff --git a/src/test/kotlin/domain/MatchResultsTest.kt b/src/test/kotlin/domain/MatchResultsTest.kt index a0772ab..4dc614f 100644 --- a/src/test/kotlin/domain/MatchResultsTest.kt +++ b/src/test/kotlin/domain/MatchResultsTest.kt @@ -1,9 +1,9 @@ package domain -import org.junit.jupiter.api.Test import domain.MatchResult.* import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatIllegalArgumentException +import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource import org.junit.jupiter.params.provider.ValueSource @@ -20,7 +20,7 @@ internal class MatchResultsTest { } @ParameterizedTest - @ValueSource(ints = [0,1,2,3,4,6,7,8]) + @ValueSource(ints = [0, 1, 2, 3, 4, 6, 7, 8]) fun `5๊ฐœ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹ˆ๋ฉด ์‹คํŒจํ•œ๋‹ค`(size: Int) { // given val matchResult = (0 until size).map { CORRECT } @@ -49,4 +49,4 @@ internal class MatchResultsTest { // then assertThat(result.isCorrect()).isFalse } -} \ No newline at end of file +} diff --git a/src/test/kotlin/domain/TilesTest.kt b/src/test/kotlin/domain/TilesTest.kt index a8f2a76..4dffc79 100644 --- a/src/test/kotlin/domain/TilesTest.kt +++ b/src/test/kotlin/domain/TilesTest.kt @@ -52,10 +52,12 @@ internal class TilesTest { } @ParameterizedTest - @CsvSource(value = [ - "h,0,true","e,1,true","l,2,true","l,3,true","o,4,true", // ์„ฑ๊ณต์ผ€์ด์Šค - "a,0,false","b,1,false","c,2,false","d,3,false","e,4,false" // ์‹คํŒจ์ผ€์ด์Šค - ]) + @CsvSource( + value = [ + "h,0,true", "e,1,true", "l,2,true", "l,3,true", "o,4,true", // ์„ฑ๊ณต์ผ€์ด์Šค + "a,0,false", "b,1,false", "c,2,false", "d,3,false", "e,4,false" // ์‹คํŒจ์ผ€์ด์Šค + ] + ) fun `Tiles๋Š” ์œ„์น˜์™€ Tile์„ ๋ฐ›์•„์„œ ํ•ด๋‹น ์œ„์น˜์— ๊ฐ™์€ ํƒ€์ผ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค`(tile: Char, index: Int, result: Boolean) { // given val tile = Tile(tile) @@ -66,7 +68,7 @@ internal class TilesTest { } @ParameterizedTest - @CsvSource(value = ["h,1","e,1","l,2","o,1","z,0"]) + @CsvSource(value = ["h,1", "e,1", "l,2", "o,1", "z,0"]) fun `Tiles์— Tile์ด ๋ช‡๊ฐœ ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค`(tile: Char, count: Int) { // given val tiles = Tiles.of("hello") From d9cefda466fa594f3e03b381aa7f93b1ceef1635 Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 15:46:59 +0900 Subject: [PATCH 25/34] =?UTF-8?q?chore()=20:=20lint=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/domain/GameTest.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index 1d08f19..cbbede4 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -4,7 +4,8 @@ import domain.MatchResult.INCORRECT import domain.MatchResult.MISSING import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import java.util.* +import java.util.LinkedList +import java.util.Queue class GameTest { @Test @@ -71,7 +72,8 @@ class GameTest { fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์žฌ์ž…๋ ฅ ๊ธฐํšŒ๋ฅผ ์ค€๋‹ค`() { // given val answer = Tiles.of("hello") - val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "hello"))) + val input = + TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "hello"))) val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer))) val game = Game(input, output, repository) From 9b74d7048c2ebcd9ac27c0f916bbb460c97d3b8e Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 17:09:21 +0900 Subject: [PATCH 26/34] =?UTF-8?q?refactor=20:=20Game=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=9D=98=20input,=20ouput=20=EC=B9=A8=ED=88=AC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/Application.kt | 11 +-- .../kotlin/controller/WordleController.kt | 27 +++++++ src/main/kotlin/domain/Game.kt | 39 ++++----- src/main/kotlin/domain/MatchResults.kt | 4 +- ...DefaultWordsRepository.kt => WordsPool.kt} | 2 +- src/main/kotlin/presentation/DefaultInput.kt | 8 +- src/main/kotlin/presentation/DefaultOutput.kt | 12 ++- src/test/kotlin/domain/AnswerTest.kt | 4 +- src/test/kotlin/domain/GameTest.kt | 81 +++++-------------- 9 files changed, 86 insertions(+), 102 deletions(-) create mode 100644 src/main/kotlin/controller/WordleController.kt rename src/main/kotlin/infra/{DefaultWordsRepository.kt => WordsPool.kt} (93%) diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt index 5a0f09d..d4c0def 100644 --- a/src/main/kotlin/Application.kt +++ b/src/main/kotlin/Application.kt @@ -1,14 +1,7 @@ -import domain.Game -import infra.DefaultWordsRepository +import controller.WordleController import presentation.DefaultInput import presentation.DefaultOutput fun main() { - val input = DefaultInput() - val output = DefaultOutput() - val repository = DefaultWordsRepository() - - val game = Game(input, output, repository) - - game.start() + WordleController(DefaultInput, DefaultOutput).start() } diff --git a/src/main/kotlin/controller/WordleController.kt b/src/main/kotlin/controller/WordleController.kt new file mode 100644 index 0000000..8ac359f --- /dev/null +++ b/src/main/kotlin/controller/WordleController.kt @@ -0,0 +1,27 @@ +package controller + +import domain.Game +import domain.Input +import domain.MatchResults +import domain.Output +import infra.WordsPool + +class WordleController( + private val input: Input, + private val output: Output +) { + + fun start() { + val game = Game(WordsPool()) + do { + var result = MatchResults() + try { + result = game.progress(input) + output.write(result) + } catch (e: IllegalArgumentException) { + print(e.message) + continue + } + } while (!result.isCorrect()) + } +} diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index 6ca8366..2c42ea5 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -1,33 +1,34 @@ package domain class Game( - private val input: Input, - private val output: Output, private val wordsRepository: WordsRepository ) { - fun start() { - val answer = Answer(wordsRepository.getTodayWords()) - var tryCount = 0 + private val answer: Answer = Answer(wordsRepository.getTodayWords()) + private var tryCount = 0 - while (tryCount < MAX_TRY_COUNT) { - val tiles = input.read() - - if (!wordsRepository.exists(tiles)) { - continue - } - - val match = answer.match(tiles) + fun progress(input: Input): MatchResults { + val tiles = input.read() + checkTryCount() + checkWord(tiles) + tryCount++ + return answer.match(tiles) + } - output.write(match) - tryCount++ + private fun checkWord(tiles: Tiles) { + if (!wordsRepository.exists(tiles)) { + throw IllegalArgumentException(NOT_FOUND_WORD) + } + } - if (match.isCorrect()) { - return - } + private fun checkTryCount() { + if (tryCount == MAX_TRY_COUNT) { + throw IllegalArgumentException(EXHAUST_TRY_COUNT) } } companion object { - const val MAX_TRY_COUNT = 6 + private const val MAX_TRY_COUNT = 6 + private const val NOT_FOUND_WORD = "์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด์ž…๋‹ˆ๋‹ค" + private const val EXHAUST_TRY_COUNT = "๊ธฐํšŒ 6๋ฒˆ์„ ๋‹ค ์จ๋ฒ„๋ ธ์”๋‹ˆ๋‹ค." } } diff --git a/src/main/kotlin/domain/MatchResults.kt b/src/main/kotlin/domain/MatchResults.kt index 45d0470..a9e599b 100644 --- a/src/main/kotlin/domain/MatchResults.kt +++ b/src/main/kotlin/domain/MatchResults.kt @@ -1,6 +1,8 @@ package domain -data class MatchResults(val results: List) { +import domain.MatchResult.MISSING + +data class MatchResults(val results: List = listOf(MISSING, MISSING, MISSING, MISSING, MISSING)) { init { require(results.size == REQUIRE_RESULTS_SIZE) { ERROR_RESULTS_SIZE_MSG } } diff --git a/src/main/kotlin/infra/DefaultWordsRepository.kt b/src/main/kotlin/infra/WordsPool.kt similarity index 93% rename from src/main/kotlin/infra/DefaultWordsRepository.kt rename to src/main/kotlin/infra/WordsPool.kt index 509a06e..bffedfa 100644 --- a/src/main/kotlin/infra/DefaultWordsRepository.kt +++ b/src/main/kotlin/infra/WordsPool.kt @@ -4,7 +4,7 @@ import domain.Tiles import domain.WordsRepository import java.time.LocalDate -class DefaultWordsRepository : WordsRepository { +class WordsPool : WordsRepository { private val words: Set private val today: Tiles diff --git a/src/main/kotlin/presentation/DefaultInput.kt b/src/main/kotlin/presentation/DefaultInput.kt index ed11e88..0cca8d2 100644 --- a/src/main/kotlin/presentation/DefaultInput.kt +++ b/src/main/kotlin/presentation/DefaultInput.kt @@ -3,7 +3,9 @@ package presentation import domain.Input import domain.Tiles -class DefaultInput : Input { +object DefaultInput : Input { + private const val INPUT_MESSAGE = "์ •๋‹ต์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." + override tailrec fun read(): Tiles { val tiles = nextTiles() @@ -23,8 +25,4 @@ class DefaultInput : Input { return null } - - companion object { - private const val INPUT_MESSAGE = "์ •๋‹ต์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." - } } diff --git a/src/main/kotlin/presentation/DefaultOutput.kt b/src/main/kotlin/presentation/DefaultOutput.kt index 0a1a03a..1f45358 100644 --- a/src/main/kotlin/presentation/DefaultOutput.kt +++ b/src/main/kotlin/presentation/DefaultOutput.kt @@ -1,18 +1,20 @@ package presentation -import domain.Game import domain.MatchResult import domain.MatchResults import domain.Output -class DefaultOutput : Output { +object DefaultOutput : Output { + private const val BLANK = "" + private const val MAX_TRY_COUNT = 6 + private val allResults: MutableList = mutableListOf() override fun write(matchResults: MatchResults) { allResults.add(matchResults) if (matchResults.isCorrect()) { - println("${allResults.size}/${Game.MAX_TRY_COUNT}") + println("${allResults.size}/${MAX_TRY_COUNT}") } printAll() @@ -37,8 +39,4 @@ class DefaultOutput : Output { MatchResult.MISSING -> "\uD83D\uDFE8" else -> "โฌœ" } - - companion object { - private const val BLANK = "" - } } diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 98a597c..316f2b0 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -1,6 +1,8 @@ package domain -import domain.MatchResult.* +import domain.MatchResult.CORRECT +import domain.MatchResult.INCORRECT +import domain.MatchResult.MISSING import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index cbbede4..9305ce2 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -1,8 +1,7 @@ package domain -import domain.MatchResult.INCORRECT -import domain.MatchResult.MISSING import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatIllegalArgumentException import org.junit.jupiter.api.Test import java.util.LinkedList import java.util.Queue @@ -12,78 +11,50 @@ class GameTest { fun `๋‹ต์•ˆ์— ์ •๋‹ต์ด ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋œ๋‹ค`() { // given val answer = Tiles.of("hello") - val input = TestInput(LinkedList(listOf("hello", "hello", "hello", "hello", "hello", "hello"))) - val output = TestOutput() + val input = TestInput(LinkedList(listOf("hello"))) val repository = TestWordsRepository(answer, setOf(Tiles(answer))) - val game = Game(input, output, repository) + val game = Game(repository) // when - game.start() + val result = game.progress(input) // then - assertThat(repository.calledTodayWords).isTrue - assertThat(repository.tilesStack).contains(Tiles(answer)) - assertThat(input.result).hasSize(5) - assertThat(output.resultsStack).hasSize(1) - assertThat(output.resultsStack[0].isCorrect()).isTrue + assertThat(result.isCorrect()).isTrue } @Test - fun `๋‹ต์„ ๋ชป๋งž์ถœ ๊ฒฝ์šฐ ์ตœ๋Œ€ 6๋ฒˆ์„ ์ž…๋ ฅํ•  ๊ธฐํšŒ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค`() { - // given - val answer = Tiles.of("hello") - val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) - val output = TestOutput() - val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) - val game = Game(input, output, repository) - - // when - game.start() - - // then - assertThat(input.result).isEmpty() - assertThat(repository.calledTodayWords).isTrue - assertThat(output.resultsStack).hasSize(6) - assertThat(output.resultsStack) - .containsOnly(MatchResults(listOf(INCORRECT, INCORRECT, INCORRECT, INCORRECT, MISSING))) - } - - @Test - fun `๊ฒŒ์ž„์€ 7๋ฒˆ ์ด์ƒ ์ž…๋ ฅ์‹œ 6๋ฒˆ๋งŒ ์ž…๋ ฅ ๋œ๋‹ค`() { + fun `๋‹ต์•ˆ์„ 7๋ฒˆ ์ด์ƒ ์ ์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค`() { // given val answer = Tiles.of("hello") val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) - val output = TestOutput() val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) - val game = Game(input, output, repository) - - // when - game.start() + val game = Game(repository) // then - assertThat(input.result).hasSize(1) - assertThat(output.resultsStack).hasSize(6) - assertThat(output.resultsStack) - .flatMap({ it.isCorrect() }) - .containsExactly(false, false, false, false, false, false) + assertThatIllegalArgumentException().isThrownBy { + game.progress(input) + game.progress(input) + game.progress(input) + game.progress(input) + game.progress(input) + game.progress(input) + game.progress(input) + } } @Test - fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์žฌ์ž…๋ ฅ ๊ธฐํšŒ๋ฅผ ์ค€๋‹ค`() { + fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค`() { // given val answer = Tiles.of("hello") val input = - TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "hello"))) - val output = TestOutput() + TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) val repository = TestWordsRepository(answer, setOf(Tiles(answer))) - val game = Game(input, output, repository) - - // when - game.start() + val game = Game(repository) // then - assertThat(input.result).hasSize(0) - assertThat(output.resultsStack).hasSize(1) + assertThatIllegalArgumentException().isThrownBy { + game.progress(input) + } } } @@ -93,14 +64,6 @@ class TestInput(val result: Queue) : Input { } } -class TestOutput : Output { - val resultsStack = mutableListOf() - - override fun write(matchResults: MatchResults) { - resultsStack.add(matchResults) - } -} - class TestWordsRepository(val answer: Tiles, val words: Set) : WordsRepository { var tilesStack = mutableListOf() var calledTodayWords = false From dde91058a473bd356d1f4c51e632792d0e4d3706 Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 17:19:15 +0900 Subject: [PATCH 27/34] =?UTF-8?q?refactor(DefaultInput.kt)=20:=20readln?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/controller/WordleController.kt | 2 +- src/main/kotlin/presentation/DefaultInput.kt | 22 ++++--------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/main/kotlin/controller/WordleController.kt b/src/main/kotlin/controller/WordleController.kt index 8ac359f..2353f9c 100644 --- a/src/main/kotlin/controller/WordleController.kt +++ b/src/main/kotlin/controller/WordleController.kt @@ -19,7 +19,7 @@ class WordleController( result = game.progress(input) output.write(result) } catch (e: IllegalArgumentException) { - print(e.message) + println(e.message) continue } } while (!result.isCorrect()) diff --git a/src/main/kotlin/presentation/DefaultInput.kt b/src/main/kotlin/presentation/DefaultInput.kt index 0cca8d2..ffa63ca 100644 --- a/src/main/kotlin/presentation/DefaultInput.kt +++ b/src/main/kotlin/presentation/DefaultInput.kt @@ -6,23 +6,9 @@ import domain.Tiles object DefaultInput : Input { private const val INPUT_MESSAGE = "์ •๋‹ต์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." - override tailrec fun read(): Tiles { - val tiles = nextTiles() - - return tiles ?: read() - } - - private fun nextTiles(): Tiles? { - try { - println(INPUT_MESSAGE) - - val text = System.`in`.bufferedReader().readLine() - - return Tiles.of(text) - } catch (e: Exception) { - println(e.message) - } - - return null + override fun read(): Tiles { + println(INPUT_MESSAGE) + val text = readln() + return Tiles.of(text) } } From 24ff1f68390e1ecb41db02e22b12ebae0ad4b62d Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 17:30:12 +0900 Subject: [PATCH 28/34] =?UTF-8?q?chore=20:=20lint=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/presentation/DefaultOutput.kt | 2 +- src/test/kotlin/domain/MatchResultsTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/presentation/DefaultOutput.kt b/src/main/kotlin/presentation/DefaultOutput.kt index 1f45358..44880e1 100644 --- a/src/main/kotlin/presentation/DefaultOutput.kt +++ b/src/main/kotlin/presentation/DefaultOutput.kt @@ -14,7 +14,7 @@ object DefaultOutput : Output { allResults.add(matchResults) if (matchResults.isCorrect()) { - println("${allResults.size}/${MAX_TRY_COUNT}") + println("${allResults.size}/$MAX_TRY_COUNT") } printAll() diff --git a/src/test/kotlin/domain/MatchResultsTest.kt b/src/test/kotlin/domain/MatchResultsTest.kt index 4dc614f..11e1dae 100644 --- a/src/test/kotlin/domain/MatchResultsTest.kt +++ b/src/test/kotlin/domain/MatchResultsTest.kt @@ -1,6 +1,6 @@ package domain -import domain.MatchResult.* +import domain.MatchResult.CORRECT import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatIllegalArgumentException import org.junit.jupiter.api.Test From 3da26d3d9b04f88eddaac263e916cc3c8c940b5a Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 17:32:39 +0900 Subject: [PATCH 29/34] =?UTF-8?q?refactor(WordsPool.kt)=20:=20WordsPool=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/infra/WordsPool.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/infra/WordsPool.kt b/src/main/kotlin/infra/WordsPool.kt index bffedfa..4312829 100644 --- a/src/main/kotlin/infra/WordsPool.kt +++ b/src/main/kotlin/infra/WordsPool.kt @@ -9,12 +9,11 @@ class WordsPool : WordsRepository { private val today: Tiles init { - val now = LocalDate.now() - val standard = LocalDate.of(2021, 6, 19) + val nowEpochDay = LocalDate.now().toEpochDay() - val values: List = this.javaClass.classLoader.getResourceAsStream("words.txt").bufferedReader().readLines() + val values: List = object {}.javaClass.getResourceAsStream("words.txt").bufferedReader().readLines() - val daysFromStandard = (now.toEpochDay() - standard.toEpochDay()).toInt() + val daysFromStandard = (nowEpochDay - BASE_TIME_EPOCH_DAY).toInt() this.words = values.map { Tiles.of(it) }.toSet() this.today = Tiles.of(values[daysFromStandard % this.words.size]) @@ -27,4 +26,8 @@ class WordsPool : WordsRepository { override fun getTodayWords(): Tiles { return today } + + companion object { + private val BASE_TIME_EPOCH_DAY = LocalDate.of(2021, 6, 19).toEpochDay() + } } From e0d8ff717bbc5fdaddacc12fa01cdf2a6496cf1f Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 17:35:22 +0900 Subject: [PATCH 30/34] =?UTF-8?q?refactor(Input.kt,=20Output.kt)=20:=20fun?= =?UTF-8?q?=20interface=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/domain/Input.kt | 2 +- src/main/kotlin/domain/Output.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/domain/Input.kt b/src/main/kotlin/domain/Input.kt index d00b155..8b5c03b 100644 --- a/src/main/kotlin/domain/Input.kt +++ b/src/main/kotlin/domain/Input.kt @@ -1,5 +1,5 @@ package domain -interface Input { +fun interface Input { fun read(): Tiles } diff --git a/src/main/kotlin/domain/Output.kt b/src/main/kotlin/domain/Output.kt index f216608..5a86732 100644 --- a/src/main/kotlin/domain/Output.kt +++ b/src/main/kotlin/domain/Output.kt @@ -1,5 +1,5 @@ package domain -interface Output { +fun interface Output { fun write(matchResults: MatchResults) } From 8ba25c6b91fcb6a496f9b988e73c8449d99921bd Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 21:15:58 +0900 Subject: [PATCH 31/34] =?UTF-8?q?refactor(words.kt)=20:=20wordsRepository?= =?UTF-8?q?=20->=20words=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20file=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/domain/Game.kt | 8 +++----- .../domain/{WordsRepository.kt => Words.kt} | 2 +- src/main/kotlin/infra/WordsPool.kt | 18 ++++++++---------- src/test/kotlin/domain/GameTest.kt | 4 ++-- 4 files changed, 14 insertions(+), 18 deletions(-) rename src/main/kotlin/domain/{WordsRepository.kt => Words.kt} (75%) diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index 2c42ea5..581157b 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -1,9 +1,7 @@ package domain -class Game( - private val wordsRepository: WordsRepository -) { - private val answer: Answer = Answer(wordsRepository.getTodayWords()) +class Game(private val words: Words) { + private val answer: Answer = Answer(words.getTodayWords()) private var tryCount = 0 fun progress(input: Input): MatchResults { @@ -15,7 +13,7 @@ class Game( } private fun checkWord(tiles: Tiles) { - if (!wordsRepository.exists(tiles)) { + if (!words.exists(tiles)) { throw IllegalArgumentException(NOT_FOUND_WORD) } } diff --git a/src/main/kotlin/domain/WordsRepository.kt b/src/main/kotlin/domain/Words.kt similarity index 75% rename from src/main/kotlin/domain/WordsRepository.kt rename to src/main/kotlin/domain/Words.kt index 0e135a4..c5a429f 100644 --- a/src/main/kotlin/domain/WordsRepository.kt +++ b/src/main/kotlin/domain/Words.kt @@ -1,6 +1,6 @@ package domain -interface WordsRepository { +interface Words { fun exists(tiles: Tiles): Boolean fun getTodayWords(): Tiles diff --git a/src/main/kotlin/infra/WordsPool.kt b/src/main/kotlin/infra/WordsPool.kt index 4312829..df91e33 100644 --- a/src/main/kotlin/infra/WordsPool.kt +++ b/src/main/kotlin/infra/WordsPool.kt @@ -1,26 +1,22 @@ package infra import domain.Tiles -import domain.WordsRepository +import domain.Words +import java.io.File import java.time.LocalDate -class WordsPool : WordsRepository { - private val words: Set +class WordsPool : Words { + private val today: Tiles init { val nowEpochDay = LocalDate.now().toEpochDay() - - val values: List = object {}.javaClass.getResourceAsStream("words.txt").bufferedReader().readLines() - val daysFromStandard = (nowEpochDay - BASE_TIME_EPOCH_DAY).toInt() - - this.words = values.map { Tiles.of(it) }.toSet() - this.today = Tiles.of(values[daysFromStandard % this.words.size]) + this.today = WORDS[daysFromStandard % WORDS.size] } override fun exists(tiles: Tiles): Boolean { - return words.contains(tiles) + return WORDS.contains(tiles) } override fun getTodayWords(): Tiles { @@ -29,5 +25,7 @@ class WordsPool : WordsRepository { companion object { private val BASE_TIME_EPOCH_DAY = LocalDate.of(2021, 6, 19).toEpochDay() + private val WORDS: List = + File(ClassLoader.getSystemResource("words.txt").file).bufferedReader().readLines().map { Tiles.of(it) } } } diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index 9305ce2..df3c735 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -58,13 +58,13 @@ class GameTest { } } -class TestInput(val result: Queue) : Input { +class TestInput(private val result: Queue) : Input { override fun read(): Tiles { return Tiles.of(result.poll()) } } -class TestWordsRepository(val answer: Tiles, val words: Set) : WordsRepository { +class TestWordsRepository(val answer: Tiles, val words: Set) : Words { var tilesStack = mutableListOf() var calledTodayWords = false From 41ef1747305094285af031619d9922a09e4664b0 Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 21:47:30 +0900 Subject: [PATCH 32/34] =?UTF-8?q?refactor(WordleController.kt,=20Game.kt,?= =?UTF-8?q?=20MatchResults)=20:=20TryCount=20Exception=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=9C=EA=B1=B0=20=ED=9B=84=20TryCount=EB=A5=BC?= =?UTF-8?q?=20=EC=B2=B4=ED=81=AC=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/controller/WordleController.kt | 11 ++++-- src/main/kotlin/domain/Game.kt | 10 ++---- src/main/kotlin/domain/MatchResults.kt | 4 +-- src/test/kotlin/domain/GameTest.kt | 34 ++++++++----------- 4 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/controller/WordleController.kt b/src/main/kotlin/controller/WordleController.kt index 2353f9c..43e25ef 100644 --- a/src/main/kotlin/controller/WordleController.kt +++ b/src/main/kotlin/controller/WordleController.kt @@ -14,14 +14,19 @@ class WordleController( fun start() { val game = Game(WordsPool()) do { - var result = MatchResults() + var result: MatchResults + try { result = game.progress(input) - output.write(result) } catch (e: IllegalArgumentException) { println(e.message) continue } - } while (!result.isCorrect()) + output.write(result) + + if (result.isCorrect()) { + break + } + } while (!game.checkToRetry()) } } diff --git a/src/main/kotlin/domain/Game.kt b/src/main/kotlin/domain/Game.kt index 581157b..23f9a00 100644 --- a/src/main/kotlin/domain/Game.kt +++ b/src/main/kotlin/domain/Game.kt @@ -6,27 +6,21 @@ class Game(private val words: Words) { fun progress(input: Input): MatchResults { val tiles = input.read() - checkTryCount() checkWord(tiles) tryCount++ return answer.match(tiles) } + fun checkToRetry() = MAX_TRY_COUNT == tryCount + private fun checkWord(tiles: Tiles) { if (!words.exists(tiles)) { throw IllegalArgumentException(NOT_FOUND_WORD) } } - private fun checkTryCount() { - if (tryCount == MAX_TRY_COUNT) { - throw IllegalArgumentException(EXHAUST_TRY_COUNT) - } - } - companion object { private const val MAX_TRY_COUNT = 6 private const val NOT_FOUND_WORD = "์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด์ž…๋‹ˆ๋‹ค" - private const val EXHAUST_TRY_COUNT = "๊ธฐํšŒ 6๋ฒˆ์„ ๋‹ค ์จ๋ฒ„๋ ธ์”๋‹ˆ๋‹ค." } } diff --git a/src/main/kotlin/domain/MatchResults.kt b/src/main/kotlin/domain/MatchResults.kt index a9e599b..45d0470 100644 --- a/src/main/kotlin/domain/MatchResults.kt +++ b/src/main/kotlin/domain/MatchResults.kt @@ -1,8 +1,6 @@ package domain -import domain.MatchResult.MISSING - -data class MatchResults(val results: List = listOf(MISSING, MISSING, MISSING, MISSING, MISSING)) { +data class MatchResults(val results: List) { init { require(results.size == REQUIRE_RESULTS_SIZE) { ERROR_RESULTS_SIZE_MSG } } diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index df3c735..4780172 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -3,15 +3,13 @@ package domain import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatIllegalArgumentException import org.junit.jupiter.api.Test -import java.util.LinkedList -import java.util.Queue class GameTest { @Test fun `๋‹ต์•ˆ์— ์ •๋‹ต์ด ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋œ๋‹ค`() { // given val answer = Tiles.of("hello") - val input = TestInput(LinkedList(listOf("hello"))) + val input = TestInput("hello") val repository = TestWordsRepository(answer, setOf(Tiles(answer))) val game = Game(repository) @@ -23,44 +21,42 @@ class GameTest { } @Test - fun `๋‹ต์•ˆ์„ 7๋ฒˆ ์ด์ƒ ์ ์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค`() { + fun `๋‹ต์•ˆ์„ 7๋ฒˆ ์ด์ƒ ์ ์œผ๋ฉด ๋”์ด์ƒ ์‹œ๋„ํ•  ์ˆ˜ ์—†๋‹ค`() { // given val answer = Tiles.of("hello") - val input = TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) + val input = listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde").map { TestInput(it) } val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) val game = Game(repository) - // then - assertThatIllegalArgumentException().isThrownBy { - game.progress(input) - game.progress(input) - game.progress(input) - game.progress(input) - game.progress(input) - game.progress(input) - game.progress(input) + // when + input.forEach { + game.progress(it) } + + // then + assertThat(game.checkToRetry()).isFalse } @Test fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค`() { // given val answer = Tiles.of("hello") - val input = - TestInput(LinkedList(listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde"))) + val input = listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde").map { TestInput(it) } val repository = TestWordsRepository(answer, setOf(Tiles(answer))) val game = Game(repository) // then assertThatIllegalArgumentException().isThrownBy { - game.progress(input) + input.forEach { + game.progress(it) + } } } } -class TestInput(private val result: Queue) : Input { +class TestInput(private val word: String) : Input { override fun read(): Tiles { - return Tiles.of(result.poll()) + return Tiles.of(word) } } From 0d7763787ad8635d2a5fb2386eba6ab5479f042a Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 22:30:00 +0900 Subject: [PATCH 33/34] =?UTF-8?q?test(AnswerTest.kt)=20:=20AnswerTest?= =?UTF-8?q?=EB=A5=BC=20JunitTest=EC=97=90=EC=84=9C=20KoTest=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/domain/AnswerTest.kt | 187 +++++++++++---------------- 1 file changed, 74 insertions(+), 113 deletions(-) diff --git a/src/test/kotlin/domain/AnswerTest.kt b/src/test/kotlin/domain/AnswerTest.kt index 316f2b0..237d30e 100644 --- a/src/test/kotlin/domain/AnswerTest.kt +++ b/src/test/kotlin/domain/AnswerTest.kt @@ -3,119 +3,80 @@ package domain import domain.MatchResult.CORRECT import domain.MatchResult.INCORRECT import domain.MatchResult.MISSING -import org.assertj.core.api.Assertions -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource - -internal class AnswerTest { - @Test - fun `Answer๋Š” 5๊ฐœ์˜ Tile๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค`() { - // given - val elements = Tiles.of("hello") - - // when - val answer = Answer(elements) - - // then - assertThat(answer.tiles).containsExactlyElementsOf(elements) - } - - @Test - fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค`() { - // given +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.ShouldSpec +import io.kotest.data.forAll +import io.kotest.data.headers +import io.kotest.data.row +import io.kotest.data.table +import io.kotest.matchers.collections.shouldContain +import io.kotest.matchers.collections.shouldContainExactly +import io.kotest.matchers.shouldBe + +internal class AnswerTest : ShouldSpec({ + context("Answer๋Š”") { val answer = Answer.of("hello") - // then - assertThat(answer.tiles) - .containsExactly(Tile('h'), Tile('e'), Tile('l'), Tile('l'), Tile('o')) - } - - @ParameterizedTest - @ValueSource(strings = ["", "h", "hell", "hellow"]) - fun `Answer๋Š” ๋ฌธ์ž์—ด 5๊ธ€์ž๋กœ ๊ตฌ์„ฑ์ด ์•ˆ๋˜๋ฉด ์‹คํŒจํ•œ๋‹ค`(words: String) { - // then - Assertions.assertThatIllegalArgumentException() - .isThrownBy { Answer.of(words) } - .withMessage(Answer.ERROR_TILE_SIZE_MSG) - } - - @Test - fun `์ •๋‹ต๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด CORRECT์ด๋‹ค`() { - // given - val answer = Answer.of("hello") - val tiles = Tiles.of("hello") - - // when - val matches = answer.match(tiles) - - // then - assertThat(matches.results).containsOnly(CORRECT) - } - - @Test - fun `์ •๋‹ต์€ ์•„๋‹ˆ์ง€๋งŒ Tile์ด ์žˆ์œผ๋ฉด MISSING์ด๋‹ค`() { - // given - val answer = Answer.of("hello") - val tiles = Tiles.of("olehl") - - // when - val matches = answer.match(tiles) - - // then - assertThat(matches.results).containsOnly(MISSING) - } - - @Test - fun `์ •๋‹ต์— Tile์ด ์—†์œผ๋ฉด INCORRECT์ด๋‹ค`() { - // given - val answer = Answer.of("hello") - val tiles = Tiles.of("zzzzz") - - // when - val matches = answer.match(tiles) - - // then - assertThat(matches.results).containsOnly(INCORRECT) - } - - @Test - fun `์ •๋‹ต์„ ๋จธ์ € CORRECT์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ์กด์žฌํ•˜๋Š” ๋ถ€๋ถ„์„ MISSING์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค`() { - // given - val answer = Answer.of("hello") - val tiles = Tiles.of("olleh") - - // when - val matches = answer.match(tiles) - - // then - assertThat(matches.results).containsExactly(MISSING, MISSING, CORRECT, MISSING, MISSING) - } - - @Test - fun `์ •๋‹ต์ด ๋’ค์— ์žˆ์œผ๋ฉด ์ •๋‹ต๋ถ€ํ„ฐ CORRECT์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { - // given - val answer = Answer.of("hello") - val tiles = Tiles.of("lllll") - - // when - val matches = answer.match(tiles) - - // then - assertThat(matches.results).containsExactly(INCORRECT, INCORRECT, CORRECT, CORRECT, INCORRECT) - } - - @Test - fun `๋‹ต์— ์žˆ๋Š” ํƒ€์ผ ๊ฐœ์ˆ˜๋ณด๋‹ค ๋งŽ์œผ๋ฉด INCORRECT์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค`() { - // given - val answer = Answer.of("hello") - val tiles = Tiles.of("llool") - - // when - val matches = answer.match(tiles) - - // then - assertThat(matches.results).containsExactly(MISSING, MISSING, MISSING, INCORRECT, INCORRECT) + context("5๊ฐœ Tile ๋กœ") { + val tiles = Tiles.of("hello") + should("๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค") { + answer.tiles shouldBe tiles + } + } + + context("5๊ฐœ๊ฐ€ ์•„๋‹Œ Tile ์€") { + should("์‹คํŒจํ•œ๋‹ค") { + forAll( + table( + headers("word"), + row(""), + row("h"), + row("hell"), + row("hellow"), + ) + ) { word -> + shouldThrow { Answer.of(word) } + } + } + } + + context("๋‹ต์•ˆ๊ณผ ๋น„๊ตํ•˜์—ฌ") { + + should("๊ฐ™์€ ์œ„์น˜์— ์žˆ์œผ๋ฉด CORRECT์ด๋‹ค") { + val tiles = Tiles.of("hello") + val matches = answer.match(tiles) + matches.results shouldContainExactly listOf(CORRECT, CORRECT, CORRECT, CORRECT, CORRECT) + } + + should("๋‹ค๋ฅธ ์œ„์น˜์— ์žˆ์œผ๋ฉด MISSING์ด๋‹ค") { + val tiles = Tiles.of("olehl") + val matches = answer.match(tiles) + matches.results shouldContain MISSING + } + + should("์—†์„ ๊ฒฝ์šฐ INCORRECT์ด๋‹ค") { + val tiles = Tiles.of("zzzzz") + val matches = answer.match(tiles) + matches.results shouldContain INCORRECT + } + + should("๋งž๋Š” ๋ถ€๋ถ„์„ CORRECT๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ์กด์žฌํ•˜๋Š” ๋ถ€๋ถ„์„ MISSING์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค ") { + val tiles = Tiles.of("olleh") + val matches = answer.match(tiles) + matches.results shouldContainExactly listOf(MISSING, MISSING, CORRECT, MISSING, MISSING) + } + + should("์ •๋‹ต์ด ๋’ค์— ์žˆ์œผ๋ฉด ์ •๋‹ต๋ถ€ํ„ฐ CORRECT์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค") { + val tiles = Tiles.of("lllll") + val matches = answer.match(tiles) + matches.results shouldContainExactly listOf(INCORRECT, INCORRECT, CORRECT, CORRECT, INCORRECT) + } + + should("๋‹ต์•ˆ์— ์žˆ๋Š” ํƒ€์ผ์ด ์ •๋‹ต ๊ฐœ์ˆ˜๋ณด๋‹ค ๋งŽ์œผ๋ฉด ๊ฒน์น˜๋Š” ๋ถ€๋ถ„์„ ์ œ์™ธํ•œ ๋ถ€๋ถ„์ด INCORRECT์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค") { + val tiles = Tiles.of("llool") + val matches = answer.match(tiles) + matches.results shouldContainExactly listOf(MISSING, MISSING, MISSING, INCORRECT, INCORRECT) + } + } } -} +}) From b844aeafd2cd3ae246d9d0b7320e6955ec944902 Mon Sep 17 00:00:00 2001 From: flamme Date: Sat, 16 Apr 2022 22:51:59 +0900 Subject: [PATCH 34/34] =?UTF-8?q?test(GameTest.kt)=20:=20GameTest=EB=A5=BC?= =?UTF-8?q?=20JunitTest=EC=97=90=EC=84=9C=20KoTest=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/domain/GameTest.kt | 61 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/test/kotlin/domain/GameTest.kt b/src/test/kotlin/domain/GameTest.kt index 4780172..bb57242 100644 --- a/src/test/kotlin/domain/GameTest.kt +++ b/src/test/kotlin/domain/GameTest.kt @@ -1,58 +1,57 @@ package domain -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatIllegalArgumentException -import org.junit.jupiter.api.Test +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.inspectors.forAll +import io.kotest.matchers.shouldBe -class GameTest { - @Test - fun `๋‹ต์•ˆ์— ์ •๋‹ต์ด ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋œ๋‹ค`() { - // given - val answer = Tiles.of("hello") +class GameTest : BehaviorSpec({ + val answer = Tiles.of("hello") + + Given("ํ•˜๋‚˜์˜ ๋‹ต์•ˆ์—") { val input = TestInput("hello") val repository = TestWordsRepository(answer, setOf(Tiles(answer))) val game = Game(repository) - // when - val result = game.progress(input) + When("์ •๋‹ต์ด ์žˆ์„ ๊ฒฝ์šฐ") { + val result = game.progress(input) - // then - assertThat(result.isCorrect()).isTrue + then("๊ฒŒ์ž„์ด ์ข…๋ฃŒ ๋œ๋‹ค") { + result.isCorrect() shouldBe true + } + } } - @Test - fun `๋‹ต์•ˆ์„ 7๋ฒˆ ์ด์ƒ ์ ์œผ๋ฉด ๋”์ด์ƒ ์‹œ๋„ํ•  ์ˆ˜ ์—†๋‹ค`() { - // given - val answer = Tiles.of("hello") + Given("๋‹ต์•ˆ์„ 7๋ฒˆ ์ด์ƒ") { val input = listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde").map { TestInput(it) } val repository = TestWordsRepository(answer, setOf(Tiles(answer), Tiles.of("abcde"))) val game = Game(repository) - // when - input.forEach { - game.progress(it) - } + When("์ ์œผ๋ฉด") { + input.forEach { + game.progress(it) + } - // then - assertThat(game.checkToRetry()).isFalse + Then("๋”์ด์ƒ ์‹œ๋„ํ•  ์ˆ˜ ์—†๋‹ค") { + game.checkToRetry() shouldBe false + } + } } - @Test - fun `์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค`() { - // given - val answer = Tiles.of("hello") + Given("์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์–ด๋Š”") { val input = listOf("abcde", "abcde", "abcde", "abcde", "abcde", "abcde", "abcde").map { TestInput(it) } val repository = TestWordsRepository(answer, setOf(Tiles(answer))) val game = Game(repository) - // then - assertThatIllegalArgumentException().isThrownBy { - input.forEach { - game.progress(it) + Then("์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค") { + input.forAll { + shouldThrow { + game.progress(it) + } } } } -} +}) class TestInput(private val word: String) : Input { override fun read(): Tiles {