From c075a15ead583a3b778efa16bca5e174efa9566c Mon Sep 17 00:00:00 2001 From: suhyun Date: Thu, 30 Nov 2023 22:54:27 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=A3=BC=EC=96=B4=EC=A7=84=20?= =?UTF-8?q?=EC=A7=80=ED=95=98=EC=B2=A0=20=EC=A0=95=EB=B3=B4=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 3 + src/main/java/subway/Application.java | 8 ++ .../subway/controller/LineController.java | 15 ++++ .../subway/controller/StationController.java | 15 ++++ .../subway/controller/SubwayController.java | 15 ++++ .../subway/domain/ConnectStationNode.java | 17 +++++ src/main/java/subway/domain/Line.java | 18 ++++- .../java/subway/domain/LineRepository.java | 26 ------- src/main/java/subway/domain/Station.java | 18 ++++- .../java/subway/domain/StationRepository.java | 26 ------- .../subway/repository/LineRepository.java | 57 +++++++++++++++ .../subway/repository/StationRepository.java | 63 ++++++++++++++++ .../subway/repository/SubwayRepository.java | 73 +++++++++++++++++++ src/main/java/subway/service/LineService.java | 11 +++ .../java/subway/service/StationService.java | 11 +++ .../java/subway/service/SubwayService.java | 11 +++ .../subway/util/constants/DistanceInfo.java | 26 +++++++ .../java/subway/util/constants/EnumUtil.java | 6 ++ .../java/subway/util/constants/LineName.java | 23 ++++++ .../subway/util/constants/StationName.java | 28 +++++++ .../java/subway/util/constants/TimeInfo.java | 25 +++++++ .../util/exception/NoResourceException.java | 7 ++ .../subway/util/message/ExceptionMessage.java | 34 +++++++++ 23 files changed, 481 insertions(+), 55 deletions(-) create mode 100644 docs/README.md create mode 100644 src/main/java/subway/controller/LineController.java create mode 100644 src/main/java/subway/controller/StationController.java create mode 100644 src/main/java/subway/controller/SubwayController.java create mode 100644 src/main/java/subway/domain/ConnectStationNode.java delete mode 100644 src/main/java/subway/domain/LineRepository.java delete mode 100644 src/main/java/subway/domain/StationRepository.java create mode 100644 src/main/java/subway/repository/LineRepository.java create mode 100644 src/main/java/subway/repository/StationRepository.java create mode 100644 src/main/java/subway/repository/SubwayRepository.java create mode 100644 src/main/java/subway/service/LineService.java create mode 100644 src/main/java/subway/service/StationService.java create mode 100644 src/main/java/subway/service/SubwayService.java create mode 100644 src/main/java/subway/util/constants/DistanceInfo.java create mode 100644 src/main/java/subway/util/constants/EnumUtil.java create mode 100644 src/main/java/subway/util/constants/LineName.java create mode 100644 src/main/java/subway/util/constants/StationName.java create mode 100644 src/main/java/subway/util/constants/TimeInfo.java create mode 100644 src/main/java/subway/util/exception/NoResourceException.java create mode 100644 src/main/java/subway/util/message/ExceptionMessage.java diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..a4e650e19 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +### 기능 요구사항 + +[ ✅ ] 주어진 지하철 정보를 초기화한다. \ No newline at end of file diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index 0bcf786cc..cb1a09c01 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -1,9 +1,17 @@ package subway; +import subway.controller.LineController; +import subway.controller.StationController; + import java.util.Scanner; public class Application { + + private static final LineController lineController = new LineController(); + private static final StationController stationController = new StationController(); public static void main(String[] args) { + lineController.initLine(); + stationController.initStation(); final Scanner scanner = new Scanner(System.in); // TODO: 프로그램 구현 } diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java new file mode 100644 index 000000000..07d8c58c3 --- /dev/null +++ b/src/main/java/subway/controller/LineController.java @@ -0,0 +1,15 @@ +package subway.controller; + +import subway.service.LineService; + +public class LineController { + + private final LineService lineService; + public LineController(){ + lineService = new LineService(); + } + + public void initLine(){ + lineService.initLine(); + } +} diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/controller/StationController.java new file mode 100644 index 000000000..329a2564f --- /dev/null +++ b/src/main/java/subway/controller/StationController.java @@ -0,0 +1,15 @@ +package subway.controller; + +import subway.service.StationService; + +public class StationController { + private final StationService stationService; + + public StationController(){ + stationService = new StationService(); + } + + public void initStation(){ + stationService.initStation(); + } +} diff --git a/src/main/java/subway/controller/SubwayController.java b/src/main/java/subway/controller/SubwayController.java new file mode 100644 index 000000000..f5058a553 --- /dev/null +++ b/src/main/java/subway/controller/SubwayController.java @@ -0,0 +1,15 @@ +package subway.controller; + +import subway.service.SubwayService; + +public class SubwayController { + private final SubwayService subwayService; + + public SubwayController(){ + subwayService = new SubwayService(); + } + + public void initSubway(){ + subwayService.initSubway(); + } +} diff --git a/src/main/java/subway/domain/ConnectStationNode.java b/src/main/java/subway/domain/ConnectStationNode.java new file mode 100644 index 000000000..64e5fcc92 --- /dev/null +++ b/src/main/java/subway/domain/ConnectStationNode.java @@ -0,0 +1,17 @@ +package subway.domain; + +public class ConnectStationNode { + private Station station; + private int distance; + private int time; + + private ConnectStationNode(Station station, int distance, int time){ + this.station = station; + this.distance = distance; + this.time = time; + } + + public static ConnectStationNode create(Station station, int distance, int time){ + return new ConnectStationNode(station, distance, time); + } +} diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java index f4d738d5a..2fc032f56 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -1,15 +1,31 @@ package subway.domain; +import java.util.ArrayList; +import java.util.List; + public class Line { private String name; + private List stations = new ArrayList<>(); - public Line(String name) { + private Line(String name) { this.name = name; } + public static Line create(String name){ + return new Line(name); + } + + public void addStationsInLine(final Station station){ + stations.add(station); + } + public String getName() { return name; } + public boolean isEqualName(String name){ + return name.equals(this.name); + } + // 추가 기능 구현 } diff --git a/src/main/java/subway/domain/LineRepository.java b/src/main/java/subway/domain/LineRepository.java deleted file mode 100644 index 2c4a723c9..000000000 --- a/src/main/java/subway/domain/LineRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package subway.domain; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -public class LineRepository { - private static final List lines = new ArrayList<>(); - - public static List lines() { - return Collections.unmodifiableList(lines); - } - - public static void addLine(Line line) { - lines.add(line); - } - - public static boolean deleteLineByName(String name) { - return lines.removeIf(line -> Objects.equals(line.getName(), name)); - } - - public static void deleteAll() { - lines.clear(); - } -} diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/Station.java index bdb142590..0001be18d 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/Station.java @@ -1,15 +1,29 @@ package subway.domain; +import java.util.ArrayList; +import java.util.List; + public class Station { private String name; + private List connectStationNodes = new ArrayList<>(); - public Station(String name) { + private Station(String name) { this.name = name; } + public static Station create(String name){ + return new Station(name); + } + + public void addConnectStations(final ConnectStationNode connectStationNode){ + connectStationNodes.add(connectStationNode); + } + public String getName() { return name; } - // 추가 기능 구현 + public boolean isEqualName(String name){ + return name.equals(this.name); + } } diff --git a/src/main/java/subway/domain/StationRepository.java b/src/main/java/subway/domain/StationRepository.java deleted file mode 100644 index 8ed9d103f..000000000 --- a/src/main/java/subway/domain/StationRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package subway.domain; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -public class StationRepository { - private static final List stations = new ArrayList<>(); - - public static List stations() { - return Collections.unmodifiableList(stations); - } - - public static void addStation(Station station) { - stations.add(station); - } - - public static boolean deleteStation(String name) { - return stations.removeIf(station -> Objects.equals(station.getName(), name)); - } - - public static void deleteAll() { - stations.clear(); - } -} diff --git a/src/main/java/subway/repository/LineRepository.java b/src/main/java/subway/repository/LineRepository.java new file mode 100644 index 000000000..135c94a85 --- /dev/null +++ b/src/main/java/subway/repository/LineRepository.java @@ -0,0 +1,57 @@ +package subway.repository; + +import subway.domain.Line; +import subway.domain.Station; +import subway.util.constants.LineName; +import subway.util.constants.StationName; +import subway.util.exception.NoResourceException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static subway.util.message.ExceptionMessage.NO_RESOURCE_MESSAGE; + +public class LineRepository { + private static final LineRepository lineRepository = new LineRepository(); + private static final StationRepository stationRepository = StationRepository.getInstance(); + private LineRepository(){ + + } + + public void initLine(){ + for (LineName lineName : LineName.values()) { + Line line = Line.create(lineName.getKey()); + addLine(line); + } + } + + public static LineRepository getInstance(){ + return lineRepository; + } + private static final List lines = new ArrayList<>(); + + public static List lines() { + return Collections.unmodifiableList(lines); + } + + public static void addLine(Line line) { + lines.add(line); + } + + public static boolean deleteLineByName(String name) { + return lines.removeIf(line -> Objects.equals(line.getName(), name)); + } + + public static void deleteAll() { + lines.clear(); + } + + public Line findByName(String name){ + return lines.stream() + .filter(line -> line.isEqualName(name)) + .findFirst() + .orElseThrow(() -> new NoResourceException(String.format(NO_RESOURCE_MESSAGE.getValue(), "해당 호선"))); + } +} diff --git a/src/main/java/subway/repository/StationRepository.java b/src/main/java/subway/repository/StationRepository.java new file mode 100644 index 000000000..5f2e2039c --- /dev/null +++ b/src/main/java/subway/repository/StationRepository.java @@ -0,0 +1,63 @@ +package subway.repository; + +import subway.domain.ConnectStationNode; +import subway.domain.Station; +import subway.util.constants.StationName; +import subway.util.exception.NoResourceException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static subway.util.message.ExceptionMessage.NO_RESOURCE_MESSAGE; + +public class StationRepository { + + private static final StationRepository stationRepository = new StationRepository(); + private StationRepository(){ + + } + + public static StationRepository getInstance(){ + return stationRepository; + } + + public void initStation(){ + for (StationName stationName : StationName.values()) { + Station station = Station.create(stationName.getKey()); + addStation(station); + } + } + private static final List stations = new ArrayList<>(); + + public static List stations() { + return Collections.unmodifiableList(stations); + } + + public static void addStation(Station station) { + stations.add(station); + } + + public static boolean deleteStation(String name) { + return stations.removeIf(station -> Objects.equals(station.getName(), name)); + } + + public static void deleteAll() { + stations.clear(); + } + + public Station findByName(String name){ + return stations.stream() + .filter(station -> station.isEqualName(name)) + .findFirst() + .orElseThrow(() -> new NoResourceException(String.format(NO_RESOURCE_MESSAGE.getValue(), "해당 역"))); + } + + public void initConnectInfo(String start, String end, int distance, int time){ + Station startStation = findByName(start); + Station endStation = findByName(end); + ConnectStationNode connectStationNode = ConnectStationNode.create(endStation, distance, time); + startStation.addConnectStations(connectStationNode); + } +} diff --git a/src/main/java/subway/repository/SubwayRepository.java b/src/main/java/subway/repository/SubwayRepository.java new file mode 100644 index 000000000..2c4811ac0 --- /dev/null +++ b/src/main/java/subway/repository/SubwayRepository.java @@ -0,0 +1,73 @@ +package subway.repository; + +import subway.domain.Line; +import subway.domain.Station; +import subway.util.constants.LineName; +import subway.util.constants.StationName; + +import static subway.util.constants.DistanceInfo.*; +import static subway.util.constants.StationName.*; +import static subway.util.constants.TimeInfo.*; + +public class SubwayRepository { + + static String[] twoLineStations = {GYODAE.getKey(), GANGNAM.getKey(), YEOKSAM.getKey()}; + static String[] threeLineStations = {GYODAE.getKey(), SOUTH_TERMINAL.getKey(), + StationName.YANGJAE.getKey(), StationName.MAEBONG.getKey()}; + static String[] shinBundangLineStations = {GANGNAM.getKey(), StationName.YANGJAE.getKey(), + StationName.YANGJAE_CITIZEN_FOREST.getKey()}; + private static final SubwayRepository subwayRepository = new SubwayRepository(); + private static final LineRepository lineRepository = LineRepository.getInstance(); + private static final StationRepository stationRepository = StationRepository.getInstance(); + + private SubwayRepository(){ + + } + + public static SubwayRepository getInstance(){ + return subwayRepository; + } + + public void initSubway(){ + initStationsSpecificLine(); + initConnectInfo(); + } + + private void initStationsSpecificLine(){ + for(LineName lineName : LineName.values()){ + Line line = lineRepository.findByName(lineName.getKey()); + addStationsInLine(line); + } + } + + private void initConnectInfo(){ + stationRepository.initConnectInfo(GYODAE.getKey(), GANGNAM.getKey(), GYODAE_GANGNAM_DISTANCE.getValue(), GYODAE_GANGNAM_TIME.getValue()); + stationRepository.initConnectInfo(GANGNAM.getKey(), YEOKSAM.getKey(), GANGNAM_YEOKSAM_DISTANCE.getValue(), GANGNAM_YEOKSAM_TIME.getValue()); + stationRepository.initConnectInfo(GYODAE.getKey(), SOUTH_TERMINAL.getKey(), GYODAE_SOUTH_TERMINAL_DISTANCE.getValue(), GYODAE_SOUTH_TERMINAL_TIME.getValue()); + stationRepository.initConnectInfo(SOUTH_TERMINAL.getKey(), YANGJAE.getKey(), SOUTH_TERMINAL_YANGJAE_DISTANCE.getValue(), SOUTH_TERMINAL_YANGJAE_TIME.getValue()); + stationRepository.initConnectInfo(YANGJAE.getKey(), MAEBONG.getKey(), YANGJAE_MAEBONG_DISTANCE.getValue(), YANGJAE_MAEBONG_TIME.getValue()); + stationRepository.initConnectInfo(GANGNAM.getKey(), YANGJAE.getKey(), GANGNAM_YANGJAE_DISTANCE.getValue(), GANGNAM_YANGJAE_TIME.getValue()); + stationRepository.initConnectInfo(YANGJAE.getKey(), YANGJAE_CITIZEN_FOREST.getKey(), YANGJAE_YANGJAE_CITIZEN_FORESET_DISTANCE.getValue(), YANGJAE_YANGJAE_CITIZEN_FORESET_TIME.getValue()); + } + + private void addStationsInLine(final Line line){ + if(line.isEqualName(LineName.LINE_2.getKey())){ + initStationsInLine(line, twoLineStations); + } + + if(line.isEqualName(LineName.LINE_3.getKey())){ + initStationsInLine(line, threeLineStations); + } + + if(line.isEqualName(LineName.SHIN_BUNDANG.getKey())){ + initStationsInLine(line, shinBundangLineStations); + } + } + + public static void initStationsInLine(final Line line, final String[] stations){ + for(String stationInfo : stations){ + Station station = stationRepository.findByName(stationInfo); + line.addStationsInLine(station); + } + } +} diff --git a/src/main/java/subway/service/LineService.java b/src/main/java/subway/service/LineService.java new file mode 100644 index 000000000..797e1630d --- /dev/null +++ b/src/main/java/subway/service/LineService.java @@ -0,0 +1,11 @@ +package subway.service; + +import subway.repository.LineRepository; + +public class LineService { + private final LineRepository lineRepository = LineRepository.getInstance(); + + public void initLine(){ + lineRepository.initLine(); + } +} diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java new file mode 100644 index 000000000..b36ce904c --- /dev/null +++ b/src/main/java/subway/service/StationService.java @@ -0,0 +1,11 @@ +package subway.service; + +import subway.repository.StationRepository; + +public class StationService { + private final StationRepository stationRepository = StationRepository.getInstance(); + + public void initStation(){ + stationRepository.initStation(); + } +} diff --git a/src/main/java/subway/service/SubwayService.java b/src/main/java/subway/service/SubwayService.java new file mode 100644 index 000000000..4b1615316 --- /dev/null +++ b/src/main/java/subway/service/SubwayService.java @@ -0,0 +1,11 @@ +package subway.service; + +import subway.repository.SubwayRepository; + +public class SubwayService { + private final SubwayRepository subwayRepository = SubwayRepository.getInstance(); + + public void initSubway(){ + subwayRepository.initSubway(); + } +} diff --git a/src/main/java/subway/util/constants/DistanceInfo.java b/src/main/java/subway/util/constants/DistanceInfo.java new file mode 100644 index 000000000..6eb62fb89 --- /dev/null +++ b/src/main/java/subway/util/constants/DistanceInfo.java @@ -0,0 +1,26 @@ +package subway.util.constants; + +public enum DistanceInfo implements EnumUtil{ + GYODAE_GANGNAM_DISTANCE(2), + GANGNAM_YEOKSAM_DISTANCE(2), + GYODAE_SOUTH_TERMINAL_DISTANCE(3), + SOUTH_TERMINAL_YANGJAE_DISTANCE(6), + YANGJAE_MAEBONG_DISTANCE(1), + GANGNAM_YANGJAE_DISTANCE(2), + YANGJAE_YANGJAE_CITIZEN_FORESET_DISTANCE(10); + + private int distance; + DistanceInfo(int distance){ + this.distance = distance; + } + + @Override + public String getKey() { + return name(); + } + + @Override + public Integer getValue() { + return distance; + } +} diff --git a/src/main/java/subway/util/constants/EnumUtil.java b/src/main/java/subway/util/constants/EnumUtil.java new file mode 100644 index 000000000..2cbe5cd02 --- /dev/null +++ b/src/main/java/subway/util/constants/EnumUtil.java @@ -0,0 +1,6 @@ +package subway.util.constants; + +public interface EnumUtil{ + T1 getKey(); + T2 getValue(); +} diff --git a/src/main/java/subway/util/constants/LineName.java b/src/main/java/subway/util/constants/LineName.java new file mode 100644 index 000000000..f56b6b094 --- /dev/null +++ b/src/main/java/subway/util/constants/LineName.java @@ -0,0 +1,23 @@ +package subway.util.constants; + +public enum LineName implements EnumUtil{ + LINE_2("2호선"), + LINE_3("3호선"), + SHIN_BUNDANG("신분당선"); + + private String lineName; + + LineName(String lineName){ + this.lineName = lineName; + } + + @Override + public String getKey() { + return lineName; + } + + @Override + public String getValue() { + return name(); + } +} diff --git a/src/main/java/subway/util/constants/StationName.java b/src/main/java/subway/util/constants/StationName.java new file mode 100644 index 000000000..84b5a02f9 --- /dev/null +++ b/src/main/java/subway/util/constants/StationName.java @@ -0,0 +1,28 @@ +package subway.util.constants; + +public enum StationName implements EnumUtil{ + GYODAE("교대역"), + GANGNAM("강남역"), + YEOKSAM("역삼역"), + SOUTH_TERMINAL("남부터미널역"), + MAEBONG("매봉역"), + YANGJAE("양재역"), + YANGJAE_CITIZEN_FOREST("양재시민의숲역"); + + private String stationName; + + StationName(String stationName){ + this.stationName = stationName; + } + + + @Override + public String getKey() { + return stationName; + } + + @Override + public String getValue() { + return name(); + } +} diff --git a/src/main/java/subway/util/constants/TimeInfo.java b/src/main/java/subway/util/constants/TimeInfo.java new file mode 100644 index 000000000..e48029325 --- /dev/null +++ b/src/main/java/subway/util/constants/TimeInfo.java @@ -0,0 +1,25 @@ +package subway.util.constants; + +public enum TimeInfo implements EnumUtil{ + GYODAE_GANGNAM_TIME(3), + GANGNAM_YEOKSAM_TIME(3), + GYODAE_SOUTH_TERMINAL_TIME(2), + SOUTH_TERMINAL_YANGJAE_TIME(5), + YANGJAE_MAEBONG_TIME(1), + GANGNAM_YANGJAE_TIME(8), + YANGJAE_YANGJAE_CITIZEN_FORESET_TIME(3); + + private int time; + TimeInfo(int time){ + this.time = time; + } + @Override + public String getKey() { + return name(); + } + + @Override + public Integer getValue() { + return time; + } +} diff --git a/src/main/java/subway/util/exception/NoResourceException.java b/src/main/java/subway/util/exception/NoResourceException.java new file mode 100644 index 000000000..0cc953273 --- /dev/null +++ b/src/main/java/subway/util/exception/NoResourceException.java @@ -0,0 +1,7 @@ +package subway.util.exception; + +public class NoResourceException extends IllegalArgumentException{ + public NoResourceException(String message){ + super(message); + } +} diff --git a/src/main/java/subway/util/message/ExceptionMessage.java b/src/main/java/subway/util/message/ExceptionMessage.java new file mode 100644 index 000000000..0ae719f9c --- /dev/null +++ b/src/main/java/subway/util/message/ExceptionMessage.java @@ -0,0 +1,34 @@ +package subway.util.message; + +import subway.util.constants.EnumUtil; + +public enum ExceptionMessage implements EnumUtil { + BLANK_MESSAGE("%s은(는) 빈 값이 들어올 수 없습니다.") + , LENGTH_MESSAGE("%d글자를 초과하였습니다.") + , INPUT_MESSAGE("입력 중에 예기치 못한 오류가 발생하였습니다. 예외 메시지: %s") + , TYPE_MESSAGE("%s은(는) 숫자만 입력할 수 있습니다.") + , RANGE_MESSAGE("%d 보다 큰 값을 입력해 주세요.") + , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") + , DUPLICATE_MESSAGE("%s을(를) 중복으로 입력할 수 없습니다.") + , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다."); + private static final String ERROR_TAG = "[ERROR] "; + private final String message; + + public String getMessage(){ + return message; + } + + ExceptionMessage(final String message) { + this.message = ERROR_TAG + message; + } + + @Override + public String getKey() { + return name(); + } + + @Override + public String getValue() { + return message; + } +} From f8da60ba3ccea97a96320e72737c555264cdce2b Mon Sep 17 00:00:00 2001 From: suhyun Date: Fri, 1 Dec 2023 10:47:46 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=A1=B0=ED=9A=8C=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EC=A0=84=EA=B9=8C=EC=A7=80=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8=EC=9D=B4=20=EC=98=AC=EB=B0=94=EB=A5=B4?= =?UTF-8?q?=EA=B2=8C=20=EB=8F=99=EC=9E=91=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 30 +++++++++- src/main/java/subway/Application.java | 7 ++- .../subway/controller/SubwayController.java | 59 ++++++++++++++++++- .../java/subway/service/SubwayService.java | 16 +++++ .../subway/util/constants/StationName.java | 3 +- .../util/exception/SameStationException.java | 7 +++ .../subway/util/message/ExceptionMessage.java | 3 +- .../subway/util/message/InputMessage.java | 28 +++++++++ src/main/java/subway/util/message/Menu.java | 28 +++++++++ .../subway/util/message/OutputMessage.java | 27 +++++++++ src/main/java/subway/view/InputView.java | 29 +++++++++ src/main/java/subway/view/OutputView.java | 22 +++++++ .../subway/view/validator/MenuValidator.java | 19 ++++++ .../view/validator/StationValidator.java | 18 ++++++ .../java/subway/view/validator/Validator.java | 11 ++++ 15 files changed, 302 insertions(+), 5 deletions(-) create mode 100644 src/main/java/subway/util/exception/SameStationException.java create mode 100644 src/main/java/subway/util/message/InputMessage.java create mode 100644 src/main/java/subway/util/message/Menu.java create mode 100644 src/main/java/subway/util/message/OutputMessage.java create mode 100644 src/main/java/subway/view/InputView.java create mode 100644 src/main/java/subway/view/OutputView.java create mode 100644 src/main/java/subway/view/validator/MenuValidator.java create mode 100644 src/main/java/subway/view/validator/StationValidator.java create mode 100644 src/main/java/subway/view/validator/Validator.java diff --git a/docs/README.md b/docs/README.md index a4e650e19..feab839fc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,31 @@ ### 기능 요구사항 -[ ✅ ] 주어진 지하철 정보를 초기화한다. \ No newline at end of file +[ ✅ ] 주어진 지하철 정보를 초기화한다. + +[ ✅ ] 아래와 같이 입력을 받는다. +``` +## 메인 화면 +1. 경로 조회 +Q. 종료 + +## 원하는 기능을 선택하세요. +1 + +## 경로 기준 +1. 최단 거리 +2. 최소 시간 +B. 돌아가기 + +## 원하는 기능을 선택하세요. +1 + +## 출발역을 입력하세요. +교대역 + +## 도착역을 입력하세요. +양재역 +``` + - 입력 받을 때, 경로 조회 시 출발역과 도착역이 같으면 에러를 출력한다. + - 정상적으로 입력하지 않았다면, 에러를 출력한다. + +[ ] 경로 조회 시 출발역과 도착역이 연결되어 있지 않으면 에러를 출력한다. \ No newline at end of file diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index cb1a09c01..7a5dfd8c8 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -2,6 +2,9 @@ import subway.controller.LineController; import subway.controller.StationController; +import subway.controller.SubwayController; +import subway.view.InputView; +import subway.view.OutputView; import java.util.Scanner; @@ -9,10 +12,12 @@ public class Application { private static final LineController lineController = new LineController(); private static final StationController stationController = new StationController(); + private static final SubwayController subwayController = new SubwayController(); public static void main(String[] args) { lineController.initLine(); stationController.initStation(); final Scanner scanner = new Scanner(System.in); - // TODO: 프로그램 구현 + InputView.init(scanner); + subwayController.start(); } } diff --git a/src/main/java/subway/controller/SubwayController.java b/src/main/java/subway/controller/SubwayController.java index f5058a553..fc701b539 100644 --- a/src/main/java/subway/controller/SubwayController.java +++ b/src/main/java/subway/controller/SubwayController.java @@ -1,10 +1,19 @@ package subway.controller; import subway.service.SubwayService; +import subway.util.message.InputMessage; +import subway.util.message.Menu; +import subway.view.InputView; +import subway.view.OutputView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; public class SubwayController { private final SubwayService subwayService; - + private final List main = new ArrayList<>(List.of(Menu.SELECT_ROUTINE.getKey(), Menu.EXIT.getKey())); + private final List routine = new ArrayList<>(List.of(Menu.SHORTEST_DISTANCE.getKey(), Menu.SHORTEST_TIME.getKey(), Menu.BACK.getKey())); public SubwayController(){ subwayService = new SubwayService(); } @@ -12,4 +21,52 @@ public SubwayController(){ public void initSubway(){ subwayService.initSubway(); } + + public void start(){ + try{ + if(questionIsproceed()){ + questionRoutine(); + }; + } catch(IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + start(); + } + } + + private boolean questionIsproceed(){ + OutputView.printMain(); + String input = InputView.inputKey(main); + return confirmProceed(input); + } + + private boolean confirmProceed(final String input){ + if(input.equals(Menu.EXIT.getKey())){ + return false; + } + return input.equals(Menu.SELECT_ROUTINE.getKey()); + } + + private void questionRoutine(){ + OutputView.printRoutine(); + String input = InputView.inputKey(routine); + questionMainNext(input); + } + + private void questionMainNext(final String input){ + if(input.equals(Menu.SHORTEST_DISTANCE.getKey())){ + getShortestDistance(); + } + if(input.equals(Menu.SHORTEST_TIME.getKey())){ + //getShortestTime(); + } + if(input.equals(Menu.BACK.getKey())){ + questionRoutine(); + } + } + + private void getShortestDistance(){ + String startStationInfo = InputView.inputStation(InputMessage.GET_START_STATION.getValue()); + String endStationInfo = InputView.inputStation(InputMessage.GET_END_STARTION.getValue()); + subwayService.getShortestDistance(startStationInfo, endStationInfo); + } } diff --git a/src/main/java/subway/service/SubwayService.java b/src/main/java/subway/service/SubwayService.java index 4b1615316..4e155bbf1 100644 --- a/src/main/java/subway/service/SubwayService.java +++ b/src/main/java/subway/service/SubwayService.java @@ -1,11 +1,27 @@ package subway.service; +import subway.domain.Station; +import subway.repository.StationRepository; import subway.repository.SubwayRepository; +import subway.util.exception.SameStationException; + +import static subway.util.message.ExceptionMessage.SAME_AS; public class SubwayService { private final SubwayRepository subwayRepository = SubwayRepository.getInstance(); + private final StationRepository stationRepository = StationRepository.getInstance(); public void initSubway(){ subwayRepository.initSubway(); } + + public void getShortestDistance(final String startStationInfo, final String endStationInfo){ + Station startStation = stationRepository.findByName(startStationInfo); + Station endStation = stationRepository.findByName(endStationInfo); + isSameStation(startStation, endStation); + } + + private void isSameStation(final Station start, final Station end){ + throw new SameStationException(SAME_AS.getValue()); + } } diff --git a/src/main/java/subway/util/constants/StationName.java b/src/main/java/subway/util/constants/StationName.java index 84b5a02f9..f2ed185f3 100644 --- a/src/main/java/subway/util/constants/StationName.java +++ b/src/main/java/subway/util/constants/StationName.java @@ -7,7 +7,8 @@ public enum StationName implements EnumUtil{ SOUTH_TERMINAL("남부터미널역"), MAEBONG("매봉역"), YANGJAE("양재역"), - YANGJAE_CITIZEN_FOREST("양재시민의숲역"); + YANGJAE_CITIZEN_FOREST("양재시민의숲역"), + STATION_SUFFIX("역"); private String stationName; diff --git a/src/main/java/subway/util/exception/SameStationException.java b/src/main/java/subway/util/exception/SameStationException.java new file mode 100644 index 000000000..98a7a1d0b --- /dev/null +++ b/src/main/java/subway/util/exception/SameStationException.java @@ -0,0 +1,7 @@ +package subway.util.exception; + +public class SameStationException extends IllegalArgumentException{ + public SameStationException(String message){ + super(message); + } +} diff --git a/src/main/java/subway/util/message/ExceptionMessage.java b/src/main/java/subway/util/message/ExceptionMessage.java index 0ae719f9c..d48505b0e 100644 --- a/src/main/java/subway/util/message/ExceptionMessage.java +++ b/src/main/java/subway/util/message/ExceptionMessage.java @@ -10,7 +10,8 @@ public enum ExceptionMessage implements EnumUtil { , RANGE_MESSAGE("%d 보다 큰 값을 입력해 주세요.") , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") , DUPLICATE_MESSAGE("%s을(를) 중복으로 입력할 수 없습니다.") - , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다."); + , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다.") + , SAME_AS("출발역과 도착역이 동일합니다."); private static final String ERROR_TAG = "[ERROR] "; private final String message; diff --git a/src/main/java/subway/util/message/InputMessage.java b/src/main/java/subway/util/message/InputMessage.java new file mode 100644 index 000000000..a763bd2fa --- /dev/null +++ b/src/main/java/subway/util/message/InputMessage.java @@ -0,0 +1,28 @@ +package subway.util.message; + +import subway.util.constants.EnumUtil; + +public enum InputMessage implements EnumUtil { + MAIN_SCREEN("## 메인 화면"), + SELECT_WANTED("## 원하는 기능을 선택하세요."), + ROUTINE("\n## 경로 기준"), + GET_START_STATION("## 출발역을 입력하세요."), + GET_END_STARTION("\n## 도착역을 입력하세요."), + SELECT_RESULT("## 조회 결과"), + DOT("..."); + + private String message; + InputMessage(String message){ + this.message = message; + } + + @Override + public String getKey() { + return name(); + } + + @Override + public String getValue() { + return message; + } +} diff --git a/src/main/java/subway/util/message/Menu.java b/src/main/java/subway/util/message/Menu.java new file mode 100644 index 000000000..60bcac6e7 --- /dev/null +++ b/src/main/java/subway/util/message/Menu.java @@ -0,0 +1,28 @@ +package subway.util.message; + +import subway.util.constants.EnumUtil; + +public enum Menu implements EnumUtil { + SELECT_ROUTINE("1", "1. 경로 조회"), + EXIT("Q", "Q. 종료\n"), + SHORTEST_DISTANCE("1", "1. 최단 거리"), + SHORTEST_TIME("2", "2. 최소 시간"), + BACK("B", "B. 돌아가기\n"); + + private String code; + private String message; + Menu(String code, String message){ + this.code = code; + this.message = message; + } + + @Override + public String getKey() { + return code; + } + + @Override + public String getValue() { + return message; + } +} diff --git a/src/main/java/subway/util/message/OutputMessage.java b/src/main/java/subway/util/message/OutputMessage.java new file mode 100644 index 000000000..a586f3470 --- /dev/null +++ b/src/main/java/subway/util/message/OutputMessage.java @@ -0,0 +1,27 @@ +package subway.util.message; + +import subway.util.constants.EnumUtil; + +public enum OutputMessage implements EnumUtil { + DASH(" --- "), + TOTAL_DISTANCE(" 총 거리 : "), + TOTAL_TIME(" 총 소요 시간: "), + KILLOMETER("km"), + MINUTE("분"); + + private String message; + private static final String INFO_TAG = "[INFO] "; + + OutputMessage(String message){ + this.message = INFO_TAG + message; + } + @Override + public String getKey() { + return name(); + } + + @Override + public String getValue() { + return message; + } +} diff --git a/src/main/java/subway/view/InputView.java b/src/main/java/subway/view/InputView.java new file mode 100644 index 000000000..1d08ed519 --- /dev/null +++ b/src/main/java/subway/view/InputView.java @@ -0,0 +1,29 @@ +package subway.view; + +import subway.util.message.InputMessage; +import subway.view.validator.MenuValidator; +import subway.view.validator.StationValidator; +import subway.view.validator.Validator; + +import java.util.List; +import java.util.Scanner; + +public class InputView { + + private static Scanner scanner; + public static void init(Scanner sc){ + scanner = sc; + } + + public static String inputKey(List candidateKeys){ + System.out.println(InputMessage.SELECT_WANTED.getValue()); + return MenuValidator.validate(scanner.next(), candidateKeys); + } + + public static String inputStation(final String str){ + System.out.println(str); + String input = scanner.next(); + StationValidator.validate(input); + return input; + } +} diff --git a/src/main/java/subway/view/OutputView.java b/src/main/java/subway/view/OutputView.java new file mode 100644 index 000000000..e4d92b2a0 --- /dev/null +++ b/src/main/java/subway/view/OutputView.java @@ -0,0 +1,22 @@ +package subway.view; + +import subway.util.message.InputMessage; +import subway.util.message.Menu; +import subway.util.message.OutputMessage; + +public class OutputView { + public static void printMessage(String message) { + System.out.println(message); + } + public static void printMain(){ + System.out.println(InputMessage.MAIN_SCREEN.getValue()); + System.out.println(Menu.SELECT_ROUTINE.getValue()); + System.out.println(Menu.EXIT.getValue()); + } + + public static void printRoutine(){ + System.out.println(Menu.SHORTEST_DISTANCE.getValue()); + System.out.println(Menu.SHORTEST_TIME.getValue()); + System.out.println(Menu.BACK.getValue()); + } +} diff --git a/src/main/java/subway/view/validator/MenuValidator.java b/src/main/java/subway/view/validator/MenuValidator.java new file mode 100644 index 000000000..7d99f4f9e --- /dev/null +++ b/src/main/java/subway/view/validator/MenuValidator.java @@ -0,0 +1,19 @@ +package subway.view.validator; + +import java.util.List; + +import static subway.util.message.ExceptionMessage.INPUT_MESSAGE; + +public class MenuValidator extends Validator{ + public static String validate(final String input, final List candidateKeys){ + validateBlank(input); + return validateString(input, candidateKeys); + } + + private static String validateString(final String input, final List candidateKeys){ + if(!candidateKeys.contains(input)){ + throw new IllegalArgumentException(String.format(INPUT_MESSAGE.getValue(), "제시한 사항들 중에 입력해주세요.")); + } + return input; + } +} diff --git a/src/main/java/subway/view/validator/StationValidator.java b/src/main/java/subway/view/validator/StationValidator.java new file mode 100644 index 000000000..e58fea66b --- /dev/null +++ b/src/main/java/subway/view/validator/StationValidator.java @@ -0,0 +1,18 @@ +package subway.view.validator; + +import subway.util.constants.StationName; + +import static subway.util.message.ExceptionMessage.INPUT_MESSAGE; + +public class StationValidator extends Validator{ + public static void validate(final String str){ + validateBlank(str); + validateStationName(str); + } + + private static void validateStationName(final String input) { + if(!input.endsWith(StationName.STATION_SUFFIX.getKey())){ + throw new IllegalArgumentException(String.format(INPUT_MESSAGE.getValue(), "역 이름을 올바르게 입력해주세요.")); + }; + } +} diff --git a/src/main/java/subway/view/validator/Validator.java b/src/main/java/subway/view/validator/Validator.java new file mode 100644 index 000000000..6053228ce --- /dev/null +++ b/src/main/java/subway/view/validator/Validator.java @@ -0,0 +1,11 @@ +package subway.view.validator; + +import static subway.util.message.ExceptionMessage.BLANK_MESSAGE; + +public class Validator { + protected static void validateBlank(final String input) { + if (input == null || input.trim().isEmpty()) { + throw new IllegalArgumentException(BLANK_MESSAGE.getValue()); + } + } +} From d774231b0c6ad6c33a227ece7cb0c52d8cd56f3b Mon Sep 17 00:00:00 2001 From: suhyun Date: Sat, 2 Dec 2023 15:27:13 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EC=B4=9D=EA=B1=B0=EB=A6=AC?= =?UTF-8?q?=EC=99=80=20=EC=B4=9D=20=EC=86=8C=EC=9A=94=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 7 +- src/main/java/subway/Application.java | 7 ++ .../subway/controller/GraphController.java | 16 ++++ .../subway/controller/SubwayController.java | 49 +++++++--- .../subway/domain/ConnectStationNode.java | 16 ++++ src/main/java/subway/domain/Graph.java | 8 ++ src/main/java/subway/domain/Line.java | 4 +- src/main/java/subway/domain/Station.java | 11 ++- .../subway/repository/GraphRepository.java | 64 +++++++++++++ .../subway/repository/LineRepository.java | 3 +- .../subway/repository/StationRepository.java | 4 +- .../subway/repository/SubwayRepository.java | 32 +++---- .../java/subway/service/GraphService.java | 89 +++++++++++++++++++ .../java/subway/service/SubwayService.java | 15 +--- .../java/subway/util/constants/LineName.java | 4 +- .../subway/util/constants/StationName.java | 7 +- .../util/exception/NotConnectException.java | 7 ++ .../subway/util/message/ExceptionMessage.java | 5 +- .../subway/util/message/InputMessage.java | 5 +- .../subway/util/message/OutputMessage.java | 8 +- src/main/java/subway/view/OutputView.java | 22 +++++ .../view/validator/StationValidator.java | 4 +- src/test/java/subway/JGraphtTest.java | 2 +- 23 files changed, 323 insertions(+), 66 deletions(-) create mode 100644 src/main/java/subway/controller/GraphController.java create mode 100644 src/main/java/subway/domain/Graph.java create mode 100644 src/main/java/subway/repository/GraphRepository.java create mode 100644 src/main/java/subway/service/GraphService.java create mode 100644 src/main/java/subway/util/exception/NotConnectException.java diff --git a/docs/README.md b/docs/README.md index feab839fc..16cc24143 100644 --- a/docs/README.md +++ b/docs/README.md @@ -28,4 +28,9 @@ B. 돌아가기 - 입력 받을 때, 경로 조회 시 출발역과 도착역이 같으면 에러를 출력한다. - 정상적으로 입력하지 않았다면, 에러를 출력한다. -[ ] 경로 조회 시 출발역과 도착역이 연결되어 있지 않으면 에러를 출력한다. \ No newline at end of file +[X] 경로 조회 시 출발역과 도착역이 연결되어 있지 않으면 에러를 출력한다. + - 모든 역이 서로 연결되어있기때문에 위 내용 구현X + +[ ✅ ] 총 거리를 구한다. + +[ ✅ ] 총 소요시간을 구한다. \ No newline at end of file diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index 7a5dfd8c8..601fd4779 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -1,5 +1,6 @@ package subway; +import subway.controller.GraphController; import subway.controller.LineController; import subway.controller.StationController; import subway.controller.SubwayController; @@ -8,14 +9,20 @@ import java.util.Scanner; +import static subway.repository.LineRepository.lines; +import static subway.repository.StationRepository.stations; + public class Application { private static final LineController lineController = new LineController(); private static final StationController stationController = new StationController(); private static final SubwayController subwayController = new SubwayController(); + private static final GraphController graphController = new GraphController(); public static void main(String[] args) { lineController.initLine(); stationController.initStation(); + subwayController.initSubway(); + graphController.initGraph(); final Scanner scanner = new Scanner(System.in); InputView.init(scanner); subwayController.start(); diff --git a/src/main/java/subway/controller/GraphController.java b/src/main/java/subway/controller/GraphController.java new file mode 100644 index 000000000..a6753c876 --- /dev/null +++ b/src/main/java/subway/controller/GraphController.java @@ -0,0 +1,16 @@ +package subway.controller; + +import subway.service.GraphService; + +public class GraphController { + private final GraphService graphService; + + public GraphController(){ + graphService = new GraphService(); + } + + public void initGraph(){ + graphService.initGraph(); + } + +} diff --git a/src/main/java/subway/controller/SubwayController.java b/src/main/java/subway/controller/SubwayController.java index fc701b539..2944e2b78 100644 --- a/src/main/java/subway/controller/SubwayController.java +++ b/src/main/java/subway/controller/SubwayController.java @@ -1,5 +1,6 @@ package subway.controller; +import subway.service.GraphService; import subway.service.SubwayService; import subway.util.message.InputMessage; import subway.util.message.Menu; @@ -12,10 +13,16 @@ public class SubwayController { private final SubwayService subwayService; + private final GraphService graphService; private final List main = new ArrayList<>(List.of(Menu.SELECT_ROUTINE.getKey(), Menu.EXIT.getKey())); private final List routine = new ArrayList<>(List.of(Menu.SHORTEST_DISTANCE.getKey(), Menu.SHORTEST_TIME.getKey(), Menu.BACK.getKey())); + + private int totalDistance; + private int totalTime; + private List path; public SubwayController(){ subwayService = new SubwayService(); + graphService = new GraphService(); } public void initSubway(){ @@ -23,13 +30,13 @@ public void initSubway(){ } public void start(){ - try{ - if(questionIsproceed()){ + while(questionIsproceed()){ + try{ + questionRoutine(); + } catch(IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); questionRoutine(); - }; - } catch(IllegalArgumentException e){ - OutputView.printMessage(e.getMessage()); - start(); + } } } @@ -53,20 +60,36 @@ private void questionRoutine(){ } private void questionMainNext(final String input){ + if(input.equals(Menu.BACK.getKey())){ + questionRoutine(); + } + List totalInfo = new ArrayList<>(); if(input.equals(Menu.SHORTEST_DISTANCE.getKey())){ - getShortestDistance(); + totalInfo = getShortestDistance(); } if(input.equals(Menu.SHORTEST_TIME.getKey())){ - //getShortestTime(); - } - if(input.equals(Menu.BACK.getKey())){ - questionRoutine(); + totalInfo = getShortestTime(); } + savetotalInfo(totalInfo); + OutputView.printResult(path, totalDistance, totalTime); } - private void getShortestDistance(){ + private List getShortestDistance(){ String startStationInfo = InputView.inputStation(InputMessage.GET_START_STATION.getValue()); String endStationInfo = InputView.inputStation(InputMessage.GET_END_STARTION.getValue()); - subwayService.getShortestDistance(startStationInfo, endStationInfo); + path = graphService.getShortestDistancePath(startStationInfo, endStationInfo); + return graphService.getTotalShortestDistanceAndShortestTime(path); + } + + private List getShortestTime(){ + String startStationInfo = InputView.inputStation(InputMessage.GET_START_STATION.getValue()); + String endStationInfo = InputView.inputStation(InputMessage.GET_END_STARTION.getValue()); + path = graphService.getShortestTimePath(startStationInfo, endStationInfo); + return graphService.getTotalShortestDistanceAndShortestTime(path); + } + + private void savetotalInfo(final List totalInfo){ + totalDistance = totalInfo.get(0); + totalTime = totalInfo.get(1); } } diff --git a/src/main/java/subway/domain/ConnectStationNode.java b/src/main/java/subway/domain/ConnectStationNode.java index 64e5fcc92..1cb7dbc0f 100644 --- a/src/main/java/subway/domain/ConnectStationNode.java +++ b/src/main/java/subway/domain/ConnectStationNode.java @@ -14,4 +14,20 @@ private ConnectStationNode(Station station, int distance, int time){ public static ConnectStationNode create(Station station, int distance, int time){ return new ConnectStationNode(station, distance, time); } + + public Station getStation(){ + return station; + } + + public int getDistance(){ + return distance; + } + + public int getTime(){ + return time; + } + + public String toString(){ + return "연결된 역 정보 = " + station.getName() + "," + getDistance() + "," + getTime(); + } } diff --git a/src/main/java/subway/domain/Graph.java b/src/main/java/subway/domain/Graph.java new file mode 100644 index 000000000..48ae6e71f --- /dev/null +++ b/src/main/java/subway/domain/Graph.java @@ -0,0 +1,8 @@ +package subway.domain; + +import org.jgrapht.graph.DefaultWeightedEdge; +import org.jgrapht.graph.WeightedMultigraph; +import subway.util.constants.StationName; + +public class Graph { +} diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java index 2fc032f56..8036d54f6 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -27,5 +27,7 @@ public boolean isEqualName(String name){ return name.equals(this.name); } - // 추가 기능 구현 + public String toString(){ + return name; + } } diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/Station.java index 0001be18d..c4d275e80 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/Station.java @@ -1,7 +1,6 @@ package subway.domain; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class Station { private String name; @@ -26,4 +25,12 @@ public String getName() { public boolean isEqualName(String name){ return name.equals(this.name); } + + public List getConnectStationNodes() { + return Collections.unmodifiableList(connectStationNodes); + } + + public String toString(){ + return name; + } } diff --git a/src/main/java/subway/repository/GraphRepository.java b/src/main/java/subway/repository/GraphRepository.java new file mode 100644 index 000000000..aaf4914ff --- /dev/null +++ b/src/main/java/subway/repository/GraphRepository.java @@ -0,0 +1,64 @@ +package subway.repository; + +import org.jgrapht.alg.shortestpath.DijkstraShortestPath; +import org.jgrapht.graph.DefaultWeightedEdge; +import org.jgrapht.graph.WeightedMultigraph; +import subway.domain.ConnectStationNode; +import subway.domain.Graph; +import subway.domain.Station; +import subway.util.constants.StationName; + +import java.util.List; + +import static subway.repository.StationRepository.stations; + +public class GraphRepository { + + private static final GraphRepository graphRepository = new GraphRepository(); + private static final StationRepository stationRepository = StationRepository.getInstance(); + + private static final WeightedMultigraph GRAPH_DISTANCE = new WeightedMultigraph( + DefaultWeightedEdge.class); + private static final WeightedMultigraph GRAPH_TIME = new WeightedMultigraph( + DefaultWeightedEdge.class); + private GraphRepository(){ + + } + + public static GraphRepository getInstance(){ + return graphRepository; + } + + public void initGraph(){ + addVertexs(); + setWeight(); + } + + private void addVertexs(){ + for (StationName stationName : StationName.values()) { + GRAPH_DISTANCE.addVertex(stationName.getValue()); + GRAPH_TIME.addVertex(stationName.getValue()); + } + } + + private void setWeight(){ + for (Station station : stations()){ + for (ConnectStationNode connectData : station.getConnectStationNodes()) { + GRAPH_DISTANCE.setEdgeWeight(GRAPH_DISTANCE.addEdge(station.getName(), connectData.getStation().getName()), connectData.getDistance()); + GRAPH_DISTANCE.setEdgeWeight(GRAPH_TIME.addEdge(station.getName(), connectData.getStation().getName()), connectData.getTime()); + } + } + } + + public List getShortestDistance(final Station startStation, final Station endStation){ + DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(GRAPH_DISTANCE); + List shortestPath = dijkstraShortestPath.getPath(startStation.getName(), endStation.getName()).getVertexList(); + return shortestPath; + } + + public List getShortestTime(final Station startStation, final Station endStation){ + DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(GRAPH_TIME); + List shortestPath = dijkstraShortestPath.getPath(startStation.getName(), endStation.getName()).getVertexList(); + return shortestPath; + } +} diff --git a/src/main/java/subway/repository/LineRepository.java b/src/main/java/subway/repository/LineRepository.java index 135c94a85..8f2a3fddd 100644 --- a/src/main/java/subway/repository/LineRepository.java +++ b/src/main/java/subway/repository/LineRepository.java @@ -15,14 +15,13 @@ public class LineRepository { private static final LineRepository lineRepository = new LineRepository(); - private static final StationRepository stationRepository = StationRepository.getInstance(); private LineRepository(){ } public void initLine(){ for (LineName lineName : LineName.values()) { - Line line = Line.create(lineName.getKey()); + Line line = Line.create(lineName.getValue()); addLine(line); } } diff --git a/src/main/java/subway/repository/StationRepository.java b/src/main/java/subway/repository/StationRepository.java index 5f2e2039c..4f5fd154e 100644 --- a/src/main/java/subway/repository/StationRepository.java +++ b/src/main/java/subway/repository/StationRepository.java @@ -25,7 +25,7 @@ public static StationRepository getInstance(){ public void initStation(){ for (StationName stationName : StationName.values()) { - Station station = Station.create(stationName.getKey()); + Station station = Station.create(stationName.getValue()); addStation(station); } } @@ -51,7 +51,7 @@ public Station findByName(String name){ return stations.stream() .filter(station -> station.isEqualName(name)) .findFirst() - .orElseThrow(() -> new NoResourceException(String.format(NO_RESOURCE_MESSAGE.getValue(), "해당 역"))); + .orElseThrow(() -> new NoResourceException(String.format(NO_RESOURCE_MESSAGE.getValue(), name))); } public void initConnectInfo(String start, String end, int distance, int time){ diff --git a/src/main/java/subway/repository/SubwayRepository.java b/src/main/java/subway/repository/SubwayRepository.java index 2c4811ac0..436eff263 100644 --- a/src/main/java/subway/repository/SubwayRepository.java +++ b/src/main/java/subway/repository/SubwayRepository.java @@ -11,11 +11,11 @@ public class SubwayRepository { - static String[] twoLineStations = {GYODAE.getKey(), GANGNAM.getKey(), YEOKSAM.getKey()}; - static String[] threeLineStations = {GYODAE.getKey(), SOUTH_TERMINAL.getKey(), - StationName.YANGJAE.getKey(), StationName.MAEBONG.getKey()}; - static String[] shinBundangLineStations = {GANGNAM.getKey(), StationName.YANGJAE.getKey(), - StationName.YANGJAE_CITIZEN_FOREST.getKey()}; + static String[] twoLineStations = {GYODAE.getValue(), GANGNAM.getValue(), YEOKSAM.getValue()}; + static String[] threeLineStations = {GYODAE.getValue(), SOUTH_TERMINAL.getValue(), + StationName.YANGJAE.getValue(), StationName.MAEBONG.getValue()}; + static String[] shinBundangLineStations = {GANGNAM.getValue(), StationName.YANGJAE.getValue(), + StationName.YANGJAE_CITIZEN_FOREST.getValue()}; private static final SubwayRepository subwayRepository = new SubwayRepository(); private static final LineRepository lineRepository = LineRepository.getInstance(); private static final StationRepository stationRepository = StationRepository.getInstance(); @@ -35,31 +35,31 @@ public void initSubway(){ private void initStationsSpecificLine(){ for(LineName lineName : LineName.values()){ - Line line = lineRepository.findByName(lineName.getKey()); + Line line = lineRepository.findByName(lineName.getValue()); addStationsInLine(line); } } private void initConnectInfo(){ - stationRepository.initConnectInfo(GYODAE.getKey(), GANGNAM.getKey(), GYODAE_GANGNAM_DISTANCE.getValue(), GYODAE_GANGNAM_TIME.getValue()); - stationRepository.initConnectInfo(GANGNAM.getKey(), YEOKSAM.getKey(), GANGNAM_YEOKSAM_DISTANCE.getValue(), GANGNAM_YEOKSAM_TIME.getValue()); - stationRepository.initConnectInfo(GYODAE.getKey(), SOUTH_TERMINAL.getKey(), GYODAE_SOUTH_TERMINAL_DISTANCE.getValue(), GYODAE_SOUTH_TERMINAL_TIME.getValue()); - stationRepository.initConnectInfo(SOUTH_TERMINAL.getKey(), YANGJAE.getKey(), SOUTH_TERMINAL_YANGJAE_DISTANCE.getValue(), SOUTH_TERMINAL_YANGJAE_TIME.getValue()); - stationRepository.initConnectInfo(YANGJAE.getKey(), MAEBONG.getKey(), YANGJAE_MAEBONG_DISTANCE.getValue(), YANGJAE_MAEBONG_TIME.getValue()); - stationRepository.initConnectInfo(GANGNAM.getKey(), YANGJAE.getKey(), GANGNAM_YANGJAE_DISTANCE.getValue(), GANGNAM_YANGJAE_TIME.getValue()); - stationRepository.initConnectInfo(YANGJAE.getKey(), YANGJAE_CITIZEN_FOREST.getKey(), YANGJAE_YANGJAE_CITIZEN_FORESET_DISTANCE.getValue(), YANGJAE_YANGJAE_CITIZEN_FORESET_TIME.getValue()); + stationRepository.initConnectInfo(GYODAE.getValue(), GANGNAM.getValue(), GYODAE_GANGNAM_DISTANCE.getValue(), GYODAE_GANGNAM_TIME.getValue()); + stationRepository.initConnectInfo(GANGNAM.getValue(), YEOKSAM.getValue(), GANGNAM_YEOKSAM_DISTANCE.getValue(), GANGNAM_YEOKSAM_TIME.getValue()); + stationRepository.initConnectInfo(GYODAE.getValue(), SOUTH_TERMINAL.getValue(), GYODAE_SOUTH_TERMINAL_DISTANCE.getValue(), GYODAE_SOUTH_TERMINAL_TIME.getValue()); + stationRepository.initConnectInfo(SOUTH_TERMINAL.getValue(), YANGJAE.getValue(), SOUTH_TERMINAL_YANGJAE_DISTANCE.getValue(), SOUTH_TERMINAL_YANGJAE_TIME.getValue()); + stationRepository.initConnectInfo(YANGJAE.getValue(), MAEBONG.getValue(), YANGJAE_MAEBONG_DISTANCE.getValue(), YANGJAE_MAEBONG_TIME.getValue()); + stationRepository.initConnectInfo(GANGNAM.getValue(), YANGJAE.getValue(), GANGNAM_YANGJAE_DISTANCE.getValue(), GANGNAM_YANGJAE_TIME.getValue()); + stationRepository.initConnectInfo(YANGJAE.getValue(), YANGJAE_CITIZEN_FOREST.getValue(), YANGJAE_YANGJAE_CITIZEN_FORESET_DISTANCE.getValue(), YANGJAE_YANGJAE_CITIZEN_FORESET_TIME.getValue()); } private void addStationsInLine(final Line line){ - if(line.isEqualName(LineName.LINE_2.getKey())){ + if(line.isEqualName(LineName.LINE_2.getValue())){ initStationsInLine(line, twoLineStations); } - if(line.isEqualName(LineName.LINE_3.getKey())){ + if(line.isEqualName(LineName.LINE_3.getValue())){ initStationsInLine(line, threeLineStations); } - if(line.isEqualName(LineName.SHIN_BUNDANG.getKey())){ + if(line.isEqualName(LineName.SHIN_BUNDANG.getValue())){ initStationsInLine(line, shinBundangLineStations); } } diff --git a/src/main/java/subway/service/GraphService.java b/src/main/java/subway/service/GraphService.java new file mode 100644 index 000000000..9a35b869b --- /dev/null +++ b/src/main/java/subway/service/GraphService.java @@ -0,0 +1,89 @@ +package subway.service; + +import subway.domain.ConnectStationNode; +import subway.domain.Station; +import subway.repository.GraphRepository; +import subway.repository.StationRepository; +import subway.util.exception.NotConnectException; +import subway.util.exception.SameStationException; +import subway.util.message.InputMessage; +import subway.view.InputView; + +import java.util.ArrayList; +import java.util.List; + +import static subway.util.message.ExceptionMessage.NO_CONNECT_AS_STATION; +import static subway.util.message.ExceptionMessage.SAME_AS; + +public class GraphService { + private final GraphRepository graphRepository = GraphRepository.getInstance(); + private final StationRepository stationRepository = StationRepository.getInstance(); + private static final int ZERO = 0; + private static final int NEGATIVE = -1; + private static final int ONE = 1; + private int totalDistance; + private int totalTime; + + public void initGraph(){ + init(); + graphRepository.initGraph(); + } + + private void init(){ + totalDistance = ZERO; + totalTime = ZERO; + } + + private List isSameStation(final String startStationInfo, final String endStationInfo){ + Station startStation = stationRepository.findByName(startStationInfo); + Station endStation = stationRepository.findByName(endStationInfo); + if(startStation.isEqualName(endStationInfo)){ + throw new SameStationException(SAME_AS.getValue()); + } + return addCompareTwoTarget(startStation, endStation); + } + + private List addCompareTwoTarget(Station start, Station end){ + return new ArrayList<>(List.of(start, end)); + } + + public List getShortestDistancePath(final String startStationInfo, final String endStationInfo){ + List stations = isSameStation(startStationInfo, endStationInfo); + return graphRepository.getShortestDistance(stations.get(0), stations.get(1)); + } + + public List getShortestTimePath(final String startStationInfo, final String endStationInfo){ + List stations = isSameStation(startStationInfo, endStationInfo); + return graphRepository.getShortestTime(stations.get(0), stations.get(1)); + } + + public List getTotalShortestDistanceAndShortestTime(final List path){ + for(int target = 0; target < path.size() - 1; target++){ + Station startStation = stationRepository.findByName(path.get(target)); + Station nextStation = stationRepository.findByName(path.get(target + 1)); + int[] data = getTargetDistanceAndTime(startStation, nextStation); + totalDistance += data[ZERO]; + totalTime += data[ONE]; + } + return new ArrayList(List.of(totalDistance, totalTime)); + } + + private int[] getTargetDistanceAndTime(final Station startStation, final Station nexStation){ + int[] data = getDistanceAndTimeAccessConnectData(startStation, nexStation); + if (data[ZERO] == NEGATIVE) { + data = getDistanceAndTimeAccessConnectData(nexStation, startStation); + } + return data; + } + + private int[] getDistanceAndTimeAccessConnectData(final Station startStation, final Station nexStation){ + int[] data = {NEGATIVE, NEGATIVE}; + for (ConnectStationNode connectData : startStation.getConnectStationNodes()) { + if (connectData.getStation().isEqualName(nexStation.getName())) { + data[ZERO] = connectData.getDistance(); + data[ONE] = connectData.getTime(); + } + } + return data; + } +} diff --git a/src/main/java/subway/service/SubwayService.java b/src/main/java/subway/service/SubwayService.java index 4e155bbf1..6db1712b7 100644 --- a/src/main/java/subway/service/SubwayService.java +++ b/src/main/java/subway/service/SubwayService.java @@ -1,27 +1,20 @@ package subway.service; import subway.domain.Station; +import subway.repository.GraphRepository; import subway.repository.StationRepository; import subway.repository.SubwayRepository; import subway.util.exception.SameStationException; +import java.util.ArrayList; +import java.util.List; + import static subway.util.message.ExceptionMessage.SAME_AS; public class SubwayService { private final SubwayRepository subwayRepository = SubwayRepository.getInstance(); - private final StationRepository stationRepository = StationRepository.getInstance(); public void initSubway(){ subwayRepository.initSubway(); } - - public void getShortestDistance(final String startStationInfo, final String endStationInfo){ - Station startStation = stationRepository.findByName(startStationInfo); - Station endStation = stationRepository.findByName(endStationInfo); - isSameStation(startStation, endStation); - } - - private void isSameStation(final Station start, final Station end){ - throw new SameStationException(SAME_AS.getValue()); - } } diff --git a/src/main/java/subway/util/constants/LineName.java b/src/main/java/subway/util/constants/LineName.java index f56b6b094..a9ac32e6c 100644 --- a/src/main/java/subway/util/constants/LineName.java +++ b/src/main/java/subway/util/constants/LineName.java @@ -13,11 +13,11 @@ public enum LineName implements EnumUtil{ @Override public String getKey() { - return lineName; + return name(); } @Override public String getValue() { - return name(); + return lineName; } } diff --git a/src/main/java/subway/util/constants/StationName.java b/src/main/java/subway/util/constants/StationName.java index f2ed185f3..59cacd77a 100644 --- a/src/main/java/subway/util/constants/StationName.java +++ b/src/main/java/subway/util/constants/StationName.java @@ -7,8 +7,7 @@ public enum StationName implements EnumUtil{ SOUTH_TERMINAL("남부터미널역"), MAEBONG("매봉역"), YANGJAE("양재역"), - YANGJAE_CITIZEN_FOREST("양재시민의숲역"), - STATION_SUFFIX("역"); + YANGJAE_CITIZEN_FOREST("양재시민의숲역"); private String stationName; @@ -19,11 +18,11 @@ public enum StationName implements EnumUtil{ @Override public String getKey() { - return stationName; + return name(); } @Override public String getValue() { - return name(); + return stationName; } } diff --git a/src/main/java/subway/util/exception/NotConnectException.java b/src/main/java/subway/util/exception/NotConnectException.java new file mode 100644 index 000000000..edd774ea4 --- /dev/null +++ b/src/main/java/subway/util/exception/NotConnectException.java @@ -0,0 +1,7 @@ +package subway.util.exception; + +public class NotConnectException extends IllegalArgumentException{ + public NotConnectException(String message){ + super(message); + } +} diff --git a/src/main/java/subway/util/message/ExceptionMessage.java b/src/main/java/subway/util/message/ExceptionMessage.java index d48505b0e..faf8b393d 100644 --- a/src/main/java/subway/util/message/ExceptionMessage.java +++ b/src/main/java/subway/util/message/ExceptionMessage.java @@ -11,8 +11,9 @@ public enum ExceptionMessage implements EnumUtil { , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") , DUPLICATE_MESSAGE("%s을(를) 중복으로 입력할 수 없습니다.") , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다.") - , SAME_AS("출발역과 도착역이 동일합니다."); - private static final String ERROR_TAG = "[ERROR] "; + , SAME_AS("출발역과 도착역이 동일합니다.") + , NO_CONNECT_AS_STATION("%s와 %s는 서로 연결되어있지 않습니다."); + private static final String ERROR_TAG = "\n[ERROR] "; private final String message; public String getMessage(){ diff --git a/src/main/java/subway/util/message/InputMessage.java b/src/main/java/subway/util/message/InputMessage.java index a763bd2fa..354985ab3 100644 --- a/src/main/java/subway/util/message/InputMessage.java +++ b/src/main/java/subway/util/message/InputMessage.java @@ -6,10 +6,9 @@ public enum InputMessage implements EnumUtil { MAIN_SCREEN("## 메인 화면"), SELECT_WANTED("## 원하는 기능을 선택하세요."), ROUTINE("\n## 경로 기준"), - GET_START_STATION("## 출발역을 입력하세요."), + GET_START_STATION("\n## 출발역을 입력하세요."), GET_END_STARTION("\n## 도착역을 입력하세요."), - SELECT_RESULT("## 조회 결과"), - DOT("..."); + SELECT_RESULT("\n## 조회 결과"); private String message; InputMessage(String message){ diff --git a/src/main/java/subway/util/message/OutputMessage.java b/src/main/java/subway/util/message/OutputMessage.java index a586f3470..2fe9e83ea 100644 --- a/src/main/java/subway/util/message/OutputMessage.java +++ b/src/main/java/subway/util/message/OutputMessage.java @@ -3,11 +3,9 @@ import subway.util.constants.EnumUtil; public enum OutputMessage implements EnumUtil { - DASH(" --- "), - TOTAL_DISTANCE(" 총 거리 : "), - TOTAL_TIME(" 총 소요 시간: "), - KILLOMETER("km"), - MINUTE("분"); + DASH("--- "), + TOTAL_DISTANCE("총 거리 : "), + TOTAL_TIME("총 소요 시간: "); private String message; private static final String INFO_TAG = "[INFO] "; diff --git a/src/main/java/subway/view/OutputView.java b/src/main/java/subway/view/OutputView.java index e4d92b2a0..8a608961a 100644 --- a/src/main/java/subway/view/OutputView.java +++ b/src/main/java/subway/view/OutputView.java @@ -4,10 +4,19 @@ import subway.util.message.Menu; import subway.util.message.OutputMessage; +import java.util.List; + public class OutputView { + private static final String KILLOMETER = "km"; + private static final String MINUTE = "분"; + private static final String INFO_TAG = "[INFO] "; public static void printMessage(String message) { System.out.println(message); } + + public static void printLine(){ + System.out.println(); + } public static void printMain(){ System.out.println(InputMessage.MAIN_SCREEN.getValue()); System.out.println(Menu.SELECT_ROUTINE.getValue()); @@ -15,8 +24,21 @@ public static void printMain(){ } public static void printRoutine(){ + System.out.println(InputMessage.ROUTINE.getValue()); System.out.println(Menu.SHORTEST_DISTANCE.getValue()); System.out.println(Menu.SHORTEST_TIME.getValue()); System.out.println(Menu.BACK.getValue()); } + + public static void printResult(final List path, final int totalDistance, final int totalTime){ + System.out.println(InputMessage.SELECT_RESULT.getValue()); + System.out.println(OutputMessage.DASH.getValue()); + System.out.println(OutputMessage.TOTAL_DISTANCE.getValue() + totalDistance + KILLOMETER); + System.out.println(OutputMessage.TOTAL_TIME.getValue() + totalTime + MINUTE); + System.out.println(OutputMessage.DASH.getValue()); + for(String vertex : path){ + System.out.println(INFO_TAG + vertex); + } + OutputView.printLine(); + } } diff --git a/src/main/java/subway/view/validator/StationValidator.java b/src/main/java/subway/view/validator/StationValidator.java index e58fea66b..8f335ff90 100644 --- a/src/main/java/subway/view/validator/StationValidator.java +++ b/src/main/java/subway/view/validator/StationValidator.java @@ -5,13 +5,15 @@ import static subway.util.message.ExceptionMessage.INPUT_MESSAGE; public class StationValidator extends Validator{ + + private static final String STATION_SUFFIX = "역"; public static void validate(final String str){ validateBlank(str); validateStationName(str); } private static void validateStationName(final String input) { - if(!input.endsWith(StationName.STATION_SUFFIX.getKey())){ + if(!input.endsWith(STATION_SUFFIX)){ throw new IllegalArgumentException(String.format(INPUT_MESSAGE.getValue(), "역 이름을 올바르게 입력해주세요.")); }; } diff --git a/src/test/java/subway/JGraphtTest.java b/src/test/java/subway/JGraphtTest.java index 4f5f76536..6ed295dd5 100644 --- a/src/test/java/subway/JGraphtTest.java +++ b/src/test/java/subway/JGraphtTest.java @@ -22,7 +22,7 @@ public void getDijkstraShortestPath() { DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(graph); List shortestPath = dijkstraShortestPath.getPath("v3", "v1").getVertexList(); - + System.out.println(shortestPath); assertThat(shortestPath.size()).isEqualTo(3); } }