diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba44..25aec891a2d 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,11 @@ package lotto; + + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + Game game = LottoGame.getInstance(); + game.play(); } } diff --git a/src/main/java/lotto/Game.java b/src/main/java/lotto/Game.java new file mode 100644 index 00000000000..ee48ad4c52c --- /dev/null +++ b/src/main/java/lotto/Game.java @@ -0,0 +1,8 @@ +package lotto; + +public interface Game { + + void play(); + + void test(); +} diff --git a/src/main/java/lotto/GameStatus.java b/src/main/java/lotto/GameStatus.java new file mode 100644 index 00000000000..05231fca876 --- /dev/null +++ b/src/main/java/lotto/GameStatus.java @@ -0,0 +1,15 @@ +package lotto; + +public enum GameStatus { + MIN_PRICE(1000); + + int value; + + GameStatus(int val) { + this.value = val; + } + + public int getValue() { + return this.value; + } +} diff --git a/src/main/java/lotto/Item.java b/src/main/java/lotto/Item.java new file mode 100644 index 00000000000..af50d83a9cf --- /dev/null +++ b/src/main/java/lotto/Item.java @@ -0,0 +1,41 @@ +package lotto; + +import java.util.List; + +public class Item { + private static List> challengeTicket; + + private static List winnerTicket; + + private static Integer bonusNumber; + + // protected current instance + private Item() { + + } + + public static void setChallengeTicket(List> cTicket) { + challengeTicket = cTicket; + } + + public static void setWinnerTicket(List wTicket) { + winnerTicket = wTicket; + } + + public static void setBonusNumber(Integer bNum) { + bonusNumber = bNum; + } + + public static List> getChallengeTicket() { + return challengeTicket; + } + + public static List getWinnerTicket() { + return winnerTicket; + } + + public static Integer getBonusNumber() { + return bonusNumber; + } + +} diff --git a/src/main/java/lotto/LotteryDrawing.java b/src/main/java/lotto/LotteryDrawing.java new file mode 100644 index 00000000000..d26e5e79478 --- /dev/null +++ b/src/main/java/lotto/LotteryDrawing.java @@ -0,0 +1,124 @@ +package lotto; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class LotteryDrawing { + + private static LotteryDrawing instance; + + private Map lottoDrawingResult; + + private Map lottoPrizeMoney; + + private Map strPrizeMoney; + + private LotteryDrawing() { + + } + + public static LotteryDrawing getInstance() { + if (instance == null) { + instance = new LotteryDrawing(); + return instance; + } + return instance; + } + + + public void lottoDrawing(List> challengeTicket, List winnerTicket, Integer bonusNum) { + setLottoGrade(); + + for (int i = 0; i < challengeTicket.size(); i++) { + List userTicket = challengeTicket.get(i); + int cnt = checkLotto(userTicket, winnerTicket); + + if (cnt > 2) { + checkPrize(cnt, userTicket, bonusNum); + } + } + + } + + private int checkLotto(List userTicket, List winnerTicket) { + int cnt = 0; + for (int i = 0; i < winnerTicket.size(); i++) { + for (int j = 0; j < userTicket.size(); j++) { + if (winnerTicket.get(i).equals(userTicket.get(j))) { + cnt += 1; + } + } + } + + return cnt; + } + + private void checkPrize(Integer cnt, List userTicket, Integer bonusNum) { + String grade = "E"; + + switch(cnt) { + case 6: + grade = "A"; + break; + case 5: + if(checkBonusNum(userTicket, bonusNum)) { + grade = "B"; + break; + } + grade = "C"; + break; + case 4: + grade = "D"; + break; + } + + // 자바 8이상에서는 이렇게 굳이 꺼내지 않고 MAP에서 업데이트 가능 + lottoDrawingResult.merge(grade, 1, Integer::sum); + } + + private boolean checkBonusNum(List userTicket, Integer bonusNum) { + for (int i = 0; i < userTicket.size(); i++) { + if (userTicket.get(i).equals(bonusNum)) { + return true; + } + } + return false; + } + + private void setLottoGrade() { + lottoDrawingResult = new HashMap<>(); + lottoPrizeMoney = new HashMap<>(); + strPrizeMoney = new HashMap<>(); + + lottoDrawingResult.put("A", 0); + lottoDrawingResult.put("B", 0); + lottoDrawingResult.put("C", 0); + lottoDrawingResult.put("D", 0); + lottoDrawingResult.put("E", 0); + + lottoPrizeMoney.put("A", 2000000000); + lottoPrizeMoney.put("B", 30000000); + lottoPrizeMoney.put("C", 1500000); + lottoPrizeMoney.put("D", 50000); + lottoPrizeMoney.put("E", 5000); + + strPrizeMoney.put("A", "2,000,000,000"); + strPrizeMoney.put("B", "30,000,000"); + strPrizeMoney.put("C", "1,500,000"); + strPrizeMoney.put("D", "50,000"); + strPrizeMoney.put("E", "5,000"); + } + + public Map getLottoDrawingResult() { + return lottoDrawingResult; + } + + public Map getLottoPrizeMoney() { + return lottoPrizeMoney; + } + + public Map getStrPrizeMoney() { + return strPrizeMoney; + } +} diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 519793d1f73..d847fabb1ed 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -2,9 +2,20 @@ import java.util.List; +/** + * 로또 클래스의 역활은 우승자 티켓 검증과 생성 (보너스) + */ + public class Lotto { + + public static Lotto instance; + private final List numbers; + private Integer bonusNumber; + + private static int useMoney; + public Lotto(List numbers) { validate(numbers); this.numbers = numbers; @@ -12,9 +23,56 @@ public Lotto(List numbers) { private void validate(List numbers) { if (numbers.size() != 6) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("[ERROR] 입력이 잘못되었습니다."); + } + + for (int i = 0; i < numbers.size(); i++) { + if (numbers.get(i) < 1) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } else if (numbers.get(i) > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + + for (int j = 0; j < numbers.size(); j++) { + if (i != j && numbers.get(i).equals(numbers.get(j))) { + throw new IllegalArgumentException("[ERROR] 로또 번호가 중복 되었습니다."); + } + } } } // TODO: 추가 기능 구현 + public static Lotto getInstance(List numbers) { + if (instance == null) { + instance = new Lotto(numbers); + } + + return instance; + } + + public List getNumbers() { + return numbers; + } + + public void setBonusNumber(Integer bonusNumber) { + if (bonusNumber < 1) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } else if (bonusNumber > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + + this.bonusNumber = bonusNumber; + } + + public Integer getBonusNumber() { + return bonusNumber; + } + + public static void setUseMoney(Integer money) { + useMoney = money; + } + + public static Integer getUseMoney() { + return useMoney; + } } diff --git a/src/main/java/lotto/LottoGame.java b/src/main/java/lotto/LottoGame.java new file mode 100644 index 00000000000..c832680b887 --- /dev/null +++ b/src/main/java/lotto/LottoGame.java @@ -0,0 +1,90 @@ +package lotto; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class LottoGame implements Game{ + private final Machine machine = LottoMachine.getMachine(); + + private final LotteryDrawing lotteryDrawing = LotteryDrawing.getInstance(); + + private static LottoGame instance; + + private LottoGame() { + + } + + // TODO 로또 티켓 당첨 확인하기 + @Override + public void play() { + try { + init(); + List> cTicket = Item.getChallengeTicket(); + List wTicket = Item.getWinnerTicket(); + Integer bNum = Item.getBonusNumber(); + + lotteryDrawing.lottoDrawing(cTicket, wTicket, bNum); + + Map lottoDrawingResult = lotteryDrawing.getLottoDrawingResult(); + Map lottoPrizeMoney = lotteryDrawing.getLottoPrizeMoney(); + Map strPrizeMoney = lotteryDrawing.getStrPrizeMoney(); + + PrintGameState.printLottoResult(lottoDrawingResult, lottoPrizeMoney, strPrizeMoney); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + + @Override + public void test() { + int[][] cArr = { + {8, 21, 23, 41, 42, 43}, + {3, 5, 11, 16, 32, 38}, + {7, 11, 16, 35, 36, 44}, + {1, 8, 11, 31, 41, 42}, + {13, 14, 16, 38, 42, 45}, + {7, 11, 30, 40, 42, 43}, + {2, 13, 22, 32, 38, 45}, + {1, 3, 5, 14, 22, 45}, + }; + int[] wArr = {1, 2, 3, 4, 5, 6}; + int bNum = 7; + Lotto.setUseMoney(8000); + List> cTicket = new ArrayList<>(); + List wTicket = new ArrayList<>(); + + for (int i = 0; i < cArr.length; i++) { + List a = new ArrayList<>(); + for (int j = 0; j < cArr[i].length; j++) { + a.add(cArr[i][j]); + } + cTicket.add(a); + } + + for (int i = 0; i < wArr.length; i++) { + wTicket.add(wArr[i]); + } + + lotteryDrawing.lottoDrawing(cTicket, wTicket, bNum); + + Map lottoDrawingResult = lotteryDrawing.getLottoDrawingResult(); + Map lottoPrizeMoney = lotteryDrawing.getLottoPrizeMoney(); + Map strPrizeMoney = lotteryDrawing.getStrPrizeMoney(); + + PrintGameState.printLottoResult(lottoDrawingResult, lottoPrizeMoney, strPrizeMoney); + } + + private void init() { + machine.operating(); + } + + public static Game getInstance() { + if (instance == null) { + instance = new LottoGame(); + return instance; + } + + return instance; + } +} diff --git a/src/main/java/lotto/LottoMachine.java b/src/main/java/lotto/LottoMachine.java new file mode 100644 index 00000000000..c32212cb36e --- /dev/null +++ b/src/main/java/lotto/LottoMachine.java @@ -0,0 +1,125 @@ +package lotto; + +import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static lotto.GameStatus.*; + +/** + * 로또 머신 클래스의 역활은 우승자 티켓과 도전자 티켓 셋팅하고 Item 클래스에 셋팅 + */ + +public class LottoMachine implements Machine { + + private static Machine machine; + + private List> challengeTickets; + + private Lotto winnerTickets; + + + @Override + public void operating() { + init(); + setItem(); + } + + private void init() { + // set challenge ticket + PrintGameState.inputTotalBuyTicketPrice(); + String strMoney = Console.readLine(); + setChallengeTickets(strMoney); + + // set winner number + PrintGameState.inputWinNumber(); + String winnerNum = Console.readLine(); + + // set bonus number + PrintGameState.inputBonusNumber(); + String bonusNum = Console.readLine(); + + setWinnerTickets(winnerNum, bonusNum); + } + + private void setItem() { + // set Item + Item.setChallengeTicket(challengeTickets); + Item.setWinnerTicket(winnerTickets.getNumbers()); + Item.setBonusNumber(winnerTickets.getBonusNumber()); + } + + public void setChallengeTickets(String str) { + // is not a happened than setItem(); + int money = LottoValidate.validateUserMoney(str); + Lotto.setUseMoney(money); + + challengeTickets = new ArrayList<>(); + while (money > 0) { + List lottoNumbers = getLottoNumbers(); + sortBefore(lottoNumbers); + challengeTickets.add(lottoNumbers); + money -= MIN_PRICE.getValue(); + } + } + + + public void setWinnerTickets(String winnerNum, String bonusNum) { + LottoValidate.validateWinnerTicket(winnerNum, bonusNum); + + String[] n = winnerNum.split(","); + List wNum = new ArrayList<>(); + Integer bNum = Integer.parseInt(bonusNum); + + for (int i = 0; i < n.length; i++) { + wNum.add(Integer.valueOf(n[i])); + } + + // is not a happened than setItem(); + winnerTickets = Lotto.getInstance(wNum); + winnerTickets.setBonusNumber(bNum); + } + + // bubble + private void sortBefore(List lottoNumber) { + for (int i = 0; i < lottoNumber.size(); i++) { + for (int j = 0; j < lottoNumber.size() - 1; j++) { + if (lottoNumber.get(j) > lottoNumber.get(j + 1)) { + int temp = lottoNumber.get(j); + lottoNumber.set(j, lottoNumber.get(j + 1)); + lottoNumber.set(j + 1, temp); + } + } + } + } + + // select + private void sortAfter(List lottoNumber) { + for (int i = 1; i < lottoNumber.size(); i++) { + int key = lottoNumber.get(i); + int j = i - 1; + + while (j >= 0 && lottoNumber.get(j) > key) { + lottoNumber.set(j + 1, lottoNumber.get(j)); + j--; + } + lottoNumber.set(j + 1, key); + } + } + + public List getLottoNumbers() { + return Randoms.pickUniqueNumbersInRange(1, 45, 6); + } + + public static Machine getMachine() { + if (machine == null) { + machine = new LottoMachine(); + } + + return machine; + } + +} diff --git a/src/main/java/lotto/LottoValidate.java b/src/main/java/lotto/LottoValidate.java new file mode 100644 index 00000000000..5400f980c1f --- /dev/null +++ b/src/main/java/lotto/LottoValidate.java @@ -0,0 +1,51 @@ +package lotto; + +import static lotto.GameStatus.*; + +/** + * LottoValidate 클래스는 사용자의 입력을 검증함 + */ + +public class LottoValidate { + public static Integer validateUserMoney(String str) { + if (str == null) { + throw new IllegalArgumentException("[ERROR] 입력이 잘못되었습니다."); + } + + if (str.isEmpty()) { + throw new IllegalArgumentException("[ERROR] 입력이 잘못되었습니다."); + } + + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + + if (c < '0') { + throw new IllegalArgumentException("[ERROR] 입력이 잘못되었습니다."); + } else if (c > '9') { + throw new IllegalArgumentException("[ERROR] 입력이 잘못되었습니다."); + } + } + + int money = Integer.parseInt(str); + + if (money < MIN_PRICE.getValue()) { + throw new IllegalArgumentException("[ERROR] 로또는 천원 단위 부터 구매 가능합니다."); + } + + if (money % MIN_PRICE.getValue() != 0) { + throw new IllegalArgumentException("[ERROR] 로또는 천원 단위 부터 구매 가능합니다."); + } + + return money; + } + + public static void validateWinnerTicket(String winnerNum, String bonusNum) { + if (!winnerNum.contains(",")) { + throw new IllegalArgumentException("[Error] 입력이 잘못되었습니다."); + } + + if (bonusNum.length() > 1) { + throw new IllegalArgumentException("[Error] 입력이 잘못되었습니다."); + } + } +} diff --git a/src/main/java/lotto/Machine.java b/src/main/java/lotto/Machine.java new file mode 100644 index 00000000000..d8785d3780e --- /dev/null +++ b/src/main/java/lotto/Machine.java @@ -0,0 +1,5 @@ +package lotto; + +public interface Machine { + void operating(); +} diff --git a/src/main/java/lotto/PrintGameState.java b/src/main/java/lotto/PrintGameState.java new file mode 100644 index 00000000000..df3ba7a0e91 --- /dev/null +++ b/src/main/java/lotto/PrintGameState.java @@ -0,0 +1,61 @@ +package lotto; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class PrintGameState { + + private static final String[] grade = {"E", "D", "C", "B", "A"}; + + public static void inputTotalBuyTicketPrice() { + System.out.println("구입금액을 입력해 주세요."); + } + + public static void inputWinNumber() { + System.out.println("당첨 번호를 입력해 주세요."); + } + + public static void inputBonusNumber() { + System.out.println("보너스 번호를 입력해 주세요."); + } + + public static void printLottoResult(Map lottoDrawingResult, Map lottoPrizeMoney, Map strPrizeMoney) { + printUserLottoTicket(); + + int cnt = 3; + for (int i = 0; i < grade.length; i++) { + String key = grade[i]; + if (key.equals("B")) { + cnt = 5; + System.out.println(cnt + "개 일치, 보너스 볼 일치 (" + strPrizeMoney.get(key) + "원) - " + lottoDrawingResult.get(key) + "개"); + } else { + System.out.println(cnt + "개 일치 (" + strPrizeMoney.get(key) + "원) - " + lottoDrawingResult.get(key) + "개"); + } + cnt += 1; + } + + printAverage(lottoDrawingResult, lottoPrizeMoney); + } + + private static void printAverage(Map lottoDrawingResult, Map lottoPrizeMoney) { + int useMoney = Lotto.getUseMoney(); + int total = 0; + + for (int i = 0; i < grade.length; i++) { + String key = grade[i]; + total += lottoPrizeMoney.get(key) * lottoDrawingResult.get(key); + } + + double avg = (double) (100 * total) / useMoney; + System.out.printf("총 수익률은 %.1f%%입니다.", avg); + } + + private static void printUserLottoTicket() { + List> lotto = Item.getChallengeTicket(); + System.out.println(lotto.size() + "개를 구매했습니다."); + for (List numbers : lotto) { + System.out.println(numbers); + } + } +}