Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
ec830c9
docs : 구현할 기능 목록 정리
brorae Feb 22, 2022
c6112ee
feat : 로또 등수 계산하는 기능 추가
brorae Feb 22, 2022
7f22b10
docs : 구현할 기능 목록 수정
brorae Feb 22, 2022
cb9ae63
refactor : 메서드 분리 및 메소드 순서 정리
brorae Feb 23, 2022
ed649e3
feat : 구입금액, 당첨 번호 입력 받는 기능 추가
brorae Feb 23, 2022
a2da1bf
test : 입력값 테스트 추가
brorae Feb 23, 2022
232e7d3
feat : 로또 번호 자동 생성 기능 추가
brorae Feb 23, 2022
e203093
feat : 로또 자동생성하여 출력하는 기능 추가
brorae Feb 23, 2022
00bd0f4
refactor : 매직넘버 제거 및 상수화
brorae Feb 23, 2022
8322669
refactor : controller에 따라 코드 수정
brorae Feb 23, 2022
4def0e0
feat : 등수 계산 기능 추가
brorae Feb 23, 2022
df43ef5
docs : 기능 예외 사항 추가
brorae Feb 23, 2022
3dddf58
refactor : enum Rank 구조 수정
brorae Feb 23, 2022
6eb9277
feat : 입력 받을 때 예외 사항 추가
brorae Feb 23, 2022
205a81b
feat : 등수 카운트 계산 후 저장하는 기능 추가
brorae Feb 23, 2022
a61d7be
feat : 통계(등수, 수익률) 계산 및 출력 기능 추가
brorae Feb 23, 2022
d89398c
refactor : 불필요 메소드 제거 및 메소드 이름, 접근제어자 수정
brorae Feb 24, 2022
92aef92
refactor : 메소드 구조 수정
brorae Feb 24, 2022
ec4515f
refactor : 에러 메시지 출력하도록 코드 수정
brorae Feb 24, 2022
45486ba
test : 정상적인 input test 추가
brorae Feb 24, 2022
34f38e5
test : 로또 당첨 테스트 케이스 추가
brorae Feb 24, 2022
0653db0
refactor : 구입 금액 입력 예외 사항 추가
brorae Feb 24, 2022
ad82fec
test : Lottos 테스트 코드 추가
brorae Feb 24, 2022
c6c2e3e
refactor : 코드 스타일에 따라 포멧 변경
brorae Feb 24, 2022
7d3b0ca
refactor : Lottos를 생성자를 통해 생성하도록 수정
brorae Feb 25, 2022
e10159f
refactor : InputController에서 객체를 반환하도록 수정
brorae Feb 25, 2022
a5d3294
refactor : 객체 내에서 검증 하도록 수정
brorae Feb 25, 2022
89f3122
refactor : lotto 생성 테스트 케이스 수정 및 추가
brorae Feb 25, 2022
9b7a782
refactor : Money model 추가
brorae Feb 25, 2022
25aa9f2
refactor : BonusNumber model 추가
brorae Feb 25, 2022
45c944f
refactor : 중복 사용 메소드 분리
brorae Feb 25, 2022
2f9dd8e
refactor : interface 추가하여 테스트하기 쉽도록 수정
brorae Feb 25, 2022
6d0dc70
refactor : InputController 제거하여 코드 수정
brorae Feb 25, 2022
07cbcbc
refactor : 코드 인덴트에 맞도록 수정
brorae Feb 25, 2022
6ead5f3
refactor : LottoNumber 모델 추가
brorae Feb 26, 2022
4ff3379
refactor : LottoNumbers 모델 추가하여 Validator 제거
brorae Feb 26, 2022
d0e8c63
refactor : Util 인터페이스 수정
brorae Feb 26, 2022
cfa0583
refactor : 로또 생성기 model로 이동
brorae Feb 26, 2022
0638557
refactor : 메소드 이름 수정 등 전체적인 리팩토링
brorae Feb 26, 2022
565795e
refactor : getter 지양하도록 코드 수정
brorae Feb 26, 2022
6f7f5e1
refactor : 단위 테스트 수정 및 getter 제거
brorae Feb 27, 2022
4ba72d8
refactor : 불필요 import 제거 및 테스트 기능 메소드화
brorae Feb 27, 2022
0fc1d2b
refactor : 불필요 import 제거
brorae Feb 27, 2022
29812b8
refactor : 예외처리 throws 추가
brorae Feb 27, 2022
4124be2
refactor : 메소드 구조 수정
brorae Feb 27, 2022
2efb822
refactor : final 키워드 추가 및 변수 이름 수정
brorae Feb 28, 2022
42b9825
refactor : LottoMachine 모델 추가
brorae Feb 28, 2022
eb76eed
refactor : 불필요한 공백 제거
brorae Feb 28, 2022
83fbf49
refactor : LottoControllerTest 테스트 추가
brorae Feb 28, 2022
5668e1b
refactor : 코드 간결하게 수정
brorae Feb 28, 2022
d94e388
refactor : 메소드, 변수 이름 수정 및 중복 제거
brorae Feb 28, 2022
08d88d1
refactor : 예외처리 종류 수정
brorae Feb 28, 2022
47341e2
refactor : 메소드 간단하게 수정
brorae Mar 1, 2022
95d9f78
refactor : LottoMachine에서 자동 로또 만들도록 수정
brorae Mar 1, 2022
7db0597
refactor : 자동 로또 처리 LottoController로 이동
brorae Mar 1, 2022
cf442a8
refactor : 불필요한 import,공백 제거
brorae Mar 1, 2022
515956f
refactor : 수익률 계산 오류 수정
brorae Mar 1, 2022
429e57c
refactor : 예외 메시지 수정
brorae Mar 1, 2022
9fb8215
refactor : 불필요 의존 제거
brorae Mar 1, 2022
5cd87bb
refactor : 자동 로또 생성 테스트 방식 수정
brorae Mar 1, 2022
fc3c309
refactor : 테스트 메시지 추가
brorae Mar 2, 2022
5d52845
refactor : unmodifiable Collection 수정 및 중복 상수 제거
brorae Mar 2, 2022
2707b67
refactor : throws 키워드 제거
brorae Mar 2, 2022
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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

