-
Notifications
You must be signed in to change notification settings - Fork 8
[로또] 김연서 미션 제출합니다. #8
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
base: main
Are you sure you want to change the base?
Changes from 11 commits
a213b57
6cd6c68
90bfcea
61b0277
e2e8d33
1d60f09
c82c2c2
2d9a8ba
099556a
9a0cb01
6d8da34
b12f110
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 +1,26 @@ | ||
| # java-lotto-precourse | ||
|
|
||
| # 기능 목록 | ||
|
|
||
| 1. 입출력 | ||
|
|
||
| - 입력 : 구입 금액, 당첨 번호 목록, 보너스 번호 | ||
| - 출력 : 구입한 로또 개수와 내용물, 당첨 개수와 수익 | ||
|
|
||
| 2. 로또 게임 관리자 | ||
|
|
||
| - 잘못된 입력 시 무한 루프 | ||
| - 입력, 처리 및 계산, 결과 출력 관장 | ||
|
|
||
| 3. 게임 관련 객체들 | ||
|
|
||
| - 로또(변경 제한), 게임, 플레이어 객체 | ||
|
|
||
| 4. 로또 게임 관련 계산 처리기 | ||
|
|
||
| - 로또 당첨 계산 | ||
| - 수익 계산 | ||
|
|
||
| 5. 예외처리 검증기 | ||
| 6. 출력 메세지 관리 | ||
| 7. 우승 종류 관리 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,17 @@ | ||
| package lotto; | ||
|
|
||
| import lotto.config.AppConfig; | ||
| import lotto.controller.LottoController; | ||
|
|
||
| public class Application { | ||
| static LottoController lottoController; | ||
|
|
||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| new Application().run(); | ||
| } | ||
|
|
||
| public void run() { | ||
| lottoController = AppConfig.getLottoController(); | ||
| lottoController.startGame(); | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package lotto.config; | ||
|
|
||
| import lotto.controller.LottoController; | ||
| import lotto.service.LottoService; | ||
| import lotto.view.LottoView; | ||
|
|
||
| public class AppConfig { | ||
| private static final LottoView lottoView = new LottoView(); | ||
| private static final LottoService lottoService = new LottoService(); | ||
|
|
||
| public static LottoController getLottoController() { | ||
| return new LottoController(lottoView, lottoService); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package lotto.controller; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Set; | ||
| import lotto.model.Game; | ||
| import lotto.model.Lotto; | ||
| import lotto.model.Player; | ||
| import lotto.service.LottoService; | ||
| import lotto.util.MajorErrorMessage; | ||
| import lotto.util.Validator; | ||
| import lotto.util.Validator.dataType; | ||
| import lotto.view.LottoView; | ||
|
|
||
| public class LottoController { | ||
| final LottoView lottoView; | ||
| final LottoService lottoService; | ||
|
|
||
|
|
||
| public void startGame() { | ||
| boolean buyContinue = true; | ||
| boolean setGameContinue = true; | ||
|
|
||
| while (buyContinue) { | ||
| buyContinue = buyStep(); | ||
| } | ||
| while (setGameContinue) { | ||
| setGameContinue = setGameStep(); | ||
| } | ||
|
|
||
| resultStep(); | ||
| } | ||
|
|
||
| public boolean buyStep() { | ||
| try { | ||
| Player player = setLottoMoney(); | ||
| attemptLottoPurchase(player); | ||
| lottoService.setPlayer(player); | ||
| return false; | ||
| } catch (IllegalArgumentException e) { | ||
| System.out.println(e.getMessage()); | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| public boolean setGameStep() { | ||
| try { | ||
| Game gameStep = setJackpot(); | ||
| gameStep = setBonus(gameStep); | ||
|
|
||
| lottoService.setGame(gameStep); | ||
| return false; | ||
| } catch (Exception e) { | ||
| System.out.println(MajorErrorMessage.LOTTONUM_WRONG.getMessage() + e.getMessage()); | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| public void resultStep() { | ||
| int[] lottoResultTypes = lottoService.calculateLottoResultType(); | ||
| float lottoResultProfitPercent = lottoService.calculateLottoResultProfit(lottoResultTypes); | ||
| lottoView.outputLottoResult(lottoResultTypes, lottoResultProfitPercent); | ||
| } | ||
|
|
||
| Player setLottoMoney() { | ||
| try { | ||
| String inputLine = lottoView.inputPurchaseMoney(); | ||
| return Player.setLottoMoney(Validator.isSingleInputType(inputLine, dataType.NUMBER)); | ||
|
Contributor
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. Validator가 값을 다시 뱉으니 가독성이 떨어지는 것 같아요!
Author
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. 글쿤요 따로 분리하겠슴다 |
||
| } catch (Exception e) { | ||
| throw new IllegalArgumentException(MajorErrorMessage.MONEY_WRONG.getMessage() + e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| void attemptLottoPurchase(Player player) { | ||
| try { | ||
| player.buyLotto(); | ||
| lottoView.outputPurchasedLottoNum(player.getPurchasedLottoNum()); | ||
| player.getPurchasedLottoList().forEach(lotto -> lottoView.outputPurchasedLottoDetail(lotto.getNumbers())); | ||
| } catch (Exception e) { | ||
| throw new IllegalArgumentException(MajorErrorMessage.LOTTONUM_WRONG.getMessage() + e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| Game setJackpot() { | ||
| String inputLine = lottoView.inputJackpotNumber(); | ||
| List<Integer> jackpotNumbers = Validator.isMultipleInputType(inputLine, dataType.NUMBER, ","); | ||
| Validator.isListItemInRange(Lotto.getLottoRangeStart(), Lotto.getLottoRangeEnd(), jackpotNumbers); | ||
| Set<Integer> jackpotNumberSet = Validator.isListItemDuplicated(jackpotNumbers); | ||
| return Game.setJackpot(jackpotNumberSet); | ||
| } | ||
|
|
||
| Game setBonus(Game game) { | ||
| String inputLine = lottoView.inputBonusNumber(); | ||
| int bonusNumber = Validator.isSingleInputType(inputLine, dataType.NUMBER); | ||
| game.setBonus(bonusNumber); | ||
| return game; | ||
| } | ||
|
|
||
| public LottoController(LottoView lottoView, LottoService lottoService) { | ||
| this.lottoView = lottoView; | ||
| this.lottoService = lottoService; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package lotto.model; | ||
|
|
||
| import java.util.Set; | ||
| import lotto.util.DetailErrorMessage; | ||
|
|
||
| public class Game { | ||
| private Set<Integer> jackpotNumbers; | ||
| private Integer bonus; | ||
|
|
||
| Game(Set<Integer> jackpotNumbers) { | ||
| this.jackpotNumbers = jackpotNumbers; | ||
| } | ||
|
|
||
| //static factory pattern | ||
| public static Game setJackpot(Set<Integer> jackpotNumbers) { | ||
| return new Game(jackpotNumbers); | ||
| } | ||
|
|
||
| public void setBonus(int bonus) { | ||
| if (jackpotNumbers.contains(bonus)) { | ||
| throw new IllegalArgumentException(DetailErrorMessage.DUPLICATED.getMessage()); | ||
| } | ||
| this.bonus = bonus; | ||
| } | ||
|
|
||
| public Set<Integer> getJackpotNumbers() { | ||
| return jackpotNumbers; | ||
| } | ||
|
|
||
| public Integer getBonus() { | ||
| return bonus; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package lotto.model; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Randoms; | ||
| import java.util.List; | ||
| import lotto.util.Validator; | ||
|
|
||
| public class Lotto { | ||
| private final List<Integer> numbers; | ||
| static final int LOTTO_RANGE_START = 1; | ||
| static final int LOTTO_RANGE_END = 45; | ||
| static final int LOTTO_BALL_COUNT = 6; | ||
|
|
||
| public Lotto(List<Integer> numbers) { | ||
| Validator.isLength(numbers.size()); | ||
| Validator.isListItemDuplicated(numbers); | ||
| this.numbers = numbers; | ||
| } | ||
|
|
||
| public static Lotto buyNew() { | ||
| return new Lotto(Randoms.pickUniqueNumbersInRange(LOTTO_RANGE_START, LOTTO_RANGE_END, LOTTO_BALL_COUNT)); | ||
| } | ||
|
|
||
| public List<Integer> getNumbers() { | ||
| return numbers; | ||
| } | ||
|
Contributor
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. 전반적으로 모델의 역할이 약한 것 같아요...!
Author
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에 가까운 넘도 모델이라구 해서 걍 이놈도 모델처리해버렸습니당 또 배열 반환 수정이 문제군요..오호.. 그럼 얕은복사한 배열을 돌려쥬면 문제가 안되겠죠??
Contributor
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 static int getLottoRangeStart() { | ||
| return LOTTO_RANGE_START; | ||
| } | ||
|
|
||
| public static int getLottoRangeEnd() { | ||
| return LOTTO_RANGE_END; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| package lotto.model; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.stream.IntStream; | ||
| import lotto.util.DetailErrorMessage; | ||
|
|
||
| public class Player { | ||
|
Contributor
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. 로또에서 Player라는 객체를 만드신 맥락이 궁금해요! 문제를 어떻게 해석하시고 객체를 어떻게 정의하셨나요??
Author
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. 로또를 사서 여러장을 가지고 있다가 추첨 결과에 따라 그 사람이 상품을 탈테니 그걸 고려하구 플레이어 모델을 만들었습니당~~ |
||
| final int purchaseMoney; | ||
| int profitMoney; | ||
| List<Lotto> purchasedLottoList; | ||
|
|
||
| public static Player setLottoMoney(int purchaseMoney) { | ||
| if (purchaseMoney <= 0) { | ||
| throw new IllegalArgumentException(DetailErrorMessage.ZERO_NEGATIVE.getMessage()); | ||
| } | ||
| if (purchaseMoney % 1000 > 0) { | ||
| throw new IllegalArgumentException(DetailErrorMessage.NOT_MULTIPLE.getMessage()); | ||
| } | ||
| return new Player(purchaseMoney); | ||
| } | ||
|
|
||
| Player(int purchaseMoney) { | ||
| this.purchaseMoney = purchaseMoney; | ||
| purchasedLottoList = new ArrayList<>(); | ||
| } | ||
|
|
||
| public void buyLotto() { | ||
| int howMuch = purchaseMoney / 1000; | ||
| IntStream.range(0, howMuch).forEach((i) -> { | ||
| purchasedLottoList.add(Lotto.buyNew()); | ||
| }); | ||
| } | ||
|
|
||
| public List<Lotto> getPurchasedLottoList() { | ||
| return purchasedLottoList; | ||
| } | ||
|
|
||
| public int getPurchasedLottoNum() { | ||
| return purchasedLottoList.size(); | ||
| } | ||
|
|
||
| public void setProfitMoney(int profitMoney) { | ||
| this.profitMoney = profitMoney; | ||
| } | ||
|
|
||
| public float getProfitPercent() { | ||
| return (float) (profitMoney * 100) / purchaseMoney; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package lotto.service; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.stream.IntStream; | ||
| import lotto.model.Game; | ||
| import lotto.model.Player; | ||
| import lotto.util.GamePrize; | ||
|
|
||
| public class LottoService { | ||
| private Game game; | ||
| private Player player; | ||
| private static final int PRIZE_LENGTH = GamePrize.values().length; | ||
|
|
||
| public void setGame(Game game) { | ||
| this.game = game; | ||
| } | ||
|
|
||
| public void setPlayer(Player player) { | ||
| this.player = player; | ||
| } | ||
|
|
||
| public int[] calculateLottoResultType() { | ||
| int[] resultList = new int[PRIZE_LENGTH]; | ||
| player.getPurchasedLottoList().forEach(lotto -> updateResultList(resultList, lotto.getNumbers())); | ||
| return resultList; | ||
| } | ||
|
|
||
| public float calculateLottoResultProfit(int[] resultList) { | ||
| int[] prizeMoneyList = Arrays.stream(GamePrize.values()).mapToInt(GamePrize::getPrizeMoney).toArray(); | ||
| int earnedMoney = IntStream.range(0, PRIZE_LENGTH).map(i -> resultList[i] * prizeMoneyList[i]).sum(); | ||
| player.setProfitMoney(earnedMoney); | ||
| return player.getProfitPercent(); | ||
| } | ||
|
|
||
| void updateResultList(int[] resultList, List<Integer> singleLotto) { | ||
| if (checkPrizeIndex(singleLotto) > -1) { | ||
| resultList[checkPrizeIndex(singleLotto)]++; | ||
| } | ||
| } | ||
|
|
||
| int checkPrizeIndex(List<Integer> singleLotto) { | ||
| Set<Integer> jackpotNumbers = game.getJackpotNumbers(); | ||
| //일치하는 로또 공 개수 셈 | ||
| int matchingLottoBall = (int) singleLotto.stream().filter(jackpotNumbers::contains).count(); | ||
| if (matchingLottoBall == 6) { | ||
| if (hasBonusMatch(singleLotto)) { | ||
| return GamePrize.PRIZE_2ND.getIndex(); | ||
| } | ||
| return GamePrize.PRIZE_1ST.getIndex(); | ||
| } | ||
| return matchingLottoBall - 3; | ||
| } | ||
|
|
||
| boolean hasBonusMatch(List<Integer> singleLotto) { | ||
| int bonus = game.getBonus(); | ||
| return singleLotto.contains(bonus); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package lotto.util; | ||
|
|
||
| public enum DetailErrorMessage { | ||
| BLANK("빈칸 입력됨"), | ||
| NOT_NUMBER("수 외의 문자 입력됨"), | ||
| NOT_ALPHABET("알파벳 외의 문자 입력됨"), | ||
| NOT_COMMA(", 외의 구분자 입력됨"), | ||
| NOT_LENGTH("6개 아님"), | ||
| NOT_RANGE("1부터 45까지의 숫자 아님"), | ||
| DUPLICATED("중복된 번호 입력됨"), | ||
| NOT_MULTIPLE("1000의 배수 아님"), | ||
| ZERO_NEGATIVE("0 또는 음수 입력됨"), | ||
| DEV_TYPE_WRONG("개발 오류, 지원되지 않는 자료형입니다."); | ||
|
|
||
| private String message; | ||
|
|
||
| DetailErrorMessage(String message) { | ||
| this.message = message; | ||
| } | ||
|
|
||
| public String getMessage() { | ||
| return " : " + message; | ||
| } | ||
| } |
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.
서비스가 있음에도 모델을 컨트롤러 내부에 두신 이유가 있나요?
제 생각에는 컨트롤러 내부에 있는 로직들은 서비스에 분리하는게 컨트롤러에 부담을 줄이고 관심사를 분리하는데 용이할 것 같습니다
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.
구현할 당시에는 로또 서비스는 로또만 다루게 해야지~~ 단순히 생각했다가 최종 제출 때 살짝 아차한 부분이긴 합니다ㅋㅋ 아무래도 서비스가 있는한 다른 모델들을 서비스 내부에서 다루게하는게 좋겠죠?