From ba649e5969d1cadbbd64a7cd2e00658e1daaa39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 19:42:08 +0900 Subject: [PATCH 01/24] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..7e9dcda60 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,29 @@ +## 기능 목록 +- [ ] 자판기 보유 금액 생성 + - [ ] 자판기 보유 금액 입력 요청 메시지 출력 + - [ ] 자판기 보유 금액 입력 + - [ ] 숫자인지 검증 + - [ ] 10원으로 나누어 떨어지는지 검증 +- [ ] 자판기 보유 동전 생성 + - [ ] 자판기 보유 동전 랜덤 생성 + - [ ] 자판기 보유 동전 저장 + - [ ] 자판기 보유 동전 출력 +- [ ] 상품 가격 및 수량 저장 + - [ ] 상품명, 가격, 수량 입력 요청 메시지 출력 + - [ ] 상품명, 가격, 수량 입력 + - [ ] 대괄호로 묶어 세미콜론으로 구분했는지 검증 + - [ ] 상품 저장 +- [ ] 투입 금액 설정 + - [ ] 투입 금액 입력 요청 메시지 출력 + - [ ] 투입 금액 입력 + - [ ] 숫자인지 검증 + - [ ] 투입 금액 저장 +- [ ] 상품 구매 + - [ ] 구매할 상품명 입력 요청 메시지 출력 + - [ ] 구매할 상품명 입력 + - [ ] 상품 구매 + - [ ] 금액 차감 + - [ ] 차감된 투입 금액 출력 +- [ ] 남은 금액이 최저 가격보다 적거나, 모든 상품 소진시 잔돈 반환 + - [ ] 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환 (잔액 부족시 or 나눠 떨어지지 않을시) + - [ ] 잔돈 동전별로 출력 From d147536cbc1b6bd759490a70faabf5fb9c4c38da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 19:49:15 +0900 Subject: [PATCH 02/24] =?UTF-8?q?feat:=20=EC=9E=90=ED=8C=90=EA=B8=B0=20?= =?UTF-8?q?=EB=B3=B4=EC=9C=A0=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 15 ++++++++++++++- src/main/java/vendingmachine/Application.java | 4 +++- .../vendingmachine/{ => constant}/Coin.java | 2 +- .../constant/VendingMachineMessage.java | 16 ++++++++++++++++ .../controller/VendingMachineController.java | 17 +++++++++++++++++ src/main/java/vendingmachine/io/OutputView.java | 10 ++++++++++ 6 files changed, 61 insertions(+), 3 deletions(-) rename src/main/java/vendingmachine/{ => constant}/Coin.java (86%) create mode 100644 src/main/java/vendingmachine/constant/VendingMachineMessage.java create mode 100644 src/main/java/vendingmachine/controller/VendingMachineController.java create mode 100644 src/main/java/vendingmachine/io/OutputView.java diff --git a/docs/README.md b/docs/README.md index 7e9dcda60..232b6e562 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ ## 기능 목록 - [ ] 자판기 보유 금액 생성 - - [ ] 자판기 보유 금액 입력 요청 메시지 출력 + - [x] 자판기 보유 금액 입력 요청 메시지 출력 - [ ] 자판기 보유 금액 입력 - [ ] 숫자인지 검증 - [ ] 10원으로 나누어 떨어지는지 검증 @@ -27,3 +27,16 @@ - [ ] 남은 금액이 최저 가격보다 적거나, 모든 상품 소진시 잔돈 반환 - [ ] 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환 (잔액 부족시 or 나눠 떨어지지 않을시) - [ ] 잔돈 동전별로 출력 + +## 구현 클래스 목록 + +- VendingMachineController + - start() + +- OutputView + - printOwningMoney() + + +## 열거형 목록 +- Coin +- VendingMachineMessage diff --git a/src/main/java/vendingmachine/Application.java b/src/main/java/vendingmachine/Application.java index 9d3be447b..698c7bf65 100644 --- a/src/main/java/vendingmachine/Application.java +++ b/src/main/java/vendingmachine/Application.java @@ -1,7 +1,9 @@ package vendingmachine; +import vendingmachine.controller.VendingMachineController; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + new VendingMachineController().start(); } } diff --git a/src/main/java/vendingmachine/Coin.java b/src/main/java/vendingmachine/constant/Coin.java similarity index 86% rename from src/main/java/vendingmachine/Coin.java rename to src/main/java/vendingmachine/constant/Coin.java index c76293fbc..ee6512fd5 100644 --- a/src/main/java/vendingmachine/Coin.java +++ b/src/main/java/vendingmachine/constant/Coin.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.constant; public enum Coin { COIN_500(500), diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java new file mode 100644 index 000000000..68c3b3257 --- /dev/null +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -0,0 +1,16 @@ +package vendingmachine.constant; + +public enum VendingMachineMessage { + + OWNING_MONEY("자판기가 보유하고 있는 금액을 입력해 주세요."); + + private final String message; + + VendingMachineMessage(final String message) { + this.message = message; + } + + public String getMessage() { + return this.message; + } +} diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java new file mode 100644 index 000000000..d58044012 --- /dev/null +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -0,0 +1,17 @@ +package vendingmachine.controller; + +import vendingmachine.io.OutputView; + +public class VendingMachineController { + + private final OutputView outputView; + + public VendingMachineController() { + this.outputView = new OutputView(); + } + + + public void start() { + outputView.printOwningMoney(); + } +} diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java new file mode 100644 index 000000000..ce8cef736 --- /dev/null +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -0,0 +1,10 @@ +package vendingmachine.io; + +import vendingmachine.constant.VendingMachineMessage; + +public class OutputView { + + public void printOwningMoney() { + System.out.println(VendingMachineMessage.OWNING_MONEY.getMessage()); + } +} From 5175785775d767005f891c571d426019f8b30260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 20:00:12 +0900 Subject: [PATCH 03/24] =?UTF-8?q?feat:=20=EC=9E=90=ED=8C=90=EA=B8=B0=20?= =?UTF-8?q?=EB=B3=B4=EC=9C=A0=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=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 --- docs/README.md | 6 ++-- .../vendingmachine/constant/ErrorMessage.java | 17 +++++++++++ .../controller/VendingMachineController.java | 9 ++++++ .../vendingmachine/domain/OwningMoney.java | 20 +++++++++++++ .../java/vendingmachine/io/InputManager.java | 28 +++++++++++++++++++ .../vendingmachine/io/InputValidator.java | 19 +++++++++++++ .../java/vendingmachine/io/InputView.java | 18 ++++++++++++ 7 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/main/java/vendingmachine/constant/ErrorMessage.java create mode 100644 src/main/java/vendingmachine/domain/OwningMoney.java create mode 100644 src/main/java/vendingmachine/io/InputManager.java create mode 100644 src/main/java/vendingmachine/io/InputValidator.java create mode 100644 src/main/java/vendingmachine/io/InputView.java diff --git a/docs/README.md b/docs/README.md index 232b6e562..232ef6014 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,9 @@ ## 기능 목록 - [ ] 자판기 보유 금액 생성 - [x] 자판기 보유 금액 입력 요청 메시지 출력 - - [ ] 자판기 보유 금액 입력 - - [ ] 숫자인지 검증 - - [ ] 10원으로 나누어 떨어지는지 검증 + - [x] 자판기 보유 금액 입력 + - [x] 숫자인지 검증 + - [x] 10원으로 나누어 떨어지는지 검증 - [ ] 자판기 보유 동전 생성 - [ ] 자판기 보유 동전 랜덤 생성 - [ ] 자판기 보유 동전 저장 diff --git a/src/main/java/vendingmachine/constant/ErrorMessage.java b/src/main/java/vendingmachine/constant/ErrorMessage.java new file mode 100644 index 000000000..60c6a6680 --- /dev/null +++ b/src/main/java/vendingmachine/constant/ErrorMessage.java @@ -0,0 +1,17 @@ +package vendingmachine.constant; + +public enum ErrorMessage { + NOT_NUMERIC("입력값은 숫자만 가능합니다."), + INVALID_MONEY("숫자가 단위로 떨어지지 않습니다."); + + private static final String ERROR_PREFIX = "[ERROR] "; + private final String message; + + ErrorMessage(final String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_PREFIX + message; + } +} diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index d58044012..f74af69b4 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -1,17 +1,26 @@ package vendingmachine.controller; +import vendingmachine.domain.OwningMoney; +import vendingmachine.io.InputManager; import vendingmachine.io.OutputView; public class VendingMachineController { private final OutputView outputView; + private final InputManager inputManager; public VendingMachineController() { this.outputView = new OutputView(); + this.inputManager = new InputManager(); } public void start() { + makeOwningMoney(); + } + + private void makeOwningMoney() { outputView.printOwningMoney(); + final OwningMoney owningMoney = inputManager.readOwningMoney(); } } diff --git a/src/main/java/vendingmachine/domain/OwningMoney.java b/src/main/java/vendingmachine/domain/OwningMoney.java new file mode 100644 index 000000000..6ead7a56b --- /dev/null +++ b/src/main/java/vendingmachine/domain/OwningMoney.java @@ -0,0 +1,20 @@ +package vendingmachine.domain; + +import vendingmachine.constant.ErrorMessage; + +public class OwningMoney { + + private static final int MONEY_UNIT = 10; + private final Integer value; + + public OwningMoney(final int value) { + validateUnit(value); + this.value = value; + } + + private void validateUnit(final int value) { + if (value % MONEY_UNIT != 0) { + throw new IllegalArgumentException(ErrorMessage.INVALID_MONEY.getMessage()); + } + } +} diff --git a/src/main/java/vendingmachine/io/InputManager.java b/src/main/java/vendingmachine/io/InputManager.java new file mode 100644 index 000000000..299736ce7 --- /dev/null +++ b/src/main/java/vendingmachine/io/InputManager.java @@ -0,0 +1,28 @@ +package vendingmachine.io; + +import vendingmachine.domain.OwningMoney; + +import java.util.function.Supplier; + +public class InputManager { + + private final InputView inputView; + + public InputManager() { + this.inputView = new InputView(); + } + + public OwningMoney readOwningMoney() { + return read(() -> new OwningMoney(Integer.parseInt(inputView.readOwningMoney()))); + } + + private T read(final Supplier supplier) { + while (true) { + try { + return supplier.get(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } +} diff --git a/src/main/java/vendingmachine/io/InputValidator.java b/src/main/java/vendingmachine/io/InputValidator.java new file mode 100644 index 000000000..661eab43a --- /dev/null +++ b/src/main/java/vendingmachine/io/InputValidator.java @@ -0,0 +1,19 @@ +package vendingmachine.io; + +import vendingmachine.constant.ErrorMessage; + +public class InputValidator { + + private static final Character MIN_NUMBER_STANDARD = '0'; + private static final Character MAX_NUMBER_STANDARD = '9'; + + public void validateNumeric(final String input) { + if (isNotNumeric(input)) { + throw new IllegalArgumentException(ErrorMessage.NOT_NUMERIC.getMessage()); + } + } + + private boolean isNotNumeric(final String input) { + return input.chars().anyMatch(c -> c < MIN_NUMBER_STANDARD || c > MAX_NUMBER_STANDARD); + } +} diff --git a/src/main/java/vendingmachine/io/InputView.java b/src/main/java/vendingmachine/io/InputView.java new file mode 100644 index 000000000..32c545c33 --- /dev/null +++ b/src/main/java/vendingmachine/io/InputView.java @@ -0,0 +1,18 @@ +package vendingmachine.io; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + + private final InputValidator inputValidator; + + public InputView() { + this.inputValidator = new InputValidator(); + } + + public String readOwningMoney() { + final String input = Console.readLine(); + inputValidator.validateNumeric(input); + return input; + } +} From 5d3b2d5d23938f126218464ea78be1a184c04f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 20:04:09 +0900 Subject: [PATCH 04/24] =?UTF-8?q?docs(README):=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/README.md b/docs/README.md index 232ef6014..84d36e62b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,7 +36,16 @@ - OutputView - printOwningMoney() +- InputView + - readOwningMoney() + +- InputManager + - readOwningMoney() + +- InputValidator + - validateNumeric() ## 열거형 목록 - Coin - VendingMachineMessage +- ErrorMessage From eccf7134136a674d2f2534e2bc9e9cb0cd6d2ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 20:24:27 +0900 Subject: [PATCH 05/24] =?UTF-8?q?feat(RandomCoinGenerator):=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=20=EC=BD=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 19 +++++++++++-- .../utils/RandomCoinGenerator.java | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/main/java/vendingmachine/utils/RandomCoinGenerator.java diff --git a/docs/README.md b/docs/README.md index 84d36e62b..e9834d065 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,11 @@ ## 기능 목록 -- [ ] 자판기 보유 금액 생성 +- [x] 자판기 보유 금액 생성 - [x] 자판기 보유 금액 입력 요청 메시지 출력 - [x] 자판기 보유 금액 입력 - [x] 숫자인지 검증 - [x] 10원으로 나누어 떨어지는지 검증 - [ ] 자판기 보유 동전 생성 - - [ ] 자판기 보유 동전 랜덤 생성 + - [x] 자판기 보유 동전 랜덤 생성 - [ ] 자판기 보유 동전 저장 - [ ] 자판기 보유 동전 출력 - [ ] 상품 가격 및 수량 저장 @@ -45,6 +45,21 @@ - InputValidator - validateNumeric() +- VendingMachineService + - makeCoins + +- VendingMachineRepository + - saveCoins() + - findCoins() + +- RandomCoinGenerator + - generate() + +- OwningMoney + - getValue() + - hasMoney() + - minusValue() + ## 열거형 목록 - Coin - VendingMachineMessage diff --git a/src/main/java/vendingmachine/utils/RandomCoinGenerator.java b/src/main/java/vendingmachine/utils/RandomCoinGenerator.java new file mode 100644 index 000000000..4cc6847cd --- /dev/null +++ b/src/main/java/vendingmachine/utils/RandomCoinGenerator.java @@ -0,0 +1,28 @@ +package vendingmachine.utils; + +import camp.nextstep.edu.missionutils.Randoms; +import vendingmachine.constant.Coin; +import vendingmachine.domain.Coins; +import vendingmachine.domain.OwningMoney; + +import java.util.List; + +public class RandomCoinGenerator { + + public Coins generate(final OwningMoney owningMoney) { + final List availableCoins = Coin.getCoinByOwningMoney(owningMoney); + final Coins coins = new Coins(); + addCoins(owningMoney, availableCoins, coins); + return coins; + } + + private void addCoins(final OwningMoney owningMoney, final List availableCoins, final Coins coins) { + while (owningMoney.hasMoney()) { + final int coin = Randoms.pickNumberInList(availableCoins); + if (owningMoney.isAvailableCoin(coin)) { + owningMoney.minusValue(coin); + coins.addCoin(Coin.valueOfAmount(coin)); + } + } + } +} From 897cb2eb0730f20d177ff8337fe413cd2320b501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 20:32:50 +0900 Subject: [PATCH 06/24] =?UTF-8?q?feat:=20=EB=B3=B4=EC=9C=A0=20=EB=8F=99?= =?UTF-8?q?=EC=A0=84=20=EC=A0=80=EC=9E=A5=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 5 ++++- .../java/vendingmachine/constant/Coin.java | 20 ++++++++++++++++- .../vendingmachine/constant/ErrorMessage.java | 3 ++- .../controller/VendingMachineController.java | 5 +++++ .../java/vendingmachine/domain/Coins.java | 20 +++++++++++++++++ .../vendingmachine/domain/OwningMoney.java | 18 ++++++++++++++- .../repository/VendingMachineRepository.java | 17 ++++++++++++++ .../service/VendingMachineService.java | 22 +++++++++++++++++++ 8 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 src/main/java/vendingmachine/domain/Coins.java create mode 100644 src/main/java/vendingmachine/repository/VendingMachineRepository.java create mode 100644 src/main/java/vendingmachine/service/VendingMachineService.java diff --git a/docs/README.md b/docs/README.md index e9834d065..9e97b48b2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,7 +6,7 @@ - [x] 10원으로 나누어 떨어지는지 검증 - [ ] 자판기 보유 동전 생성 - [x] 자판기 보유 동전 랜덤 생성 - - [ ] 자판기 보유 동전 저장 + - [x] 자판기 보유 동전 저장 - [ ] 자판기 보유 동전 출력 - [ ] 상품 가격 및 수량 저장 - [ ] 상품명, 가격, 수량 입력 요청 메시지 출력 @@ -60,6 +60,9 @@ - hasMoney() - minusValue() +- Coins + - addCoin() + ## 열거형 목록 - Coin - VendingMachineMessage diff --git a/src/main/java/vendingmachine/constant/Coin.java b/src/main/java/vendingmachine/constant/Coin.java index ee6512fd5..5312b63a8 100644 --- a/src/main/java/vendingmachine/constant/Coin.java +++ b/src/main/java/vendingmachine/constant/Coin.java @@ -1,5 +1,11 @@ package vendingmachine.constant; +import vendingmachine.domain.OwningMoney; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + public enum Coin { COIN_500(500), COIN_100(100), @@ -12,5 +18,17 @@ public enum Coin { this.amount = amount; } - // 추가 기능 구현 + public static List getCoinByOwningMoney(final OwningMoney owningMoney) { + return Arrays.stream(values()) + .filter(value -> value.amount <= owningMoney.getValue()) + .map(coin -> coin.amount) + .collect(Collectors.toList()); + } + + public static Coin valueOfAmount(final int amount) { + return Arrays.stream(values()) + .filter(value -> value.amount == amount) + .findFirst() + .orElseThrow(() -> new IllegalStateException(ErrorMessage.INVALID_AMOUNT.getMessage())); + } } diff --git a/src/main/java/vendingmachine/constant/ErrorMessage.java b/src/main/java/vendingmachine/constant/ErrorMessage.java index 60c6a6680..d913f6d28 100644 --- a/src/main/java/vendingmachine/constant/ErrorMessage.java +++ b/src/main/java/vendingmachine/constant/ErrorMessage.java @@ -2,7 +2,8 @@ public enum ErrorMessage { NOT_NUMERIC("입력값은 숫자만 가능합니다."), - INVALID_MONEY("숫자가 단위로 떨어지지 않습니다."); + INVALID_MONEY("숫자가 단위로 떨어지지 않습니다."), + INVALID_AMOUNT("잘못된 Amount 입니다."); private static final String ERROR_PREFIX = "[ERROR] "; private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index f74af69b4..aebe270d9 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -1,17 +1,21 @@ package vendingmachine.controller; +import vendingmachine.domain.Coins; import vendingmachine.domain.OwningMoney; import vendingmachine.io.InputManager; import vendingmachine.io.OutputView; +import vendingmachine.service.VendingMachineService; public class VendingMachineController { private final OutputView outputView; private final InputManager inputManager; + private final VendingMachineService vendingMachineService; public VendingMachineController() { this.outputView = new OutputView(); this.inputManager = new InputManager(); + this.vendingMachineService = new VendingMachineService(); } @@ -22,5 +26,6 @@ public void start() { private void makeOwningMoney() { outputView.printOwningMoney(); final OwningMoney owningMoney = inputManager.readOwningMoney(); + final Coins coins = vendingMachineService.makeCoins(owningMoney); } } diff --git a/src/main/java/vendingmachine/domain/Coins.java b/src/main/java/vendingmachine/domain/Coins.java new file mode 100644 index 000000000..a0f5436f5 --- /dev/null +++ b/src/main/java/vendingmachine/domain/Coins.java @@ -0,0 +1,20 @@ +package vendingmachine.domain; + +import vendingmachine.constant.Coin; + +import java.util.ArrayList; +import java.util.List; + +public class Coins { + + private final List coins; + + + public Coins() { + this.coins = new ArrayList<>(); + } + + public void addCoin(final Coin coin) { + this.coins.add(coin); + } +} diff --git a/src/main/java/vendingmachine/domain/OwningMoney.java b/src/main/java/vendingmachine/domain/OwningMoney.java index 6ead7a56b..0ff8306d9 100644 --- a/src/main/java/vendingmachine/domain/OwningMoney.java +++ b/src/main/java/vendingmachine/domain/OwningMoney.java @@ -5,7 +5,7 @@ public class OwningMoney { private static final int MONEY_UNIT = 10; - private final Integer value; + private Integer value; public OwningMoney(final int value) { validateUnit(value); @@ -17,4 +17,20 @@ private void validateUnit(final int value) { throw new IllegalArgumentException(ErrorMessage.INVALID_MONEY.getMessage()); } } + + public int getValue() { + return this.value; + } + + public boolean hasMoney() { + return this.value != 0; + } + + public void minusValue(final int coin) { + this.value -= coin; + } + + public boolean isAvailableCoin(final int coin) { + return this.value > coin; + } } diff --git a/src/main/java/vendingmachine/repository/VendingMachineRepository.java b/src/main/java/vendingmachine/repository/VendingMachineRepository.java new file mode 100644 index 000000000..f299dc84d --- /dev/null +++ b/src/main/java/vendingmachine/repository/VendingMachineRepository.java @@ -0,0 +1,17 @@ +package vendingmachine.repository; + +import vendingmachine.domain.Coins; + +public class VendingMachineRepository { + + private Coins coins; + + public Coins saveCoins(final Coins coins) { + this.coins = coins; + return this.coins; + } + + public Coins findCoins() { + return this.coins; + } +} diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java new file mode 100644 index 000000000..21e788c56 --- /dev/null +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -0,0 +1,22 @@ +package vendingmachine.service; + +import vendingmachine.domain.Coins; +import vendingmachine.domain.OwningMoney; +import vendingmachine.repository.VendingMachineRepository; +import vendingmachine.utils.RandomCoinGenerator; + +public class VendingMachineService { + + private final VendingMachineRepository vendingMachineRepository; + private final RandomCoinGenerator ranhdomCoinGenerator; + + public VendingMachineService() { + this.vendingMachineRepository = new VendingMachineRepository(); + this.ranhdomCoinGenerator = new RandomCoinGenerator(); + } + + public Coins makeCoins(final OwningMoney owningMoney) { + final Coins coins = ranhdomCoinGenerator.generate(owningMoney); + return vendingMachineRepository.saveCoins(coins); + } +} From ac78a651b0c9af20fc531314db64f16d743bca8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 20:43:08 +0900 Subject: [PATCH 07/24] =?UTF-8?q?feat:=20=EB=B3=B4=EC=9C=A0=20=EB=8F=99?= =?UTF-8?q?=EC=A0=84=20=EC=B6=9C=EB=A0=A5=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/constant/Coin.java | 4 ++++ .../constant/VendingMachineMessage.java | 3 ++- .../controller/VendingMachineController.java | 1 + src/main/java/vendingmachine/domain/Coins.java | 11 +++++++++++ src/main/java/vendingmachine/io/OutputView.java | 8 +++++++- 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/vendingmachine/constant/Coin.java b/src/main/java/vendingmachine/constant/Coin.java index 5312b63a8..5bbbce6c7 100644 --- a/src/main/java/vendingmachine/constant/Coin.java +++ b/src/main/java/vendingmachine/constant/Coin.java @@ -31,4 +31,8 @@ public static Coin valueOfAmount(final int amount) { .findFirst() .orElseThrow(() -> new IllegalStateException(ErrorMessage.INVALID_AMOUNT.getMessage())); } + + public int getAmount() { + return this.amount; + } } diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java index 68c3b3257..3df27dcec 100644 --- a/src/main/java/vendingmachine/constant/VendingMachineMessage.java +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -2,7 +2,8 @@ public enum VendingMachineMessage { - OWNING_MONEY("자판기가 보유하고 있는 금액을 입력해 주세요."); + OWNING_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."), + OWNING_COINS("자판기가 보유한 동전"); private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index aebe270d9..94ba4e6ca 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -27,5 +27,6 @@ private void makeOwningMoney() { outputView.printOwningMoney(); final OwningMoney owningMoney = inputManager.readOwningMoney(); final Coins coins = vendingMachineService.makeCoins(owningMoney); + outputView.printCoins(coins); } } diff --git a/src/main/java/vendingmachine/domain/Coins.java b/src/main/java/vendingmachine/domain/Coins.java index a0f5436f5..4c804d17f 100644 --- a/src/main/java/vendingmachine/domain/Coins.java +++ b/src/main/java/vendingmachine/domain/Coins.java @@ -3,10 +3,13 @@ import vendingmachine.constant.Coin; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public class Coins { + private static final String COIN_FORMAT = "%d원 - %d개\n"; private final List coins; @@ -17,4 +20,12 @@ public Coins() { public void addCoin(final Coin coin) { this.coins.add(coin); } + + public String getCoinMessage() { + return Arrays.stream(Coin.values()) + .map(c -> { + final long count = coins.stream().filter(coin -> c == coin).count(); + return String.format(COIN_FORMAT, c.getAmount(), count); + }).collect(Collectors.joining()); + } } diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java index ce8cef736..c7f44b846 100644 --- a/src/main/java/vendingmachine/io/OutputView.java +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -1,10 +1,16 @@ package vendingmachine.io; import vendingmachine.constant.VendingMachineMessage; +import vendingmachine.domain.Coins; public class OutputView { public void printOwningMoney() { - System.out.println(VendingMachineMessage.OWNING_MONEY.getMessage()); + System.out.println(VendingMachineMessage.OWNING_MONEY_REQUEST.getMessage()); + } + + public void printCoins(final Coins coins) { + System.out.println(VendingMachineMessage.OWNING_COINS.getMessage()); + System.out.println(coins.getCoinMessage()); } } From 96d078a656c7b66dbc2243809599aba85fcb32e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 20:48:11 +0900 Subject: [PATCH 08/24] =?UTF-8?q?feat:=20=EC=A0=9C=ED=92=88=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EC=9A=94=EC=B2=AD=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 8 +++++--- .../vendingmachine/constant/VendingMachineMessage.java | 3 ++- .../controller/VendingMachineController.java | 7 ++++++- src/main/java/vendingmachine/io/OutputView.java | 6 +++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/README.md b/docs/README.md index 9e97b48b2..7df615ad0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,12 +4,12 @@ - [x] 자판기 보유 금액 입력 - [x] 숫자인지 검증 - [x] 10원으로 나누어 떨어지는지 검증 -- [ ] 자판기 보유 동전 생성 +- [x] 자판기 보유 동전 생성 - [x] 자판기 보유 동전 랜덤 생성 - [x] 자판기 보유 동전 저장 - - [ ] 자판기 보유 동전 출력 + - [x] 자판기 보유 동전 출력 - [ ] 상품 가격 및 수량 저장 - - [ ] 상품명, 가격, 수량 입력 요청 메시지 출력 + - [x] 상품명, 가격, 수량 입력 요청 메시지 출력 - [ ] 상품명, 가격, 수량 입력 - [ ] 대괄호로 묶어 세미콜론으로 구분했는지 검증 - [ ] 상품 저장 @@ -35,6 +35,8 @@ - OutputView - printOwningMoney() + - printCoins() + - printProductRequest() - InputView - readOwningMoney() diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java index 3df27dcec..b9c682123 100644 --- a/src/main/java/vendingmachine/constant/VendingMachineMessage.java +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -3,7 +3,8 @@ public enum VendingMachineMessage { OWNING_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."), - OWNING_COINS("자판기가 보유한 동전"); + OWNING_COINS("자판기가 보유한 동전"), + PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."); private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 94ba4e6ca..1d0351773 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -21,10 +21,15 @@ public VendingMachineController() { public void start() { makeOwningMoney(); + makeProduct(); + } + + private void makeProduct() { + outputView.printProductRequest(); } private void makeOwningMoney() { - outputView.printOwningMoney(); + outputView.printOwningMoneyRequest(); final OwningMoney owningMoney = inputManager.readOwningMoney(); final Coins coins = vendingMachineService.makeCoins(owningMoney); outputView.printCoins(coins); diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java index c7f44b846..b3ed404c8 100644 --- a/src/main/java/vendingmachine/io/OutputView.java +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -5,7 +5,7 @@ public class OutputView { - public void printOwningMoney() { + public void printOwningMoneyRequest() { System.out.println(VendingMachineMessage.OWNING_MONEY_REQUEST.getMessage()); } @@ -13,4 +13,8 @@ public void printCoins(final Coins coins) { System.out.println(VendingMachineMessage.OWNING_COINS.getMessage()); System.out.println(coins.getCoinMessage()); } + + public void printProductRequest() { + System.out.println(VendingMachineMessage.PRODUCT_REQUEST.getMessage()); + } } From b2547cd42b66f47831cca15914403e352babde42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:00:40 +0900 Subject: [PATCH 09/24] =?UTF-8?q?feat:=20=EC=A0=9C=ED=92=88=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/constant/ErrorMessage.java | 4 ++- .../controller/VendingMachineController.java | 2 ++ .../java/vendingmachine/domain/Product.java | 27 +++++++++++++++++++ .../java/vendingmachine/domain/Products.java | 26 ++++++++++++++++++ .../java/vendingmachine/io/InputManager.java | 18 +++++++++++++ .../vendingmachine/io/InputValidator.java | 10 +++++++ .../java/vendingmachine/io/InputView.java | 6 +++++ 7 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/main/java/vendingmachine/domain/Product.java create mode 100644 src/main/java/vendingmachine/domain/Products.java diff --git a/src/main/java/vendingmachine/constant/ErrorMessage.java b/src/main/java/vendingmachine/constant/ErrorMessage.java index d913f6d28..672a65333 100644 --- a/src/main/java/vendingmachine/constant/ErrorMessage.java +++ b/src/main/java/vendingmachine/constant/ErrorMessage.java @@ -3,7 +3,9 @@ public enum ErrorMessage { NOT_NUMERIC("입력값은 숫자만 가능합니다."), INVALID_MONEY("숫자가 단위로 떨어지지 않습니다."), - INVALID_AMOUNT("잘못된 Amount 입니다."); + INVALID_AMOUNT("잘못된 Amount 입니다."), + INVALID_PRODUCTS_INPUT("잘못된 Product 입력입니다."), + NEGATIVE_NUMBER("음수는 받을 수 없습니다."); private static final String ERROR_PREFIX = "[ERROR] "; private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 1d0351773..30c9a5982 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -2,6 +2,7 @@ import vendingmachine.domain.Coins; import vendingmachine.domain.OwningMoney; +import vendingmachine.domain.Products; import vendingmachine.io.InputManager; import vendingmachine.io.OutputView; import vendingmachine.service.VendingMachineService; @@ -26,6 +27,7 @@ public void start() { private void makeProduct() { outputView.printProductRequest(); + final Products products = inputManager.readProducts(); } private void makeOwningMoney() { diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java new file mode 100644 index 000000000..9c5a4c774 --- /dev/null +++ b/src/main/java/vendingmachine/domain/Product.java @@ -0,0 +1,27 @@ +package vendingmachine.domain; + +import vendingmachine.constant.ErrorMessage; + +public class Product { + + private final String name; + private final Integer price; + private Integer amount; + + public Product(final String name, final Integer price, final Integer amount) { + validateNumbers(price, amount); + this.name = name; + this.price = price; + this.amount = amount; + } + + private void validateNumbers(final Integer price, final Integer amount) { + if (price <= 0 || amount <= 0) { + throw new IllegalArgumentException(ErrorMessage.NEGATIVE_NUMBER.getMessage()); + } + } + + public String getName() { + return this.name; + } +} diff --git a/src/main/java/vendingmachine/domain/Products.java b/src/main/java/vendingmachine/domain/Products.java new file mode 100644 index 000000000..e8798733b --- /dev/null +++ b/src/main/java/vendingmachine/domain/Products.java @@ -0,0 +1,26 @@ +package vendingmachine.domain; + +import vendingmachine.constant.ErrorMessage; + +import java.util.Collections; +import java.util.List; + +public class Products { + + private final List products; + + public Products(final List products) { + validateUniqueName(products); + this.products = Collections.unmodifiableList(products); + } + + private void validateUniqueName(final List products) { + if (isUnique(products)) { + throw new IllegalArgumentException(ErrorMessage.INVALID_PRODUCTS_INPUT.getMessage()); + } + } + + private boolean isUnique(final List products) { + return products.stream().map(Product::getName).distinct().count() != products.size(); + } +} diff --git a/src/main/java/vendingmachine/io/InputManager.java b/src/main/java/vendingmachine/io/InputManager.java index 299736ce7..049d3f6bc 100644 --- a/src/main/java/vendingmachine/io/InputManager.java +++ b/src/main/java/vendingmachine/io/InputManager.java @@ -1,8 +1,13 @@ package vendingmachine.io; import vendingmachine.domain.OwningMoney; +import vendingmachine.domain.Product; +import vendingmachine.domain.Products; +import java.util.Arrays; +import java.util.List; import java.util.function.Supplier; +import java.util.stream.Collectors; public class InputManager { @@ -16,6 +21,19 @@ public OwningMoney readOwningMoney() { return read(() -> new OwningMoney(Integer.parseInt(inputView.readOwningMoney()))); } + public Products readProducts() { + return read(() -> { + final String input = inputView.readProducts(); + final List products = Arrays.stream(input.split(";")) + .map(i -> i.substring(1, i.length() - 1)) + .map(s -> { + final String[] strings = s.split(","); + return new Product(strings[0], Integer.parseInt(strings[1]), Integer.parseInt(strings[2])); + }).collect(Collectors.toList()); + return new Products(products); + }); + } + private T read(final Supplier supplier) { while (true) { try { diff --git a/src/main/java/vendingmachine/io/InputValidator.java b/src/main/java/vendingmachine/io/InputValidator.java index 661eab43a..322f9a563 100644 --- a/src/main/java/vendingmachine/io/InputValidator.java +++ b/src/main/java/vendingmachine/io/InputValidator.java @@ -16,4 +16,14 @@ public void validateNumeric(final String input) { private boolean isNotNumeric(final String input) { return input.chars().anyMatch(c -> c < MIN_NUMBER_STANDARD || c > MAX_NUMBER_STANDARD); } + + public void validateProducts(final String input) { + if (isInvalidProductsInput(input)) { + throw new IllegalArgumentException(ErrorMessage.INVALID_PRODUCTS_INPUT.getMessage()); + } + } + + private boolean isInvalidProductsInput(final String input) { + return !input.startsWith("[") || !input.endsWith("]") || !input.contains(","); + } } diff --git a/src/main/java/vendingmachine/io/InputView.java b/src/main/java/vendingmachine/io/InputView.java index 32c545c33..4e3670146 100644 --- a/src/main/java/vendingmachine/io/InputView.java +++ b/src/main/java/vendingmachine/io/InputView.java @@ -15,4 +15,10 @@ public String readOwningMoney() { inputValidator.validateNumeric(input); return input; } + + public String readProducts() { + final String input = Console.readLine(); + inputValidator.validateProducts(input); + return input; + } } From 40e26b0a5120b22198a1e5883859157a1b988f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:01:54 +0900 Subject: [PATCH 10/24] =?UTF-8?q?docs(README):=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=A0=95=EB=B3=B4=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 7df615ad0..180c3ad21 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,10 +8,10 @@ - [x] 자판기 보유 동전 랜덤 생성 - [x] 자판기 보유 동전 저장 - [x] 자판기 보유 동전 출력 -- [ ] 상품 가격 및 수량 저장 +- [x] 상품 가격 및 수량 저장 - [x] 상품명, 가격, 수량 입력 요청 메시지 출력 - - [ ] 상품명, 가격, 수량 입력 - - [ ] 대괄호로 묶어 세미콜론으로 구분했는지 검증 + - [x] 상품명, 가격, 수량 입력 + - [x] 대괄호로 묶어 세미콜론으로 구분했는지 검증 - [ ] 상품 저장 - [ ] 투입 금액 설정 - [ ] 투입 금액 입력 요청 메시지 출력 @@ -65,6 +65,11 @@ - Coins - addCoin() +- Product + - getName() + +- Products + ## 열거형 목록 - Coin - VendingMachineMessage From 471cd5b170ea4972bff45aac88a00e6f7e14ed8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:03:31 +0900 Subject: [PATCH 11/24] =?UTF-8?q?feat:=20=EC=A0=9C=ED=92=88=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 +++- .../controller/VendingMachineController.java | 1 + .../repository/VendingMachineRepository.java | 10 ++++++++++ .../vendingmachine/service/VendingMachineService.java | 5 +++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 180c3ad21..d255a672f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,7 +12,7 @@ - [x] 상품명, 가격, 수량 입력 요청 메시지 출력 - [x] 상품명, 가격, 수량 입력 - [x] 대괄호로 묶어 세미콜론으로 구분했는지 검증 - - [ ] 상품 저장 + - [x] 상품 저장 - [ ] 투입 금액 설정 - [ ] 투입 금액 입력 요청 메시지 출력 - [ ] 투입 금액 입력 @@ -53,6 +53,8 @@ - VendingMachineRepository - saveCoins() - findCoins() + - saveProducts() + - findProducts() - RandomCoinGenerator - generate() diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 30c9a5982..c6f216df8 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -28,6 +28,7 @@ public void start() { private void makeProduct() { outputView.printProductRequest(); final Products products = inputManager.readProducts(); + vendingMachineService.saveProducts(products); } private void makeOwningMoney() { diff --git a/src/main/java/vendingmachine/repository/VendingMachineRepository.java b/src/main/java/vendingmachine/repository/VendingMachineRepository.java index f299dc84d..9178724e7 100644 --- a/src/main/java/vendingmachine/repository/VendingMachineRepository.java +++ b/src/main/java/vendingmachine/repository/VendingMachineRepository.java @@ -1,10 +1,12 @@ package vendingmachine.repository; import vendingmachine.domain.Coins; +import vendingmachine.domain.Products; public class VendingMachineRepository { private Coins coins; + private Products products; public Coins saveCoins(final Coins coins) { this.coins = coins; @@ -14,4 +16,12 @@ public Coins saveCoins(final Coins coins) { public Coins findCoins() { return this.coins; } + + public void saveProducts(final Products products) { + this.products = products; + } + + public Products findProducts() { + return this.products; + } } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index 21e788c56..8e0974960 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -2,6 +2,7 @@ import vendingmachine.domain.Coins; import vendingmachine.domain.OwningMoney; +import vendingmachine.domain.Products; import vendingmachine.repository.VendingMachineRepository; import vendingmachine.utils.RandomCoinGenerator; @@ -19,4 +20,8 @@ public Coins makeCoins(final OwningMoney owningMoney) { final Coins coins = ranhdomCoinGenerator.generate(owningMoney); return vendingMachineRepository.saveCoins(coins); } + + public void saveProducts(final Products products) { + vendingMachineRepository.saveProducts(products); + } } From e8cd1dd5e0dd39fcc43d8d9fe0d6718fcb56f9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:05:56 +0900 Subject: [PATCH 12/24] =?UTF-8?q?feat:=20=ED=88=AC=EC=9E=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=9E=85=EB=A0=A5=20=EC=9A=94=EC=B2=AD=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 3 ++- .../java/vendingmachine/constant/VendingMachineMessage.java | 3 ++- .../vendingmachine/controller/VendingMachineController.java | 5 +++++ src/main/java/vendingmachine/io/OutputView.java | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index d255a672f..bfd209980 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,7 +14,7 @@ - [x] 대괄호로 묶어 세미콜론으로 구분했는지 검증 - [x] 상품 저장 - [ ] 투입 금액 설정 - - [ ] 투입 금액 입력 요청 메시지 출력 + - [x] 투입 금액 입력 요청 메시지 출력 - [ ] 투입 금액 입력 - [ ] 숫자인지 검증 - [ ] 투입 금액 저장 @@ -37,6 +37,7 @@ - printOwningMoney() - printCoins() - printProductRequest() + - printUserMoneyRequest() - InputView - readOwningMoney() diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java index b9c682123..44441bcce 100644 --- a/src/main/java/vendingmachine/constant/VendingMachineMessage.java +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -4,7 +4,8 @@ public enum VendingMachineMessage { OWNING_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."), OWNING_COINS("자판기가 보유한 동전"), - PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."); + PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."), + USER_MONEY_REQUEST("투입 금액을 입력해 주세요."); private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index c6f216df8..5a5a8b23b 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -23,6 +23,11 @@ public VendingMachineController() { public void start() { makeOwningMoney(); makeProduct(); + makeUserMoney(); + } + + private void makeUserMoney() { + outputView.printUserMoneyRequest(); } private void makeProduct() { diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java index b3ed404c8..425e72176 100644 --- a/src/main/java/vendingmachine/io/OutputView.java +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -17,4 +17,8 @@ public void printCoins(final Coins coins) { public void printProductRequest() { System.out.println(VendingMachineMessage.PRODUCT_REQUEST.getMessage()); } + + public void printUserMoneyRequest() { + System.out.println(VendingMachineMessage.USER_MONEY_REQUEST.getMessage()); + } } From 03da17688361a39b09a9ea4b4471bac9a0a80be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:09:05 +0900 Subject: [PATCH 13/24] =?UTF-8?q?feat(UserMoney):=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/domain/UserMoney.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/vendingmachine/domain/UserMoney.java diff --git a/src/main/java/vendingmachine/domain/UserMoney.java b/src/main/java/vendingmachine/domain/UserMoney.java new file mode 100644 index 000000000..515a69b80 --- /dev/null +++ b/src/main/java/vendingmachine/domain/UserMoney.java @@ -0,0 +1,10 @@ +package vendingmachine.domain; + +public class UserMoney { + + private Integer amount; + + public UserMoney(final int amount) { + this.amount = amount; + } +} From 96d3cef0f39201736b06b31a5817354acb3b408e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:09:18 +0900 Subject: [PATCH 14/24] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 9 +++++++-- .../controller/VendingMachineController.java | 2 ++ src/main/java/vendingmachine/io/InputManager.java | 5 +++++ src/main/java/vendingmachine/io/InputView.java | 6 ++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index bfd209980..d02e861ac 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,8 +15,8 @@ - [x] 상품 저장 - [ ] 투입 금액 설정 - [x] 투입 금액 입력 요청 메시지 출력 - - [ ] 투입 금액 입력 - - [ ] 숫자인지 검증 + - [x] 투입 금액 입력 + - [x] 숫자인지 검증 - [ ] 투입 금액 저장 - [ ] 상품 구매 - [ ] 구매할 상품명 입력 요청 메시지 출력 @@ -41,12 +41,17 @@ - InputView - readOwningMoney() + - readProducts() + - readUserMoney() - InputManager - readOwningMoney() + - readProducts() + - readUserMoney() - InputValidator - validateNumeric() + - validateProducts() - VendingMachineService - makeCoins diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 5a5a8b23b..e44c59b4d 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -3,6 +3,7 @@ import vendingmachine.domain.Coins; import vendingmachine.domain.OwningMoney; import vendingmachine.domain.Products; +import vendingmachine.domain.UserMoney; import vendingmachine.io.InputManager; import vendingmachine.io.OutputView; import vendingmachine.service.VendingMachineService; @@ -28,6 +29,7 @@ public void start() { private void makeUserMoney() { outputView.printUserMoneyRequest(); + final UserMoney userMoney = inputManager.readUserMoney(); } private void makeProduct() { diff --git a/src/main/java/vendingmachine/io/InputManager.java b/src/main/java/vendingmachine/io/InputManager.java index 049d3f6bc..d1b46265c 100644 --- a/src/main/java/vendingmachine/io/InputManager.java +++ b/src/main/java/vendingmachine/io/InputManager.java @@ -3,6 +3,7 @@ import vendingmachine.domain.OwningMoney; import vendingmachine.domain.Product; import vendingmachine.domain.Products; +import vendingmachine.domain.UserMoney; import java.util.Arrays; import java.util.List; @@ -34,6 +35,10 @@ public Products readProducts() { }); } + public UserMoney readUserMoney() { + return read(() -> new UserMoney(Integer.parseInt(inputView.readUserMoney()))); + } + private T read(final Supplier supplier) { while (true) { try { diff --git a/src/main/java/vendingmachine/io/InputView.java b/src/main/java/vendingmachine/io/InputView.java index 4e3670146..3493ffbf9 100644 --- a/src/main/java/vendingmachine/io/InputView.java +++ b/src/main/java/vendingmachine/io/InputView.java @@ -21,4 +21,10 @@ public String readProducts() { inputValidator.validateProducts(input); return input; } + + public String readUserMoney() { + final String input = Console.readLine(); + inputValidator.validateNumeric(input); + return input; + } } From c1fc6698bef92abf956f208bb0494375b62fc129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:10:37 +0900 Subject: [PATCH 15/24] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=A0=80=EC=9E=A5=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 ++++-- .../controller/VendingMachineController.java | 1 + .../repository/VendingMachineRepository.java | 10 ++++++++++ .../vendingmachine/service/VendingMachineService.java | 5 +++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index d02e861ac..3b8c3450e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,11 +13,11 @@ - [x] 상품명, 가격, 수량 입력 - [x] 대괄호로 묶어 세미콜론으로 구분했는지 검증 - [x] 상품 저장 -- [ ] 투입 금액 설정 +- [x] 투입 금액 설정 - [x] 투입 금액 입력 요청 메시지 출력 - [x] 투입 금액 입력 - [x] 숫자인지 검증 - - [ ] 투입 금액 저장 + - [x] 투입 금액 저장 - [ ] 상품 구매 - [ ] 구매할 상품명 입력 요청 메시지 출력 - [ ] 구매할 상품명 입력 @@ -61,6 +61,8 @@ - findCoins() - saveProducts() - findProducts() + - saveUserMoney() + - findUserMoney() - RandomCoinGenerator - generate() diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index e44c59b4d..75ea369ec 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -30,6 +30,7 @@ public void start() { private void makeUserMoney() { outputView.printUserMoneyRequest(); final UserMoney userMoney = inputManager.readUserMoney(); + vendingMachineService.saveUserMoney(userMoney); } private void makeProduct() { diff --git a/src/main/java/vendingmachine/repository/VendingMachineRepository.java b/src/main/java/vendingmachine/repository/VendingMachineRepository.java index 9178724e7..4463e77be 100644 --- a/src/main/java/vendingmachine/repository/VendingMachineRepository.java +++ b/src/main/java/vendingmachine/repository/VendingMachineRepository.java @@ -2,11 +2,13 @@ import vendingmachine.domain.Coins; import vendingmachine.domain.Products; +import vendingmachine.domain.UserMoney; public class VendingMachineRepository { private Coins coins; private Products products; + private UserMoney userMoney; public Coins saveCoins(final Coins coins) { this.coins = coins; @@ -24,4 +26,12 @@ public void saveProducts(final Products products) { public Products findProducts() { return this.products; } + + public void saveUserMoney(final UserMoney userMoney) { + this.userMoney = userMoney; + } + + public UserMoney findUserMoney() { + return this.userMoney; + } } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index 8e0974960..5b33e7f86 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -3,6 +3,7 @@ import vendingmachine.domain.Coins; import vendingmachine.domain.OwningMoney; import vendingmachine.domain.Products; +import vendingmachine.domain.UserMoney; import vendingmachine.repository.VendingMachineRepository; import vendingmachine.utils.RandomCoinGenerator; @@ -24,4 +25,8 @@ public Coins makeCoins(final OwningMoney owningMoney) { public void saveProducts(final Products products) { vendingMachineRepository.saveProducts(products); } + + public void saveUserMoney(final UserMoney userMoney) { + vendingMachineRepository.saveUserMoney(userMoney); + } } From 69e88d7f61c6d6471547ac377c799ee783b3fd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:25:30 +0900 Subject: [PATCH 16/24] =?UTF-8?q?feat:=20=EA=B5=AC=EB=A7=A4=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EC=9A=94=EC=B2=AD=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 15 +++++++++++++-- .../constant/VendingMachineMessage.java | 4 +++- src/main/java/vendingmachine/io/OutputView.java | 6 ++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 3b8c3450e..a376b0109 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,8 +19,8 @@ - [x] 숫자인지 검증 - [x] 투입 금액 저장 - [ ] 상품 구매 - - [ ] 구매할 상품명 입력 요청 메시지 출력 - - [ ] 구매할 상품명 입력 + - [x] 구매할 상품명 입력 요청 메시지 출력 + - [x] 구매할 상품명 입력 - [ ] 상품 구매 - [ ] 금액 차감 - [ ] 차감된 투입 금액 출력 @@ -38,11 +38,13 @@ - printCoins() - printProductRequest() - printUserMoneyRequest() + - printBuyProductRequest() - InputView - readOwningMoney() - readProducts() - readUserMoney() + - readBuyProduct() - InputManager - readOwningMoney() @@ -55,6 +57,10 @@ - VendingMachineService - makeCoins + - saveProducts() + - saveUserMoney() + - findRemainingUserMoney() + - purchaseProduct() - VendingMachineRepository - saveCoins() @@ -80,6 +86,11 @@ - Products +- UserMoney + - getAmount() + +- BuyProduct + ## 열거형 목록 - Coin - VendingMachineMessage diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java index 44441bcce..f3910141c 100644 --- a/src/main/java/vendingmachine/constant/VendingMachineMessage.java +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -5,7 +5,9 @@ public enum VendingMachineMessage { OWNING_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."), OWNING_COINS("자판기가 보유한 동전"), PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."), - USER_MONEY_REQUEST("투입 금액을 입력해 주세요."); + USER_MONEY_REQUEST("투입 금액을 입력해 주세요."), + REMAINING_MONEY("투입 금액: %d원"), + BUY_PRODUCT_REQUEST("구매할 상품명을 입력해 주세요."); private final String message; diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java index 425e72176..7385d0635 100644 --- a/src/main/java/vendingmachine/io/OutputView.java +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -2,6 +2,7 @@ import vendingmachine.constant.VendingMachineMessage; import vendingmachine.domain.Coins; +import vendingmachine.domain.UserMoney; public class OutputView { @@ -21,4 +22,9 @@ public void printProductRequest() { public void printUserMoneyRequest() { System.out.println(VendingMachineMessage.USER_MONEY_REQUEST.getMessage()); } + + public void printBuyProductRequest(final UserMoney userMoney) { + System.out.println(String.format(VendingMachineMessage.REMAINING_MONEY.getMessage(), userMoney.getAmount())); + System.out.println(VendingMachineMessage.BUY_PRODUCT_REQUEST.getMessage()); + } } From e0b4d0220e51cb3c5b3a197a1cea1a6ac640c2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:25:57 +0900 Subject: [PATCH 17/24] =?UTF-8?q?feat:=20=EA=B5=AC=EB=A7=A4=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/domain/BuyProduct.java | 10 ++++++++++ src/main/java/vendingmachine/domain/UserMoney.java | 4 ++++ src/main/java/vendingmachine/io/InputManager.java | 9 +++++---- src/main/java/vendingmachine/io/InputView.java | 4 ++++ 4 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 src/main/java/vendingmachine/domain/BuyProduct.java diff --git a/src/main/java/vendingmachine/domain/BuyProduct.java b/src/main/java/vendingmachine/domain/BuyProduct.java new file mode 100644 index 000000000..2ef2afaa9 --- /dev/null +++ b/src/main/java/vendingmachine/domain/BuyProduct.java @@ -0,0 +1,10 @@ +package vendingmachine.domain; + +public class BuyProduct { + + private final String name; + + public BuyProduct(final String name) { + this.name = name; + } +} diff --git a/src/main/java/vendingmachine/domain/UserMoney.java b/src/main/java/vendingmachine/domain/UserMoney.java index 515a69b80..6fc81c105 100644 --- a/src/main/java/vendingmachine/domain/UserMoney.java +++ b/src/main/java/vendingmachine/domain/UserMoney.java @@ -7,4 +7,8 @@ public class UserMoney { public UserMoney(final int amount) { this.amount = amount; } + + public int getAmount() { + return this.amount; + } } diff --git a/src/main/java/vendingmachine/io/InputManager.java b/src/main/java/vendingmachine/io/InputManager.java index d1b46265c..721caeb8b 100644 --- a/src/main/java/vendingmachine/io/InputManager.java +++ b/src/main/java/vendingmachine/io/InputManager.java @@ -1,9 +1,6 @@ package vendingmachine.io; -import vendingmachine.domain.OwningMoney; -import vendingmachine.domain.Product; -import vendingmachine.domain.Products; -import vendingmachine.domain.UserMoney; +import vendingmachine.domain.*; import java.util.Arrays; import java.util.List; @@ -39,6 +36,10 @@ public UserMoney readUserMoney() { return read(() -> new UserMoney(Integer.parseInt(inputView.readUserMoney()))); } + public BuyProduct readBuyProduct() { + return read(() -> new BuyProduct(inputView.readBuyProduct())); + } + private T read(final Supplier supplier) { while (true) { try { diff --git a/src/main/java/vendingmachine/io/InputView.java b/src/main/java/vendingmachine/io/InputView.java index 3493ffbf9..8a514adaa 100644 --- a/src/main/java/vendingmachine/io/InputView.java +++ b/src/main/java/vendingmachine/io/InputView.java @@ -27,4 +27,8 @@ public String readUserMoney() { inputValidator.validateNumeric(input); return input; } + + public String readBuyProduct() { + return Console.readLine(); + } } From 6f27cb0f27632bf9d81abae6243ca9aeb8f75895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:42:43 +0900 Subject: [PATCH 18/24] =?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 --- docs/README.md | 15 +++++++++--- .../vendingmachine/constant/BuyStatus.java | 9 ++++++++ .../vendingmachine/constant/ErrorMessage.java | 4 +++- .../controller/VendingMachineController.java | 19 +++++++++++---- .../vendingmachine/domain/BuyProduct.java | 4 ++++ .../java/vendingmachine/domain/Product.java | 19 +++++++++++++++ .../java/vendingmachine/domain/Products.java | 22 ++++++++++++++++++ .../java/vendingmachine/domain/UserMoney.java | 17 ++++++++++++++ .../service/VendingMachineService.java | 23 +++++++++++++++---- 9 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 src/main/java/vendingmachine/constant/BuyStatus.java diff --git a/docs/README.md b/docs/README.md index a376b0109..fa30c1204 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,9 +21,9 @@ - [ ] 상품 구매 - [x] 구매할 상품명 입력 요청 메시지 출력 - [x] 구매할 상품명 입력 - - [ ] 상품 구매 - - [ ] 금액 차감 - - [ ] 차감된 투입 금액 출력 + - [x] 상품 구매 + - [x] 금액 차감 + - [x] 차감된 투입 금액 출력 - [ ] 남은 금액이 최저 가격보다 적거나, 모든 상품 소진시 잔돈 반환 - [ ] 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환 (잔액 부족시 or 나눠 떨어지지 않을시) - [ ] 잔돈 동전별로 출력 @@ -83,15 +83,24 @@ - Product - getName() + - getPrice() + - hasSameName() + - purchase() - Products + - hasLowerPrice() + - getProduct() - UserMoney - getAmount() + - hasRemainingMoney() + - decrease() - BuyProduct + - getName() ## 열거형 목록 - Coin - VendingMachineMessage - ErrorMessage +- BuyStatus diff --git a/src/main/java/vendingmachine/constant/BuyStatus.java b/src/main/java/vendingmachine/constant/BuyStatus.java new file mode 100644 index 000000000..5a4c1e4a8 --- /dev/null +++ b/src/main/java/vendingmachine/constant/BuyStatus.java @@ -0,0 +1,9 @@ +package vendingmachine.constant; + +public enum BuyStatus { + CONTINUE, FINISHED; + + public boolean isFinished() { + return this ==FINISHED; + } +} diff --git a/src/main/java/vendingmachine/constant/ErrorMessage.java b/src/main/java/vendingmachine/constant/ErrorMessage.java index 672a65333..821312532 100644 --- a/src/main/java/vendingmachine/constant/ErrorMessage.java +++ b/src/main/java/vendingmachine/constant/ErrorMessage.java @@ -5,7 +5,9 @@ public enum ErrorMessage { INVALID_MONEY("숫자가 단위로 떨어지지 않습니다."), INVALID_AMOUNT("잘못된 Amount 입니다."), INVALID_PRODUCTS_INPUT("잘못된 Product 입력입니다."), - NEGATIVE_NUMBER("음수는 받을 수 없습니다."); + NEGATIVE_NUMBER("음수는 받을 수 없습니다."), + PRODUCT_NOT_EXISTS("존재하지 않는 상품입니다."), + NOT_ENOUGH_MONEY("잔액이 충분하지 않습니다."); private static final String ERROR_PREFIX = "[ERROR] "; private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 75ea369ec..066d6ad26 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -1,9 +1,7 @@ package vendingmachine.controller; -import vendingmachine.domain.Coins; -import vendingmachine.domain.OwningMoney; -import vendingmachine.domain.Products; -import vendingmachine.domain.UserMoney; +import vendingmachine.constant.BuyStatus; +import vendingmachine.domain.*; import vendingmachine.io.InputManager; import vendingmachine.io.OutputView; import vendingmachine.service.VendingMachineService; @@ -25,6 +23,19 @@ public void start() { makeOwningMoney(); makeProduct(); makeUserMoney(); + buyProducts(); + } + + private void buyProducts() { + while (true) { + final UserMoney userMoney = vendingMachineService.findRemainingUserMoney(); + outputView.printBuyProductRequest(userMoney); + final BuyProduct buyProduct = inputManager.readBuyProduct(); + final BuyStatus buyStatus = vendingMachineService.purchaseProduct(buyProduct); + if (buyStatus.isFinished()) { + break; + } + } } private void makeUserMoney() { diff --git a/src/main/java/vendingmachine/domain/BuyProduct.java b/src/main/java/vendingmachine/domain/BuyProduct.java index 2ef2afaa9..791cc5b5f 100644 --- a/src/main/java/vendingmachine/domain/BuyProduct.java +++ b/src/main/java/vendingmachine/domain/BuyProduct.java @@ -7,4 +7,8 @@ public class BuyProduct { public BuyProduct(final String name) { this.name = name; } + + public String getName() { + return this.name; + } } diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index 9c5a4c774..ec948cce1 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -24,4 +24,23 @@ private void validateNumbers(final Integer price, final Integer amount) { public String getName() { return this.name; } + + public Integer getPrice() { + return this.price; + } + + public boolean hasSameName(final BuyProduct buyProduct) { + return this.name.equals(buyProduct.getName()); + } + + public void purchase() { + validateAmount(); + this.amount--; + } + + private void validateAmount() { + if (this.amount <= 0) { + throw new IllegalStateException(ErrorMessage.PRODUCT_NOT_EXISTS.getMessage()); + } + } } diff --git a/src/main/java/vendingmachine/domain/Products.java b/src/main/java/vendingmachine/domain/Products.java index e8798733b..27bf55326 100644 --- a/src/main/java/vendingmachine/domain/Products.java +++ b/src/main/java/vendingmachine/domain/Products.java @@ -23,4 +23,26 @@ private void validateUniqueName(final List products) { private boolean isUnique(final List products) { return products.stream().map(Product::getName).distinct().count() != products.size(); } + + public Product getProduct(final BuyProduct buyProduct) { + validateProduct(buyProduct); + return products.stream() + .filter(product -> product.hasSameName(buyProduct)) + .findFirst() + .orElseThrow(() -> new IllegalStateException(ErrorMessage.PRODUCT_NOT_EXISTS.getMessage())); + } + + private void validateProduct(final BuyProduct buyProduct) { + if (hasNoMatchingProduct(buyProduct)) { + throw new IllegalArgumentException(ErrorMessage.PRODUCT_NOT_EXISTS.getMessage()); + } + } + + private boolean hasNoMatchingProduct(final BuyProduct buyProduct) { + return this.products.stream().map(Product::getName).noneMatch(name -> name.equals(buyProduct.getName())); + } + + public boolean hasLowerPrice(final Integer amount) { + return this.products.stream().map(Product::getPrice).anyMatch(price -> price < amount); + } } diff --git a/src/main/java/vendingmachine/domain/UserMoney.java b/src/main/java/vendingmachine/domain/UserMoney.java index 6fc81c105..6e411e9a0 100644 --- a/src/main/java/vendingmachine/domain/UserMoney.java +++ b/src/main/java/vendingmachine/domain/UserMoney.java @@ -1,5 +1,7 @@ package vendingmachine.domain; +import vendingmachine.constant.ErrorMessage; + public class UserMoney { private Integer amount; @@ -11,4 +13,19 @@ public UserMoney(final int amount) { public int getAmount() { return this.amount; } + + public boolean hasRemainingMoney(final Products products) { + return products.hasLowerPrice(this.amount); + } + + public void decrease(final Product product) { + validateMoney(product); + this.amount -= product.getPrice(); + } + + private void validateMoney(final Product product) { + if (this.amount < product.getPrice()) { + throw new IllegalStateException(ErrorMessage.NOT_ENOUGH_MONEY.getMessage()); + } + } } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index 5b33e7f86..72618dc59 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -1,9 +1,7 @@ package vendingmachine.service; -import vendingmachine.domain.Coins; -import vendingmachine.domain.OwningMoney; -import vendingmachine.domain.Products; -import vendingmachine.domain.UserMoney; +import vendingmachine.constant.BuyStatus; +import vendingmachine.domain.*; import vendingmachine.repository.VendingMachineRepository; import vendingmachine.utils.RandomCoinGenerator; @@ -29,4 +27,21 @@ public void saveProducts(final Products products) { public void saveUserMoney(final UserMoney userMoney) { vendingMachineRepository.saveUserMoney(userMoney); } + + public UserMoney findRemainingUserMoney() { + return vendingMachineRepository.findUserMoney(); + } + + public BuyStatus purchaseProduct(final BuyProduct buyProduct) { + final Products products = vendingMachineRepository.findProducts(); + final Product product = products.getProduct(buyProduct); + + final UserMoney userMoney = vendingMachineRepository.findUserMoney(); + if (userMoney.hasRemainingMoney(products)) { + userMoney.decrease(product); + product.purchase(); + return BuyStatus.CONTINUE; + } + return BuyStatus.FINISHED; + } } From e16d67f075d2a821324e6d162180675b785197d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 21:46:16 +0900 Subject: [PATCH 19/24] =?UTF-8?q?feat:=20=EC=9E=94=EC=97=AC=20=EC=A0=9C?= =?UTF-8?q?=ED=92=88=20=EC=A1=B4=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A7=81=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/domain/Product.java | 4 ++++ src/main/java/vendingmachine/domain/Products.java | 5 +++++ .../java/vendingmachine/service/VendingMachineService.java | 6 +++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index ec948cce1..9d446143c 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -43,4 +43,8 @@ private void validateAmount() { throw new IllegalStateException(ErrorMessage.PRODUCT_NOT_EXISTS.getMessage()); } } + + public Integer getAmount() { + return this.amount; + } } diff --git a/src/main/java/vendingmachine/domain/Products.java b/src/main/java/vendingmachine/domain/Products.java index 27bf55326..2b8ea9a51 100644 --- a/src/main/java/vendingmachine/domain/Products.java +++ b/src/main/java/vendingmachine/domain/Products.java @@ -45,4 +45,9 @@ private boolean hasNoMatchingProduct(final BuyProduct buyProduct) { public boolean hasLowerPrice(final Integer amount) { return this.products.stream().map(Product::getPrice).anyMatch(price -> price < amount); } + + public boolean hasProduct() { + return this.products.stream() + .anyMatch(product -> product.getAmount() > 0); + } } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index 72618dc59..391cfc863 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -37,11 +37,15 @@ public BuyStatus purchaseProduct(final BuyProduct buyProduct) { final Product product = products.getProduct(buyProduct); final UserMoney userMoney = vendingMachineRepository.findUserMoney(); - if (userMoney.hasRemainingMoney(products)) { + if (isPurchasable(userMoney, products)) { userMoney.decrease(product); product.purchase(); return BuyStatus.CONTINUE; } return BuyStatus.FINISHED; } + + private boolean isPurchasable(final UserMoney userMoney, final Products products) { + return userMoney.hasRemainingMoney(products) && products.hasProduct(); + } } From 5cb4fda06b24d4c3401cc27f70f345cb466e5f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 22:19:22 +0900 Subject: [PATCH 20/24] =?UTF-8?q?feat:=20=EC=9E=94=EB=8F=88=20=EC=BD=94?= =?UTF-8?q?=EC=9D=B8=20=EB=B0=98=ED=99=98=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 9 ++++---- .../constant/VendingMachineMessage.java | 3 ++- .../controller/VendingMachineController.java | 10 ++++++++- .../java/vendingmachine/domain/Coins.java | 16 ++++++++++++++ .../vendingmachine/domain/OwningMoney.java | 2 +- .../java/vendingmachine/domain/Product.java | 5 +++-- .../java/vendingmachine/domain/Products.java | 9 ++------ .../java/vendingmachine/domain/UserMoney.java | 4 ---- .../java/vendingmachine/io/OutputView.java | 11 +++++++++- .../service/VendingMachineService.java | 21 ++++++++++++------- 10 files changed, 62 insertions(+), 28 deletions(-) diff --git a/docs/README.md b/docs/README.md index fa30c1204..1191a70d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,15 +18,15 @@ - [x] 투입 금액 입력 - [x] 숫자인지 검증 - [x] 투입 금액 저장 -- [ ] 상품 구매 +- [x] 상품 구매 - [x] 구매할 상품명 입력 요청 메시지 출력 - [x] 구매할 상품명 입력 - [x] 상품 구매 - [x] 금액 차감 - [x] 차감된 투입 금액 출력 -- [ ] 남은 금액이 최저 가격보다 적거나, 모든 상품 소진시 잔돈 반환 - - [ ] 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환 (잔액 부족시 or 나눠 떨어지지 않을시) - - [ ] 잔돈 동전별로 출력 +- [x] 남은 금액이 최저 가격보다 적거나, 모든 상품 소진시 잔돈 반환 + - [x] 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환 (잔액 부족시 or 나눠 떨어지지 않을시) + - [x] 잔돈 동전별로 출력 ## 구현 클래스 목록 @@ -39,6 +39,7 @@ - printProductRequest() - printUserMoneyRequest() - printBuyProductRequest() + - printRemainingMoney() - InputView - readOwningMoney() diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java index f3910141c..c98a0dd8c 100644 --- a/src/main/java/vendingmachine/constant/VendingMachineMessage.java +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -7,7 +7,8 @@ public enum VendingMachineMessage { PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."), USER_MONEY_REQUEST("투입 금액을 입력해 주세요."), REMAINING_MONEY("투입 금액: %d원"), - BUY_PRODUCT_REQUEST("구매할 상품명을 입력해 주세요."); + BUY_PRODUCT_REQUEST("구매할 상품명을 입력해 주세요."), + CHANGE_MONEY("잔돈"); private final String message; diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 066d6ad26..71dae2c99 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -24,6 +24,14 @@ public void start() { makeProduct(); makeUserMoney(); buyProducts(); + changeCoins(); + } + + private void changeCoins() { + final UserMoney userMoney = vendingMachineService.findRemainingUserMoney(); + outputView.printRemainingMoney(userMoney); + final Coins coins = vendingMachineService.changeMoney(userMoney); + outputView.printChangeMoney(coins); } private void buyProducts() { @@ -31,7 +39,7 @@ private void buyProducts() { final UserMoney userMoney = vendingMachineService.findRemainingUserMoney(); outputView.printBuyProductRequest(userMoney); final BuyProduct buyProduct = inputManager.readBuyProduct(); - final BuyStatus buyStatus = vendingMachineService.purchaseProduct(buyProduct); + final BuyStatus buyStatus = vendingMachineService.purchaseProduct(buyProduct, userMoney); if (buyStatus.isFinished()) { break; } diff --git a/src/main/java/vendingmachine/domain/Coins.java b/src/main/java/vendingmachine/domain/Coins.java index 4c804d17f..842aef7d9 100644 --- a/src/main/java/vendingmachine/domain/Coins.java +++ b/src/main/java/vendingmachine/domain/Coins.java @@ -28,4 +28,20 @@ public String getCoinMessage() { return String.format(COIN_FORMAT, c.getAmount(), count); }).collect(Collectors.joining()); } + + public Coins calculateCoin(final UserMoney userMoney) { + int userMoneyAmount = userMoney.getAmount(); + final Coins result = new Coins(); + + for (final Coin coin : coins) { + final int coinAmount = coin.getAmount(); + if (coinAmount > userMoneyAmount) { + continue; + } + userMoneyAmount -= coinAmount; + result.addCoin(coin); + } + + return result; + } } diff --git a/src/main/java/vendingmachine/domain/OwningMoney.java b/src/main/java/vendingmachine/domain/OwningMoney.java index 0ff8306d9..8eacc2bfc 100644 --- a/src/main/java/vendingmachine/domain/OwningMoney.java +++ b/src/main/java/vendingmachine/domain/OwningMoney.java @@ -31,6 +31,6 @@ public void minusValue(final int coin) { } public boolean isAvailableCoin(final int coin) { - return this.value > coin; + return this.value >= coin; } } diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index 9d446143c..521621349 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -4,6 +4,7 @@ public class Product { + private static final int NO_AMOUNT = 0; private final String name; private final Integer price; private Integer amount; @@ -44,7 +45,7 @@ private void validateAmount() { } } - public Integer getAmount() { - return this.amount; + public boolean hasAmount() { + return this.amount > NO_AMOUNT; } } diff --git a/src/main/java/vendingmachine/domain/Products.java b/src/main/java/vendingmachine/domain/Products.java index 2b8ea9a51..944e6aaba 100644 --- a/src/main/java/vendingmachine/domain/Products.java +++ b/src/main/java/vendingmachine/domain/Products.java @@ -42,12 +42,7 @@ private boolean hasNoMatchingProduct(final BuyProduct buyProduct) { return this.products.stream().map(Product::getName).noneMatch(name -> name.equals(buyProduct.getName())); } - public boolean hasLowerPrice(final Integer amount) { - return this.products.stream().map(Product::getPrice).anyMatch(price -> price < amount); - } - - public boolean hasProduct() { - return this.products.stream() - .anyMatch(product -> product.getAmount() > 0); + public boolean isPurchasable(final UserMoney userMoney) { + return this.products.stream().anyMatch(product -> product.hasAmount() && product.getPrice() <= userMoney.getAmount()); } } diff --git a/src/main/java/vendingmachine/domain/UserMoney.java b/src/main/java/vendingmachine/domain/UserMoney.java index 6e411e9a0..f404b3e9e 100644 --- a/src/main/java/vendingmachine/domain/UserMoney.java +++ b/src/main/java/vendingmachine/domain/UserMoney.java @@ -14,10 +14,6 @@ public int getAmount() { return this.amount; } - public boolean hasRemainingMoney(final Products products) { - return products.hasLowerPrice(this.amount); - } - public void decrease(final Product product) { validateMoney(product); this.amount -= product.getPrice(); diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java index 7385d0635..b506bc6bb 100644 --- a/src/main/java/vendingmachine/io/OutputView.java +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -24,7 +24,16 @@ public void printUserMoneyRequest() { } public void printBuyProductRequest(final UserMoney userMoney) { - System.out.println(String.format(VendingMachineMessage.REMAINING_MONEY.getMessage(), userMoney.getAmount())); + printRemainingMoney(userMoney); System.out.println(VendingMachineMessage.BUY_PRODUCT_REQUEST.getMessage()); } + + public void printRemainingMoney(final UserMoney userMoney) { + System.out.println(String.format(VendingMachineMessage.REMAINING_MONEY.getMessage(), userMoney.getAmount())); + } + + public void printChangeMoney(final Coins coins) { + System.out.println(VendingMachineMessage.CHANGE_MONEY.getMessage()); + System.out.println(coins.getCoinMessage()); + } } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index 391cfc863..fe97436e4 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -32,20 +32,27 @@ public UserMoney findRemainingUserMoney() { return vendingMachineRepository.findUserMoney(); } - public BuyStatus purchaseProduct(final BuyProduct buyProduct) { + public BuyStatus purchaseProduct(final BuyProduct buyProduct, final UserMoney userMoney) { final Products products = vendingMachineRepository.findProducts(); final Product product = products.getProduct(buyProduct); - final UserMoney userMoney = vendingMachineRepository.findUserMoney(); - if (isPurchasable(userMoney, products)) { - userMoney.decrease(product); - product.purchase(); + if (products.isPurchasable(userMoney)) { + return purchase(userMoney, product, products); + } + return BuyStatus.FINISHED; + } + + private BuyStatus purchase(final UserMoney userMoney, final Product product, final Products products) { + userMoney.decrease(product); + product.purchase(); + if (products.isPurchasable(userMoney)) { return BuyStatus.CONTINUE; } return BuyStatus.FINISHED; } - private boolean isPurchasable(final UserMoney userMoney, final Products products) { - return userMoney.hasRemainingMoney(products) && products.hasProduct(); + public Coins changeMoney(final UserMoney userMoney) { + final Coins coins = vendingMachineRepository.findCoins(); + return coins.calculateCoin(userMoney); } } From 96dc9258cb339e83e4ce49ec064353b259eda895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 25 Sep 2023 22:32:43 +0900 Subject: [PATCH 21/24] =?UTF-8?q?refactor:=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=EA=B0=9C=EC=88=98=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=EB=AA=85=20quantity=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/domain/Coins.java | 5 +++- .../vendingmachine/domain/OwningMoney.java | 3 ++- .../java/vendingmachine/domain/Product.java | 27 ++++++++++--------- .../java/vendingmachine/domain/Products.java | 2 +- .../java/vendingmachine/io/InputManager.java | 17 +++++++++--- .../vendingmachine/io/InputValidator.java | 5 +++- 6 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/main/java/vendingmachine/domain/Coins.java b/src/main/java/vendingmachine/domain/Coins.java index 842aef7d9..7514cd764 100644 --- a/src/main/java/vendingmachine/domain/Coins.java +++ b/src/main/java/vendingmachine/domain/Coins.java @@ -31,6 +31,10 @@ public String getCoinMessage() { public Coins calculateCoin(final UserMoney userMoney) { int userMoneyAmount = userMoney.getAmount(); + return getCalculateResult(userMoneyAmount); + } + + private Coins getCalculateResult(int userMoneyAmount) { final Coins result = new Coins(); for (final Coin coin : coins) { @@ -41,7 +45,6 @@ public Coins calculateCoin(final UserMoney userMoney) { userMoneyAmount -= coinAmount; result.addCoin(coin); } - return result; } } diff --git a/src/main/java/vendingmachine/domain/OwningMoney.java b/src/main/java/vendingmachine/domain/OwningMoney.java index 8eacc2bfc..91ccdb87a 100644 --- a/src/main/java/vendingmachine/domain/OwningMoney.java +++ b/src/main/java/vendingmachine/domain/OwningMoney.java @@ -5,6 +5,7 @@ public class OwningMoney { private static final int MONEY_UNIT = 10; + private static final int NO_REMAINING_MONEY = 0; private Integer value; public OwningMoney(final int value) { @@ -23,7 +24,7 @@ public int getValue() { } public boolean hasMoney() { - return this.value != 0; + return this.value != NO_REMAINING_MONEY; } public void minusValue(final int coin) { diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index 521621349..36dee3415 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -4,20 +4,21 @@ public class Product { - private static final int NO_AMOUNT = 0; + private static final int NO_QUANTITY = 0; + private static final int ZERO_PRICE = 0; private final String name; private final Integer price; - private Integer amount; + private Integer quantity; - public Product(final String name, final Integer price, final Integer amount) { - validateNumbers(price, amount); + public Product(final String name, final Integer price, final Integer quantity) { + validateNumbers(price, quantity); this.name = name; this.price = price; - this.amount = amount; + this.quantity = quantity; } - private void validateNumbers(final Integer price, final Integer amount) { - if (price <= 0 || amount <= 0) { + private void validateNumbers(final Integer price, final Integer quantity) { + if (price <= ZERO_PRICE || quantity <= NO_QUANTITY) { throw new IllegalArgumentException(ErrorMessage.NEGATIVE_NUMBER.getMessage()); } } @@ -35,17 +36,17 @@ public boolean hasSameName(final BuyProduct buyProduct) { } public void purchase() { - validateAmount(); - this.amount--; + validateQuantity(); + this.quantity--; } - private void validateAmount() { - if (this.amount <= 0) { + private void validateQuantity() { + if (this.quantity <= NO_QUANTITY) { throw new IllegalStateException(ErrorMessage.PRODUCT_NOT_EXISTS.getMessage()); } } - public boolean hasAmount() { - return this.amount > NO_AMOUNT; + public boolean hasQuantity() { + return this.quantity > NO_QUANTITY; } } diff --git a/src/main/java/vendingmachine/domain/Products.java b/src/main/java/vendingmachine/domain/Products.java index 944e6aaba..a1b7084b8 100644 --- a/src/main/java/vendingmachine/domain/Products.java +++ b/src/main/java/vendingmachine/domain/Products.java @@ -43,6 +43,6 @@ private boolean hasNoMatchingProduct(final BuyProduct buyProduct) { } public boolean isPurchasable(final UserMoney userMoney) { - return this.products.stream().anyMatch(product -> product.hasAmount() && product.getPrice() <= userMoney.getAmount()); + return this.products.stream().anyMatch(product -> product.hasQuantity() && product.getPrice() <= userMoney.getAmount()); } } diff --git a/src/main/java/vendingmachine/io/InputManager.java b/src/main/java/vendingmachine/io/InputManager.java index 721caeb8b..8b9845d7d 100644 --- a/src/main/java/vendingmachine/io/InputManager.java +++ b/src/main/java/vendingmachine/io/InputManager.java @@ -9,6 +9,12 @@ public class InputManager { + private static final String PRODUCT_DELIMITER = ";"; + private static final String FIELD_DELIMITER = ","; + private static final int DELIMITER_INDEX = 1; + private static final int NAME_INDEX = 0; + private static final int PRICE_INDEX = 1; + private static final int QUANTITY_INDEX = 2; private final InputView inputView; public InputManager() { @@ -22,11 +28,14 @@ public OwningMoney readOwningMoney() { public Products readProducts() { return read(() -> { final String input = inputView.readProducts(); - final List products = Arrays.stream(input.split(";")) - .map(i -> i.substring(1, i.length() - 1)) + final List products = Arrays.stream(input.split(PRODUCT_DELIMITER)) + .map(i -> i.substring(DELIMITER_INDEX, i.length() - DELIMITER_INDEX)) .map(s -> { - final String[] strings = s.split(","); - return new Product(strings[0], Integer.parseInt(strings[1]), Integer.parseInt(strings[2])); + final String[] strings = s.split(FIELD_DELIMITER); + return new Product( + strings[NAME_INDEX], + Integer.parseInt(strings[PRICE_INDEX]), + Integer.parseInt(strings[QUANTITY_INDEX])); }).collect(Collectors.toList()); return new Products(products); }); diff --git a/src/main/java/vendingmachine/io/InputValidator.java b/src/main/java/vendingmachine/io/InputValidator.java index 322f9a563..d961daf2f 100644 --- a/src/main/java/vendingmachine/io/InputValidator.java +++ b/src/main/java/vendingmachine/io/InputValidator.java @@ -6,6 +6,9 @@ public class InputValidator { private static final Character MIN_NUMBER_STANDARD = '0'; private static final Character MAX_NUMBER_STANDARD = '9'; + private static final String START_UNIT = "["; + private static final String DELIMITER = ","; + private static final String END_UNIT = "]"; public void validateNumeric(final String input) { if (isNotNumeric(input)) { @@ -24,6 +27,6 @@ public void validateProducts(final String input) { } private boolean isInvalidProductsInput(final String input) { - return !input.startsWith("[") || !input.endsWith("]") || !input.contains(","); + return !input.startsWith(START_UNIT) || !input.endsWith(END_UNIT) || !input.contains(DELIMITER); } } From c4588321b0a82cc132664c710d3902edff360112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Tue, 26 Sep 2023 00:01:55 +0900 Subject: [PATCH 22/24] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../java/vendingmachine/domain/Coins.java | 4 +- .../vendingmachine/domain/OwningMoney.java | 12 +- .../java/vendingmachine/domain/Products.java | 17 +++ .../java/vendingmachine/domain/UserMoney.java | 14 ++- .../service/VendingMachineService.java | 20 +--- .../utils/RandomCoinGenerator.java | 8 +- .../java/vendingmachine/domain/CoinsTest.java | 30 +++++ .../domain/OwningMoneyTest.java | 26 +++++ .../vendingmachine/domain/ProductTest.java | 33 ++++++ .../vendingmachine/domain/ProductsTest.java | 104 ++++++++++++++++++ .../vendingmachine/domain/UserMoneyTest.java | 24 ++++ .../vendingmachine/io/InputValidatorTest.java | 26 +++++ 12 files changed, 291 insertions(+), 27 deletions(-) create mode 100644 src/test/java/vendingmachine/domain/CoinsTest.java create mode 100644 src/test/java/vendingmachine/domain/OwningMoneyTest.java create mode 100644 src/test/java/vendingmachine/domain/ProductTest.java create mode 100644 src/test/java/vendingmachine/domain/ProductsTest.java create mode 100644 src/test/java/vendingmachine/domain/UserMoneyTest.java create mode 100644 src/test/java/vendingmachine/io/InputValidatorTest.java diff --git a/src/main/java/vendingmachine/domain/Coins.java b/src/main/java/vendingmachine/domain/Coins.java index 7514cd764..b5558f2da 100644 --- a/src/main/java/vendingmachine/domain/Coins.java +++ b/src/main/java/vendingmachine/domain/Coins.java @@ -24,7 +24,7 @@ public void addCoin(final Coin coin) { public String getCoinMessage() { return Arrays.stream(Coin.values()) .map(c -> { - final long count = coins.stream().filter(coin -> c == coin).count(); + final long count = this.coins.stream().filter(coin -> c == coin).count(); return String.format(COIN_FORMAT, c.getAmount(), count); }).collect(Collectors.joining()); } @@ -37,7 +37,7 @@ public Coins calculateCoin(final UserMoney userMoney) { private Coins getCalculateResult(int userMoneyAmount) { final Coins result = new Coins(); - for (final Coin coin : coins) { + for (final Coin coin : this.coins) { final int coinAmount = coin.getAmount(); if (coinAmount > userMoneyAmount) { continue; diff --git a/src/main/java/vendingmachine/domain/OwningMoney.java b/src/main/java/vendingmachine/domain/OwningMoney.java index 91ccdb87a..dd7d410ae 100644 --- a/src/main/java/vendingmachine/domain/OwningMoney.java +++ b/src/main/java/vendingmachine/domain/OwningMoney.java @@ -1,5 +1,6 @@ package vendingmachine.domain; +import vendingmachine.constant.Coin; import vendingmachine.constant.ErrorMessage; public class OwningMoney { @@ -9,11 +10,11 @@ public class OwningMoney { private Integer value; public OwningMoney(final int value) { - validateUnit(value); + validateMoneyUnit(value); this.value = value; } - private void validateUnit(final int value) { + private void validateMoneyUnit(final int value) { if (value % MONEY_UNIT != 0) { throw new IllegalArgumentException(ErrorMessage.INVALID_MONEY.getMessage()); } @@ -28,9 +29,16 @@ public boolean hasMoney() { } public void minusValue(final int coin) { + validateCoin(coin); this.value -= coin; } + private void validateCoin(final int coin) { + if (!isAvailableCoin(coin)) { + throw new IllegalStateException(ErrorMessage.INVALID_AMOUNT.getMessage()); + } + } + public boolean isAvailableCoin(final int coin) { return this.value >= coin; } diff --git a/src/main/java/vendingmachine/domain/Products.java b/src/main/java/vendingmachine/domain/Products.java index a1b7084b8..ca91a540d 100644 --- a/src/main/java/vendingmachine/domain/Products.java +++ b/src/main/java/vendingmachine/domain/Products.java @@ -1,5 +1,6 @@ package vendingmachine.domain; +import vendingmachine.constant.BuyStatus; import vendingmachine.constant.ErrorMessage; import java.util.Collections; @@ -45,4 +46,20 @@ private boolean hasNoMatchingProduct(final BuyProduct buyProduct) { public boolean isPurchasable(final UserMoney userMoney) { return this.products.stream().anyMatch(product -> product.hasQuantity() && product.getPrice() <= userMoney.getAmount()); } + + public BuyStatus purchaseProduct(final UserMoney userMoney, final Product product) { + if (isPurchasable(userMoney)) { + return purchase(userMoney, product); + } + return BuyStatus.FINISHED; + } + + private BuyStatus purchase(final UserMoney userMoney, final Product product) { + userMoney.decrease(product); + product.purchase(); + if (isPurchasable(userMoney)) { + return BuyStatus.CONTINUE; + } + return BuyStatus.FINISHED; + } } diff --git a/src/main/java/vendingmachine/domain/UserMoney.java b/src/main/java/vendingmachine/domain/UserMoney.java index f404b3e9e..e54a29aa6 100644 --- a/src/main/java/vendingmachine/domain/UserMoney.java +++ b/src/main/java/vendingmachine/domain/UserMoney.java @@ -4,23 +4,31 @@ public class UserMoney { + private static final int NO_MONEY = 0; private Integer amount; public UserMoney(final int amount) { + validatePositive(amount); this.amount = amount; } + private void validatePositive(final int amount) { + if (amount <= NO_MONEY) { + throw new IllegalArgumentException(ErrorMessage.INVALID_AMOUNT.getMessage()); + } + } + public int getAmount() { return this.amount; } public void decrease(final Product product) { - validateMoney(product); + validateMoney(product.getPrice()); this.amount -= product.getPrice(); } - private void validateMoney(final Product product) { - if (this.amount < product.getPrice()) { + private void validateMoney(final Integer amount) { + if (this.amount < amount) { throw new IllegalStateException(ErrorMessage.NOT_ENOUGH_MONEY.getMessage()); } } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index fe97436e4..61cc01b81 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -8,15 +8,15 @@ public class VendingMachineService { private final VendingMachineRepository vendingMachineRepository; - private final RandomCoinGenerator ranhdomCoinGenerator; + private final RandomCoinGenerator randomCoinGenerator; public VendingMachineService() { this.vendingMachineRepository = new VendingMachineRepository(); - this.ranhdomCoinGenerator = new RandomCoinGenerator(); + this.randomCoinGenerator = new RandomCoinGenerator(); } public Coins makeCoins(final OwningMoney owningMoney) { - final Coins coins = ranhdomCoinGenerator.generate(owningMoney); + final Coins coins = randomCoinGenerator.generate(owningMoney); return vendingMachineRepository.saveCoins(coins); } @@ -36,19 +36,7 @@ public BuyStatus purchaseProduct(final BuyProduct buyProduct, final UserMoney us final Products products = vendingMachineRepository.findProducts(); final Product product = products.getProduct(buyProduct); - if (products.isPurchasable(userMoney)) { - return purchase(userMoney, product, products); - } - return BuyStatus.FINISHED; - } - - private BuyStatus purchase(final UserMoney userMoney, final Product product, final Products products) { - userMoney.decrease(product); - product.purchase(); - if (products.isPurchasable(userMoney)) { - return BuyStatus.CONTINUE; - } - return BuyStatus.FINISHED; + return products.purchaseProduct(userMoney, product); } public Coins changeMoney(final UserMoney userMoney) { diff --git a/src/main/java/vendingmachine/utils/RandomCoinGenerator.java b/src/main/java/vendingmachine/utils/RandomCoinGenerator.java index 4cc6847cd..4e3696567 100644 --- a/src/main/java/vendingmachine/utils/RandomCoinGenerator.java +++ b/src/main/java/vendingmachine/utils/RandomCoinGenerator.java @@ -11,12 +11,11 @@ public class RandomCoinGenerator { public Coins generate(final OwningMoney owningMoney) { final List availableCoins = Coin.getCoinByOwningMoney(owningMoney); - final Coins coins = new Coins(); - addCoins(owningMoney, availableCoins, coins); - return coins; + return addCoins(owningMoney, availableCoins); } - private void addCoins(final OwningMoney owningMoney, final List availableCoins, final Coins coins) { + private Coins addCoins(final OwningMoney owningMoney, final List availableCoins) { + final Coins coins = new Coins(); while (owningMoney.hasMoney()) { final int coin = Randoms.pickNumberInList(availableCoins); if (owningMoney.isAvailableCoin(coin)) { @@ -24,5 +23,6 @@ private void addCoins(final OwningMoney owningMoney, final List availab coins.addCoin(Coin.valueOfAmount(coin)); } } + return coins; } } diff --git a/src/test/java/vendingmachine/domain/CoinsTest.java b/src/test/java/vendingmachine/domain/CoinsTest.java new file mode 100644 index 000000000..b3629ef74 --- /dev/null +++ b/src/test/java/vendingmachine/domain/CoinsTest.java @@ -0,0 +1,30 @@ +package vendingmachine.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import vendingmachine.constant.Coin; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("코인 일급컬렉션에서") +class CoinsTest { + + @Test + @DisplayName("남은 코인 계산 과정에서 가능한 코인이 없으면 모두 0개로 표시한다") + void calculateCoin() { + //given + Coins coins = new Coins(); + coins.addCoin(Coin.COIN_100); + + //when + final Coins result = coins.calculateCoin(new UserMoney(50)); + + //then + System.out.println(result.getCoinMessage()); + assertThat(result.getCoinMessage()).contains( + "500원 - 0개\n" + + "100원 - 0개\n" + + "50원 - 0개\n" + + "10원 - 0개"); + } +} diff --git a/src/test/java/vendingmachine/domain/OwningMoneyTest.java b/src/test/java/vendingmachine/domain/OwningMoneyTest.java new file mode 100644 index 000000000..fe1cbe29d --- /dev/null +++ b/src/test/java/vendingmachine/domain/OwningMoneyTest.java @@ -0,0 +1,26 @@ +package vendingmachine.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("자판기가 가지는 거스름돈 총 합 도메인에서") +class OwningMoneyTest { + + @Test + @DisplayName("최소 단위로 나눠떨어지지 않는 경우 예외를 던진다") + void constructor() { + assertThatThrownBy(() -> new OwningMoney(5)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("") + void minusValue() { + assertThatThrownBy(() -> new OwningMoney(50).minusValue(60)) + .isInstanceOf(IllegalStateException.class); + } +} diff --git a/src/test/java/vendingmachine/domain/ProductTest.java b/src/test/java/vendingmachine/domain/ProductTest.java new file mode 100644 index 000000000..64350f241 --- /dev/null +++ b/src/test/java/vendingmachine/domain/ProductTest.java @@ -0,0 +1,33 @@ +package vendingmachine.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("제품 도메인에서") +class ProductTest { + + @Test + @DisplayName("가격이 음수일 경우 생성시 예외를 던진다") + void constructorWithMinusPrice() { + assertThatThrownBy(() -> new Product("abc", -1, 10)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("가격이 음수일 경우 생성시 예외를 던진다") + void constructorWithMinusQuantity() { + assertThatThrownBy(() -> new Product("abc", 100, -1)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void purchase() { + assertThatThrownBy(() -> { + final Product product = new Product("abc", 100, 1); + product.purchase(); + product.purchase(); + }).isInstanceOf(IllegalStateException.class); + } +} diff --git a/src/test/java/vendingmachine/domain/ProductsTest.java b/src/test/java/vendingmachine/domain/ProductsTest.java new file mode 100644 index 000000000..42c50f31b --- /dev/null +++ b/src/test/java/vendingmachine/domain/ProductsTest.java @@ -0,0 +1,104 @@ +package vendingmachine.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import vendingmachine.constant.BuyStatus; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("제품 일급 컬렉션에서") +class ProductsTest { + + @Test + @DisplayName("같은 이름의 제품 존재시 예외를 던진다") + void constructor() { + assertThatThrownBy(() -> new Products(Arrays.asList(new Product("abc", 20, 20), new Product("abc", 10, 10)))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("원하는 이름의 제품이 존재하지 않으면 예외를 던진다") + void getProduct() { + assertThatThrownBy(() -> new Products(Arrays.asList(new Product("abc", 20, 20), new Product("def", 10, 10))) + .getProduct(new BuyProduct("ghi"))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("가격에 비해 UserMoney의 Amount가 낮은 경우 False를 반환한다") + void isPurchasableWithInvalidMoney() { + //given + final Products products = new Products(Arrays.asList(new Product("abc", 20, 20), new Product("def", 10, 10))); + + //when + final boolean purchasable = products.isPurchasable(new UserMoney(5)); + + //then + assertThat(purchasable).isFalse(); + } + + @Test + @DisplayName("제품의 가격보다 큰 UserMoney의 경우 True를 반환한다") + void isPurchasableWithValidMoney() { + //given + final Products products = new Products(Arrays.asList(new Product("abc", 20, 20), new Product("def", 10, 10))); + + //when + final boolean purchasable = products.isPurchasable(new UserMoney(5)); + + //then + assertThat(purchasable).isFalse(); + } + + @Nested + class PurchaseProduct { + @Test + @DisplayName("제품을 살 때 살 수 있는 제품이 없으면 FINISHED를 반환한다") + void purchaseProductWhenNotPurchasable() { + //given + final Product product = new Product("abc", 2000, 20); + final Products products = new Products(Arrays.asList(product, new Product("def", 1000, 10))); + + //when + final BuyStatus buyStatus = products.purchaseProduct(new UserMoney(100), product); + + //then + assertThat(buyStatus).isEqualTo(BuyStatus.FINISHED); + } + + @Test + @DisplayName("제품을 살 때 살 수 있는 제품이 남아있으면 CONTINUE를 반환한다") + void purchaseProductWhenPurchasable() { + //given + final Product product = new Product("abc", 20, 10); + final Products products = new Products(Arrays.asList(product, new Product("def", 10, 10))); + + //when + final BuyStatus buyStatus = products.purchaseProduct(new UserMoney(1000), product); + + //then + assertThat(buyStatus).isEqualTo(BuyStatus.CONTINUE); + } + + @Test + @DisplayName("제품을 산 후 살 수 있는 제품이 없으면 FINISHED를 반환한다") + void purchaseProductWhenPurchasableAndFinish() { + //given + final Product product1 = new Product("abc", 20, 1); + final Product product2 = new Product("def", 10, 1); + final Products products = new Products(Arrays.asList(product1, product2)); + + //when + final BuyStatus buyStatus1 = products.purchaseProduct(new UserMoney(30), product1); + final BuyStatus buyStatus2 = products.purchaseProduct(new UserMoney(30), product2); + + //then + assertThat(buyStatus1).isEqualTo(BuyStatus.CONTINUE); + assertThat(buyStatus2).isEqualTo(BuyStatus.FINISHED); + } + } +} diff --git a/src/test/java/vendingmachine/domain/UserMoneyTest.java b/src/test/java/vendingmachine/domain/UserMoneyTest.java new file mode 100644 index 000000000..a3aeba885 --- /dev/null +++ b/src/test/java/vendingmachine/domain/UserMoneyTest.java @@ -0,0 +1,24 @@ +package vendingmachine.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("유저 잔액 도메인에서") +class UserMoneyTest { + + @Test + @DisplayName("amount를 음수로 생성시 예외를 던진다") + void constructor() { + assertThatThrownBy(() -> new UserMoney(-100)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("잔액보다 큰 금액의 상품 구매시 예외를 던진다") + void decrease() { + assertThatThrownBy(() -> new UserMoney(10).decrease(new Product("123", 100, 123))) + .isInstanceOf(IllegalStateException.class); + } +} diff --git a/src/test/java/vendingmachine/io/InputValidatorTest.java b/src/test/java/vendingmachine/io/InputValidatorTest.java new file mode 100644 index 000000000..56f6e7330 --- /dev/null +++ b/src/test/java/vendingmachine/io/InputValidatorTest.java @@ -0,0 +1,26 @@ +package vendingmachine.io; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("입력값 검증 클래스에서") +class InputValidatorTest { + + private InputValidator inputValidator = new InputValidator(); + + @Test + @DisplayName("숫자가 아닌 입력이 들어온 경우 예외를 던진다") + void validateNumeric() { + assertThatThrownBy(() -> inputValidator.validateNumeric("123abc")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("입력 형태와 맞지 않는 입력이 들어온 경우 예외를 던진다") + void validateProducts() { + assertThatThrownBy(() -> inputValidator.validateProducts("123abc")) + .isInstanceOf(IllegalArgumentException.class); + } +} From f55277b24945d8fe53f31a77c967459d57188bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Tue, 26 Sep 2023 00:07:54 +0900 Subject: [PATCH 23/24] =?UTF-8?q?refactor:=20=EB=A6=AC=ED=8C=A9=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EB=B0=8F=20=EB=8F=84=EB=A9=94=EC=9D=B8=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 8 ++++---- .../java/vendingmachine/constant/Coin.java | 6 +++--- .../constant/VendingMachineMessage.java | 4 ++-- .../controller/VendingMachineController.java | 19 +++++++++---------- ...ingMoney.java => VendingMachineMoney.java} | 5 ++--- .../java/vendingmachine/io/InputManager.java | 4 ++-- .../java/vendingmachine/io/InputView.java | 2 +- .../java/vendingmachine/io/OutputView.java | 6 +++--- .../service/VendingMachineService.java | 4 ++-- .../utils/RandomCoinGenerator.java | 16 ++++++++-------- ...Test.java => VendingMachineMoneyTest.java} | 8 +++----- 11 files changed, 39 insertions(+), 43 deletions(-) rename src/main/java/vendingmachine/domain/{OwningMoney.java => VendingMachineMoney.java} (90%) rename src/test/java/vendingmachine/domain/{OwningMoneyTest.java => VendingMachineMoneyTest.java} (70%) diff --git a/docs/README.md b/docs/README.md index 1191a70d7..75c82b58d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,7 +34,7 @@ - start() - OutputView - - printOwningMoney() + - printVendingMachineMoney() - printCoins() - printProductRequest() - printUserMoneyRequest() @@ -42,13 +42,13 @@ - printRemainingMoney() - InputView - - readOwningMoney() + - readVendingMachineMoney() - readProducts() - readUserMoney() - readBuyProduct() - InputManager - - readOwningMoney() + - readVendingMachineMoney() - readProducts() - readUserMoney() @@ -74,7 +74,7 @@ - RandomCoinGenerator - generate() -- OwningMoney +- VendingMachineMoney - getValue() - hasMoney() - minusValue() diff --git a/src/main/java/vendingmachine/constant/Coin.java b/src/main/java/vendingmachine/constant/Coin.java index 5bbbce6c7..18b5fc54f 100644 --- a/src/main/java/vendingmachine/constant/Coin.java +++ b/src/main/java/vendingmachine/constant/Coin.java @@ -1,6 +1,6 @@ package vendingmachine.constant; -import vendingmachine.domain.OwningMoney; +import vendingmachine.domain.VendingMachineMoney; import java.util.Arrays; import java.util.List; @@ -18,9 +18,9 @@ public enum Coin { this.amount = amount; } - public static List getCoinByOwningMoney(final OwningMoney owningMoney) { + public static List getCoinByVendingMachineMoney(final VendingMachineMoney vendingMachineMoney) { return Arrays.stream(values()) - .filter(value -> value.amount <= owningMoney.getValue()) + .filter(value -> value.amount <= vendingMachineMoney.getValue()) .map(coin -> coin.amount) .collect(Collectors.toList()); } diff --git a/src/main/java/vendingmachine/constant/VendingMachineMessage.java b/src/main/java/vendingmachine/constant/VendingMachineMessage.java index c98a0dd8c..5b9e1860b 100644 --- a/src/main/java/vendingmachine/constant/VendingMachineMessage.java +++ b/src/main/java/vendingmachine/constant/VendingMachineMessage.java @@ -2,8 +2,8 @@ public enum VendingMachineMessage { - OWNING_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."), - OWNING_COINS("자판기가 보유한 동전"), + VENDING_MACHINE_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."), + VENDING_MACHINE_COINS("자판기가 보유한 동전"), PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."), USER_MONEY_REQUEST("투입 금액을 입력해 주세요."), REMAINING_MONEY("투입 금액: %d원"), diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 71dae2c99..950a3cb9d 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -20,7 +20,7 @@ public VendingMachineController() { public void start() { - makeOwningMoney(); + makeVendingMachineMoney(); makeProduct(); makeUserMoney(); buyProducts(); @@ -35,14 +35,13 @@ private void changeCoins() { } private void buyProducts() { - while (true) { + BuyStatus buyStatus = BuyStatus.CONTINUE; + + while (buyStatus.isFinished()) { final UserMoney userMoney = vendingMachineService.findRemainingUserMoney(); outputView.printBuyProductRequest(userMoney); final BuyProduct buyProduct = inputManager.readBuyProduct(); - final BuyStatus buyStatus = vendingMachineService.purchaseProduct(buyProduct, userMoney); - if (buyStatus.isFinished()) { - break; - } + buyStatus = vendingMachineService.purchaseProduct(buyProduct, userMoney); } } @@ -58,10 +57,10 @@ private void makeProduct() { vendingMachineService.saveProducts(products); } - private void makeOwningMoney() { - outputView.printOwningMoneyRequest(); - final OwningMoney owningMoney = inputManager.readOwningMoney(); - final Coins coins = vendingMachineService.makeCoins(owningMoney); + private void makeVendingMachineMoney() { + outputView.printVendingMachineMoneyRequest(); + final VendingMachineMoney vendingMachineMoney = inputManager.readVendingMachineMoney(); + final Coins coins = vendingMachineService.makeCoins(vendingMachineMoney); outputView.printCoins(coins); } } diff --git a/src/main/java/vendingmachine/domain/OwningMoney.java b/src/main/java/vendingmachine/domain/VendingMachineMoney.java similarity index 90% rename from src/main/java/vendingmachine/domain/OwningMoney.java rename to src/main/java/vendingmachine/domain/VendingMachineMoney.java index dd7d410ae..8e8ea0bdf 100644 --- a/src/main/java/vendingmachine/domain/OwningMoney.java +++ b/src/main/java/vendingmachine/domain/VendingMachineMoney.java @@ -1,15 +1,14 @@ package vendingmachine.domain; -import vendingmachine.constant.Coin; import vendingmachine.constant.ErrorMessage; -public class OwningMoney { +public class VendingMachineMoney { private static final int MONEY_UNIT = 10; private static final int NO_REMAINING_MONEY = 0; private Integer value; - public OwningMoney(final int value) { + public VendingMachineMoney(final int value) { validateMoneyUnit(value); this.value = value; } diff --git a/src/main/java/vendingmachine/io/InputManager.java b/src/main/java/vendingmachine/io/InputManager.java index 8b9845d7d..72c0d9798 100644 --- a/src/main/java/vendingmachine/io/InputManager.java +++ b/src/main/java/vendingmachine/io/InputManager.java @@ -21,8 +21,8 @@ public InputManager() { this.inputView = new InputView(); } - public OwningMoney readOwningMoney() { - return read(() -> new OwningMoney(Integer.parseInt(inputView.readOwningMoney()))); + public VendingMachineMoney readVendingMachineMoney() { + return read(() -> new VendingMachineMoney(Integer.parseInt(inputView.readVendingMachineMoney()))); } public Products readProducts() { diff --git a/src/main/java/vendingmachine/io/InputView.java b/src/main/java/vendingmachine/io/InputView.java index 8a514adaa..36de3cd80 100644 --- a/src/main/java/vendingmachine/io/InputView.java +++ b/src/main/java/vendingmachine/io/InputView.java @@ -10,7 +10,7 @@ public InputView() { this.inputValidator = new InputValidator(); } - public String readOwningMoney() { + public String readVendingMachineMoney() { final String input = Console.readLine(); inputValidator.validateNumeric(input); return input; diff --git a/src/main/java/vendingmachine/io/OutputView.java b/src/main/java/vendingmachine/io/OutputView.java index b506bc6bb..fb21a38dc 100644 --- a/src/main/java/vendingmachine/io/OutputView.java +++ b/src/main/java/vendingmachine/io/OutputView.java @@ -6,12 +6,12 @@ public class OutputView { - public void printOwningMoneyRequest() { - System.out.println(VendingMachineMessage.OWNING_MONEY_REQUEST.getMessage()); + public void printVendingMachineMoneyRequest() { + System.out.println(VendingMachineMessage.VENDING_MACHINE_MONEY_REQUEST.getMessage()); } public void printCoins(final Coins coins) { - System.out.println(VendingMachineMessage.OWNING_COINS.getMessage()); + System.out.println(VendingMachineMessage.VENDING_MACHINE_COINS.getMessage()); System.out.println(coins.getCoinMessage()); } diff --git a/src/main/java/vendingmachine/service/VendingMachineService.java b/src/main/java/vendingmachine/service/VendingMachineService.java index 61cc01b81..49c7a44e8 100644 --- a/src/main/java/vendingmachine/service/VendingMachineService.java +++ b/src/main/java/vendingmachine/service/VendingMachineService.java @@ -15,8 +15,8 @@ public VendingMachineService() { this.randomCoinGenerator = new RandomCoinGenerator(); } - public Coins makeCoins(final OwningMoney owningMoney) { - final Coins coins = randomCoinGenerator.generate(owningMoney); + public Coins makeCoins(final VendingMachineMoney vendingMachineMoney) { + final Coins coins = randomCoinGenerator.generate(vendingMachineMoney); return vendingMachineRepository.saveCoins(coins); } diff --git a/src/main/java/vendingmachine/utils/RandomCoinGenerator.java b/src/main/java/vendingmachine/utils/RandomCoinGenerator.java index 4e3696567..1db9e2c52 100644 --- a/src/main/java/vendingmachine/utils/RandomCoinGenerator.java +++ b/src/main/java/vendingmachine/utils/RandomCoinGenerator.java @@ -3,23 +3,23 @@ import camp.nextstep.edu.missionutils.Randoms; import vendingmachine.constant.Coin; import vendingmachine.domain.Coins; -import vendingmachine.domain.OwningMoney; +import vendingmachine.domain.VendingMachineMoney; import java.util.List; public class RandomCoinGenerator { - public Coins generate(final OwningMoney owningMoney) { - final List availableCoins = Coin.getCoinByOwningMoney(owningMoney); - return addCoins(owningMoney, availableCoins); + public Coins generate(final VendingMachineMoney vendingMachineMoney) { + final List availableCoins = Coin.getCoinByVendingMachineMoney(vendingMachineMoney); + return addCoins(vendingMachineMoney, availableCoins); } - private Coins addCoins(final OwningMoney owningMoney, final List availableCoins) { + private Coins addCoins(final VendingMachineMoney vendingMachineMoney, final List availableCoins) { final Coins coins = new Coins(); - while (owningMoney.hasMoney()) { + while (vendingMachineMoney.hasMoney()) { final int coin = Randoms.pickNumberInList(availableCoins); - if (owningMoney.isAvailableCoin(coin)) { - owningMoney.minusValue(coin); + if (vendingMachineMoney.isAvailableCoin(coin)) { + vendingMachineMoney.minusValue(coin); coins.addCoin(Coin.valueOfAmount(coin)); } } diff --git a/src/test/java/vendingmachine/domain/OwningMoneyTest.java b/src/test/java/vendingmachine/domain/VendingMachineMoneyTest.java similarity index 70% rename from src/test/java/vendingmachine/domain/OwningMoneyTest.java rename to src/test/java/vendingmachine/domain/VendingMachineMoneyTest.java index fe1cbe29d..51ca68695 100644 --- a/src/test/java/vendingmachine/domain/OwningMoneyTest.java +++ b/src/test/java/vendingmachine/domain/VendingMachineMoneyTest.java @@ -1,26 +1,24 @@ package vendingmachine.domain; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; @DisplayName("자판기가 가지는 거스름돈 총 합 도메인에서") -class OwningMoneyTest { +class VendingMachineMoneyTest { @Test @DisplayName("최소 단위로 나눠떨어지지 않는 경우 예외를 던진다") void constructor() { - assertThatThrownBy(() -> new OwningMoney(5)) + assertThatThrownBy(() -> new VendingMachineMoney(5)) .isInstanceOf(IllegalArgumentException.class); } @Test @DisplayName("") void minusValue() { - assertThatThrownBy(() -> new OwningMoney(50).minusValue(60)) + assertThatThrownBy(() -> new VendingMachineMoney(50).minusValue(60)) .isInstanceOf(IllegalStateException.class); } } From 022dec712737434921fae53f3486d1c91d44dc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Tue, 26 Sep 2023 00:13:48 +0900 Subject: [PATCH 24/24] =?UTF-8?q?fix:=20=EC=83=81=ED=83=9C=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/constant/BuyStatus.java | 4 ++-- .../vendingmachine/controller/VendingMachineController.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/vendingmachine/constant/BuyStatus.java b/src/main/java/vendingmachine/constant/BuyStatus.java index 5a4c1e4a8..6fd6e7883 100644 --- a/src/main/java/vendingmachine/constant/BuyStatus.java +++ b/src/main/java/vendingmachine/constant/BuyStatus.java @@ -3,7 +3,7 @@ public enum BuyStatus { CONTINUE, FINISHED; - public boolean isFinished() { - return this ==FINISHED; + public boolean isContinue() { + return this == CONTINUE; } } diff --git a/src/main/java/vendingmachine/controller/VendingMachineController.java b/src/main/java/vendingmachine/controller/VendingMachineController.java index 950a3cb9d..3fc44cbbd 100644 --- a/src/main/java/vendingmachine/controller/VendingMachineController.java +++ b/src/main/java/vendingmachine/controller/VendingMachineController.java @@ -37,7 +37,7 @@ private void changeCoins() { private void buyProducts() { BuyStatus buyStatus = BuyStatus.CONTINUE; - while (buyStatus.isFinished()) { + while (buyStatus.isContinue()) { final UserMoney userMoney = vendingMachineService.findRemainingUserMoney(); outputView.printBuyProductRequest(userMoney); final BuyProduct buyProduct = inputManager.readBuyProduct();