로또 미션 저장소

1. 구입금액을 입력받는다.
* 0보다 큰 숫자가 아닌 경우, RuntimeException을 발생시킨다.
* 1000보다 작은 수 일 경우
2. 당첨 번호를 입력받는다.
* 6개가 아닌 경우
* 문자가 들어온 경우
* 1-45 사이의 수가 아닌경우
* 중복 숫자인 경우
3. 보너스 번호를 입력받는다.
* 1-45 사이의 숫자가 아닌경우
* 당첨 번호와 중복된 경우
4. 로또 번호를 자동으로 생성한다.
5. 등수를 계산한다.
6. 통계를 저장하고 출력한다.




## 우아한테크코스 코드리뷰

- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)

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

import lotto.controller.LottoController;
import lotto.model.generator.AutoLottoGenerator;

public class Application {
public static void main(String[] args) {
LottoController lottoController = new LottoController(new AutoLottoGenerator());

try {
lottoController.run();
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
}
85 changes: 85 additions & 0 deletions src/main/java/lotto/controller/LottoController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package lotto.controller;

import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import lotto.model.LottoMachine;
import lotto.model.Money;
import lotto.model.WinningLotto;
import lotto.model.generator.LottoGenerator;
import lotto.model.number.LottoNumber;
import lotto.model.number.LottoNumbers;
import lotto.view.InputView;
import lotto.view.ResultView;

public class LottoController {

private static final String NOT_NUMBER_ERROR_MESSAGE = "[ERROR] 문자가 입력되었습니다.";
private static final String NUMBER_REGEX = "\\d+";

private LottoGenerator lottoGenerator;

public LottoController(LottoGenerator lottoGenerator) {
this.lottoGenerator = lottoGenerator;
}

public void run() {
LottoMachine lottoMachine = new LottoMachine(lottoGenerator, validateMoney(InputView.inputMoney()));
ResultView.printBuyingLottosResult(lottoMachine.getLottos());
WinningLotto winningLotto = makeWinningLotto(InputView.inputWinningNumbers(),
InputView.inputBonusNumber());
lottoMachine.calculateResult(winningLotto);
ResultView.printTotalRankResult(lottoMachine);
}

private Money validateMoney(String money) {
if (!Pattern.matches(NUMBER_REGEX, money)) {
throw new IllegalArgumentException(Money.MONEY_ERROR_MESSAGE);
}
return new Money(Integer.parseInt(money));
}

private WinningLotto makeWinningLotto(String winningNumbers, String bonusNumber) {
LottoNumbers lottoNumbers = splitWinningNumbers(winningNumbers);
LottoNumber lottoBonusNumber = new LottoNumber(toIntBonusNumber(bonusNumber));
return new WinningLotto(lottoNumbers, lottoBonusNumber);
}

private LottoNumbers splitWinningNumbers(String winningNumbers) {
String[] splitNumbers = validateLottoNumbers(winningNumbers);
return new LottoNumbers(Arrays.stream(splitNumbers)
.map(String::trim)
.mapToInt(Integer::parseInt)
.boxed()
.map(LottoNumber::new)
.collect(Collectors.toList()));
}

private String[] validateLottoNumbers(String numbers) {
String[] splitNumbers = numbers.split(",");
for (String number : splitNumbers) {
validateNumber(number);
}
return trimLottoNumbers(splitNumbers);
}

private int validateNumber(String number) {
try {
String trimNumber = number.trim();
return Integer.parseInt(trimNumber);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(NOT_NUMBER_ERROR_MESSAGE);
}
}

private String[] trimLottoNumbers(String[] numbers) {
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i].trim();
}
return numbers;
}

private int toIntBonusNumber(String bonusNumber) {
return validateNumber(bonusNumber);
}
}
39 changes: 39 additions & 0 deletions src/main/java/lotto/model/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package lotto.model;

