From 33bb09e37b5e8c2274447a1f2b8d252c57a417e2 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 7 Dec 2022 21:57:14 +0900 Subject: [PATCH 01/13] =?UTF-8?q?fix:=20=EC=9E=90=EB=B0=94=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 8 -> 11 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 67e032179..cf1e54f32 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ dependencies { java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(11) } } From 8a827690a371ca26c44f88f95c44e9f7e82879c1 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 8 Dec 2022 00:50:05 +0900 Subject: [PATCH 02/13] =?UTF-8?q?docs:=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=AA=A9=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..d0e322147 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,22 @@ +# 자판기 + +## 기능 목록 + +### 자판기 +- [ ] 자판기가 보유하고 있는 금액으로 동전을 무작위로 생성하는 기능 + - [ ] 자판기가 보유하고 있는 금액을 입력받는 기능 + - [ ] 자판기가 보유한 동전을 출력하는 기능 +- [ ] 상품명, 가격, 수량을 입력하여 상품을 추가하는 기능 + - [ ] 상품 가격이 100원 이상인지 확인하는 기능 + - [ ] 상품 가격이 10원으로 나누어지는지 확인하는 기능 + - [ ] 상품명이 다른 상품명과 중복 되지않는지 확인하는 기능 + - [ ] 수량이 양수 인지 확인하는 기능 +- [ ] 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 잔돈 반환 기능 + - [ ] 잔돈을 돌려줄 때 현재 보유한 최소 개수의 동전으로 잔돈 반환 기능 + - [ ] 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환하는 기능 + - [ ] 잔돈 출력 기능 + +### 사용자 +- [ ] 사용자가 투입한 금액으로 상품을 구매하는 기능 + - [ ] 투입 금액이 양수 인지 확인하는 기능 + - [ ] 투입 금액 출력 기능 \ No newline at end of file From 14fcd46a02d5b9a9b7cf9cfa5c9e71d163e4c1d3 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 8 Dec 2022 10:16:10 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20skeleton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Application.java | 5 ++++- .../controller/VendingMachineController.java | 14 ++++++++++++++ .../java/vendingmachine/{ => domain}/Coin.java | 2 +- .../java/vendingmachine/domain/VendingMachine.java | 4 ++++ src/main/java/vendingmachine/view/InputView.java | 4 ++++ src/main/java/vendingmachine/view/OutputView.java | 4 ++++ 6 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/main/java/vendingmachine/controller/VendingMachineController.java rename src/main/java/vendingmachine/{ => domain}/Coin.java (87%) create mode 100644 src/main/java/vendingmachine/domain/VendingMachine.java create mode 100644 src/main/java/vendingmachine/view/InputView.java create mode 100644 src/main/java/vendingmachine/view/OutputView.java diff --git a/src/main/java/vendingmachine/Application.java b/src/main/java/vendingmachine/Application.java index 9d3be447b..3d38d50ff 100644 --- a/src/main/java/vendingmachine/Application.java +++ b/src/main/java/vendingmachine/Application.java @@ -1,7 +1,10 @@ package vendingmachine; +import vendingmachine.controller.VendingMachineController; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + VendingMachineController vendingMachineController = new VendingMachineController(); + vendingMachineController.runVendingMachine(); } } diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java new file mode 100644 index 000000000..d40038a8c --- /dev/null +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -0,0 +1,14 @@ +package vendingmachine.controller; + +import vendingmachine.view.InputView; +import vendingmachine.view.OutputView; + +public class VendingMachineController { + + private final InputView inputView = new InputView(); + private final OutputView outputView = new OutputView(); + + public void runVendingMachine() { + + } +} diff --git a/src/main/java/vendingmachine/Coin.java b/src/main/java/vendingmachine/domain/Coin.java similarity index 87% rename from src/main/java/vendingmachine/Coin.java rename to src/main/java/vendingmachine/domain/Coin.java index c76293fbc..7bb89c146 100644 --- a/src/main/java/vendingmachine/Coin.java +++ b/src/main/java/vendingmachine/domain/Coin.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.domain; public enum Coin { COIN_500(500), diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java new file mode 100644 index 000000000..7adc90a84 --- /dev/null +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -0,0 +1,4 @@ +package vendingmachine.domain; + +public class VendingMachine { +} diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java new file mode 100644 index 000000000..126e50dbd --- /dev/null +++ b/src/main/java/vendingmachine/view/InputView.java @@ -0,0 +1,4 @@ +package vendingmachine.view; + +public class InputView { +} diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java new file mode 100644 index 000000000..2a53e8a58 --- /dev/null +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -0,0 +1,4 @@ +package vendingmachine.view; + +public class OutputView { +} From c72a7838cc0832f49e286ff8712b636cefec92f0 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 9 Dec 2022 07:23:54 +0900 Subject: [PATCH 04/13] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EC=9E=90?= =?UTF-8?q?=ED=8C=90=EA=B8=B0=EA=B0=80=20=EB=B3=B4=EC=9C=A0=ED=95=98?= =?UTF-8?q?=EA=B3=A0=20=EC=9E=88=EB=8A=94=20=EA=B8=88=EC=95=A1=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=8F=99=EC=A0=84=EC=9D=84=20=EB=AC=B4=EC=9E=91?= =?UTF-8?q?=EC=9C=84=EB=A1=9C=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VendingMachineController.java | 28 +++++++++++ src/main/java/vendingmachine/domain/Coin.java | 16 ------ .../java/vendingmachine/domain/Money.java | 41 ++++++++++++++++ .../vendingmachine/domain/VendingMachine.java | 8 +++ .../vendingmachine/domain/coins/Coin.java | 49 +++++++++++++++++++ .../vendingmachine/domain/coins/Coins.java | 45 +++++++++++++++++ .../domain/coins/NumberGenerator.java | 8 +++ .../domain/coins/RandomNumberGenerator.java | 14 ++++++ .../exception/CoinEmptyException.java | 10 ++++ .../exception/IntConvertException.java | 10 ++++ .../exception/MoneyRangeException.java | 10 ++++ .../java/vendingmachine/util/IntConvert.java | 14 ++++++ .../java/vendingmachine/view/InputView.java | 9 ++++ .../java/vendingmachine/view/OutputView.java | 29 +++++++++++ .../java/vendingmachine/IntConvertTest.java | 22 +++++++++ 15 files changed, 297 insertions(+), 16 deletions(-) delete mode 100644 src/main/java/vendingmachine/domain/Coin.java create mode 100644 src/main/java/vendingmachine/domain/Money.java create mode 100644 src/main/java/vendingmachine/domain/coins/Coin.java create mode 100644 src/main/java/vendingmachine/domain/coins/Coins.java create mode 100644 src/main/java/vendingmachine/domain/coins/NumberGenerator.java create mode 100644 src/main/java/vendingmachine/domain/coins/RandomNumberGenerator.java create mode 100644 src/main/java/vendingmachine/exception/CoinEmptyException.java create mode 100644 src/main/java/vendingmachine/exception/IntConvertException.java create mode 100644 src/main/java/vendingmachine/exception/MoneyRangeException.java create mode 100644 src/main/java/vendingmachine/util/IntConvert.java create mode 100644 src/test/java/vendingmachine/IntConvertTest.java diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index d40038a8c..8b5f55f00 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -1,14 +1,42 @@ package vendingmachine.controller; +import vendingmachine.domain.*; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; +import java.util.function.Supplier; + public class VendingMachineController { private final InputView inputView = new InputView(); private final OutputView outputView = new OutputView(); + private VendingMachine vendingMachine; public void runVendingMachine() { + makeCoins(); + } + + private Coins makeCoins() { + Coins coins = new Coins(); + coins.makeRandomCoins(new RandomNumberGenerator(), askMoney()); + outputView.printCoins(coins); + return coins; + } + + private Money askMoney() { + outputView.printInputVendingMachineAmount(); + Money money = reenterProcess(inputView::readMoney); + outputView.printNewLine(); + return money; + } + private T reenterProcess(Supplier reader) { + while (true) { + try { + return reader.get(); + } catch (IllegalArgumentException exception) { + outputView.printExceptionMessage(exception); + } + } } } diff --git a/src/main/java/vendingmachine/domain/Coin.java b/src/main/java/vendingmachine/domain/Coin.java deleted file mode 100644 index 7bb89c146..000000000 --- a/src/main/java/vendingmachine/domain/Coin.java +++ /dev/null @@ -1,16 +0,0 @@ -package vendingmachine.domain; - -public enum Coin { - COIN_500(500), - COIN_100(100), - COIN_50(50), - COIN_10(10); - - private final int amount; - - Coin(final int amount) { - this.amount = amount; - } - - // 추가 기능 구현 -} diff --git a/src/main/java/vendingmachine/domain/Money.java b/src/main/java/vendingmachine/domain/Money.java new file mode 100644 index 000000000..3f41571bc --- /dev/null +++ b/src/main/java/vendingmachine/domain/Money.java @@ -0,0 +1,41 @@ +package vendingmachine.domain; + +import vendingmachine.exception.MoneyRangeException; + +public class Money { + + private static final int MIN_MONEY = 0; + private static final int MAX_MONEY = 1_000_000_000; + private static final int ZERO_MONEY = 0; + + private int money; + + private Money(int money) { + validate(money); + this.money = money; + } + + public static Money from(int money) { + return new Money(money); + } + + private static void validate(int money) { + validateRange(money); + } + + private static void validateRange(int money) { + if (money < MIN_MONEY || money > MAX_MONEY) { + throw new MoneyRangeException(MIN_MONEY, MAX_MONEY); + } + } + + public void useMoney(int pay) { + if (isUseMoney(pay)) { + this.money -= pay; + } + } + + public boolean isUseMoney(int money) { + return (this.money - money) >= ZERO_MONEY; + } +} diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 7adc90a84..68c6bcea6 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -1,4 +1,12 @@ package vendingmachine.domain; public class VendingMachine { + + private final Money money; + private final Coins coins; + + private VendingMachine(Money money, Coins coins) { + this.money = money; + this.coins = coins; + } } diff --git a/src/main/java/vendingmachine/domain/coins/Coin.java b/src/main/java/vendingmachine/domain/coins/Coin.java new file mode 100644 index 000000000..70dbd1117 --- /dev/null +++ b/src/main/java/vendingmachine/domain/coins/Coin.java @@ -0,0 +1,49 @@ +package vendingmachine.domain.coins; + +import vendingmachine.domain.Money; +import vendingmachine.exception.CoinEmptyException; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public enum Coin { + COIN_500(500), + COIN_100(100), + COIN_50(50), + COIN_10(10); + + private final int amount; + + Coin(final int amount) { + this.amount = amount; + } + + public static Coin of(int amount) { + return Arrays.stream(values()) + .filter(coin -> coin.amount == amount) + .findAny() + .orElseThrow(CoinEmptyException::new); + } + + public static List makeAmountList() { + return Arrays.stream(values()) + .map(Coin::getAmount) + .collect(Collectors.toList()); + } + + public static int findMinAmount() { + return Arrays.stream(values()) + .mapToInt(Coin::getAmount) + .min() + .orElseThrow(CoinEmptyException::new); + } + + public Money exchangeCoinToMoney() { + return Money.from(amount); + } + + public int getAmount() { + return amount; + } +} diff --git a/src/main/java/vendingmachine/domain/coins/Coins.java b/src/main/java/vendingmachine/domain/coins/Coins.java new file mode 100644 index 000000000..099948d9a --- /dev/null +++ b/src/main/java/vendingmachine/domain/coins/Coins.java @@ -0,0 +1,45 @@ +package vendingmachine.domain.coins; + +import vendingmachine.domain.Money; + +import java.util.EnumMap; +import java.util.List; + +public class Coins { + + private static final int INITIAL_COIN_NUMBER = 0; + + private final EnumMap coins; + + public Coins() { + this.coins = initCoins(); + } + + public void makeRandomCoins(NumberGenerator numberGenerator, Money money) { + List coinAmounts = Coin.makeAmountList(); + int minAmount = Coin.findMinAmount(); + + while (money.isUseMoney(minAmount)) { + int number = numberGenerator.generate(coinAmounts); + if (money.isUseMoney(number)) { + money.useMoney(number); + this.coins.put(Coin.of(number), this.coins.get(Coin.of(number)) + 1); + } + if (!money.isUseMoney(number)) { + coinAmounts.remove((Integer) number); + } + } + } + + private EnumMap initCoins() { + EnumMap coins = new EnumMap<>(Coin.class); + for (Coin coin : Coin.values()) { + coins.put(coin, INITIAL_COIN_NUMBER); + } + return coins; + } + + public EnumMap getCoins() { + return coins; + } +} diff --git a/src/main/java/vendingmachine/domain/coins/NumberGenerator.java b/src/main/java/vendingmachine/domain/coins/NumberGenerator.java new file mode 100644 index 000000000..3b8220aa4 --- /dev/null +++ b/src/main/java/vendingmachine/domain/coins/NumberGenerator.java @@ -0,0 +1,8 @@ +package vendingmachine.domain.coins; + +import java.util.List; + +public interface NumberGenerator { + + int generate(List numbers); +} diff --git a/src/main/java/vendingmachine/domain/coins/RandomNumberGenerator.java b/src/main/java/vendingmachine/domain/coins/RandomNumberGenerator.java new file mode 100644 index 000000000..6d84d3c48 --- /dev/null +++ b/src/main/java/vendingmachine/domain/coins/RandomNumberGenerator.java @@ -0,0 +1,14 @@ +package vendingmachine.domain.coins; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.List; + + +public class RandomNumberGenerator implements NumberGenerator { + + @Override + public int generate(List numbers) { + return Randoms.pickNumberInList(numbers); + } +} diff --git a/src/main/java/vendingmachine/exception/CoinEmptyException.java b/src/main/java/vendingmachine/exception/CoinEmptyException.java new file mode 100644 index 000000000..7ad501bd7 --- /dev/null +++ b/src/main/java/vendingmachine/exception/CoinEmptyException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class CoinEmptyException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_COIN_EMPTY = "[ERROR] 존재하지 않는 코인입니다."; + + public CoinEmptyException() { + super(EXCEPTION_MESSAGE_COIN_EMPTY); + } +} diff --git a/src/main/java/vendingmachine/exception/IntConvertException.java b/src/main/java/vendingmachine/exception/IntConvertException.java new file mode 100644 index 000000000..c41f0ed2d --- /dev/null +++ b/src/main/java/vendingmachine/exception/IntConvertException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class IntConvertException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_CONVERT_INT = "[ERROR] 입력값이 숫자가 아니거나 값의 범위를 초과했습니다."; + + public IntConvertException() { + super(EXCEPTION_MESSAGE_CONVERT_INT); + } +} diff --git a/src/main/java/vendingmachine/exception/MoneyRangeException.java b/src/main/java/vendingmachine/exception/MoneyRangeException.java new file mode 100644 index 000000000..91a6bab93 --- /dev/null +++ b/src/main/java/vendingmachine/exception/MoneyRangeException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class MoneyRangeException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_MONEY_RANGE = "[ERROR] 돈은 %d 원 이상, %d 원 이하 이어야 합니다."; + + public MoneyRangeException(int minMoney, int maxMoney) { + super(String.format(EXCEPTION_MESSAGE_MONEY_RANGE, minMoney, maxMoney)); + } +} diff --git a/src/main/java/vendingmachine/util/IntConvert.java b/src/main/java/vendingmachine/util/IntConvert.java new file mode 100644 index 000000000..653b411ab --- /dev/null +++ b/src/main/java/vendingmachine/util/IntConvert.java @@ -0,0 +1,14 @@ +package vendingmachine.util; + +import vendingmachine.exception.IntConvertException; + +public class IntConvert { + + public static int convert(String input) { + try { + return Integer.parseInt(input); + } catch (NumberFormatException exception) { + throw new IntConvertException(); + } + } +} diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 126e50dbd..f13d67973 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -1,4 +1,13 @@ package vendingmachine.view; +import vendingmachine.domain.Money; +import vendingmachine.util.ConvertInt; + +import static camp.nextstep.edu.missionutils.Console.readLine; + public class InputView { + + public Money readMoney() { + return Money.from(ConvertInt.convert(readLine())); + } } diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index 2a53e8a58..8f00ce0c8 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -1,4 +1,33 @@ package vendingmachine.view; +import vendingmachine.domain.Coin; +import vendingmachine.domain.Coins; + +import java.util.EnumMap; +import java.util.Map; + public class OutputView { + + private static final String MESSAGE_INPUT_VENDING_MACHINE_AMOUNT = "자판기가 보유하고 있는 금액을 입력해 주세요."; + private static final String MESSAGE_COINS = "%d원 - %d개"; + + public void printExceptionMessage(IllegalArgumentException exception) { + System.out.println(exception.getMessage()); + } + + public void printInputVendingMachineAmount() { + System.out.println(MESSAGE_INPUT_VENDING_MACHINE_AMOUNT); + } + + public void printNewLine() { + System.out.println(); + } + + public void printCoins(Coins coins) { + for (Map.Entry coinEntry : coins.getCoins().entrySet()) { + System.out.printf(MESSAGE_COINS, coinEntry.getKey().getAmount(), coinEntry.getValue()); + System.out.println(); + } + System.out.println(); + } } diff --git a/src/test/java/vendingmachine/IntConvertTest.java b/src/test/java/vendingmachine/IntConvertTest.java new file mode 100644 index 000000000..c22a9f63f --- /dev/null +++ b/src/test/java/vendingmachine/IntConvertTest.java @@ -0,0 +1,22 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.util.IntConvert; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class IntConvertTest { + + private static final String EXCEPTION_MESSAGE_CONVERT_INT = "[ERROR] 입력값이 숫자가 아니거나 값의 범위를 초과했습니다."; + + @DisplayName("숫자가 아니면 에러가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"a", "$%", "\n"}) + void InputIsNotNumber(String input) { + assertThatThrownBy(() -> IntConvert.convert(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_CONVERT_INT); + } +} From fe08b52e16924f7ff3be9f12f29482de861c29a8 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 9 Dec 2022 07:24:21 +0900 Subject: [PATCH 05/13] =?UTF-8?q?test:=20=EC=B6=94=EA=B0=80=20=EC=9E=90?= =?UTF-8?q?=ED=8C=90=EA=B8=B0=EA=B0=80=20=EB=B3=B4=EC=9C=A0=ED=95=98?= =?UTF-8?q?=EA=B3=A0=20=EC=9E=88=EB=8A=94=20=EA=B8=88=EC=95=A1=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=8F=99=EC=A0=84=EC=9D=84=20=EB=AC=B4=EC=9E=91?= =?UTF-8?q?=EC=9C=84=EB=A1=9C=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/vendingmachine/CoinTest.java | 35 +++++++++++++ src/test/java/vendingmachine/CoinsTest.java | 43 ++++++++++++++++ src/test/java/vendingmachine/MoneyTest.java | 55 +++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 src/test/java/vendingmachine/CoinTest.java create mode 100644 src/test/java/vendingmachine/CoinsTest.java create mode 100644 src/test/java/vendingmachine/MoneyTest.java diff --git a/src/test/java/vendingmachine/CoinTest.java b/src/test/java/vendingmachine/CoinTest.java new file mode 100644 index 000000000..18563cec2 --- /dev/null +++ b/src/test/java/vendingmachine/CoinTest.java @@ -0,0 +1,35 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.domain.coins.Coin; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CoinTest { + + @DisplayName("입력한 코인금액에 맞는 코인을 반환한다.") + @Test + void getCoinByAmountSuccess() { + assertThat(Coin.of(10)).isEqualTo(Coin.COIN_10); + assertThat(Coin.of(50)).isEqualTo(Coin.COIN_50); + assertThat(Coin.of(100)).isEqualTo(Coin.COIN_100); + assertThat(Coin.of(500)).isEqualTo(Coin.COIN_500); + } + + @DisplayName("amount 만 담은 리스트를 반환한다.") + @Test + void makeAmountListSuccess() { + List amounts = Arrays.asList(500, 100, 50, 10); + assertThat(Coin.makeAmountList()).isEqualTo(amounts); + } + + @DisplayName("amount 중 최소값을 반환한다.") + @Test + void findMinAmountSuccess() { + assertThat(Coin.findMinAmount()).isEqualTo(10); + } +} diff --git a/src/test/java/vendingmachine/CoinsTest.java b/src/test/java/vendingmachine/CoinsTest.java new file mode 100644 index 000000000..ac0b7faa1 --- /dev/null +++ b/src/test/java/vendingmachine/CoinsTest.java @@ -0,0 +1,43 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.domain.coins.Coin; +import vendingmachine.domain.coins.Coins; +import vendingmachine.domain.Money; +import vendingmachine.domain.coins.NumberGenerator; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.util.Lists.newArrayList; + +public class CoinsTest { + + @DisplayName("랜덤한 코인을 성공적으로 생성한다.") + @Test + void makeRandomCoinsSuccess() { + Coins coins = new Coins(); + coins.makeRandomCoins(new TestNumberGenerator(newArrayList(500, 500, 100, 100, 50, 50, 10, 50, 10, 10)) + , Money.from(676)); + + assertThat(coins.getCoins().get(Coin.COIN_500)).isEqualTo(1); + assertThat(coins.getCoins().get(Coin.COIN_100)).isEqualTo(1); + assertThat(coins.getCoins().get(Coin.COIN_50)).isEqualTo(1); + assertThat(coins.getCoins().get(Coin.COIN_10)).isEqualTo(2); + } + + static class TestNumberGenerator implements NumberGenerator { + + private final List numbers; + + TestNumberGenerator(List numbers) { + this.numbers = numbers; + } + + @Override + public int generate(List test) { + return numbers.remove(0); + } + } +} diff --git a/src/test/java/vendingmachine/MoneyTest.java b/src/test/java/vendingmachine/MoneyTest.java new file mode 100644 index 000000000..f2c2ad8b4 --- /dev/null +++ b/src/test/java/vendingmachine/MoneyTest.java @@ -0,0 +1,55 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.domain.Money; + +import static org.assertj.core.api.Assertions.*; + +public class MoneyTest { + + private static final String EXCEPTION_MESSAGE_MONEY_RANGE = "[ERROR] 돈은 0 원 이상, 1000000000 원 이하 이어야 합니다."; + + @DisplayName("돈 클래스를 정상적으로 생성한다.") + @ParameterizedTest + @ValueSource(ints = {0, 1, 100, 99999999, 1000000000}) + void createMoneySuccess(int input) { + boolean result = true; + try { + Money.from(input); + } catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("잘못된 범위의 금액이 들어올시 예외를 발생한다.") + @ParameterizedTest + @ValueSource(ints = {-1, -1000, 1000000001}) + void createMoneyFail(int input) { + assertThatThrownBy(() -> Money.from(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_MONEY_RANGE); + } + + @DisplayName("지불 가능한 돈이면 true 를 반환한다.") + @ParameterizedTest + @ValueSource(ints = {1, 10, 50, 100, 499, 500}) + void isUseMoneyTrue(int input) { + Money money = Money.from(500); + assertThat(money.isUseMoney(input)).isEqualTo(true); + } + + @DisplayName("돈을 정상적으로 지불한다.") + @Test + void useMoneySuccess() { + Money money = Money.from(500); + money.useMoney(1); + money.useMoney(50); + money.useMoney(122); + money.useMoney(27); + assertThat(money).extracting("money").isEqualTo(300); + } +} From a029d9811642f8873a8a3da5930fc9693beb21f3 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 9 Dec 2022 10:09:35 +0900 Subject: [PATCH 06/13] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EC=83=81?= =?UTF-8?q?=ED=92=88=EB=AA=85,=20=EA=B0=80=EA=B2=A9,=20=EC=88=98=EB=9F=89?= =?UTF-8?q?=EC=9D=84=20=EC=9E=85=EB=A0=A5=ED=95=98=EC=97=AC=20=EC=83=81?= =?UTF-8?q?=ED=92=88=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VendingMachineController.java | 24 ++++++++-- .../vendingmachine/domain/VendingMachine.java | 11 ++++- .../vendingmachine/domain/products/Price.java | 40 ++++++++++++++++ .../domain/products/Product.java | 29 ++++++++++++ .../domain/products/Products.java | 30 ++++++++++++ .../domain/products/Quantity.java | 30 ++++++++++++ .../exception/PriceDividingException.java | 10 ++++ .../exception/PriceRangeException.java | 10 ++++ .../exception/ProductsConvertException.java | 11 +++++ .../ProductsDuplicatedNameException.java | 10 ++++ .../exception/QuantityRangeException.java | 10 ++++ .../vendingmachine/util/ProductsConvert.java | 46 +++++++++++++++++++ .../java/vendingmachine/view/InputView.java | 10 +++- .../java/vendingmachine/view/OutputView.java | 10 ++-- 14 files changed, 272 insertions(+), 9 deletions(-) create mode 100644 src/main/java/vendingmachine/domain/products/Price.java create mode 100644 src/main/java/vendingmachine/domain/products/Product.java create mode 100644 src/main/java/vendingmachine/domain/products/Products.java create mode 100644 src/main/java/vendingmachine/domain/products/Quantity.java create mode 100644 src/main/java/vendingmachine/exception/PriceDividingException.java create mode 100644 src/main/java/vendingmachine/exception/PriceRangeException.java create mode 100644 src/main/java/vendingmachine/exception/ProductsConvertException.java create mode 100644 src/main/java/vendingmachine/exception/ProductsDuplicatedNameException.java create mode 100644 src/main/java/vendingmachine/exception/QuantityRangeException.java create mode 100644 src/main/java/vendingmachine/util/ProductsConvert.java diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 8b5f55f00..1bac01e92 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -1,6 +1,9 @@ package vendingmachine.controller; import vendingmachine.domain.*; +import vendingmachine.domain.coins.Coins; +import vendingmachine.domain.coins.RandomNumberGenerator; +import vendingmachine.domain.products.Products; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; @@ -13,12 +16,27 @@ public class VendingMachineController { private VendingMachine vendingMachine; public void runVendingMachine() { - makeCoins(); + makeVendingMachine(); } - private Coins makeCoins() { + private void makeVendingMachine() { + Money money = askMoney(); + Coins coins = makeCoins(money); + Products products = askProducts(); + + vendingMachine = VendingMachine.of(money, coins, products); + } + + private Products askProducts() { + outputView.printInputProducts(); + Products products = reenterProcess(inputView::readProducts); + outputView.printNewLine(); + return products; + } + + private Coins makeCoins(Money money) { Coins coins = new Coins(); - coins.makeRandomCoins(new RandomNumberGenerator(), askMoney()); + coins.makeRandomCoins(new RandomNumberGenerator(), money); outputView.printCoins(coins); return coins; } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 68c6bcea6..355923964 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -1,12 +1,21 @@ package vendingmachine.domain; +import vendingmachine.domain.coins.Coins; +import vendingmachine.domain.products.Products; + public class VendingMachine { private final Money money; private final Coins coins; + private final Products products; - private VendingMachine(Money money, Coins coins) { + private VendingMachine(Money money, Coins coins, Products products) { this.money = money; this.coins = coins; + this.products = products; + } + + public static VendingMachine of(Money money, Coins coins, Products products) { + return new VendingMachine(money, coins, products); } } diff --git a/src/main/java/vendingmachine/domain/products/Price.java b/src/main/java/vendingmachine/domain/products/Price.java new file mode 100644 index 000000000..ca24e9582 --- /dev/null +++ b/src/main/java/vendingmachine/domain/products/Price.java @@ -0,0 +1,40 @@ +package vendingmachine.domain.products; + +import vendingmachine.exception.PriceDividingException; +import vendingmachine.exception.PriceRangeException; + +public class Price { + + private static final int MIN_PRICE = 100; + private static final int MAX_PRICE = 1_000_000_000; + private static final int DIVIDING_PRICE = 10; + private static final int DIVIDING_RESULT = 0; + + private final int price; + + private Price(int price) { + validate(price); + this.price = price; + } + + public static Price from(int price) { + return new Price(price); + } + + private static void validate(int price) { + validateRange(price); + validateDividing(price); + } + + private static void validateRange(int price) { + if (price < MIN_PRICE || price > MAX_PRICE) { + throw new PriceRangeException(MIN_PRICE, MAX_PRICE); + } + } + + private static void validateDividing(int price) { + if ((price % DIVIDING_PRICE) != DIVIDING_RESULT){ + throw new PriceDividingException(DIVIDING_PRICE); + } + } +} diff --git a/src/main/java/vendingmachine/domain/products/Product.java b/src/main/java/vendingmachine/domain/products/Product.java new file mode 100644 index 000000000..fd0e171dc --- /dev/null +++ b/src/main/java/vendingmachine/domain/products/Product.java @@ -0,0 +1,29 @@ +package vendingmachine.domain.products; + +import java.util.Objects; + +public class Product { + + private final String name; + private final Price price; + private final Quantity quantity; + + public Product(String name, Price price, Quantity quantity) { + this.name = name; + this.price = price; + this.quantity = quantity; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Product) { + return this.name.equals(((Product) o).name); + } + return false; + } + + @Override + public int hashCode() { + return this.name.hashCode(); + } +} diff --git a/src/main/java/vendingmachine/domain/products/Products.java b/src/main/java/vendingmachine/domain/products/Products.java new file mode 100644 index 000000000..41e948ff1 --- /dev/null +++ b/src/main/java/vendingmachine/domain/products/Products.java @@ -0,0 +1,30 @@ +package vendingmachine.domain.products; + +import vendingmachine.exception.ProductsDuplicatedNameException; + +import java.util.List; +import java.util.stream.Collectors; + +public class Products { + + private final List products; + + public Products(List products) { + validate(products); + this.products = products; + } + + public static Products from(List products) { + return new Products(products); + } + + private void validate(List products) { + validateDuplicatedName(products); + } + + private void validateDuplicatedName(List products) { + if (products.size() != products.stream().distinct().count()) { + throw new ProductsDuplicatedNameException(); + } + } +} diff --git a/src/main/java/vendingmachine/domain/products/Quantity.java b/src/main/java/vendingmachine/domain/products/Quantity.java new file mode 100644 index 000000000..ad6e612c5 --- /dev/null +++ b/src/main/java/vendingmachine/domain/products/Quantity.java @@ -0,0 +1,30 @@ +package vendingmachine.domain.products; + +import vendingmachine.exception.QuantityRangeException; + +public class Quantity { + + private static final int MIN_QUANTITY = 0; + private static final int MAX_QUANTITY = 1_000_000_000; + + private final int quantity; + + private Quantity(int quantity) { + validate(quantity); + this.quantity = quantity; + } + + public static Quantity from(int quantity){ + return new Quantity(quantity); + } + + private void validate(int quantity) { + validateRange(quantity); + } + + private static void validateRange(int quantity) { + if (quantity < MIN_QUANTITY || quantity > MAX_QUANTITY) { + throw new QuantityRangeException(MIN_QUANTITY, MAX_QUANTITY); + } + } +} diff --git a/src/main/java/vendingmachine/exception/PriceDividingException.java b/src/main/java/vendingmachine/exception/PriceDividingException.java new file mode 100644 index 000000000..cfda47e4f --- /dev/null +++ b/src/main/java/vendingmachine/exception/PriceDividingException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class PriceDividingException extends IllegalArgumentException{ + + private static final String EXCEPTION_MESSAGE_PRICE_DIVIDING = "[ERROR] 가격은 %d 원으로 나누어 떨어져야 합니다."; + + public PriceDividingException(int dividing) { + super(String.format(EXCEPTION_MESSAGE_PRICE_DIVIDING, dividing)); + } +} diff --git a/src/main/java/vendingmachine/exception/PriceRangeException.java b/src/main/java/vendingmachine/exception/PriceRangeException.java new file mode 100644 index 000000000..0fffe912b --- /dev/null +++ b/src/main/java/vendingmachine/exception/PriceRangeException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class PriceRangeException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_PRICE_RANGE = "[ERROR] 가격은 %d 원 이상, %d 원 이하 이어야 합니다."; + + public PriceRangeException(int minPrice, int maxPrice) { + super(String.format(EXCEPTION_MESSAGE_PRICE_RANGE, minPrice, maxPrice)); + } +} diff --git a/src/main/java/vendingmachine/exception/ProductsConvertException.java b/src/main/java/vendingmachine/exception/ProductsConvertException.java new file mode 100644 index 000000000..cf85d151a --- /dev/null +++ b/src/main/java/vendingmachine/exception/ProductsConvertException.java @@ -0,0 +1,11 @@ +package vendingmachine.exception; + +public class ProductsConvertException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_CONVERT_PRODUCT = + "[ERROR] 입력 형식이 잘못됬습니다. [상품,가격,수량];[상품,가격,수량]"; + + public ProductsConvertException() { + super(EXCEPTION_MESSAGE_CONVERT_PRODUCT); + } +} diff --git a/src/main/java/vendingmachine/exception/ProductsDuplicatedNameException.java b/src/main/java/vendingmachine/exception/ProductsDuplicatedNameException.java new file mode 100644 index 000000000..112a62f84 --- /dev/null +++ b/src/main/java/vendingmachine/exception/ProductsDuplicatedNameException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class ProductsDuplicatedNameException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_PRODUCTS_DUPLICATED_NAME = "[ERROR] 중복되는 제품이름이 있습니다."; + + public ProductsDuplicatedNameException() { + super(EXCEPTION_MESSAGE_PRODUCTS_DUPLICATED_NAME); + } +} diff --git a/src/main/java/vendingmachine/exception/QuantityRangeException.java b/src/main/java/vendingmachine/exception/QuantityRangeException.java new file mode 100644 index 000000000..870f5479e --- /dev/null +++ b/src/main/java/vendingmachine/exception/QuantityRangeException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class QuantityRangeException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_QUANTITY_RANGE = "[ERROR] 수량은 %d 원 이상, %d 원 이하 이어야 합니다."; + + public QuantityRangeException(int minQuantity, int maxQuantity) { + super(String.format(EXCEPTION_MESSAGE_QUANTITY_RANGE, minQuantity, maxQuantity)); + } +} diff --git a/src/main/java/vendingmachine/util/ProductsConvert.java b/src/main/java/vendingmachine/util/ProductsConvert.java new file mode 100644 index 000000000..0caa2f3f6 --- /dev/null +++ b/src/main/java/vendingmachine/util/ProductsConvert.java @@ -0,0 +1,46 @@ +package vendingmachine.util; + +import vendingmachine.domain.products.Price; +import vendingmachine.domain.products.Product; +import vendingmachine.domain.products.Products; +import vendingmachine.domain.products.Quantity; +import vendingmachine.exception.ProductsConvertException; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class ProductsConvert { + + private static final String PRODUCTS_DELIMITER = ";"; + private static final String PRODUCTS_DUPLICATED_DELIMITER_REGEX = ";+"; + private static final String PRODUCT_DELIMITER = ","; + private static final String PRODUCT_DUPLICATED_DELIMITER_REGEX = ",+"; + private static final String PRODUCT_START_END_REGEX = "^\\[|\\]$"; + private static final String BLANK = ""; + private static final int NAME = 0; + private static final int PRICE = 1; + private static final int QUANTITY = 2; + + public static Products convert(String input) { + String[] products = input.replaceAll(PRODUCTS_DUPLICATED_DELIMITER_REGEX, PRODUCTS_DELIMITER) + .split(PRODUCTS_DELIMITER); + + return Products.from(Arrays.stream(products) + .map(ProductsConvert::makeProduct) + .collect(Collectors.toList())); + } + + private static Product makeProduct(String product) { + String[] contents = product.replaceAll(PRODUCT_START_END_REGEX, BLANK) + .replaceAll(PRODUCT_DUPLICATED_DELIMITER_REGEX, PRODUCT_DELIMITER) + .split(PRODUCT_DELIMITER); + + if (contents.length != 3) { + throw new ProductsConvertException(); + } + + return new Product(contents[NAME], + Price.from(IntConvert.convert(contents[PRICE])), + Quantity.from(IntConvert.convert(contents[QUANTITY]))); + } +} diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index f13d67973..dfeebe7d1 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -1,13 +1,19 @@ package vendingmachine.view; import vendingmachine.domain.Money; -import vendingmachine.util.ConvertInt; +import vendingmachine.domain.products.Products; +import vendingmachine.util.IntConvert; +import vendingmachine.util.ProductsConvert; import static camp.nextstep.edu.missionutils.Console.readLine; public class InputView { public Money readMoney() { - return Money.from(ConvertInt.convert(readLine())); + return Money.from(IntConvert.convert(readLine())); + } + + public Products readProducts() { + return ProductsConvert.convert(readLine()); } } diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index 8f00ce0c8..f1b385f78 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -1,15 +1,15 @@ package vendingmachine.view; -import vendingmachine.domain.Coin; -import vendingmachine.domain.Coins; +import vendingmachine.domain.coins.Coin; +import vendingmachine.domain.coins.Coins; -import java.util.EnumMap; import java.util.Map; public class OutputView { private static final String MESSAGE_INPUT_VENDING_MACHINE_AMOUNT = "자판기가 보유하고 있는 금액을 입력해 주세요."; private static final String MESSAGE_COINS = "%d원 - %d개"; + private static final String MESSAGE_INPUT_PRODUCTS = "상품명과 가격, 수량을 입력해 주세요."; public void printExceptionMessage(IllegalArgumentException exception) { System.out.println(exception.getMessage()); @@ -30,4 +30,8 @@ public void printCoins(Coins coins) { } System.out.println(); } + + public void printInputProducts() { + System.out.println(MESSAGE_INPUT_PRODUCTS); + } } From 02196fd9b7372c65941bf4f1b3a30e3a60bd6ea6 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 9 Dec 2022 10:09:53 +0900 Subject: [PATCH 07/13] =?UTF-8?q?test:=20=EC=B6=94=EA=B0=80=20=EC=83=81?= =?UTF-8?q?=ED=92=88=EB=AA=85,=20=EA=B0=80=EA=B2=A9,=20=EC=88=98=EB=9F=89?= =?UTF-8?q?=EC=9D=84=20=EC=9E=85=EB=A0=A5=ED=95=98=EC=97=AC=20=EC=83=81?= =?UTF-8?q?=ED=92=88=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/vendingmachine/PriceTest.java | 47 +++++++++++++++++++ .../vendingmachine/ProductsConvertTest.java | 25 ++++++++++ .../java/vendingmachine/QuantityTest.java | 37 +++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 src/test/java/vendingmachine/PriceTest.java create mode 100644 src/test/java/vendingmachine/ProductsConvertTest.java create mode 100644 src/test/java/vendingmachine/QuantityTest.java diff --git a/src/test/java/vendingmachine/PriceTest.java b/src/test/java/vendingmachine/PriceTest.java new file mode 100644 index 000000000..54c72bd61 --- /dev/null +++ b/src/test/java/vendingmachine/PriceTest.java @@ -0,0 +1,47 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.domain.products.Price; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class PriceTest { + + private static final String EXCEPTION_MESSAGE_PRICE_RANGE = + "[ERROR] 가격은 100 원 이상, 1000000000 원 이하 이어야 합니다."; + private static final String EXCEPTION_MESSAGE_PRICE_DIVIDING = "[ERROR] 가격은 10 원으로 나누어 떨어져야 합니다."; + + @DisplayName("Price 클래스를 정상적으로 생성한다.") + @ParameterizedTest + @ValueSource(ints = {100, 1510, 1000000000}) + void createPriceSuccess(int input) { + boolean result = true; + try { + Price.from(input); + } catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("잘못된 범위의 금액이 들어올시 예외를 발생한다.") + @ParameterizedTest + @ValueSource(ints = {-1000, -1, 0, 1, 99, 1000000001}) + void createPriceFailByRange(int input) { + assertThatThrownBy(() -> Price.from(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_PRICE_RANGE); + } + + @DisplayName("10원으로 나눠지지 않는 금액이 들어올시 예외를 발생한다.") + @ParameterizedTest + @ValueSource(ints = {101, 4999}) + void createPriceFailByDividing(int input) { + assertThatThrownBy(() -> Price.from(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_PRICE_DIVIDING); + } +} diff --git a/src/test/java/vendingmachine/ProductsConvertTest.java b/src/test/java/vendingmachine/ProductsConvertTest.java new file mode 100644 index 000000000..1eb5275fd --- /dev/null +++ b/src/test/java/vendingmachine/ProductsConvertTest.java @@ -0,0 +1,25 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.domain.products.Products; +import vendingmachine.util.IntConvert; +import vendingmachine.util.ProductsConvert; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class ProductsConvertTest { + + private static final String EXCEPTION_MESSAGE = "[ERROR]"; + + @DisplayName("잘못된 형식의 입력이면 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"[사이다,1000,10];[[콜라,1500,20]]", "[]", "[콜라150000]", "[콜라,150000]", "[콜라,15,10,2]", + "[콜라,백원,20]", "[콜라,100,이십]", "[콜라,백원,이십]", "[사이다,1000,10];[사이다,1500,20]"}) + void InputIsNotNumber(String input) { + assertThatThrownBy(() -> ProductsConvert.convert(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE); + } +} diff --git a/src/test/java/vendingmachine/QuantityTest.java b/src/test/java/vendingmachine/QuantityTest.java new file mode 100644 index 000000000..7dbd83e4b --- /dev/null +++ b/src/test/java/vendingmachine/QuantityTest.java @@ -0,0 +1,37 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.domain.products.Quantity; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class QuantityTest { + + private static final String EXCEPTION_MESSAGE_QUANTITY_RANGE = + "[ERROR] 수량은 0 원 이상, 1000000000 원 이하 이어야 합니다."; + + @DisplayName("Quantity 클래스를 정상적으로 생성한다.") + @ParameterizedTest + @ValueSource(ints = {0, 1, 100, 1510, 1000000000}) + void createQuantitySuccess(int input) { + boolean result = true; + try { + Quantity.from(input); + } catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("잘못된 범위의 금액이 들어올시 예외를 발생한다.") + @ParameterizedTest + @ValueSource(ints = {-1000, -1, 1000000001}) + void createQuantityFail(int input) { + assertThatThrownBy(() -> Quantity.from(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_QUANTITY_RANGE); + } +} From c2f70053338683072c6918fba2a0279a24392843 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 9 Dec 2022 23:02:32 +0900 Subject: [PATCH 08/13] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EA=B0=80=20=ED=88=AC=EC=9E=85=ED=95=9C=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=EC=9C=BC=EB=A1=9C=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EC=9D=84=20=EA=B5=AC=EB=A7=A4=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VendingMachineController.java | 56 ++++++++++++++++--- .../java/vendingmachine/domain/Money.java | 4 ++ .../vendingmachine/domain/VendingMachine.java | 10 ++++ .../vendingmachine/domain/products/Price.java | 21 +++++++ .../domain/products/Product.java | 37 +++++++++++- .../domain/products/Products.java | 26 ++++++++- .../domain/products/Quantity.java | 10 +++- .../exception/PriceNotPurchaseException.java | 10 ++++ .../exception/ProductsNotFind.java | 10 ++++ .../java/vendingmachine/view/InputView.java | 4 ++ .../java/vendingmachine/view/OutputView.java | 17 ++++++ 11 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 src/main/java/vendingmachine/exception/PriceNotPurchaseException.java create mode 100644 src/main/java/vendingmachine/exception/ProductsNotFind.java diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 1bac01e92..08b052811 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -3,10 +3,12 @@ import vendingmachine.domain.*; import vendingmachine.domain.coins.Coins; import vendingmachine.domain.coins.RandomNumberGenerator; +import vendingmachine.domain.products.Product; import vendingmachine.domain.products.Products; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; +import java.util.function.Consumer; import java.util.function.Supplier; public class VendingMachineController { @@ -14,24 +16,60 @@ public class VendingMachineController { private final InputView inputView = new InputView(); private final OutputView outputView = new OutputView(); private VendingMachine vendingMachine; + private Money playerMoney; public void runVendingMachine() { makeVendingMachine(); + operateVendingMachine(); + } + + private void operateVendingMachine() { + playerMoney = askPlayerMoney(); + while (vendingMachine.isSellProduct(playerMoney)) { + buyProduct(); + } + } + + private void buyProduct() { + while (true) { + try { + vendingMachine.purchaseProduct(askBuyingProduct(), playerMoney); + return; + } catch (IllegalArgumentException exception) { + outputView.printExceptionMessage(exception); + } + } + } + + private String askBuyingProduct() { + outputView.printRemainMoney(playerMoney); + outputView.printInputProductName(); + String name = inputView.readProductName(); + outputView.printNewLine(); + return name; + } + + + private Money askPlayerMoney() { + outputView.printInputMoney(); + Money money = reenterProcess(inputView::readMoney); + outputView.printNewLine(); + return money; } private void makeVendingMachine() { - Money money = askMoney(); + Money money = askMachineMoney(); Coins coins = makeCoins(money); Products products = askProducts(); vendingMachine = VendingMachine.of(money, coins, products); } - private Products askProducts() { - outputView.printInputProducts(); - Products products = reenterProcess(inputView::readProducts); + private Money askMachineMoney() { + outputView.printInputVendingMachineAmount(); + Money money = reenterProcess(inputView::readMoney); outputView.printNewLine(); - return products; + return money; } private Coins makeCoins(Money money) { @@ -41,11 +79,11 @@ private Coins makeCoins(Money money) { return coins; } - private Money askMoney() { - outputView.printInputVendingMachineAmount(); - Money money = reenterProcess(inputView::readMoney); + private Products askProducts() { + outputView.printInputProducts(); + Products products = reenterProcess(inputView::readProducts); outputView.printNewLine(); - return money; + return products; } private T reenterProcess(Supplier reader) { diff --git a/src/main/java/vendingmachine/domain/Money.java b/src/main/java/vendingmachine/domain/Money.java index 3f41571bc..cd685c6fb 100644 --- a/src/main/java/vendingmachine/domain/Money.java +++ b/src/main/java/vendingmachine/domain/Money.java @@ -38,4 +38,8 @@ public void useMoney(int pay) { public boolean isUseMoney(int money) { return (this.money - money) >= ZERO_MONEY; } + + public int getMoney() { + return money; + } } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 355923964..9e84a673d 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -1,6 +1,7 @@ package vendingmachine.domain; import vendingmachine.domain.coins.Coins; +import vendingmachine.domain.products.Product; import vendingmachine.domain.products.Products; public class VendingMachine { @@ -18,4 +19,13 @@ private VendingMachine(Money money, Coins coins, Products products) { public static VendingMachine of(Money money, Coins coins, Products products) { return new VendingMachine(money, coins, products); } + + public void purchaseProduct(String name, Money money){ + Product product = products.findPurchasableProduct(name, money); + product.purchase(money); + } + + public boolean isSellProduct(Money money) { + return (products.findMinPriceProduct().isPurchaseProduct(money) && !products.isAllQuantityZero()); + } } diff --git a/src/main/java/vendingmachine/domain/products/Price.java b/src/main/java/vendingmachine/domain/products/Price.java index ca24e9582..f2febbc12 100644 --- a/src/main/java/vendingmachine/domain/products/Price.java +++ b/src/main/java/vendingmachine/domain/products/Price.java @@ -1,6 +1,8 @@ package vendingmachine.domain.products; +import vendingmachine.domain.Money; import vendingmachine.exception.PriceDividingException; +import vendingmachine.exception.PriceNotPurchaseException; import vendingmachine.exception.PriceRangeException; public class Price { @@ -37,4 +39,23 @@ private static void validateDividing(int price) { throw new PriceDividingException(DIVIDING_PRICE); } } + + public boolean isCheaperPrice(Price price) { + return this.price < price.price; + } + + public boolean validateMoney(Money money) { + if (money.isUseMoney(this.price)){ + return true; + } + throw new PriceNotPurchaseException(); + } + + public boolean isPurchase(Money money) { + return money.isUseMoney(this.price); + } + + public void payPrice(Money money) { + money.useMoney(this.price); + } } diff --git a/src/main/java/vendingmachine/domain/products/Product.java b/src/main/java/vendingmachine/domain/products/Product.java index fd0e171dc..412538a34 100644 --- a/src/main/java/vendingmachine/domain/products/Product.java +++ b/src/main/java/vendingmachine/domain/products/Product.java @@ -1,6 +1,6 @@ package vendingmachine.domain.products; -import java.util.Objects; +import vendingmachine.domain.Money; public class Product { @@ -14,6 +14,41 @@ public Product(String name, Price price, Quantity quantity) { this.quantity = quantity; } + public boolean isSameName(String name) { + return this.name.equals(name); + } + + public boolean purchasableProduct(Money money) { + return purchasablePrice(money) && purchasableQuantity(); + } + + private boolean purchasablePrice(Money money) { + return price.validateMoney(money); + } + + private boolean purchasableQuantity() { + return quantity.isRemain(); + } + + public Product CheaperPriceProduct(Product product) { + if (this.price.isCheaperPrice(product.price)) { + return this; + } + return product; + } + + public void purchase(Money money) { + price.payPrice(money); + quantity.decrease(); + } + + public boolean isPurchaseProduct(Money money) { + return price.isPurchase(money); + } + public boolean isSoldOut(){ + return !quantity.isRemain(); + } + @Override public boolean equals(Object o) { if (o instanceof Product) { diff --git a/src/main/java/vendingmachine/domain/products/Products.java b/src/main/java/vendingmachine/domain/products/Products.java index 41e948ff1..7c1f224ef 100644 --- a/src/main/java/vendingmachine/domain/products/Products.java +++ b/src/main/java/vendingmachine/domain/products/Products.java @@ -1,9 +1,10 @@ package vendingmachine.domain.products; +import vendingmachine.domain.Money; import vendingmachine.exception.ProductsDuplicatedNameException; +import vendingmachine.exception.ProductsNotFind; import java.util.List; -import java.util.stream.Collectors; public class Products { @@ -27,4 +28,27 @@ private void validateDuplicatedName(List products) { throw new ProductsDuplicatedNameException(); } } + + public Product findPurchasableProduct(String name, Money money) { + return products.stream() + .filter(product -> product.isSameName(name)) + .filter(product -> product.purchasableProduct(money)) + .findAny() + .orElseThrow(ProductsNotFind::new); + } + + public Product findMinPriceProduct() { + return products.stream() + .reduce(this::compareCheaperPrice) + .orElseThrow(ProductsNotFind::new); + } + + private Product compareCheaperPrice(Product p1, Product p2) { + return p1.CheaperPriceProduct(p2); + } + + public boolean isAllQuantityZero() { + return products.stream() + .allMatch(Product::isSoldOut); + } } diff --git a/src/main/java/vendingmachine/domain/products/Quantity.java b/src/main/java/vendingmachine/domain/products/Quantity.java index ad6e612c5..63f7948d1 100644 --- a/src/main/java/vendingmachine/domain/products/Quantity.java +++ b/src/main/java/vendingmachine/domain/products/Quantity.java @@ -7,7 +7,7 @@ public class Quantity { private static final int MIN_QUANTITY = 0; private static final int MAX_QUANTITY = 1_000_000_000; - private final int quantity; + private int quantity; private Quantity(int quantity) { validate(quantity); @@ -27,4 +27,12 @@ private static void validateRange(int quantity) { throw new QuantityRangeException(MIN_QUANTITY, MAX_QUANTITY); } } + + public boolean isRemain() { + return quantity > MIN_QUANTITY; + } + + public void decrease() { + this.quantity--; + } } diff --git a/src/main/java/vendingmachine/exception/PriceNotPurchaseException.java b/src/main/java/vendingmachine/exception/PriceNotPurchaseException.java new file mode 100644 index 000000000..53d2482a1 --- /dev/null +++ b/src/main/java/vendingmachine/exception/PriceNotPurchaseException.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class PriceNotPurchaseException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_PRICE_NOT_PURCHASE = "[ERROR] 소지금액으로 해당 제품을 구매할 수 없습니다"; + + public PriceNotPurchaseException() { + super(String.format(EXCEPTION_MESSAGE_PRICE_NOT_PURCHASE)); + } +} diff --git a/src/main/java/vendingmachine/exception/ProductsNotFind.java b/src/main/java/vendingmachine/exception/ProductsNotFind.java new file mode 100644 index 000000000..43ec5d0c4 --- /dev/null +++ b/src/main/java/vendingmachine/exception/ProductsNotFind.java @@ -0,0 +1,10 @@ +package vendingmachine.exception; + +public class ProductsNotFind extends IllegalArgumentException{ + + private static final String EXCEPTION_MESSAGE_PRODUCTS_NOT_FIND_NAME = "[ERROR] 존재하지 않는 제품입니다."; + + public ProductsNotFind() { + super(EXCEPTION_MESSAGE_PRODUCTS_NOT_FIND_NAME); + } +} diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index dfeebe7d1..9c68240ec 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -16,4 +16,8 @@ public Money readMoney() { public Products readProducts() { return ProductsConvert.convert(readLine()); } + + public String readProductName() { + return readLine(); + } } diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index f1b385f78..b0375cd3b 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -1,5 +1,6 @@ package vendingmachine.view; +import vendingmachine.domain.Money; import vendingmachine.domain.coins.Coin; import vendingmachine.domain.coins.Coins; @@ -10,6 +11,9 @@ public class OutputView { private static final String MESSAGE_INPUT_VENDING_MACHINE_AMOUNT = "자판기가 보유하고 있는 금액을 입력해 주세요."; private static final String MESSAGE_COINS = "%d원 - %d개"; private static final String MESSAGE_INPUT_PRODUCTS = "상품명과 가격, 수량을 입력해 주세요."; + private static final String MESSAGE_INPUT_MONEY = "투입 금액을 입력해 주세요."; + private static final String MESSAGE_REMAIN_MONEY = "투입 금액: %d 원"; + private static final String MESSAGE_INPUT_PRODUCT_NAME = "구매할 상품명을 입력해 주세요."; public void printExceptionMessage(IllegalArgumentException exception) { System.out.println(exception.getMessage()); @@ -34,4 +38,17 @@ public void printCoins(Coins coins) { public void printInputProducts() { System.out.println(MESSAGE_INPUT_PRODUCTS); } + + public void printInputMoney() { + System.out.println(MESSAGE_INPUT_MONEY); + } + + public void printRemainMoney(Money money) { + System.out.printf(MESSAGE_REMAIN_MONEY, money.getMoney()); + System.out.println(); + } + + public void printInputProductName() { + System.out.println(MESSAGE_INPUT_PRODUCT_NAME); + } } From 786b4ca2e5daeaf7f0e91c317ccf6cfc5e414460 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 9 Dec 2022 23:02:46 +0900 Subject: [PATCH 09/13] =?UTF-8?q?test:=20=EC=B6=94=EA=B0=80=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EA=B0=80=20=ED=88=AC=EC=9E=85=ED=95=9C=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=EC=9C=BC=EB=A1=9C=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EC=9D=84=20=EA=B5=AC=EB=A7=A4=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/vendingmachine/PriceTest.java | 25 +++++++- .../java/vendingmachine/ProductsTest.java | 54 +++++++++++++++++ .../vendingmachine/VendingMachineTest.java | 59 +++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/test/java/vendingmachine/ProductsTest.java create mode 100644 src/test/java/vendingmachine/VendingMachineTest.java diff --git a/src/test/java/vendingmachine/PriceTest.java b/src/test/java/vendingmachine/PriceTest.java index 54c72bd61..261ecd4f9 100644 --- a/src/test/java/vendingmachine/PriceTest.java +++ b/src/test/java/vendingmachine/PriceTest.java @@ -3,16 +3,17 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.domain.Money; import vendingmachine.domain.products.Price; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.*; public class PriceTest { private static final String EXCEPTION_MESSAGE_PRICE_RANGE = "[ERROR] 가격은 100 원 이상, 1000000000 원 이하 이어야 합니다."; private static final String EXCEPTION_MESSAGE_PRICE_DIVIDING = "[ERROR] 가격은 10 원으로 나누어 떨어져야 합니다."; + private static final String EXCEPTION_MESSAGE_PRICE_NOT_PURCHASE = "[ERROR] 소지금액으로 해당 제품을 구매할 수 없습니다"; @DisplayName("Price 클래스를 정상적으로 생성한다.") @ParameterizedTest @@ -44,4 +45,24 @@ void createPriceFailByDividing(int input) { .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining(EXCEPTION_MESSAGE_PRICE_DIVIDING); } + + @DisplayName("구매가 가능하면 true 를 반환한다.") + @ParameterizedTest + @ValueSource(ints = {100, 490, 500}) + void isCheaperMoneySuccess(int input) { + Money money = Money.from(500); + Price price = Price.from(input); + assertThat(price.validateMoney(money)).isEqualTo(true); + } + + @DisplayName("구매가 불가능하면 예외를 반환한다.") + @ParameterizedTest + @ValueSource(ints = {510, 5000}) + void isCheaperMoneyFail(int input) { + Money money = Money.from(500); + Price price = Price.from(input); + assertThatThrownBy(() -> price.validateMoney(money)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_PRICE_NOT_PURCHASE); + } } diff --git a/src/test/java/vendingmachine/ProductsTest.java b/src/test/java/vendingmachine/ProductsTest.java new file mode 100644 index 000000000..91873ec22 --- /dev/null +++ b/src/test/java/vendingmachine/ProductsTest.java @@ -0,0 +1,54 @@ +package vendingmachine; + +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 org.junit.jupiter.params.provider.ValueSource; +import vendingmachine.domain.Money; +import vendingmachine.domain.products.Price; +import vendingmachine.domain.products.Product; +import vendingmachine.domain.products.Products; +import vendingmachine.domain.products.Quantity; +import vendingmachine.util.ProductsConvert; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class ProductsTest { + + private static final String EXCEPTION_MESSAGE = "[ERROR]"; + + @DisplayName("정상적으로 구매 가능한 상품을 찾는다.") + @Test + void findPurchasableProductSuccess() { + Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10]"); + boolean result = true; + try { + products.findPurchasableProduct("콜라", Money.from(3000)); + } catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("구매 가능한 상품이 없을시 예외를 발생한다.") + @ParameterizedTest + @CsvSource(value = {"콜라, 1000", "콜라라, 5000", "솔의눈, 10000"}) + void createPriceFailByRange(String name, int money) { + Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10];[솔의눈,1000,0]"); + assertThatThrownBy(() -> products.findPurchasableProduct(name, Money.from(money))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE); + } + + @DisplayName("정상적으로 최소가격 상품을 찾는다.") + @Test + void findMinPriceProductSuccess() { + Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10];[솔의눈,10000,0]"); + Product product = new Product("사이다", Price.from(1000), Quantity.from(10)); + assertThat(products.findMinPriceProduct()).isEqualTo(product); + } +} diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/VendingMachineTest.java new file mode 100644 index 000000000..184c36a35 --- /dev/null +++ b/src/test/java/vendingmachine/VendingMachineTest.java @@ -0,0 +1,59 @@ +package vendingmachine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.domain.Money; +import vendingmachine.domain.VendingMachine; +import vendingmachine.domain.coins.Coins; +import vendingmachine.domain.products.Products; +import vendingmachine.util.ProductsConvert; + +import static org.assertj.core.api.Assertions.assertThat; + +public class VendingMachineTest { + + @DisplayName("정상적으로 상품 구매하면 상품 수량 감소 및 소지금이 감소한다.") + @Test + void purchaseProductSuccess() { + Money money = Money.from(5000); + Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10];[솔의눈,10000,10]"); + Coins coins = new Coins(); + VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + vendingMachine.purchaseProduct("콜라", money); + + Products compareProducts = ProductsConvert.convert("[콜라,2000,19];[사이다,1000,10];[솔의눈,10000,10]"); + + assertThat(money.getMoney()).isEqualTo(3000); + assertThat(products).usingRecursiveComparison().isEqualTo(compareProducts); + } + + @DisplayName("구매가능한 상품이 있으면 true 를 반환한다.") + @Test + void isSellProductTrue() { + Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10];[솔의눈,10000,10]"); + Coins coins = new Coins(); + VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + + assertThat(vendingMachine.isSellProduct(Money.from(5000))).isEqualTo(true); + } + + @DisplayName("구매가능한 상품 수량이 없으면 false 를 반환한다.") + @Test + void isSellProductFalseByQuantity() { + Products products = ProductsConvert.convert("[콜라,2000,0];[사이다,1000,0];[솔의눈,10000,0]"); + Coins coins = new Coins(); + VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + + assertThat(vendingMachine.isSellProduct(Money.from(5000))).isEqualTo(false); + } + + @DisplayName("구매가능한 상품 가격이 없으면 false 를 반환한다.") + @Test + void isSellProductFalseByMoney() { + Products products = ProductsConvert.convert("[콜라,2000,10];[사이다,1000,100];[솔의눈,10000,20]"); + Coins coins = new Coins(); + VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + + assertThat(vendingMachine.isSellProduct(Money.from(500))).isEqualTo(false); + } +} From 05ec3957522ed73fcc37e30c6becca5f7e03f79c Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 10 Dec 2022 03:50:25 +0900 Subject: [PATCH 10/13] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EB=82=A8?= =?UTF-8?q?=EC=9D=80=20=EA=B8=88=EC=95=A1=EC=9D=B4=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EC=9D=98=20=EC=B5=9C=EC=A0=80=20=EA=B0=80=EA=B2=A9=EB=B3=B4?= =?UTF-8?q?=EB=8B=A4=20=EC=A0=81=EA=B1=B0=EB=82=98,=20=EB=AA=A8=EB=93=A0?= =?UTF-8?q?=20=EC=83=81=ED=92=88=EC=9D=B4=20=EC=86=8C=EC=A7=84=EB=90=9C=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=9E=94=EB=8F=88=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VendingMachineController.java | 6 +++++ .../java/vendingmachine/domain/Money.java | 4 ++++ .../vendingmachine/domain/VendingMachine.java | 4 ++++ .../vendingmachine/domain/coins/Coin.java | 4 +--- .../vendingmachine/domain/coins/Coins.java | 24 +++++++++++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 08b052811..950d6a0c9 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -21,6 +21,12 @@ public class VendingMachineController { public void runVendingMachine() { makeVendingMachine(); operateVendingMachine(); + showResult(); + } + + private void showResult() { + outputView.printRemainMoney(playerMoney); + outputView.printCoins(vendingMachine.makeChanges(playerMoney)); } private void operateVendingMachine() { diff --git a/src/main/java/vendingmachine/domain/Money.java b/src/main/java/vendingmachine/domain/Money.java index cd685c6fb..c659eacd7 100644 --- a/src/main/java/vendingmachine/domain/Money.java +++ b/src/main/java/vendingmachine/domain/Money.java @@ -39,6 +39,10 @@ public boolean isUseMoney(int money) { return (this.money - money) >= ZERO_MONEY; } + public int calculateDividingMoney(int number) { + return this.money / number; + } + public int getMoney() { return money; } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 9e84a673d..36facffd2 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -28,4 +28,8 @@ public void purchaseProduct(String name, Money money){ public boolean isSellProduct(Money money) { return (products.findMinPriceProduct().isPurchaseProduct(money) && !products.isAllQuantityZero()); } + + public Coins makeChanges(Money money) { + return coins.makeLargestCoins(money); + } } diff --git a/src/main/java/vendingmachine/domain/coins/Coin.java b/src/main/java/vendingmachine/domain/coins/Coin.java index 70dbd1117..37d58cdaf 100644 --- a/src/main/java/vendingmachine/domain/coins/Coin.java +++ b/src/main/java/vendingmachine/domain/coins/Coin.java @@ -39,9 +39,7 @@ public static int findMinAmount() { .orElseThrow(CoinEmptyException::new); } - public Money exchangeCoinToMoney() { - return Money.from(amount); - } + public int getAmount() { return amount; diff --git a/src/main/java/vendingmachine/domain/coins/Coins.java b/src/main/java/vendingmachine/domain/coins/Coins.java index 099948d9a..882545c93 100644 --- a/src/main/java/vendingmachine/domain/coins/Coins.java +++ b/src/main/java/vendingmachine/domain/coins/Coins.java @@ -2,6 +2,7 @@ import vendingmachine.domain.Money; +import java.util.Comparator; import java.util.EnumMap; import java.util.List; @@ -15,6 +16,10 @@ public Coins() { this.coins = initCoins(); } + public Coins(EnumMap coins) { + this.coins = coins; + } + public void makeRandomCoins(NumberGenerator numberGenerator, Money money) { List coinAmounts = Coin.makeAmountList(); int minAmount = Coin.findMinAmount(); @@ -39,6 +44,25 @@ private EnumMap initCoins() { return coins; } + public Coins makeLargestCoins(Money money) { + EnumMap changes = new EnumMap<>(Coin.class); + coins.entrySet().stream() + .sorted(Comparator.comparingInt(o -> o.getKey().getAmount())) + .forEach(coin -> changes.put(coin.getKey(), calculateCoin(coin.getKey(), money))); + return new Coins(changes); + } + + private int calculateCoin(Coin coin, Money money) { + int count = money.calculateDividingMoney(coin.getAmount()); + int coinNumber = coins.get(coin); + if(coinNumber <= count) { + money.useMoney(coinNumber * coin.getAmount()); + return coins.get(coin); + } + money.useMoney(count * coin.getAmount()); + return count; + } + public EnumMap getCoins() { return coins; } From aa7e51799e06b4f950d6630b312f71bf26c23a69 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 10 Dec 2022 03:50:46 +0900 Subject: [PATCH 11/13] =?UTF-8?q?test:=20=EC=B6=94=EA=B0=80=20=EB=82=A8?= =?UTF-8?q?=EC=9D=80=20=EA=B8=88=EC=95=A1=EC=9D=B4=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EC=9D=98=20=EC=B5=9C=EC=A0=80=20=EA=B0=80=EA=B2=A9=EB=B3=B4?= =?UTF-8?q?=EB=8B=A4=20=EC=A0=81=EA=B1=B0=EB=82=98,=20=EB=AA=A8=EB=93=A0?= =?UTF-8?q?=20=EC=83=81=ED=92=88=EC=9D=B4=20=EC=86=8C=EC=A7=84=EB=90=9C=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=9E=94=EB=8F=88=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/vendingmachine/CoinsTest.java | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/vendingmachine/CoinsTest.java b/src/test/java/vendingmachine/CoinsTest.java index ac0b7faa1..a2c9fe4b7 100644 --- a/src/test/java/vendingmachine/CoinsTest.java +++ b/src/test/java/vendingmachine/CoinsTest.java @@ -2,11 +2,14 @@ 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 vendingmachine.domain.coins.Coin; import vendingmachine.domain.coins.Coins; import vendingmachine.domain.Money; import vendingmachine.domain.coins.NumberGenerator; +import java.util.EnumMap; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -27,6 +30,26 @@ void makeRandomCoinsSuccess() { assertThat(coins.getCoins().get(Coin.COIN_10)).isEqualTo(2); } + @DisplayName("잔돈을 성공적으로 반환한다.") + @ParameterizedTest + @CsvSource(value = { + "1100, 1, 2, 4, 20", "1000, 0, 2, 4, 20", "800, 0, 2, 4, 20", "500, 0, 1, 4, 20", "400, 0, 0, 4, 20", + "350, 0, 0, 3, 20", "200, 0, 0, 0, 20", "220, 0, 0, 0, 20", "130, 0, 0, 0, 13", "0, 0, 0, 0, 0"}) + void makeLargestCoinsSuccess(int money, int coin500, int coin100, int coin50, int coin10) { + EnumMap coins = new EnumMap<>(Coin.class); + coins.put(Coin.COIN_500, 1); + coins.put(Coin.COIN_100, 2); + coins.put(Coin.COIN_50, 4); + coins.put(Coin.COIN_10, 20); + Coins temp = new Coins(coins); + Coins changes = temp.makeLargestCoins(Money.from(money)); + + assertThat(changes.getCoins().get(Coin.COIN_500)).isEqualTo(coin500); + assertThat(changes.getCoins().get(Coin.COIN_100)).isEqualTo(coin100); + assertThat(changes.getCoins().get(Coin.COIN_50)).isEqualTo(coin50); + assertThat(changes.getCoins().get(Coin.COIN_10)).isEqualTo(coin10); + } + static class TestNumberGenerator implements NumberGenerator { private final List numbers; From 2059c158e00da3d1e1b26326ae60278e1d622f42 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 10 Dec 2022 03:56:26 +0900 Subject: [PATCH 12/13] =?UTF-8?q?fix:=20=EC=B6=94=EA=B0=80=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=EB=AC=B8=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VendingMachineController.java | 63 +++++++++---------- .../java/vendingmachine/view/OutputView.java | 16 ++++- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 950d6a0c9..4badf2afa 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -24,29 +24,6 @@ public void runVendingMachine() { showResult(); } - private void showResult() { - outputView.printRemainMoney(playerMoney); - outputView.printCoins(vendingMachine.makeChanges(playerMoney)); - } - - private void operateVendingMachine() { - playerMoney = askPlayerMoney(); - while (vendingMachine.isSellProduct(playerMoney)) { - buyProduct(); - } - } - - private void buyProduct() { - while (true) { - try { - vendingMachine.purchaseProduct(askBuyingProduct(), playerMoney); - return; - } catch (IllegalArgumentException exception) { - outputView.printExceptionMessage(exception); - } - } - } - private String askBuyingProduct() { outputView.printRemainMoney(playerMoney); outputView.printInputProductName(); @@ -55,14 +32,6 @@ private String askBuyingProduct() { return name; } - - private Money askPlayerMoney() { - outputView.printInputMoney(); - Money money = reenterProcess(inputView::readMoney); - outputView.printNewLine(); - return money; - } - private void makeVendingMachine() { Money money = askMachineMoney(); Coins coins = makeCoins(money); @@ -81,7 +50,7 @@ private Money askMachineMoney() { private Coins makeCoins(Money money) { Coins coins = new Coins(); coins.makeRandomCoins(new RandomNumberGenerator(), money); - outputView.printCoins(coins); + outputView.printVendingMachineCoins(coins); return coins; } @@ -92,6 +61,36 @@ private Products askProducts() { return products; } + private void operateVendingMachine() { + playerMoney = askPlayerMoney(); + while (vendingMachine.isSellProduct(playerMoney)) { + buyProduct(); + } + } + + private Money askPlayerMoney() { + outputView.printInputMoney(); + Money money = reenterProcess(inputView::readMoney); + outputView.printNewLine(); + return money; + } + + private void buyProduct() { + while (true) { + try { + vendingMachine.purchaseProduct(askBuyingProduct(), playerMoney); + return; + } catch (IllegalArgumentException exception) { + outputView.printExceptionMessage(exception); + } + } + } + + private void showResult() { + outputView.printRemainMoney(playerMoney); + outputView.printChanges(vendingMachine.makeChanges(playerMoney)); + } + private T reenterProcess(Supplier reader) { while (true) { try { diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index b0375cd3b..6a3457ae3 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -9,11 +9,13 @@ public class OutputView { private static final String MESSAGE_INPUT_VENDING_MACHINE_AMOUNT = "자판기가 보유하고 있는 금액을 입력해 주세요."; + private static final String MESSAGE_VENDING_MACHINE_COINS = "자판기가 보유한 동전"; private static final String MESSAGE_COINS = "%d원 - %d개"; private static final String MESSAGE_INPUT_PRODUCTS = "상품명과 가격, 수량을 입력해 주세요."; private static final String MESSAGE_INPUT_MONEY = "투입 금액을 입력해 주세요."; - private static final String MESSAGE_REMAIN_MONEY = "투입 금액: %d 원"; + private static final String MESSAGE_REMAIN_MONEY = "투입 금액: %d원"; private static final String MESSAGE_INPUT_PRODUCT_NAME = "구매할 상품명을 입력해 주세요."; + private static final String MESSAGE_CHANGES = "잔돈"; public void printExceptionMessage(IllegalArgumentException exception) { System.out.println(exception.getMessage()); @@ -27,7 +29,12 @@ public void printNewLine() { System.out.println(); } - public void printCoins(Coins coins) { + public void printVendingMachineCoins(Coins coins) { + System.out.println(MESSAGE_VENDING_MACHINE_COINS); + printCoins(coins); + } + + private void printCoins(Coins coins) { for (Map.Entry coinEntry : coins.getCoins().entrySet()) { System.out.printf(MESSAGE_COINS, coinEntry.getKey().getAmount(), coinEntry.getValue()); System.out.println(); @@ -51,4 +58,9 @@ public void printRemainMoney(Money money) { public void printInputProductName() { System.out.println(MESSAGE_INPUT_PRODUCT_NAME); } + + public void printChanges(Coins coins) { + System.out.println(MESSAGE_CHANGES); + printCoins(coins); + } } From 9f81dddd64f9c247f27f1bb4aa4bea2da66288f6 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 10 Dec 2022 04:00:17 +0900 Subject: [PATCH 13/13] =?UTF-8?q?refactor:=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=ED=81=B4=EB=A6=B0=EC=BD=94=EB=93=9C,=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EB=B3=80=EC=88=98=EC=A0=9C=EA=B1=B0=20ref?= =?UTF-8?q?actor:=20getter=20=ED=95=A8=EC=88=98=20=EC=A7=80=EC=96=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VendingMachineController.java | 5 +---- src/main/java/vendingmachine/domain/Money.java | 5 +++-- src/main/java/vendingmachine/domain/VendingMachine.java | 8 +++----- src/main/java/vendingmachine/domain/coins/Coin.java | 8 ++++++-- src/main/java/vendingmachine/domain/coins/Coins.java | 8 ++++---- src/main/java/vendingmachine/domain/products/Price.java | 4 ++-- src/main/java/vendingmachine/domain/products/Product.java | 3 ++- .../java/vendingmachine/domain/products/Quantity.java | 2 +- src/test/java/vendingmachine/VendingMachineTest.java | 8 ++++---- 9 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 4badf2afa..96e13e132 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -3,12 +3,9 @@ import vendingmachine.domain.*; import vendingmachine.domain.coins.Coins; import vendingmachine.domain.coins.RandomNumberGenerator; -import vendingmachine.domain.products.Product; import vendingmachine.domain.products.Products; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; - -import java.util.function.Consumer; import java.util.function.Supplier; public class VendingMachineController { @@ -37,7 +34,7 @@ private void makeVendingMachine() { Coins coins = makeCoins(money); Products products = askProducts(); - vendingMachine = VendingMachine.of(money, coins, products); + vendingMachine = VendingMachine.of(coins, products); } private Money askMachineMoney() { diff --git a/src/main/java/vendingmachine/domain/Money.java b/src/main/java/vendingmachine/domain/Money.java index c659eacd7..b37f9f1b4 100644 --- a/src/main/java/vendingmachine/domain/Money.java +++ b/src/main/java/vendingmachine/domain/Money.java @@ -1,5 +1,6 @@ package vendingmachine.domain; +import vendingmachine.domain.coins.Coin; import vendingmachine.exception.MoneyRangeException; public class Money { @@ -39,8 +40,8 @@ public boolean isUseMoney(int money) { return (this.money - money) >= ZERO_MONEY; } - public int calculateDividingMoney(int number) { - return this.money / number; + public int calculateDividingCoin(Coin coin) { + return coin.exchangeCoin(this.money); } public int getMoney() { diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 36facffd2..af9c297ed 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -6,18 +6,16 @@ public class VendingMachine { - private final Money money; private final Coins coins; private final Products products; - private VendingMachine(Money money, Coins coins, Products products) { - this.money = money; + private VendingMachine(Coins coins, Products products) { this.coins = coins; this.products = products; } - public static VendingMachine of(Money money, Coins coins, Products products) { - return new VendingMachine(money, coins, products); + public static VendingMachine of(Coins coins, Products products) { + return new VendingMachine(coins, products); } public void purchaseProduct(String name, Money money){ diff --git a/src/main/java/vendingmachine/domain/coins/Coin.java b/src/main/java/vendingmachine/domain/coins/Coin.java index 37d58cdaf..9b279afa7 100644 --- a/src/main/java/vendingmachine/domain/coins/Coin.java +++ b/src/main/java/vendingmachine/domain/coins/Coin.java @@ -1,8 +1,6 @@ package vendingmachine.domain.coins; -import vendingmachine.domain.Money; import vendingmachine.exception.CoinEmptyException; - import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -39,7 +37,13 @@ public static int findMinAmount() { .orElseThrow(CoinEmptyException::new); } + public int exchangeCoin(int money) { + return (money / amount); + } + public int multiCoin(int multi) { + return (multi * amount); + } public int getAmount() { return amount; diff --git a/src/main/java/vendingmachine/domain/coins/Coins.java b/src/main/java/vendingmachine/domain/coins/Coins.java index 882545c93..324cdc758 100644 --- a/src/main/java/vendingmachine/domain/coins/Coins.java +++ b/src/main/java/vendingmachine/domain/coins/Coins.java @@ -53,13 +53,13 @@ public Coins makeLargestCoins(Money money) { } private int calculateCoin(Coin coin, Money money) { - int count = money.calculateDividingMoney(coin.getAmount()); + int count = money.calculateDividingCoin(coin); int coinNumber = coins.get(coin); - if(coinNumber <= count) { - money.useMoney(coinNumber * coin.getAmount()); + if (coinNumber <= count) { + money.useMoney(coin.multiCoin(coinNumber)); return coins.get(coin); } - money.useMoney(count * coin.getAmount()); + money.useMoney(coin.multiCoin(count)); return count; } diff --git a/src/main/java/vendingmachine/domain/products/Price.java b/src/main/java/vendingmachine/domain/products/Price.java index f2febbc12..1366bd0f4 100644 --- a/src/main/java/vendingmachine/domain/products/Price.java +++ b/src/main/java/vendingmachine/domain/products/Price.java @@ -35,7 +35,7 @@ private static void validateRange(int price) { } private static void validateDividing(int price) { - if ((price % DIVIDING_PRICE) != DIVIDING_RESULT){ + if ((price % DIVIDING_PRICE) != DIVIDING_RESULT) { throw new PriceDividingException(DIVIDING_PRICE); } } @@ -45,7 +45,7 @@ public boolean isCheaperPrice(Price price) { } public boolean validateMoney(Money money) { - if (money.isUseMoney(this.price)){ + if (money.isUseMoney(this.price)) { return true; } throw new PriceNotPurchaseException(); diff --git a/src/main/java/vendingmachine/domain/products/Product.java b/src/main/java/vendingmachine/domain/products/Product.java index 412538a34..0afafdd25 100644 --- a/src/main/java/vendingmachine/domain/products/Product.java +++ b/src/main/java/vendingmachine/domain/products/Product.java @@ -45,7 +45,8 @@ public void purchase(Money money) { public boolean isPurchaseProduct(Money money) { return price.isPurchase(money); } - public boolean isSoldOut(){ + + public boolean isSoldOut() { return !quantity.isRemain(); } diff --git a/src/main/java/vendingmachine/domain/products/Quantity.java b/src/main/java/vendingmachine/domain/products/Quantity.java index 63f7948d1..2a8697ed9 100644 --- a/src/main/java/vendingmachine/domain/products/Quantity.java +++ b/src/main/java/vendingmachine/domain/products/Quantity.java @@ -14,7 +14,7 @@ private Quantity(int quantity) { this.quantity = quantity; } - public static Quantity from(int quantity){ + public static Quantity from(int quantity) { return new Quantity(quantity); } diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/VendingMachineTest.java index 184c36a35..17a222268 100644 --- a/src/test/java/vendingmachine/VendingMachineTest.java +++ b/src/test/java/vendingmachine/VendingMachineTest.java @@ -18,7 +18,7 @@ void purchaseProductSuccess() { Money money = Money.from(5000); Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10];[솔의눈,10000,10]"); Coins coins = new Coins(); - VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + VendingMachine vendingMachine = VendingMachine.of(coins, products); vendingMachine.purchaseProduct("콜라", money); Products compareProducts = ProductsConvert.convert("[콜라,2000,19];[사이다,1000,10];[솔의눈,10000,10]"); @@ -32,7 +32,7 @@ void purchaseProductSuccess() { void isSellProductTrue() { Products products = ProductsConvert.convert("[콜라,2000,20];[사이다,1000,10];[솔의눈,10000,10]"); Coins coins = new Coins(); - VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + VendingMachine vendingMachine = VendingMachine.of(coins, products); assertThat(vendingMachine.isSellProduct(Money.from(5000))).isEqualTo(true); } @@ -42,7 +42,7 @@ void isSellProductTrue() { void isSellProductFalseByQuantity() { Products products = ProductsConvert.convert("[콜라,2000,0];[사이다,1000,0];[솔의눈,10000,0]"); Coins coins = new Coins(); - VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + VendingMachine vendingMachine = VendingMachine.of(coins, products); assertThat(vendingMachine.isSellProduct(Money.from(5000))).isEqualTo(false); } @@ -52,7 +52,7 @@ void isSellProductFalseByQuantity() { void isSellProductFalseByMoney() { Products products = ProductsConvert.convert("[콜라,2000,10];[사이다,1000,100];[솔의눈,10000,20]"); Coins coins = new Coins(); - VendingMachine vendingMachine = VendingMachine.of(Money.from(676), coins, products); + VendingMachine vendingMachine = VendingMachine.of(coins, products); assertThat(vendingMachine.isSellProduct(Money.from(500))).isEqualTo(false); }