Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
43fa28a
docs(readme): 기능 구현 목록 정리
Gyuchool Dec 10, 2021
7d3308e
feat(inputView): 자판기가 보유하고 있는 금액 입력받는 기능 구현
Gyuchool Dec 10, 2021
f891380
docs(readme): 거스름돈 생성하는 기능 목록 추가
Gyuchool Dec 10, 2021
919cd0b
feat(change): 처음 자판기에 입력받은 돈으로 랜덤한 거스름돈 생성하는 기능 구현
Gyuchool Dec 10, 2021
c69d3c3
feat(outputView): 자판기가 보유한 동전 출력하는 기능 구현
Gyuchool Dec 10, 2021
707b043
feat(inputView): 상품명과 가격, 수량을 입력받는 기능 구현
Gyuchool Dec 10, 2021
8149f91
docs(readme): 예외 처리 클래스 분리
Gyuchool Dec 10, 2021
6c83942
feat(exception): 세미콜론으로 구별되는지 예외처리
Gyuchool Dec 10, 2021
520ed71
feat(exception): 개별상품이 대괄호로 묶여있는지 예외처리
Gyuchool Dec 10, 2021
4aaf7ab
feat(inputView): 투입 금액을 입력받는 기능 구현
Gyuchool Dec 10, 2021
dd9e87d
docs(readme): 정수가 아닌 입력에 대한 예외처리사항 추가
Gyuchool Dec 10, 2021
8fa7926
feat(beverages): 일급 컬랙션 클레스 생성
Gyuchool Dec 10, 2021
c31c68d
feat(exception): 입력받은 금액과 가격, 수량이 정수가 아니면 예외 처리
Gyuchool Dec 10, 2021
196cf70
refactor(exception): validation 기능하는 함수와 error출력하는 함수 분리
Gyuchool Dec 10, 2021
873183e
refactor(exception): 정수형식 검증 로직 재사용가능하도록 수정
Gyuchool Dec 10, 2021
2f5ce11
feat(money): 금액 객체화 및 그에따른 함수들 수정
Gyuchool Dec 10, 2021
ac8b0cf
docs(readme): 남은 투입 금액 출력하는 기능 구현 추가
Gyuchool Dec 10, 2021
81ee501
feat(outputView): 남은 투입 금액 출력하는 기능 구현
Gyuchool Dec 10, 2021
feab4cb
refactor(inputView): getHavingMoney함수 라인 줄이기
Gyuchool Dec 10, 2021
c5b1cf5
feat(inputView): 구매할 상품명을 입력받는 기능 구현
Gyuchool Dec 10, 2021
21f4eaa
feat(money): 구매 상품에 따라 가격 감소하는 기능 구현
Gyuchool Dec 10, 2021
3ac15b5
refactor(beverages): 자료구조 map으로 바꾸고 beverage에 있던 음료 개수 변수인 stock을 bev…
Gyuchool Dec 10, 2021
21e7a16
feat(beverages): 구매 상품에 따라 수량 감소하는 기능 구현
Gyuchool Dec 10, 2021
d516e48
docs(readme): 종료되는 경우 처리하는 담당 클래스 변경
Gyuchool Dec 10, 2021
b757ccc
feat(beverages): 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 잔돈을 반환하는 기능 구현
Gyuchool Dec 10, 2021
994f781
style(machineController): 변수명 가독성 좋게 변경
Gyuchool Dec 10, 2021
9e698bc
style: 출력형식 조정 및 변수에 final 추가
Gyuchool Dec 10, 2021
359bb1c
refactor(change): 클래스 내부에 사용하지 않는 맴버 변수 제거
Gyuchool Dec 10, 2021
7d5f989
refactor(vendingMachine): vendinMachine클래스내에서 상품 거래 작업이 일어나도록 클래스 추가
Gyuchool Dec 10, 2021
6892294
docs(readme): 구현했던 사항 정리 및 money, change가 하는 일 vendingMachine에게 위임
Gyuchool Dec 10, 2021
bff0397
feat(vendingMachine): 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환하도록 기능 구현
Gyuchool Dec 11, 2021
43fb3a1
feat(outputView): 종료 되었을때, 남은 투입 금액과 잔돈을 출력해주는 기능 구현
Gyuchool Dec 11, 2021
1dd611d
refactor(vendingMachine, change): 안쓰는 매서드 제거 및 매서드 이름 의미 분명해지도록 수정
Gyuchool Dec 11, 2021
c533b62
refactor(beverages): 비즈니스에 종속족인 자료구조를 위한 매서드 위치 수정
Gyuchool Dec 11, 2021
14f5219
style(vendingMachine): 매서드 및 변수명 의미 분명해지도록 변경
Gyuchool Dec 11, 2021
53f2a76
feat(vendingMachine): 잔돈을 돌려줄때 보유한 최소 개수의 동전으로 돌려주는 기능 구현
Gyuchool Dec 11, 2021
c1b9264
feat(exception): 입력된 상품 가격이 100원부터 시작하며 10원으로 나누어 떨어지는지 예외 처리
Gyuchool Dec 11, 2021
5f5ab47
feat(exception): 입력된 상품 수량이 0이하이면 예외 처리
Gyuchool Dec 11, 2021
82e4995
docs(readme): 기능 담당 클래스 변경 및 가독성 좋게 README 정리
Gyuchool Dec 11, 2021
fd111e9
feat(change): 투입 금액으로 동전 생성하지 않도록 기능 구현
Gyuchool Dec 11, 2021
317511a
feat(exception): 에러 발생시 에러 메시지 출력 후 해당 부분부터 다시 입력을 받는 기능 구현
Gyuchool Dec 11, 2021
e738dc9
refactor(inputValidator): 가격과 수량의 형식을 검증하는 매서드 위치를 Validator클래스로 이동
Gyuchool Dec 11, 2021
84da695
refactor(inputValidator): 개별상품 사이에 세미콜론으로 구별하는지 점검하는 로직 변경
Gyuchool Dec 11, 2021
dd82cd6
refactor(inputValidator): 대괄호 제거하는 로직 정규식으로 변경
Gyuchool Dec 11, 2021
8b5801f
refactor(machineController): 존재하지 않는 상품 구매하려고 할때 예외 처리
Gyuchool Dec 11, 2021
6502e8c
docs(readme): 투입 금액이 구매하려는 상품보다 작을 경우 구매 불가 예외 처리 추가
Gyuchool Dec 11, 2021
1c4c6db
feat(exception): 투입 금액이 구매하려는 상품보다 적을 경우 구매 불가 예외 처리
Gyuchool Dec 11, 2021
cc24fc9
refactor: 사용하지 않는 메서드 제거 및 불필요한 구문 제거
Gyuchool Dec 11, 2021
b9bee35
refactor(change): 거스름돈 생성하는 로직의 유효성 검증 매서드 분리
Gyuchool Dec 11, 2021
750dfed
style(inputValidator): 맴버 변수 선언 위치 checkStyle에 맞게 조정
Gyuchool Dec 11, 2021
0fc27ba
docs(readme): 상품 이름 입력할때 공백 입력이 들어오면 예외 처리 추가
Gyuchool Dec 11, 2021
6d2ee79
feat(exception): 상품 이름 입력할때 공백 입력이 들어오면 예외 처리
Gyuchool Dec 11, 2021
fdabae3
docs(readme): 상품 정보 입력할때 상품 이름, 가격, 수량 중 하나라도 입력이 안들어오면 예외 처리
Gyuchool Dec 11, 2021
4837797
style(readme): 가독성 좋아보이게 마크다운 문법 활용하여 README 수정
Gyuchool Dec 11, 2021
b4ca74f
feat(exception): 상품 정보 입력할때 상품 이름, 가격, 수량 중 하나라도 입력이 안 들어오면 예외 처리
Gyuchool Dec 11, 2021
6f1187a
refactor(exception): 단일 상품일경우 ;(세미콜론)없이 입력받도록 수정
Gyuchool Dec 11, 2021
d0a5e2d
docs(readme): 동일 이름의 상품을 등록할때 예외 처리 추가
Gyuchool Dec 11, 2021
e62a104
feat(exception): 동일 이름의 상품을 등록할때 예외 처리
Gyuchool Dec 11, 2021
d3f8677
style: java code convention에 맞게 수정
Gyuchool Dec 13, 2021
6bf726f
docs(readme): ;및 []중복 입력 발생시 예외 처리 사항 추가
Gyuchool Dec 13, 2021
25367ba
refactor(exception): 정규식 수정으로 ; 및 [] 중복 입력 발생시 에러 처리
Gyuchool Dec 13, 2021
903bf58
refactor(vendingMachine): 구매 가능 여부 검증 로직 수정 및 디렉토리 위치 변경
Gyuchool Dec 13, 2021
f944afb
refactor(coin): 하드 코딩된 상수 변경
Gyuchool Dec 13, 2021
7689906
refactor: for문 반복문을 lambda식으로 변환
Gyuchool Dec 14, 2021
9ce7369
docs(readme): 반환되지 않은 금액은 자판기에 남고 반환된만큼 동전 개수가 줄도록하는 기능 추가
Gyuchool Dec 14, 2021
14d522b
feat(vendingMachine): 반환되지 않은 금액은 자판기에 남도록 구현
Gyuchool Dec 14, 2021
2923275
test(validator): 올바른 입력으로 들어왔을때 입력 폼 검증 테스트
Gyuchool Dec 14, 2021
987094c
test(validator): 세미클론 존재 여부와 위치에 따라 입력폼 검증 실패 테스트
Gyuchool Dec 14, 2021
4ebd633
test(validator): 금액이 100원 이상 10원으로 나누어 떨어질때는 예외가 발생하지 않는지 검증 테스트
Gyuchool Dec 14, 2021
a1ce6dc
test(validator): 금액이 100원 미만이거나 10원으로 나누어 떨어지지 않을때 예외 발생하는 실패 테스트
Gyuchool Dec 14, 2021
65cd763
test(validator): 입력 상품의 수량이 음수일때 실패 테스트
Gyuchool Dec 14, 2021
62524cd
style(test): 매서드명 의미가 분명해지도록 수정
Gyuchool Dec 14, 2021
56d1012
refactor(test): 투입금액 테스트에서 상품 금액 테스트로 수정
Gyuchool Dec 14, 2021
3397546
test(validator): 투입 금액이 10원 단위가 아닐때 실패 테스트
Gyuchool Dec 14, 2021
a60a110
style(validator): 변수명 형식 카멜 케이스로 변환
Gyuchool Dec 14, 2021
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
93 changes: 93 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# 3주차 미션 - 🧃 자판기

