diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..16cc24143 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,36 @@ +### 기능 요구사항 + +[ ✅ ] 주어진 지하철 정보를 초기화한다. + +[ ✅ ] 아래와 같이 입력을 받는다. +``` +## 메인 화면 +1. 경로 조회 +Q. 종료 + +## 원하는 기능을 선택하세요. +1 + +## 경로 기준 +1. 최단 거리 +2. 최소 시간 +B. 돌아가기 + +## 원하는 기능을 선택하세요. +1 + +## 출발역을 입력하세요. +교대역 + +## 도착역을 입력하세요. +양재역 +``` + - 입력 받을 때, 경로 조회 시 출발역과 도착역이 같으면 에러를 출력한다. + - 정상적으로 입력하지 않았다면, 에러를 출력한다. + +[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 0bcf786cc..601fd4779 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -1,10 +1,30 @@ package subway; +import subway.controller.GraphController; +import subway.controller.LineController; +import subway.controller.StationController; +import subway.controller.SubwayController; +import subway.view.InputView; +import subway.view.OutputView; + 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); - // TODO: 프로그램 구현 + 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/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..2944e2b78 --- /dev/null +++ b/src/main/java/subway/controller/SubwayController.java @@ -0,0 +1,95 @@ +package subway.controller; + +import subway.service.GraphService; +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 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(){ + subwayService.initSubway(); + } + + public void start(){ + while(questionIsproceed()){ + try{ + questionRoutine(); + } catch(IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + questionRoutine(); + } + } + } + + 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.BACK.getKey())){ + questionRoutine(); + } + List totalInfo = new ArrayList<>(); + if(input.equals(Menu.SHORTEST_DISTANCE.getKey())){ + totalInfo = getShortestDistance(); + } + if(input.equals(Menu.SHORTEST_TIME.getKey())){ + totalInfo = getShortestTime(); + } + savetotalInfo(totalInfo); + OutputView.printResult(path, totalDistance, totalTime); + } + + private List getShortestDistance(){ + String startStationInfo = InputView.inputStation(InputMessage.GET_START_STATION.getValue()); + String endStationInfo = InputView.inputStation(InputMessage.GET_END_STARTION.getValue()); + 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 new file mode 100644 index 000000000..1cb7dbc0f --- /dev/null +++ b/src/main/java/subway/domain/ConnectStationNode.java @@ -0,0 +1,33 @@ +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); + } + + 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 f4d738d5a..8036d54f6 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -1,15 +1,33 @@ 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); + } + + public String toString(){ + return 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..c4d275e80 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/Station.java @@ -1,15 +1,36 @@ package subway.domain; +import java.util.*; + 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); + } + + public List getConnectStationNodes() { + return Collections.unmodifiableList(connectStationNodes); + } + + public String toString(){ + return 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/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 new file mode 100644 index 000000000..8f2a3fddd --- /dev/null +++ b/src/main/java/subway/repository/LineRepository.java @@ -0,0 +1,56 @@ +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 LineRepository(){ + + } + + public void initLine(){ + for (LineName lineName : LineName.values()) { + Line line = Line.create(lineName.getValue()); + 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..4f5fd154e --- /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.getValue()); + 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(), name))); + } + + 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..436eff263 --- /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.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(); + + 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.getValue()); + addStationsInLine(line); + } + } + + private void initConnectInfo(){ + 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.getValue())){ + initStationsInLine(line, twoLineStations); + } + + if(line.isEqualName(LineName.LINE_3.getValue())){ + initStationsInLine(line, threeLineStations); + } + + if(line.isEqualName(LineName.SHIN_BUNDANG.getValue())){ + 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/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/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..6db1712b7 --- /dev/null +++ b/src/main/java/subway/service/SubwayService.java @@ -0,0 +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(); + + 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..a9ac32e6c --- /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 name(); + } + + @Override + public String getValue() { + return lineName; + } +} 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..59cacd77a --- /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 name(); + } + + @Override + public String getValue() { + return stationName; + } +} 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/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/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 new file mode 100644 index 000000000..faf8b393d --- /dev/null +++ b/src/main/java/subway/util/message/ExceptionMessage.java @@ -0,0 +1,36 @@ +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(이)가 존재하지 않습니다.") + , SAME_AS("출발역과 도착역이 동일합니다.") + , NO_CONNECT_AS_STATION("%s와 %s는 서로 연결되어있지 않습니다."); + private static final String ERROR_TAG = "\n[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; + } +} 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..354985ab3 --- /dev/null +++ b/src/main/java/subway/util/message/InputMessage.java @@ -0,0 +1,27 @@ +package subway.util.message; + +import subway.util.constants.EnumUtil; + +public enum InputMessage implements EnumUtil { + MAIN_SCREEN("## 메인 화면"), + SELECT_WANTED("## 원하는 기능을 선택하세요."), + ROUTINE("\n## 경로 기준"), + GET_START_STATION("\n## 출발역을 입력하세요."), + GET_END_STARTION("\n## 도착역을 입력하세요."), + SELECT_RESULT("\n## 조회 결과"); + + 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..2fe9e83ea --- /dev/null +++ b/src/main/java/subway/util/message/OutputMessage.java @@ -0,0 +1,25 @@ +package subway.util.message; + +import subway.util.constants.EnumUtil; + +public enum OutputMessage implements EnumUtil { + DASH("--- "), + TOTAL_DISTANCE("총 거리 : "), + TOTAL_TIME("총 소요 시간: "); + + 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..8a608961a --- /dev/null +++ b/src/main/java/subway/view/OutputView.java @@ -0,0 +1,44 @@ +package subway.view; + +import subway.util.message.InputMessage; +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()); + System.out.println(Menu.EXIT.getValue()); + } + + 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/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..8f335ff90 --- /dev/null +++ b/src/main/java/subway/view/validator/StationValidator.java @@ -0,0 +1,20 @@ +package subway.view.validator; + +import subway.util.constants.StationName; + +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(STATION_SUFFIX)){ + 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()); + } + } +} 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); } }