Skip to content

[사다리 1-4단계] 천희정 미션 제출합니다. #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: heejung72
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Application {
public static void main(String[] args) {
LadderApplication app = new LadderApplication();
app.run();
}
}
28 changes: 28 additions & 0 deletions src/main/java/LadderApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import controller.LadderController;
import view.InputView;
import view.OutputView;
import service.LadderService;

public class LadderApplication {
public void run() {
InputView inputView = new InputView();
OutputView outputView = new OutputView();
LadderService ladderService = new LadderService();
LadderController controller = new LadderController(inputView, outputView, ladderService);

controller.start();
processQueries(controller);

// 종료
System.exit(0);
}

private void processQueries(LadderController controller) {
while (shouldContinue(controller)) {
}
}

private boolean shouldContinue(LadderController controller) {
return controller.processQuery();
}
}
102 changes: 102 additions & 0 deletions src/main/java/controller/LadderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package controller;

import domain.Height;
import domain.Result;
import domain.LadderGame;
import domain.Ladder;
import domain.Line;
import service.LadderService;
import domain.Name;
import domain.Names;
import domain.Results;
import view.InputView;
import view.OutputView;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class LadderController {
private final InputView inputView;
private final OutputView outputView;
private final LadderService ladderService;
private LadderGame ladderGame;

public LadderController(InputView inputView, OutputView outputView, LadderService ladderService) {
this.inputView = inputView;
this.outputView = outputView;
this.ladderService = ladderService;
}

public void start() {
try {
String namesInput = inputView.readNames();
String resultsInput = inputView.readResults();
int heightInput = inputView.readHeight();

Names names = ladderService.createNames(namesInput);
Results results = ladderService.createResults(resultsInput);
Height height = ladderService.createHeight(heightInput);

this.ladderGame = ladderService.createLadderGame(names, results, height);

// domain 객체 -> OutputView
outputView.printLadder(
convertNamesToStrings(names),
convertLadderToLists(ladderGame.getLadder()),
convertResultsToStrings(results)
);
} catch (IllegalArgumentException e) {
outputView.printError(e.getMessage());
start();
}
}

public boolean processQuery() {
try {
String target = inputView.readNameForResult();

if (ladderService.isAllQuery(target)) {
Map<Name, Result> allResults = ladderGame.playAll();
Map<String, String> convertedResults = convertAllResultsToMap(allResults);
outputView.printAllResults(convertedResults);
return false;
}

Name targetName = ladderService.createName(target);
Result result = ladderGame.play(targetName);

outputView.printResult(result.getValue());
return true;

} catch (IllegalArgumentException e) {
outputView.printError(e.getMessage());
return true;
}
}

private List<String> convertNamesToStrings(Names names) {
return names.getValues().stream()
.map(Name::getValue)
.collect(Collectors.toList());
}

private List<List<Boolean>> convertLadderToLists(Ladder ladder) {
return ladder.getLines().stream()
.map(Line::getSteps)
.collect(Collectors.toList());
}

private List<String> convertResultsToStrings(Results results) {
return results.getValues().stream()
.map(Result::getValue)
.collect(Collectors.toList());
}

private Map<String, String> convertAllResultsToMap(Map<Name, Result> gameResults) {
return gameResults.entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().getValue(),
entry -> entry.getValue().getValue()
));
}
}
16 changes: 16 additions & 0 deletions src/main/java/domain/Height.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package domain;

public class Height {
private final int value;

public Height(int value) {
if (value <= 0) {
throw new IllegalArgumentException("Height는 0보다 커야한다");
}
this.value = value;
}

public int getValue() {
return value;
}
}
27 changes: 27 additions & 0 deletions src/main/java/domain/Ladder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package domain;

import java.util.List;

public class Ladder {
private final List<Line> lines;

public Ladder(List<Line> lines) {
if (lines == null || lines.isEmpty()) {
throw new IllegalArgumentException("사다리는 최소 한 줄 이상이어야 합니다.");
}

this.lines = List.copyOf(lines);
}

public int traverse(int startPosition) {
int position = startPosition;
for (Line line : lines) {
position = line.move(position);
}
return position;
}

public List<Line> getLines() {
return lines;
}
}
34 changes: 34 additions & 0 deletions src/main/java/domain/LadderGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package domain;

import java.util.Map;
import java.util.stream.Collectors;

