Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
e23b17e
docs: 구현할 기능 목록 작성
kmj990929 Dec 11, 2020
07e92f0
docs: 마크다운 문법에 맞추어 수정
kmj990929 Dec 11, 2020
e60cdf4
docs: 소제목 강조되도록 수정
kmj990929 Dec 11, 2020
aa2a8d0
feat: 메인화면 출력 기능 구현
kmj990929 Dec 11, 2020
6d9a2a9
feat: 원하는 메인 기능 입력 메소드 구현
kmj990929 Dec 11, 2020
ed0ee44
refactor: 필요없는 import문 삭제
kmj990929 Dec 11, 2020
177dd5e
feat: 입력된 메인기능 기호 유효성 검사 메소드 구현
kmj990929 Dec 11, 2020
dbbea34
feat: 기능목록에 존재하는 기능 선택할 떄까지 재입력받는 메소드 구현
kmj990929 Dec 12, 2020
6b157b3
feat: menu를 선택받는 메소드를 scanXXX로 이름 변경
kmj990929 Dec 12, 2020
06226df
feat: 세부기능화면 출력 메소드 구현
kmj990929 Dec 12, 2020
d4984a3
feat: 세부기능 입력받는 메소드 구현
kmj990929 Dec 12, 2020
b316233
refactor: 기능을 클래스로 분리
kmj990929 Dec 12, 2020
86ed8a6
refactor: 세부기능화면 출력 메소드의 중복코드를 정리하여 하나의 메소드로 구현
kmj990929 Dec 12, 2020
f67bb08
style: menu 선택받는 메소드의 이름 변경
kmj990929 Dec 12, 2020
a0252f8
feat: 선택한 기능을 실행 메소드로 연결하는 로직 구현
kmj990929 Dec 13, 2020
620b36c
refactor: 필요없는 import문 삭제
kmj990929 Dec 13, 2020
59eb9a7
refactor: 선택한 기능을 실행하도록 하는 메소드를 분리하여 Menu 클래스로 이동
kmj990929 Dec 13, 2020
a3f4497
feat: 역 등록 시 이름 입력 안내 메시지 출력 기능 구현
kmj990929 Dec 13, 2020
8ca7792
refactor: scanner를 inputView 객체로 전달하도록 수정
kmj990929 Dec 13, 2020
c7e4e29
feat: 역 등록 시 역 객체 생성 기능 구현
kmj990929 Dec 13, 2020
7e6b77c
feat: 역 등록 시 예외상황 처리 기능 구현
kmj990929 Dec 13, 2020
568d408
feat: 예외상황 시 재입력 기능 구현
kmj990929 Dec 13, 2020
b19dc1e
refactor: 인덱스 값 상수로 구현하여 하드코딩 수정
kmj990929 Dec 13, 2020
1ef11bd
feat: 역 삭제 기능 구현
kmj990929 Dec 13, 2020
6b616cd
feat: 역 목록 조회 기능 구현
kmj990929 Dec 13, 2020
d866d63
feat: 돌아가기 기능 구현
kmj990929 Dec 13, 2020
c3245c9
feat: 종료 기능 구현
kmj990929 Dec 13, 2020
966b0a5
fix: 역 등록 시 중복 이름 검사 기능 수정
kmj990929 Dec 13, 2020
5520713
feat: 노선 등록 기능 구현
kmj990929 Dec 13, 2020
6aafb44
docs: 노선 등록 시 예외상황 추가
kmj990929 Dec 13, 2020
1e1e3ef
feat: 노선 삭제 기능 구현
kmj990929 Dec 13, 2020
7fd3113
feat: 노선 삭제 기능 구현
kmj990929 Dec 13, 2020
2ae518a
feat: 노선 관리 화면 돌아가기 기능 구현
kmj990929 Dec 13, 2020
bd9de75
feat: 구간 추가 시 입력한 노선 이름 유효성 검사 기능 구현
kmj990929 Dec 13, 2020
eebaeaf
feat: 구간 추가 시 입력한 역 유효성 검사 기능 구현
kmj990929 Dec 13, 2020
a86728a
docs: 구간 추가 시 예외상황 수정
kmj990929 Dec 13, 2020
7c0847b
feat: 구간 추가 시 입력한 구간 순서 유효성 검사 기능 구현
kmj990929 Dec 14, 2020
13599c7
feat: 구간 추가 시 노선에 역 등록 기능 구현
kmj990929 Dec 14, 2020
1e50266
feat: 구간 삭제 시 입력한 노선 유효성 검사 기능 구현
kmj990929 Dec 14, 2020
ed43655
feat: 구간 삭제 시 입력한 역 유효성 검사 기능 구현
kmj990929 Dec 14, 2020
38c0a09
feat: 구간 삭제 기능 구현
kmj990929 Dec 14, 2020
68f60e3
feat: 구간 관리 화면 돌아가기 기능 구현
kmj990929 Dec 14, 2020
386402e
feat: 지하철 노선도 출력 기능 구현
kmj990929 Dec 14, 2020
9ed41cb
refactor: 세부기능 실행 메소드를 line, Station에서 각각의 Repository로 이동
kmj990929 Dec 14, 2020
18299aa
fix: 노선의 stations list를 인스턴스 변수로 변경하여 노선별로 다른 station list를 가지도록 수정
kmj990929 Dec 14, 2020
3d8ce4d
fix: 구간 추가 시 순서에 맞게 추가하도록 수정
kmj990929 Dec 14, 2020
5568285
style: 출력문구 수정
kmj990929 Dec 14, 2020
7b4efb3
feat: 초기 설정 구현
kmj990929 Dec 14, 2020
3d21e45
style: import문 정리
kmj990929 Dec 14, 2020
e461525
refactor: 변수명을 직관적으로 수정
kmj990929 Dec 15, 2020
5d198ee
refactor: MenuController를 인스턴스화하도록 수정
kmj990929 Dec 15, 2020
a24f370
refactor: 중복 코드 삭제
kmj990929 Dec 15, 2020
a722c97
refactor: 노선도 출력 기능의 return값을 다른 메뉴와 동일하게 수정
kmj990929 Dec 15, 2020
f687689
fix: 노선에 포함된 역이 2개 이하일 경우 구간 삭제 예외처리하도록 수정
kmj990929 Dec 15, 2020
0bd2c50
style: 에러 메시지 수정
kmj990929 Dec 15, 2020
534464b
refactor: 중복 코드 메소드 분리
kmj990929 Dec 15, 2020
07e8716
style: 출력 문구 수정
kmj990929 Dec 15, 2020
ef00186
refactor: 구조 변경으로 인해 필요없어진 변수 선언 삭제
kmj990929 Dec 15, 2020
5160563
refactor: action 실행 메소드 Menu class로 이동
kmj990929 Dec 15, 2020
5d145b5
refactor: 패키지 구조 변경
kmj990929 Dec 15, 2020
dc42af5
refactor: Action 클래스 분리
kmj990929 Dec 15, 2020
d2342c6
refactor: actionList를 get하는 대신 메시지를 보내는 방법으로 수정
kmj990929 Dec 15, 2020
6ab31c7
refactor: 함수명 직관적으로 수정
kmj990929 Dec 15, 2020
a149282
refactor: 중복코드 삭제
kmj990929 Dec 15, 2020
666cf64
refactor: line명 중복 검사 기능을 LineRepository로 이동
kmj990929 Dec 15, 2020
6792a64
docs: README.md 구현 기능 목록 추가
kmj990929 Dec 15, 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
469 changes: 0 additions & 469 deletions README.md

