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

java-lotto step2 #3265

Open
wants to merge 11 commits into
base: prolkh
Choose a base branch
from
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@
* 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.

## 온라인 코드 리뷰 과정
* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)
* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)


## step2 요구사항
* [x] 로또 구매
* [x] 자동생성
* [x] 당첨번호 확인,
* [x] 수익률 계산 기능
26 changes: 26 additions & 0 deletions src/main/java/lotto/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package lotto;

import lotto.domain.LottoBuy;
import lotto.domain.LottoWin;

import java.util.Scanner;

public class LottoApplication {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

System.out.println("구입금액을 입력해 주세요.");
int purchasePrice = Integer.parseInt(scanner.nextLine());

LottoBuy lottoBuy = new LottoBuy(purchasePrice);

System.out.println(lottoBuy);

System.out.println("지난 주 당첨 번호를 입력해주세요");
String winNumber = scanner.nextLine();

LottoWin lottoWin = new LottoWin(lottoBuy, winNumber);

System.out.println(lottoWin);
}
}
36 changes: 36 additions & 0 deletions src/main/java/lotto/domain/LottoBuy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package lotto.domain;

import java.util.Map;

public class LottoBuy {

private final LottoBuyCount lottoBuyCount;
private final LottoTickets lottoTickets;

public LottoBuy(int buyPrice) {
lottoBuyCount = new LottoBuyCount(buyPrice);
lottoTickets = new LottoTickets(lottoBuyCount);
}

public LottoBuy(String lottoTicketString) {
lottoBuyCount = new LottoBuyCount(lottoTicketString);
lottoTickets = new LottoTickets(lottoTicketString);
}

public boolean lottoBuyCountIsEqualTo(int otherLottoCount) {
return this.lottoBuyCount.isEqualTo(otherLottoCount);
}

@Override
public String toString() {
return lottoBuyCount + "개를 구매했습니다.\n" + lottoTickets;
}
Comment on lines +24 to +27
Copy link

Choose a reason for hiding this comment

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

도메인(model) 내부에 출력(view)과 관련된 로직이 들어가 있으면 안 돼요
model 과 view 를 분리해주세요~!


public Map<Integer, Integer> calculateLottoWinStatistics(LottoWinNumber lottoWinNumber) {
return lottoTickets.calculateLottoWinStatistics(lottoWinNumber);
}

public int getLottoBuyPrice() {
return lottoBuyCount.getLottoBuyPrice();
}
}
37 changes: 37 additions & 0 deletions src/main/java/lotto/domain/LottoBuyCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package lotto.domain;

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

public class LottoBuyCount {

private static final int LOTTO_PRICE = 1000;

private final int lottoBuyCount;

LottoBuyCount(int buyPrice) {
this.lottoBuyCount = buyPrice / LOTTO_PRICE;
Copy link

Choose a reason for hiding this comment

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

buyPrice 가 음수이거나 0 일 경우는 어떤 일이 벌어지나요?

}

// 테스트용 생성자
public LottoBuyCount(String lottoTicketString) {
this.lottoBuyCount = lottoTicketString.split("\n").length;
}

public boolean isEqualTo(int otherLottoCount) {
return this.lottoBuyCount == otherLottoCount;
}

@Override
public String toString() {
return String.valueOf(lottoBuyCount);
}

public int getLottoBuyCount() {
return lottoBuyCount;
}

public int getLottoBuyPrice() {
return lottoBuyCount * LOTTO_PRICE;
}
}
17 changes: 17 additions & 0 deletions src/main/java/lotto/domain/LottoNumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package lotto.domain;

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

