diff --git a/README.md b/README.md index d911493a8f..fbf72b82f0 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,15 @@ - [x] 요구사항 1 - Optional을 활용해 조건에 따른 반환 - [x] 요구사항 2 - Optional에서 값을 반환 - [x] 요구사항 3 - Optional에서 exception 처리 + - [x] 요구사항 3 - Optional에서 exception 처리 +- 리뷰 + - [x] 전체 테스트 코드 통과 + +### 사다리(생성) +- [x] 라인 길이를 전달받아 사다리 라인을 생성한다. +- [x] 각 사다리 라인은 이웃한 곳과 이어져있을 수 있다. +- [x] 각 사다리 라인은 겹치지 않게 이어져 있어야 한다. +- ~~[x] 라인의 각 포인트는 왼쪽/오른쪽 연결 유무를 갖는다.~~ +- [x] 라인의 각 포인트는 오른쪽 연결 유무만 갖는다. +- [x] 사다리 높이와 라인 길이를 전달받아 사다리를 생성한다. +- [x] 사람 이름은 최대 5글자까지만 가능하다. diff --git a/src/main/java/ladder/Main.java b/src/main/java/ladder/Main.java new file mode 100644 index 0000000000..1b785cee33 --- /dev/null +++ b/src/main/java/ladder/Main.java @@ -0,0 +1,21 @@ +package ladder; + +import ladder.domain.Ladder; +import ladder.domain.People; +import ladder.view.InputView; +import ladder.view.ResultView; + +import java.util.Random; + +public class Main { + private static void makeLadder() { + People people = InputView.inputPeople(); + int ladderHeight = InputView.inputLadderHeight(); + Ladder ladder = new Ladder(ladderHeight, people, (idx, preConnected) -> !preConnected && new Random().nextBoolean()); + ResultView.printLadder(people, ladder); + } + + public static void main(String[] args) { + makeLadder(); + } +} diff --git a/src/main/java/ladder/domain/ConnectStrategy.java b/src/main/java/ladder/domain/ConnectStrategy.java new file mode 100644 index 0000000000..2baea24625 --- /dev/null +++ b/src/main/java/ladder/domain/ConnectStrategy.java @@ -0,0 +1,5 @@ +package ladder.domain; + +public interface ConnectStrategy { + boolean connect(int idx, boolean preConnected); +} diff --git a/src/main/java/ladder/domain/Ladder.java b/src/main/java/ladder/domain/Ladder.java new file mode 100644 index 0000000000..3be2ae133f --- /dev/null +++ b/src/main/java/ladder/domain/Ladder.java @@ -0,0 +1,19 @@ +package ladder.domain; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class Ladder { + private final List lines; + + public Ladder(int height, People people, ConnectStrategy connectStrategy) { + this.lines = IntStream.range(0, height) + .mapToObj(i -> new Line(people.size(), connectStrategy)) + .collect(Collectors.toList()); + } + + public List lines() { + return lines; + } +} diff --git a/src/main/java/ladder/domain/Line.java b/src/main/java/ladder/domain/Line.java new file mode 100644 index 0000000000..354c2ffd01 --- /dev/null +++ b/src/main/java/ladder/domain/Line.java @@ -0,0 +1,32 @@ +package ladder.domain; + +import java.util.List; +import java.util.Objects; + +public class Line { + private final Points points; + + public Line(List points) { + this.points = new Points(points); + } + + public Line(int size, ConnectStrategy connectStrategy) { + this.points = new Points(size, connectStrategy); + } + + public Points points() { + return points; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Line line = (Line) o; + return Objects.equals(points, line.points); + } + + @Override + public int hashCode() { + return Objects.hashCode(points); + } +} diff --git a/src/main/java/ladder/domain/People.java b/src/main/java/ladder/domain/People.java new file mode 100644 index 0000000000..6ba508cb08 --- /dev/null +++ b/src/main/java/ladder/domain/People.java @@ -0,0 +1,25 @@ +package ladder.domain; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class People { + private final static String DELIMITER = ","; + + private final List people; + + public People(String input) { + this.people = Arrays.stream(input.split(DELIMITER)) + .map(Person::new) + .collect(Collectors.toList()); + } + + public int size() { + return people.size(); + } + + public List values() { + return people; + } +} diff --git a/src/main/java/ladder/domain/Person.java b/src/main/java/ladder/domain/Person.java new file mode 100644 index 0000000000..55002fc6fd --- /dev/null +++ b/src/main/java/ladder/domain/Person.java @@ -0,0 +1,18 @@ +package ladder.domain; + +public class Person { + private static final int NAME_MAX_LENGTH = 5; + + private final String name; + + public Person(String name) { + if (name.length() > 5) { + throw new IllegalArgumentException("이름 길이는 최대 " + NAME_MAX_LENGTH + "자입니다."); + } + this.name = name; + } + + public String name() { + return name; + } +} diff --git a/src/main/java/ladder/domain/Point.java b/src/main/java/ladder/domain/Point.java new file mode 100644 index 0000000000..21e0f78161 --- /dev/null +++ b/src/main/java/ladder/domain/Point.java @@ -0,0 +1,27 @@ +package ladder.domain; + +import java.util.Objects; + +public class Point { + private final boolean rightConnected; + + public Point(boolean rightConnected) { + this.rightConnected = rightConnected; + } + + public boolean connected() { + return rightConnected; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Point point = (Point) o; + return rightConnected == point.rightConnected; + } + + @Override + public int hashCode() { + return Objects.hashCode(rightConnected); + } +} diff --git a/src/main/java/ladder/domain/Points.java b/src/main/java/ladder/domain/Points.java new file mode 100644 index 0000000000..b8519e01f8 --- /dev/null +++ b/src/main/java/ladder/domain/Points.java @@ -0,0 +1,55 @@ +package ladder.domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.IntStream; + +public class Points { + private final List points; + + public Points(List points) { + this.points = points; + validate(); + } + + public Points(int size, ConnectStrategy connectStrategy) { + this(generatePoints(size, connectStrategy)); + } + + public List values() { + return points; + } + + private static List generatePoints(int size, ConnectStrategy connectStrategy) { + List points = new ArrayList<>(size); + IntStream.range(0, size) + .forEach(i -> points.add(new Point(connectStrategy.connect(i, i != 0 && points.get(i - 1).connected())))); + return points; + } + + public void validate() { + IntStream.range(0, points.size()-1) + .filter(this::continuousConnected) + .findFirst() + .ifPresent(i -> { + throw new IllegalArgumentException("각 포인트는 연속적으로 연결될 수 없음"); + }); + } + + private boolean continuousConnected(int idx) { + return points.get(idx).connected() && points.get(idx+1).connected(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Points points1 = (Points) o; + return Objects.equals(points, points1.points); + } + + @Override + public int hashCode() { + return Objects.hashCode(points); + } +} diff --git a/src/main/java/ladder/view/InputView.java b/src/main/java/ladder/view/InputView.java new file mode 100644 index 0000000000..e32054c96b --- /dev/null +++ b/src/main/java/ladder/view/InputView.java @@ -0,0 +1,19 @@ +package ladder.view; + +import ladder.domain.People; + +import java.util.Scanner; + +public class InputView { + private final static Scanner scanner = new Scanner(System.in); + + public static People inputPeople() { + System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"); + return new People(scanner.nextLine()); + } + + public static int inputLadderHeight() { + System.out.println("최대 사다리 높이는 몇인가요?"); + return scanner.nextInt(); + } +} diff --git a/src/main/java/ladder/view/ResultView.java b/src/main/java/ladder/view/ResultView.java new file mode 100644 index 0000000000..81fec2f393 --- /dev/null +++ b/src/main/java/ladder/view/ResultView.java @@ -0,0 +1,27 @@ +package ladder.view; + +import ladder.domain.Ladder; +import ladder.domain.People; + +public class ResultView { + public static void printLadder(People people, Ladder ladder) { + System.out.println("실행결과"); + printPeople(people); + printLadder(ladder); + } + + private static void printPeople(People people) { + people.values().forEach(v -> System.out.printf("%-6s", v.name())); + System.out.println(); + } + + private static void printLadder(Ladder ladder) { + ladder.lines().forEach(l -> { + l.points().values().forEach(p -> { + System.out.print("|"); + System.out.printf("%5s", p.connected() ? "-----" : ""); + }); + System.out.println(); + }); + } +} diff --git a/src/main/java/nextstep/optional/ComputerStore.java b/src/main/java/nextstep/optional/ComputerStore.java index 2695c967ac..0c95c286f0 100644 --- a/src/main/java/nextstep/optional/ComputerStore.java +++ b/src/main/java/nextstep/optional/ComputerStore.java @@ -3,6 +3,8 @@ import nextstep.optional.Computer.Soundcard; import nextstep.optional.Computer.USB; +import java.util.Optional; + public class ComputerStore { public static final String UNKNOWN_VERSION = "UNKNOWN"; @@ -21,6 +23,10 @@ public static String getVersion(Computer computer) { } public static String getVersionOptional(Computer computer) { - return null; + return Optional.ofNullable(computer) + .map(Computer::getSoundcard) + .map(Soundcard:: getUsb) + .map(USB::getVersion) + .orElse(UNKNOWN_VERSION); } } diff --git a/src/main/java/nextstep/optional/Users.java b/src/main/java/nextstep/optional/Users.java index 3d9333b188..63815d1c28 100644 --- a/src/main/java/nextstep/optional/Users.java +++ b/src/main/java/nextstep/optional/Users.java @@ -2,7 +2,6 @@ import java.util.Arrays; import java.util.List; -import java.util.Optional; public class Users { static final User DEFAULT_USER = new User("codesquad", 100); @@ -15,7 +14,7 @@ public class Users { User getUser(String name) { return users.stream() - .filter(user -> user.getName().equals(name)) + .filter(user -> user.matchName(name)) .findFirst() .orElse(DEFAULT_USER); } diff --git a/src/test/java/ladder/LineTest.java b/src/test/java/ladder/LineTest.java new file mode 100644 index 0000000000..07636a1dd1 --- /dev/null +++ b/src/test/java/ladder/LineTest.java @@ -0,0 +1,38 @@ +package ladder; + +import ladder.domain.Line; +import ladder.domain.Point; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class LineTest { + Point notConnected = new Point(false); + Point connected = new Point(true); + + @Test + void 라인_생성() { + Line line = new Line(4, (idx, preConnected) -> false); + assertThat(line).isEqualTo(new Line(List.of(notConnected, notConnected, notConnected, notConnected))); + } + + @Test + void 처음에만_연결() { + Line line = new Line(4, (idx, preConnected) -> idx == 0); + assertThat(line).isEqualTo(new Line(List.of(connected, notConnected, notConnected, notConnected))); + } + + @Test + void 홀수번째만_연결() { + Line line = new Line(4, (idx, preConnected) -> idx % 2 != 0); + assertThat(line).isEqualTo(new Line(List.of(notConnected, connected, notConnected, connected))); + } + + @Test + void 연속적으로_연결되면_예외() { + assertThatThrownBy(() -> new Line(4, (idx, preConnected) -> true)).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/ladder/PeopleTest.java b/src/test/java/ladder/PeopleTest.java new file mode 100644 index 0000000000..0eaba3742d --- /dev/null +++ b/src/test/java/ladder/PeopleTest.java @@ -0,0 +1,13 @@ +package ladder; + +import ladder.domain.People; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +public class PeopleTest { + @Test + void 이름_길이_예외() { + assertThatThrownBy(() -> new People("finnnnnn,foo")) + .isInstanceOf(IllegalArgumentException.class); + } +}