Skip to content
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

oereo 2차과제 제출합니다! #7

Open
wants to merge 72 commits into
base: oereo
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
d9441fe
docs(guide): 구현할 기능 목록과 예외 처리 목록 작성
oereo Apr 1, 2021
16b3952
feat: Lotto 객체 생성 및 테스트 케이스 작성, NotValidLottoLengthException 예외처리 추가
oereo Apr 1, 2021
44d3e1a
feat: 로또 넘버를 랜덤으로 생성해주는 RandomLottoNumberStrategy class 추가
oereo Apr 1, 2021
a6ef619
feat: RandomLottoNumberStrategy class 생성 및 shuffle을 통해서 중복되지 않는 랜덤숫자 …
oereo Apr 1, 2021
3314074
refactor: .gitignore 파일에 out 파일 추가와 setLottoNumberRange 안의 변수 naming 수정
oereo Apr 8, 2021
d58b466
refactor: Lotto class 를 추상화 클래스로 변경
oereo Apr 8, 2021
c0f662f
refactor: LottoValidation class 를 만들어서 Lotto 객체 생성시에 validate 여부 확인
oereo Apr 8, 2021
d1d653f
feat: checkDuplicatedNumber method를 구현함으로써 중복되는 로또 숫자가 들어올 시에 excepti…
oereo Apr 8, 2021
a159daa
feat: checkDuplicatedNumber method 구현
oereo Apr 8, 2021
086390e
feat: NotDuplicatedNumberException class 생성
oereo Apr 8, 2021
468a962
feat: LottoAutomaticTicket class 생성 및 test case 수정
oereo Apr 8, 2021
7154d90
feat: 로또 숫자가 6개일 때 겹치는 숫자가 있을 경우에 대한 테스트 케이스 추가
oereo Apr 8, 2021
abe5f75
refactor: 프로젝트 구조 변경
oereo Apr 8, 2021
4b16472
feat: PurchaseAmount class 생성
oereo Apr 8, 2021
2fdafea
feat: 로또 구입금액 객체를 생성하는 test case 작성
oereo Apr 8, 2021
626d3ce
feat: PurchaseAmount 객체에 대한 validation 체크를 해주는 class 생성
oereo Apr 8, 2021
8d7bcfb
feat: 로또 구입 금액이 0이하일 경우 IllegalArgumentException 을 던지는 test case 작성
oereo Apr 8, 2021
6c7f169
feat: 구입한 금액에 따라 로또 티켓수를 관리하는 LottoTicketOfNumber class 생성
oereo Apr 8, 2021
810e10d
feat: 로또 티켓 수를 관리하는 객체를 생성하는 test case 작성
oereo Apr 8, 2021
410dd30
feat: LottoTicketOfNumber class를 수동복권 장수를 받음과 동시에 각 로또의 수를 관리하는 class…
oereo Apr 8, 2021
105b982
feat: 자동 로또 티켓의 수를 가져오는 test case 와 입력할 로또 구입 금액으로 로또를 살 수 없는 경우 NotV…
oereo Apr 8, 2021
400a17f
feat: LottoTicketOfNumberValidation class 생성
oereo Apr 8, 2021
b93c455
feat: NotValidLottoTicketOfNumberException class 추가
oereo Apr 8, 2021
e679a21
refactor: 불필요하거나 맞지 않는 로직 변경
oereo Apr 8, 2021
ff36d2f
refactor: LottoManualTicket(수동복권) class 추가
oereo Apr 8, 2021
84bce7b
feat: RandomLottoNumberGenerator class 생성
oereo Apr 8, 2021
eb4c72e
refactor: 패키지 구조 변경
oereo Apr 8, 2021
dd367b9
refactor: 패키지 구조 변경
oereo Apr 8, 2021
da70a37
feat: LottoApplication class 생성
oereo Apr 8, 2021
a6dc029
feat: Printer class 생성
oereo Apr 8, 2021
a0d13ba
feat: Receiver class 생성
oereo Apr 8, 2021
1d12786
feat: view logic 을 담당하는 LottoStore class 생성
oereo Apr 8, 2021
5859dc5
feat: requestLottoManualTicketNumber method 구현
oereo Apr 8, 2021
5287a42
feat: inputLottoManualTicketNumber method 구현
oereo Apr 8, 2021
d7e838b
feat: receiverLottoManualTickets method 구현 및 method 에 필요한 convertStri…
oereo Apr 8, 2021
31a24f1
feat: requestLottoManualTicket method 구현
oereo Apr 8, 2021
a4ce239
feat: LottoManualTicket 객체들을 관리하는 LottoManualTickets class 생성
oereo Apr 8, 2021
26d61ed
feat: lottoManualTicket 객체들을 만들고 lottoManualTickets 객체를 만드는 inputLott…
oereo Apr 8, 2021
e48382c
refactor: invalid 한 class 및 method 이름 수정
oereo Apr 8, 2021
5ef4133
feat: generateLottoAutomaticTickets method 구현
oereo Apr 8, 2021
57a0cee
feat: 자동복권과 수동복권을 각각 몇장씩 샀는지 출력하는 printNumberOfEachLottoTicket method 구현
oereo Apr 8, 2021
655004a
refactor: naming 변경 및 구조 변경
oereo Apr 8, 2021
87274f7
refactor: 자동복권 객체들을 관리하는 LottoAutomaticTickets class 구현
oereo Apr 8, 2021
7feae6d
feat: 자동복권을 출력하는 informLottoAutomaticTickets method 구현
oereo Apr 8, 2021
b67f680
feat: LastWeekWinningLotto class 생성
oereo Apr 8, 2021
1eacddf
feat: printLottoAutomaticTickets method 와 printLottoManualTickets met…
oereo Apr 8, 2021
7a26eff
refactor: invalid 한 method naming 수정
oereo Apr 8, 2021
bd9ad04
feat: requestLastWeekLottoWinningNumber method 구현
oereo Apr 8, 2021
c162ffd
refactor: list 에 담기지 않는 문제로 인해 기존 로직으로 수정
oereo Apr 8, 2021
d92e3ef
feat: 자동복권 객체를 생성하고 객체들을 보관하는 LottoAutomaticTicket 객체를 생성하는 generateL…
oereo Apr 8, 2021
589959e
feat: 지난 주 로또 당첨번호를 받는 receiveLastWeekLottoWinningNumbers method 구현
oereo Apr 8, 2021
3a9bc9e
feat: 지난 주 로또 당첨번호를 받는 inputLastWeekWinningLotto method 구현
oereo Apr 8, 2021
11ee54c
feat: LastWeekWinningBonusBall class 구현
oereo Apr 8, 2021
e850955
feat: 보너스볼을 입력을 요구하는 메시지 출력 담당의 requestLottoBonusBallNumber method 구현
oereo Apr 8, 2021
6c97b6e
feat: 로또 결과를 비교하여 matched 된 여부를 파악하는 WinningStatus enum class 생성
oereo Apr 8, 2021
1e60a5d
feat: 보너스볼을 받는 receiveLottoBonusBallNumber method 구현
oereo Apr 8, 2021
e1773ee
feat: 보너스볼을 받고 객체화를 하는 inputLastWeekWinningBonusBall method 구현
oereo Apr 8, 2021
67041a0
feat: 보너스볼 일치여부와 로또번호 일치하는 수를 Map에 담아 반환하는 method 구현
oereo Apr 8, 2021
a6cc6fa
feat: 자동복권의 보너스볼 일치여부와 로또번호 일치하는 수를 Map에 담아 반환하는 method 구현
oereo Apr 8, 2021
3dddc32
feat: 로또 티켓 하나당 일치하는 결과를 담는 객체를 관리하는 LottoMatchStatus class 생성
oereo Apr 8, 2021
3205eca
feat: 일치하는 lotto number 수를 출력하는 printer method 들 구현
oereo Apr 8, 2021
9aaabfa
feat: 로또 결과 통계를 출력하는 method 들 구현
oereo Apr 8, 2021
e2d5526
feat: 수익률을 출력하는 printLottoProfit method 와 수익률이 1보다 작을 경우 출력하는 printIs…
oereo Apr 8, 2021
6b432c5
feat: 수익률에 대한 Profit class 생성
oereo Apr 8, 2021
9fb25c1
feat: getLottoTicketPrice method 구현
oereo Apr 8, 2021
36d6809
feat: informLottoStatistics method 구현
oereo Apr 8, 2021
80d552f
feat: profit 객체를 반환하는 getProfitInformation method 구현
oereo Apr 8, 2021
3d82bb6
feat: run method 구현 및 method 정리
oereo Apr 8, 2021
fc06755
feat: Profit 객체의 수익률이 1보다 클 때의 test case 와 작을 때의 test case 작성
oereo Apr 8, 2021
082fb66
feat: Profit 객체의 수익률을 반환하는 method 에 대한 test case 작성
oereo Apr 8, 2021
7c0aec0
style: 라인 정리 및 띄어쓰기 정리
oereo Apr 8, 2021
8eca2f2
refactor: checkPurchaseAmountNotPositive method 를 PurchaseAmount clas…
oereo Apr 9, 2021
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea/
.gradle/
build/
out
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# 🚀 로또 1단계 - 자동

