From cbbb052cb44d391fe3200dae1230acca0a9356b9 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:27:44 +0900 Subject: [PATCH 01/44] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B4=88=EC=95=88=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..e28752bf6 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,24 @@ +# 미션 제목 + +## 기능 +- [ ] 입력 받은 금액에 따라 동전을 무작위로 생성한다. +- [ ] 구입한 상품의 수량을 1 감소시킨다. +- [ ] 상품 가격만큼 투입 금액을 감소시킨다. +- [ ] 남은 투입 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. + - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. + - 반환되지 않은 금액은 자판기에 남는다. + +## 입력 +- [ ] 자판기가 보유한 금액을 입력 받는다. + - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. +- [ ] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. +- [ ] 투입 금액을 입력 받는다. +- [ ] 구매할 상품의 상품명을 입력 받는다. + +## 출력 +- [ ] 자판기가 보유한 동전 내역을 출력한다. +- [ ] 남은 투입 금액을 출력한다. +- [ ] 잔돈을 출력한다. + +## 검증 내용 +- [ ] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file From 108910d82464e2418aa865d3f65673fa7f9361f0 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:28:42 +0900 Subject: [PATCH 02/44] =?UTF-8?q?feat(RandomNumberGenerator):=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=20=EC=88=AB=EC=9E=90=20=EC=83=9D=EC=84=B1=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../vendingmachine/RandomNumberGenerator.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/java/vendingmachine/RandomNumberGenerator.java diff --git a/docs/README.md b/docs/README.md index e28752bf6..c6d597047 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,7 @@ # 미션 제목 ## 기능 -- [ ] 입력 받은 금액에 따라 동전을 무작위로 생성한다. +- [x] 입력 받은 금액에 따라 동전을 무작위로 생성한다. - [ ] 구입한 상품의 수량을 1 감소시킨다. - [ ] 상품 가격만큼 투입 금액을 감소시킨다. - [ ] 남은 투입 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. diff --git a/src/main/java/vendingmachine/RandomNumberGenerator.java b/src/main/java/vendingmachine/RandomNumberGenerator.java new file mode 100644 index 000000000..47bd1fd9f --- /dev/null +++ b/src/main/java/vendingmachine/RandomNumberGenerator.java @@ -0,0 +1,15 @@ +package vendingmachine; + +import java.util.List; + +import camp.nextstep.edu.missionutils.Randoms; + +public class RandomNumberGenerator { + + private RandomNumberGenerator() { + } + + public int generate(List numbers) { + return Randoms.pickNumberInList(numbers); + } +} From bc0287e4940bebc3e33feefe35e5265667181cf9 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:31:46 +0900 Subject: [PATCH 03/44] =?UTF-8?q?feat(VendingMachine):=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 1 + src/main/java/vendingmachine/VendingMachine.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/main/java/vendingmachine/VendingMachine.java diff --git a/docs/README.md b/docs/README.md index c6d597047..d5d253e29 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,6 +2,7 @@ ## 기능 - [x] 입력 받은 금액에 따라 동전을 무작위로 생성한다. +- [x] 입력 받은 상품 하나를 추가한다. - [ ] 구입한 상품의 수량을 1 감소시킨다. - [ ] 상품 가격만큼 투입 금액을 감소시킨다. - [ ] 남은 투입 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java new file mode 100644 index 000000000..ec5a950a6 --- /dev/null +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -0,0 +1,16 @@ +package vendingmachine; + +import java.util.List; + +public class VendingMachine { + + private List products; + + public VendingMachine(List products) { + this.products = products; + } + + public void addProduct(Product product) { + products.add(product); + } +} From fcd832cd0ede2afcf868515e83f97534e852a007 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:34:08 +0900 Subject: [PATCH 04/44] =?UTF-8?q?feat(Product):=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=88=98=EB=9F=89=201=EA=B0=9C=20=EA=B0=90=EC=86=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/Product.java | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/main/java/vendingmachine/Product.java diff --git a/docs/README.md b/docs/README.md index d5d253e29..2b394d165 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@ ## 기능 - [x] 입력 받은 금액에 따라 동전을 무작위로 생성한다. - [x] 입력 받은 상품 하나를 추가한다. -- [ ] 구입한 상품의 수량을 1 감소시킨다. +- [x] 구입한 상품의 수량을 1 감소시킨다. - [ ] 상품 가격만큼 투입 금액을 감소시킨다. - [ ] 남은 투입 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/Product.java new file mode 100644 index 000000000..327396713 --- /dev/null +++ b/src/main/java/vendingmachine/Product.java @@ -0,0 +1,20 @@ +package vendingmachine; + +import java.math.BigDecimal; + +public class Product { + + private String name; + private BigDecimal price; + private int quantity; + + public Product(String name, BigDecimal price, int quantity) { + this.name = name; + this.price = price; + this.quantity = quantity; + } + + public void decreaseQuantity() { + this.quantity--; + } +} From aaa4f319d63a81cb09da65bb7560cfe00e7253a3 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:51:37 +0900 Subject: [PATCH 05/44] =?UTF-8?q?feat(InputAmount):=20=ED=88=AC=EC=9E=85?= =?UTF-8?q?=20=EA=B8=88=EC=95=A1=20=EC=83=81=ED=92=88=20=EA=B0=80=EA=B2=A9?= =?UTF-8?q?=EB=A7=8C=ED=81=BC=20=EA=B0=90=EC=86=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 ++-- src/main/java/vendingmachine/InputAmount.java | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 src/main/java/vendingmachine/InputAmount.java diff --git a/docs/README.md b/docs/README.md index 2b394d165..cd1bf241f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,15 +4,15 @@ - [x] 입력 받은 금액에 따라 동전을 무작위로 생성한다. - [x] 입력 받은 상품 하나를 추가한다. - [x] 구입한 상품의 수량을 1 감소시킨다. -- [ ] 상품 가격만큼 투입 금액을 감소시킨다. +- [x] 상품 가격만큼 투입 금액을 감소시킨다. - [ ] 남은 투입 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. - 반환되지 않은 금액은 자판기에 남는다. ## 입력 - [ ] 자판기가 보유한 금액을 입력 받는다. +- [ ] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. -- [ ] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. - [ ] 투입 금액을 입력 받는다. - [ ] 구매할 상품의 상품명을 입력 받는다. diff --git a/src/main/java/vendingmachine/InputAmount.java b/src/main/java/vendingmachine/InputAmount.java new file mode 100644 index 000000000..2c8df5ade --- /dev/null +++ b/src/main/java/vendingmachine/InputAmount.java @@ -0,0 +1,14 @@ +package vendingmachine; + +public class InputAmount { + + private int amount; + + private InputAmount(int amount) { + this.amount = amount; + } + + public void decrease(int amount) { + this.amount -= amount; + } +} From e7fc6e77be89278fc815c5e4606fb9481eb65bfd Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:52:39 +0900 Subject: [PATCH 06/44] =?UTF-8?q?feat(InputView):=20=EC=9E=90=ED=8C=90?= =?UTF-8?q?=EA=B8=B0=EA=B0=80=20=EB=B3=B4=EC=9C=A0=ED=95=98=EA=B3=A0=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../java/vendingmachine/view/InputView.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/main/java/vendingmachine/view/InputView.java diff --git a/docs/README.md b/docs/README.md index cd1bf241f..0e53116aa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,7 +10,7 @@ - 반환되지 않은 금액은 자판기에 남는다. ## 입력 -- [ ] 자판기가 보유한 금액을 입력 받는다. +- [x] 자판기가 보유한 금액을 입력 받는다. - [ ] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. - [ ] 투입 금액을 입력 받는다. diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java new file mode 100644 index 000000000..18734d159 --- /dev/null +++ b/src/main/java/vendingmachine/view/InputView.java @@ -0,0 +1,19 @@ +package vendingmachine.view; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + + private InputView() { + } + + public static int readVendingMachineAmount() { + System.out.println("자판기가 보유하고 있는 금액을 입력해 주세요."); + String input = Console.readLine(); + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); + } + } +} From 2538f2b1b8eb6ed94674d5adb41a9439f7e2ea48 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:53:07 +0900 Subject: [PATCH 07/44] =?UTF-8?q?feat(InputView):=20=EC=9E=90=ED=8C=90?= =?UTF-8?q?=EA=B8=B0=EC=97=90=20=EC=B6=94=EA=B0=80=ED=95=A0=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/view/InputView.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 0e53116aa..70d70bd3d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,7 +11,7 @@ ## 입력 - [x] 자판기가 보유한 금액을 입력 받는다. -- [ ] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. +- [x] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. - [ ] 투입 금액을 입력 받는다. - [ ] 구매할 상품의 상품명을 입력 받는다. diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 18734d159..00427111e 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -1,5 +1,9 @@ package vendingmachine.view; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + import camp.nextstep.edu.missionutils.Console; public class InputView { @@ -16,4 +20,10 @@ public static int readVendingMachineAmount() { throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); } } + + public static List readProducts() { + System.out.println("상품명과 가격, 수량을 입력해 주세요."); + String input = Console.readLine(); + return Arrays.stream(input.split(";")).collect(Collectors.toList()); + } } From fa3769c40814b0756116ea7a792285502792bb45 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:53:59 +0900 Subject: [PATCH 08/44] =?UTF-8?q?feat(InputView):=20=ED=88=AC=EC=9E=85=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/view/InputView.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 70d70bd3d..b0fac302d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ - [x] 자판기가 보유한 금액을 입력 받는다. - [x] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. -- [ ] 투입 금액을 입력 받는다. +- [x] 투입 금액을 입력 받는다. - [ ] 구매할 상품의 상품명을 입력 받는다. ## 출력 diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 00427111e..b1e52103f 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -26,4 +26,14 @@ public static List readProducts() { String input = Console.readLine(); return Arrays.stream(input.split(";")).collect(Collectors.toList()); } + + public static int readInputAmount() { + System.out.println("투입 금액을 입력해 주세요."); + String input = Console.readLine(); + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); + } + } } From b02888a453e1080696c8d0384b08f0023546104e Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 15:55:22 +0900 Subject: [PATCH 09/44] =?UTF-8?q?feat(InputView):=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=ED=95=A0=20=EC=83=81=ED=92=88=EB=AA=85=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/view/InputView.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index b0fac302d..f6520e4b8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,7 +14,7 @@ - [x] 자판기에 추가할 상품명, 가격, 수량을 입력 받는다. - 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분한다. - [x] 투입 금액을 입력 받는다. -- [ ] 구매할 상품의 상품명을 입력 받는다. +- [x] 구매할 상품의 상품명을 입력 받는다. ## 출력 - [ ] 자판기가 보유한 동전 내역을 출력한다. diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index b1e52103f..2f7ba7ab7 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -36,4 +36,9 @@ public static int readInputAmount() { throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); } } + + public static String readProductNameToPurchase() { + System.out.println("구매할 상품명을 입력해 주세요."); + return Console.readLine(); + } } From c831690152f02c2c840509d96f74e0ac2f93204d Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:00:57 +0900 Subject: [PATCH 10/44] =?UTF-8?q?feat(OutputView):=20=EC=9E=90=ED=8C=90?= =?UTF-8?q?=EA=B8=B0=EA=B0=80=20=EB=B3=B4=EC=9C=A0=ED=95=9C=20=EB=8F=99?= =?UTF-8?q?=EC=A0=84=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../java/vendingmachine/view/OutputView.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/main/java/vendingmachine/view/OutputView.java diff --git a/docs/README.md b/docs/README.md index f6520e4b8..83226a90a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -17,7 +17,7 @@ - [x] 구매할 상품의 상품명을 입력 받는다. ## 출력 -- [ ] 자판기가 보유한 동전 내역을 출력한다. +- [x] 자판기가 보유한 동전 내역을 출력한다. - [ ] 남은 투입 금액을 출력한다. - [ ] 잔돈을 출력한다. diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java new file mode 100644 index 000000000..4fe40d703 --- /dev/null +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -0,0 +1,16 @@ +package vendingmachine.view; + +import java.util.Map; + +public class OutputView { + + private OutputView() { + } + + public static void printCoinsOfVendingMachine(Map coins) { + System.out.println("자판기가 보유한 동전"); + for (String coin : coins.keySet()) { + System.out.println(coin + " - " + coins.get(coin) + "개"); + } + } +} From 32d90976dd02755885c87eed23b75530add2f299 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:03:50 +0900 Subject: [PATCH 11/44] =?UTF-8?q?feat(OutputView):=20=EB=82=A8=EC=9D=80=20?= =?UTF-8?q?=ED=88=AC=EC=9E=85=20=EA=B8=88=EC=95=A1=20=EC=B6=9C=EB=A0=A5=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/view/OutputView.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 83226a90a..3feef63c7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,7 +18,7 @@ ## 출력 - [x] 자판기가 보유한 동전 내역을 출력한다. -- [ ] 남은 투입 금액을 출력한다. +- [x] 남은 투입 금액을 출력한다. - [ ] 잔돈을 출력한다. ## 검증 내용 diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index 4fe40d703..ca2970123 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -13,4 +13,8 @@ public static void printCoinsOfVendingMachine(Map coins) { System.out.println(coin + " - " + coins.get(coin) + "개"); } } + + public static void printRemainingInputAmount(int amount) { + System.out.println("투입 금액: " + amount + "원"); + } } From 473978a72b29993606851771b01c34dc72ccb65f Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:07:56 +0900 Subject: [PATCH 12/44] =?UTF-8?q?feat(OutputView):=20=EC=9E=94=EB=8F=88=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/view/OutputView.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 3feef63c7..234783938 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,7 +19,7 @@ ## 출력 - [x] 자판기가 보유한 동전 내역을 출력한다. - [x] 남은 투입 금액을 출력한다. -- [ ] 잔돈을 출력한다. +- [x] 잔돈을 출력한다. ## 검증 내용 - [ ] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index ca2970123..88d71b09b 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -17,4 +17,11 @@ public static void printCoinsOfVendingMachine(Map coins) { public static void printRemainingInputAmount(int amount) { System.out.println("투입 금액: " + amount + "원"); } + + public static void printChanges(Map coins) { + System.out.println("잔돈"); + for (String coin : coins.keySet()) { + System.out.println(coin + " - " + coins.get(coin) + "개"); + } + } } From 8c98537d15906be0e866503ebfe7ce5db8e256b7 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:13:27 +0900 Subject: [PATCH 13/44] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 234783938..a39bd29f6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,7 +5,9 @@ - [x] 입력 받은 상품 하나를 추가한다. - [x] 구입한 상품의 수량을 1 감소시킨다. - [x] 상품 가격만큼 투입 금액을 감소시킨다. -- [ ] 남은 투입 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. +- [ ] 남은 투입 금액이 상품의 최저 가격보다 적은지 확인한다. +- [ ] 모든 상품이 소진되었는지 확인한다. +- [ ] 잔돈을 반환한다. - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. - 반환되지 않은 금액은 자판기에 남는다. From 4564904e3934fdac6c78f46d3fa216dc834d2752 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:22:17 +0900 Subject: [PATCH 14/44] =?UTF-8?q?feat(VendingMachine,=20Product):=20?= =?UTF-8?q?=EB=82=A8=EC=9D=80=20=ED=88=AC=EC=9E=85=20=EA=B8=88=EC=95=A1?= =?UTF-8?q?=EC=9D=B4=20=EC=83=81=ED=92=88=EC=9D=98=20=EC=B5=9C=EC=A0=80=20?= =?UTF-8?q?=EA=B0=80=EA=B2=A9=EB=B3=B4=EB=8B=A4=20=EC=A0=81=EC=9D=80?= =?UTF-8?q?=EC=A7=80=20=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/Product.java | 10 ++++++---- src/main/java/vendingmachine/VendingMachine.java | 12 +++++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/README.md b/docs/README.md index a39bd29f6..89a18b31e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,7 +5,7 @@ - [x] 입력 받은 상품 하나를 추가한다. - [x] 구입한 상품의 수량을 1 감소시킨다. - [x] 상품 가격만큼 투입 금액을 감소시킨다. -- [ ] 남은 투입 금액이 상품의 최저 가격보다 적은지 확인한다. +- [x] 남은 투입 금액이 상품의 최저 가격보다 적은지 확인한다. - [ ] 모든 상품이 소진되었는지 확인한다. - [ ] 잔돈을 반환한다. - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/Product.java index 327396713..de9378b10 100644 --- a/src/main/java/vendingmachine/Product.java +++ b/src/main/java/vendingmachine/Product.java @@ -1,14 +1,12 @@ package vendingmachine; -import java.math.BigDecimal; - public class Product { private String name; - private BigDecimal price; + private int price; private int quantity; - public Product(String name, BigDecimal price, int quantity) { + public Product(String name, int price, int quantity) { this.name = name; this.price = price; this.quantity = quantity; @@ -17,4 +15,8 @@ public Product(String name, BigDecimal price, int quantity) { public void decreaseQuantity() { this.quantity--; } + + public boolean isPriceGreaterThan(int amount) { + return price > amount; + } } diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java index ec5a950a6..7b830be4f 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -1,16 +1,18 @@ package vendingmachine; +import java.util.ArrayList; import java.util.List; public class VendingMachine { - private List products; - - public VendingMachine(List products) { - this.products = products; - } + private List products = new ArrayList<>(); public void addProduct(Product product) { products.add(product); } + + public boolean isAllPriceGreaterThan(int amount) { + return products.stream() + .allMatch(product -> product.isPriceGreaterThan(amount)); + } } From 9aa7b9575aba93d9f9b07c646baca0d44d3df5a2 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:22:48 +0900 Subject: [PATCH 15/44] =?UTF-8?q?feat(VendingMachineTest):=20=EB=82=A8?= =?UTF-8?q?=EC=9D=80=20=ED=88=AC=EC=9E=85=20=EA=B8=88=EC=95=A1=EC=9D=B4=20?= =?UTF-8?q?=EC=83=81=ED=92=88=EC=9D=98=20=EC=B5=9C=EC=A0=80=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=EB=B3=B4=EB=8B=A4=20=EC=A0=81=EC=9D=80=EC=A7=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=8B=A8=EC=9C=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/VendingMachineTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/java/vendingmachine/VendingMachineTest.java diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/VendingMachineTest.java new file mode 100644 index 000000000..569eb4c4a --- /dev/null +++ b/src/test/java/vendingmachine/VendingMachineTest.java @@ -0,0 +1,21 @@ +package vendingmachine; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class VendingMachineTest { + + @Test + void isAllPriceGreaterThan_True() { + // given + Product coke = new Product("콜라", 1500, 20); + Product sprite = new Product("사이다", 2000, 10); + VendingMachine vendingMachine = new VendingMachine(); + vendingMachine.addProduct(coke); + vendingMachine.addProduct(sprite); + + // when, then + Assertions.assertThat(vendingMachine.isAllPriceGreaterThan(1000)).isTrue(); + } + +} \ No newline at end of file From a031dd71bd8586d5ab43de0e7dc7025ab716906c Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:25:49 +0900 Subject: [PATCH 16/44] =?UTF-8?q?feat(VendingMachine,=20Product):=20?= =?UTF-8?q?=EB=AA=A8=EB=93=A0=20=EC=83=81=ED=92=88=EC=9D=B4=20=EC=86=8C?= =?UTF-8?q?=EC=A7=84=EB=90=98=EC=97=88=EB=8A=94=EC=A7=80=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/vendingmachine/Product.java | 4 ++++ src/main/java/vendingmachine/VendingMachine.java | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 89a18b31e..9591e0b49 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,7 +6,7 @@ - [x] 구입한 상품의 수량을 1 감소시킨다. - [x] 상품 가격만큼 투입 금액을 감소시킨다. - [x] 남은 투입 금액이 상품의 최저 가격보다 적은지 확인한다. -- [ ] 모든 상품이 소진되었는지 확인한다. +- [x] 모든 상품이 소진되었는지 확인한다. - [ ] 잔돈을 반환한다. - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. - 반환되지 않은 금액은 자판기에 남는다. diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/Product.java index de9378b10..4c9a05960 100644 --- a/src/main/java/vendingmachine/Product.java +++ b/src/main/java/vendingmachine/Product.java @@ -19,4 +19,8 @@ public void decreaseQuantity() { public boolean isPriceGreaterThan(int amount) { return price > amount; } + + public boolean isSoldOut() { + return quantity == 0; + } } diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/VendingMachine.java index 7b830be4f..7a36bf2e9 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/VendingMachine.java @@ -15,4 +15,9 @@ public boolean isAllPriceGreaterThan(int amount) { return products.stream() .allMatch(product -> product.isPriceGreaterThan(amount)); } + + public boolean isAllProductSoldOut() { + return products.stream() + .allMatch(Product::isSoldOut); + } } From 25da272ddde589c9aed015360a89a043af70df1b Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:26:03 +0900 Subject: [PATCH 17/44] =?UTF-8?q?feat(VendingMachineTest):=20=EB=AA=A8?= =?UTF-8?q?=EB=93=A0=20=EC=83=81=ED=92=88=EC=9D=B4=20=EC=86=8C=EC=A7=84?= =?UTF-8?q?=EB=90=98=EC=97=88=EB=8A=94=EC=A7=80=20=ED=99=95=EC=9D=B8?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EB=8B=A8=EC=9C=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/vendingmachine/VendingMachineTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/VendingMachineTest.java index 569eb4c4a..7e3cb6cd5 100644 --- a/src/test/java/vendingmachine/VendingMachineTest.java +++ b/src/test/java/vendingmachine/VendingMachineTest.java @@ -18,4 +18,16 @@ void isAllPriceGreaterThan_True() { Assertions.assertThat(vendingMachine.isAllPriceGreaterThan(1000)).isTrue(); } + @Test + void isAllProductSoldOut_True() { + // given + Product coke = new Product("콜라", 1500, 0); + Product sprite = new Product("사이다", 2000, 0); + VendingMachine vendingMachine = new VendingMachine(); + vendingMachine.addProduct(coke); + vendingMachine.addProduct(sprite); + + // when, then + Assertions.assertThat(vendingMachine.isAllProductSoldOut()).isTrue(); + } } \ No newline at end of file From 026a5d0b8bc0054178c4621996b0eca56723a358 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 16:29:14 +0900 Subject: [PATCH 18/44] =?UTF-8?q?chore:=20domain=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/{ => domain}/Coin.java | 2 +- src/main/java/vendingmachine/{ => domain}/InputAmount.java | 2 +- src/main/java/vendingmachine/{ => domain}/Product.java | 2 +- src/main/java/vendingmachine/{ => domain}/VendingMachine.java | 2 +- src/test/java/vendingmachine/VendingMachineTest.java | 3 +++ 5 files changed, 7 insertions(+), 4 deletions(-) rename src/main/java/vendingmachine/{ => domain}/Coin.java (87%) rename src/main/java/vendingmachine/{ => domain}/InputAmount.java (86%) rename src/main/java/vendingmachine/{ => domain}/Product.java (93%) rename src/main/java/vendingmachine/{ => domain}/VendingMachine.java (94%) diff --git a/src/main/java/vendingmachine/Coin.java b/src/main/java/vendingmachine/domain/Coin.java similarity index 87% rename from src/main/java/vendingmachine/Coin.java rename to src/main/java/vendingmachine/domain/Coin.java index c76293fbc..7bb89c146 100644 --- a/src/main/java/vendingmachine/Coin.java +++ b/src/main/java/vendingmachine/domain/Coin.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.domain; public enum Coin { COIN_500(500), diff --git a/src/main/java/vendingmachine/InputAmount.java b/src/main/java/vendingmachine/domain/InputAmount.java similarity index 86% rename from src/main/java/vendingmachine/InputAmount.java rename to src/main/java/vendingmachine/domain/InputAmount.java index 2c8df5ade..c0dea9cd0 100644 --- a/src/main/java/vendingmachine/InputAmount.java +++ b/src/main/java/vendingmachine/domain/InputAmount.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.domain; public class InputAmount { diff --git a/src/main/java/vendingmachine/Product.java b/src/main/java/vendingmachine/domain/Product.java similarity index 93% rename from src/main/java/vendingmachine/Product.java rename to src/main/java/vendingmachine/domain/Product.java index 4c9a05960..286f4c1ba 100644 --- a/src/main/java/vendingmachine/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.domain; public class Product { diff --git a/src/main/java/vendingmachine/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java similarity index 94% rename from src/main/java/vendingmachine/VendingMachine.java rename to src/main/java/vendingmachine/domain/VendingMachine.java index 7a36bf2e9..56b662c77 100644 --- a/src/main/java/vendingmachine/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.domain; import java.util.ArrayList; import java.util.List; diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/VendingMachineTest.java index 7e3cb6cd5..faa5b0b4f 100644 --- a/src/test/java/vendingmachine/VendingMachineTest.java +++ b/src/test/java/vendingmachine/VendingMachineTest.java @@ -3,6 +3,9 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import vendingmachine.domain.Product; +import vendingmachine.domain.VendingMachine; + class VendingMachineTest { @Test From 60f36e26a39fb5cea8c05edafb490bd986e7f363 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 17:05:14 +0900 Subject: [PATCH 19/44] =?UTF-8?q?feat(Coin,=20VendingMachine,=20RandomNumb?= =?UTF-8?q?erGenerator):=20=EB=8F=99=EC=A0=84=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/RandomNumberGenerator.java | 2 +- src/main/java/vendingmachine/domain/Coin.java | 21 +++++++++++++- .../vendingmachine/domain/VendingMachine.java | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/main/java/vendingmachine/RandomNumberGenerator.java b/src/main/java/vendingmachine/RandomNumberGenerator.java index 47bd1fd9f..015a654c1 100644 --- a/src/main/java/vendingmachine/RandomNumberGenerator.java +++ b/src/main/java/vendingmachine/RandomNumberGenerator.java @@ -9,7 +9,7 @@ public class RandomNumberGenerator { private RandomNumberGenerator() { } - public int generate(List numbers) { + public static int generate(List numbers) { return Randoms.pickNumberInList(numbers); } } diff --git a/src/main/java/vendingmachine/domain/Coin.java b/src/main/java/vendingmachine/domain/Coin.java index 7bb89c146..de35fee6f 100644 --- a/src/main/java/vendingmachine/domain/Coin.java +++ b/src/main/java/vendingmachine/domain/Coin.java @@ -1,5 +1,9 @@ package vendingmachine.domain; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + public enum Coin { COIN_500(500), COIN_100(100), @@ -12,5 +16,20 @@ public enum Coin { this.amount = amount; } - // 추가 기능 구현 + public static List getCoinAmounts() { + return Arrays.stream(Coin.values()) + .map(coin -> coin.amount) + .collect(Collectors.toList()); + } + + public static Coin from(int amount) { + return Arrays.stream(Coin.values()) + .filter(coin -> coin.amount == amount) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } + + public int getAmount() { + return amount; + } } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 56b662c77..57fea5156 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -1,12 +1,36 @@ package vendingmachine.domain; import java.util.ArrayList; +import java.util.EnumMap; import java.util.List; +import java.util.Map; + +import vendingmachine.RandomNumberGenerator; public class VendingMachine { + private Map coins = new EnumMap<>(Coin.class); private List products = new ArrayList<>(); + public VendingMachine() { + coins.put(Coin.COIN_500, 0); + coins.put(Coin.COIN_100, 0); + coins.put(Coin.COIN_50, 0); + coins.put(Coin.COIN_10, 0); + } + + public void addCoins(int amount) { + while (amount > 0) { + int generatedNumber = RandomNumberGenerator.generate(Coin.getCoinAmounts()); + if (generatedNumber > amount) { + continue; + } + Coin coin = Coin.from(generatedNumber); + coins.put(coin, coins.getOrDefault(coin, 0) + 1); + amount -= generatedNumber; + } + } + public void addProduct(Product product) { products.add(product); } @@ -20,4 +44,8 @@ public boolean isAllProductSoldOut() { return products.stream() .allMatch(Product::isSoldOut); } + + public Map getCoins() { + return coins; + } } From 673a84263430f74624b21691fba031c8a1ba29e6 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 17:09:05 +0900 Subject: [PATCH 20/44] =?UTF-8?q?feat(Controller,=20VendingMachine,=20Outp?= =?UTF-8?q?utView):=20=EC=9E=90=ED=8C=90=EA=B8=B0=20=EB=8F=99=EC=A0=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/Application.java | 4 ++++ .../vendingmachine/controller/Controller.java | 15 +++++++++++++++ .../vendingmachine/domain/VendingMachine.java | 2 +- src/main/java/vendingmachine/view/OutputView.java | 8 +++++--- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/main/java/vendingmachine/controller/Controller.java diff --git a/src/main/java/vendingmachine/Application.java b/src/main/java/vendingmachine/Application.java index 9d3be447b..53cdbbb8d 100644 --- a/src/main/java/vendingmachine/Application.java +++ b/src/main/java/vendingmachine/Application.java @@ -1,7 +1,11 @@ package vendingmachine; +import vendingmachine.controller.Controller; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + Controller controller = new Controller(); + controller.run(); } } diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java new file mode 100644 index 000000000..659327d85 --- /dev/null +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -0,0 +1,15 @@ +package vendingmachine.controller; + +import vendingmachine.domain.VendingMachine; +import vendingmachine.view.InputView; +import vendingmachine.view.OutputView; + +public class Controller { + + public void run() { + int vendingMachineAmount = InputView.readVendingMachineAmount(); + VendingMachine vendingMachine = new VendingMachine(); + vendingMachine.addCoins(vendingMachineAmount); + OutputView.printCoinsOfVendingMachine(vendingMachine.getCoins()); + } +} diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 57fea5156..0d99240dc 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -26,7 +26,7 @@ public void addCoins(int amount) { continue; } Coin coin = Coin.from(generatedNumber); - coins.put(coin, coins.getOrDefault(coin, 0) + 1); + coins.put(coin, coins.get(coin) + 1); amount -= generatedNumber; } } diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index 88d71b09b..1fbb789e9 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -2,15 +2,17 @@ import java.util.Map; +import vendingmachine.domain.Coin; + public class OutputView { private OutputView() { } - public static void printCoinsOfVendingMachine(Map coins) { + public static void printCoinsOfVendingMachine(Map coins) { System.out.println("자판기가 보유한 동전"); - for (String coin : coins.keySet()) { - System.out.println(coin + " - " + coins.get(coin) + "개"); + for (Coin coin : coins.keySet()) { + System.out.println(coin.getAmount() + "원 - " + coins.get(coin) + "개"); } } From 60abfeebbe55eefcf1b52b6a7597760aa3763c85 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 17:20:29 +0900 Subject: [PATCH 21/44] =?UTF-8?q?feat(Controller,=20InputView):=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/controller/Controller.java | 12 ++++++++++++ src/main/java/vendingmachine/view/InputView.java | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 659327d85..4814a9791 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -1,5 +1,11 @@ package vendingmachine.controller; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import vendingmachine.domain.Product; import vendingmachine.domain.VendingMachine; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; @@ -11,5 +17,11 @@ public void run() { VendingMachine vendingMachine = new VendingMachine(); vendingMachine.addCoins(vendingMachineAmount); OutputView.printCoinsOfVendingMachine(vendingMachine.getCoins()); + + List inputProducts = InputView.readProducts(); + for (String inputProduct : inputProducts) { + String[] split = inputProduct.split(","); + vendingMachine.addProduct(new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2]))); + } } } diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 2f7ba7ab7..35b723b36 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -24,7 +24,9 @@ public static int readVendingMachineAmount() { public static List readProducts() { System.out.println("상품명과 가격, 수량을 입력해 주세요."); String input = Console.readLine(); - return Arrays.stream(input.split(";")).collect(Collectors.toList()); + return Arrays.stream(input.split(";")) + .map(product -> product.substring(1, product.length() - 1)) + .collect(Collectors.toList()); } public static int readInputAmount() { From 46cb1b456c7b2b38bb9f65ef9e6db3f0236528ca Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 17:39:42 +0900 Subject: [PATCH 22/44] =?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=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/controller/Controller.java | 11 +++++++++++ src/main/java/vendingmachine/domain/InputAmount.java | 6 +++++- src/main/java/vendingmachine/domain/Product.java | 8 ++++++++ .../java/vendingmachine/domain/VendingMachine.java | 10 ++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 4814a9791..3a54d9d88 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -5,6 +5,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import vendingmachine.domain.InputAmount; import vendingmachine.domain.Product; import vendingmachine.domain.VendingMachine; import vendingmachine.view.InputView; @@ -23,5 +24,15 @@ public void run() { String[] split = inputProduct.split(","); vendingMachine.addProduct(new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2]))); } + + InputAmount inputAmount = new InputAmount(InputView.readInputAmount()); + while (true) { + OutputView.printRemainingInputAmount(inputAmount.getAmount()); + if (vendingMachine.isAllPriceGreaterThan(inputAmount.getAmount()) || vendingMachine.isAllProductSoldOut()) { + break; + } + String productNameToPurchase = InputView.readProductNameToPurchase(); + vendingMachine.purchase(productNameToPurchase, inputAmount); + } } } diff --git a/src/main/java/vendingmachine/domain/InputAmount.java b/src/main/java/vendingmachine/domain/InputAmount.java index c0dea9cd0..001bdeb56 100644 --- a/src/main/java/vendingmachine/domain/InputAmount.java +++ b/src/main/java/vendingmachine/domain/InputAmount.java @@ -4,11 +4,15 @@ public class InputAmount { private int amount; - private InputAmount(int amount) { + public InputAmount(int amount) { this.amount = amount; } public void decrease(int amount) { this.amount -= amount; } + + public int getAmount() { + return amount; + } } diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index 286f4c1ba..e63b2be0e 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -23,4 +23,12 @@ public boolean isPriceGreaterThan(int amount) { public boolean isSoldOut() { return quantity == 0; } + + public boolean isName(String name) { + return this.name.equals(name); + } + + public int getPrice() { + return price; + } } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 0d99240dc..0bacfaf5f 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -4,6 +4,7 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import vendingmachine.RandomNumberGenerator; @@ -45,6 +46,15 @@ public boolean isAllProductSoldOut() { .allMatch(Product::isSoldOut); } + public void purchase(String productName, InputAmount inputAmount) { + Product productForPurchase = products.stream() + .filter(product -> product.isName(productName)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("[ERROR] 존재하지 않는 상품입니다.")); + productForPurchase.decreaseQuantity(); + inputAmount.decrease(productForPurchase.getPrice()); + } + public Map getCoins() { return coins; } From 6dac1585c7cbd8a17ffc6bea6c6bddab25b04302 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:21:08 +0900 Subject: [PATCH 23/44] =?UTF-8?q?feat:=20=EC=9E=94=EB=8F=88=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/controller/Controller.java | 5 +++++ .../vendingmachine/domain/VendingMachine.java | 17 ++++++++++++++++- .../java/vendingmachine/view/OutputView.java | 6 +++--- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 3a54d9d88..74e7a9f2f 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -2,9 +2,11 @@ import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; +import vendingmachine.domain.Coin; import vendingmachine.domain.InputAmount; import vendingmachine.domain.Product; import vendingmachine.domain.VendingMachine; @@ -34,5 +36,8 @@ public void run() { String productNameToPurchase = InputView.readProductNameToPurchase(); vendingMachine.purchase(productNameToPurchase, inputAmount); } + + Map changes = vendingMachine.changes(inputAmount); + OutputView.printChanges(changes); } } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 0bacfaf5f..9fdc97e76 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -4,7 +4,6 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import vendingmachine.RandomNumberGenerator; @@ -55,6 +54,22 @@ public void purchase(String productName, InputAmount inputAmount) { inputAmount.decrease(productForPurchase.getPrice()); } + public Map changes(InputAmount inputAmount) { + Map changes = new EnumMap<>(Coin.class); + for (Coin coin : Coin.values()) { + int count = coins.get(coin); + for (int i = 0; i < count; i++) { + if (inputAmount.getAmount() <= 0) { + break; + } + inputAmount.decrease(coin.getAmount()); + coins.replace(coin, coins.get(coin) - 1); + changes.put(coin, changes.getOrDefault(coin, 0) + 1); + } + } + return changes; + } + public Map getCoins() { return coins; } diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index 1fbb789e9..b8ef1d3b4 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -20,10 +20,10 @@ public static void printRemainingInputAmount(int amount) { System.out.println("투입 금액: " + amount + "원"); } - public static void printChanges(Map coins) { + public static void printChanges(Map coins) { System.out.println("잔돈"); - for (String coin : coins.keySet()) { - System.out.println(coin + " - " + coins.get(coin) + "개"); + for (Coin coin : coins.keySet()) { + System.out.println(coin.getAmount() + "원 - " + coins.get(coin) + "개"); } } } From 04ce38c81917393ee1bd2ce798165c9cac9a18cf Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:22:18 +0900 Subject: [PATCH 24/44] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B5=9C=EC=8B=A0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 9591e0b49..826d7b845 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,7 +7,7 @@ - [x] 상품 가격만큼 투입 금액을 감소시킨다. - [x] 남은 투입 금액이 상품의 최저 가격보다 적은지 확인한다. - [x] 모든 상품이 소진되었는지 확인한다. -- [ ] 잔돈을 반환한다. +- [x] 잔돈을 반환한다. - 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다. - 반환되지 않은 금액은 자판기에 남는다. From cb525afc6b83f9b771bcf20bb0e8a33de5119132 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:23:04 +0900 Subject: [PATCH 25/44] =?UTF-8?q?feat(OutputView):=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/controller/Controller.java | 10 ++++++++++ src/main/java/vendingmachine/view/OutputView.java | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 74e7a9f2f..7d7e6556a 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -40,4 +41,13 @@ public void run() { Map changes = vendingMachine.changes(inputAmount); OutputView.printChanges(changes); } + + private T repeatReadForInvalid(Supplier reader) { + try { + return reader.get(); + } catch (IllegalArgumentException e) { + OutputView.printErrorMessage(e); + return repeatReadForInvalid(reader); + } + } } diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index b8ef1d3b4..00e226b90 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -26,4 +26,8 @@ public static void printChanges(Map coins) { System.out.println(coin.getAmount() + "원 - " + coins.get(coin) + "개"); } } + + public static void printErrorMessage(IllegalArgumentException e) { + System.out.println(e.getMessage()); + } } From a8e38799e2fd10bf6bad162b6ef9cd38ca3fba02 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:27:02 +0900 Subject: [PATCH 26/44] =?UTF-8?q?feat(Product,=20Controller):=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EA=B0=80=EA=B2=A9=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../java/vendingmachine/controller/Controller.java | 9 +++++---- src/main/java/vendingmachine/domain/Product.java | 10 ++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/README.md b/docs/README.md index 826d7b845..3c3f6fef2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,4 +24,4 @@ - [x] 잔돈을 출력한다. ## 검증 내용 -- [ ] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file +- [x] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 7d7e6556a..8b890697b 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -1,11 +1,8 @@ package vendingmachine.controller; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; import vendingmachine.domain.Coin; import vendingmachine.domain.InputAmount; @@ -25,7 +22,7 @@ public void run() { List inputProducts = InputView.readProducts(); for (String inputProduct : inputProducts) { String[] split = inputProduct.split(","); - vendingMachine.addProduct(new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2]))); + vendingMachine.addProduct(repeatReadForInvalid(() -> this.createProduct(split))); } InputAmount inputAmount = new InputAmount(InputView.readInputAmount()); @@ -42,6 +39,10 @@ public void run() { OutputView.printChanges(changes); } + private Product createProduct(String[] split) { + return new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2])); + } + private T repeatReadForInvalid(Supplier reader) { try { return reader.get(); diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index e63b2be0e..1d8fff1e2 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -8,10 +8,20 @@ public class Product { public Product(String name, int price, int quantity) { this.name = name; + validatePrice(price); this.price = price; this.quantity = quantity; } + private void validatePrice(int price) { + if (price < 100) { + throw new IllegalArgumentException("[ERROR] 상품 가격은 100원 이상이어야 합니다."); + } + if (price % 10 != 0) { + throw new IllegalArgumentException("[ERROR] 상품 가격은 10원 단위만 가능합니다."); + } + } + public void decreaseQuantity() { this.quantity--; } From 9629730fed42f6e1a7c839fa44d636d1ca567e72 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:32:09 +0900 Subject: [PATCH 27/44] =?UTF-8?q?feat(VendingMachineAmount,=20Controller):?= =?UTF-8?q?=20=EC=9E=90=ED=8C=90=EA=B8=B0=20=EB=B3=B4=EC=9C=A0=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 3 ++- .../vendingmachine/controller/Controller.java | 9 +++++-- .../domain/VendingMachineAmount.java | 24 +++++++++++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/main/java/vendingmachine/domain/VendingMachineAmount.java diff --git a/docs/README.md b/docs/README.md index 3c3f6fef2..d921a8047 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,4 +24,5 @@ - [x] 잔돈을 출력한다. ## 검증 내용 -- [x] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file +- [x] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. +- [x] 자판기 보유 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 8b890697b..edea05234 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -8,15 +8,16 @@ import vendingmachine.domain.InputAmount; import vendingmachine.domain.Product; import vendingmachine.domain.VendingMachine; +import vendingmachine.domain.VendingMachineAmount; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; public class Controller { public void run() { - int vendingMachineAmount = InputView.readVendingMachineAmount(); + VendingMachineAmount vendingMachineAmount = repeatReadForInvalid(this::createVendingMachineAmount); VendingMachine vendingMachine = new VendingMachine(); - vendingMachine.addCoins(vendingMachineAmount); + vendingMachine.addCoins(vendingMachineAmount.getVendingMachineAmount()); OutputView.printCoinsOfVendingMachine(vendingMachine.getCoins()); List inputProducts = InputView.readProducts(); @@ -43,6 +44,10 @@ private Product createProduct(String[] split) { return new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2])); } + private VendingMachineAmount createVendingMachineAmount() { + return new VendingMachineAmount(InputView.readVendingMachineAmount()); + } + private T repeatReadForInvalid(Supplier reader) { try { return reader.get(); diff --git a/src/main/java/vendingmachine/domain/VendingMachineAmount.java b/src/main/java/vendingmachine/domain/VendingMachineAmount.java new file mode 100644 index 000000000..41460a27d --- /dev/null +++ b/src/main/java/vendingmachine/domain/VendingMachineAmount.java @@ -0,0 +1,24 @@ +package vendingmachine.domain; + +public class VendingMachineAmount { + + private int vendingMachineAmount; + + public VendingMachineAmount(int vendingMachineAmount) { + validate(vendingMachineAmount); + this.vendingMachineAmount = vendingMachineAmount; + } + + private void validate(int vendingMachineAmount) { + if (vendingMachineAmount < 10) { + throw new IllegalArgumentException("[ERROR] 자판기가 보유 금액은 10원 이상이어야 합니다."); + } + if (vendingMachineAmount % 10 != 0) { + throw new IllegalArgumentException("[ERROR] 자판기 보유 금액은 10원 단위만 가능합니다."); + } + } + + public int getVendingMachineAmount() { + return vendingMachineAmount; + } +} From f7a19baa4c2ea2d3b930f187e2181594c21ed74b Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:32:44 +0900 Subject: [PATCH 28/44] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=AF=B8=EC=85=98=20=EC=A0=9C=EB=AA=A9=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index d921a8047..550199353 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# 미션 제목 +# 자판기 ## 기능 - [x] 입력 받은 금액에 따라 동전을 무작위로 생성한다. From 506f681dda4c039bc9f47a0198919c54115f3e0e Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:43:08 +0900 Subject: [PATCH 29/44] =?UTF-8?q?refactor(VendingMachine):=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/domain/VendingMachine.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 9fdc97e76..7bc598778 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -4,7 +4,6 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; - import vendingmachine.RandomNumberGenerator; public class VendingMachine { @@ -58,18 +57,22 @@ public Map changes(InputAmount inputAmount) { Map changes = new EnumMap<>(Coin.class); for (Coin coin : Coin.values()) { int count = coins.get(coin); - for (int i = 0; i < count; i++) { - if (inputAmount.getAmount() <= 0) { - break; - } - inputAmount.decrease(coin.getAmount()); - coins.replace(coin, coins.get(coin) - 1); - changes.put(coin, changes.getOrDefault(coin, 0) + 1); - } + repeatChangesForCount(count, inputAmount, changes, coin); } return changes; } + private void repeatChangesForCount(int count, InputAmount inputAmount, Map changes, Coin coin) { + for (int i = 0; i < count; i++) { + if (inputAmount.getAmount() <= 0) { + return; + } + inputAmount.decrease(coin.getAmount()); + coins.replace(coin, coins.get(coin) - 1); + changes.put(coin, changes.getOrDefault(coin, 0) + 1); + } + } + public Map getCoins() { return coins; } From ded3b4460cda5a36c0f57602356f2375215dfcfd Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:48:24 +0900 Subject: [PATCH 30/44] =?UTF-8?q?feat(InputAmount,=20Controller):=20?= =?UTF-8?q?=ED=88=AC=EC=9E=85=20=EA=B8=88=EC=95=A1=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/controller/Controller.java | 26 ++++++++++++++----- .../vendingmachine/domain/InputAmount.java | 10 +++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index edea05234..13bd34c0c 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -3,7 +3,6 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; - import vendingmachine.domain.Coin; import vendingmachine.domain.InputAmount; import vendingmachine.domain.Product; @@ -15,18 +14,36 @@ public class Controller { public void run() { - VendingMachineAmount vendingMachineAmount = repeatReadForInvalid(this::createVendingMachineAmount); VendingMachine vendingMachine = new VendingMachine(); + VendingMachineAmount vendingMachineAmount = repeatReadForInvalid(this::createVendingMachineAmount); + addCoinsToVendingMachine(vendingMachineAmount, vendingMachine); + addProductsToVendingMachine(vendingMachine); + + InputAmount inputAmount = repeatReadForInvalid(this::createInputAmount); + repeatPurchaseProduct(vendingMachine, inputAmount); + + Map changes = vendingMachine.changes(inputAmount); + OutputView.printChanges(changes); + } + + private void addCoinsToVendingMachine(VendingMachineAmount vendingMachineAmount, VendingMachine vendingMachine) { vendingMachine.addCoins(vendingMachineAmount.getVendingMachineAmount()); OutputView.printCoinsOfVendingMachine(vendingMachine.getCoins()); + } + private void addProductsToVendingMachine(VendingMachine vendingMachine) { List inputProducts = InputView.readProducts(); for (String inputProduct : inputProducts) { String[] split = inputProduct.split(","); vendingMachine.addProduct(repeatReadForInvalid(() -> this.createProduct(split))); } + } + + private InputAmount createInputAmount() { + return new InputAmount(InputView.readInputAmount()); + } - InputAmount inputAmount = new InputAmount(InputView.readInputAmount()); + private void repeatPurchaseProduct(VendingMachine vendingMachine, InputAmount inputAmount) { while (true) { OutputView.printRemainingInputAmount(inputAmount.getAmount()); if (vendingMachine.isAllPriceGreaterThan(inputAmount.getAmount()) || vendingMachine.isAllProductSoldOut()) { @@ -35,9 +52,6 @@ public void run() { String productNameToPurchase = InputView.readProductNameToPurchase(); vendingMachine.purchase(productNameToPurchase, inputAmount); } - - Map changes = vendingMachine.changes(inputAmount); - OutputView.printChanges(changes); } private Product createProduct(String[] split) { diff --git a/src/main/java/vendingmachine/domain/InputAmount.java b/src/main/java/vendingmachine/domain/InputAmount.java index 001bdeb56..c051fd3d4 100644 --- a/src/main/java/vendingmachine/domain/InputAmount.java +++ b/src/main/java/vendingmachine/domain/InputAmount.java @@ -5,9 +5,19 @@ public class InputAmount { private int amount; public InputAmount(int amount) { + validate(amount); this.amount = amount; } + private void validate(int amount) { + if (amount < 10) { + throw new IllegalArgumentException("[ERROR] 투입 금액은 10원 이상이어야 합니다."); + } + if (amount % 10 != 0) { + throw new IllegalArgumentException("[ERROR] 투입 금액은 10원 단위만 가능합니다."); + } + } + public void decrease(int amount) { this.amount -= amount; } From 6bcefd69fd63afe8952a0cbe26b9dce657af8b49 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:51:26 +0900 Subject: [PATCH 31/44] =?UTF-8?q?refactor(Controller):=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=20=EC=A1=B0=EA=B1=B4=EB=AC=B8=EC=9D=98=20=EC=9D=98?= =?UTF-8?q?=EB=8F=84=EA=B0=80=20=EB=AA=85=ED=99=95=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/controller/Controller.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 13bd34c0c..686ad6935 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -44,16 +44,18 @@ private InputAmount createInputAmount() { } private void repeatPurchaseProduct(VendingMachine vendingMachine, InputAmount inputAmount) { - while (true) { + while (canPurchase(vendingMachine, inputAmount)) { OutputView.printRemainingInputAmount(inputAmount.getAmount()); - if (vendingMachine.isAllPriceGreaterThan(inputAmount.getAmount()) || vendingMachine.isAllProductSoldOut()) { - break; - } String productNameToPurchase = InputView.readProductNameToPurchase(); vendingMachine.purchase(productNameToPurchase, inputAmount); } } + private boolean canPurchase(VendingMachine vendingMachine, InputAmount inputAmount) { + return !vendingMachine.isAllPriceGreaterThan(inputAmount.getAmount()) + && !vendingMachine.isAllProductSoldOut(); + } + private Product createProduct(String[] split) { return new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2])); } From b4d384b523f625a1895157b5e3fa7f77897a99a0 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:55:46 +0900 Subject: [PATCH 32/44] =?UTF-8?q?refactor(Converter,=20Controller,=20Input?= =?UTF-8?q?View):=20Converter=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=A0=95=EC=88=98?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=ED=99=98=ED=95=98=EB=8A=94=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A4=91=EB=B3=B5=20=EC=B5=9C=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/controller/Controller.java | 3 ++- src/main/java/vendingmachine/utils/Converter.java | 15 +++++++++++++++ src/main/java/vendingmachine/view/InputView.java | 13 +++---------- 3 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 src/main/java/vendingmachine/utils/Converter.java diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 686ad6935..24d53df34 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -8,6 +8,7 @@ import vendingmachine.domain.Product; import vendingmachine.domain.VendingMachine; import vendingmachine.domain.VendingMachineAmount; +import vendingmachine.utils.Converter; import vendingmachine.view.InputView; import vendingmachine.view.OutputView; @@ -57,7 +58,7 @@ private boolean canPurchase(VendingMachine vendingMachine, InputAmount inputAmou } private Product createProduct(String[] split) { - return new Product(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2])); + return new Product(split[0], Converter.convertToInt(split[1]), Converter.convertToInt(split[2])); } private VendingMachineAmount createVendingMachineAmount() { diff --git a/src/main/java/vendingmachine/utils/Converter.java b/src/main/java/vendingmachine/utils/Converter.java new file mode 100644 index 000000000..6b0bf10e7 --- /dev/null +++ b/src/main/java/vendingmachine/utils/Converter.java @@ -0,0 +1,15 @@ +package vendingmachine.utils; + +public class Converter { + + private Converter() { + } + + public static int convertToInt(String input) { + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); + } + } +} diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 35b723b36..027e2b48a 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -5,6 +5,7 @@ import java.util.stream.Collectors; import camp.nextstep.edu.missionutils.Console; +import vendingmachine.utils.Converter; public class InputView { @@ -14,11 +15,7 @@ private InputView() { public static int readVendingMachineAmount() { System.out.println("자판기가 보유하고 있는 금액을 입력해 주세요."); String input = Console.readLine(); - try { - return Integer.parseInt(input); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); - } + return Converter.convertToInt(input); } public static List readProducts() { @@ -32,11 +29,7 @@ public static List readProducts() { public static int readInputAmount() { System.out.println("투입 금액을 입력해 주세요."); String input = Console.readLine(); - try { - return Integer.parseInt(input); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("[ERROR] 숫자만 입력 가능합니다."); - } + return Converter.convertToInt(input); } public static String readProductNameToPurchase() { From d73a5393ab277527f754d437b7822324e6790d22 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 18:56:25 +0900 Subject: [PATCH 33/44] =?UTF-8?q?chore(RandomNumberGenerator,=20VendingMac?= =?UTF-8?q?hine):=20RandomNumberGenerator=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9C=84=EC=B9=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/domain/VendingMachine.java | 2 +- .../java/vendingmachine/{ => utils}/RandomNumberGenerator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/vendingmachine/{ => utils}/RandomNumberGenerator.java (90%) diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index 7bc598778..d38d12379 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -4,7 +4,7 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import vendingmachine.RandomNumberGenerator; +import vendingmachine.utils.RandomNumberGenerator; public class VendingMachine { diff --git a/src/main/java/vendingmachine/RandomNumberGenerator.java b/src/main/java/vendingmachine/utils/RandomNumberGenerator.java similarity index 90% rename from src/main/java/vendingmachine/RandomNumberGenerator.java rename to src/main/java/vendingmachine/utils/RandomNumberGenerator.java index 015a654c1..a30966930 100644 --- a/src/main/java/vendingmachine/RandomNumberGenerator.java +++ b/src/main/java/vendingmachine/utils/RandomNumberGenerator.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.utils; import java.util.List; From 64bf97345af8e95c2900b24c9c8282eb0c6908c5 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:01:14 +0900 Subject: [PATCH 34/44] =?UTF-8?q?refactor(Constants,=20InputAmount):=20?= =?UTF-8?q?=EB=A7=A4=EC=A7=81=20=EB=A6=AC=ED=84=B0=EB=9F=B4=20=EC=83=81?= =?UTF-8?q?=EC=88=98=ED=99=94=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/vendingmachine/constants/Constants.java | 16 ++++++++++++++++ .../java/vendingmachine/domain/InputAmount.java | 15 +++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/main/java/vendingmachine/constants/Constants.java diff --git a/src/main/java/vendingmachine/constants/Constants.java b/src/main/java/vendingmachine/constants/Constants.java new file mode 100644 index 000000000..17f22e938 --- /dev/null +++ b/src/main/java/vendingmachine/constants/Constants.java @@ -0,0 +1,16 @@ +package vendingmachine.constants; + +public enum Constants { + + ERROR_PREFIX("[ERROR]"); + + private final String value; + + Constants(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/vendingmachine/domain/InputAmount.java b/src/main/java/vendingmachine/domain/InputAmount.java index c051fd3d4..4d2612797 100644 --- a/src/main/java/vendingmachine/domain/InputAmount.java +++ b/src/main/java/vendingmachine/domain/InputAmount.java @@ -1,7 +1,12 @@ package vendingmachine.domain; +import vendingmachine.constants.Constants; + public class InputAmount { + private static final int MIN_INPUT_AMOUNT = 10; + private static final int INPUT_AMOUNT_UNIT = 10; + private int amount; public InputAmount(int amount) { @@ -10,11 +15,13 @@ public InputAmount(int amount) { } private void validate(int amount) { - if (amount < 10) { - throw new IllegalArgumentException("[ERROR] 투입 금액은 10원 이상이어야 합니다."); + if (amount < MIN_INPUT_AMOUNT) { + throw new IllegalArgumentException( + String.format("%s 투입 금액은 %d원 이상이어야 합니다.", Constants.ERROR_PREFIX, MIN_INPUT_AMOUNT)); } - if (amount % 10 != 0) { - throw new IllegalArgumentException("[ERROR] 투입 금액은 10원 단위만 가능합니다."); + if (amount % INPUT_AMOUNT_UNIT != 0) { + throw new IllegalArgumentException( + String.format("%s 투입 금액은 %d원 단위만 가능합니다.", Constants.ERROR_PREFIX, INPUT_AMOUNT_UNIT)); } } From ddc1f52bdeafc1934a2b315cfcd185fdeb387149 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:03:40 +0900 Subject: [PATCH 35/44] =?UTF-8?q?refactor(Product):=20=EB=A7=A4=EC=A7=81?= =?UTF-8?q?=20=EB=84=98=EB=B2=84=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/domain/Product.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index 1d8fff1e2..a43542ad5 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -1,7 +1,12 @@ package vendingmachine.domain; +import vendingmachine.constants.Constants; + public class Product { + private static final int MIN_PRICE = 100; + private static final int PRICE_UNIT = 10; + private String name; private int price; private int quantity; @@ -14,11 +19,13 @@ public Product(String name, int price, int quantity) { } private void validatePrice(int price) { - if (price < 100) { - throw new IllegalArgumentException("[ERROR] 상품 가격은 100원 이상이어야 합니다."); + if (price < MIN_PRICE) { + throw new IllegalArgumentException( + String.format("%s 상품 가격은 %d원 이상이어야 합니다.", Constants.ERROR_PREFIX, MIN_PRICE)); } - if (price % 10 != 0) { - throw new IllegalArgumentException("[ERROR] 상품 가격은 10원 단위만 가능합니다."); + if (price % PRICE_UNIT != 0) { + throw new IllegalArgumentException( + String.format("%s 상품 가격은 %d원 단위만 가능합니다.", Constants.ERROR_PREFIX, PRICE_UNIT)); } } From 5e5171eb121d94b62bc56f0e267f4ff85a1769e9 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:11:01 +0900 Subject: [PATCH 36/44] =?UTF-8?q?refactor(VendingMachine,=20VendingMachine?= =?UTF-8?q?Amount,=20Controller):=20=EC=BA=A1=EC=8A=90=ED=99=94=EB=A5=BC?= =?UTF-8?q?=20=ED=86=B5=ED=95=B4=20=EC=9C=A0=EC=A7=80=EB=B3=B4=EC=88=98?= =?UTF-8?q?=EC=84=B1=20=ED=96=A5=EC=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/controller/Controller.java | 2 +- .../vendingmachine/domain/VendingMachine.java | 8 ++--- .../domain/VendingMachineAmount.java | 30 +++++++++++++------ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 24d53df34..7fe27d31b 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -28,7 +28,7 @@ public void run() { } private void addCoinsToVendingMachine(VendingMachineAmount vendingMachineAmount, VendingMachine vendingMachine) { - vendingMachine.addCoins(vendingMachineAmount.getVendingMachineAmount()); + vendingMachine.addCoins(vendingMachineAmount); OutputView.printCoinsOfVendingMachine(vendingMachine.getCoins()); } diff --git a/src/main/java/vendingmachine/domain/VendingMachine.java b/src/main/java/vendingmachine/domain/VendingMachine.java index d38d12379..afaa9d2da 100644 --- a/src/main/java/vendingmachine/domain/VendingMachine.java +++ b/src/main/java/vendingmachine/domain/VendingMachine.java @@ -18,15 +18,15 @@ public VendingMachine() { coins.put(Coin.COIN_10, 0); } - public void addCoins(int amount) { - while (amount > 0) { + public void addCoins(VendingMachineAmount vendingMachineAmount) { + while (vendingMachineAmount.isGreaterThanZero()) { int generatedNumber = RandomNumberGenerator.generate(Coin.getCoinAmounts()); - if (generatedNumber > amount) { + if (vendingMachineAmount.isLessThan(generatedNumber)) { continue; } Coin coin = Coin.from(generatedNumber); coins.put(coin, coins.get(coin) + 1); - amount -= generatedNumber; + vendingMachineAmount.decrease(generatedNumber); } } diff --git a/src/main/java/vendingmachine/domain/VendingMachineAmount.java b/src/main/java/vendingmachine/domain/VendingMachineAmount.java index 41460a27d..9ac1b1501 100644 --- a/src/main/java/vendingmachine/domain/VendingMachineAmount.java +++ b/src/main/java/vendingmachine/domain/VendingMachineAmount.java @@ -2,23 +2,35 @@ public class VendingMachineAmount { - private int vendingMachineAmount; + private int amount; - public VendingMachineAmount(int vendingMachineAmount) { - validate(vendingMachineAmount); - this.vendingMachineAmount = vendingMachineAmount; + public VendingMachineAmount(int amount) { + validate(amount); + this.amount = amount; } - private void validate(int vendingMachineAmount) { - if (vendingMachineAmount < 10) { + private void validate(int amount) { + if (amount < 10) { throw new IllegalArgumentException("[ERROR] 자판기가 보유 금액은 10원 이상이어야 합니다."); } - if (vendingMachineAmount % 10 != 0) { + if (amount % 10 != 0) { throw new IllegalArgumentException("[ERROR] 자판기 보유 금액은 10원 단위만 가능합니다."); } } - public int getVendingMachineAmount() { - return vendingMachineAmount; + public boolean isGreaterThanZero() { + return amount > 0; + } + + public boolean isLessThan(int amount) { + return this.amount < amount; + } + + public void decrease(int amount) { + this.amount -= amount; + } + + public int getAmount() { + return amount; } } From 5a7ac570a1b0de6ead300a53aa4f5e596cf59fce Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:15:07 +0900 Subject: [PATCH 37/44] =?UTF-8?q?refactor(VendingMachineAmount):=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94=20=EB=B0=8F=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/VendingMachineAmount.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/vendingmachine/domain/VendingMachineAmount.java b/src/main/java/vendingmachine/domain/VendingMachineAmount.java index 9ac1b1501..0c86e82af 100644 --- a/src/main/java/vendingmachine/domain/VendingMachineAmount.java +++ b/src/main/java/vendingmachine/domain/VendingMachineAmount.java @@ -1,7 +1,12 @@ package vendingmachine.domain; +import vendingmachine.constants.Constants; + public class VendingMachineAmount { + private static final int MIN_AMOUNT = 10; + private static final int AMOUNT_UNIT = 10; + private int amount; public VendingMachineAmount(int amount) { @@ -10,11 +15,13 @@ public VendingMachineAmount(int amount) { } private void validate(int amount) { - if (amount < 10) { - throw new IllegalArgumentException("[ERROR] 자판기가 보유 금액은 10원 이상이어야 합니다."); + if (amount < MIN_AMOUNT) { + throw new IllegalArgumentException( + String.format("%s 자판기가 보유 금액은 %d원 이상이어야 합니다.", Constants.ERROR_PREFIX, MIN_AMOUNT)); } - if (amount % 10 != 0) { - throw new IllegalArgumentException("[ERROR] 자판기 보유 금액은 10원 단위만 가능합니다."); + if (amount % AMOUNT_UNIT != 0) { + throw new IllegalArgumentException( + String.format("%s 자판기가 보유 금액은 %d원 단위만 가능합니다.", Constants.ERROR_PREFIX, MIN_AMOUNT)); } } @@ -29,8 +36,4 @@ public boolean isLessThan(int amount) { public void decrease(int amount) { this.amount -= amount; } - - public int getAmount() { - return amount; - } } From 6aca1dac488d651b1397e0990acbedcbe1569111 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:19:39 +0900 Subject: [PATCH 38/44] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=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/domain/InputAmount.java | 6 ++++-- src/main/java/vendingmachine/domain/Product.java | 6 ++++-- .../java/vendingmachine/domain/VendingMachineAmount.java | 6 ++++-- .../java/vendingmachine/utils/RandomNumberGenerator.java | 3 +-- src/main/java/vendingmachine/view/InputView.java | 3 +-- src/main/java/vendingmachine/view/OutputView.java | 1 - 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/vendingmachine/domain/InputAmount.java b/src/main/java/vendingmachine/domain/InputAmount.java index 4d2612797..de6efd699 100644 --- a/src/main/java/vendingmachine/domain/InputAmount.java +++ b/src/main/java/vendingmachine/domain/InputAmount.java @@ -17,11 +17,13 @@ public InputAmount(int amount) { private void validate(int amount) { if (amount < MIN_INPUT_AMOUNT) { throw new IllegalArgumentException( - String.format("%s 투입 금액은 %d원 이상이어야 합니다.", Constants.ERROR_PREFIX, MIN_INPUT_AMOUNT)); + String.format("%s 투입 금액은 %d원 이상이어야 합니다.", + Constants.ERROR_PREFIX.getValue(), MIN_INPUT_AMOUNT)); } if (amount % INPUT_AMOUNT_UNIT != 0) { throw new IllegalArgumentException( - String.format("%s 투입 금액은 %d원 단위만 가능합니다.", Constants.ERROR_PREFIX, INPUT_AMOUNT_UNIT)); + String.format("%s 투입 금액은 %d원 단위만 가능합니다.", + Constants.ERROR_PREFIX.getValue(), INPUT_AMOUNT_UNIT)); } } diff --git a/src/main/java/vendingmachine/domain/Product.java b/src/main/java/vendingmachine/domain/Product.java index a43542ad5..daba6f8cd 100644 --- a/src/main/java/vendingmachine/domain/Product.java +++ b/src/main/java/vendingmachine/domain/Product.java @@ -21,11 +21,13 @@ public Product(String name, int price, int quantity) { private void validatePrice(int price) { if (price < MIN_PRICE) { throw new IllegalArgumentException( - String.format("%s 상품 가격은 %d원 이상이어야 합니다.", Constants.ERROR_PREFIX, MIN_PRICE)); + String.format("%s 상품 가격은 %d원 이상이어야 합니다.", + Constants.ERROR_PREFIX.getValue(), MIN_PRICE)); } if (price % PRICE_UNIT != 0) { throw new IllegalArgumentException( - String.format("%s 상품 가격은 %d원 단위만 가능합니다.", Constants.ERROR_PREFIX, PRICE_UNIT)); + String.format("%s 상품 가격은 %d원 단위만 가능합니다.", + Constants.ERROR_PREFIX.getValue(), PRICE_UNIT)); } } diff --git a/src/main/java/vendingmachine/domain/VendingMachineAmount.java b/src/main/java/vendingmachine/domain/VendingMachineAmount.java index 0c86e82af..a579b0dd7 100644 --- a/src/main/java/vendingmachine/domain/VendingMachineAmount.java +++ b/src/main/java/vendingmachine/domain/VendingMachineAmount.java @@ -17,11 +17,13 @@ public VendingMachineAmount(int amount) { private void validate(int amount) { if (amount < MIN_AMOUNT) { throw new IllegalArgumentException( - String.format("%s 자판기가 보유 금액은 %d원 이상이어야 합니다.", Constants.ERROR_PREFIX, MIN_AMOUNT)); + String.format("%s 자판기가 보유 금액은 %d원 이상이어야 합니다.", + Constants.ERROR_PREFIX.getValue(), MIN_AMOUNT)); } if (amount % AMOUNT_UNIT != 0) { throw new IllegalArgumentException( - String.format("%s 자판기가 보유 금액은 %d원 단위만 가능합니다.", Constants.ERROR_PREFIX, MIN_AMOUNT)); + String.format("%s 자판기가 보유 금액은 %d원 단위만 가능합니다.", + Constants.ERROR_PREFIX.getValue(), MIN_AMOUNT)); } } diff --git a/src/main/java/vendingmachine/utils/RandomNumberGenerator.java b/src/main/java/vendingmachine/utils/RandomNumberGenerator.java index a30966930..1141d39bf 100644 --- a/src/main/java/vendingmachine/utils/RandomNumberGenerator.java +++ b/src/main/java/vendingmachine/utils/RandomNumberGenerator.java @@ -1,8 +1,7 @@ package vendingmachine.utils; -import java.util.List; - import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; public class RandomNumberGenerator { diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 027e2b48a..8e3b47a1b 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -1,10 +1,9 @@ package vendingmachine.view; +import camp.nextstep.edu.missionutils.Console; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; - -import camp.nextstep.edu.missionutils.Console; import vendingmachine.utils.Converter; public class InputView { diff --git a/src/main/java/vendingmachine/view/OutputView.java b/src/main/java/vendingmachine/view/OutputView.java index 00e226b90..9357e6cfe 100644 --- a/src/main/java/vendingmachine/view/OutputView.java +++ b/src/main/java/vendingmachine/view/OutputView.java @@ -1,7 +1,6 @@ package vendingmachine.view; import java.util.Map; - import vendingmachine.domain.Coin; public class OutputView { From 169b66be3529930b749f6c9b43562d0618b35788 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:24:54 +0900 Subject: [PATCH 39/44] =?UTF-8?q?test(InputAmountTest):=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EB=8B=A8=EC=9C=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/InputAmountTest.java | 32 +++++++++++++++++++ .../{ => domain}/VendingMachineTest.java | 4 +-- 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/test/java/vendingmachine/domain/InputAmountTest.java rename src/test/java/vendingmachine/{ => domain}/VendingMachineTest.java (96%) diff --git a/src/test/java/vendingmachine/domain/InputAmountTest.java b/src/test/java/vendingmachine/domain/InputAmountTest.java new file mode 100644 index 000000000..2e9dc47ad --- /dev/null +++ b/src/test/java/vendingmachine/domain/InputAmountTest.java @@ -0,0 +1,32 @@ +package vendingmachine.domain; + +import static org.junit.jupiter.api.Assertions.*; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import vendingmachine.constants.Constants; + +class InputAmountTest { + + private static final int MIN_INPUT_AMOUNT = 10; + private static final int INPUT_AMOUNT_UNIT = 10; + + @Test + void construct_Fail_ByAmountIsLessThanMinimum() { + // when, then + Assertions.assertThatThrownBy(() -> new InputAmount(1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format("%s 투입 금액은 %d원 이상이어야 합니다.", + Constants.ERROR_PREFIX.getValue(), MIN_INPUT_AMOUNT)); + } + + @Test + void construct_Fail_ByInvalidUnit() { + // when, then + Assertions.assertThatThrownBy(() -> new InputAmount(111)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format("%s 투입 금액은 %d원 단위만 가능합니다.", + Constants.ERROR_PREFIX.getValue(), INPUT_AMOUNT_UNIT)); + } +} diff --git a/src/test/java/vendingmachine/VendingMachineTest.java b/src/test/java/vendingmachine/domain/VendingMachineTest.java similarity index 96% rename from src/test/java/vendingmachine/VendingMachineTest.java rename to src/test/java/vendingmachine/domain/VendingMachineTest.java index faa5b0b4f..f3d7bc3ed 100644 --- a/src/test/java/vendingmachine/VendingMachineTest.java +++ b/src/test/java/vendingmachine/domain/VendingMachineTest.java @@ -1,4 +1,4 @@ -package vendingmachine; +package vendingmachine.domain; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; @@ -33,4 +33,4 @@ void isAllProductSoldOut_True() { // when, then Assertions.assertThat(vendingMachine.isAllProductSoldOut()).isTrue(); } -} \ No newline at end of file +} From d42a7b47402d51fe953d7c3519fc7d7ae16b209d Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:30:38 +0900 Subject: [PATCH 40/44] =?UTF-8?q?test(ProductTest):=20=EC=83=81=ED=92=88?= =?UTF-8?q?=20=EA=B0=80=EA=B2=A9=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendingmachine/domain/ProductTest.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/java/vendingmachine/domain/ProductTest.java diff --git a/src/test/java/vendingmachine/domain/ProductTest.java b/src/test/java/vendingmachine/domain/ProductTest.java new file mode 100644 index 000000000..8831f88e5 --- /dev/null +++ b/src/test/java/vendingmachine/domain/ProductTest.java @@ -0,0 +1,29 @@ +package vendingmachine.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import vendingmachine.constants.Constants; + +class ProductTest { + + private static final int MIN_PRICE = 100; + private static final int PRICE_UNIT = 10; + + @Test + void construct_Fail_ByPriceIsLessThanMinimum() { + // when, then + Assertions.assertThatThrownBy(() -> new Product("콜라", 1, 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format("%s 상품 가격은 %d원 이상이어야 합니다.", + Constants.ERROR_PREFIX.getValue(), MIN_PRICE)); + } + + @Test + void construct_Fail_ByInvalidPriceUnit() { + // when, then + Assertions.assertThatThrownBy(() -> new Product("콜라", 111, 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format("%s 상품 가격은 %d원 단위만 가능합니다.", + Constants.ERROR_PREFIX.getValue(), PRICE_UNIT)); + } +} From 7fad6817e20c2780d6022e4c7892b8850f8084be Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:33:47 +0900 Subject: [PATCH 41/44] =?UTF-8?q?style:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/vendingmachine/domain/InputAmountTest.java | 3 --- src/test/java/vendingmachine/domain/VendingMachineTest.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/test/java/vendingmachine/domain/InputAmountTest.java b/src/test/java/vendingmachine/domain/InputAmountTest.java index 2e9dc47ad..8dfab7a3f 100644 --- a/src/test/java/vendingmachine/domain/InputAmountTest.java +++ b/src/test/java/vendingmachine/domain/InputAmountTest.java @@ -1,10 +1,7 @@ package vendingmachine.domain; -import static org.junit.jupiter.api.Assertions.*; - import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; - import vendingmachine.constants.Constants; class InputAmountTest { diff --git a/src/test/java/vendingmachine/domain/VendingMachineTest.java b/src/test/java/vendingmachine/domain/VendingMachineTest.java index f3d7bc3ed..16c398193 100644 --- a/src/test/java/vendingmachine/domain/VendingMachineTest.java +++ b/src/test/java/vendingmachine/domain/VendingMachineTest.java @@ -3,9 +3,6 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import vendingmachine.domain.Product; -import vendingmachine.domain.VendingMachine; - class VendingMachineTest { @Test From 45ec4bc8d55bfbc7acb50cf8c5d187d6a9db5e48 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:35:39 +0900 Subject: [PATCH 42/44] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B5=9C=EC=8B=A0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 550199353..2371fd012 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,4 +25,5 @@ ## 검증 내용 - [x] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. -- [x] 자판기 보유 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file +- [x] 자판기 보유 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. +- [x] 투입 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file From 6059b553ef091593ba1921728a9eda0d675029e5 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:52:17 +0900 Subject: [PATCH 43/44] =?UTF-8?q?feat(InputView,=20Controller):=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=9E=85=EB=A0=A5=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 3 ++- .../java/vendingmachine/controller/Controller.java | 2 +- src/main/java/vendingmachine/view/InputView.java | 10 ++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 2371fd012..c5d1f88fe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -26,4 +26,5 @@ ## 검증 내용 - [x] 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다. - [x] 자판기 보유 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. -- [x] 투입 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. \ No newline at end of file +- [x] 투입 금액은 10원부터 시작하며, 10원으로 나누어떨어져야 한다. +- [x] 자판기에 추가할 상품의 상품명, 가격, 수량은 쉼표로, 개별 상품은 대괄호([])로 묶어 세미콜론(;)으로 구분해야 한다. \ No newline at end of file diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 7fe27d31b..8aa1c001f 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -33,7 +33,7 @@ private void addCoinsToVendingMachine(VendingMachineAmount vendingMachineAmount, } private void addProductsToVendingMachine(VendingMachine vendingMachine) { - List inputProducts = InputView.readProducts(); + List inputProducts = repeatReadForInvalid(InputView::readProducts); for (String inputProduct : inputProducts) { String[] split = inputProduct.split(","); vendingMachine.addProduct(repeatReadForInvalid(() -> this.createProduct(split))); diff --git a/src/main/java/vendingmachine/view/InputView.java b/src/main/java/vendingmachine/view/InputView.java index 8e3b47a1b..560b2f8fb 100644 --- a/src/main/java/vendingmachine/view/InputView.java +++ b/src/main/java/vendingmachine/view/InputView.java @@ -3,11 +3,17 @@ import camp.nextstep.edu.missionutils.Console; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Collectors; + +import vendingmachine.constants.Constants; import vendingmachine.utils.Converter; public class InputView { + private static final Pattern PRODUCTS_REGEX = + Pattern.compile("^(\\[[가-힣a-zA-Z]+,\\d+,\\d+\\])(;\\[[가-힣a-zA-Z]+,\\d+,\\d+\\])*$"); + private InputView() { } @@ -20,6 +26,10 @@ public static int readVendingMachineAmount() { public static List readProducts() { System.out.println("상품명과 가격, 수량을 입력해 주세요."); String input = Console.readLine(); + if (!PRODUCTS_REGEX.matcher(input).matches()) { + throw new IllegalArgumentException( + String.format("%s 유효하지 않은 형식입니다.", Constants.ERROR_PREFIX.getValue())); + } return Arrays.stream(input.split(";")) .map(product -> product.substring(1, product.length() - 1)) .collect(Collectors.toList()); From 28e084187b5ab9b639206a951b2f76185041b05a Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Wed, 22 Nov 2023 19:58:07 +0900 Subject: [PATCH 44/44] =?UTF-8?q?feat(Controller):=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/vendingmachine/controller/Controller.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/vendingmachine/controller/Controller.java b/src/main/java/vendingmachine/controller/Controller.java index 8aa1c001f..e466a13ec 100644 --- a/src/main/java/vendingmachine/controller/Controller.java +++ b/src/main/java/vendingmachine/controller/Controller.java @@ -47,7 +47,7 @@ private InputAmount createInputAmount() { private void repeatPurchaseProduct(VendingMachine vendingMachine, InputAmount inputAmount) { while (canPurchase(vendingMachine, inputAmount)) { OutputView.printRemainingInputAmount(inputAmount.getAmount()); - String productNameToPurchase = InputView.readProductNameToPurchase(); + String productNameToPurchase = repeatReadForInvalid(InputView::readProductNameToPurchase); vendingMachine.purchase(productNameToPurchase, inputAmount); } }