Skip to content

[LBP] 현정빈 로또 미션 2-5 단계 제출합니다. #90

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

Open
wants to merge 13 commits into
base: jeongbeanhyun
Choose a base branch
from
Open
74 changes: 45 additions & 29 deletions src/main/java/controller/LottoController.java
Original file line number Diff line number Diff line change
@@ -1,54 +1,70 @@
package controller;

import model.Lotto;
import model.LottoTickets;
import model.*;
import view.ErrorView;
import view.InputView;
import view.ResultView;

import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;


public class LottoController {

public void run() {
try {
int purchaseAmount = InputView.getPurchaseAmount();

validatePurchaseAmount(purchaseAmount);

int ticketCount = LottoTickets.getTicketCount(purchaseAmount);

LottoTickets lottoTickets = new LottoTickets(ticketCount);

ResultView.printOrderTickets(ticketCount);

ResultView.printPurchasedLottoTickets(formatTickets(lottoTickets.getTickets()));

LottoPurchaseInfo lottoPurchaseInfo = getPurchaseAmount();
int manualCount = getManualCount(lottoPurchaseInfo);
LottoTickets lottoTickets = generateLottoTickets(lottoPurchaseInfo, manualCount);
ResultView.printOrderTickets(manualCount, lottoPurchaseInfo.getTicketCount() - manualCount);
ResultView.printPurchasedLottoTickets(lottoTickets.getFormattedTicketNumbers());
processWinningResults(lottoTickets, lottoPurchaseInfo);
InputView.closeScanner();
} catch (IllegalArgumentException e) {
ErrorView.printErrorMessage(e.getMessage());
}
}

private List<String> formatTickets(List<Lotto> tickets) {
return tickets.stream()
.map(this::convertLottoToString)
.toList();
private LottoPurchaseInfo getPurchaseAmount() {
return new LottoPurchaseInfo(InputView.getPurchaseAmount());
}

private String convertLottoToString(Lotto lotto) {
return lotto.getSortedNumbers().stream()
.map(String::valueOf)
.collect(Collectors.joining(",", "[", "]"));
private int getManualCount(LottoPurchaseInfo lottoPurchaseInfo) {
int manualCount = InputView.getManualTicketCount();
validateManualCount(manualCount, lottoPurchaseInfo);
return manualCount;
}

private void validatePurchaseAmount(int purchaseAmount) {
if (purchaseAmount < LottoTickets.LOTTO_PRICE) {
throw new IllegalArgumentException("구매 금액은 1000원 이상이어야 합니다.");
}
private LottoTickets generateLottoTickets(LottoPurchaseInfo lottoPurchaseInfo, int manualCount) {
List<List<Integer>> manualNumbers = InputView.getManualNumbers(manualCount);
int autoCount = lottoPurchaseInfo.getTicketCount() - manualCount;
LottoTickets manualTickets = new LottoTickets(manualNumbers);
LottoTickets autoTickets = new LottoTickets(autoCount);
return LottoTickets.merge(manualTickets, autoTickets);
}

if (purchaseAmount % LottoTickets.LOTTO_PRICE != 0) {
throw new IllegalArgumentException("구매 금액은 1000원 단위여야 합니다.");
public void validateManualCount(int manualCount, LottoPurchaseInfo lottoPurchaseInfo) {
if (manualCount > lottoPurchaseInfo.getTicketCount()) {
throw new IllegalArgumentException("수동 구매 개수가 구매 가능한 개수를 초과할 수 없습니다.");
}
}

private void processWinningResults(LottoTickets lottoTickets, LottoPurchaseInfo lottoPurchaseInfo) {
LottoResult lottoResult = createLottoResult(lottoTickets, getWinningNumbers());

Map<String, Integer> formattedWinningDetails = lottoResult.getFormattedWinningDetails();
double profitRate = lottoResult.calculateProfitRate(lottoPurchaseInfo.getAmount());

ResultView.printWinningStatistics(formattedWinningDetails, profitRate);
}

private WinningNumbers getWinningNumbers() {
List<Integer> winningNumbers = InputView.getWinningNumbers();
int bonusNumber = InputView.getBonusNumber();
return new WinningNumbers(winningNumbers, bonusNumber);
}

private LottoResult createLottoResult(LottoTickets lottoTickets, WinningNumbers winningNumbers) {
return new LottoResult(lottoTickets.getTickets(), winningNumbers);
}
}
36 changes: 10 additions & 26 deletions src/main/java/model/Lotto.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,22 @@
package model;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

//로또 한 장
public class Lotto {
private final LottoNumbers lottoNumbers;

// 로또 번호 관련 상수 선언
public static final int LOTTO_MIN_NUMBER = 1;
public static final int LOTTO_MAX_NUMBER = 45;
public static final int LOTTO_CREATE_SIZE = 6;
public static final List<Integer> LOTTO_NUMBER_POOL =
IntStream.rangeClosed(LOTTO_MIN_NUMBER,LOTTO_MAX_NUMBER)
.boxed()
.collect(Collectors.toList());

private List<Integer> numbers;

public Lotto(){
this.numbers = createLottoNumbers();
//수동 로또
public Lotto(List<Integer> numbers) {
this.lottoNumbers = new LottoNumbers(numbers);
}

private List<Integer> createLottoNumbers(){
List<Integer> shuffledNumbers = new ArrayList<>(LOTTO_NUMBER_POOL);
Collections.shuffle(shuffledNumbers);
numbers = shuffledNumbers.subList(0, LOTTO_CREATE_SIZE);

return numbers;
//자동 로또
public Lotto(LottoNumbers lottoNumbers) {
this.lottoNumbers = lottoNumbers;
}

public List<Integer> getSortedNumbers() {
List<Integer> sortedNumbers = new ArrayList<>(numbers);
Collections.sort(sortedNumbers);

return sortedNumbers;
public List<Integer> getNumbers() {
return lottoNumbers.getNumbers();
}
}
53 changes: 53 additions & 0 deletions src/main/java/model/LottoNumbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class LottoNumbers {
private static final int LOTTO_MIN_NUMBER = 1;
private static final int LOTTO_MAX_NUMBER = 45;
private static final int LOTTO_CREATE_SIZE = 6;

private final List<Integer> numbers;

public LottoNumbers() {
this.numbers = sortedNumbers(generateAutoLottoNumbers());
}

public LottoNumbers(List<Integer> numbers) {
validate(numbers);
this.numbers = sortedNumbers(numbers);
}

private void validate(List<Integer> numbers) {
if (numbers.size() != LOTTO_CREATE_SIZE) {
throw new IllegalArgumentException("로또 번호는 6개여야 합니다.");
}
if (numbers.stream().distinct().count() != LOTTO_CREATE_SIZE) {
throw new IllegalArgumentException("중복된 숫자가 있습니다.");
}
if (numbers.stream().anyMatch(n -> n < LOTTO_MIN_NUMBER || n > LOTTO_MAX_NUMBER)) {
throw new IllegalArgumentException("로또 번호는 1~45 사이여야 합니다.");
}
}

private List<Integer> generateAutoLottoNumbers() {
List<Integer> shuffledNumbers = IntStream.rangeClosed(LOTTO_MIN_NUMBER, LOTTO_MAX_NUMBER)
.boxed()
.collect(Collectors.toList());
Collections.shuffle(shuffledNumbers);

return shuffledNumbers.subList(0,LOTTO_CREATE_SIZE);
}

private List<Integer> sortedNumbers(List<Integer> numbers) {
return List.copyOf(numbers.stream().sorted().toList());
}

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

public class LottoPurchaseInfo {
private static final int LOTTO_PRICE = 1000;
private final int amount;

public LottoPurchaseInfo(int amount) {
validatePurchaseAmount(amount);
this.amount = amount;
}

private void validatePurchaseAmount(int amount) {
if (amount < LOTTO_PRICE) {
throw new IllegalArgumentException("구매 금액은 1000원 이상이어야 합니다.");
}
if (amount % LOTTO_PRICE != 0) {
throw new IllegalArgumentException("구매 금액은 1000원 단위여야 합니다.");
}
}

public int getTicketCount() {
return amount / LOTTO_PRICE;
}

public int getAmount() {
return amount;
}

public void validateManualCount(int manualCount) {
if (manualCount > getTicketCount()) {
throw new IllegalArgumentException("수동 구매 개수가 구매 가능한 개수를 초과할 수 없습니다.");
}
}
}
92 changes: 92 additions & 0 deletions src/main/java/model/LottoResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package model;

import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class LottoResult {
private final Map<Rank, Integer> matchCountMap = new EnumMap<>(Rank.class);

public LottoResult(List<Lotto> tickets, WinningNumbers winningNumbers) {
for (Lotto ticket : tickets) {
Rank rank = determineRank(ticket, winningNumbers);
matchCountMap.put(rank, matchCountMap.getOrDefault(rank, 0) + 1);
}
}

private Rank determineRank(Lotto ticket, WinningNumbers winningNumbers) {
int matchCount = countMatchingNumbers(ticket, winningNumbers);
boolean hasBonus = hasBonusNumber(ticket, winningNumbers);

return getRank(matchCount, hasBonus);
}

// 일치하는 숫자 개수 계산
private int countMatchingNumbers(Lotto ticket, WinningNumbers winningNumbers) {
return (int) ticket.getNumbers().stream()
.filter(winningNumbers.getNumbers()::contains)
.count();
}

// 보너스 번호 포함 여부 확인
private boolean hasBonusNumber(Lotto ticket, WinningNumbers winningNumbers) {
return ticket.getNumbers().contains(winningNumbers.getBonusNumber());
}

private Rank getRank(int matchCount, boolean hasBonus) {
if (matchCount == 6) return Rank.FIRST;
if (matchCount == 5 && hasBonus) return Rank.SECOND;
if (matchCount == 5) return Rank.THIRD;
if (matchCount == 4) return Rank.FOURTH;
if (matchCount == 3) return Rank.FIFTH;
return Rank.NONE;
}

public Map<Rank, Integer> getMatchCountMap() {
return matchCountMap;
}

public double calculateProfitRate(int totalCost) {
List<Integer> prizeAmounts = convertToPrizeAmounts();
int totalPrize = sumPrizeAmounts(prizeAmounts);
return (double) totalPrize / totalCost;
}

// 데이터 변환
private List<Integer> convertToPrizeAmounts() {
return matchCountMap.entrySet().stream()
.map(this::convertToPrizeAmount)
.toList();
}

// Rank 데이터를 변환
private int convertToPrizeAmount(Map.Entry<Rank, Integer> rankEntry) {
Rank rank = rankEntry.getKey();
int count = rankEntry.getValue();
return rank.getPrizeMoney() * count;
}

// 변환된 데이터를 계산
private int sumPrizeAmounts(List<Integer> prizeAmounts) {
return prizeAmounts.stream()
.mapToInt(Integer::intValue)
.sum();
}

public Map<String, Integer> getFormattedWinningDetails() {
Map<String, Integer> formattedDetails = new LinkedHashMap<>();

for (Rank rank : Rank.values()) {
addRankIfValid(formattedDetails, rank);
}

return formattedDetails;
}

private void addRankIfValid(Map<String, Integer> formattedDetails, Rank rank) {
if (rank != Rank.NONE) {
formattedDetails.put(rank.getDescription(), matchCountMap.getOrDefault(rank, 0));
}
}
}
48 changes: 36 additions & 12 deletions src/main/java/model/LottoTickets.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,51 @@
import java.util.List;

public class LottoTickets {

private final List<Lotto> tickets;
public static final int LOTTO_PRICE = 1000;

public LottoTickets(int ticketCount) {
this.tickets = generateLottoTickets(ticketCount);
private LottoTickets(List<Lotto> tickets, boolean unused) {
this.tickets = List.copyOf(tickets);
}

public LottoTickets(List<List<Integer>> manualNumbers) {
List<Lotto> manualTickets = new ArrayList<>();
addManualTickets(manualTickets, manualNumbers);
this.tickets = List.copyOf(manualTickets);
}

public LottoTickets(int autoTicketCount) {
List<Lotto> autoTickets = new ArrayList<>();
addAutoTickets(autoTickets, autoTicketCount);
this.tickets = List.copyOf(autoTickets);
}

public static LottoTickets merge(LottoTickets manualTickets, LottoTickets autoTickets) {
List<Lotto> mergedTickets = new ArrayList<>(manualTickets.tickets);
mergedTickets.addAll(autoTickets.tickets);
return new LottoTickets(mergedTickets, true);
}

private List<Lotto> generateLottoTickets(int ticketCount) {
List<Lotto> tickets = new ArrayList<>();
for (int i = 0; i < ticketCount; i++) {
tickets.add(new Lotto());
private static void addManualTickets(List<Lotto> tickets, List<List<Integer>> manualNumbers) {
for (List<Integer> numbers : manualNumbers) {
tickets.add(new Lotto(numbers));
}
}

private static void addAutoTickets(List<Lotto> tickets, int autoTicketCount) {
for (int i = 0; i < autoTicketCount; i++) {
tickets.add(new Lotto(new LottoNumbers()));
}
return tickets;
}

public List<Lotto> getTickets() {
return new ArrayList<>(tickets);
return tickets;
}

public static int getTicketCount(int purchaseAmount){
return purchaseAmount / LOTTO_PRICE;
public List<List<Integer>> getFormattedTicketNumbers() {
List<List<Integer>> ticketNumbers = new ArrayList<>();
for (Lotto ticket : tickets) {
ticketNumbers.add(ticket.getNumbers());
}
return ticketNumbers;
}
}
Loading