This file was deleted.

153 changes: 153 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# 지하철 노선도 미션
: 지하철 역과 노선을 관리하는 지하철 노선도 기능을 구현한다.
<br>
본 프로젝트는 우아한 테크코스 3기 프리코스 백엔드 과정의 3주차 미션을 구현한 것입니다.

<br>

## 프로젝트 내용
사용자의 입력에 따라 역, 노선, 구간을 추가하고 삭제할 수 있는 프로그램입니다.
사용자가 사용할 수 있는 기능 목록은 다음과 같습니다.
* 역 관리
+ 역 등록
+ 역 삭제
+ 역 조회
* 노선 관리
+ 노선 등록
+ 노선 삭제
+ 노선 조회
* 구간 관리
+ 구간 등록
+ 구간 삭제
* 지하철 노선도 출력

세부 내용은 <https://github.com/woowacourse/java-subway-map-precourse>을 따랐습니다.


## 기능 요구사항

### 초기 설정
- 프로그램 시작 시 역, 노선 등 필요한 정보를 미리 셋팅할 수 있다.

> 아래의 사전 등록 정보로 반드시 초기 설정을 하기
>
```
1. 지하철역으로 교대역, 강남역, 역삼역, 남부터미널역, 양재역, 양재시민의숲역, 매봉역이 등록되어 있다.
2. 지하철 노선으로 2호선, 3호선, 신분당선이 등록되어 있다.
3. 노선에 역이 아래와 같이 등록되어 있다.(왼쪽 끝이 상행 종점)
- 2호선: 교대역 - 강남역 - 역삼역
- 3호선: 교대역 - 남부터미널역 - 양재역 - 매봉역
- 신분당선: 강남역 - 양재역 - 양재시민의숲역
```

