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

[로또] 김연진 미션 제출합니다. #4

Open
wants to merge 61 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
df61745
docs: 기능 구현 목록 작성
homebdy Aug 5, 2023
248b549
feat(LottoController): 게임 시작 기능 구현
homebdy Aug 5, 2023
b1d0b9b
feat(InputFactory): 구입 금액 입력 기능 구현
homebdy Aug 5, 2023
a72eec3
feat(LottoCounter): 입력 금액에 맞는 로또 개수 계산 기능 구현
homebdy Aug 5, 2023
a2e4933
docs: 사용자 로또, 당첨 로또 수정
homebdy Aug 5, 2023
b99af57
feat(InputFactory): 당첨 번호 입력 기능 구현
homebdy Aug 5, 2023
4efc0f7
docs: Lotto 기능 수정
homebdy Aug 5, 2023
7ad77f4
Revert "docs: Lotto 기능 수정"
homebdy Aug 5, 2023
fb95bef
docs: PlayerLotto 수정
homebdy Aug 5, 2023
c3bb7bb
feat(RandomLottoGenerator): 랜덤 번호로 로또 생성 기능 구현
homebdy Aug 5, 2023
fbb2df7
feat(PlayerLottoes): 원하는 개수만큼 로또 생성 기능 구현
homebdy Aug 5, 2023
9841622
feat(WinningLotto): 당첨 로또 생성 기능 구현
homebdy Aug 5, 2023
ba32447
docs: 보너스 숫자 관리 기능 추가
homebdy Aug 5, 2023
af31536
feat(InputFactory): 보너스 숫자 입력 기능 구현
homebdy Aug 5, 2023
3bffc0f
feat(WinningLotto): 보너스 숫자 관리 기능 구현
homebdy Aug 5, 2023
d89c8c9
feat(Ranking): 당첨 결과를 저장하는 enum 구현
homebdy Aug 5, 2023
12c6803
feat(LottoResult): 당첨 결과 계산 기능 구현
homebdy Aug 5, 2023
7356fde
feat(YieldCalculator): 수익률 계산 기능 구현
homebdy Aug 5, 2023
dbef4cb
docs: 로또 당첨 계산 역할 수정
homebdy Aug 6, 2023
7eadde7
feat(LottoResult): 수익률 계산 구현
homebdy Aug 6, 2023
654efd7
feat(OutputView): 당첨 통계 출력 기능 구현
homebdy Aug 6, 2023
25eaa4c
feat(OutputView): 구매 개수 출력 기능 구현
homebdy Aug 6, 2023
150ff62
feat(OutputView): 생성된 랜덤 숫자 로또 출력 기능 구현
homebdy Aug 6, 2023
0992394
feat(OutputView): 수익률 출력 기능 구현
homebdy Aug 6, 2023
c9131a3
feat(InputValidator): 보너스 숫자 예외 처리 기능 구현
homebdy Aug 6, 2023
5a41494
feat(InputValidator): 금액 입력 예외 처리
homebdy Aug 6, 2023
525d50b
feat(InputValidator): 당첨 번호 입력 형식 예외 처리 구현
homebdy Aug 6, 2023
6d8a330
docs: 예외 처리 기능 수정
homebdy Aug 6, 2023
f89612c
chore: Lotto 패키지 이동
homebdy Aug 6, 2023
ae13c46
feat(Lotto): 중복된 숫자 입력시 예외 처리 기능 구현
homebdy Aug 6, 2023
f75f5d4
feat(Lotto): 범위 이외 숫자가 있는 경우 예외 처리 기능 구현
homebdy Aug 6, 2023
41b062d
feat(WinningLotto): 당첨 로또 숫자와 보너스 숫자가 겹칠 경우 예외 처리
homebdy Aug 6, 2023
319051b
feat(OutputView): 오류 메시지 출력 기능 구현
homebdy Aug 6, 2023
798e2b4
feat(LottoController): 게임 진행 기능 구현
homebdy Aug 6, 2023
53113e9
test(Lotto): 로또 생성 테스트
homebdy Aug 6, 2023
0a42128
test(LottoCounter): 로또 개수 계산 기능 테스트
homebdy Aug 6, 2023
6e29881
test(PlayerLottoes): 사용자 로또 생성 테스트
homebdy Aug 6, 2023
58c28af
test(WinningLotto): 정상 입력, 비정상 입력 테스트
homebdy Aug 6, 2023
ab5bd93
test(InputFactory): 입력 예외 테스트
homebdy Aug 6, 2023
51eec34
fix(Ranking): 보너스 숫자 일치 확인 기능 수정
homebdy Aug 6, 2023
6372e8f
test(LottoResult): 순위 확인 기능 테스트
homebdy Aug 6, 2023
7751db4
refactor: 메서드 이름 변경
homebdy Aug 6, 2023
b4d0e28
fix(LottoResult): 당첨 순위 계산 방식 변경
homebdy Aug 8, 2023
4073020
refactor: 당첨 금액 언더바 추가
homebdy Aug 8, 2023
a4f0d03
refactor: 로또 결과 출력시 인덱스 사용 제거
homebdy Aug 8, 2023
7b918e3
refactor(InputFactory): 메시지 출력 내용 제거
homebdy Aug 8, 2023
2b49989
refactor: InputValidator 내 bonusNumber 범위 검증 내용 분리
homebdy Aug 8, 2023
946ddec
refactor: InputValidator 내 금액 단위 검증 내용 분리
homebdy Aug 8, 2023
0448acb
refactor: 당첨 로또 입력 정규식 검증
homebdy Aug 8, 2023
651b83c
refactor: 정규식으로 숫자 검증
homebdy Aug 8, 2023
1191f88
refactor: 메서드 이름 변경
homebdy Aug 8, 2023
83b0247
refactor: LottoResult 클래스 이름 변경
homebdy Aug 8, 2023
d89ecc9
refactor: 로또 당첨 결과를 저장하는 LottoResult 일급 컬렉션 생성
homebdy Aug 8, 2023
ed93615
refactor(LottoResult): result map 초기화
homebdy Aug 8, 2023
92d2afd
refactor: 패키지 명 변경
homebdy Aug 8, 2023
54d4d13
refactor: LottoResultCalculator 호출 시 당첨 결과 계산
homebdy Aug 8, 2023
de443a7
refactor: 게임 중 반복 사용되는 상수 분리
homebdy Aug 8, 2023
673d2bf
refactor(LottoResultCalculator): 당첨 결과 총액 계산 람다식으로 변경
homebdy Aug 8, 2023
1d22ec1
refactor(LottoResult): 당첨 결과 출력 방식 변경
homebdy Aug 10, 2023
fb10ae0
refactor(LottoResultCalculator): 당첨 결과 계산 위치 변경
homebdy Aug 10, 2023
ff698d7
refactor(ProfitCalculator): 수익률 결과 계산 역할 분리
homebdy Aug 10, 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
48 changes: 48 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## 3주차 미션 로또 기능 정의

