Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bd3cddf
docs: docs/README 추가
doorisopen Dec 19, 2020
2833e4d
docs: 기능 구현 목록 추가
doorisopen Dec 19, 2020
88f7e81
feat: 지하철 노선도 경로 조회를 시작한다
doorisopen Dec 19, 2020
af1d966
docs: 기능 구현 목록 수정
doorisopen Dec 19, 2020
efa9387
feat: 원하는 기능 입력 요청 메시지 출력
doorisopen Dec 19, 2020
0baef33
feat: 출발역과 도착역 입력 요청 메시지 출력
doorisopen Dec 19, 2020
2f1486f
feat: 원하는 기능을 입력한다
doorisopen Dec 19, 2020
241ae3a
feat: 출발역과 도착역을 입력한다
doorisopen Dec 19, 2020
4a8ed06
feat: 메인 화면을 출력한다
doorisopen Dec 19, 2020
dd52c13
feat: 경로 조회 화면을 출력한다
doorisopen Dec 19, 2020
8eaea59
docs: 기능 구현 완료 확인 및 수정
doorisopen Dec 19, 2020
e44a937
feat: 지하철 초기 정보를 저장한다
doorisopen Dec 19, 2020
2f1add9
feat: 노선 초기 정보를 저장한다
doorisopen Dec 19, 2020
6fe3561
feat: 구간 정보 관리 객체 생성
doorisopen Dec 19, 2020
7e9faa8
feat: 메뉴 정보 관리 객체 생성
doorisopen Dec 19, 2020
02e90b7
feat: 선택 가능한 기능인지 검증한다
doorisopen Dec 19, 2020
7bd8eeb
feat: 메인 화면의 메뉴를 선택한다
doorisopen Dec 19, 2020
db867ed
test: 경로 계산을 테스트 한다
doorisopen Dec 19, 2020
c4e4e0e
feat: 선택 가능 메뉴 검증 로직 추가
doorisopen Dec 19, 2020
1c01a90
feat: 메인 화면의 메뉴를 선택한다
doorisopen Dec 19, 2020
1bff171
feat: 역 이름을 출력한다
doorisopen Dec 19, 2020
4b4abc3
feat: 경로 기준을 선택한다
doorisopen Dec 19, 2020
d2f5e44
feat: 출발역과 도착역을 입력한다
doorisopen Dec 19, 2020
9715781
docs: 기능 구현 목록 수정
doorisopen Dec 19, 2020
0a3bedf
feat: 등록된 역을 검색한다
doorisopen Dec 19, 2020
8738b52
feat: 최단 경로를 계산한다
doorisopen Dec 19, 2020
db3a9b2
feat: 초기 정보를 저장한다
doorisopen Dec 19, 2020
a5c6c5f
feat: 최소 시간을 계산한다
doorisopen Dec 19, 2020
3b353da
feat: 경로를 계산한다
doorisopen Dec 19, 2020
8196e83
feat: 경로가 동일할때 검증한다
doorisopen Dec 19, 2020
76a66ca
feat: 역 존재 유무 로직 수정
doorisopen Dec 19, 2020
6458109
feat: 경로를 초기화한다
doorisopen Dec 19, 2020
ff2d5a1
feat: 소요시간을 출력한다
doorisopen Dec 19, 2020
b967732
docs: 구현 완료 목록 확인
doorisopen Dec 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 지하철 노선도 경로 조회 미션
우테코 3기 2차 코딩테스트(2020-12-19 13:00 ~ 18:00)

## 기능 구현 목록
* **입력**
+ [메인 화면]
- [x] 원하는 기능을 입력한다.
+ [경로 조회]
- [x] 원하는 기능을 입력한다.
- [x] 출발역과 도착역을 입력한다.
* **처리**
+ [초기화]
+ [x] 지하철(Station) 초기 정보를 저장한다.
+ [x] 노선(Line) 초기 정보를 저장한다.
+ [ ] 노선에 연결된 역 초기 정보를 저장한다.
+ [메인 화면]
- [x] 메인 화면의 메뉴를 선택한다.
- [예외 처리] 선택 가능한 기능인지 검증한다.
+ [경로 조회]
+ [x] 경로 기준을 선택한다.
- [예외 처리] 선택 가능한 기능인지 검증한다.
+ [x] 등록된 역을 검색한다.
+ [ ] 경로를 조회한다.
- [예외 처리] 출발역이 존재하는지 검증한다.
- [예외 처리] 도착역이 존재하는지 검증한다.
- [예외 처리] 출발역과 도착역이 같은지 검증한다.
- [예외 처리] 출발역과 도착역이 연결되어있는지 검증한다.
+ [x] 경로의 총 거리를 계산한다.
+ [x] 경로의 총 소요 시간을 계산한다.
* **출력**
+ [메인 화면]
- [x] 메인 화면을 출력한다.
+ [경로 조회]
- [x] 경로 조회 화면을 출력한다.
- [x] 총 거리를 출력한다
- [x] 총 소요 시간을 출력한다.
- [x] 출발역 부터 도착역까지 역을 출력한다.
6 changes: 5 additions & 1 deletion src/main/java/subway/Application.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package subway;