### 지하철 역 관련 기능
- 지하철 역을 등록하고 삭제할 수 있다. (단, 노선에 등록된 역은 삭제할 수 없다)
- 중복된 지하철 역 이름이 등록될 수 없다.
- 역 이름은 2자 이상, 5자 이하만 가능하다.
- 지하철 역의 목록을 조회할 수 있다.

### 지하철 노선 관련 기능
- 지하철 노선을 등록하고 삭제할 수 있다.
- 중복된 지하철 노선 이름이 등록될 수 없다.
- 노선 이름은 2자 이상, 5자 이하만 가능하다.
- 노선 등록 시 상행 종점역과 하행 종점역을 입력받는다.
- 지하철 노선의 목록을 조회할 수 있다.

### 지하철 구간 추가 기능
- 지하철 노선에 구간을 추가하는 기능은 노선에 역을 추가하는 기능이라고도 할 수 있다.
- 역과 역사이를 구간이라 하고 이 구간들의 모음이 노선이다.
- 하나의 역은 여러개의 노선에 추가될 수 있다.
- 역과 역 사이에 새로운 역이 추가 될 수 있다.
- 노선에서 갈래길은 생길 수 없다.

### 지하철 구간 삭제 기능
- 노선에 등록된 역을 제거할 수 있다.
- 종점을 제거할 경우 다음 역이 종점이 된다.
- 노선에 포함된 역이 두개 이하일 때는 역을 제거할 수 없다.

### 지하철 노선에 등록된 역 조회 기능
- 노선의 상행 종점부터 하행 종점까지 연결된 순서대로 역 목록을 조회할 수 있다.

<br>

## 구현 기능 목록
### 기능 선택
- 초기 노선 정보로 노선도를 초기화한다.
- 화면(선택 가능한 기능 목록)을 출력한다.
- 사용자가 원하는 기능을 기호로 입력받는다.
- 종료를 선택할 경우 프로그램을 종료한다.
- 돌아가기 기능을 선택할 경우 메인 화면으로 돌아간다.
- 예외상황일 경우 재입력받는다.
**<예외상황>**
- 사용자가 입력한 기호가 기능목록에 존재하지 않는 경우
### 역 관리
#### 1. 역 등록
- 사용자에게 등록하고자 하는 역 이름을 입력받는다.
- 사용자가 입력한 이름이 조건에 부합하면, 역 객체를 생성한다.
- 예외상황일 경우 에러 메시지를 출력하고 재입력 받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 역 이름 중에 존재하는 경우
- 사용자가 입력한 이름이 1글자 이하인 경우
#### 2. 역 삭제
- 사용자에게 삭제하고자 하는 역 이름을 입력받는다.
- 사용자가 입력한 이름이 조건에 부합하면, 역 객체를 삭제한다.
- 예외상황일 경우 에러 메시지를 출력하고 재입력 받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 역 이름 중에 존재하지 않는 경우
- 사용자가 입력한 이름이 노선에 등록된 역인 경우
#### 3. 역 목록 조회
- 현재 존재하는 역을 모두 출력한다.