import lotto.model.number.LottoNumber;
import lotto.model.number.LottoNumbers;

public class Lotto {

private final LottoNumbers lottoNumbers;
private Rank rank;

public Lotto(final LottoNumbers lottoNumbers) {
this.lottoNumbers = lottoNumbers;
this.rank = null;
}

public Rank calculateRank(final LottoNumbers winningNumbers, final LottoNumber bonusNumber) {
if (this.rank == null) {
int matchingCount = countMatchingNumber(winningNumbers);
boolean win = isWinBonusNumber(matchingCount, bonusNumber);
return this.rank = Rank.getRank(matchingCount, win);
}
return this.rank;
}

private boolean isWinBonusNumber(final int matchingCount, final LottoNumber bonusNumber) {
if (matchingCount == Rank.SECOND.getCount()) {
return lottoNumbers.containNumber(bonusNumber);
}
return false;
}

private int countMatchingNumber(LottoNumbers winningNumbers) {
return lottoNumbers.countMatchingNumber(winningNumbers);
}

public LottoNumbers getLottoNumbers() {
return lottoNumbers;
}
}
40 changes: 40 additions & 0 deletions src/main/java/lotto/model/LottoMachine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package lotto.model;

import java.util.Map;
import lotto.model.generator.LottoGenerator;
import lotto.model.number.LottoNumber;
import lotto.model.number.LottoNumbers;

public class LottoMachine {

private final Money money;
private final Lottos lottos;

private Map<Rank, Integer> rankCount;

public LottoMachine(final LottoGenerator lottoGenerator, final Money money) {
this.money = money;
this.lottos = lottoGenerator.generateLottos(money.lottoCount(), LottoNumber.LOTTO_NUMBER_MINIMUM_RANGE,
LottoNumber.LOTTO_NUMBER_MAXIMUM_RANGE, LottoNumbers.LOTTO_LENGTH);
}

public void calculateResult(final WinningLotto winningLotto) {
this.rankCount = winningLotto.checkRank(lottos);
}

public Lottos getLottos() {
return lottos;
}

public double getRevenue() {
int sum = 0;
for (Rank rank : Rank.values()) {
sum += rank.getPrice() * getEachRankCount(rank);
}
return ((double) sum / money.getMoney());
}

public Integer getEachRankCount(final Rank rank) {
return rankCount.get(rank);
}
}
41 changes: 41 additions & 0 deletions src/main/java/lotto/model/Lottos.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package lotto.model;

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import lotto.model.number.LottoNumber;
import lotto.model.number.LottoNumbers;

public class Lottos {

private final List<Lotto> lottos;

public Lottos(final List<Lotto> lottos) {
this.lottos = lottos;
}

public Map<Rank, Integer> calculateRanks(final LottoNumbers winningNumbers, final LottoNumber bonusNumber) {
Map<Rank, Integer> rankCount = initMap();
lottos.forEach(lotto -> {
Rank rank = lotto.calculateRank(winningNumbers, bonusNumber);
rankCount.put(rank, rankCount.get(rank) + 1);
});
return rankCount;
}

private Map<Rank, Integer> initMap() {
Map<Rank, Integer> map = new LinkedHashMap<>();
Arrays.stream(Rank.values()).forEach(rank -> map.put(rank, 0));
return map;
}

public List<Lotto> getLottos() {
return Collections.unmodifiableList(lottos);
}

public int size() {
return lottos.size();
}
}
28 changes: 28 additions & 0 deletions src/main/java/lotto/model/Money.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package lotto.model;

