diff --git a/README.md b/README.md
index d0286c8..04ce620 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,89 @@
-# java-racingcar-precourse
+# 2주차 미션 : 자동차 경주
+
+ 과제 세부 내용
+
+## 과제
+- 초간단 자동차 경주 게임을 구현한다.
+ - 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
+ - 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
+ - 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
+ - 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
+ - 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
+ - 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
+ - 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
+ - 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료되어야 한다.
+### 입출력
+- 경주 할 자동차 이름(이름은 쉽표(,) 기준으로 구분)
+
+ pobi,woni,jun
+
+- 시도할 횟수
+
+ 5
+
+- 각 차수별 실행 결과
+
+ pobi : --
+ woni : ----
+ jun : ---
+
+- 단독 우승자 안내 문구
+
+ 최종 우승자 : pobi
+
+- 공동 우승자 안내 문구
+
+ 최종 우승자 : pobi, jun
+
+### 실행 결과 예시
+ 경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
+ pobi,woni,jun
+ 시도할 회수는 몇회인가요?
+ 5
+
+ 실행 결과
+ pobi : -
+ woni :
+ jun : -
+
+ pobi : --
+ woni : -
+ jun : --
+
+ pobi : ---
+ woni : --
+ jun : ---
+
+ pobi : ----
+ woni : ---
+ jun : ----
+
+ pobi : -----
+ woni : ----
+ jun : -----
+
+ 최종 우승자 : pobi, jun
+
+
+
+## 구현할 기능 목록
+### Model
+ Car() // Class
+ - name
+ - count
+ - getName()
+ - getCount()
+ - forward()
+ - printResult()
+### Service
+ - sliceName()
+ - getWinner()
+ - checkInput()
+### View
+ - input()
+ - inputTimes()
+ - interimTally()
+ - outputResult()
+ - output()
+### Controller
+ - startRace()
\ No newline at end of file
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index a17a52e..964db17 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -1,7 +1,9 @@
package racingcar;
+import racingcar.controller.RaceController;
+
public class Application {
public static void main(String[] args) {
- // TODO: 프로그램 구현
+ RaceController.startRace();
}
}
diff --git a/src/main/java/racingcar/controller/RaceController.java b/src/main/java/racingcar/controller/RaceController.java
new file mode 100644
index 0000000..d8a2931
--- /dev/null
+++ b/src/main/java/racingcar/controller/RaceController.java
@@ -0,0 +1,26 @@
+package racingcar.controller;
+
+import racingcar.model.Car;
+import racingcar.service.CheckInput;
+import racingcar.service.GetWinner;
+import racingcar.service.SliceName;
+import racingcar.view.RaceView;
+
+import java.util.List;
+
+public class RaceController {
+ public static void startRace() {
+ String p = RaceView.inputCars();
+ int times = CheckInput.checkNumber(RaceView.inputTimes());
+
+ List participant = CheckInput.checkName(p);
+
+ for (String s : participant) {
+ Car.cars.add(new Car(s));
+ }
+
+ RaceView.outputResult(times);
+
+ RaceView.outputWinner(GetWinner.getWinner(Car.cars.stream(), GetWinner.getMax(Car.cars.stream())));
+ }
+}
diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java
new file mode 100644
index 0000000..e701b8e
--- /dev/null
+++ b/src/main/java/racingcar/model/Car.java
@@ -0,0 +1,36 @@
+package racingcar.model;
+
+import camp.nextstep.edu.missionutils.Randoms;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Car {
+ public static List cars = new ArrayList<>();
+
+ String name;
+ int count;
+
+ public Car(String name) {
+ this.name = name;
+ this.count = 0;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void forward() {
+ if (Randoms.pickNumberInRange(0, 9) >= 4) {
+ count++;
+ }
+ }
+
+ public void printResult() {
+ System.out.println(name + " : " + "-".repeat(count));
+ }
+}
diff --git a/src/main/java/racingcar/service/CheckInput.java b/src/main/java/racingcar/service/CheckInput.java
new file mode 100644
index 0000000..6d4aa25
--- /dev/null
+++ b/src/main/java/racingcar/service/CheckInput.java
@@ -0,0 +1,35 @@
+package racingcar.service;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class CheckInput {
+ public static List checkName(String s) {
+ if (s.isEmpty()) throw new IllegalArgumentException("자동차 이름들이 비어있습니다.");
+
+ if (s.split(",").length < 2) throw new IllegalArgumentException("자동차 이름이 부족하거나 구분자가 없습니다.");
+
+ List l = SliceName.slice(s);
+
+ for (String p : l) {
+ if (Pattern.matches("\\s+", p)) throw new IllegalArgumentException("자동차 이름이 비어있습니다.");
+ if (p.length() > 5) throw new IllegalArgumentException("자동차 이름이 5자 초과입니다.");
+ }
+
+ return l;
+ }
+
+ public static int checkNumber(String s) {
+ if (s.isEmpty()) throw new IllegalArgumentException("횟수값이 비어있습니다.");
+
+ try {
+ Integer.parseInt(s);
+ }catch (NumberFormatException e) {
+ throw new IllegalArgumentException("횟수값이 숫자가 아니거나 너무 많습니다.");
+ }
+
+ if (Integer.parseInt(s) <= 0) throw new IllegalArgumentException("횟수값이 양수가 아닙니다.");
+
+ return Integer.parseInt(s);
+ }
+}
diff --git a/src/main/java/racingcar/service/GetWinner.java b/src/main/java/racingcar/service/GetWinner.java
new file mode 100644
index 0000000..799e26e
--- /dev/null
+++ b/src/main/java/racingcar/service/GetWinner.java
@@ -0,0 +1,17 @@
+package racingcar.service;
+
+import racingcar.model.Car;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+public class GetWinner {
+ public static int getMax(Stream c) {
+ return c.map(Car::getCount).max(Integer::compare).get();
+ }
+
+ public static String getWinner(Stream c, int max) {
+ List result = c.filter(car -> car.getCount() == max).map(Car::getName).toList();
+ return String.join(", ", result);
+ }
+}
diff --git a/src/main/java/racingcar/service/SliceName.java b/src/main/java/racingcar/service/SliceName.java
new file mode 100644
index 0000000..a6a32ed
--- /dev/null
+++ b/src/main/java/racingcar/service/SliceName.java
@@ -0,0 +1,10 @@
+package racingcar.service;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SliceName {
+ public static List slice(String s) {
+ return Arrays.asList(s.split(","));
+ }
+}
diff --git a/src/main/java/racingcar/view/RaceView.java b/src/main/java/racingcar/view/RaceView.java
new file mode 100644
index 0000000..e0f297e
--- /dev/null
+++ b/src/main/java/racingcar/view/RaceView.java
@@ -0,0 +1,36 @@
+package racingcar.view;
+
+import camp.nextstep.edu.missionutils.Console;
+import racingcar.model.Car;
+
+import java.util.List;
+
+public class RaceView {
+ public static String inputCars() {
+ System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
+ return Console.readLine();
+ }
+ public static String inputTimes() {
+ System.out.println("시도할 회수는 몇회인가요?");
+ return Console.readLine();
+ }
+
+ public static void interimTally(List c) {
+ for (Car car : c ) {
+ car.forward();
+ car.printResult();
+ }
+ System.out.println();
+ }
+
+ public static void outputResult(int t) {
+ System.out.println("실행 결과");
+ for (int i = 0; i < t; i++) {
+ RaceView.interimTally(Car.cars);
+ }
+ }
+
+ public static void outputWinner(String winner) {
+ System.out.println("최종 우승자 : " + winner);
+ }
+}
diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java
index 1d35fc3..5a12b44 100644
--- a/src/test/java/racingcar/ApplicationTest.java
+++ b/src/test/java/racingcar/ApplicationTest.java
@@ -13,7 +13,7 @@ class ApplicationTest extends NsTest {
private static final int STOP = 3;
@Test
- void 기능_테스트() {
+ void functionTest() {
assertRandomNumberInRangeTest(
() -> {
run("pobi,woni", "1");
@@ -24,10 +24,42 @@ class ApplicationTest extends NsTest {
}
@Test
- void 예외_테스트() {
+ void isEmpty1() {
assertSimpleTest(() ->
- assertThatThrownBy(() -> runException("pobi,javaji", "1"))
- .isInstanceOf(IllegalArgumentException.class)
+ assertThatThrownBy(() -> runException("", "1"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void isEmpty2() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,woni", " "))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void isEmpty3() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi, ", "1"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void overFlow() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,woni ", "10000000000000000000"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void notPositiveNumber() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,woni ", "-1"))
+ .isInstanceOf(IllegalArgumentException.class)
);
}