diff --git a/README.md b/README.md index 8a4f22ed0..42255a9db 100644 --- a/README.md +++ b/README.md @@ -1 +1,77 @@ -# java-planetlotto-precourse +# 미션 : 행성 로또 - 구현 기능 정리 + +## 구현한 기능 목록 +- [x] 사용자에게서 금액을 입력받으면, lottoMaker는 lotto를 만들어준다. +- [x] 당첨 번호와 보너스 번호를 입력하면, 내가 구매한 로또가 몇 등인지를 알 수 있다. +- [x] 총 통계를 결과로 내보낸다. + +## 예외 처리 +### Lotto + - [x] 번호는 숫자여야 한다. + - [x] 번호의 범위는 1~30이다. + - [x] 번호는 중복되어서는 안된다. + +## ✅ 추가 기능 +### 새로운 등급 마련 +- 4, 5등에 해당하는데 아쉽게 보너스 번호 한끝 차이로 당첨금을 못 받을 경우를 위한 새로운 등급 마련 +- 기존의 로또 당첨금 체계에 추가할 경우, 로또 기본 기능 사항을 어기는 것이 되므로, 새로운 기능인 **게임**기능에 연결하도록 구성 +- 4, 5등의 점수인데 보너스 번호 하나 어긋나서 상금 수령이 어려운 경우, 상금은 0이지만, 4,5등과 같은 행운 스코어를 게임에서 적립하도록 한다. +- 시간 관계상 행운 스코어를 적립하는 로직은 만들지 못하였지만, 이를 통해 사용자들이 더 재미있게 로또 게임을 즐길 수 있을 것으로 보여집니다:) + +```java +BONUS_FOURTH("보너스 4등", 3, false, 0, 500_000), +BONUS_FIFTH("보너스 5등", 2, false, 0, 5_000); + +private final String displayName; +private final int countNum; +private final boolean isBonus; +private final int price; +private final int luckyScore; +``` + +----- + +# 🍀 도전 과제 - 행운 점수 게임 +> 저는 항상 무언가를 만들고, 새로 배울때 하고 싶은 것을 무작정 시도해보고는 합니다. +> +> 오픈 미션을 통해 Rust라는 언어를 배우고, 이 언어의 쓰임새를 확장해보고 싶어서 Rudis를 만들었듯이 +> +> 이번에도 lotto 프로젝트를 확장하여 **lotto로 쌓은 나만의 행운 점수로 하는 게임**을 만들어보고자 합니다. + +최근에 저와 제 친구들은, 카카오톡의 **검 키우기**에 빠져 있습니다. +이 게임의 매력은, 검으로 벌어들인 돈으로 여러 랜덤 무기들을 뽑고, 결투를 통해 승률을 올리는 것입니다. +단순한 게임이지만 참 재밌어서 아직까지도 하는 중이고, 제 친구들도 이미 중독되어 버렸습니다. + +> 😋 만약 로또를 사는것에서 끝나지 않고, 로또뽑기를 통해 얻은 행운점수로 게임을 할 수 있다면 어떨까요? + +## 구현 목표 기능 +> 🌟 원래 view를 생성해서 제가 만든 기능으로 콘솔 전환할 수 있는 기능을 만들고 싶었는데, 이렇게 하니 기본 **기능 테스트가 NoSuchArgumentException으>로 깨져서**, 뷰 없이 기능들만 만들어 뒀습니다. + +### 1. 내 프로필 확인 (완성, GameOutputView는 미완) +- [x] 유저가 행운점수 기능에 입장하면, 1번을 클릭하여 내 프로필을 볼 수 있습니다. +- [x] 각 유저들은 자신만의 행운 점수를 가지고 있습니다. (행운 점수는 로또 당첨을 통해 크게 얻을 수도 있고, 승률을 올리면 얻을 수 있습니다.) +- [x] 승률은 ENUM으로 관리하여 각 승률을 통해 얻을 수 있는 행운 점수를 내부에 포함하도록 합니다. + +### 2. 랭킹 확인 (미완) +- [ ] 플레이 유저들의 승률 순위를 볼 수 있습니다 +- [ ] 사용자들은 자신의 순위를 보고, 더 분발해서 게임을 즐길 수 있습니다. + +### 3. 내 무기 강화하기 (미완) +- [ ] 💥 아마 시간관계상 여기까지 못 만들 것 같습니다... +- [ ] 유저들은 각자 자신의 무기를 가집니다. +- [ ] 무기의 레벨이 오를수록 공격력이 올라 승리 확률이 커집니다. +- [ ] 무기는 레벨이 오를수록 파괴 확률도 올라갑니다. + +## 신경쓴 부분 +### enum 도메인 test 로직 작성 +- 현재 승,무,패를 관리하는 WinRate에는 승리, 패배 로직이 있습니다. +- 이 로직의 경우, 각각 유저의 럭키 스코어를 수정해야 함과 동시에 WinRecord의 승,무,패 count도 수정해야 합니다. +- 정합성이 유지되어야 하는 로직이므로, test code를 작성하여 검증하였습니다. + +### DTO 마련 +- 유저의 프로필을 조회하는 기능을 만들기 위해, 유저의 여러 정보와 무기의 정보, 승패의 정보를 가져와야 했습니다. +- 해당 정보들을 outputView에서 더 쉽게 화면에 출력할 수 있도록 하기 위해 dto를 마련했습니다. + +### Service 분기 +- 원래 view 연결이 가능했다면, 입력받는 번호별로 기능을 분기해서 잡을 계획이었으나, view 연결이 불가능한 상황이라 임시 view를 만들어서 각각 서비스별로 분기하도록 해두었습니다. +- 시간 관계상 목표했던 두 번째 기능인 랭킹 확인 기능은 만들지 못하였으나, 첫 번째 기능인 프로필 확인 기능을 GameProfileService로 따로 분기하여 구성했습니다. \ No newline at end of file diff --git a/src/main/java/planetlotto/Application.java b/src/main/java/planetlotto/Application.java index 27d0a8f96..7e1686caa 100644 --- a/src/main/java/planetlotto/Application.java +++ b/src/main/java/planetlotto/Application.java @@ -1,7 +1,11 @@ package planetlotto; +import planetlotto.controller.MainController; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + MainController controller = new MainController(); + controller.run(); } } diff --git a/src/main/java/planetlotto/controller/GameController.java b/src/main/java/planetlotto/controller/GameController.java new file mode 100644 index 000000000..33a36ecd7 --- /dev/null +++ b/src/main/java/planetlotto/controller/GameController.java @@ -0,0 +1,25 @@ +package planetlotto.controller; + +import planetlotto.repository.UserRepository; +import planetlotto.service.GameProfileService; +import planetlotto.view.GameInputView; + +public class GameController { + private final GameInputView inputView; + private final GameProfileService gameProfileService; + + public GameController() { + this.inputView = new GameInputView(); + UserRepository userRepository = new UserRepository(); + this.gameProfileService = new GameProfileService(userRepository); + } + + public void run(){ + // 원래 시나리오 대로라면, 1을 누르면 연결된다. + String input = inputView.chooseMenu(); + if(input.equals("1")){ + String nickName = inputView.inputNick(); + gameProfileService.getUserProfile(nickName); + } + } +} diff --git a/src/main/java/planetlotto/controller/LottoController.java b/src/main/java/planetlotto/controller/LottoController.java new file mode 100644 index 000000000..01458f534 --- /dev/null +++ b/src/main/java/planetlotto/controller/LottoController.java @@ -0,0 +1,80 @@ +package planetlotto.controller; + +import planetlotto.domain.Lotto; +import planetlotto.domain.Stats; +import planetlotto.domain.WinningLotto; +import planetlotto.repository.LottoRepository; +import planetlotto.service.LottoService; +import planetlotto.view.InputView; +import planetlotto.view.OutputView; + +import java.util.List; +import java.util.Map; + +public class LottoController { + private final InputView inputView; + private final OutputView outputView; + private final LottoService lottoService; + + public LottoController() { + this.inputView = new InputView(); + this.outputView = new OutputView(); + + LottoRepository lottoRepository = new LottoRepository(); + this.lottoService = new LottoService(lottoRepository); + } + + public void run() { + int amount = getAmount(); + generateLottos(amount); + + WinningLotto winningLotto = createWinningLotto(); + + Stats stats = new Stats(); + Map rankStat = lottoService.calculateRank(winningLotto, stats); + outputView.printResult(rankStat); + } + + private int getAmount() { + int amount; + while (true) { + try { + amount = inputView.askAmount(); + break; + } catch (IllegalArgumentException e) { + System.out.println("[ERROR] " + e.getMessage()); + } + } + return amount; + } + + private WinningLotto createWinningLotto() { + WinningLotto winningLotto; + + while (true) { + try { + List nums = inputView.askWinningLotto(); + int bonus = inputView.askBonusNumber(); + winningLotto = new WinningLotto(new Lotto(nums), bonus); + break; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + + return winningLotto; + } + + private void generateLottos(int amount) { + while (true) { + try { + List> lottos = lottoService.generateLotto(amount); + outputView.printPurchasedLottos(lottos); + + break; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } +} diff --git a/src/main/java/planetlotto/controller/MainController.java b/src/main/java/planetlotto/controller/MainController.java new file mode 100644 index 000000000..3826900ae --- /dev/null +++ b/src/main/java/planetlotto/controller/MainController.java @@ -0,0 +1,24 @@ +package planetlotto.controller; +/* +원래 로또가 끝나고 바로 연결하는 로직을 만들고 싶었으나, 이렇게 하면 기능 테스트에서 에러가 나서,, 주석 처리 해두었습니다. + */ +public class MainController { + private LottoController lottoController; + private GameController gameController; + + public MainController() { + lottoController = new LottoController(); + gameController = new GameController(); + } + + public void run() { + lottoController.run(); + +// String input = gampInputView.inputEnterButton(); +// if ("종료".equals(input)) { +// return; +// } + // 여기서 새로 붙인 기능으로 기능변환 +// gameController.run(); + } +} diff --git a/src/main/java/planetlotto/domain/Lotto.java b/src/main/java/planetlotto/domain/Lotto.java new file mode 100644 index 000000000..bdeaff0b2 --- /dev/null +++ b/src/main/java/planetlotto/domain/Lotto.java @@ -0,0 +1,58 @@ +package planetlotto.domain; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Lotto { + private static final int MINIMUM_NUMBER_OF_LOTTO = 1; + private static final int MAXIMUM_NUMBER_OF_LOTTO = 30; + + private final List lotto; + + public Lotto(List nums) { + validate(nums); + this.lotto = nums; + } + + public List getLotto() { + return lotto; + } + + private void validate(List nums) { + validateRange(nums); + validateDuplicate(nums); + } + + private void validateRange(List nums) { + for (Integer num : nums) { + if (num < MINIMUM_NUMBER_OF_LOTTO || num > MAXIMUM_NUMBER_OF_LOTTO) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1과 30 사이어야 합니다."); + } + } + } + + private void validateDuplicate(List nums) { + Set numSet = new HashSet<>(); + for (Integer num : nums) { + numSet.add(num); + } + + if (numSet.size() != nums.size()) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 중복이 없어야 합니다."); + } + } + + public int countNum(List compareNumber) { + int count = 0; + for (Integer compare : compareNumber) { + if (this.lotto.contains(compare)) + count++; + } + return count; + } + + public boolean contains(int number) { + return this.lotto.contains(number); + } +} diff --git a/src/main/java/planetlotto/domain/Rank.java b/src/main/java/planetlotto/domain/Rank.java new file mode 100644 index 000000000..10969731a --- /dev/null +++ b/src/main/java/planetlotto/domain/Rank.java @@ -0,0 +1,89 @@ +package planetlotto.domain; + +public enum Rank { + NONE("낙첨", 0, false, 0, 0), + FIRST("1등", 5, false, 100_000_000, 100_000_000), + SECOND("2등", 4, true, 10_000_000, 10_000_000), + THIRD("3등", 4, false, 1_500_000, 1_500_000), + FOURTH("4등", 3, true, 500_000, 500_000), + FIFTH("5첨", 2, true, 5_000, 5_000), + BONUS_FOURTH("보너스 4등", 3, false, 0, 500_000), + BONUS_FIFTH("보너스 5등", 2, false, 0, 5_000); + + private final String displayName; + private final int countNum; + private final boolean isBonus; + private final int price; + private final int luckyScore; + + Rank(String displayName, int countNum, boolean isBonus, int price, int luckyScore) { + this.displayName = displayName; + this.countNum = countNum; + this.isBonus = isBonus; + this.price = price; + this.luckyScore = luckyScore; + } + + public String getDisplayName() { + return displayName; + } + + public int getCountNum() { + return countNum; + } + + public boolean isBonus() { + return isBonus; + } + + public int getPrice() { + return price; + } + + public int getLuckyScore() { + return luckyScore; + } + + public static boolean isBonusRank(Rank rank) { + if (rank == Rank.BONUS_FOURTH || rank == Rank.BONUS_FIFTH) { + return true; + } + return false; + } + + public static Rank getBonusRank(int countNum, boolean isBonus) { + if (countNum == 3 && !isBonus) { // 아쉽게 보너스 번호 하나 안 맞은 당신! 럭키 스코어는 그대로 + return BONUS_FOURTH; + } + + if (countNum == 2 && !isBonus) { // 아쉽게 보너스 번호 하나 안 맞은 당신! 럭키 스코어는 그대로 + return BONUS_FIFTH; + } + + return NONE; + } + + public static Rank calculateRank(int countNum, boolean isBonus) { + if (countNum == 5 && !isBonus) { + return FIRST; + } + + if (countNum == 4 && isBonus) { + return SECOND; + } + + if (countNum == 4 && !isBonus) { + return THIRD; + } + + if (countNum == 3 && isBonus) { + return FOURTH; + } + + if (countNum == 2 && isBonus) { + return FIFTH; + } + + return getBonusRank(countNum, isBonus); + } +} diff --git a/src/main/java/planetlotto/domain/Stats.java b/src/main/java/planetlotto/domain/Stats.java new file mode 100644 index 000000000..d9a111c6d --- /dev/null +++ b/src/main/java/planetlotto/domain/Stats.java @@ -0,0 +1,25 @@ +package planetlotto.domain; + +import java.util.HashMap; +import java.util.Map; + +public class Stats { + private Map rank; // 순위 인덱스와 카운트 + + public Stats() { + this.rank = new HashMap<>(); + } + + public Map getRank() { + return rank; + } + + public void addCount(Rank rank) { + int rankInd = rank.ordinal(); + + int cnt = this.rank.getOrDefault(rankInd, 0); + cnt++; + + this.rank.put(rankInd, cnt); + } +} diff --git a/src/main/java/planetlotto/domain/User.java b/src/main/java/planetlotto/domain/User.java new file mode 100644 index 000000000..9888c453d --- /dev/null +++ b/src/main/java/planetlotto/domain/User.java @@ -0,0 +1,43 @@ +package planetlotto.domain; + +public class User { + private final String userName; + private final Weapon weapon; // 무기 + private final WinRecord record; // 승패 상태 + private int luckyScore; + + public User(String userName, Weapon weapon) { + this.userName = userName; + this.weapon = weapon; + record = new WinRecord(); + this.luckyScore = 1000; // 첫 입장시 럭키스코어 기본 1000 + } + + // 유저 데이터 넣기 위한 +// public User(String userName, Weapon weapon, WinRecord record, int luckyScore) { +// this.userName = userName; +// this.weapon = weapon; +// this.record = record; +// this.luckyScore = luckyScore; +// } + + public String getUserName() { + return userName; + } + + public Weapon getWeapon() { + return weapon; + } + + public WinRecord getRecord() { + return record; + } + + public int getLuckyScore() { + return luckyScore; + } + + public void setLuckyScore(int luckyScore) { + this.luckyScore = luckyScore; + } +} diff --git a/src/main/java/planetlotto/domain/Weapon.java b/src/main/java/planetlotto/domain/Weapon.java new file mode 100644 index 000000000..8756c1eff --- /dev/null +++ b/src/main/java/planetlotto/domain/Weapon.java @@ -0,0 +1,31 @@ +package planetlotto.domain; + +public class Weapon { + private final String weaponName; + private final String type; + private int level; + private int power; + + public Weapon(String weaponName, String type) { + this.weaponName = weaponName; + this.type = type; + level = 1; + power = 1; + } + + public String getWeaponName() { + return weaponName; + } + + public String getType() { + return type; + } + + public int getLevel() { + return level; + } + + public int getPower() { + return power; + } +} diff --git a/src/main/java/planetlotto/domain/WinRate.java b/src/main/java/planetlotto/domain/WinRate.java new file mode 100644 index 000000000..913ad4e2e --- /dev/null +++ b/src/main/java/planetlotto/domain/WinRate.java @@ -0,0 +1,54 @@ +package planetlotto.domain; + +/* +승룰 관리 + +1승은 행운점수 + 10점, +1무는 행운점수 + 0점 +1패는 행운점수 -3점 + */ +public enum WinRate { + WIN("승", "plus", 10), + TIE("무", "plus", 0), + LOSS("패", "minus", 3); + + private final String type; + private final String calculate; + private final int score; + + WinRate(String type, String calculate, int score) { + this.type = type; + this.calculate = calculate; + this.score = score; + } + + // 한번 이김 + public static void win(User user, WinRecord record) { + int luckyScore = user.getLuckyScore(); + user.setLuckyScore(luckyScore + WIN.score); + record.win(); // 이겼으니까 같이 업데이트 해야 한다. + } + + // 한번 짐 + public static void lose(User user, WinRecord record) { + int luckyScore = user.getLuckyScore(); + user.setLuckyScore(luckyScore - LOSS.score); + record.loss(); + } + + public static void tie(User user, WinRecord record) { + record.tie(); + } + + public String getType() { + return type; + } + + public String getCalculate() { + return calculate; + } + + public int getScore() { + return score; + } +} diff --git a/src/main/java/planetlotto/domain/WinRecord.java b/src/main/java/planetlotto/domain/WinRecord.java new file mode 100644 index 000000000..65d156169 --- /dev/null +++ b/src/main/java/planetlotto/domain/WinRecord.java @@ -0,0 +1,37 @@ +package planetlotto.domain; + +public class WinRecord { + private int winCnt; + private int tieCnt; + private int lossCnt; + + public WinRecord() { // 처음엔 0승 0무 0패로 시작한다. + this.winCnt = 0; + this.tieCnt = 0; + this.lossCnt = 0; + } + + public int getWinCnt() { + return winCnt; + } + + public int getTieCnt() { + return tieCnt; + } + + public int getLossCnt() { + return lossCnt; + } + + public void win(){ + this.winCnt++; + } + + public void tie(){ + this.tieCnt++; + } + + public void loss(){ + this.lossCnt++; + } +} diff --git a/src/main/java/planetlotto/domain/WinningLotto.java b/src/main/java/planetlotto/domain/WinningLotto.java new file mode 100644 index 000000000..bc3484ac6 --- /dev/null +++ b/src/main/java/planetlotto/domain/WinningLotto.java @@ -0,0 +1,27 @@ +package planetlotto.domain; + +public class WinningLotto { + private final Lotto winningLotto; + private final int bonus; + + public WinningLotto(Lotto lotto, int bonus) { + this.winningLotto = lotto; + + validateRange(bonus); + this.bonus = bonus; + } + + public Lotto getWinningLotto() { + return winningLotto; + } + + public int getBonus() { + return bonus; + } + + private void validateRange(int bonus) { + if (bonus < 1 || bonus > 30) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1과 30 사이어야 합니다."); + } + } +} diff --git a/src/main/java/planetlotto/dto/ProfileDto.java b/src/main/java/planetlotto/dto/ProfileDto.java new file mode 100644 index 000000000..b09dd04a1 --- /dev/null +++ b/src/main/java/planetlotto/dto/ProfileDto.java @@ -0,0 +1,30 @@ +package planetlotto.dto; + +import planetlotto.domain.User; +import planetlotto.domain.Weapon; +import planetlotto.domain.WinRecord; + +public record ProfileDto( + String userName, + int userWinNum, + int userTieNum, + int userLossNum, + String weaponName, + int weaponLevel, + int userLuckyScore +) { + public static ProfileDto of(User user) { + WinRecord winRecord = user.getRecord(); + Weapon weapon = user.getWeapon(); + + return new ProfileDto( + user.getUserName(), + winRecord.getWinCnt(), + winRecord.getTieCnt(), + winRecord.getLossCnt(), + weapon.getWeaponName(), + weapon.getLevel(), + user.getLuckyScore() + ); + } +} diff --git a/src/main/java/planetlotto/repository/LottoRepository.java b/src/main/java/planetlotto/repository/LottoRepository.java new file mode 100644 index 000000000..52fa0a28d --- /dev/null +++ b/src/main/java/planetlotto/repository/LottoRepository.java @@ -0,0 +1,32 @@ +package planetlotto.repository; + +import planetlotto.domain.Lotto; + +import java.util.ArrayList; +import java.util.List; + +public class LottoRepository { + private final List lottos; + + public LottoRepository() { + this.lottos = new ArrayList<>(); + } + + public void addLotto(Lotto lotto) { + lottos.add(lotto); + } + + public List getLottos() { + return lottos; + } + + public List> findAllLottos() { + List> result = new ArrayList<>(); + + for (Lotto lotto : lottos) { + result.add(lotto.getLotto()); + } + + return result; + } +} diff --git a/src/main/java/planetlotto/repository/UserRepository.java b/src/main/java/planetlotto/repository/UserRepository.java new file mode 100644 index 000000000..d6ff6ab6a --- /dev/null +++ b/src/main/java/planetlotto/repository/UserRepository.java @@ -0,0 +1,24 @@ +package planetlotto.repository; + +import planetlotto.domain.User; + +import java.util.ArrayList; +import java.util.List; + +public class UserRepository { + private final List users; + + public UserRepository() { + this.users = new ArrayList<>(); + } + + public List getUsers() { + return users; + } + + public User findUserByUsername(String userName) { + return users.stream() + .filter(user -> userName.equals(user.getUserName())) + .findFirst().orElse(null); + } +} diff --git a/src/main/java/planetlotto/service/GameProfileService.java b/src/main/java/planetlotto/service/GameProfileService.java new file mode 100644 index 000000000..52efea079 --- /dev/null +++ b/src/main/java/planetlotto/service/GameProfileService.java @@ -0,0 +1,23 @@ +package planetlotto.service; + +import planetlotto.domain.User; +import planetlotto.dto.ProfileDto; +import planetlotto.repository.UserRepository; + +/* +유저의 프로필과 관련된 서비스 + +1. 해당 유저의 프로필 확인하는 기능 + */ +public class GameProfileService { + private UserRepository repository; + + public GameProfileService(UserRepository repository) { + this.repository = repository; + } + + public ProfileDto getUserProfile(String userName) { + User user = repository.findUserByUsername(userName); + return ProfileDto.of(user); + } +} diff --git a/src/main/java/planetlotto/service/LottoService.java b/src/main/java/planetlotto/service/LottoService.java new file mode 100644 index 000000000..ea1a7d872 --- /dev/null +++ b/src/main/java/planetlotto/service/LottoService.java @@ -0,0 +1,48 @@ +package planetlotto.service; + +import camp.nextstep.edu.missionutils.Randoms; +import planetlotto.domain.Lotto; +import planetlotto.domain.Rank; +import planetlotto.domain.Stats; +import planetlotto.domain.WinningLotto; +import planetlotto.repository.LottoRepository; + +import java.sql.SQLOutput; +import java.util.List; +import java.util.Map; + +public class LottoService { + private final LottoRepository repository; + + public LottoService(LottoRepository repository) { + this.repository = repository; + } + + public List> generateLotto(int amount) { + int count = amount / 500; + + for (int i = 0; i < count; i++) { + List nums = Randoms.pickUniqueNumbersInRange(1, 30, 5); + repository.addLotto(new Lotto(nums)); + } + + return repository.findAllLottos(); + } + + public Map calculateRank(WinningLotto winningLotto, Stats stats) { + List lottos = repository.getLottos(); + + for (Lotto lotto : lottos) { + int count = lotto.countNum(winningLotto.getWinningLotto().getLotto()); + boolean isBonus = lotto.contains(winningLotto.getBonus()); + + Rank rank = Rank.calculateRank(count, isBonus); + // 여기서 BONUS_FOURTH, BONUS_FIFTH는 통계에서 제외 (이건 행운 게임에서만 사용한다.) + if(Rank.isBonusRank(rank)){ + continue; + } + stats.addCount(rank); + } + return stats.getRank(); + } +} diff --git a/src/main/java/planetlotto/view/GameInputView.java b/src/main/java/planetlotto/view/GameInputView.java new file mode 100644 index 000000000..6b136a7c0 --- /dev/null +++ b/src/main/java/planetlotto/view/GameInputView.java @@ -0,0 +1,51 @@ +package planetlotto.view; + +import camp.nextstep.edu.missionutils.Console; + +import java.util.function.Supplier; + +public class GameInputView { + public String gameIntro() { + return retryOnError(() -> { + System.out.println("🍀 로또로 얻은 행운 점수로 행운 점수 게임을 해보세요!"); + System.out.println("입장을 원하시면 입장을, 종료를 원하시면 종료를 입력해주세요"); + String input = Console.readLine(); + + if(!"입장".equals(input) && !"종료".equals(input)){ + throw new IllegalArgumentException("[ERROR] 입장 혹은 종료만 입력 가능합니다."); + } + + return input; + }); + } + + public String chooseMenu() { + return retryOnError(() -> { + System.out.println("🍀 원하시는 메뉴를 입력해주세요 (1~3, 종료를 원하실 경우 Q를 입력해주세요)"); + + String input = Console.readLine(); + + return input; + }); + } + + public String inputNick() { + return retryOnError(() -> { + System.out.println("🍀 유저 닉네임을 입력해주세요"); + + String input = Console.readLine(); + + return input; + }); + } + + private T retryOnError(Supplier supplier) { + while (true) { + try { + return supplier.get(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } +} diff --git a/src/test/java/planetlotto/domain/WinRateTest.java b/src/test/java/planetlotto/domain/WinRateTest.java new file mode 100644 index 000000000..22eec34ed --- /dev/null +++ b/src/test/java/planetlotto/domain/WinRateTest.java @@ -0,0 +1,81 @@ +package planetlotto.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; + +/* +1. 유저가 이겼을때, +2. 유저가 졌을때 + +두 경우의 행운 점수를 test한다. + */ +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class WinRateTest { + private User user; + private WinRecord record; + + @BeforeEach + void setUp() { + user = new User("김말랑이", new Weapon("아주 단단한 몽둥이", "땅")); + record = user.getRecord(); + } + + @Test + void 유저_생성시_기본_행운점수_1000점() { + //then + assertSimpleTest(() -> { + Assertions.assertThat(user.getLuckyScore()).isEqualTo(1000); + }); + } + + @Test + void 유저가_지면_행운점수가_3점_깎인다() { + //when + WinRate.lose(user, record); + + //then + assertSimpleTest(() -> { + Assertions.assertThat(user.getLuckyScore()).isEqualTo(997); + }); + } + + @Test + void 유저가_이기면_행운점수가_10점_늘어난다() { + //when + WinRate.win(user, record); + + //then + assertSimpleTest(() -> { + Assertions.assertThat(user.getLuckyScore()).isEqualTo(1010); + }); + } + + @Test + void 유저가_지면_loss의_카운트가_1_증가한다() { + //given + + //when + WinRate.lose(user, record); + //then + assertSimpleTest(() -> { + Assertions.assertThat(record.getLossCnt()).isEqualTo(1); + }); + } + + @Test + void 유저가_이기면_win의_카운트가_1_증가한다() { + //given + + //when + WinRate.win(user, record); + //then + assertSimpleTest(() -> { + Assertions.assertThat(record.getWinCnt()).isEqualTo(1); + }); + } +} \ No newline at end of file