diff --git a/README.md b/README.md index 05654d74e8..53c063b58a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ## 구현 기능 목록 -- [x] 게임참가자(플레이어)의 이름을 입력받는다. +- [x] 1. 게임참가자(플레이어)의 이름을 입력받는다. - [x] 입력된 이름들이 플레이어가 된다. - [x] 플레이어의 이름은 (,)로 구분된다. - [x] 예외 처리: (,) 사이의 공백 제거 @@ -19,17 +19,26 @@ - [x] 예외 처리: 5글자가 넘거나 공백일 경우 - [x] 플레이어는 최소 2명 있어야 한다. (사다리의 다리는 최소 2개 이상이므로) - [x] 예외 처리: 플레이어가 2명 미만일 경우 -- [x] 사다리 높이를 입력받는다. +- [x] 2. 실행 결과(당첨 상품)를 입력받는다. + - [x] 예외 처리: 5글자가 넘거나 공백일 경우 + - [x] 예외 처리: 플레이어의 수와 상품의 수가 같지 않을 경우 +- [x] 3. 사다리 높이를 입력받는다. - [x] 예외 처리: 사다리 높이가 1 미만일 경우 -- [x] 플레이어들을 출력한다. +- [x] 4. 플레이어들을 출력한다. - [x] 플레이어 이름 - [x] 플레이어 이름이 5글자 미만일 경우 부족한 만큼 왼쪽으로 공백을 채운다. -- [x] 사다리를 출력한다. +- [x] 5. 사다리를 출력한다. - [x] 사다리의 열을 생성한다. - [x] 각 열은 기둥과 바(bar)로 이루어져있다. - [x] 기둥 사이를 잇는 바를 랜덤으로 생성한다. - [x] 바는 연속될 수 없다. - [x] 바는 '-' 5개로 이루어져있다. - [x] 입력받은 높이만큼 열을 추가한다. - +- [x] 6. 당첨 상품 들을 출력한다. +- [x] 7. 사다리 게임을 실행한다. + - [x] 사용자의 현재 위치를 기준으로 사다리를 타고, 최종 위치를 계산한다. + - [x] 사용자의 현재 위치와 bar의 위치가 1만큼 작으면 사용자의 현재위치는 1만큼 감소 + - [x] 사용자의 현재 위치보다 bar의 위치가 같으면 사용자의 현재위치가 1만큼 증가 +- [x] 8. 결과를 보고싶은 플레이어(혹은 전체)를 묻고 입력받는다. +- [x] 9. 해당 플레이어(혹은 전체)의 실행 결과를 반환한다. diff --git a/src/main/java/ladder/Application.java b/src/main/java/ladder/Application.java index bea374a704..a816702e61 100644 --- a/src/main/java/ladder/Application.java +++ b/src/main/java/ladder/Application.java @@ -1,19 +1,29 @@ package ladder; -import ladder.domain.Height; -import ladder.domain.Ladder; -import ladder.domain.Players; +import ladder.domain.*; import ladder.view.InputView; import ladder.view.OutputView; +import java.util.HashMap; +import java.util.Map; + public class Application { public static void main(String[] args) { Players players = Players.of(InputView.askPlayers()); + Prizes prizes = Prizes.from(InputView.askPrizes(), players.numberOfPlayers()); Height height = Height.from(InputView.askHeight()); Ladder ladder = Ladder.from(players, height); + OutputView.drawLadder(players, ladder, prizes); + + GameResult gameResult = GameResult.of(players, ladder, prizes); + String wantedPlayer = InputView.askWhichResultWant(); - OutputView.printResult(players, ladder); + if ("all".equals(wantedPlayer)) { + OutputView.printAllResult(gameResult); + return; + } + OutputView.printSingleResult(gameResult.findResult(wantedPlayer)); } } diff --git a/src/main/java/ladder/domain/Bar.java b/src/main/java/ladder/domain/Bar.java new file mode 100644 index 0000000000..108781fc79 --- /dev/null +++ b/src/main/java/ladder/domain/Bar.java @@ -0,0 +1,18 @@ +package ladder.domain; + +public class Bar { + + private final boolean bar; + + private Bar(boolean bar) { + this.bar = bar; + } + + public static Bar from(boolean doesBarExist) { + return new Bar(doesBarExist); + } + + public boolean isExist() { + return bar; + } +} diff --git a/src/main/java/ladder/domain/BarGenerator.java b/src/main/java/ladder/domain/BarGenerator.java index edf646c426..76e97a5c55 100644 --- a/src/main/java/ladder/domain/BarGenerator.java +++ b/src/main/java/ladder/domain/BarGenerator.java @@ -1,5 +1,6 @@ package ladder.domain; +@FunctionalInterface public interface BarGenerator { boolean generateBar(); diff --git a/src/main/java/ladder/domain/GameResult.java b/src/main/java/ladder/domain/GameResult.java new file mode 100644 index 0000000000..6d491a9910 --- /dev/null +++ b/src/main/java/ladder/domain/GameResult.java @@ -0,0 +1,46 @@ +package ladder.domain; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class GameResult { + private static final String ALERT_FOR_INVALID_PLAYER_NAME = "입력하신 플레이어는 존재하지 않습니다."; + + private final Map resultMap; + + private GameResult(Map resultMap) { + this.resultMap = new HashMap<>(resultMap); + } + + public static GameResult of(Players players, Ladder ladder, Prizes prizes) { + return new GameResult(playGame(players, ladder, prizes)); + } + + private static Map playGame(Players players, Ladder ladder, Prizes prizes) { + Map resultMap = new HashMap<>(); + int numberOfPlayers = players.numberOfPlayers(); + + for (int i = 0; i < numberOfPlayers; i++) { + Player player = players.getPlayers().get(i); + Position finalPosition = ladder.goThroughLinesFrom(Position.from(i)); + Prize prize = prizes.getPrizes().get(finalPosition.getPosition()); + + resultMap.put(player, prize); + } + return resultMap; + } + + public String findResult(String wantedPlayer) { + Player playerWanted = resultMap.keySet().stream() + .filter(player -> player.isSame(wantedPlayer)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(ALERT_FOR_INVALID_PLAYER_NAME)); + + return resultMap.get(playerWanted).getPrize(); + } + + public Map getResultMap() { + return Collections.unmodifiableMap(resultMap); + } +} diff --git a/src/main/java/ladder/domain/Height.java b/src/main/java/ladder/domain/Height.java index e50c1d8420..ce819d20ab 100644 --- a/src/main/java/ladder/domain/Height.java +++ b/src/main/java/ladder/domain/Height.java @@ -7,9 +7,7 @@ public class Height { private final int height; private Height(int inputHeight) { - if (inputHeight < MINIMUM_LADDER_HEIGHT) { - throw new IllegalArgumentException(ALERT_MINIMUM_LADDER_HEIGHT); - } + validationHeight(inputHeight); this.height = inputHeight; } @@ -17,7 +15,13 @@ public static Height from(int inputHeight) { return new Height(inputHeight); } - public int getHeight() { + private void validationHeight(int inputHeight) { + if (inputHeight < MINIMUM_LADDER_HEIGHT) { + throw new IllegalArgumentException(ALERT_MINIMUM_LADDER_HEIGHT); + } + } + + int getHeight() { return height; } } diff --git a/src/main/java/ladder/domain/Ladder.java b/src/main/java/ladder/domain/Ladder.java index 12f4a23121..b3072477a1 100644 --- a/src/main/java/ladder/domain/Ladder.java +++ b/src/main/java/ladder/domain/Ladder.java @@ -1,5 +1,6 @@ package ladder.domain; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -10,7 +11,7 @@ public class Ladder { private List lines; private Ladder(List lines) { - this.lines = lines; + this.lines = new ArrayList<>(lines); } public static Ladder from(Players players, Height height) { @@ -20,6 +21,13 @@ public static Ladder from(Players players, Height height) { .collect(Collectors.toList())); } + Position goThroughLinesFrom(Position position) { + for (Line line : lines) { + position = line.travel(position); + } + return position; + } + public List getLines() { return Collections.unmodifiableList(lines); } diff --git a/src/main/java/ladder/domain/Line.java b/src/main/java/ladder/domain/Line.java index 6eb68ae13d..edb0f5dd9d 100644 --- a/src/main/java/ladder/domain/Line.java +++ b/src/main/java/ladder/domain/Line.java @@ -6,9 +6,9 @@ public class Line { - private List bars; + private List bars; - private Line(List bars) { + Line(List bars) { this.bars = new ArrayList<>(bars); } @@ -17,7 +17,18 @@ public static Line from(int numberOfPlayers) { return new Line(lineMaker.generateBars(numberOfPlayers)); } - public List getBars() { + public List getBars() { return Collections.unmodifiableList(bars); } + + Position travel(Position position) { + if (bars.get(position.getPosition()).isExist()) { //사용자의 현재 위치와 bar의 위치가 같으면 사용자의 현재위치가 1만큼 증가 + return position.moveToRight(); + } + if (position.getPosition() > 0 && bars.get(position.getLeftPosition()).isExist()) { //사용자의 현재 위치보다 bar의 위치가 1만큼 작으면 사용자의 현재위치는 1만큼 감소 + return position.moveToLeft(); + } + return position; + } //TODO: 이 로직을 Bar 객체로 위임하고 싶은데, Bar 2개를 사용해서 위치를 갱신하는 방식이라 이 곳에서 처리하는 상태 + } diff --git a/src/main/java/ladder/domain/LineMaker.java b/src/main/java/ladder/domain/LineMaker.java index a55022a900..f03ed11c79 100644 --- a/src/main/java/ladder/domain/LineMaker.java +++ b/src/main/java/ladder/domain/LineMaker.java @@ -4,29 +4,40 @@ import java.util.List; class LineMaker { + private static final int NUMBER_OF_FIRST_AND_LAST_BAR = 2; - private List randomBars = new ArrayList<>(); - private BarGeneratorImpl barGenerator = new BarGeneratorImpl(); + private List randomBars; + private RandomBarGenerator barGenerator = new RandomBarGenerator(); - List generateBars(int numberOfPlayers) { - randomBars.add(barGenerator.generateBar()); - for (int i = 1; i < numberOfPlayers - 1; i++) { - boolean previousBarExist = randomBars.get(i - 1); - addNextBar(previousBarExist); - } - addBlankBar(); + List generateBars(int numberOfPlayers) { + this.randomBars = new ArrayList<>(); + generateFirstBar(); + generateMiddleBars(numberOfPlayers); + generateLastBar(); return randomBars; } - private void addNextBar(boolean previousBarExist) { - if (previousBarExist) { - addBlankBar(); + private void generateFirstBar() { + randomBars.add(Bar.from(barGenerator.generateBar())); + } + + private void generateMiddleBars(int numberOfPlayers) { + int spaceForMiddleBars = numberOfPlayers - NUMBER_OF_FIRST_AND_LAST_BAR; + for (int i = 0; i < spaceForMiddleBars; i++) { + Bar previousBar = randomBars.get(i); + addNextBar(previousBar); + } + } + + private void addNextBar(Bar previousBar) { + if (previousBar.isExist()) { + generateLastBar(); return; } - randomBars.add(barGenerator.generateBar()); + randomBars.add(Bar.from(barGenerator.generateBar())); } - private void addBlankBar() { - randomBars.add(false); + private void generateLastBar() { + randomBars.add(Bar.from(Boolean.FALSE)); } } diff --git a/src/main/java/ladder/domain/Player.java b/src/main/java/ladder/domain/Player.java index a0a993b979..300723cc63 100644 --- a/src/main/java/ladder/domain/Player.java +++ b/src/main/java/ladder/domain/Player.java @@ -25,6 +25,10 @@ private void validationPlayerName(String name) { } } + boolean isSame(String wantedPlayer) { + return wantedPlayer.equals(name); + } + public String getName() { return name; } diff --git a/src/main/java/ladder/domain/Players.java b/src/main/java/ladder/domain/Players.java index 2e2ea84b2a..c0d8ae6d52 100644 --- a/src/main/java/ladder/domain/Players.java +++ b/src/main/java/ladder/domain/Players.java @@ -1,5 +1,6 @@ package ladder.domain; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -13,10 +14,8 @@ public class Players { private final List players; private Players(List players) { - if (players.size() < MINIMUM_NUMBER_OF_PLAYERS) { - throw new IllegalArgumentException(ALERT_SHORTAGE_OF_NUMBER_OF_PLAYERS); - } - this.players = players; + validationPlayers(players); + this.players = new ArrayList<>(players); } public static Players of(String inputNames) { @@ -26,6 +25,12 @@ public static Players of(String inputNames) { .collect(Collectors.toList())); } + private void validationPlayers(List players) { + if (players.size() < MINIMUM_NUMBER_OF_PLAYERS) { + throw new IllegalArgumentException(ALERT_SHORTAGE_OF_NUMBER_OF_PLAYERS); + } + } + public int numberOfPlayers() { return players.size(); } diff --git a/src/main/java/ladder/domain/Position.java b/src/main/java/ladder/domain/Position.java new file mode 100644 index 0000000000..f9bda7ff3a --- /dev/null +++ b/src/main/java/ladder/domain/Position.java @@ -0,0 +1,49 @@ +package ladder.domain; + +public class Position { + + private static final int MOVE_ONE_STEP_TO_RIGHT = 1; + private static final int MOVE_ONE_STEP_TO_LEFT = -1; + static final String ALERT_UNMOVABLE_TO_LEFT = "더 이상 왼쪽으로 이동할 수 없습니다."; + private int position; + + private Position(int currentPosition) { + this.position = currentPosition; + } + + public static Position from(int currentPosition) { + return new Position(currentPosition); + } + + public boolean isSameWith(int targetPosition) { + return position == targetPosition; + } + + Position moveToRight() { + return from(this.position + MOVE_ONE_STEP_TO_RIGHT); + } + + Position moveToLeft() { + validationMovableToLeft(); + return from(this.position + MOVE_ONE_STEP_TO_LEFT); + } + + int getPosition() { + return position; + } + + int getLeftPosition() { + validationMovableToLeft(); + return this.position + MOVE_ONE_STEP_TO_LEFT; + } + + private void validationMovableToLeft() { + if (unmovableToLeft()) { + throw new IllegalArgumentException(ALERT_UNMOVABLE_TO_LEFT); + } + } + + private boolean unmovableToLeft() { + return position <= 0; + } +} diff --git a/src/main/java/ladder/domain/Prize.java b/src/main/java/ladder/domain/Prize.java new file mode 100644 index 0000000000..dce124be71 --- /dev/null +++ b/src/main/java/ladder/domain/Prize.java @@ -0,0 +1,38 @@ +package ladder.domain; + +public class Prize { + static final String ALERT_EXCEED_LENGTH_OF_PRIZE_NAME = "상품은 다섯 글자 이내로 작성해주세요."; + static final String ALERT_MISSING_PRIZE = "상품명을 입력해주세요."; + private static final int MAXIMUM_LENGTH_OF_PRIZE_NAME = 5; + + private final String prize; + + private Prize(String inputPrize) { + validationPrize(inputPrize); + this.prize = inputPrize; + } + + public static Prize from(String inputPrize) { + return new Prize(inputPrize); + } + + private void validationPrize(String inputPrize) { + if (inputPrize.isEmpty()) { + throw new IllegalArgumentException(ALERT_MISSING_PRIZE); + } + if (inputPrize.length() > MAXIMUM_LENGTH_OF_PRIZE_NAME) { + throw new IllegalArgumentException(ALERT_EXCEED_LENGTH_OF_PRIZE_NAME); + } + } + + public String getPrize() { + return prize; + } + + @Override + public String toString() { + return "Prize{" + + "prize='" + prize + '\'' + + '}'; + } +} diff --git a/src/main/java/ladder/domain/Prizes.java b/src/main/java/ladder/domain/Prizes.java new file mode 100644 index 0000000000..80fa052f2e --- /dev/null +++ b/src/main/java/ladder/domain/Prizes.java @@ -0,0 +1,37 @@ +package ladder.domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class Prizes { + static final String ALERT_INVALID_NUMBER_OF_PRIZES = "상품의 수는 참여자 수와 같아야 합니다."; + private static final String PRIZE_SEPARATOR = ","; + + private final List prizes; + + private Prizes(List prizes, int numberOfPlayers) { + validationPrizes(prizes, numberOfPlayers); + this.prizes = new ArrayList<>(prizes); + } + + public static Prizes from(String inputPrizes, int numberOfPlayers) { + return new Prizes(Arrays + .stream(inputPrizes.split(PRIZE_SEPARATOR)) + .map(String::trim) + .map(Prize::from) + .collect(Collectors.toList()), numberOfPlayers); + } + + private void validationPrizes(List prizes, int numberOfPlayers) { + if (prizes.size() != numberOfPlayers) { + throw new IllegalArgumentException(ALERT_INVALID_NUMBER_OF_PRIZES); + } + } + + public List getPrizes() { + return Collections.unmodifiableList(prizes); + } +} diff --git a/src/main/java/ladder/domain/BarGeneratorImpl.java b/src/main/java/ladder/domain/RandomBarGenerator.java similarity index 76% rename from src/main/java/ladder/domain/BarGeneratorImpl.java rename to src/main/java/ladder/domain/RandomBarGenerator.java index e08d7dc001..fcf5793da1 100644 --- a/src/main/java/ladder/domain/BarGeneratorImpl.java +++ b/src/main/java/ladder/domain/RandomBarGenerator.java @@ -2,7 +2,7 @@ import java.util.Random; -public class BarGeneratorImpl implements BarGenerator{ +public class RandomBarGenerator implements BarGenerator { private Random random = new Random(); diff --git a/src/main/java/ladder/formatter/DataPrintFormatter.java b/src/main/java/ladder/formatter/DataPrintFormatter.java new file mode 100644 index 0000000000..958ef8950a --- /dev/null +++ b/src/main/java/ladder/formatter/DataPrintFormatter.java @@ -0,0 +1,6 @@ +package ladder.formatter; + +public interface DataPrintFormatter { + + String dataPrintFormat(T data); +} diff --git a/src/main/java/ladder/formatter/NameFormatter.java b/src/main/java/ladder/formatter/NameFormatter.java new file mode 100644 index 0000000000..a735975736 --- /dev/null +++ b/src/main/java/ladder/formatter/NameFormatter.java @@ -0,0 +1,8 @@ +package ladder.formatter; + +public interface NameFormatter { + int SPACE_FOR_NAME = 5; + String BLANK_TO_FILL_THE_NAME_SPACE = " "; //TODO: 질문입니다. 인터페이스에 이런 상수들을 둬도 되는건지 궁금합니다. + + String nameFormat(T object); +} diff --git a/src/main/java/ladder/formatter/PlayerNameFormatter.java b/src/main/java/ladder/formatter/PlayerNameFormatter.java new file mode 100644 index 0000000000..80f6c1feab --- /dev/null +++ b/src/main/java/ladder/formatter/PlayerNameFormatter.java @@ -0,0 +1,20 @@ +package ladder.formatter; + +import ladder.domain.Player; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PlayerNameFormatter implements NameFormatter { + + @Override + public String nameFormat(Player player) { + String name = player.getName(); + int spaceForBlank = SPACE_FOR_NAME - name.length(); + + return IntStream.rangeClosed(0, spaceForBlank) + .mapToObj((integer) -> BLANK_TO_FILL_THE_NAME_SPACE) + .collect(Collectors.joining()) + .concat(name); + } +} diff --git a/src/main/java/ladder/formatter/PlayersPrintFormatter.java b/src/main/java/ladder/formatter/PlayersPrintFormatter.java new file mode 100644 index 0000000000..3fc9a2c2e9 --- /dev/null +++ b/src/main/java/ladder/formatter/PlayersPrintFormatter.java @@ -0,0 +1,18 @@ +package ladder.formatter; + +import ladder.domain.Player; +import ladder.domain.Players; + +import java.util.stream.Collectors; + +public class PlayersPrintFormatter implements DataPrintFormatter { + + private final NameFormatter playerNameFormatter = new PlayerNameFormatter(); + + @Override + public String dataPrintFormat(Players players) { + return players.getPlayers().stream() + .map(player -> String.format(playerNameFormatter.nameFormat(player), player.getName())) + .collect(Collectors.joining()); + } +} diff --git a/src/main/java/ladder/formatter/PrizeNameFormatter.java b/src/main/java/ladder/formatter/PrizeNameFormatter.java new file mode 100644 index 0000000000..6d47681095 --- /dev/null +++ b/src/main/java/ladder/formatter/PrizeNameFormatter.java @@ -0,0 +1,20 @@ +package ladder.formatter; + +import ladder.domain.Prize; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PrizeNameFormatter implements NameFormatter { + + @Override + public String nameFormat(Prize prize) { + String name = prize.getPrize(); + int spaceForBlank = SPACE_FOR_NAME - name.length(); + + return IntStream.rangeClosed(0, spaceForBlank) + .mapToObj((integer) -> BLANK_TO_FILL_THE_NAME_SPACE) + .collect(Collectors.joining()) + .concat(name); + } +} diff --git a/src/main/java/ladder/formatter/PrizesPrintFormatter.java b/src/main/java/ladder/formatter/PrizesPrintFormatter.java new file mode 100644 index 0000000000..49fe3fdef7 --- /dev/null +++ b/src/main/java/ladder/formatter/PrizesPrintFormatter.java @@ -0,0 +1,18 @@ +package ladder.formatter; + +import ladder.domain.Prize; +import ladder.domain.Prizes; + +import java.util.stream.Collectors; + +public class PrizesPrintFormatter implements DataPrintFormatter { + + private final NameFormatter prizeNameFormatter = new PrizeNameFormatter(); + + @Override + public String dataPrintFormat(Prizes prizes) { + return prizes.getPrizes().stream() + .map(prize -> String.format(prizeNameFormatter.nameFormat(prize), prize.getPrize())) + .collect(Collectors.joining()); + } +} diff --git a/src/main/java/ladder/view/InputView.java b/src/main/java/ladder/view/InputView.java index 9a9c1849dc..75b536f103 100644 --- a/src/main/java/ladder/view/InputView.java +++ b/src/main/java/ladder/view/InputView.java @@ -5,6 +5,8 @@ public class InputView { private static final String MESSAGE_FOR_INPUT_PLAYER_NAMES = "참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"; private static final String MESSAGE_FOR_MAXIMUM_LADDER_HEIGHT = "최대 사다리 높이는 몇 개인가요?"; + private static final String MESSAGE_FOR_PRIZES = "실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)"; + private static final String MESSAGE_FOR_WANTED_RESULT = "결과를 보고 싶은 사람은?"; private static Scanner scanner = new Scanner(System.in); @@ -13,10 +15,24 @@ public static String askPlayers() { return scanner.nextLine(); } + public static String askPrizes() { + printEmptyLine(); + System.out.println(MESSAGE_FOR_PRIZES); + return scanner.nextLine(); + } + public static int askHeight() { printEmptyLine(); System.out.println(MESSAGE_FOR_MAXIMUM_LADDER_HEIGHT); - return scanner.nextInt(); + int height = scanner.nextInt(); + scanner.nextLine(); + return height; + } + + public static String askWhichResultWant() { + printEmptyLine(); + System.out.println(MESSAGE_FOR_WANTED_RESULT); + return scanner.nextLine(); } static void printEmptyLine() { diff --git a/src/main/java/ladder/view/OutputView.java b/src/main/java/ladder/view/OutputView.java index c1a860c706..73b4ae4c01 100644 --- a/src/main/java/ladder/view/OutputView.java +++ b/src/main/java/ladder/view/OutputView.java @@ -1,27 +1,23 @@ package ladder.view; -import ladder.domain.Ladder; -import ladder.domain.Line; -import ladder.domain.Player; -import ladder.domain.Players; - -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static ladder.view.InputView.printEmptyLine; +import ladder.domain.*; +import ladder.formatter.*; public class OutputView { - private static final String MESSAGE_RESULT_TITLE = "실행결과"; + private static final String MESSAGE_RESULT_TITLE = "사다리 결과"; private static final String EMPTY_SPACE = " "; private static final String BAR = "-----"; private static final String COLUMN = "|"; - private static final String BLANK_TO_FILL_THE_NAME_SPACE = " "; - private static final int SPACE_FOR_NAME = 5; + private static final String MESSAGE_FOR_RESULT = "실행 결과"; - public static void printResult(Players players, Ladder ladder) { + private static DataPrintFormatter playersPrintFormatter = new PlayersPrintFormatter(); + private static DataPrintFormatter prizesPrintFormatter = new PrizesPrintFormatter(); + + public static void drawLadder(Players players, Ladder ladder, Prizes prizes) { printResultTitle(); printPlayers(players); printLadder(ladder); + printPrizes(prizes); } private static void printResultTitle() { @@ -31,20 +27,11 @@ private static void printResultTitle() { } private static void printPlayers(Players players) { - players.getPlayers().stream() - .map(OutputView::adjustNameLength) - .forEach(System.out::print); - printEmptyLine(); + System.out.println(playersPrintFormatter.dataPrintFormat(players)); } - private static String adjustNameLength(Player player) { - String name = player.getName(); - int spaceForBlank = SPACE_FOR_NAME - name.length(); - - return IntStream.rangeClosed(0, spaceForBlank) - .mapToObj((integer) -> BLANK_TO_FILL_THE_NAME_SPACE) - .collect(Collectors.joining()) - .concat(name); + private static void printPrizes(Prizes prizes) { + System.out.println(prizesPrintFormatter.dataPrintFormat(prizes)); } private static void printLadder(Ladder ladder) { @@ -59,12 +46,31 @@ private static void printLine(Line line) { printEmptyLine(); } - private static String printBars(Boolean bar) { + private static String printBars(Bar bar) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(COLUMN); - if (bar) { + if (bar.isExist()) { return stringBuilder.append(BAR).toString(); } return stringBuilder.append(EMPTY_SPACE).toString(); } + + public static void printSingleResult(String resultForWantedPlayer) { + printEmptyLine(); + System.out.println(MESSAGE_FOR_RESULT); + System.out.println(resultForWantedPlayer); + } + + public static void printAllResult(GameResult gameResult) { + printEmptyLine(); + System.out.println(MESSAGE_FOR_RESULT); + gameResult.getResultMap() + .entrySet() + .forEach(result -> System.out.println( + result.getKey().getName() + " : " + result.getValue().getPrize())); + } + + private static void printEmptyLine() { + System.out.println(); + } } diff --git a/src/test/java/ladder/domain/BarTest.java b/src/test/java/ladder/domain/BarTest.java new file mode 100644 index 0000000000..15e57c2008 --- /dev/null +++ b/src/test/java/ladder/domain/BarTest.java @@ -0,0 +1,15 @@ +package ladder.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BarTest { + @Test + void 사다리_기둥_사이를_잇는_Bar를_생성한다() { + boolean doesBarExist = true; + Bar bar = Bar.from(doesBarExist); + + assertThat(bar.isExist()).isTrue(); + } +} diff --git a/src/test/java/ladder/domain/LineTest.java b/src/test/java/ladder/domain/LineTest.java index f81d1c83c1..029f5092cf 100644 --- a/src/test/java/ladder/domain/LineTest.java +++ b/src/test/java/ladder/domain/LineTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.Test; +import java.util.Arrays; + import static org.assertj.core.api.Assertions.assertThat; public class LineTest { @@ -13,4 +15,49 @@ public class LineTest { assertThat(line.getBars().size()).isEqualTo(numberOfPlayers); } + + @Test + void 플레이어의_위치와_Bar의_위치가_같으면_플레이어의_위치를_1만큼_증가시킨다() { + Line line = new Line(Arrays.asList(Bar.from(false), Bar.from(true), Bar.from(false))); + + int currentPosition = 1; + Position playerPosition = Position.from(currentPosition); + + assertThat(line.travel(playerPosition).getPosition()) + .isEqualTo(currentPosition + 1); + } + + @Test + void 플레이어의_위치보다_Bar의_위치가_1만큼_작으면_플레이어의_위치를_1만큼_감소시킨다() { + Line line = new Line(Arrays.asList(Bar.from(false), Bar.from(true), Bar.from(false))); + + int currentPosition = 2; + Position playerPosition = Position.from(currentPosition); + + assertThat(line.travel(playerPosition).getPosition()) + .isEqualTo(currentPosition - 1); + } + + @Test + void 플레이어의_위치보다_Bar의_위치가_1만큼_크면_플레이어의_위치는_바뀌지_않는다() { + Line line = new Line(Arrays.asList(Bar.from(false), Bar.from(true), Bar.from(false))); + + int currentPosition = 0; + Position playerPosition = Position.from(currentPosition); + + assertThat(line.travel(playerPosition).getPosition()) + .isEqualTo(currentPosition); + } + + @Test + void 플레이어의_위치와_Bar의_위치가_2이상_차이나면_플레이어의_위치는_바뀌지_않는다() { + Line line = new Line(Arrays.asList(Bar.from(true), Bar.from(false), Bar.from(false))); + + int currentPosition = 2; + Position playerPosition = Position.from(currentPosition); + + assertThat(line.travel(playerPosition).getPosition()) + .isEqualTo(currentPosition); + } + } diff --git a/src/test/java/ladder/domain/PositionTest.java b/src/test/java/ladder/domain/PositionTest.java new file mode 100644 index 0000000000..868e7b4ef1 --- /dev/null +++ b/src/test/java/ladder/domain/PositionTest.java @@ -0,0 +1,42 @@ +package ladder.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class PositionTest { + + private final int currentPosition = 1; + private Position position = Position.from(currentPosition); + + @Test + void 플레이어의_현재_위치를_생성한다() { + assertThat(position.isSameWith(1)).isTrue(); + } + + @Test + void 위치를_오른쪽으로_1만큼_이동한다() { + assertThat(position.moveToRight().getPosition()).isEqualTo(currentPosition + 1); + } + + @Test + void 위치를_왼쪽으로_1만큼_이동한다() { + assertThat(position.moveToLeft().getPosition()).isEqualTo(currentPosition - 1); + } + + @Test + void 현재_위치보다_1만큼_작은_위치를_반환한다() { + assertThat(position.getLeftPosition()).isEqualTo(currentPosition - 1); + } + + @Test + void 현재_위치가_0보다_크지_않으면_왼쪽으로_이동할_경우_예외가_발생한다() { + int position = 0; + Position testPosition = Position.from(position); + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(testPosition::moveToLeft) + .withMessage(Position.ALERT_UNMOVABLE_TO_LEFT); + } +} diff --git a/src/test/java/ladder/domain/PrizeTest.java b/src/test/java/ladder/domain/PrizeTest.java new file mode 100644 index 0000000000..f6eebd3492 --- /dev/null +++ b/src/test/java/ladder/domain/PrizeTest.java @@ -0,0 +1,38 @@ +package ladder.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class PrizeTest { + @Test + void 각_사다리의_상품을_입력받아_생성한다() { + String testPrize = "꽝"; + Prize prize = Prize.from(testPrize); + + assertThat(prize.getPrize()).isEqualTo(testPrize); + } + + @Test + void 상품이름이_공백이면_예외가_발생한다() { + String emptyPrize = ""; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + Prize.from(emptyPrize); + }).withMessage(Prize.ALERT_MISSING_PRIZE); + } + + @Test + void 상품이름이_다섯글자_이상이면_예외가_발생한다() { + String lengthExceedPrizeName = "길이 제한을 초과하는 상품이름"; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + Prize.from(lengthExceedPrizeName); + }).withMessage(Prize.ALERT_EXCEED_LENGTH_OF_PRIZE_NAME); + } + + +} diff --git a/src/test/java/ladder/domain/PrizesTest.java b/src/test/java/ladder/domain/PrizesTest.java new file mode 100644 index 0000000000..6635ab5f59 --- /dev/null +++ b/src/test/java/ladder/domain/PrizesTest.java @@ -0,0 +1,28 @@ +package ladder.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class PrizesTest { + @Test + void 입력된_각_사다리의_결과들로_Results를_생성한다() { + int numberOfPlayers = 4; + String inputPrizes = "꽝,5000,꽝,5000"; + Prizes prizes = Prizes.from(inputPrizes, numberOfPlayers); + + assertThat(prizes.getPrizes().size()).isEqualTo(numberOfPlayers); + } + + @Test + void 플레이어_수와_결과의_수가_같지_않으면_예외가_발생한다() { + int numberOfPlayers = 4; + String inputResults = "꽝,꽝,꽝,꽝,당첨"; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + Prizes.from(inputResults, numberOfPlayers); + }).withMessage(Prizes.ALERT_INVALID_NUMBER_OF_PRIZES); + } +}