Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[자판기] 김승진 미션 제출합니다. #3

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ba649e5
docs(README): 기능 목록 추가
ohksj77 Sep 25, 2023
d147536
feat: 자판기 보유 금액 입력 요청 메시지 출력
ohksj77 Sep 25, 2023
5175785
feat: 자판기 보유 금액 입력 기능
ohksj77 Sep 25, 2023
5d3b2d5
docs(README): 구현 클래스 추가
ohksj77 Sep 25, 2023
eccf713
feat(RandomCoinGenerator): 랜덤 코인 생성
ohksj77 Sep 25, 2023
897cb2e
feat: 보유 동전 저장 기능
ohksj77 Sep 25, 2023
ac78a65
feat: 보유 동전 출력 기능
ohksj77 Sep 25, 2023
96d078a
feat: 제품 입력 요청 메시지 출력
ohksj77 Sep 25, 2023
b2547cd
feat: 제품 입력 기능
ohksj77 Sep 25, 2023
40e26b0
docs(README): 구현 클래스 정보 업데이트
ohksj77 Sep 25, 2023
471cd5b
feat: 제품 저장 기능
ohksj77 Sep 25, 2023
e8cd1dd
feat: 투입 금액 입력 요청 메시지 출력
ohksj77 Sep 25, 2023
03da176
feat(UserMoney): 유저 금액 도메인 추가
ohksj77 Sep 25, 2023
96d3cef
feat: 유저 금액 입력 기능
ohksj77 Sep 25, 2023
c1fc669
feat: 유저 금액 저장 기능
ohksj77 Sep 25, 2023
69e88d7
feat: 구매 상품 요청 메시지 출력
ohksj77 Sep 25, 2023
e0b4d02
feat: 구매 상품 입력
ohksj77 Sep 25, 2023
6f27cb0
feat: 상품 구매 기능
ohksj77 Sep 25, 2023
e16d67f
feat: 잔여 제품 존재 여부 필터링 기능
ohksj77 Sep 25, 2023
5cb4fda
feat: 잔돈 코인 반환 기능
ohksj77 Sep 25, 2023
96dc925
refactor: 상수 적용 및 개수 필드명 quantity로 수정
ohksj77 Sep 25, 2023
c458832
test: 테스트 추가
ohksj77 Sep 25, 2023
f55277b
refactor: 리팩터링 및 도메인명 변경
ohksj77 Sep 25, 2023
022dec7
fix: 상태 오류 수정
ohksj77 Sep 25, 2023
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
107 changes: 107 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
## 기능 목록
- [x] 자판기 보유 금액 생성
- [x] 자판기 보유 금액 입력 요청 메시지 출력
- [x] 자판기 보유 금액 입력
- [x] 숫자인지 검증
- [x] 10원으로 나누어 떨어지는지 검증
- [x] 자판기 보유 동전 생성
- [x] 자판기 보유 동전 랜덤 생성
- [x] 자판기 보유 동전 저장
- [x] 자판기 보유 동전 출력
- [x] 상품 가격 및 수량 저장
- [x] 상품명, 가격, 수량 입력 요청 메시지 출력
- [x] 상품명, 가격, 수량 입력
- [x] 대괄호로 묶어 세미콜론으로 구분했는지 검증
- [x] 상품 저장
- [x] 투입 금액 설정
- [x] 투입 금액 입력 요청 메시지 출력
- [x] 투입 금액 입력
- [x] 숫자인지 검증
- [x] 투입 금액 저장
- [x] 상품 구매
- [x] 구매할 상품명 입력 요청 메시지 출력
- [x] 구매할 상품명 입력
- [x] 상품 구매
- [x] 금액 차감
- [x] 차감된 투입 금액 출력
- [x] 남은 금액이 최저 가격보다 적거나, 모든 상품 소진시 잔돈 반환
- [x] 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환 (잔액 부족시 or 나눠 떨어지지 않을시)
- [x] 잔돈 동전별로 출력

## 구현 클래스 목록

- VendingMachineController
- start()

- OutputView
- printVendingMachineMoney()
- printCoins()
- printProductRequest()
- printUserMoneyRequest()
- printBuyProductRequest()
- printRemainingMoney()

- InputView
- readVendingMachineMoney()
- readProducts()
- readUserMoney()
- readBuyProduct()

- InputManager
- readVendingMachineMoney()
- readProducts()
- readUserMoney()

- InputValidator
- validateNumeric()
- validateProducts()

- VendingMachineService
- makeCoins
- saveProducts()
- saveUserMoney()
- findRemainingUserMoney()
- purchaseProduct()

- VendingMachineRepository
- saveCoins()
- findCoins()
- saveProducts()
- findProducts()
- saveUserMoney()
- findUserMoney()

- RandomCoinGenerator
- generate()

- VendingMachineMoney
- getValue()
- hasMoney()
- minusValue()

- Coins
- addCoin()

- Product
- getName()
- getPrice()
- hasSameName()
- purchase()

- Products
- hasLowerPrice()
- getProduct()

- UserMoney
- getAmount()
- hasRemainingMoney()
- decrease()

- BuyProduct
- getName()

## 열거형 목록
- Coin
- VendingMachineMessage
- ErrorMessage
- BuyStatus
4 changes: 3 additions & 1 deletion src/main/java/vendingmachine/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package vendingmachine;

import vendingmachine.controller.VendingMachineController;

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

This file was deleted.

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

public enum BuyStatus {
CONTINUE, FINISHED;

public boolean isContinue() {
return this == CONTINUE;
}
}
38 changes: 38 additions & 0 deletions src/main/java/vendingmachine/constant/Coin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package vendingmachine.constant;

import vendingmachine.domain.VendingMachineMoney;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

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

private final int amount;

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

