diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java index 400fab8adb0..1a575513ca6 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/Car.java @@ -9,23 +9,35 @@ public class Car { private static final int RANDOM_BOUND = 10; private static final int PROCEED_THRESHOLD = 4; private static final int INIT_POSITION = 1; + public static final int MAX_NAME_LENGTH = 5; private final Random random = new Random(); + + private final String name; private final List positions; - Car(int trialCount) { + Car(String name, int trialCount) { + this.name = name; positions = new ArrayList<>(); int position = INIT_POSITION; - for(int i=0; i< trialCount; i++) { + for (int i = 0; i < trialCount; i++) { addPosition(position); position += proceedOrStop(); } } - Car(List positions) { + Car(String name, List positions) { + validateCarName(name); + this.name = name; this.positions = new ArrayList<>(positions); } + private void validateCarName(String name) { + if (name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException("자동차 이름은 5자를 초과할 수 없다."); + } + } + public int getTrialCount() { return positions.size(); } @@ -34,6 +46,14 @@ public int getPosition(int index) { return positions.get(index); } + public int getLastPosition() { + if (positions.isEmpty()) { + return -1; + } + + return positions.get(positions.size() - 1); + } + private void addPosition(int position) { positions.add(position); } @@ -42,4 +62,12 @@ public int proceedOrStop() { int randomValue = random.nextInt(RANDOM_BOUND); return randomValue >= PROCEED_THRESHOLD ? 1 : 0; } + + public String getName() { + return name; + } + + public List getPositions() { + return positions; + } } diff --git a/src/main/java/racingcar/CarCollection.java b/src/main/java/racingcar/CarCollection.java new file mode 100644 index 00000000000..62646fe20b1 --- /dev/null +++ b/src/main/java/racingcar/CarCollection.java @@ -0,0 +1,32 @@ +package racingcar; + +import java.util.ArrayList; +import java.util.List; + +public class CarCollection { + private final List cars; + + public CarCollection() { + this.cars = new ArrayList<>(); + } + + public CarCollection(List cars) { + this.cars = cars; + } + + public void addCar(Car car) { + cars.add(car); + } + + public void removeCar(Car car) { + cars.remove(car); + } + + public int getCarCount() { + return cars.size(); + } + + public List getCars() { + return new ArrayList<>(cars); + } +} diff --git a/src/main/java/racingcar/InputView.java b/src/main/java/racingcar/InputView.java index e3ba6916d4a..a8a4c2d191e 100644 --- a/src/main/java/racingcar/InputView.java +++ b/src/main/java/racingcar/InputView.java @@ -4,21 +4,20 @@ public class InputView { - public Racing init() { - Scanner scanner = new Scanner(System.in); + private InputViewDto inputViewDto; - Integer carCount = getCarCount(scanner); - Integer trialCount = getTrialCount(scanner); - System.out.println("carCount = " + carCount); - System.out.println("trialCount = " + trialCount); + InputView() { + Scanner scanner = new Scanner(System.in); - return new Racing(carCount, trialCount); + inputViewDto = new InputViewDto(); + inputViewDto.setCarNames(getCarNames(scanner)); + inputViewDto.setTrialCount(getTrialCount(scanner)); } - private Integer getCarCount(Scanner scanner) { - System.out.println("자동차 대수는 몇 대 인가요?"); - return Integer.parseInt(scanner.nextLine()); + private String getCarNames(Scanner scanner) { + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + return scanner.nextLine(); } private static Integer getTrialCount(Scanner scanner) { @@ -26,4 +25,11 @@ private static Integer getTrialCount(Scanner scanner) { return Integer.parseInt(scanner.nextLine()); } + public String getCarNames() { + return inputViewDto.getCarNames(); + } + + public int getTrialCount() { + return inputViewDto.getTrialCount(); + } } diff --git a/src/main/java/racingcar/InputViewDto.java b/src/main/java/racingcar/InputViewDto.java new file mode 100644 index 00000000000..c49c12ddded --- /dev/null +++ b/src/main/java/racingcar/InputViewDto.java @@ -0,0 +1,24 @@ +package racingcar; + +import java.util.Scanner; + +public class InputViewDto { + private String carNames; + private int trialCount; + + public String getCarNames() { + return carNames; + } + + public void setCarNames(String carNames) { + this.carNames = carNames; + } + + public int getTrialCount() { + return trialCount; + } + + public void setTrialCount(int trialCount) { + this.trialCount = trialCount; + } +} diff --git a/src/main/java/racingcar/Racing.java b/src/main/java/racingcar/Racing.java index 2a202b2f8b5..07cd769e66c 100644 --- a/src/main/java/racingcar/Racing.java +++ b/src/main/java/racingcar/Racing.java @@ -1,24 +1,30 @@ package racingcar; -import java.util.ArrayList; -import java.util.List; - public class Racing { - private final List cars; + // private final List cars; + private CarCollection carCollection; + + public void main() { + InputView inputView = new InputView(); + ResultView resultView = new ResultView(); - Racing(int carCount, int trialCount) { - this.cars = createCars(carCount, trialCount); + buildCarCollection(inputView.getCarNames(), inputView.getTrialCount()); + resultView.displayResults(carCollection); + resultView.displayWinnerMessage(carCollection); } - private static List createCars(int carCount, int trialCount) { - List cars = new ArrayList<>(); - for(int i=0; i getCars() { - return new ArrayList<>(cars); + public CarCollection getCarCollection() { + return carCollection; } } diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java index 73bbb6fb80e..0e7225fe79e 100644 --- a/src/main/java/racingcar/ResultView.java +++ b/src/main/java/racingcar/ResultView.java @@ -1,25 +1,79 @@ package racingcar; +import java.util.ArrayList; import java.util.List; public class ResultView { - public void displayResults(List cars) { - int trialCount = cars.get(0).getTrialCount(); + public void displayResults(CarCollection carCollection) { + System.out.println(getResults(carCollection)); + } + + public String getResults(CarCollection carCollection) { + StringBuilder sb = new StringBuilder(); + int trialCount = carCollection.getCars().get(0).getTrialCount(); for (int i = 0; i < trialCount; i++) { - displayColumn(cars, i); - System.out.println(); + sb.append(getColumn(carCollection, i)); + sb.append(System.lineSeparator()); } + + return sb.toString(); } - private void displayColumn(List cars, int columnIndex) { - for (Car car : cars) { - System.out.println(getPositionLine(car, columnIndex)); + private String getColumn(CarCollection carCollection, int index) { + StringBuilder sb = new StringBuilder(); + + for (Car car : carCollection.getCars()) { + sb.append(car.getName()) + .append(" : ") + .append(getPositionLine(car, index)) + .append(System.lineSeparator()); } + + return sb.toString(); } + private String getPositionLine(Car car, int columnIndex) { return "-".repeat(car.getPosition(columnIndex)); } + + public void displayWinnerMessage(CarCollection carCollection) { + System.out.println(getWinnerMessage(carCollection)); + } + + public String getWinnerMessage(CarCollection carCollection) { + String winner = getWinner(carCollection, getBiggestLastPosition(carCollection)); + + return winner + "가 최종 우승했습니다."; + } + + private int getBiggestLastPosition(CarCollection carCollection) { + int max = -1; + + for (Car car : carCollection.getCars()) { + int lastPosition = car.getLastPosition(); + + if (max < lastPosition) { + max = lastPosition; + } + } + return max; + } + + private String getWinner(CarCollection carCollection, int biggestLastPosition) { + ArrayList winnerList = new ArrayList<>(); + + for (Car car : carCollection.getCars()) { + int lastPosition = car.getLastPosition(); + + if (lastPosition == biggestLastPosition) { + winnerList.add(car.getName()); + } + } + + return String.join(", ", winnerList); + } + } diff --git a/src/test/java/racingcar/CarTest.java b/src/test/java/racingcar/CarTest.java new file mode 100644 index 00000000000..2ed7a68b7e2 --- /dev/null +++ b/src/test/java/racingcar/CarTest.java @@ -0,0 +1,41 @@ +package racingcar; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.junit.jupiter.api.Assertions.*; + +class CarTest { + @Test + void proceedOrStop함수는_0_또는_1을_반환한다() { + // Given + Car car = new Car("pobi", Arrays.asList(1, 2, 3, 4, 4)); + + // Then + assertThat(car.proceedOrStop()).isIn(0, 1); + assertThat(car.proceedOrStop()).isIn(0, 1); + assertThat(car.proceedOrStop()).isIn(0, 1); + assertThat(car.proceedOrStop()).isIn(0, 1); + assertThat(car.proceedOrStop()).isIn(0, 1); + } + + @Test + void Car_객체_테스트() { + // Given + Car car = new Car("pobi", Arrays.asList(1, 2, 3, 4, 5)); + + // Then + assertThat(car.getName()).isEqualTo("pobi"); + assertThat(car.getPositions()).isEqualTo(Arrays.asList(1, 2, 3, 4, 5)); + } + + @Test + void 자동차_이름은_5자를_초과할_수_없다() { + assertThatIllegalArgumentException().isThrownBy(() -> { + Car car = new Car("pobibi", Arrays.asList(1, 2, 3, 4, 5)); + }).withMessage("자동차 이름은 5자를 초과할 수 없다."); + } +} \ No newline at end of file diff --git a/src/test/java/racingcar/InputViewTest.java b/src/test/java/racingcar/InputViewTest.java new file mode 100644 index 00000000000..c7cb6d89301 --- /dev/null +++ b/src/test/java/racingcar/InputViewTest.java @@ -0,0 +1,27 @@ +package racingcar; + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; + +import static org.assertj.core.api.Assertions.assertThat; + +class InputViewTest { + + public InputView inputView; + + @Test + void 문자_입력_받기() { + // Given + String testInput = "pobi,crong,honux\n5\n"; + ByteArrayInputStream in = new ByteArrayInputStream(testInput.getBytes()); + System.setIn(in); + + // When + inputView = new InputView(); + + // Then + assertThat(inputView.getCarNames()).isEqualTo("pobi,crong,honux"); + assertThat(inputView.getTrialCount()).isEqualTo(5); + } +} \ No newline at end of file diff --git a/src/test/java/racingcar/RacingTest.java b/src/test/java/racingcar/RacingTest.java index 3631c4bdbdc..d29c44a375c 100644 --- a/src/test/java/racingcar/RacingTest.java +++ b/src/test/java/racingcar/RacingTest.java @@ -6,58 +6,21 @@ import java.util.Arrays; import java.util.List; -public class RacingTest { - - public InputView inputView = new InputView(); - public ResultView resultView = new ResultView(); - - +import static org.assertj.core.api.Assertions.*; - @Test - void 전부_합친_테스트() { - // Given - String testInput = "3\n5\n"; - ByteArrayInputStream in = new ByteArrayInputStream(testInput.getBytes()); - System.setIn(in); +public class RacingTest { - // Then - Racing race = inputView.init(); - resultView.displayResults(race.getCars()); - } + private Racing racing = new Racing(); @Test - void 문자_입력_받기() { + void 레이싱_전체_테스트() { // Given - String testInput = "3\n5\n"; + String testInput = "pobi,crong,honux\n5\n"; ByteArrayInputStream in = new ByteArrayInputStream(testInput.getBytes()); System.setIn(in); - // Then - inputView.init(); - } - - @Test - void 랜덤하게_전진() { - // Given - Racing race = new Racing(3, 5); - // When - - // Then - resultView.displayResults(race.getCars()); - } - - @Test - void 자동차_출력하기() { - // Given - - List cars = Arrays.asList( - new Car(Arrays.asList(1, 2, 3, 4, 4)), - new Car(Arrays.asList(1, 1, 2, 3, 4)), - new Car(Arrays.asList(1, 2, 3, 4, 5)) - ); - // Then - resultView.displayResults(cars); + racing.main(); } } diff --git a/src/test/java/racingcar/ResultViewTest.java b/src/test/java/racingcar/ResultViewTest.java new file mode 100644 index 00000000000..bc296ee928b --- /dev/null +++ b/src/test/java/racingcar/ResultViewTest.java @@ -0,0 +1,67 @@ +package racingcar; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class ResultViewTest { + + public ResultView resultView = new ResultView(); + + @Test + void 자동차_출력하기() { + // Given + List cars = Arrays.asList( + new Car("pobi", Arrays.asList(1, 2, 3, 4, 4)), + new Car("crong", Arrays.asList(1, 1, 2, 3, 4)), + new Car("honux", Arrays.asList(1, 2, 3, 4, 5)) + ); + + // When + CarCollection carCollection = new CarCollection(cars); + String results = resultView.getResults(carCollection); + String lineSeparator = System.lineSeparator(); + + // Then + assertThat(results).isEqualTo( + "pobi : -" + lineSeparator + + "crong : -" + lineSeparator + + "honux : -" + lineSeparator + + "" + lineSeparator + + "pobi : --" + lineSeparator + + "crong : -" + lineSeparator + + "honux : --" + lineSeparator + + "" + lineSeparator + + "pobi : ---" + lineSeparator + + "crong : --" + lineSeparator + + "honux : ---" + lineSeparator + + "" + lineSeparator + + "pobi : ----" + lineSeparator + + "crong : ---" + lineSeparator + + "honux : ----" + lineSeparator + + "" + lineSeparator + + "pobi : ----" + lineSeparator + + "crong : ----" + lineSeparator + + "honux : -----" + lineSeparator + + "" + lineSeparator); + } + + + @Test + void 우승자_출력하기() { + // Given + List cars = Arrays.asList( + new Car("pobi", Arrays.asList(1, 2, 3, 4, 4)), + new Car("crong", Arrays.asList(1, 1, 2, 3, 4)), + new Car("honux", Arrays.asList(1, 2, 3, 3, 3)) + ); + + // Then + CarCollection carCollection = new CarCollection(cars); + assertThat(resultView.getWinnerMessage(carCollection)).isEqualTo("pobi, crong가 최종 우승했습니다."); + } +} \ No newline at end of file