From 65bb8891cb8dc52a5b843208b60f982793811777 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 13:39:43 +0900 Subject: [PATCH 01/15] =?UTF-8?q?docs=20:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..181426ad5 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,11 @@ +# 지하철 노선도 경로 조회 + +## 기능 요구사항 + +- 경로 조회 기능을 제공한다. + - 경로 조회 기준은 최단 거리 / 최소 시간 의 두 가지 기준을 사용한다. + - 경로 조회 기준을 선택한다. + - 잘못된 메뉴 입력시 예외 발생 + - 1, 2를 제외한 모든 입력에서 예외 발생 + - 출발열과 도착역을 입력하면 경로 조회 기준에 따라 조회 결과를 출력한다. + - [EXCEPTION] 출발 역과 도착 역이 같으면 예외 발생 \ No newline at end of file From ac926ef095cbf37fd7c2a8bdd1d95910c87bdaa5 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 13:52:12 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat=20:=20View=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/Application.java | 1 + src/main/java/subway/view/View.java | 41 +++++++++++++++++++++++ src/main/java/subway/view/io/Printer.java | 8 +++++ src/main/java/subway/view/io/Reader.java | 14 ++++++++ 4 files changed, 64 insertions(+) create mode 100644 src/main/java/subway/view/View.java create mode 100644 src/main/java/subway/view/io/Printer.java create mode 100644 src/main/java/subway/view/io/Reader.java diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index 0bcf786cc..222401b12 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -3,6 +3,7 @@ import java.util.Scanner; public class Application { + public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); // TODO: 프로그램 구현 diff --git a/src/main/java/subway/view/View.java b/src/main/java/subway/view/View.java new file mode 100644 index 000000000..397e0bfd8 --- /dev/null +++ b/src/main/java/subway/view/View.java @@ -0,0 +1,41 @@ +package subway.view; + +import java.util.Scanner; +import subway.view.io.Printer; +import subway.view.io.Reader; + +public class View { + + //todo 각 입력에 대해 실행할 메서드를 enum이 가지게 하면? + private final Reader reader; + private final Printer printer = new Printer(); + + public View(Scanner scanner) { + reader = new Reader(scanner); + } + + public String mainMenuView() { + printer.printMessage("## 메인 화면"); + printer.printMessage("1. 경로 조회"); + printer.printMessage("Q. 종료"); + printer.printMessage(""); + printInputMenu(); + + return reader.getString(); + } + + private void printInputMenu(){ + printer.printMessage("## 원하는 기능을 선택하세요."); + + } + + public void printInfo(String infoMessage) { + //todo 상수 추출 + printer.printMessage("[INFO] " + infoMessage); + } + + public void printException(String exceptionMessage) { + //todo 상수 추출 + printer.printMessage("[ERROR] " + exceptionMessage); + } +} diff --git a/src/main/java/subway/view/io/Printer.java b/src/main/java/subway/view/io/Printer.java new file mode 100644 index 000000000..f1bd85f96 --- /dev/null +++ b/src/main/java/subway/view/io/Printer.java @@ -0,0 +1,8 @@ +package subway.view.io; + +public class Printer { + public void printMessage(String message) { + System.out.println(message); + } + +} diff --git a/src/main/java/subway/view/io/Reader.java b/src/main/java/subway/view/io/Reader.java new file mode 100644 index 000000000..ada45a3ed --- /dev/null +++ b/src/main/java/subway/view/io/Reader.java @@ -0,0 +1,14 @@ +package subway.view.io; + +import java.util.Scanner; + +public class Reader { + private final Scanner scanner; + public Reader(Scanner scanner){ + this.scanner = scanner; + } + + public String getString(){ + return scanner.nextLine(); + } +} From 2756ebdd4829b96fc1a18ef6d0fd779adb9a4c9a Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 14:03:53 +0900 Subject: [PATCH 03/15] =?UTF-8?q?feat=20:=20Button=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=B0=8F=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/subway/controller/button/Button.java | 6 ++++++ .../controller/button/FindPathButton.java | 18 ++++++++++++++++++ .../subway/controller/button/MainButton.java | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 src/main/java/subway/controller/button/Button.java create mode 100644 src/main/java/subway/controller/button/FindPathButton.java create mode 100644 src/main/java/subway/controller/button/MainButton.java diff --git a/src/main/java/subway/controller/button/Button.java b/src/main/java/subway/controller/button/Button.java new file mode 100644 index 000000000..8604bf525 --- /dev/null +++ b/src/main/java/subway/controller/button/Button.java @@ -0,0 +1,6 @@ +package subway.controller.button; + +public interface Button { + Button getButtonByInput(); + void execute(); +} diff --git a/src/main/java/subway/controller/button/FindPathButton.java b/src/main/java/subway/controller/button/FindPathButton.java new file mode 100644 index 000000000..b7870740f --- /dev/null +++ b/src/main/java/subway/controller/button/FindPathButton.java @@ -0,0 +1,18 @@ +package subway.controller.button; + +public enum FindPathButton { + SHORTEST_DISTANCE("1", "최단 거리", null), + SHORTEST_TIME("2", "최소 시간", null), + BACK("B", "돌아가기", null), + ; + + private final String input; + private final String description; + private final Runnable method; + + FindPathButton(String input, String description, Runnable method) { + this.input = input; + this.description = description; + this.method = method; + } +} diff --git a/src/main/java/subway/controller/button/MainButton.java b/src/main/java/subway/controller/button/MainButton.java new file mode 100644 index 000000000..62e95bc22 --- /dev/null +++ b/src/main/java/subway/controller/button/MainButton.java @@ -0,0 +1,18 @@ +package subway.controller.button; + +public enum MainButton { + + FIND_PATH("1", "경로 조회", null), + EXIT("Q", "종료", null), + ; + + private final String input; + private final String description; + private final Runnable method; + + MainButton(String input, String description, Runnable method) { + this.input = input; + this.description = description; + this.method = method; + } +} From 78adbeff46a66779a1d3efa4853cdc9daae0c385 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 14:44:41 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat=20:=20=EA=B2=BD=EB=A1=9C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A0=80=EC=9E=A5=ED=95=A0=20`UnitPath`?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/domain/UnitPath.java | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/subway/domain/UnitPath.java diff --git a/src/main/java/subway/domain/UnitPath.java b/src/main/java/subway/domain/UnitPath.java new file mode 100644 index 000000000..6689a0b6b --- /dev/null +++ b/src/main/java/subway/domain/UnitPath.java @@ -0,0 +1,29 @@ +package subway.domain; + +import java.util.HashSet; +import java.util.Set; + +public class UnitPath { + private final Set stations; + + //todo 아래 두 값 래핑 + private final int time; + private final int distance; + + public UnitPath(Station source, Station target, int time, int distance) { + this.stations = new HashSet<>(); + stations.add(source); + stations.add(target); + this.time = time; + this.distance = distance; + } + + public boolean isPathOf(Station source, Station target) { + if(source == target){ + //todo + throw new IllegalArgumentException("출발 끝 같음"); + } + + return this.stations.contains(source) && this.stations.contains(target); + } +} From 8841edc9496152732fed89ee6baecd3b39dc4272 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 14:49:45 +0900 Subject: [PATCH 05/15] =?UTF-8?q?feat=20:=20`Line`=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EC=97=90=20`Path`=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/domain/Line.java | 14 ++++++++++++++ src/main/java/subway/domain/LineRepository.java | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java index f4d738d5a..f732034b2 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -1,7 +1,12 @@ package subway.domain; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + public class Line { private String name; + private final Set paths = new HashSet<>(); public Line(String name) { this.name = name; @@ -12,4 +17,13 @@ public String getName() { } // 추가 기능 구현 + public void addPath(UnitPath path){ + paths.add(path); + } + + public Optional getPathOf(Station start, Station end) { + return paths.stream() + .filter(path -> path.isPathOf(start, end)) + .findFirst(); + } } diff --git a/src/main/java/subway/domain/LineRepository.java b/src/main/java/subway/domain/LineRepository.java index 2c4a723c9..a1f6ebc3b 100644 --- a/src/main/java/subway/domain/LineRepository.java +++ b/src/main/java/subway/domain/LineRepository.java @@ -5,6 +5,10 @@ import java.util.List; import java.util.Objects; +/* + * Repository 는 어떻게 사용해야 하나 + * 필요한 정보 : 각 역 사이의 거리/시간 정보 + */ public class LineRepository { private static final List lines = new ArrayList<>(); From 4ef33b22f58a0d32d2307b447b68c23d1d43a08c Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 15:09:46 +0900 Subject: [PATCH 06/15] =?UTF-8?q?refactor=20:=20`UnitPath`=EA=B0=80=20`Set?= =?UTF-8?q?`=20=EB=8C=80=EC=8B=A0=20`Station`=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=EB=A5=BC=20=EB=91=90=20=EA=B0=9C=20=EA=B0=80=EC=A7=80=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/domain/Line.java | 6 ++++ src/main/java/subway/domain/UnitPath.java | 38 ++++++++++++++++------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java index f732034b2..ddb708bf9 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -1,6 +1,8 @@ package subway.domain; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Optional; import java.util.Set; @@ -26,4 +28,8 @@ public Optional getPathOf(Station start, Station end) { .filter(path -> path.isPathOf(start, end)) .findFirst(); } + + public Set getPaths() { + return Collections.unmodifiableSet(paths); + } } diff --git a/src/main/java/subway/domain/UnitPath.java b/src/main/java/subway/domain/UnitPath.java index 6689a0b6b..6a3ea3678 100644 --- a/src/main/java/subway/domain/UnitPath.java +++ b/src/main/java/subway/domain/UnitPath.java @@ -1,29 +1,45 @@ package subway.domain; -import java.util.HashSet; import java.util.Set; public class UnitPath { - private final Set stations; + private final Station start; + private final Station end; //todo 아래 두 값 래핑 private final int time; private final int distance; - public UnitPath(Station source, Station target, int time, int distance) { - this.stations = new HashSet<>(); - stations.add(source); - stations.add(target); + public UnitPath(Station start, Station end, int time, int distance) { + this.start = start; + this.end = end; this.time = time; this.distance = distance; } - public boolean isPathOf(Station source, Station target) { - if(source == target){ - //todo - throw new IllegalArgumentException("출발 끝 같음"); + public boolean isPathOf(Station start, Station end) { + if (this.start.equals(start) && this.end.equals(end)) { + return true; } + if (this.start.equals(end) && this.end.equals(start)) { + return true; + } + return false; + } + + public Station getEnd() { + return end; + } + + public Station getStart() { + return start; + } + + public int getDistance() { + return distance; + } - return this.stations.contains(source) && this.stations.contains(target); + public int getTime() { + return time; } } From 21f1db3c4ad02cead9c3cde4ebebf41170518e95 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 15:10:39 +0900 Subject: [PATCH 07/15] =?UTF-8?q?feat=20:=20=EA=B0=81=20=EA=B0=80=EC=A4=91?= =?UTF-8?q?=EC=B9=98=EB=A5=BC=20=EA=B8=B0=EC=A4=80=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=B5=9C=EB=8B=A8=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EA=B5=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20`StationPathFinder`=EC=9D=98=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/pathFinder/DistancePathFinder.java | 15 ++++++++ .../domain/pathFinder/StationPathFinder.java | 36 +++++++++++++++++++ .../domain/pathFinder/TimePathFinder.java | 15 ++++++++ 3 files changed, 66 insertions(+) create mode 100644 src/main/java/subway/domain/pathFinder/DistancePathFinder.java create mode 100644 src/main/java/subway/domain/pathFinder/StationPathFinder.java create mode 100644 src/main/java/subway/domain/pathFinder/TimePathFinder.java diff --git a/src/main/java/subway/domain/pathFinder/DistancePathFinder.java b/src/main/java/subway/domain/pathFinder/DistancePathFinder.java new file mode 100644 index 000000000..4b721b87c --- /dev/null +++ b/src/main/java/subway/domain/pathFinder/DistancePathFinder.java @@ -0,0 +1,15 @@ +package subway.domain.pathFinder; + +import subway.domain.LineRepository; +import subway.domain.UnitPath; + +public class DistancePathFinder extends StationPathFinder{ + public DistancePathFinder(LineRepository lineRepository) { + super(lineRepository); + } + + @Override + protected int getCost(UnitPath path) { + return path.getDistance(); + } +} diff --git a/src/main/java/subway/domain/pathFinder/StationPathFinder.java b/src/main/java/subway/domain/pathFinder/StationPathFinder.java new file mode 100644 index 000000000..6c558717c --- /dev/null +++ b/src/main/java/subway/domain/pathFinder/StationPathFinder.java @@ -0,0 +1,36 @@ +package subway.domain.pathFinder; + +import java.util.Set; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.shortestpath.DijkstraShortestPath; +import org.jgrapht.graph.WeightedMultigraph; +import subway.domain.Line; +import subway.domain.LineRepository; +import subway.domain.Station; +import subway.domain.UnitPath; + +public abstract class StationPathFinder { + + private final DijkstraShortestPath dijkstraShortestPath; + public StationPathFinder(LineRepository lineRepository){ + WeightedMultigraph graph = new WeightedMultigraph<>(Integer.class); + lineRepository.lines().stream() + .map(Line::getPaths) + .flatMap(Set::stream) + .forEach(path -> addPathToGraph(graph, path)); + + this.dijkstraShortestPath = new DijkstraShortestPath<>(graph); + } + + public GraphPath findPath(Station start, Station end){ + return dijkstraShortestPath.getPath(start, end); + } + + private void addPathToGraph(WeightedMultigraph graph, UnitPath path) { + graph.addVertex(path.getStart()); + graph.addVertex(path.getEnd()); + graph.addEdge(path.getStart(), path.getEnd(), getCost(path)); + } + + abstract protected int getCost(UnitPath path); +} diff --git a/src/main/java/subway/domain/pathFinder/TimePathFinder.java b/src/main/java/subway/domain/pathFinder/TimePathFinder.java new file mode 100644 index 000000000..810dff424 --- /dev/null +++ b/src/main/java/subway/domain/pathFinder/TimePathFinder.java @@ -0,0 +1,15 @@ +package subway.domain.pathFinder; + +import subway.domain.LineRepository; +import subway.domain.UnitPath; + +public class TimePathFinder extends StationPathFinder{ + public TimePathFinder(LineRepository lineRepository) { + super(lineRepository); + } + + @Override + protected int getCost(UnitPath path) { + return path.getTime(); + } +} From bf65abea0a996e41c0ce75c0d354842cecd90a1e Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 15:41:34 +0900 Subject: [PATCH 08/15] =?UTF-8?q?feat=20:=20Repository=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/Application.java | 3 + src/main/java/subway/domain/Station.java | 22 ++++++++ .../domain/pathFinder/DistancePathFinder.java | 2 +- .../domain/pathFinder/StationPathFinder.java | 2 +- .../domain/pathFinder/TimePathFinder.java | 2 +- .../{ => repository}/LineRepository.java | 3 +- .../domain/repository/RepositoryConfig.java | 55 +++++++++++++++++++ .../{ => repository}/StationRepository.java | 17 +++++- 8 files changed, 101 insertions(+), 5 deletions(-) rename src/main/java/subway/domain/{ => repository}/LineRepository.java (92%) create mode 100644 src/main/java/subway/domain/repository/RepositoryConfig.java rename src/main/java/subway/domain/{ => repository}/StationRepository.java (55%) diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index 222401b12..ca74d11cf 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -1,11 +1,14 @@ package subway; import java.util.Scanner; +import subway.domain.repository.RepositoryConfig; public class Application { public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); + RepositoryConfig.initRepository(); + // TODO: 프로그램 구현 } } diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/Station.java index bdb142590..dd40e8a37 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/Station.java @@ -1,5 +1,7 @@ package subway.domain; +import java.util.Objects; + public class Station { private String name; @@ -12,4 +14,24 @@ public String getName() { } // 추가 기능 구현 + public boolean isName(String name) { + return this.name.equals(name); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Station station = (Station) o; + return Objects.equals(name, station.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } } diff --git a/src/main/java/subway/domain/pathFinder/DistancePathFinder.java b/src/main/java/subway/domain/pathFinder/DistancePathFinder.java index 4b721b87c..d3aa72cee 100644 --- a/src/main/java/subway/domain/pathFinder/DistancePathFinder.java +++ b/src/main/java/subway/domain/pathFinder/DistancePathFinder.java @@ -1,6 +1,6 @@ package subway.domain.pathFinder; -import subway.domain.LineRepository; +import subway.domain.repository.LineRepository; import subway.domain.UnitPath; public class DistancePathFinder extends StationPathFinder{ diff --git a/src/main/java/subway/domain/pathFinder/StationPathFinder.java b/src/main/java/subway/domain/pathFinder/StationPathFinder.java index 6c558717c..33963b4cf 100644 --- a/src/main/java/subway/domain/pathFinder/StationPathFinder.java +++ b/src/main/java/subway/domain/pathFinder/StationPathFinder.java @@ -5,7 +5,7 @@ import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.graph.WeightedMultigraph; import subway.domain.Line; -import subway.domain.LineRepository; +import subway.domain.repository.LineRepository; import subway.domain.Station; import subway.domain.UnitPath; diff --git a/src/main/java/subway/domain/pathFinder/TimePathFinder.java b/src/main/java/subway/domain/pathFinder/TimePathFinder.java index 810dff424..d1ec7f393 100644 --- a/src/main/java/subway/domain/pathFinder/TimePathFinder.java +++ b/src/main/java/subway/domain/pathFinder/TimePathFinder.java @@ -1,6 +1,6 @@ package subway.domain.pathFinder; -import subway.domain.LineRepository; +import subway.domain.repository.LineRepository; import subway.domain.UnitPath; public class TimePathFinder extends StationPathFinder{ diff --git a/src/main/java/subway/domain/LineRepository.java b/src/main/java/subway/domain/repository/LineRepository.java similarity index 92% rename from src/main/java/subway/domain/LineRepository.java rename to src/main/java/subway/domain/repository/LineRepository.java index a1f6ebc3b..b0b9884b7 100644 --- a/src/main/java/subway/domain/LineRepository.java +++ b/src/main/java/subway/domain/repository/LineRepository.java @@ -1,9 +1,10 @@ -package subway.domain; +package subway.domain.repository; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import subway.domain.Line; /* * Repository 는 어떻게 사용해야 하나 diff --git a/src/main/java/subway/domain/repository/RepositoryConfig.java b/src/main/java/subway/domain/repository/RepositoryConfig.java new file mode 100644 index 000000000..a5d7c6b31 --- /dev/null +++ b/src/main/java/subway/domain/repository/RepositoryConfig.java @@ -0,0 +1,55 @@ +package subway.domain.repository; + +import subway.domain.Line; +import subway.domain.Station; +import subway.domain.UnitPath; + +public class RepositoryConfig { + + public static void initRepository(){ + initStationRepository(); + initLineRepository(); + } + + private static void initStationRepository(){ + //todo enum 추출 가능할 듯 - 근데 class로 이미 있어서 의미 있나 + addStationToRepository(new Station("교대역")); + addStationToRepository(new Station("강남역")); + addStationToRepository(new Station("역삼역")); + addStationToRepository(new Station("남부터미널역")); + addStationToRepository(new Station("양재역")); + addStationToRepository(new Station("매봉역")); + addStationToRepository(new Station("양재시민의숲")); + } + + public static void addStationToRepository(Station station){ + if(StationRepository.contains(station)){ + return; + } + StationRepository.addStation(station); + } + + private static void initLineRepository() { + Line line2 = new Line("2호선"); + line2.addPath(makePath("교대역", "강남역", 2, 3)); + line2.addPath(makePath("강남역", "역삼역", 2, 3)); + LineRepository.addLine(line2); + + Line line3 = new Line("3호선"); + line3.addPath(makePath("교대역", "남부터미널역", 3, 2)); + line3.addPath(makePath("남부터미널역", "양재역", 6, 5)); + line3.addPath(makePath("양재역", "매봉역", 1, 1)); + LineRepository.addLine(line3); + + Line shinbundang = new Line("신분당선"); + shinbundang.addPath(makePath("강남역", "양재역", 2, 8)); + shinbundang.addPath(makePath("양재역", "양재시민의숲", 10, 3)); + LineRepository.addLine(shinbundang); + } + + public static UnitPath makePath(String startName, String endName, int distance, int time) { + Station start = StationRepository.getStationByName(startName); + Station end = StationRepository.getStationByName(endName); + return new UnitPath(start, end, time, distance); + } +} diff --git a/src/main/java/subway/domain/StationRepository.java b/src/main/java/subway/domain/repository/StationRepository.java similarity index 55% rename from src/main/java/subway/domain/StationRepository.java rename to src/main/java/subway/domain/repository/StationRepository.java index 8ed9d103f..3e631c5c9 100644 --- a/src/main/java/subway/domain/StationRepository.java +++ b/src/main/java/subway/domain/repository/StationRepository.java @@ -1,9 +1,10 @@ -package subway.domain; +package subway.domain.repository; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import subway.domain.Station; public class StationRepository { private static final List stations = new ArrayList<>(); @@ -23,4 +24,18 @@ public static boolean deleteStation(String name) { public static void deleteAll() { stations.clear(); } + + // + public static boolean contains(Station input) { + return stations.stream() + .anyMatch(station -> station.equals(input)); + } + + public static Station getStationByName(String name){ + return stations.stream() + .filter(station -> station.isName(name)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + //todo 예외 메시지 + } } From 03cf1f1fa745c88a2b492447be240936f8180cff Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 15:43:20 +0900 Subject: [PATCH 09/15] =?UTF-8?q?feat=20:=20PathFinder=EA=B0=80=20Reposito?= =?UTF-8?q?ry=EC=9D=98=20static=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/subway/domain/pathFinder/DistancePathFinder.java | 4 ++-- src/main/java/subway/domain/pathFinder/StationPathFinder.java | 4 ++-- src/main/java/subway/domain/pathFinder/TimePathFinder.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/subway/domain/pathFinder/DistancePathFinder.java b/src/main/java/subway/domain/pathFinder/DistancePathFinder.java index d3aa72cee..9e8de580e 100644 --- a/src/main/java/subway/domain/pathFinder/DistancePathFinder.java +++ b/src/main/java/subway/domain/pathFinder/DistancePathFinder.java @@ -4,8 +4,8 @@ import subway.domain.UnitPath; public class DistancePathFinder extends StationPathFinder{ - public DistancePathFinder(LineRepository lineRepository) { - super(lineRepository); + public DistancePathFinder() { + super(); } @Override diff --git a/src/main/java/subway/domain/pathFinder/StationPathFinder.java b/src/main/java/subway/domain/pathFinder/StationPathFinder.java index 33963b4cf..6799d7bd9 100644 --- a/src/main/java/subway/domain/pathFinder/StationPathFinder.java +++ b/src/main/java/subway/domain/pathFinder/StationPathFinder.java @@ -12,9 +12,9 @@ public abstract class StationPathFinder { private final DijkstraShortestPath dijkstraShortestPath; - public StationPathFinder(LineRepository lineRepository){ + public StationPathFinder(){ WeightedMultigraph graph = new WeightedMultigraph<>(Integer.class); - lineRepository.lines().stream() + LineRepository.lines().stream() .map(Line::getPaths) .flatMap(Set::stream) .forEach(path -> addPathToGraph(graph, path)); diff --git a/src/main/java/subway/domain/pathFinder/TimePathFinder.java b/src/main/java/subway/domain/pathFinder/TimePathFinder.java index d1ec7f393..9130fbd6c 100644 --- a/src/main/java/subway/domain/pathFinder/TimePathFinder.java +++ b/src/main/java/subway/domain/pathFinder/TimePathFinder.java @@ -4,8 +4,8 @@ import subway.domain.UnitPath; public class TimePathFinder extends StationPathFinder{ - public TimePathFinder(LineRepository lineRepository) { - super(lineRepository); + public TimePathFinder() { + super(); } @Override From 47d466d5c4209488eca72a826edfac63d5152190 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 16:26:43 +0900 Subject: [PATCH 10/15] =?UTF-8?q?fix=20:=20PathFinder=EC=9D=98=20Edge=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=9D=84=20DefaultWeightedEdge=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/pathFinder/StationPathFinder.java | 15 ++++--- .../domain/pathFinder/TimePathFinder.java | 1 - src/test/java/subway/JGraphtTest.java | 32 +++++++++++++++ .../domain/pathFinder/TimePathFinderTest.java | 41 +++++++++++++++++++ 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 src/test/java/subway/domain/pathFinder/TimePathFinderTest.java diff --git a/src/main/java/subway/domain/pathFinder/StationPathFinder.java b/src/main/java/subway/domain/pathFinder/StationPathFinder.java index 6799d7bd9..151a3c51c 100644 --- a/src/main/java/subway/domain/pathFinder/StationPathFinder.java +++ b/src/main/java/subway/domain/pathFinder/StationPathFinder.java @@ -3,6 +3,7 @@ import java.util.Set; import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; +import org.jgrapht.graph.DefaultWeightedEdge; import org.jgrapht.graph.WeightedMultigraph; import subway.domain.Line; import subway.domain.repository.LineRepository; @@ -11,9 +12,9 @@ public abstract class StationPathFinder { - private final DijkstraShortestPath dijkstraShortestPath; + private final DijkstraShortestPath dijkstraShortestPath; public StationPathFinder(){ - WeightedMultigraph graph = new WeightedMultigraph<>(Integer.class); + WeightedMultigraph graph = new WeightedMultigraph<>(DefaultWeightedEdge.class); LineRepository.lines().stream() .map(Line::getPaths) .flatMap(Set::stream) @@ -22,14 +23,18 @@ public StationPathFinder(){ this.dijkstraShortestPath = new DijkstraShortestPath<>(graph); } - public GraphPath findPath(Station start, Station end){ + public GraphPath findPath(Station start, Station end){ return dijkstraShortestPath.getPath(start, end); } - private void addPathToGraph(WeightedMultigraph graph, UnitPath path) { + private void addPathToGraph(WeightedMultigraph graph, UnitPath path) { graph.addVertex(path.getStart()); graph.addVertex(path.getEnd()); - graph.addEdge(path.getStart(), path.getEnd(), getCost(path)); + int cost = getCost(path); + + graph.setEdgeWeight(graph.addEdge(path.getStart(), path.getEnd()), cost); + graph.setEdgeWeight(graph.addEdge(path.getEnd(), path.getStart()), cost); + } abstract protected int getCost(UnitPath path); diff --git a/src/main/java/subway/domain/pathFinder/TimePathFinder.java b/src/main/java/subway/domain/pathFinder/TimePathFinder.java index 9130fbd6c..1acbf6e47 100644 --- a/src/main/java/subway/domain/pathFinder/TimePathFinder.java +++ b/src/main/java/subway/domain/pathFinder/TimePathFinder.java @@ -1,6 +1,5 @@ package subway.domain.pathFinder; -import subway.domain.repository.LineRepository; import subway.domain.UnitPath; public class TimePathFinder extends StationPathFinder{ diff --git a/src/test/java/subway/JGraphtTest.java b/src/test/java/subway/JGraphtTest.java index 4f5f76536..8d3d14f4b 100644 --- a/src/test/java/subway/JGraphtTest.java +++ b/src/test/java/subway/JGraphtTest.java @@ -1,5 +1,6 @@ package subway; +import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.graph.DefaultWeightedEdge; import org.jgrapht.graph.WeightedMultigraph; @@ -25,4 +26,35 @@ public void getDijkstraShortestPath() { assertThat(shortestPath.size()).isEqualTo(3); } + + @Test + public void 학습_테스트() { + WeightedMultigraph graph = new WeightedMultigraph(DefaultWeightedEdge.class); + graph.addVertex("v1"); + graph.addVertex("v2"); + graph.addVertex("v3"); + graph.addVertex("v4"); + graph.addVertex("v5"); + graph.setEdgeWeight(graph.addEdge("v1", "v2"), 2); + graph.setEdgeWeight(graph.addEdge("v1", "v3"), 7); + graph.setEdgeWeight(graph.addEdge("v1", "v4"), 8); + graph.setEdgeWeight(graph.addEdge("v1", "v5"), 5); + + graph.setEdgeWeight(graph.addEdge("v2", "v3"), 2); + graph.setEdgeWeight(graph.addEdge("v2", "v4"), 4); + graph.setEdgeWeight(graph.addEdge("v2", "v5"), 8); + + graph.setEdgeWeight(graph.addEdge("v3", "v4"), 11); + graph.setEdgeWeight(graph.addEdge("v3", "v5"), 7); + + graph.setEdgeWeight(graph.addEdge("v4", "v5"), 8); + + DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(graph); + + GraphPath path = dijkstraShortestPath.getPath("v4", "v1"); + List shortestPath = path.getVertexList(); + System.out.println(shortestPath); + + assertThat(shortestPath.size()).isEqualTo(3); + } } diff --git a/src/test/java/subway/domain/pathFinder/TimePathFinderTest.java b/src/test/java/subway/domain/pathFinder/TimePathFinderTest.java new file mode 100644 index 000000000..28c69e903 --- /dev/null +++ b/src/test/java/subway/domain/pathFinder/TimePathFinderTest.java @@ -0,0 +1,41 @@ +package subway.domain.pathFinder; + +import static org.junit.jupiter.api.Assertions.*; + +import org.assertj.core.api.Assertions; +import org.jgrapht.GraphPath; +import org.jgrapht.graph.DefaultWeightedEdge; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import subway.domain.Station; +import subway.domain.repository.RepositoryConfig; +import subway.domain.repository.StationRepository; + +class TimePathFinderTest { + TimePathFinder pathFinder; + + @BeforeEach + void initRepository(){ + RepositoryConfig.initRepository(); + pathFinder = new TimePathFinder(); + } + + @ParameterizedTest + @CsvSource({"교대역,양재역,7,2", + "강남역,매봉역,9,2"}) + void 정상_결과_테스트(String startName, String endName, int time, int length){ + Station start = StationRepository.getStationByName(startName); + Station end = StationRepository.getStationByName(endName); + GraphPath path = pathFinder.findPath(start, end); + System.out.println(path.getVertexList()); + Assertions.assertThat(path.getWeight()) + .isEqualTo(time); + Assertions.assertThat(path.getLength()) + .isEqualTo(length); + } + + /* + */ +} \ No newline at end of file From 1931b3b2eba87713b1f14748a73453fcbcd560d9 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 17:38:45 +0900 Subject: [PATCH 11/15] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/Application.java | 62 ++++++++++++++++++- .../subway/controller/SubwayController.java | 37 +++++++++++ .../subway/controller/button/MainButton.java | 26 ++++---- .../controller/exception/RetryHandler.java | 33 ++++++++++ src/main/java/subway/domain/PathResult.java | 27 ++++++++ src/main/java/subway/domain/Station.java | 7 +++ .../java/subway/domain/SubwayService.java | 30 +++++++++ .../domain/repository/LineRepository.java | 1 + .../domain/repository/PathRepository.java | 40 ++++++++++++ .../domain/repository/RepositoryConfig.java | 9 +++ src/main/java/subway/view/View.java | 35 +++++++---- src/main/java/subway/view/io/Reader.java | 14 ----- 12 files changed, 283 insertions(+), 38 deletions(-) create mode 100644 src/main/java/subway/controller/SubwayController.java create mode 100644 src/main/java/subway/controller/exception/RetryHandler.java create mode 100644 src/main/java/subway/domain/PathResult.java create mode 100644 src/main/java/subway/domain/SubwayService.java create mode 100644 src/main/java/subway/domain/repository/PathRepository.java delete mode 100644 src/main/java/subway/view/io/Reader.java diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index ca74d11cf..a7b105952 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -1,14 +1,74 @@ package subway; import java.util.Scanner; +import subway.controller.exception.RetryHandler; +import subway.domain.PathResult; +import subway.domain.Station; +import subway.domain.SubwayService; import subway.domain.repository.RepositoryConfig; +import subway.domain.repository.StationRepository; +import subway.view.View; public class Application { + private static final View view = new View(); + private static final RetryHandler handler = new RetryHandler(); + private static SubwayService subwayService; public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); RepositoryConfig.initRepository(); + subwayService = new SubwayService(); - // TODO: 프로그램 구현 + handler.runOrRetry(() -> run(scanner)); } + + public static void run(Scanner scanner){ + String input = scanner.nextLine(); + while(true) { + view.printMenuView(); + if (input.equals("Q")) { + return; + } + if (input.equals("1")) { + handler.runOrRetry(() -> _findPath(scanner)); + continue; + } + throw new IllegalArgumentException("잘못된 메뉴 입력입니다."); + } + } + + private static void _findPath(Scanner scanner) { + String input = scanner.nextLine(); + if (input.equals("B")) { + return; + } + if (input.equals("1") || input.equals("2")) { + _findPath(scanner, input); + return; + } + + //todo + throw new IllegalArgumentException("잘못된 메뉴 입력입니다."); + } + + private static void _findPath(Scanner scanner, String input) { + Station start = getStation(scanner); + Station end = getStation(scanner); + + PathResult result = null; + if(input.equals("1")){ + result = subwayService.findShortestPath(start, end); + } + if (input.equals("2")) { + result = subwayService.findFastestPath(start, end); + } + view.printPathResult(result); + } + + private static Station getStation(Scanner scanner) { + String stationName = scanner.nextLine(); + return StationRepository.getStationByName(stationName); + } + + } diff --git a/src/main/java/subway/controller/SubwayController.java b/src/main/java/subway/controller/SubwayController.java new file mode 100644 index 000000000..6db2c51d6 --- /dev/null +++ b/src/main/java/subway/controller/SubwayController.java @@ -0,0 +1,37 @@ +package subway.controller; + +import subway.view.View; + +public class SubwayController { + private final View view; + + public SubwayController(View view) { + this.view = view; + } + //todo Button 사용 가능할지 고민해 보기 + + /* + 경로 기준은 경로 탐색 전략을 결정해 준다. + 이후 시작, 끝 점을 사용해 경로를 탐색한다. + + + 1. 전략 선택 (최단 거리 / 최단 시간) + 2. 시작 / 끝 역 선택 + 3. 경로 구함 + 4. 결과 출력 + - 총 거리 + - 총 시간 + - 경로 내 모든 역 (이건 라이브러리의 반환 결과 사용하면 됨) + + -> 총 거리, 총 시간은 라이브러리 반환 결과의 경로를 이용해 구하는 것이 맞는 것 같음 + -> A-B-C-D 경로일 경우 + 각 `Line`을 순회하면서 `A-B` 경로가 존재하는지 확인 후 거리와 시간을 가져온다. + + 그럼 경로 정보는 `Line`이 가지고 있어야 하겠네 + + StationRepository 는 그냥 입력받은 역들이 존재하는 역인지 판단하는 역할 이상은 못할 것 같음 + + */ + + +} diff --git a/src/main/java/subway/controller/button/MainButton.java b/src/main/java/subway/controller/button/MainButton.java index 62e95bc22..1f06b8050 100644 --- a/src/main/java/subway/controller/button/MainButton.java +++ b/src/main/java/subway/controller/button/MainButton.java @@ -2,17 +2,21 @@ public enum MainButton { - FIND_PATH("1", "경로 조회", null), - EXIT("Q", "종료", null), - ; + FIND_PATH("1", "경로 조회", null), + EXIT("Q", "종료", null), + ; - private final String input; - private final String description; - private final Runnable method; + private final String input; + private final String description; + private final Runnable method; - MainButton(String input, String description, Runnable method) { - this.input = input; - this.description = description; - this.method = method; - } + MainButton(String input, String description, Runnable method) { + this.input = input; + this.description = description; + this.method = method; + } + + /*public static MainButton from(String input){ + + }*/ } diff --git a/src/main/java/subway/controller/exception/RetryHandler.java b/src/main/java/subway/controller/exception/RetryHandler.java new file mode 100644 index 000000000..f376ed590 --- /dev/null +++ b/src/main/java/subway/controller/exception/RetryHandler.java @@ -0,0 +1,33 @@ +package subway.controller.exception; + +import java.util.function.Supplier; +import subway.view.View; + +public class RetryHandler { + private final View view = new View(); + + public T getOrRetry(Supplier supplier){ + while(true){ + try { + return supplier.get(); + } catch (IllegalArgumentException e){ + view.printException(e.getMessage()); + } finally { + view.printLine(); + } + } + } + + public void runOrRetry(Runnable runnable){ + while(true){ + try { + runnable.run(); + return; + } catch (IllegalArgumentException e){ + view.printException(e.getMessage()); + } finally { + view.printLine(); + } + } + } +} diff --git a/src/main/java/subway/domain/PathResult.java b/src/main/java/subway/domain/PathResult.java new file mode 100644 index 000000000..aee02ae9e --- /dev/null +++ b/src/main/java/subway/domain/PathResult.java @@ -0,0 +1,27 @@ +package subway.domain; + +import java.util.List; + +public class PathResult { + private final List stations; + private final int time; + private final int distance; + + public PathResult(List stations, int time, int distance) { + this.stations = stations; + this.time = time; + this.distance = distance; + } + + public List getStations() { + return stations; + } + + public int getTime() { + return time; + } + + public int getDistance() { + return distance; + } +} diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/Station.java index dd40e8a37..698cc3982 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/Station.java @@ -34,4 +34,11 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(name); } + + @Override + public String toString() { + return "Station{" + + "name='" + name + '\'' + + '}'; + } } diff --git a/src/main/java/subway/domain/SubwayService.java b/src/main/java/subway/domain/SubwayService.java new file mode 100644 index 000000000..20b7d968b --- /dev/null +++ b/src/main/java/subway/domain/SubwayService.java @@ -0,0 +1,30 @@ +package subway.domain; + +import org.jgrapht.GraphPath; +import org.jgrapht.graph.DefaultWeightedEdge; +import subway.domain.pathFinder.DistancePathFinder; +import subway.domain.pathFinder.StationPathFinder; +import subway.domain.pathFinder.TimePathFinder; +import subway.domain.repository.PathRepository; + +public class SubwayService { + private static final StationPathFinder timePathFinder = new TimePathFinder(); + private static final StationPathFinder distanceFinder = new DistancePathFinder(); + + + public PathResult findShortestPath(Station start, Station end) { + GraphPath path = findPath(distanceFinder, start, end); + int time = PathRepository.getTotalTime(path.getVertexList()); + return new PathResult(path.getVertexList(), time, (int)path.getWeight()); + } + + public PathResult findFastestPath(Station start, Station end) { + GraphPath path = findPath(timePathFinder, start, end); + int distance = PathRepository.getTotalDistance(path.getVertexList()); + return new PathResult(path.getVertexList(), distance, (int) path.getWeight()); + } + private GraphPath findPath(StationPathFinder pathFinder, Station start, Station end) { + return pathFinder.findPath(start, end); + } + +} diff --git a/src/main/java/subway/domain/repository/LineRepository.java b/src/main/java/subway/domain/repository/LineRepository.java index b0b9884b7..f4dcd24fc 100644 --- a/src/main/java/subway/domain/repository/LineRepository.java +++ b/src/main/java/subway/domain/repository/LineRepository.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Objects; import subway.domain.Line; +import subway.domain.Station; /* * Repository 는 어떻게 사용해야 하나 diff --git a/src/main/java/subway/domain/repository/PathRepository.java b/src/main/java/subway/domain/repository/PathRepository.java new file mode 100644 index 000000000..41da42285 --- /dev/null +++ b/src/main/java/subway/domain/repository/PathRepository.java @@ -0,0 +1,40 @@ +package subway.domain.repository; + +import java.util.HashSet; +import java.util.List; +import subway.domain.Station; +import subway.domain.UnitPath; + +public class PathRepository { + private static HashSet paths; + + public static void addPath(UnitPath path){ + paths.add(path); + } + + public static int getTotalTime(List totalPath){ + int time = 0; + for (int i = 0; i < totalPath.size() - 2; i++) { + int finalI = i; + UnitPath unitPath = paths.stream() + .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1))) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + time += unitPath.getTime(); + } + return time; + } + + public static int getTotalDistance(List totalPath){ + int distance = 0; + for (int i = 0; i < totalPath.size() - 2; i++) { + int finalI = i; + UnitPath unitPath = paths.stream() + .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1))) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + distance += unitPath.getDistance(); + } + return distance; + } +} diff --git a/src/main/java/subway/domain/repository/RepositoryConfig.java b/src/main/java/subway/domain/repository/RepositoryConfig.java index a5d7c6b31..1aa8d64a9 100644 --- a/src/main/java/subway/domain/repository/RepositoryConfig.java +++ b/src/main/java/subway/domain/repository/RepositoryConfig.java @@ -1,5 +1,6 @@ package subway.domain.repository; +import java.util.Set; import subway.domain.Line; import subway.domain.Station; import subway.domain.UnitPath; @@ -52,4 +53,12 @@ public static UnitPath makePath(String startName, String endName, int distance, Station end = StationRepository.getStationByName(endName); return new UnitPath(start, end, time, distance); } + + private static void initPathRepository(){ + LineRepository.lines().stream() + .map(Line::getPaths) + .flatMap(Set::stream) + .forEach(PathRepository::addPath); + + } } diff --git a/src/main/java/subway/view/View.java b/src/main/java/subway/view/View.java index 397e0bfd8..45027f4ed 100644 --- a/src/main/java/subway/view/View.java +++ b/src/main/java/subway/view/View.java @@ -1,30 +1,24 @@ package subway.view; -import java.util.Scanner; +import java.util.List; +import subway.domain.PathResult; +import subway.domain.Station; import subway.view.io.Printer; -import subway.view.io.Reader; public class View { //todo 각 입력에 대해 실행할 메서드를 enum이 가지게 하면? - private final Reader reader; private final Printer printer = new Printer(); - public View(Scanner scanner) { - reader = new Reader(scanner); - } - - public String mainMenuView() { + public void printMenuView() { printer.printMessage("## 메인 화면"); printer.printMessage("1. 경로 조회"); printer.printMessage("Q. 종료"); printer.printMessage(""); - printInputMenu(); - - return reader.getString(); + printChooseMenu(); } - private void printInputMenu(){ + public void printChooseMenu(){ printer.printMessage("## 원하는 기능을 선택하세요."); } @@ -38,4 +32,21 @@ public void printException(String exceptionMessage) { //todo 상수 추출 printer.printMessage("[ERROR] " + exceptionMessage); } + + public void printLine() { + printer.printMessage(""); + } + + public void printPathResult(PathResult result) { + printer.printMessage("## 조회 결과"); + printInfo("---"); + printInfo("총 거리: " + result.getDistance() + "km"); + printInfo("총 소요 시간: " + result.getTime() + "분"); + printInfo("---"); + printStations(result.getStations()); + } + + private void printStations(List stations){ + stations.forEach(station -> printInfo(station.getName())); + } } diff --git a/src/main/java/subway/view/io/Reader.java b/src/main/java/subway/view/io/Reader.java deleted file mode 100644 index ada45a3ed..000000000 --- a/src/main/java/subway/view/io/Reader.java +++ /dev/null @@ -1,14 +0,0 @@ -package subway.view.io; - -import java.util.Scanner; - -public class Reader { - private final Scanner scanner; - public Reader(Scanner scanner){ - this.scanner = scanner; - } - - public String getString(){ - return scanner.nextLine(); - } -} From dbbdd7cf41cf8db21bc09975f4d10592be41d4cd Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 17:56:58 +0900 Subject: [PATCH 12/15] =?UTF-8?q?bug:=20=EC=B4=9D=20=EC=86=8C=EC=9A=94=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84,=20=EC=B4=9D=20=EA=B1=B0=EB=A6=AC=EB=A5=BC?= =?UTF-8?q?=20=EA=B5=AC=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=98=A4=EB=A5=98=20=EB=B0=9C=EA=B2=AC=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/Application.java | 10 +++++---- .../java/subway/controller/button/Button.java | 6 ----- .../controller/button/FindPathButton.java | 18 --------------- .../subway/controller/button/MainButton.java | 22 ------------------- .../java/subway/domain/SubwayService.java | 6 +++-- .../domain/repository/PathRepository.java | 6 ++--- .../domain/repository/StationRepository.java | 3 +-- src/main/java/subway/view/View.java | 19 +++++++++++++++- .../java/subway/domain/SubwayServiceTest.java | 8 +++++++ 9 files changed, 40 insertions(+), 58 deletions(-) delete mode 100644 src/main/java/subway/controller/button/Button.java delete mode 100644 src/main/java/subway/controller/button/FindPathButton.java delete mode 100644 src/main/java/subway/controller/button/MainButton.java create mode 100644 src/test/java/subway/domain/SubwayServiceTest.java diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index a7b105952..de0399db1 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -23,21 +23,22 @@ public static void main(String[] args) { } public static void run(Scanner scanner){ - String input = scanner.nextLine(); while(true) { view.printMenuView(); + String input = scanner.nextLine(); if (input.equals("Q")) { return; } if (input.equals("1")) { - handler.runOrRetry(() -> _findPath(scanner)); + handler.runOrRetry(() -> findPath(scanner)); continue; } throw new IllegalArgumentException("잘못된 메뉴 입력입니다."); } } - private static void _findPath(Scanner scanner) { + private static void findPath(Scanner scanner) { + view.printPathMenu(); String input = scanner.nextLine(); if (input.equals("B")) { return; @@ -52,9 +53,10 @@ private static void _findPath(Scanner scanner) { } private static void _findPath(Scanner scanner, String input) { + view.guideStartStation(); Station start = getStation(scanner); + view.guideEndStation(); Station end = getStation(scanner); - PathResult result = null; if(input.equals("1")){ result = subwayService.findShortestPath(start, end); diff --git a/src/main/java/subway/controller/button/Button.java b/src/main/java/subway/controller/button/Button.java deleted file mode 100644 index 8604bf525..000000000 --- a/src/main/java/subway/controller/button/Button.java +++ /dev/null @@ -1,6 +0,0 @@ -package subway.controller.button; - -public interface Button { - Button getButtonByInput(); - void execute(); -} diff --git a/src/main/java/subway/controller/button/FindPathButton.java b/src/main/java/subway/controller/button/FindPathButton.java deleted file mode 100644 index b7870740f..000000000 --- a/src/main/java/subway/controller/button/FindPathButton.java +++ /dev/null @@ -1,18 +0,0 @@ -package subway.controller.button; - -public enum FindPathButton { - SHORTEST_DISTANCE("1", "최단 거리", null), - SHORTEST_TIME("2", "최소 시간", null), - BACK("B", "돌아가기", null), - ; - - private final String input; - private final String description; - private final Runnable method; - - FindPathButton(String input, String description, Runnable method) { - this.input = input; - this.description = description; - this.method = method; - } -} diff --git a/src/main/java/subway/controller/button/MainButton.java b/src/main/java/subway/controller/button/MainButton.java deleted file mode 100644 index 1f06b8050..000000000 --- a/src/main/java/subway/controller/button/MainButton.java +++ /dev/null @@ -1,22 +0,0 @@ -package subway.controller.button; - -public enum MainButton { - - FIND_PATH("1", "경로 조회", null), - EXIT("Q", "종료", null), - ; - - private final String input; - private final String description; - private final Runnable method; - - MainButton(String input, String description, Runnable method) { - this.input = input; - this.description = description; - this.method = method; - } - - /*public static MainButton from(String input){ - - }*/ -} diff --git a/src/main/java/subway/domain/SubwayService.java b/src/main/java/subway/domain/SubwayService.java index 20b7d968b..414b6a009 100644 --- a/src/main/java/subway/domain/SubwayService.java +++ b/src/main/java/subway/domain/SubwayService.java @@ -11,7 +11,6 @@ public class SubwayService { private static final StationPathFinder timePathFinder = new TimePathFinder(); private static final StationPathFinder distanceFinder = new DistancePathFinder(); - public PathResult findShortestPath(Station start, Station end) { GraphPath path = findPath(distanceFinder, start, end); int time = PathRepository.getTotalTime(path.getVertexList()); @@ -21,9 +20,12 @@ public PathResult findShortestPath(Station start, Station end) { public PathResult findFastestPath(Station start, Station end) { GraphPath path = findPath(timePathFinder, start, end); int distance = PathRepository.getTotalDistance(path.getVertexList()); - return new PathResult(path.getVertexList(), distance, (int) path.getWeight()); + return new PathResult(path.getVertexList(), (int) path.getWeight(), distance); } private GraphPath findPath(StationPathFinder pathFinder, Station start, Station end) { + if(start.equals(end)){ + throw new IllegalArgumentException("출발역과 도착역이 동일합니다."); + } return pathFinder.findPath(start, end); } diff --git a/src/main/java/subway/domain/repository/PathRepository.java b/src/main/java/subway/domain/repository/PathRepository.java index 41da42285..2614c9c26 100644 --- a/src/main/java/subway/domain/repository/PathRepository.java +++ b/src/main/java/subway/domain/repository/PathRepository.java @@ -20,7 +20,7 @@ public static int getTotalTime(List totalPath){ .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1))) .findFirst() .orElseThrow(IllegalArgumentException::new); - time += unitPath.getTime(); + //time += unitPath.getTime(); } return time; } @@ -29,11 +29,11 @@ public static int getTotalDistance(List totalPath){ int distance = 0; for (int i = 0; i < totalPath.size() - 2; i++) { int finalI = i; - UnitPath unitPath = paths.stream() + /*UnitPath unitPath = paths.stream() .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1))) .findFirst() .orElseThrow(IllegalArgumentException::new); - distance += unitPath.getDistance(); + distance += unitPath.getDistance();*/ } return distance; } diff --git a/src/main/java/subway/domain/repository/StationRepository.java b/src/main/java/subway/domain/repository/StationRepository.java index 3e631c5c9..27ce1a86f 100644 --- a/src/main/java/subway/domain/repository/StationRepository.java +++ b/src/main/java/subway/domain/repository/StationRepository.java @@ -35,7 +35,6 @@ public static Station getStationByName(String name){ return stations.stream() .filter(station -> station.isName(name)) .findFirst() - .orElseThrow(IllegalArgumentException::new); - //todo 예외 메시지 + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 역 이름입니다.")); } } diff --git a/src/main/java/subway/view/View.java b/src/main/java/subway/view/View.java index 45027f4ed..2f3ce05c9 100644 --- a/src/main/java/subway/view/View.java +++ b/src/main/java/subway/view/View.java @@ -18,7 +18,16 @@ public void printMenuView() { printChooseMenu(); } - public void printChooseMenu(){ + public void printPathMenu(){ + printer.printMessage("## 경로 기준"); + printer.printMessage("1. 최단 거리"); + printer.printMessage("2. 최소 시간"); + printer.printMessage("B. 돌아가기"); + printer.printMessage(""); + printChooseMenu(); + } + + private void printChooseMenu(){ printer.printMessage("## 원하는 기능을 선택하세요."); } @@ -49,4 +58,12 @@ public void printPathResult(PathResult result) { private void printStations(List stations){ stations.forEach(station -> printInfo(station.getName())); } + + public void guideStartStation() { + printer.printMessage("## 출발역을 입력하세요."); + } + + public void guideEndStation() { + printer.printMessage("## 도착역을 입력하세요."); + } } diff --git a/src/test/java/subway/domain/SubwayServiceTest.java b/src/test/java/subway/domain/SubwayServiceTest.java new file mode 100644 index 000000000..93704285a --- /dev/null +++ b/src/test/java/subway/domain/SubwayServiceTest.java @@ -0,0 +1,8 @@ +package subway.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class SubwayServiceTest { + + +} \ No newline at end of file From cbc0fbab1611ccf8629e8c6dbff67e3f3535a279 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 17:59:24 +0900 Subject: [PATCH 13/15] =?UTF-8?q?fix=20:=20=EC=B4=9D=20=EC=86=8C=EC=9A=94?= =?UTF-8?q?=20=EC=8B=9C=EA=B0=84,=20=EC=B4=9D=20=EA=B1=B0=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=EA=B5=AC=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/subway/domain/repository/PathRepository.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/subway/domain/repository/PathRepository.java b/src/main/java/subway/domain/repository/PathRepository.java index 2614c9c26..feae1981d 100644 --- a/src/main/java/subway/domain/repository/PathRepository.java +++ b/src/main/java/subway/domain/repository/PathRepository.java @@ -6,7 +6,7 @@ import subway.domain.UnitPath; public class PathRepository { - private static HashSet paths; + private static HashSet paths = new HashSet<>(); public static void addPath(UnitPath path){ paths.add(path); @@ -16,11 +16,12 @@ public static int getTotalTime(List totalPath){ int time = 0; for (int i = 0; i < totalPath.size() - 2; i++) { int finalI = i; - UnitPath unitPath = paths.stream() + UnitPath unitPath = + paths.stream() .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1))) .findFirst() .orElseThrow(IllegalArgumentException::new); - //time += unitPath.getTime(); + time += unitPath.getTime(); } return time; } @@ -29,11 +30,11 @@ public static int getTotalDistance(List totalPath){ int distance = 0; for (int i = 0; i < totalPath.size() - 2; i++) { int finalI = i; - /*UnitPath unitPath = paths.stream() + UnitPath unitPath = paths.stream() .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1))) .findFirst() .orElseThrow(IllegalArgumentException::new); - distance += unitPath.getDistance();*/ + distance += unitPath.getDistance(); } return distance; } From ec9805af106d5bedba098561e2a323e54e052a05 Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 18:00:15 +0900 Subject: [PATCH 14/15] =?UTF-8?q?fix=20:=20=EA=B2=BD=EB=A1=9C=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=EC=86=8C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/domain/repository/RepositoryConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/subway/domain/repository/RepositoryConfig.java b/src/main/java/subway/domain/repository/RepositoryConfig.java index 1aa8d64a9..ff54c5a2a 100644 --- a/src/main/java/subway/domain/repository/RepositoryConfig.java +++ b/src/main/java/subway/domain/repository/RepositoryConfig.java @@ -10,6 +10,7 @@ public class RepositoryConfig { public static void initRepository(){ initStationRepository(); initLineRepository(); + initPathRepository(); } private static void initStationRepository(){ From b06a553ec5eacbf05f81bea9cee82ff465f39bde Mon Sep 17 00:00:00 2001 From: zangsu Date: Thu, 30 Nov 2023 21:36:55 +0900 Subject: [PATCH 15/15] =?UTF-8?q?fix=20:=20=EC=B4=9D=20=EA=B1=B0=EB=A6=AC,?= =?UTF-8?q?=20=EC=B4=9D=20=EC=86=8C=EC=9A=94=20=EC=8B=9C=EA=B0=84=EC=9D=B4?= =?UTF-8?q?=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EA=B3=84=EC=82=B0=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/domain/repository/PathRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/subway/domain/repository/PathRepository.java b/src/main/java/subway/domain/repository/PathRepository.java index feae1981d..8e5aa29b4 100644 --- a/src/main/java/subway/domain/repository/PathRepository.java +++ b/src/main/java/subway/domain/repository/PathRepository.java @@ -14,7 +14,7 @@ public static void addPath(UnitPath path){ public static int getTotalTime(List totalPath){ int time = 0; - for (int i = 0; i < totalPath.size() - 2; i++) { + for (int i = 0; i < totalPath.size() - 1; i++) { int finalI = i; UnitPath unitPath = paths.stream() @@ -28,7 +28,7 @@ public static int getTotalTime(List totalPath){ public static int getTotalDistance(List totalPath){ int distance = 0; - for (int i = 0; i < totalPath.size() - 2; i++) { + for (int i = 0; i < totalPath.size() - 1; i++) { int finalI = i; UnitPath unitPath = paths.stream() .filter(path -> path.isPathOf(totalPath.get(finalI), totalPath.get(finalI + 1)))