Skip to content
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 로또(자동) 피드백부탁드립니다~ #3244

Open
wants to merge 3 commits into
base: so-junhyeok
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,18 @@
* method가 한 가지 일만 하도록 최대한 작게 만들어라.
* else를 사용하지 마라.

## 기능정의
## 기능정의(문자열 계산기)
* 문자열 입력 기능
* 공백으로 연산 대상 구분
*
* 사칙연산 실행
* 계산식/결과 출력
* 계산식/결과 출력

## 기능정의(로또)
* 구매 금액
- 금액 입력
- 숫자 유효성 체크
* 로또 구매 개수 구하기
* 로또번호 만들기
* 당첨번호 입력
* 당첨통계
24 changes: 24 additions & 0 deletions src/main/java/lotto/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package lotto;

import lotto.domain.Lotto;
import lotto.domain.LottoStatistics;
import lotto.view.InputView;
import lotto.view.ResultView;

import java.util.List;

public class Main {
static InputView inputView = new InputView();
static ResultView resultView = new ResultView();
static Lotto lotto = new Lotto();

public static void main(String[] args) {
int lottoQuantity = lotto.lottoQuantity(inputView.inputCost());
resultView.lottoCountPrint(lottoQuantity);
List<List<Integer>> purchasedLottery = lotto.getPurchasedLottery(lottoQuantity);
resultView.printLotto(purchasedLottery);

LottoStatistics lottoStatistics = new LottoStatistics(inputView.inputWinningNumber());
resultView.winningResult(lottoStatistics.winningRank(purchasedLottery));
}
}
55 changes: 55 additions & 0 deletions src/main/java/lotto/domain/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package lotto.domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class Lotto {

Choose a reason for hiding this comment

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

Lotto는 1-45사이의 6개의 숫자를 가져야 합니다. winningNumber도 동일하구요.

지금 Lotto 클래스는 이 로또라는 규칙을 잘 표현하고 있지 않습니다. 로또를 만들기 위한 LottoFactory에 가까워 보여요. List<Integer>를 사용하기 보다는 로또의 특성을 가지는 Lotto 클래스를 만들어보시면 좋겠습니다.


static final String regularExpression = "^[0-9]+$";
static final List<Integer> lottoNumber = new ArrayList<>();

static {
for (int i = 0; i < 45; i++) {
lottoNumber.add(i+1);
}
}

List<List<Integer>> purchasedLottery = new ArrayList<List<Integer>>();

Boolean integerValidation(String amount){
return amount.matches(regularExpression);
}

public int lottoQuantity(String amount) {
if (integerValidation(amount)) {
return Integer.valueOf(amount) / 1000;
}
return 0;
}

List<Integer> outputLottoNumber(){
List<Integer> result = new ArrayList<>();
Collections.shuffle(lottoNumber);

for (int i = 0; i < 6; i++) {
result.add(lottoNumber.get(i));
}
Comment on lines +36 to +38

Choose a reason for hiding this comment

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

subList를 활용해볼 수 있을 것 같아요.

Comment on lines +36 to +38

Choose a reason for hiding this comment

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

대부분 for loop를 사용해주셨는데요. Stream을 쓸 수 있는 상황에서는 for loop의 사용을 지양하고 Stream을 활용해보시면 좋겠습니다.

return result;
}

void buyLotto(int lottoQuantity){
for (int i = 0; i < lottoQuantity; i++) {
List<Integer> lotto = outputLottoNumber();
Collections.sort(lotto);
purchasedLottery.add(lotto);
}
}
public List<List<Integer>> getPurchasedLottery(int lottoQuantity){
buyLotto(lottoQuantity);
return purchasedLottery;
}


}
82 changes: 82 additions & 0 deletions src/main/java/lotto/domain/LottoStatistics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package lotto.domain;