public class LottoNumberGenerator {

public List<Integer> generateLottoNumbers() {
List<Integer> lottoNumbers = new ArrayList<>();
Copy link

Choose a reason for hiding this comment

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

1부터 45 까지의 lottoNumber 도 LottoNumber 클래스로 래핑해주세요~!


for(int i = 1; i <= 45; i++) {
lottoNumbers.add(i);
}

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

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

public class LottoTicket {
private final List<Integer> lottoNumbers = new ArrayList<>();

LottoTicket() {
List<Integer> numbers = new LottoNumberGenerator().generateLottoNumbers();
Collections.shuffle(numbers);

for(int i = 0; i < 6; i++) {
lottoNumbers.add(numbers.get(i));
}

Collections.sort(lottoNumbers);
}

// 테스트용 생성자
public LottoTicket(String lottoTicketString) {
String[] split = lottoTicketString.replaceAll("\\[|]", "").split(",");

for (String s : split) {
lottoNumbers.add(Integer.valueOf(s.trim()));
}
}

@Override
public String toString() {
return lottoNumbers.toString();
}

public List<Integer> getLottoNumbers() {
return lottoNumbers;
}

public int getMatchCount(LottoWinNumber lottoWinNumber) {
return lottoWinNumber.countMatchingNumbers(lottoNumbers);
}
}
50 changes: 50 additions & 0 deletions src/main/java/lotto/domain/LottoTickets.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package lotto.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LottoTickets {

private final List<LottoTicket> lottoTickets;

public LottoTickets(LottoBuyCount lottoBuyCount) {
lottoTickets = new ArrayList<>();
for(int i=0; i < lottoBuyCount.getLottoBuyCount(); i++) {
lottoTickets.add(new LottoTicket());
}
}

// 테스트용 생성자
public LottoTickets(String lottoTicketsString) {
String[] split = lottoTicketsString.split("\n");

lottoTickets = new ArrayList<>();
for (String s : split) {
lottoTickets.add(new LottoTicket(s));
}
}

public Map<Integer, Integer> calculateLottoWinStatistics(LottoWinNumber lottoWinNumber) {
Map<Integer, Integer> resultMap = new HashMap<>();
Copy link

Choose a reason for hiding this comment

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

변수명에 컬렉션 이름(list, map, set 등)을 사용하지 말아주세요, 객체지향적인 사고를 저해하는 요소입니다.

Copy link

Choose a reason for hiding this comment

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

result 도 별도의 클래스로 추출해 보면 어떨까요?


for (LottoTicket lottoTicket : lottoTickets) {
int idx = lottoTicket.getMatchCount(lottoWinNumber);
resultMap.put(idx, resultMap.getOrDefault(idx, 0) + 1);
}

return resultMap;
}

@Override
public String toString() {
StringBuilder result = new StringBuilder();

for (LottoTicket lottoTicket : lottoTickets) {
result.append(lottoTicket.toString()).append("\n");
}

return result.toString();
}
}
17 changes: 17 additions & 0 deletions src/main/java/lotto/domain/LottoWin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package lotto.domain;

public class LottoWin {
public static final String HEADER = "당첨통계\n---------\n";
private final LottoWinNumber lottoWinNumber;
private final LottoWinStatistics lottoWinStatistics;

public LottoWin(LottoBuy lottoBuy, String winNumberString) {
this.lottoWinNumber = new LottoWinNumber(winNumberString);
this.lottoWinStatistics = new LottoWinStatistics(lottoBuy, lottoWinNumber);
}

@Override
public String toString() {
return HEADER + lottoWinStatistics;
}
}
34 changes: 34 additions & 0 deletions src/main/java/lotto/domain/LottoWinNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package lotto.domain;

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

public class LottoWinNumber {

private final List<Integer> lottoWinNumber;

// 문자열을 당첨문자열로 변경
LottoWinNumber(String winNumberString) {
String[] split = winNumberString.split(",");
lottoWinNumber = new ArrayList<>();

for (String s : split) {
lottoWinNumber.add(Integer.parseInt(s.trim()));
}
}

// 당첨번호와 일치하는 개수 카운트
public int countMatchingNumbers(List<Integer> lottoNumbers) {
int result = 0;

for (Integer lottoNumber : lottoNumbers) {
result += getMatchCount(lottoNumber);
}

return result;
}

public int getMatchCount(Integer lottoNumber) {
return lottoWinNumber.contains(lottoNumber) ? 1 : 0;
}
}
69 changes: 69 additions & 0 deletions src/main/java/lotto/domain/LottoWinStatistics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package lotto.domain;

import java.util.Map;

public class LottoWinStatistics {
Copy link

Choose a reason for hiding this comment

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

로또 결과는 일치하는 갯수와 당첨금으로 구성되어 있습니다.
이는 변하지 않는 값인데요 enum으로 구현해보면 어떨까요?


private static final float MATCH_THREE_PRIZE = 5_000;
private static final float MATCH_FOUR_PRIZE = 50_000;
private static final float MATCH_FIVE_PRIZE = 1_500_000;
private static final float MATCH_SIX_PRIZE = 2_000_000_000;

private final Map<Integer, Integer> lottoWinStatistics;
private final Float rateOfReturn;

public LottoWinStatistics(LottoBuy lottoBuy, LottoWinNumber lottoWinNumber) {
this.lottoWinStatistics = lottoBuy.calculateLottoWinStatistics(lottoWinNumber);
this.rateOfReturn = getRateOfReturn(lottoBuy.getLottoBuyPrice());
}

private String getThreeMatches() {
return "3개 일치 (5000원)- " + lottoWinStatistics.getOrDefault(3, 0) + "개\n";
}

private String getFourMatches() {
return "4개 일치 (50000원)- " + lottoWinStatistics.getOrDefault(4, 0) + "개\n";
}

private String getFiveMatches() {
return "5개 일치 (1500000원)- " + lottoWinStatistics.getOrDefault(5, 0) + "개\n";
}

private String getSixMatches() {
return "6개 일치 (2000000000원)- " + lottoWinStatistics.getOrDefault(6, 0)+ "개\n";
}

private String getConclusion() {
double roundedRateOfReturn = Math.floor(rateOfReturn * 100) / 100;
String result = String.format("총 수익률은 %.2f입니다.", roundedRateOfReturn);

if (rateOfReturn < 1) {
result += "(기준이 1이기 때문에 결과적으로 손해라는 의미임)";
}

return result;
}

private Float getRateOfReturn(int lottoBuyPrice) {
int threeMatchCount = lottoWinStatistics.getOrDefault(3, 0);
int fourMatchCount = lottoWinStatistics.getOrDefault(4, 0);
int fiveMatchCount = lottoWinStatistics.getOrDefault(5, 0);
int sixMatchCount = lottoWinStatistics.getOrDefault(6, 0);


return (MATCH_THREE_PRIZE * threeMatchCount
+ MATCH_FOUR_PRIZE * fourMatchCount
+ MATCH_FIVE_PRIZE * fiveMatchCount
+ MATCH_SIX_PRIZE * sixMatchCount)
/ lottoBuyPrice;
}

@Override
public String toString() {
return getThreeMatches()
+ getFourMatches()
+ getFiveMatches()
+ getSixMatches()
+ getConclusion();
}
}
14 changes: 14 additions & 0 deletions src/test/java/lotto/domain/LottoBuyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lotto.domain;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class LottoBuyTest {

@Test
void 로또_구매() {
LottoBuy lottoBuy = new LottoBuy(14000);

Assertions.assertThat(lottoBuy.lottoBuyCountIsEqualTo(14)).isTrue();
}
}
21 changes: 21 additions & 0 deletions src/test/java/lotto/domain/LottoTicketTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package lotto.domain;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.*;

class LottoTicketTest {

@Test
void 로또_번호_생성() {
LottoTicket lottoTicket = new LottoTicket();

System.out.println(lottoTicket);

// Then
assertThat(lottoTicket.getLottoNumbers()).hasSize(6);
assertThat(lottoTicket.getLottoNumbers().stream().allMatch(number -> number >= 1 && number <= 45)).isTrue();
assertThat(lottoTicket.getLottoNumbers().stream().distinct().count()).isEqualTo(6);
}
}
Loading