From 815cb56e8e1dbe0b99693690d9f37d43e30724d1 Mon Sep 17 00:00:00 2001 From: Kykim0818 Date: Tue, 31 Oct 2023 00:04:46 +0900 Subject: [PATCH 1/9] =?UTF-8?q?docs:=20=EA=B5=AC=ED=98=84=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..51b1eea0f --- /dev/null +++ b/docs/README.md @@ -0,0 +1,44 @@ +## 구현할 기능 목록 + +- **Git의 커밋 단위는 앞 단계에서 docs/README.md에 정리한 기능 목록 단위** +- **indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.** +- **Jest를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.** +- **@woowacourse/mission-utils에서 제공하는 Random 및 Console API를 사용하여 구현해야 한다.** +
+
+ +- [ ] 자동차 이름 입력 받기 (문구 출력 및 이름 변수 초기화) +- [ ] 🧪TEST🧪 자동차 이름 입력 받기 (문구 출력 및 이름 변수 초기화) +
+ +- [ ] 이름 예외 처리 + + - 이름은 5자 이하만 가능 + +- [ ] 🧪TEST🧪 이름 예외 처리 +- [ ] 시도할 횟수 입력 받기 (문구 출력 및 횟수 변수 초기화) +- [ ] 🧪TEST🧪 시도할 횟수 입력 받기 (문구 출력 및 횟수 변수 초기화) +- [ ] 횟수 예외 처리 + + - 숫자 외 값 입력 + - 0 이하의 값 입력 +- [ ] 🧪TEST🧪 횟수 예외 처리 +- [ ] 자동차 이동하기 구현 + + - 이동조건 : 0~9사이 무작위 값이 4이상인 경우 +- [ ] 🧪TEST🧪 자동차 이동하기 구현 +- [ ] 자동차별 이동하기 구현 +- [ ] 🧪TEST🧪 자동차별 이동하기 구현 +- [ ] 1회 시행에 대한 결과 출력 + + - 결과 출력 후 줄 바꿈 되어야함 +- [ ] 🧪TEST🧪 1회 시행에 대한 결과 출력 +- [ ] 입력받은 횟수 만큼 시행하는 기능 구현 +- [ ] 🧪TEST🧪 입력받은 횟수 만큼 시행하는 기능 구현 +- [ ] 종료 시(입력 횟수 만큼 시행) 결과 문구 출력 + + - 단독 우승: '최종 우승자 : pobi' + - 공동 우승: '최종 우승자 : pobi, jun' +- [ ] 🧪TEST🧪 종료 시(입력 횟수 만큼 시행) 결과 문구 출력 +- [ ] 결과 확인 후 버그 수정 + From a5f35fd0e90c651a0baee8e97503caeb76b9a7d9 Mon Sep 17 00:00:00 2001 From: Kykim0818 Date: Wed, 1 Nov 2023 18:15:32 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=9E=85=EB=A0=A5=20=EB=B0=9B=EA=B8=B0=20?= =?UTF-8?q?(=EB=AC=B8=EA=B5=AC=20=EC=B6=9C=EB=A0=A5=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EC=88=98=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index c38b30d5b..c16f819eb 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,16 @@ +import { Console } from "@woowacourse/mission-utils"; + class App { - async play() {} + async play() { + const carNames = await this.enterCarnames(); + } + + async enterCarnames() { + const inputCarNames = await Console.readLineAsync( + "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\n" + ); + return inputCarNames.split(","); + } } export default App; From bddeb342d6a8bdf1bef84d276cad8ead3266867f Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Wed, 1 Nov 2023 23:04:07 +0900 Subject: [PATCH 3/9] =?UTF-8?q?test:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=9E=85=EB=A0=A5=20=EB=B0=9B=EA=B8=B0=20?= =?UTF-8?q?(=EB=AC=B8=EA=B5=AC=20=EC=B6=9C=EB=A0=A5=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EC=88=98=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/ApplicationTest.js | 41 ++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/__tests__/ApplicationTest.js b/__tests__/ApplicationTest.js index f93b27c7a..2b5df277c 100644 --- a/__tests__/ApplicationTest.js +++ b/__tests__/ApplicationTest.js @@ -23,7 +23,26 @@ const getLogSpy = () => { return logSpy; }; +const getReadLineSpy = () => { + const logSpy = jest.spyOn(MissionUtils.Console, "readLineAsync"); + logSpy.mockClear(); + return logSpy; +}; + describe("자동차 경주 게임", () => { + test("입력 문구 테스트", async () => { + const inputs = ["pobi,woni"]; + const output = + "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"; + const logSpy = getReadLineSpy(); + + mockQuestions(inputs); + + const app = new App(); + await app.enterCarnames(); + expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output)); + }); + test("전진-정지", async () => { // given const MOVING_FORWARD = 4; @@ -46,17 +65,17 @@ describe("자동차 경주 게임", () => { }); }); - test.each([ - [["pobi,javaji"]], - [["pobi,eastjun"]] - ])("이름에 대한 예외 처리", async (inputs) => { - // given - mockQuestions(inputs); + test.each([[["pobi,javaji"]], [["pobi,eastjun"]]])( + "이름에 대한 예외 처리", + async (inputs) => { + // given + mockQuestions(inputs); - // when - const app = new App(); + // when + const app = new App(); - // then - await expect(app.play()).rejects.toThrow("[ERROR]"); - }); + // then + await expect(app.play()).rejects.toThrow("[ERROR]"); + } + ); }); From f4659453cc89b6a489c1c58eea7efc37c34456f5 Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Wed, 1 Nov 2023 23:12:06 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A6=84=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20(=EC=9D=B4=EB=A6=84=EC=9D=80?= =?UTF-8?q?=205=EC=9E=90=20=EC=9D=B4=ED=95=98=EB=A7=8C=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/ApplicationTest.js | 2 +- src/App.js | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/__tests__/ApplicationTest.js b/__tests__/ApplicationTest.js index 2b5df277c..2e9fdc9eb 100644 --- a/__tests__/ApplicationTest.js +++ b/__tests__/ApplicationTest.js @@ -39,7 +39,7 @@ describe("자동차 경주 게임", () => { mockQuestions(inputs); const app = new App(); - await app.enterCarnames(); + await app.enterCarNames(); expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output)); }); diff --git a/src/App.js b/src/App.js index c16f819eb..3d6ca18c9 100644 --- a/src/App.js +++ b/src/App.js @@ -2,15 +2,26 @@ import { Console } from "@woowacourse/mission-utils"; class App { async play() { - const carNames = await this.enterCarnames(); + try { + const carNames = await this.enterCarNames(); + } catch (e) { + throw new Error(`[Error] : ${e.message}`); + } } - async enterCarnames() { + async enterCarNames() { const inputCarNames = await Console.readLineAsync( "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\n" ); - return inputCarNames.split(","); + const ret = inputCarNames.split(","); + if (ret.every((carName) => carName.length <= 5)) { + return ret; + } + throw new Error("자동차 이름을 5자 이하로 입력해주세요"); } } +const app = new App(); +app.play(); + export default App; From 1848e4672f5ab5764dcc68dd5c10208819292227 Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Wed, 1 Nov 2023 23:28:51 +0900 Subject: [PATCH 5/9] =?UTF-8?q?test:=20=EC=9D=B4=EB=A6=84=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20(5=EC=9E=90=20=EC=9D=B4?= =?UTF-8?q?=ED=95=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/ApplicationTest.js | 10 ++++++++++ src/App.js | 5 +---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/__tests__/ApplicationTest.js b/__tests__/ApplicationTest.js index 2e9fdc9eb..016f0f05a 100644 --- a/__tests__/ApplicationTest.js +++ b/__tests__/ApplicationTest.js @@ -43,6 +43,16 @@ describe("자동차 경주 게임", () => { expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output)); }); + test("자동차 이름 예외처리 : 5자이하 차 이름 입력", async () => { + const inputs = ["pobi,woniaaaaa"]; + mockQuestions(inputs); + + const app = new App(); + await expect(app.play()).rejects.toThrow( + "[ERROR] : 자동차 이름을 5자 이하로 입력해주세요" + ); + }); + test("전진-정지", async () => { // given const MOVING_FORWARD = 4; diff --git a/src/App.js b/src/App.js index 3d6ca18c9..b96245037 100644 --- a/src/App.js +++ b/src/App.js @@ -5,7 +5,7 @@ class App { try { const carNames = await this.enterCarNames(); } catch (e) { - throw new Error(`[Error] : ${e.message}`); + throw new Error(`[ERROR] : ${e.message}`); } } @@ -21,7 +21,4 @@ class App { } } -const app = new App(); -app.play(); - export default App; From 2c3b53010917ab3bd3f2eef50c30c6b9a307326e Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Wed, 1 Nov 2023 23:32:27 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=EC=8B=9C=EB=8F=84=ED=95=A0=20?= =?UTF-8?q?=ED=9A=9F=EC=88=98=20=EC=9E=85=EB=A0=A5=20=EB=B0=9B=EA=B8=B0=20?= =?UTF-8?q?(=EB=AC=B8=EA=B5=AC=20=EC=B6=9C=EB=A0=A5=20=EB=B0=8F=20?= =?UTF-8?q?=ED=9A=9F=EC=88=98=20=EB=B3=80=EC=88=98=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/App.js b/src/App.js index b96245037..01b3f5146 100644 --- a/src/App.js +++ b/src/App.js @@ -4,6 +4,7 @@ class App { async play() { try { const carNames = await this.enterCarNames(); + const tryCount = await this.enterTryCount(); } catch (e) { throw new Error(`[ERROR] : ${e.message}`); } @@ -19,6 +20,13 @@ class App { } throw new Error("자동차 이름을 5자 이하로 입력해주세요"); } + + async enterTryCount() { + const inputTryCount = await Console.readLineAsync( + "시도할 횟수는 몇 회인가요?\n" + ); + return inputTryCount; + } } export default App; From ddd63b286ddce7c449ce879c2e28357268778437 Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Wed, 1 Nov 2023 23:39:02 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=ED=9A=9F=EC=88=98=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 숫자 외 값 입력 - 0 이하의 값 입력 --- src/App.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index 01b3f5146..eb92a05c8 100644 --- a/src/App.js +++ b/src/App.js @@ -22,9 +22,16 @@ class App { } async enterTryCount() { - const inputTryCount = await Console.readLineAsync( + let inputTryCount = await Console.readLineAsync( "시도할 횟수는 몇 회인가요?\n" ); + if (isNaN(inputTryCount)) { + throw new Error("입력 값은 숫자여야 합니다."); + } + inputTryCount = parseInt(inputTryCount); + if (inputTryCount <= 0) { + throw new Error("1 이상의 값을 입력해야 합니다."); + } return inputTryCount; } } From f02ad1c097b6c4cb5a6421ad4cd9d98f304af614 Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Wed, 1 Nov 2023 23:52:29 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat:=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=95=98=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 6 ++++++ src/Car.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/Car.js diff --git a/src/App.js b/src/App.js index eb92a05c8..998c2660e 100644 --- a/src/App.js +++ b/src/App.js @@ -1,10 +1,16 @@ import { Console } from "@woowacourse/mission-utils"; +import { Car } from "./Car"; class App { async play() { try { const carNames = await this.enterCarNames(); const tryCount = await this.enterTryCount(); + + const cars = {}; + carNames.array.forEach((carName) => { + cars[carName] = new Car(carName); + }); } catch (e) { throw new Error(`[ERROR] : ${e.message}`); } diff --git a/src/Car.js b/src/Car.js new file mode 100644 index 000000000..8ce759c2e --- /dev/null +++ b/src/Car.js @@ -0,0 +1,14 @@ +export class Car { + name; + result = ""; + constructor(name) { + this.name = name; + } + + moveSimulate(count) { + if (count >= 4) this.result += "-"; + } + printResult() { + return `${this.name} : ${this.result}`; + } +} From a8f03e6926c8bfd8e7efb3dc27d8d4e43d292d41 Mon Sep 17 00:00:00 2001 From: Ki-Young Date: Thu, 2 Nov 2023 00:22:22 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat:=EC=8B=9C=ED=96=89=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/App.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index 998c2660e..c31968300 100644 --- a/src/App.js +++ b/src/App.js @@ -1,16 +1,27 @@ -import { Console } from "@woowacourse/mission-utils"; -import { Car } from "./Car"; +import { Console, Random } from "@woowacourse/mission-utils"; +import { Car } from "./Car.js"; class App { async play() { try { const carNames = await this.enterCarNames(); - const tryCount = await this.enterTryCount(); + let tryCount = await this.enterTryCount(); const cars = {}; - carNames.array.forEach((carName) => { + carNames.forEach((carName) => { cars[carName] = new Car(carName); }); + + Console.print("실행 결과"); + while (tryCount > 0) { + carNames.forEach((carName) => { + const car = cars[carName]; + car.moveSimulate(Random.pickNumberInRange(0, 9)); + Console.print(car.printResult()); + }); + Console.print("\n"); + tryCount -= 1; + } } catch (e) { throw new Error(`[ERROR] : ${e.message}`); } @@ -42,4 +53,7 @@ class App { } } +const app = new App(); +app.play(); + export default App;