diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/build.gradle b/build.gradle old mode 100644 new mode 100755 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar old mode 100644 new mode 100755 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties old mode 100644 new mode 100755 diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 diff --git a/settings.gradle b/settings.gradle old mode 100644 new mode 100755 diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep old mode 100644 new mode 100755 diff --git a/src/main/java/cholog/Main.java b/src/main/java/cholog/Main.java new file mode 100644 index 00000000..6e0aa723 --- /dev/null +++ b/src/main/java/cholog/Main.java @@ -0,0 +1,15 @@ +import domain.RacingContest; +import view.InputView; +import view.ResultView; + + +public class Main { + + public static void main(String[] args) throws Exception { + final var playerNames = InputView.getPlayerNames(); + final var rounds = InputView.getRounds(); + final var racingContest = new RacingContest(playerNames, rounds); + + ResultView.printContest(racingContest); + } +} diff --git a/src/main/java/cholog/domain/RacingCar.java b/src/main/java/cholog/domain/RacingCar.java new file mode 100644 index 00000000..71436e8a --- /dev/null +++ b/src/main/java/cholog/domain/RacingCar.java @@ -0,0 +1,26 @@ +package domain; + +import lombok.Getter; + +@Getter +public class RacingCar { + private String name; + + public RacingCar(String name) { + setName(name); + } + + public int moveByRandom(int random){ + if (random >= 4){ + return 1; //go + } + return 0; //stop + } + + private void setName(String name) { + if (name == null || name.trim().isEmpty()) { + throw new IllegalArgumentException("Racing car name cannot be empty"); + } + this.name = name; + } +} diff --git a/src/main/java/cholog/domain/RacingContest.java b/src/main/java/cholog/domain/RacingContest.java new file mode 100644 index 00000000..8fc165a0 --- /dev/null +++ b/src/main/java/cholog/domain/RacingContest.java @@ -0,0 +1,43 @@ +package domain; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import lombok.Getter; + +@Getter +public class RacingContest { + private static final Random random = new Random(); + private final List racingCars; + private final Map distances; + private final int rounds; + + public RacingContest(List playerNames, int rounds) { + this.racingCars = playerNames.stream().map(RacingCar::new).toList(); + this.distances = new HashMap<>(); + for (RacingCar car : racingCars){ + distances.putIfAbsent(car.getName(), 0); + } + this.rounds = rounds; + } + + public void goRound(){ + for (RacingCar car : racingCars) { + String name = car.getName(); + int move = car.moveByRandom(random.nextInt(10)); + distances.compute(name, (k, v) -> v + move); + } + } + + public List getWinners() { + List winners = new ArrayList<>(); + int max = distances.values().stream().max(Integer::compareTo).get(); + distances.entrySet().stream() + .filter(e -> e.getValue() >= max) + .forEach(e -> winners.add(e.getKey())); + + return winners; + } +} diff --git a/src/main/java/cholog/view/InputView.java b/src/main/java/cholog/view/InputView.java new file mode 100644 index 00000000..ffae42d5 --- /dev/null +++ b/src/main/java/cholog/view/InputView.java @@ -0,0 +1,31 @@ +package view; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +public class InputView { + private static final Scanner sc = new Scanner(System.in); + + public static List getPlayerNames() throws Exception { + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + var playerNames = Arrays.asList(sc.nextLine().split(",")); + if (playerNames.isEmpty()) { + throw new Exception("자동차 이름이 입력되지 않았습니다."); + } + if (playerNames.size() < 2) { + throw new Exception("2개 이상의 자동차 이름이 입력되지 않았습니다."); + } + return playerNames; + } + + public static int getRounds() throws Exception { + System.out.println("시도할 회수는 몇회인가요?"); + var rounds = Integer.parseInt(sc.nextLine()); + if (rounds <= 0) { + throw new IOException(); + } + return rounds; + } +} diff --git a/src/main/java/cholog/view/ResultView.java b/src/main/java/cholog/view/ResultView.java new file mode 100644 index 00000000..bbafb76d --- /dev/null +++ b/src/main/java/cholog/view/ResultView.java @@ -0,0 +1,44 @@ +package view; + +import domain.RacingContest; +import java.util.List; +import java.util.Map; + +public class ResultView { + + private static void printRound(Map distances) { + if (distances.isEmpty()) { + throw new IllegalArgumentException(); + } + StringBuilder sb = new StringBuilder(); + + for (Map.Entry player : distances.entrySet()) { + sb.append(player.getKey()).append(" : "); + sb.append("-".repeat(player.getValue())).append("\n"); + } + + System.out.println(sb); + } + + public static void printWinners(List winners) { + if (winners.isEmpty()) { + throw new IllegalArgumentException(); + } + System.out.print(String.join(", ", winners)); + System.out.println("가 최종 우승했습니다."); + } + + public static void printContest(RacingContest contest) { + if (contest == null) { + throw new IllegalArgumentException(); + } + int rounds = contest.getRounds(); + + System.out.println("\n실행 결과"); + for (int r = 0; r < rounds; r++){ + contest.goRound(); + printRound(contest.getDistances()); + } + printWinners(contest.getWinners()); + } +} diff --git a/src/test/java/.gitkeep b/src/test/java/.gitkeep old mode 100644 new mode 100755 diff --git a/src/test/java/cholog/TestRacingCar.java b/src/test/java/cholog/TestRacingCar.java new file mode 100644 index 00000000..97207bd8 --- /dev/null +++ b/src/test/java/cholog/TestRacingCar.java @@ -0,0 +1,58 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.RacingCar; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class TestRacingCar { + + private RacingCar racingCar; + + @BeforeEach + void setUp() { + racingCar = new RacingCar("myRacingCar"); + } + + @Test + @DisplayName("레이싱카 전진 확인") + public void testGo(){ + //given + int random = 9; + + //when + int actual = racingCar.moveByRandom(random); + int expected = 1; + + //then + assertThat(actual).isEqualTo(expected); + } + @Test + @DisplayName("레이싱카 정지 확인") + public void testStop(){ + //given + int random = 0; + + //when + int actual = racingCar.moveByRandom(random); + int expected = 0; + + //then + assertThat(actual).isEqualTo(expected); + } + + @Test + @DisplayName("레이싱카의 이름이 유효하지 않을 시 에러 발생") + public void testValidName(){ + //given + String name = null; + + //when + + //then + assertThatThrownBy(() -> { + new RacingCar(name); + }).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/cholog/TestRacingContest.java b/src/test/java/cholog/TestRacingContest.java new file mode 100644 index 00000000..11a92ae6 --- /dev/null +++ b/src/test/java/cholog/TestRacingContest.java @@ -0,0 +1,53 @@ +import static org.assertj.core.api.Assertions.assertThat; + +import domain.RacingCar; +import domain.RacingContest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class TestRacingContest { + + private static RacingContest contest; + + @BeforeAll + public static void setUp() { + int rounds = 5; + List playerNames = Arrays.asList("neo", "brie", "brown"); + contest = new RacingContest(playerNames, rounds); + } + + @Test + @DisplayName("경기 결과 모든 차의 주행거리가 0 이상이고 주어진 횟수 round 이하인지 확인") + public void testStart() { + //given + int round = contest.getRounds(); + var distances = contest.getDistances(); + + //when + int maxDist = distances.values().stream().max(Integer::compareTo).get(); + int minDist = distances.values().stream().min(Integer::compareTo).get(); + + //then + assertThat(maxDist).isBetween(0, round + 1); + assertThat(minDist).isBetween(0, round + 1); + } + @Test + @DisplayName("경기 결과를 바탕으로 우승자를 가려낼 수 있는지 확인") + public void testRanking() { + //given + contest.goRound(); + var distances = contest.getDistances(); + var winners = contest.getWinners(); + + //when + var actual = distances.get(winners.get(0)); + var expected = distances.values().stream().max(Integer::compareTo).get(); + + //then + assertThat(actual).isEqualTo(expected); + } +}