diff --git a/README.md b/README.md
index 3bcfc25784..26a14be9b8 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,78 @@
블랙잭 게임 미션 저장소
## 우아한테크코스 코드리뷰
-* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)
\ No newline at end of file
+* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)
+
+
+
+## 기능 구현 목록
+- 참가자 추상 클래스 구현
+ - 플레이어 구현
+ - 손에 카드를 가지고 있다
+ - 카드를 받는다, 안받는다
+ - [x] y, n 이 아닌 다른 값 입력
+ - [x] 공백 또는 NULL
+ - 이름을 가지고 있는다
+ - [x] 공백 또는 NULL
+ - 딜러 구현
+ - 손에 카드를 가지고 있다
+ - 점수 총합이 16 이하일시 카드를 받는다
+ - 카드를 플레이어들에게 나눠준다
+- 카드덱 구현 Deque
+ - 카드 구현 Card 클래스
+ - 카드 숫자 Enum
+ - 카드 무늬 Enum
+ -
+- 블랙잭 구현
+ - 플레이어들의 이름을 받는다
+ - [x] 플레이어의 이름 개수가 7개 초과
+ - 점수를 계산하여 승자를 판단한다
+ - 점수가 21을 초과할 경우 패배시킨다
+
+
+
+## 테스트 구상 목록
+- 카드덱 뭉치
+ - [x] 사이즈가 52인지
+ - [x] 중복 카드가 입력 되었는지
+ - [x] 무늬별 13장씩 있는지
+ - [x] 무늬가 총 4개로 분류되는지
+ - [x] 덱에서 카드가 잘 나오는지
+- 카드
+ - [x] 카드가 잘 생성 되는지
+- 승패 테스트
+ - [x] 플레이어 승패 잘 판단되는지
+ - [x] 딜러 승패 잘 반환 되는지
+
+
+
+## 질문 리스트
+- 카드 셔플을 딜러가 아닌 카드가 해도 되는지
+- 제네레이터 클래스를 만든것에 대해.
+- Number Enum 클래스가 번호별 출력양식을 가진 것에 대하여.
+ - 만일 OutputView 쪽에서 Enum별 출력 양식을 가지면 그건 도메인 역할을 침범하는게 아닌가?
+
+
+
+## 리팩토링 구상 목록
+- `BlackjackManager`가 꼭 유틸 클래스일 필요가 있는가?
+ - `BlackjackManager` 가 꼭 유틸 클래스이지 말라는 법은 없지만, 꼭 유틸 클래스일 필요도 없다.
+ - 게다가, 대부분의 경우 유틸 클래스를 지양하라는 피드백을 받았었다.
+ - 대안 1. `BlackjackManager` 클래스를 제거한다.
+ - 미립이 `BlackjackManager` 존재의 필요성에 대해 의문을 표시해주셨다.
+ - "현재 컨트롤러가 `BlackjackManager`의 역할을 모두 수행하고 있는 것이 아닌가?"
+ - 대안 2. `BlackjackManager`가 덱을 갖도록 한다.
+ - 딜러가 카드를 꼭 나눠줄 필요가 없다. 객체지향은 현실세계 모방일뿐.
+ - 카드가 직접 딜러와 플레이어에게 나눠주는 행동을 하자.
+
+- Dto 변경
+ - `BlackjackManager` 를 서비스레이어처럼 생각하고 Dto를 만드는 역할 추가
+
+- 블랙잭 승패 비교를 GameResult Enum 클래스가 아닌 딜러가 하도록
+
+- `InputView` 이름 파싱 조금 더 여유롭게 (정규표현식 사용)
+
+- Controller 쪽으로 Player, Players, Dealer가 빠져나가지 않도록
+ - 핵심은 `BlackjackManager` 혹은 `Players` 쪽에 현재 플레이어를 기억할 방법을 찾는 것.
+
+- 도메인(`BlackjackManager`)이 Dto 로직을 모르도록
diff --git a/src/main/java/blackjack/Application.java b/src/main/java/blackjack/Application.java
new file mode 100644
index 0000000000..524cbbd98a
--- /dev/null
+++ b/src/main/java/blackjack/Application.java
@@ -0,0 +1,11 @@
+package blackjack;
+
+import blackjack.controller.BlackjackController;
+
+public class Application {
+
+ public static void main(String[] args) {
+ BlackjackController blackjackController = new BlackjackController();
+ blackjackController.play();
+ }
+}
diff --git a/src/main/java/blackjack/controller/BlackjackController.java b/src/main/java/blackjack/controller/BlackjackController.java
new file mode 100644
index 0000000000..74d7ff9e2c
--- /dev/null
+++ b/src/main/java/blackjack/controller/BlackjackController.java
@@ -0,0 +1,84 @@
+package blackjack.controller;
+
+import blackjack.domain.BlackjackManager;
+import blackjack.domain.DtoAssembler;
+import blackjack.domain.participant.Dealer;
+import blackjack.domain.participant.Players;
+import blackjack.view.InputView;
+import blackjack.view.OutputView;
+import blackjack.view.dto.ParticipantDto;
+import blackjack.view.dto.ResultDto;
+import java.util.List;
+
+public class BlackjackController {
+
+ public void play() {
+ Dealer dealer = new Dealer();
+ Players players = new Players(InputView.getPlayerNames());
+ BlackjackManager blackjackManager = new BlackjackManager(dealer, players);
+
+ initDrawCardsDealerAndAllPlayers(blackjackManager);
+ hitOrStayAllPlayers(blackjackManager);
+ hitDealerUntilOverLimitScore(blackjackManager);
+ printCardsWithScoreOfDealerAndAllPlayers(blackjackManager);
+ printBlackjackResult(blackjackManager);
+ }
+
+ private void initDrawCardsDealerAndAllPlayers(BlackjackManager blackjackManager) {
+ blackjackManager.initDrawCards();
+ ParticipantDto dealerInitStatus = DtoAssembler
+ .createDealerInitStatusDto(blackjackManager.getDealer());
+ List playerStatuses = DtoAssembler
+ .createPlayerStatusDtos(blackjackManager.getPlayers());
+ OutputView.printInitStatuses(dealerInitStatus, playerStatuses);
+ }
+
+ private void hitOrStayAllPlayers(BlackjackManager blackjackManager) {
+ while (!blackjackManager.isFinishedAllPlayers()) {
+ hitOrStayCurrentPlayer(blackjackManager);
+ blackjackManager.passTurnToNextPlayer();
+ }
+ blackjackManager.passTurnToNextPlayer();
+ }
+
+ private void hitOrStayCurrentPlayer(BlackjackManager blackjackManager) {
+ if (!blackjackManager.isFinishedCurrentPlayer()) {
+ blackjackManager.hitOrStayCurrentPlayer(
+ InputView.getHitOrStay(blackjackManager.getCurrentPlayerName()));
+ OutputView.printPlayerStatus(
+ DtoAssembler.createPlayerStatusDto(blackjackManager.getCurrentPlayer()));
+ }
+ }
+
+ private void hitDealerUntilOverLimitScore(BlackjackManager blackjackManager) {
+ OutputView.printNewLine();
+ while (!blackjackManager.isFinishedDealer()) {
+ hitOrStayDealer(blackjackManager);
+ }
+ OutputView.printNewLine();
+ }
+
+ private void hitOrStayDealer(BlackjackManager blackjackManager) {
+ if (blackjackManager.isDealerScoreOverThenLimit()) {
+ blackjackManager.stayDealer();
+ return;
+ }
+ blackjackManager.hitDealer();
+ OutputView.printDealerHit();
+ }
+
+ private void printCardsWithScoreOfDealerAndAllPlayers(BlackjackManager blackjackManager) {
+ OutputView
+ .printStatusWithScore(DtoAssembler.createDealerStatusDto(blackjackManager.getDealer()));
+ DtoAssembler.createPlayerStatusDtos(blackjackManager.getPlayers())
+ .forEach(OutputView::printStatusWithScore);
+ }
+
+ private void printBlackjackResult(BlackjackManager blackjackManager) {
+ Dealer dealer = blackjackManager.getDealer();
+ Players players = blackjackManager.getPlayers();
+ ResultDto dealerResult = DtoAssembler.createDealerResultDto(dealer, players);
+ List playerResultDtos = DtoAssembler.createPlayerResultDtos(dealer, players);
+ OutputView.printBlackjackResult(dealerResult, playerResultDtos);
+ }
+}
diff --git a/src/main/java/blackjack/domain/BlackjackManager.java b/src/main/java/blackjack/domain/BlackjackManager.java
new file mode 100644
index 0000000000..759f88df7b
--- /dev/null
+++ b/src/main/java/blackjack/domain/BlackjackManager.java
@@ -0,0 +1,80 @@
+package blackjack.domain;
+
+import blackjack.domain.carddeck.CardDeck;
+import blackjack.domain.participant.Dealer;
+import blackjack.domain.participant.Player;
+import blackjack.domain.participant.Players;
+
+public class BlackjackManager {
+
+ private final CardDeck cardDeck;
+ private final Dealer dealer;
+ private final Players players;
+
+ public BlackjackManager(final Dealer dealer, final Players players) {
+ this(CardDeck.newShuffledDeck(), dealer, players);
+ }
+
+ public BlackjackManager(final CardDeck cardDeck, final Dealer dealer, final Players players) {
+ this.cardDeck = cardDeck;
+ this.dealer = dealer;
+ this.players = players;
+ }
+
+ public void initDrawCards() {
+ this.dealer.initDraw(this.cardDeck);
+ this.players.initDraw(this.cardDeck);
+ }
+
+ public void hitOrStayCurrentPlayer(boolean isPlayerHit) {
+ if (isPlayerHit) {
+ this.players.drawFirstOrderPlayer(this.cardDeck.draw());
+ return;
+ }
+ this.players.stayFirstOrderPlayer();
+ }
+
+ public void passTurnToNextPlayer() {
+ this.players.passTurnToNextPlayer();
+ }
+
+ public boolean isFinishedCurrentPlayer() {
+ return this.players.isFinishedCurrentPlayer();
+ }
+
+ public boolean isFinishedAllPlayers() {
+ return this.players.isAllPlayerFinished();
+ }
+
+ public void hitDealer() {
+ this.dealer.draw(this.cardDeck.draw());
+ }
+
+ public void stayDealer() {
+ this.dealer.stay();
+ }
+
+ public boolean isDealerScoreOverThenLimit() {
+ return this.dealer.isOverThenLimitScore();
+ }
+
+ public boolean isFinishedDealer() {
+ return this.dealer.isFinished();
+ }
+
+ public Players getPlayers() {
+ return this.players;
+ }
+
+ public Player getCurrentPlayer() {
+ return this.players.getFirstOrderPlayer();
+ }
+
+ public String getCurrentPlayerName() {
+ return this.players.getFirstOrderPlayerName();
+ }
+
+ public Dealer getDealer() {
+ return this.dealer;
+ }
+}
diff --git a/src/main/java/blackjack/domain/DtoAssembler.java b/src/main/java/blackjack/domain/DtoAssembler.java
new file mode 100644
index 0000000000..8f59744988
--- /dev/null
+++ b/src/main/java/blackjack/domain/DtoAssembler.java
@@ -0,0 +1,85 @@
+package blackjack.domain;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.participant.Dealer;
+import blackjack.domain.participant.Player;
+import blackjack.domain.participant.Players;
+import blackjack.view.dto.CardDto;
+import blackjack.view.dto.ParticipantDto;
+import blackjack.view.dto.ResultDto;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class DtoAssembler {
+
+ private static final String DELIMITER = ", ";
+
+ public static ParticipantDto createDealerInitStatusDto(final Dealer dealer) {
+ return new ParticipantDto(
+ createCardDtos(dealer.getInitCard()),
+ dealer.getScoreToInt()
+ );
+ }
+
+ public static ParticipantDto createDealerStatusDto(Dealer dealer) {
+ return new ParticipantDto(
+ createCardDtos(dealer.getCards()),
+ dealer.getScoreToInt()
+ );
+ }
+
+ public static List createPlayerStatusDtos(final Players players) {
+ return players.toList()
+ .stream()
+ .map(DtoAssembler::createPlayerStatusDto)
+ .collect(Collectors.toList())
+ ;
+ }
+
+ public static ParticipantDto createPlayerStatusDto(final Player player) {
+ return new ParticipantDto(
+ player.getName(),
+ createCardDtos(player.getCards()),
+ player.getScoreToInt()
+ );
+ }
+
+ private static List createCardDtos(final List cards) {
+ return cards.stream()
+ .map(card -> new CardDto(card.getNumberName() + card.getPatternName()))
+ .collect(Collectors.toList())
+ ;
+ }
+
+ public static ResultDto createDealerResultDto(final Dealer dealer, Players players) {
+ List results = getResults(dealer, players);
+ return new ResultDto(
+ getResultString(results, Result.WIN) + DELIMITER
+ + getResultString(results, Result.LOSE) + DELIMITER
+ + getResultString(results, Result.DRAW)
+ );
+ }
+
+ private static List getResults(final Dealer dealer, final Players players) {
+ return players.toList()
+ .stream()
+ .map(player -> player.judgeByDealerState(dealer))
+ .map(Result::reverse)
+ .collect(Collectors.toList());
+ }
+
+ private static String getResultString(final List results, final Result result) {
+ return results.stream()
+ .filter(compareResult -> compareResult.equals(result))
+ .count() + result.getResult();
+ }
+
+ public static List createPlayerResultDtos(final Dealer dealer,
+ final Players players) {
+ return players.toList()
+ .stream()
+ .map(player -> new ResultDto(player.getName(),
+ player.judgeByDealerState(dealer).getResult()))
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/blackjack/domain/Result.java b/src/main/java/blackjack/domain/Result.java
new file mode 100644
index 0000000000..8db9919c87
--- /dev/null
+++ b/src/main/java/blackjack/domain/Result.java
@@ -0,0 +1,28 @@
+package blackjack.domain;
+
+public enum Result {
+
+ WIN("승"),
+ LOSE("패"),
+ DRAW("무");
+
+ private final String result;
+
+ Result(final String result) {
+ this.result = result;
+ }
+
+ public Result reverse() {
+ if (this == WIN) {
+ return LOSE;
+ }
+ if (this == LOSE) {
+ return WIN;
+ }
+ return DRAW;
+ }
+
+ public String getResult() {
+ return this.result;
+ }
+}
diff --git a/src/main/java/blackjack/domain/carddeck/Card.java b/src/main/java/blackjack/domain/carddeck/Card.java
new file mode 100644
index 0000000000..ce09f59420
--- /dev/null
+++ b/src/main/java/blackjack/domain/carddeck/Card.java
@@ -0,0 +1,83 @@
+package blackjack.domain.carddeck;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class Card {
+
+ private static final List CACHE_DECK = new ArrayList<>();
+
+ static {
+ for (Pattern pattern : Pattern.values()) {
+ for (Number number : Number.values()) {
+ CACHE_DECK.add(new Card(pattern, number));
+ }
+ }
+ }
+
+ private final Pattern pattern;
+ private final Number number;
+
+ private Card(final Pattern pattern, final Number number) {
+ this.pattern = pattern;
+ this.number = number;
+ }
+
+ public static Card valueOf(final Pattern pattern, final Number number) {
+ Card card = CACHE_DECK.stream()
+ .filter(cardPatterns -> cardPatterns.hasPattern(pattern))
+ .filter(cardNumbers -> cardNumbers.hasNumber(number))
+ .findAny()
+ .get();
+ if (Objects.isNull(card)) {
+ throw new IllegalArgumentException("해당 카드가 존재하지 않습니다.");
+ }
+ return card;
+ }
+
+ public static List generate() {
+ return new ArrayList<>(CACHE_DECK);
+ }
+
+ private boolean hasNumber(final Number number) {
+ return this.number.equals(number);
+ }
+
+ private boolean hasPattern(final Pattern pattern) {
+ return this.pattern.equals(pattern);
+ }
+
+ public boolean isAce() {
+ return this.number.isAce();
+ }
+
+ public int getScore() {
+ return this.number.getScore();
+ }
+
+ public String getPatternName() {
+ return this.pattern.getPattern();
+ }
+
+ public String getNumberName() {
+ return this.number.getName();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Card card = (Card) o;
+ return pattern == card.pattern && number == card.number;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(pattern, number);
+ }
+}
diff --git a/src/main/java/blackjack/domain/carddeck/CardDeck.java b/src/main/java/blackjack/domain/carddeck/CardDeck.java
new file mode 100644
index 0000000000..2ec61f73f4
--- /dev/null
+++ b/src/main/java/blackjack/domain/carddeck/CardDeck.java
@@ -0,0 +1,29 @@
+package blackjack.domain.carddeck;
+
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.List;
+
+public class CardDeck {
+
+ private final Deque deck;
+
+ private CardDeck(final Deque cards) {
+ this.deck = cards;
+ }
+
+ public static CardDeck newShuffledDeck() {
+ List cards = Card.generate();
+ Collections.shuffle(cards);
+ return new CardDeck(new ArrayDeque<>(cards));
+ }
+
+ public static CardDeck customDeck(final List cards) {
+ return new CardDeck(new ArrayDeque<>(cards));
+ }
+
+ public Card draw() {
+ return this.deck.pop();
+ }
+}
diff --git a/src/main/java/blackjack/domain/carddeck/Number.java b/src/main/java/blackjack/domain/carddeck/Number.java
new file mode 100644
index 0000000000..799cb0abf6
--- /dev/null
+++ b/src/main/java/blackjack/domain/carddeck/Number.java
@@ -0,0 +1,37 @@
+package blackjack.domain.carddeck;
+
+public enum Number {
+ ACE(11, "A"),
+ TWO(2, "2"),
+ THREE(3, "3"),
+ FOUR(4, "4"),
+ FIVE(5, "5"),
+ SIX(6, "6"),
+ SEVEN(7, "7"),
+ EIGHT(8, "8"),
+ NINE(9, "9"),
+ TEN(10, "10"),
+ JACK(10, "J"),
+ QUEEN(10, "Q"),
+ KING(10, "K");
+
+ private final int score;
+ private final String name;
+
+ Number(final int score, final String name) {
+ this.score = score;
+ this.name = name;
+ }
+
+ public int getScore() {
+ return this.score;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public boolean isAce() {
+ return this.score == ACE.score;
+ }
+}
diff --git a/src/main/java/blackjack/domain/carddeck/Pattern.java b/src/main/java/blackjack/domain/carddeck/Pattern.java
new file mode 100644
index 0000000000..9cd214ae79
--- /dev/null
+++ b/src/main/java/blackjack/domain/carddeck/Pattern.java
@@ -0,0 +1,19 @@
+package blackjack.domain.carddeck;
+
+public enum Pattern {
+
+ SPADE("스페이드"),
+ DIAMOND("다이아몬드"),
+ CLOVER("클로버"),
+ HEART("하트");
+
+ private final String pattern;
+
+ Pattern(final String pattern) {
+ this.pattern = pattern;
+ }
+
+ public String getPattern() {
+ return this.pattern;
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/Dealer.java b/src/main/java/blackjack/domain/participant/Dealer.java
new file mode 100644
index 0000000000..ad330c6e1a
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/Dealer.java
@@ -0,0 +1,21 @@
+package blackjack.domain.participant;
+
+import blackjack.domain.carddeck.Card;
+import java.util.Collections;
+import java.util.List;
+
+public class Dealer extends Participant {
+
+ private static final int LIMIT_SCORE = 17;
+
+ public Dealer() {
+ }
+
+ public boolean isOverThenLimitScore() {
+ return getScoreToInt() >= LIMIT_SCORE;
+ }
+
+ public List getInitCard() {
+ return Collections.singletonList(getCards().get(0));
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/Name.java b/src/main/java/blackjack/domain/participant/Name.java
new file mode 100644
index 0000000000..8c91e516b6
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/Name.java
@@ -0,0 +1,46 @@
+package blackjack.domain.participant;
+
+import java.util.Objects;
+
+public class Name {
+
+ private static final String BLANK = " ";
+ private final String value;
+
+ public Name(final String value) {
+ this.value = value;
+ validateNull(this.value);
+ validateBlank(this.value);
+ }
+
+ private void validateNull(final String name) {
+ Objects.requireNonNull(name, "이름은 null 일수 없습니다.");
+ }
+
+ private void validateBlank(final String name) {
+ if (name.isEmpty() || name.contains(BLANK)) {
+ throw new IllegalArgumentException("이름은 공백을 포함할 수 없습니다.");
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Name name1 = (Name) o;
+ return Objects.equals(value, name1.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/Participant.java b/src/main/java/blackjack/domain/participant/Participant.java
new file mode 100644
index 0000000000..7547fb2968
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/Participant.java
@@ -0,0 +1,53 @@
+package blackjack.domain.participant;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.CardDeck;
+import blackjack.domain.participant.state.Init;
+import blackjack.domain.participant.state.Score;
+import blackjack.domain.participant.state.State;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class Participant {
+
+ protected State state;
+
+ protected Participant() {
+ }
+
+ public void initDraw(final CardDeck cardDeck) {
+ this.state = Init.draw(cardDeck.draw(), cardDeck.draw());
+ }
+
+ public void draw(final Card card) {
+ this.state = this.state.draw(card);
+ }
+
+ public void stay() {
+ this.state = this.state.stay();
+ }
+
+ public boolean isFinished() {
+ return this.state.isFinished();
+ }
+
+ public Score score() {
+ return this.state.score();
+ }
+
+ public int getScoreToInt() {
+ return score().getValue();
+ }
+
+ public List getCards() {
+ return Collections.unmodifiableList(this.state.cards());
+ }
+
+ public boolean isBlackjack() {
+ return score().isBlackjack();
+ }
+
+ public boolean isBust() {
+ return score().isBust();
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/Player.java b/src/main/java/blackjack/domain/participant/Player.java
new file mode 100644
index 0000000000..5b2e3b845c
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/Player.java
@@ -0,0 +1,20 @@
+package blackjack.domain.participant;
+
+import blackjack.domain.Result;
+
+public class Player extends Participant {
+
+ private final Name name;
+
+ public Player(final Name name) {
+ this.name = name;
+ }
+
+ public Result judgeByDealerState(final Dealer dealer) {
+ return this.state.calculatePlayerResult(dealer.state);
+ }
+
+ public String getName() {
+ return this.name.getValue();
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/Players.java b/src/main/java/blackjack/domain/participant/Players.java
new file mode 100644
index 0000000000..f696fc628d
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/Players.java
@@ -0,0 +1,85 @@
+package blackjack.domain.participant;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.CardDeck;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.stream.Collectors;
+
+public class Players {
+
+ public static final int MAX_PLAYER = 7;
+
+ private final Queue players;
+
+ public Players(final List names) {
+ this.players = convertToPlayers(names);
+ validatePlayerCount(this.players);
+ validateDuplicate(this.players);
+ }
+
+ private Queue convertToPlayers(final List names) {
+ Queue players = new LinkedList<>();
+ for (String name : names) {
+ players.offer(new Player(new Name(name)));
+ }
+ return players;
+ }
+
+ private void validatePlayerCount(final Queue players) {
+ if (players.size() > MAX_PLAYER) {
+ throw new IllegalArgumentException("최대 참여 플레이어는 " + MAX_PLAYER + "명입니다.");
+ }
+ }
+
+ private void validateDuplicate(final Queue players) {
+ int setSize = this.players.stream()
+ .map(Player::getName)
+ .collect(Collectors.toSet())
+ .size();
+ if (setSize != players.size()) {
+ throw new IllegalArgumentException("중복된 이름은 사용할 수 없습니다.");
+ }
+ }
+
+ public void initDraw(final CardDeck cardDeck) {
+ this.players.forEach(player -> player.initDraw(cardDeck));
+ }
+
+ public boolean isAllPlayerFinished() {
+ return this.players
+ .stream()
+ .filter(Player::isFinished)
+ .count() == this.players.size();
+ }
+
+ public void passTurnToNextPlayer() {
+ this.players.offer(this.players.poll());
+ }
+
+ public void drawFirstOrderPlayer(final Card card) {
+ getFirstOrderPlayer().draw(card);
+ }
+
+ public void stayFirstOrderPlayer() {
+ getFirstOrderPlayer().stay();
+ }
+
+ public Player getFirstOrderPlayer() {
+ return this.players.peek();
+ }
+
+ public boolean isFinishedCurrentPlayer() {
+ return getFirstOrderPlayer().isFinished();
+ }
+
+ public String getFirstOrderPlayerName() {
+ return getFirstOrderPlayer().getName();
+ }
+
+ public List toList() {
+ return new ArrayList<>(this.players);
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/AfterInit.java b/src/main/java/blackjack/domain/participant/state/AfterInit.java
new file mode 100644
index 0000000000..2d59826877
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/AfterInit.java
@@ -0,0 +1,23 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.carddeck.Card;
+import java.util.List;
+
+public abstract class AfterInit implements State {
+
+ protected final Hand hand;
+
+ public AfterInit(final Hand hand) {
+ this.hand = hand;
+ }
+
+ @Override
+ public List cards() {
+ return this.hand.getCards();
+ }
+
+ @Override
+ public Score score() {
+ return this.hand.score();
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Blackjack.java b/src/main/java/blackjack/domain/participant/state/Blackjack.java
new file mode 100644
index 0000000000..77fe1edb52
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Blackjack.java
@@ -0,0 +1,18 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.Result;
+
+public class Blackjack extends Finished {
+
+ public Blackjack(final Hand hand) {
+ super(hand);
+ }
+
+ @Override
+ public Result calculatePlayerResult(final State dealerState) {
+ if (dealerState.score().isBlackjack()) {
+ return Result.DRAW;
+ }
+ return Result.WIN;
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Bust.java b/src/main/java/blackjack/domain/participant/state/Bust.java
new file mode 100644
index 0000000000..16c9569dcd
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Bust.java
@@ -0,0 +1,15 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.Result;
+
+public class Bust extends Finished {
+
+ public Bust(final Hand hand) {
+ super(hand);
+ }
+
+ @Override
+ public Result calculatePlayerResult(State dealerState) {
+ return Result.LOSE;
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Finished.java b/src/main/java/blackjack/domain/participant/state/Finished.java
new file mode 100644
index 0000000000..e98f7c4f8b
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Finished.java
@@ -0,0 +1,25 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.carddeck.Card;
+
+public abstract class Finished extends AfterInit {
+
+ public Finished(final Hand hand) {
+ super(hand);
+ }
+
+ @Override
+ public State draw(Card card) {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public State stay() {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean isFinished() {
+ return true;
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Hand.java b/src/main/java/blackjack/domain/participant/state/Hand.java
new file mode 100644
index 0000000000..791ba84e66
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Hand.java
@@ -0,0 +1,58 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.carddeck.Card;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Hand {
+
+ private final List cards;
+
+ public Hand(final List cards) {
+ this.cards = new ArrayList<>(cards);
+ }
+
+ public void addCard(final Card card) {
+ this.cards.add(card);
+ }
+
+ public Score score() {
+ Score score = sumScores();
+ int countOfAce = getCountOfAce();
+ for (int i = 0; i < countOfAce; i++) {
+ score = score.reduceScoreIfBust();
+ }
+ return score;
+ }
+
+ private Score sumScores() {
+ return new Score(this.cards
+ .stream()
+ .mapToInt(Card::getScore)
+ .sum()
+ );
+ }
+
+ public int getScoreToInt() {
+ return score().getValue();
+ }
+
+ public boolean isBlackjack() {
+ return cards.size() == 2 && score().isBlackjack();
+ }
+
+ public boolean isBust() {
+ return score().isBust();
+ }
+
+ private int getCountOfAce() {
+ return (int) this.cards
+ .stream()
+ .filter(Card::isAce)
+ .count();
+ }
+
+ public List getCards() {
+ return new ArrayList<>(this.cards);
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Hit.java b/src/main/java/blackjack/domain/participant/state/Hit.java
new file mode 100644
index 0000000000..22039b4eaa
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Hit.java
@@ -0,0 +1,22 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.carddeck.Card;
+
+public class Hit extends Running {
+
+ public Hit(final Hand hand) {
+ super(hand);
+ }
+
+ public State draw(final Card card) {
+ this.hand.addCard(card);
+ if (this.hand.isBust()) {
+ return new Bust(this.hand);
+ }
+ return new Hit(this.hand);
+ }
+
+ public State stay() {
+ return new Stay(this.hand);
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Init.java b/src/main/java/blackjack/domain/participant/state/Init.java
new file mode 100644
index 0000000000..545a41962a
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Init.java
@@ -0,0 +1,15 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.carddeck.Card;
+import java.util.Arrays;
+
+public class Init {
+
+ public static State draw(final Card firstCard, final Card secondCard) {
+ Hand hand = new Hand(Arrays.asList(firstCard, secondCard));
+ if (hand.isBlackjack()) {
+ return new Blackjack(hand);
+ }
+ return new Hit(hand);
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Running.java b/src/main/java/blackjack/domain/participant/state/Running.java
new file mode 100644
index 0000000000..477fed38be
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Running.java
@@ -0,0 +1,20 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.Result;
+
+public abstract class Running extends AfterInit {
+
+ public Running(final Hand hand) {
+ super(hand);
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public Result calculatePlayerResult(final State state) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Score.java b/src/main/java/blackjack/domain/participant/state/Score.java
new file mode 100644
index 0000000000..814f8091d8
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Score.java
@@ -0,0 +1,44 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.Result;
+
+public class Score {
+
+ private static final int BLACKJACK = 21;
+ private static final int TEN = 10;
+
+ private final int value;
+
+ public Score(final int value) {
+ this.value = value;
+ }
+
+ public Score reduceScoreIfBust() {
+ if (this.isBust()) {
+ return new Score(this.value - TEN);
+ }
+ return this;
+ }
+
+ public boolean isBust() {
+ return this.value > BLACKJACK;
+ }
+
+ public boolean isBlackjack() {
+ return this.value == BLACKJACK;
+ }
+
+ public Result compare(final Score score) {
+ if (this.value > score.value) {
+ return Result.WIN;
+ }
+ if (this.value < score.value) {
+ return Result.LOSE;
+ }
+ return Result.DRAW;
+ }
+
+ public int getValue() {
+ return this.value;
+ }
+}
diff --git a/src/main/java/blackjack/domain/participant/state/State.java b/src/main/java/blackjack/domain/participant/state/State.java
new file mode 100644
index 0000000000..e977afb3d2
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/State.java
@@ -0,0 +1,20 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.Result;
+import blackjack.domain.carddeck.Card;
+import java.util.List;
+
+public interface State {
+
+ State draw(final Card card);
+
+ State stay();
+
+ List cards();
+
+ boolean isFinished();
+
+ Score score();
+
+ Result calculatePlayerResult(final State state);
+}
diff --git a/src/main/java/blackjack/domain/participant/state/Stay.java b/src/main/java/blackjack/domain/participant/state/Stay.java
new file mode 100644
index 0000000000..898b94e6af
--- /dev/null
+++ b/src/main/java/blackjack/domain/participant/state/Stay.java
@@ -0,0 +1,21 @@
+package blackjack.domain.participant.state;
+
+import blackjack.domain.Result;
+
+public class Stay extends Finished {
+
+ public Stay(final Hand hand) {
+ super(hand);
+ }
+
+ @Override
+ public Result calculatePlayerResult(State dealerState) {
+ if (dealerState.score().isBlackjack()) {
+ return Result.LOSE;
+ }
+ if (dealerState.score().isBust()) {
+ return Result.WIN;
+ }
+ return this.score().compare(dealerState.score());
+ }
+}
diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java
new file mode 100644
index 0000000000..9d492dc428
--- /dev/null
+++ b/src/main/java/blackjack/view/InputView.java
@@ -0,0 +1,35 @@
+package blackjack.view;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+
+public class InputView {
+
+ private final static String NEW_LINE = System.lineSeparator();
+ private final static Scanner SCANNER = new Scanner(System.in);
+
+
+ public static List getPlayerNames() {
+ System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)");
+ return splitNames(SCANNER.nextLine());
+ }
+
+ private static List splitNames(final String inputString) {
+ return Arrays.asList(inputString.split(","));
+ }
+
+ public static boolean getHitOrStay(final String name) {
+ System.out.printf("%s(은)는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)", name);
+ System.out.print(NEW_LINE);
+ String input = SCANNER.nextLine().toLowerCase();
+ validateHitOrStay(input);
+ return input.equals("y");
+ }
+
+ private static void validateHitOrStay(final String input) {
+ if (!input.equals("y") && !input.equals("n")) {
+ throw new IllegalArgumentException("요청은 y(Y) 또는 n(N) 이어야 합니다.");
+ }
+ }
+}
diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java
new file mode 100644
index 0000000000..a9497b63bf
--- /dev/null
+++ b/src/main/java/blackjack/view/OutputView.java
@@ -0,0 +1,92 @@
+package blackjack.view;
+
+import static java.util.stream.Collectors.joining;
+
+import blackjack.view.dto.CardDto;
+import blackjack.view.dto.ParticipantDto;
+import blackjack.view.dto.ResultDto;
+import java.util.List;
+
+public class OutputView {
+
+ private static final String NEW_LINE = System.lineSeparator();
+ private static final String DELIMITER = ", ";
+ private static final String INIT_GAME_FORMAT = "%s와 %s에게 2장을 나누었습니다.";
+ private static final String HAND_FORMAT = "%s 카드: %s";
+ private static final String SCORE_FORMAT = " - 결과: %d";
+ private static final String PARTICIPANT_BURST_FORMAT = "%s(은)는 21점을 넘어 버스트 되었습니다.";
+ private static final String DEALER_HIT_IF_UNDER_LIMIT_SCORE = "딜러는 16이하라 한장의 카드를 더 받았습니다.";
+ private static final String TOTAL_GAME_RESULT_MESSAGE = "## 최종 승패";
+ private static final String TOTAL_GAME_RESULT_FORMAT = "%s: %s";
+
+ public static void printInitStatuses(final ParticipantDto dealer,
+ final List players) {
+ System.out.print(NEW_LINE);
+ System.out.printf(INIT_GAME_FORMAT, dealer.getName(), getPlayerNames(players));
+ System.out.print(NEW_LINE);
+ printInitDealerHand(dealer);
+ players.forEach(OutputView::printPlayerStatus);
+ System.out.print(NEW_LINE);
+ }
+
+ private static String getPlayerNames(final List players) {
+ return players.stream()
+ .map(ParticipantDto::getName)
+ .collect(joining(DELIMITER));
+ }
+
+ private static void printInitDealerHand(final ParticipantDto dealer) {
+ System.out.printf(HAND_FORMAT, dealer.getName(), dealer.getCards().get(0).getName());
+ System.out.print(NEW_LINE);
+ }
+
+ public static void printPlayerStatus(final ParticipantDto player) {
+ System.out.printf(HAND_FORMAT, player.getName(), player.getCards()
+ .stream()
+ .map(CardDto::getName)
+ .collect(joining(DELIMITER))
+ );
+ System.out.print(NEW_LINE);
+ }
+
+ public static void printStatusWithScore(ParticipantDto participant) {
+ System.out.printf(HAND_FORMAT, participant.getName(), participant.getCards()
+ .stream()
+ .map(CardDto::getName)
+ .collect(joining(DELIMITER))
+ );
+ System.out.printf(SCORE_FORMAT, participant.getScore());
+ System.out.print(NEW_LINE);
+ }
+
+ public static void printDealerHit() {
+ System.out.println(DEALER_HIT_IF_UNDER_LIMIT_SCORE);
+ }
+
+ private static void printDealerHandWithScore(final ParticipantDto dealer) {
+ System.out.printf(HAND_FORMAT, dealer.getName(), dealer.getCards()
+ .stream()
+ .map(CardDto::getName)
+ .collect(joining(DELIMITER))
+ );
+ System.out.printf(SCORE_FORMAT, dealer.getScore());
+ System.out.print(NEW_LINE);
+ }
+
+ public static void printBlackjackResult(final ResultDto dealerResult,
+ final List playerResultDtos) {
+ System.out.print(NEW_LINE);
+ System.out.println(TOTAL_GAME_RESULT_MESSAGE);
+ printResult(dealerResult);
+ playerResultDtos.forEach(OutputView::printResult);
+ }
+
+ private static void printResult(final ResultDto result) {
+ System.out.printf(TOTAL_GAME_RESULT_FORMAT, result.getName(), result.getResult());
+ System.out.print(NEW_LINE);
+ }
+
+ public static void printNewLine() {
+ System.out.print(NEW_LINE);
+ }
+}
diff --git a/src/main/java/blackjack/view/dto/CardDto.java b/src/main/java/blackjack/view/dto/CardDto.java
new file mode 100644
index 0000000000..9241e05e91
--- /dev/null
+++ b/src/main/java/blackjack/view/dto/CardDto.java
@@ -0,0 +1,14 @@
+package blackjack.view.dto;
+
+public class CardDto {
+
+ private final String name;
+
+ public CardDto(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+}
diff --git a/src/main/java/blackjack/view/dto/ParticipantDto.java b/src/main/java/blackjack/view/dto/ParticipantDto.java
new file mode 100644
index 0000000000..61f1ee6a3a
--- /dev/null
+++ b/src/main/java/blackjack/view/dto/ParticipantDto.java
@@ -0,0 +1,34 @@
+package blackjack.view.dto;
+
+import java.util.List;
+
+public class ParticipantDto {
+
+ public static final String DEALER_NAME = "딜러";
+
+ private final String name;
+ private final List cards;
+ private final int score;
+
+ public ParticipantDto(final List cards, final int score) {
+ this(DEALER_NAME, cards, score);
+ }
+
+ public ParticipantDto(final String name, final List cards, final int score) {
+ this.name = name;
+ this.cards = cards;
+ this.score = score;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public List getCards() {
+ return this.cards;
+ }
+
+ public int getScore() {
+ return this.score;
+ }
+}
diff --git a/src/main/java/blackjack/view/dto/ResultDto.java b/src/main/java/blackjack/view/dto/ResultDto.java
new file mode 100644
index 0000000000..7a0f3b9e24
--- /dev/null
+++ b/src/main/java/blackjack/view/dto/ResultDto.java
@@ -0,0 +1,26 @@
+package blackjack.view.dto;
+
+public class ResultDto {
+
+ public static final String DEALER_NAME = "딜러";
+
+ private final String name;
+ private final String result;
+
+ public ResultDto(final String result) {
+ this(DEALER_NAME, result);
+ }
+
+ public ResultDto(final String name, final String result) {
+ this.name = name;
+ this.result = result;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getResult() {
+ return this.result;
+ }
+}
diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/main/java/rentcar/abstractcar/Avante.java b/src/main/java/rentcar/abstractcar/Avante.java
new file mode 100644
index 0000000000..09dd96d053
--- /dev/null
+++ b/src/main/java/rentcar/abstractcar/Avante.java
@@ -0,0 +1,20 @@
+package rentcar.abstractcar;
+
+public class Avante extends Car {
+
+ private final double tripDistance;
+
+ public Avante(final double tripDistance) {
+ this.tripDistance = tripDistance;
+ }
+
+ @Override
+ double getDistancePerLiter() {
+ return 15;
+ }
+
+ @Override
+ double getTripDistance() {
+ return this.tripDistance;
+ }
+}
diff --git a/src/main/java/rentcar/abstractcar/Car.java b/src/main/java/rentcar/abstractcar/Car.java
new file mode 100644
index 0000000000..5744bfe4c8
--- /dev/null
+++ b/src/main/java/rentcar/abstractcar/Car.java
@@ -0,0 +1,17 @@
+package rentcar.abstractcar;
+
+public abstract class Car {
+
+ abstract double getDistancePerLiter();
+
+ abstract double getTripDistance();
+
+ double getChargeQuantity() {
+ return getTripDistance() / getDistancePerLiter();
+ }
+
+ public String getName() {
+ return this.getClass().getSimpleName();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/rentcar/abstractcar/K5.java b/src/main/java/rentcar/abstractcar/K5.java
new file mode 100644
index 0000000000..924b8a1255
--- /dev/null
+++ b/src/main/java/rentcar/abstractcar/K5.java
@@ -0,0 +1,20 @@
+package rentcar.abstractcar;
+
+public class K5 extends Car {
+
+ private final double tripDistance;
+
+ public K5(final double tripDistance) {
+ this.tripDistance = tripDistance;
+ }
+
+ @Override
+ double getDistancePerLiter() {
+ return 13;
+ }
+
+ @Override
+ double getTripDistance() {
+ return this.tripDistance;
+ }
+}
diff --git a/src/main/java/rentcar/abstractcar/RentCompany.java b/src/main/java/rentcar/abstractcar/RentCompany.java
new file mode 100644
index 0000000000..05bfc73839
--- /dev/null
+++ b/src/main/java/rentcar/abstractcar/RentCompany.java
@@ -0,0 +1,32 @@
+package rentcar.abstractcar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RentCompany {
+
+ private static final String REPORT_FORMAT =
+ "%s : %.0f리터" + System.getProperty("line.separator");
+
+ private final List cars;
+
+ private RentCompany() {
+ this.cars = new ArrayList<>();
+ }
+
+ public static RentCompany create() {
+ return new RentCompany();
+ }
+
+ public void addCar(final Car car) {
+ this.cars.add(car);
+ }
+
+ public String generateReport() {
+ StringBuilder sb = new StringBuilder();
+ for (Car car : this.cars) {
+ sb.append(String.format(REPORT_FORMAT, car.getName(), car.getChargeQuantity()));
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/rentcar/abstractcar/Sonata.java b/src/main/java/rentcar/abstractcar/Sonata.java
new file mode 100644
index 0000000000..d39924ba29
--- /dev/null
+++ b/src/main/java/rentcar/abstractcar/Sonata.java
@@ -0,0 +1,20 @@
+package rentcar.abstractcar;
+
+public class Sonata extends Car {
+
+ private final double tripDistance;
+
+ public Sonata(final double tripDistance) {
+ this.tripDistance = tripDistance;
+ }
+
+ @Override
+ double getDistancePerLiter() {
+ return 10;
+ }
+
+ @Override
+ double getTripDistance() {
+ return this.tripDistance;
+ }
+}
diff --git a/src/main/java/rentcar/interfacecar/Avante.java b/src/main/java/rentcar/interfacecar/Avante.java
new file mode 100644
index 0000000000..0312e7ae75
--- /dev/null
+++ b/src/main/java/rentcar/interfacecar/Avante.java
@@ -0,0 +1,20 @@
+package rentcar.interfacecar;
+
+public class Avante implements Car {
+
+ private final double tripDistance;
+
+ public Avante(final double tripDistance) {
+ this.tripDistance = tripDistance;
+ }
+
+ @Override
+ public double getDistancePerLiter() {
+ return 15;
+ }
+
+ @Override
+ public double getTripDistance() {
+ return this.tripDistance;
+ }
+}
diff --git a/src/main/java/rentcar/interfacecar/Car.java b/src/main/java/rentcar/interfacecar/Car.java
new file mode 100644
index 0000000000..552c1c9e66
--- /dev/null
+++ b/src/main/java/rentcar/interfacecar/Car.java
@@ -0,0 +1,16 @@
+package rentcar.interfacecar;
+
+public interface Car {
+
+ double getDistancePerLiter();
+
+ double getTripDistance();
+
+ default double getChargeQuantity() {
+ return getTripDistance() / getDistancePerLiter();
+ }
+
+ default String getName() {
+ return this.getClass().getSimpleName();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rentcar/interfacecar/K5.java b/src/main/java/rentcar/interfacecar/K5.java
new file mode 100644
index 0000000000..9fa4318def
--- /dev/null
+++ b/src/main/java/rentcar/interfacecar/K5.java
@@ -0,0 +1,20 @@
+package rentcar.interfacecar;
+
+public class K5 implements Car {
+
+ private final double tripDistance;
+
+ public K5(final double tripDistance) {
+ this.tripDistance = tripDistance;
+ }
+
+ @Override
+ public double getDistancePerLiter() {
+ return 13;
+ }
+
+ @Override
+ public double getTripDistance() {
+ return this.tripDistance;
+ }
+}
diff --git a/src/main/java/rentcar/interfacecar/RentCompany.java b/src/main/java/rentcar/interfacecar/RentCompany.java
new file mode 100644
index 0000000000..f0a2e98790
--- /dev/null
+++ b/src/main/java/rentcar/interfacecar/RentCompany.java
@@ -0,0 +1,32 @@
+package rentcar.interfacecar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RentCompany {
+
+ private static final String REPORT_FORMAT =
+ "%s : %.0f리터" + System.getProperty("line.separator");
+
+ private final List cars;
+
+ private RentCompany() {
+ this.cars = new ArrayList<>();
+ }
+
+ public static RentCompany create() {
+ return new RentCompany();
+ }
+
+ public void addCar(final Car car) {
+ this.cars.add(car);
+ }
+
+ public String generateReport() {
+ StringBuilder sb = new StringBuilder();
+ for (Car car : this.cars) {
+ sb.append(String.format(REPORT_FORMAT, car.getName(), car.getChargeQuantity()));
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/rentcar/interfacecar/Sonata.java b/src/main/java/rentcar/interfacecar/Sonata.java
new file mode 100644
index 0000000000..c49ef07505
--- /dev/null
+++ b/src/main/java/rentcar/interfacecar/Sonata.java
@@ -0,0 +1,20 @@
+package rentcar.interfacecar;
+
+public class Sonata implements Car {
+
+ private final double tripDistance;
+
+ public Sonata(final double tripDistance) {
+ this.tripDistance = tripDistance;
+ }
+
+ @Override
+ public double getDistancePerLiter() {
+ return 10;
+ }
+
+ @Override
+ public double getTripDistance() {
+ return this.tripDistance;
+ }
+}
diff --git a/src/test/java/blackjack/domain/BlackjackManagerTest.java b/src/test/java/blackjack/domain/BlackjackManagerTest.java
new file mode 100644
index 0000000000..b4303776a3
--- /dev/null
+++ b/src/test/java/blackjack/domain/BlackjackManagerTest.java
@@ -0,0 +1,128 @@
+package blackjack.domain;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.CardDeck;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import blackjack.domain.participant.Dealer;
+import blackjack.domain.participant.Players;
+import java.util.Arrays;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class BlackjackManagerTest {
+
+ private Dealer dealer;
+ private Players players;
+ private BlackjackManager blackjackManager;
+
+ @BeforeEach
+ void setUp() {
+ this.dealer = new Dealer();
+ this.players = new Players(Arrays.asList("pobi", "jason"));
+ this.blackjackManager = new BlackjackManager(
+ getDrawTestCardDeck(),
+ this.dealer,
+ this.players
+ );
+ }
+
+ private CardDeck getDrawTestCardDeck() {
+ return CardDeck.customDeck(Arrays.asList(
+ Card.valueOf(Pattern.HEART, Number.SIX),
+ Card.valueOf(Pattern.HEART, Number.TEN),
+ Card.valueOf(Pattern.HEART, Number.JACK),
+ Card.valueOf(Pattern.HEART, Number.TEN),
+ Card.valueOf(Pattern.HEART, Number.QUEEN),
+ Card.valueOf(Pattern.HEART, Number.KING),
+ Card.valueOf(Pattern.DIAMOND, Number.KING)
+ ));
+ }
+
+ @Test
+ @DisplayName("각 플레이어가 초기 2장씩 소지한다.")
+ void testAllPlayersGetTwoCards() {
+ this.blackjackManager.initDrawCards();
+
+ assertThat(this.players
+ .toList()
+ .stream()
+ .filter(player -> player.getCards().size() == 2)
+ .count())
+ .isEqualTo(2);
+ }
+
+ @Test
+ @DisplayName("한 명의 플레이어 카드뽑기 완료 테스트")
+ void testOnePlayerCompleteHit() {
+ this.blackjackManager.initDrawCards();
+ this.blackjackManager.hitOrStayCurrentPlayer(true);
+ assertThat(this.blackjackManager.isFinishedCurrentPlayer()).isTrue();
+ }
+
+ @Test
+ @DisplayName("한 명의 플레이어가 stay 상태 변화 완료")
+ void testOnePlayerCompleteToStay() {
+ this.blackjackManager.initDrawCards();
+ this.blackjackManager.hitOrStayCurrentPlayer(false);
+ assertThat(this.blackjackManager.isFinishedCurrentPlayer()).isTrue();
+ }
+
+ @Test
+ @DisplayName("플레이어 턴 넘기기 완료")
+ void testPassTurnToNextPlayer() {
+ assertThat(this.blackjackManager.getCurrentPlayerName()).isEqualTo("pobi");
+ this.blackjackManager.passTurnToNextPlayer();
+ assertThat(this.blackjackManager.getCurrentPlayerName()).isEqualTo("jason");
+ }
+
+ @Test
+ @DisplayName("한 플레이어의 차례가 끝났는지 확인 테스트")
+ void testOnePlayerFinished() {
+ this.blackjackManager.initDrawCards();
+ this.blackjackManager.hitOrStayCurrentPlayer(true);
+ assertThat(this.blackjackManager.isFinishedCurrentPlayer()).isTrue();
+ }
+
+ @Test
+ @DisplayName("전체 플레이어의 차례가 끝났는지 확인 테스트")
+ void testAllPlayersFinished() {
+ this.blackjackManager.initDrawCards();
+ this.blackjackManager.hitOrStayCurrentPlayer(false);
+ this.blackjackManager.passTurnToNextPlayer();
+ this.blackjackManager.hitOrStayCurrentPlayer(false);
+ assertThat(this.blackjackManager.isFinishedAllPlayers()).isTrue();
+ }
+
+ @Test
+ @DisplayName("딜러 카드 뽑기 테스트")
+ void testDealerDraw() {
+ this.blackjackManager.initDrawCards();
+ assertThat(this.blackjackManager.getDealer().getScoreToInt()).isEqualTo(16);
+ this.blackjackManager.hitDealer();
+ assertThat(this.blackjackManager.getDealer().getScoreToInt()).isEqualTo(26);
+ }
+
+ @Test
+ @DisplayName("딜러 Stay 상태변화 테스트")
+ void testDealerToStay() {
+ this.blackjackManager.initDrawCards();
+ assertThat(this.blackjackManager.isFinishedDealer()).isFalse();
+ this.blackjackManager.stayDealer();
+ assertThat(this.blackjackManager.isFinishedDealer()).isTrue();
+ }
+
+ @Test
+ @DisplayName("딜러 카드뽑기 후 17점 이상시 상태전환 테스트")
+ void testDealerToStayIfScoreOverThenLimit() {
+ this.blackjackManager.initDrawCards();
+ assertThat(this.blackjackManager.isFinishedDealer()).isFalse();
+ assertThat(this.blackjackManager.isDealerScoreOverThenLimit()).isFalse();
+ this.blackjackManager.hitDealer();
+ assertThat(this.blackjackManager.isFinishedDealer()).isTrue();
+ assertThat(this.blackjackManager.isDealerScoreOverThenLimit()).isTrue();
+ }
+}
diff --git a/src/test/java/blackjack/domain/ResultTest.java b/src/test/java/blackjack/domain/ResultTest.java
new file mode 100644
index 0000000000..f517d0901f
--- /dev/null
+++ b/src/test/java/blackjack/domain/ResultTest.java
@@ -0,0 +1,74 @@
+package blackjack.domain;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.CardDeck;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import blackjack.domain.participant.Dealer;
+import blackjack.domain.participant.Player;
+import blackjack.domain.participant.Players;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class ResultTest {
+
+ private BlackjackManager blackjackManager;
+ private Dealer dealer;
+
+ @BeforeEach
+ void setUp() {
+ CardDeck cardDeck = getDrawTestCardDeck();
+ this.dealer = new Dealer();
+ Players players = new Players(Collections.singletonList("미립"));
+ this.blackjackManager = new BlackjackManager(cardDeck, this.dealer, players);
+ this.blackjackManager.initDrawCards();
+ }
+
+ private CardDeck getDrawTestCardDeck() {
+ return CardDeck.customDeck(Arrays.asList(
+ Card.valueOf(Pattern.HEART, Number.SEVEN),
+ Card.valueOf(Pattern.HEART, Number.TEN),
+ Card.valueOf(Pattern.HEART, Number.FOUR),
+ Card.valueOf(Pattern.HEART, Number.FIVE),
+ Card.valueOf(Pattern.DIAMOND, Number.EIGHT),
+ Card.valueOf(Pattern.DIAMOND, Number.TWO)
+ ));
+ }
+
+ @Test
+ @DisplayName("플레이어의 승 / 딜러 패 테스트")
+ void testPlayerWinAndDealerLose() {
+ this.blackjackManager.hitOrStayCurrentPlayer(true);
+ this.blackjackManager.hitOrStayCurrentPlayer(true);
+ this.blackjackManager.hitOrStayCurrentPlayer(false);
+ Player player = this.blackjackManager.getCurrentPlayer();
+ assertThat(player.judgeByDealerState(this.dealer)).isEqualTo(Result.WIN);
+ assertThat(player.judgeByDealerState(this.dealer).reverse()).isEqualTo(Result.LOSE);
+ }
+
+ @Test
+ @DisplayName("플레이어의 패 / 딜러 승 테스트")
+ void testPlayerLoseAndDealerWin() {
+ this.blackjackManager.hitOrStayCurrentPlayer(false);
+ Player player = this.blackjackManager.getCurrentPlayer();
+ assertThat(player.judgeByDealerState(this.dealer)).isEqualTo(Result.LOSE);
+ assertThat(player.judgeByDealerState(this.dealer).reverse()).isEqualTo(Result.WIN);
+ }
+
+ @Test
+ @DisplayName("무승부 테스트")
+ void testPlayerAndDealerDraw() {
+ this.blackjackManager.hitOrStayCurrentPlayer(true);
+ this.blackjackManager.hitOrStayCurrentPlayer(false);
+ Player player = this.blackjackManager.getCurrentPlayer();
+ assertThat(player.judgeByDealerState(this.dealer)).isEqualTo(Result.DRAW);
+ assertThat(player.judgeByDealerState(this.dealer).reverse()).isEqualTo(Result.DRAW);
+ }
+
+
+}
diff --git a/src/test/java/blackjack/domain/carddeck/CardDeckTest.java b/src/test/java/blackjack/domain/carddeck/CardDeckTest.java
new file mode 100644
index 0000000000..63c560e69b
--- /dev/null
+++ b/src/test/java/blackjack/domain/carddeck/CardDeckTest.java
@@ -0,0 +1,75 @@
+package blackjack.domain.carddeck;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.HashSet;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class CardDeckTest {
+
+ private CardDeck cardDeck;
+
+ @BeforeEach
+ void setUp() {
+ this.cardDeck = CardDeck.newShuffledDeck();
+ }
+
+ @Test
+ @DisplayName("카드를 한장 뽑는다.")
+ void testCardDeckDraw() {
+ assertThat(this.cardDeck.draw()).isInstanceOf(Card.class);
+ }
+
+ @Test
+ @DisplayName("카드는 52장이다.")
+ void testCardDeckSize() {
+ for (int i = 0; i < 52; i++) {
+ this.cardDeck.draw();
+ }
+ assertThatThrownBy(this.cardDeck::draw)
+ .isInstanceOf(NoSuchElementException.class);
+ }
+
+ @Test
+ @DisplayName("카드 52장은 중복이 없다.")
+ void testCardDuplicate() {
+ Set cards = new HashSet<>();
+ for (int i = 0; i < 52; i++) {
+ cards.add(this.cardDeck.draw());
+ }
+ assertThat(cards).hasSize(52);
+ }
+
+ @Test
+ @DisplayName("문양별 카드는 각각 13장씩 존재한다.")
+ void testCountOfCardPatterns() {
+ Set cloverCards = new HashSet<>();
+ Set spadeCards = new HashSet<>();
+ Set heartCards = new HashSet<>();
+ Set diamondCards = new HashSet<>();
+
+ for (int i = 0; i < 52; i++) {
+ Card card = this.cardDeck.draw();
+ compareCardPattern(cloverCards, card, Pattern.CLOVER);
+ compareCardPattern(spadeCards, card, Pattern.SPADE);
+ compareCardPattern(heartCards, card, Pattern.HEART);
+ compareCardPattern(diamondCards, card, Pattern.DIAMOND);
+ }
+
+ assertThat(cloverCards).hasSize(13);
+ assertThat(spadeCards).hasSize(13);
+ assertThat(heartCards).hasSize(13);
+ assertThat(diamondCards).hasSize(13);
+ }
+
+ private void compareCardPattern(final Set cards, final Card card, final Pattern pattern) {
+ if (card.getPatternName().equals(pattern.getPattern())) {
+ cards.add(card);
+ }
+ }
+}
diff --git a/src/test/java/blackjack/domain/carddeck/CardTest.java b/src/test/java/blackjack/domain/carddeck/CardTest.java
new file mode 100644
index 0000000000..86eef7f1d0
--- /dev/null
+++ b/src/test/java/blackjack/domain/carddeck/CardTest.java
@@ -0,0 +1,29 @@
+package blackjack.domain.carddeck;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class CardTest {
+
+ @Test
+ @DisplayName("카드캐싱 테스트")
+ void testCreateCard() {
+ Card card = Card.valueOf(Pattern.CLOVER, Number.ACE);
+
+ assertThat(card).isEqualTo(Card.valueOf(Pattern.CLOVER, Number.ACE));
+ assertThat(card).isNotEqualTo(Card.valueOf(Pattern.HEART, Number.ACE));
+ assertThat(card).isNotEqualTo(Card.valueOf(Pattern.CLOVER, Number.KING));
+ }
+
+ @Test
+ @DisplayName("자신이 ACE 카드인지 확인한다.")
+ void testIsAceCard() {
+ Card card1 = Card.valueOf(Pattern.CLOVER, Number.ACE);
+ Card card2 = Card.valueOf(Pattern.CLOVER, Number.TWO);
+
+ assertThat(card1.isAce()).isTrue();
+ assertThat(card2.isAce()).isFalse();
+ }
+}
diff --git a/src/test/java/blackjack/domain/carddeck/NumberTest.java b/src/test/java/blackjack/domain/carddeck/NumberTest.java
new file mode 100644
index 0000000000..809f2f3965
--- /dev/null
+++ b/src/test/java/blackjack/domain/carddeck/NumberTest.java
@@ -0,0 +1,27 @@
+package blackjack.domain.carddeck;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class NumberTest {
+
+ @Test
+ @DisplayName("카드 숫자별 점수 테스트")
+ void testCarNumberScore() {
+ assertThat(Number.ACE.getScore()).isEqualTo(11);
+ assertThat(Number.TWO.getScore()).isEqualTo(2);
+ assertThat(Number.THREE.getScore()).isEqualTo(3);
+ assertThat(Number.FOUR.getScore()).isEqualTo(4);
+ assertThat(Number.FIVE.getScore()).isEqualTo(5);
+ assertThat(Number.SIX.getScore()).isEqualTo(6);
+ assertThat(Number.SEVEN.getScore()).isEqualTo(7);
+ assertThat(Number.EIGHT.getScore()).isEqualTo(8);
+ assertThat(Number.NINE.getScore()).isEqualTo(9);
+ assertThat(Number.TEN.getScore()).isEqualTo(10);
+ assertThat(Number.JACK.getScore()).isEqualTo(10);
+ assertThat(Number.QUEEN.getScore()).isEqualTo(10);
+ assertThat(Number.KING.getScore()).isEqualTo(10);
+ }
+}
diff --git a/src/test/java/blackjack/domain/carddeck/PatternTest.java b/src/test/java/blackjack/domain/carddeck/PatternTest.java
new file mode 100644
index 0000000000..1d204392aa
--- /dev/null
+++ b/src/test/java/blackjack/domain/carddeck/PatternTest.java
@@ -0,0 +1,19 @@
+package blackjack.domain.carddeck;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class PatternTest {
+
+ @Test
+ @DisplayName("카드 문양별 출력형태 테스트")
+ void testCardPatternPrintFormat() {
+ assertThat(Pattern.CLOVER.getPattern()).isEqualTo("클로버");
+ assertThat(Pattern.DIAMOND.getPattern()).isEqualTo("다이아몬드");
+ assertThat(Pattern.SPADE.getPattern()).isEqualTo("스페이드");
+ assertThat(Pattern.HEART.getPattern()).isEqualTo("하트");
+ }
+
+}
diff --git a/src/test/java/blackjack/domain/participant/DealerTest.java b/src/test/java/blackjack/domain/participant/DealerTest.java
new file mode 100644
index 0000000000..b16a26058f
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/DealerTest.java
@@ -0,0 +1,52 @@
+package blackjack.domain.participant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.CardDeck;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import java.util.Arrays;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class DealerTest {
+
+ private Dealer dealer;
+
+ @BeforeEach
+ void setUp() {
+ this.dealer = new Dealer();
+ }
+
+ @Test
+ @DisplayName("딜러는 총점수 17이상일시 카드 뽑기를 멈춘다.")
+ void testStopDrawDealerWhenTotalScoreOverSeventeen() {
+ CardDeck cardDeck = getCustomCardDeck();
+ this.dealer.initDraw(cardDeck);
+
+ for (int i = 0; i < 999999; i++) {
+ while (!this.dealer.isOverThenLimitScore()) {
+ this.dealer.draw(cardDeck.draw());
+ }
+ assertThat(this.dealer.getScoreToInt()).isEqualTo(17);
+ }
+ }
+
+ @Test
+ @DisplayName("초기 출력을 위한 카드 요청시 첫 1장만 반환한다.")
+ void testGetInitFirstOneCard() {
+ this.dealer.initDraw(getCustomCardDeck());
+ assertThat(this.dealer.getInitCard()).hasSize(1);
+ assertThat(this.dealer.getInitCard().get(0).getScore()).isEqualTo(11);
+ }
+
+ private CardDeck getCustomCardDeck() {
+ Card firstCard = Card.valueOf(Pattern.HEART, Number.ACE);
+ Card secondCard = Card.valueOf(Pattern.HEART, Number.SIX);
+ Card thirdCard = Card.valueOf(Pattern.HEART, Number.TEN);
+ Card fourthCard = Card.valueOf(Pattern.HEART, Number.KING);
+ return CardDeck.customDeck(Arrays.asList(firstCard, secondCard, thirdCard, fourthCard));
+ }
+}
diff --git a/src/test/java/blackjack/domain/participant/NameTest.java b/src/test/java/blackjack/domain/participant/NameTest.java
new file mode 100644
index 0000000000..2970a2ff28
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/NameTest.java
@@ -0,0 +1,34 @@
+package blackjack.domain.participant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+public class NameTest {
+
+ @Test
+ @DisplayName("이름 생성된다.")
+ void testCreateName() {
+ String nameString = "pobi";
+ Name name = new Name(nameString);
+ assertThat(name).isEqualTo(new Name(nameString));
+ }
+
+ @ParameterizedTest
+ @NullSource
+ void testValidateNull(String name) {
+ assertThatThrownBy(() -> new Name(name)).isInstanceOf(NullPointerException.class);
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " ", " "})
+ void testCreateName(String name) {
+ assertThatThrownBy(() -> new Name(name)).isInstanceOf(IllegalArgumentException.class);
+ }
+
+}
diff --git a/src/test/java/blackjack/domain/participant/PlayerTest.java b/src/test/java/blackjack/domain/participant/PlayerTest.java
new file mode 100644
index 0000000000..274ae8244e
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/PlayerTest.java
@@ -0,0 +1,23 @@
+package blackjack.domain.participant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class PlayerTest {
+
+ private Player player;
+
+ @BeforeEach
+ void setUp() {
+ this.player = new Player(new Name("pobi"));
+ }
+
+ @Test
+ @DisplayName("플레이어 이름 반환 테스트")
+ void testPlayerName() {
+ assertThat(this.player.getName()).isEqualTo("pobi");
+ }
+}
diff --git a/src/test/java/blackjack/domain/participant/PlayersTest.java b/src/test/java/blackjack/domain/participant/PlayersTest.java
new file mode 100644
index 0000000000..7b448f9abe
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/PlayersTest.java
@@ -0,0 +1,127 @@
+package blackjack.domain.participant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import blackjack.domain.BlackjackManager;
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.CardDeck;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class PlayersTest {
+
+ @Test
+ @DisplayName("이름들을 입력받아서 플레이어들을 생성")
+ void testCreatePlayers() {
+ List names = Arrays.asList("pobi", "brown", "jason");
+ Players players = new Players(names);
+ assertThat(players.toList()).hasSize(3);
+ }
+
+ @Test
+ @DisplayName("중복된 이름 입력시 예외처리")
+ void testDuplicateException() {
+ List names = Arrays.asList("pobi", "pobi", "jason");
+ assertThatThrownBy(() -> new Players(names))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ @DisplayName("NULL 혹은 공백을 입력했을 시 예외처리")
+ void testNullOrBlankException() {
+ List blank1 = Collections.singletonList("");
+ assertThatThrownBy(() -> new Players(blank1))
+ .isInstanceOf(IllegalArgumentException.class);
+ List blank2 = Collections.singletonList(" ");
+ assertThatThrownBy(() -> new Players(blank2))
+ .isInstanceOf(IllegalArgumentException.class);
+ List nullList = null;
+ assertThatThrownBy(() -> new Players(nullList))
+ .isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ @DisplayName("각 플레이어가 초기 2장씩 소지한다.")
+ void testAllPlayersGetTwoCards() {
+ List names = Arrays.asList("pobi", "jason");
+ Dealer dealer = new Dealer();
+ Players players = new Players(names);
+ BlackjackManager blackjackManager = new BlackjackManager(dealer, players);
+ blackjackManager.initDrawCards();
+
+ assertThat(players.toList()
+ .stream()
+ .filter(player -> player.getCards().size() == 2)
+ .count())
+ .isEqualTo(2);
+ }
+
+ @Test
+ @DisplayName("모든 플레이어가 플레이를 완료했는지 확인한다.")
+ void testIsAllPlayerPlayedBlackJack() {
+ List names = Arrays.asList("미립", "현구막");
+ Players players = new Players(names);
+ players.initDraw(getCustomCardDeck());
+
+ players.drawFirstOrderPlayer(Card.valueOf(Pattern.SPADE, Number.JACK));
+ players.passTurnToNextPlayer();
+ players.drawFirstOrderPlayer(Card.valueOf(Pattern.DIAMOND, Number.JACK));
+
+ assertThat(players.isAllPlayerFinished()).isTrue();
+ }
+
+ private CardDeck getCustomCardDeck() {
+ Card firstCard = Card.valueOf(Pattern.HEART, Number.TEN);
+ Card secondCard = Card.valueOf(Pattern.HEART, Number.KING);
+ Card thirdCard = Card.valueOf(Pattern.HEART, Number.QUEEN);
+ Card fourthCard = Card.valueOf(Pattern.HEART, Number.JACK);
+ return CardDeck.customDeck(Arrays.asList(firstCard, secondCard, thirdCard, fourthCard));
+ }
+
+ @Test
+ @DisplayName("가장 앞 차례 플레이어 턴이 넘어갔는지 확인한다.")
+ void testIsSuccessPassThePlayerTurn() {
+ List names = Arrays.asList("미립", "현구막");
+ Players players = new Players(names);
+ players.initDraw(getCustomCardDeck());
+
+ assertThat(players.getFirstOrderPlayerName()).isEqualTo("미립");
+ players.passTurnToNextPlayer();
+ assertThat(players.getFirstOrderPlayerName()).isEqualTo("현구막");
+ }
+
+ @Test
+ @DisplayName("가장 앞 차례 플레이어가 카드를 뽑았는지 확인한다.")
+ void testPlayerDrawCard() {
+ List name = Collections.singletonList("미립");
+ Players players = new Players(name);
+ players.initDraw(getDrawTestCardDeck());
+
+ assertThat(players.getFirstOrderPlayer().getScoreToInt()).isEqualTo(12);
+ players.drawFirstOrderPlayer(Card.valueOf(Pattern.DIAMOND, Number.THREE));
+ assertThat(players.getFirstOrderPlayer().getScoreToInt()).isEqualTo(15);
+ }
+
+ @Test
+ @DisplayName("가장 앞 차례 플레이어가 Stay 상태로 변화에 성공했는지 확인한다.")
+ void testPlayerStateToStay() {
+ List name = Collections.singletonList("미립");
+ Players players = new Players(name);
+ players.initDraw(getDrawTestCardDeck());
+ players.stayFirstOrderPlayer();
+
+ assertThat(players.isFinishedCurrentPlayer()).isTrue();
+ }
+
+ private CardDeck getDrawTestCardDeck() {
+ Card firstCard = Card.valueOf(Pattern.HEART, Number.TWO);
+ Card secondCard = Card.valueOf(Pattern.HEART, Number.KING);
+ return CardDeck.customDeck(Arrays.asList(firstCard, secondCard));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/blackjack/domain/participant/state/BlackjackTest.java b/src/test/java/blackjack/domain/participant/state/BlackjackTest.java
new file mode 100644
index 0000000000..313a3cc1e5
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/BlackjackTest.java
@@ -0,0 +1,87 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import blackjack.domain.Result;
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class BlackjackTest {
+
+ private Card card;
+ private State blackjack;
+
+ @BeforeEach
+ void setUp() {
+ this.card = Card.valueOf(Pattern.HEART, Number.KING);
+ Card firstCard = Card.valueOf(Pattern.HEART, Number.ACE);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.KING);
+ this.blackjack = Init.draw(firstCard, secondCard);
+ }
+
+ @Test
+ @DisplayName("첫 2장을 받은 후 상태가 Blackjack인지 테스트")
+ void testFromInitDrawToHit() {
+ assertThat(this.blackjack).isInstanceOf(Blackjack.class);
+ }
+
+ @Test
+ @DisplayName("Blackjack 에서 draw 요청시 에러처리")
+ void testDrawException() {
+ assertThatThrownBy(() -> this.blackjack.draw(this.card))
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ @DisplayName("Blackjack 에서 stay 요청시 에러처리")
+ void testStayException() {
+ assertThatThrownBy(() -> this.blackjack.stay())
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ @DisplayName("Blackjack 가 종료된 상태임을 확인")
+ void testIsFinishedTrue() {
+ assertThat(this.blackjack.isFinished()).isTrue();
+ }
+
+ @Test
+ @DisplayName("Blackjack 에서 카드목록을 요구했을 시 가져갔던 카드개수가 맞는지 확인")
+ void testHitCards() {
+ assertThat(this.blackjack.cards()).hasSize(2);
+ }
+
+ @Test
+ @DisplayName("플레이어 Blackjack기준 딜러의 Blackjack을 받았을 때 무승부 반환")
+ void testPlayerBlackjackVersusDealerBlackjack() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.ACE);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerBlackjack = Init.draw(firstCard, secondCard);
+ assertThat(this.blackjack.calculatePlayerResult(dealerBlackjack)).isEqualTo(Result.DRAW);
+ }
+
+ @Test
+ @DisplayName("플레이어 Blackjack기준 딜러의 Stay를 받았을 때 승리 반환")
+ void testPlayerBlackjackVersusDealerStay() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.TWO);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerHit = Init.draw(firstCard, secondCard);
+ State dealerStay = dealerHit.stay();
+ assertThat(this.blackjack.calculatePlayerResult(dealerStay)).isEqualTo(Result.WIN);
+ }
+
+ @Test
+ @DisplayName("플레이어 Blackjack기준 딜러의 Bust를 받았을 때 승리 반환")
+ void testPlayerBlackjackVersusDealerBust() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.KING);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerHit = Init.draw(firstCard, secondCard);
+ State dealerBust = dealerHit.draw(Card.valueOf(Pattern.HEART, Number.JACK));
+ assertThat(this.blackjack.calculatePlayerResult(dealerBust)).isEqualTo(Result.WIN);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/blackjack/domain/participant/state/BustTest.java b/src/test/java/blackjack/domain/participant/state/BustTest.java
new file mode 100644
index 0000000000..74fe6f20ee
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/BustTest.java
@@ -0,0 +1,82 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import blackjack.domain.Result;
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import java.util.Arrays;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class BustTest {
+
+ private State bust;
+ private Card card;
+
+ @BeforeEach
+ void setUp() {
+ Card firstCard = Card.valueOf(Pattern.HEART, Number.TEN);
+ Card secondCard = Card.valueOf(Pattern.HEART, Number.KING);
+ this.card = Card.valueOf(Pattern.HEART, Number.FIVE);
+ this.bust = new Bust(new Hand(Arrays.asList(firstCard, secondCard)));
+ }
+
+ @Test
+ @DisplayName("Bust 에서 draw 요청시 에러처리")
+ void testDrawException() {
+ assertThatThrownBy(() -> this.bust.draw(this.card))
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ @DisplayName("Bust 에서 stay 요청시 에러처리")
+ void testStayException() {
+ assertThatThrownBy(() -> this.bust.stay())
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ @DisplayName("Bust 가 종료된 상태임을 확인")
+ void testIsFinishedTrue() {
+ assertThat(this.bust.isFinished()).isTrue();
+ }
+
+ @Test
+ @DisplayName("Bust 에서 카드목록을 요구했을 시 가져갔던 카드개수가 맞는지 확인")
+ void testHitCards() {
+ assertThat(this.bust.cards()).hasSize(2);
+ }
+
+ @Test
+ @DisplayName("플레이어 Bust기준 딜러의 Blackjack을 받았을 때 패배 반환")
+ void testPlayerBlackjackVersusDealerBlackjack() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.ACE);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerBlackjack = Init.draw(firstCard, secondCard);
+ assertThat(this.bust.calculatePlayerResult(dealerBlackjack)).isEqualTo(Result.LOSE);
+ }
+
+ @Test
+ @DisplayName("플레이어 Bust기준 딜러의 Stay를 받았을 때 패배 반환")
+ void testPlayerBlackjackVersusDealerStay() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.TWO);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerHit = Init.draw(firstCard, secondCard);
+ State dealerStay = dealerHit.stay();
+ assertThat(this.bust.calculatePlayerResult(dealerStay)).isEqualTo(Result.LOSE);
+ }
+
+ @Test
+ @DisplayName("플레이어 Bust기준 딜러의 Bust를 받았을 때 패배 반환")
+ void testPlayerBlackjackVersusDealerBust() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.KING);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerHit = Init.draw(firstCard, secondCard);
+ State dealerBust = dealerHit.draw(Card.valueOf(Pattern.HEART, Number.JACK));
+ assertThat(this.bust.calculatePlayerResult(dealerBust)).isEqualTo(Result.LOSE);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/blackjack/domain/participant/state/HandTest.java b/src/test/java/blackjack/domain/participant/state/HandTest.java
new file mode 100644
index 0000000000..1a55e02a22
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/HandTest.java
@@ -0,0 +1,48 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import java.util.Collections;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class HandTest {
+
+ private Hand hand;
+
+ @BeforeEach
+ void setUp() {
+ this.hand = new Hand(
+ Collections.singletonList(Card.valueOf(Pattern.DIAMOND, Number.THREE))
+ );
+ }
+
+ @Test
+ @DisplayName("손패에 카드 추가 테스트")
+ void testAddCardInHand() {
+ this.hand.addCard(Card.valueOf(Pattern.DIAMOND, Number.TWO));
+ assertThat(this.hand.getScoreToInt()).isEqualTo(5);
+ }
+
+ @Test
+ @DisplayName("손패 점수 총합 테스트")
+ void testHandsTotalScore() {
+ this.hand.addCard(Card.valueOf(Pattern.CLOVER, Number.EIGHT));
+ this.hand.addCard(Card.valueOf(Pattern.CLOVER, Number.NINE));
+ this.hand.addCard(Card.valueOf(Pattern.CLOVER, Number.QUEEN));
+ assertThat(this.hand.getScoreToInt()).isEqualTo(30);
+ }
+
+ @Test
+ @DisplayName("SoftAce에서 HardAce로 자동변환 테스트")
+ void testAceAutoChange() {
+ this.hand.addCard(Card.valueOf(Pattern.DIAMOND, Number.ACE));
+ this.hand.addCard(Card.valueOf(Pattern.CLOVER, Number.ACE));
+ this.hand.addCard(Card.valueOf(Pattern.HEART, Number.ACE));
+ assertThat(this.hand.getScoreToInt()).isEqualTo(16);
+ }
+}
diff --git a/src/test/java/blackjack/domain/participant/state/HitTest.java b/src/test/java/blackjack/domain/participant/state/HitTest.java
new file mode 100644
index 0000000000..f34672fef8
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/HitTest.java
@@ -0,0 +1,62 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class HitTest {
+
+ private Card toBustCard;
+ private Card toHitCard;
+ private State hit;
+
+ @BeforeEach
+ void setUp() {
+ Card firstCard = Card.valueOf(Pattern.HEART, Number.FIVE);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ this.hit = Init.draw(firstCard, secondCard);
+ this.toBustCard = Card.valueOf(Pattern.HEART, Number.KING);
+ this.toHitCard = Card.valueOf(Pattern.HEART, Number.TWO);
+ }
+
+ @Test
+ @DisplayName("첫 2장을 받은 후 상태가 Hit인지 테스트")
+ void testFromInitDrawToHit() {
+ assertThat(this.hit).isInstanceOf(Hit.class);
+ }
+
+ @Test
+ @DisplayName("Hit 에서 추가로 카드를 받았을 때 합이 21 이하인 경우 Hit이 되는지 테스트")
+ void testFromHitToHit() {
+ assertThat(this.hit.draw(this.toHitCard)).isInstanceOf(Hit.class);
+ }
+
+ @Test
+ @DisplayName("Hit 에서 추가로 카드를 받았을 때 합이 21을 넘기는 경우 Bust가 되는지 테스트")
+ void testFromHitToBust() {
+ assertThat(this.hit.draw(this.toBustCard)).isInstanceOf(Bust.class);
+ }
+
+ @Test
+ @DisplayName("Hit 에서 추가로 카드를 받고 싶지 않을 때 Stay가 되는지 테스트")
+ void testFromHitToStay() {
+ assertThat(this.hit.stay()).isInstanceOf(Stay.class);
+ }
+
+ @Test
+ @DisplayName("Hit 에서 더 이상 뽑을 수 없는 상태인지 질문이 왔을 때 false 를 반환하는지 테스트")
+ void testIfAskedFinishedThenReplyNo() {
+ assertThat(this.hit.isFinished()).isFalse();
+ }
+
+ @Test
+ @DisplayName("Hit 에서 카드목록을 요구했을 시 가져갔던 카드개수가 맞는지 확인")
+ void testHitCards() {
+ assertThat(this.hit.cards()).hasSize(2);
+ }
+}
diff --git a/src/test/java/blackjack/domain/participant/state/InitTest.java b/src/test/java/blackjack/domain/participant/state/InitTest.java
new file mode 100644
index 0000000000..67bdd6459e
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/InitTest.java
@@ -0,0 +1,34 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class InitTest {
+
+ @Test
+ @DisplayName("처음 받은 2장의 카드를 받은 후 Blackjack인지 테스트")
+ void testInitDrawBlackjack() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.ACE);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+
+ State blackjack = Init.draw(firstCard, secondCard);
+
+ assertThat(blackjack).isInstanceOf(Blackjack.class);
+ }
+
+ @Test
+ @DisplayName("처음 받은 2장의 카드를 받은 후 Hit인지 테스트")
+ void testInitDrawHit() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.TWO);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+
+ State hit = Init.draw(firstCard, secondCard);
+
+ assertThat(hit).isInstanceOf(Hit.class);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/blackjack/domain/participant/state/ScoreTest.java b/src/test/java/blackjack/domain/participant/state/ScoreTest.java
new file mode 100644
index 0000000000..98a63ddac4
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/ScoreTest.java
@@ -0,0 +1,58 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import blackjack.domain.Result;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class ScoreTest {
+
+ @Test
+ @DisplayName("점수 생성 테스트")
+ void testCreateScore() {
+ Score score = new Score(15);
+ assertThat(score.getValue()).isEqualTo(15);
+ }
+
+ @Test
+ @DisplayName("점수 버스트 테스트")
+ void testScoreBust() {
+ Score notBustScore = new Score(21);
+ assertThat(notBustScore.isBust()).isFalse();
+
+ Score bustScore = new Score(22);
+ assertThat(bustScore.isBust()).isTrue();
+ }
+
+ @Test
+ @DisplayName("점수 블랙잭 테스트")
+ void testScoreBlackjack() {
+ Score notBlackjackScore = new Score(20);
+ assertThat(notBlackjackScore.isBlackjack()).isFalse();
+
+ Score blackjackScore = new Score(21);
+ assertThat(blackjackScore.isBlackjack()).isTrue();
+ }
+
+ @Test
+ @DisplayName("점수 버스트일 경우 줄이기 테스트")
+ void testReduceScoreIfBust() {
+ Score score = new Score(25);
+ assertThat(score.isBust()).isTrue();
+ assertThat(score.reduceScoreIfBust().isBust()).isFalse();
+ }
+
+ @Test
+ @DisplayName("점수 비교 테스트")
+ void testCompareScore() {
+ Score compareScore = new Score(17);
+ Score firstScore = new Score(15);
+ Score secondScore = new Score(19);
+ Score thirdScore = new Score(17);
+
+ assertThat(compareScore.compare(firstScore)).isEqualTo(Result.WIN);
+ assertThat(compareScore.compare(secondScore)).isEqualTo(Result.LOSE);
+ assertThat(compareScore.compare(thirdScore)).isEqualTo(Result.DRAW);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/blackjack/domain/participant/state/StayTest.java b/src/test/java/blackjack/domain/participant/state/StayTest.java
new file mode 100644
index 0000000000..95cfe74a3f
--- /dev/null
+++ b/src/test/java/blackjack/domain/participant/state/StayTest.java
@@ -0,0 +1,92 @@
+package blackjack.domain.participant.state;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import blackjack.domain.Result;
+import blackjack.domain.carddeck.Card;
+import blackjack.domain.carddeck.Number;
+import blackjack.domain.carddeck.Pattern;
+import java.util.Collections;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class StayTest {
+
+ private State stay;
+ private Card card;
+
+ @BeforeEach
+ void setUp() {
+ this.card = Card.valueOf(Pattern.HEART, Number.FIVE);
+ this.stay = new Stay(new Hand(Collections.singletonList(this.card)));
+ }
+
+ @Test
+ @DisplayName("Stay 에서 draw 요청시 에러처리")
+ void testDrawException() {
+ assertThatThrownBy(() -> this.stay.draw(this.card))
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ @DisplayName("Stay 에서 stay 요청시 에러처리")
+ void testStayException() {
+ assertThatThrownBy(() -> this.stay.stay())
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ @DisplayName("Stay 가 종료된 상태임을 확인")
+ void testIsFinishedTrue() {
+ assertThat(this.stay.isFinished()).isTrue();
+ }
+
+ @Test
+ @DisplayName("Stay 에서 카드목록을 요구했을 시 가져갔던 카드개수가 맞는지 확인")
+ void testHitCards() {
+ assertThat(this.stay.cards()).hasSize(1);
+ }
+
+ @Test
+ @DisplayName("플레이어 Stay기준 딜러의 Blackjack을 받았을 때 패배 반환")
+ void testPlayerBlackjackVersusDealerBlackjack() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.ACE);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerBlackjack = Init.draw(firstCard, secondCard);
+ assertThat(this.stay.calculatePlayerResult(dealerBlackjack)).isEqualTo(Result.LOSE);
+ }
+
+ @Test
+ @DisplayName("플레이어 Stay기준 딜러의 Bust를 받았을 때 승리 반환")
+ void testPlayerBlackjackVersusDealerBust() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.KING);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerHit = Init.draw(firstCard, secondCard);
+ State dealerBust = dealerHit.draw(Card.valueOf(Pattern.HEART, Number.JACK));
+ assertThat(this.stay.calculatePlayerResult(dealerBust)).isEqualTo(Result.WIN);
+ }
+
+ @Test
+ @DisplayName("플레이어 Stay기준 딜러의 Stay를 받았을 때 점수비교 결과 반환")
+ void testPlayerBlackjackVersusDealerStay() {
+ Card firstCard = Card.valueOf(Pattern.DIAMOND, Number.TWO);
+ Card secondCard = Card.valueOf(Pattern.DIAMOND, Number.TEN);
+ State dealerHit = Init.draw(firstCard, secondCard);
+ State dealerStay = dealerHit.stay();
+ assertThat(this.stay.calculatePlayerResult(dealerStay)).isEqualTo(Result.LOSE); // 5 vs 12
+
+ firstCard = Card.valueOf(Pattern.DIAMOND, Number.TWO);
+ secondCard = Card.valueOf(Pattern.DIAMOND, Number.THREE);
+ dealerHit = Init.draw(firstCard, secondCard);
+ dealerStay = dealerHit.stay();
+ assertThat(this.stay.calculatePlayerResult(dealerStay)).isEqualTo(Result.DRAW); // 5 vs 5
+
+ firstCard = Card.valueOf(Pattern.DIAMOND, Number.TWO);
+ secondCard = Card.valueOf(Pattern.HEART, Number.TWO);
+ dealerHit = Init.draw(firstCard, secondCard);
+ dealerStay = dealerHit.stay();
+ assertThat(this.stay.calculatePlayerResult(dealerStay)).isEqualTo(Result.WIN); // 5 vs 4
+ }
+}
\ 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 e69de29bb2..0000000000
diff --git a/src/test/java/rentcar/abstractcar/AvanteTest.java b/src/test/java/rentcar/abstractcar/AvanteTest.java
new file mode 100644
index 0000000000..2f695caccc
--- /dev/null
+++ b/src/test/java/rentcar/abstractcar/AvanteTest.java
@@ -0,0 +1,41 @@
+package rentcar.abstractcar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class AvanteTest {
+
+ private Avante avante;
+
+ @BeforeEach
+ private void setUp() {
+ avante = new Avante(150);
+ }
+
+ @Test
+ @DisplayName("아반떼의 연비 반환 테스트")
+ void testDistancePerLiter() {
+ assertThat(avante.getDistancePerLiter()).isEqualTo(15);
+ }
+
+ @Test
+ @DisplayName("아반뗴 생성할 때 이동할 거리 주입된다.")
+ void testTripDistance() {
+ assertThat(avante.getTripDistance()).isEqualTo(150);
+ }
+
+ @Test
+ @DisplayName("아반떼에 필요한 주유량 테스트")
+ void testChargeQuantity() {
+ assertThat(avante.getChargeQuantity()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("아반떼 이름 반환된다.")
+ void testName() {
+ assertThat(avante.getName()).isEqualTo("Avante");
+ }
+}
diff --git a/src/test/java/rentcar/abstractcar/K5Test.java b/src/test/java/rentcar/abstractcar/K5Test.java
new file mode 100644
index 0000000000..0327191d8a
--- /dev/null
+++ b/src/test/java/rentcar/abstractcar/K5Test.java
@@ -0,0 +1,41 @@
+package rentcar.abstractcar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class K5Test {
+
+ private K5 k5;
+
+ @BeforeEach
+ private void setUp() {
+ k5 = new K5(130);
+ }
+
+ @Test
+ @DisplayName("K5의 연비 반환 테스트")
+ void testDistancePerLiter() {
+ assertThat(k5.getDistancePerLiter()).isEqualTo(13);
+ }
+
+ @Test
+ @DisplayName("K5 생성할 때 이동할 거리 주입된다.")
+ void testTripDistance() {
+ assertThat(k5.getTripDistance()).isEqualTo(130);
+ }
+
+ @Test
+ @DisplayName("K5에 필요한 주유량 테스트")
+ void testChargeQuantity() {
+ assertThat(k5.getChargeQuantity()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("K5 이름 반환된다.")
+ void testName() {
+ assertThat(k5.getName()).isEqualTo("K5");
+ }
+}
diff --git a/src/test/java/rentcar/abstractcar/RentCompanyTest.java b/src/test/java/rentcar/abstractcar/RentCompanyTest.java
new file mode 100644
index 0000000000..1ca29b0d1e
--- /dev/null
+++ b/src/test/java/rentcar/abstractcar/RentCompanyTest.java
@@ -0,0 +1,29 @@
+package rentcar.abstractcar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+public class RentCompanyTest {
+
+ private static final String NEWLINE = System.getProperty("line.separator");
+
+ @Test
+ public void report() throws Exception {
+ RentCompany company = RentCompany.create();
+ 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리터" + NEWLINE
+ );
+ }
+}
diff --git a/src/test/java/rentcar/abstractcar/SonataTest.java b/src/test/java/rentcar/abstractcar/SonataTest.java
new file mode 100644
index 0000000000..5a4969a0f7
--- /dev/null
+++ b/src/test/java/rentcar/abstractcar/SonataTest.java
@@ -0,0 +1,41 @@
+package rentcar.abstractcar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class SonataTest {
+
+ private Sonata sonata;
+
+ @BeforeEach
+ private void setUp() {
+ sonata = new Sonata(100);
+ }
+
+ @Test
+ @DisplayName("소나타의 연비 반환 테스트")
+ void testDistancePerLiter() {
+ assertThat(sonata.getDistancePerLiter()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("소나타 생성할 때 이동할 거리 주입된다.")
+ void testTripDistance() {
+ assertThat(sonata.getTripDistance()).isEqualTo(100);
+ }
+
+ @Test
+ @DisplayName("소나타에 필요한 주유량 테스트")
+ void testChargeQuantity() {
+ assertThat(sonata.getChargeQuantity()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("소나타 이름 반환된다.")
+ void testName() {
+ assertThat(sonata.getName()).isEqualTo("Sonata");
+ }
+}
diff --git a/src/test/java/rentcar/interfacecar/AvanteTest.java b/src/test/java/rentcar/interfacecar/AvanteTest.java
new file mode 100644
index 0000000000..6ac2388c9e
--- /dev/null
+++ b/src/test/java/rentcar/interfacecar/AvanteTest.java
@@ -0,0 +1,41 @@
+package rentcar.interfacecar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class AvanteTest {
+
+ private Avante avante;
+
+ @BeforeEach
+ private void setUp() {
+ avante = new Avante(150);
+ }
+
+ @Test
+ @DisplayName("아반떼의 연비 반환 테스트")
+ void testDistancePerLiter() {
+ assertThat(avante.getDistancePerLiter()).isEqualTo(15);
+ }
+
+ @Test
+ @DisplayName("아반뗴 생성할 때 이동할 거리 주입된다.")
+ void testTripDistance() {
+ assertThat(avante.getTripDistance()).isEqualTo(150);
+ }
+
+ @Test
+ @DisplayName("아반떼에 필요한 주유량 테스트")
+ void testChargeQuantity() {
+ assertThat(avante.getChargeQuantity()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("아반떼 이름 반환된다.")
+ void testName() {
+ assertThat(avante.getName()).isEqualTo("Avante");
+ }
+}
diff --git a/src/test/java/rentcar/interfacecar/K5Test.java b/src/test/java/rentcar/interfacecar/K5Test.java
new file mode 100644
index 0000000000..5ed3c4373c
--- /dev/null
+++ b/src/test/java/rentcar/interfacecar/K5Test.java
@@ -0,0 +1,41 @@
+package rentcar.interfacecar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class K5Test {
+
+ private K5 k5;
+
+ @BeforeEach
+ private void setUp() {
+ k5 = new K5(130);
+ }
+
+ @Test
+ @DisplayName("K5의 연비 반환 테스트")
+ void testDistancePerLiter() {
+ assertThat(k5.getDistancePerLiter()).isEqualTo(13);
+ }
+
+ @Test
+ @DisplayName("K5 생성할 때 이동할 거리 주입된다.")
+ void testTripDistance() {
+ assertThat(k5.getTripDistance()).isEqualTo(130);
+ }
+
+ @Test
+ @DisplayName("K5에 필요한 주유량 테스트")
+ void testChargeQuantity() {
+ assertThat(k5.getChargeQuantity()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("K5 이름 반환된다.")
+ void testName() {
+ assertThat(k5.getName()).isEqualTo("K5");
+ }
+}
diff --git a/src/test/java/rentcar/interfacecar/RentCompanyTest.java b/src/test/java/rentcar/interfacecar/RentCompanyTest.java
new file mode 100644
index 0000000000..6ef0ad82bb
--- /dev/null
+++ b/src/test/java/rentcar/interfacecar/RentCompanyTest.java
@@ -0,0 +1,29 @@
+package rentcar.interfacecar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+public class RentCompanyTest {
+
+ private static final String NEWLINE = System.getProperty("line.separator");
+
+ @Test
+ public void report() throws Exception {
+ RentCompany company = RentCompany.create();
+ 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리터" + NEWLINE
+ );
+ }
+}
diff --git a/src/test/java/rentcar/interfacecar/SonataTest.java b/src/test/java/rentcar/interfacecar/SonataTest.java
new file mode 100644
index 0000000000..b0ccf4056e
--- /dev/null
+++ b/src/test/java/rentcar/interfacecar/SonataTest.java
@@ -0,0 +1,41 @@
+package rentcar.interfacecar;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class SonataTest {
+
+ private Sonata sonata;
+
+ @BeforeEach
+ private void setUp() {
+ sonata = new Sonata(100);
+ }
+
+ @Test
+ @DisplayName("소나타의 연비 반환 테스트")
+ void testDistancePerLiter() {
+ assertThat(sonata.getDistancePerLiter()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("소나타 생성할 때 이동할 거리 주입된다.")
+ void testTripDistance() {
+ assertThat(sonata.getTripDistance()).isEqualTo(100);
+ }
+
+ @Test
+ @DisplayName("소나타에 필요한 주유량 테스트")
+ void testChargeQuantity() {
+ assertThat(sonata.getChargeQuantity()).isEqualTo(10);
+ }
+
+ @Test
+ @DisplayName("소나타 이름 반환된다.")
+ void testName() {
+ assertThat(sonata.getName()).isEqualTo("Sonata");
+ }
+}