## 구현할 기능 목록
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기능목록을 구현하면 - [x]로 채워주는게 더 좋을것 같아요!

- [ ] 구입금액을 입력받을 수 있다.
- [ ] 구입금액에 따라 몇개의 로또를 구입했는지 알려준다.
- [ ] 로또의 갯수에 맞추어 1~45까지 6개의 랜덤 숫자 리스트를 만든다.
- [ ] 지난 주 담청 번호를 입력받을 수 있다.
- [ ] 보너스 볼을 입력받을 수 있다.
- [ ] 담청 통계를 출력한다.
- [ ] 로또와 담청 번호를 비교하여 각 몇개의 숫자가 맞았는지 출력한다.
- [ ] 총 수익률을 소숫점 2번째 자리까지 출력한다.

## 예외 처리 목록
- [ ] 구입금액이 0원일 경우 로또 한장의 가격이 1000원이라는 메시지와 함께 `구입금액을 입력해주세요` 라는 메시지를 출력한다.
- [ ] 로또 넘버의 범위는 1~45까지로 제한하며 이외의 숫자는 허용하지 않는다.
- [ ] 담청번호와 보너스 번호가 같은 상황은 허용하지 않는다.
- [ ] 저번주 담청번호들이 2개 이상 중복되는 것을 허용하지 않는다.