public class LadderGame {
private final Names names;
private final Results results;
private final Ladder ladder;

public LadderGame(Names names, Results results, Ladder ladder) {
this.names = names;
this.results = results;
this.ladder = ladder;
}

public Result play(Name name) {
int index = names.indexOf(name);
if (index == -1) {
throw new IllegalArgumentException("존재하지 않는 참가자입니다: " + name.getValue());
}
int resultIndex = ladder.traverse(index);
return results.get(resultIndex);
}

public Map<Name, Result> playAll() {
return names.getValues().stream()
.collect(Collectors.toMap(n -> n, this::play));
}

public Ladder getLadder() {
return ladder;
}
}
14 changes: 14 additions & 0 deletions src/main/java/domain/LadderGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package domain;

import java.util.ArrayList;
import java.util.List;

public class LadderGenerator {
public static Ladder generate(int countOfPlayers, Height height) {
List<Line> lines = new ArrayList<>();
for (int i = 0; i < height.getValue(); i++) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기를 보니까 결국 height가 굳이 클래스일 필요가 없는 것이 증명되긴 했군요

lines.add(Line.generate(countOfPlayers));
}
return new Ladder(lines);
}
}
55 changes: 55 additions & 0 deletions src/main/java/domain/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package domain;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Line {
private final List<Boolean> steps;
private static final Random RANDOM = new Random();

public Line(List<Boolean> steps) {
this.steps = List.copyOf(steps);
}

public static Line generate(int width) {
List<Boolean> steps = new ArrayList<>();
for (int index = 0; index < width - 1; index++) {
steps.add(nextStep(index, steps));
}
return new Line(steps);
}

private static boolean nextStep(int index, List<Boolean> steps) {
if (hasLeftStep(index, steps)) {
return false;
}
return RANDOM.nextBoolean();
}

private static boolean hasLeftStep(int index, List<Boolean> steps) {
return index > 0 && steps.get(index - 1);
}

public int move(int position) {
if (canMoveLeft(position)) {
return position - 1;
}
if (canMoveRight(position)) {
return position + 1;
}
return position;
}

private boolean canMoveLeft(int position) {
return position > 0 && steps.get(position - 1);
}

private boolean canMoveRight(int position) {
return position < steps.size() && steps.get(position);
}

public List<Boolean> getSteps() {
return steps;
}
}
35 changes: 35 additions & 0 deletions src/main/java/domain/Name.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package domain;

public class Name {
private final String value;

public Name(String value) {
validate(value);
this.value = value;
}

private void validate(String value) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException("이름은 비어있을 수 없습니다.");
}
if (value.length() > 5) {
throw new IllegalArgumentException("이름은 5글자 이하여야 합니다.");
}
if (value.equals("all")) {
throw new IllegalArgumentException("\"all\"은 참가자 이름으로 사용할 수 없습니다.");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

escape 👍

}
}

public String getValue() {
return value;
}

public boolean equals(Object obj) {
if (!(obj instanceof Name)) return false;
return value.equals(((Name) obj).value);
}

public int hashCode() {
return value.hashCode();
}
}
50 changes: 50 additions & 0 deletions src/main/java/domain/Names.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package domain;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Names {
private final List<Name> values;

private Names(List<Name> values) {
validateDuplicates(values);
this.values = values;
}

public static Names from(String input) {
if (input == null || input.trim().isEmpty()) {
throw new IllegalArgumentException("참가자 이름을 입력해주세요.");
}

List<Name> names = Arrays.stream(input.split(","))
.map(String::trim)
.map(Name::new)
.collect(Collectors.toList());

if (names.isEmpty()) {
throw new IllegalArgumentException("유효한 참가자 이름을 입력해주세요.");
}

return new Names(names);
}

private void validateDuplicates(List<Name> names) {
long uniqueCount = names.stream().distinct().count();
if (uniqueCount != names.size()) {
throw new IllegalArgumentException("중복된 참가자 이름이 있습니다.");
}
}

public int size() {
return values.size();
}

public List<Name> getValues() {
return values;
}

public int indexOf(Name name) {
return values.indexOf(name);
}
}
22 changes: 22 additions & 0 deletions src/main/java/domain/Result.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package domain;

public class Result {
private final String value;

public Result(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public boolean equals(Object obj) {
if (!(obj instanceof Result)) return false;
return value.equals(((Result) obj).value);
}

public int hashCode() {
return value.hashCode();
}
}
Loading