-
Notifications
You must be signed in to change notification settings - Fork 2k
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
mvc 연습 #2135
base: main
Are you sure you want to change the base?
mvc 연습 #2135
Changes from all commits
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,13 @@ | ||
package lotto; | ||
|
||
import lotto.config.AppConfig; | ||
import lotto.controller.LottoController; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
AppConfig appConfig = new AppConfig(); | ||
LottoController lottoController = appConfig.lottoController(); | ||
lottoController.run(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package lotto.config; | ||
|
||
import lotto.controller.LottoController; | ||
import lotto.service.LottoService; | ||
import lotto.service.LottoServiceImpl; | ||
|
||
public class AppConfig { | ||
public LottoService lottoService(){ | ||
return new LottoServiceImpl(); | ||
}; | ||
|
||
public LottoController lottoController(){ | ||
return new LottoController(lottoService()); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package lotto.controller; | ||
|
||
import lotto.dto.LottoDto; | ||
import lotto.model.Lotto; | ||
import lotto.service.LottoService; | ||
import lotto.view.InputView; | ||
import lotto.view.OutputView; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class LottoController { | ||
private final LottoService lottoService; | ||
|
||
public LottoController(LottoService lottoService) { | ||
this.lottoService = lottoService; | ||
} | ||
|
||
public void run(){ | ||
int purchaseAmount = InputView.getPurchaseAmount(); | ||
int numberOfLottos = purchaseAmount/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. 컨트롤러에서 계산 로직이 있는것은 지양하는게 좋습니다 |
||
Lotto winningLotto = null; | ||
|
||
List<List<Integer>> lottoNumbersList = lottoService.generateLottoNumbers(numberOfLottos); | ||
OutputView.printPurchaseCount(numberOfLottos); | ||
OutputView.printLottoNumers(lottoNumbersList); | ||
|
||
while(true) { | ||
LottoDto winningNumbersDto = InputView.getWinningNumbers(); | ||
try { | ||
winningLotto = new Lotto(winningNumbersDto.getNumbers()); | ||
break; | ||
} catch (IllegalArgumentException e) { | ||
System.out.println("[ERROR] " + e.getMessage()); | ||
} | ||
} | ||
Comment on lines
+28
to
+36
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. 트라이 캐치를 컨트롤러에서만 하면돼 여기서 입력 검증을 할 수 있는 클래스를 호출하고 다음에 도메인 모델 검증을 하게 한다면 컨트롤러 내부에서만 재입력 처리를 해주면 돼 |
||
|
||
int bonusNumber = InputView.getBonusNumber(); | ||
|
||
Map<String, Integer> statistics = lottoService.calculateLotto(lottoNumbersList, winningLotto, bonusNumber); | ||
OutputView.printStatistics(statistics); | ||
|
||
double profitRate = lottoService.calculateProfitRate(purchaseAmount, statistics); | ||
OutputView.printProfitRate(profitRate); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package lotto.dto; | ||
|
||
import java.util.List; | ||
|
||
public class LottoDto { | ||
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. dto는 데이터가 이동할때 한번 감싸서 넘겨줘 이것은 나중에 할건데 |
||
private final List<Integer> numbers; | ||
|
||
public LottoDto(List<Integer> numbers) { | ||
this.numbers = numbers; | ||
} | ||
|
||
public List<Integer> getNumbers() { | ||
return numbers; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package lotto.model; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
public class Lotto { | ||
private final List<Integer> numbers; | ||
|
||
public Lotto(List<Integer> numbers) { | ||
validate(numbers); | ||
this.numbers = numbers; | ||
} | ||
|
||
private void validate(List<Integer> numbers) { | ||
if (numbers.size() != 6) { | ||
throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); | ||
} | ||
for (int num : numbers) { | ||
if (num < 1 || num > 45) { | ||
throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 합니다."); | ||
} | ||
} | ||
Set<Integer> uniqueNumbers = new HashSet<>(numbers); | ||
if (uniqueNumbers.size() != numbers.size()) { | ||
throw new IllegalArgumentException("로또 번호에는 중복이 존재하지 않아야 합니다."); | ||
} | ||
} | ||
|
||
public List<Integer> getNumbers() { | ||
return numbers; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package lotto.service; | ||
|
||
import lotto.model.Lotto; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public interface LottoService { | ||
List<List<Integer>> generateLottoNumbers(int numberOfLottos); | ||
Map<String, Integer> calculateLotto(List<List<Integer>> lottoNumbers, Lotto winningLotto, int bonusNumber); | ||
double calculateProfitRate(int purchaseAmount, Map<String, Integer> lottoNumberMap); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,77 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
package lotto.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
import camp.nextstep.edu.missionutils.Randoms; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import lotto.model.Lotto; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.ArrayList; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.HashMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.Map; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
/* 실제 LottoService 기능 구현*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
public class LottoServiceImpl implements LottoService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||
public List<List<Integer>> generateLottoNumbers(int numberOfLottos) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
List<List<Integer>> lottoNumbersList = new ArrayList<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
for (int i = 0; i < numberOfLottos; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
List<Integer> lottoNumbers = Randoms.pickUniqueNumbersInRange(1, 45, 6); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbers.sort(Integer::compareTo); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersList.add(lottoNumbers); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
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. 불변 객체를 sorted 하고 있어서 문제가 발생하고 있음
Suggested change
불변 객체를 가변 객체로 만들어 주면 통과~ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return lottoNumbersList; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||
public Map<String, Integer> calculateLotto(List<List<Integer>> lottoNumbers, Lotto winningLotto, int bonusNumber){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Map<String, Integer> lottoNumbersMap = new HashMap<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("3개 일치", 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("4개 일치", 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("5개 일치", 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("5개 일치, 보너스 볼 일치", 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("6개 일치", 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
for (List<Integer> lottoNumber : lottoNumbers) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
int matchCount = getMatchCount(lottoNumber, winningLotto.getNumbers()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
boolean bonusMatch = lottoNumber.contains(bonusNumber); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
if (matchCount == 6) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("6개 일치", lottoNumbersMap.get("6개 일치") + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (matchCount == 5 && bonusMatch) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("5개 일치, 보너스 볼 일치", lottoNumbersMap.get("5개 일치, 보너스 볼 일치") + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (matchCount == 5) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("5개 일치", lottoNumbersMap.get("5개 일치") + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (matchCount == 4) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("4개 일치", lottoNumbersMap.get("4개 일치") + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (matchCount == 3) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lottoNumbersMap.put("3개 일치", lottoNumbersMap.get("3개 일치") + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+37
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. 미션 요구 사항에 있는거긴 한데 else if를 최대한 지양 하여야해 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return lottoNumbersMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+37
to
+49
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
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+25
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. 해당 내용은 도메인 로직으로 이동 시켜야 할것 같아 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
private int getMatchCount(List<Integer> lottoNumber, List<Integer> winningNumbers) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
int matchCount = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
for (int number : lottoNumber) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
if(winningNumbers.contains(number)) matchCount++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return matchCount; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||
public double calculateProfitRate(int purchaseAmount, Map<String, Integer> lottoNumberMap) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
int totalWinningAmount = calculateTotalWinningAmount(lottoNumberMap); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return (double) totalWinningAmount / purchaseAmount; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+60
to
+65
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. 수익률 계산이 잘못 되고 있어 전체 수악/사용 금액 * 100 이 되어야 수익률이 정상적으로 작동돼 또한 수익률을 담당하는 도메인 클래스로 따로 분리하는게 좋아보여 서비스 로직과 도메인 로직의 차이를 이해하는게 좋을것 같아 서비스 로직에서는 도메인 로직과 애플리케이션 계층 간의 조정 및 흐름 제어를 처리하는곳으로 나중에 디비 까지 쓴다면 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
private int calculateTotalWinningAmount(Map<String, Integer> statistics) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
int totalAmount = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
totalAmount += statistics.get("3개 일치") * 5000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
totalAmount += statistics.get("4개 일치") * 50000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
totalAmount += statistics.get("5개 일치") * 1500000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
totalAmount += statistics.get("5개 일치, 보너스 볼 일치") * 30000000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
totalAmount += statistics.get("6개 일치") * 2000000000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+61
to
+73
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 totalAmount; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package lotto.view; | ||
|
||
import camp.nextstep.edu.missionutils.Console; | ||
import lotto.dto.LottoDto; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
|
||
public class InputView { | ||
/* 구입 금액 입력 */ | ||
public static int getPurchaseAmount() { | ||
while (true) { | ||
try { | ||
System.out.println("구입 금액을 입력해주세요."); | ||
String input = Console.readLine(); | ||
validatePurchaseAmount(input); | ||
return Integer.parseInt(input); | ||
} catch (IllegalArgumentException e) { | ||
System.out.println("[ERROR] " + e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
private static void validatePurchaseAmount(String purchaseAmount) { | ||
try { | ||
int amount = Integer.parseInt(purchaseAmount); | ||
if (amount <= 0) { | ||
throw new IllegalArgumentException("구매 금액은 0보다 커야 합니다."); | ||
} | ||
if (amount % 1000 != 0) { | ||
throw new IllegalArgumentException("구매 금액은 1000 단위로 나누어 떨어져야 합니다."); | ||
} | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("구매 금액은 숫자여야 합니다."); | ||
} | ||
Comment on lines
+26
to
+36
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. validation 은 크게 두가지로 나뉘어 입력단계 검증과 도메인 단계 검증 |
||
} | ||
|
||
/* 당첨 금액 입력 */ | ||
public static LottoDto getWinningNumbers(){ | ||
while (true) { | ||
try { | ||
System.out.println("\n당첨 번호를 입력해주세요."); | ||
String inputWinningNumbers = Console.readLine(); | ||
List<Integer> numbers = parseWinningNumbers(inputWinningNumbers); | ||
return new LottoDto(numbers); | ||
} catch (IllegalArgumentException e) { | ||
System.out.println("[ERROR] " + e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
private static List<Integer> parseWinningNumbers(String inputWinningNumbers) { | ||
String[] numberStrings = inputWinningNumbers.split(","); | ||
List<Integer> numbers = new ArrayList<>(); | ||
|
||
try { | ||
for (String numberString : numberStrings) { | ||
numbers.add(Integer.parseInt(numberString.trim())); | ||
} | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("로또 번호는 숫자여야 합니다."); | ||
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 numbers; | ||
} | ||
|
||
/* 보너스 번호 입력 */ | ||
public static int getBonusNumber(){ | ||
while (true) { | ||
try { | ||
System.out.println("\n보너스 번호를 입력해주세요."); | ||
String input = Console.readLine(); | ||
int bonusNumber = Integer.parseInt(input.trim()); | ||
if (bonusNumber < 1 || bonusNumber > 45) { | ||
throw new IllegalArgumentException("보너스 번호는 1과 45 사이의 숫자여야 합니다."); | ||
} | ||
return Integer.parseInt(input.trim()); | ||
} catch (IllegalArgumentException e) { | ||
System.out.println("[ERROR] " + e.getMessage()); | ||
} | ||
} | ||
Comment on lines
+69
to
+82
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,34 @@ | ||
package lotto.view; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class OutputView { | ||
/* 로또 구입 개수 출력 */ | ||
public static void printPurchaseCount(int numberOfLottos){ | ||
System.out.println("\n"+numberOfLottos+"개를 구매했습니다."); | ||
} | ||
|
||
/* 로또 번호 출력 */ | ||
public static void printLottoNumers(List<List<Integer>> lottoNumbers){ | ||
for (List<Integer> numbers : lottoNumbers) { | ||
System.out.println(numbers); | ||
} | ||
} | ||
|
||
/* 당첨 통계 출력 */ | ||
public static void printStatistics(Map<String, Integer> statistics) { | ||
System.out.println("\n당첨 통계"); | ||
System.out.println("---"); | ||
System.out.println("3개 일치 (5,000원) - " + statistics.get("3개 일치") + "개"); | ||
System.out.println("4개 일치 (50,000원) - " + statistics.get("4개 일치") + "개"); | ||
System.out.println("5개 일치 (1,500,000원) - " + statistics.get("5개 일치") + "개"); | ||
System.out.println("5개 일치, 보너스 볼 일치 (30,000,000원) - " + statistics.get("5개 일치, 보너스 볼 일치") + "개"); | ||
System.out.println("6개 일치 (2,000,000,000원) - " + statistics.get("6개 일치") + "개"); | ||
} | ||
|
||
/* 수익률 출력 */ | ||
public static void printProfitRate(double profitRate) { | ||
System.out.printf("총 수익률은 %.1f%%입니다.\n", profitRate); | ||
} | ||
} |
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.
컨트롤러는 서비스 뿐만 아니라 view또한 외부 주입 받아야 하나 현재 의존성 주입이 안되고 있으
그냥 static 으로 열어버리는걸 지양해야해!