diff --git a/README.md b/README.md index 7b4e53d2437..abe46ec22cc 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,11 @@ * 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다. ## 온라인 코드 리뷰 과정 -* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview) \ No newline at end of file +* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview) + + +## step2 요구사항 +* [x] 로또 구매 +* [x] 자동생성 +* [x] 당첨번호 확인, +* [x] 수익률 계산 기능 \ No newline at end of file diff --git a/src/main/java/lotto/LottoApplication.java b/src/main/java/lotto/LottoApplication.java new file mode 100644 index 00000000000..34ff067931c --- /dev/null +++ b/src/main/java/lotto/LottoApplication.java @@ -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); + } +} diff --git a/src/main/java/lotto/domain/LottoBuy.java b/src/main/java/lotto/domain/LottoBuy.java new file mode 100644 index 00000000000..d01568fa769 --- /dev/null +++ b/src/main/java/lotto/domain/LottoBuy.java @@ -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; + } + + public Map calculateLottoWinStatistics(LottoWinNumber lottoWinNumber) { + return lottoTickets.calculateLottoWinStatistics(lottoWinNumber); + } + + public int getLottoBuyPrice() { + return lottoBuyCount.getLottoBuyPrice(); + } +} diff --git a/src/main/java/lotto/domain/LottoBuyCount.java b/src/main/java/lotto/domain/LottoBuyCount.java new file mode 100644 index 00000000000..66440f1e615 --- /dev/null +++ b/src/main/java/lotto/domain/LottoBuyCount.java @@ -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; + } + + // 테스트용 생성자 + 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; + } +} diff --git a/src/main/java/lotto/domain/LottoNumberGenerator.java b/src/main/java/lotto/domain/LottoNumberGenerator.java new file mode 100644 index 00000000000..54b2e83f373 --- /dev/null +++ b/src/main/java/lotto/domain/LottoNumberGenerator.java @@ -0,0 +1,17 @@ +package lotto.domain; + +import java.util.ArrayList; +import java.util.List; + +public class LottoNumberGenerator { + + public List generateLottoNumbers() { + List lottoNumbers = new ArrayList<>(); + + for(int i = 1; i <= 45; i++) { + lottoNumbers.add(i); + } + + return lottoNumbers; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/domain/LottoTicket.java b/src/main/java/lotto/domain/LottoTicket.java new file mode 100644 index 00000000000..e57694aea02 --- /dev/null +++ b/src/main/java/lotto/domain/LottoTicket.java @@ -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 lottoNumbers = new ArrayList<>(); + + LottoTicket() { + List 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 getLottoNumbers() { + return lottoNumbers; + } + + public int getMatchCount(LottoWinNumber lottoWinNumber) { + return lottoWinNumber.countMatchingNumbers(lottoNumbers); + } +} diff --git a/src/main/java/lotto/domain/LottoTickets.java b/src/main/java/lotto/domain/LottoTickets.java new file mode 100644 index 00000000000..94c7fd8827c --- /dev/null +++ b/src/main/java/lotto/domain/LottoTickets.java @@ -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 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 calculateLottoWinStatistics(LottoWinNumber lottoWinNumber) { + Map resultMap = new HashMap<>(); + + 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(); + } +} diff --git a/src/main/java/lotto/domain/LottoWin.java b/src/main/java/lotto/domain/LottoWin.java new file mode 100644 index 00000000000..9649f981824 --- /dev/null +++ b/src/main/java/lotto/domain/LottoWin.java @@ -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; + } +} diff --git a/src/main/java/lotto/domain/LottoWinNumber.java b/src/main/java/lotto/domain/LottoWinNumber.java new file mode 100644 index 00000000000..a964153c56d --- /dev/null +++ b/src/main/java/lotto/domain/LottoWinNumber.java @@ -0,0 +1,34 @@ +package lotto.domain; + +import java.util.ArrayList; +import java.util.List; + +public class LottoWinNumber { + + private final List 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 lottoNumbers) { + int result = 0; + + for (Integer lottoNumber : lottoNumbers) { + result += getMatchCount(lottoNumber); + } + + return result; + } + + public int getMatchCount(Integer lottoNumber) { + return lottoWinNumber.contains(lottoNumber) ? 1 : 0; + } +} diff --git a/src/main/java/lotto/domain/LottoWinStatistics.java b/src/main/java/lotto/domain/LottoWinStatistics.java new file mode 100644 index 00000000000..64053425cb6 --- /dev/null +++ b/src/main/java/lotto/domain/LottoWinStatistics.java @@ -0,0 +1,69 @@ +package lotto.domain; + +import java.util.Map; + +public class LottoWinStatistics { + + 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 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(); + } +} diff --git a/src/test/java/lotto/domain/LottoBuyTest.java b/src/test/java/lotto/domain/LottoBuyTest.java new file mode 100644 index 00000000000..525a6e45008 --- /dev/null +++ b/src/test/java/lotto/domain/LottoBuyTest.java @@ -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(); + } +} diff --git a/src/test/java/lotto/domain/LottoTicketTest.java b/src/test/java/lotto/domain/LottoTicketTest.java new file mode 100644 index 00000000000..d95f5026fe4 --- /dev/null +++ b/src/test/java/lotto/domain/LottoTicketTest.java @@ -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); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/LottoWinTest.java b/src/test/java/lotto/domain/LottoWinTest.java new file mode 100644 index 00000000000..33ba30001ce --- /dev/null +++ b/src/test/java/lotto/domain/LottoWinTest.java @@ -0,0 +1,48 @@ +package lotto.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class LottoWinTest { + + @Test + void 로또_당첨_확인하기() { + // Given + LottoBuy lottoBuy = new LottoBuy( + "[8, 21, 23, 41, 42, 43]\n" + + "[3, 5, 11, 16, 32, 38]\n" + + "[7, 11, 16, 35, 36, 44]\n" + + "[1, 8, 11, 31, 41, 42]\n" + + "[13, 14, 16, 38, 42, 45]\n" + + "[7, 11, 30, 40, 42, 43]\n" + + "[2, 13, 22, 32, 38, 45]\n" + + "[23, 25, 33, 36, 39, 41]\n" + + "[1, 3, 5, 14, 22, 45]\n" + + "[5, 9, 38, 41, 43, 44]\n" + + "[2, 8, 9, 18, 19, 21]\n" + + "[13, 14, 18, 21, 23, 35]\n" + + "[17, 21, 29, 37, 42, 45]\n" + + "[3, 8, 27, 30, 35, 44]"); + + // When + String winNumber = "1, 2, 3, 4, 5, 6"; + LottoWin lottoWin = new LottoWin(lottoBuy, winNumber); + +// System.out.println(lottoBuy.toString()); + + System.out.println(lottoWin); + + // Then + Assertions.assertThat(lottoWin.toString()) + .isEqualTo( + "당첨통계\n" + + "---------\n" + + "3개 일치 (5000원)- 1개\n" + + "4개 일치 (50000원)- 0개\n" + + "5개 일치 (1500000원)- 0개\n" + + "6개 일치 (2000000000원)- 0개\n" + + "총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)"); + } +} \ No newline at end of file