### 노선 관리
#### 1. 노선 등록
- 사용자에게 등록하고자 하는 노선 이름을 입력받는다.
- 사용자에게 상행 종점역과 하행 종점역 이름을 입력받는다.
- 사용자에게 받은 입력이 조건에 부합하면, 노선 객체를 생성한다.
- 예외상황일 경우 에러 메시지를 출력하고 재입력받는다.
**<예외상황>**
- 사용자가 입력한 노선 이름이 기존 노선 이름 중에 존재하는 경우
- 사용자가 입력한 노선 이름이 1자 이하인 경우
- 사용자가 입력한 상행 종점역 / 하행 종점역이 기존에 존재하던 역이 아닌 경우
- 사용자가 입력한 상행 종점역 / 하행 종점역이 동일한 경우
#### 2. 노선 삭제
- 사용자에게 삭제하고자 하는 노선 이름을 입력받는다.
- 사용자가 입력한 이름이 조건에 부합하면, 역 객체를 삭제한다.
- 예외상황일 경우 에러 메시지를 출력하고 재입력받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 노선 이름 중에 존재하지 않는 경우
#### 3. 노선 목록 조회
- 현재 존재하는 노선을 모두 출력한다.

### 구간 관리
#### 1. 구간 추가
- 사용자가 추가하고자 하는 구간의 노선을 입력받는다.
- 예외상황일 경우 에러 메시지를 출력하고 재입력받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 노선 이름 중에 존재하지 않는 경우
- 사용자가 추가하고자 하는 구간의 역을 입력받는다.
- 예외상황일 경우 에러 메시지를 출력하고 재입력받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 역 이름 중에 존재하지 않는 경우
- 사용자가 입력한 이름이 해당 노선에 이미 포함되어 있는 경우
- 사용자가 추가하고자 하는 구간의 순서를 입력받는다.
**<예외상황>**
- 사용자가 입력한 구간 순서가 integer가 아닌 경우
- 사용자가 입력한 구간 순서가 양수가 아닌 경우
- 사용자가 입력한 구간 순서가 현재 있는 리스트의 범위 밖인 경우
- 사용자의 입력이 조건에 부합하면 해당 구간을 생성한다.
#### 2. 구간 삭제
- 사용자가 삭제하고자 하는 구간의 노선을 입력받는다.
- 입력이 조건에 부합하지 않으면 에러 메시지를 출력하고 재입력받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 노선 이름 중에 존재하지 않는 경우
- 사용자가 입력한 노선에 있는 역이 2개 이하인 경우
- 사용자가 삭제하고자 하는 구간의 역을 입력받는다.
- 입력이 조건에 부합하지 않으면 에러 메시지를 출력하고 재입력받는다.
**<예외상황>**
- 사용자가 입력한 이름이 기존 역 이름 중에 존재하지 않는 경우
- 사용자가 입력한 이름이 해당 노선에 포함되어 있지 않는 경우
- 사용자의 입력이 조건에 부합하면 해당 구간을 삭제한다.

### 노선도 출력
- 현재 존재하는 노선을 출력한다.
- 각 노선에 포함되어 있는 역을 상행 종점역부터 하행 종점역까지 순서대로 출력한다.
7 changes: 6 additions & 1 deletion src/main/java/subway/Application.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package subway;

import subway.controller.LineMapManager;
import subway.view.InputView;

import java.util.Scanner;

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

import subway.domain.Line;
import subway.domain.LineRepository;
import subway.domain.StationRepository;
import subway.domain.exception.IncludeInLineException;
import subway.domain.exception.MinimumStationNumberException;
import subway.domain.exception.NonExistentNameException;
import subway.domain.exception.NotIncludeInLineException;
import subway.domain.exception.OrderRangeException;
import subway.domain.exception.OrderTypeException;
import subway.view.InputView;
import subway.view.OutputView;

