Skip to content

2주차 - Step2 로또(자동) 피드백 요청드립니다. #226

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

Merged
merged 22 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8153635
[step2] docs : 구현 기능 목록 생성, step1 피드백 반영
Integerous Jun 23, 2019
412ce97
[step2] feat : LottoNumber 객체 생성, 구현 기능 목록 수정
Integerous Jun 23, 2019
56340cf
[step2] refactor : 매직넘버 대신 상수 사용, 로또번호 범위 예외처리 테스트
Integerous Jun 23, 2019
fbd4229
[step2] feat : LottoTicket 테스트, 객체 생성
Integerous Jun 23, 2019
855d9fe
[step2] feat : 로또번호 생성 테스트, 메서드 추가
Integerous Jun 23, 2019
8b0d430
[step2] refactor : stream 사용, 매직넘버 대신 상수 사용
Jun 24, 2019
36a6fb5
[step2] refactor : LottoTicket 정적팩토리 메서드명 변경, 정렬 메서드 추가
Jun 24, 2019
002a92a
[step2] feat : 로또복권 생성기능을 LottoTicketGenerator로 위임
Jun 24, 2019
452aef6
[step2] feat : 중복된 로또번호 검증 메소드, 예외처리 테스트 추가
Jun 24, 2019
a59795f
[step2] feat : 로또복권의 로또번호 개수가 6개가 아닌 경우 검증 메서드, 테스트 추가
Jun 24, 2019
4f648e9
[step2] docs : 구현 기능 목록 업데이트
Jun 24, 2019
b1a5556
[step2] feat : 당첨번호(LuckyNumber) 객체 생성, toString()메서드 추가
Jun 24, 2019
8e95c0f
[step2] refactor : LottoTicket을 List<LottoNumber>로 변경, 중복번호 검증 메서드 수정
Jun 24, 2019
1208d8e
[step2] feat : 당첨번호 비교 테스트, 메서드 추가
Integerous Jun 24, 2019
fa8964c
[step2] feat : 로또자동판매기(LottoSeller) 객체, 테스트 생성
Integerous Jun 24, 2019
8c29b04
[step2] refactor : 예외처리 추가, 구입할 로또복권 개수 계산 메서드 추가
Integerous Jun 24, 2019
5687bd0
[step2] refactor : 구입할 개수만큼 로또복권 발행하는 메서드 추가, LottoTickets 객체 삭제
Integerous Jun 24, 2019
7413d1a
[step2] refactor : 복권 생성할때마다 lottoBalls 생성하지 않고 객체로 분리
Integerous Jun 24, 2019
1afb997
[step2] feat : Enum 클래스(LottoRank) 추가
Integerous Jun 24, 2019
b8c1133
[step2] feat : 당첨 통계(LottoResult) 클래스 생성 및 메서드 작성중
Integerous Jun 24, 2019
6c222c8
[step2] refactor : (커밋 병합) view, apllication 생성, LuckNumber 객체 제거 등
Integerous Jun 25, 2019
7f6c548
[step2] refactor : 패키지 분리, 총 수익률계산 메서드 수정, 상수 사용
Integerous Jun 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,43 @@
- [x] REFACTORING
- [x] 외부로 위임된 StringCalculator 안의 메서드들 정리


### step1 - 이슈
- Element 객체를 불변 객체로 만들 필요가 있을지
- Element 객체를 불변 객체로 만들 필요가 있을지


