Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 기능 요구 사항

- [ ] 자판기의 보유 금액을 입력한다. `InputView`
- [ ] 자판기의 보유 금액을 기반으로 무작위로 동전의 갯수를 생성한다. `Machine`
- [ ] 생성한 자판기의 동전갯수를 출력한다. `OutputView`
- [ ] 상품명, 가격, 수량을 입력받는다. `InputView`
- [ ] 사용자에게 투입 금액을 입력받는다. `InputView`
- [ ] 구매할 상품 명을 입력받는다. `상품의 최소 금액 > 남은 금액일 때 까지 반복` - `InputView`
- [ ] 상품을 구매하고 남은 돈을 출력한다. `OutputView`
- [ ] 상품을 구매하고 나면 동전을 최소로 해서 거슬러 준다. `동전이 모자랄 땐 남은 금액은 반환하지 않음` `OutputView`
6 changes: 5 additions & 1 deletion src/main/java/vendingmachine/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package vendingmachine;

import vendingmachine.controller.MainController;


public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
MainController mainController = new MainController();
mainController.run();
}
}
16 changes: 0 additions & 16 deletions src/main/java/vendingmachine/Coin.java

This file was deleted.

26 changes: 26 additions & 0 deletions src/main/java/vendingmachine/Validator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package vendingmachine;

import vendingmachine.domain.Product;

public class Validator {

private Validator () {}
public static void validateMachineHasMoneyInput(String money) {
if (Integer.parseInt(money) <= 0) {
throw new IllegalArgumentException("[ERROR] 입력한 금액이 올바르지 않습니다.");
}
}

public static void validateMachineHasMoneyInputType(String money) {
String regExp = "^[0-9]+$";
if (!money.matches(regExp)) {
throw new IllegalArgumentException("[ERROR] 숫자가 아닌 값이 포함되어 있습니다.");
}
}

public static void validateProduct(Product product) {
if (product == null) {
throw new IllegalArgumentException("[ERROR]");
}
}
}
151 changes: 151 additions & 0 deletions src/main/java/vendingmachine/controller/MainController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package vendingmachine.controller;

import vendingmachine.Validator;
import vendingmachine.util.Constant;
import vendingmachine.domain.Coin;
import vendingmachine.domain.Machine;
import vendingmachine.domain.Product;
import vendingmachine.view.InputView;
import vendingmachine.view.OutputView;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class MainController {
private static LinkedHashMap<Coin, Integer> coinMap = generateRandomMachineCoin();
private static LinkedHashMap<Coin, Integer> changeCoins = setChangeMap();

public void run() {
List<Product> products = new ArrayList<>(); // 상품 객체 생성
createProductInfo(products);
int minProductPrice = getMinProductPrice(products);
int userMoneyInput = InputView.inputMoney();
while (userMoneyInput > minProductPrice) {
userMoneyInput = purchaseProduct(products, userMoneyInput);
}
printChangeResult(coinMap, userMoneyInput, changeCoins);
}

private static void printChangeResult(LinkedHashMap<Coin, Integer> coinMap, int userMoneyInput, LinkedHashMap<Coin, Integer> changeCoins) {
OutputView.printCurrentInputMoney(userMoneyInput);
makeChange(userMoneyInput);
OutputView.printChange(changeCoins);
}

private static LinkedHashMap<Coin, Integer> generateRandomMachineCoin() {
Machine machine = new Machine();
LinkedHashMap<Coin, Integer> coinMap = machine.getCoins();
generateMachineHasCoins(machine);
OutputView.printMachineHasCoins(coinMap);
return coinMap;
}

private static void makeChange(int userMoneyInput) {
while (userMoneyInput != 0) {
if (hasCoin(userMoneyInput, 500)) {
calculateChange(500);
userMoneyInput -= 500;
continue;
}
if (hasCoin(userMoneyInput, 100)) {
calculateChange(100);
userMoneyInput -= 100;
continue;
}
if (hasCoin(userMoneyInput, 50)) {
calculateChange(50);
userMoneyInput -= 50;
continue;
}
if (hasCoin(userMoneyInput, 10)) {
calculateChange(10);
userMoneyInput -= 10;
continue;
}
if (checkRemainingCoins()) break;
}
}

private static boolean hasCoin(int userMoneyInput, int coin) {
return userMoneyInput >= coin && coinMap.get(Coin.valueOf(coin)) > 0;
}

private static void createProductInfo(List<Product> products) {
String[] productsInput = InputView.inputProductDetail().split(";");
insertProduct(products, productsInput);
}

private static int purchaseProduct(List<Product> products, int userMoneyInput) {
OutputView.printCurrentInputMoney(userMoneyInput);
String purchasingProduct = InputView.inputPurchaseProduct();
Product inputProduct = getProduct(products, purchasingProduct);
int productPrice = inputProduct.getPrice();
userMoneyInput -= productPrice;
return userMoneyInput;
}

private static void generateMachineHasCoins(Machine machine) {
int machineInputMoney = InputView.inputMachineHoldMoney();
machine.generateCoin(machineInputMoney);
}


private static int generateChange(Map<Coin, Integer> coinMap, int userMoneyInput ,Map<Coin, Integer> changeCoins) {
calculateChange(10);
userMoneyInput -= 10;
return userMoneyInput;
}

private static boolean checkRemainingCoins() {
return coinMap.get(Coin.COIN_500) == 0 && coinMap.get(Coin.COIN_100) == 0 && coinMap.get(Coin.COIN_50) == 0 && coinMap.get(Coin.COIN_10) == 0;
}

private static int getMinProductPrice(List<Product> products) {
int minProductPrice = products.get(0).getPrice();
for (int i = 1; i < products.size(); i++) {
if (minProductPrice > products.get(i).getPrice()) {
minProductPrice = products.get(i).getPrice();
}
}
return minProductPrice;
}

private static void insertProduct(List<Product> products, String[] productsInput) {
for (String product : productsInput) {
String productDetail = product.replaceAll(Constant.REGEX, "");
String[] productInfo = productDetail.split(",");
Product freshProduct = new Product(productInfo[0], Integer.parseInt(productInfo[1]), Integer.parseInt(productInfo[2]));
products.add(freshProduct);
}
}

private static LinkedHashMap<Coin, Integer> setChangeMap() {
LinkedHashMap<Coin, Integer> changeCoins = new LinkedHashMap<>();
setChangeMap(changeCoins);
return changeCoins;
}

private static Product getProduct(List<Product> products, String purchasingProduct) {
Product inputProduct = products.stream()
.filter(x -> x.getName().equals(purchasingProduct))
.findFirst()
.orElse(null);
Validator.validateProduct(inputProduct);
return inputProduct;
}

private static void calculateChange(int inputCoin) {
Coin coin = Coin.valueOf(inputCoin);
coinMap.put(coin, coinMap.get(coin) - 1);
changeCoins.put(coin, changeCoins.get(coin) + 1);
}

private static void setChangeMap(Map<Coin, Integer> coinsMap) {
coinsMap.put(Coin.COIN_500, 0);
coinsMap.put(Coin.COIN_100, 0);
coinsMap.put(Coin.COIN_50, 0);
coinsMap.put(Coin.COIN_10, 0);
}
}
35 changes: 35 additions & 0 deletions src/main/java/vendingmachine/domain/Coin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package vendingmachine.domain;

