From 3ac4cd1f4cd2220ef6c8d577a15467643aeff507 Mon Sep 17 00:00:00 2001 From: Heesoo Date: Sun, 24 Nov 2024 17:11:04 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[docs]=20README=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-HS.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 README-HS.md diff --git a/README-HS.md b/README-HS.md new file mode 100644 index 0000000..8275fdb --- /dev/null +++ b/README-HS.md @@ -0,0 +1,23 @@ +## 요구사항 +1. depth 는 3이 넘지 않도록 구현 +2. else 사용 불가 +3. 3항 연산자 불가 +4. 메소드는 한가지 일만 하도록 구현 +5. 모든 원시 값과 문자열을 포장 +6. 일급 컬렉션 사용 + +**Scanner 를 사용한 입력은 구현하지 않고 도메인만 구현** + +--- + +## 구현 내용 +1. 자동차 이름 입력 + - 5자 초과 불가 + - 쉼표로 구분 +2. 시도 횟수 입력 + - 숫자 입력만 가능 +3. 시도 횟수 만큼 실행 + 1. 랜덤 값 생성 + 2. 랜덤 값 4 이상일 경우 전진 + 3. 실행 결과 출력 +4. 최종 레이싱 결과와 우승자 출력 \ No newline at end of file From 4941d374e19c8cac9b42a041722c56c357c7290b Mon Sep 17 00:00:00 2001 From: Heesoo Date: Mon, 25 Nov 2024 18:44:49 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[feat]=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EA=B2=BD=EC=A3=BC=20=EA=B2=8C=EC=9E=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-HS.md | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/RacingCarApplication.java | 11 ++++ src/main/java/racingcar/domain/Car.java | 24 +++++++++ src/main/java/racingcar/domain/Cars.java | 51 +++++++++++++++++++ .../racingcar/exception/CarException.java | 7 +++ .../exception/messages/ErrorMessages.java | 5 ++ .../java/racingcar/util/RacingCarUtil.java | 18 +++++++ .../java/racingcar/validation/Validator.java | 21 ++++++++ src/main/java/racingcar/view/RaceResult.java | 43 ++++++++++++++++ src/test/java/racingcar/domain/CarTest.java | 22 ++++++++ src/test/java/racingcar/domain/CarsTest.java | 23 +++++++++ .../racingcar/util/RacingCarUtilTest.java | 51 +++++++++++++++++++ .../racingcar/validation/ValidatorTest.java | 51 +++++++++++++++++++ 14 files changed, 329 insertions(+), 2 deletions(-) create mode 100644 src/main/java/RacingCarApplication.java create mode 100644 src/main/java/racingcar/domain/Car.java create mode 100644 src/main/java/racingcar/domain/Cars.java create mode 100644 src/main/java/racingcar/exception/CarException.java create mode 100644 src/main/java/racingcar/exception/messages/ErrorMessages.java create mode 100644 src/main/java/racingcar/util/RacingCarUtil.java create mode 100644 src/main/java/racingcar/validation/Validator.java create mode 100644 src/main/java/racingcar/view/RaceResult.java create mode 100644 src/test/java/racingcar/domain/CarTest.java create mode 100644 src/test/java/racingcar/domain/CarsTest.java create mode 100644 src/test/java/racingcar/util/RacingCarUtilTest.java create mode 100644 src/test/java/racingcar/validation/ValidatorTest.java diff --git a/README-HS.md b/README-HS.md index 8275fdb..6b606fe 100644 --- a/README-HS.md +++ b/README-HS.md @@ -20,4 +20,4 @@ 1. 랜덤 값 생성 2. 랜덤 값 4 이상일 경우 전진 3. 실행 결과 출력 -4. 최종 레이싱 결과와 우승자 출력 \ No newline at end of file +4. 최종 레이싱 결과와 우승자 출력 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..d2880ba 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/RacingCarApplication.java b/src/main/java/RacingCarApplication.java new file mode 100644 index 0000000..1ecb9df --- /dev/null +++ b/src/main/java/RacingCarApplication.java @@ -0,0 +1,11 @@ +import racingcar.domain.Cars; +import racingcar.view.RaceResult; + +public class RacingCarApplication { + public static void main(String[] args) { + Cars cars = new Cars("red,blue,pink"); + RaceResult raceResult = cars.race(3); + raceResult.printAllRaceResult(); + raceResult.printWinner(); + } +} diff --git a/src/main/java/racingcar/domain/Car.java b/src/main/java/racingcar/domain/Car.java new file mode 100644 index 0000000..1ebd37d --- /dev/null +++ b/src/main/java/racingcar/domain/Car.java @@ -0,0 +1,24 @@ +package racingcar.domain; + +public class Car { + private String name; + private int location; + + public Car(String name) { + this.name = name; + this.location = 0; + } + + public void move() { + location++; + } + + public String getName(){ + return name; + } + + public int getLocation() { + return location; + } + +} diff --git a/src/main/java/racingcar/domain/Cars.java b/src/main/java/racingcar/domain/Cars.java new file mode 100644 index 0000000..57855f5 --- /dev/null +++ b/src/main/java/racingcar/domain/Cars.java @@ -0,0 +1,51 @@ +package racingcar.domain; + +import racingcar.view.RaceResult; +import racingcar.util.RacingCarUtil; +import racingcar.validation.Validator; + +import java.util.ArrayList; +import java.util.List; + +public class Cars { + private static final int RANDOM_NUMBER_STANDARD = 4; + + private final List cars; + + public Cars(String carNameStr) { + this.cars = new ArrayList<>(); + createCar(carNameStr); + } + + public void createCar(String carNameStr) { + String[] carNames = RacingCarUtil.splitName(carNameStr); + + for (String carName : carNames){ + Validator.checkValidCarName(carName); + cars.add(new Car(carName)); + } + } + + + public RaceResult race(int repeatNum){ + RaceResult raceResult = new RaceResult(cars); + for(int i=0; i= RANDOM_NUMBER_STANDARD){ + car.move(); + } + } + raceResult.printAllRaceResult(); + } + + + +} diff --git a/src/main/java/racingcar/exception/CarException.java b/src/main/java/racingcar/exception/CarException.java new file mode 100644 index 0000000..b183a70 --- /dev/null +++ b/src/main/java/racingcar/exception/CarException.java @@ -0,0 +1,7 @@ +package racingcar.exception; + +public class CarException extends RuntimeException { + public CarException(String message) { + super(message); + } +} diff --git a/src/main/java/racingcar/exception/messages/ErrorMessages.java b/src/main/java/racingcar/exception/messages/ErrorMessages.java new file mode 100644 index 0000000..9aa6cfc --- /dev/null +++ b/src/main/java/racingcar/exception/messages/ErrorMessages.java @@ -0,0 +1,5 @@ +package racingcar.exception.messages; + +public class ErrorMessages { + public static final String CAR_NAME_OVER_FIVE = "자동차 이름은 5자를 초과할 수 없습니다."; +} diff --git a/src/main/java/racingcar/util/RacingCarUtil.java b/src/main/java/racingcar/util/RacingCarUtil.java new file mode 100644 index 0000000..599e58e --- /dev/null +++ b/src/main/java/racingcar/util/RacingCarUtil.java @@ -0,0 +1,18 @@ +package racingcar.util; + +import java.util.Random; + +public class RacingCarUtil { + private static final int RANDOM_BOUND = 9; + + private static final Random random = new Random(); + + public static int createRandomNumber() { + return random.nextInt(RANDOM_BOUND) + 1; + } + + public static String[] splitName(String carNameStr) { + return carNameStr.replaceAll(" ", "").split(","); + } + +} diff --git a/src/main/java/racingcar/validation/Validator.java b/src/main/java/racingcar/validation/Validator.java new file mode 100644 index 0000000..b717d0b --- /dev/null +++ b/src/main/java/racingcar/validation/Validator.java @@ -0,0 +1,21 @@ +package racingcar.validation; + +import racingcar.exception.CarException; +import racingcar.exception.messages.ErrorMessages; + +public class Validator { + private static final int CAR_NAME_MAX = 5; + + public static void checkValidCarName(String carName){ + if(!isNameLengthLessThanFive(carName)){ + throw new CarException(ErrorMessages.CAR_NAME_OVER_FIVE); + } + } + + public static boolean isNameLengthLessThanFive(String carName) { + return carName.length() < CAR_NAME_MAX; + } + + + +} diff --git a/src/main/java/racingcar/view/RaceResult.java b/src/main/java/racingcar/view/RaceResult.java new file mode 100644 index 0000000..5c5bc55 --- /dev/null +++ b/src/main/java/racingcar/view/RaceResult.java @@ -0,0 +1,43 @@ +package racingcar.view; + +import racingcar.domain.Car; + +import java.util.List; +import java.util.stream.Collectors; + +public class RaceResult { + private final List cars; + + public RaceResult(List cars) { + this.cars = cars; + } + + public void printAllRaceResult(){ + for(Car car : cars){ + System.out.println(drawRaceResult(car)); + } + System.out.println(); + } + + public String drawRaceResult(Car car){ + return car.getName() + " : " + "-".repeat(car.getLocation()); + } + + public void printWinner(){ + int winnerLocation = cars.stream() + .mapToInt(Car::getLocation) + .max() + .orElse(0); + + + String winnerName = cars.stream() + .filter(car -> car.getLocation() == winnerLocation) + .map(Car::getName) + .collect(Collectors.joining(", ")); + + System.out.println(winnerName + "가 최종 우승했습니다."); + + } + + +} diff --git a/src/test/java/racingcar/domain/CarTest.java b/src/test/java/racingcar/domain/CarTest.java new file mode 100644 index 0000000..ea2b85c --- /dev/null +++ b/src/test/java/racingcar/domain/CarTest.java @@ -0,0 +1,22 @@ +package racingcar.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class CarTest { + + @Test + @DisplayName("자동차 전진") + void move(){ + // given + Car car = new Car("red"); + + // when + car.move(); + + // then + assertThat(car.getLocation()).isEqualTo(1); + } +} diff --git a/src/test/java/racingcar/domain/CarsTest.java b/src/test/java/racingcar/domain/CarsTest.java new file mode 100644 index 0000000..038d1cb --- /dev/null +++ b/src/test/java/racingcar/domain/CarsTest.java @@ -0,0 +1,23 @@ +package racingcar.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racingcar.view.RaceResult; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CarsTest { + + @Test + @DisplayName("쉼표를 기준으로 이름 분할") + void Cars(){ + // given + Cars cars = new Cars("red, blue, pink"); + + // when + RaceResult response = cars.race(3); + + // then + } + +} diff --git a/src/test/java/racingcar/util/RacingCarUtilTest.java b/src/test/java/racingcar/util/RacingCarUtilTest.java new file mode 100644 index 0000000..092f12b --- /dev/null +++ b/src/test/java/racingcar/util/RacingCarUtilTest.java @@ -0,0 +1,51 @@ +package racingcar.util; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class RacingCarUtilTest { + + @RepeatedTest(10) + @DisplayName("랜덤 값 생성") + void createRandomNumber(){ + // given, when + int response = RacingCarUtil.createRandomNumber(); + + // then + assertTrue(response > 0); + assertTrue(response < 10); + } + + @Test + @DisplayName("문자열 쉼표 기준으로 분리") + void splitName(){ + // given, when + String[] response = RacingCarUtil.splitName("red,blue,pink"); + + assertThat(response).isEqualTo(new String[]{"red", "blue", "pink"}); + } + + @Test + @DisplayName("문자열 쉼표 기준으로 분리 시 공백 포함되어 있는 경우") + void splitNameContainsSpace(){ + // given, when + String[] response = RacingCarUtil.splitName("red, blue,pink"); + + assertThat(response).isEqualTo(new String[]{"red", "blue", "pink"}); + } + + @Test + @DisplayName("문자열 쉼표 기준으로 분리 시 쉼표 없는 경우") + void splitNameNotContainsComma(){ + // given, when + String[] response = RacingCarUtil.splitName("racingCar^^"); + + assertThat(response).isEqualTo(new String[]{"racingCar^^"}); + } + +} diff --git a/src/test/java/racingcar/validation/ValidatorTest.java b/src/test/java/racingcar/validation/ValidatorTest.java new file mode 100644 index 0000000..6b1b880 --- /dev/null +++ b/src/test/java/racingcar/validation/ValidatorTest.java @@ -0,0 +1,51 @@ +package racingcar.validation; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racingcar.exception.CarException; +import racingcar.exception.messages.ErrorMessages; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ValidatorTest { + + @Test + @DisplayName("자동차 이름이 5글자 넘지 않아 예외 미발생") + void checkValidCarName(){ + // given, when, then + assertDoesNotThrow(() -> Validator.checkValidCarName("blue")); + } + + @Test + @DisplayName("자동차 이름이 5글자 넘어 예외 발생") + void checkValidCarName_carException(){ + // given, when + CarException fail = assertThrows(CarException.class, () -> Validator.checkValidCarName("green")); + + // then + assertThat(fail.getMessage()).isEqualTo(ErrorMessages.CAR_NAME_OVER_FIVE); + + } + + @Test + @DisplayName("자동차 이름이 5글자가 넘지 않아 true 반환") + void isNameLengthLessThanFive_true(){ + // given, when + boolean response = Validator.isNameLengthLessThanFive("blue"); + + // then + assertThat(response).isTrue(); + } + + @Test + @DisplayName("자동차 이름이 5글자가 넘어 false 반환") + void isNameLengthLessThanFive_false(){ + // given, when + boolean response = Validator.isNameLengthLessThanFive("green"); + + // then + assertThat(response).isFalse(); + } +} From 2fc03722a0c8c2b86b71bd1e8a02cc10cecc825b Mon Sep 17 00:00:00 2001 From: Heesoo Date: Mon, 25 Nov 2024 22:39:29 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[refactor]=20Cars=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20Race=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/RacingCarApplication.java | 4 +- src/main/java/racingcar/Race.java | 38 +++++++++++++++ src/main/java/racingcar/domain/Cars.java | 31 ++++++------ src/main/java/racingcar/view/RaceResult.java | 21 ++------ src/test/java/racingcar/domain/CarsTest.java | 50 ++++++++++++++++++-- 5 files changed, 106 insertions(+), 38 deletions(-) create mode 100644 src/main/java/racingcar/Race.java diff --git a/src/main/java/RacingCarApplication.java b/src/main/java/RacingCarApplication.java index 1ecb9df..a14da69 100644 --- a/src/main/java/RacingCarApplication.java +++ b/src/main/java/RacingCarApplication.java @@ -1,10 +1,12 @@ +import racingcar.Race; import racingcar.domain.Cars; import racingcar.view.RaceResult; public class RacingCarApplication { public static void main(String[] args) { Cars cars = new Cars("red,blue,pink"); - RaceResult raceResult = cars.race(3); + Race race = new Race(cars, 3); + RaceResult raceResult = race.raceStart(); raceResult.printAllRaceResult(); raceResult.printWinner(); } diff --git a/src/main/java/racingcar/Race.java b/src/main/java/racingcar/Race.java new file mode 100644 index 0000000..8cc772b --- /dev/null +++ b/src/main/java/racingcar/Race.java @@ -0,0 +1,38 @@ +package racingcar; + +import racingcar.domain.Car; +import racingcar.domain.Cars; +import racingcar.util.RacingCarUtil; +import racingcar.view.RaceResult; + +public class Race { + private static final int RANDOM_NUMBER_STANDARD = 4; + + private final Cars cars; + private final int repeatNum; + + public Race(Cars cars, int repeatNum){ + this.cars = cars; + this.repeatNum = repeatNum; + } + + public RaceResult raceStart(){ + RaceResult raceResult = new RaceResult(cars); + for(int i=0; i= RANDOM_NUMBER_STANDARD){ + car.move(); + } + } + raceResult.printAllRaceResult(); + } + +} diff --git a/src/main/java/racingcar/domain/Cars.java b/src/main/java/racingcar/domain/Cars.java index 57855f5..c7cdc06 100644 --- a/src/main/java/racingcar/domain/Cars.java +++ b/src/main/java/racingcar/domain/Cars.java @@ -6,10 +6,9 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class Cars { - private static final int RANDOM_NUMBER_STANDARD = 4; - private final List cars; public Cars(String carNameStr) { @@ -26,26 +25,24 @@ public void createCar(String carNameStr) { } } + public List getCars(){ + return List.copyOf(cars); + } - public RaceResult race(int repeatNum){ - RaceResult raceResult = new RaceResult(cars); - for(int i=0; i= RANDOM_NUMBER_STANDARD){ - car.move(); - } - } - raceResult.printAllRaceResult(); + return cars.stream() + .filter(car -> car.getLocation() == winnerLocation) + .map(Car::getName) + .collect(Collectors.joining(", ")); } + } diff --git a/src/main/java/racingcar/view/RaceResult.java b/src/main/java/racingcar/view/RaceResult.java index 5c5bc55..6cdc14b 100644 --- a/src/main/java/racingcar/view/RaceResult.java +++ b/src/main/java/racingcar/view/RaceResult.java @@ -1,19 +1,17 @@ package racingcar.view; import racingcar.domain.Car; - -import java.util.List; -import java.util.stream.Collectors; +import racingcar.domain.Cars; public class RaceResult { - private final List cars; + private final Cars cars; - public RaceResult(List cars) { + public RaceResult(Cars cars) { this.cars = cars; } public void printAllRaceResult(){ - for(Car car : cars){ + for(Car car : cars.getCars()){ System.out.println(drawRaceResult(car)); } System.out.println(); @@ -24,16 +22,7 @@ public String drawRaceResult(Car car){ } public void printWinner(){ - int winnerLocation = cars.stream() - .mapToInt(Car::getLocation) - .max() - .orElse(0); - - - String winnerName = cars.stream() - .filter(car -> car.getLocation() == winnerLocation) - .map(Car::getName) - .collect(Collectors.joining(", ")); + String winnerName = cars.getWinnerName(); System.out.println(winnerName + "가 최종 우승했습니다."); diff --git a/src/test/java/racingcar/domain/CarsTest.java b/src/test/java/racingcar/domain/CarsTest.java index 038d1cb..114fa5a 100644 --- a/src/test/java/racingcar/domain/CarsTest.java +++ b/src/test/java/racingcar/domain/CarsTest.java @@ -2,22 +2,64 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import racingcar.view.RaceResult; +import racingcar.exception.CarException; +import racingcar.exception.messages.ErrorMessages; + +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; public class CarsTest { @Test - @DisplayName("쉼표를 기준으로 이름 분할") - void Cars(){ + @DisplayName("Cars 객체 생성") + void createCar(){ // given Cars cars = new Cars("red, blue, pink"); // when - RaceResult response = cars.race(3); + List response = cars.getCars(); + + // then + assertThat(response.size()).isEqualTo(3); + assertThat(response).extracting(Car::getName).contains("red", "blue", "pink"); + } + + @Test + @DisplayName("자동차 이름이 5자 초과로 예외 발생") + void createCar_exception(){ + // given, when + CarException fail = assertThrows(CarException.class, () -> new Cars("red, blue, green")); + + // then + assertThat(fail.getMessage()).isEqualTo(ErrorMessages.CAR_NAME_OVER_FIVE); + + } + + @Test + @DisplayName("자동차 리스트에 객체 추가 시도로 에러 발생") + void getCars(){ + Cars cars = new Cars("red,blue,pink"); + + assertThrows(UnsupportedOperationException.class, () -> cars.getCars().add(new Car("test"))); + } + + @Test + @DisplayName("우승자 이름 반환") + void getWinnerName(){ + // given + Cars cars = new Cars("red,blue,pink"); + + for (Car car : cars.getCars()) { + car.move(); + } + + // when + String response = cars.getWinnerName(); // then + assertThat(response).isEqualTo("red, blue, pink"); } } From b01f639247af77d27c115816d1d85fb0d1d62fb4 Mon Sep 17 00:00:00 2001 From: Heesoo Date: Thu, 5 Dec 2024 13:37:34 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[refactor]=20Name,=20Location=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20Validator?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/RacingCarApplication.java | 4 +- src/main/java/racingcar/Race.java | 38 --------- src/main/java/racingcar/domain/Car.java | 32 ++++++-- src/main/java/racingcar/domain/Cars.java | 37 +++++---- src/main/java/racingcar/domain/Location.java | 44 +++++++++++ src/main/java/racingcar/domain/Name.java | 35 ++++++++ src/main/java/racingcar/domain/Race.java | 32 ++++++++ .../java/racingcar/validation/Validator.java | 21 ----- src/main/java/racingcar/view/RaceResult.java | 19 ++--- src/test/java/racingcar/domain/CarTest.java | 79 ++++++++++++++++++- src/test/java/racingcar/domain/CarsTest.java | 50 ++++++++---- .../java/racingcar/domain/LocationTest.java | 43 ++++++++++ .../racingcar/validation/ValidatorTest.java | 51 ------------ 13 files changed, 322 insertions(+), 163 deletions(-) delete mode 100644 src/main/java/racingcar/Race.java create mode 100644 src/main/java/racingcar/domain/Location.java create mode 100644 src/main/java/racingcar/domain/Name.java create mode 100644 src/main/java/racingcar/domain/Race.java delete mode 100644 src/main/java/racingcar/validation/Validator.java create mode 100644 src/test/java/racingcar/domain/LocationTest.java delete mode 100644 src/test/java/racingcar/validation/ValidatorTest.java diff --git a/src/main/java/RacingCarApplication.java b/src/main/java/RacingCarApplication.java index a14da69..d5ed30d 100644 --- a/src/main/java/RacingCarApplication.java +++ b/src/main/java/RacingCarApplication.java @@ -1,4 +1,4 @@ -import racingcar.Race; +import racingcar.domain.Race; import racingcar.domain.Cars; import racingcar.view.RaceResult; @@ -6,8 +6,8 @@ public class RacingCarApplication { public static void main(String[] args) { Cars cars = new Cars("red,blue,pink"); Race race = new Race(cars, 3); + RaceResult raceResult = race.raceStart(); - raceResult.printAllRaceResult(); raceResult.printWinner(); } } diff --git a/src/main/java/racingcar/Race.java b/src/main/java/racingcar/Race.java deleted file mode 100644 index 8cc772b..0000000 --- a/src/main/java/racingcar/Race.java +++ /dev/null @@ -1,38 +0,0 @@ -package racingcar; - -import racingcar.domain.Car; -import racingcar.domain.Cars; -import racingcar.util.RacingCarUtil; -import racingcar.view.RaceResult; - -public class Race { - private static final int RANDOM_NUMBER_STANDARD = 4; - - private final Cars cars; - private final int repeatNum; - - public Race(Cars cars, int repeatNum){ - this.cars = cars; - this.repeatNum = repeatNum; - } - - public RaceResult raceStart(){ - RaceResult raceResult = new RaceResult(cars); - for(int i=0; i= RANDOM_NUMBER_STANDARD){ - car.move(); - } - } - raceResult.printAllRaceResult(); - } - -} diff --git a/src/main/java/racingcar/domain/Car.java b/src/main/java/racingcar/domain/Car.java index 1ebd37d..d65f365 100644 --- a/src/main/java/racingcar/domain/Car.java +++ b/src/main/java/racingcar/domain/Car.java @@ -1,24 +1,40 @@ package racingcar.domain; public class Car { - private String name; - private int location; + private static final int FORWARD_NUM = 4; + + private Name name; + private Location location; public Car(String name) { - this.name = name; - this.location = 0; + this.name = new Name(name); + this.location = new Location(); + } + + public void move(int randomNum) { + if (randomNum >= FORWARD_NUM){ + location.forward(); + } } - public void move() { - location++; + public boolean isWinner(Location maxLocation){ + return location.equals(maxLocation); } - public String getName(){ + public Location getMaxLocation(Location maxLocation) { + return location.lessThan(maxLocation); + } + + public Name getName(){ return name; } - public int getLocation() { + public Location getLocation() { return location; } + @Override + public String toString() { + return name.toString() + " : " + location.toString(); + } } diff --git a/src/main/java/racingcar/domain/Cars.java b/src/main/java/racingcar/domain/Cars.java index c7cdc06..23285b4 100644 --- a/src/main/java/racingcar/domain/Cars.java +++ b/src/main/java/racingcar/domain/Cars.java @@ -1,8 +1,8 @@ package racingcar.domain; -import racingcar.view.RaceResult; +import racingcar.exception.CarException; +import racingcar.exception.messages.ErrorMessages; import racingcar.util.RacingCarUtil; -import racingcar.validation.Validator; import java.util.ArrayList; import java.util.List; @@ -20,28 +20,37 @@ public void createCar(String carNameStr) { String[] carNames = RacingCarUtil.splitName(carNameStr); for (String carName : carNames){ - Validator.checkValidCarName(carName); + if(!Name.isNameLengthLessThanFive(carName)){ + throw new CarException(ErrorMessages.CAR_NAME_OVER_FIVE); + } cars.add(new Car(carName)); } } - public List getCars(){ - return List.copyOf(cars); - } - public String getWinnerName(){ - int winnerLocation = cars.stream() - .mapToInt(Car::getLocation) - .max() - .orElse(0); - + Location maxLocation = getMaxLocation(); return cars.stream() - .filter(car -> car.getLocation() == winnerLocation) - .map(Car::getName) + .filter(car -> car.isWinner(maxLocation)) + .map(car -> car.getName().toString()) .collect(Collectors.joining(", ")); + } + public Location getMaxLocation(){ + Location maxLocation = new Location(); + + for(Car car : cars){ + maxLocation = car.getMaxLocation(maxLocation); + } + + return maxLocation; + + } + + public List getCars(){ + return List.copyOf(cars); + } diff --git a/src/main/java/racingcar/domain/Location.java b/src/main/java/racingcar/domain/Location.java new file mode 100644 index 0000000..673929e --- /dev/null +++ b/src/main/java/racingcar/domain/Location.java @@ -0,0 +1,44 @@ +package racingcar.domain; + +import java.util.Objects; + +public class Location { + private int location; + + public Location(){ + this.location = 0; + } + + public Location(int location){ + this.location = location; + } + + public void forward(){ + location++; + } + + public Location lessThan(Location maxLocation) { + if (location > maxLocation.location){ + return this; + } + return maxLocation; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Location location1 = (Location) o; + return location == location1.location; + } + + @Override + public int hashCode() { + return Objects.hashCode(location); + } + + @Override + public String toString() { + return "-".repeat(location); + } +} diff --git a/src/main/java/racingcar/domain/Name.java b/src/main/java/racingcar/domain/Name.java new file mode 100644 index 0000000..0e9f1db --- /dev/null +++ b/src/main/java/racingcar/domain/Name.java @@ -0,0 +1,35 @@ +package racingcar.domain; + +import java.util.Objects; + +public class Name { + private static final int CAR_NAME_MAX = 5; + + private String name; + + public Name(String name){ + this.name = name; + } + + public static boolean isNameLengthLessThanFive(String name) { + return name.length() < CAR_NAME_MAX; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Name name1 = (Name) o; + return Objects.equals(name, name1.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public String toString() { + return name; + } +} diff --git a/src/main/java/racingcar/domain/Race.java b/src/main/java/racingcar/domain/Race.java new file mode 100644 index 0000000..5f8b2f6 --- /dev/null +++ b/src/main/java/racingcar/domain/Race.java @@ -0,0 +1,32 @@ +package racingcar.domain; + +import racingcar.util.RacingCarUtil; +import racingcar.view.RaceResult; + +public class Race { + private final Cars cars; + private final int repeatNum; + private final RaceResult raceResult; + + public Race(Cars cars, int repeatNum){ + this.cars = cars; + this.repeatNum = repeatNum; + this.raceResult = new RaceResult(cars); + } + + public RaceResult raceStart(){ + for(int i=0; i response = cars.getCars(); // then - assertThat(response.size()).isEqualTo(3); - assertThat(response).extracting(Car::getName).contains("red", "blue", "pink"); + assertThat(response.size()).isEqualTo(2); + assertThat(response).extracting(Car::getName).contains(red, blue); } @Test @@ -37,13 +39,6 @@ void createCar_exception(){ } - @Test - @DisplayName("자동차 리스트에 객체 추가 시도로 에러 발생") - void getCars(){ - Cars cars = new Cars("red,blue,pink"); - - assertThrows(UnsupportedOperationException.class, () -> cars.getCars().add(new Car("test"))); - } @Test @DisplayName("우승자 이름 반환") @@ -51,15 +46,42 @@ void getWinnerName(){ // given Cars cars = new Cars("red,blue,pink"); - for (Car car : cars.getCars()) { - car.move(); - } + Car car1 = cars.getCars().get(0); + car1.move(4); + Car car2 = cars.getCars().get(1); + car2.move(4); // when String response = cars.getWinnerName(); // then - assertThat(response).isEqualTo("red, blue, pink"); + assertThat(response).isEqualTo(car1.getName().toString()+ ", " + car2.getName().toString()); + } + + @Test + @DisplayName("레이싱 가장 큰 위치 반환") + void getMaxLocation(){ + // given + Cars cars = new Cars("red,blue,pink"); + Car car = cars.getCars().get(0); + car.move(4); + car.move(4); + + // when + Location response = cars.getMaxLocation(); + + // then + assertThat(response).isEqualTo(car.getLocation()); } + @Test + @DisplayName("자동차 리스트에 객체 추가 시도로 에러 발생") + void getCars(){ + Cars cars = new Cars("red,blue,pink"); + + assertThrows(UnsupportedOperationException.class, () -> cars.getCars().add(new Car("test"))); + } + + + } diff --git a/src/test/java/racingcar/domain/LocationTest.java b/src/test/java/racingcar/domain/LocationTest.java new file mode 100644 index 0000000..fcc9545 --- /dev/null +++ b/src/test/java/racingcar/domain/LocationTest.java @@ -0,0 +1,43 @@ +package racingcar.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LocationTest { + + @Test + @DisplayName("Location 비교") + void lessThan(){ + // given + Location maxLocation = new Location(3); + Location lessLocation = new Location(2); + + // when + Location response = lessLocation.lessThan(maxLocation); + + // then + assertThat(response).isEqualTo(maxLocation); + } + + @Test + @DisplayName("자동차 이름이 5글자가 넘지 않아 true 반환") + void isNameLengthLessThanFive_true(){ + // given, when + boolean response = Name.isNameLengthLessThanFive("blue"); + + // then + assertThat(response).isTrue(); + } + + @Test + @DisplayName("자동차 이름이 5글자가 넘어 false 반환") + void isNameLengthLessThanFive_false(){ + // given, when + boolean response = Name.isNameLengthLessThanFive("green"); + + // then + assertThat(response).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/racingcar/validation/ValidatorTest.java b/src/test/java/racingcar/validation/ValidatorTest.java deleted file mode 100644 index 6b1b880..0000000 --- a/src/test/java/racingcar/validation/ValidatorTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package racingcar.validation; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import racingcar.exception.CarException; -import racingcar.exception.messages.ErrorMessages; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class ValidatorTest { - - @Test - @DisplayName("자동차 이름이 5글자 넘지 않아 예외 미발생") - void checkValidCarName(){ - // given, when, then - assertDoesNotThrow(() -> Validator.checkValidCarName("blue")); - } - - @Test - @DisplayName("자동차 이름이 5글자 넘어 예외 발생") - void checkValidCarName_carException(){ - // given, when - CarException fail = assertThrows(CarException.class, () -> Validator.checkValidCarName("green")); - - // then - assertThat(fail.getMessage()).isEqualTo(ErrorMessages.CAR_NAME_OVER_FIVE); - - } - - @Test - @DisplayName("자동차 이름이 5글자가 넘지 않아 true 반환") - void isNameLengthLessThanFive_true(){ - // given, when - boolean response = Validator.isNameLengthLessThanFive("blue"); - - // then - assertThat(response).isTrue(); - } - - @Test - @DisplayName("자동차 이름이 5글자가 넘어 false 반환") - void isNameLengthLessThanFive_false(){ - // given, when - boolean response = Validator.isNameLengthLessThanFive("green"); - - // then - assertThat(response).isFalse(); - } -}