Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/main/java/FlowController
Copy link

Choose a reason for hiding this comment

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

패키지 구조 유의해주세요

Copy link

Choose a reason for hiding this comment

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

컨트롤러가 너무 담당하는 일이 많고, 협력 객체를 직접 생성하고 있기 때문에 결합도가 너무 높습니다.
컨트롤러는 단순히 view와 model을 연결해 주는 곳이라고 생각하시면 됩니다. 유효성 검사가 컨트롤러에 있을 필요가 있을지 생각해 보시는게 좋을 것 같습니다!
AppConfig를 사용하셔서 담당하는 일을 줄이고, DI(생성자 주입)를 사용하셔보시기 바랍니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package controller;

import domain.model.BunchOfLotties;
import domain.service.Calculator;
import domain.service.Validator;
import domain.model.Lotto;
import domain.model.User;
import domain.model.WinningLotto;
import view.Input;
import view.Output;

import java.util.List;

public class FlowManager {
private final Input input = new Input();
private final Output output = new Output();
private final Validator validator = new Validator();
private final User user = new User();
private final Calculator calculator = new Calculator();
private final BunchOfLotties bunchOfLotties = new BunchOfLotties();


public void Start(){
// 금액 입력 -> 검증 -> 개수 계산 -> 로또 생성 -> 유저가 로또 리스트를 가짐.
output.printAskPrice();
int inputMoney = input.readInputMoney();
validator.validateAmountOfMoney(inputMoney);
int lottoCount = calculator.getLottoCountByMoney(inputMoney);
List<Lotto> lottoList = bunchOfLotties.createLottoList(lottoCount);
user.setLottoList(lottoList);

output.printAskNumbers();
List<Integer> winningNumbers = input.readLottoNumbers();
validator.validateNumbers(winningNumbers); // 당첨 넘버 받고, 검증.

output.printAskBonusNumber();
int bonusNumber = input.readBonusNumber();
validator.validateBonusNumber(bonusNumber,winningNumbers); // 보너스 넘버 받고, 검증.

output.printLotties(lottoList); //생성된 로또 리스트를 보여줌.

WinningLotto winningLotto = new WinningLotto(winningNumbers, bonusNumber);
user.checkMatchingNumbers(winningLotto); // winningLotto와 체크하고 count를 센다.
output.printMatchingResult(user.getThreeNumberMatchingLottoCount(), user.getFourNumberMatchingLottoCount(), user.getFiveNumberMatchingLottoCount(), user.getWinningLottoCount());

double profitability = calculator.getProfitablity(inputMoney,user.getThreeNumberMatchingLottoCount(), user.getFourNumberMatchingLottoCount(), user.getFiveNumberMatchingLottoCount(), user.getWinningLottoCount());
output.printProfitability(profitability);
}
}
79 changes: 79 additions & 0 deletions src/main/java/READ ME.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
## 입력:
로또 금액: 1000원 단위, 나누어 떨어지지 않으면 예외 처리
당첨 금액: 6개(", "으로 구분) + 1개

## 출력:
로또 수량
로또 번호 정렬해서 보여주기

당첨내역 출력
수익률 출력

## RULE:: 내 state를 남이 건드리면 안돼!

# 구현하고 싶은 기능들.
* 금액 입력 받기 (개수 자동 계산) [Input]

-> validation check: 1000원 단위?[validator]

* 로또 Winning 번호 입력 받기 + 보너스 넘버도.[Input]

-> Check validation: 개수/중복/범위 [validator]
-> 입력한 값들 오름차순으로 정렬 []

* Lotto 생성(사용자 입력도 고려) []

-> 1-45 무작위 생성 [RandomNumberCreator]
-> 오름차순 정렬 *** 얘가 문제인데, 많이 쓰이는 기능임. but lotto의 내부의 값을 건드리는 거라서 외부 클래스를 두는 것은 적절하지 않아. [Lotto]
-> Check validation: 개수/중복/범위 [Lotto]

* 사용자 로또 <-> Winning Lotto 비교
-> 일치 개수 비교

* 사용자 당첨 금액 계산



