Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
140 changes: 140 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# 지하철 노선도 경로 조회 미션
- 등록된 지하철 노선도에서 경로를 조회하는 기능을 구현한다.

<br>

## 🚀 기능 요구사항

> 프리코스 3주차 미션에서 사용한 코드를 참고해도 무관하다.

### 초기 설정
- 프로그램 시작 시 역, 노선, 구간 정보를 초기 설정 해야 한다.
- 거리와 소요 시간은 양의 정수이며 단위는 km와 분을 의미한다.
- 아래의 사전 등록 정보로 반드시 초기 설정을 한다.

```
1. 지하철역으로 교대역, 강남역, 역삼역, 남부터미널역, 양재역, 양재시민의숲역, 매봉역이 등록되어 있다.
2. 지하철 노선으로 2호선, 3호선, 신분당선이 등록되어 있다.
3. 노선에 역이 아래와 같이 등록되어 있다.(왼쪽 끝이 상행 종점)
- 2호선: 교대역 - ( 2km / 3분 ) - 강남역 - ( 2km / 3분 ) - 역삼역
- 3호선: 교대역 - ( 3km / 2분 ) - 남부터미널역 - ( 6km / 5분 ) - 양재역 - ( 1km / 1분 ) - 매봉역
- 신분당선: 강남역 - ( 2km / 8분 ) - 양재역 - ( 10km / 3분 ) - 양재시민의숲역
```

## Livenow 프로그램 구현
## 🚩 객체 책임 (아는 것과 하는 것)
### **지하철 역**
- 아는 것
- 역 이름

<br>

- 하는 것


### **지하철 역 저장소**
- 아는 것
- 지하철 역

<br>

- 하는 것
- 지하철 역 저장

### **거리**
- 아는 것
- 거리(km)

<br>

- 하는 것

### **시간**
- 아는 것
- 분

<br>

- 하는 것

### **거리(분)**
- 아는 것
- 거리(분)

<br>

- 하는 것

### **노선**
- 아는 것
- 노선 이름
- 지하철 역(들)

<br>

- 하는 것

### **라인(들)**
- 아는 것
- 라인

<br>

- 하는 것
### **라인 저장소**
- 아는 것
- 라인

<br>

- 하는 것
- 라인저장


## 🚩 구현할 기능
### **메인 화면**
- [x] 객체 모델링
- [x] 메인화면 출력
- [x] 보장된 값 입력
- 보장된 값(1,Q 만을 허용)
- 보장된 값이 아닐 시 에러 출력
- `SelectionException`
- [x] Q가 입력될 시, 종료 ( 소문자 q 도 허용 함. )

### **경로 조회**
- [x] 경로 조회 화면 출력
- [x] 보장된 값 입력
- 보장된 값(1,2,B 만을 허용)
- 보장된 값이 아닐 시 에러 출력
- `SelectionException`
- [x] 지하철 역 저장
- [x] 노선 저장
- [x] 구간 저장
- [x] 초기 저장 (시간(분) 미포함)
- [x] 초기 저장(구간마다 거리, 시간 포함)
- [x] 1을 입력시 최단 거리 조회
- [x] 출발역을 입력
- [x] 저장소에 저장되어 있는 지하철 역이 아닐 시 에러가 발생한다.
- `StationException`
- [x] 도착역 역을 입력
- [x] 저장소에 저장되어 있는 지하철 역이 아닐 시 에러가 발생한다.
- `StationException`
- [x] 출발역과 도착역이 같으면 에러를 출력한다
- `StationException`
- [x] 최단 거리를 조회한다.

- [x] 2를 입력시 최소 시간 조회
- [x] 출발역을 입력
- [x] 저장소에 저장되어 있는 지하철 역이 아닐 시 에러가 발생한다.
- `에러 발생`
- [x] 도착역 역을 입력
- [x] 저장소에 저장되어 있는 지하철 역이 아닐 시 에러가 발생한다.
- `에러 발생`
- [x] 출발역과 도착역이 같으면 에러를 출력한다
- `에러 발생`
- [x] 최소 시간를 조회한다.

- [ ] 최단 거리 최소시간 같이 출력

### **에러가 발생해도 서비스가 죽지 않아야 한다**
- [x] 에러 핸들링
11 changes: 11 additions & 0 deletions src/main/java/subway/Application.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
package subway;

import subway.domain.section.SectionRepository;
import subway.domain.section.SectionService;
import subway.domain.station.StationService;
import subway.view.InputView;
import subway.view.OutputView;

import java.util.Scanner;

public class Application {
public static void main(String[] args) {
final Scanner scanner = new Scanner(System.in);
// TODO: 프로그램 구현
DataInitService dataInitService = new DataInitService(new StationService(), new SectionService(new SectionRepository()));
dataInitService.init();

SubwayManageApp subwayManageApp = new SubwayManageApp(new InputView(scanner), new OutputView(new StringBuilder()));
subwayManageApp.startApp();
}
}
120 changes: 120 additions & 0 deletions src/main/java/subway/DataInitService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package subway;