## 📢 작동 순서

```
1. 자판기가 보유하고 있는 금액을 입력 받고, 동전을 무작위로 생성한다.
- 투입 금액으로는 동전을 생성하지 않는다.

2. 자판기가 보유한 동전을 보여준다.

3. 상품명, 가격, 수량을 입력하여 상품을 추가한다.
- 상품 가격은 100원부터 시작하며, 10원으로 나누어떨어져야 한다.

4. 사용자가 금액을 투입한다.

5. 투입한 금액(남은 금액)을 출력하고 구매할 상품명을 입력받는다.

6. 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 바로 잔돈을 돌려준다. (종료)
- 반환되지 않은 금액은 자판기에 남는다.
- 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다.
- 잔돈을 돌려줄 때 현재 보유한 최소 개수의 동전으로 잔돈을 돌려준다.
- 지폐를 잔돈으로 반환하는 경우는 없다고 가정한다.
```

## 💻 기능 구현 목록

### MachineController

- 전체적인 진행이 일어나는 클래스이다.

### VendingMachine

- Beverages(음료)와 Money(투입 금액) 그리고 Change(잔돈)를 가지고 있다.
- [x] 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환하도록 구현
- [x] 잔돈을 돌려줄때 보유한 최소 개수의 동전으로 돌려주는 기능 구현
- [x] 반환되지 않은 금액은 자판기에 남도록 구현

