-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Step2 - 로또(자동) #3462
base: kwonyoungbin
Are you sure you want to change the base?
Step2 - 로또(자동) #3462
Changes from all commits
5b53d4c
f0c43f8
55dc717
e9ec165
f4878ad
fca58c8
465d10a
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,23 @@ | ||
package lotto; | ||
|
||
import lotto.domain.MyLotto; | ||
import lotto.domain.PrizeResult; | ||
import lotto.view.InputView; | ||
import lotto.view.ResultView; | ||
|
||
import java.util.List; | ||
|
||
public class LottoApplication { | ||
public static void main(String[] args){ | ||
int money = InputView.inputPurchaseAmount(); | ||
|
||
MyLotto myLotto = new MyLotto(money); | ||
ResultView.printMyLottoList(myLotto); | ||
|
||
List<Integer> winningNumbers = InputView.inputWinningNumbers(); | ||
PrizeResult prizeResult = myLotto.getResult(winningNumbers); | ||
|
||
ResultView.printLottoResult(prizeResult); | ||
ResultView.printEarnRate(prizeResult, money); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package lotto.domain; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
public class Lotto { | ||
private final List<Integer> numList = IntStream.range(1, 45).boxed().collect(Collectors.toList()); | ||
|
||
private final List<Integer> lottoNumberList; | ||
|
||
public Lotto(){ | ||
shuffle(); | ||
this.lottoNumberList = numList.subList(0, 6); | ||
sort(); | ||
} | ||
Comment on lines
+13
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. 생성자에 로직은 제거하고 필드에 할당할 인자를 받으면 어떨까요? |
||
|
||
private void shuffle(){ | ||
Collections.shuffle(numList); | ||
} | ||
|
||
private void sort(){ | ||
Collections.sort(this.lottoNumberList); | ||
} | ||
|
||
public List<Integer> getLottoNumberList() { | ||
return this.lottoNumberList; | ||
} | ||
|
||
public long getMatchCount(List<Integer> winningNumbers){ | ||
return lottoNumberList.stream() | ||
.filter(val -> winningNumbers.contains(val)) | ||
.count(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package lotto.domain; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public enum MatchInfo { | ||
MATCH_SIX(6, 2000000000) | ||
, MATCH_FIVE(5, 1500000) | ||
, MATCH_FOUR(4, 50000) | ||
, MATCH_THREE(3, 5000) | ||
, OTHERS(0, 0); | ||
|
||
private final long count; | ||
private final int reward; | ||
|
||
MatchInfo(int count, int reward){ | ||
this.count = count; | ||
this.reward = reward; | ||
} | ||
|
||
public long getCount(){ | ||
return this.count; | ||
} | ||
|
||
public int getReward(){ | ||
return this.reward; | ||
} | ||
|
||
public static MatchInfo checkMatch(long count){ | ||
return Arrays.stream(MatchInfo.values()) | ||
.filter(matchInfo -> matchInfo.count == count) | ||
.findFirst() | ||
.orElse(OTHERS); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package lotto.domain; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class MyLotto { | ||
private static int LOTTO_PRICE = 1000; | ||
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. 공유하는 자원을 변경하면 어떤 이슈가 발생할까요? |
||
private List<Lotto> lottoList = new ArrayList<>(); | ||
|
||
public MyLotto(int money){ | ||
for(int i=0; i<money/LOTTO_PRICE; i++){ | ||
lottoList.add(new Lotto()); | ||
} | ||
} | ||
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. 모든 클래스의 생성자에 로직이 있네요 |
||
|
||
public List<Lotto> getLottoList() { | ||
return lottoList; | ||
} | ||
|
||
public PrizeResult getResult(List<Integer> winningNumbers){ | ||
PrizeResult prizeResult = new PrizeResult(); | ||
for(Lotto lotto : lottoList){ | ||
prizeResult.addPrizeResult(matchResult(winningNumbers, lotto)); | ||
} | ||
|
||
return prizeResult; | ||
} | ||
|
||
private MatchInfo matchResult(List<Integer> winningNumbers, Lotto lotto){ | ||
return MatchInfo.checkMatch(lotto.getMatchCount(winningNumbers)); | ||
} | ||
Comment on lines
+20
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. 단위 테스트가 누락되었네요 |
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,30 @@ | ||||||||||||||||||||||
package lotto.domain; | ||||||||||||||||||||||
|
||||||||||||||||||||||
import java.util.HashMap; | ||||||||||||||||||||||
import java.util.Map; | ||||||||||||||||||||||
|
||||||||||||||||||||||
public class PrizeResult { | ||||||||||||||||||||||
private final Map<MatchInfo, Integer> prizeResultInfoList = new HashMap<>(); | ||||||||||||||||||||||
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. HashMap 대신 EnumMap 을 활용해 보셔도 좋을 것 같아요 |
||||||||||||||||||||||
|
||||||||||||||||||||||
public PrizeResult(){ | ||||||||||||||||||||||
for(MatchInfo matchInfo : MatchInfo.values()){ | ||||||||||||||||||||||
prizeResultInfoList.put(matchInfo, 0); | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
Comment on lines
+9
to
+13
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 addPrizeResult(MatchInfo matchInfo){ | ||||||||||||||||||||||
prizeResultInfoList.put(matchInfo, prizeResultInfoList.get(matchInfo)+1); | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
public Map<MatchInfo, Integer> getPrizeResultInfoList(){ | ||||||||||||||||||||||
return prizeResultInfoList; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
public double getEarnRate(int inputMoney){ | ||||||||||||||||||||||
int income = prizeResultInfoList.entrySet() | ||||||||||||||||||||||
.stream() | ||||||||||||||||||||||
.mapToInt(matchInfoIntegerEntry -> matchInfoIntegerEntry.getKey().getReward() * matchInfoIntegerEntry.getValue()) | ||||||||||||||||||||||
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. 스트림 내부에서의 변수 명도 의미있게 작성해 보시면 좋을 것 같아요 |
||||||||||||||||||||||
.sum(); | ||||||||||||||||||||||
return (double) income/inputMoney; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package lotto.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 INPUT_MESSAGE_OF_PURCHASE_AMOUNT = "구입금액을 입력해 주세요."; | ||
private static final String INPUT_MESSAGE_OF_WINNING_NUMBER = "지난 주 당첨 번호를 입력해 주세요."; | ||
private static final String SEPARATOR = ", "; | ||
private static final Scanner scanner = new Scanner(System.in); | ||
|
||
public static int inputPurchaseAmount(){ | ||
System.out.println(INPUT_MESSAGE_OF_PURCHASE_AMOUNT); | ||
return Integer.parseInt(scanner.nextLine()); | ||
} | ||
|
||
public static List<Integer> inputWinningNumbers(){ | ||
System.out.println(INPUT_MESSAGE_OF_WINNING_NUMBER); | ||
String numbers = scanner.nextLine(); | ||
return getWinningNumbers(numbers); | ||
} | ||
|
||
private static List<Integer> getWinningNumbers(String numbers){ | ||
return Arrays.asList(numbers.split(SEPARATOR)) | ||
.stream().mapToInt(Integer::parseInt) | ||
.boxed() | ||
.collect(Collectors.toList()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package lotto.view; | ||
|
||
import lotto.domain.Lotto; | ||
import lotto.domain.MatchInfo; | ||
import lotto.domain.MyLotto; | ||
import lotto.domain.PrizeResult; | ||
|
||
import java.util.Comparator; | ||
import java.util.List; | ||
|
||
public class ResultView { | ||
private static final String OUTPUT_MESSAGE_OF_PURCHASE_AMOUNT = "개를 구매했습니다."; | ||
private static final String OUTPUT_MESSAGE_OF_RESULT_START = "당첨 통계\n---------"; | ||
private static final String OUTPUT_FORMAT_OF_MATCHING = "%d개 일치 (%d원)- %d개\n"; | ||
private static final String OUTPUT_FORMAT_OF_RATE = "총 수익률은 %.2f입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)"; | ||
|
||
public static void printMyLottoList(MyLotto myLotto){ | ||
List<Lotto> lottoList = myLotto.getLottoList(); | ||
printAmount(lottoList.size()); | ||
for(Lotto lotto : lottoList){ | ||
System.out.println(lotto.getLottoNumberList()); | ||
} | ||
System.out.println(); | ||
} | ||
|
||
private static void printAmount(int amount){ | ||
StringBuilder builder = new StringBuilder(); | ||
builder.append(amount); | ||
builder.append(OUTPUT_MESSAGE_OF_PURCHASE_AMOUNT); | ||
System.out.println(builder); | ||
} | ||
|
||
public static void printLottoResult(PrizeResult prizeResult){ | ||
System.out.println(OUTPUT_MESSAGE_OF_RESULT_START); | ||
prizeResult.getPrizeResultInfoList().entrySet() | ||
.stream() | ||
.filter(matchInfoIntegerEntry -> !matchInfoIntegerEntry.getKey().equals(MatchInfo.OTHERS)) | ||
.sorted(Comparator.comparing(matchInfoIntegerEntry -> matchInfoIntegerEntry.getKey().getCount())) | ||
.forEach(matchInfoIntegerEntry -> printMatchResult(matchInfoIntegerEntry.getKey(), matchInfoIntegerEntry.getValue())); | ||
} | ||
|
||
private static void printMatchResult(MatchInfo matchInfo, Integer matchCount){ | ||
System.out.printf(OUTPUT_FORMAT_OF_MATCHING, matchInfo.getCount(), matchInfo.getReward(), matchCount); | ||
} | ||
|
||
public static void printEarnRate(PrizeResult prizeResult, int inputMoney){ | ||
System.out.printf(OUTPUT_FORMAT_OF_RATE, prizeResult.getEarnRate(inputMoney)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package calculator; | ||
|
||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.NullAndEmptySource; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
public class CalculatorTest { | ||
@DisplayName("빈 문자 혹은 공백 입력 테스트") | ||
@ParameterizedTest | ||
@NullAndEmptySource | ||
void emptyOrNullInputTest(String text){ | ||
assertThatThrownBy(() -> Calculator.calculate(text)) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@DisplayName("문자열 사칙연산 테스트") | ||
@Test | ||
void formulaTest(){ | ||
String formula = "2 + 3 * 4 / 2"; | ||
assertThat(Calculator.calculate(formula)).isEqualTo(10); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package calculator; | ||
|
||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public class OperatorTest { | ||
@DisplayName("단순 사칙연산 테스트") | ||
@Test | ||
void calculateTest(){ | ||
assertThat(Operator.PLUS.calculate(4, 2)).isEqualTo(6); | ||
assertThat(Operator.MINUS.calculate(4, 2)).isEqualTo(2); | ||
assertThat(Operator.MULTIPLE.calculate(4, 2)).isEqualTo(8); | ||
assertThat(Operator.DIVIDE.calculate(4, 2)).isEqualTo(2); | ||
} | ||
|
||
@DisplayName("나눗셈 결과 정수 여부 테스트") | ||
@Test | ||
void divideResultIntegerTest(){ | ||
assertThat(Operator.DIVIDE.calculate(5, 2)).isEqualTo(2); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package lotto; | ||
|
||
import lotto.domain.Lotto; | ||
import lotto.domain.MatchInfo; | ||
import lotto.domain.MyLotto; | ||
import lotto.domain.PrizeResult; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.RepeatedTest; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import java.util.*; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public class LottoTest { | ||
private static final int LOTTO_PRICE = 1000; | ||
private static final int LOTTO_NUMBER_COUNT = 6; | ||
|
||
@DisplayName("로또 1장 가격 1000원 및 금액에 해당하는 로또 발급 여부 테스트") | ||
@ParameterizedTest() | ||
@ValueSource(ints = {14000, 8000, 999, 2000}) | ||
void lottoCountTest(int money){ | ||
MyLotto myLotto = new MyLotto(money); | ||
assertThat(myLotto.getLottoList().size()).isEqualTo(money/LOTTO_PRICE); | ||
} | ||
Comment on lines
+21
to
+27
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. 테스트는 클래스별로 만들어 주세요 (MyLottoTest, MatchInfoTest) 테스트를 검증할 때 로직을 사용하지 마시고 명시된 값을 활용하면 어떨까요? |
||
|
||
@DisplayName("로또 중복 번호 존재 유무 테스트") | ||
@RepeatedTest(value = 10) | ||
void lottoNumberDuplicateTest(){ | ||
Lotto lotto = new Lotto(); | ||
assertThat(new HashSet<>(lotto.getLottoNumberList()).size()).isEqualTo(LOTTO_NUMBER_COUNT); | ||
} | ||
Comment on lines
+29
to
+34
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 객체가 중복되지 않는 6개 숫자를 가진다는 사실을 어떻게 알 수 있을까요? lotto를 생성할 때 5개, 7개 숫자를 주입한다거나, 중복된 숫자가 포하된 6개 숫자를 주입하면 객체 생성 시 예외가 발생함을 검증하면 어떨까요? |
||
|
||
@DisplayName("로또 번호 오름차순 정렬 유무 테스트") | ||
@RepeatedTest(value = 10) | ||
void lottoNumberSortingTest(){ | ||
Lotto lotto = new Lotto(); | ||
List<Integer> lottoNumberList = lotto.getLottoNumberList(); | ||
assertThat(lottoNumberList).allSatisfy(val ->{ | ||
int idx = lottoNumberList.indexOf(val); | ||
assertThat(Collections.max(lottoNumberList.subList(0, idx+1))).isEqualTo(val); | ||
}); | ||
} | ||
|
||
@DisplayName("로또 당첨 통계 테스트") | ||
@ParameterizedTest() | ||
@ValueSource(ints = {0, 1, 2, 3, 4, 5, 6}) | ||
void lottoMatchTest(int matchCount){ | ||
Lotto lotto = new Lotto(); | ||
List<Integer> winningNumbers = Arrays.asList(0, 0, 0, 0, 0, 0); | ||
for(int i=0; i<matchCount; i++){ | ||
winningNumbers.set(i, lotto.getLottoNumberList().get(i)); | ||
} | ||
assertThat(MatchInfo.checkMatch(lotto.getMatchCount(winningNumbers))) | ||
.isEqualTo(MatchInfo.checkMatch(matchCount)); | ||
} | ||
|
||
@DisplayName("로또 수익률 테스트") | ||
@ParameterizedTest() | ||
@ValueSource(ints = {14000, 8000, 999, 2000}) | ||
void lottoEarnRateTest(int inputMoney){ | ||
List<MatchInfo> matchInfoList = new ArrayList<>(); | ||
PrizeResult prizeResult = new PrizeResult(); | ||
for(int i=0; i<inputMoney/1000; i++){ | ||
int rand = (int) (Math.random()*7); | ||
MatchInfo matchInfo = MatchInfo.checkMatch(rand); | ||
matchInfoList.add(matchInfo); | ||
prizeResult.addPrizeResult(matchInfo); | ||
} | ||
|
||
int reward = matchInfoList.stream() | ||
.mapToInt(MatchInfo::getReward) | ||
.sum(); | ||
|
||
assertThat(prizeResult.getEarnRate(inputMoney)).isEqualTo((double) (reward/inputMoney)); | ||
} | ||
Comment on lines
+63
to
+78
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. |
||
} |
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.
객체별로 기능을 정리해 보셔도 좋을 것 같아요