diff --git a/README.md b/README.md index 03ba7ed3..140c404f 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ -# java-blackjack \ No newline at end of file +# 연료 주입 + +## 기능요구사항 + +- [x] 렌터카는 Sonata 2대, Avante 1대, K5 2대로 총 5대의 차량을 보유하고 있다. + - [x] 차량 별 연비 정보를 저장하고 있다. + - Sonata : 10km/리터 + - Avante : 15km/리터 + - K5 : 13km/리터) + - 차량 별 보유 대수를 저장하고 있다. +- [x] 고객은 여행할 목적지의 대략적인 이동거리를 입력 받는다. +- [x] 이 이동거리를 활용해 차량 별로 필요한 연료를 주입한다. +- [x] 차량 별로 주입해야 할 연료량을 확인할 수 있는 보고서를 생성한다. +- [x] 보고서를 출력한다. + +# java-blackjack + +- [x] 게임에 참여할 사람의 이름을 입력하세요. +- [x] 게임이 시작하면 참여한 사람과 딜러는 카드 2개씩을 받는다. +- [x] 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다. +- [x] 게임에 참여한 사람 순서대로 카드를 더 받을지 물어보고 카드를 제공한다. 21점을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. 단, 여기서 카드의 합은 21점을 넘어가지 않는다. +- [x] 게임에 딜러도 기존에 받았던 카드들의 합이 16점 이하이면 한장의 카드를 더 받아야 한다. 17점 이상이면 추가로 받을 수 없다. +- [x] 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21점 또는 21점에 가장 가까운 숫자를 가지는 쪽이 이기는 게임이다. +- [x] 블랙잭 게임을 완료한 후 각 플레이어별로 승패를 출력한다. diff --git a/src/main/java/blackjack/Application.java b/src/main/java/blackjack/Application.java new file mode 100644 index 00000000..845b98cd --- /dev/null +++ b/src/main/java/blackjack/Application.java @@ -0,0 +1,11 @@ +package blackjack; + +import blackjack.controller.Controller; + +public class Application { + + public static void main(String[] args) { + Controller controller = new Controller(); + controller.run(); + } +} diff --git a/src/main/java/blackjack/controller/Controller.java b/src/main/java/blackjack/controller/Controller.java new file mode 100644 index 00000000..56aae841 --- /dev/null +++ b/src/main/java/blackjack/controller/Controller.java @@ -0,0 +1,65 @@ +package blackjack.controller; + +import blackjack.domain.Game; +import blackjack.domain.Winner; +import blackjack.domain.card.CardDeck; +import blackjack.domain.player.Player; +import blackjack.domain.state.Gameable; +import blackjack.domain.state.State; +import blackjack.view.InputView; +import blackjack.view.OutputView; + +public class Controller { + + private static void initGame(Game game) { + OutputView.printStartMessage(game); + OutputView.printDealerCard(game.getDealer()); + OutputView.printPlayerCard(game.getPlayers()); + } + + public void run() { + Game game = new Game(InputView.inputPlayers()); + + initGame(game); + playGame(game); + finishGame(game); + } + + private void playGame(Game game) { + game.getPlayers().forEach(this::receive); + if (game.giveCardToDealer()) { + OutputView.printMessageToGiveCardToDealer(); + } + } + + private void finishGame(Game game) { + Winner winner = new Winner(game); + + OutputView.printGameResults(game.getDealer(), game.getPlayers()); + + OutputView.printGameWinOrLose(game.getDealer(), winner.calculateDealerGameResult()); + game.getPlayers().forEach( + player -> OutputView.printGameWinOrLose( + player, winner.calculatePlayerGameResult(player) + ) + ); + } + + public void receive(Player player) { + Gameable gameable = player.getCards(); + String yesOrNo = ""; + do { + yesOrNo = InputView.inputYesOrNo(player.getName()); + if (yesOrNo.equals("y")) { + gameable.addCard(CardDeck.pop()); + OutputView.printCurrentCardsState(player.getName(), player.getCards()); + gameable = gameable.judge(); + } + if (yesOrNo.equals("n")) { + gameable = new State(gameable.cards(), false); + } + } while (gameable.isEnd()); + } + + +} diff --git a/src/main/java/blackjack/domain/Game.java b/src/main/java/blackjack/domain/Game.java new file mode 100644 index 00000000..d3ea1cde --- /dev/null +++ b/src/main/java/blackjack/domain/Game.java @@ -0,0 +1,64 @@ +package blackjack.domain; + +import blackjack.domain.card.CardDeck; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; +import blackjack.domain.state.State; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class Game { + + private static final int PASS_CARD_NUMBER = 2; + private static final String DEALER_NAME = "딜러"; + private final static int DEALER_THRESHOLD = 16; + + private final List players; + private final Dealer dealer; + + public Game(Dealer dealer, List players) { + this.players = players; + this.dealer = dealer; + } + + public Game(List playerNames) { + this(new Dealer(DEALER_NAME, handOutCards()), playerNames.stream() + .map(Game::createPlayer) + .collect(Collectors.toList())); + } + + private static Player createPlayer(String name) { + return new Player(name, handOutCards()); + } + + private static State handOutCards() { + return new State(CardDeck.pop(PASS_CARD_NUMBER), true); + } + + public boolean giveCardToDealer() { + if (dealer.getCards().cards().sumScore() <= DEALER_THRESHOLD) { + dealer.getCards().addCard(CardDeck.pop()); + return true; + } + return false; + } + + public int getTotalScoreOfPlayer(Player player) { + return player.getCards().cards().sumScore(); + } + + public List getScoresOfPlayers() { + return players.stream() + .mapToInt(this::getTotalScoreOfPlayer) + .boxed().collect(Collectors.toList()); + } + + public List getPlayers() { + return Collections.unmodifiableList(players); + } + + public Dealer getDealer() { + return dealer; + } +} diff --git a/src/main/java/blackjack/domain/Winner.java b/src/main/java/blackjack/domain/Winner.java new file mode 100644 index 00000000..683021cf --- /dev/null +++ b/src/main/java/blackjack/domain/Winner.java @@ -0,0 +1,57 @@ +package blackjack.domain; + +import blackjack.domain.player.Player; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Winner { + + private final int BLACKJACK = 21; + private final Game game; + + public Winner(final Game game) { + this.game = game; + } + + public List calculateDealerGameResult() { + int dealerScore = game.getDealer().getCards().cards().sumScore(); + return calculateGameResult(dealerScore); + } + + public List calculatePlayerGameResult(final Player player) { + int playerScore = player.getCards().cards().sumScore(); + return calculateGameResult(playerScore); + } + + private List calculateGameResult(final int sourceScore) { + List targetScores = game.getScoresOfPlayers().stream() + .map(this::convertZeroScore) + .collect(Collectors.toList()); + return Arrays.asList(countWin(sourceScore, targetScores), + countLose(sourceScore, targetScores)); + } + + private int convertZeroScore(final int score) { + if (score > BLACKJACK) { + return 0; + } + return score; + } + + private int countWin(final int sourceScore, final List targetScores) { + if (sourceScore > BLACKJACK) { + return 0; + } + return Long.valueOf(targetScores.stream() + .filter(targetScore -> sourceScore > targetScore).count()).intValue(); + } + + private int countLose(final int sourceScore, final List targetScores) { + if (sourceScore > BLACKJACK) { + return targetScores.size(); + } + return Long.valueOf(targetScores.stream() + .filter(targetScore -> sourceScore < targetScore).count()).intValue(); + } +} \ No newline at end of file diff --git a/src/main/java/blackjack/domain/card/Card.java b/src/main/java/blackjack/domain/card/Card.java new file mode 100644 index 00000000..323323e3 --- /dev/null +++ b/src/main/java/blackjack/domain/card/Card.java @@ -0,0 +1,21 @@ +package blackjack.domain.card; + +public class Card { + + private final CardNumber cardNumber; + private final CardPattern cardPattern; + + public Card(final CardNumber cardNumber, final CardPattern cardPattern) { + this.cardNumber = cardNumber; + this.cardPattern = cardPattern; + } + + @Override + public String toString() { + return cardNumber.getName() + cardPattern.getName(); + } + + public CardNumber getCardNumber() { + return cardNumber; + } +} diff --git a/src/main/java/blackjack/domain/card/CardDeck.java b/src/main/java/blackjack/domain/card/CardDeck.java new file mode 100644 index 00000000..c09d8733 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardDeck.java @@ -0,0 +1,35 @@ +package blackjack.domain.card; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class CardDeck { + + private static final int FIRST_INDEX = 0; + private static List cards = new ArrayList<>(); + + static { + Arrays.stream(CardNumber.values()).forEach( + cardNumber -> Arrays.stream(CardPattern.values()).forEach( + cardPattern -> cards.add(new Card(cardNumber, cardPattern)) + ) + ); + Collections.shuffle(cards); + } + + public static Cards pop(final int count) { + List newCards = new ArrayList<>(cards.subList(FIRST_INDEX, count)); + cards = cards.subList(count, cards.size() - count); + return new Cards(newCards); + } + + public static Card pop() { + return cards.remove(FIRST_INDEX); + } + + public static List getCards() { + return Collections.unmodifiableList(cards); + } +} diff --git a/src/main/java/blackjack/domain/card/CardNumber.java b/src/main/java/blackjack/domain/card/CardNumber.java new file mode 100644 index 00000000..78d7fb3c --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardNumber.java @@ -0,0 +1,33 @@ +package blackjack.domain.card; + +public enum CardNumber { + ACE("A", 11), + TWO("2", 2), + THREE("3", 3), + FOUR("4", 4), + FIVE("5", 5), + SIX("6", 6), + SEVEN("7", 7), + EIGHT("8", 8), + NINE("9", 9), + JACK("J", 10), + QUEEN("Q", 10), + KING("K", 10); + + private final String name; + private final int score; + + CardNumber(final String name, final int score) { + this.name = name; + this.score = score; + } + + public String getName() { + return name; + } + + public int getScore() { + return score; + } + +} diff --git a/src/main/java/blackjack/domain/card/CardPattern.java b/src/main/java/blackjack/domain/card/CardPattern.java new file mode 100644 index 00000000..1d612dd9 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardPattern.java @@ -0,0 +1,18 @@ +package blackjack.domain.card; + +public enum CardPattern { + DIAMOND("다이아몬드"), + CLOVER("클로버"), + HEART("하트"), + SPADE("스페이드"); + + private final String name; + + CardPattern(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/blackjack/domain/card/Cards.java b/src/main/java/blackjack/domain/card/Cards.java new file mode 100644 index 00000000..8e5ffed7 --- /dev/null +++ b/src/main/java/blackjack/domain/card/Cards.java @@ -0,0 +1,46 @@ +package blackjack.domain.card; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class Cards { + + private final static int BLACKJACK = 21; + private final List cards; + + public Cards(final List cards) { + this.cards = cards; + } + + private static int getScoreToSum(final int score1, final int score2) { + if ((score2 == CardNumber.ACE.getScore()) && (score1 + CardNumber.ACE.getScore() > 21)) { + return 1; + } + return score2; + } + + public void add(final Card card) { + cards.add(card); + } + + public boolean sum() { + return sumScore() >= BLACKJACK; + } + + public int sumScore() { + Comparator comparator = (a, b) -> b.getCardNumber().getScore() - a.getCardNumber() + .getScore(); + + List newCards = new ArrayList<>(cards); + newCards.sort(comparator); + + return newCards.stream() + .mapToInt(card -> card.getCardNumber().getScore()) + .reduce(0, (a, b) -> a + getScoreToSum(a, b)); + } + + public List getCards() { + return cards; + } +} \ No newline at end of file diff --git a/src/main/java/blackjack/domain/player/Dealer.java b/src/main/java/blackjack/domain/player/Dealer.java new file mode 100644 index 00000000..25efa019 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Dealer.java @@ -0,0 +1,17 @@ +package blackjack.domain.player; + +import blackjack.domain.state.Gameable; + +public class Dealer extends Person { + + private final Gameable cards; + + public Dealer(String name, Gameable cards) { + super(name); + this.cards = cards; + } + + public Gameable getCards() { + return cards; + } +} diff --git a/src/main/java/blackjack/domain/player/Person.java b/src/main/java/blackjack/domain/player/Person.java new file mode 100644 index 00000000..d2358cb9 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Person.java @@ -0,0 +1,14 @@ +package blackjack.domain.player; + +public abstract class Person { + + private final String name; + + public Person(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/blackjack/domain/player/Player.java b/src/main/java/blackjack/domain/player/Player.java new file mode 100644 index 00000000..5c4d63c6 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Player.java @@ -0,0 +1,17 @@ +package blackjack.domain.player; + +import blackjack.domain.state.Gameable; + +public class Player extends Person { + + private final Gameable cards; + + public Player(final String name, final Gameable cards) { + super(name); + this.cards = cards; + } + + public Gameable getCards() { + return cards; + } +} diff --git a/src/main/java/blackjack/domain/state/CardAddibleSupport.java b/src/main/java/blackjack/domain/state/CardAddibleSupport.java new file mode 100644 index 00000000..95d1a069 --- /dev/null +++ b/src/main/java/blackjack/domain/state/CardAddibleSupport.java @@ -0,0 +1,23 @@ +package blackjack.domain.state; + +import blackjack.domain.card.Card; +import blackjack.domain.card.Cards; + +public abstract class CardAddibleSupport implements Gameable { + + Cards cards; + + public CardAddibleSupport(Cards cards) { + this.cards = cards; + } + + @Override + public Cards cards() { + return cards; + } + + @Override + public void addCard(Card card) { + cards.add(card); + } +} diff --git a/src/main/java/blackjack/domain/state/Gameable.java b/src/main/java/blackjack/domain/state/Gameable.java new file mode 100644 index 00000000..139dd062 --- /dev/null +++ b/src/main/java/blackjack/domain/state/Gameable.java @@ -0,0 +1,15 @@ +package blackjack.domain.state; + +import blackjack.domain.card.Card; +import blackjack.domain.card.Cards; + +public interface Gameable { + + Cards cards(); + + void addCard(Card card); + + boolean isEnd(); + + Gameable judge(); +} \ No newline at end of file diff --git a/src/main/java/blackjack/domain/state/State.java b/src/main/java/blackjack/domain/state/State.java new file mode 100644 index 00000000..a1001037 --- /dev/null +++ b/src/main/java/blackjack/domain/state/State.java @@ -0,0 +1,20 @@ +package blackjack.domain.state; + +import blackjack.domain.card.Cards; + +public class State extends StateSupport { + + public State(Cards cards, boolean end) { + super(cards, end); + } + + @Override + public Gameable judge() { + if (cards.sum()) { + return new State(cards, false); + } + return new State(cards, true); + } +} + + diff --git a/src/main/java/blackjack/domain/state/StateSupport.java b/src/main/java/blackjack/domain/state/StateSupport.java new file mode 100644 index 00000000..2e1d5eff --- /dev/null +++ b/src/main/java/blackjack/domain/state/StateSupport.java @@ -0,0 +1,18 @@ +package blackjack.domain.state; + +import blackjack.domain.card.Cards; + +public abstract class StateSupport extends CardAddibleSupport { + + boolean end; + + public StateSupport(final Cards card, boolean end) { + super(card); + this.end = end; + } + + @Override + public boolean isEnd() { + return end; + } +} diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java new file mode 100644 index 00000000..1601e19c --- /dev/null +++ b/src/main/java/blackjack/view/InputView.java @@ -0,0 +1,30 @@ +package blackjack.view; + +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +public class InputView { + + private static final String PARTICIPANTS_MESSAGE = "게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"; + private static final String YES_OR_NO_MESSAGE = "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"; + private static final String SPLIT_DELIMITER = ","; + private static final Scanner SCANNER = new Scanner(System.in); + + public static List inputPlayers() { + String players = getInputValueWithMessage(PARTICIPANTS_MESSAGE); + return Arrays.stream(players.split(SPLIT_DELIMITER)) + .map(String::trim) + .collect(Collectors.toList()); + } + + public static String inputYesOrNo(String name) { + return getInputValueWithMessage(name + YES_OR_NO_MESSAGE); + } + + public static String getInputValueWithMessage(String message) { + System.out.println(message); + return SCANNER.nextLine().trim(); + } +} diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java new file mode 100644 index 00000000..383dd03f --- /dev/null +++ b/src/main/java/blackjack/view/OutputView.java @@ -0,0 +1,67 @@ +package blackjack.view; + +import blackjack.domain.Game; +import blackjack.domain.card.Card; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Person; +import blackjack.domain.player.Player; +import blackjack.domain.state.Gameable; +import java.util.List; +import java.util.stream.Collectors; + +public class OutputView { + + private static final String START_MESSAGE = "딜러와 %s 에게 2장을 나누었습니다.\n"; + private static final String CURRENT_STATE_MESSAGE = "%s 카드 : %s\n"; + private static final String RESULT_MESSAGE = "%s 카드 : %s - 결과: %s\n"; + private static final String GIVE_CARD_TO_DEALER_MESSAGE = "\n딜러는 16 이하라 한장의 카드를 더 받았습니다\n"; + private static final String DELIMITER = " : "; + private static final String JOIN_DELIMITER = ", "; + private static final int DEALER_FIRST_CARD_INDEX = 0; + + public static void printStartMessage(final Game game) { + System.out.printf(START_MESSAGE, game.getPlayers().stream() + .map(Person::getName) + .collect(Collectors.joining(JOIN_DELIMITER))); + } + + public static void printCurrentCardsState(final String name, final Gameable cards) { + System.out.printf(CURRENT_STATE_MESSAGE, name, + cards.cards().getCards().stream().map(Card::toString) + .collect(Collectors.joining(JOIN_DELIMITER))); + } + + public static void printResult(final String name, final List cards, final int score) { + System.out.printf(RESULT_MESSAGE, name, cards.stream().map(Card::toString) + .collect(Collectors.joining(JOIN_DELIMITER)), score); + } + + public static void printGameResults(Dealer dealer, List players) { + printResult(dealer.getName(), dealer.getCards().cards().getCards(), + dealer.getCards().cards().sumScore() + ); + + players.forEach(player -> printResult(player.getName(), + player.getCards().cards().getCards(), + player.getCards().cards().sumScore()) + ); + } + + public static void printDealerCard(final Dealer dealer) { + System.out.println(dealer.getName() + DELIMITER + dealer.getCards().cards().getCards() + .get(DEALER_FIRST_CARD_INDEX)); + } + + public static void printPlayerCard(final List players) { + players.forEach( + player -> OutputView.printCurrentCardsState(player.getName(), player.getCards())); + } + + public static void printMessageToGiveCardToDealer() { + System.out.println(GIVE_CARD_TO_DEALER_MESSAGE); + } + + public static void printGameWinOrLose(Person person, List gameResult) { + System.out.printf("%s : %d승 %d패%n", person.getName(), gameResult.get(0), gameResult.get(1)); + } +} diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/rentcar/Application.java b/src/main/java/rentcar/Application.java new file mode 100644 index 00000000..f9e63123 --- /dev/null +++ b/src/main/java/rentcar/Application.java @@ -0,0 +1,10 @@ +package rentcar; + +import rentcar.controller.Controller; + +public class Application { + + public static void main(String[] args) { + Controller.run(); + } +} diff --git a/src/main/java/rentcar/controller/Controller.java b/src/main/java/rentcar/controller/Controller.java new file mode 100644 index 00000000..54b6ad2c --- /dev/null +++ b/src/main/java/rentcar/controller/Controller.java @@ -0,0 +1,22 @@ +package rentcar.controller; + +import java.util.List; +import java.util.stream.IntStream; +import rentcar.domain.RentCar; +import rentcar.domain.RentCompany; +import rentcar.view.InputView; +import rentcar.view.OutputView; + +public class Controller { + + public static void run() { + List rentCar = InputView.inputRentCar(); + List distance = InputView.inputDistance(); + + RentCompany company = RentCompany.create(); + IntStream.range(0, rentCar.size()) + .forEach(idx -> company.addCar(RentCar.of(rentCar.get(idx), distance.get(idx)))); + + OutputView.printReport(company.generateReport()); + } +} diff --git a/src/main/java/rentcar/domain/Avante.java b/src/main/java/rentcar/domain/Avante.java new file mode 100644 index 00000000..9e3b5632 --- /dev/null +++ b/src/main/java/rentcar/domain/Avante.java @@ -0,0 +1,27 @@ +package rentcar.domain; + +public class Avante extends Car { + + private static final String CAR_NAME = "Avante"; + private static final double DISTANCE_PER_LITER = 15; + private final double distance; + + public Avante(final double distance) { + this.distance = distance; + } + + @Override + double getDistancePerLiter() { + return DISTANCE_PER_LITER; + } + + @Override + double getTripDistance() { + return distance; + } + + @Override + String getName() { + return CAR_NAME; + } +} diff --git a/src/main/java/rentcar/domain/Car.java b/src/main/java/rentcar/domain/Car.java new file mode 100644 index 00000000..3cf7d03f --- /dev/null +++ b/src/main/java/rentcar/domain/Car.java @@ -0,0 +1,27 @@ +package rentcar.domain; + +public abstract class Car { + + /** + * 리터당 이동 거리. 즉, 연비 + */ + abstract double getDistancePerLiter(); + + /** + * 여행하려는 거리 + */ + abstract double getTripDistance(); + + /** + * 차종의 이름 + */ + abstract String getName(); + + /** + * 주입해야할 연료량을 구한다. + */ + double getChargeQuantity() { + return getTripDistance() / getDistancePerLiter(); + } +} + diff --git a/src/main/java/rentcar/domain/K5.java b/src/main/java/rentcar/domain/K5.java new file mode 100644 index 00000000..f0c45d6c --- /dev/null +++ b/src/main/java/rentcar/domain/K5.java @@ -0,0 +1,27 @@ +package rentcar.domain; + +public class K5 extends Car { + + private static final String CAR_NAME = "K5"; + private static final double DISTANCE_PER_LITER = 13; + private final double distance; + + public K5(final double distance) { + this.distance = distance; + } + + @Override + double getDistancePerLiter() { + return DISTANCE_PER_LITER; + } + + @Override + double getTripDistance() { + return distance; + } + + @Override + String getName() { + return CAR_NAME; + } +} diff --git a/src/main/java/rentcar/domain/RentCar.java b/src/main/java/rentcar/domain/RentCar.java new file mode 100644 index 00000000..292e7332 --- /dev/null +++ b/src/main/java/rentcar/domain/RentCar.java @@ -0,0 +1,29 @@ +package rentcar.domain; + +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Function; + +public enum RentCar { + SONATA("Sonata", Sonata::new), + AVANTE("Avante", Avante::new), + K5("K5", K5::new); + + private final String rentCarName; + private final Function function; + + RentCar(String rentCarName, final Function function) { + this.rentCarName = rentCarName; + this.function = function; + } + + public static Car of(final String rentCarName, final double distance) { + return (Car) Objects.requireNonNull(Arrays.stream(values()) + .filter(car -> Objects.equals(car.rentCarName, rentCarName)) + .findAny().orElse(null)).apply(distance); + } + + private Object apply(final double distance) { + return function.apply(distance); + } +} \ No newline at end of file diff --git a/src/main/java/rentcar/domain/RentCompany.java b/src/main/java/rentcar/domain/RentCompany.java new file mode 100644 index 00000000..6cd37860 --- /dev/null +++ b/src/main/java/rentcar/domain/RentCompany.java @@ -0,0 +1,41 @@ +package rentcar.domain; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class RentCompany { + + private static final String DELIMITER = " : "; + private static final String LITER = "리터"; + private static final String NEW_LINE = "\n"; + + private final List cars; + + private RentCompany() { + this.cars = new ArrayList<>(); + } + + public static RentCompany create() { + return new RentCompany(); + } + + public void addCar(Car car) { + cars.add(car); + } + + public String generateReport() { + return cars.stream() + .map(this::getCarInfo) + .collect(Collectors.joining(NEW_LINE)); + } + + public String getCarInfo(Car car) { + return car.getName() + DELIMITER + (int) car.getChargeQuantity() + LITER; + } + + public List cars() { + return Collections.unmodifiableList(cars); + } +} diff --git a/src/main/java/rentcar/domain/Sonata.java b/src/main/java/rentcar/domain/Sonata.java new file mode 100644 index 00000000..ba60e848 --- /dev/null +++ b/src/main/java/rentcar/domain/Sonata.java @@ -0,0 +1,27 @@ +package rentcar.domain; + +public class Sonata extends Car { + + private static final String CAR_NAME = "Sonata"; + private static final double DISTANCE_PER_LITER = 10; + private final double distance; + + public Sonata(final double distance) { + this.distance = distance; + } + + @Override + double getDistancePerLiter() { + return DISTANCE_PER_LITER; + } + + @Override + double getTripDistance() { + return distance; + } + + @Override + String getName() { + return CAR_NAME; + } +} diff --git a/src/main/java/rentcar/view/InputView.java b/src/main/java/rentcar/view/InputView.java new file mode 100644 index 00000000..26a663f2 --- /dev/null +++ b/src/main/java/rentcar/view/InputView.java @@ -0,0 +1,29 @@ +package rentcar.view; + +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +public class InputView { + + private static final Scanner SCANNER = new Scanner(System.in); + private static final String RENT_CAR_TYPE_MESSAGE = "Sonata, K5, Avante 중 렌트할 차 타입을 콤마(,) 기준으로 연속해서 입력해주세요."; + private static final String RENT_CAR_DISTANCE_MESSAGE = "차량별 이동거리를 입력해주세요."; + + + public static List inputRentCar() { + System.out.println(RENT_CAR_TYPE_MESSAGE); + return Arrays.stream(SCANNER.nextLine().split(",")) + .map(String::trim) + .collect(Collectors.toList()); + } + + public static List inputDistance() { + System.out.println(RENT_CAR_DISTANCE_MESSAGE); + return Arrays.stream(SCANNER.nextLine().split(",")) + .map(String::trim) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/rentcar/view/OutputView.java b/src/main/java/rentcar/view/OutputView.java new file mode 100644 index 00000000..46abdd86 --- /dev/null +++ b/src/main/java/rentcar/view/OutputView.java @@ -0,0 +1,10 @@ +package rentcar.view; + +; + +public class OutputView { + + public static void printReport(String rentCarReport) { + System.out.println(rentCarReport); + } +} diff --git a/src/test/java/blackjack/domain/DealerTest.java b/src/test/java/blackjack/domain/DealerTest.java new file mode 100644 index 00000000..d0801b33 --- /dev/null +++ b/src/test/java/blackjack/domain/DealerTest.java @@ -0,0 +1,23 @@ +package blackjack.domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import blackjack.domain.card.CardDeck; +import blackjack.domain.player.Dealer; +import blackjack.domain.state.State; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class DealerTest { + + @DisplayName("딜러_생성_테스트") + @Test + void createDealerTest() { + Dealer dealer = new Dealer("딜러", new State(CardDeck.pop(2), true)); + assertAll( + () -> assertThat(dealer.getName()).isEqualTo("딜러"), + () -> assertThat(dealer).isNotNull() + ); + } +} \ No newline at end of file diff --git a/src/test/java/blackjack/domain/GameTest.java b/src/test/java/blackjack/domain/GameTest.java new file mode 100644 index 00000000..1f6f3a0c --- /dev/null +++ b/src/test/java/blackjack/domain/GameTest.java @@ -0,0 +1,36 @@ +package blackjack.domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class GameTest { + + @DisplayName("Game_생성_테스트") + @Test + void createGameTest() { + List playerNames = Arrays.stream("pobi, jason".split(",")) + .map(String::trim) + .collect(Collectors.toList()); + Game game = new Game(playerNames); + assertAll( + () -> assertThat(game.getPlayers()).isNotNull(), + () -> assertThat(game.getDealer()).isNotNull() + ); + } + + @DisplayName("가진 카드가 16 이하일 때 딜러에게 카드 전달 테스트") + @Test + void giveCardToDealerTest() { + List playerNames = Arrays.stream("pobi, jason".split(",")) + .map(String::trim) + .collect(Collectors.toList()); + Game game = new Game(playerNames); + assertThat(game.giveCardToDealer()).isNotNull(); // Fix + } +} \ No newline at end of file diff --git a/src/test/java/blackjack/domain/PlayerTest.java b/src/test/java/blackjack/domain/PlayerTest.java new file mode 100644 index 00000000..e878922b --- /dev/null +++ b/src/test/java/blackjack/domain/PlayerTest.java @@ -0,0 +1,23 @@ +package blackjack.domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import blackjack.domain.card.CardDeck; +import blackjack.domain.player.Player; +import blackjack.domain.state.State; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PlayerTest { + + @DisplayName("플레이어_생성_테스트") + @Test + void createPlayer() { + Player player = new Player("pobi", new State(CardDeck.pop(2), true)); + assertAll( + () -> assertThat(player.getName()).isEqualTo("pobi"), + () -> assertThat(player).isNotNull() + ); + } +} \ No newline at end of file diff --git a/src/test/java/blackjack/domain/WinnerTest.java b/src/test/java/blackjack/domain/WinnerTest.java new file mode 100644 index 00000000..3c48e2b5 --- /dev/null +++ b/src/test/java/blackjack/domain/WinnerTest.java @@ -0,0 +1,75 @@ +package blackjack.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import blackjack.domain.card.Card; +import blackjack.domain.card.CardNumber; +import blackjack.domain.card.CardPattern; +import blackjack.domain.card.Cards; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; +import blackjack.domain.state.State; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class WinnerTest { + + @DisplayName("딜러 게임 승패 여부 테스트") + @Test + void calculateDealerGameResultTest() { + Dealer dealer = new Dealer("딜러", + new State(new Cards(Arrays.asList( + new Card(CardNumber.ACE, CardPattern.CLOVER), + new Card(CardNumber.NINE, CardPattern.CLOVER)) + ), true)); + List players = Arrays.asList( + new Player("pobi", new State(new Cards(Arrays.asList( + new Card(CardNumber.TWO, CardPattern.HEART), + new Card(CardNumber.THREE, CardPattern.DIAMOND)) + ), true)), + new Player("jason", new State(new Cards(Arrays.asList( + new Card(CardNumber.ACE, CardPattern.DIAMOND), + new Card(CardNumber.TWO, CardPattern.CLOVER)) + ), true)) + ); + + Game game = new Game(dealer, players); + Winner winner = new Winner(game); + List result = winner.calculateDealerGameResult(); + assertAll( + () -> assertThat(result.get(0)).isEqualTo(2), + () -> assertThat(result.get(1)).isEqualTo(0) + ); + } + + @DisplayName("플레이어 게임 승패 여부 테스트") + @Test + void calculatePlayerGameResultTest() { + Dealer dealer = new Dealer("딜러", + new State(new Cards(Arrays.asList( + new Card(CardNumber.ACE, CardPattern.CLOVER), + new Card(CardNumber.NINE, CardPattern.CLOVER)) + ), true)); + List players = Arrays.asList( + new Player("pobi", new State(new Cards(Arrays.asList( + new Card(CardNumber.TWO, CardPattern.HEART), + new Card(CardNumber.THREE, CardPattern.DIAMOND)) + ), true)), + new Player("jason", new State(new Cards(Arrays.asList( + new Card(CardNumber.ACE, CardPattern.DIAMOND), + new Card(CardNumber.TWO, CardPattern.CLOVER)) + ), true)) + ); + + Game game = new Game(dealer, players); + Winner winner = new Winner(game); + List result = winner.calculatePlayerGameResult(players.get(0)); + assertAll( + () -> assertThat(result.get(0)).isEqualTo(0), + () -> assertThat(result.get(1)).isEqualTo(1) + ); + } +} \ No newline at end of file diff --git a/src/test/java/blackjack/domain/card/CardDeckTest.java b/src/test/java/blackjack/domain/card/CardDeckTest.java new file mode 100644 index 00000000..df08f517 --- /dev/null +++ b/src/test/java/blackjack/domain/card/CardDeckTest.java @@ -0,0 +1,15 @@ +package blackjack.domain.card; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CardDeckTest { + + @Test + @DisplayName("CardDeck 생성 테스트") + void createCardDeckTest() { + assertThat(CardDeck.getCards().size()).isEqualTo(48); + } +} \ No newline at end of file diff --git a/src/test/java/blackjack/domain/card/CardTest.java b/src/test/java/blackjack/domain/card/CardTest.java new file mode 100644 index 00000000..eadd493c --- /dev/null +++ b/src/test/java/blackjack/domain/card/CardTest.java @@ -0,0 +1,16 @@ +package blackjack.domain.card; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CardTest { + + @DisplayName("카드 객체 생성 테스트") + @Test + void createCardTest() { + Card card = new Card(CardNumber.ACE, CardPattern.CLOVER); + assertThat(card.toString()).isEqualTo("A클로버"); + } +} \ No newline at end of file diff --git a/src/test/java/blackjack/domain/card/CardsTest.java b/src/test/java/blackjack/domain/card/CardsTest.java new file mode 100644 index 00000000..5e3af9e5 --- /dev/null +++ b/src/test/java/blackjack/domain/card/CardsTest.java @@ -0,0 +1,36 @@ +package blackjack.domain.card; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.Arrays; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CardsTest { + + @DisplayName("Cards 객체 생성 테스트") + @Test + void createCardsTest() { + Cards cards = new Cards(Arrays.asList( + new Card(CardNumber.ACE, CardPattern.CLOVER), + new Card(CardNumber.KING, CardPattern.HEART), + new Card(CardNumber.NINE, CardPattern.DIAMOND)) + ); + assertAll( + () -> assertThat(cards).isNotNull(), + () -> assertThat(cards.getCards().size()).isEqualTo(3) + ); + } + + @DisplayName("Cards 점수 계산 테스트") + @Test + void sumScoresOfCardsTest() { + Cards cards = new Cards(Arrays.asList( + new Card(CardNumber.TWO, CardPattern.CLOVER), + new Card(CardNumber.KING, CardPattern.HEART), + new Card(CardNumber.NINE, CardPattern.DIAMOND)) + ); + assertThat(cards.sumScore()).isEqualTo(21); + } +} \ No newline at end of file diff --git a/src/test/java/empty.txt b/src/test/java/empty.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/test/java/rentcar/domain/CarTest.java b/src/test/java/rentcar/domain/CarTest.java new file mode 100644 index 00000000..c4ef3ffb --- /dev/null +++ b/src/test/java/rentcar/domain/CarTest.java @@ -0,0 +1,23 @@ +package rentcar.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CarTest { + + @DisplayName("자동차_생성_테스트") + @Test + void createRentCarTest() { + Car Sonata = new Sonata(150); + Car K5 = new K5(260); + Car Avante = new Avante(300); + assertAll( + () -> assertThat(Sonata.getChargeQuantity()).isEqualTo(15), + () -> assertThat(K5.getChargeQuantity()).isEqualTo(20), + () -> assertThat(Avante.getChargeQuantity()).isEqualTo(20) + ); + } +} \ No newline at end of file diff --git a/src/test/java/rentcar/domain/RentCarTest.java b/src/test/java/rentcar/domain/RentCarTest.java new file mode 100644 index 00000000..3ba1d4cb --- /dev/null +++ b/src/test/java/rentcar/domain/RentCarTest.java @@ -0,0 +1,27 @@ +package rentcar.domain; + + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class RentCarTest { + + + @DisplayName("자동차_타입_생성_테스트") + @Test + void createRentCarTest() { + List rentCar = Arrays.asList("Sonata", "K5", "Sonata", "Avante", "K5"); + List distance = Arrays.asList(150, 260, 120, 300, 390); + + IntStream.range(0, 5) + .forEach(idx -> + assertThat(RentCar.of(rentCar.get(idx), distance.get(idx)).getName()).isEqualTo( + rentCar.get(idx)) + ); + } +} \ No newline at end of file diff --git a/src/test/java/rentcar/domain/RentCompanyTest.java b/src/test/java/rentcar/domain/RentCompanyTest.java new file mode 100644 index 00000000..e2d789e3 --- /dev/null +++ b/src/test/java/rentcar/domain/RentCompanyTest.java @@ -0,0 +1,51 @@ +package rentcar.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class RentCompanyTest { + + private static final String NEWLINE = System.getProperty("line.separator"); + + @DisplayName("RentCompany_객체_생성_테스트") + @Test + public void createRentCarTest() { + RentCompany company = RentCompany.create(); + assertThat(company).isNotNull(); + } + + @DisplayName("RentCompany_Car_추가_테스트") + @Test + public void addCarTest() { + RentCompany company = RentCompany.create(); + company.addCar(new Sonata(150)); + company.addCar(new Sonata(150)); + company.addCar(new K5(260)); + company.addCar(new Sonata(120)); + company.addCar(new Avante(300)); + company.addCar(new K5(390)); + assertThat(company.cars().size()).isEqualTo(6); + } + + @DisplayName("RentCompany_레포트_생성_테스트") + @Test + public void generateReportTest() { + RentCompany company = RentCompany.create(); // factory method를 사용해 생성 + company.addCar(new Sonata(150)); + company.addCar(new K5(260)); + company.addCar(new Sonata(120)); + company.addCar(new Avante(300)); + company.addCar(new K5(390)); + + String report = company.generateReport(); + assertThat(report).isEqualTo( + "Sonata : 15리터" + NEWLINE + + "K5 : 20리터" + NEWLINE + + "Sonata : 12리터" + NEWLINE + + "Avante : 20리터" + NEWLINE + + "K5 : 30리터" + ); + } +} \ No newline at end of file