From 1e04007a016d415f03797f1649b2be5f6a3f4247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:17:32 +0900 Subject: [PATCH 01/25] chore: application common module setting --- .../coordinate/exception/CoordinateException.java | 8 ++++++++ .../java/coordinate/io/ConsoleInputHandler.java | 15 +++++++++++++++ .../java/coordinate/io/ConsoleOutputHandler.java | 8 ++++++++ .../java/coordinate/messages/ErrorMessage.java | 10 ++++++++++ .../java/coordinate/messages/SystemMessage.java | 8 ++++++++ 5 files changed, 49 insertions(+) create mode 100644 src/main/java/coordinate/exception/CoordinateException.java create mode 100644 src/main/java/coordinate/io/ConsoleInputHandler.java create mode 100644 src/main/java/coordinate/io/ConsoleOutputHandler.java create mode 100644 src/main/java/coordinate/messages/ErrorMessage.java create mode 100644 src/main/java/coordinate/messages/SystemMessage.java diff --git a/src/main/java/coordinate/exception/CoordinateException.java b/src/main/java/coordinate/exception/CoordinateException.java new file mode 100644 index 0000000..e2d71bd --- /dev/null +++ b/src/main/java/coordinate/exception/CoordinateException.java @@ -0,0 +1,8 @@ +package coordinate.exception; + +public class CoordinateException extends RuntimeException { + + public CoordinateException(String message) { + super(message); + } +} diff --git a/src/main/java/coordinate/io/ConsoleInputHandler.java b/src/main/java/coordinate/io/ConsoleInputHandler.java new file mode 100644 index 0000000..6bf9984 --- /dev/null +++ b/src/main/java/coordinate/io/ConsoleInputHandler.java @@ -0,0 +1,15 @@ +package coordinate.io; + +import coordinate.messages.SystemMessage; +import java.util.Scanner; + +public class ConsoleInputHandler { + + private final Scanner scanner = new Scanner(System.in); + + public String inputFromUser() { + System.out.println(SystemMessage.inputFigureSize); + return scanner.nextLine(); + } + +} diff --git a/src/main/java/coordinate/io/ConsoleOutputHandler.java b/src/main/java/coordinate/io/ConsoleOutputHandler.java new file mode 100644 index 0000000..01bba90 --- /dev/null +++ b/src/main/java/coordinate/io/ConsoleOutputHandler.java @@ -0,0 +1,8 @@ +package coordinate.io; + +public class ConsoleOutputHandler { + + public void printGraph(StringBuilder builder) { + System.out.println(builder.toString()); + } +} diff --git a/src/main/java/coordinate/messages/ErrorMessage.java b/src/main/java/coordinate/messages/ErrorMessage.java new file mode 100644 index 0000000..1cfde64 --- /dev/null +++ b/src/main/java/coordinate/messages/ErrorMessage.java @@ -0,0 +1,10 @@ +package coordinate.messages; + +public class ErrorMessage { + + public static final String invalidPoint = "좌표는 최소 0부터 최대 24까지 입력 할 수 있습니다."; + public static final String hyphenMustHave = "두 점의 좌표를 구분을 위해 '-' 필수로 입력 해야 합니다."; + public static final String numberFormatFailed = "좌표는 숫자만 입력해야 합니다."; + public static final String regexNotMatched = "좌표는 '(x, y) 형식으로 입력하며 숫자만 입력 해야 합니다."; + +} diff --git a/src/main/java/coordinate/messages/SystemMessage.java b/src/main/java/coordinate/messages/SystemMessage.java new file mode 100644 index 0000000..7e3af80 --- /dev/null +++ b/src/main/java/coordinate/messages/SystemMessage.java @@ -0,0 +1,8 @@ +package coordinate.messages; + +public class SystemMessage { + + public static final String inputFigureSize = "좌표를 입력하세요."; + public static final String distancePoints = "두 점 사이의 거리는: "; + +} From b153cea5d0dbcb1cb63b6d6624453104b344f356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:18:20 +0900 Subject: [PATCH 02/25] feat: coordinate point VO --- src/main/java/coordinate/point/Point.java | 59 +++++++++++++++++ src/test/java/coordinate/point/PointTest.java | 65 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/main/java/coordinate/point/Point.java create mode 100644 src/test/java/coordinate/point/PointTest.java diff --git a/src/main/java/coordinate/point/Point.java b/src/main/java/coordinate/point/Point.java new file mode 100644 index 0000000..b05c126 --- /dev/null +++ b/src/main/java/coordinate/point/Point.java @@ -0,0 +1,59 @@ +package coordinate.point; + +import coordinate.exception.CoordinateException; +import coordinate.messages.ErrorMessage; +import java.util.Objects; + +public class Point { + + private static final int MIN_VALUE = 0; + private static final int MAX_VALUE = 24; + private final int x; + private final int y; + + private Point(int x, int y) { + if (validateInputValue(x) || validateInputValue(y)) { + throw new CoordinateException(ErrorMessage.invalidPoint); + } + + this.x = x; + this.y = y; + } + + public static Point of(int x, int y) { + return new Point(x, y); + } + + public boolean isMark(int x, int y) { + return this.x == x && this.y == y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + private boolean validateInputValue(int point) { + return point < MIN_VALUE || point > MAX_VALUE; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Point point = (Point) o; + return x == point.x && y == point.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } +} diff --git a/src/test/java/coordinate/point/PointTest.java b/src/test/java/coordinate/point/PointTest.java new file mode 100644 index 0000000..9032ece --- /dev/null +++ b/src/test/java/coordinate/point/PointTest.java @@ -0,0 +1,65 @@ +package coordinate.point; + +import static org.assertj.core.api.Assertions.*; + +import coordinate.exception.CoordinateException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class PointTest { + + @ParameterizedTest + @DisplayName("[정상] 좌표는 0 ~ 24까지의 값만 입력할 수 있다") + @CsvSource({"0,24"}) + void testPointValidateByMinMaxValues(int x, int y) { + // Given + Point given = Point.of(0, 24); + + // When + Point point = Point.of(x, y); + + // Then + assertThat(point).isEqualTo(given); + } + + @ParameterizedTest + @DisplayName("[예외] 좌표는 0 ~ 24까지의 값만 입력할 수 있다") + @CsvSource({"-1,24", "0,25"}) + void testPointValidateByMinMaxValuesException(int x, int y) { + assertThatThrownBy(() -> { + // Given & When + Point.of(x, y); + }) + // Then + .hasMessage("좌표는 최소 0부터 최대 24까지 입력 할 수 있습니다.") + .isInstanceOf(CoordinateException.class); + } + + @Test + @DisplayName("[정상] 좌표값이 같을 때 마크가 활성화 된다.") + void testPointMarkIsTrue() { + // Given + Point point = Point.of(10, 10); + + // When + boolean markIsEnabled = point.isMark(10, 10); + + // Then + assertThat(markIsEnabled).isTrue(); + } + + @Test + @DisplayName("[실패] 좌표값이 같을 때 마크가 활성화 된다.") + void testPointMarkIsFalse() { + // Given + Point point = Point.of(10, 10); + + // When + boolean markIsEnabled = point.isMark(10, 11); + + // Then + assertThat(markIsEnabled).isFalse(); + } +} From f4322bdd9d426d68d53c033765f8310791b9b557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:18:36 +0900 Subject: [PATCH 03/25] feat: coordinate point list custom collection --- src/main/java/coordinate/point/PointList.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/coordinate/point/PointList.java diff --git a/src/main/java/coordinate/point/PointList.java b/src/main/java/coordinate/point/PointList.java new file mode 100644 index 0000000..2a1dbbe --- /dev/null +++ b/src/main/java/coordinate/point/PointList.java @@ -0,0 +1,43 @@ +package coordinate.point; + +import java.util.List; +import java.util.Objects; + +public class PointList { + + private final List points; + + private PointList(List points) { + this.points = points; + } + + public static PointList from(List points) { + return new PointList(points); + } + + public boolean isMark(int x, int y) { + return points.stream() + .anyMatch(point -> point.isMark(x, y)); + } + + public List getPoints() { + return points; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PointList pointList = (PointList) o; + return Objects.equals(points, pointList.points); + } + + @Override + public int hashCode() { + return Objects.hashCode(points); + } +} From de253b63829b0cb6cc90b5797a5e9ddcb380d264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:18:53 +0900 Subject: [PATCH 04/25] feat: figure plot factory class --- src/main/java/coordinate/plot/LinePlot.java | 62 +++++++++++++++++ .../java/coordinate/plot/LinePlotTest.java | 66 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/main/java/coordinate/plot/LinePlot.java create mode 100644 src/test/java/coordinate/plot/LinePlotTest.java diff --git a/src/main/java/coordinate/plot/LinePlot.java b/src/main/java/coordinate/plot/LinePlot.java new file mode 100644 index 0000000..ae293a8 --- /dev/null +++ b/src/main/java/coordinate/plot/LinePlot.java @@ -0,0 +1,62 @@ +package coordinate.plot; + +import coordinate.point.Point; +import coordinate.point.PointList; +import coordinate.utils.StringUtils; +import java.util.List; +import java.util.stream.Collectors; + +public class LinePlot { + + private final PointList figureSize; + + private LinePlot(PointList figureSize) { + // [Point(x, y), Point(x, y)] + this.figureSize = figureSize; + } + + public static LinePlot from(String figureSize) { + List splitedByHyphen = StringUtils.splitByHyphen(figureSize); + + PointList figureSizes = PointList.from(splitedByHyphen.stream() + .map(StringUtils::extractFromStringByRegex) + .map(LinePlot::linePointNumberListToPointObject) + .collect(Collectors.toList())); + + return new LinePlot(figureSizes); + } + + /** + * 제곱근((A.x - B.x)^제곱 + (A.y - B.y)^제곱) + */ + public double distanceBetweenPoints() { + Point firstPoint = figureSize.getPoints().get(0); + Point secondPoint = figureSize.getPoints().get(1); + + return Math.sqrt((calculateByX(firstPoint, secondPoint) + calculateByY(firstPoint, secondPoint))); + } + + public PointList getFigureSize() { + return figureSize; + } + + private static Point linePointNumberListToPointObject(List pointNumberList) { + int x = pointNumberList.get(0); + int y = pointNumberList.get(1); + return Point.of(x, y); + } + + private double calculateByX(Point firstPoint, Point secondPoint) { + int firstPointX = firstPoint.getX(); + int secondPointX = secondPoint.getX(); + return Math.pow(firstPointX - secondPointX, 2); + } + + private double calculateByY(Point firstPoint, Point secondPoint) { + int firstPointY = firstPoint.getY(); + int secondPointY = secondPoint.getY(); + + return Math.pow(firstPointY - secondPointY, 2); + } + +} diff --git a/src/test/java/coordinate/plot/LinePlotTest.java b/src/test/java/coordinate/plot/LinePlotTest.java new file mode 100644 index 0000000..89fa5a1 --- /dev/null +++ b/src/test/java/coordinate/plot/LinePlotTest.java @@ -0,0 +1,66 @@ +package coordinate.plot; + +import static org.assertj.core.api.Assertions.*; + +import coordinate.exception.CoordinateException; +import coordinate.point.Point; +import coordinate.point.PointList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class LinePlotTest { + + @Test + @DisplayName("[정상] 문자열을 입력 하면 두 점의 좌표를 반환한다") + void testLinePlotToPoints() { + // Given + String input = "(10,10)-(14,15)"; + PointList points = PointList.from(List.of(Point.of(10, 10), Point.of(14, 15))); + + // When + LinePlot linePlot = LinePlot.from(input); + + // Then + assertThat(linePlot.getFigureSize()).isEqualTo(points); + } + + @Test + @DisplayName("[실패] 좌표에 숫자가 아닌 문자를 입력할 시 예외를 반환한다") + void TestLinePlotToPointsExceptionByString() { + // Given + String input = "(10,asd)-(14,15)"; + + // When + assertThatThrownBy(() -> { + LinePlot.from(input); + }).hasMessage("좌표는 '(x, y) 형식으로 입력하며 숫자만 입력 해야 합니다.") + .isInstanceOf(CoordinateException.class); + } + + @Test + @DisplayName("[실패] 두 점의 좌표를 '-'으로 구분하지 않는 경우 예외를 반환한다") + void testLinePlotToPointExceptionByHyphenSeperate() { + // Given + String input = "(10,10),(14,15)"; + + // When + assertThatThrownBy(() -> { + LinePlot.from(input); + }).hasMessage("두 점의 좌표를 구분을 위해 '-' 필수로 입력 해야 합니다.") + .isInstanceOf(CoordinateException.class); + } + + @Test + @DisplayName("두 점의 사이 값을 검증한다") + void testLinePlotCalculateDistance() { + // Given + String input = "(10,10)-(14,15)"; + + // When + double distance = LinePlot.from(input).distanceBetweenPoints(); + + // Then + assertThat(distance).isEqualTo(6.403124, offset(0.00099)); + } +} From b0e23fa3f46ac2d8f32df98beb754fec2fdd53a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:19:01 +0900 Subject: [PATCH 05/25] feat: console output graph model --- src/main/java/coordinate/graph/Graph.java | 97 +++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/main/java/coordinate/graph/Graph.java diff --git a/src/main/java/coordinate/graph/Graph.java b/src/main/java/coordinate/graph/Graph.java new file mode 100644 index 0000000..beb05cb --- /dev/null +++ b/src/main/java/coordinate/graph/Graph.java @@ -0,0 +1,97 @@ +package coordinate.graph; + +import coordinate.messages.SystemMessage; +import coordinate.plot.LinePlot; +import coordinate.point.PointList; +import java.util.stream.IntStream; + +public class Graph { + + public static final int MAX_VALUE = 24; + public static final int MIN_VALUE = 0; + public static final int MAX_INT_RANGE = 25; + public static final String PLUS_MARK = "+"; + private static final String PIPE = "|"; + private static final String DOUBLE_HYPHEN = "--"; + private static final String NEW_LINE = System.lineSeparator(); + public static final String POINT_MARK = "•"; + public static final String SPACE = " "; + + private final StringBuilder graphBuilder = new StringBuilder(); + private final LinePlot linePlot; + + private Graph(LinePlot linePlot) { + this.linePlot = linePlot; + } + + public static Graph from(LinePlot linePlot) { + return new Graph(linePlot); + } + + public StringBuilder draw() { + verticalDrawAndPoint(); + horizontalDraw(); + distanceBetweenPointsResult(); + return graphBuilder; + } + + private void distanceBetweenPointsResult() { + graphBuilder.append(NEW_LINE); + graphBuilder.append(SystemMessage.distancePoints); + graphBuilder.append(linePlot.distanceBetweenPoints()); + } + + private void verticalDrawAndPoint() { + for (int y = MAX_VALUE; y > MIN_VALUE; y--) { + verticalDrawNumberWithPipe(y); + drawPoint(y, linePlot.getFigureSize()); + graphBuilder.append(NEW_LINE); + } + } + + private void verticalDrawNumberWithPipe(int y) { + if (isEvenNumber(y)) { + graphBuilder.append(String.format("%3d|", y)); + return; + } + + graphBuilder.append(String.format("%4s", PIPE)); + } + + private void drawPoint(int y, PointList points) { + for (int x = 0; x < MAX_INT_RANGE; x++) { + markAdd(x, y, points); + } + } + + private void markAdd(int x, int y, PointList points) { + if (points.isMark(x, y)) { + graphBuilder.append(String.format("%s", POINT_MARK)); + return; + } + + graphBuilder.append(String.format("%2s", SPACE)); + } + + private void horizontalDraw() { + horizontalLineDraw(); + horizontalNumberDraw(); + } + + private void horizontalNumberDraw() { + IntStream.range(MIN_VALUE, MAX_INT_RANGE) + .filter(this::isEvenNumber) + .forEach(x -> graphBuilder.append(String.format("%4d", x))); + graphBuilder.append(NEW_LINE); + } + + private void horizontalLineDraw() { + graphBuilder.append(String.format("%4s", PLUS_MARK)); + IntStream.range(MIN_VALUE, MAX_VALUE).forEach(i -> graphBuilder.append(String.format("%2s", DOUBLE_HYPHEN))); + graphBuilder.append("\n"); + } + + private boolean isEvenNumber(int value) { + return value % 2 == MIN_VALUE; + } +} From 17f2f8bffbf768dabd576fe70bcc90b7680212c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:19:12 +0900 Subject: [PATCH 06/25] feat: application string util class --- .../java/coordinate/utils/StringUtils.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/coordinate/utils/StringUtils.java diff --git a/src/main/java/coordinate/utils/StringUtils.java b/src/main/java/coordinate/utils/StringUtils.java new file mode 100644 index 0000000..312f2b2 --- /dev/null +++ b/src/main/java/coordinate/utils/StringUtils.java @@ -0,0 +1,43 @@ +package coordinate.utils; + +import coordinate.exception.CoordinateException; +import coordinate.messages.ErrorMessage; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class StringUtils { + + public static List splitByHyphen(String string) { + if (!string.contains("-")) { + throw new CoordinateException(ErrorMessage.hyphenMustHave); + } + + return List.of(string.split("-")); + } + + public static List extractFromStringByRegex(String string) { + String regex = "\\((\\d+),(\\d+)\\)"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(string); + + if (matcher.matches()) { + return IntStream.range(1, matcher.groupCount() + 1) + .mapToObj(i -> stringMatcherToInt(matcher, i)) + .collect(Collectors.toList()); + } + + throw new CoordinateException(ErrorMessage.regexNotMatched); + } + + private static int stringMatcherToInt(Matcher matcher, int groupIndex) { + try { + return Integer.parseInt(matcher.group(groupIndex)); + } catch (NumberFormatException e) { + throw new CoordinateException(ErrorMessage.numberFormatFailed); + } + } + +} From d9915e14a7d6ff7f8a5e8aaaf2093bc699fb5279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:19:19 +0900 Subject: [PATCH 07/25] chore: main application runner --- src/main/java/coordinate/MainApplication.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/coordinate/MainApplication.java diff --git a/src/main/java/coordinate/MainApplication.java b/src/main/java/coordinate/MainApplication.java new file mode 100644 index 0000000..e22bc68 --- /dev/null +++ b/src/main/java/coordinate/MainApplication.java @@ -0,0 +1,21 @@ +package coordinate; + +import coordinate.graph.Graph; +import coordinate.io.ConsoleInputHandler; +import coordinate.io.ConsoleOutputHandler; +import coordinate.plot.LinePlot; + +public class MainApplication { + + public static void main(String[] args) { + ConsoleInputHandler inputHandler = new ConsoleInputHandler(); + ConsoleOutputHandler outputHandler = new ConsoleOutputHandler(); + + String figureSize = inputHandler.inputFromUser(); + + LinePlot linePlot = LinePlot.from(figureSize); + Graph graph = Graph.from(linePlot); + outputHandler.printGraph(graph.draw()); + + } +} From 2047cd7b32f8ae4abe3cb75596c09343b97ba9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:32:19 +0900 Subject: [PATCH 08/25] rm: delete the plot files --- src/main/java/coordinate/plot/LinePlot.java | 62 ----------------- .../java/coordinate/plot/LinePlotTest.java | 66 ------------------- 2 files changed, 128 deletions(-) delete mode 100644 src/main/java/coordinate/plot/LinePlot.java delete mode 100644 src/test/java/coordinate/plot/LinePlotTest.java diff --git a/src/main/java/coordinate/plot/LinePlot.java b/src/main/java/coordinate/plot/LinePlot.java deleted file mode 100644 index ae293a8..0000000 --- a/src/main/java/coordinate/plot/LinePlot.java +++ /dev/null @@ -1,62 +0,0 @@ -package coordinate.plot; - -import coordinate.point.Point; -import coordinate.point.PointList; -import coordinate.utils.StringUtils; -import java.util.List; -import java.util.stream.Collectors; - -public class LinePlot { - - private final PointList figureSize; - - private LinePlot(PointList figureSize) { - // [Point(x, y), Point(x, y)] - this.figureSize = figureSize; - } - - public static LinePlot from(String figureSize) { - List splitedByHyphen = StringUtils.splitByHyphen(figureSize); - - PointList figureSizes = PointList.from(splitedByHyphen.stream() - .map(StringUtils::extractFromStringByRegex) - .map(LinePlot::linePointNumberListToPointObject) - .collect(Collectors.toList())); - - return new LinePlot(figureSizes); - } - - /** - * 제곱근((A.x - B.x)^제곱 + (A.y - B.y)^제곱) - */ - public double distanceBetweenPoints() { - Point firstPoint = figureSize.getPoints().get(0); - Point secondPoint = figureSize.getPoints().get(1); - - return Math.sqrt((calculateByX(firstPoint, secondPoint) + calculateByY(firstPoint, secondPoint))); - } - - public PointList getFigureSize() { - return figureSize; - } - - private static Point linePointNumberListToPointObject(List pointNumberList) { - int x = pointNumberList.get(0); - int y = pointNumberList.get(1); - return Point.of(x, y); - } - - private double calculateByX(Point firstPoint, Point secondPoint) { - int firstPointX = firstPoint.getX(); - int secondPointX = secondPoint.getX(); - return Math.pow(firstPointX - secondPointX, 2); - } - - private double calculateByY(Point firstPoint, Point secondPoint) { - int firstPointY = firstPoint.getY(); - int secondPointY = secondPoint.getY(); - - return Math.pow(firstPointY - secondPointY, 2); - } - -} diff --git a/src/test/java/coordinate/plot/LinePlotTest.java b/src/test/java/coordinate/plot/LinePlotTest.java deleted file mode 100644 index 89fa5a1..0000000 --- a/src/test/java/coordinate/plot/LinePlotTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package coordinate.plot; - -import static org.assertj.core.api.Assertions.*; - -import coordinate.exception.CoordinateException; -import coordinate.point.Point; -import coordinate.point.PointList; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -public class LinePlotTest { - - @Test - @DisplayName("[정상] 문자열을 입력 하면 두 점의 좌표를 반환한다") - void testLinePlotToPoints() { - // Given - String input = "(10,10)-(14,15)"; - PointList points = PointList.from(List.of(Point.of(10, 10), Point.of(14, 15))); - - // When - LinePlot linePlot = LinePlot.from(input); - - // Then - assertThat(linePlot.getFigureSize()).isEqualTo(points); - } - - @Test - @DisplayName("[실패] 좌표에 숫자가 아닌 문자를 입력할 시 예외를 반환한다") - void TestLinePlotToPointsExceptionByString() { - // Given - String input = "(10,asd)-(14,15)"; - - // When - assertThatThrownBy(() -> { - LinePlot.from(input); - }).hasMessage("좌표는 '(x, y) 형식으로 입력하며 숫자만 입력 해야 합니다.") - .isInstanceOf(CoordinateException.class); - } - - @Test - @DisplayName("[실패] 두 점의 좌표를 '-'으로 구분하지 않는 경우 예외를 반환한다") - void testLinePlotToPointExceptionByHyphenSeperate() { - // Given - String input = "(10,10),(14,15)"; - - // When - assertThatThrownBy(() -> { - LinePlot.from(input); - }).hasMessage("두 점의 좌표를 구분을 위해 '-' 필수로 입력 해야 합니다.") - .isInstanceOf(CoordinateException.class); - } - - @Test - @DisplayName("두 점의 사이 값을 검증한다") - void testLinePlotCalculateDistance() { - // Given - String input = "(10,10)-(14,15)"; - - // When - double distance = LinePlot.from(input).distanceBetweenPoints(); - - // Then - assertThat(distance).isEqualTo(6.403124, offset(0.00099)); - } -} From 7137c7d4613d1a777c73f240681d066a16a3f283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:34:09 +0900 Subject: [PATCH 09/25] fix: retry invalid coordinate when user input --- src/main/java/coordinate/MainApplication.java | 13 ++++--------- .../java/coordinate/io/ConsoleInputHandler.java | 13 ++++++++++++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/coordinate/MainApplication.java b/src/main/java/coordinate/MainApplication.java index e22bc68..978994f 100644 --- a/src/main/java/coordinate/MainApplication.java +++ b/src/main/java/coordinate/MainApplication.java @@ -8,14 +8,9 @@ public class MainApplication { public static void main(String[] args) { - ConsoleInputHandler inputHandler = new ConsoleInputHandler(); - ConsoleOutputHandler outputHandler = new ConsoleOutputHandler(); - - String figureSize = inputHandler.inputFromUser(); - - LinePlot linePlot = LinePlot.from(figureSize); - Graph graph = Graph.from(linePlot); - outputHandler.printGraph(graph.draw()); - + FigureSize figureSize = inputHandler.getFigureSize(); + Figure figure = FigureFactory.create(figureSize); + Graph graph = Graph.from(figure); + outputHandler.printGraph(graph); } } diff --git a/src/main/java/coordinate/io/ConsoleInputHandler.java b/src/main/java/coordinate/io/ConsoleInputHandler.java index 6bf9984..1c01f81 100644 --- a/src/main/java/coordinate/io/ConsoleInputHandler.java +++ b/src/main/java/coordinate/io/ConsoleInputHandler.java @@ -1,5 +1,7 @@ package coordinate.io; +import coordinate.exception.CoordinateException; +import coordinate.figure.FigureSize; import coordinate.messages.SystemMessage; import java.util.Scanner; @@ -7,7 +9,16 @@ public class ConsoleInputHandler { private final Scanner scanner = new Scanner(System.in); - public String inputFromUser() { + public FigureSize getFigureSize() { + try { + return FigureSize.from(inputFromUser()); + } catch (CoordinateException e) { + System.out.println(e.getMessage()); + return getFigureSize(); + } + } + + private String inputFromUser() { System.out.println(SystemMessage.inputFigureSize); return scanner.nextLine(); } From dae1c7e5ed0bfe822e3d12fe4dda58477f4402e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:38:20 +0900 Subject: [PATCH 10/25] feat: figure factory class to create line, rectangle and another --- src/main/java/coordinate/figure/Figure.java | 8 +++ .../java/coordinate/figure/FigureFactory.java | 8 +++ .../java/coordinate/figure/FigureType.java | 39 +++++++++++++ .../coordinate/messages/ErrorMessage.java | 2 +- .../coordinate/figure/FigureFactoryTest.java | 37 ++++++++++++ .../coordinate/figure/FigureTypeTest.java | 56 +++++++++++++++++++ 6 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/main/java/coordinate/figure/Figure.java create mode 100644 src/main/java/coordinate/figure/FigureFactory.java create mode 100644 src/main/java/coordinate/figure/FigureType.java create mode 100644 src/test/java/coordinate/figure/FigureFactoryTest.java create mode 100644 src/test/java/coordinate/figure/FigureTypeTest.java diff --git a/src/main/java/coordinate/figure/Figure.java b/src/main/java/coordinate/figure/Figure.java new file mode 100644 index 0000000..d42ae3e --- /dev/null +++ b/src/main/java/coordinate/figure/Figure.java @@ -0,0 +1,8 @@ +package coordinate.figure; + +public interface Figure { + + double calculate(); + + boolean isMark(int x, int y); +} diff --git a/src/main/java/coordinate/figure/FigureFactory.java b/src/main/java/coordinate/figure/FigureFactory.java new file mode 100644 index 0000000..ac49eac --- /dev/null +++ b/src/main/java/coordinate/figure/FigureFactory.java @@ -0,0 +1,8 @@ +package coordinate.figure; + +public class FigureFactory { + + public static Figure create(FigureSize figureSize) { + return FigureType.get(figureSize); + } +} diff --git a/src/main/java/coordinate/figure/FigureType.java b/src/main/java/coordinate/figure/FigureType.java new file mode 100644 index 0000000..2f5765b --- /dev/null +++ b/src/main/java/coordinate/figure/FigureType.java @@ -0,0 +1,39 @@ +package coordinate.figure; + +import coordinate.exception.CoordinateException; +import coordinate.messages.ErrorMessage; +import coordinate.point.Points; +import java.util.Arrays; + +public enum FigureType { + LINE(2) { + @Override + public Figure createFigure(Points points) { + return Line.from(points); + } + }, + RECTANGLE(4) { + @Override + public Figure createFigure(Points points) { + return Rectangle.from(points); + } + }; + + private final int pointsSize; + + FigureType(int pointsSize) { + this.pointsSize = pointsSize; + } + + public abstract Figure createFigure(Points points); + + public static Figure get(FigureSize figureSize) { + Points points = figureSize.toPoints(); + + return Arrays.stream(values()) + .filter(type -> type.pointsSize == points.size()) + .findFirst() + .orElseThrow(() -> new CoordinateException(ErrorMessage.invalidFigureSize)) + .createFigure(points); + } +} diff --git a/src/main/java/coordinate/messages/ErrorMessage.java b/src/main/java/coordinate/messages/ErrorMessage.java index 1cfde64..9ad09d7 100644 --- a/src/main/java/coordinate/messages/ErrorMessage.java +++ b/src/main/java/coordinate/messages/ErrorMessage.java @@ -4,7 +4,7 @@ public class ErrorMessage { public static final String invalidPoint = "좌표는 최소 0부터 최대 24까지 입력 할 수 있습니다."; public static final String hyphenMustHave = "두 점의 좌표를 구분을 위해 '-' 필수로 입력 해야 합니다."; - public static final String numberFormatFailed = "좌표는 숫자만 입력해야 합니다."; public static final String regexNotMatched = "좌표는 '(x, y) 형식으로 입력하며 숫자만 입력 해야 합니다."; + public static final String invalidFigureSize = "해당 좌표로 도형을 생성 할 수 없습니다."; } diff --git a/src/test/java/coordinate/figure/FigureFactoryTest.java b/src/test/java/coordinate/figure/FigureFactoryTest.java new file mode 100644 index 0000000..ba68206 --- /dev/null +++ b/src/test/java/coordinate/figure/FigureFactoryTest.java @@ -0,0 +1,37 @@ +package coordinate.figure; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class FigureFactoryTest { + + @Test + @DisplayName("2개의 좌표를 입력 하면 Line 객체를 반환한다") + void testFigureFactoryCreateLine() { + + // Given + FigureSize figureSize = FigureSize.from("(10,10)-(14,15)"); + + // When + Figure figure = FigureFactory.create(figureSize); + + // Then + assertThat(figure).isInstanceOf(Line.class); + } + + @Test + @DisplayName("4개의 좌표를 입력 하면 Rectangle 객체를 반환한다") + void testFigureFactoryCreateRectangle() { + + // Given + FigureSize figureSize = FigureSize.from("(10,10)-(22,10)-(22,18)-(10,18)"); + + // When + Figure figure = FigureFactory.create(figureSize); + + // Then + assertThat(figure).isInstanceOf(Rectangle.class); + } +} diff --git a/src/test/java/coordinate/figure/FigureTypeTest.java b/src/test/java/coordinate/figure/FigureTypeTest.java new file mode 100644 index 0000000..2db399c --- /dev/null +++ b/src/test/java/coordinate/figure/FigureTypeTest.java @@ -0,0 +1,56 @@ +package coordinate.figure; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import coordinate.exception.CoordinateException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class FigureTypeTest { + + @Test + @DisplayName("2개의 좌표를 입력하면 Line 객체를 반환한다") + void testLineFigureType() { + // Given + FigureSize figureSize = FigureSize.from("(10,10)-(14,15)"); + + // When + Figure line = FigureType.get(figureSize); + + // Then + assertThat(line).isInstanceOf(Line.class); + } + + @Test + @DisplayName("4개의 좌표를 입력하면 Rectangle 객체를 반환한다") + void testRectangleFigureType() { + // Given + FigureSize figureSize = FigureSize.from("(10,10)-(22,10)-(22,18)-(10,18)"); + + // When + Figure rectangle = FigureType.get(figureSize); + + // Then + assertThat(rectangle).isInstanceOf(Rectangle.class); + } + + @ParameterizedTest + @DisplayName("정의 되지 않은 좌표 개 수를 입력하면 예외를 반환한다") + @CsvSource(value = {"(10,10)-(1,1)-(1,2)-(1,3)-(1,4):", "(1,1)-"}, delimiter = ':') + void testInvalidCoordinateSizes(String testFigureSize) { + // Given + FigureSize figureSize = FigureSize.from(testFigureSize); + + assertThatThrownBy(() -> { + // When + FigureType.get(figureSize); + }) + // Then + .hasMessage("해당 좌표로 도형을 생성 할 수 없습니다.") + .isInstanceOf(CoordinateException.class); + } + +} From b3caf2399cbc2a816a6d34abed9a460550b8a386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:38:53 +0900 Subject: [PATCH 11/25] update: modify to graph method signature --- src/main/java/coordinate/graph/Graph.java | 33 +++++++++++------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/coordinate/graph/Graph.java b/src/main/java/coordinate/graph/Graph.java index beb05cb..ff64c2a 100644 --- a/src/main/java/coordinate/graph/Graph.java +++ b/src/main/java/coordinate/graph/Graph.java @@ -1,8 +1,6 @@ package coordinate.graph; -import coordinate.messages.SystemMessage; -import coordinate.plot.LinePlot; -import coordinate.point.PointList; +import coordinate.figure.Figure; import java.util.stream.IntStream; public class Graph { @@ -18,14 +16,14 @@ public class Graph { public static final String SPACE = " "; private final StringBuilder graphBuilder = new StringBuilder(); - private final LinePlot linePlot; + private final Figure figure; - private Graph(LinePlot linePlot) { - this.linePlot = linePlot; + private Graph(Figure figure) { + this.figure = figure; } - public static Graph from(LinePlot linePlot) { - return new Graph(linePlot); + public static Graph from(Figure figure) { + return new Graph(figure); } public StringBuilder draw() { @@ -37,14 +35,13 @@ public StringBuilder draw() { private void distanceBetweenPointsResult() { graphBuilder.append(NEW_LINE); - graphBuilder.append(SystemMessage.distancePoints); - graphBuilder.append(linePlot.distanceBetweenPoints()); + graphBuilder.append(figure.toString()); } private void verticalDrawAndPoint() { for (int y = MAX_VALUE; y > MIN_VALUE; y--) { verticalDrawNumberWithPipe(y); - drawPoint(y, linePlot.getFigureSize()); + drawPoint(y); graphBuilder.append(NEW_LINE); } } @@ -58,15 +55,15 @@ private void verticalDrawNumberWithPipe(int y) { graphBuilder.append(String.format("%4s", PIPE)); } - private void drawPoint(int y, PointList points) { + private void drawPoint(int y) { for (int x = 0; x < MAX_INT_RANGE; x++) { - markAdd(x, y, points); + markAdd(x, y, figure); } } - private void markAdd(int x, int y, PointList points) { - if (points.isMark(x, y)) { - graphBuilder.append(String.format("%s", POINT_MARK)); + private void markAdd(int x, int y, Figure figure) { + if (figure.isMark(x, y)) { + graphBuilder.append(POINT_MARK); return; } @@ -87,8 +84,8 @@ private void horizontalNumberDraw() { private void horizontalLineDraw() { graphBuilder.append(String.format("%4s", PLUS_MARK)); - IntStream.range(MIN_VALUE, MAX_VALUE).forEach(i -> graphBuilder.append(String.format("%2s", DOUBLE_HYPHEN))); - graphBuilder.append("\n"); + IntStream.range(MIN_VALUE, MAX_VALUE).forEach(i -> graphBuilder.append(DOUBLE_HYPHEN)); + graphBuilder.append(NEW_LINE); } private boolean isEvenNumber(int value) { From 45bb884c1e649627823c28e4dae580c817a7e8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:40:59 +0900 Subject: [PATCH 12/25] update: modify to output handler print graph method signature --- src/main/java/coordinate/io/ConsoleOutputHandler.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/coordinate/io/ConsoleOutputHandler.java b/src/main/java/coordinate/io/ConsoleOutputHandler.java index 01bba90..5360a3d 100644 --- a/src/main/java/coordinate/io/ConsoleOutputHandler.java +++ b/src/main/java/coordinate/io/ConsoleOutputHandler.java @@ -1,8 +1,10 @@ package coordinate.io; +import coordinate.graph.Graph; + public class ConsoleOutputHandler { - public void printGraph(StringBuilder builder) { - System.out.println(builder.toString()); + public void printGraph(Graph graph) { + System.out.println(graph.draw().toString()); } } From 6fd21d0f5da8f335fdff5a51d31e0d94f4a3249c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:42:16 +0900 Subject: [PATCH 13/25] feat: manage to list integer type first class collection --- .../java/coordinate/point/Coordinate.java | 39 +++++++++++++ .../java/coordinate/point/CoordinateTest.java | 55 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/main/java/coordinate/point/Coordinate.java create mode 100644 src/test/java/coordinate/point/CoordinateTest.java diff --git a/src/main/java/coordinate/point/Coordinate.java b/src/main/java/coordinate/point/Coordinate.java new file mode 100644 index 0000000..c635807 --- /dev/null +++ b/src/main/java/coordinate/point/Coordinate.java @@ -0,0 +1,39 @@ +package coordinate.point; + +import coordinate.utils.StringUtils; +import java.util.List; +import java.util.Objects; + +public class Coordinate { + + private final List coordinate; + + private Coordinate(List coordinate) { + this.coordinate = coordinate; + } + + public static Coordinate from(String coordinateStringWithBracket) { + return new Coordinate(StringUtils.extractFromStringToIntegerByRegex(coordinateStringWithBracket)); + } + + public Point toPoint() { + return Point.of(coordinate.get(0), coordinate.get(1)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Coordinate that = (Coordinate) o; + return Objects.equals(coordinate, that.coordinate); + } + + @Override + public int hashCode() { + return Objects.hashCode(coordinate); + } +} diff --git a/src/test/java/coordinate/point/CoordinateTest.java b/src/test/java/coordinate/point/CoordinateTest.java new file mode 100644 index 0000000..4162f57 --- /dev/null +++ b/src/test/java/coordinate/point/CoordinateTest.java @@ -0,0 +1,55 @@ +package coordinate.point; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import coordinate.exception.CoordinateException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class CoordinateTest { + + + @Test + @DisplayName("좌표는 '(x,y)' 형태로 입력해야 한다.") + void testCoordinateValidation() { + // Given + String coordinateInput = "(10,10)"; + + // When + Coordinate coordinate = Coordinate.from(coordinateInput); + + // Then + assertThat(coordinate.toPoint()).isEqualTo(Point.of(10, 10)); + } + + @Test + @DisplayName("좌표를 입력할 때 괄호 형식을 지키지 않으면 예외를 반환한다") + void testCoordinateBracketValidation() { + // Given + String coordinateInput = "10,10"; + + assertThatThrownBy(() -> { + // When + Coordinate.from(coordinateInput); + }) + // Then + .hasMessage("좌표는 '(x, y) 형식으로 입력하며 숫자만 입력 해야 합니다.") + .isInstanceOf(CoordinateException.class); + } + + @Test + @DisplayName("좌표에 입력한 값이 숫자가 아닌 경우 예외를 반환한다") + void testCoordinateValueValidation() { + // Given + String coordinateInput = "(10,a)"; + + assertThatThrownBy(() -> { + // When + Coordinate.from(coordinateInput); + }) + // Then + .hasMessage("좌표는 '(x, y) 형식으로 입력하며 숫자만 입력 해야 합니다.") + .isInstanceOf(CoordinateException.class); + } +} From 20b8264e6252da9acaf4cf3b8e75cbc2df18592b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:42:54 +0900 Subject: [PATCH 14/25] feat: user input string to first class collection --- .../java/coordinate/figure/FigureSize.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/coordinate/figure/FigureSize.java diff --git a/src/main/java/coordinate/figure/FigureSize.java b/src/main/java/coordinate/figure/FigureSize.java new file mode 100644 index 0000000..a7ec5c6 --- /dev/null +++ b/src/main/java/coordinate/figure/FigureSize.java @@ -0,0 +1,33 @@ +package coordinate.figure; + +import coordinate.point.Coordinate; +import coordinate.point.Points; +import coordinate.utils.StringUtils; +import java.util.List; +import java.util.stream.Collectors; + +public class FigureSize { + + private final List figureSizes; + + private FigureSize(List figureSizes) { + this.figureSizes = figureSizes; + } + + public static FigureSize from(String userInputFigureSize) { + List splitedByHyphen = StringUtils.splitByHyphen(userInputFigureSize); + + List figureSizes = splitedByHyphen.stream() + .map(Coordinate::from) + .collect(Collectors.toList()); + + return new FigureSize(figureSizes); + } + + public Points toPoints() { + return Points.from(figureSizes.stream() + .map(Coordinate::toPoint) + .collect(Collectors.toList())); + } + +} From 293dd5ccd9a91845050226c041469ade32b4a1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:43:26 +0900 Subject: [PATCH 15/25] update: change the method name --- src/main/java/coordinate/point/Point.java | 10 ++--- src/test/java/coordinate/point/PointTest.java | 43 ++++++++++++++++--- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main/java/coordinate/point/Point.java b/src/main/java/coordinate/point/Point.java index b05c126..104b5d1 100644 --- a/src/main/java/coordinate/point/Point.java +++ b/src/main/java/coordinate/point/Point.java @@ -24,16 +24,16 @@ public static Point of(int x, int y) { return new Point(x, y); } - public boolean isMark(int x, int y) { + public boolean isSamePosition(int x, int y) { return this.x == x && this.y == y; } - public int getX() { - return x; + public int subtractionByX(Point anotherPoint) { + return x - anotherPoint.x; } - public int getY() { - return y; + public int subtractionByY(Point anotherPoint) { + return y - anotherPoint.y; } private boolean validateInputValue(int point) { diff --git a/src/test/java/coordinate/point/PointTest.java b/src/test/java/coordinate/point/PointTest.java index 9032ece..647e787 100644 --- a/src/test/java/coordinate/point/PointTest.java +++ b/src/test/java/coordinate/point/PointTest.java @@ -1,6 +1,7 @@ package coordinate.point; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import coordinate.exception.CoordinateException; import org.junit.jupiter.api.DisplayName; @@ -11,7 +12,7 @@ public class PointTest { @ParameterizedTest - @DisplayName("[정상] 좌표는 0 ~ 24까지의 값만 입력할 수 있다") + @DisplayName("좌표는 0 ~ 24까지의 값만 입력할 수 있다") @CsvSource({"0,24"}) void testPointValidateByMinMaxValues(int x, int y) { // Given @@ -25,7 +26,7 @@ void testPointValidateByMinMaxValues(int x, int y) { } @ParameterizedTest - @DisplayName("[예외] 좌표는 0 ~ 24까지의 값만 입력할 수 있다") + @DisplayName("입력한 좌표가 0 ~ 24 범위를 벗어나면 예외를 반환한다") @CsvSource({"-1,24", "0,25"}) void testPointValidateByMinMaxValuesException(int x, int y) { assertThatThrownBy(() -> { @@ -38,28 +39,56 @@ void testPointValidateByMinMaxValuesException(int x, int y) { } @Test - @DisplayName("[정상] 좌표값이 같을 때 마크가 활성화 된다.") + @DisplayName("좌표값이 같을 때 마크 표시 상태값이 활성화된다.") void testPointMarkIsTrue() { // Given Point point = Point.of(10, 10); // When - boolean markIsEnabled = point.isMark(10, 10); + boolean markIsEnabled = point.isSamePosition(10, 10); // Then assertThat(markIsEnabled).isTrue(); } @Test - @DisplayName("[실패] 좌표값이 같을 때 마크가 활성화 된다.") + @DisplayName("좌표값이 같지 않으면 마크 표시 상태값이 활성화 되지 않는다.") void testPointMarkIsFalse() { // Given Point point = Point.of(10, 10); // When - boolean markIsEnabled = point.isMark(10, 11); + boolean markIsEnabled = point.isSamePosition(10, 11); // Then assertThat(markIsEnabled).isFalse(); } + + @Test + @DisplayName("두 점에서 X좌표 끼리 뺄셈 연산을 한다.") + void testSubtractByX() { + // Given + Point firstPoint = Point.of(10, 10); + Point secondPoint = Point.of(20, 20); + + // When + int result = firstPoint.subtractionByX(secondPoint); + + // Then + assertThat(result).isEqualTo(-10); + } + + @Test + @DisplayName("두 점에서 Y좌표 끼리 뺄셈 연산을 한다.") + void testSubtractByY() { + // Given + Point firstPoint = Point.of(10, 14); + Point secondPoint = Point.of(20, 20); + + // When + int result = firstPoint.subtractionByY(secondPoint); + + // Then + assertThat(result).isEqualTo(-6); + } } From 180f9eac9208c473e17d839cbdf087068572ba4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:43:52 +0900 Subject: [PATCH 16/25] feat: points in attribute get size --- .../point/{PointList.java => Points.java} | 21 +++-- .../java/coordinate/point/PointsTest.java | 80 +++++++++++++++++++ 2 files changed, 93 insertions(+), 8 deletions(-) rename src/main/java/coordinate/point/{PointList.java => Points.java} (58%) create mode 100644 src/test/java/coordinate/point/PointsTest.java diff --git a/src/main/java/coordinate/point/PointList.java b/src/main/java/coordinate/point/Points.java similarity index 58% rename from src/main/java/coordinate/point/PointList.java rename to src/main/java/coordinate/point/Points.java index 2a1dbbe..239bfaf 100644 --- a/src/main/java/coordinate/point/PointList.java +++ b/src/main/java/coordinate/point/Points.java @@ -1,27 +1,32 @@ package coordinate.point; +import java.util.ArrayList; import java.util.List; import java.util.Objects; -public class PointList { +public class Points { private final List points; - private PointList(List points) { + private Points(List points) { this.points = points; } - public static PointList from(List points) { - return new PointList(points); + public static Points from(List points) { + return new Points(points); } - public boolean isMark(int x, int y) { + public boolean isMarkedAt(int x, int y) { return points.stream() - .anyMatch(point -> point.isMark(x, y)); + .anyMatch(point -> point.isSamePosition(x, y)); + } + + public int size() { + return points.size(); } public List getPoints() { - return points; + return new ArrayList<>(points); } @Override @@ -32,7 +37,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - PointList pointList = (PointList) o; + Points pointList = (Points) o; return Objects.equals(points, pointList.points); } diff --git a/src/test/java/coordinate/point/PointsTest.java b/src/test/java/coordinate/point/PointsTest.java new file mode 100644 index 0000000..69faaf3 --- /dev/null +++ b/src/test/java/coordinate/point/PointsTest.java @@ -0,0 +1,80 @@ +package coordinate.point; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class PointsTest { + + @ParameterizedTest + @DisplayName("그래프의 좌표 값과 포인트의 좌표 값이 일치할 경우 마크 표시를 활성화한다") + @CsvSource(value = {"10,10", "14,15"}) + void testPointsMark(int x, int y) { + // Given + Points points = Points.from(List.of(Point.of(10, 10), Point.of(14, 15))); + + // When + boolean markedAt = points.isMarkedAt(x, y); + + // Then + assertThat(markedAt).isTrue(); + } + + @ParameterizedTest + @DisplayName("그래프의 좌표 값과 포인트의 좌표 값이 일치하지 않을 경우 마크 표시가 활성화 되지 않는다") + @CsvSource(value = {"11,10", "14,16"}) + void testPointsIsNotMark(int x, int y) { + // Given + Points points = Points.from(List.of(Point.of(10, 10), Point.of(14, 15))); + + // When + boolean markedAt = points.isMarkedAt(x, y); + + // Then + assertThat(markedAt).isFalse(); + } + + @Test + @DisplayName("입력한 좌표가 2개일 때 Points 객체의 사이즈는 2여야한다") + void testPointsSizeTwo() { + // Given + Points points = Points.from(List.of(Point.of(10, 10), Point.of(14, 15))); + + // When + int size = points.size(); + + // Then + assertThat(size).isEqualTo(2); + } + + @Test + @DisplayName("입력한 좌표가 4개일 때 Points 객체의 사이즈는 4여야한다") + void testPointsSizeFour() { + // Given + Points points = Points.from(List.of(Point.of(10, 10), Point.of(20, 20), Point.of(22, 18), Point.of(10, 18))); + + // When + int size = points.size(); + + // Then + assertThat(size).isEqualTo(4); + } + + @Test + @DisplayName("Points 객체가 가진 Point 배열을 반환한다") + void testGetPoints() { + // Given + Points points = Points.from(List.of(Point.of(10, 10), Point.of(14, 15))); + List pointList = List.of(Point.of(10, 10), Point.of(14, 15)); + + // When + List getPoints = points.getPoints(); + + // Then + assertThat(getPoints).isEqualTo(pointList); + } +} From 6ac84a1a788d6d9463828838421a7e4029c094e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:44:28 +0900 Subject: [PATCH 17/25] feat: 2 points to line class --- src/main/java/coordinate/figure/Line.java | 59 ++++++++++++++ src/test/java/coordinate/figure/LineTest.java | 81 +++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/main/java/coordinate/figure/Line.java create mode 100644 src/test/java/coordinate/figure/LineTest.java diff --git a/src/main/java/coordinate/figure/Line.java b/src/main/java/coordinate/figure/Line.java new file mode 100644 index 0000000..24b27c1 --- /dev/null +++ b/src/main/java/coordinate/figure/Line.java @@ -0,0 +1,59 @@ +package coordinate.figure; + +import coordinate.point.Point; +import coordinate.point.Points; +import java.util.List; + +public class Line implements Figure { + + private final Points points; + + private Line(Points points) { + this.points = points; + } + + public static Line from(Points points) { + return new Line(points); + } + + @Override + public String toString() { + return String.format("두 점 사이의 거리는: " + calculate()); + } + + @Override + public boolean isMark(int x, int y) { + return points.isMarkedAt(x, y); + } + + /** + * 제곱근((A.x - B.x)^제곱 + (A.y - B.y)^제곱) + */ + @Override + public double calculate() { + List points = this.points.getPoints(); + + Point firstPoint = getFirstPoint(points); + Point secondPoint = getSecondPoint(points); + + return calculateDistanceBetweenPoints(firstPoint, secondPoint); + } + + private Point getFirstPoint(List points) { + return points.get(0); + } + + private Point getSecondPoint(List points) { + return points.get(1); + } + + private double calculateDistanceBetweenPoints(Point point1, Point point2) { + double subX = square(point1.subtractionByX(point2)); + double subY = square(point1.subtractionByY(point2)); + return Math.sqrt(subX + subY); + } + + private double square(int value) { + return Math.pow(value, 2); + } +} diff --git a/src/test/java/coordinate/figure/LineTest.java b/src/test/java/coordinate/figure/LineTest.java new file mode 100644 index 0000000..81e512e --- /dev/null +++ b/src/test/java/coordinate/figure/LineTest.java @@ -0,0 +1,81 @@ +package coordinate.figure; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.offset; + +import coordinate.point.Point; +import coordinate.point.Points; +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class LineTest { + + private static Points points; + + @BeforeAll + static void setUp() { + points = Points.from(List.of(Point.of(10, 10), Point.of(14, 15))); + } + + @ParameterizedTest + @DisplayName("두 점의 위치와 좌표 위치가 같을 때 마크 표시 여부가 True 가 된다") + @CsvSource(value = {"10,10", "14,15"}) + void testLineIsMark(int x, int y) { + + // Given + Line line = Line.from(points); + + // When + boolean isMark = line.isMark(x, y); + + // Then + assertThat(isMark).isTrue(); + } + + @ParameterizedTest + @DisplayName("두 점의 위치와 좌표 위치가 다르면 마크 표시 여부가 False 이다") + @CsvSource(value = {"10,11", "14,16"}) + void testLineIsNotMark(int x, int y) { + + // Given + Line line = Line.from(points); + + // When + boolean isMark = line.isMark(x, y); + + // Then + assertThat(isMark).isFalse(); + } + + @Test + @DisplayName("두 점사이의 거리를 계산한 값을 검증한다") + void testLineDistanceBetweenPoints() { + + // Given + Line line = Line.from(points); + + // When + double distance = line.calculate(); + + // Then + assertThat(distance).isEqualTo(6.40312, offset(0.00099)); + } + + @Test + @DisplayName("Line 객체를 문자열로 반환할 시 두 점 사이의 거리를 출력 해야한다") + void testLineToString() { + + // Given + Line line = Line.from(points); + + // When + String string = line.toString(); + + // Then + assertThat(string).isEqualTo("두 점 사이의 거리는: " + 6.4031242374328485); + } +} From 2d3a1456a885b10d019020b7010c52333935a426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:44:39 +0900 Subject: [PATCH 18/25] feat: 4 points to rectangle class --- .../java/coordinate/figure/Rectangle.java | 58 +++++++++++++ .../java/coordinate/figure/RectangleTest.java | 82 +++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/main/java/coordinate/figure/Rectangle.java create mode 100644 src/test/java/coordinate/figure/RectangleTest.java diff --git a/src/main/java/coordinate/figure/Rectangle.java b/src/main/java/coordinate/figure/Rectangle.java new file mode 100644 index 0000000..b58fe4a --- /dev/null +++ b/src/main/java/coordinate/figure/Rectangle.java @@ -0,0 +1,58 @@ +package coordinate.figure; + +import coordinate.point.Point; +import coordinate.point.Points; +import java.util.List; + +public class Rectangle implements Figure { + + Points points; + + private Rectangle(Points points) { + this.points = points; + } + + public static Rectangle from(Points points) { + return new Rectangle(points); + } + + @Override + public boolean isMark(int x, int y) { + return points.isMarkedAt(x, y); + } + + @Override + public String toString() { + return "사각형의 넓이는 " + (int) calculate(); + } + + /** + * width * height + */ + @Override + public double calculate() { + List points = this.points.getPoints(); + + Point leftBottomPoint = getLeftBottomPoint(points); + Point rightTopPoint = getRightTopPoint(points); + + return getWidth(leftBottomPoint, rightTopPoint) * getHeight(leftBottomPoint, rightTopPoint); + } + + private Point getLeftBottomPoint(List points) { + return points.get(0); + } + + private static Point getRightTopPoint(List points) { + return points.get(2); + } + + private double getWidth(Point point1, Point point2) { + return Math.abs(point1.subtractionByX(point2)); + } + + private double getHeight(Point point1, Point point2) { + return Math.abs(point1.subtractionByY(point2)); + } + +} diff --git a/src/test/java/coordinate/figure/RectangleTest.java b/src/test/java/coordinate/figure/RectangleTest.java new file mode 100644 index 0000000..82b5f0c --- /dev/null +++ b/src/test/java/coordinate/figure/RectangleTest.java @@ -0,0 +1,82 @@ +package coordinate.figure; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.offset; + +import coordinate.point.Point; +import coordinate.point.Points; +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class RectangleTest { + + private static Points points; + + @BeforeAll + static void setUp() { + points = Points.from(List.of(Point.of(10, 10), Point.of(22, 10), Point.of(22, 18), Point.of(10, 18))); + } + + + @ParameterizedTest + @DisplayName("네 점의 위치와 좌표 위치가 같을 때 마크 표시 여부가 True 가 된다") + @CsvSource(value = {"10,10", "22,10", "22,18", "10,18"}) + void testRectangleIsMark(int x, int y) { + + // Given + Rectangle rectangle = Rectangle.from(points); + + // When + boolean isMark = rectangle.isMark(x, y); + + // Then + assertThat(isMark).isTrue(); + } + + @ParameterizedTest + @DisplayName("네 점의 위치와 좌표 위치가 다른 경우 마크 표시 여부는 False 이다") + @CsvSource(value = {"10,11", "2,10", "22,13", "5,18"}) + void testRectangleIsNotMark(int x, int y) { + + // Given + Rectangle rectangle = Rectangle.from(points); + + // When + boolean isMark = rectangle.isMark(x, y); + + // Then + assertThat(isMark).isFalse(); + } + + @Test + @DisplayName("사각형의 면접을 계산하는 반환 값을 검증한다") + void testRectangleCalculate() { + + // Given + Rectangle rectangle = Rectangle.from(points); + + // When + double result = rectangle.calculate(); + + // Then + assertThat(result).isEqualTo(96.0, offset(0.00099)); + } + + @Test + @DisplayName("Rectangle 객체를 문자열로 변환 할 시 사각형의 넓이를 반환한다") + void testRectangleToString() { + + // Given + Rectangle rectangle = Rectangle.from(points); + + // When + String string = rectangle.toString(); + + // Then + assertThat(string).isEqualTo("사각형의 넓이는 " + 96); + } +} From e217c2874c77ac89d301acf57e8d049a3245be12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:45:40 +0900 Subject: [PATCH 19/25] update: string util private method remove the exception block --- .../java/coordinate/utils/StringUtils.java | 8 +-- .../coordinate/utils/StringUtilsTest.java | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 src/test/java/coordinate/utils/StringUtilsTest.java diff --git a/src/main/java/coordinate/utils/StringUtils.java b/src/main/java/coordinate/utils/StringUtils.java index 312f2b2..62ae7fd 100644 --- a/src/main/java/coordinate/utils/StringUtils.java +++ b/src/main/java/coordinate/utils/StringUtils.java @@ -18,7 +18,7 @@ public static List splitByHyphen(String string) { return List.of(string.split("-")); } - public static List extractFromStringByRegex(String string) { + public static List extractFromStringToIntegerByRegex(String string) { String regex = "\\((\\d+),(\\d+)\\)"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(string); @@ -33,11 +33,7 @@ public static List extractFromStringByRegex(String string) { } private static int stringMatcherToInt(Matcher matcher, int groupIndex) { - try { - return Integer.parseInt(matcher.group(groupIndex)); - } catch (NumberFormatException e) { - throw new CoordinateException(ErrorMessage.numberFormatFailed); - } + return Integer.parseInt(matcher.group(groupIndex)); } } diff --git a/src/test/java/coordinate/utils/StringUtilsTest.java b/src/test/java/coordinate/utils/StringUtilsTest.java new file mode 100644 index 0000000..114dbe9 --- /dev/null +++ b/src/test/java/coordinate/utils/StringUtilsTest.java @@ -0,0 +1,55 @@ +package coordinate.utils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import coordinate.exception.CoordinateException; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class StringUtilsTest { + + @Test + @DisplayName("문자열을 '-'을 기준으로 분리한다") + void testSplitByHyphen() { + // Given + String string = "10-11"; + + // When + List strings = StringUtils.splitByHyphen(string); + + // Then + assertThat(strings).contains("10", "11"); + assertThat(strings.size()).isEqualTo(2); + } + + @Test + @DisplayName("'-'이 포함 되지 않은 문자열을 분리 시킬 때 예외를 반환한다") + void testSplitToNotContainsHyphenString() { + // Given + String string = "10, 11"; + + assertThatThrownBy(() -> { + // When + StringUtils.splitByHyphen(string); + }) + // Then + .hasMessage("두 점의 좌표를 구분을 위해 '-' 필수로 입력 해야 합니다.") + .isInstanceOf(CoordinateException.class); + } + + @Test + @DisplayName("좌표 형식에 맞는 문자열을 추출 하여 숫자로 변환한다") + void testExtractFromCoordinateString() { + // Given + String coordinateString = "(10,11)"; + + // When + List integers = StringUtils.extractFromStringToIntegerByRegex(coordinateString); + + // Then + assertThat(integers).contains(10, 11); + assertThat(integers.size()).isEqualTo(2); + } +} From f15728820ef0b8ae6a09c7004bbe38652b625bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:46:01 +0900 Subject: [PATCH 20/25] update: delete the constant message --- src/main/java/coordinate/messages/SystemMessage.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/coordinate/messages/SystemMessage.java b/src/main/java/coordinate/messages/SystemMessage.java index 7e3af80..8e8137c 100644 --- a/src/main/java/coordinate/messages/SystemMessage.java +++ b/src/main/java/coordinate/messages/SystemMessage.java @@ -3,6 +3,4 @@ public class SystemMessage { public static final String inputFigureSize = "좌표를 입력하세요."; - public static final String distancePoints = "두 점 사이의 거리는: "; - } From 3976ae02fbc8e4e18c846c19e8c69c9bc473dded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:46:16 +0900 Subject: [PATCH 21/25] update: factory return type --- src/main/java/coordinate/MainApplication.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/coordinate/MainApplication.java b/src/main/java/coordinate/MainApplication.java index 978994f..c845519 100644 --- a/src/main/java/coordinate/MainApplication.java +++ b/src/main/java/coordinate/MainApplication.java @@ -1,11 +1,15 @@ package coordinate; +import coordinate.figure.Figure; +import coordinate.figure.FigureFactory; +import coordinate.figure.FigureSize; import coordinate.graph.Graph; import coordinate.io.ConsoleInputHandler; import coordinate.io.ConsoleOutputHandler; -import coordinate.plot.LinePlot; public class MainApplication { + private static final ConsoleInputHandler inputHandler = new ConsoleInputHandler(); + private static final ConsoleOutputHandler outputHandler = new ConsoleOutputHandler(); public static void main(String[] args) { FigureSize figureSize = inputHandler.getFigureSize(); @@ -13,4 +17,4 @@ public static void main(String[] args) { Graph graph = Graph.from(figure); outputHandler.printGraph(graph); } -} +} \ No newline at end of file From 3ebbdf5b5567fc3b278897e9da79826e1d1ab807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:14:05 +0900 Subject: [PATCH 22/25] update: change factory method name --- src/main/java/coordinate/figure/FigureFactory.java | 2 +- src/main/java/coordinate/figure/FigureType.java | 2 +- src/test/java/coordinate/figure/FigureTypeTest.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/coordinate/figure/FigureFactory.java b/src/main/java/coordinate/figure/FigureFactory.java index ac49eac..e6c1e6f 100644 --- a/src/main/java/coordinate/figure/FigureFactory.java +++ b/src/main/java/coordinate/figure/FigureFactory.java @@ -3,6 +3,6 @@ public class FigureFactory { public static Figure create(FigureSize figureSize) { - return FigureType.get(figureSize); + return FigureType.create(figureSize); } } diff --git a/src/main/java/coordinate/figure/FigureType.java b/src/main/java/coordinate/figure/FigureType.java index 2f5765b..923d750 100644 --- a/src/main/java/coordinate/figure/FigureType.java +++ b/src/main/java/coordinate/figure/FigureType.java @@ -27,7 +27,7 @@ public Figure createFigure(Points points) { public abstract Figure createFigure(Points points); - public static Figure get(FigureSize figureSize) { + public static Figure create(FigureSize figureSize) { Points points = figureSize.toPoints(); return Arrays.stream(values()) diff --git a/src/test/java/coordinate/figure/FigureTypeTest.java b/src/test/java/coordinate/figure/FigureTypeTest.java index 2db399c..ccebb28 100644 --- a/src/test/java/coordinate/figure/FigureTypeTest.java +++ b/src/test/java/coordinate/figure/FigureTypeTest.java @@ -18,7 +18,7 @@ void testLineFigureType() { FigureSize figureSize = FigureSize.from("(10,10)-(14,15)"); // When - Figure line = FigureType.get(figureSize); + Figure line = FigureType.create(figureSize); // Then assertThat(line).isInstanceOf(Line.class); @@ -31,7 +31,7 @@ void testRectangleFigureType() { FigureSize figureSize = FigureSize.from("(10,10)-(22,10)-(22,18)-(10,18)"); // When - Figure rectangle = FigureType.get(figureSize); + Figure rectangle = FigureType.create(figureSize); // Then assertThat(rectangle).isInstanceOf(Rectangle.class); @@ -46,7 +46,7 @@ void testInvalidCoordinateSizes(String testFigureSize) { assertThatThrownBy(() -> { // When - FigureType.get(figureSize); + FigureType.create(figureSize); }) // Then .hasMessage("해당 좌표로 도형을 생성 할 수 없습니다.") From 5db2e6af1f8984e4661723f73ae1f10b39be83e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:14:58 +0900 Subject: [PATCH 23/25] feat: triangle type --- .../java/coordinate/figure/FigureType.java | 6 ++ src/main/java/coordinate/figure/Triangle.java | 78 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/main/java/coordinate/figure/Triangle.java diff --git a/src/main/java/coordinate/figure/FigureType.java b/src/main/java/coordinate/figure/FigureType.java index 923d750..4b0d005 100644 --- a/src/main/java/coordinate/figure/FigureType.java +++ b/src/main/java/coordinate/figure/FigureType.java @@ -17,6 +17,12 @@ public Figure createFigure(Points points) { public Figure createFigure(Points points) { return Rectangle.from(points); } + }, + TRIANGLE(3) { + @Override + public Figure createFigure(Points points) { + return Triangle.from(points); + } }; private final int pointsSize; diff --git a/src/main/java/coordinate/figure/Triangle.java b/src/main/java/coordinate/figure/Triangle.java new file mode 100644 index 0000000..b04fa26 --- /dev/null +++ b/src/main/java/coordinate/figure/Triangle.java @@ -0,0 +1,78 @@ +package coordinate.figure; + +import coordinate.point.Point; +import coordinate.point.Points; +import java.util.ArrayList; +import java.util.List; + +public class Triangle implements Figure{ + + private final Points points; + + private Triangle(Points points) { + this.points = points; + } + + public static Triangle from(Points points) { + return new Triangle(points); + } + + @Override + public boolean isMark(int x, int y) { + return points.isMarkedAt(x, y); + } + + @Override + public String toString() { + return "삼각형의 넓이는: " + (double) Math.round(calculate()); + } + + @Override + public double calculate() { + List distances = getDistances(); + double half = getHalf(distances); + return getTriangleWidthByDistances(distances, half); + } + + private List getDistances() { + List pointsArray = points.getPoints(); + List distances = new ArrayList<>(); + + for (int i = 0; i < points.size(); i++) { + int nextIndex = getPointNextIndex(i); + distances.add(getPointsBetweenDistance(pointsArray.get(i), pointsArray.get(nextIndex))); + } + + return distances; + } + + private int getPointNextIndex(int index) { + int pointSize = points.size(); + + if (index == pointSize-1) { + return 0; + } + + return index + 1; + } + + private double getPointsBetweenDistance(Point point1, Point point2) { + Line line = Line.from(Points.from(List.of(point1, point2))); + return line.calculate(); + } + + private double getHalf(List distances) { + return distances.stream().mapToDouble(Double::doubleValue).sum() / 2; + } + + private double getTriangleWidthByDistances(List distances, double half) { + double width = 1; + for (double distance : distances) { + width *= (half - distance); + } + width *= half; + + return Math.sqrt(width); + } + +} From 70a11645a89dfe8db733ab75cddcb55fbee44cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:15:38 +0900 Subject: [PATCH 24/25] fix: instance variable to private --- src/main/java/coordinate/figure/Rectangle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/coordinate/figure/Rectangle.java b/src/main/java/coordinate/figure/Rectangle.java index b58fe4a..40bc276 100644 --- a/src/main/java/coordinate/figure/Rectangle.java +++ b/src/main/java/coordinate/figure/Rectangle.java @@ -6,7 +6,7 @@ public class Rectangle implements Figure { - Points points; + private final Points points; private Rectangle(Points points) { this.points = points; From d14e423cd288e38013edb7b8b034ecfa29953320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=99=98?= <118493627+LeeJuHwan@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:00:15 +0900 Subject: [PATCH 25/25] feat: triangle type figure --- src/main/java/coordinate/figure/Triangle.java | 2 +- .../java/coordinate/figure/TriangleTest.java | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/test/java/coordinate/figure/TriangleTest.java diff --git a/src/main/java/coordinate/figure/Triangle.java b/src/main/java/coordinate/figure/Triangle.java index b04fa26..6f8bfd0 100644 --- a/src/main/java/coordinate/figure/Triangle.java +++ b/src/main/java/coordinate/figure/Triangle.java @@ -24,7 +24,7 @@ public boolean isMark(int x, int y) { @Override public String toString() { - return "삼각형의 넓이는: " + (double) Math.round(calculate()); + return "삼각형의 넓이는 " + (double) Math.round(calculate()); } @Override diff --git a/src/test/java/coordinate/figure/TriangleTest.java b/src/test/java/coordinate/figure/TriangleTest.java new file mode 100644 index 0000000..1d2e18a --- /dev/null +++ b/src/test/java/coordinate/figure/TriangleTest.java @@ -0,0 +1,49 @@ +package coordinate.figure; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.offset; + +import coordinate.point.Point; +import coordinate.point.Points; +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class TriangleTest { + + private static Points points; + + @BeforeAll + static void setUp() { + points = Points.from(List.of(Point.of(10, 10), Point.of(14, 15), Point.of(20, 8))); + } + + @Test + @DisplayName("삼각형의 면적을 계산하는 반환 값을 검증한다") + void testTriangleCalculate() { + // Given + Triangle rectangle = Triangle.from(points); + + // When + double result = rectangle.calculate(); + + // Then + assertThat(result).isEqualTo(29.0, offset(0.00099)); + } + + @Test + @DisplayName("Rectangle 객체를 문자열로 변환 할 시 사각형의 넓이를 반환한다") + void testTriangleToString() { + + // Given + Triangle rectangle = Triangle.from(points); + + // When + String string = rectangle.toString(); + + // Then + assertThat(string).isEqualTo("삼각형의 넓이는 " + 29.0); + } + +}