Skip to content

Commit fcd4b0c

Browse files
IntegerousYoungJae Kim
authored and
YoungJae Kim
committed
2주차 - Step4 로또(수동) 리뷰 요청드립니다. (#262)
* [step4] feat : step4 패키지 생성 * [step4] refactor : LottoTickets 일급 컬렉션 추가 (피드백 반영) * [step4] refactor : List<LottoTicket> 사용되던 곳을 LottoTickets로 변경(피드백 반영) * [step4] refactor : 도메인 영역 내에서 int bonusNumber를LottoNumber 불변객체로 주고 받도록 수정 * [step4] refactor : 당첨티켓과 보너스번호를 담는 LuckyTicket 객체 생성 * [step4] refactor : lottoTicket과 bonusNumber를 인자로 사용하던 부분을 LuckyTicket으로 대체 * [step4] refactor : LottoRank를 생성할때 원시값 대신 객체 전달 * [step4] refactor : LottoRank 정적팩토리메서드의 로직 개선 * [step4] refactor : OutputView의 당첨결과 출력 로직 개선 * [step4] refactor : 테스트코드 수정 * [step4] feat : 로또 수동 구매 view 생성 * [step4] feat : 각 수동로또와 자동로또 개수 저장 * [step4] feat : 수동으로 구매할 번호를 입력받아 컬렉션으로 반환하는 메서드 추가 * [step4] feat : 자동 생성되는 로또복권 리스트에 수동복권 추가 * [step4] refactor : 총 구입개수 반환하는 메서드 개선 * [step4] refactor : 5개 맞추면 모두 2등으로 추출되는 오류 해결 * [step4] refactor : 5등 미만(LOSER)는 출력하지 않도록 수정 * [step4] refactor : 필요없는 import 제거 * [step4] refactor : (피드백 반영) List<List<Integer>> 대신 List<String> 사용 * [step4] refactor : 결과 출력 로직 개선
1 parent 02d3169 commit fcd4b0c

16 files changed

+735
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package step4;
2+
3+
import step4.domain.*;
4+
import step4.view.InputView;
5+
import step4.view.OutputView;
6+
7+
import java.util.List;
8+
9+
public class LottoApplication {
10+
11+
public static void main(String[] args) {
12+
final int inputMoney = InputView.askMoneyToInput();
13+
final int numberOfManualTickets = InputView.askNumberOfManualTicket();
14+
final int numberOfAutoTickets = LottoSeller.countAutoTickets(inputMoney, numberOfManualTickets);
15+
16+
List<String> manualTickets = InputView.askNumbersForManualTickets(numberOfManualTickets);
17+
OutputView.printNumberOfTickets(numberOfManualTickets, numberOfAutoTickets);
18+
19+
LottoTickets lottoTickets = LottoSeller.issueLottoTicket(manualTickets, numberOfAutoTickets);
20+
OutputView.printLottoTickets(lottoTickets);
21+
22+
LuckyTicket luckyTicket = LottoSeller
23+
.getLuckyNumber(InputView.askLuckyNumber(), InputView.askBonusNumber());
24+
25+
ResultSheet result = ResultSheet.getResult(lottoTickets, luckyTicket);
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 step4.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+
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 step4.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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package step4.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(LottoTicket lottoTicket, LuckyTicket luckyTicket) {
23+
int countMatchedNumbers = lottoTicket.getNumberOfMatchedToLuckyNumber(luckyTicket);
24+
boolean isMatchedToBonusNumber = lottoTicket.isBonusNumberMatched(luckyTicket);
25+
26+
if ((countMatchedNumbers == SECOND_PLACE.numberOfMatchedToLuckyNumber) && isMatchedToBonusNumber) {
27+
return LottoRank.SECOND_PLACE;
28+
}
29+
return Arrays.stream(LottoRank.values())
30+
.filter(lottoRank -> lottoRank.numberOfMatchedToLuckyNumber == countMatchedNumbers)
31+
.filter(lottoRank -> lottoRank.prizeMoney != SECOND_PLACE.prizeMoney)
32+
.findFirst()
33+
.orElse(LOSER);
34+
}
35+
36+
public int getNumberOfMatchingNumber() {
37+
return numberOfMatchedToLuckyNumber;
38+
}
39+
40+
public int getPrizeMoney() {
41+
return prizeMoney;
42+
}
43+
44+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package step4.domain;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
import java.util.stream.Collectors;
7+
8+
public class LottoSeller {
9+
static final int PRICE_OF_A_LOTTO_TICKET = 1000;
10+
static final String ALERT_MISSING_MONEY = "돈을 넣어주세요. 로또복권은 한 장당 1000원 입니다.";
11+
private static final String ALERT_SHORT_OF_MONEY = "돈이 모자랍니다.";
12+
private static final String ALERT_NEGATIVE_NUMBER = "구매할 수동로또 개수는 음수가 될 수 없습니다.";
13+
static final String NUMBER_SEPARATOR = ",";
14+
15+
public static int countAutoTickets(int inputMoney, int numberOfManualTickets) {
16+
validationInputData(inputMoney, numberOfManualTickets);
17+
return (inputMoney / PRICE_OF_A_LOTTO_TICKET) - numberOfManualTickets;
18+
}
19+
20+
public static LottoTickets issueLottoTicket(List<String> manualTickets, int numberOfAutoTickets) {
21+
List<LottoTicket> lottoTickets = new ArrayList<>();
22+
23+
for (String manualTicket : manualTickets) {
24+
List<Integer> parsedManualTicket = parseToNumbers(manualTicket);
25+
lottoTickets.add(LottoTicketGenerator.issueManualTickets(parsedManualTicket));
26+
}
27+
for (int i = 0; i < numberOfAutoTickets; i++) { //TODO: index i가 사용되지 않고 있음
28+
lottoTickets.add(LottoTicketGenerator.issueAutoTickets());
29+
}
30+
return LottoTickets.from(lottoTickets);
31+
}
32+
33+
private static List<Integer> parseToNumbers(String manualTicket) {
34+
return Arrays.stream(manualTicket.split(NUMBER_SEPARATOR))
35+
.map(String::trim)
36+
.mapToInt(Integer::parseInt)
37+
.boxed()
38+
.collect(Collectors.toList());
39+
}
40+
41+
public static LuckyTicket getLuckyNumber(List<Integer> inputLuckyNumber, int bonusNumber) {
42+
List<LottoNumber> luckyTicket = inputLuckyNumber.stream()
43+
.map(LottoNumber::from)
44+
.collect(Collectors.toList());
45+
return LuckyTicket.of(luckyTicket, LottoNumber.from(bonusNumber));
46+
}
47+
48+
private static void validationInputData(int inputMoney, int numberOfManualTickets) {
49+
if (inputMoney < PRICE_OF_A_LOTTO_TICKET) {
50+
throw new IllegalArgumentException(ALERT_MISSING_MONEY);
51+
}
52+
if (numberOfManualTickets < 0) {
53+
throw new IllegalArgumentException(ALERT_NEGATIVE_NUMBER);
54+
}
55+
if (numberOfManualTickets * PRICE_OF_A_LOTTO_TICKET > inputMoney) {
56+
throw new IllegalArgumentException(ALERT_SHORT_OF_MONEY);
57+
}
58+
}
59+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package step4.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(LuckyTicket luckyTicket) {
20+
return (int) luckyTicket.getLuckyNumber().stream()
21+
.filter(lottoTicket::contains)
22+
.count();
23+
}
24+
25+
boolean isBonusNumberMatched(LuckyTicket luckyTicket) {
26+
return luckyTicket.checkBonusNumber(lottoTicket);
27+
}
28+
29+
private void validationNumberSize(List<LottoNumber> lottoTicket) {
30+
if (lottoTicket.size() != LottoTicketGenerator.BASIC_LOTTO_SIZE) {
31+
throw new IllegalArgumentException(AlERT_DIFFERENT_SIZE_OF_NUMBERS);
32+
}
33+
}
34+
35+
private void validationNumberOverlap(List<LottoNumber> lottoTicket) {
36+
long SizeOfLottoTicket = lottoTicket.stream()
37+
.mapToLong(LottoNumber::getNumber)
38+
.distinct()
39+
.count();
40+
41+
if (SizeOfLottoTicket != LottoTicketGenerator.BASIC_LOTTO_SIZE) {
42+
throw new IllegalArgumentException(ALERT_NUMBER_OVERLAP);
43+
}
44+
}
45+
46+
public List<LottoNumber> getLottoTicket() {
47+
return Collections.unmodifiableList(lottoTicket);
48+
}
49+
50+
@Override
51+
public boolean equals(Object o) {
52+
if (this == o) return true;
53+
if (o == null || getClass() != o.getClass()) return false;
54+
LottoTicket that = (LottoTicket) o;
55+
return Objects.equals(lottoTicket, that.lottoTicket);
56+
}
57+
58+
@Override
59+
public int hashCode() {
60+
return Objects.hash(lottoTicket);
61+
}
62+
63+
@Override
64+
public String toString() {
65+
return "LottoTicket{" +
66+
"lottoTicket=" + lottoTicket +
67+
'}';
68+
}
69+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package step4.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 issueAutoTickets() {
11+
return new LottoTicket(pickLottoBalls(LottoBalls.getLottoBalls()));
12+
}
13+
14+
static LottoTicket issueManualTickets(List<Integer> manualTicket) {
15+
return new LottoTicket(manualTicket.stream()
16+
.sorted()
17+
.map(LottoNumber::from)
18+
.collect(Collectors.toList()));
19+
}
20+
21+
static List<LottoNumber> pickLottoBalls(List<Integer> lottoBalls) {
22+
shuffleLottoBalls(lottoBalls);
23+
return lottoBalls.stream()
24+
.limit(BASIC_LOTTO_SIZE)
25+
.sorted()
26+
.map(LottoNumber::from)
27+
.collect(Collectors.toList());
28+
}
29+
30+
static void shuffleLottoBalls(List<Integer> lottoBalls) {
31+
Collections.shuffle(lottoBalls);
32+
}
33+
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package step4.domain;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
public class LottoTickets {
7+
private final List<LottoTicket> lottoTickets;
8+
9+
private LottoTickets(List<LottoTicket> lottoTickets) {
10+
this.lottoTickets = lottoTickets;
11+
}
12+
13+
public static LottoTickets from(List<LottoTicket> lottoTickets) {
14+
return new LottoTickets(lottoTickets);
15+
}
16+
17+
public List<LottoTicket> getLottoTickets() {
18+
return Collections.unmodifiableList(lottoTickets);
19+
}
20+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package step4.domain;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
public class LuckyTicket {
7+
private final List<LottoNumber> luckyNumber;
8+
private final LottoNumber bonusNumber;
9+
10+
private LuckyTicket(List<LottoNumber> luckyNumber, LottoNumber bonusNumber) {
11+
this.luckyNumber = luckyNumber;
12+
this.bonusNumber = bonusNumber;
13+
}
14+
15+
static LuckyTicket of(List<LottoNumber> luckyNumber, LottoNumber bonusNumber) {
16+
return new LuckyTicket(luckyNumber, bonusNumber);
17+
}
18+
19+
public List<LottoNumber> getLuckyNumber() {
20+
return Collections.unmodifiableList(luckyNumber);
21+
}
22+
23+
boolean checkBonusNumber(List<LottoNumber> lottoTicket) {
24+
return lottoTicket.contains(bonusNumber);
25+
}
26+
}

0 commit comments

Comments
 (0)