## 기능 요구사항
- 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다.
- 로또 1장의 가격은 1000원이다.
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/lotto/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package lotto;

import lotto.domain.LottoStore;
import lotto.domain.NumberOfLottoTicket;
import lotto.domain.PurchaseAmount;
import lotto.domain.lotto.LastWeekWinningBonusBall;
import lotto.domain.lotto.LastWeekWinningLotto;
import lotto.domain.lotto.LottoAutomaticTickets;
import lotto.domain.lotto.LottoManualTickets;

public class LottoApplication {
private final LottoStore lottoStore = new LottoStore();

public void run() {
PurchaseAmount purchaseAmount = lottoStore.inputLottoPurchaseAmount();
int lottoManualTicketNumber = lottoStore.inputLottoManualTicketNumber();
LottoManualTickets lottoManualTickets = lottoStore.inputLottoManualTickets(lottoManualTicketNumber);
NumberOfLottoTicket numberOfLottoTicket = lottoStore.informNumberOfLottoTicket(purchaseAmount, lottoManualTicketNumber);
LottoAutomaticTickets lottoAutomaticTickets = lottoStore.informLottoAutomaticTickets(lottoManualTickets, numberOfLottoTicket);
LastWeekWinningLotto lastWeekWinningLotto = lottoStore.inputLastWeekWinningLotto();
LastWeekWinningBonusBall lastWeekWinningBonusBall = lottoStore.inputLastWeekWinningBonusBall();
lottoStore.informLottoStatistics(numberOfLottoTicket, lottoManualTickets, lottoAutomaticTickets, lastWeekWinningLotto, lastWeekWinningBonusBall);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정하기 -> method에 4개이상의 인자 받지 않기 -> 객체로 빼기

Comment on lines +15 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다양한 객체에게 역할을 위임하고 값을 리턴 받으면서 로직이 진행되어야 하는데,
지금처럼 LottoStore에게서만 위임한다면 굳이 LottoApplication으로 값을 리턴받을 필요가 있을까요?

그리고 한 가지 객체(LottoStore)에게만 값을 요청한다는 것은 그 객체가 갖고 있는 책임이 많다는 것을 의미하기도 해요.
역할에 맞는 다양한 객체로 분리해보는건 어떨까요?

}

public static void main(String[] args) {
LottoApplication app = new LottoApplication();
app.run();
Comment on lines +26 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Application이 Application을 생성해서 실행시키는 것이 어색하게 느껴지네요.
run()은 애플리케이션의 흐름을 제어하면서 로직을 진행시키는 것 같은데 이것을 따로 객체로 분리해보면 어떨까요?
MVC 패턴과 Controller의 역할에 대해 학습해보면 좋을것같아요.

https://m.blog.naver.com/jhc9639/220967034588

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

import lotto.domain.lotto.*;
import lotto.domain.strategy.RandomLottoNumberGenerator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class LottoMachine {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자동 티켓 만들기, 수동 티켓과 지난주 당첨번호 비교, 자동 티켓과 지난주 당첨번호 비교, 전체 로또 티켓의 비교 결과로 당첨 통계 내기, 총 수익률 계산까지 이 모든 것들을 담기에는 LottoMachine의 그릇이 너무 작은 것 같네요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

빈약한 도메인모델의 문제점을 해결하면서 method들도 최대한 분리 시키고 LottoMachine 의 역할을 명확하게 다시 바꿔볼게요!

private final static int LOTTO_SIZE = 6;
private final static int WINNING_LOTTO_WITH_BONUS_BALL_MATCHED_COUNT = 5;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수명을 보너스 볼 없이 5개의 matchedCount를 가진 경우도 포함될 수 있게 해주세요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보너스 볼이 있는 경우의 WINNING_LOTTO_WITH_BONUS_BALL_MATCHED_COUNT = 5 로 상수를 빼놓은 이유는 이 경우에 대한 예외처리가 필요해서 넣은 거였습니다! 상수명을 보너스 볼 없이 라는 의미를 같이 넣을 경우 밑에서 예외처리를 할 때 의미전달이 잘 될지가 살짝 의문인 것 같아요!


private final RandomLottoNumberGenerator randomLottoNumberGenerator = new RandomLottoNumberGenerator();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateLottoAutomaticTicket()에서만 사용되고 있네요

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LottoMachine에 대한 테스트가 없어서 체감을 못하셨을텐데, 랜덤으로 인해 generateLottoAutomaticTicket()를 테스트하기 어려울거에요.
RandomLottoNumberGenerator를 인터페이스로 추출하고 LottoMachine을 생성하는 부분에서 RandomLottoNumberGenerator를 넣어주는 방식으로 변경해보세요!

private final ArrayList<WinningStatus> lottoPrices = new ArrayList<>();

public LottoAutomaticTickets generateLottoAutomaticTicket(NumberOfLottoTicket numberOfLottoTicket) {
int numberOfLottoAutomaticTicket = numberOfLottoTicket.getAutomaticLottoTicketOfNumber();
List<LottoAutomaticTicket> lottoAutomaticTicket = IntStream.range(0, numberOfLottoAutomaticTicket).
mapToObj(lottoTicket -> new LottoAutomaticTicket(randomLottoNumberGenerator.getRandomLottoNumbers())).
collect(Collectors.toList());
return new LottoAutomaticTickets(lottoAutomaticTicket);
}

public List<LottoMatchStatus> lottoManualTicketsDiscriminator(
LottoManualTickets lottoManualTickets,
LastWeekWinningLotto lastWeekWinningLotto,
LastWeekWinningBonusBall lastWeekWinningBonusBall) {
List<LottoMatchStatus> lottoMatchStatuses = new ArrayList<>();

for (LottoManualTicket lottoManualTicket : lottoManualTickets.getLottoManualTickets()) {
int matchedLottoManualTicketCount = calculateMatchedLottoManualTicket(lottoManualTicket, lastWeekWinningLotto);
Boolean isMatchedBonusBall = calculateMatchedBonusBallManualTicket(lottoManualTicket, lastWeekWinningBonusBall);
LottoMatchStatus lottoMatchStatus = new LottoMatchStatus(matchedLottoManualTicketCount, isMatchedBonusBall);
lottoMatchStatuses.add(lottoMatchStatus);
}
Comment on lines +34 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LottoManualTicket를 get()해서 처리하고 있다는 것은 이 로직이 LottoManualTicket의 역할이란 의미에요.
LottoManualTicket 내부로 로직을 이동해보세요!

return lottoMatchStatuses;
}

public List<LottoMatchStatus> lottoAutomaticTicketsDiscriminator(
LottoAutomaticTickets lottoAutomaticTickets,
LastWeekWinningLotto lastWeekWinningLotto,
LastWeekWinningBonusBall lastWeekWinningBonusBall) {
List<LottoMatchStatus> lottoMatchStatuses = new ArrayList<>();

for (LottoAutomaticTicket lottoAutomaticTicket : lottoAutomaticTickets.getLottoAutomaticTickets()) {
int matchedLottoAutomaticTicketCount = calculateMatchedLottoAutomaticTicket(lottoAutomaticTicket, lastWeekWinningLotto);
Boolean isMatchedBonusBall = calculateMatchedBonusBallAutomaticTicket(lottoAutomaticTicket, lastWeekWinningBonusBall);
LottoMatchStatus lottoMatchStatus = new LottoMatchStatus(matchedLottoAutomaticTicketCount, isMatchedBonusBall);
lottoMatchStatuses.add(lottoMatchStatus);
}
Comment on lines +49 to +54
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마찬가지로 lottoAutomaticTickets의 역할로 변경해보세요 :)

return lottoMatchStatuses;
}

private Boolean calculateMatchedBonusBallAutomaticTicket(
LottoAutomaticTicket lottoAutomaticTicket,
LastWeekWinningBonusBall lastWeekWinningBonusBall) {

List<Integer> lottoTicket = lottoAutomaticTicket.getLotto();
int WinningBonusBalls = lastWeekWinningBonusBall.getLastWeekWinningBonusBall();
return lottoTicket.contains(WinningBonusBalls);
}
Comment on lines +58 to +65
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calculateMatchedBonusBallManualTicket()와 포맷이 아예 같네요!
다형성을 이용하여 하나의 메서드로 줄일 수 있을 것 같아요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 이부분을 진짜 어떻게 해야될지 고민을 많이 했는데 다형성을 이용해야겠네요!


private int calculateMatchedLottoAutomaticTicket(
LottoAutomaticTicket lottoAutomaticTicket,
LastWeekWinningLotto lastWeekWinningLotto) {
Comment on lines +67 to +69
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 또한 calculateMatchedLottoManualTicket()과 포맷이 아예 같군요또한 calculateMatchedLottoManualTicket()과 구현 내용이 아예 같군요

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요. 동일한 기능을 하는 객체를 추출하는 방식으로 변경해보는건 어떨까요?


List<Integer> lottoTicket = lottoAutomaticTicket.getLotto();
List<Integer> lastWeekWinningLottoTicket = lastWeekWinningLotto.getLotto();
int matchedCount = 0;
for (int lottoNumber = 0; lottoNumber < LOTTO_SIZE; lottoNumber++) {
Boolean isMatchLottoNumber = lottoTicket.contains(lastWeekWinningLottoTicket.get(lottoNumber));
matchedCount += countMatchedLottoNumber(isMatchLottoNumber);
Comment on lines +75 to +76
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Boolean isMatchLottoNumber = lottoTicket.contains(lastWeekWinningLottoTicket.get(lottoNumber));
matchedCount += countMatchedLottoNumber(isMatchLottoNumber);
if(lottoTicket.contains(lastWeekWinningLottoTicket.get(lottoNumber)) {
matchCount++;
}
continue;

이렇게 하고 lottoTicket.contains(lastWeekWinningLottoTicket.get(lottoNumber)를 적절한 이름으로 추출하는 것이 더 나아보여요

}
return matchedCount;

}

private Boolean calculateMatchedBonusBallManualTicket(
LottoManualTicket lottoManualTicket,
LastWeekWinningBonusBall lastWeekWinningBonusBall) {

List<Integer> lottoTicket = lottoManualTicket.getLotto();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이곳 뿐만 아니라 대부분의 코드에서,
로또 티켓이 List 타입이라서 관련된 행위들이 전부다 get()해서 사용되어지고 있어요.
그리고 그러다보니 제약사항이나 관련된 기능도 모두 선언하는 곳이 아니라 사용하는 곳에서 이루어지고 있어요.

원시값을 포장하고, 관련된 로직을 해당 객체 안에서 처리하는 방식으로 변경하면 좋을 것 같아요 :)

int WinningBonusBalls = lastWeekWinningBonusBall.getLastWeekWinningBonusBall();
return lottoTicket.contains(WinningBonusBalls);
}

private int calculateMatchedLottoManualTicket(
LottoManualTicket lottoManualTicket,
LastWeekWinningLotto lastWeekWinningLotto) {

List<Integer> lottoTicket = lottoManualTicket.getLotto();
List<Integer> lastWeekWinningLottoTicket = lastWeekWinningLotto.getLotto();
int matchedCount = 0;
for (int lottoNumber = 0; lottoNumber < LOTTO_SIZE; lottoNumber++) {
Boolean isMatchLottoNumber = lottoTicket.contains(lastWeekWinningLottoTicket.get(lottoNumber));
matchedCount += countMatchedLottoNumber(isMatchLottoNumber);
}
Comment on lines +98 to +101
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위와 마찬가지로 변경해보세요 :)

return matchedCount;
}

private int countMatchedLottoNumber(Boolean isMatchLottoNumber) {
if (isMatchLottoNumber) {
return 1;
}
return 0;
}

public List<WinningStatus> getStatistics(List<LottoMatchStatus> lottoAllTicketMatchStatuses) {
for (LottoMatchStatus lottoMatchStatus : lottoAllTicketMatchStatuses) {
mappingLottoTicketWithBonusBall(lottoMatchStatus);
}
return lottoPrices;
}

private void mappingLottoTicketWithBonusBall(LottoMatchStatus lottoMatchStatus) {
for (WinningStatus winningStatus : WinningStatus.values()) {
compareWinningStatus(winningStatus, lottoMatchStatus.getMatchedCount(), lottoMatchStatus.getHasBonusBall());
}
}
Comment on lines +119 to +123
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matchedCount와 hasBonusBall 두 개를 비교하는데 메서드 이름은 mappingLottoTicketWithBonusBall이네요ㅠㅠ


private void compareWinningStatus(WinningStatus winningStatus, int lottoMatchedCount, Boolean hasBonusBall) {
if ((winningStatus.getMatchCount() == lottoMatchedCount) && (lottoMatchedCount != WINNING_LOTTO_WITH_BONUS_BALL_MATCHED_COUNT)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if문이 길어질땐 if문의 조건 식을 메소드로 추출해서 직관적으로 표현하는 것이 좋습니다 :)

lottoPrices.add(winningStatus);
}
if ((winningStatus.hasBonusBall() == hasBonusBall) && (lottoMatchedCount == WINNING_LOTTO_WITH_BONUS_BALL_MATCHED_COUNT)) {
lottoPrices.add(winningStatus);
}
}
Comment on lines +125 to +132
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private void compareWinningStatus(WinningStatus winningStatus, int lottoMatchedCount, Boolean hasBonusBall) {
if ((winningStatus.getMatchCount() == lottoMatchedCount) && (lottoMatchedCount != WINNING_LOTTO_WITH_BONUS_BALL_MATCHED_COUNT)) {
lottoPrices.add(winningStatus);
}
if ((winningStatus.hasBonusBall() == hasBonusBall) && (lottoMatchedCount == WINNING_LOTTO_WITH_BONUS_BALL_MATCHED_COUNT)) {
lottoPrices.add(winningStatus);
}
}
private void compareWinningStatus(WinningStatus winningStatus, int lottoMatchedCount, Boolean hasBonusBall) {
if (매치 카운트 5개일 경우 || 매치 카운트 5 아닐 경우) {
lottoPrices.add(winningStatus);
}
}

if문 안을 메서드로 분리하여 이렇게 통일할 수 있겠어요


public Map<WinningStatus, Integer> getMappingLottoWithBonusBall() {
Map<WinningStatus, Integer> mappingLottoWithBonusBall = new HashMap<>();

for (WinningStatus key : lottoPrices) {
mappingLottoWithBonusBall.put(key, mappingLottoWithBonusBall.getOrDefault(key, 0) + 1);
}
return mappingLottoWithBonusBall;
}

public Profit getProfitInformation(List<WinningStatus> lottoStatistics, NumberOfLottoTicket numberOfLottoTicket) {
return new Profit(lottoStatistics, numberOfLottoTicket);
}
}
19 changes: 19 additions & 0 deletions src/main/java/lotto/domain/LottoMatchStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package lotto.domain;

