-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[2단계 - 경로 조회 기능] 테오(최우성) 미션 제출합니다. (#161)
* refactor: 테이블 이름 변경 * refactor: 외래키 제약조건 추가 * refactor: 데이터베이스 예외 발생 시 문구 반환 * chore: 코드 리포맷팅 * refactor: 동등성 비교조건 변경 * refactor: URI에서 컬렉션이 드러나도록 변경 * test: 컨트롤러 테스트 보완 * refactor: logback-access가 아닌 인터셉터로 로깅 처리 * refactor: 서비스 입력 모델 생성 * refactor: 서비스 출력 모델 생성 * chore: 패키지 구조 변경 * chore: 패키지 이름 변경 * feat: 경로 조회 및 요금 계산 비즈니스 로직 구현 * refactor: RouteMap 객체를 재사용 가능하게 Section List으로 구성 * feat: 요금 계산용 값 객체 생성 * refactor: 경로 조회 및 요금 계산 로직 수정 * feat: 경로탐색 구현체 생성 * feat: 경로 조회 및 요금 계산 API 구현 * test: 통합 테스트용 http 파일 생성 * chore: 테스트 패키지 구조 프로덕션과 동일하게 변경 * fix: 몇몇 입력 모델에서 검증을 하지 않던 문제 수정 * refactor: 메소드 추가 분리 * refactor: 경로 추적 시 두 번의 연산을 수행하지 않도록 DTO 생성 * chore: 사용하지 않는 메소드 제거 * test: jgrapht 구현체 테스트 생성 * chore: 메소드 분리, 가독성 개선 * test: service 테스트 보완, dummy.sql 생성 * test: 최단 경로 관련 통합테스트 생성 * chore: sql 파일 위치 변경 * feat: 프로덕션 환경에서는 MySQL, 테스트 환경에서는 H2를 사용하도록 변경 * fix: 더미 데이터 사용에 따른 테스트 코드 수정 * chore: .http 파일 삭제 * feat: swagger를 통한 API 명세 자동화 * chore: 메소드명 변경 * docs: 고민사항 기재 * chore: 클래스명 변경 * refactor: `@Validated` 어노테이션을 통한 검증 * chore: 구현체가 있으므로 인터페이스에서 `@Component` 제거 * chore: 메소드 인자명 변경 * chore: 불필요한 `support` 패키지 삭제 * refactor: repository의 insert가 도메인 엔티티를 반환하도록 수정 * test: Repository 테스트 보완 의존관계가 복잡한 경우 mock 사용 * refactor: 출력 모델에서 도메인 엔티티 제거 * refactor: 중복된 의미를 가지는 예외객체 제거 * refactor: 요금 계산 로직을 enum으로 수행 * refactor: 입력 모델 규칙 위반에 대한 예외처리 생성 * chore: 불필요한 `@Valid` 제거 * docs: 리팩토링 기록 작성 및 아키텍쳐 이미지 변경 * refactor: Repository가 H2와 관련이 없기에 네이밍 수정
- Loading branch information
1 parent
3be4612
commit 944f9c4
Showing
100 changed files
with
2,970 additions
and
1,095 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package subway.application.core.domain; | ||
|
||
import subway.application.core.exception.FareCantCalculatedException; | ||
|
||
import java.util.Arrays; | ||
|
||
public enum Fare { | ||
|
||
UNDER_TEN_KM(0.0, 10.0) { | ||
@Override | ||
int calculateFare(double distance) { | ||
return BASE_FARE; | ||
} | ||
}, | ||
BETWEEN_TEN_AND_FIFTY(10.0, 50.0) { | ||
@Override | ||
int calculateFare(double distance) { | ||
distance -= 10; | ||
return BASE_FARE + calculateOverFareForEveryDistance(distance, REFERENCE_DISTANCE_UNDER_FIFTY); | ||
} | ||
}, | ||
OVER_FIFTY(50.0, Integer.MAX_VALUE) { | ||
@Override | ||
int calculateFare(double distance) { | ||
distance -= 50; | ||
return BASE_FARE + calculateOverFareForEveryDistance(40, REFERENCE_DISTANCE_UNDER_FIFTY) + | ||
calculateOverFareForEveryDistance(distance, REFERENCE_DISTANCE_OVER_FIFTY); | ||
} | ||
}; | ||
|
||
private static final int BASE_FARE = 1_250; | ||
private static final double REFERENCE_DISTANCE_UNDER_FIFTY = 5.0; | ||
private static final double REFERENCE_DISTANCE_OVER_FIFTY = 8.0; | ||
|
||
protected final double startPoint; | ||
protected final double endPoint; | ||
|
||
Fare(double startPoint, double endPoint) { | ||
this.startPoint = startPoint; | ||
this.endPoint = endPoint; | ||
} | ||
|
||
public static int of(double distance) { | ||
return Arrays.stream(values()) | ||
.filter(fareEnum -> fareEnum.matches(distance)) | ||
.findAny() | ||
.orElseThrow(FareCantCalculatedException::new) | ||
.calculateFare(distance); | ||
} | ||
|
||
abstract int calculateFare(double distance); | ||
|
||
protected int calculateOverFareForEveryDistance(double distance, double referenceDistance) { | ||
return (int) ((Math.ceil(((int) distance - 1) / (int) referenceDistance) + 1) * 100); | ||
} | ||
|
||
protected boolean matches(double distance) { | ||
return Double.compare(startPoint, distance) <= 0 && Double.compare(distance, endPoint) <= 0; | ||
} | ||
} |
10 changes: 5 additions & 5 deletions
10
.../java/subway/application/domain/Line.java → .../subway/application/core/domain/Line.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...bway/application/domain/LineProperty.java → ...application/core/domain/LineProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package subway.application.domain; | ||
package subway.application.core.domain; | ||
|
||
import java.util.Objects; | ||
|
||
|
102 changes: 102 additions & 0 deletions
102
src/main/java/subway/application/core/domain/RouteMap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package subway.application.core.domain; | ||
|
||
import subway.application.core.exception.CircularRouteException; | ||
import subway.application.core.exception.RouteNotConnectedException; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
public class RouteMap { | ||
|
||
private final List<Section> routeMap; | ||
|
||
public RouteMap(List<Section> sections) { | ||
this.routeMap = alignedRouteOf(sections); | ||
} | ||
|
||
private List<Section> alignedRouteOf(List<Section> sections) { | ||
if (sections.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
return alignSections(sections); | ||
} | ||
|
||
private List<Section> alignSections(List<Section> sections) { | ||
List<Section> temporarySections = new ArrayList<>(); | ||
Section indexSection = findFirstSection(sections); | ||
while (canMove(sections, indexSection) && !isInnerCircle(sections, temporarySections)) { | ||
temporarySections.add(indexSection); | ||
indexSection = findNext(sections, indexSection); | ||
} | ||
temporarySections.add(indexSection); | ||
validate(sections, temporarySections); | ||
return temporarySections; | ||
} | ||
|
||
private Section findFirstSection(List<Section> sections) { | ||
Station firstStation = getEndPoints(sections).stream() | ||
.findAny() | ||
.orElseThrow(CircularRouteException::new); | ||
|
||
return sections.stream() | ||
.filter(section -> section.hasUpBound(firstStation)) | ||
.findAny() | ||
.orElseThrow(); | ||
} | ||
|
||
private List<Station> getEndPoints(List<Section> sections) { | ||
List<Station> allUpBounds = sections.stream() | ||
.map(Section::getUpBound) | ||
.collect(Collectors.toList()); | ||
|
||
List<Station> allDownBounds = sections.stream() | ||
.map(Section::getDownBound) | ||
.collect(Collectors.toList()); | ||
|
||
allUpBounds.removeAll(allDownBounds); | ||
return allUpBounds; | ||
} | ||
|
||
private boolean canMove(List<Section> sections, Section targetSection) { | ||
return sections.stream() | ||
.anyMatch(section -> section.getUpBound().equals(targetSection.getDownBound())); | ||
} | ||
|
||
private boolean isInnerCircle(List<Section> originalSections, List<Section> temporarySections) { | ||
return originalSections.size() < temporarySections.size(); | ||
} | ||
|
||
private Section findNext(List<Section> sections, Section targetSection) { | ||
return sections.stream() | ||
.filter(section -> section.getUpBound().equals(targetSection.getDownBound())) | ||
.findAny() | ||
.orElseThrow(); | ||
} | ||
|
||
private void validate(List<Section> originalSections, List<Section> temporarySections) { | ||
if (originalSections.size() < temporarySections.size()) { | ||
throw new CircularRouteException(); | ||
} | ||
if (temporarySections.size() < originalSections.size()) { | ||
throw new RouteNotConnectedException(); | ||
} | ||
} | ||
|
||
public List<Station> stations() { | ||
Set<Station> alignedStations = new HashSet<>(); | ||
routeMap.forEach(section -> { | ||
alignedStations.add(section.getUpBound()); | ||
alignedStations.add(section.getDownBound()); | ||
}); | ||
return alignedStations.stream() | ||
.collect(Collectors.toUnmodifiableList()); | ||
} | ||
|
||
public List<Section> values() { | ||
return Collections.unmodifiableList(routeMap); | ||
} | ||
} |
4 changes: 2 additions & 2 deletions
4
...va/subway/application/domain/Section.java → ...bway/application/core/domain/Section.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ion/exception/CircularRouteException.java → ...ore/exception/CircularRouteException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/subway/application/core/exception/DistanceNotPositiveException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package subway.application.core.exception; | ||
|
||
public class DistanceNotPositiveException extends ExpectedException { | ||
|
||
private static final String MESSAGE = "거리는 음수일 수 없습니다."; | ||
|
||
public DistanceNotPositiveException() { | ||
super(MESSAGE); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...lication/exception/ExpectedException.java → ...ion/core/exception/ExpectedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/subway/application/core/exception/FareCantCalculatedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package subway.application.core.exception; | ||
|
||
public class FareCantCalculatedException extends ExpectedException { | ||
|
||
private static final String MESSAGE = "해당하는 거리에 맞는 요금을 찾을 수 없습니다."; | ||
|
||
public FareCantCalculatedException() { | ||
super(MESSAGE); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...exception/RouteNotConnectedException.java → ...exception/RouteNotConnectedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...on/exception/SectionConnectException.java → ...re/exception/SectionConnectException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...eption/StationAlreadyExistsException.java → ...eption/StationAlreadyExistsException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.