-
Notifications
You must be signed in to change notification settings - Fork 92
[그리디] 김태우 로또 미션 3,4,5 단계 제출합니다. #146
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
base: tae-wooo
Are you sure you want to change the base?
Changes from all commits
849e2fe
84ad2df
cf566ce
84fe5a6
ee9214d
b0320e9
caad7b4
3625fd2
3c52ba5
5256990
6eaeb8f
35d5b27
1925a09
59a8dbd
3960e78
8f78037
bf9eb51
8a1ed8f
ea203ae
53e53c6
c0d24e0
2578a3e
3b73ece
8f4157d
fa8c3ae
dcc3c70
32ff258
0293eee
5dcf37f
a45f213
d87205d
98ea697
036ccdb
510b0c0
9f18556
f74a8ac
fd6c52f
87965f2
3c5d1a1
eb187e4
6d47438
de36cc9
2393907
b32bfa9
28647f0
579c2f3
450573a
022567f
fb04843
e1680af
e4cddbd
6a4da86
58fe1f0
7b87bf7
5cda9d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# 로또 미션 | ||
|
||
## 기능 요구사항 | ||
|
||
- 로또 당첨 번호를 받아 일치한 번호 수에 따라 당첨 결과를 보여준다. | ||
|
||
## 프로그래밍 요구사항 | ||
|
||
- 모든 원시 값과 문자열을 포장한다. | ||
- 일급 컬렉션을 쓴다. | ||
|
||
## 추가 기능 요구사항 | ||
|
||
- 2등을 위한 보너스볼을 추첨한다. | ||
- 당첨 통계에 2등을 추가한다. | ||
- 2등 당첨 조건은 당첨 번호 5개 + 보너스 볼이다 | ||
- 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다. | ||
- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import controller.LottoController; | ||
import model.PurchaseAmount; | ||
import model.LottoNumber; | ||
import model.LottoTicket; | ||
import model.LottoTicketBundle; | ||
|
||
public class Main { | ||
public static void main(String[] args) { | ||
LottoController controller = new LottoController(); | ||
|
||
// 1. 구입 금액 입력 | ||
PurchaseAmount purchaseAmount = controller.askPurchaseAmount(); | ||
|
||
// 2. 수동 및 자동 로또 번호 생성 | ||
LottoTicketBundle allTickets = controller.buyTickets(purchaseAmount.calculateLottoCount()); | ||
|
||
// 3. 당첨 번호 입력 | ||
LottoTicket winningNumbers = controller.askWinningNumbers(); | ||
|
||
// 4. 보너스 볼 입력 | ||
LottoNumber bonusBall = controller.askBonusBall(); | ||
|
||
// 5. 통계 출력 | ||
controller.showStatistics(allTickets.readLottoNumbersRepository(), | ||
winningNumbers.getNumbers(), | ||
purchaseAmount.getValue(), | ||
bonusBall | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package controller; | ||
|
||
import view.InputView; | ||
import view.OutputView; | ||
import model.PurchaseAmount; | ||
import model.LottoNumber; | ||
import model.LottoTicket; | ||
import model.LottoService; | ||
import model.LottoTicketBundle; | ||
import model.MatchResult; | ||
|
||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class LottoController { | ||
private final LottoService lottoService = new LottoService(); | ||
private final OutputView outView = new OutputView(); | ||
private final InputView inputView = new InputView(); | ||
|
||
private PurchaseAmount readPrice() { | ||
outView.printInputPrice(); | ||
while (true) { | ||
PurchaseAmount purchaseAmount = readPriceException(); | ||
if (purchaseAmount != null) return purchaseAmount; | ||
} | ||
} | ||
|
||
private PurchaseAmount readPriceException() { | ||
try { | ||
return new PurchaseAmount(Integer.parseInt(inputView.inputPrice())); | ||
} catch (NumberFormatException input) { | ||
outView.printInvalidNumber(); | ||
} catch (IllegalArgumentException input) { | ||
outView.printInvalidPrice(); | ||
} | ||
return null; | ||
} | ||
|
||
public PurchaseAmount askPurchaseAmount() { | ||
PurchaseAmount purchaseAmount = readPrice(); | ||
outView.printPriceValue(purchaseAmount.getValue()); | ||
outView.printBlankLine(); | ||
return purchaseAmount; | ||
} | ||
|
||
public LottoTicketBundle buyTickets(int ticketCount) { | ||
int manualCount = requestManualTicketCount(); | ||
int autoCount = calculateAutoCount(ticketCount, manualCount); | ||
|
||
LottoTicketBundle tickets = generateTickets(manualCount, autoCount); | ||
displayTickets(manualCount, autoCount, tickets); | ||
|
||
return tickets; | ||
} | ||
|
||
private int requestManualTicketCount() { | ||
outView.printManualTicketCount(); | ||
return Integer.parseInt(inputView.inputManualCount()); | ||
} | ||
|
||
private int calculateAutoCount(int totalTickets, int manualCount) { | ||
return totalTickets - manualCount; | ||
} | ||
|
||
private LottoTicketBundle generateTickets(int manualCount, int autoCount) { | ||
outView.printManualLottoNumbersPrompt(); | ||
List<String> manualInputs = inputView.inputManualLottos(manualCount); | ||
|
||
LottoTicketBundle manualTickets = lottoService.createManualLottos(manualInputs); | ||
LottoTicketBundle autoTickets = lottoService.createLottos(autoCount); | ||
|
||
return lottoService.mergeAutoAndManualLottos(manualTickets, autoTickets); | ||
} | ||
|
||
private void displayTickets(int manualCount, int autoCount, LottoTicketBundle tickets) { | ||
outView.printBuyCount(manualCount, autoCount); | ||
outView.printLottos(tickets.readLottoNumbersRepository()); | ||
} | ||
|
||
public LottoTicket askWinningNumbers() { | ||
outView.printInputWinningNumbers(); | ||
LottoTicket winningLotto = lottoService.createInputLotto(inputView.inputWinningNumbers()); | ||
outView.printBlankLine(); | ||
return winningLotto; | ||
} | ||
|
||
public LottoNumber askBonusBall() { | ||
outView.printBonusBall(); | ||
LottoNumber bonusNumber = new LottoNumber(Integer.parseInt(inputView.inputBonusBall())); | ||
outView.printBlankLine(); | ||
return bonusNumber; | ||
} | ||
|
||
public void showStatistics(List<LottoTicket> allTickets, List<LottoNumber> winningNumbers, int purchaseAmount, LottoNumber bonusBall) { | ||
Map<MatchResult, Integer> matchCounts = lottoService.countMatchResults(allTickets, winningNumbers, bonusBall); | ||
String profitRate = lottoService.calculateProfitRate(matchCounts, purchaseAmount); | ||
outView.printLotteryStatistics(matchCounts, profitRate); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 전체적으로 Controller 클래스임에도 출력문이 직접적으로 작성되어 있는 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 Controller가 출력까지 책임지는 것으로 이해하고 있었는데, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 말한 부분은 아래 코드인데요, 현재 print문은 모두 OutputView에서 작성해주신 것 같아요! System.out.println(); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. view와 controller의 역할을 분리하려고 신경 썼는데, 말씀해주신 부분은 놓쳤네요! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package model; | ||
|
||
import java.util.List; | ||
|
||
public class FixedLottoNumberGenerator implements LottoNumberGenerator { | ||
private final List<LottoNumber> fixedNumbers; | ||
|
||
public FixedLottoNumberGenerator(List<Integer> numbers) { | ||
if (numbers.size() != 6) { | ||
throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); | ||
} | ||
this.fixedNumbers = numbers.stream() | ||
.map(LottoNumber::new) | ||
.toList(); | ||
} | ||
|
||
@Override | ||
public LottoTicket generate() { | ||
return new LottoTicket(fixedNumbers); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package model; | ||
|
||
import java.util.Objects; | ||
|
||
public class LottoNumber { | ||
private final int number; | ||
|
||
public LottoNumber(int number) { | ||
validateRange(number); | ||
this.number = number; | ||
} | ||
|
||
private void validateRange(int number) { | ||
if (number < 1 || number > 45) { | ||
throw new IllegalArgumentException("로또 번호는 1~45 사이여야 합니다"); | ||
} | ||
} | ||
|
||
public int getNumber() { | ||
return number; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return String.valueOf(number); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (!(o instanceof LottoNumber)) return false; | ||
LottoNumber lottoNumber = (LottoNumber) o; | ||
return number == lottoNumber.number; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(number); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package model; | ||
|
||
public interface LottoNumberGenerator { | ||
LottoTicket generate(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package model; | ||
|
||
|
||
import java.util.ArrayList; | ||
import java.util.EnumMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class LottoService { | ||
private final LottoNumberGenerator generator; | ||
|
||
public LottoService() { | ||
this(new RandomLottoNumberGenerator()); | ||
} | ||
|
||
public LottoService(LottoNumberGenerator generator) { | ||
this.generator = generator; | ||
} | ||
|
||
public LottoTicket createOneLotto() { | ||
return generator.generate(); | ||
} | ||
|
||
public LottoTicketBundle createLottos(int count) { | ||
LottoTicketBundle repository = new LottoTicketBundle(); | ||
for (int i = 0; i < count; i++) { | ||
repository.addLottoNumbers(createOneLotto().sortNumbers()); | ||
} | ||
return repository; | ||
} | ||
|
||
public LottoTicket createInputLotto(String inputNumber) { | ||
List<LottoNumber> numbers = parseInputToNumbers(inputNumber); | ||
return new LottoTicket(numbers); | ||
} | ||
|
||
private List<LottoNumber> parseInputToNumbers(String inputNumber) { | ||
String[] rawNumbers = inputNumber.split(","); | ||
List<LottoNumber> numbers = new ArrayList<>(); | ||
for (String raw : rawNumbers) { | ||
numbers.add(new LottoNumber(Integer.parseInt(raw.trim()))); | ||
} | ||
return numbers; | ||
} | ||
|
||
public LottoTicketBundle createManualLottos(List<String> inputs) { | ||
LottoTicketBundle repository = new LottoTicketBundle(); | ||
for (String input : inputs) { | ||
repository.addLottoNumbers(createInputLotto(input)); | ||
} | ||
return repository; | ||
} | ||
|
||
public LottoTicketBundle mergeAutoAndManualLottos(LottoTicketBundle manual, LottoTicketBundle auto) { | ||
LottoTicketBundle repository = new LottoTicketBundle(); | ||
for (LottoTicket lotto : manual.readLottoNumbersRepository()) { | ||
repository.addLottoNumbers(lotto); | ||
} | ||
|
||
for (LottoTicket lotto : auto.readLottoNumbersRepository()) { | ||
repository.addLottoNumbers(lotto); | ||
} | ||
return repository; | ||
} | ||
|
||
public Map<MatchResult, Integer> countMatchResults(List<LottoTicket> allLotteries, | ||
List<LottoNumber> winningLotto, | ||
LottoNumber bonusBall) { | ||
Comment on lines
+66
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 참고) 보통 메서드 인자가 길어지면 이런 형태로 많이 쓰는 것 같아요! public Map<MatchResult, Integer> countMatchResults(
List<LottoTicket> allLotteries,
List<LottoNumber> winningLotto,
LottoNumber bonusBall
) { |
||
Map<MatchResult, Integer> matchCounts = initializeMatchCounts(); | ||
for (LottoTicket lotto : allLotteries) { | ||
int count = matchLottoNumber(lotto.getNumbers(), winningLotto); | ||
boolean bonusMatch = matchBonus(lotto.getNumbers(), bonusBall, count); | ||
MatchResult result = MatchResult.fromCount(count, bonusMatch); | ||
matchCounts.put(result, matchCounts.get(result) + 1); | ||
} | ||
return matchCounts; | ||
} | ||
|
||
private Map<MatchResult, Integer> initializeMatchCounts() { | ||
Map<MatchResult, Integer> counts = new EnumMap<>(MatchResult.class); | ||
for (MatchResult result : MatchResult.values()) { | ||
counts.put(result, 0); | ||
} | ||
return counts; | ||
} | ||
|
||
private int matchLottoNumber(List<LottoNumber> lotto, List<LottoNumber> winningLotto) { | ||
return (int) lotto.stream() | ||
.filter(winningLotto::contains) | ||
.count(); | ||
} | ||
|
||
private boolean matchBonus(List<LottoNumber> lotto, LottoNumber bonusBall, int count) { | ||
if (count == 5) { | ||
return lotto.contains(bonusBall); | ||
} | ||
return false; | ||
} | ||
|
||
public String calculateProfitRate(Map<MatchResult, Integer> matchCounts, int money) { | ||
double profitRate = 0; | ||
for (MatchResult result : matchCounts.keySet()) { | ||
profitRate += matchCounts.get(result) * result.getReward(); | ||
} | ||
profitRate = profitRate / (double) money; | ||
return String.format("%.2f", profitRate); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package model; | ||
|
||
import java.util.*; | ||
|
||
public class LottoTicket { | ||
private final List<LottoNumber> numbers; | ||
|
||
public LottoTicket(List<LottoNumber> numbers) { | ||
validateSize(numbers); | ||
this.numbers = List.copyOf(numbers); | ||
} | ||
|
||
private void validateSize(List<LottoNumber> numbers) { | ||
if (numbers.size() != 6) { | ||
throw new IllegalArgumentException("로또 번호가 6개가 아닙니다"); | ||
} | ||
} | ||
|
||
public LottoTicket sortNumbers() { | ||
List<LottoNumber> sortNumber = new ArrayList<>(numbers); | ||
Collections.sort(sortNumber, Comparator.comparingInt(LottoNumber::getNumber)); | ||
return new LottoTicket(sortNumber); | ||
} | ||
|
||
public List<LottoNumber> getNumbers() { | ||
return numbers; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package model; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
public class LottoTicketBundle { | ||
private final List<LottoTicket> repository = new ArrayList<>(); | ||
|
||
public void addLottoNumbers(LottoTicket lottoTicket) { | ||
repository.add(lottoTicket); | ||
} | ||
|
||
public List<LottoTicket> readLottoNumbersRepository() { | ||
return Collections.unmodifiableList(repository); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 파일에 코틀린 관련 코드가 추가된 것 같은데 무슨 이유인가요?
제 로컬에서는 이 코드로 인해 갑자기 실행이 안 되는 것 같더라구요!