public class LottoMatchStatus {
private final int matchedCount;
private final Boolean hasBonusBall;

public LottoMatchStatus(int matchedCount, Boolean hasBonusBall) {
this.matchedCount = matchedCount;
this.hasBonusBall = hasBonusBall;
}

public int getMatchedCount() {
return matchedCount;
}

public Boolean getHasBonusBall() {
return hasBonusBall;
}
}
80 changes: 80 additions & 0 deletions src/main/java/lotto/domain/LottoStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package lotto.domain;

import lotto.domain.lotto.*;
import lotto.ui.Printer;
import lotto.ui.Receiver;

import java.util.ArrayList;
import java.util.List;

public class LottoStore {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어플리케이션의 전체적인 흐름을 담당하는 클래스군요

private final Printer printer = new Printer();
private final Receiver receiver = new Receiver();
private final LottoMachine lottoMachine = new LottoMachine();

public PurchaseAmount inputLottoPurchaseAmount() {
printer.requestPurchaseAmount();
int lottoPurchaseAmount = receiver.receiveLottoPurchaseAmount();

return new PurchaseAmount(lottoPurchaseAmount);
}

public int inputLottoManualTicketNumber() {
printer.requestLottoManualTicketNumber();
return receiver.receiverLottoManualTicketNumber();
}

public LottoManualTickets inputLottoManualTickets(int lottoManualTicketNumber) {
ArrayList<LottoManualTicket> lottoManualTicketDummy = new ArrayList<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

printer.requestLottoManualTicket();
for (int lottoTicket = 0; lottoTicket < lottoManualTicketNumber; lottoTicket++) {
LottoManualTicket lottoManualTicket = new LottoManualTicket(receiver.receiverLottoManualTicket());
lottoManualTicketDummy.add(lottoManualTicket);
}
return new LottoManualTickets(lottoManualTicketDummy);
}

public LottoAutomaticTickets informLottoAutomaticTickets(LottoManualTickets lottoManualTickets, NumberOfLottoTicket numberOfLottoTicket) {
printer.printLottoManualTickets(lottoManualTickets);
LottoAutomaticTickets lottoAutomaticTickets = lottoMachine.generateLottoAutomaticTicket(numberOfLottoTicket);
printer.printLottoAutomaticTickets(lottoAutomaticTickets);
return lottoAutomaticTickets;
}
Comment on lines +37 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구매한 수동 로또 티켓을 출력하고, 자동 로또 티켓을 만들고, 자동 로또 티켓을 출력하기까지의 기능을 informLottoAutomaticTickets()라는 이름이 모두 나타내기엔 아쉬워요


public NumberOfLottoTicket informNumberOfLottoTicket(PurchaseAmount purchaseAmount, int lottoManualTicketNumber) {
NumberOfLottoTicket numberOfLottoTicket = new NumberOfLottoTicket(purchaseAmount, lottoManualTicketNumber);
printer.printNumberOfEachLottoTicket(numberOfLottoTicket);
return numberOfLottoTicket;
}
Comment on lines +37 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app의 전체적인 흐름을 담당하는 클래스이므로 메서드도 그 흐름 순서대로면 좋을 것 같아요~


public LastWeekWinningLotto inputLastWeekWinningLotto() {
printer.requestLastWeekLottoWinningNumber();
List<Integer> LastWeekLottoWinningNumbers = receiver.receiveLastWeekLottoWinningNumbers();
return new LastWeekWinningLotto(LastWeekLottoWinningNumbers);
}

public LastWeekWinningBonusBall inputLastWeekWinningBonusBall() {
printer.requestLottoBonusBallNumber();
int BonusBall = receiver.receiveLottoBonusBallNumber();
return new LastWeekWinningBonusBall(BonusBall);
}

public void informLottoStatistics(
NumberOfLottoTicket numberOfLottoTicket,
LottoManualTickets lottoManualTickets,
LottoAutomaticTickets lottoAutomaticTickets,
LastWeekWinningLotto lastWeekWinningLotto,
LastWeekWinningBonusBall lastWeekWinningBonusBall) {
Comment on lines +62 to +67
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인자가 너무 많다는 것은 메소드가 너무 많은 일을 한다는 의미에요.
메소드의 책임을 분리해보세요 :)


List<LottoMatchStatus> lottoAllTicketMatchStatuses = new ArrayList<>();
List<LottoMatchStatus> lottoManualTicketMatchStatuses = lottoMachine.lottoManualTicketsDiscriminator(lottoManualTickets, lastWeekWinningLotto, lastWeekWinningBonusBall);
List<LottoMatchStatus> lottoAutomaticTicketMatchStatuses = lottoMachine.lottoAutomaticTicketsDiscriminator(lottoAutomaticTickets, lastWeekWinningLotto, lastWeekWinningBonusBall);
lottoAllTicketMatchStatuses.addAll(lottoManualTicketMatchStatuses);
lottoAllTicketMatchStatuses.addAll(lottoAutomaticTicketMatchStatuses);
List<WinningStatus> lottoStatistics = lottoMachine.getStatistics(lottoAllTicketMatchStatuses);
printer.printAllMatchedLottoResults(lottoMachine.getMappingLottoWithBonusBall());
Profit profit = lottoMachine.getProfitInformation(lottoStatistics, numberOfLottoTicket);
printer.printLottoProfit(profit.getProfit());
printer.printIsLottoProfit(profit.isProfit());
Comment on lines +69 to +78
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

줄바꿈으로 가독성을 높여주세요

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lottoMachine.lottoManualTicketsDiscriminator()lottoMachine.lottoAutomaticTicketsDiscriminator()의 결과를 받아와서 그대로 다시 lottoMachine으로 넘겨주는군요. 굳이 LottoStore로 넘겨주지 않고도 LottoMachine 내에서 알아서 만들어서 lottoMachine.getStatistics() 한 줄만으로도 결과를 가져올 수 있겠네요

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

import lotto.domain.validation.LottoTicketOfNumberValidation;

public class NumberOfLottoTicket {
private final static int LOTTO_TICKET_PRICE = 1000;

private final int totalNumberOfLottoTicket;
private final int numberOfManualLottoTicket;
private final int automaticLottoTicketOfNumber;

public NumberOfLottoTicket(PurchaseAmount purchaseAmount, int purchaseManualLottoOfNumber) {
LottoTicketOfNumberValidation lottoTicketOfNumberValidation = new LottoTicketOfNumberValidation();
this.totalNumberOfLottoTicket = calculateLottoTicketOfNumber(purchaseAmount.getPurchaseAmount());
this.numberOfManualLottoTicket = purchaseManualLottoOfNumber;
this.automaticLottoTicketOfNumber = calculateAutomaticLottoTicketOfNumber(totalNumberOfLottoTicket, numberOfManualLottoTicket);
lottoTicketOfNumberValidation.checkLottoTicketOfNumber(this.totalNumberOfLottoTicket);
Comment on lines +13 to +17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

totalNumberOfLottoTicket을 계산하고 다른 값을 넣어주기 전에 바로 Validation.check()를 해주는게 검증의 의미가 있을 것 같아요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그 저번주에 코드진행으로 보여주신 것에서
this.purchasedAmount = purchaseAmount 다음에 validateNotPositive()를 넣으신 것을 예제로 보여주신 부분이 있는데 이것과 다른건가요?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 아뇨 값을 주입한 후에 validate를 진행하는 순서에 대해 얘기한 것이 아니라

this.automaticLottoTicketOfNumber = calculateAutomaticLottoTicketOfNumber(totalNumberOfLottoTicket, numberOfManualLottoTicket);  // line 16

에서 totalNumberOfLottoTicket이 사용되는데, 여기서 검증이 된 totalNumberOfLottoTicket가 사용되어야지 맞지 않나라는 말이었습니다!

this.totalNumberOfLottoTicket = totalNumberOfLottoTicket -> this.totalNumberOfLottoTicket 검증 -> automaticLottoTicketOfNumber 계산할 때 totalNumberOfLottoTicket 사용 이 순서요!

}

private int calculateLottoTicketOfNumber(int purchaseAmount) {
return purchaseAmount / LOTTO_TICKET_PRICE;
}

private int calculateAutomaticLottoTicketOfNumber(int lottoTicketOfTotalNumber, int manualLottoTicketOfNumber) {
return lottoTicketOfTotalNumber - manualLottoTicketOfNumber;
}

public int getLottoTicketPrice() {
return LOTTO_TICKET_PRICE;
}
Comment on lines +28 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static이면 getter가 아니라 public으로 열어두고 사용해도 될 것 같아요


public int getNumberOfManualLottoTicket() {
return numberOfManualLottoTicket;
}

public int getAutomaticLottoTicketOfNumber() {
return automaticLottoTicketOfNumber;
}

public int getTotalNumberOfLottoTicket() {
return totalNumberOfLottoTicket;
}

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

import java.util.List;

public class Profit {
private static final int PROFIT_THRESHOLD = 1;

private final int sumLottoPrices;
private final NumberOfLottoTicket numberOfLottoTicket;
private final float calculatedProfit;

public Profit(List<WinningStatus> lottoPrices, NumberOfLottoTicket numberOfLottoTicket) {
this.sumLottoPrices = sumLottoPrices(lottoPrices);
this.numberOfLottoTicket = numberOfLottoTicket;
this.calculatedProfit = CalculatedProfit();
}

private int sumLottoPrices(List<WinningStatus> lottoPrices) {
return lottoPrices.stream().mapToInt(WinningStatus::getWinningMoney).sum();
}

private float CalculatedProfit() {
return (float) sumLottoPrices / (numberOfLottoTicket.getTotalNumberOfLottoTicket() * numberOfLottoTicket.getLottoTicketPrice());
}
Comment on lines +22 to +24
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

티켓의 개수를 상태를 가질 필요 없이 인자로만 넘겨줘도 될 것 같아요

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

메서드명은 lower camel case!


public boolean isProfit() {
if (calculatedProfit < PROFIT_THRESHOLD) {
return false;
}
return true;
}
Comment on lines +26 to +31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if에 노란 박스가 뜨네요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쿄쿄쿄쿄.... !(calculatedProfit < PROFIT_THRESHOLD); 이것으로 다시 바꾸었습니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 :) calculatedProfit 이 PROFIT_THRESHOLD보다 작은게 아니다 보다는 calculatedProfit > PROFIT_THRESHOLD가 훨씬 눈에 잘 들어올 것 같네요!


public float getProfit() {
return calculatedProfit;
}
}
Loading