import java.util.Arrays;
import java.util.function.Supplier;
import java.util.stream.Stream;

public enum Coin {
COIN_500(500),
COIN_100(100),
COIN_50(50),
COIN_10(10);

private final int amount;

Coin(final int amount) {
this.amount = amount;
}

/**
* 이 함수가 요구하는 것은 coin이라는 숫자를 받았을때 Coin Enum을 가져오는 것
* @param coin
* @return
*/
public static Coin valueOf(int coin) {
return Arrays.stream(Coin.values())
.filter(Coin -> Coin.amount == coin)
.findFirst()
.orElseThrow(null);
}

@Override
public String toString() {
return this.amount + "원";
}
}
58 changes: 58 additions & 0 deletions src/main/java/vendingmachine/domain/Machine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package vendingmachine.domain;

import camp.nextstep.edu.missionutils.Randoms;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

public class Machine {
private LinkedHashMap<Coin, Integer> coins;

public Machine() {
this.coins = generateCoinMap();
}

public LinkedHashMap<Coin, Integer> getCoins() {
return coins;
}

private LinkedHashMap<Coin, Integer> generateCoinMap() {
LinkedHashMap<Coin, Integer> coinMap = new LinkedHashMap<>();
coinMap.put(Coin.COIN_500, 0);
coinMap.put(Coin.COIN_100, 0);
coinMap.put(Coin.COIN_50, 0);
coinMap.put(Coin.COIN_10, 0);
return coinMap;

}

public void generateCoin(int moneyInput) {
List<Integer> coinUnit = getCoinUnit();
generateRandomCoin(moneyInput, coinUnit);
}

private void generateRandomCoin(int moneyInput, List<Integer> coinUnit) {
while(moneyInput > 0) {
int pickRandomNum = Randoms.pickNumberInList(coinUnit);
Coin randomCoin = Coin.valueOf(pickRandomNum);
if (isInputRemainingMoney(moneyInput, pickRandomNum)) continue;
moneyInput -= pickRandomNum;
coins.put(randomCoin, coins.get(randomCoin) + 1);
}
}

private static boolean isInputRemainingMoney(int moneyInput, int pickRandomNum) {
return moneyInput - pickRandomNum < 0;
}

private static List<Integer> getCoinUnit() {
List<Integer> coinUnit = new ArrayList<>();
coinUnit.add(500);
coinUnit.add(100);
coinUnit.add(50);
coinUnit.add(10);
return coinUnit;
}

}
29 changes: 29 additions & 0 deletions src/main/java/vendingmachine/domain/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package vendingmachine.domain;

import java.util.Arrays;
import java.util.stream.Stream;

public class Product {

private String name;
private int price;
private int quantity;

public Product(String name, int price, int quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}

public String getName() {
return name;
}

public int getPrice() {
return price;
}

public int getQuantity() {
return quantity;
}
}
5 changes: 5 additions & 0 deletions src/main/java/vendingmachine/util/Constant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package vendingmachine.util;

public class Constant {
public static final String REGEX= "[^ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9,]";
}
7 changes: 7 additions & 0 deletions src/main/java/vendingmachine/util/MessageConstant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package vendingmachine.util;

public class MessageConstant {
public static final String INPUT_VENDING_MACHINE_HAS_MONEY_MSG = "자판기가 보유하고 있는 금액을 입력해 주세요.";
public static final String MACHINE_HAS_COIN_MSG = "자판기가 보유한 동전";

}
Loading