import subway.controller.SubwayController;

import java.util.Scanner;

public class Application {
public static void main(String[] args) {
final Scanner scanner = new Scanner(System.in);
// TODO: 프로그램 구현
SubwayController subway = new SubwayController();
subway.start(scanner);
}
}
}
28 changes: 28 additions & 0 deletions src/main/java/subway/controller/SubwayController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package subway.controller;

import subway.domain.MenuType;
import subway.service.InputService;
import subway.view.OutputView;
import subway.service.SubwayService;

import java.util.Scanner;

import static subway.domain.MenuType.MAIN_MENU_RANGE;

public class SubwayController extends InputService {
private final SubwayService subwayService = new SubwayService();

public void start(Scanner scanner) {
String menu = "";
try {
while (!MenuType.MAIN_EXIT.isKeyEquals(menu)) {
OutputView.printMainMenu();
menu = inputSelectMenu(scanner, MAIN_MENU_RANGE);
subwayService.selectMainMenu(scanner, menu);
}
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
start(scanner);
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/subway/domain/LineStationRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package subway.domain;

import org.jgrapht.GraphPath;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.WeightedMultigraph;

import static subway.domain.SubwayPathFactory.creatPathFirstGraph;
import static subway.domain.SubwayPathFactory.creatTimeFirstGraph;

public class LineStationRepository {
private static WeightedMultigraph<String, DefaultWeightedEdge> lineStation
= new WeightedMultigraph<>(DefaultWeightedEdge.class);

public static void addLineStationOfSection(String startStation, String endStation, int weight) {
lineStation.setEdgeWeight(lineStation.addEdge(startStation, endStation), weight);
}

public static void addVertex(String startStation) {
lineStation.addVertex(startStation);
}

public static GraphPath findShortestPath(String start, String end) {
SubwayPathFactory.init();
creatPathFirstGraph();
DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(lineStation);
return dijkstraShortestPath.getPath(start, end);
}

public static GraphPath findShortestTime(String start, String end) {
SubwayPathFactory.init();
creatTimeFirstGraph();
DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(lineStation);
return dijkstraShortestPath.getPath(start, end);
}
}
36 changes: 36 additions & 0 deletions src/main/java/subway/domain/MenuType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package subway.domain;

import java.util.Arrays;
import java.util.List;

public enum MenuType {
MAIN_MENU_RANGE(Arrays.asList("1","2","Q")),
MAIN_SEARCH_PATH("1"),
MAIN_EXIT("Q"),
SEARCH_PATH_MENU_RANGE(Arrays.asList("1","2","B")),
SEARCH_SHORTEST_PATH("1"),
SEARCH_SHORTEST_TIME("2"),
BACK("B");

private String key;
private List<String> keys;

private MenuType(String key) {
this.key = key;
}

private MenuType(List<String> keys) {
this.keys = keys;
}

public boolean isKeyEquals(String menu) {
return this.key.equals(menu);
}

public void validateMenuRange(String menu) {
boolean isContains = this.keys.contains(menu);
if (!isContains) {
throw new IllegalArgumentException("\n[ERROR] 선택할 수 없는 기능입니다.");
}
}
}
29 changes: 29 additions & 0 deletions src/main/java/subway/domain/Section.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package subway.domain;

import org.jgrapht.graph.DefaultWeightedEdge;

public class Section extends DefaultWeightedEdge {
private Station startStation;
private Station endStation;
private int time;
private int distance;

public Section(Station startStation, Station endStation, int time, int distance) {
this.startStation = startStation;
this.endStation = endStation;
this.time = time;
this.distance = distance;
}

public int getTime() {
return time;
}

public int getDistance() {
return distance;
}

public static Section of(Station start, Station end, int time, int distance) {
return new Section(start, end, time, distance);
}
}
4 changes: 4 additions & 0 deletions src/main/java/subway/domain/Station.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ public String getName() {
}

// 추가 기능 구현
@Override
public String toString() {
return "[INFO] " + name + "\n";
}
}
10 changes: 10 additions & 0 deletions src/main/java/subway/domain/StationRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,14 @@ public static boolean deleteStation(String name) {
public static void deleteAll() {
stations.clear();
}

public static void findStationByName(String stationName) {
Station station = stations.stream()
.filter(s -> s.getName().equals(stationName))
.findAny()
.orElse(null);
if (station.equals(null)) {
throw new IllegalArgumentException("\n[ERROR] 해당 역은 존재하지 않습니다.");
}
}
}
57 changes: 57 additions & 0 deletions src/main/java/subway/domain/SubwayPathFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package subway.domain;

import static subway.domain.LineStationRepository.*;
import static subway.domain.StationRepository.findStationByName;

public class SubwayPathFactory {
private static String[] startStations = {"교대역", "강남역", "강남역", "역삼역", "교대역", "남부터미널역", "남부터미널역", "양재역",
"양재역", "매봉역", "강남역", "양재역", "양재역", "양재시민의숲역"};
private static String[] endStations = {"강남역", "교대역", "역삼역", "강남역", "남부터미널역", "교대역", "양재역", "남부터미널역",
"매봉역", "양재역", "양재역", "강남역", "양재시민의숲역", "양재역"};
private static int[] distances = {2, 2, 2, 2, 3, 3, 6, 6, 1, 1, 1, 1, 10, 10};
private static int[] times = {3, 3, 3, 3, 2, 2, 5, 5, 1, 1, 8, 8, 3, 3};

public static void init() {
initStation();
initLine();
initGraphVertex();
}

public static void creatPathFirstGraph() {
for (int i = 0; i < startStations.length; i++) {
addLineStationOfSection(startStations[i], endStations[i], distances[i]);
}
}

public static void creatTimeFirstGraph() {
for (int i = 0; i < startStations.length; i++) {
addLineStationOfSection(startStations[i], endStations[i], times[i]);
}
}

private static void initStation() {
StationRepository.addStation(new Station("교대역"));
StationRepository.addStation(new Station("강남역"));
StationRepository.addStation(new Station("역삼역"));
StationRepository.addStation(new Station("남부터미널역"));
StationRepository.addStation(new Station("양재역"));
StationRepository.addStation(new Station("양재시민의숲역"));
StationRepository.addStation(new Station("매봉역"));
}

private static void initLine() {
LineRepository.addLine(new Line("2호선"));
LineRepository.addLine(new Line("3호선"));
LineRepository.addLine(new Line("신분당선"));
}

private static void initGraphVertex() {
addVertex("교대역");
addVertex("강남역");
addVertex("역삼역");
addVertex("남부터미널역");
addVertex("양재역");
addVertex("양재시민의숲역");
addVertex("매봉역");
}
}
28 changes: 28 additions & 0 deletions src/main/java/subway/service/InputService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package subway.service;

import subway.domain.MenuType;
import subway.view.InputView;

import java.util.Scanner;

public class InputService extends InputView {

public String inputSelectMenu(Scanner scanner, MenuType menuType) {
inputSelectMenuMessage();
String menu = scanner.nextLine();
menuType.validateMenuRange(menu);
return menu;
}

public String inputStartStationName(Scanner scanner) {
inputStartStationNameMessage();
String stationName = scanner.nextLine();
return stationName;
}

public String inputEndStationName(Scanner scanner) {
inputEndStationNameMessage();
String stationName = scanner.nextLine();
return stationName;
}
}
73 changes: 73 additions & 0 deletions src/main/java/subway/service/SearchPathService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package subway.service;

import org.jgrapht.GraphPath;
import subway.domain.LineStationRepository;
import subway.view.OutputView;

import java.util.Scanner;

import static subway.domain.MenuType.*;
import static subway.domain.StationRepository.findStationByName;
import static subway.view.OutputView.printResult;

public class SearchPathService extends InputService {

public boolean selectSearchPathMenu(Scanner scanner, String menu) {
if (SEARCH_SHORTEST_PATH.isKeyEquals(menu)) {
return searchShortestPath(scanner);
}
if (SEARCH_SHORTEST_TIME.isKeyEquals(menu)) {
return searchShortestTime(scanner);
}
if (BACK.isKeyEquals(menu)) {
return true;
}
return false;
}

private boolean searchShortestPath(Scanner scanner) {
try {
String startStationName = inputStartStationName(scanner);
String endStationName = inputEndStationName(scanner);
calculationShortestPath(startStationName, endStationName);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return false;
}
return true;
}

private boolean searchShortestTime(Scanner scanner) {
try {
String startStationName = inputStartStationName(scanner);
String endStationName = inputEndStationName(scanner);
calculationShortestTime(startStationName, endStationName);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return false;
}
return true;
}

private void calculationShortestPath(String startStationName, String endStationName) {
if (startStationName.equals(endStationName)) {
throw new IllegalArgumentException("[ERROR] 출발역과 도착역이 동일합니다.");
}
findStationByName(startStationName);
findStationByName(endStationName);
GraphPath shortestPath = LineStationRepository.findShortestPath(startStationName, endStationName);
GraphPath shortestTime = LineStationRepository.findShortestTime(startStationName, endStationName);
printResult(shortestPath, shortestTime);
}

private void calculationShortestTime(String startStationName, String endStationName) {
if (startStationName.equals(endStationName)) {
throw new IllegalArgumentException("[ERROR] 출발역과 도착역이 동일합니다.");
}
findStationByName(startStationName);
findStationByName(endStationName);
GraphPath shortestPath = LineStationRepository.findShortestPath(startStationName, endStationName);
GraphPath shortestTime = LineStationRepository.findShortestTime(startStationName, endStationName);
printResult(shortestPath, shortestTime);
}
}
Loading