public class Edge {
private static final String STATION_MESSAGE = "역";
private static final String LINE_MESSAGE = "노선";
private static final String EDGE_MESSAGE = "구간";
private static final String NAME_MESSAGE = "이름";
private static final int ORDER_INDEX_CONSTANT = 1;
private static final int MINIMUM_DELETE_CONDITION_STAION_NUMBER = 3;

private Edge() {
}

public static void add(InputView inputView) {
String lineName = scanAddEdgeLineName(inputView);
String stationName = scanAddEdgeStationName(inputView, lineName);
int order = scanOrder(inputView, lineName);
for (int i = 0; i < LineRepository.lines().size(); i++) {
Line line = LineRepository.lines().get(i);
if (line.getName().equals(lineName)) {
line.addStationByName(stationName, order);
}
}
OutputView.printEdgeAddActionFinishMessage(EDGE_MESSAGE);
}

public static void delete(InputView inputView) {
String lineName = scanDeleteEdgeLineName(inputView);
String stationName = scanDeleteEdgeStationName(inputView, lineName);
for (int i = 0; i < LineRepository.lines().size(); i++) {
Line line = LineRepository.lines().get(i);
if (line.getName().equals(lineName)) {
line.deleteStationByName(stationName);
}
}
OutputView.printEdgeDeleteActionFinishMessage(EDGE_MESSAGE);
}

private static void validateLineState(String lineName) {
LineRepository.validateExistentLineName(lineName, LINE_MESSAGE);
validateLineRange(lineName);
}

private static void validateLineRange(String lineName) {
boolean isValidRange = false;
for (int i = 0; i < LineRepository.lines().size(); i++) {
Line line = LineRepository.lines().get(i);
if (line.getName().equals(lineName)) {
isValidRange = line.validateRange(MINIMUM_DELETE_CONDITION_STAION_NUMBER);
}
}
if (!isValidRange) {
throw new MinimumStationNumberException();
}
}

private static void validateStationState(String stationName, String lineName) {
if (StationRepository.validateUniqueName(stationName)) {
throw new NonExistentNameException(STATION_MESSAGE);
}
if (!validateLineIncludeStation(lineName, stationName)) {
throw new NotIncludeInLineException();
}
}

private static String scanAddEdgeLineName(InputView inputView) {
OutputView.printInputMessage(LINE_MESSAGE);
String lineName = inputView.getInput();
LineRepository.validateExistentLineName(lineName, LINE_MESSAGE);
return lineName;
}

private static String scanAddEdgeStationName(InputView inputView, String lineName) {
String stationNameMessage = STATION_MESSAGE + NAME_MESSAGE;
OutputView.printInputMessage(stationNameMessage);
String stationName = inputView.getInput();
validateStationName(lineName, stationName);
return stationName;
}

private static String scanDeleteEdgeLineName(InputView inputView) {
OutputView.printDeleteEdgeOptionMessage(LINE_MESSAGE);
String lineName = inputView.getInput();
validateLineState(lineName);
return lineName;
}

private static String scanDeleteEdgeStationName(InputView inputView, String lineName) {
OutputView.printDeleteEdgeOptionMessage(STATION_MESSAGE);
String stationName = inputView.getInput();
validateStationState(stationName, lineName);
return stationName;
}

private static int scanOrder(InputView inputView, String lineName) {
OutputView.printOrderInputMessage();
String order = inputView.getInput();
validateOrder(order, lineName);
return Integer.parseInt(order);
}

private static void validateStationName(String lineName, String stationName) {
if (StationRepository.validateUniqueName(stationName)) {
throw new NonExistentNameException(STATION_MESSAGE);
}
if (validateLineIncludeStation(lineName, stationName)) {
throw new IncludeInLineException();
}
}

private static boolean validateLineIncludeStation(String lineName, String stationName) {
for (int i = 0; i < LineRepository.lines().size(); i++) {
Line line = LineRepository.lines().get(i);
if (line.getName().equals(lineName)) {
return !line.validateLineIncludeStation(stationName);
}
}
return false;
}

private static void validateOrder(String order, String lineName) {
if (!validateOrderType(order)) {
throw new OrderTypeException();
}
int orderNumber = Integer.parseInt(order);
if ((!validateOrderPositiveNumber(orderNumber)) || (!validateOrderRange(orderNumber, lineName))){
throw new OrderRangeException();
}
}

private static boolean validateOrderType(String order) {
try {
Integer.parseInt(order);
return true;
} catch (RuntimeException e) {
return false;
}
}

private static boolean validateOrderRange(int order, String lineName) {
for (int i = 0; i < LineRepository.lines().size(); i++) {
Line line = LineRepository.lines().get(i);
if (line.getName().equals(lineName)) {
int orderIndex = order - ORDER_INDEX_CONSTANT;
return line.validateRange(orderIndex);
}
}
return false;
}

private static boolean validateOrderPositiveNumber(int order) {
if (order <= 0) {
return false;
}
return true;
}
}
Loading