public static List<Integer> getCoinByVendingMachineMoney(final VendingMachineMoney vendingMachineMoney) {
return Arrays.stream(values())
.filter(value -> value.amount <= vendingMachineMoney.getValue())
.map(coin -> coin.amount)
.collect(Collectors.toList());
}

public static Coin valueOfAmount(final int amount) {
return Arrays.stream(values())
.filter(value -> value.amount == amount)
.findFirst()
.orElseThrow(() -> new IllegalStateException(ErrorMessage.INVALID_AMOUNT.getMessage()));
}

public int getAmount() {
return this.amount;
}
}
22 changes: 22 additions & 0 deletions src/main/java/vendingmachine/constant/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package vendingmachine.constant;

public enum ErrorMessage {
NOT_NUMERIC("입력값은 숫자만 가능합니다."),
INVALID_MONEY("숫자가 단위로 떨어지지 않습니다."),
INVALID_AMOUNT("잘못된 Amount 입니다."),
INVALID_PRODUCTS_INPUT("잘못된 Product 입력입니다."),
NEGATIVE_NUMBER("음수는 받을 수 없습니다."),
PRODUCT_NOT_EXISTS("존재하지 않는 상품입니다."),
NOT_ENOUGH_MONEY("잔액이 충분하지 않습니다.");

private static final String ERROR_PREFIX = "[ERROR] ";
private final String message;

ErrorMessage(final String message) {
this.message = message;
}

public String getMessage() {
return ERROR_PREFIX + message;
}
}
22 changes: 22 additions & 0 deletions src/main/java/vendingmachine/constant/VendingMachineMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package vendingmachine.constant;

public enum VendingMachineMessage {

VENDING_MACHINE_MONEY_REQUEST("자판기가 보유하고 있는 금액을 입력해 주세요."),
VENDING_MACHINE_COINS("자판기가 보유한 동전"),
PRODUCT_REQUEST("상품명과 가격, 수량을 입력해 주세요."),
USER_MONEY_REQUEST("투입 금액을 입력해 주세요."),
REMAINING_MONEY("투입 금액: %d원"),
BUY_PRODUCT_REQUEST("구매할 상품명을 입력해 주세요."),
CHANGE_MONEY("잔돈");

private final String message;

VendingMachineMessage(final String message) {
this.message = message;
}

public String getMessage() {
return this.message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package vendingmachine.controller;

import vendingmachine.constant.BuyStatus;
import vendingmachine.domain.*;
import vendingmachine.io.InputManager;
import vendingmachine.io.OutputView;
import vendingmachine.service.VendingMachineService;

public class VendingMachineController {

private final OutputView outputView;
private final InputManager inputManager;
private final VendingMachineService vendingMachineService;

public VendingMachineController() {
this.outputView = new OutputView();
this.inputManager = new InputManager();
this.vendingMachineService = new VendingMachineService();
}


public void start() {
makeVendingMachineMoney();
makeProduct();
makeUserMoney();
buyProducts();
changeCoins();
}

private void changeCoins() {
final UserMoney userMoney = vendingMachineService.findRemainingUserMoney();
outputView.printRemainingMoney(userMoney);
final Coins coins = vendingMachineService.changeMoney(userMoney);
outputView.printChangeMoney(coins);
}

private void buyProducts() {
BuyStatus buyStatus = BuyStatus.CONTINUE;

while (buyStatus.isContinue()) {
final UserMoney userMoney = vendingMachineService.findRemainingUserMoney();
outputView.printBuyProductRequest(userMoney);
final BuyProduct buyProduct = inputManager.readBuyProduct();
buyStatus = vendingMachineService.purchaseProduct(buyProduct, userMoney);
}
}

private void makeUserMoney() {
outputView.printUserMoneyRequest();
final UserMoney userMoney = inputManager.readUserMoney();
vendingMachineService.saveUserMoney(userMoney);
}

private void makeProduct() {
outputView.printProductRequest();
final Products products = inputManager.readProducts();
vendingMachineService.saveProducts(products);
}

private void makeVendingMachineMoney() {
outputView.printVendingMachineMoneyRequest();
final VendingMachineMoney vendingMachineMoney = inputManager.readVendingMachineMoney();
final Coins coins = vendingMachineService.makeCoins(vendingMachineMoney);
outputView.printCoins(coins);
}
}
14 changes: 14 additions & 0 deletions src/main/java/vendingmachine/domain/BuyProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package vendingmachine.domain;

public class BuyProduct {

private final String name;

public BuyProduct(final String name) {
this.name = name;
}

public String getName() {
return this.name;
}
}
50 changes: 50 additions & 0 deletions src/main/java/vendingmachine/domain/Coins.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package vendingmachine.domain;

import vendingmachine.constant.Coin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Coins {

private static final String COIN_FORMAT = "%d원 - %d개\n";
private final List<Coin> coins;


public Coins() {
this.coins = new ArrayList<>();
}

public void addCoin(final Coin coin) {
this.coins.add(coin);
}

public String getCoinMessage() {
return Arrays.stream(Coin.values())
.map(c -> {
final long count = this.coins.stream().filter(coin -> c == coin).count();
return String.format(COIN_FORMAT, c.getAmount(), count);
}).collect(Collectors.joining());
}

public Coins calculateCoin(final UserMoney userMoney) {
int userMoneyAmount = userMoney.getAmount();
return getCalculateResult(userMoneyAmount);
}

private Coins getCalculateResult(int userMoneyAmount) {
final Coins result = new Coins();

for (final Coin coin : this.coins) {
final int coinAmount = coin.getAmount();
if (coinAmount > userMoneyAmount) {
continue;
}
userMoneyAmount -= coinAmount;
result.addCoin(coin);
}
return result;
}
}
Loading