* 수익률 계산
-> 당첨금액 / 소비 금액
-------------
## FLOW
1. input 사실상 개수 + winning number
2. validate
3. input에 맞는 로또 생성 (User에!!) with RandomNumberCreator + WinningNumber에 사용자 입력 + bonus number 저장.
4. Winning Number <-> User Number랑 비교! (어디서...??)
5. 비교 결과를 바탕으로 수익 계산 + 수익률 계산
6. 수익률 출력

## Lotto Class


---------------------------------

## 배운 내용:

* public static final int => #define과 거의 유사!
* List 활용법
1) 정의: import java.util.List; + List< type> name; 이런 식으로 정의

* 겹치지 않고 정수 리스트 생성법
1) 가장 단순한 방법: 랜덤으로 숫자 생성 -> 기존의 리스트와 비교해서 없으면 ok 아니면 다시! count 세서 원하는 만큼 while loop
2) set이용!
set으로 랜덤 넘버 생성 -> list로 변환
import java.util.Set;

Set<Integer> uniqueNumbers = new HashSet<>();
int min = 1;
int max = 45;
count = 6;

while(uniqueNumebr.size() < count){
int num = random.nextInt(max - min +1) + min;
uniqueNubers.add(num);
}

List<Integer> list = new ArrayList<uniqueNumbers>
3) 오름차순 정렬방법
- Collections.sort( list );

// 내부 list를 자체로 바꿈. 즉, return하는 것이 아니고 리스트의 값들에 접근해서 순서를 바꾸고 영구적으로 저장함.
16 changes: 16 additions & 0 deletions src/main/java/User_checkMatchingNumbers
Copy link

Choose a reason for hiding this comment

The 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,16 @@
public void checkMatchingNumbers(WinningLotto winningLotto) {
List<Integer> totalList = winningLotto.getTotalNumbers();
for(Lotto lotto : lottoList){
if (lotto.getSameNumberCount(totalList) == 3){
threeNumberMatchingLottoCount++;
}
else if (lotto.getSameNumberCount(totalList) == 4){
fourNumberMatchingLottoCount++;
} else if (lotto.getSameNumberCount(totalList) == 5) {
fiveNumberMatchingLottoCount++;
}
else if (lotto.getSameNumberCount(totalList) == 6) {
winningLottoCount++;
}
}
}
14 changes: 14 additions & 0 deletions src/main/java/app/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package app;

import controller.FlowManager;

public class Application {

public static void main(String[] args) {

FlowManager flowManager = new FlowManager();
// TODO: 프로그램 구현
flowManager.Run();

}
Comment on lines +7 to +13
Copy link

Choose a reason for hiding this comment

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

AppConfig 에 대해서 공부하시면 좋을 것 같습니다!
"AppConfig 순수자바" 키워드로 검색 하시면 좋은 자료가 많아서 도움될거같아요!!

}
48 changes: 48 additions & 0 deletions src/main/java/controller/FlowManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// user없는 버전.

package controller;

import java.util.List;

import domain.model.BunchOfLotties;
import view.*;
import domain.service.*;
import domain.model.*;

public class FlowManager {
Copy link

Choose a reason for hiding this comment

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

흐름 관리자라는게 의인화 했을때 필요한지 조금 더 생각해 보시면 좋을 것 같습니다.
FlowContoller 가 상위 패키지에 있는데 contoller 패키지 안에 이 클래스가 있어야 되는 이유가 있을까요?

Copy link

Choose a reason for hiding this comment

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

똑같이 이것에도 너무 많은 역활이 부여되어 있습니다.
검증을 각 도메인 안으로 넣어서 책임을 분배해주시는게 저는 좋아보입니다!

private Input input = new Input();
private Output output = new Output();
private Validator validator = new Validator();
private Calculator calculator = new Calculator();

public void Run() {

output.printAskPrice(); // 묻고
int amountOfMoney = input.readInputMoney(); // 입력받고
validator.validateAmountOfMoney(amountOfMoney); // validation check

output.printAskWinningNumbers();
List<Integer> winningNumbers = input.readNumbers();
validator.validateNumbers(winningNumbers);

output.printAskBonusNumber();
int bonusNumber = input.readBonusNumber();

Choose a reason for hiding this comment

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

보너스 번호도 검사를 일부러 안하신건가요?

Copy link
Author

Choose a reason for hiding this comment

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

이 부분은 까먹었습니다ㅠㅠ

validator.validateBonusNumber(bonusNumber, winningNumbers);

int numberOfLotties = calculator.getLottoCountByMoney(amountOfMoney); // 지불 금액 -> 로또 개수로 변환.

BunchOfLotties lotties = new BunchOfLotties(numberOfLotties); // 로또 개수에 맞게 생성

WinningLotto winningLotto = new WinningLotto(winningNumbers, bonusNumber); // 당첨 로또도 생성함.


output.printLotties(lotties.getLottoList()); // 생성한 사용자의 로또들을 print.
List<Integer> winnerCounts = lotties.getWinningLottiesCounts(winningLotto);

output.printMatchingResult(winnerCounts);

double profitMargin = calculator.getProfitMargin(amountOfMoney,winnerCounts);
output.printProfitMargin(profitMargin);

}
}
66 changes: 66 additions & 0 deletions src/main/java/domain/model/BunchOfLotties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package domain.model;
import domain.service.LOTTOINFO;
import domain.service.WINNERCOUNT;
import util.RandomNumberCreator;

