-
Notifications
You must be signed in to change notification settings - Fork 0
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
[로또] 조윤호 제출합니다 #3
base: main
Are you sure you want to change the base?
Changes from all commits
8b7f9c7
a97de00
ec15121
0ada73b
583242a
6ba1265
f51b94d
77b2e36
a063735
5b0a3d4
5244242
3c03b63
d878bb0
b4bb8e7
8099c5c
fde7c09
184b14e
51e4d73
14407eb
44e98a1
47cd5d9
f1da751
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 |
---|---|---|
@@ -1,7 +1,10 @@ | ||
package lotto; | ||
|
||
import lotto.lotto.LottoService; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
LottoService lottoService = new LottoService(); | ||
lottoService.run(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package lotto.config; | ||
|
||
public class LottoConfig { | ||
|
||
private LottoConfig() { | ||
} | ||
|
||
public final static int LOTTO_NUM_LENGTH = 6; | ||
public final static int LOTTO_MIN_NUM = 1; | ||
public final static int LOTTO_MAX_NUM = 45; | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package lotto.lotto; | ||
|
||
import lotto.config.LottoConfig; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Comparator; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class Lotto { | ||
private final List<Integer> numbers; | ||
|
||
public Lotto(List<Integer> numbers) { | ||
validate(numbers); | ||
|
||
try { | ||
numbers.sort(Comparator.naturalOrder()); | ||
} catch (UnsupportedOperationException ignored) {} | ||
Comment on lines
+17
to
+19
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. 프로덕션 코드에서 테스트코드의 영향을 받아야할까요? |
||
|
||
this.numbers = numbers; | ||
} | ||
|
||
private void validate(List<Integer> numbers) { | ||
if (numbers.size() != LottoConfig.LOTTO_NUM_LENGTH) | ||
throw new IllegalArgumentException("[ERROR] 숫자의 개수가 올바르지 않습니다."); | ||
if (numbers.size() != (new HashSet<>(numbers)).size()) | ||
throw new IllegalArgumentException("[ERROR] 숫자에 중복이 없어야 합니다."); | ||
Comment on lines
+25
to
+28
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. validate가 한 번에 '개수 검증'과 '중복 검증'이라는 두 가지 일을 처리하고 있네요. |
||
} | ||
|
||
|
||
public Prize comparePrize(Lotto winningLotto, int bonus) { | ||
List<Integer> list = new ArrayList<>(); | ||
list.addAll(numbers); | ||
list.addAll(winningLotto.numbers); | ||
int matches = list.size() - (new HashSet<>(list)).size(); | ||
boolean isBonus = numbers.contains(bonus); | ||
|
||
Prize prize = Prize.NONE; | ||
for (Prize p : Prize.values()) { | ||
if ( | ||
p.isPrized() && | ||
p.getMatchNum() <= matches && | ||
p.getGrade() <= prize.getGrade() | ||
) { | ||
if (p.isBonus() && !isBonus) // 보너스 true인 경우 isBonus 확인한다. | ||
continue; | ||
prize = p; | ||
} | ||
} | ||
Comment on lines
+40
to
+50
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.
|
||
return prize; | ||
} | ||
|
||
public boolean contains(int num) { | ||
return numbers.contains(num); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[" + | ||
numbers.stream().map(String::valueOf).collect(Collectors.joining(", ")) + | ||
"]"; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,99 @@ | ||||||||
package lotto.lotto; | ||||||||
|
||||||||
import lotto.purchase.PurchaseService; | ||||||||
import lotto.util.LottoUtil; | ||||||||
import lotto.util.UserOutput; | ||||||||
|
||||||||
import java.util.ArrayList; | ||||||||
import java.util.List; | ||||||||
|
||||||||
public class LottoBundle { | ||||||||
private List<Lotto> lottos = new ArrayList<>(); | ||||||||
private Lotto winningLotto; | ||||||||
private int bonus; | ||||||||
|
||||||||
Comment on lines
+10
to
+14
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. 불변 객체로 만들지 않으면 프로그램이 동작할때 어떤 문제가 발생할까요? |
||||||||
|
||||||||
/** | ||||||||
* lottoNum의 수만큼 새로운 로또 생성하기 | ||||||||
*/ | ||||||||
public void createLottos(int lottoNum) { | ||||||||
for (int i = 0; i < lottoNum; i++) { | ||||||||
Lotto lotto = new Lotto(LottoUtil.createLotto()); | ||||||||
lottos.add(lotto); | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
/** | ||||||||
* 당첨번호 저장하기 | ||||||||
*/ | ||||||||
public void setWinningLotto(List<Integer> winningNumList) { | ||||||||
Lotto lotto = new Lotto(winningNumList); | ||||||||
this.winningLotto = lotto; | ||||||||
Comment on lines
+30
to
+31
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.
Suggested change
재사용 가능성이 없는 경우 변수에 담지 않고 바로 사용하는게 더 좋은 것 같아요! |
||||||||
} | ||||||||
|
||||||||
/** | ||||||||
* 보너스번호 저장하기 | ||||||||
*/ | ||||||||
public void setBonus(int bonus) { | ||||||||
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. setter 사용 대신 좀 더 의미있는 네이밍을 하면 좋을 것 같아요! |
||||||||
if (winningLotto.contains(bonus)) { | ||||||||
throw new IllegalArgumentException("[ERROR] 보너스 번호와 당첨 번호에 중복이 있습니다."); | ||||||||
} | ||||||||
this.bonus = bonus; | ||||||||
} | ||||||||
|
||||||||
/** | ||||||||
* 로또 출력하기 | ||||||||
*/ | ||||||||
public void printLottos() { | ||||||||
StringBuilder sb = new StringBuilder(); | ||||||||
|
||||||||
for (Lotto lotto : lottos) | ||||||||
sb.append(lotto).append("\n"); | ||||||||
|
||||||||
UserOutput.printLottos(lottos.size(), sb.toString()); | ||||||||
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. Domain에서 view에 의존하는 것이 맞을까요? |
||||||||
} | ||||||||
|
||||||||
/** | ||||||||
* 당첨 통계 출력하기 | ||||||||
*/ | ||||||||
public void printResult() { | ||||||||
int[] prizeStat = getPrizeStat(); | ||||||||
int totalreward = getTotalReward(prizeStat); | ||||||||
double rewardPercent = PurchaseService.getRewardPercent(lottos.size(), totalreward); | ||||||||
|
||||||||
StringBuilder sb = new StringBuilder(); | ||||||||
for (Prize prize : Prize.values()){ | ||||||||
if (!prize.isPrized()) continue; | ||||||||
sb.append(prize.getToString()); | ||||||||
sb.append( | ||||||||
String.format(" (%,d원) - %d개", | ||||||||
prize.getReward(), | ||||||||
prizeStat[prize.ordinal()] | ||||||||
)); | ||||||||
sb.append("\n"); | ||||||||
} | ||||||||
sb.append(String.format("총 수익률은 %.1f%%입니다.", rewardPercent)); | ||||||||
|
||||||||
UserOutput.printResult(sb.toString()); | ||||||||
} | ||||||||
|
||||||||
public int[] getPrizeStat() { | ||||||||
int[] prizeStat = new int[Prize.values().length]; | ||||||||
for (Lotto lotto : lottos) { | ||||||||
Prize prize = lotto.comparePrize(winningLotto, bonus); | ||||||||
if (prize.isPrized()) | ||||||||
prizeStat[prize.ordinal()]++; | ||||||||
} | ||||||||
return prizeStat; | ||||||||
} | ||||||||
|
||||||||
public int getTotalReward(int[] prizeStat) { | ||||||||
Comment on lines
+80
to
+90
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. 두 메소드는 LottoBundle 내부에서만 사용되네요. private로 선언해주시면 좋을 것 같아요! |
||||||||
int totalReward = 0; | ||||||||
for (Prize prize : Prize.values()){ | ||||||||
if (prizeStat[prize.ordinal()] != 0) | ||||||||
totalReward += prize.getReward() * prizeStat[prize.ordinal()]; | ||||||||
} | ||||||||
return totalReward; | ||||||||
} | ||||||||
|
||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,74 @@ | ||||||||||||||||||||||||||
package lotto.lotto; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
import lotto.purchase.PurchaseService; | ||||||||||||||||||||||||||
import lotto.util.UserInput; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
import java.util.ArrayList; | ||||||||||||||||||||||||||
import java.util.Arrays; | ||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||
import java.util.stream.Collectors; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public class LottoService { | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public void run() { | ||||||||||||||||||||||||||
LottoBundle bundle = new LottoBundle(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// 구입금액 입력받기 | ||||||||||||||||||||||||||
String userInput = UserInput.getCostInput(); | ||||||||||||||||||||||||||
int cost = getNum(userInput); | ||||||||||||||||||||||||||
int lottoNum = PurchaseService.getLottoNum(cost); | ||||||||||||||||||||||||||
Comment on lines
+18
to
+19
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. 구입금액은 그냥 정수보다 좀 더 의미있는 값 같아요. '구입금액'이라는 객체를 생성하는 건 어떨까요? |
||||||||||||||||||||||||||
bundle.createLottos(lottoNum); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// 로또 출력하기 | ||||||||||||||||||||||||||
bundle.printLottos(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// 당첨번호 입력받기 | ||||||||||||||||||||||||||
userInput = UserInput.getLottoInput(); | ||||||||||||||||||||||||||
List<Integer> winningList = getNumList(userInput); | ||||||||||||||||||||||||||
bundle.setWinningLotto(winningList); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// 보너스번호 입력받기 | ||||||||||||||||||||||||||
userInput = UserInput.getBonusInput(); | ||||||||||||||||||||||||||
int bonus = getNum(userInput); | ||||||||||||||||||||||||||
bundle.setBonus(bonus); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// 당첨 통계 출력하기 | ||||||||||||||||||||||||||
bundle.printResult(); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public int getNum (String input) { | ||||||||||||||||||||||||||
int num; | ||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||
num = Integer.parseInt(input); | ||||||||||||||||||||||||||
} catch (NumberFormatException ne) { | ||||||||||||||||||||||||||
throw new IllegalArgumentException("[ERROR] 정수를 입력해주세요."); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
return num; | ||||||||||||||||||||||||||
Comment on lines
+41
to
+47
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. 이런 식으로 early return 패턴을 사용하는게 더 가독성이 좋을 것 같아요!
Suggested change
|
||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public List<Integer> getNumList(String input) { | ||||||||||||||||||||||||||
List<String> strList = new ArrayList<>( | ||||||||||||||||||||||||||
Arrays.asList( | ||||||||||||||||||||||||||
input.split(",") | ||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// "," 개수를 이용해서 배열의 길이가 올바르게 입력되었는지 확인한다. | ||||||||||||||||||||||||||
int commas = input.length() - input.replace(String.valueOf(","), "").length(); | ||||||||||||||||||||||||||
if (commas+1 != strList.size()) | ||||||||||||||||||||||||||
throw new IllegalArgumentException("[ERROR] 정수와 ,로 이루어진 배열을 입력해주세요."); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
List<Integer> numList = strList.stream() | ||||||||||||||||||||||||||
.map(s -> { | ||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||
return Integer.parseInt(s); | ||||||||||||||||||||||||||
} catch (NumberFormatException ne) { | ||||||||||||||||||||||||||
throw new IllegalArgumentException("[ERROR] 정수와 ,로 이루어진 배열을 입력해주세요."); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} ).collect(Collectors.toList()); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
return numList; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package lotto.lotto; | ||
|
||
public enum Prize { | ||
FIFTH(true, 5, 3, false, 5000, "3개 일치"), | ||
FOURTH(true, 4, 4, false, 50000, "4개 일치"), | ||
THIRD(true, 3, 5, false, 1500000, "5개 일치"), | ||
SECOND(true, 2, 5, true, 30000000, "5개 일치, 보너스 볼 일치"), | ||
FIRST(true, 1, 6, false, 2000000000, "6개 일치"), | ||
NONE(false, 99999, 0, false, 0, ""); | ||
|
||
private final boolean prized; | ||
private final int grade; | ||
private final int matchNum; | ||
private final boolean bonus; | ||
private final int reward; | ||
private final String toString; | ||
|
||
Prize(boolean prized, int grade, int matchNum, boolean bonus, int reward, String toString) { | ||
this.prized = prized; | ||
this.grade = grade; | ||
this.matchNum = matchNum; | ||
this.bonus = bonus; | ||
this.reward = reward; | ||
this.toString = toString; | ||
} | ||
|
||
public boolean isPrized() { | ||
return prized; | ||
} | ||
|
||
public int getGrade() { | ||
return grade; | ||
} | ||
|
||
public int getMatchNum() { | ||
return matchNum; | ||
} | ||
|
||
public boolean isBonus() { | ||
return bonus; | ||
} | ||
|
||
public int getReward() { | ||
return reward; | ||
} | ||
|
||
public String getToString() { | ||
return toString; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package lotto.purchase; | ||
|
||
public class PurchaseService { | ||
|
||
private final static int PRICE_PER_LOTTO = 1000; | ||
|
||
private PurchaseService() { | ||
} | ||
|
||
/** | ||
* 텍스트 입력을 lotto 수로 변환 | ||
*/ | ||
public static int getLottoNum(int cost) { | ||
if (cost <=0 ) | ||
throw new IllegalArgumentException("[ERROR] 1 이상의 양수를 입력해주세요"); | ||
Comment on lines
+14
to
+15
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. 음수와 0 처리는 생각하지 못했던 부분이네요! 👍🏻 |
||
if (cost % PRICE_PER_LOTTO != 0) | ||
throw new IllegalArgumentException("[ERROR] 가격의 배수에 해당하는 가격을 입력해주세요"); | ||
Comment on lines
+14
to
+17
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. 검증의 책임을 분리하면 좋을 것 같아요! |
||
|
||
return cost / PRICE_PER_LOTTO; | ||
} | ||
|
||
/** | ||
* 총 로또 수익률을 퍼센트 단위로 반환 | ||
*/ | ||
public static double getRewardPercent(int num, int reward){ | ||
return (double) reward / (num * PRICE_PER_LOTTO) * 100; | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package lotto.util; | ||
|
||
import camp.nextstep.edu.missionutils.Randoms; | ||
import lotto.config.LottoConfig; | ||
|
||
import java.util.List; | ||
|
||
public class LottoUtil { | ||
|
||
private LottoUtil() { | ||
} | ||
|
||
public static List<Integer> createLotto() { | ||
return Randoms.pickUniqueNumbersInRange( | ||
LottoConfig.LOTTO_MIN_NUM, | ||
LottoConfig.LOTTO_MAX_NUM, | ||
LottoConfig.LOTTO_NUM_LENGTH | ||
); | ||
} | ||
|
||
} |
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.
public static final 형태로 상수를 관리하는 것은 굉장히 안좋은 방법입니다!
절차 지향적인 방법으로 코드를 작성하고 계신것 같아요