From a5872a4a3d715ad0cc018f5f8e29c6f8e753b37b Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 5 Aug 2024 20:46:16 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EA=B8=B0=EB=8A=A5=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 --- README.md | 44 +++++++++++- src/main/java/Application.java | 8 +++ src/main/java/Service/CarService.java | 69 +++++++++++++++++++ src/main/java/controller/GameController.java | 58 ++++++++++++++++ src/main/java/domain/Car.java | 45 ++++++++++++ src/main/java/domain/NumberGenerator.java | 5 ++ .../java/domain/RandomNumberGenerator.java | 20 ++++++ src/main/java/view/ErrorView.java | 7 ++ src/main/java/view/InputValidator.java | 33 +++++++++ src/main/java/view/InputView.java | 39 +++++++++++ src/main/java/view/OutputView.java | 22 ++++++ 11 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/Service/CarService.java create mode 100644 src/main/java/controller/GameController.java create mode 100644 src/main/java/domain/Car.java create mode 100644 src/main/java/domain/NumberGenerator.java create mode 100644 src/main/java/domain/RandomNumberGenerator.java create mode 100644 src/main/java/view/ErrorView.java create mode 100644 src/main/java/view/InputValidator.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java diff --git a/README.md b/README.md index 8d7e8aee..6547a6e4 100644 --- a/README.md +++ b/README.md @@ -1 +1,43 @@ -# java-baseball-precourse \ No newline at end of file +# java-racingcar-precourse + +--- + +## πŸš€ κΈ°λŠ₯ λͺ©λ‘ + +### βœ… car κΈ°λŠ₯ +[x] μ΄λ™ν•œλ‹€. +[x] 이름을 λ°˜ν™˜ν•œλ‹€. +[x] μœ„μΉ˜λ₯Ό λ°˜ν™˜ν•œλ‹€. + +### βœ… car service κΈ°λŠ₯ +[x] μžλ™μ°¨λ“€μ„ λ§Œλ“ λ‹€. +[x] μžλ™μ°¨λ“€μ„ random값을 μ΄μš©ν•˜μ—¬ μ΄λ™μ‹œν‚¨λ‹€. +[x] 우승자λ₯Ό μ°ΎλŠ”λ‹€. +[x] λΌμš΄λ“œλ§ˆλ‹€ μžλ™μ°¨λ“€μ˜ κ²°κ³Όλ₯Ό μ•Œλ €μ€€λ‹€. + +### βœ… controller κΈ°λŠ₯ +[x] μžλ™μ°¨ 이름을 μž…λ ₯을 λ°›λŠ”λ‹€. +[x] μ‹œλ„νšŸμˆ˜λ₯Ό μž…λ ₯λ°›λŠ”λ‹€. +[x] 우승자λ₯Ό μ°ΎλŠ”λ‹€. +[x] car game을 μ§„ν–‰ν•œλ‹€. + +### βœ… view κΈ°λŠ₯ +[x] μž…λ ₯을 λ°›λŠ”λ‹€. +[x] μž…λ ₯의 κΈ°λ³Έ 검증을 ν•œλ‹€. +[x] 좜λ ₯을 보여쀀닀. +[x] μ—λŸ¬λ₯Ό 좜λ ₯ν•œλ‹€. + +--- + +## πŸ˜• μž…λ ₯ μ—λŸ¬ +### βœ… μž…λ ₯ μ—λŸ¬ +[x] μž…λ ₯ λ¬Έμžμ—΄μ΄ 곡백일 경우 + +### βœ… μ–‘μˆ˜ μž…λ ₯ μ—λŸ¬ +[x] μ •μˆ˜κ°€ 아닐 경우 +[x] μ–‘μˆ˜κ°€ 아닐 경우 + +### βœ… car 이름 μž…λ ₯ +[x] 길이가 5κΈ€μž μ΄ν•˜μ—¬μ•Ό 함. +[x] μžλ™μ°¨ 이름이 곡백인 경우 +[x] μ€‘λ³΅λœ μžλ™μ°¨ 이름이 μžˆμ„ 경우 \ No newline at end of file diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000..ceb401a4 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,8 @@ +import controller.GameController; + +public class Application { + public static void main(String[] args) { + GameController gameController = new GameController(); + gameController.start(); + } +} diff --git a/src/main/java/Service/CarService.java b/src/main/java/Service/CarService.java new file mode 100644 index 00000000..2a100728 --- /dev/null +++ b/src/main/java/Service/CarService.java @@ -0,0 +1,69 @@ +package Service; + +import domain.Car; +import domain.NumberGenerator; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class CarService { + private static final Integer CAR_NAME_LENGTH = 5; + + private final List cars = new ArrayList<>(); + private final NumberGenerator numberGenerator; + + public CarService(NumberGenerator numberGenerator) { + this.numberGenerator = numberGenerator; + } + + public void addCars(String[] names) { + for (String name : names) { + validateCarName(name); + cars.add(new Car(name)); + } + } + + public Map run() { + Map roundResult = new HashMap<>(); + for (Car car : cars) { + car.move(numberGenerator.generate()); + roundResult.put(car.getName(), car.getDistance()); + } + return roundResult; + } + + public List findWinner() { + Car winner = cars.stream() + .max(Comparator.comparingInt(Car::getDistance)).get(); + return cars.stream() + .filter(car -> car.getDistance().equals(winner.getDistance())) + .map(Car::getName) + .collect(Collectors.toList()); + } + + /** + * validate + */ + private void validateCarName(String name) throws IllegalArgumentException { + validateCarNameLength(name); + validateCarNameDup(name); + } + + private void validateCarNameLength(String name) throws IllegalArgumentException { + if (name.length() > CAR_NAME_LENGTH) { + throw new IllegalArgumentException("μžλ™μ°¨ 이름이 λ„ˆλ¬΄ κΉλ‹ˆλ‹€."); + } + if (name.isEmpty()) { + throw new IllegalArgumentException("μžλ™μ°¨ 이름이 κ³΅λ°±μž…λ‹ˆλ‹€.,"); + } + } + + private void validateCarNameDup(String name) throws IllegalArgumentException { + if (cars.stream().anyMatch(car -> car.getName().equals(name))) { + throw new IllegalArgumentException("μžλ™μ°¨ 이름이 쀑볡 λ©λ‹ˆλ‹€."); + } + } +} diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java new file mode 100644 index 00000000..15afe047 --- /dev/null +++ b/src/main/java/controller/GameController.java @@ -0,0 +1,58 @@ +package controller; + +import Service.CarService; +import domain.RandomNumberGenerator; +import view.ErrorView; +import view.InputView; +import view.OutputView; + +public class GameController { + private final CarService carService; + private Integer roundNum; + + public GameController() { + this.carService = new CarService(new RandomNumberGenerator()); + } + + public void start() { + setUpCars(); + setUpRoundNum(); + runRound(); + findWinner(); + } + + private void setUpCars() { + boolean success = false; + do { + try { + carService.addCars(InputView.inputCarNames().split(",")); + success = true; + } catch (IllegalArgumentException e) { + ErrorView.printError(e); + } + } while (!success); + } + + private void setUpRoundNum() { + boolean success = false; + do { + try { + this.roundNum = Integer.parseInt(InputView.inputRoundNum()); + success = true; + } catch (IllegalArgumentException e) { + ErrorView.printError(e); + } + } while (!success); + } + + private void runRound() { + OutputView.printRoundResultInit(); + for (int i = 0; i < roundNum; i++) { + OutputView.printRoundResult(carService.run()); + } + } + + private void findWinner() { + OutputView.printWinner(carService.findWinner()); + } +} diff --git a/src/main/java/domain/Car.java b/src/main/java/domain/Car.java new file mode 100644 index 00000000..2e4bf508 --- /dev/null +++ b/src/main/java/domain/Car.java @@ -0,0 +1,45 @@ +package domain; + +public class Car { + private static final Integer BOUNDARY_VALUE = 4; + + private final String name; + private Integer distance; + + public Car(String name) { + validate(name); + this.name = name; + this.distance = 0; + } + + public void move(Integer number) { + if (number.compareTo(BOUNDARY_VALUE) >= 0) { + advance(); + } + } + + /** + * get + */ + public String getName() { + return this.name; + } + + public Integer getDistance() { + return this.distance; + } + + /** + * private λ©”μ„œλ“œ + */ + private void advance() { + this.distance++; + } + + private void validate(String name) { + if (name.length() > 6) { + throw new IllegalArgumentException("name length is greater than 5"); + } + } + +} diff --git a/src/main/java/domain/NumberGenerator.java b/src/main/java/domain/NumberGenerator.java new file mode 100644 index 00000000..ff72b20b --- /dev/null +++ b/src/main/java/domain/NumberGenerator.java @@ -0,0 +1,5 @@ +package domain; + +public interface NumberGenerator { + public Integer generate(); +} diff --git a/src/main/java/domain/RandomNumberGenerator.java b/src/main/java/domain/RandomNumberGenerator.java new file mode 100644 index 00000000..ae5626d2 --- /dev/null +++ b/src/main/java/domain/RandomNumberGenerator.java @@ -0,0 +1,20 @@ +package domain; + + +import java.util.Random; + +public class RandomNumberGenerator implements NumberGenerator{ + +// @Override +// public Integer generate(){ +// Random random = new Random(); +// random.setSeed(System.currentTimeMillis()); +// return random.nextInt(9); +// } + + @Override + public Integer generate() { + double randomValue = Math.random(); + return (int)(randomValue*10); + } +} diff --git a/src/main/java/view/ErrorView.java b/src/main/java/view/ErrorView.java new file mode 100644 index 00000000..cc7b6eae --- /dev/null +++ b/src/main/java/view/ErrorView.java @@ -0,0 +1,7 @@ +package view; + +public class ErrorView { + public static void printError(RuntimeException error){ + System.out.println("[ERROR] "+error.getMessage()); + } +} diff --git a/src/main/java/view/InputValidator.java b/src/main/java/view/InputValidator.java new file mode 100644 index 00000000..b5c4a2c4 --- /dev/null +++ b/src/main/java/view/InputValidator.java @@ -0,0 +1,33 @@ +package view; + +public class InputValidator { + public static void validateString(String input) { + isNotEmpty(input); + } + + public static void validatePositiveNumber(String input) { + isNotEmpty(input); + isInteger(input); + isPositive(input); + } + + private static void isNotEmpty(String input) { + if (input.isEmpty()) { + throw new IllegalArgumentException("μž…λ ₯ λ¬Έμžμ—΄μ΄ κ³΅λ°±μž…λ‹ˆλ‹€."); + } + } + + private static void isInteger(String input) { + try { + Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("μ •μˆ˜λ₯Ό μž…λ ₯ν•΄ μ£Όμ„Έμš”."); + } + } + + private static void isPositive(String input) { + if (Integer.parseInt(input) < 1) { + throw new IllegalArgumentException("μ–‘μˆ˜λ₯Ό μž…λ ₯ν•΄ μ£Όμ„Έμš”."); + } + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..9f02ec76 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,39 @@ +package view; + +import java.util.Scanner; + +public class InputView { + private static final Scanner sc = new Scanner(System.in); + + public static String inputCarNames() { + boolean success = false; + String input; + do { + System.out.println("κ²½μ£Όν•  μžλ™μ°¨ 이름을 μž…λ ₯ν•˜μ„Έμš”.(이름은 μ‰Όν‘œ(,) κΈ°μ€€μœΌλ‘œ ꡬ뢄)"); + input = sc.next(); + try { + InputValidator.validateString(input); + success = true; + } catch (IllegalArgumentException e) { + ErrorView.printError(e); + } + } while (!success); + return input; + } + + public static String inputRoundNum() { + boolean success = false; + String input; + do { + System.out.println("μ‹œλ„ν•  νšŒμˆ˜λŠ” λͺ‡νšŒμΈκ°€μš”?"); + input = sc.next(); + try { + InputValidator.validatePositiveNumber(input); + success = true; + } catch (IllegalArgumentException e) { + ErrorView.printError(e); + } + } while (!success); + return input; + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000..6803f622 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,22 @@ +package view; + +import java.util.List; +import java.util.Map; + +public class OutputView { + public static void printRoundResultInit() { + System.out.println(); + System.out.println("μ‹€ν–‰ κ²°κ³Ό"); + } + + public static void printRoundResult(Map cars) { + for (Map.Entry car : cars.entrySet()) { + System.out.println(car.getKey() + " : " + "-".repeat(car.getValue())); + } + System.out.println(); + } + + public static void printWinner(List winners){ + System.out.print("μ΅œμ’… 우승자 : "+String.join(", ",winners)); + } +} From 61aff5dcff859a1df6718a6348a89a4eab8e1b2e Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 5 Aug 2024 20:50:27 +0900 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20README.md=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6547a6e4..96f8ee2b 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,41 @@ # java-racingcar-precourse ---- ## πŸš€ κΈ°λŠ₯ λͺ©λ‘ ### βœ… car κΈ°λŠ₯ -[x] μ΄λ™ν•œλ‹€. -[x] 이름을 λ°˜ν™˜ν•œλ‹€. -[x] μœ„μΉ˜λ₯Ό λ°˜ν™˜ν•œλ‹€. +- [x] μ΄λ™ν•œλ‹€. +- [x] 이름을 λ°˜ν™˜ν•œλ‹€. +- [x] μœ„μΉ˜λ₯Ό λ°˜ν™˜ν•œλ‹€. ### βœ… car service κΈ°λŠ₯ -[x] μžλ™μ°¨λ“€μ„ λ§Œλ“ λ‹€. -[x] μžλ™μ°¨λ“€μ„ random값을 μ΄μš©ν•˜μ—¬ μ΄λ™μ‹œν‚¨λ‹€. -[x] 우승자λ₯Ό μ°ΎλŠ”λ‹€. -[x] λΌμš΄λ“œλ§ˆλ‹€ μžλ™μ°¨λ“€μ˜ κ²°κ³Όλ₯Ό μ•Œλ €μ€€λ‹€. +- [x] μžλ™μ°¨λ“€μ„ λ§Œλ“ λ‹€. +- [x] μžλ™μ°¨λ“€μ„ random값을 μ΄μš©ν•˜μ—¬ μ΄λ™μ‹œν‚¨λ‹€. +- [x] 우승자λ₯Ό μ°ΎλŠ”λ‹€. +- [x] λΌμš΄λ“œλ§ˆλ‹€ μžλ™μ°¨λ“€μ˜ κ²°κ³Όλ₯Ό μ•Œλ €μ€€λ‹€. ### βœ… controller κΈ°λŠ₯ -[x] μžλ™μ°¨ 이름을 μž…λ ₯을 λ°›λŠ”λ‹€. -[x] μ‹œλ„νšŸμˆ˜λ₯Ό μž…λ ₯λ°›λŠ”λ‹€. -[x] 우승자λ₯Ό μ°ΎλŠ”λ‹€. -[x] car game을 μ§„ν–‰ν•œλ‹€. +- [x] μžλ™μ°¨ 이름을 μž…λ ₯을 λ°›λŠ”λ‹€. +- [x] μ‹œλ„νšŸμˆ˜λ₯Ό μž…λ ₯λ°›λŠ”λ‹€. +- [x] 우승자λ₯Ό μ°ΎλŠ”λ‹€. +- [x] car game을 μ§„ν–‰ν•œλ‹€. ### βœ… view κΈ°λŠ₯ -[x] μž…λ ₯을 λ°›λŠ”λ‹€. -[x] μž…λ ₯의 κΈ°λ³Έ 검증을 ν•œλ‹€. -[x] 좜λ ₯을 보여쀀닀. -[x] μ—λŸ¬λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] μž…λ ₯을 λ°›λŠ”λ‹€. +- [x] μž…λ ₯의 κΈ°λ³Έ 검증을 ν•œλ‹€. +- [x] 좜λ ₯을 보여쀀닀. +- [x] μ—λŸ¬λ₯Ό 좜λ ₯ν•œλ‹€. ---- ## πŸ˜• μž…λ ₯ μ—λŸ¬ ### βœ… μž…λ ₯ μ—λŸ¬ -[x] μž…λ ₯ λ¬Έμžμ—΄μ΄ 곡백일 경우 +- [x] μž…λ ₯ λ¬Έμžμ—΄μ΄ 곡백일 경우 ### βœ… μ–‘μˆ˜ μž…λ ₯ μ—λŸ¬ -[x] μ •μˆ˜κ°€ 아닐 경우 -[x] μ–‘μˆ˜κ°€ 아닐 경우 +- [x] μ •μˆ˜κ°€ 아닐 경우 +- [x] μ–‘μˆ˜κ°€ 아닐 경우 ### βœ… car 이름 μž…λ ₯ -[x] 길이가 5κΈ€μž μ΄ν•˜μ—¬μ•Ό 함. -[x] μžλ™μ°¨ 이름이 곡백인 경우 -[x] μ€‘λ³΅λœ μžλ™μ°¨ 이름이 μžˆμ„ 경우 \ No newline at end of file +- [x] 길이가 5κΈ€μž μ΄ν•˜μ—¬μ•Ό 함. +- [x] μžλ™μ°¨ 이름이 곡백인 경우 +- [x] μ€‘λ³΅λœ μžλ™μ°¨ 이름이 μžˆμ„ 경우 \ No newline at end of file From bdc2949c07c0659f76c276ff6ab50a5f95360d6d Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 5 Aug 2024 23:11:36 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20test=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Service/CarService.java | 69 -------------- src/main/java/controller/GameController.java | 5 +- src/main/java/domain/Car.java | 19 +--- src/main/java/domain/CarService.java | 97 ++++++++++++++++++++ src/test/java/domain/CarServiceTest.java | 90 ++++++++++++++++++ src/test/java/domain/CarTest.java | 46 ++++++++++ 6 files changed, 240 insertions(+), 86 deletions(-) delete mode 100644 src/main/java/Service/CarService.java create mode 100644 src/main/java/domain/CarService.java create mode 100644 src/test/java/domain/CarServiceTest.java create mode 100644 src/test/java/domain/CarTest.java diff --git a/src/main/java/Service/CarService.java b/src/main/java/Service/CarService.java deleted file mode 100644 index 2a100728..00000000 --- a/src/main/java/Service/CarService.java +++ /dev/null @@ -1,69 +0,0 @@ -package Service; - -import domain.Car; -import domain.NumberGenerator; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class CarService { - private static final Integer CAR_NAME_LENGTH = 5; - - private final List cars = new ArrayList<>(); - private final NumberGenerator numberGenerator; - - public CarService(NumberGenerator numberGenerator) { - this.numberGenerator = numberGenerator; - } - - public void addCars(String[] names) { - for (String name : names) { - validateCarName(name); - cars.add(new Car(name)); - } - } - - public Map run() { - Map roundResult = new HashMap<>(); - for (Car car : cars) { - car.move(numberGenerator.generate()); - roundResult.put(car.getName(), car.getDistance()); - } - return roundResult; - } - - public List findWinner() { - Car winner = cars.stream() - .max(Comparator.comparingInt(Car::getDistance)).get(); - return cars.stream() - .filter(car -> car.getDistance().equals(winner.getDistance())) - .map(Car::getName) - .collect(Collectors.toList()); - } - - /** - * validate - */ - private void validateCarName(String name) throws IllegalArgumentException { - validateCarNameLength(name); - validateCarNameDup(name); - } - - private void validateCarNameLength(String name) throws IllegalArgumentException { - if (name.length() > CAR_NAME_LENGTH) { - throw new IllegalArgumentException("μžλ™μ°¨ 이름이 λ„ˆλ¬΄ κΉλ‹ˆλ‹€."); - } - if (name.isEmpty()) { - throw new IllegalArgumentException("μžλ™μ°¨ 이름이 κ³΅λ°±μž…λ‹ˆλ‹€.,"); - } - } - - private void validateCarNameDup(String name) throws IllegalArgumentException { - if (cars.stream().anyMatch(car -> car.getName().equals(name))) { - throw new IllegalArgumentException("μžλ™μ°¨ 이름이 쀑볡 λ©λ‹ˆλ‹€."); - } - } -} diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 15afe047..5770eabb 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,7 +1,8 @@ package controller; -import Service.CarService; +import domain.CarService; import domain.RandomNumberGenerator; +import java.util.Arrays; import view.ErrorView; import view.InputView; import view.OutputView; @@ -25,7 +26,7 @@ private void setUpCars() { boolean success = false; do { try { - carService.addCars(InputView.inputCarNames().split(",")); + carService.addCars(Arrays.stream(InputView.inputCarNames().split(",")).toList()); success = true; } catch (IllegalArgumentException e) { ErrorView.printError(e); diff --git a/src/main/java/domain/Car.java b/src/main/java/domain/Car.java index 2e4bf508..003cb90e 100644 --- a/src/main/java/domain/Car.java +++ b/src/main/java/domain/Car.java @@ -7,7 +7,6 @@ public class Car { private Integer distance; public Car(String name) { - validate(name); this.name = name; this.distance = 0; } @@ -18,6 +17,10 @@ public void move(Integer number) { } } + private void advance() { + this.distance++; + } + /** * get */ @@ -28,18 +31,4 @@ public String getName() { public Integer getDistance() { return this.distance; } - - /** - * private λ©”μ„œλ“œ - */ - private void advance() { - this.distance++; - } - - private void validate(String name) { - if (name.length() > 6) { - throw new IllegalArgumentException("name length is greater than 5"); - } - } - } diff --git a/src/main/java/domain/CarService.java b/src/main/java/domain/CarService.java new file mode 100644 index 00000000..fd74dd1c --- /dev/null +++ b/src/main/java/domain/CarService.java @@ -0,0 +1,97 @@ +package domain; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class CarService { + private static final Integer CAR_NAME_LENGTH = 5; + + private final List cars = new ArrayList<>(); + private final NumberGenerator numberGenerator; + + public CarService(NumberGenerator numberGenerator) { + this.numberGenerator = numberGenerator; + } + + // public void addCars(String[] names) { +// for (String name : names) { +// validateCarName(name); +// cars.add(new Car(name)); +// } +// } + public void addCars(List names) { + validateCarNames(names); + for (String name : names) { + cars.add(new Car(name)); + } + } + + public Map run() { + Map roundResult = new HashMap<>(); + for (Car car : cars) { + car.move(numberGenerator.generate()); + roundResult.put(car.getName(), car.getDistance()); + } + return roundResult; + } + + public List findWinner() { + Car winner = cars.stream() + .max(Comparator.comparingInt(Car::getDistance)).get(); + return cars.stream() + .filter(car -> car.getDistance().equals(winner.getDistance())) + .map(Car::getName) + .collect(Collectors.toList()); + } + + /** + * validate + */ + private void validateCarNames(List names) throws IllegalArgumentException { + validateCarNamesEmpty(names); + validateCarNamesLength(names); + validateCarNameDup(names); + } + + private void validateCarNamesLength(List names) throws IllegalArgumentException { + if (names.stream().anyMatch(name -> name.length() > CAR_NAME_LENGTH)) { + throw new IllegalArgumentException("μžλ™μ°¨ 이름이 λ„ˆλ¬΄ κΉλ‹ˆλ‹€."); + } + } + + private void validateCarNamesEmpty(List names) throws IllegalArgumentException { + if (names.stream().anyMatch(String::isEmpty)) { + throw new IllegalArgumentException("μžλ™μ°¨ 이름이 κ³΅λ°±μž…λ‹ˆλ‹€."); + } + } + + private void validateCarNameDup(List names) throws IllegalArgumentException { + if (names.stream().distinct().count() < names.size()) { + throw new IllegalArgumentException("μžλ™μ°¨ 이름이 쀑볡 λ©λ‹ˆλ‹€."); + } + } + + // private void validateCarName(String name) throws IllegalArgumentException { +// validateCarNameLength(name); +// validateCarNameDup(name); +// } +// +// private void validateCarNameLength(String name) throws IllegalArgumentException { +// if (name.length() > CAR_NAME_LENGTH) { +// throw new IllegalArgumentException("μžλ™μ°¨ 이름이 λ„ˆλ¬΄ κΉλ‹ˆλ‹€."); +// } +// if (name.isEmpty()) { +// throw new IllegalArgumentException("μžλ™μ°¨ 이름이 κ³΅λ°±μž…λ‹ˆλ‹€."); +// } +// } +// +// private void validateCarNameDup(String name) throws IllegalArgumentException { +// if (cars.stream().anyMatch(car -> car.getName().equals(name))) { +// throw new IllegalArgumentException("μžλ™μ°¨ 이름이 쀑볡 λ©λ‹ˆλ‹€."); +// } +// } +} diff --git a/src/test/java/domain/CarServiceTest.java b/src/test/java/domain/CarServiceTest.java new file mode 100644 index 00000000..f648f974 --- /dev/null +++ b/src/test/java/domain/CarServiceTest.java @@ -0,0 +1,90 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CarServiceTest { + static class FakeNumberGenerator implements NumberGenerator { +// private static final Integer[] numbers = {4,2,5,8,8,5,4,5,6,1,2,3,3,3,7}; + private static final Integer[] numbers = {4,5,6,4,5,6,4,5,6,4,5,6,4,5,6}; + private int i = 0; + + @Override + public Integer generate(){ + return numbers[i++]; + } + + public static int getNumbersSize(){ + return numbers.length; + } + } + + CarService carService; + + @BeforeEach + void setCarService(){ + this.carService = new CarService(new FakeNumberGenerator()); + } + + @DisplayName("car 이름 쀑볡 ν…ŒμŠ€νŠΈ") + @Test + void car_names_dup_test() { + //given + List names = List.of("pobi", "woni", "jun", "pobi"); + //when + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> carService.addCars(names)); + //then + // μ˜ˆμ™Έμ˜ νƒ€μž… 확인 + assertThat(exception).isInstanceOf(IllegalArgumentException.class); + // μ˜ˆμ™Έ λ©”μ‹œμ§€ 확인 + assertThat(exception.getMessage()).isEqualTo("μžλ™μ°¨ 이름이 쀑볡 λ©λ‹ˆλ‹€."); + } + + @DisplayName("car 이름 곡백 ν…ŒμŠ€νŠΈ") + @Test + void car_names_empty_test() { + //given + List names = List.of("pobi", "woni", "jun", ""); + //when + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> carService.addCars(names)); + //then + // μ˜ˆμ™Έμ˜ νƒ€μž… 확인 + assertThat(exception).isInstanceOf(IllegalArgumentException.class); + // μ˜ˆμ™Έ λ©”μ‹œμ§€ 확인 + assertThat(exception.getMessage()).isEqualTo("μžλ™μ°¨ 이름이 κ³΅λ°±μž…λ‹ˆλ‹€."); + } + + @DisplayName("car 이름 길이 ν…ŒμŠ€νŠΈ") + @Test + void car_names_length_test() { + //given + List names = List.of("pobi", "woni", "abcdef"); + //when + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> carService.addCars(names)); + //then + // μ˜ˆμ™Έμ˜ νƒ€μž… 확인 + assertThat(exception).isInstanceOf(IllegalArgumentException.class); + // μ˜ˆμ™Έ λ©”μ‹œμ§€ 확인 + assertThat(exception.getMessage()).isEqualTo("μžλ™μ°¨ 이름이 λ„ˆλ¬΄ κΉλ‹ˆλ‹€."); + } + + @DisplayName("κ²½μ£Ό 우승자 μ°ΎκΈ°") + @Test + void car_find_winner_test() { + //given + List names = List.of("pobi", "woni", "jun"); + //when + carService.addCars(names); + for(int i=0;i winners = carService.findWinner(); + //then + assertThat(winners).isEqualTo(List.of("pobi","woni","jun")); + } +} \ No newline at end of file diff --git a/src/test/java/domain/CarTest.java b/src/test/java/domain/CarTest.java new file mode 100644 index 00000000..ee674aa5 --- /dev/null +++ b/src/test/java/domain/CarTest.java @@ -0,0 +1,46 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CarTest { + + @DisplayName("car μ „μ§„ ν…ŒμŠ€νŠΈ") + @Test + void move_test_when_advance() { + //given + Car car = new Car("advance"); + //when + car.move(4); + //then + assertThat(car.getDistance()).isEqualTo(1); + } + + @DisplayName("car 멈좀 ν…ŒμŠ€νŠΈ") + @Test + void move_test_when_stop() { + //given + Car car = new Car("stop"); + //when + car.move(3); + //then + assertThat(car.getDistance()).isEqualTo(0); + } + + @DisplayName("car move ν…ŒμŠ€νŠΈ") + @Test + void move_test() { + //given + Car car = new Car("move"); + //when + car.move(0); + car.move(8); + car.move(9); + car.move(5); + //then + assertThat(car.getDistance()).isEqualTo(3); + } + +} \ No newline at end of file