import java.util.ArrayList;
import java.util.List;

public class BunchOfLotties {
int lottiesCount;
RandomNumberCreator randomCreator = new RandomNumberCreator(); // 이걸 instance로 진짜 해야돼?

Choose a reason for hiding this comment

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

필드 주입을 하신 이유가 무엇인가요?

Copy link
Author

Choose a reason for hiding this comment

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

외부에서 전체적인 로직을 알 필요 없다고 생각해서 숨기려고 했습니다..!
randomCreator도 FlowManager에서 가지고 있다가 함수 파라미터로 넣어주는게 적절할까요?

Choose a reason for hiding this comment

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

오호 의존성 주입에 대한 개념을 아시나요??
의도 자체는 굉장히 좋은 것 같아요.
소프트웨어에서는 BunchOfLotties가 RandomCreator를 사용할 때 직접 고르는 것을 선호하지 않거든요!
현우멘토님이 보내신 AppConfig를 한번 보시면 좋을 것 같아요

Copy link
Author

Choose a reason for hiding this comment

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

넵!! 더 공부해보겠습니다..!!

List<Lotto> lottoList = new ArrayList<>();

public BunchOfLotties(int numOfLotties) {
lottoList = createLottoList(numOfLotties);
}

private List<Lotto> createLottoList(int numberOfLotties){
List<Lotto> lottoList = new ArrayList<>();
for(int i = 0; i < numberOfLotties; i++){
Lotto lotto = new Lotto(randomCreator.createRandomNumbers());
lottoList.add(lotto);
}
return lottoList;
}

public List<Lotto> getLottoList() {
return lottoList;
}

public List<Integer> getWinningLottiesCounts(WinningLotto winningLotto) {

List<Integer> winningLottiesCounts = new ArrayList<>();
List<Integer> winningLottoNumbers = winningLotto.getNumbers();

int[] winnerCount = new int[WINNERCOUNT.MAXWINNER];

for(int i = 0; i < lottoList.size(); i++){
if(lottoList.get(i).getSameNumberCount(winningLottoNumbers) == LOTTOINFO.MAX_LOTTO_COUNT)
{
winnerCount[WINNERCOUNT.WINNER]++;
}
else if (lottoList.get(i).getSameNumberCount(winningLottoNumbers) == LOTTOINFO.MAX_LOTTO_COUNT -1){
winnerCount[WINNERCOUNT.SECONDWINNER]++;
}
else if (lottoList.get(i).getSameNumberCount(winningLottoNumbers) == LOTTOINFO.MAX_LOTTO_COUNT -2){
winnerCount[WINNERCOUNT.THIRDWINNER]++;
}
else if (lottoList.get(i).getSameNumberCount(winningLottoNumbers) == LOTTOINFO.MAX_LOTTO_COUNT -3){
winnerCount[WINNERCOUNT.FOURTHWINNER]++;
}
else if (lottoList.get(i).getSameNumberCount(winningLottoNumbers) == LOTTOINFO.MAX_LOTTO_COUNT -4){
winnerCount[WINNERCOUNT.FIFTHWINNER]++;
}
Comment on lines +38 to +54
Copy link

Choose a reason for hiding this comment

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

미션 구현 항목 잘 읽어보시길 바랍니다.

}

for(int i =0; i < WINNERCOUNT.MAXWINNER; i++){
winningLottiesCounts.add(winnerCount[i]);
}

return winningLottiesCounts;
}



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

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

public class Lotto {
private final List<Integer> numbers;

public Lotto(List<Integer> numbers) {
this.numbers = numbers;
Collections.sort(numbers); // 정렬 함.
// this.type = Type.DEFAULT; // 굳이 type 필요한가?? 지금이 직관적인 듯....
}
Comment on lines +9 to +13
Copy link

Choose a reason for hiding this comment

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

로또 번호에 대한 검증이 없습니다.
외부에서 검증을 하더라도 번호가 생성될때 검증하는게 더 안전하다고 생각해요!


public int getSameNumberCount(List<Integer> winningNumbers) { // 외부에서 직접 체크를 하지말고 내부에서 체크하자. = lotto내부의 값들을 외부에서 들여다보는게 적절치X
int count = 0;
for(int i = 0; i < numbers.size(); i++) { // MAX_LOTTO_COUNT -> numbers.size()
if(winningNumbers.contains(numbers.get(i))) {
count++;
}
}

return count; //몇개가 같은지 내보내는 함수
}
Comment on lines +15 to +24
Copy link

Choose a reason for hiding this comment

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

메서드 명이 적절하지 않아보입니다.
무엇을 의미하는지 잘 모르겠어요


public List<Integer> getNumbers() {
return numbers;
}

public boolean hasBonusNumber(int bonusNum){
for(Integer number : numbers){
if(number == bonusNum){
return true;
}
}
return false;
}

// TODO: 추가 기능 구현
}
28 changes: 28 additions & 0 deletions src/main/java/domain/model/WinningLotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package domain.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class WinningLotto {
// lotto class를 모두가 갖고 있는건 종속성이 너무 강해진다.
Copy link

Choose a reason for hiding this comment

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

좋습니다.
하지만 지금 WinningLotto가 단순히 List를 받도록 되어 있어서
이 숫자들이 진짜 로또 번호인지에 대한 보장이 전혀 없습니다.
어떻게 하면 좋을까요?

private List<Integer> winningNumbers = new ArrayList<Integer>();
private int bonusNumber;

public WinningLotto(List<Integer> winningNumbers, int bonusNumber) {
this.winningNumbers = winningNumbers;
Collections.sort(winningNumbers);
this.bonusNumber = bonusNumber;
}

public List<Integer> getNumbers() {

return winningNumbers;
}

public int getBonusNumber() {
return bonusNumber;
}


}
18 changes: 18 additions & 0 deletions src/main/java/domain/service/Calculator.java
Copy link

Choose a reason for hiding this comment

The 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,18 @@
package domain.service;
import java.util.List;

public class Calculator {

public int getLottoCountByMoney(int money) {
return money / PRIZE.LOTTO_PRICE;
}

public double getProfitMargin(int originalMoney,List<Integer> winnerCount) {
int totalPrize = winnerCount.get(WINNERCOUNT.WINNER) * PRIZE.WINNING_PRIZE + winnerCount.get(WINNERCOUNT.SECONDWINNER) * PRIZE.SECOND_WINNER_PRIZE + winnerCount.get(WINNERCOUNT.THIRDWINNER) * PRIZE.THIRD_WINNER_PRIZE
+ winnerCount.get(WINNERCOUNT.THIRDWINNER) * PRIZE.FOURTH_WINNER_PRIZE + winnerCount.get(WINNERCOUNT.FIFTHWINNER) * PRIZE.FIFTH_WINNER_PRIZE;
double profitability = (double) totalPrize / originalMoney * 100; // %계산

return profitability;
}

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

public class ErrorMessage {
static String MONEY_RANGE = "Money must be in units of 1000.";
static String NUMBER_RANGE = "Numbers must be between 1 and 45.";
static String NUMBER_COUNT = "Numbers must be 6 different numbers.";
static String SAME_NUMBER = "Same numbers are not allowed.";
}
Copy link

Choose a reason for hiding this comment

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

8 changes: 8 additions & 0 deletions src/main/java/domain/service/LOTTOINFO.java
Copy link

Choose a reason for hiding this comment

The 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,8 @@
package domain.service;

public interface LOTTOINFO {
int MAX_NUMBER = 45;
int MIN_NUMBER = 1;

int MAX_LOTTO_COUNT = 6;
}
Loading