public class Money {

private static final int PRICE_PER_LOTTO = 1000;
public static final String MONEY_ERROR_MESSAGE = "[ERROR] 유효한 구매 금액이 아닙니다.";

private final int money;

public Money(final int money) {
validateMoney(money);
this.money = money;
}

private void validateMoney(final int money) {
if (money < 0) {
throw new IllegalArgumentException(MONEY_ERROR_MESSAGE);
}
}

public int getMoney() {
return money;
}

public int lottoCount() {
return money / PRICE_PER_LOTTO;
}
}
42 changes: 42 additions & 0 deletions src/main/java/lotto/model/Rank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package lotto.model;

import java.util.Arrays;

public enum Rank {
LOSER(0, false, 0),
FIFTH(3, false, 5_000),
FOURTH(4, false, 50_000),
THIRD(5, false, 1_500_000),
SECOND(5, true, 30_000_000),
FIRST(6, false, 2_000_000_000);

private final int count;
private final boolean winBonusNumber;
private final int price;

Rank(final int count, final boolean winBonusNumber, final int price) {
this.count = count;
this.winBonusNumber = winBonusNumber;
this.price = price;
}

public int getCount() {
return count;
}

public boolean isWinBonusNumber() {
return winBonusNumber;
}

public int getPrice() {
return price;
}

public static Rank getRank(final int count, final boolean winBonusNumber) {
return Arrays.stream(Rank.values())
.filter(rank -> rank.count == count)
.filter(rank -> rank.winBonusNumber == winBonusNumber)
.findFirst()
.orElse(LOSER);
}
}
29 changes: 29 additions & 0 deletions src/main/java/lotto/model/WinningLotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package lotto.model;

import java.util.Map;
import lotto.model.number.LottoNumber;
import lotto.model.number.LottoNumbers;

public class WinningLotto {

private static final String DUPLICATED_NUMBER_ERROR_MESSAGE = "[ERROR] 보너스 번호가 중복되었습니다.";

private final LottoNumbers winningNumbers;
private final LottoNumber bonusNumber;

public WinningLotto(final LottoNumbers winningNumbers, final LottoNumber bonusNumber) {
this.winningNumbers = winningNumbers;
checkDuplicateNumber(bonusNumber);
this.bonusNumber = bonusNumber;
}

private void checkDuplicateNumber(LottoNumber bonusNumber) {
if (winningNumbers.containNumber(bonusNumber)) {
throw new IllegalArgumentException(DUPLICATED_NUMBER_ERROR_MESSAGE);
}
}

public Map<Rank, Integer> checkRank(Lottos lottos) {
return lottos.calculateRanks(winningNumbers, bonusNumber);
}
}
45 changes: 45 additions & 0 deletions src/main/java/lotto/model/generator/AutoLottoGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package lotto.model.generator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lotto.model.Lotto;
import lotto.model.Lottos;
import lotto.model.number.LottoNumber;
import lotto.model.number.LottoNumbers;

public class AutoLottoGenerator implements LottoGenerator {

private static final int LOTTO_START_INDEX = 0;

@Override
public Lottos generateLottos(int lottoCount, int minimumNumber, int maximumNumber, int lottoLength) {
List<Lotto> lottos = new ArrayList<>();
for (int i = 0; i < lottoCount; i++) {
LottoNumbers lottoNumbers = makeLottoNumbers(minimumNumber, maximumNumber, lottoLength);
lottos.add(makeLotto(lottoNumbers));
}
return new Lottos(lottos);
}

private LottoNumbers makeLottoNumbers(int minimumNumber, int maximumNumber, int lottoLength) {
List<Integer> numberCollection = makeNumberCollection(minimumNumber, maximumNumber);
Collections.shuffle(numberCollection);
return new LottoNumbers(numberCollection.subList(LOTTO_START_INDEX, lottoLength).stream()
.sorted()
.map(LottoNumber::new)
.collect(Collectors.toList()));
}

private List<Integer> makeNumberCollection(int minimumNumber, int maximumNumber) {
return IntStream.rangeClosed(minimumNumber, maximumNumber)
.boxed()
.collect(Collectors.toList());
}

private Lotto makeLotto(LottoNumbers lottoNumbers) {
return new Lotto(lottoNumbers);
}
}
Loading