diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922..cbf3bcd 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,15 @@ package lotto; +import lotto.controller.LottoController; +import lotto.domain.Numbers; + +import java.util.List; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + + LottoController lottoController = new LottoController(); + lottoController.run(); } } diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 519793d..84b370f 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -1,5 +1,8 @@ package lotto; +import lotto.view.ExceptionMessage; + +import java.util.HashSet; import java.util.List; public class Lotto { @@ -14,7 +17,20 @@ private void validate(List numbers) { if (numbers.size() != 6) { throw new IllegalArgumentException(); } + HashSet integers = new HashSet<>(numbers); + if (integers.size() != numbers.size()) { + throw new IllegalArgumentException(); + } + + } + + public List getNumbers() { + return numbers; } // TODO: 추가 기능 구현 } + + + +//git 연결 확인 \ No newline at end of file diff --git a/src/main/java/lotto/controller/LottoController.java b/src/main/java/lotto/controller/LottoController.java new file mode 100644 index 0000000..666cddc --- /dev/null +++ b/src/main/java/lotto/controller/LottoController.java @@ -0,0 +1,136 @@ +package lotto.controller; + +import lotto.Lotto; +import lotto.domain.LottoNumber; +import lotto.domain.Numbers; +import lotto.domain.Rank; +import lotto.view.ExceptionMessage; +import lotto.view.InputView; +import lotto.view.OutputView; + +import java.util.*; + +public class LottoController { + + private static List lottoList; + + public void run() { + try { + start(); + } catch (IllegalStateException e) { + System.out.println(e.getMessage()); + } + } + + public void start() { + int money = InputView.inputMyMoney(); + int ticketCount = new LottoNumber(money).count; + OutputView.printTicketCount(ticketCount); + + lottoList = makeLottoList(ticketCount); + List winningNumber = InputView.inputWinningNumber(); + validateWinningNumber(winningNumber); + int bonusNumber = InputView.inputBonusNumber(winningNumber); + validateBonusNumber(winningNumber, bonusNumber); + lottoResult(lottoList, winningNumber, bonusNumber); + } + + private void validateWinningNumber(List winningNumber) { + if (winningNumber.size() != 6) { + ExceptionMessage.isCountNotSix(); + throw new IllegalArgumentException(); + } + for (int i = 0; i < winningNumber.size(); i++) { + if (winningNumber.get(i) < 1 || winningNumber.get(i) > 45) { + ExceptionMessage.isNotRange(); + throw new IllegalArgumentException(); + } + } + HashSet numbers = new HashSet<>(winningNumber); + if (winningNumber.size() != numbers.size()) { + ExceptionMessage.isDuplicate(); + throw new IllegalArgumentException(); + } + } + + private void validateBonusNumber(List winningNumber, int bonusNumber) { + if (winningNumber.contains(bonusNumber)) { + ExceptionMessage.isNotPossibleBonus(); + throw new IllegalArgumentException(); + } + } + + + private static List makeLottoList(int ticketCount) { + lottoList = new ArrayList<>(); + + for (int i = 0; i < ticketCount; i++) { + lottoList.add(makeLotto()); + } + return lottoList; + } + + private static Lotto makeLotto() { + List lotto; + lotto = Numbers.randomNumbers(); + System.out.println(lotto); + + return new Lotto(lotto); + } + + private void lottoResult(List lottoList, List winningNumber, int bonusNumber) { + System.out.println("당첨 통계"); + System.out.println("---"); + + Map count = findRank(lottoList, winningNumber, bonusNumber); + printResult(count); + printRate(count, lottoList.size()); + } + + private Map findRank(List lottoList, List winningNumber, int bonusNumber) { + Map count = setCountZero(); + + for (int i = 0; i < lottoList.size(); i++) { + Rank rank = match(lottoList.get(i), winningNumber, bonusNumber); + count.put(rank, count.get(rank) + 1); + } + return count; + } + + private Map setCountZero() { + Map count = new HashMap<>(); + + for (Rank rank : Rank.values()) { + count.put(rank, 0); + } + return count; + } + + private static Rank match(Lotto lotto, List winningNumber, int bonusNumber) { + int countMatch; + boolean containBonus; + List numbers = lotto.getNumbers(); + + countMatch = (int) numbers.stream() + .filter(winningNumber::contains) // 이중콜론 -> 메서드 참조 + .count(); + + containBonus = numbers.contains(bonusNumber); + + return Rank.findRank(countMatch, containBonus); + } + + private static void printResult(Map count) { + for (int i = Rank.values().length - 1; i >= 0; i--) { + Rank.values()[i].printMessage(count.get(Rank.values()[i])); + } + } + + private static void printRate(Map count, int ticketCount) { + double rate = 0; + for (Rank rank : count.keySet()) { + rate = rate + ((double) (rank.getWinningPrice()) / (ticketCount * 1000) * count.get(rank) * 100); + } + OutputView.printRate(rate); + } +} diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java new file mode 100644 index 0000000..271c7c7 --- /dev/null +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -0,0 +1,40 @@ +package lotto.domain; + +import lotto.Lotto; +import lotto.view.ExceptionMessage; + +import java.util.ArrayList; +import java.util.List; + +public class LottoNumber { + public final int count; + public final List lottos = new ArrayList<>(); + + public LottoNumber(int money) { + moneyValidate(money); + this.count = money / 1000; + } + + private void moneyValidate(int money) { + if (money <= 0) { + ExceptionMessage.isPositive(); + throw new IllegalArgumentException(); + } + if (money % 1000 != 0) { + ExceptionMessage.isDivisible(); + throw new IllegalArgumentException(); + } + } + + public void createLotto() { + for (int i = 0; i < count ; i++) { + Lotto lotto = createLottoNumber(); + lottos.add(lotto); + } + } + + public Lotto createLottoNumber() { + List integers = Numbers.randomNumbers(); + return new Lotto(integers); + } +} diff --git a/src/main/java/lotto/domain/Numbers.java b/src/main/java/lotto/domain/Numbers.java new file mode 100644 index 0000000..9c40e1f --- /dev/null +++ b/src/main/java/lotto/domain/Numbers.java @@ -0,0 +1,17 @@ +package lotto.domain; + +import org.kokodak.Randoms; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Numbers { + public static List randomNumbers() { + List numberList = new ArrayList<>(Randoms.pickUniqueNumbersInRange(1, 45, 6)); + // unsupportedoperationexception 에러 -> ArrayList로 받아서 해결 + Collections.sort(numberList); + + return numberList; + } +} diff --git a/src/main/java/lotto/domain/Rank.java b/src/main/java/lotto/domain/Rank.java new file mode 100644 index 0000000..faac5df --- /dev/null +++ b/src/main/java/lotto/domain/Rank.java @@ -0,0 +1,44 @@ +package lotto.domain; + +import lotto.view.OutputView; + +import java.util.Arrays; + +public enum Rank { + FIRST(6, 2_000_000_000, "6개 일치 (2,000,000,000원) - ", false), // 1등 + SECOND(5, 30_000_000, "5개 일치, 보너스 볼 일치 (30,000,000원) - ", true), // 2등 + THIRD(5, 1_500_000, "5개 일치 (1,500,000원) - ", false), // 3등 + FOURTH(4, 50_000, "4개 일치 (50,000원) - ", false), // 4등 + FIFTH(3, 5_000, "3개 일치 (5,000원) - ", false), // 5등 + MISS(0, 0, "", false); + + private final int countMatch; + private final int winningPrice; + private final String message; + private final boolean bonus; + + Rank(int countMatch, int winningPrice, String message, boolean bonus) { + this.countMatch = countMatch; + this.winningPrice = winningPrice; + this.message = message; + this.bonus = bonus; + } + + public static Rank findRank(int countMatch, boolean bonus) { + return Arrays.stream(values()) + .filter(rank -> rank.countMatch == countMatch) + .filter(rank -> rank.bonus == bonus) + .findAny() + .orElse(Rank.MISS); + } + + public void printMessage(int count) { + if (this != MISS) { + OutputView.printSuccessMessage(message, count); + } + } + + public int getWinningPrice() { + return winningPrice; + } +} diff --git a/src/main/java/lotto/view/ExceptionMessage.java b/src/main/java/lotto/view/ExceptionMessage.java new file mode 100644 index 0000000..a2a6ef2 --- /dev/null +++ b/src/main/java/lotto/view/ExceptionMessage.java @@ -0,0 +1,39 @@ +package lotto.view; + +public class ExceptionMessage { + + // 1. 구입 금액 양수 + public static void isPositive() { + System.out.println("[ERROR] 구입 금액은 양수여야 한다."); + } + + // 2. 구입 금액 1000의 배수 + public static void isDivisible() { + System.out.println("[ERROR] 구입 금액은 1000의 배수여야 한다."); + } + + // 3. 입력 숫자 중복 + public static void isDuplicate() { + System.out.println("[ERROR] 로또 번호는 중복되지 않아야 한다."); + } + + //4. 입력 숫자 범위 + public static void isNotRange() { + System.out.println("[ERROR] 로또 번호는 1-45 사이여야 한다."); + } + + // 5. 입력 숫자 개수 6 + public static void isCountNotSix() { + System.out.println("[ERROR] 로또 번호는 6개를 선택해야 한다."); + } + + // 6. 보너스 숫자 중복 + public static void isNotPossibleBonus() { + System.out.println("[ERROR] 보너스 번호는 기존의 번호와 달라야 한다."); + } + + // 7. 숫자가 아닌 입력 + public static void isNotNumber() { + System.out.println("[ERROR] 입력은 숫자여야 한다."); + } +} \ No newline at end of file diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java new file mode 100644 index 0000000..626bee2 --- /dev/null +++ b/src/main/java/lotto/view/InputView.java @@ -0,0 +1,50 @@ +package lotto.view; + +import org.kokodak.Console; + +import java.util.ArrayList; +import java.util.List; + +public class InputView { + + public static int inputMyMoney() { + System.out.println("구입금액을 입력해 주세요."); + try { + return Integer.parseInt(Console.readLine()); + } catch (NumberFormatException e) { + ExceptionMessage.isNotNumber(); + throw new IllegalArgumentException(); + } + + } + + public static List inputWinningNumber() { + System.out.println("당첨 번호를 입력해 주세요."); + return numberList(Console.readLine()); + } + + private static List numberList(String winningNumber) { + String[] numbers = winningNumber.split(","); + ArrayList winningNumberList = new ArrayList(); + for (int i = 0; i < numbers.length; i++) { + try { + winningNumberList.add(Integer.parseInt(numbers[i])); + } catch (NumberFormatException e){ + ExceptionMessage.isNotNumber(); + throw new IllegalArgumentException(); + } + } + return winningNumberList; + } + + public static int inputBonusNumber(List winningNumber) { + System.out.println("보너스 번호를 입력해 주세요."); + try { + return Integer.parseInt(Console.readLine()); + } catch (NumberFormatException e) { + ExceptionMessage.isNotNumber(); + throw new IllegalArgumentException(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java new file mode 100644 index 0000000..98358f7 --- /dev/null +++ b/src/main/java/lotto/view/OutputView.java @@ -0,0 +1,16 @@ +package lotto.view; + +public class OutputView { + + public static void printTicketCount(int count) { + System.out.println(count + "개를 구매했습니다."); + } + + public static void printSuccessMessage(String message, int count) { + System.out.println(message + count + "개"); + } + + public static void printRate(double rate) { + System.out.println("총 수익률은 " + String.format("%.1f", rate) + "%입니다."); + } +}