### 로또 게임 진행 (LottoController)
- [X] 게임 시작
- [x] 게임 진행

### 로또 개수 계산 (LottoCounter)
- [x] 금액에 맞는 로또 개수 계산

### 랜덤 로또 생성 (RandomLottoGenerator)
- [x] 랜덤 번호 6개로 로또 생성

### 사용자 생성 로또 (PlayerLotto)
- [x] 원하는 개수만큼 로또 생성

### 당첨 로또 (WinningLotto)
- [x] 입력받은 당첨 로또 관리
- [x] 보너스 숫자 관리
- [x] 예외) 당첨 로또 숫자와 보너스 숫자가 겹칠 경우

### 로또 당첨 계산 (LottoResult)
- [x] 로또 당첨 여부 판별
- [x] 수익률 계산

### 로또 번호 관리(Lotto)
- [x] 예외) 중복된 수를 입력한 경우
- [x] 예외) 번호가 6개가 아닌 경우
- [x] 예외) 범위 이외의 수인 경우

### 입력 (InputFactory)
- [x] 로또 구입 금액 입력 기능
- [x] 당첨 번호 입력 기능
- [x] 보너스 번호 입력 기능

### 로또 구매 안내 출력 (OutputView)
- [x] 구매 개수 안내
- [x] 생성된 로또 번호 안내
- [x] 당첨 통계 안내
- [x] 수익률 안내

### 예외 처리(InputValidator)
- [x] 보너스 번호를 입력할 때 숫자가 아닌 입력한 경우
- [x] 범위 이외의 숫자를 보너스 숫자로 입력한 경우
- [x] 구입 금액이 1000원 단위가 아닌 경우
- [x] 구입 금액 입력이 숫자가 아닌 경우
- [x] 잘못된 형식으로 당첨 번호를 입력한 경우 (쉼표가 없는 경우 등)


7 changes: 6 additions & 1 deletion src/main/java/lotto/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package lotto;

import lotto.controller.LottoController;
import lotto.view.InputFactory;
import lotto.view.OutputView;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
LottoController lottoController = new LottoController(new OutputView(), new InputFactory());
lottoController.start();
}
}
20 changes: 0 additions & 20 deletions src/main/java/lotto/Lotto.java

This file was deleted.

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

import lotto.model.*;
import lotto.view.InputFactory;
import lotto.view.OutputView;