### step2 - 로또(자동)
- [ ] 로또번호(LottoNumber) 객체 생성
- [x] TEST - 로또번호의 범위는 1~45의 자연수
- [x] REFACTORING
- [ ] 로또복권(LottoTicket) 객체 생성
- [x] TEST - 로또복권의 로또번호는 중복이 없다
- [x] TEST - 로또복권의 로또번호는 6개다
- [x] TEST - 당첨번호와 비교해서 일치하는 개수를 반환한다 (ArrayList.contains())
- [ ] REFACTORING
- [ ] 로또복권생성기(LottoTicketGenerator) 객체 생성
- [x] TEST - 로또번호(1~45)가 담긴 리스트를 생성한다
- [x] TEST - 생성된 로또번호를 섞는다 (Collections.shuffle())
- [x] TEST - 섞인 로또번호 리스트에서 6개의 로또번호를 선택한다
- [x] TEST - 선택된 로또번호를 정렬한다 (Collections.sort())
- [ ] REFACTORING
- [ ] 당첨번호(LuckyNumber) 객체 생성
- [x] TEST - 입력받은 당첨번호로 일급 컬렉션을 생성한다
- [ ] REFACTORING
- [ ] 로또자동판매기(LottoSeller) 객체 생성
- [x] TEST - 금액을 입력 받아 구입할 로또 복권 개수를 반환한다
- [x] TEST - 구입할 개수만큼 로또복권을 생성한다
- [x] TEST - 각 일치 개수 별 당첨된 복권의 개수를 반환한다
- [x] TEST - 생성된 로또복권의 수익률을 계산한다
- [ ] REFACTORING
- [ ] 당첨결과를 매칭할 Enum(LottoRank) 객체 생성
- [x] REFACTORING
- [ ] InputView 객체 생성
- [x] TEST - 구입 금액을 입력받고, 출력한다
- [x] TEST - 구매 개수를 LottoSeller로 부터 반환받아서 출력한다
- [x] TEST - 구매 개수만큼 생성된 로또복권들을 출력한다
- [x] TEST - 지난주 당첨 번호를 입력 받는다
- [ ] REFACTORING
- [ ] OutputView 객체 생성
- [x] TEST - 각 일치 개수 별 당첨된 복권의 개수를 LottoSeller로 부터 반환받아서 출력한다
- [ ] TEST - 총 수익률을 LottoSeller로 부터 반환받아서 출력한다.
- [ ] REFACTORING
2 changes: 1 addition & 1 deletion src/main/java/step1/Element.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class Element {

private int value;

public Element(int value) {
private Element(int value) {
this.value = value;
}

Expand Down
29 changes: 29 additions & 0 deletions src/main/java/step2/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package step2;

import step2.domain.LottoRank;
import step2.domain.LottoSeller;
import step2.domain.LottoTicket;
import step2.view.InputView;
import step2.view.OutputView;

import java.util.List;
import java.util.Map;

public class LottoApplication {

public static void main(String[] args) {
final int inputMoney = InputView.askMoneyToInput();
final int numberOfTicketsToBuy = LottoSeller.countLottoTickets(inputMoney);

OutputView.printNumberOfLottoTickets(numberOfTicketsToBuy);

List<LottoTicket> lottoTickets = LottoSeller.issueLottoTicket(numberOfTicketsToBuy);
OutputView.printLottoTickets(lottoTickets);

LottoTicket luckyNumber = LottoSeller.getLuckyNumber(InputView.askLuckyNumber());
Map<LottoRank, List<LottoTicket>> lottoResultMap = LottoSeller.getLottoResult(lottoTickets, luckyNumber);

Choose a reason for hiding this comment

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

Map<LottoRank, List> lottoResultMap이 아닌
LottoResult같은 객체로 결과를 계산하는 객체가 나오면 좋을것 같네요.


OutputView.printResult(lottoResultMap, numberOfTicketsToBuy);
}
}

17 changes: 17 additions & 0 deletions src/main/java/step2/domain/LottoBalls.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package step2.domain;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class LottoBalls {

private static List<Integer> lottoBalls = IntStream
.rangeClosed(LottoNumber.MINIMUM_LOTTO_NUMBER, LottoNumber.MAXIMUM_LOTTO_NUMBER)
.boxed()
.collect(Collectors.toList());

public static List<Integer> getLottoBalls() {
return lottoBalls;
}
}
47 changes: 47 additions & 0 deletions src/main/java/step2/domain/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package step2.domain;

import java.util.Objects;

public class LottoNumber {
static final String ALERT_OUT_OF_RANGE_OF_LOTTO_NUMBER = "로또번호는 1부터 45까지의 자연수만 가능합니다.";
static final int MINIMUM_LOTTO_NUMBER = 1;
static final int MAXIMUM_LOTTO_NUMBER = 45;
private int number;

private LottoNumber(int number) {
if (isOutOfRange(number)) {
throw new IllegalArgumentException(ALERT_OUT_OF_RANGE_OF_LOTTO_NUMBER);
}
this.number = number;
}

public static LottoNumber from(Integer number) {
return new LottoNumber(number);
}

private boolean isOutOfRange(int number) {
return number < MINIMUM_LOTTO_NUMBER || number > MAXIMUM_LOTTO_NUMBER;
}

public int getNumber() {
return number;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LottoNumber that = (LottoNumber) o;
return number == that.number;
}

@Override
public int hashCode() {
return Objects.hash(number);
}

@Override
public String toString() {
return number + "";
}
}
35 changes: 35 additions & 0 deletions src/main/java/step2/domain/LottoRank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package step2.domain;

import java.util.Arrays;

public enum LottoRank {

FIRST_PLACE(6, 2000000000),
SECOND_PLACE(5, 1500000),
THIRD_PLACE(4, 50000),
FOURTH_PLACE(3, 5000),
LOSER(0, 0);

private int numberOfMatchedToLuckyNumber;
private int prizeMoney;

LottoRank(int numberOfMatchedToLuckyNumber, int prizeMoney) {
this.numberOfMatchedToLuckyNumber = numberOfMatchedToLuckyNumber;
this.prizeMoney = prizeMoney;
}

public static LottoRank from(int countMatchedNumbers) {
return Arrays.stream(LottoRank.values())
.filter(lottoRank -> lottoRank.numberOfMatchedToLuckyNumber == countMatchedNumbers)
.findFirst()
.orElse(LOSER);
}

public int getNumberOfMatchedToLuckyNumber() {
return numberOfMatchedToLuckyNumber;
}

public int getPrizeMoney() {
return prizeMoney;
}
}
48 changes: 48 additions & 0 deletions src/main/java/step2/domain/LottoSeller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package step2.domain;

import java.util.*;
import java.util.stream.Collectors;

public class LottoSeller {
static final int PRICE_OF_A_LOTTO_TICKET = 1000;
static final String ALERT_MISSING_MONEY = "돈을 넣어주세요. 로또복권은 한 장당 1000원 입니다.";

public static int countLottoTickets(int inputMoney) {
validationInputMoney(inputMoney);
return inputMoney / PRICE_OF_A_LOTTO_TICKET;
}

public static List<LottoTicket> issueLottoTicket(int numberOfTicketsToBuy) {
List<LottoTicket> lottoTickets = new ArrayList<>();

for (int i = 0; i < numberOfTicketsToBuy; i++) {
lottoTickets.add(LottoTicketGenerator.issue());
}
return lottoTickets;
}

public static LottoTicket getLuckyNumber(List<Integer> inputLuckyNumber) {
List<LottoNumber> lottoTicket = inputLuckyNumber.stream()
.map(LottoNumber::from)
.collect(Collectors.toList());
return LottoTicketGenerator.issue(lottoTicket);
}

public static Map<LottoRank, List<LottoTicket>> getLottoResult(List<LottoTicket> lottoTickets, LottoTicket luckyNumber) {
Map<LottoRank, List<LottoTicket>> lottoResultMap = new HashMap<>();

for (LottoTicket ticket : lottoTickets) {
LottoRank lottoRank = LottoRank.from(ticket.getNumberOfMatchedToLuckyNumber(luckyNumber));
List<LottoTicket> ticketsCorrespondingToRank = lottoResultMap.getOrDefault(lottoRank, new ArrayList<>());
ticketsCorrespondingToRank.add(ticket);
lottoResultMap.put(lottoRank, ticketsCorrespondingToRank);
}
return lottoResultMap;
}

private static void validationInputMoney(int inputMoney) {
if (inputMoney < PRICE_OF_A_LOTTO_TICKET) {
throw new IllegalArgumentException(ALERT_MISSING_MONEY);
}
}
}
66 changes: 66 additions & 0 deletions src/main/java/step2/domain/LottoTicket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package step2.domain;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class LottoTicket {
static final String ALERT_NUMBER_OVERLAP = "중복된 로또 번호가 존재합니다.";
static final String AlERT_DIFFERENT_SIZE_OF_NUMBERS = "로또번호의 개수가 6개가 아닙니다.";

private final List<LottoNumber> lottoTicket;

LottoTicket(List<LottoNumber> lottoTicket) {
validationNumberSize(lottoTicket);
validationNumberOverlap(lottoTicket);
this.lottoTicket = lottoTicket;
}

private void validationNumberSize(List<LottoNumber> lottoTicket) {
if (lottoTicket.size() != LottoTicketGenerator.BASIC_LOTTO_SIZE) {
throw new IllegalArgumentException(AlERT_DIFFERENT_SIZE_OF_NUMBERS);
}
}

private void validationNumberOverlap(List<LottoNumber> lottoTicket) {
long SizeOfLottoTicket = lottoTicket.stream()
.mapToLong(LottoNumber::getNumber)
.distinct()
.count();

if (SizeOfLottoTicket != LottoTicketGenerator.BASIC_LOTTO_SIZE) {
throw new IllegalArgumentException(ALERT_NUMBER_OVERLAP);
}
}

public int getNumberOfMatchedToLuckyNumber(LottoTicket luckyNumber) {
return (int) luckyNumber.getLottoTicket().stream()
.filter(lottoTicket::contains)
.count();
}

public List<LottoNumber> getLottoTicket() {
return Collections.unmodifiableList(lottoTicket);
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LottoTicket that = (LottoTicket) o;
return Objects.equals(lottoTicket, that.lottoTicket);
}

@Override
public int hashCode() {
return Objects.hash(lottoTicket);
}

@Override
public String toString() {
return "LottoTicket{" +
"lottoTicket=" + lottoTicket +
'}';
}
}
31 changes: 31 additions & 0 deletions src/main/java/step2/domain/LottoTicketGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package step2.domain;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class LottoTicketGenerator {
static final int BASIC_LOTTO_SIZE = 6;

static LottoTicket issue() {
return new LottoTicket(pickLottoBalls(LottoBalls.getLottoBalls()));
}

static LottoTicket issue(List<LottoNumber> lottoTicket) {
return new LottoTicket(lottoTicket);
}

static List<LottoNumber> pickLottoBalls(List<Integer> lottoBalls) {
shuffleLottoBalls(lottoBalls);
return lottoBalls.stream()
.limit(BASIC_LOTTO_SIZE)
.sorted()
.map(LottoNumber::from)
.collect(Collectors.toList());
}

static void shuffleLottoBalls(List<Integer> lottoBalls) {
Collections.shuffle(lottoBalls);
}

}
34 changes: 34 additions & 0 deletions src/main/java/step2/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package step2.view;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class InputView {
private static final String LUCKY_NUMBER_SEPARATOR = ",";
private static Scanner scanner = new Scanner(System.in);

public static int askMoneyToInput() {
System.out.println("구입금액을 입력해 주세요.");
return scanner.nextInt();
}

public static List<Integer> askLuckyNumber() {
printBlackLine();
scanner.nextLine();
System.out.println("지난 주 당첨 번호를 입력해주세요.");
String inputLuckyNumber = scanner.nextLine();
printBlackLine();

return Arrays.stream(inputLuckyNumber.split(LUCKY_NUMBER_SEPARATOR))
.map(String::trim)
.mapToInt(Integer::parseInt)
.boxed()
.collect(Collectors.toList());
}

private static void printBlackLine() {
System.out.println();
}
}
Loading