import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.WeightedMultigraph;
import subway.domain.distanceTime.Distance;
import subway.domain.distanceTime.Time;
import subway.domain.section.SectionService;
import subway.domain.section.dto.SectionSaveReqDto;
import subway.domain.section.dto.SectionStationAddReqDto;
import subway.domain.station.StationService;
import subway.domain.station.dto.StationSaveReqDto;

public class DataInitService {
private static final String STATION_GYODAE = "교대역";
private static final String STATION_GANGNAM = "강남역";
private static final String STATION_YEOKSAM = "역삼역";
private static final String STATION_SOUTH_TERMINAL = "남부터미널역";
private static final String STATION_YANGJAE = "양재역";
private static final String STATION_CITIZEN_FOREST = "양재시민의숲역";
private static final String STATION_MAEBONG = "매봉역";
private static final String LINE_TWO = "2호선";
private static final String LINE_THREE = "3호선";
private static final String LINE_SINBUNDANG = "신분당선";

private static final int SECOND = 2;
private static final int THIRD = 3;

private static final int KM_ONE = 1;
private static final int KM_TWO = 2;
private static final int KM_THREE = 3;
private static final int KM_SIX = 6;
private static final int KM_TEN = 10;

private static final int MINUTE_ONE = 1;
private static final int MINUTE_TWO = 2;
private static final int MINUTE_THREE = 3;
private static final int MINUTE_FIVE = 5;
private static final int MINUTE_EIGHT = 8;

private final StationService stationService;
private final SectionService sectionService;

public DataInitService(StationService stationService, SectionService sectionService) {
this.stationService = stationService;
this.sectionService = sectionService;
}

public void init() {
saveStation();
saveSection();
saveDistance();
saveTime();
}

private void saveDistance() {
WeightedMultigraph<String, DefaultWeightedEdge> graph = getStringDefaultWeightedEdgeWeightedMultigraph();

graph.setEdgeWeight(graph.addEdge(STATION_GYODAE, STATION_GANGNAM), new Distance(KM_TWO).getKm());
graph.setEdgeWeight(graph.addEdge(STATION_GANGNAM, STATION_YEOKSAM), new Distance(KM_TWO).getKm());

graph.setEdgeWeight(graph.addEdge(STATION_GYODAE, STATION_SOUTH_TERMINAL), new Distance(KM_THREE).getKm());
graph.setEdgeWeight(graph.addEdge(STATION_SOUTH_TERMINAL, STATION_YANGJAE), new Distance(KM_SIX).getKm());
graph.setEdgeWeight(graph.addEdge(STATION_YANGJAE, STATION_MAEBONG), new Distance(KM_ONE).getKm());

graph.setEdgeWeight(graph.addEdge(STATION_GANGNAM, STATION_YANGJAE), new Distance(KM_TWO).getKm());
graph.setEdgeWeight(graph.addEdge(STATION_YANGJAE, STATION_CITIZEN_FOREST), new Distance(KM_TEN).getKm());

DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(graph);
SearchService.addDijkstraShortestPath(dijkstraShortestPath);
}

private void saveTime() {
WeightedMultigraph<String, DefaultWeightedEdge> graph = getStringDefaultWeightedEdgeWeightedMultigraph();

graph.setEdgeWeight(graph.addEdge(STATION_GYODAE, STATION_GANGNAM), new Time(MINUTE_THREE).getMinute());
graph.setEdgeWeight(graph.addEdge(STATION_GANGNAM, STATION_YEOKSAM), new Time(MINUTE_THREE).getMinute());

graph.setEdgeWeight(graph.addEdge(STATION_GYODAE, STATION_SOUTH_TERMINAL), new Time(MINUTE_TWO).getMinute());
graph.setEdgeWeight(graph.addEdge(STATION_SOUTH_TERMINAL, STATION_YANGJAE), new Time(MINUTE_FIVE).getMinute());
graph.setEdgeWeight(graph.addEdge(STATION_YANGJAE, STATION_MAEBONG), new Time(MINUTE_ONE).getMinute());

graph.setEdgeWeight(graph.addEdge(STATION_GANGNAM, STATION_YANGJAE), new Time(MINUTE_EIGHT).getMinute());
graph.setEdgeWeight(graph.addEdge(STATION_YANGJAE, STATION_CITIZEN_FOREST), new Time(MINUTE_THREE).getMinute());

DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(graph);
SearchService.addDijkstraShortestPath(dijkstraShortestPath);
}

private WeightedMultigraph<String, DefaultWeightedEdge> getStringDefaultWeightedEdgeWeightedMultigraph() {
WeightedMultigraph<String, DefaultWeightedEdge> graph = new WeightedMultigraph(DefaultWeightedEdge.class);
graph.addVertex(STATION_GYODAE);
graph.addVertex(STATION_GANGNAM);
graph.addVertex(STATION_YEOKSAM);
graph.addVertex(STATION_SOUTH_TERMINAL);
graph.addVertex(STATION_YANGJAE);
graph.addVertex(STATION_MAEBONG);
graph.addVertex(STATION_CITIZEN_FOREST);
return graph;
}

private void saveSection() {
sectionService.saveSection(new SectionSaveReqDto(LINE_TWO, STATION_GYODAE, STATION_YEOKSAM));
sectionService.addStation(new SectionStationAddReqDto(LINE_TWO, STATION_GANGNAM, SECOND));

sectionService.saveSection(new SectionSaveReqDto(LINE_THREE, STATION_GYODAE, STATION_MAEBONG));
sectionService.addStation(new SectionStationAddReqDto(LINE_THREE, STATION_SOUTH_TERMINAL, SECOND));
sectionService.addStation(new SectionStationAddReqDto(LINE_THREE, STATION_YANGJAE, THIRD));

sectionService.saveSection(new SectionSaveReqDto(LINE_SINBUNDANG, STATION_GANGNAM, STATION_CITIZEN_FOREST));
sectionService.addStation(new SectionStationAddReqDto(LINE_SINBUNDANG, STATION_YANGJAE, SECOND));
}

private void saveStation() {
String[] stationNames = {STATION_GYODAE, STATION_GANGNAM, STATION_YEOKSAM, STATION_SOUTH_TERMINAL, STATION_YANGJAE, STATION_CITIZEN_FOREST, STATION_MAEBONG};
for (String stationName : stationNames) {
stationService.saveStation(new StationSaveReqDto(stationName));
}
}
}
79 changes: 79 additions & 0 deletions src/main/java/subway/SearchService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package subway;

