Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
57 changes: 12 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,52 +200,19 @@ public class StationRepository {

<br>

## ❗️힌트
### 최단 경로 라이브러리
- jgrapht 라이브러리를 활용하면 간편하게 최단거리를 조회할 수 있음
- Dijkstra 알고리즘을 반드시 이해할 필요는 없고 미션에 적용할 정도로만 이해하면 됨
- JGraphtTest 클래스의 테스트를 활용하여 미션에 필요한 라이브러리의 기능을 학습할 수 있음
- 정점(vertex)과 간선(edge), 그리고 가중치 개념을 이용
- 정점: 지하철역
- 간선: 지하철역 연결정보
- 가중치: 거리 or 소요 시간
- 최단 거리 기준 조회 시 가중치를 거리로 설정
## 기능 구현 목록
- Line 안에 Station list 변수 생성 및 추가 기능 구현
- 구간 객체 생성
- JGrapht 활용하여 시간, 거리 개념의 구간 정보 가짐
- 최단거리, 최단시간 도출해내는 기능 구현
- Line 객체가 구간 거리, 구간 시간 정보가지도록 구현
- 초기화 작업
- Manager 디렉토리 생성하여 초기화 작업하는 기능 구현
- Controller 생성하고 프로그램 실행 기능 구현
- Menu 생성하여 버튼 동작 기능 구현
- view 담당 디렉토리 생성
- Input, Output, Error

```java
@Test
public void getDijkstraShortestPath() {
WeightedMultigraph<String, DefaultWeightedEdge> graph
= new WeightedMultigraph(DefaultWeightedEdge.class);
graph.addVertex("v1");
graph.addVertex("v2");
graph.addVertex("v3");
graph.setEdgeWeight(graph.addEdge("v1", "v2"), 2);
graph.setEdgeWeight(graph.addEdge("v2", "v3"), 2);
graph.setEdgeWeight(graph.addEdge("v1", "v3"), 100);

DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(graph);
List<String> shortestPath = dijkstraShortestPath.getPath("v3", "v1").getVertexList();

assertThat(shortestPath.size()).isEqualTo(3);
}
```

#### 테스트 설명

<img src="image/dijkstra-sample.png" width=400>

- 역 사이의 거리를 고려하지 않는 경우 V1->V3 경로가 최단 경로
- 역 사이의 거리를 고려할 경우 V1->V3 경로의 거리는 100km, V1->V2->V3 경로의 거리는 4km이므로 최단 경로는 V1->V2->V3

<br>

## 📈 진행 요구사항
- 미션은 [java-subway-path-precourse 저장소](https://github.com/woowacourse/java-subway-path-precourse) 를 fork/clone해 시작한다.
- 기능을 구현하기 전에 java-subway-path-precourse/docs/README.md 파일에 구현할 기능 목록을 정리해 추가한다.
- git의 commit 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다.
- [AngularJS Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 commit log를 남긴다.
- [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 절차를 따라 미션을 제출한다.
- [프리코스 과제 FAQ](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse/faq) 문서를 참고하여 진행할 수 있다.
<br>

## 📝 License
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/subway/Application.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package subway;

import java.util.Scanner;
import subway.controller.UserController;

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

import subway.domain.Line;
import subway.domain.LineRepository;
import subway.domain.Station;
import subway.domain.StationRepository;

public class InitializingManager {
private static final String[] defaultStations = {"교대역", "강남역", "역삼역", "남부터미널역", "양재역", "양재시민의숲역", "매봉역"};
private static final String[] defaultLines = {"2호선", "3호선", "신분당선"};
private static final String[][] defaultInLineStations = {{"교대역", "강남역", "역삼역"}, {"교대역", "남부터미널역", "양재역", "매봉역"},
{"강남역", "양재역", "양재시민의숲역"}};

private static final int[][] defaultLineDistance = {{2, 2}, {3, 6, 1}, {2, 10}};
private static final int[][] defaultLineTime = {{3, 3}, {2, 5, 1}, {8, 3}};

public static void initialize() {
initiateStation();
initiateLine();
initiateInterval();
}

private static void initiateStation() {
for (String station : defaultStations) {
StationRepository.addStation(new Station(station));
}
}

private static void initiateLine() {
for (int i = 0; i < defaultLines.length; i++) {
LineRepository.addLine(
new Line(defaultLines[i], defaultInLineStations[i], defaultLineDistance[i], defaultLineTime[i]));
}
}

private static void initiateInterval() {
for (Line line : LineRepository.lines()) {
line.registerInterval();
}
}

}
32 changes: 32 additions & 0 deletions src/main/java/subway/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package subway.controller;

import subway.domain.MenuRepository;
import subway.userinterface.ErrorOutput;
import subway.userinterface.Input;

public class UserController {
public static void start() {
InitializingManager.initialize();
boolean runStatus = true;
while (runStatus) {
Input.printMainMenu();
runStatus = startMainMenu();
}
Input.closeScanner();
}

private static boolean startMainMenu() {
String input = Input.newInput().toUpperCase();
if (ErrorOutput.isWrongMainMenuInput(input)) {
return true;
}

for (String key : MenuRepository.mainMenu.keySet()) {
if (input.equals(key)) {
MenuRepository.mainMenu.get(key).run();
return true;
}
}
return false;
}
}
50 changes: 50 additions & 0 deletions src/main/java/subway/domain/Interval.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package subway.domain;

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

import java.util.List;

public class Interval {
public static WeightedMultigraph<Station, DefaultWeightedEdge> distanceInterval = new WeightedMultigraph(DefaultWeightedEdge.class);
public static WeightedMultigraph<Station, DefaultWeightedEdge> timeInterval = new WeightedMultigraph(DefaultWeightedEdge.class);

public static void registerIntervals(List<Station> stationInLine, List<Integer> distance, List<Integer> time) {
for (Station station : stationInLine) {
distanceInterval.addVertex(station);
timeInterval.addVertex(station);
}

for (int i = 0; i < stationInLine.size() - 1; i++) {
distanceInterval.setEdgeWeight(distanceInterval.addEdge(stationInLine.get(i), stationInLine.get(i + 1)), distance.get(i));
timeInterval.setEdgeWeight(timeInterval.addEdge(stationInLine.get(i), stationInLine.get(i + 1)), time.get(i));
}
}

public static List<Station> shortestDistancePath(Station start, Station end) {
DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(distanceInterval);
return dijkstraShortestPath.getPath(start, end).getVertexList();
}

public static List<Station> shortestTimePath(Station start, Station end) {
DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(timeInterval);
return dijkstraShortestPath.getPath(start, end).getVertexList();
}

public static int getTotalDistance(List<Station> path) {
int total = 0;
for (int i = 0; i < path.size() - 1; i++) {
total += distanceInterval.getEdgeWeight(distanceInterval.getEdge(path.get(i), path.get(i + 1)));
}
return total;
}

public static int getTotalTime(List<Station> path) {
int total = 0;
for (int i = 0; i < path.size() - 1; i++) {
total += timeInterval.getEdgeWeight(timeInterval.getEdge(path.get(i), path.get(i + 1)));
}
return total;
}
}
37 changes: 35 additions & 2 deletions src/main/java/subway/domain/Line.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
package subway.domain;

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

public class Line {
private String name;
private final List<Station> stationInLine = new ArrayList<>();
private final List<Integer> distanceInterval = new ArrayList<>();
private final List<Integer> timeInterval = new ArrayList<>();

public Line(String name) {
public Line(String name, String[] stations, int[] distance, int[] time) {
this.name = name;
for (String station : stations) {
addStationInLine(StationRepository.findStationByName(station));
}
for (int i = 0; i < distance.length; i++) {
addDistanceInterval(distance[i]);
addTimeInterval(time[i]);
}
}

private void addStationInLine(Station station) {
stationInLine.add(station);
}

private void addDistanceInterval(int distance) {
distanceInterval.add(distance);
}

private void addTimeInterval(int time) {
timeInterval.add(time);
}

public void registerInterval() {
Interval.registerIntervals(stationInLine, distanceInterval, timeInterval);
}

public String getName() {
return name;
}

// 추가 기능 구현
public List<Station> stationsInLine() {
return Collections.unmodifiableList(stationInLine);
}

}
32 changes: 32 additions & 0 deletions src/main/java/subway/domain/MenuRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package subway.domain;

import subway.menu.mainmenu.MainMenu;
import subway.menu.mainmenu.QuitMenu;
import subway.menu.mainmenu.SearchPathMenu;
import subway.menu.searchmenu.ExitMenu;
import subway.menu.searchmenu.SearchMenu;
import subway.menu.searchmenu.SearchShortestDistanceMenu;
import subway.menu.searchmenu.SearchShortestTimeMenu;

import java.util.*;

public class MenuRepository {
public static final List<String> mainMenuButtons = new ArrayList<>(Arrays.asList(SearchPathMenu.MENU_BUTTON, QuitMenu.MENU_BUTTON));
public static final List<String> searchMenuButtons = new ArrayList<>(
Arrays.asList(SearchShortestDistanceMenu.MENU_BUTTON, SearchShortestTimeMenu.MENU_BUTTON, ExitMenu.MENU_BUTTON));

public static final List<String> mainMenuNames = new ArrayList<>(Arrays.asList(SearchPathMenu.MENU_NAME, QuitMenu.MENU_NAME));
public static final List<String> searchMenuNames = new ArrayList<>(
Arrays.asList(SearchShortestDistanceMenu.MENU_NAME, SearchShortestTimeMenu.MENU_NAME, ExitMenu.MENU_NAME));

public static final Map<String, MainMenu> mainMenu = new HashMap<>();
public static final Map<String, SearchMenu> searchMenu = new HashMap<>();

static {
mainMenu.put(SearchPathMenu.MENU_BUTTON, new SearchPathMenu());

searchMenu.put(SearchShortestDistanceMenu.MENU_BUTTON, new SearchShortestDistanceMenu());
searchMenu.put(SearchShortestTimeMenu.MENU_BUTTON, new SearchShortestTimeMenu());
}

}
11 changes: 11 additions & 0 deletions src/main/java/subway/domain/StationRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,21 @@ public static void addStation(Station station) {
stations.add(station);
}

public static Station findStationByName(String name) {
return stations.stream()
.filter(station -> station.getName().equals(name))
.findFirst()
.get();
}

public static boolean deleteStation(String name) {
return stations.removeIf(station -> Objects.equals(station.getName(), name));
}

public static boolean isStationPresent(String name) {
return stations.stream().anyMatch(station -> station.getName().equals(name));
}

public static void deleteAll() {
stations.clear();
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/subway/menu/mainmenu/MainMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package subway.menu.mainmenu;

public interface MainMenu {
void run();
}
6 changes: 6 additions & 0 deletions src/main/java/subway/menu/mainmenu/QuitMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package subway.menu.mainmenu;

public class QuitMenu {
public static final String MENU_BUTTON = "Q";
public static final String MENU_NAME = "종료";
}
33 changes: 33 additions & 0 deletions src/main/java/subway/menu/mainmenu/SearchPathMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package subway.menu.mainmenu;

import subway.domain.MenuRepository;
import subway.userinterface.ErrorOutput;
import subway.userinterface.Input;

public class SearchPathMenu implements MainMenu{
public static final String MENU_BUTTON = "1";
public static final String MENU_NAME = "경로 조회";

public void run() {
boolean runStatus = true;
while(runStatus) {
Input.printSearchMenu();
runStatus = runSearchMenu();
}
}

private boolean runSearchMenu() {
String input = Input.newInput().toUpperCase();
if (ErrorOutput.isWrongSearchMenuInput(input)) {
return true;
}

for (String key : MenuRepository.searchMenu.keySet()) {
if (input.equals(key)) {
MenuRepository.searchMenu.get(key).run();
return true;
}
}
return false;
}
}
7 changes: 7 additions & 0 deletions src/main/java/subway/menu/searchmenu/ExitMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package subway.menu.searchmenu;

public class ExitMenu {
public static final String MENU_BUTTON = "B";
public static final String MENU_NAME = "돌아가기";

}
5 changes: 5 additions & 0 deletions src/main/java/subway/menu/searchmenu/SearchMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package subway.menu.searchmenu;

public interface SearchMenu {
void run();
}
Loading