public class LottoController {

private final OutputView outputView;
private final InputFactory inputFactory;

public LottoController(OutputView outputView, InputFactory inputFactory) {
this.outputView = outputView;
this.inputFactory = inputFactory;
}

public void start() {
try {
PlayerLottoes playerLottoes = buyLotto();
WinningLotto winningLotto = createWinningLotto();
calculateResult(playerLottoes, winningLotto);
} catch (IllegalArgumentException error) {
outputView.printErrorMessage(error.getMessage());
}
}

private PlayerLottoes buyLotto() {
LottoCounter lottoCounter = new LottoCounter(inputFactory.readPurchaseAmount());
PlayerLottoes playerLottoes = new PlayerLottoes(lottoCounter.getLotteryTicket());
outputView.printPurchaseCount(lottoCounter.getLotteryTicket());
outputView.printPlayerLottoes(playerLottoes);
return playerLottoes;
}

private WinningLotto createWinningLotto() {
return new WinningLotto(inputFactory.readWinningNumber(), inputFactory.readBonusNumber());
}

private void calculateResult(PlayerLottoes playerLottoes, WinningLotto winningLotto) {
LottoResultCalculator lottoResultCalculator = new LottoResultCalculator(winningLotto, playerLottoes);
ProfitCalculator profitCalculator = new ProfitCalculator(lottoResultCalculator.getRankingsResult());
outputView.printLottoResult(lottoResultCalculator.getRankingsResult());
outputView.printProfit(profitCalculator.getProfit());
}
}
26 changes: 26 additions & 0 deletions src/main/java/lotto/model/BonusNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package lotto.model;

import lotto.view.ExceptionMessage;

