diff --git a/src/main/java/nextstep/ladder/controller/LadderController.java b/src/main/java/nextstep/ladder/controller/LadderController.java index 3954b27f65..2485bcd39d 100644 --- a/src/main/java/nextstep/ladder/controller/LadderController.java +++ b/src/main/java/nextstep/ladder/controller/LadderController.java @@ -1,19 +1,27 @@ package nextstep.ladder.controller; -import nextstep.ladder.domain.Height; -import nextstep.ladder.domain.LadderGame; -import nextstep.ladder.domain.Names; +import nextstep.ladder.domain.*; import nextstep.ladder.domain.strategy.RandomLadderPoint; import nextstep.ladder.view.InputView; import nextstep.ladder.view.OutputView; +import java.util.List; + public class LadderController { public static void main(String[] args) { Names names = InputView.inputNames(); + List inputLadderResults = InputView.inputLadderResults(); Height height = InputView.inputHeight(); + Lines lines = new Lines(); + lines.initialize(names.size(), height, new RandomLadderPoint()); + + OutputView.printNames(names); + OutputView.printLadders(lines); + OutputView.printInputResults(inputLadderResults); - LadderGame ladderGame = new LadderGame(names, new RandomLadderPoint(), height); + LadderGame ladderGame = new LadderGame(names, lines, inputLadderResults); + LadderResults ladderResults = ladderGame.play(); - OutputView.printNamesAndLadders(ladderGame); + OutputView.printResultByName(InputView.inputNameForResult(), ladderResults); } } diff --git a/src/main/java/nextstep/ladder/domain/LadderGame.java b/src/main/java/nextstep/ladder/domain/LadderGame.java index d3a6bf48e1..03cdbc43f1 100644 --- a/src/main/java/nextstep/ladder/domain/LadderGame.java +++ b/src/main/java/nextstep/ladder/domain/LadderGame.java @@ -1,29 +1,25 @@ package nextstep.ladder.domain; -import nextstep.ladder.domain.strategy.GenerateLadderPoint; - import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; public class LadderGame { private Names names; private Lines lines; + private final List results; - public LadderGame(Names names, GenerateLadderPoint generateLadderPoint, Height height) { + public LadderGame(Names names, Lines lines, List results) { this.names = names; - initialize(height, generateLadderPoint); - } - - private void initialize(Height height, GenerateLadderPoint generateLadderPoint) { - this.lines = createLines(height, generateLadderPoint); + this.lines = lines; + validateResults(results); + this.results = results; } - private Lines createLines(Height height, GenerateLadderPoint generateLadderPoint) { - List lines = IntStream.range(0, height.getPoint()) - .mapToObj(i -> new Line(names.size(), generateLadderPoint)) - .collect(Collectors.toList()); - return new Lines(lines); + public LadderResults play() { + Map gameResults = generateGameResults(); + return new LadderResults(gameResults); } public Names getNames() { @@ -33,4 +29,20 @@ public Names getNames() { public Lines getLines() { return lines; } + + private Map generateGameResults() { + return IntStream.range(0, names.size()) + .boxed() + .collect(Collectors.toMap(names.getNames()::get, this::calculateResult)); + } + + private LadderResult calculateResult(int index) { + return results.get(lines.move(index)); + } + + private void validateResults(List results) { + if (results.size() != names.size()) { + throw new IllegalArgumentException("참가자 수와 결과 수가 일치하지 않습니다."); + } + } } diff --git a/src/main/java/nextstep/ladder/domain/LadderResult.java b/src/main/java/nextstep/ladder/domain/LadderResult.java new file mode 100644 index 0000000000..b5e99e4f5d --- /dev/null +++ b/src/main/java/nextstep/ladder/domain/LadderResult.java @@ -0,0 +1,22 @@ +package nextstep.ladder.domain; + +public class LadderResult { + private final String result; + + public LadderResult(String result) { + validateResult(result); + + this.result = result; + } + + public String getResult() { + return result; + } + + private void validateResult(String result) { + if (result == null || result.isEmpty()) { + throw new IllegalArgumentException("결과가 입력되지 않았습니다."); + } + } + +} \ No newline at end of file diff --git a/src/main/java/nextstep/ladder/domain/LadderResults.java b/src/main/java/nextstep/ladder/domain/LadderResults.java new file mode 100644 index 0000000000..a1ecec622e --- /dev/null +++ b/src/main/java/nextstep/ladder/domain/LadderResults.java @@ -0,0 +1,21 @@ +package nextstep.ladder.domain; + +import java.util.Map; +import java.util.Optional; + +public class LadderResults { + private final Map ladderResults; + + public LadderResults(Map ladderResults) { + this.ladderResults = ladderResults; + } + + public LadderResult getResultForParticipant(Name name) { + return Optional.ofNullable(ladderResults.get(name)) + .orElseThrow(() -> new IllegalArgumentException(name.getName() + " 참가자가 존재하지 않습니다.")); + } + + public Map getAllResults() { + return ladderResults; + } +} diff --git a/src/main/java/nextstep/ladder/domain/Line.java b/src/main/java/nextstep/ladder/domain/Line.java index 36ddb04768..6b1e4e1275 100644 --- a/src/main/java/nextstep/ladder/domain/Line.java +++ b/src/main/java/nextstep/ladder/domain/Line.java @@ -15,7 +15,25 @@ public Line(int namesSize, GenerateLadderPoint generateLadderPoint) { } } + public int move(int position) { + if (isMoveRight(position)) { + return position + 1; + } + if (isMoveLeft(position)) { + return position - 1; + } + return position; + } + public List getPoints() { return points; } + + private boolean isMoveRight(int position) { + return position < points.size() && points.get(position); + } + + private boolean isMoveLeft(int position) { + return position > 0 && points.get(position - 1); + } } diff --git a/src/main/java/nextstep/ladder/domain/Lines.java b/src/main/java/nextstep/ladder/domain/Lines.java index 642cedcd7f..307e37bead 100644 --- a/src/main/java/nextstep/ladder/domain/Lines.java +++ b/src/main/java/nextstep/ladder/domain/Lines.java @@ -1,12 +1,34 @@ package nextstep.ladder.domain; +import nextstep.ladder.domain.strategy.GenerateLadderPoint; +import nextstep.ladder.domain.strategy.RandomLadderPoint; + +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class Lines { private List lines; - public Lines(List lines) { - this.lines = lines; + public Lines() { + } + + public void initialize(int size, Height height, GenerateLadderPoint generateLadderPoint) { + this.lines = createLines(size, height, generateLadderPoint); + } + + public int move(int position) { + for (Line line : lines) { + position = line.move(position); + } + return position; + } + + private List createLines(int size, Height height, GenerateLadderPoint generateLadderPoint) { + return IntStream.range(0, height.getPoint()) + .mapToObj(i -> new Line(size, generateLadderPoint)) + .collect(Collectors.toList()); } public List getLines() { diff --git a/src/main/java/nextstep/ladder/view/InputView.java b/src/main/java/nextstep/ladder/view/InputView.java index 850b981f1d..0d934e5667 100644 --- a/src/main/java/nextstep/ladder/view/InputView.java +++ b/src/main/java/nextstep/ladder/view/InputView.java @@ -1,6 +1,7 @@ package nextstep.ladder.view; import nextstep.ladder.domain.Height; +import nextstep.ladder.domain.LadderResult; import nextstep.ladder.domain.Name; import nextstep.ladder.domain.Names; @@ -27,10 +28,30 @@ public static Height inputHeight() { return new Height(SCANNER.nextInt()); } + public static List inputLadderResults() { + System.out.println("실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)"); + + return parseLadderResults(SCANNER.nextLine()); + } + + public static Name inputNameForResult() { + System.out.println("결과를 보고 싶은 사람은?"); + String inputNames = SCANNER.nextLine(); + + return new Name(inputNames); + } + private static Names splitNames(String inputNames) { List names = Arrays.stream(inputNames.split(COMMA)) .map(Name::new) .collect(Collectors.toList()); return new Names(names); } + + private static List parseLadderResults(String inputLadderResults) { + return Arrays.stream(inputLadderResults.split(COMMA)) + .map(String::trim) + .map(LadderResult::new) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/nextstep/ladder/view/OutputView.java b/src/main/java/nextstep/ladder/view/OutputView.java index 08be752ac3..5e918d90c0 100644 --- a/src/main/java/nextstep/ladder/view/OutputView.java +++ b/src/main/java/nextstep/ladder/view/OutputView.java @@ -1,10 +1,8 @@ package nextstep.ladder.view; -import nextstep.ladder.domain.LadderGame; -import nextstep.ladder.domain.Line; -import nextstep.ladder.domain.Lines; -import nextstep.ladder.domain.Names; +import nextstep.ladder.domain.*; +import java.util.List; import java.util.stream.Collectors; public class OutputView { @@ -15,34 +13,58 @@ public class OutputView { private static final String LADDER_SPACE = " "; private static final String NEWLINE = System.lineSeparator(); - public static void printNamesAndLadders(LadderGame ladderGame) { - System.out.println("실행 결과" + NEWLINE); + private static final String PARTICIPANT_NAME_ALL = "all"; + private static final int MAX_NAME_LENGTH = 5; - String output = formatParticipantNames(ladderGame.getNames()) + - formatLines(ladderGame.getNames().getFirstNameLength(), ladderGame.getLines()); + private OutputView() { + } + + public static void printInputResults(List inputLadderResults) { + System.out.println(formatLadderResults(inputLadderResults) + NEWLINE); + } + + public static void printResultByName(Name inputName, LadderResults ladderResults) { + printHeader(); + if (inputName.getName().equals(PARTICIPANT_NAME_ALL)) { + printAllParticipantResults(ladderResults); + } else { + printSingleParticipantResult(inputName, ladderResults); + } + } + + private static void printHeader() { + System.out.println("실행 결과"); + } - System.out.println(output); + private static void printAllParticipantResults(LadderResults ladderResults) { + ladderResults.getAllResults().forEach((participant, result) -> + System.out.println(participant.getName() + " : " + result.getResult())); } - private static String formatParticipantNames(Names names) { - int lastIndex = names.getNames().size() - 1; + private static void printSingleParticipantResult(Name name, LadderResults ladderResults) { + System.out.println(ladderResults.getResultForParticipant(name).getResult()); + } + public static void printNames(Names names) { String strNames = names.getNames().stream() - .limit(lastIndex) .map(name -> String.format(NAME_FORMAT, name.getName())) .collect(Collectors.joining()); - return strNames + String.format(NAME_FORMAT, names.getNames().get(lastIndex).getName()) + NEWLINE; + System.out.println(strNames); + } + + public static void printLadders(Lines lines) { + System.out.println(formatLines(lines)); } - private static String formatLines(int firstNameLength, Lines lines) { + private static String formatLines(Lines lines) { return lines.getLines().stream() - .map(line -> formatSingleLine(firstNameLength, line)) - .collect(Collectors.joining(NEWLINE)) + NEWLINE; + .map(OutputView::formatSingleLine) + .collect(Collectors.joining(NEWLINE)); } - private static String formatSingleLine(int firstNameLength, Line line) { - StringBuilder ladder = new StringBuilder(LADDER_SPACE.repeat(firstNameLength) + LADDER_VERTICAL_LINE); + private static String formatSingleLine(Line line) { + StringBuilder ladder = new StringBuilder(LADDER_SPACE.repeat(MAX_NAME_LENGTH) + LADDER_VERTICAL_LINE); line.getPoints().stream() .map(point -> point ? LADDER_HORIZONTAL_LINE : LADDER_EMPTY_SPACE) @@ -50,4 +72,9 @@ private static String formatSingleLine(int firstNameLength, Line line) { return ladder.toString(); } + private static String formatLadderResults(List inputLadderResults) { + return inputLadderResults.stream() + .map(ladderResult -> String.format(NAME_FORMAT, ladderResult.getResult())) + .collect(Collectors.joining()); + } } diff --git a/src/test/java/nextstep/ladder/domain/LadderGameTest.java b/src/test/java/nextstep/ladder/domain/LadderGameTest.java new file mode 100644 index 0000000000..20128d86f3 --- /dev/null +++ b/src/test/java/nextstep/ladder/domain/LadderGameTest.java @@ -0,0 +1,25 @@ +package nextstep.ladder.domain; + +import nextstep.ladder.domain.strategy.RandomLadderPoint; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LadderGameTest { + + @Test + @DisplayName("참가자 수와 결과 수가 일치하지 않으면 예외가 발생한다") + void validateLadderResults_exception() { + Names names = new Names(List.of(new Name("a"))); + List inputLadderResults = List.of(new LadderResult("꽝"), new LadderResult("1000")); + Lines lines = new Lines(); + lines.initialize(1, new Height(1), new RandomLadderPoint()); + Assertions.assertThatIllegalArgumentException().isThrownBy(() -> { + new LadderGame(names, lines, inputLadderResults); + }); + } +} \ No newline at end of file diff --git a/src/test/java/nextstep/ladder/domain/LadderResultTest.java b/src/test/java/nextstep/ladder/domain/LadderResultTest.java new file mode 100644 index 0000000000..9dcfe7fa56 --- /dev/null +++ b/src/test/java/nextstep/ladder/domain/LadderResultTest.java @@ -0,0 +1,16 @@ +package nextstep.ladder.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LadderResultTest { + @Test + @DisplayName("결과가 입력되지않으면 예외가 발생한다") + void create_exception() { + Assertions.assertThatIllegalArgumentException().isThrownBy(() -> { + new LadderResult(""); + new LadderResult(null); + }); + } +} \ No newline at end of file