import stringCalculator.domain.Arithmetic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LottoStatistics {

List<Integer> winningNumber = new ArrayList<>();

Choose a reason for hiding this comment

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

위에서 Lotto의 특성을 갖는 클래스를 추출해보라고 말씀드렸는데요. 이를 활용해 WinningNumber 클래스를 만들어보세요.

상속 혹은 컴포지션을 쓸 수 있을 것 같은데요, 컴포지션을 사용해보시고 상속 대비 어떤 이점이 있는지도 한번 찾아보세요.


static Map<Integer, Rank> rankCount = new HashMap<>();

static {
rankCount.put(6, Rank.FIRST);
rankCount.put(5, Rank.SECOND);
rankCount.put(4, Rank.THIRD);
rankCount.put(3, Rank.FOURTH);
}
Comment on lines +14 to +21

Choose a reason for hiding this comment

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

Rank 자체에 몇개가 일치하는지에 대한 정보가 포함되어 있는데요. 6, 5, 4, 3을 키로 할 이유가 있을까요~?

Choose a reason for hiding this comment

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

Map<Rank, Integer> 형태로 사용하는게 좀 더 적절하지 않을까 하는 생각이 듭니다.


public LottoStatistics(){}

public LottoStatistics(String winningNumber){
saveWinningNumber(winningNumber);
}
private void saveWinningNumber(String winningNumber){
for (String number : winningNumberArray(winningNumber)){
this.winningNumber.add(Integer.valueOf(number));
}
}
private String[] winningNumberArray(String winningNumber){
if(!validationWinningNumber(winningNumber)){
new Exception("입력값이 유효하지 않습니다.");
};
return winningNumber.split(",");
}
private Boolean validationWinningNumber(String winningNumber){
return winningNumber.split(",").length == 6;
}
Comment on lines +28 to +41

Choose a reason for hiding this comment

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

LottoStatistics에서 로또 결과값 카운팅, winningNumber 관련된 책임까지 가지면 너무 많은 책임을 가지게 되지 않을까요?

이름 그대로 로또 결과값 카운팅에 대한 책임만 가지고 winningNumber와 관련된 책임은 분리하면 어떨까요?


public int sameNumberQuantity(List<Integer> lottoNumber){
int count = 0;
for (int number : lottoNumber){
count = count + sameNumberIncrease(number);
}
return count;
}

private int sameNumberIncrease(int number){
if(this.winningNumber.contains(number)){

Choose a reason for hiding this comment

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

어떤 코드는

for (

어떤 코드는 아래와 같이 일관성이 없습니다.

if(

IDE의 자동 정렬 기능을 활용하시고 조금 더 꼼꼼하게 코드를 작성해주세요.

return 1;
};
return 0;
}

public Float winningRank(List<List<Integer>>lottoNumber){

Choose a reason for hiding this comment

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

Lotto 클래스를 추출하셨으면 List<Integer>가 아닌 Lotto 클래스를 활용해주세요.

Choose a reason for hiding this comment

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

스페이스 간격이 빠져 있네요. IDE의 자동 정렬 기능을 활용하시고 조금 더 꼼꼼하게 코드를 작성해주세요.

addRankQuantity(lottoNumber);
return Float.valueOf(winningAmount()/(lottoNumber.size()*1000));
}

void addRankQuantity(List<List<Integer>> lottoNumber) {
for (int i = 0; i < lottoNumber.size(); i++) {
checkWinningRank(lottoNumber, i);
}
}
int winningAmount(){
int amount = 0;
for (Rank rank : Rank.values()) {
amount = amount + rank.getTotelMoney();
}
return amount;
}
private void checkWinningRank(List<List<Integer>> lottoNumber, int i) {
if(sameNumberQuantity(lottoNumber.get(i)) >= 3){
rankCount.get(sameNumberQuantity(lottoNumber.get(i))).addCount();
}
}
Comment on lines +63 to +79

Choose a reason for hiding this comment

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

for loop 없이 이 로직을 Stream의 groupingBy와 Function.identity를 활용해서 구해볼 수 있을 것 같네요. 한번 학습해보시면 좋겠습니다.



}
38 changes: 38 additions & 0 deletions src/main/java/lotto/domain/Rank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package lotto.domain;

public enum Rank {

FIRST(6, 2000000000, 0),
SECOND(5, 1500000, 0),
THIRD(4, 5000, 0),
FOURTH(3, 5000, 0),
MISS(0, 0, 0);

private int match;
private int money;
private int count;

private Rank(int match, int money, int count){
this.match = match;
this.money = money;
this.count = count;
}

public void addCount(){
count++;
}
Comment on lines +21 to +23

Choose a reason for hiding this comment

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

enum에 이렇게 프로퍼티를 넣고 값을 증가시키거나 하는 로직의 구현은 피해주세요.

이렇게 사용하면 좋지 않은 이유와 이렇게 구현하면 여러 로또 게임에 대한 결과 집계를 할 수 있을지에 대해서 상수의 특성을 고려해 고민해보시면 좋겠습니다.


public int getCount(){
return count;
}

public int getMoney(){
return money;
}

public int getTotelMoney(){
return money * count;
}


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

import java.util.Scanner;

public class InputView {

public String inputCost(){
System.out.println("구입금액을 입력해주세요");
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}

public String inputWinningNumber(){
System.out.println("지난 주 당첨 번호를 입력해 주세요.");
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}

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

import lotto.domain.Rank;

import java.util.List;

public class ResultView {
public void lottoCountPrint(int lottoQuantity){
System.out.println(lottoQuantity+"개를 구매했습니다.");
}

public void printLotto(List<List<Integer>> lotto){

for (List<Integer> lottoNumber : lotto){
System.out.print("[");
printLottoNumber(lottoNumber);
System.out.println("]");
}
}

public void printLottoNumber(List<Integer> lottoNumber){
for (int i = 0; i < lottoNumber.size(); i++) {
System.out.print(addComma(i)+lottoNumber.get(i));
}
}

String addComma(int index){
if(index != 0){
return ",";
}
return "";
}

public void winningResult(Float revenue){
System.out.println("6개일치"+"("+Rank.FIRST.getMoney()+")- "+Rank.FIRST.getCount());
System.out.println("5개일치"+"("+Rank.SECOND.getMoney()+")- "+Rank.SECOND.getCount());
System.out.println("4개일치"+"("+Rank.THIRD.getMoney()+")- "+Rank.THIRD.getCount());
System.out.println("3개일치"+"("+Rank.FOURTH.getMoney()+")- "+Rank.FOURTH.getCount());
System.out.println("");
String result = String.format("%.2f", revenue);

System.out.println("총 수익률은 "+result+"입니다");

}
}
63 changes: 63 additions & 0 deletions src/test/java/lotto/domain/LottoStatisticsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package lotto.domain;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.beans.Transient;
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
public class LottoStatisticsTest {

List<List<Integer>> lottoNumber = new ArrayList<>();
@BeforeEach
private void lotto(){
List<Integer> number = new ArrayList<>();
for (int i = 1; i < 7; i++) {
number.add(i);
}
lottoNumber.add(number);
}


@Test
@DisplayName("로또 당첨번호 포함 여부")
public void test1(){

List<Integer> lottoNumber = new ArrayList<>();
lottoNumber.add(1);
lottoNumber.add(2);

LottoStatistics lottoStatistics = new LottoStatistics("1,2,3,4,5,6");
assertThat(lottoStatistics.sameNumberQuantity(lottoNumber)).isEqualTo(2);
}

@Test
@DisplayName("일치한 로또 COUNT")
public void test2(){
Rank.FIRST.addCount();
assertThat(Rank.FIRST.getCount()).isEqualTo(1);
Rank.FIRST.addCount();
assertThat(Rank.FIRST.getCount()).isEqualTo(2);
}

@Test
@DisplayName("당첨 금액")
public void test3(){
LottoStatistics lottoStatistics = new LottoStatistics("1,2,3,4,5,7");
lottoStatistics.winningRank(lottoNumber);
assertThat(lottoStatistics.winningAmount()).isEqualTo(1500000);

}

@Test
@DisplayName("로또 수익률")
public void test4(){
LottoStatistics lottoStatistics = new LottoStatistics("1,2,3,7,8,9");
assertThat(lottoStatistics.winningRank(lottoNumber)).isEqualTo(5);
}

}
39 changes: 39 additions & 0 deletions src/test/java/lotto/domain/LottoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package lotto.domain;

import lotto.domain.Lotto;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
public class LottoTest {

@Test
@DisplayName("정수입력 테스트")
public void test1(){
Lotto lotto = new Lotto();
assertThat(lotto.integerValidation("140000")).isTrue();
assertThat(lotto.integerValidation("14,0000")).isFalse();
}

@Test
@DisplayName("로또 구매 수량")
public void test2(){
Lotto lotto = new Lotto();
assertThat(lotto.lottoQuantity("14000")).isEqualTo(14);
}

@Test
@DisplayName("로또 번호 뽑기")
public void test3(){
Lotto lotto = new Lotto();
assertThat(lotto.outputLottoNumber().size()).isEqualTo(6);
}

@Test
@DisplayName("총 구매 로또 수")
public void test4(){
Lotto lotto = new Lotto();
assertThat(lotto.getPurchasedLottery(2).size()).isEqualTo(2);

}

}