diff --git a/src/main/java/calculator/application/CalculatorApp.java b/src/main/java/calculator/application/CalculatorApp.java new file mode 100644 index 0000000..f70da0a --- /dev/null +++ b/src/main/java/calculator/application/CalculatorApp.java @@ -0,0 +1,25 @@ +package calculator.application; + +import calculator.domain.Calculator; +import calculator.domain.InputMachine; +import calculator.view.ScreenMassage; + +public class CalculatorApp { + public static void main(String[] args) { + InputMachine inputMachine = new InputMachine(); + Calculator calculator = new Calculator(); + ScreenMassage screen = new ScreenMassage(); + + screen.showMassage(); + + int answer = 0; + try { + String userInput = inputMachine.getUserInput(); + answer = calculator.getTotalCalculation(userInput); + } catch (Exception e) { + screen.showErrorMassage(e); + } + + screen.showResult(answer); + } +} diff --git a/src/main/java/calculator/domain/Calculator.java b/src/main/java/calculator/domain/Calculator.java new file mode 100644 index 0000000..e7baca0 --- /dev/null +++ b/src/main/java/calculator/domain/Calculator.java @@ -0,0 +1,59 @@ +package calculator.domain; + +public class Calculator { + public int getTotalCalculation(String arithmeticOperation) { + StringReader reader = new StringReader(); + + int[] numbers = reader.extractNumber(arithmeticOperation); + String[] operators = reader.extractOperator(arithmeticOperation); + + int answer = 0; + + for (int i = 0; i < operators.length; i += 1) { + if (operators[i].equals("+")) { + int value = this.add(numbers[i], numbers[i + 1]); + numbers[i + 1] = value; + answer = value; + continue; + } + + if (operators[i].equals("-")) { + int value = this.subtract(numbers[i], numbers[i + 1]); + numbers[i + 1] = value; + answer = value; + continue; + } + + if (operators[i].equals("*")) { + int value = this.multiply(numbers[i], numbers[i + 1]); + numbers[i + 1] = value; + answer = value; + continue; + } + + if (operators[i].equals("/")) { + int value = this.divide(numbers[i], numbers[i + 1]); + numbers[i + 1] = value; + answer = value; + } + } + + return answer; + } + + public int add(int a, int b) { + return a + b; + } + + public int subtract(int a, int b) { + return a - b; + } + + public int multiply(int a, int b) { + return a * b; + } + + public int divide(int a, int b) { + return a / b; + } +} diff --git a/src/main/java/calculator/domain/InputMachine.java b/src/main/java/calculator/domain/InputMachine.java new file mode 100644 index 0000000..cc9197b --- /dev/null +++ b/src/main/java/calculator/domain/InputMachine.java @@ -0,0 +1,20 @@ +package calculator.domain; + +import java.util.Scanner; + +public class InputMachine { + public String getUserInput() { + Scanner input = new Scanner(System.in); + String userInput = input.nextLine(); + + validateUserInput(userInput); + + return userInput; + } + + public void validateUserInput(String str) { + if (str == null || str == "") { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/calculator/domain/StringReader.java b/src/main/java/calculator/domain/StringReader.java new file mode 100644 index 0000000..c5dc869 --- /dev/null +++ b/src/main/java/calculator/domain/StringReader.java @@ -0,0 +1,104 @@ +package calculator.domain; + +import java.util.*; +import java.util.regex.*; + +public class StringReader { + public int[] extractNumber(String str) { + if (this.checkWeird(str)) { + throw new IllegalArgumentException(); + } + + String[] arr = str.split(" "); + + removeUnnecessaryParts(arr); + ArrayList pureNumbers = convertArrayToArrayList(arr); + ArrayList result = considerBracket(pureNumbers); + + return extractNumbersFromBracket(result); + } + + public String[] extractOperator(String str) { + if (this.checkWeird(str)) { + throw new IllegalArgumentException(); + } + + String[] arr = str.split(" "); + + ArrayList pureOperators = convertArrayToArrayList(arr); + Object[] objOperators = pureOperators.stream() + .filter(v -> Pattern.matches("[\\*\\-\\+\\/]", v)) + .toArray(); + + return convertObjectArrayToStringArray(objOperators); + } + + public boolean checkWeird(String str) { + String weirds = str.replaceAll("[0-9\\+\\-\\*\\/\\' '\\(\\)]", ""); + return weirds.length() > 0; + } + + private void removeUnnecessaryParts(String[] arr) { + for (int i = 0; i < arr.length; i += 1) { + arr[i] = arr[i].replaceAll("[^0-9\\-\\(\\)]", ""); + } + } + + private ArrayList convertArrayToArrayList(String[] arr) { + ArrayList arrayList = new ArrayList<>(); + + for (String e : arr) { + arrayList.add(e); + } + + return arrayList; + } + + private String[] convertObjectArrayToStringArray(Object[] objArr) { + String[] strArr = new String[objArr.length]; + + int index = 0; + for (Object operator: objArr) { + strArr[index] = operator.toString(); + index += 1; + } + + return strArr; + } + + private ArrayList considerBracket(ArrayList arrayList) { + ArrayList result = new ArrayList<>(); + + for (int i = 0; i < arrayList.size(); i += 1) { + String e = arrayList.get(i); + if (e.length() > 0 && e.charAt(0) == '(') { + result.add(e); + continue; + } + + if (Pattern.matches("[0-9]{1,}", e)) { + result.add(e); + } + } + + return result; + } + + private int[] extractNumbersFromBracket(ArrayList arrayList) { + int[] answer = new int[arrayList.size()]; + + for (int i = 0; i < answer.length; i += 1) { + String e = arrayList.get(i); + + if (e.charAt(0) == '(') { + String substr = e.substring(1, e.length() - 1); + answer[i] = Integer.parseInt(substr); + continue; + } + + answer[i] = Integer.parseInt(e); + } + + return answer; + } +} diff --git a/src/main/java/calculator/view/ScreenMassage.java b/src/main/java/calculator/view/ScreenMassage.java new file mode 100644 index 0000000..c583175 --- /dev/null +++ b/src/main/java/calculator/view/ScreenMassage.java @@ -0,0 +1,15 @@ +package calculator.view; + +public class ScreenMassage { + public void showMassage() { + System.out.println("수식을 입력해주세요. 계산은 제가 합니다 ㅋ"); + } + + public void showResult(int result) { + System.out.printf("답은 %d 입니다.", result); + } + + public void showErrorMassage(Exception e) { + System.out.println(e); + } +} diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/racingcar/application/RacingCarApp.java b/src/main/java/racingcar/application/RacingCarApp.java new file mode 100644 index 0000000..e2a84ee --- /dev/null +++ b/src/main/java/racingcar/application/RacingCarApp.java @@ -0,0 +1,31 @@ +package racingcar.application; + +import racingcar.domain.Car; +import racingcar.domain.CarList; +import racingcar.view.InputView; +import racingcar.view.ResultView; + +import java.util.Arrays; + +public class RacingCarApp { + public static void main(String[] args) { + InputView inputView = new InputView(); + + inputView.whatCarNamesAre(); + String nameOfCars = inputView.getUserStringInput(); + inputView.howManyTimes(); + int numberOfTimes = inputView.getUserIntInput(); + + CarList carList = new CarList(nameOfCars); + ResultView resultView = new ResultView(); + + for (int i = 0; i < numberOfTimes; i += 1) { + carList.moveAllCars(); + + Car[] cars = carList.getCars(); + resultView.showResult(cars); + } + + resultView.showWinner(carList.getWinners()); + } +} diff --git a/src/main/java/racingcar/domain/Car.java b/src/main/java/racingcar/domain/Car.java new file mode 100644 index 0000000..2b34803 --- /dev/null +++ b/src/main/java/racingcar/domain/Car.java @@ -0,0 +1,29 @@ +package racingcar.domain; + +public class Car implements Comparable { + private int status = 0; + private final String name; + + public Car(String carName) { + this.name = carName; + } + + public void move(int randomNumber) { + if (randomNumber >= 4) { + this.status += 1; + } + } + + public int getStatus() { + return this.status; + } + + public String getName() { + return this.name; + } + + public int compareTo(Object obj) { + Car car = (Car)obj; + return this.status < car.getStatus() ? 1 : -1; + } +} diff --git a/src/main/java/racingcar/domain/CarList.java b/src/main/java/racingcar/domain/CarList.java new file mode 100644 index 0000000..a372ae9 --- /dev/null +++ b/src/main/java/racingcar/domain/CarList.java @@ -0,0 +1,49 @@ +package racingcar.domain; + +import racingcar.domain.Car; + +import java.util.ArrayList; +import java.util.Arrays; + +public class CarList { + private final Car[] cars; + + public CarList(String carNames) { + String[] names = carNames.split(","); + cars = new Car[names.length]; + for (int i = 0; i < names.length; i += 1) { + cars[i] = new Car(names[i]); + } + } + + public Car[] getCars() { + return cars; + } + + public void moveAllCars() { + RandomGenerator randomGenerator = new RandomGenerator(); + for (Car car : cars) { + car.move(randomGenerator.get()); + } + } + + public Object[] getWinners() { + Arrays.sort(cars); + Car winner = cars[0]; + + ArrayList winners = new ArrayList<>(); + winners.add(winner.getName()); + + for (int i = 1; i < cars.length; i += 1) { + addWinner(winners, cars[i], winner); + } + + return winners.toArray(); + } + + private void addWinner(ArrayList winners, Car current, Car existingWinner) { + if (current.getStatus() == existingWinner.getStatus()) { + winners.add(current.getName()); + } + } +} diff --git a/src/main/java/racingcar/domain/RandomGenerator.java b/src/main/java/racingcar/domain/RandomGenerator.java new file mode 100644 index 0000000..7a44421 --- /dev/null +++ b/src/main/java/racingcar/domain/RandomGenerator.java @@ -0,0 +1,10 @@ +package racingcar.domain; + +import java.util.Random; + +public class RandomGenerator { + public int get() { + Random random = new Random(); + return Math.abs(random.nextInt()) % 9; + } +} diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java new file mode 100644 index 0000000..4f1a3b4 --- /dev/null +++ b/src/main/java/racingcar/view/InputView.java @@ -0,0 +1,28 @@ +package racingcar.view; + +import java.util.Scanner; + +public class InputView { + public int getUserIntInput() { + try { + Scanner input = new Scanner(System.in); + return input.nextInt(); + } catch (Exception e) { + System.out.println("숫자로 다시 입력해주세요"); + return this.getUserIntInput(); + } + } + + public String getUserStringInput() { + Scanner input = new Scanner(System.in); + return input.nextLine(); + } + + public void whatCarNamesAre() { + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분합니다)"); + } + + public void howManyTimes() { + System.out.println("몇 번 시도하시겠습니까?"); + } +} diff --git a/src/main/java/racingcar/view/ResultView.java b/src/main/java/racingcar/view/ResultView.java new file mode 100644 index 0000000..0176395 --- /dev/null +++ b/src/main/java/racingcar/view/ResultView.java @@ -0,0 +1,27 @@ +package racingcar.view; + +import racingcar.domain.Car; + +public class ResultView { + public void showResult(Car[] cars) { + for (Car car : cars) { + this.showCarStatus(car); + } + System.out.println("──────────────────────"); + } + + private void showCarStatus(Car car) { + System.out.printf("[%s] ", car.getName()); + for (int i = 0; i < car.getStatus(); i += 1) { + System.out.print("-"); + } + System.out.println(""); + } + + public void showWinner(Object[] cars) { + System.out.print("최종 우승: "); + for (Object car : cars) { + System.out.printf("%s ", car); + } + } +} diff --git a/src/test/java/calculator/CalculatorTest.java b/src/test/java/calculator/CalculatorTest.java new file mode 100644 index 0000000..72f8b3d --- /dev/null +++ b/src/test/java/calculator/CalculatorTest.java @@ -0,0 +1,40 @@ +package calculator; + +import calculator.domain.Calculator; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("Calculator") +public class CalculatorTest { + Calculator calculator = new Calculator(); + + @Test + @DisplayName("add") + public void add() { + assertThat(calculator.add(1, 1)).isEqualTo(2); + assertThat(calculator.add(-1, 1)).isEqualTo(0); + } + + @Test + @DisplayName("subtract") + public void subtract() { + assertThat(calculator.subtract(1, 1)).isEqualTo(0); + assertThat(calculator.subtract(-1, 1)).isEqualTo(-2); + } + + @Test + @DisplayName("multiply") + public void multiply() { + assertThat(calculator.multiply(2, 2)).isEqualTo(4); + assertThat(calculator.multiply(-2, 5)).isEqualTo(-10); + } + + @Test + @DisplayName("divide") + public void divide() { + assertThat(calculator.divide(6, 2)).isEqualTo(3); + assertThat(calculator.divide(3, 2)).isEqualTo(1); + } +} diff --git a/src/test/java/calculator/InputMachineTest.java b/src/test/java/calculator/InputMachineTest.java new file mode 100644 index 0000000..5849b10 --- /dev/null +++ b/src/test/java/calculator/InputMachineTest.java @@ -0,0 +1,28 @@ +package calculator; + +import calculator.domain.InputMachine; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("InputMachine") +public class InputMachineTest { + @Test + @DisplayName("validateUserInput") + public void validateUserInput() { + InputMachine inputMachine = new InputMachine(); + + assertThatThrownBy(() -> { + inputMachine.validateUserInput(""); + }) + .isInstanceOf(IllegalArgumentException.class) + .hasToString("java.lang.IllegalArgumentException"); + + assertThatThrownBy(() -> { + inputMachine.validateUserInput(null); + }) + .isInstanceOf(IllegalArgumentException.class) + .hasToString("java.lang.IllegalArgumentException"); + } +} diff --git a/src/test/java/calculator/StringReaderTest.java b/src/test/java/calculator/StringReaderTest.java new file mode 100644 index 0000000..496df41 --- /dev/null +++ b/src/test/java/calculator/StringReaderTest.java @@ -0,0 +1,75 @@ +package calculator; + +import calculator.domain.StringReader; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("StringReader") +public class StringReaderTest { + @Test + @DisplayName("extractNumber") + public void extractNumber() { + StringReader stringReader = new StringReader(); + + String input1 = "1 + 2 * 3"; + int[] expected1= {1, 2, 3}; + assertThat(stringReader.extractNumber(input1)).isEqualTo(expected1); + + String input2 = "11 - 2 * 3 + 2"; + int[] expected2 = {11, 2, 3, 2}; + assertThat(stringReader.extractNumber(input2)).isEqualTo(expected2); + + String input3 = "(-2) * (-3) + (-10)"; + int[] expected3 = {-2, -3, -10}; + assertThat(stringReader.extractNumber(input3)).isEqualTo(expected3); + + String input4 = "1 & 3 + 5"; + assertThatThrownBy(() -> { + stringReader.extractNumber(input4); + }) + .hasToString("java.lang.IllegalArgumentException") + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("extractOperator") + public void extractOperator() { + StringReader stringReader = new StringReader(); + + String input1 = "1 + 2 * 3"; + String[] expected1= {"+", "*"}; + assertThat(stringReader.extractOperator(input1)).isEqualTo(expected1); + + String input2 = "11 - 2 * 3 + 2"; + String[] expected2 = {"-", "*", "+"}; + assertThat(stringReader.extractOperator(input2)).isEqualTo(expected2); + + String input3 = "(-2) * 3 + 4"; + String[] expected3 = {"*", "+"}; + assertThat(stringReader.extractOperator(input3)).isEqualTo(expected3); + + String input4 = "1 & 3 + 5"; + assertThatThrownBy(() -> { + stringReader.extractNumber(input4); + }) + .hasToString("java.lang.IllegalArgumentException") + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @CsvSource(value = { + "1 + 2 * 3, false", + "4 # 2 * 3, true", + }) + @DisplayName("checkWeird") + public void checkWeird(String input, boolean expected) { + StringReader stringReader = new StringReader(); + + assertThat(stringReader.checkWeird(input)).isEqualTo(expected); + } +} diff --git a/src/test/java/empty.txt b/src/test/java/empty.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/method/CharAtTest.java b/src/test/java/method/CharAtTest.java new file mode 100644 index 0000000..671fcc4 --- /dev/null +++ b/src/test/java/method/CharAtTest.java @@ -0,0 +1,31 @@ +package method; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CharAtTest { + @ParameterizedTest + @CsvSource(value = {"0:a", "1:b", "2:c"}, delimiter = ':') + @DisplayName("test charAt() with in of bound") + public void charAt(int input, char expected) { + String abc = "abc"; + assertEquals(expected, abc.charAt(input)); + } + + @Test + @DisplayName("test charAt() with out of bound") + public void charAtException() { + String abc = "abc"; + + assertThatThrownBy(() -> { + System.out.println(abc.charAt(3)); + }) + .isInstanceOf(IndexOutOfBoundsException.class) + .hasMessageContaining("String index out of range: 3"); + } +} diff --git a/src/test/java/method/SetTest.java b/src/test/java/method/SetTest.java new file mode 100644 index 0000000..0470634 --- /dev/null +++ b/src/test/java/method/SetTest.java @@ -0,0 +1,45 @@ +package method; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.util.HashSet; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SetTest { + private Set numbers; + + @BeforeEach + void setUp() { + numbers = new HashSet<>(); + numbers.add(1); + numbers.add(1); + numbers.add(2); + numbers.add(3); + } + + @Test + @DisplayName("test size()") + public void size() { + assertThat(numbers.size()).isEqualTo(3); + } + + @ParameterizedTest + @CsvSource(value = { + "1:true", + "2:true", + "3:true", + "4:false", + "5:false", + }, delimiter = ':') + @DisplayName("test contains()") + public void contains(int input, boolean expected) { + assertEquals(expected, numbers.contains(input)); + } +} diff --git a/src/test/java/method/SplitTest.java b/src/test/java/method/SplitTest.java new file mode 100644 index 0000000..445538f --- /dev/null +++ b/src/test/java/method/SplitTest.java @@ -0,0 +1,19 @@ +package method; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +public class SplitTest { + @Test + @DisplayName("test split()") + public void splitTest() { + String testString = "1,2"; + String[] splitted = testString.split(","); + + assertThat(splitted).contains("1"); + assertThat(splitted).contains("2"); + assertThat(splitted).containsExactly("1", "2"); + } +} diff --git a/src/test/java/method/SubstringTest.java b/src/test/java/method/SubstringTest.java new file mode 100644 index 0000000..438b51c --- /dev/null +++ b/src/test/java/method/SubstringTest.java @@ -0,0 +1,17 @@ +package method; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SubstringTest { + @Test + @DisplayName("test substring()") + public void substringTest() { + String testString ="(1,2)"; + String testSubString = testString.substring(1, 4); + + assertThat(testSubString).isEqualTo("1,2"); + } +} diff --git a/src/test/java/racingcar/CarTest.java b/src/test/java/racingcar/CarTest.java new file mode 100644 index 0000000..441b67b --- /dev/null +++ b/src/test/java/racingcar/CarTest.java @@ -0,0 +1,36 @@ +package racingcar; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import racingcar.domain.Car; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CarTest { + @ParameterizedTest + @CsvSource(value = { + "1, 0", + "2, 0", + "3, 0", + "4, 1", + "5, 1", + "9, 1", + }) + @DisplayName("move and getStatus") + public void moveAndGetStatus(int input, int expected) { + Car car = new Car("Audi"); + + car.move(input); + assertThat(car.getStatus()).isEqualTo(expected); + } + + @Test + public void getName() { + Car car = new Car("Audi"); + + assertThat(car.getName()).isEqualTo("Audi"); + } +} diff --git a/src/test/java/racingcar/RandomGeneratorTest.java b/src/test/java/racingcar/RandomGeneratorTest.java new file mode 100644 index 0000000..40da526 --- /dev/null +++ b/src/test/java/racingcar/RandomGeneratorTest.java @@ -0,0 +1,17 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racingcar.domain.RandomGenerator; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RandomGeneratorTest { + @Test + @DisplayName("get") + public void get() { + RandomGenerator randomGenerator = new RandomGenerator(); + assertThat(randomGenerator.get() >= 0).isTrue(); + assertThat(randomGenerator.get() <= 9).isTrue(); + } +}