diff --git a/.gradle/6.7/executionHistory/executionHistory.bin b/.gradle/6.7/executionHistory/executionHistory.bin index cb365fbb..fd56b24e 100644 Binary files a/.gradle/6.7/executionHistory/executionHistory.bin and b/.gradle/6.7/executionHistory/executionHistory.bin differ diff --git a/.gradle/6.7/executionHistory/executionHistory.lock b/.gradle/6.7/executionHistory/executionHistory.lock index d27311c9..87e5b36e 100644 Binary files a/.gradle/6.7/executionHistory/executionHistory.lock and b/.gradle/6.7/executionHistory/executionHistory.lock differ diff --git a/.gradle/6.7/fileHashes/fileHashes.bin b/.gradle/6.7/fileHashes/fileHashes.bin index 5b917a3f..5e74c2e6 100644 Binary files a/.gradle/6.7/fileHashes/fileHashes.bin and b/.gradle/6.7/fileHashes/fileHashes.bin differ diff --git a/.gradle/6.7/fileHashes/fileHashes.lock b/.gradle/6.7/fileHashes/fileHashes.lock index 59d7ba9c..90510e18 100644 Binary files a/.gradle/6.7/fileHashes/fileHashes.lock and b/.gradle/6.7/fileHashes/fileHashes.lock differ diff --git a/.gradle/6.7/javaCompile/classAnalysis.bin b/.gradle/6.7/javaCompile/classAnalysis.bin index e15bcaec..ac05204d 100644 Binary files a/.gradle/6.7/javaCompile/classAnalysis.bin and b/.gradle/6.7/javaCompile/classAnalysis.bin differ diff --git a/.gradle/6.7/javaCompile/javaCompile.lock b/.gradle/6.7/javaCompile/javaCompile.lock index 61c208d8..fcf44449 100644 Binary files a/.gradle/6.7/javaCompile/javaCompile.lock and b/.gradle/6.7/javaCompile/javaCompile.lock differ diff --git a/.gradle/6.7/javaCompile/taskHistory.bin b/.gradle/6.7/javaCompile/taskHistory.bin index 0ee7808c..0acfc2c8 100644 Binary files a/.gradle/6.7/javaCompile/taskHistory.bin and b/.gradle/6.7/javaCompile/taskHistory.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 80442d67..fd5ad722 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/README.md b/README.md index fcd16a85..8766b296 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,33 @@ - 기대 수익은 동작 예시를 참고하자. ### 프로그래밍 요구사항 -- [ ] indent(인덴트, 들여쓰기) depth를 1단계로 구현한다. -- [ ] depth의 경우 if문을 사용하는 경우 1단계의 depth가 증가한다. if문 안에 while문을 사용한다면 depth가 2단계가 된다. +- [x] indent(인덴트, 들여쓰기) depth를 1단계로 구현한다. +- [x] depth의 경우 if문을 사용하는 경우 1단계의 depth가 증가한다. if문 안에 while문을 사용한다면 depth가 2단계가 된다. - [x] else를 사용하지 마라. - [x] 메소드의 크기가 최대 10라인을 넘지 않도록 구현한다. -- [ ] method가 한 가지 일만 하도록 최대한 작게 만들어라. +- [x] method가 한 가지 일만 하도록 최대한 작게 만들어라. - [x] ArrayList를 사용해서 구현한다. ---- \ No newline at end of file +--- + +## 로또 2단계 - 보너스 번호 추가 +### 기능요구사항 +- [x] 2등을 위해 추가 번호를 하나 더 추첨한다. 당첨 통계에 2등도 추가해야 한다. + +### 프로그래밍 요구사항 +- [x] enum을 적용해 프로그래밍을 구현한다. + +### 힌트 +- [x] Lotto 클래스를 사용자가 구매한 Lotto와 기계에 의해 추첨한 Lotto로 구분해서 생성한다. + +--- + +## 로또 3단계 - 수동구매 기능 추가 +### 기능요구사항 +- [x] 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다. +- [x] 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다. + +### 프로그래밍 요구사항 +- [ ] 예외가 발생하는 부분에 대해 자바 Exception을 적용해 예외처리한다. +- [ ] 사용자가 입력한 값에 대한 예외 처리를 철저히 한다. +- [x] 상속과 인터페이스를 통해 구현을 간결히 할 수 없는지 고민해 본다. \ No newline at end of file diff --git a/build/tmp/compileJava/source-classes-mapping.txt b/build/tmp/compileJava/source-classes-mapping.txt index c7e52837..d799060b 100644 --- a/build/tmp/compileJava/source-classes-mapping.txt +++ b/build/tmp/compileJava/source-classes-mapping.txt @@ -1,12 +1,16 @@ Main.java Main +domain/Rank.java + domain.Rank view/OutputView.java view.OutputView domain/LottoTicket.java domain.LottoTicket view/InputView.java view.InputView -domain/ProfitAmount.java - domain.ProfitAmount +domain/User.java + domain.User domain/TicketOffice.java domain.TicketOffice +domain/LottoCompany.java + domain.LottoCompany diff --git a/src/main/java/Main.java b/src/main/java/Main.java index ac9606f6..228f87b7 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,13 +1,12 @@ -import domain.LottoTicket; -import domain.TicketOffice; +import domain.*; import java.util.List; public class Main { public static void main(String[] args) { - TicketOffice to = new TicketOffice(); - List tickets = to.issueTickets(); - to.setWinningNumber(); - to.getStatistic(tickets); + LottoCompany lottoCompany = new LottoCompany(); + User user = new User(); + user.goTicketOffice(); + user.checkMyTicketsFrom(lottoCompany); } } diff --git a/src/main/java/domain/AutoTicketOffice.java b/src/main/java/domain/AutoTicketOffice.java new file mode 100644 index 00000000..050041bb --- /dev/null +++ b/src/main/java/domain/AutoTicketOffice.java @@ -0,0 +1,38 @@ +package domain; + +import java.util.*; + +public class AutoTicketOffice extends TicketOffice { + private final List lottoNumber = new ArrayList<>(); + private final int SELECTABLE_NUMBER = 45; + private final int SELECTED_NUMBER = 6; + + public AutoTicketOffice() { + setLottoNumber(); + } + + @Override + public List issueTickets(int numberOfTickets) { + List tickets = new ArrayList<>(); + for (int j = 0; j < numberOfTickets; j++){ + tickets.add(makeAutoTicket()); + } + return tickets; + } + + private LottoTicket makeAutoTicket() { + List ticketNumber = new ArrayList<>(); + Collections.shuffle(lottoNumber); + for (int i = 0; i < SELECTED_NUMBER; i++) { + ticketNumber.add(lottoNumber.get(i)); + } + Collections.sort(ticketNumber); + return new LottoTicket(ticketNumber); + } + + private void setLottoNumber() { + for (int i = 1; i <= SELECTABLE_NUMBER; i++) { + this.lottoNumber.add(i); + } + } +} diff --git a/src/main/java/domain/LottoCompany.java b/src/main/java/domain/LottoCompany.java new file mode 100644 index 00000000..b4e88e5a --- /dev/null +++ b/src/main/java/domain/LottoCompany.java @@ -0,0 +1,59 @@ +package domain; + +import view.InputView; +import view.OutputView; + +import java.util.*; + +public class LottoCompany { + private LottoTicket winningTicket; + private int bonusNumber; + private int totalPrice; + private final int PRICE = 1000; + private final Map statistics = new HashMap<>(); + + + public void setInitialStatistic() { + for (Rank rank : Rank.values()) { + statistics.put(rank, 0); + } + } + + public void check(List tickets){ + setWinningTicket(); + setBonusNumber(); + this.totalPrice = tickets.size() * PRICE; + getStatistic(tickets); + } + + public void setWinningTicket() { + this.winningTicket = new LottoTicket(InputView.getWinningNumber()); + } + + public void setBonusNumber() { // 추후 당첨 번호에 없는 번호만 받도록 예외처리 필요 + this.bonusNumber = InputView.getBonusNumber(); + } + + public void getStatistic(List tickets) { + setInitialStatistic(); + int matchedNumber; + boolean isBonus; + Rank currentRank; + for (LottoTicket ticket : tickets) { + matchedNumber = ticket.comparisonWinningTicket(this.winningTicket); + isBonus = ticket.checkBonusNumber(this.bonusNumber); + currentRank = Rank.designateRank(matchedNumber, isBonus); + statistics.computeIfPresent(currentRank, (k, v) -> v + 1); + } + OutputView.showWinningResult(this.statistics, calculateProfit()); + } + + public double calculateProfit() { + int totalPrize = 0; + for (Rank rank : this.statistics.keySet()) { + totalPrize += rank.getPrize() * statistics.get(rank); + } + return ((double) (totalPrize - totalPrice) / totalPrice) * 100; + } + +} diff --git a/src/main/java/domain/LottoTicket.java b/src/main/java/domain/LottoTicket.java index 7e4984d9..8b0d66c5 100644 --- a/src/main/java/domain/LottoTicket.java +++ b/src/main/java/domain/LottoTicket.java @@ -10,10 +10,35 @@ public LottoTicket(List lottoTicket) { this.lottoTicket = lottoTicket; } - - public List getTicketInfo() { return Collections.unmodifiableList(this.lottoTicket); } + public int get(int index){ + if (index < 0 || index >= lottoTicket.size()){ + throw new IndexOutOfBoundsException("인덱스를 초과하였습니다."); + } + return lottoTicket.get(index); + } + + public int comparisonWinningTicket(LottoTicket winningTicket){ + int count = 0; + for(int i=0; i issueTickets(int numberOfManualTicket) { + List tickets = new ArrayList<>(); + if (numberOfManualTicket > 0) { + tickets.addAll(makeManualTickets(numberOfManualTicket)); + } + return tickets; + } + + private List makeManualTickets(int numberOfManualTicket) { + List manualLottoTickets = new ArrayList<>(); + System.out.println("수동으로 구매할 번호를 입력해 주세요. (응모할 번호 6자리)"); + for (int i = 0; i < numberOfManualTicket; i++) { + manualLottoTickets.add(new LottoTicket(InputView.getManualNumber())); + } + return manualLottoTickets; + } +} diff --git a/src/main/java/domain/ProfitAmount.java b/src/main/java/domain/ProfitAmount.java deleted file mode 100644 index e0a5d4de..00000000 --- a/src/main/java/domain/ProfitAmount.java +++ /dev/null @@ -1,24 +0,0 @@ -package domain; - -public enum ProfitAmount { - FORTH(3, 5000), - THIRD(4, 50000), - SECOND(5, 1500000), - FIRST(6, 2000000000); - - private final int matchedNumber; - private final int prize; - - ProfitAmount(int matchedNumber, int prize) { - this.matchedNumber = matchedNumber; - this.prize = prize; - } - - public int getMatchedNumber() { - return matchedNumber; - } - - public int getPrize(){ - return prize; - } -} diff --git a/src/main/java/domain/Rank.java b/src/main/java/domain/Rank.java new file mode 100644 index 00000000..75c9fd1a --- /dev/null +++ b/src/main/java/domain/Rank.java @@ -0,0 +1,47 @@ +package domain; + +public enum Rank { + FAIL(0, 0), + FIFTH(3, 5_000), + FORTH(4, 50_000), + THIRD(5, 1_500_000), + SECOND(5, 30_000_000), + FIRST(6, 2_000_000_000); + + private final int matchedNumber; + private final int prize; + + private Rank(int matchedNumber, int prize) { + this.matchedNumber = matchedNumber; + this.prize = prize; + } + + public int getMatchedNumber() { + return matchedNumber; + } + + public int getPrize() { + return prize; + } + + public static Rank designateRank(int matchedNumber, boolean isBonus) { + switch (matchedNumber) { + case 3: + return FIFTH; + case 4: + return FORTH; + case 5: + return checkBonus(isBonus); + case 6: + return FIRST; + default: + return FAIL; + } + } + + private static Rank checkBonus(boolean isBonus){ + if(isBonus) + return SECOND; + return THIRD; + } +} diff --git a/src/main/java/domain/TicketOffice.java b/src/main/java/domain/TicketOffice.java index 89f71a62..fd5c79c8 100644 --- a/src/main/java/domain/TicketOffice.java +++ b/src/main/java/domain/TicketOffice.java @@ -1,110 +1,15 @@ package domain; import view.InputView; -import view.OutputView; import java.util.*; -public class TicketOffice { - private final List lottoNumber = new ArrayList<>(); - private final int SELECTABLE_NUMBER = 45; - private final int SELECTED_NUMBER = 6; - private final int PRICE = 1000; - private int TOTAL_PRICE; - private List winningNumbers = new ArrayList<>(); - private Map statistics = new HashMap<>(); +public abstract class TicketOffice { + private final static int PRICE = 1000; - { - statistics.put(3, 0); - statistics.put(4, 0); - statistics.put(5, 0); - statistics.put(6, 0); - } - - - public TicketOffice() { - setLottoNumber(); - } - - private void setLottoNumber() { - for (int i = 1; i <= SELECTABLE_NUMBER; i++) { - this.lottoNumber.add(i); - } - } - - private LottoTicket makeNewLottoTicket() { - List ticketNumber = new ArrayList<>(); - Collections.shuffle(lottoNumber); - for (int i = 0; i < SELECTED_NUMBER; i++) { - ticketNumber.add(lottoNumber.get(i)); - } - Collections.sort(ticketNumber); - return new LottoTicket(ticketNumber); - } - - public List issueTickets() { - int amount = InputView.getAmount(); - int numberOfTickets = amount / PRICE; - int change = amount % PRICE; - TOTAL_PRICE = PRICE * numberOfTickets; - List tickets = new ArrayList<>(); - for (int i = 0; i < numberOfTickets; i++) { - tickets.add(makeNewLottoTicket()); - } - OutputView.completePurchase(numberOfTickets, change, tickets); - return tickets; - } - - public void setWinningNumber() { - String[] winning = InputView.getWinningNumber(); - for (int i = 0; i < winning.length; i++) { - winningNumbers.add(Integer.parseInt(winning[i])); - } - } - - public void getStatistic(List tickets) { - int matchedNumber = 0; - for (LottoTicket ticket : tickets) { - matchedNumber = checkWinningNumber(ticket.getTicketInfo()); - statistics.computeIfPresent(matchedNumber, (k, v) -> v + 1); - } - OutputView.showWinningResult(this.statistics, calculateProfit()); - } - - public double calculateProfit() { - int totalPrize = 0; - for (Integer matchedNumber : statistics.keySet()) { - totalPrize += (switchPrize(matchedNumber) * statistics.get(matchedNumber)); - } - return ((double) (totalPrize - TOTAL_PRICE) / TOTAL_PRICE) * 100; - } - - private int switchPrize(int matchedNumber) { - switch (matchedNumber) { - case 3: - return ProfitAmount.FORTH.getPrize(); - case 4: - return ProfitAmount.THIRD.getPrize(); - case 5: - return ProfitAmount.SECOND.getPrize(); - default: - return ProfitAmount.FIRST.getPrize(); - } - - } - - private int checkWinningNumber(List ticketInfo) { - int count = 0; - for (Integer number : ticketInfo) { - count += isWinningNumber(number); - } - return count; - } + public abstract List issueTickets(int numberOfTickets); - private int isWinningNumber(int number) { - if (winningNumbers.contains(number)) { - return 1; - } - return 0; + public static int getPrice() { + return PRICE; } } diff --git a/src/main/java/domain/User.java b/src/main/java/domain/User.java new file mode 100644 index 00000000..90bbc19f --- /dev/null +++ b/src/main/java/domain/User.java @@ -0,0 +1,39 @@ +package domain; + +import view.InputView; +import view.OutputView; + +import java.util.ArrayList; +import java.util.List; + +public class User { + private int purchasedAmount; + private int change; + private int amount; + private int totalNumberOfTickets; + private List tickets = new ArrayList<>(); + + public void goTicketOffice(){ + this.amount = InputView.getAmount(); + int pricePerTicket = TicketOffice.getPrice(); + int numberOfManualTicket = InputView.getNumberOfManualTicket(); + int numberOfAutoTicket = (this.amount / pricePerTicket) - numberOfManualTicket; + this.totalNumberOfTickets = numberOfAutoTicket + numberOfManualTicket; + + purchaseTicketsFrom(new ManualTicketOffice(), numberOfManualTicket); + purchaseTicketsFrom(new AutoTicketOffice(), numberOfAutoTicket); + + this.purchasedAmount = pricePerTicket * totalNumberOfTickets; + this.change += this.amount - purchasedAmount; + OutputView.printPurchase(totalNumberOfTickets, change, tickets); + + } + + private void purchaseTicketsFrom(TicketOffice to, int numberOfTickets) { + this.tickets.addAll(to.issueTickets(numberOfTickets)); + } + + public void checkMyTicketsFrom(LottoCompany lottoCompany){ + lottoCompany.check(this.tickets); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a9d8e181..474f956a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,6 +1,7 @@ package view; -import java.util.Scanner; +import java.util.*; +import java.util.stream.Collectors; public class InputView { private static Scanner sc; @@ -13,9 +14,32 @@ public static int getAmount() { } - public static String[] getWinningNumber() { + public static List getWinningNumber() { sc = new Scanner(System.in); - System.out.println("\n당첨 번호를 입력해 주세요."); - return sc.nextLine().split(","); + System.out.println("\n지난 주 당첨 번호를 입력해 주세요."); + String[] winningNumbers = sc.nextLine().split(","); + return Arrays.stream(winningNumbers) + .map(Integer::parseInt).collect(Collectors.toList()); + } + + public static int getNumberOfManualTicket() { + sc = new Scanner(System.in); + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + return Integer.parseInt(sc.nextLine()); + } + + public static List getManualNumber() { + List manualNumber = new ArrayList<>(); + sc = new Scanner(System.in); + String[] userInput = sc.nextLine().split(","); + for (String number : userInput) + manualNumber.add(Integer.parseInt(number)); + return manualNumber; + } + + public static int getBonusNumber(){ + sc = new Scanner(System.in); + System.out.println("보너스 볼을 입력해 주세요."); + return Integer.parseInt(sc.nextLine()); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d378e59e..de53c076 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,15 +1,13 @@ package view; import domain.LottoTicket; -import domain.ProfitAmount; +import domain.Rank; import java.util.List; import java.util.Map; public class OutputView { - private final int SELECTED_NUMBER = 6; - - public static void completePurchase(int numberOfTickets, int change, List tickets) { + public static void printPurchase(int numberOfTickets, int change, List tickets) { System.out.println(numberOfTickets + "개를 구매했습니다."); System.out.println("거스름돈은 " + change + "원 입니다."); @@ -18,17 +16,32 @@ public static void completePurchase(int numberOfTickets, int change, List statistics, double profitRate) { - System.out.println("\n당첨 통계"); - System.out.println("__________"); + public static void showWinningResult(Map statistics, double profitRate) { + StringBuilder sb = new StringBuilder(); int matchedNumber; - int prize; - for (ProfitAmount pa : ProfitAmount.values()) { - matchedNumber = pa.getMatchedNumber(); - prize = pa.getPrize(); - System.out.printf("%d개 일치 (%d원) - %d개", matchedNumber, prize, statistics.get(matchedNumber)); - System.out.println(); + System.out.println("\n당첨 통계\n__________"); + for (Rank rank : Rank.values()) { + matchedNumber = rank.getMatchedNumber(); + sb.append(matchedNumber).append("개 일치"); + sb.append(checkBonusBall(rank)); + sb.append(" (").append(rank.getPrize()).append(")원 - "); + sb.append(statistics.get(rank)).append("개\n"); + initString(matchedNumber, sb); } + System.out.println(sb.toString()); System.out.printf("총 수익률은 %.2f%%입니다.", profitRate); } + + private static void initString(int matchedNumber, StringBuilder sb){ + if(matchedNumber==0){ + sb.setLength(0); + } + } + + private static String checkBonusBall(Rank rank){ + if (rank == Rank.SECOND) { + return ", 보너스 볼 일치"; + } + return ""; + } }