From 094c88b1e7a0272e973bcef3d8fd039282e4aac5 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:02:18 +0900 Subject: [PATCH 01/40] =?UTF-8?q?docs:=20=EC=9E=90=ED=8C=90=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EB=AA=A9=EB=A1=9D/=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Readme.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/Readme.md diff --git a/docs/Readme.md b/docs/Readme.md new file mode 100644 index 000000000..c3025b255 --- /dev/null +++ b/docs/Readme.md @@ -0,0 +1,23 @@ +## 기능 목록 + +- InputView + - 자판기가 보유하고 있는 금액 입력 + - 상품명, 가격, 수량을 입력 + - 구매할 상품명 입력 + +- MakeRandomCoin + - 자판기가 보유하고 있는 금액으로 동전을 무작위로 생성 + +- Products + - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. + - 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. + +- Calculator + - 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. + - 잔돈을 돌려줄 때 현재 보유한 최소 개수의 동전으로 잔돈을 돌려준다. + - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. + - 반환되지 않은 금액은 자판기에 남는다. + +## 에러 처리 +- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. +- 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. \ No newline at end of file From 68759f0ad9f8409d5e34b8fc08ceb542bc07d405 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:02:48 +0900 Subject: [PATCH 02/40] =?UTF-8?q?feat:=20InputView=20inputMachineAmountHel?= =?UTF-8?q?d=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/InputView.java | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/vendingmachine/InputView.java diff --git a/src/main/java/vendingmachine/InputView.java b/src/main/java/vendingmachine/InputView.java new file mode 100644 index 000000000..f108af82d --- /dev/null +++ b/src/main/java/vendingmachine/InputView.java @@ -0,0 +1,32 @@ +package vendingmachine; + +import java.util.function.Supplier; +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + + private final OutputView outputView = new OutputView(); + private final InputValidator inputValidator = new InputValidator(); + + public Integer inputMachineAmountHeld(){ + return read(() -> { + outputView.printInputMachineAmountHeld(); + String amount = Console.readLine(); + inputValidator.validateMachineAmountHeld(amount); + outputView.printEnter(); + return Integer.parseInt(amount); + }); + } + + + + private T read(Supplier input){ + while (true){ + try { + return input.get(); + }catch (IllegalArgumentException e){ + outputView.printError(e.getMessage()); + } + } + } +} From 25428b482ce5f9eda37daa61d40f362296a4a0e8 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:03:31 +0900 Subject: [PATCH 03/40] =?UTF-8?q?feat:=20InputValidator=20validateMachineA?= =?UTF-8?q?mountHeld=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/InputValidator.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/vendingmachine/InputValidator.java diff --git a/src/main/java/vendingmachine/InputValidator.java b/src/main/java/vendingmachine/InputValidator.java new file mode 100644 index 000000000..a635cb535 --- /dev/null +++ b/src/main/java/vendingmachine/InputValidator.java @@ -0,0 +1,21 @@ +package vendingmachine; + +public class InputValidator { + private static final String NUMERIC_REGEX = "^[0-9]+$"; + private static final int MIN_MACHINE_AMOUNT_HELD = 100; + + public void validateMachineAmountHeld(String amount){ + validateNumeric(amount); + if (Integer.parseInt(amount) < MIN_MACHINE_AMOUNT_HELD){ + throw new IllegalArgumentException(ErrorMessage.MIN_MACHINE_AMOUNT_HELD_ERROR.getMessage()); + } + } + + private void validateNumeric(String amount) { + if (!amount.matches(NUMERIC_REGEX)){ + throw new IllegalArgumentException(ErrorMessage.MACHINE_AMOUNT_HELD_NUMERIC_ERROR.getMessage()); + } + } + + +} From 95739ed14a5bb0309526453e25df238e779bb6f1 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:03:43 +0900 Subject: [PATCH 04/40] =?UTF-8?q?feat:=20OutputView=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/OutputView.java | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/vendingmachine/OutputView.java diff --git a/src/main/java/vendingmachine/OutputView.java b/src/main/java/vendingmachine/OutputView.java new file mode 100644 index 000000000..059e92262 --- /dev/null +++ b/src/main/java/vendingmachine/OutputView.java @@ -0,0 +1,21 @@ +package vendingmachine; + +public class OutputView { + + public void printError(String error){ + System.out.println(error); + } + + public void printInputMachineAmountHeld(){ + System.out.println(ProgressMessage.INPUT_MACHINE_AMOUNT_HELD); + } + + public void printEnter(){ + System.out.println(); + } + + public void printMachineAmountHeld(String screen){ + System.out.println(ProgressMessage.MACHINE_AMOUNT_HELD); + System.out.println(screen); + } +} From 9bf6d9a23c53209875dc75937b56209376bbd9e7 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:03:51 +0900 Subject: [PATCH 05/40] =?UTF-8?q?feat:=20ProgressMessage=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/ProgressMessage.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/vendingmachine/ProgressMessage.java diff --git a/src/main/java/vendingmachine/ProgressMessage.java b/src/main/java/vendingmachine/ProgressMessage.java new file mode 100644 index 000000000..fd8ee439d --- /dev/null +++ b/src/main/java/vendingmachine/ProgressMessage.java @@ -0,0 +1,17 @@ +package vendingmachine; + +public enum ProgressMessage { + INPUT_MACHINE_AMOUNT_HELD("자판기가 보유하고 있는 금액을 입력해 주세요."), + MACHINE_AMOUNT_HELD("자판기가 보유한 동전"); + + private final String message; + + ProgressMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } +} From 4797d6558e2fbe00848250d8e57c1434ea4fe646 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:03:59 +0900 Subject: [PATCH 06/40] =?UTF-8?q?feat:=20ErrorMessage=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/ErrorMessage.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/vendingmachine/ErrorMessage.java diff --git a/src/main/java/vendingmachine/ErrorMessage.java b/src/main/java/vendingmachine/ErrorMessage.java new file mode 100644 index 000000000..32e09741f --- /dev/null +++ b/src/main/java/vendingmachine/ErrorMessage.java @@ -0,0 +1,23 @@ +package vendingmachine; + +public enum ErrorMessage { + MACHINE_AMOUNT_HELD_NUMERIC_ERROR("숫자를 입력해 주세요"), + MIN_MACHINE_AMOUNT_HELD_ERROR("자판기 보유 금액은 최소 100원 부터 시작해주세요"), + NOT_FOUND_COIN("존재 하지 않는 Coin 입니다."); + + + private final String message; + + ErrorMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + @Override + public String toString() { + return message; + } +} From 5d37b28c5f279decf6e1cc1c468f5e7d6129d988 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:04:40 +0900 Subject: [PATCH 07/40] =?UTF-8?q?feat:=20Coin=20coinPrices=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Coin.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/vendingmachine/Coin.java b/src/main/java/vendingmachine/Coin.java index c76293fbc..456967dac 100644 --- a/src/main/java/vendingmachine/Coin.java +++ b/src/main/java/vendingmachine/Coin.java @@ -1,5 +1,9 @@ package vendingmachine; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + public enum Coin { COIN_500(500), COIN_100(100), @@ -13,4 +17,17 @@ public enum Coin { } // 추가 기능 구현 + public static List coinPrices() { + return Stream.of(Coin.values()) + .map(coin -> coin.amount) + .collect(Collectors.toList()); + } + + public static Coin getByAmount(Integer coinAmount) { + return Stream.of(Coin.values()) + .filter(coin -> coin.amount == coinAmount) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.NOT_FOUND_COIN.getMessage())); + + } } From 9ae386ab6e507277dcfb3f8db4a5f87f3b2db9bb Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:04:54 +0900 Subject: [PATCH 08/40] =?UTF-8?q?feat:=20MakeRandomCoin=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/MakeRandomCoin.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/vendingmachine/MakeRandomCoin.java diff --git a/src/main/java/vendingmachine/MakeRandomCoin.java b/src/main/java/vendingmachine/MakeRandomCoin.java new file mode 100644 index 000000000..31713aa99 --- /dev/null +++ b/src/main/java/vendingmachine/MakeRandomCoin.java @@ -0,0 +1,40 @@ +package vendingmachine; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.List; + +public class MakeRandomCoin { + private final List randomCoins = new ArrayList<>(); + + public void makeCoins(int amount) { + while (isMakingRandomCoins(amount)) { + randomCoins.add(randomCoin()); + removeOverCoin(amount); + } + } + + private boolean isMakingRandomCoins(int amount) { + return getSum(randomCoins) != amount; + } + + private int randomCoin(){ + return Randoms.pickNumberInList(Coin.coinPrices()); + } + + private void removeOverCoin(int amount) { + if (getSum(randomCoins) > amount) { + randomCoins.remove(randomCoins.size() - 1); + } + } + + private int getSum(List coins) { + return coins.stream() + .mapToInt(Integer::intValue) + .sum(); + } + + public List getRandomCoins() { + return randomCoins; + } +} From ab3488016fecbc9fb98c4461ddbcd62254276958 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:05:04 +0900 Subject: [PATCH 09/40] =?UTF-8?q?feat:=20ScreenElement=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/ScreenElement.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/vendingmachine/ScreenElement.java diff --git a/src/main/java/vendingmachine/ScreenElement.java b/src/main/java/vendingmachine/ScreenElement.java new file mode 100644 index 000000000..d375aa689 --- /dev/null +++ b/src/main/java/vendingmachine/ScreenElement.java @@ -0,0 +1,18 @@ +package vendingmachine; + +public enum ScreenElement { + COIN_UNIT("원"), + DIVISION(" - "), + COUNT_UNIT("개"); + + private final String value; + + ScreenElement(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} From 2ba448e0aa6c2ff0fbd674e3c660c3a38d13e200 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 00:05:11 +0900 Subject: [PATCH 10/40] =?UTF-8?q?feat:=20VendingMachine=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/VendingMachine.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/vendingmachine/VendingMachine.java diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java new file mode 100644 index 000000000..ec0e6d190 --- /dev/null +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -0,0 +1,42 @@ +package vendingmachine; + +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class VendingMachine { + private final EnumMap coins = new EnumMap<>(Coin.class); + private final MakeRandomCoin makeRandomCoin = new MakeRandomCoin(); + + public VendingMachine() { + for (Coin coin : Coin.values()){ + coins.put(coin, 0); + } + } + + public void saveRandomCoin(int amount){ + makeRandomCoin.makeCoins(amount); + List randomCoins = makeRandomCoin.getRandomCoins(); + + coins.putAll(randomCoins.stream() + .collect(Collectors.groupingBy( + Coin::getByAmount, + Collectors.summingInt(coinAmount -> 1) + ))); + } + + public String showRandomCoins(){ + StringBuilder sb = new StringBuilder(); + for (Map.Entry coins : coins.entrySet()){ + sb.append(coins.getKey()) + .append(ScreenElement.COIN_UNIT) + .append(ScreenElement.DIVISION) + .append(coins.getValue()) + .append(ScreenElement.COUNT_UNIT) + .append("\n"); + } + return sb.toString(); + } + +} From f8c582aee8ad4f0c7fb0206bf5ffdbbbf36446aa Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:08:20 +0900 Subject: [PATCH 11/40] =?UTF-8?q?feat:=20InputView=20inputProducts=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 --- src/main/java/vendingmachine/InputView.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/vendingmachine/InputView.java b/src/main/java/vendingmachine/InputView.java index f108af82d..22165511c 100644 --- a/src/main/java/vendingmachine/InputView.java +++ b/src/main/java/vendingmachine/InputView.java @@ -18,6 +18,15 @@ public Integer inputMachineAmountHeld(){ }); } + public Products inputProducts(){ + return read(() -> { + outputView.printInputProductsDetail(); + String products = Console.readLine(); + inputValidator.validateDivisionProducts(products); + return new Products(products); + }); + } + private T read(Supplier input){ From fb9b1182a0daadb6371d3f1a5144edf26bc05207 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:08:38 +0900 Subject: [PATCH 12/40] =?UTF-8?q?feat:=20Product=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Product.java | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/vendingmachine/Product.java diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/Product.java new file mode 100644 index 000000000..d984a258c --- /dev/null +++ b/src/main/java/vendingmachine/Product.java @@ -0,0 +1,27 @@ +package vendingmachine; + +public class Product { + + private static final int MIN_PRICE = 100; + private static final int COIN_UNIT = 10; + private final String name; + private final int price; + private final int amount; + + public Product(String name, int price, int amount) { + validatePriceRule(price); + this.name = name; + this.price = price; + this.amount = amount; + } + + private void validatePriceRule(int price) { + if (isaBreakPriceRule(price)){ + throw new IllegalArgumentException(ErrorMessage.PRODUCT_PRICE_ERROR.getMessage()); + } + } + + private static boolean isaBreakPriceRule(int price) { + return price < MIN_PRICE || price % COIN_UNIT != 0; + } +} From 6189a9ea9018fbcddd3e3b14db5f8111dacb659f Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:08:54 +0900 Subject: [PATCH 13/40] =?UTF-8?q?feat:=20Products=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Products.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/vendingmachine/Products.java diff --git a/src/main/java/vendingmachine/Products.java b/src/main/java/vendingmachine/Products.java new file mode 100644 index 000000000..fe15c2e1e --- /dev/null +++ b/src/main/java/vendingmachine/Products.java @@ -0,0 +1,21 @@ +package vendingmachine; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Products { + + private static final String PRODUCT_DIVISION = ";"; + private static final String PRODUCT_DETAIL_DIVISION = ","; + private final List products; + + + public Products(String productData) { + products = Arrays.stream(productData.split(PRODUCT_DIVISION)) + .map(productToken -> productToken.substring(1, productToken.length() - 1).split(PRODUCT_DETAIL_DIVISION)) + .map(productDetails -> new Product(productDetails[0], Integer.parseInt(productDetails[1]), Integer.parseInt(productDetails[2]))) + .collect(Collectors.toList()); + } + +} From 7ec27121b2739cae248229c06c649c8b60146eca Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:09:22 +0900 Subject: [PATCH 14/40] =?UTF-8?q?feat:=20ProgressMessage=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=B6=94=EA=B0=80=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/ProgressMessage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/ProgressMessage.java b/src/main/java/vendingmachine/ProgressMessage.java index fd8ee439d..9b8a587cd 100644 --- a/src/main/java/vendingmachine/ProgressMessage.java +++ b/src/main/java/vendingmachine/ProgressMessage.java @@ -2,7 +2,8 @@ public enum ProgressMessage { INPUT_MACHINE_AMOUNT_HELD("자판기가 보유하고 있는 금액을 입력해 주세요."), - MACHINE_AMOUNT_HELD("자판기가 보유한 동전"); + MACHINE_AMOUNT_HELD("자판기가 보유한 동전"), + INPUT_PRODUCTS_DETAIL("상품명과 가격, 수량을 입력해 주세요."); private final String message; From 610a97561631b55e79e80b2799617ae1b751703c Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:09:28 +0900 Subject: [PATCH 15/40] =?UTF-8?q?feat:=20ErrorMessage=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EC=B6=94=EA=B0=80=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/ErrorMessage.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/ErrorMessage.java b/src/main/java/vendingmachine/ErrorMessage.java index 32e09741f..0f2842541 100644 --- a/src/main/java/vendingmachine/ErrorMessage.java +++ b/src/main/java/vendingmachine/ErrorMessage.java @@ -3,7 +3,9 @@ public enum ErrorMessage { MACHINE_AMOUNT_HELD_NUMERIC_ERROR("숫자를 입력해 주세요"), MIN_MACHINE_AMOUNT_HELD_ERROR("자판기 보유 금액은 최소 100원 부터 시작해주세요"), - NOT_FOUND_COIN("존재 하지 않는 Coin 입니다."); + NOT_FOUND_COIN("존재 하지 않는 Coin 입니다."), + PRODUCT_REGEX_ERROR("일치하지 않는 상품 형식입니다."), + PRODUCT_PRICE_ERROR("상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다."); private final String message; From 5de2c0c0db59351a2c798378f95d34fbd5d02c88 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:10:14 +0900 Subject: [PATCH 16/40] =?UTF-8?q?feat:=20InputValidator=20validateDivision?= =?UTF-8?q?Products=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/InputValidator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/InputValidator.java b/src/main/java/vendingmachine/InputValidator.java index a635cb535..98fc132e8 100644 --- a/src/main/java/vendingmachine/InputValidator.java +++ b/src/main/java/vendingmachine/InputValidator.java @@ -3,6 +3,7 @@ public class InputValidator { private static final String NUMERIC_REGEX = "^[0-9]+$"; private static final int MIN_MACHINE_AMOUNT_HELD = 100; + private static final String PRODUCT_PATTERN_REGEX = "\\[([^,]+),(\\d+),(\\d+)];"; public void validateMachineAmountHeld(String amount){ validateNumeric(amount); @@ -17,5 +18,9 @@ private void validateNumeric(String amount) { } } - + public void validateDivisionProducts(String products) { + if (products.matches(PRODUCT_PATTERN_REGEX)){ + throw new IllegalArgumentException(ErrorMessage.PRODUCT_REGEX_ERROR.getMessage()); + } + } } From 0370da16db6b6b6cc254762acdaed072af458621 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:10:31 +0900 Subject: [PATCH 17/40] =?UTF-8?q?feat:=20OutputView=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/OutputView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/vendingmachine/OutputView.java b/src/main/java/vendingmachine/OutputView.java index 059e92262..7032f85ea 100644 --- a/src/main/java/vendingmachine/OutputView.java +++ b/src/main/java/vendingmachine/OutputView.java @@ -10,6 +10,10 @@ public void printInputMachineAmountHeld(){ System.out.println(ProgressMessage.INPUT_MACHINE_AMOUNT_HELD); } + public void printInputProductsDetail() { + System.out.println(ProgressMessage.INPUT_PRODUCTS_DETAIL); + } + public void printEnter(){ System.out.println(); } From 55752d5ef552dfd81150aa3229eb14de28bf60f6 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 01:10:58 +0900 Subject: [PATCH 18/40] =?UTF-8?q?feat:=20MachineController=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/MachineController.java | 21 +++++++++++++++++++ .../java/vendingmachine/VendingMachine.java | 4 ++++ 2 files changed, 25 insertions(+) create mode 100644 src/main/java/vendingmachine/MachineController.java diff --git a/src/main/java/vendingmachine/MachineController.java b/src/main/java/vendingmachine/MachineController.java new file mode 100644 index 000000000..524de63a0 --- /dev/null +++ b/src/main/java/vendingmachine/MachineController.java @@ -0,0 +1,21 @@ +package vendingmachine; + +public class MachineController { + + private final InputView inputView; + private final OutputView outputView; + private final VendingMachine vendingMachine; + + public MachineController() { + this.inputView = new InputView(); + this.outputView = new OutputView(); + this.vendingMachine = new VendingMachine(); + } + + public void run(){ + int amountHeld = inputView.inputMachineAmountHeld(); + vendingMachine.saveRandomCoin(amountHeld); + outputView.printMachineAmountHeld(vendingMachine.showRandomCoins()); + vendingMachine.registerProducts(inputView.inputProducts()); + } +} diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java index ec0e6d190..64550cfb8 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -8,6 +8,7 @@ public class VendingMachine { private final EnumMap coins = new EnumMap<>(Coin.class); private final MakeRandomCoin makeRandomCoin = new MakeRandomCoin(); + private Products products; public VendingMachine() { for (Coin coin : Coin.values()){ @@ -39,4 +40,7 @@ public String showRandomCoins(){ return sb.toString(); } + public void registerProducts(Products products) { + this.products = products; + } } From 0742b1f167952ef801d0ab37debdfb3ffdb8f0a1 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 10:36:33 +0900 Subject: [PATCH 19/40] =?UTF-8?q?feat:=20InputView=20inputMoney=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 --- src/main/java/vendingmachine/InputView.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/vendingmachine/InputView.java b/src/main/java/vendingmachine/InputView.java index 22165511c..624a4fbdb 100644 --- a/src/main/java/vendingmachine/InputView.java +++ b/src/main/java/vendingmachine/InputView.java @@ -27,6 +27,16 @@ public Products inputProducts(){ }); } + public Integer inputMoney(Products products){ + return read(() -> { + outputView.printInputMoney(); + String money = Console.readLine(); + inputValidator.validateNumeric(money); + products.validateInputMoney(money); + return Integer.parseInt(money); + }); + } + private T read(Supplier input){ From aac391a285ab08fd90a54d3b09797be153400368 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 10:37:09 +0900 Subject: [PATCH 20/40] =?UTF-8?q?refactor:=20validateNumeric=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/InputValidator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/vendingmachine/InputValidator.java b/src/main/java/vendingmachine/InputValidator.java index 98fc132e8..77746e531 100644 --- a/src/main/java/vendingmachine/InputValidator.java +++ b/src/main/java/vendingmachine/InputValidator.java @@ -12,9 +12,9 @@ public void validateMachineAmountHeld(String amount){ } } - private void validateNumeric(String amount) { + public void validateNumeric(String amount) { if (!amount.matches(NUMERIC_REGEX)){ - throw new IllegalArgumentException(ErrorMessage.MACHINE_AMOUNT_HELD_NUMERIC_ERROR.getMessage()); + throw new IllegalArgumentException(ErrorMessage.MACHINE_COIN_NUMERIC_ERROR.getMessage()); } } From 2737cec79a71b70ff4f79ccc1f1602ed54ff30a1 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 10:37:37 +0900 Subject: [PATCH 21/40] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EB=9E=A8=20=EB=A9=94=EC=8B=9C=EC=A7=80=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/vendingmachine/ErrorMessage.java | 6 ++++-- src/main/java/vendingmachine/OutputView.java | 4 ++++ src/main/java/vendingmachine/ProgressMessage.java | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/vendingmachine/ErrorMessage.java b/src/main/java/vendingmachine/ErrorMessage.java index 0f2842541..33d4a12d1 100644 --- a/src/main/java/vendingmachine/ErrorMessage.java +++ b/src/main/java/vendingmachine/ErrorMessage.java @@ -1,11 +1,13 @@ package vendingmachine; public enum ErrorMessage { - MACHINE_AMOUNT_HELD_NUMERIC_ERROR("숫자를 입력해 주세요"), + MACHINE_COIN_NUMERIC_ERROR("숫자를 입력해 주세요"), MIN_MACHINE_AMOUNT_HELD_ERROR("자판기 보유 금액은 최소 100원 부터 시작해주세요"), NOT_FOUND_COIN("존재 하지 않는 Coin 입니다."), PRODUCT_REGEX_ERROR("일치하지 않는 상품 형식입니다."), - PRODUCT_PRICE_ERROR("상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다."); + PRODUCT_PRICE_ERROR("상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 합니다."), + INPUT_MONEY_ERROR("입력한 금액이 너무 적습니다."); + private final String message; diff --git a/src/main/java/vendingmachine/OutputView.java b/src/main/java/vendingmachine/OutputView.java index 7032f85ea..5a90231af 100644 --- a/src/main/java/vendingmachine/OutputView.java +++ b/src/main/java/vendingmachine/OutputView.java @@ -22,4 +22,8 @@ public void printMachineAmountHeld(String screen){ System.out.println(ProgressMessage.MACHINE_AMOUNT_HELD); System.out.println(screen); } + + public void printInputMoney(){ + System.out.println(ProgressMessage.INPUT_MONEY); + } } diff --git a/src/main/java/vendingmachine/ProgressMessage.java b/src/main/java/vendingmachine/ProgressMessage.java index 9b8a587cd..4e79114b5 100644 --- a/src/main/java/vendingmachine/ProgressMessage.java +++ b/src/main/java/vendingmachine/ProgressMessage.java @@ -3,7 +3,8 @@ public enum ProgressMessage { INPUT_MACHINE_AMOUNT_HELD("자판기가 보유하고 있는 금액을 입력해 주세요."), MACHINE_AMOUNT_HELD("자판기가 보유한 동전"), - INPUT_PRODUCTS_DETAIL("상품명과 가격, 수량을 입력해 주세요."); + INPUT_PRODUCTS_DETAIL("상품명과 가격, 수량을 입력해 주세요."), + INPUT_MONEY("투입 금액을 입력해 주세요."); private final String message; From f2a4170ddf49d344b0fdc5f00b90bd0103328fdd Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 10:38:05 +0900 Subject: [PATCH 22/40] =?UTF-8?q?feat:=20Products=20validateInputMoney=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 --- src/main/java/vendingmachine/Products.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/vendingmachine/Products.java b/src/main/java/vendingmachine/Products.java index fe15c2e1e..37d887dd6 100644 --- a/src/main/java/vendingmachine/Products.java +++ b/src/main/java/vendingmachine/Products.java @@ -18,4 +18,11 @@ public Products(String productData) { .collect(Collectors.toList()); } + public void validateInputMoney(String money){ + int price = Integer.parseInt(money); + if(products.stream().anyMatch(product -> product.getPrice() > price)){ + throw new IllegalArgumentException(ErrorMessage.INPUT_MONEY_ERROR.getMessage()); + } + } + } From 5f61b2c87481646c35ad57f579e02e489d4e2730 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 10:38:32 +0900 Subject: [PATCH 23/40] =?UTF-8?q?feat:=20Calculator=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Calculator.java | 15 +++++++++++++++ .../java/vendingmachine/MachineController.java | 6 +++++- src/main/java/vendingmachine/Product.java | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/main/java/vendingmachine/Calculator.java diff --git a/src/main/java/vendingmachine/Calculator.java b/src/main/java/vendingmachine/Calculator.java new file mode 100644 index 000000000..eb5ebf133 --- /dev/null +++ b/src/main/java/vendingmachine/Calculator.java @@ -0,0 +1,15 @@ +package vendingmachine; + +public class Calculator { + + private final VendingMachine vendingMachine; + private int inputMoney; + + public Calculator(VendingMachine vendingMachine) { + this.vendingMachine = vendingMachine; + } + + public void receiveMoney(int inputMoney) { + this.inputMoney = inputMoney; + } +} diff --git a/src/main/java/vendingmachine/MachineController.java b/src/main/java/vendingmachine/MachineController.java index 524de63a0..f4d17509a 100644 --- a/src/main/java/vendingmachine/MachineController.java +++ b/src/main/java/vendingmachine/MachineController.java @@ -5,17 +5,21 @@ public class MachineController { private final InputView inputView; private final OutputView outputView; private final VendingMachine vendingMachine; + private final Calculator calculator; public MachineController() { this.inputView = new InputView(); this.outputView = new OutputView(); this.vendingMachine = new VendingMachine(); + this.calculator = new Calculator(vendingMachine); } public void run(){ int amountHeld = inputView.inputMachineAmountHeld(); vendingMachine.saveRandomCoin(amountHeld); outputView.printMachineAmountHeld(vendingMachine.showRandomCoins()); - vendingMachine.registerProducts(inputView.inputProducts()); + Products products = inputView.inputProducts(); + vendingMachine.registerProducts(products); + calculator.receiveMoney(inputView.inputMoney(products)); } } diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/Product.java index d984a258c..a05ab0290 100644 --- a/src/main/java/vendingmachine/Product.java +++ b/src/main/java/vendingmachine/Product.java @@ -24,4 +24,8 @@ private void validatePriceRule(int price) { private static boolean isaBreakPriceRule(int price) { return price < MIN_PRICE || price % COIN_UNIT != 0; } + + public int getPrice() { + return price; + } } From 5a8764230f92991b8008ab4a4a2f1bf36a9c313d Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 11:49:35 +0900 Subject: [PATCH 24/40] =?UTF-8?q?feat:=20InputView=20inputBuyProduct?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/InputView.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/vendingmachine/InputView.java b/src/main/java/vendingmachine/InputView.java index 624a4fbdb..8d33e5d1c 100644 --- a/src/main/java/vendingmachine/InputView.java +++ b/src/main/java/vendingmachine/InputView.java @@ -37,6 +37,15 @@ public Integer inputMoney(Products products){ }); } + public String inputBuyProduct(Products products) { + return read(() -> { + outputView.printInputBuyProductName(); + String name = Console.readLine(); + products.validateInputProductName(name); + return name; + }); + } + private T read(Supplier input){ From be89774c6b9e3f89e046a6984a16f242b4a7452f Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 11:49:57 +0900 Subject: [PATCH 25/40] =?UTF-8?q?feat:=20=EB=A9=94=EC=8B=9C=EC=A7=80=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/vendingmachine/ErrorMessage.java | 3 ++- src/main/java/vendingmachine/OutputView.java | 8 ++++++++ src/main/java/vendingmachine/ProgressMessage.java | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/vendingmachine/ErrorMessage.java b/src/main/java/vendingmachine/ErrorMessage.java index 33d4a12d1..5ca001b11 100644 --- a/src/main/java/vendingmachine/ErrorMessage.java +++ b/src/main/java/vendingmachine/ErrorMessage.java @@ -6,7 +6,8 @@ public enum ErrorMessage { NOT_FOUND_COIN("존재 하지 않는 Coin 입니다."), PRODUCT_REGEX_ERROR("일치하지 않는 상품 형식입니다."), PRODUCT_PRICE_ERROR("상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 합니다."), - INPUT_MONEY_ERROR("입력한 금액이 너무 적습니다."); + INPUT_MONEY_ERROR("입력한 금액이 너무 적습니다."), + INPUT_PRODUCT_NAME_ERROR("존재하지 않는 상품명 입니다."); diff --git a/src/main/java/vendingmachine/OutputView.java b/src/main/java/vendingmachine/OutputView.java index 5a90231af..80ce676c5 100644 --- a/src/main/java/vendingmachine/OutputView.java +++ b/src/main/java/vendingmachine/OutputView.java @@ -26,4 +26,12 @@ public void printMachineAmountHeld(String screen){ public void printInputMoney(){ System.out.println(ProgressMessage.INPUT_MONEY); } + + public void printInputBuyProductName() { + System.out.println(ProgressMessage.INPUT_BUY_PRODUCT_NAME); + } + + public void printCurInputMoney(int money){ + System.out.printf((ProgressMessage.CUR_INPUT_MONEY) + "%n", money); + } } diff --git a/src/main/java/vendingmachine/ProgressMessage.java b/src/main/java/vendingmachine/ProgressMessage.java index 4e79114b5..38c8a1c6e 100644 --- a/src/main/java/vendingmachine/ProgressMessage.java +++ b/src/main/java/vendingmachine/ProgressMessage.java @@ -4,7 +4,9 @@ public enum ProgressMessage { INPUT_MACHINE_AMOUNT_HELD("자판기가 보유하고 있는 금액을 입력해 주세요."), MACHINE_AMOUNT_HELD("자판기가 보유한 동전"), INPUT_PRODUCTS_DETAIL("상품명과 가격, 수량을 입력해 주세요."), - INPUT_MONEY("투입 금액을 입력해 주세요."); + INPUT_MONEY("투입 금액을 입력해 주세요."), + INPUT_BUY_PRODUCT_NAME("구매할 상품명을 입력해 주세요."), + CUR_INPUT_MONEY("투입 금액: %d원"); private final String message; From a5c8eeb9eff14421332b356c68f649ec03499784 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 11:50:59 +0900 Subject: [PATCH 26/40] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Calculator.java | 16 +++++++++++ src/main/java/vendingmachine/Product.java | 8 ++++++ src/main/java/vendingmachine/Products.java | 28 ++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/main/java/vendingmachine/Calculator.java b/src/main/java/vendingmachine/Calculator.java index eb5ebf133..af35a81ec 100644 --- a/src/main/java/vendingmachine/Calculator.java +++ b/src/main/java/vendingmachine/Calculator.java @@ -12,4 +12,20 @@ public Calculator(VendingMachine vendingMachine) { public void receiveMoney(int inputMoney) { this.inputMoney = inputMoney; } + + public boolean isBuyingProducts(){ + Products products = vendingMachine.getProducts(); + return products.isBuyingProducts(inputMoney) ; + } + + public void buyProducts(String name){ + Products products = vendingMachine.getProducts(); + int productPrice = products.getProductPrice(name); + inputMoney -= productPrice; + } + + public int getInputMoney() { + return inputMoney; + } + } diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/Product.java index a05ab0290..7dee80949 100644 --- a/src/main/java/vendingmachine/Product.java +++ b/src/main/java/vendingmachine/Product.java @@ -28,4 +28,12 @@ private static boolean isaBreakPriceRule(int price) { public int getPrice() { return price; } + + public String getName() { + return name; + } + + public int getAmount() { + return amount; + } } diff --git a/src/main/java/vendingmachine/Products.java b/src/main/java/vendingmachine/Products.java index 37d887dd6..ff36b3447 100644 --- a/src/main/java/vendingmachine/Products.java +++ b/src/main/java/vendingmachine/Products.java @@ -25,4 +25,32 @@ public void validateInputMoney(String money){ } } + public void validateInputProductName(String name) { + if (products.stream().noneMatch(product -> product.getName().equals(name))){ + throw new IllegalArgumentException(ErrorMessage.INPUT_PRODUCT_NAME_ERROR.getMessage()); + } + } + + public boolean isBuyingProducts(int inputMoney){ + int minProductPrice = products.stream() + .mapToInt(Product::getPrice) + .min() + .orElse(Integer.MAX_VALUE); + return inputMoney > minProductPrice && isNotProductSoldOut(); + } + + private boolean isNotProductSoldOut(){ + int amount = products.stream() + .mapToInt(Product::getAmount) + .sum(); + return amount != 0; + } + + public int getProductPrice(String name){ + return products.stream() + .filter(product -> product.getName().equals(name)) + .findFirst() + .map(Product::getPrice) + .orElse(Integer.MAX_VALUE); + } } From d8bc433c3b8159bbc3b4acd8eac54c0befae0bc8 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 11:51:29 +0900 Subject: [PATCH 27/40] =?UTF-8?q?feat:=20MachineController=20buyProducts?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/MachineController.java | 13 +++++++++++++ src/main/java/vendingmachine/VendingMachine.java | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/vendingmachine/MachineController.java b/src/main/java/vendingmachine/MachineController.java index f4d17509a..9253fa0a5 100644 --- a/src/main/java/vendingmachine/MachineController.java +++ b/src/main/java/vendingmachine/MachineController.java @@ -18,8 +18,21 @@ public void run(){ int amountHeld = inputView.inputMachineAmountHeld(); vendingMachine.saveRandomCoin(amountHeld); outputView.printMachineAmountHeld(vendingMachine.showRandomCoins()); + Products products = inputView.inputProducts(); vendingMachine.registerProducts(products); + calculator.receiveMoney(inputView.inputMoney(products)); + buyProducts(products); + + } + + private void buyProducts(Products products) { + while (calculator.isBuyingProducts()){ + outputView.printCurInputMoney(calculator.getInputMoney()); + String name = inputView.inputBuyProduct(products); + calculator.buyProducts(name); + } + //TODO : 잔돈 반환 } } diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java index 64550cfb8..1a181a1bc 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -43,4 +43,8 @@ public String showRandomCoins(){ public void registerProducts(Products products) { this.products = products; } + + public Products getProducts() { + return products; + } } From c3c64673848380ac7562e103fb487b1c3b5e537b Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:27:44 +0900 Subject: [PATCH 28/40] =?UTF-8?q?feat:=20=ED=99=94=EB=A9=B4=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=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/vendingmachine/Coin.java | 9 +++++++++ src/main/java/vendingmachine/ErrorMessage.java | 8 ++------ src/main/java/vendingmachine/InputView.java | 3 +++ src/main/java/vendingmachine/OutputView.java | 5 +++++ src/main/java/vendingmachine/ProgressMessage.java | 3 ++- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/main/java/vendingmachine/Coin.java b/src/main/java/vendingmachine/Coin.java index 456967dac..e00f5fa08 100644 --- a/src/main/java/vendingmachine/Coin.java +++ b/src/main/java/vendingmachine/Coin.java @@ -30,4 +30,13 @@ public static Coin getByAmount(Integer coinAmount) { .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.NOT_FOUND_COIN.getMessage())); } + + public int getAmount() { + return amount; + } + + @Override + public String toString() { + return String.valueOf(amount); + } } diff --git a/src/main/java/vendingmachine/ErrorMessage.java b/src/main/java/vendingmachine/ErrorMessage.java index 5ca001b11..65edfb460 100644 --- a/src/main/java/vendingmachine/ErrorMessage.java +++ b/src/main/java/vendingmachine/ErrorMessage.java @@ -11,6 +11,7 @@ public enum ErrorMessage { + private static final String ERROR = "[ERROR] "; private final String message; ErrorMessage(String message) { @@ -18,11 +19,6 @@ public enum ErrorMessage { } public String getMessage() { - return message; - } - - @Override - public String toString() { - return message; + return ERROR + message; } } diff --git a/src/main/java/vendingmachine/InputView.java b/src/main/java/vendingmachine/InputView.java index 8d33e5d1c..8b90eef7e 100644 --- a/src/main/java/vendingmachine/InputView.java +++ b/src/main/java/vendingmachine/InputView.java @@ -23,6 +23,7 @@ public Products inputProducts(){ outputView.printInputProductsDetail(); String products = Console.readLine(); inputValidator.validateDivisionProducts(products); + outputView.printEnter(); return new Products(products); }); } @@ -33,6 +34,7 @@ public Integer inputMoney(Products products){ String money = Console.readLine(); inputValidator.validateNumeric(money); products.validateInputMoney(money); + outputView.printEnter(); return Integer.parseInt(money); }); } @@ -42,6 +44,7 @@ public String inputBuyProduct(Products products) { outputView.printInputBuyProductName(); String name = Console.readLine(); products.validateInputProductName(name); + outputView.printEnter(); return name; }); } diff --git a/src/main/java/vendingmachine/OutputView.java b/src/main/java/vendingmachine/OutputView.java index 80ce676c5..db6ddc9f3 100644 --- a/src/main/java/vendingmachine/OutputView.java +++ b/src/main/java/vendingmachine/OutputView.java @@ -34,4 +34,9 @@ public void printInputBuyProductName() { public void printCurInputMoney(int money){ System.out.printf((ProgressMessage.CUR_INPUT_MONEY) + "%n", money); } + + public void printResultChange(String returnChange) { + System.out.println(ProgressMessage.RETURN_CHANGE); + System.out.println(returnChange); + } } diff --git a/src/main/java/vendingmachine/ProgressMessage.java b/src/main/java/vendingmachine/ProgressMessage.java index 38c8a1c6e..8280b8ffc 100644 --- a/src/main/java/vendingmachine/ProgressMessage.java +++ b/src/main/java/vendingmachine/ProgressMessage.java @@ -6,7 +6,8 @@ public enum ProgressMessage { INPUT_PRODUCTS_DETAIL("상품명과 가격, 수량을 입력해 주세요."), INPUT_MONEY("투입 금액을 입력해 주세요."), INPUT_BUY_PRODUCT_NAME("구매할 상품명을 입력해 주세요."), - CUR_INPUT_MONEY("투입 금액: %d원"); + CUR_INPUT_MONEY("투입 금액: %d원"), + RETURN_CHANGE("잔돈"); private final String message; From 4484c5ffd7e03350f4fb843c7c44500d12a5590d Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:28:03 +0900 Subject: [PATCH 29/40] =?UTF-8?q?feat:=20Calculator=20returnChange=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 --- src/main/java/vendingmachine/Calculator.java | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/vendingmachine/Calculator.java b/src/main/java/vendingmachine/Calculator.java index af35a81ec..8447b0794 100644 --- a/src/main/java/vendingmachine/Calculator.java +++ b/src/main/java/vendingmachine/Calculator.java @@ -1,5 +1,8 @@ package vendingmachine; +import java.util.EnumMap; +import java.util.Map; + public class Calculator { private final VendingMachine vendingMachine; @@ -24,6 +27,25 @@ public void buyProducts(String name){ inputMoney -= productPrice; } + public String returnChange(){ + StringBuilder sb = new StringBuilder(); + EnumMap changeCoins = vendingMachine.returnChange(inputMoney); + + for (Map.Entry coins : changeCoins.entrySet()){ + if (coins.getValue() != 0) { + sb.append(coins.getKey()) + .append(ScreenElement.COIN_UNIT) + .append(ScreenElement.DIVISION) + .append(coins.getValue()) + .append(ScreenElement.COUNT_UNIT) + .append("\n"); + } + } + return sb.toString(); + } + + + public int getInputMoney() { return inputMoney; } From 75dff969ed7353215084dad4f17a26ea31d02d28 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:28:33 +0900 Subject: [PATCH 30/40] =?UTF-8?q?feat:=20VendingMachine=20returnChange=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 --- .../java/vendingmachine/VendingMachine.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java index 1a181a1bc..c0ae04c5b 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -30,7 +30,7 @@ public void saveRandomCoin(int amount){ public String showRandomCoins(){ StringBuilder sb = new StringBuilder(); for (Map.Entry coins : coins.entrySet()){ - sb.append(coins.getKey()) + sb.append(coins.getKey().toString()) .append(ScreenElement.COIN_UNIT) .append(ScreenElement.DIVISION) .append(coins.getValue()) @@ -40,6 +40,22 @@ public String showRandomCoins(){ return sb.toString(); } + public EnumMap returnChange(int inputMoney){ + int remainingChange = inputMoney; + EnumMap changeCoins = new EnumMap<>(Coin.class); + + for (Coin coin : Coin.values()) { + int coinValue = coin.getAmount(); + int coinCount = coins.get(coin); + int changeCount = Math.min(coinCount, remainingChange / coinValue); + + coins.put(coin, coins.get(coin) - changeCount); + changeCoins.put(coin, changeCount); + remainingChange -= changeCount * coinValue; + } + return changeCoins; + } + public void registerProducts(Products products) { this.products = products; } From 4362d8cb55059d71fa2af6484e0b8edc0d3bedaa Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:28:55 +0900 Subject: [PATCH 31/40] =?UTF-8?q?feat:=20MachineController=20buyProducts?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/MachineController.java | 6 ++++-- src/main/java/vendingmachine/Products.java | 13 ++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/vendingmachine/MachineController.java b/src/main/java/vendingmachine/MachineController.java index 9253fa0a5..055b47556 100644 --- a/src/main/java/vendingmachine/MachineController.java +++ b/src/main/java/vendingmachine/MachineController.java @@ -28,11 +28,13 @@ public void run(){ } private void buyProducts(Products products) { - while (calculator.isBuyingProducts()){ + while (true){ outputView.printCurInputMoney(calculator.getInputMoney()); + if(calculator.isBuyingProducts()) break; + String name = inputView.inputBuyProduct(products); calculator.buyProducts(name); } - //TODO : 잔돈 반환 + outputView.printResultChange(calculator.returnChange()); } } diff --git a/src/main/java/vendingmachine/Products.java b/src/main/java/vendingmachine/Products.java index ff36b3447..a01eca871 100644 --- a/src/main/java/vendingmachine/Products.java +++ b/src/main/java/vendingmachine/Products.java @@ -20,7 +20,7 @@ public Products(String productData) { public void validateInputMoney(String money){ int price = Integer.parseInt(money); - if(products.stream().anyMatch(product -> product.getPrice() > price)){ + if(getMinProductPrice() > price){ throw new IllegalArgumentException(ErrorMessage.INPUT_MONEY_ERROR.getMessage()); } } @@ -32,18 +32,21 @@ public void validateInputProductName(String name) { } public boolean isBuyingProducts(int inputMoney){ - int minProductPrice = products.stream() + return inputMoney < getMinProductPrice() || isProductSoldOut(); + } + + private int getMinProductPrice() { + return products.stream() .mapToInt(Product::getPrice) .min() .orElse(Integer.MAX_VALUE); - return inputMoney > minProductPrice && isNotProductSoldOut(); } - private boolean isNotProductSoldOut(){ + private boolean isProductSoldOut(){ int amount = products.stream() .mapToInt(Product::getAmount) .sum(); - return amount != 0; + return amount == 0; } public int getProductPrice(String name){ From 8ef7581b0ecc90019bec0735f49d1533f7c3e6d5 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:29:07 +0900 Subject: [PATCH 32/40] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Application.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/vendingmachine/Application.java b/src/main/java/vendingmachine/Application.java index 9d3be447b..2b2f479eb 100644 --- a/src/main/java/vendingmachine/Application.java +++ b/src/main/java/vendingmachine/Application.java @@ -3,5 +3,7 @@ public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + MachineController machineController = new MachineController(); + machineController.run(); } } From ab62a201553e606e70ecd252b048424940eb4ce6 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:45:36 +0900 Subject: [PATCH 33/40] =?UTF-8?q?feat:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Application.java | 2 + src/main/java/vendingmachine/Calculator.java | 53 ------------------- .../vendingmachine/MachineController.java | 40 -------------- .../vendingmachine/{ => constants}/Coin.java | 2 +- .../{ => constants}/ErrorMessage.java | 3 +- .../{ => constants}/ProgressMessage.java | 2 +- .../{ => constants}/ScreenElement.java | 2 +- .../controller/MachineController.java | 49 +++++++++++++++++ .../{ => domain}/MakeRandomCoin.java | 6 ++- .../vendingmachine/{ => domain}/Product.java | 14 ++--- .../vendingmachine/{ => domain}/Products.java | 16 +++--- .../{ => domain}/VendingMachine.java | 28 +++++----- .../service/CalculatorService.java | 50 +++++++++++++++++ .../{ => view}/InputValidator.java | 12 +++-- .../vendingmachine/{ => view}/InputView.java | 19 +++---- .../vendingmachine/{ => view}/OutputView.java | 16 +++--- 16 files changed, 164 insertions(+), 150 deletions(-) delete mode 100644 src/main/java/vendingmachine/Calculator.java delete mode 100644 src/main/java/vendingmachine/MachineController.java rename src/main/java/vendingmachine/{ => constants}/Coin.java (96%) rename src/main/java/vendingmachine/{ => constants}/ErrorMessage.java (96%) rename src/main/java/vendingmachine/{ => constants}/ProgressMessage.java (95%) rename src/main/java/vendingmachine/{ => constants}/ScreenElement.java (88%) create mode 100644 src/main/java/vendingmachine/controller/MachineController.java rename src/main/java/vendingmachine/{ => domain}/MakeRandomCoin.java (90%) rename src/main/java/vendingmachine/{ => domain}/Product.java (87%) rename src/main/java/vendingmachine/{ => domain}/Products.java (83%) rename src/main/java/vendingmachine/{ => domain}/VendingMachine.java (67%) create mode 100644 src/main/java/vendingmachine/service/CalculatorService.java rename src/main/java/vendingmachine/{ => view}/InputValidator.java (70%) rename src/main/java/vendingmachine/{ => view}/InputView.java (83%) rename src/main/java/vendingmachine/{ => view}/OutputView.java (71%) diff --git a/src/main/java/vendingmachine/Application.java b/src/main/java/vendingmachine/Application.java index 2b2f479eb..a918e8d40 100644 --- a/src/main/java/vendingmachine/Application.java +++ b/src/main/java/vendingmachine/Application.java @@ -1,5 +1,7 @@ package vendingmachine; +import vendingmachine.controller.MachineController; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 diff --git a/src/main/java/vendingmachine/Calculator.java b/src/main/java/vendingmachine/Calculator.java deleted file mode 100644 index 8447b0794..000000000 --- a/src/main/java/vendingmachine/Calculator.java +++ /dev/null @@ -1,53 +0,0 @@ -package vendingmachine; - -import java.util.EnumMap; -import java.util.Map; - -public class Calculator { - - private final VendingMachine vendingMachine; - private int inputMoney; - - public Calculator(VendingMachine vendingMachine) { - this.vendingMachine = vendingMachine; - } - - public void receiveMoney(int inputMoney) { - this.inputMoney = inputMoney; - } - - public boolean isBuyingProducts(){ - Products products = vendingMachine.getProducts(); - return products.isBuyingProducts(inputMoney) ; - } - - public void buyProducts(String name){ - Products products = vendingMachine.getProducts(); - int productPrice = products.getProductPrice(name); - inputMoney -= productPrice; - } - - public String returnChange(){ - StringBuilder sb = new StringBuilder(); - EnumMap changeCoins = vendingMachine.returnChange(inputMoney); - - for (Map.Entry coins : changeCoins.entrySet()){ - if (coins.getValue() != 0) { - sb.append(coins.getKey()) - .append(ScreenElement.COIN_UNIT) - .append(ScreenElement.DIVISION) - .append(coins.getValue()) - .append(ScreenElement.COUNT_UNIT) - .append("\n"); - } - } - return sb.toString(); - } - - - - public int getInputMoney() { - return inputMoney; - } - -} diff --git a/src/main/java/vendingmachine/MachineController.java b/src/main/java/vendingmachine/MachineController.java deleted file mode 100644 index 055b47556..000000000 --- a/src/main/java/vendingmachine/MachineController.java +++ /dev/null @@ -1,40 +0,0 @@ -package vendingmachine; - -public class MachineController { - - private final InputView inputView; - private final OutputView outputView; - private final VendingMachine vendingMachine; - private final Calculator calculator; - - public MachineController() { - this.inputView = new InputView(); - this.outputView = new OutputView(); - this.vendingMachine = new VendingMachine(); - this.calculator = new Calculator(vendingMachine); - } - - public void run(){ - int amountHeld = inputView.inputMachineAmountHeld(); - vendingMachine.saveRandomCoin(amountHeld); - outputView.printMachineAmountHeld(vendingMachine.showRandomCoins()); - - Products products = inputView.inputProducts(); - vendingMachine.registerProducts(products); - - calculator.receiveMoney(inputView.inputMoney(products)); - buyProducts(products); - - } - - private void buyProducts(Products products) { - while (true){ - outputView.printCurInputMoney(calculator.getInputMoney()); - if(calculator.isBuyingProducts()) break; - - String name = inputView.inputBuyProduct(products); - calculator.buyProducts(name); - } - outputView.printResultChange(calculator.returnChange()); - } -} diff --git a/src/main/java/vendingmachine/Coin.java b/src/main/java/vendingmachine/constants/Coin.java similarity index 96% rename from src/main/java/vendingmachine/Coin.java rename to src/main/java/vendingmachine/constants/Coin.java index e00f5fa08..268f069c8 100644 --- a/src/main/java/vendingmachine/Coin.java +++ b/src/main/java/vendingmachine/constants/Coin.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.constants; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/vendingmachine/ErrorMessage.java b/src/main/java/vendingmachine/constants/ErrorMessage.java similarity index 96% rename from src/main/java/vendingmachine/ErrorMessage.java rename to src/main/java/vendingmachine/constants/ErrorMessage.java index 65edfb460..49b3e328f 100644 --- a/src/main/java/vendingmachine/ErrorMessage.java +++ b/src/main/java/vendingmachine/constants/ErrorMessage.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.constants; public enum ErrorMessage { MACHINE_COIN_NUMERIC_ERROR("숫자를 입력해 주세요"), @@ -10,7 +10,6 @@ public enum ErrorMessage { INPUT_PRODUCT_NAME_ERROR("존재하지 않는 상품명 입니다."); - private static final String ERROR = "[ERROR] "; private final String message; diff --git a/src/main/java/vendingmachine/ProgressMessage.java b/src/main/java/vendingmachine/constants/ProgressMessage.java similarity index 95% rename from src/main/java/vendingmachine/ProgressMessage.java rename to src/main/java/vendingmachine/constants/ProgressMessage.java index 8280b8ffc..42088e149 100644 --- a/src/main/java/vendingmachine/ProgressMessage.java +++ b/src/main/java/vendingmachine/constants/ProgressMessage.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.constants; public enum ProgressMessage { INPUT_MACHINE_AMOUNT_HELD("자판기가 보유하고 있는 금액을 입력해 주세요."), diff --git a/src/main/java/vendingmachine/ScreenElement.java b/src/main/java/vendingmachine/constants/ScreenElement.java similarity index 88% rename from src/main/java/vendingmachine/ScreenElement.java rename to src/main/java/vendingmachine/constants/ScreenElement.java index d375aa689..d49245308 100644 --- a/src/main/java/vendingmachine/ScreenElement.java +++ b/src/main/java/vendingmachine/constants/ScreenElement.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.constants; public enum ScreenElement { COIN_UNIT("원"), diff --git a/src/main/java/vendingmachine/controller/MachineController.java b/src/main/java/vendingmachine/controller/MachineController.java new file mode 100644 index 000000000..b15ef9fd2 --- /dev/null +++ b/src/main/java/vendingmachine/controller/MachineController.java @@ -0,0 +1,49 @@ +package vendingmachine.controller; + +import vendingmachine.domain.Products; +import vendingmachine.domain.VendingMachine; +import vendingmachine.service.CalculatorService; +import vendingmachine.view.InputView; +import vendingmachine.view.OutputView; + +public class MachineController { + + private final InputView inputView; + private final OutputView outputView; + private final VendingMachine vendingMachine; + private final CalculatorService calculatorService; + + public MachineController() { + this.inputView = new InputView(); + this.outputView = new OutputView(); + this.vendingMachine = new VendingMachine(); + this.calculatorService = new CalculatorService(vendingMachine); + } + + public void run() { + initVendingMachineAmountHeld(); + + Products products = inputView.inputProducts(); + vendingMachine.registerProducts(products); + + calculatorService.receiveMoney(inputView.inputMoney(products)); + buyProducts(products); + } + + private void initVendingMachineAmountHeld() { + int amountHeld = inputView.inputMachineAmountHeld(); + vendingMachine.saveRandomCoin(amountHeld); + outputView.printMachineAmountHeld(vendingMachine.showRandomCoins()); + } + + private void buyProducts(Products products) { + while (true) { + outputView.printCurInputMoney(calculatorService.getInputMoney()); + if (calculatorService.isBuyingProducts()) break; + + String name = inputView.inputBuyProduct(products); + calculatorService.buyProducts(name); + } + outputView.printResultChange(calculatorService.returnChange()); + } +} diff --git a/src/main/java/vendingmachine/MakeRandomCoin.java b/src/main/java/vendingmachine/domain/MakeRandomCoin.java similarity index 90% rename from src/main/java/vendingmachine/MakeRandomCoin.java rename to src/main/java/vendingmachine/domain/MakeRandomCoin.java index 31713aa99..2b1a4e45e 100644 --- a/src/main/java/vendingmachine/MakeRandomCoin.java +++ b/src/main/java/vendingmachine/domain/MakeRandomCoin.java @@ -1,5 +1,7 @@ -package vendingmachine; +package vendingmachine.domain; + import camp.nextstep.edu.missionutils.Randoms; +import vendingmachine.constants.Coin; import java.util.ArrayList; import java.util.List; @@ -18,7 +20,7 @@ private boolean isMakingRandomCoins(int amount) { return getSum(randomCoins) != amount; } - private int randomCoin(){ + private int randomCoin() { return Randoms.pickNumberInList(Coin.coinPrices()); } diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/domain/Product.java similarity index 87% rename from src/main/java/vendingmachine/Product.java rename to src/main/java/vendingmachine/domain/Product.java index 7dee80949..ab3ce802b 100644 --- a/src/main/java/vendingmachine/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -1,4 +1,6 @@ -package vendingmachine; +package vendingmachine.domain; + +import vendingmachine.constants.ErrorMessage; public class Product { @@ -15,16 +17,16 @@ public Product(String name, int price, int amount) { this.amount = amount; } + private static boolean isaBreakPriceRule(int price) { + return price < MIN_PRICE || price % COIN_UNIT != 0; + } + private void validatePriceRule(int price) { - if (isaBreakPriceRule(price)){ + if (isaBreakPriceRule(price)) { throw new IllegalArgumentException(ErrorMessage.PRODUCT_PRICE_ERROR.getMessage()); } } - private static boolean isaBreakPriceRule(int price) { - return price < MIN_PRICE || price % COIN_UNIT != 0; - } - public int getPrice() { return price; } diff --git a/src/main/java/vendingmachine/Products.java b/src/main/java/vendingmachine/domain/Products.java similarity index 83% rename from src/main/java/vendingmachine/Products.java rename to src/main/java/vendingmachine/domain/Products.java index a01eca871..3871a2416 100644 --- a/src/main/java/vendingmachine/Products.java +++ b/src/main/java/vendingmachine/domain/Products.java @@ -1,4 +1,6 @@ -package vendingmachine; +package vendingmachine.domain; + +import vendingmachine.constants.ErrorMessage; import java.util.Arrays; import java.util.List; @@ -18,20 +20,20 @@ public Products(String productData) { .collect(Collectors.toList()); } - public void validateInputMoney(String money){ + public void validateInputMoney(String money) { int price = Integer.parseInt(money); - if(getMinProductPrice() > price){ + if (getMinProductPrice() > price) { throw new IllegalArgumentException(ErrorMessage.INPUT_MONEY_ERROR.getMessage()); } } public void validateInputProductName(String name) { - if (products.stream().noneMatch(product -> product.getName().equals(name))){ + if (products.stream().noneMatch(product -> product.getName().equals(name))) { throw new IllegalArgumentException(ErrorMessage.INPUT_PRODUCT_NAME_ERROR.getMessage()); } } - public boolean isBuyingProducts(int inputMoney){ + public boolean isBuyingProducts(int inputMoney) { return inputMoney < getMinProductPrice() || isProductSoldOut(); } @@ -42,14 +44,14 @@ private int getMinProductPrice() { .orElse(Integer.MAX_VALUE); } - private boolean isProductSoldOut(){ + private boolean isProductSoldOut() { int amount = products.stream() .mapToInt(Product::getAmount) .sum(); return amount == 0; } - public int getProductPrice(String name){ + public int getProductPrice(String name) { return products.stream() .filter(product -> product.getName().equals(name)) .findFirst() diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java similarity index 67% rename from src/main/java/vendingmachine/VendingMachine.java rename to src/main/java/vendingmachine/domain/VendingMachine.java index c0ae04c5b..ae15715cc 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -1,8 +1,10 @@ -package vendingmachine; +package vendingmachine.domain; + +import vendingmachine.constants.Coin; +import vendingmachine.constants.ScreenElement; import java.util.EnumMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public class VendingMachine { @@ -11,12 +13,12 @@ public class VendingMachine { private Products products; public VendingMachine() { - for (Coin coin : Coin.values()){ + for (Coin coin : Coin.values()) { coins.put(coin, 0); } } - public void saveRandomCoin(int amount){ + public void saveRandomCoin(int amount) { makeRandomCoin.makeCoins(amount); List randomCoins = makeRandomCoin.getRandomCoins(); @@ -27,20 +29,14 @@ public void saveRandomCoin(int amount){ ))); } - public String showRandomCoins(){ - StringBuilder sb = new StringBuilder(); - for (Map.Entry coins : coins.entrySet()){ - sb.append(coins.getKey().toString()) - .append(ScreenElement.COIN_UNIT) - .append(ScreenElement.DIVISION) - .append(coins.getValue()) - .append(ScreenElement.COUNT_UNIT) - .append("\n"); - } - return sb.toString(); + public String showRandomCoins() { + return coins.entrySet().stream() + .map(entry -> entry.getKey().toString() + ScreenElement.COIN_UNIT + + ScreenElement.DIVISION + entry.getValue() + ScreenElement.COUNT_UNIT) + .collect(Collectors.joining("\n")); } - public EnumMap returnChange(int inputMoney){ + public EnumMap returnChange(int inputMoney) { int remainingChange = inputMoney; EnumMap changeCoins = new EnumMap<>(Coin.class); diff --git a/src/main/java/vendingmachine/service/CalculatorService.java b/src/main/java/vendingmachine/service/CalculatorService.java new file mode 100644 index 000000000..8f4a4457c --- /dev/null +++ b/src/main/java/vendingmachine/service/CalculatorService.java @@ -0,0 +1,50 @@ +package vendingmachine.service; + +import vendingmachine.constants.Coin; +import vendingmachine.constants.ScreenElement; +import vendingmachine.domain.Products; +import vendingmachine.domain.VendingMachine; + +import java.util.EnumMap; +import java.util.stream.Collectors; + +public class CalculatorService { + + private final VendingMachine vendingMachine; + private int inputMoney; + + public CalculatorService(VendingMachine vendingMachine) { + this.vendingMachine = vendingMachine; + } + + public void receiveMoney(int inputMoney) { + this.inputMoney = inputMoney; + } + + public boolean isBuyingProducts() { + Products products = vendingMachine.getProducts(); + return products.isBuyingProducts(inputMoney); + } + + public void buyProducts(String name) { + Products products = vendingMachine.getProducts(); + int productPrice = products.getProductPrice(name); + inputMoney -= productPrice; + } + + public String returnChange() { + EnumMap changeCoins = vendingMachine.returnChange(inputMoney); + + return changeCoins.entrySet().stream() + .filter(entry -> entry.getValue() != 0) + .map(entry -> entry.getKey().toString() + ScreenElement.COIN_UNIT + + ScreenElement.DIVISION + entry.getValue() + + ScreenElement.COUNT_UNIT) + .collect(Collectors.joining("\n")); + } + + public int getInputMoney() { + return inputMoney; + } + +} diff --git a/src/main/java/vendingmachine/InputValidator.java b/src/main/java/vendingmachine/view/InputValidator.java similarity index 70% rename from src/main/java/vendingmachine/InputValidator.java rename to src/main/java/vendingmachine/view/InputValidator.java index 77746e531..80fb38951 100644 --- a/src/main/java/vendingmachine/InputValidator.java +++ b/src/main/java/vendingmachine/view/InputValidator.java @@ -1,25 +1,27 @@ -package vendingmachine; +package vendingmachine.view; + +import vendingmachine.constants.ErrorMessage; public class InputValidator { private static final String NUMERIC_REGEX = "^[0-9]+$"; private static final int MIN_MACHINE_AMOUNT_HELD = 100; private static final String PRODUCT_PATTERN_REGEX = "\\[([^,]+),(\\d+),(\\d+)];"; - public void validateMachineAmountHeld(String amount){ + public void validateMachineAmountHeld(String amount) { validateNumeric(amount); - if (Integer.parseInt(amount) < MIN_MACHINE_AMOUNT_HELD){ + if (Integer.parseInt(amount) < MIN_MACHINE_AMOUNT_HELD) { throw new IllegalArgumentException(ErrorMessage.MIN_MACHINE_AMOUNT_HELD_ERROR.getMessage()); } } public void validateNumeric(String amount) { - if (!amount.matches(NUMERIC_REGEX)){ + if (!amount.matches(NUMERIC_REGEX)) { throw new IllegalArgumentException(ErrorMessage.MACHINE_COIN_NUMERIC_ERROR.getMessage()); } } public void validateDivisionProducts(String products) { - if (products.matches(PRODUCT_PATTERN_REGEX)){ + if (products.matches(PRODUCT_PATTERN_REGEX)) { throw new IllegalArgumentException(ErrorMessage.PRODUCT_REGEX_ERROR.getMessage()); } } diff --git a/src/main/java/vendingmachine/InputView.java b/src/main/java/vendingmachine/view/InputView.java similarity index 83% rename from src/main/java/vendingmachine/InputView.java rename to src/main/java/vendingmachine/view/InputView.java index 8b90eef7e..66fbe6d5f 100644 --- a/src/main/java/vendingmachine/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -1,14 +1,16 @@ -package vendingmachine; +package vendingmachine.view; -import java.util.function.Supplier; import camp.nextstep.edu.missionutils.Console; +import vendingmachine.domain.Products; + +import java.util.function.Supplier; public class InputView { private final OutputView outputView = new OutputView(); private final InputValidator inputValidator = new InputValidator(); - public Integer inputMachineAmountHeld(){ + public Integer inputMachineAmountHeld() { return read(() -> { outputView.printInputMachineAmountHeld(); String amount = Console.readLine(); @@ -18,7 +20,7 @@ public Integer inputMachineAmountHeld(){ }); } - public Products inputProducts(){ + public Products inputProducts() { return read(() -> { outputView.printInputProductsDetail(); String products = Console.readLine(); @@ -28,7 +30,7 @@ public Products inputProducts(){ }); } - public Integer inputMoney(Products products){ + public Integer inputMoney(Products products) { return read(() -> { outputView.printInputMoney(); String money = Console.readLine(); @@ -50,12 +52,11 @@ public String inputBuyProduct(Products products) { } - - private T read(Supplier input){ - while (true){ + private T read(Supplier input) { + while (true) { try { return input.get(); - }catch (IllegalArgumentException e){ + } catch (IllegalArgumentException e) { outputView.printError(e.getMessage()); } } diff --git a/src/main/java/vendingmachine/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java similarity index 71% rename from src/main/java/vendingmachine/OutputView.java rename to src/main/java/vendingmachine/view/OutputView.java index db6ddc9f3..a9c16f0d9 100644 --- a/src/main/java/vendingmachine/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -1,12 +1,14 @@ -package vendingmachine; +package vendingmachine.view; + +import vendingmachine.constants.ProgressMessage; public class OutputView { - public void printError(String error){ + public void printError(String error) { System.out.println(error); } - public void printInputMachineAmountHeld(){ + public void printInputMachineAmountHeld() { System.out.println(ProgressMessage.INPUT_MACHINE_AMOUNT_HELD); } @@ -14,16 +16,16 @@ public void printInputProductsDetail() { System.out.println(ProgressMessage.INPUT_PRODUCTS_DETAIL); } - public void printEnter(){ + public void printEnter() { System.out.println(); } - public void printMachineAmountHeld(String screen){ + public void printMachineAmountHeld(String screen) { System.out.println(ProgressMessage.MACHINE_AMOUNT_HELD); System.out.println(screen); } - public void printInputMoney(){ + public void printInputMoney() { System.out.println(ProgressMessage.INPUT_MONEY); } @@ -31,7 +33,7 @@ public void printInputBuyProductName() { System.out.println(ProgressMessage.INPUT_BUY_PRODUCT_NAME); } - public void printCurInputMoney(int money){ + public void printCurInputMoney(int money) { System.out.printf((ProgressMessage.CUR_INPUT_MONEY) + "%n", money); } From fdd42ce893d0b13da85a935f2297bb50d8014513 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 14:52:38 +0900 Subject: [PATCH 34/40] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Readme.md | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/Readme.md b/docs/Readme.md index c3025b255..64ed85f39 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -1,23 +1,34 @@ ## 기능 목록 - InputView - - 자판기가 보유하고 있는 금액 입력 - - 상품명, 가격, 수량을 입력 - - 구매할 상품명 입력 + - [x] 자판기가 보유하고 있는 금액 입력 + - [x] 상품명, 가격, 수량을 입력 + - [x] 구매할 상품명 입력 - MakeRandomCoin - - 자판기가 보유하고 있는 금액으로 동전을 무작위로 생성 + - [x] 자판기가 보유하고 있는 금액으로 동전을 무작위로 생성 + +- product + - [x] 상품 정보 저장 + - [x] 상품 저장 형식이 옳지 않으면 오류 발생 - Products - - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. - - 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. + - [x] 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. + - [x] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. + - [x] 상품 최소 가격이 입력 가격 보다 크면 오류 발생 + - [x] 상품리스트에 없는 상품이름을 입력하면 오류 발생 + +- VendingMachine + - [x] 보유 금액, 상품 저장 + - [x] 잔돈 반환 -- Calculator - - 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. - - 잔돈을 돌려줄 때 현재 보유한 최소 개수의 동전으로 잔돈을 돌려준다. - - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. - - 반환되지 않은 금액은 자판기에 남는다. +- CalculatorService + - [x] 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. + - [x] 잔돈을 돌려줄 때 현재 보유한 최소 개수의 동전으로 잔돈을 돌려준다. + - [x] 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. + - [x] 반환되지 않은 금액은 자판기에 남는다. ## 에러 처리 -- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. -- 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. \ No newline at end of file +- [x] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. +- [x] 상품 저장 형식 에러 처리 +- [x] 자판기 보유 금액 에러 처리(숫자, 최솟값) \ No newline at end of file From 487e2fbbf1480e1fdf4d5013833d6fa6cd53b851 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 15:03:18 +0900 Subject: [PATCH 35/40] test: CoinTest --- src/test/java/vendingmachine/CoinTest.java | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/java/vendingmachine/CoinTest.java diff --git a/src/test/java/vendingmachine/CoinTest.java b/src/test/java/vendingmachine/CoinTest.java new file mode 100644 index 000000000..27fbf9d84 --- /dev/null +++ b/src/test/java/vendingmachine/CoinTest.java @@ -0,0 +1,26 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.constants.Coin; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +class CoinTest { + + @Test + @DisplayName("코인 가격들을 리스트로 반환한다.") + void getCoinPrices(){ + List coins = Coin.coinPrices(); + assertThat(coins).contains(500, 100, 50, 10); + } + + @Test + @DisplayName("코인 가격에 맞는 Coin을 반환한다.") + void getCoinByPrice(){ + Coin coin = Coin.getByAmount(500); + assertThat(coin).isEqualTo(Coin.COIN_500); + } +} From b2b0a0155540b7336c27aed6bb233df811c96892 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 15:08:15 +0900 Subject: [PATCH 36/40] test: MakeRandomCoinTest --- .../vendingmachine/MakeRandomCoinTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/java/vendingmachine/MakeRandomCoinTest.java diff --git a/src/test/java/vendingmachine/MakeRandomCoinTest.java b/src/test/java/vendingmachine/MakeRandomCoinTest.java new file mode 100644 index 000000000..848e4903a --- /dev/null +++ b/src/test/java/vendingmachine/MakeRandomCoinTest.java @@ -0,0 +1,24 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.domain.MakeRandomCoin; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +public class MakeRandomCoinTest { + + MakeRandomCoin makeRandomCoin = new MakeRandomCoin(); + + @Test + @DisplayName("랜덤된 Coin을 저장한다.") + void saveRandomCoin(){ + makeRandomCoin.makeCoins(450); + + List coins = makeRandomCoin.getRandomCoins(); + + assertThat(coins).containsAnyOf(500, 100, 50, 10); + } +} From 604c9f6bc63da5f8abdec923d6fa7536ca065975 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 15:12:47 +0900 Subject: [PATCH 37/40] test: ProductTest --- src/test/java/vendingmachine/ProductTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/java/vendingmachine/ProductTest.java diff --git a/src/test/java/vendingmachine/ProductTest.java b/src/test/java/vendingmachine/ProductTest.java new file mode 100644 index 000000000..aa70deadb --- /dev/null +++ b/src/test/java/vendingmachine/ProductTest.java @@ -0,0 +1,20 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.domain.Product; + +import static org.assertj.core.api.Assertions.*; + +public class ProductTest { + + private static final String ERROR = "[ERROR] "; + + @Test + @DisplayName("상품 가격은 100원부터 시작하며, 10원으로 나누어떨어지지 않으면 에러가 발생한다.") + void validateProductRule(){ + assertThatThrownBy(() -> new Product("콜라", 455, 20)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(ERROR); + } +} From d032920097e11448b3d7978ebd887510fcae4c81 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 15:19:27 +0900 Subject: [PATCH 38/40] test: ProductsTest --- .../java/vendingmachine/ProductsTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/test/java/vendingmachine/ProductsTest.java diff --git a/src/test/java/vendingmachine/ProductsTest.java b/src/test/java/vendingmachine/ProductsTest.java new file mode 100644 index 000000000..c80a2b2a7 --- /dev/null +++ b/src/test/java/vendingmachine/ProductsTest.java @@ -0,0 +1,37 @@ +package vendingmachine; + + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.domain.Products; + +import static org.assertj.core.api.Assertions.*; + +public class ProductsTest { + + private static final String ERROR = "[ERROR] "; + Products products = new Products("[콜라,1500,20];[사이다,1000,10]"); + @Test + @DisplayName("상품이 저장되는지 확인한다.") + void saveProducts(){ + int price = products.getProductPrice("콜라"); + + assertThat(price).isEqualTo(1500); + } + + @Test + @DisplayName("상품의 최저 가격보다 낮은 돈을 입력하면 에러가 발생한다..") + void validateInputMoney(){ + assertThatThrownBy(() -> products.validateInputMoney("500")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(ERROR); + } + + @Test + @DisplayName("저장된 상품의 이름과 일치하지 않으면 에러가 발생한다.") + void validateInputProductName(){ + assertThatThrownBy(() -> products.validateInputProductName("환타")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(ERROR); + } +} From c80845ea2649ab3a88cf85a401a48113c9365202 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 15:32:44 +0900 Subject: [PATCH 39/40] test: VendingMachineTest --- .../vendingmachine/VendingMachineTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/test/java/vendingmachine/VendingMachineTest.java diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/VendingMachineTest.java new file mode 100644 index 000000000..2db6b3725 --- /dev/null +++ b/src/test/java/vendingmachine/VendingMachineTest.java @@ -0,0 +1,35 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.constants.Coin; +import vendingmachine.domain.VendingMachine; + +import java.util.EnumMap; + +import static org.assertj.core.api.Assertions.*; +public class VendingMachineTest { + + VendingMachine vendingMachine = new VendingMachine(); + @Test + @DisplayName("랜덤으로 생성된 동전을 확인 할 수 있다.") + void showRandomCoins(){ + vendingMachine.saveRandomCoin(30); + + String screen = vendingMachine.showRandomCoins(); + + assertThat(screen).containsAnyOf("500원 - 0개", "100원 - 0개", "50원 - 0개", "10원 - 3개"); + } + + @Test + @DisplayName("자판기가 잔돈을 최소의 개수로 반환할 수 있다.") + void getMinCountChange(){ + vendingMachine.saveRandomCoin(30); + EnumMap changeCoins = vendingMachine.returnChange(30); + + int amount = changeCoins.get(Coin.COIN_10); + + assertThat(amount).isEqualTo(3); + + } +} From a631c1f8e0c79973fe8c7b9d1fa67998d80e7a58 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Mon, 25 Sep 2023 15:40:49 +0900 Subject: [PATCH 40/40] test: InputValidatorTest --- .../vendingmachine/view/InputValidator.java | 4 +- .../vendingmachine/InputValidatorTest.java | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/test/java/vendingmachine/InputValidatorTest.java diff --git a/src/main/java/vendingmachine/view/InputValidator.java b/src/main/java/vendingmachine/view/InputValidator.java index 80fb38951..0c546aaaf 100644 --- a/src/main/java/vendingmachine/view/InputValidator.java +++ b/src/main/java/vendingmachine/view/InputValidator.java @@ -5,7 +5,7 @@ public class InputValidator { private static final String NUMERIC_REGEX = "^[0-9]+$"; private static final int MIN_MACHINE_AMOUNT_HELD = 100; - private static final String PRODUCT_PATTERN_REGEX = "\\[([^,]+),(\\d+),(\\d+)];"; + private static final String PRODUCT_PATTERN_REGEX = "\\[[^\\[\\]]+,\\d+,\\d+\\](;\\[[^\\[\\]]+,\\d+,\\d+\\])*"; public void validateMachineAmountHeld(String amount) { validateNumeric(amount); @@ -21,7 +21,7 @@ public void validateNumeric(String amount) { } public void validateDivisionProducts(String products) { - if (products.matches(PRODUCT_PATTERN_REGEX)) { + if (!products.matches(PRODUCT_PATTERN_REGEX)) { throw new IllegalArgumentException(ErrorMessage.PRODUCT_REGEX_ERROR.getMessage()); } } diff --git a/src/test/java/vendingmachine/InputValidatorTest.java b/src/test/java/vendingmachine/InputValidatorTest.java new file mode 100644 index 000000000..f4c35e3e2 --- /dev/null +++ b/src/test/java/vendingmachine/InputValidatorTest.java @@ -0,0 +1,38 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.view.InputValidator; + + +import static org.assertj.core.api.Assertions.*; + +public class InputValidatorTest { + + InputValidator inputValidator = new InputValidator(); + private static final String ERROR = "[ERROR] "; + + @Test + @DisplayName("자판기가 보유한 금액이 100원 이상 입력하지 않으면 에러가 발생한다.") + void validateMachineAmountHeld(){ + assertThatThrownBy(() -> inputValidator.validateMachineAmountHeld("50")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(ERROR); + } + + @Test + @DisplayName("자판기가 보유한 금액이 숫자가 않으면 에러가 발생한다.") + void validateNumeric(){ + assertThatThrownBy(() -> inputValidator.validateNumeric("ㄱㄱ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(ERROR); + } + + @Test + @DisplayName("상품저장 형식이 옳지 않으면 에러가 발생한다.") + void validateDivisionProducts(){ + assertThatThrownBy(() -> inputValidator.validateDivisionProducts("ㄱㄱ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(ERROR); + } +}