-
Notifications
You must be signed in to change notification settings - Fork 4
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
[java-lotto] yohan.kim(김요한) 과제 제출합니다. #2
base: yohan/java-lotto
Are you sure you want to change the base?
Changes from all commits
9f52f00
7576de1
008b6c1
52c519f
4638e9f
1425896
1a0f5bd
83c1bdd
8355f3b
57d7b7d
ac4142d
d30908f
a57eeae
c21af95
7a8900b
f620885
c544e51
c63bddb
1dfbf77
3a4147f
1765eca
e405f96
1c8507a
33e67dc
d08ea77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
## 기능 목록 | ||
|
||
- [x] 로또 Lotto | ||
- [x] 여섯 개인지 검증 - validateCounts() | ||
- [x] 로또 번호에 중복된 숫자가 있는지 검증 - validateDuplication() | ||
- [x] 정답과 비교 후 등수 반환 - calculateRank() | ||
- [x] 3항 연산자 제거 | ||
- [x] 로또 판매기 Seller | ||
- [x] 금액에 받아 구매 가능한 로또 개수 반환 - calculateLottoCount() | ||
- [x] 로또 발행 - getLotto() | ||
- [x] 오름차순으로 발행 | ||
- [x] 개수만큼 로또 발행 - getLottos() | ||
- [x] 로또 당첨 통계 반환 - getResult() | ||
- [x] 수익률 계산 - calculateRate() | ||
- [x] 수익률은 소수점 둘째자리에서 반올림 | ||
- [x] UI | ||
- [x] 구입금액 입력받기 - receivePurchaseMoney() | ||
- [x] 구매한 로또 출력 - printBoughtLottos() | ||
- [x] 당첨 번호 입력받기 - receiveAnswers() | ||
- [x] 보너스 번호 입력받기 - receiveBonus() | ||
- [x] 당첨 통계 출력 - printResult() | ||
- [x] 수익률 출력 - printRate() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,31 @@ | ||
package lotto; | ||
|
||
import java.util.List; | ||
|
||
public class Application { | ||
|
||
public static final int LOTTO_PRICE = 1_000; | ||
|
||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
|
||
String purchaseMoneyStr = UI.receivePurchaseMoney(); | ||
Seller seller = new Seller(LOTTO_PRICE); | ||
|
||
try { | ||
int purchaseCount = seller.calculateLottoCount(seller.parsePurchaseMoneyStr(purchaseMoneyStr)); | ||
|
||
List<Lotto> lottos = seller.getLottos(purchaseCount); | ||
UI.printBoughtLottos(lottos); | ||
|
||
List<Integer> answers = UI.receiveAnswers(); | ||
int bonus = UI.receiveBonus(); | ||
|
||
List<Integer> result = seller.getResult(lottos, answers, bonus); | ||
UI.printResult(result); | ||
UI.printRate(seller.calculateRate(result, purchaseCount)); | ||
} catch (IllegalArgumentException e) { | ||
UI.handlingIllegalArgumentException(e); | ||
} | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
package lotto; | ||
|
||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
public class Lotto { | ||
private final List<Integer> numbers; | ||
|
@@ -11,10 +14,59 @@ public Lotto(List<Integer> numbers) { | |
} | ||
|
||
private void validate(List<Integer> numbers) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lotto 내부에서 예외처리를 선언하다보니 코드가 지저분해지는것 같습니다! 클래스를 따로 만들어 예외처리를 하는 방법은 별로인가요?? |
||
validateCounts(numbers); | ||
validateDuplication(numbers); | ||
} | ||
|
||
private void validateCounts(List<Integer> numbers) { | ||
if (numbers.size() != 6) { | ||
throw new IllegalArgumentException(); | ||
throw new IllegalArgumentException("로또 번호의 개수는 6개여야 합니다."); | ||
} | ||
} | ||
|
||
private void validateDuplication(List<Integer> numbers) { | ||
if (new HashSet<>(numbers).size() != numbers.size()) { | ||
throw new IllegalArgumentException("로또 번호는 중복되어선 안됩니다."); | ||
} | ||
} | ||
|
||
public int calculateRank(List<Integer> answers, int bonus) { | ||
|
||
Set<Integer> set = new HashSet<>(numbers); | ||
|
||
int correct = getCorrect(answers, set); | ||
int bonusCorrect = getBonusCorrect(bonus, set, correct); | ||
|
||
return rankByCondition(correct, bonusCorrect); | ||
} | ||
|
||
private static int getCorrect(List<Integer> answers, Set<Integer> set) { | ||
return (int) answers.stream() | ||
.filter(set::contains) | ||
.count(); | ||
} | ||
|
||
private static int getBonusCorrect(int bonus, Set<Integer> set, int correct) { | ||
if (set.contains(bonus) && correct == 5) { | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
// TODO: 추가 기능 구현 | ||
private int rankByCondition(int correct, int bonusCorrect) { | ||
if (correct == 6) { | ||
return 1; | ||
} | ||
|
||
if (correct + bonusCorrect <= 2) { | ||
return 6; | ||
} | ||
|
||
return 8 - (correct + bonusCorrect); | ||
} | ||
Comment on lines
+49
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아까 피드백 드렸듯이, 매직 넘버를 상수로 치환하는 것이 좋습니다. 더 의미있는 상수로 치환해주세요! |
||
|
||
@Override | ||
public String toString() { | ||
return numbers.toString(); | ||
} | ||
} | ||
Comment on lines
+69
to
72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 객체를 더 객체답게 사용하려면 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package lotto; | ||
|
||
import camp.nextstep.edu.missionutils.Randoms; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
public class Seller { | ||
|
||
private final int lottoPrice; | ||
private static final List<Integer> prize = List.of(2_000_000_000, 30_000_000, 1_500_000, 50_000, 5_000, 0); | ||
|
||
public Seller(int lottoPrice) { | ||
this.lottoPrice = lottoPrice; | ||
} | ||
|
||
public int parsePurchaseMoneyStr(String purchaseMoneyStr) { | ||
try { | ||
return Integer.parseInt(purchaseMoneyStr); | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("입력은 1000으로 나눠지는 값이어야 합니다."); | ||
} | ||
} | ||
|
||
public int calculateLottoCount(int money) { | ||
return money / lottoPrice; | ||
} | ||
|
||
public Lotto getLotto() { | ||
List<Integer> randoms = new ArrayList<>(Randoms.pickUniqueNumbersInRange(1, 45, 6)); | ||
Collections.sort(randoms); | ||
return new Lotto(randoms); | ||
} | ||
|
||
public List<Lotto> getLottos(int count) { | ||
return IntStream.range(0, count) | ||
.mapToObj(i -> getLotto()) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public List<Integer> getResult(List<Lotto> lottos, List<Integer> answers, int bonus) { | ||
List<Integer> result = new ArrayList<>(List.of(0, 0, 0, 0, 0, 0)); | ||
|
||
for (Lotto lotto: lottos) { | ||
int index = lotto.calculateRank(answers, bonus) - 1; | ||
result.set(index, result.get(index) + 1); | ||
} | ||
return result; | ||
} | ||
|
||
public BigDecimal calculateRate(List<Integer> ranks, int count) { | ||
|
||
long prizeSum = IntStream.range(0, 6) | ||
.mapToLong(index -> (long) ranks.get(index) * prize.get(index)) | ||
.sum(); | ||
int cost = lottoPrice * count; | ||
|
||
double rate = prizeSum * 100 / (double) cost; | ||
return new BigDecimal(rate).setScale(1, BigDecimal.ROUND_HALF_UP); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package lotto; | ||
|
||
import camp.nextstep.edu.missionutils.Console; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
public class UI { | ||
|
||
private static final Map<Integer, String> resultOutputByRank = Map.of( | ||
1, "6개 일치 (2,000,000,000원)", | ||
2, "5개 일치, 보너스 볼 일치 (30,000,000원)", | ||
3, "5개 일치 (1,500,000원)", | ||
4, "4개 일치 (50,000원)", | ||
5, "3개 일치 (5,000원)" | ||
); | ||
|
||
public static String receivePurchaseMoney() { | ||
System.out.println("구입금액을 입력해 주세요."); | ||
return Console.readLine(); | ||
} | ||
|
||
public static void printBoughtLottos(List<Lotto> lottos) { | ||
System.out.println("\n" + lottos.size() + "개를 구매했습니다."); | ||
for (Lotto lotto : lottos) { | ||
System.out.println(lotto); | ||
} | ||
} | ||
|
||
public static List<Integer> receiveAnswers() { | ||
System.out.println("\n당첨 번호를 입력해 주세요."); | ||
String[] split = Console.readLine().split(","); | ||
return Arrays.stream(split) | ||
.map(Integer::parseInt) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public static int receiveBonus() { | ||
System.out.println("\n보너스 번호를 입력해 주세요."); | ||
return Integer.parseInt(Console.readLine()); | ||
} | ||
|
||
public static void printResult(List<Integer> result) { | ||
System.out.println("\n당첨 통계"); | ||
System.out.println("---"); | ||
|
||
for (int index = 4; index >= 0; index--) { | ||
System.out.println(resultOutputByRank.get(index + 1) + " - " + result.get(index) + "개"); | ||
} | ||
} | ||
|
||
public static void printRate(BigDecimal rate) { | ||
System.out.println("총 수익률은 " + rate.toPlainString() + "%입니다."); | ||
} | ||
|
||
public static void handlingIllegalArgumentException(IllegalArgumentException e) { | ||
System.out.println("[ERROR] " + e.getMessage()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
package lotto; | ||
|
||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
class LottoTest { | ||
|
@@ -18,10 +20,97 @@ void createLottoByOverSize() { | |
@DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.") | ||
@Test | ||
void createLottoByDuplicatedNumber() { | ||
// TODO: 이 테스트가 통과할 수 있게 구현 코드 작성 | ||
assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
// 아래에 추가 테스트 작성 가능 | ||
@DisplayName("6개 일치하면, 1을 반환한다.") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 테스트를 직접 만드신 부분 대단합니다 👍 |
||
@Test | ||
void calculateRank_1st() { | ||
//given | ||
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 6)); | ||
List<Integer> answers = List.of(1, 2, 3, 4, 5, 6); | ||
int bonus = 7; | ||
|
||
//when | ||
int rank = lotto.calculateRank(answers, bonus); | ||
|
||
//then | ||
assertThat(rank).isEqualTo(1); | ||
} | ||
|
||
@DisplayName("5개 일치하고, 보너스 볼 일치하면, 2을 반환한다.") | ||
@Test | ||
void calculateRank_2nd() { | ||
//given | ||
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 7)); | ||
List<Integer> answers = List.of(1, 2, 3, 4, 5, 6); | ||
int bonus = 7; | ||
|
||
//when | ||
int rank = lotto.calculateRank(answers, bonus); | ||
|
||
//then | ||
assertThat(rank).isEqualTo(2); | ||
} | ||
|
||
@DisplayName("5개 일치하면, 3을 반환한다.") | ||
@Test | ||
void calculateRank_3rd() { | ||
//given | ||
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 8)); | ||
List<Integer> answers = List.of(1, 2, 3, 4, 5, 6); | ||
int bonus = 7; | ||
|
||
//when | ||
int rank = lotto.calculateRank(answers, bonus); | ||
|
||
//then | ||
assertThat(rank).isEqualTo(3); | ||
} | ||
|
||
@DisplayName("4개 일치하면, 4을 반환한다.") | ||
@Test | ||
void calculateRank_4th() { | ||
//given | ||
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 7, 8)); | ||
List<Integer> answers = List.of(1, 2, 3, 4, 5, 6); | ||
int bonus = 7; | ||
|
||
//when | ||
int rank = lotto.calculateRank(answers, bonus); | ||
|
||
//then | ||
assertThat(rank).isEqualTo(4); | ||
} | ||
|
||
@DisplayName("3개 일치하면, 5을 반환한다.") | ||
@Test | ||
void calculateRank_5th() { | ||
//given | ||
Lotto lotto = new Lotto(List.of(1, 2, 3, 7, 8, 9)); | ||
List<Integer> answers = List.of(1, 2, 3, 4, 5, 6); | ||
int bonus = 7; | ||
|
||
//when | ||
int rank = lotto.calculateRank(answers, bonus); | ||
|
||
//then | ||
assertThat(rank).isEqualTo(5); | ||
} | ||
|
||
@DisplayName("2개 이하 일치하면, 6을 반환한다.") | ||
@Test | ||
void calculateRank_6th() { | ||
//given | ||
Lotto lotto = new Lotto(List.of(1, 2, 7, 8, 9, 10)); | ||
List<Integer> answers = List.of(1, 2, 3, 4, 5, 6); | ||
int bonus = 7; | ||
|
||
//when | ||
int rank = lotto.calculateRank(answers, bonus); | ||
|
||
//then | ||
assertThat(rank).isEqualTo(6); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MVC 패턴에 따라 설게구조를 변경해도 좋을 듯 합니다! 이 부분을 컨트롤러로 분리해도 좋을 것 같아요!