### Beverage

- [x] 상품명, 가격, 수량을 가지고 있다.

### Beverages

- Beverage의 상태와 행위를 관리하는 클래스이다.
- 비즈니스에 종속적으로 구현한다.
- [x] 구매 상품에 따라 수량 감소하는 기능 구현
- [x] 남은 금액이 상품의 최저 가격보다 적거나, 모든 상품이 소진된 경우 잔돈을 반환하는 기능 구현

### Money

- 자판기가 현재 보유하고 있는 금액이다.
- [x] 구매 상품에 따라 가격 감소하는 기능 구현

### Change

- 자판기가 가지고 있는 거스름 돈 클래스이다.
- [x] 처음 자판기에 입력받은 돈으로 랜덤한 거스름돈 생성하는 기능 구현
- [x] 투입 금액으로 동전 생성하지 않도록 기능 구현


### InputView

- [x] 자판기가 보유하고 있는 금액 입력받는 기능 구현
- [x] 상품명과 가격, 수량을 입력받는 기능 구현
- [x] 투입 금액을 입력받는 기능 구현
- [x] 구매할 상품명을 입력받는 기능 구현

### OutputView

- [x] 자판기가 보유한 동전 출력하는 기능 구현
- [x] 남은 투입 금액 출력하는 기능 구현
- [x] 남은 자판기의 금액을 출력하는 기능 구현
- [x] 종료 되었을때, 남은 투입 금액과 잔돈을 출력해주는 기능 구현

