Skip to content

Commit 02d3169

Browse files
IntegerousYoungJae Kim
authored and
YoungJae Kim
committed
2주차 - Step3 로또(2등) 리뷰 부탁드립니다. (#249)
* [step3] refactor : step3 패키지 생성, ResultSheet 객체 생성 * [step3] refactor : 셔플링 테스트 제거 * [step3] refactor : 로또 결과를 담는 Map에 각 등수에 해당하는 당첨로또티켓의 갯수를 담도록 수정 * [step3] refactor : 결과를 담는 ResultSheet 객체에 총 수익 계산하는 메서드 추가 * [step3] refactor : 결과를 담는 ResultSheet 객체에 구매한 복권 개수 반환하는 메서드 추가 * [step3] refactor : step2 피드백 반영 마무리 * [step3] feat : 2등과 3등 분리 로직 추가 (실험적) * [step3] refactor : 2등 출력 메서드 수정, 무의미한 변수 제거 * [step3] refactor : 총 수익률 계산 오류 수정 * [step3] refactor : 로또 결과 출력 로직 수정
1 parent e2cfedc commit 02d3169

14 files changed

+651
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package step3;
2+
3+
import step3.domain.LottoSeller;
4+
import step3.domain.LottoTicket;
5+
import step3.domain.ResultSheet;
6+
import step3.view.InputView;
7+
import step3.view.OutputView;
8+
9+
import java.util.List;
10+
11+
public class LottoApplication {
12+
13+
public static void main(String[] args) {
14+
final int inputMoney = InputView.askMoneyToInput();
15+
final int numberOfTicketsToBuy = LottoSeller.countLottoTickets(inputMoney);
16+
17+
OutputView.printNumberOfTickets(numberOfTicketsToBuy);
18+
19+
List<LottoTicket> lottoTickets = LottoSeller.issueLottoTicket(numberOfTicketsToBuy);
20+
OutputView.printLottoTickets(lottoTickets);
21+
22+
LottoTicket luckyNumber = LottoSeller.getLuckyNumber(InputView.askLuckyNumber());
23+
int bonusNumber = InputView.askBonusNumber();
24+
25+
ResultSheet result = ResultSheet.getResult(lottoTickets, luckyNumber, bonusNumber);
26+
OutputView.printResult(result);
27+
}
28+
}
29+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package step3.domain;
2+
3+
import java.util.List;
4+
import java.util.stream.Collectors;
5+
import java.util.stream.IntStream;
6+
7+
public class LottoBalls {
8+
9+
private static List<Integer> lottoBalls = IntStream
10+
.rangeClosed(LottoNumber.MINIMUM_LOTTO_NUMBER, LottoNumber.MAXIMUM_LOTTO_NUMBER)
11+
.boxed()
12+
.collect(Collectors.toList());
13+
14+
public static List<Integer> getLottoBalls() {
15+
return lottoBalls;
16+
}
17+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package step3.domain;
2+
3+
import java.util.Objects;
4+
5+
public class LottoNumber {
6+
static final String ALERT_OUT_OF_RANGE_OF_LOTTO_NUMBER = "로또번호는 1부터 45까지의 자연수만 가능합니다.";
7+
static final int MINIMUM_LOTTO_NUMBER = 1;
8+
static final int MAXIMUM_LOTTO_NUMBER = 45;
9+
private int number;
10+
11+
private LottoNumber(int number) {
12+
if (isOutOfRange(number)) {
13+
throw new IllegalArgumentException(ALERT_OUT_OF_RANGE_OF_LOTTO_NUMBER);
14+
}
15+
this.number = number;
16+
}
17+
18+
public static LottoNumber from(Integer number) {
19+
return new LottoNumber(number);
20+
}
21+
22+
private boolean isOutOfRange(int number) {
23+
return number < MINIMUM_LOTTO_NUMBER || number > MAXIMUM_LOTTO_NUMBER;
24+
}
25+
26+
public int getNumber() {
27+
return number;
28+
}
29+
30+
@Override
31+
public boolean equals(Object o) {
32+
if (this == o) return true;
33+
if (o == null || getClass() != o.getClass()) return false;
34+
LottoNumber that = (LottoNumber) o;
35+
return number == that.number;
36+
}
37+
38+
@Override
39+
public int hashCode() {
40+
return Objects.hash(number);
41+
}
42+
43+
@Override
44+
public String toString() {
45+
return number + "";
46+
}
47+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package step3.domain;
2+
3+
import java.util.Arrays;
4+
5+
public enum LottoRank {
6+
7+
FIRST_PLACE(6, 2_000_000_000),
8+
SECOND_PLACE(5, 30_000_000),
9+
THIRD_PLACE(5, 1_500_000),
10+
FOURTH_PLACE(4, 50_000),
11+
FIFTH_PLACE(3, 5_000),
12+
LOSER(0, 0);
13+
14+
private int numberOfMatchedToLuckyNumber;
15+
private int prizeMoney;
16+
17+
LottoRank(int numberOfMatchedToLuckyNumber, int prizeMoney) {
18+
this.numberOfMatchedToLuckyNumber = numberOfMatchedToLuckyNumber;
19+
this.prizeMoney = prizeMoney;
20+
}
21+
22+
public static LottoRank from(int countMatchedNumbers, boolean isMatchedToBonusNumber) {
23+
if ((countMatchedNumbers == SECOND_PLACE.numberOfMatchedToLuckyNumber) && isMatchedToBonusNumber) {
24+
return Arrays.stream(LottoRank.values())
25+
.filter(lottoRank -> lottoRank.prizeMoney == SECOND_PLACE.prizeMoney)
26+
.findFirst()
27+
.get();
28+
}
29+
return Arrays.stream(LottoRank.values())
30+
.filter(lottoRank -> lottoRank.numberOfMatchedToLuckyNumber == countMatchedNumbers)
31+
.findFirst()
32+
.orElse(LOSER);
33+
}
34+
35+
public int getNumberOfMatchingNumber() {
36+
return numberOfMatchedToLuckyNumber;
37+
}
38+
39+
public int getPrizeMoney() {
40+
return prizeMoney;
41+
}
42+
43+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package step3.domain;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.stream.Collectors;
6+
7+
public class LottoSeller {
8+
static final int PRICE_OF_A_LOTTO_TICKET = 1000;
9+
static final String ALERT_MISSING_MONEY = "돈을 넣어주세요. 로또복권은 한 장당 1000원 입니다.";
10+
11+
public static int countLottoTickets(int inputMoney) {
12+
validationInputMoney(inputMoney);
13+
return inputMoney / PRICE_OF_A_LOTTO_TICKET;
14+
}
15+
16+
public static List<LottoTicket> issueLottoTicket(int numberOfTicketsToBuy) {
17+
List<LottoTicket> lottoTickets = new ArrayList<>();
18+
19+
for (int i = 0; i < numberOfTicketsToBuy; i++) {
20+
lottoTickets.add(LottoTicketGenerator.issue());
21+
}
22+
return lottoTickets;
23+
}
24+
25+
public static LottoTicket getLuckyNumber(List<Integer> inputLuckyNumber) {
26+
List<LottoNumber> lottoTicket = inputLuckyNumber.stream()
27+
.map(LottoNumber::from)
28+
.collect(Collectors.toList());
29+
return LottoTicketGenerator.issue(lottoTicket);
30+
}
31+
32+
private static void validationInputMoney(int inputMoney) {
33+
if (inputMoney < PRICE_OF_A_LOTTO_TICKET) {
34+
throw new IllegalArgumentException(ALERT_MISSING_MONEY);
35+
}
36+
}
37+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package step3.domain;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.Objects;
6+
7+
public class LottoTicket {
8+
static final String ALERT_NUMBER_OVERLAP = "중복된 로또 번호가 존재합니다.";
9+
static final String AlERT_DIFFERENT_SIZE_OF_NUMBERS = "로또번호의 개수가 6개가 아닙니다.";
10+
11+
private final List<LottoNumber> lottoTicket;
12+
13+
LottoTicket(List<LottoNumber> lottoTicket) {
14+
validationNumberSize(lottoTicket);
15+
validationNumberOverlap(lottoTicket);
16+
this.lottoTicket = lottoTicket;
17+
}
18+
19+
public int getNumberOfMatchedToLuckyNumber(LottoTicket luckyNumber) {
20+
return (int) luckyNumber.getLottoTicket().stream()
21+
.filter(lottoTicket::contains)
22+
.count();
23+
}
24+
25+
boolean isBonusNumberMatched(int bonusNumber) {
26+
return lottoTicket.stream()
27+
.mapToInt(LottoNumber::getNumber)
28+
.anyMatch(i -> i == bonusNumber);
29+
}
30+
31+
private void validationNumberSize(List<LottoNumber> lottoTicket) {
32+
if (lottoTicket.size() != LottoTicketGenerator.BASIC_LOTTO_SIZE) {
33+
throw new IllegalArgumentException(AlERT_DIFFERENT_SIZE_OF_NUMBERS);
34+
}
35+
}
36+
37+
private void validationNumberOverlap(List<LottoNumber> lottoTicket) {
38+
long SizeOfLottoTicket = lottoTicket.stream()
39+
.mapToLong(LottoNumber::getNumber)
40+
.distinct()
41+
.count();
42+
43+
if (SizeOfLottoTicket != LottoTicketGenerator.BASIC_LOTTO_SIZE) {
44+
throw new IllegalArgumentException(ALERT_NUMBER_OVERLAP);
45+
}
46+
}
47+
48+
public List<LottoNumber> getLottoTicket() {
49+
return Collections.unmodifiableList(lottoTicket);
50+
}
51+
52+
@Override
53+
public boolean equals(Object o) {
54+
if (this == o) return true;
55+
if (o == null || getClass() != o.getClass()) return false;
56+
LottoTicket that = (LottoTicket) o;
57+
return Objects.equals(lottoTicket, that.lottoTicket);
58+
}
59+
60+
@Override
61+
public int hashCode() {
62+
return Objects.hash(lottoTicket);
63+
}
64+
65+
@Override
66+
public String toString() {
67+
return "LottoTicket{" +
68+
"lottoTicket=" + lottoTicket +
69+
'}';
70+
}
71+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package step3.domain;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.stream.Collectors;
6+
7+
public class LottoTicketGenerator {
8+
static final int BASIC_LOTTO_SIZE = 6;
9+
10+
static LottoTicket issue() {
11+
return new LottoTicket(pickLottoBalls(LottoBalls.getLottoBalls()));
12+
}
13+
14+
static LottoTicket issue(List<LottoNumber> lottoTicket) {
15+
return new LottoTicket(lottoTicket);
16+
}
17+
18+
static List<LottoNumber> pickLottoBalls(List<Integer> lottoBalls) {
19+
shuffleLottoBalls(lottoBalls);
20+
return lottoBalls.stream()
21+
.limit(BASIC_LOTTO_SIZE)
22+
.sorted()
23+
.map(LottoNumber::from)
24+
.collect(Collectors.toList());
25+
}
26+
27+
static void shuffleLottoBalls(List<Integer> lottoBalls) {
28+
Collections.shuffle(lottoBalls);
29+
}
30+
31+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package step3.domain;
2+
3+
import java.util.HashMap;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
public class ResultSheet {
8+
private static final int LOTTO_TICKET_PRICE = 1000;
9+
10+
private Map<LottoRank, Integer> resultSheet;
11+
12+
private ResultSheet(Map<LottoRank, Integer> resultSheet) {
13+
this.resultSheet = resultSheet;
14+
}
15+
16+
public static ResultSheet getResult(List<LottoTicket> lottoTickets, LottoTicket luckyNumber, int bonusNumber) {
17+
Map<LottoRank, Integer> lottoResultMap = new HashMap<>();
18+
19+
for (LottoTicket ticket : lottoTickets) {
20+
LottoRank lottoRank = LottoRank.from(ticket.getNumberOfMatchedToLuckyNumber(luckyNumber), ticket.isBonusNumberMatched(bonusNumber));
21+
int numberOfTicketsCorrespondingToRank = lottoResultMap.getOrDefault(lottoRank, 0);
22+
lottoResultMap.put(lottoRank, ++numberOfTicketsCorrespondingToRank);
23+
}
24+
return new ResultSheet(lottoResultMap);
25+
}
26+
27+
private int getTotalTicketsBought() {
28+
return resultSheet.values()
29+
.stream()
30+
.reduce(Integer::sum)
31+
.get();
32+
}
33+
34+
private int totalMoneySpentForTickets() {
35+
return getTotalTicketsBought() * LOTTO_TICKET_PRICE;
36+
}
37+
38+
private int getNumberOfTicketsCorrespondingToRank(LottoRank lottoRank) {
39+
return resultSheet.getOrDefault(lottoRank, 0);
40+
}
41+
42+
private int getEachPrizeMoney(LottoRank lottoRank) {
43+
return lottoRank.getPrizeMoney() * this.getNumberOfTicketsCorrespondingToRank(lottoRank);
44+
}
45+
46+
private int getTotalPrizeMoney() {
47+
return resultSheet.keySet()
48+
.stream()
49+
.mapToInt(this::getEachPrizeMoney)
50+
.sum();
51+
}
52+
53+
public double getEarningRate() {
54+
return getTotalPrizeMoney() / totalMoneySpentForTickets();
55+
}
56+
57+
public Map<LottoRank, Integer> getResultMap() {
58+
return resultSheet;
59+
}
60+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package step3.view;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Scanner;
6+
import java.util.stream.Collectors;
7+
8+
public class InputView {
9+
private static final String LUCKY_NUMBER_SEPARATOR = ",";
10+
private static Scanner scanner = new Scanner(System.in);
11+
12+
public static int askMoneyToInput() {
13+
System.out.println("구입금액을 입력해 주세요.");
14+
return scanner.nextInt();
15+
}
16+
17+
public static List<Integer> askLuckyNumber() {
18+
printBlackLine();
19+
scanner.nextLine();
20+
System.out.println("지난 주 당첨 번호를 입력해주세요.");
21+
String inputLuckyNumber = scanner.nextLine();
22+
printBlackLine();
23+
24+
return Arrays.stream(inputLuckyNumber.split(LUCKY_NUMBER_SEPARATOR))
25+
.map(String::trim)
26+
.mapToInt(Integer::parseInt)
27+
.boxed()
28+
.collect(Collectors.toList());
29+
}
30+
31+
public static int askBonusNumber() {
32+
System.out.println("보너스 볼을 입력해 주세요.");
33+
return scanner.nextInt();
34+
}
35+
36+
private static void printBlackLine() {
37+
System.out.println();
38+
}
39+
}

0 commit comments

Comments
 (0)