import org.jgrapht.GraphPath;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import subway.domain.station.Station;
import subway.domain.station.StationRepository;
import subway.exception.ErrorCode;
import subway.exception.StationException;
import subway.view.InputView;
import subway.view.screen.SearchView;

import java.util.ArrayList;
import java.util.List;

public class SearchService {
private static final List<DijkstraShortestPath> dijkstraShortestPaths = new ArrayList<>();
private static final int DISTANCE_INDEX = 0;
private static final int TIME_INDEX = 1;

private final InputView inputView;
private final SearchView searchView;

public SearchService(InputView inputView, SearchView searchView) {
this.inputView = inputView;
this.searchView = searchView;
}

public static void addDijkstraShortestPath(DijkstraShortestPath dijkstraShortestPath) {
dijkstraShortestPaths.add(dijkstraShortestPath);
}

public void findShortestDistance() {
searchView.printAdd();
String firstStationName = inputView.inputNextLine();
Station firstStation = StationRepository.findByName(firstStationName);

searchView.printSecondAdd();
String secondStationName = inputView.inputNextLine();
Station secondStation = StationRepository.findByName(secondStationName);
checkSameName(firstStationName, secondStationName);

searchView.printAfterAdd();
printDistance(firstStation, secondStation);
}

public void findShortestTime() {
searchView.printAdd();
String firstStationName = inputView.inputNextLine();
Station firstStation = StationRepository.findByName(firstStationName);

searchView.printSecondAdd();
String secondStationName = inputView.inputNextLine();
Station secondStation = StationRepository.findByName(secondStationName);
checkSameName(firstStationName, secondStationName);

searchView.printAfterAdd();
printTime(firstStation, secondStation);
}

private void printTime(Station firstStation, Station secondStation) {
DijkstraShortestPath dijkstraShortestPathDistance = dijkstraShortestPaths.get(TIME_INDEX);
double pathWeight = dijkstraShortestPathDistance.getPathWeight(firstStation.getName(), secondStation.getName());
GraphPath path = dijkstraShortestPathDistance.getPath(firstStation.getName(), secondStation.getName());
searchView.printTimeList(path, pathWeight);
}

private void printDistance(Station firstStation, Station secondStation) {
DijkstraShortestPath dijkstraShortestPathDistance = dijkstraShortestPaths.get(DISTANCE_INDEX);
double pathWeight = dijkstraShortestPathDistance.getPathWeight(firstStation.getName(), secondStation.getName());
GraphPath path = dijkstraShortestPathDistance.getPath(firstStation.getName(), secondStation.getName());
searchView.printDistanceList(path, pathWeight);
}

private void checkSameName(String firstStationName, String secondStationName) {
if (firstStationName.equals(secondStationName)) {
throw new StationException(ErrorCode.STATION_SAME_NAME);
}
}
}
Loading