public class BonusNumber {

private final int bonusNumber;
private static final int MAX_NUMBER = 45;
private static final int MIN_NUMBER = 1;

public BonusNumber(int bonusNumber) {
validateCorrectRange(bonusNumber);
this.bonusNumber = bonusNumber;
}

public int getBonus() {
return bonusNumber;
}

private void validateCorrectRange(int bonusNumber) {
if (!(MIN_NUMBER <= bonusNumber && bonusNumber <= MAX_NUMBER)) {
ExceptionMessage exceptionMessage = ExceptionMessage.INCORRECT_RANGE;
throw new IllegalArgumentException(exceptionMessage.toString());
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/lotto/model/Constant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package lotto.model;

public enum Constant {

MAX_NUMBER(45),
MIN_NUMBER(1),
LOTTO_SIZE(6),
LOTTO_PRICE(1000);

private final Integer constant;

Constant(Integer constant) {
this.constant = constant;
}

public Integer getConstant() {
return this.constant;
}
}
52 changes: 52 additions & 0 deletions src/main/java/lotto/model/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package lotto.model;

import lotto.view.ExceptionMessage;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Lotto {
private final List<Integer> numbers;

public Lotto(List<Integer> numbers) {
validateLottoSize(numbers);
validateDuplicateNumber(numbers);
validateRange(numbers);
this.numbers = numbers;
}

private void validateLottoSize(List<Integer> numbers) {
if (numbers.size() != Constant.LOTTO_SIZE.getConstant()) {
ExceptionMessage message = ExceptionMessage.INCORRECT_LOTTO_SIZE;
throw new IllegalArgumentException(message.toString());
}
}

private void validateDuplicateNumber(List<Integer> numbers) {
Set<Integer> numberToSet = new HashSet<>(numbers);
if (numberToSet.size() != Constant.LOTTO_SIZE.getConstant()) {
ExceptionMessage message = ExceptionMessage.DUPLICATE_NUMBER;
throw new IllegalArgumentException(message.toString());
}
}

private void validateRange(List<Integer> numbers) {
numbers.forEach(this::isCorrectRange);
}
private void isCorrectRange(int number) {
int maxNumber = Constant.MAX_NUMBER.getConstant();
int minNumber = Constant.MIN_NUMBER.getConstant();
if (!(minNumber <= number && number <= maxNumber)) {
ExceptionMessage exceptionMessage = ExceptionMessage.INCORRECT_RANGE;
throw new IllegalArgumentException(exceptionMessage.toString());
}
}

public List<Integer> getNumbers() {
return numbers;
}
public boolean hasNumber(int number) {
return numbers.contains(number);
}
}
28 changes: 28 additions & 0 deletions src/main/java/lotto/model/LottoCounter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package lotto.model;

import lotto.view.ExceptionMessage;

public class LottoCounter {

private final int lotteryTicket;

public LottoCounter(int payment) {
validateThousandUnits(payment);
this.lotteryTicket = calculateLotteryTicket(payment);
}

public int calculateLotteryTicket(int payment) {
return payment / Constant.LOTTO_PRICE.getConstant();
}

public int getLotteryTicket() {
return lotteryTicket;
}

private void validateThousandUnits(Integer amount) {
if((amount % Constant.LOTTO_PRICE.getConstant()) != 0) {
ExceptionMessage exceptionMessage = ExceptionMessage.INCORRECT_AMOUNT;
throw new IllegalArgumentException(exceptionMessage.toString());
}
}
}
68 changes: 68 additions & 0 deletions src/main/java/lotto/model/LottoResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package lotto.model;

import java.util.Arrays;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;

public class LottoResult {

private final Map<Ranking, Integer> result;

public LottoResult() {
this.result = new EnumMap<>(Ranking.class);
Arrays.stream(Ranking.values())
.forEach(ranking -> result.put(ranking, 0));
}

public void putResult(Ranking ranking) {
result.put(ranking, result.get(ranking) + 1);
}

public Set<Ranking> keySet() {
return result.keySet();
}

public Integer get(Ranking ranking) {
return result.get(ranking);
}

@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
Arrays.stream(Ranking.values())
.filter(ranking -> ranking != Ranking.NONE)
.forEach(ranking -> {
appendMatchNumberMessage(ranking, stringBuilder);
appendBonusMessage(ranking, stringBuilder);
appendPrizeAmountMessage(ranking, stringBuilder);
appendWinningNumberMessage(ranking, stringBuilder);
stringBuilder.append(ResultMessage.NEW_LINE);
});
return stringBuilder.toString();
}

private void appendMatchNumberMessage(Ranking ranking, StringBuilder stringBuilder) {
ResultMessage resultMessage = ResultMessage.MATCH_NUMBER_MESSAGE;
int matchNumber = ranking.getMatchNumber();
stringBuilder.append(String.format(resultMessage.toString(), matchNumber));
}

private void appendPrizeAmountMessage(Ranking ranking, StringBuilder stringBuilder) {
ResultMessage resultMessage = ResultMessage.AMOUNT_MESSAGE;
int prize = ranking.getPrize();
stringBuilder.append(String.format(resultMessage.toString(), prize));
}

private void appendBonusMessage(Ranking ranking, StringBuilder stringBuilder) {
if (ranking == Ranking.SECOND) {
stringBuilder.append(ResultMessage.BONUS_MESSAGE);
}
}

private void appendWinningNumberMessage(Ranking ranking, StringBuilder stringBuilder) {
ResultMessage resultMessage = ResultMessage.WINNING_NUMBER_MESSAGE;
int winningNumber = result.get(ranking);
stringBuilder.append(String.format(resultMessage.toString(), winningNumber));
}
}
56 changes: 56 additions & 0 deletions src/main/java/lotto/model/LottoResultCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package lotto.model;

import java.util.Arrays;

public class LottoResultCalculator {

private final WinningLotto winningLotto;
private final PlayerLottoes playerLottoes;
private final LottoResult lottoResult;
private static final int THIRD_RANKING_NUMBER = 5;

public LottoResultCalculator(WinningLotto winningLotto, PlayerLottoes playerLottoes) {
this.winningLotto = winningLotto;
this.playerLottoes = playerLottoes;
this.lottoResult = calculateWinningRank();
}

private LottoResult calculateWinningRank() {
LottoResult result = new LottoResult();
for (Lotto lotto : playerLottoes.getLottoes()) {
int matchNumber = calculateMatchNumber(lotto);
boolean matchBonusNumber = hasBonusNumber(matchNumber, lotto);
Ranking ranking = calculateRanking(matchNumber, matchBonusNumber);
result.putResult(ranking);
}
return result;
}

private static Ranking calculateRanking(int matchNumber, boolean isMatchBonus) {
return Arrays.stream(Ranking.values())
.filter(ranking -> ranking.getMatchNumber() == matchNumber)
.filter(ranking -> ranking.getBonusMatch() == isMatchBonus)
.findAny()
.orElse(Ranking.NONE);
}

private Integer calculateMatchNumber(Lotto lotto) {
Lotto winningLottoNumbers = winningLotto.getLotto();
return (int) winningLottoNumbers.getNumbers()
.stream()
.filter(lotto::hasNumber)
.count();
}

private boolean hasBonusNumber(int matchNumber, Lotto lotto) {
if (matchNumber != THIRD_RANKING_NUMBER) {
return false;
}
BonusNumber bonusNumber = winningLotto.getBonusNumber();
return lotto.hasNumber(bonusNumber.getBonus());
}

public LottoResult getRankingsResult() {
return lottoResult;
}
}
Loading