### 예외 처리

- Validator에서 점검 후, exception발생시 Exception 클래스에서 처리해준다.
- [x] 사용자가 잘못된 값을 입력할 경우 ```IllegalArgumentException```를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는 기능 구현
- [x] 입력된 ```상품 가격```이 100원부터 시작하며 10원으로 나누어 떨어지는지 예외 처리
- [x] 입력 형식 예외 처리
- [x] 개별상품이 ```[]``` 로 묶여있는지 예외 처리
- [x] ```;```으로 구별 되는지 예외 처리
- [x] ```투입 금액```이 정수가 아니면 예외 처리
- [x] 입력받은 ```가격과 수량```이 정수가 아니면 예외 처리
- [x] 입력된 ```상품 수량```이 0이하이면 예외 처리
- [x] 존재하지 않는 상품 구매하려고 할때 예외 처리
- [x] ```투입 금액```이 구매하려는 ```상품 가격```보다 적을 경우 구매 불가 예외 처리
- [x] ```상품 이름``` 입력할때 공백 입력이 들어오면 예외 처리
- [x] 상품 정보 입력할때 ```상품 이름, 가격, 수량``` 중 하나라도 입력이 안 들어오면 예외 처리
- [x] 동일 이름의 상품을 등록할때 예외 처리
- [x] 입력 형식에서 ```;``` 또는 ```[]``` 중복에 따른 구체적 예외 처리 사항
ex) ```[콜라,1500,20];[사이다,1,10]``` 또는 ```[콜라,1500,20]];[[사이다,1,10]```또는```[콜라,1500,20];;[사이다,1,10]``` 또는 ```[콜라,1500,20];[사이다,1,10];```

10 changes: 7 additions & 3 deletions 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.MachineController;

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

This file was deleted.

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

import vendingmachine.domain.Beverage;
import vendingmachine.domain.Beverages;
import vendingmachine.domain.Change;
import vendingmachine.domain.Money;
import vendingmachine.service.VendingMachine;
import vendingmachine.exception.InputException;
import vendingmachine.view.InputView;
import vendingmachine.view.OutputView;

public class MachineController {

private VendingMachine vendingMachine;

public void run() {
setting();
progress();
finishWithReturn();
}

private void setting() {
Change changes = new Change();
changes.generateChanges(InputView.getHavingMoney());
OutputView.printHavingMachineCoin(changes);
Beverages beverages = InputView.getItemPriceStock();
Money inputMoney = InputView.getUserInputMoney();
vendingMachine = new VendingMachine(beverages, changes, inputMoney);
}

private void progress() {
while (vendingMachine.canSell()) {
OutputView.printInputMoney(vendingMachine.getMoney());
try {
Beverage beverage = vendingMachine.findBeverageByName(InputView.getItemName());
validationCanBuy(beverage);
vendingMachine.sell(beverage);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}

private void validationCanBuy(Beverage beverage) {
if (vendingMachine.canNotSellOne(beverage)) {
InputException.printNotEnoughMoney();
}
}

private void finishWithReturn() {
Change calculatedChange = vendingMachine.returnChange();
OutputView.printInputMoney(vendingMachine.getMoney());
OutputView.printExtraMoneyAndChange(calculatedChange);
}

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

public class Beverage {
private final String name;
private final int price;

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

public String getName() {
return name;
}

public int getPrice() {
return price;
}

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

import java.util.HashMap;
import java.util.Map;

public class Beverages {
private final Map<Beverage, Integer> beverages;

public Beverages() {
beverages = new HashMap<>();
}

public Map<Beverage, Integer> getBeverages() {
return beverages;
}

public void add(Beverage beverage, int stock) {
beverages.put(beverage, stock);
}

public int size() {
return beverages.size();
}

public void sell(Beverage beverage) {
beverages.put(beverage, beverages.get(beverage) - 1);
}
}
48 changes: 48 additions & 0 deletions src/main/java/vendingmachine/domain/Change.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package vendingmachine.domain;

import java.util.Map;
import java.util.TreeMap;

import camp.nextstep.edu.missionutils.Randoms;

public class Change {

private final Map<Coin, Integer> changes;

public Change() {
changes = new TreeMap<>();
}

public Change(Map<Coin, Integer> changes) {
this.changes = changes;
}

public Map<Coin, Integer> getChanges() {
return changes;
}

public void generateChanges(Money money) {
initChanges();
int tmpMoney = 0;
while (!money.isSame(tmpMoney)) {
int random = Randoms.pickNumberInList(Coin.getList());
if (notValidChange(money, tmpMoney, random)) {
continue;
}
tmpMoney += random;
Coin coin = Coin.getCoin(random);
changes.put(coin, changes.get(coin) + 1);
}
}

private static boolean notValidChange(Money money, int tmpMoney, int random) {
return random == money.getTotal() || money.isSmaller(tmpMoney + random);
}

private void initChanges() {
this.changes.put(Coin.COIN_500, 0);
this.changes.put(Coin.COIN_100, 0);
this.changes.put(Coin.COIN_50, 0);
this.changes.put(Coin.COIN_10, 0);
}
}
34 changes: 34 additions & 0 deletions src/main/java/vendingmachine/domain/Coin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package vendingmachine.domain;

import java.util.Arrays;
import java.util.List;

import vendingmachine.exception.NotFoundCoinException;

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 int getAmount() {
return amount;
}

public static List<Integer> getList() {
return Arrays.asList(COIN_10.getAmount(), COIN_50.getAmount(), COIN_100.getAmount(), COIN_500.getAmount());
}

public static Coin getCoin(int amount) {
return Arrays.stream(Coin.values())
.filter(coin -> coin.getAmount() == amount)
.findAny()
.orElseThrow(NotFoundCoinException::new);
}
}
29 changes: 29 additions & 0 deletions src/main/java/vendingmachine/domain/Money.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package vendingmachine.domain;

public class Money {
private int total;

public Money() {
this.total = 0;
}

public Money(int amount) {
this.total = amount;
}

public int getTotal() {
return total;
}

public boolean isSame(int money) {
return total == money;
}

public boolean isSmaller(int money) {
return total < money;
}

public void spend(int money) {
total -= money;
}
}
Loading