diff --git a/src/main/java/nextstep/subway/application/dto/request/AddSectionRequest.java b/src/main/java/nextstep/subway/application/dto/request/AddSectionRequest.java index dd2b221ca..a76307cfc 100644 --- a/src/main/java/nextstep/subway/application/dto/request/AddSectionRequest.java +++ b/src/main/java/nextstep/subway/application/dto/request/AddSectionRequest.java @@ -7,14 +7,14 @@ public class AddSectionRequest { private final Long upStationId; - private final Long downStationId; - private final Long distance; + private final Long duration; - public AddSectionRequest(Long upStationId, Long downStationId, Long distance) { + public AddSectionRequest(Long upStationId, Long downStationId, Long distance, Long duration) { this.upStationId = upStationId; this.downStationId = downStationId; this.distance = distance; + this.duration = duration; } } diff --git a/src/main/java/nextstep/subway/application/dto/request/LineCreateRequest.java b/src/main/java/nextstep/subway/application/dto/request/LineCreateRequest.java index 3be6e41d6..d9ce3bb59 100644 --- a/src/main/java/nextstep/subway/application/dto/request/LineCreateRequest.java +++ b/src/main/java/nextstep/subway/application/dto/request/LineCreateRequest.java @@ -15,12 +15,15 @@ public class LineCreateRequest { private final Long downStationId; private final Long distance; + private final Long duration; - public LineCreateRequest(String name, String color, Long upStationId, Long downStationId, Long distance) { + public LineCreateRequest(String name, String color, Long upStationId, Long downStationId, Long distance, + Long duration) { this.name = name; this.color = color; this.upStationId = upStationId; this.downStationId = downStationId; this.distance = distance; + this.duration = duration; } } diff --git a/src/main/java/nextstep/subway/application/dto/response/PathResponse.java b/src/main/java/nextstep/subway/application/dto/response/PathResponse.java index 47ede6ff5..6bda00fda 100644 --- a/src/main/java/nextstep/subway/application/dto/response/PathResponse.java +++ b/src/main/java/nextstep/subway/application/dto/response/PathResponse.java @@ -1,10 +1,8 @@ package nextstep.subway.application.dto.response; import java.util.List; -import java.util.stream.Collectors; import lombok.Getter; import lombok.NoArgsConstructor; -import nextstep.subway.domain.entity.Path; import nextstep.subway.domain.entity.Station; @NoArgsConstructor @@ -28,14 +26,11 @@ public StationDto(Station station) { private List stations; private long distance; + private long duration; - public PathResponse(Path shortestPath) { - this.stations = shortestPath.getStations().stream() - .map(StationDto::new) - .collect(Collectors.toList()); - this.distance = (long) shortestPath.getDistance(); - + public PathResponse(List stations, long distance, long duration) { + this.stations = stations; + this.distance = distance; + this.duration = duration; } - - } diff --git a/src/main/java/nextstep/subway/application/service/LineService.java b/src/main/java/nextstep/subway/application/service/LineService.java index 0d3badd12..d2f8ed5ff 100644 --- a/src/main/java/nextstep/subway/application/service/LineService.java +++ b/src/main/java/nextstep/subway/application/service/LineService.java @@ -32,7 +32,15 @@ public LineResponse saveLine(LineCreateRequest lineCreateRequest) { lineCreateRequest.getName(), lineCreateRequest.getColor() )); - line.addSection(Section.of(line, upStation, downStation, lineCreateRequest.getDistance())); + line.addSection( + Section.of( + line, + upStation, + downStation, + lineCreateRequest.getDistance(), + lineCreateRequest.getDuration() + ) + ); return new LineResponse(line); } @@ -67,7 +75,13 @@ public LineResponse addSection(Long lineId, AddSectionRequest addSectionRequest) Station upStation = stationService.getStationById(addSectionRequest.getUpStationId()); Station downStation = stationService.getStationById(addSectionRequest.getDownStationId()); line.addSection( - Section.of(line, upStation, downStation, addSectionRequest.getDistance()) + Section.of( + line, + upStation, + downStation, + addSectionRequest.getDistance(), + addSectionRequest.getDuration() + ) ); return new LineResponse(line); } diff --git a/src/main/java/nextstep/subway/application/service/PathService.java b/src/main/java/nextstep/subway/application/service/PathService.java index cf4c6a94f..f214bf073 100644 --- a/src/main/java/nextstep/subway/application/service/PathService.java +++ b/src/main/java/nextstep/subway/application/service/PathService.java @@ -8,6 +8,7 @@ import nextstep.subway.domain.entity.Path; import nextstep.subway.domain.entity.PathFinder; import nextstep.subway.domain.entity.Station; +import nextstep.subway.domain.enums.PathSearchType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,14 +20,18 @@ public class PathService { private final StationService stationService; private final LineService lineService; - public PathResponse findPath(Long sourceStationId, Long targetStationId) { + public PathResponse findPath(Long sourceStationId, Long targetStationId, PathSearchType type) { Station source = stationService.getStationById(sourceStationId); Station target = stationService.getStationById(targetStationId); List lines = lineService.getLines(); PathFinder pathFinder = new PathFinder(lines); - Path shortestPath = pathFinder.findShortestPath(source, target) + Path shortestPath = pathFinder.findShortestPath(source, target, type) .orElseThrow(() -> new CanNotFindPathException("Unable to find the shortest path.")); - return new PathResponse(shortestPath); + return new PathResponse( + shortestPath.getStationDtoOfPath(target), + shortestPath.getDistance(), + shortestPath.getDuration() + ); } diff --git a/src/main/java/nextstep/subway/domain/entity/Path.java b/src/main/java/nextstep/subway/domain/entity/Path.java index fba795c61..3fb85d039 100644 --- a/src/main/java/nextstep/subway/domain/entity/Path.java +++ b/src/main/java/nextstep/subway/domain/entity/Path.java @@ -1,16 +1,44 @@ package nextstep.subway.domain.entity; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.Getter; +import nextstep.subway.application.dto.response.PathResponse.StationDto; @Getter public class Path { - private List stations; - private double distance; + private final Sections sections; - public Path(List stations, double distance) { - this.stations = stations; - this.distance = distance; + public Path(Sections sections) { + this.sections = sections; + } + + public List getStationDtoOfPath(Station target) { + List stations = this.getStationsOfPath(); + if (!stations.isEmpty()) { + Station sourceStation = stations.get(0); + if (Objects.equals(sourceStation.getId(), target.getId())) { + Collections.reverse(stations); + } + } + return stations.stream() + .map(StationDto::new) + .collect(Collectors.toList()); + } + + public List getStationsOfPath() { + return this.sections.getSortedStationsByUpDirection(true); + } + + + public long getDistance() { + return this.sections.getDistance(); + } + + public long getDuration() { + return this.sections.getDuration(); } } diff --git a/src/main/java/nextstep/subway/domain/entity/PathFinder.java b/src/main/java/nextstep/subway/domain/entity/PathFinder.java index abfe99b8a..50c53a2f6 100644 --- a/src/main/java/nextstep/subway/domain/entity/PathFinder.java +++ b/src/main/java/nextstep/subway/domain/entity/PathFinder.java @@ -2,7 +2,10 @@ import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import nextstep.subway.domain.enums.PathSearchType; import org.jgrapht.Graph; import org.jgrapht.GraphPath; import org.jgrapht.WeightedGraph; @@ -13,21 +16,36 @@ @Slf4j public class PathFinder { + @Getter + static class SectionEdge extends DefaultWeightedEdge { + + private final Section section; + + SectionEdge(Section section) { + this.section = section; + } + } + private final List lines; - private final DijkstraShortestPath dijkstraShortestPath; + private final DijkstraShortestPath distanceShortestPath; + private final DijkstraShortestPath durationShortestPath; public PathFinder(List lines) { this.lines = lines; - this.dijkstraShortestPath = new DijkstraShortestPath<>(createWeightedGraph()); + this.distanceShortestPath = new DijkstraShortestPath<>(createWeightedGraph(PathSearchType.DISTANCE)); + this.durationShortestPath = new DijkstraShortestPath<>(createWeightedGraph(PathSearchType.DURATION)); } - public Optional findShortestPath(Station source, Station target) { + public Optional findShortestPath(Station source, Station target, PathSearchType type) { if (source == target) { throw new IllegalArgumentException("Source and target stations are the same"); } try { - GraphPath result = dijkstraShortestPath.getPath(source, target); - return Optional.of(new Path(result.getVertexList(), result.getWeight())); + GraphPath result = getShortedPath(source, target, type); + List
sections = result.getEdgeList().stream() + .map(SectionEdge::getSection) + .collect(Collectors.toList()); + return Optional.of(new Path(new Sections(sections))); } catch (Exception e) { return Optional.empty(); } @@ -35,30 +53,55 @@ public Optional findShortestPath(Station source, Station target) { public boolean isValidPath(Station source, Station target) { try { - Optional path = findShortestPath(source, target); + Optional path = findShortestPath(source, target, PathSearchType.DISTANCE); return path.isPresent(); } catch (IllegalArgumentException e) { return false; } } - private WeightedGraph createWeightedGraph() { - SimpleWeightedGraph graph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class); + private GraphPath getShortedPath(Station source, Station target, + PathSearchType type) { + if (type == PathSearchType.DISTANCE) { + return distanceShortestPath.getPath(source, target); + } + if (type == PathSearchType.DURATION) { + return durationShortestPath.getPath(source, target); + } + throw new IllegalStateException("invalid PathSearchType type"); + } + + private WeightedGraph createWeightedGraph(PathSearchType type) { + SimpleWeightedGraph graph = new SimpleWeightedGraph<>(SectionEdge.class); addStationsAsVerticesToGraph(graph); - addSectionsAdSeightedEdgeToGraph(graph); + addSectionsAsWeightedEdgeToGraph(graph, type); return graph; } - private void addStationsAsVerticesToGraph(Graph graph) { + private void addStationsAsVerticesToGraph(Graph graph) { this.lines.stream() .flatMap(line -> line.getAllStationsByDistinct().stream()) .forEach(graph::addVertex); } - private void addSectionsAdSeightedEdgeToGraph(WeightedGraph graph) { + private void addSectionsAsWeightedEdgeToGraph(WeightedGraph graph, + PathSearchType type) { this.lines.stream() .flatMap(line -> line.getSections().getAllSections().stream()) - .forEach(section -> graph.setEdgeWeight( - graph.addEdge(section.getUpStation(), section.getDownStation()), section.getDistance())); + .forEach(section -> { + SectionEdge sectionEdge = new SectionEdge(section); + graph.addEdge(section.getUpStation(), section.getDownStation(), sectionEdge); + graph.setEdgeWeight(sectionEdge, getSectionEdgeWeight(section, type)); + }); + } + + private long getSectionEdgeWeight(Section section, PathSearchType type) { + if (type == PathSearchType.DISTANCE) { + return section.getDistance(); + } + if (type == PathSearchType.DURATION) { + return section.getDuration(); + } + throw new IllegalStateException("invalid PathSearchType type"); } } diff --git a/src/main/java/nextstep/subway/domain/entity/Section.java b/src/main/java/nextstep/subway/domain/entity/Section.java index e8523dfba..45f7e28d6 100644 --- a/src/main/java/nextstep/subway/domain/entity/Section.java +++ b/src/main/java/nextstep/subway/domain/entity/Section.java @@ -35,15 +35,18 @@ public class Section implements Comparable
{ private long distance; - public Section(Line line, Station upStation, Station downStation, long distance) { + private long duration; + + public Section(Line line, Station upStation, Station downStation, long distance, long duration) { this.line = line; this.upStation = upStation; this.downStation = downStation; this.distance = distance; + this.duration = duration; } - public static Section of(Line line, Station upStation, Station downStation, long distance) { - return new Section(line, upStation, downStation, distance); + public static Section of(Line line, Station upStation, Station downStation, long distance, long duration) { + return new Section(line, upStation, downStation, distance, duration); } @Override diff --git a/src/main/java/nextstep/subway/domain/entity/Sections.java b/src/main/java/nextstep/subway/domain/entity/Sections.java index 444f4ea0f..3c07161ea 100644 --- a/src/main/java/nextstep/subway/domain/entity/Sections.java +++ b/src/main/java/nextstep/subway/domain/entity/Sections.java @@ -140,4 +140,12 @@ private Optional
getSectionByDownStation(Station station) { public List
getAllSections() { return this.sections; } + + public long getDistance() { + return this.sections.stream().mapToLong(Section::getDistance).sum(); + } + + public long getDuration() { + return this.sections.stream().mapToLong(Section::getDuration).sum(); + } } diff --git a/src/main/java/nextstep/subway/domain/enums/PathSearchType.java b/src/main/java/nextstep/subway/domain/enums/PathSearchType.java new file mode 100644 index 000000000..da5eac454 --- /dev/null +++ b/src/main/java/nextstep/subway/domain/enums/PathSearchType.java @@ -0,0 +1,6 @@ +package nextstep.subway.domain.enums; + +public enum PathSearchType { + DISTANCE, + DURATION +} diff --git a/src/main/java/nextstep/subway/ui/PathController.java b/src/main/java/nextstep/subway/ui/PathController.java index c5d6df00f..de057856d 100644 --- a/src/main/java/nextstep/subway/ui/PathController.java +++ b/src/main/java/nextstep/subway/ui/PathController.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import nextstep.subway.application.dto.response.PathResponse; import nextstep.subway.application.service.PathService; +import nextstep.subway.domain.enums.PathSearchType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -20,9 +21,10 @@ public class PathController { @GetMapping public ResponseEntity findPath( @RequestParam(name = "source") Long sourceStationId, - @RequestParam(name = "target") Long targetStationId + @RequestParam(name = "target") Long targetStationId, + @RequestParam(name = "type") PathSearchType type ) { - return ResponseEntity.ok().body(pathService.findPath(sourceStationId, targetStationId)); + return ResponseEntity.ok().body(pathService.findPath(sourceStationId, targetStationId, type)); } } diff --git a/src/test/java/nextstep/cucumber/AcceptanceContext.java b/src/test/java/nextstep/cucumber/AcceptanceContext.java index 9bbbcf582..1561e01eb 100644 --- a/src/test/java/nextstep/cucumber/AcceptanceContext.java +++ b/src/test/java/nextstep/cucumber/AcceptanceContext.java @@ -13,4 +13,8 @@ public class AcceptanceContext { public Map store = new HashMap<>(); public ExtractableResponse response; + + public T getValueFromStore(String name, Class responseType) { + return responseType.cast(this.store.get(name)); + } } diff --git a/src/test/java/nextstep/cucumber/steps/LineStepDef.java b/src/test/java/nextstep/cucumber/steps/LineStepDef.java index 2b73eb24f..782e523bd 100644 --- a/src/test/java/nextstep/cucumber/steps/LineStepDef.java +++ b/src/test/java/nextstep/cucumber/steps/LineStepDef.java @@ -27,10 +27,11 @@ public LineStepDef() { params.put("name", param.get("name")); params.put("color", param.get("color")); params.put("upStationId", - ((StationResponse) context.store.get(param.get("upStation"))).getId().toString()); + context.getValueFromStore(param.get("upStation"), StationResponse.class).getId().toString()); params.put("downStationId", - ((StationResponse) context.store.get(param.get("downStation"))).getId().toString()); + context.getValueFromStore(param.get("downStation"), StationResponse.class).getId().toString()); params.put("distance", param.get("distance")); + params.put("duration", param.get("duration")); ExtractableResponse response = 지하철_노선_생성_요청(params); context.store.put(params.get("name").toString(), response.as(LineResponse.class)); }); @@ -38,4 +39,5 @@ public LineStepDef() { } + } diff --git a/src/test/java/nextstep/cucumber/steps/PathStepDef.java b/src/test/java/nextstep/cucumber/steps/PathStepDef.java index bf060ac04..01986b152 100644 --- a/src/test/java/nextstep/cucumber/steps/PathStepDef.java +++ b/src/test/java/nextstep/cucumber/steps/PathStepDef.java @@ -2,6 +2,7 @@ import static nextstep.subway.acceptance.step.PathSteps.지하철_경로_조회_요청; import static nextstep.subway.acceptance.step.PathSteps.지하철역_경로_조회_응답에서_경로_거리_추출; +import static nextstep.subway.acceptance.step.PathSteps.지하철역_경로_조회_응답에서_경로_시간_추출; import static nextstep.subway.acceptance.step.PathSteps.지하철역_경로_조회_응답에서_역_이름_목록_추출; import static nextstep.subway.acceptance.step.SectionSteps.지하철_구간_등록_요청; import io.cucumber.datatable.DataTable; @@ -13,6 +14,7 @@ import nextstep.cucumber.AcceptanceContext; import nextstep.subway.application.dto.response.LineResponse; import nextstep.subway.application.dto.response.StationResponse; +import nextstep.subway.domain.enums.PathSearchType; import org.assertj.core.api.SoftAssertions; import org.springframework.beans.factory.annotation.Autowired; @@ -30,30 +32,49 @@ public PathStepDef() { String lineName = param.get("lineName"); Map params = new HashMap<>(); params.put("upStationId", - ((StationResponse) context.store.get(param.get("upStation"))).getId().toString()); + context.getValueFromStore(param.get("upStation"), StationResponse.class).getId().toString()); params.put("downStationId", - ((StationResponse) context.store.get(param.get("downStation"))).getId().toString()); + context.getValueFromStore(param.get("downStation"), StationResponse.class).getId().toString()); params.put("distance", param.get("distance")); - LineResponse line = (LineResponse) context.store.get(lineName); + params.put("duration", param.get("duration")); + LineResponse line = context.getValueFromStore(lineName, LineResponse.class); 지하철_구간_등록_요청(line.getId(), params); }); }); - When("{string}과 {string}의 경로를 조회하면", (String sourceStationName, String targetStationName) -> { - Long sourceId = ((StationResponse) context.store.get(sourceStationName)).getId(); - Long targetId = ((StationResponse) context.store.get(targetStationName)).getId(); - context.response = 지하철_경로_조회_요청(sourceId, targetId); - }); - - Then("거리가 {long}인 {string}경로가 조회된다", (Long distance, String path) -> { + When("{string}에서 {string}까지의 {string} 기준으로 경로 조회를 요청하면", + (String sourceStationName, String targetStationName, String type) -> { + Long sourceId = ((StationResponse) context.store.get(sourceStationName)).getId(); + Long targetId = ((StationResponse) context.store.get(targetStationName)).getId(); + PathSearchType searchType = getPathSearchType(type); + context.response = 지하철_경로_조회_요청(sourceId, targetId, searchType); + }); + Then("{string} 기준 {string} 경로를 응답", (String type, String path) -> { List stationNames = Arrays.asList(path.split(",")); SoftAssertions.assertSoftly(softAssertions -> { softAssertions.assertThat(지하철역_경로_조회_응답에서_역_이름_목록_추출(context.response)) .containsExactlyElementsOf(stationNames); + }); + }); + + And("총 거리 {long}와 소요 시간 {long}을 함께 응답함", (Long distance, Long duration) -> { + SoftAssertions.assertSoftly(softAssertions -> { softAssertions.assertThat(지하철역_경로_조회_응답에서_경로_거리_추출(context.response)) .isEqualTo(distance); + softAssertions.assertThat(지하철역_경로_조회_응답에서_경로_시간_추출(context.response)) + .isEqualTo(duration); }); }); } + private PathSearchType getPathSearchType(String type) { + if (type.equals("최소 시간")) { + return PathSearchType.DURATION; + } + if (type.equals("최소 거리")) { + return PathSearchType.DISTANCE; + } + throw new IllegalArgumentException(String.format("do not match PathSearchType: %s", type)); + } + } diff --git a/src/test/java/nextstep/favorite/acceptance/step/FavoriteAcceptanceTest.java b/src/test/java/nextstep/favorite/acceptance/step/FavoriteAcceptanceTest.java index 0858622b1..4e95c7113 100644 --- a/src/test/java/nextstep/favorite/acceptance/step/FavoriteAcceptanceTest.java +++ b/src/test/java/nextstep/favorite/acceptance/step/FavoriteAcceptanceTest.java @@ -129,11 +129,11 @@ void deleteFavorite() { 양재역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(지하철역_생성_요청_본문("양재역"))); 남부터미널역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(지하철역_생성_요청_본문("남부터미널역"))); - 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("2호선", "green", 교대역_아이디, 강남역_아이디, 10L))); - 신분당선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("신분당선", "red", 강남역_아이디, 양재역_아이디, 10L))); - 삼호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("삼호선", "orange", 교대역_아이디, 남부터미널역_아이디, 2L))); + 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("2호선", "green", 교대역_아이디, 강남역_아이디, 10L, 10L))); + 신분당선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("신분당선", "red", 강남역_아이디, 양재역_아이디, 10L, 10L))); + 삼호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("삼호선", "orange", 교대역_아이디, 남부터미널역_아이디, 2L, 2L))); - 지하철_구간_등록_요청(삼호선_아이디, 구간_등록_요청_본문(남부터미널역_아이디, 양재역_아이디, 3L)); + 지하철_구간_등록_요청(삼호선_아이디, 구간_등록_요청_본문(남부터미널역_아이디, 양재역_아이디, 3L, 3L)); } diff --git a/src/test/java/nextstep/subway/acceptance/LineAcceptanceTest.java b/src/test/java/nextstep/subway/acceptance/LineAcceptanceTest.java index 0a84f1566..a206dae00 100644 --- a/src/test/java/nextstep/subway/acceptance/LineAcceptanceTest.java +++ b/src/test/java/nextstep/subway/acceptance/LineAcceptanceTest.java @@ -60,7 +60,8 @@ void createLine() { COLOR_ONE, 강남역_아이디, 교대역_아이디, - DISTANCE + DISTANCE, + 10L )); // then diff --git a/src/test/java/nextstep/subway/acceptance/LineSectionAcceptanceTest.java b/src/test/java/nextstep/subway/acceptance/LineSectionAcceptanceTest.java index 3166645d3..4c31f8ade 100644 --- a/src/test/java/nextstep/subway/acceptance/LineSectionAcceptanceTest.java +++ b/src/test/java/nextstep/subway/acceptance/LineSectionAcceptanceTest.java @@ -54,6 +54,7 @@ void addSection() { ExtractableResponse 지하철_구간_등록_응답 = 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문( 교대역_아이디, 봉천역_아이디, + 10L, 10L )); @@ -83,6 +84,7 @@ void addSectionWithInvalidUpStation() { ExtractableResponse 지하철_구간_등록_응답 = 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문( 낙성대역_아이디, 봉천역_아이디, + 10L, 10L )); @@ -106,7 +108,7 @@ void addSectionWithAlreadyExistsStation() { Long 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(강남_교대_이호선_응답); Long 교대역_아이디 = 지하철_노선_응답에서_노선의_하행_종점역_아이디_추출(강남_교대_이호선_응답); Long 봉천역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(봉천역_생성_요청_본문())); - 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문(교대역_아이디, 봉천역_아이디, 10L)); + 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문(교대역_아이디, 봉천역_아이디, 10L, 10L)); Long 서울대입구역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(서울대입구역_생성_요청_본문())); @@ -114,6 +116,7 @@ void addSectionWithAlreadyExistsStation() { ExtractableResponse 지하철_구간_등록_응답 = 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문( 서울대입구역_아이디, 봉천역_아이디, + 10L, 10L )); @@ -133,7 +136,7 @@ void addSectionWithAlreadyExistsStation() { @Test void addSectionWithIndex() { // given - ExtractableResponse 강남_봉천_이호선_응답 = 지하철_노선_생성_요청(강남역_봉천역_구간_이호선_생성_요청(10L)); + ExtractableResponse 강남_봉천_이호선_응답 = 지하철_노선_생성_요청(강남역_봉천역_구간_이호선_생성_요청()); Long 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(강남_봉천_이호선_응답); Long 강남역_아이디 = 지하철_노선_응답에서_노선의_상행_종점역_아이디_추출(강남_봉천_이호선_응답); Long 봉천역_아이디 = 지하철_노선_응답에서_노선의_하행_종점역_아이디_추출(강남_봉천_이호선_응답); @@ -143,6 +146,7 @@ void addSectionWithIndex() { ExtractableResponse 지하철_구간_등록_응답 = 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문( 강남역_아이디, 서울대입구역_아이디, + 5L, 5L )); @@ -169,7 +173,7 @@ void removeSection() { Long 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(강남_교대_이호선_응답); Long 교대역_아이디 = 지하철_노선_응답에서_노선의_하행_종점역_아이디_추출(강남_교대_이호선_응답); Long 봉천역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(봉천역_생성_요청_본문())); - 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문(교대역_아이디, 봉천역_아이디, 10L)); + 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문(교대역_아이디, 봉천역_아이디, 10L, 10L)); // when ExtractableResponse 지하철_구간_삭제_응답 = 지하철_구간_삭제_요청(이호선_아이디, 봉천역_아이디); @@ -217,8 +221,8 @@ void removeSectionWithIndex() { Long 강남역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(강남역_생성_요청_본문())); Long 교대역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(교대역_생성_요청_본문())); Long 낙성대역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(낙성대역_생성_요청_본문())); - Long 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문(이호선_이름, 이호선_색, 강남역_아이디, 교대역_아이디, 10L))); - 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문(교대역_아이디, 낙성대역_아이디, 10L)); + Long 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문(이호선_이름, 이호선_색, 강남역_아이디, 교대역_아이디, 10L, 10L))); + 지하철_구간_등록_요청(이호선_아이디, 구간_등록_요청_본문(교대역_아이디, 낙성대역_아이디, 10L, 10L)); // when ExtractableResponse 지하철_구간_삭제_응답 = 지하철_구간_삭제_요청(이호선_아이디, 교대역_아이디); diff --git a/src/test/java/nextstep/subway/acceptance/PathAcceptanceTest.java b/src/test/java/nextstep/subway/acceptance/PathAcceptanceTest.java index 05057f7a7..bf97ac7c1 100644 --- a/src/test/java/nextstep/subway/acceptance/PathAcceptanceTest.java +++ b/src/test/java/nextstep/subway/acceptance/PathAcceptanceTest.java @@ -14,6 +14,7 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import nextstep.subway.acceptance.step.PathSteps; +import nextstep.subway.domain.enums.PathSearchType; import nextstep.utils.context.AcceptanceTest; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.DisplayName; @@ -38,14 +39,14 @@ class PathAcceptanceTest { * When 출발역과 도착역을 기준으로 경로를 조회하면 * Then 최단거리를 기준으로 경로를 조회한다. */ - @DisplayName("지하철역 경로를 조회한다.") + @DisplayName("지하철역 최단 거리 기준 경로를 조회한다.") @Test void getPaths() { // given 이호선_삼호선_신분당선_노선의_구간_존재(); // when - ExtractableResponse 지하철_경로_조회_응답 = 지하철_경로_조회_요청(교대역_아이디, 양재역_아이디); + ExtractableResponse 지하철_경로_조회_응답 = 지하철_경로_조회_요청(교대역_아이디, 양재역_아이디, PathSearchType.DISTANCE); // then SoftAssertions.assertSoftly(softAssertions -> { softAssertions.assertThat(지하철_경로_조회_응답.statusCode()).isEqualTo(HttpStatus.OK.value()); @@ -70,11 +71,11 @@ void getPaths() { 양재역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(지하철역_생성_요청_본문("양재역"))); 남부터미널역_아이디 = 지하철역_응답에서_역_아이디_추출(지하철_역_생성_요청(지하철역_생성_요청_본문("남부터미널역"))); - 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("2호선", "green", 교대역_아이디, 강남역_아이디, 10L))); - 신분당선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("신분당선", "red", 강남역_아이디, 양재역_아이디, 10L))); - 삼호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("삼호선", "orange", 교대역_아이디, 남부터미널역_아이디, 2L))); + 이호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("2호선", "green", 교대역_아이디, 강남역_아이디, 10L, 10L))); + 신분당선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("신분당선", "red", 강남역_아이디, 양재역_아이디, 10L, 10L))); + 삼호선_아이디 = 지하철_노선_응답에서_노선_아이디_추출(지하철_노선_생성_요청(노선_생성_요청_본문("삼호선", "orange", 교대역_아이디, 남부터미널역_아이디, 2L, 2L))); - 지하철_구간_등록_요청(삼호선_아이디, 구간_등록_요청_본문(남부터미널역_아이디, 양재역_아이디, 3L)); + 지하철_구간_등록_요청(삼호선_아이디, 구간_등록_요청_본문(남부터미널역_아이디, 양재역_아이디, 3L, 3L)); } } diff --git a/src/test/java/nextstep/subway/acceptance/step/PathSteps.java b/src/test/java/nextstep/subway/acceptance/step/PathSteps.java index 8981f59d6..2e9f17595 100644 --- a/src/test/java/nextstep/subway/acceptance/step/PathSteps.java +++ b/src/test/java/nextstep/subway/acceptance/step/PathSteps.java @@ -4,16 +4,19 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import java.util.List; +import nextstep.subway.domain.enums.PathSearchType; import org.springframework.http.MediaType; public class PathSteps { public static final String SUBWAY_PATH_BASE_PATH = "/paths"; - public static ExtractableResponse 지하철_경로_조회_요청(Long sourceStationId, Long targetStationId) { + public static ExtractableResponse 지하철_경로_조회_요청(Long sourceStationId, Long targetStationId, + PathSearchType searchType) { return RestAssured.given().log().all() .queryParam("source", sourceStationId) .queryParam("target", targetStationId) + .queryParam("type", searchType.name()) .accept(MediaType.APPLICATION_JSON_VALUE) .when().get(SUBWAY_PATH_BASE_PATH) .then().log().all() @@ -33,4 +36,8 @@ public class PathSteps { public static long 지하철역_경로_조회_응답에서_경로_거리_추출(ExtractableResponse 지하철_경로_조회_응답) { return 지하철_경로_조회_응답.jsonPath().getLong("distance"); } + + public static long 지하철역_경로_조회_응답에서_경로_시간_추출(ExtractableResponse 지하철_경로_조회_응답) { + return 지하철_경로_조회_응답.jsonPath().getLong("duration"); + } } diff --git a/src/test/java/nextstep/subway/fixture/LineFixture.java b/src/test/java/nextstep/subway/fixture/LineFixture.java index bcbe1e839..c42cd9742 100644 --- a/src/test/java/nextstep/subway/fixture/LineFixture.java +++ b/src/test/java/nextstep/subway/fixture/LineFixture.java @@ -1,9 +1,9 @@ package nextstep.subway.fixture; import java.util.Map; +import nextstep.subway.acceptance.step.StationSteps; import nextstep.subway.application.dto.response.StationResponse; import nextstep.subway.domain.entity.Line; -import nextstep.subway.acceptance.step.StationSteps; import org.springframework.test.util.ReflectionTestUtils; public class LineFixture { @@ -18,19 +18,19 @@ public class LineFixture { StationResponse 서울역 = StationSteps.지하철_역_생성_요청(StationFixture.서울역_생성_요청_본문()).as(StationResponse.class); StationResponse 청량리역 = StationSteps.지하철_역_생성_요청(StationFixture.청량리역_생성_요청_본문()).as(StationResponse.class); return 노선_생성_요청_본문(일호선_이름, 일호선_색, 서울역.getId(), 청량리역.getId(), - 10L); + 10L, 10L); } public static Map 강남역_교대역_구간_이호선_생성_요청() { StationResponse 강남역 = StationSteps.지하철_역_생성_요청(StationFixture.강남역_생성_요청_본문()).as(StationResponse.class); StationResponse 교대역 = StationSteps.지하철_역_생성_요청(StationFixture.교대역_생성_요청_본문()).as(StationResponse.class); - return 노선_생성_요청_본문(이호선_이름, 이호선_색, 강남역.getId(), 교대역.getId(), 10L); + return 노선_생성_요청_본문(이호선_이름, 이호선_색, 강남역.getId(), 교대역.getId(), 10L, 10L); } - public static Map 강남역_봉천역_구간_이호선_생성_요청(long distance) { + public static Map 강남역_봉천역_구간_이호선_생성_요청() { StationResponse 강남역 = StationSteps.지하철_역_생성_요청(StationFixture.강남역_생성_요청_본문()).as(StationResponse.class); StationResponse 봉천역 = StationSteps.지하철_역_생성_요청(StationFixture.봉천역_생성_요청_본문()).as(StationResponse.class); - return 노선_생성_요청_본문(이호선_이름, 이호선_색, 강남역.getId(), 봉천역.getId(), distance); + return 노선_생성_요청_본문(이호선_이름, 이호선_색, 강남역.getId(), 봉천역.getId(), 10L, 10L); } public static Map 노선_생성_요청_본문( @@ -38,10 +38,11 @@ public class LineFixture { String color, Long upStationId, Long downStationId, - Long distance + Long distance, + Long duration ) { return Map.of("name", name, "color", color, "upStationId", upStationId, "downStationId", downStationId, - "distance", distance); + "distance", distance, "duration", duration); } public static Map 노선_수정_요청( diff --git a/src/test/java/nextstep/subway/fixture/SectionFixture.java b/src/test/java/nextstep/subway/fixture/SectionFixture.java index 67de189e4..3bebc3254 100644 --- a/src/test/java/nextstep/subway/fixture/SectionFixture.java +++ b/src/test/java/nextstep/subway/fixture/SectionFixture.java @@ -8,20 +8,21 @@ public class SectionFixture { - public static Map 구간_등록_요청_본문(Long upStationId, Long downStationId, Long distance) { + public static Map 구간_등록_요청_본문(Long upStationId, Long downStationId, Long distance, long duration) { return Map.of( "upStationId", upStationId, "downStationId", downStationId, - "distance", distance + "distance", distance, + "duration", duration ); } - public static Section giveOne(Line line, Station upStation, Station downStation, long distance) { - return new Section(line, upStation, downStation, distance); + public static Section giveOne(Line line, Station upStation, Station downStation, long distance, long duration) { + return new Section(line, upStation, downStation, distance, duration); } - public static Section giveOne(long id, Line line, Station upStation, Station downStation, long distance) { - Section section = new Section(line, upStation, downStation, distance); + public static Section giveOne(long id, Line line, Station upStation, Station downStation, long distance, long duration) { + Section section = new Section(line, upStation, downStation, distance, duration); ReflectionTestUtils.setField(section, "id", id); return section; } diff --git a/src/test/java/nextstep/subway/unit/LineServiceMockTest.java b/src/test/java/nextstep/subway/unit/LineServiceMockTest.java index 8a738f107..e485d624f 100644 --- a/src/test/java/nextstep/subway/unit/LineServiceMockTest.java +++ b/src/test/java/nextstep/subway/unit/LineServiceMockTest.java @@ -71,9 +71,9 @@ void setUp() { 이호선 = LineFixture.giveOne(1L, 이호선_이름, 이호선_색); 일호선 = LineFixture.giveOne(2L, 일호선_이름, 일호선_색); - 강남역_교대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 교대역, 10L); - 교대역_낙성대역_구간 = SectionFixture.giveOne(2L, 이호선, 교대역, 낙성대역, 10L); - 서울역_청량리역_구간 = SectionFixture.giveOne(3L, 일호선, 서울역, 청량리역, 10L); + 강남역_교대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 교대역, 10L, 10L); + 교대역_낙성대역_구간 = SectionFixture.giveOne(2L, 이호선, 교대역, 낙성대역, 10L, 10L); + 서울역_청량리역_구간 = SectionFixture.giveOne(3L, 일호선, 서울역, 청량리역, 10L, 10L); } @DisplayName("노선의 구간 추가 서비스 단위 테스트") @@ -86,7 +86,7 @@ void addSection() { given(stationService.getStationById(낙성대역.getId())).willReturn(낙성대역); // when - AddSectionRequest 교대역_낙성대역_구간_추가_요청 = new AddSectionRequest(교대역.getId(), 낙성대역.getId(), 10L); + AddSectionRequest 교대역_낙성대역_구간_추가_요청 = new AddSectionRequest(교대역.getId(), 낙성대역.getId(), 10L, 10L); LineResponse result = lineService.addSection(이호선.getId(), 교대역_낙성대역_구간_추가_요청); // then diff --git a/src/test/java/nextstep/subway/unit/LineServiceTest.java b/src/test/java/nextstep/subway/unit/LineServiceTest.java index 85c06b3c1..6cd3e1444 100644 --- a/src/test/java/nextstep/subway/unit/LineServiceTest.java +++ b/src/test/java/nextstep/subway/unit/LineServiceTest.java @@ -69,9 +69,9 @@ void setUp() { 이호선 = lineRepository.save(LineFixture.giveOne(1L, 이호선_이름, 이호선_색)); 일호선 = lineRepository.save(LineFixture.giveOne(2L, 일호선_이름, 일호선_색)); - 강남역_교대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 교대역, 10L); - 교대역_낙성대역_구간 = SectionFixture.giveOne(2L, 이호선, 교대역, 낙성대역, 10L); - 서울역_청량리역_구간 = SectionFixture.giveOne(3L, 일호선, 서울역, 청량리역, 10L); + 강남역_교대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 교대역, 10L, 10L); + 교대역_낙성대역_구간 = SectionFixture.giveOne(2L, 이호선, 교대역, 낙성대역, 10L, 10L); + 서울역_청량리역_구간 = SectionFixture.giveOne(3L, 일호선, 서울역, 청량리역, 10L, 10L); } @DisplayName("노선의 구간 추가 서비스 단위 테스트") @@ -81,7 +81,7 @@ void addSection() { Line 이호선 = 강남역_교대역_구간_이호선(); // when - AddSectionRequest 교대역_낙성대역_구간_추가_요청 = new AddSectionRequest(교대역.getId(), 낙성대역.getId(), 10L); + AddSectionRequest 교대역_낙성대역_구간_추가_요청 = new AddSectionRequest(교대역.getId(), 낙성대역.getId(), 10L, 10L); LineResponse result = lineService.addSection(이호선.getId(), 교대역_낙성대역_구간_추가_요청); // then diff --git a/src/test/java/nextstep/subway/unit/LineTest.java b/src/test/java/nextstep/subway/unit/LineTest.java index 28f82af3d..41a4e8566 100644 --- a/src/test/java/nextstep/subway/unit/LineTest.java +++ b/src/test/java/nextstep/subway/unit/LineTest.java @@ -39,8 +39,8 @@ void setUp() { 이호선 = LineFixture.giveOne(1L, 이호선_이름, 이호선_색); - 강남역_교대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 교대역, 10L); - 교대역_낙성대역_구간 = SectionFixture.giveOne(2L, 이호선, 교대역, 낙성대역, 10L); + 강남역_교대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 교대역, 10L, 10L); + 교대역_낙성대역_구간 = SectionFixture.giveOne(2L, 이호선, 교대역, 낙성대역, 10L, 10L); } diff --git a/src/test/java/nextstep/subway/unit/PathFinderTest.java b/src/test/java/nextstep/subway/unit/PathFinderTest.java index 879b81175..7e0b2bba4 100644 --- a/src/test/java/nextstep/subway/unit/PathFinderTest.java +++ b/src/test/java/nextstep/subway/unit/PathFinderTest.java @@ -12,6 +12,7 @@ import nextstep.subway.domain.entity.PathFinder; import nextstep.subway.domain.entity.Section; import nextstep.subway.domain.entity.Station; +import nextstep.subway.domain.enums.PathSearchType; import nextstep.subway.fixture.LineFixture; import nextstep.subway.fixture.SectionFixture; import nextstep.subway.fixture.StationFixture; @@ -53,10 +54,10 @@ class PathFinderTest { 삼호선 = LineFixture.giveOne(2L, "3호선", "orange"); 신분당선 = LineFixture.giveOne(3L, "신분당선", "red"); - 교대역_강남역_구간 = SectionFixture.giveOne(1L, 이호선, 교대역, 강남역, 10L); - 교대역_남부터미널역_구간 = SectionFixture.giveOne(2L, 삼호선, 교대역, 남부터미널역, 2L); - 남부터미널역_양재역_구간 = SectionFixture.giveOne(3L, 삼호선, 남부터미널역, 양재역, 3L); - 강남역_양재역_구간 = SectionFixture.giveOne(4L, 신분당선, 강남역, 양재역, 10L); + 교대역_강남역_구간 = SectionFixture.giveOne(1L, 이호선, 교대역, 강남역, 10L, 10L); + 교대역_남부터미널역_구간 = SectionFixture.giveOne(2L, 삼호선, 교대역, 남부터미널역, 2L, 2L); + 남부터미널역_양재역_구간 = SectionFixture.giveOne(3L, 삼호선, 남부터미널역, 양재역, 3L, 3L); + 강남역_양재역_구간 = SectionFixture.giveOne(4L, 신분당선, 강남역, 양재역, 10L, 10L); 이호선.addSection(교대역_강남역_구간); 삼호선.addSection(교대역_남부터미널역_구간); @@ -72,12 +73,12 @@ void findShorPath() { PathFinder pathFinder = new PathFinder(List.of(이호선, 삼호선, 신분당선)); // when - Optional 교대역_양재역_최단경로 = pathFinder.findShortestPath(교대역, 양재역); + Optional 교대역_양재역_최단경로 = pathFinder.findShortestPath(교대역, 양재역, PathSearchType.DISTANCE); // then SoftAssertions.assertSoftly(softAssertions -> { Path shortestPath = 교대역_양재역_최단경로.orElseThrow(); - softAssertions.assertThat(shortestPath.getStations()).containsExactly(교대역, 남부터미널역, 양재역); + softAssertions.assertThat(shortestPath.getStationsOfPath()).containsExactly(교대역, 남부터미널역, 양재역); softAssertions.assertThat(shortestPath.getDistance()).isEqualTo(5L); }); @@ -92,7 +93,7 @@ void findShorPathWithError() { // when Throwable catchThrowable = catchThrowable(() -> { - pathFinder.findShortestPath(교대역, 교대역); + pathFinder.findShortestPath(교대역, 교대역, PathSearchType.DISTANCE); }); // then @@ -111,7 +112,7 @@ void findShorPathWithError2() { PathFinder pathFinder = new PathFinder(List.of(이호선, 신분당선)); // when - Optional 교대역_남부터미널역_경로 = pathFinder.findShortestPath(교대역, 남부터미널역); + Optional 교대역_남부터미널역_경로 = pathFinder.findShortestPath(교대역, 남부터미널역, PathSearchType.DISTANCE); // then SoftAssertions.assertSoftly(softAssertions -> { @@ -130,7 +131,7 @@ void findShorPathWithError3() { Station 존재하지_않는_역 = StationFixture.giveOne(Long.MAX_VALUE, "폐쇄역"); // when - Optional 존재하지_않는_경로 = pathFinder.findShortestPath(존재하지_않는_역, 양재역); + Optional 존재하지_않는_경로 = pathFinder.findShortestPath(존재하지_않는_역, 양재역, PathSearchType.DISTANCE); // then SoftAssertions.assertSoftly(softAssertions -> { diff --git a/src/test/java/nextstep/subway/unit/SectionsTest.java b/src/test/java/nextstep/subway/unit/SectionsTest.java index 5008bf94e..d1eaa218e 100644 --- a/src/test/java/nextstep/subway/unit/SectionsTest.java +++ b/src/test/java/nextstep/subway/unit/SectionsTest.java @@ -48,10 +48,11 @@ void setUp() { 이호선 = LineFixture.giveOne(1L, 이호선_이름, 이호선_색); - 강남역_낙성대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 낙성대역, 10L); - 낙성대역_봉천역_구간 = SectionFixture.giveOne(2L, 이호선, 낙성대역, 봉천역, 10L); - 강남역_교대역_구간 = SectionFixture.giveOne(3L, 이호선, 강남역, 교대역, 5L); - 강남역_낙성대역_구간의_길이와_같은_강남역_교대역_구간 = SectionFixture.giveOne(4L, 이호선, 강남역, 교대역, 강남역_낙성대역_구간.getDistance()); + 강남역_낙성대역_구간 = SectionFixture.giveOne(1L, 이호선, 강남역, 낙성대역, 10L, 10L); + 낙성대역_봉천역_구간 = SectionFixture.giveOne(2L, 이호선, 낙성대역, 봉천역, 10L, 10L); + 강남역_교대역_구간 = SectionFixture.giveOne(3L, 이호선, 강남역, 교대역, 5L, 5L); + 강남역_낙성대역_구간의_길이와_같은_강남역_교대역_구간 = SectionFixture + .giveOne(4L, 이호선, 강남역, 교대역, 강남역_낙성대역_구간.getDistance(), 강남역_낙성대역_구간.getDuration()); } diff --git a/src/test/resources/features/path.feature b/src/test/resources/features/path.feature index e3835f3f1..918c19d8b 100644 --- a/src/test/resources/features/path.feature +++ b/src/test/resources/features/path.feature @@ -1,11 +1,11 @@ Feature: 지하철역 경로 관련 기능 # /** -# * 교대역 --- 2호선, 10 ---- 강남역 -# * | | -# * 3호선, 2 신분당선, 10 -# * | | -# * 남부터미널역 --- 3호선, 3 --- 양재 +# * 교대역 --- 2호선, 10, 1 ---- 강남역 +# * | | +# * 3호선, 2, 20 신분당선, 10, 1 +# * | | +# * 남부터미널역 -- 3호선, 3, 30 ---- 양재 # */ Background: 이호선, 삼호선, 신분당선 노선의 구간 Given 지하철역들을 생성 요청하고 @@ -15,14 +15,20 @@ Feature: 지하철역 경로 관련 기능 | 양재역 | | 남부터미널역 | And 지하철 노선들을 생성 요청하고 - | name | color | upStation | downStation | distance | - | 2호선 | green | 교대역 | 강남역 | 10 | - | 신분당선 | red | 강남역 | 양재역 | 10 | - | 3호선 | orange | 교대역 | 남부터미널역 | 2 | + | name | color | upStation | downStation | distance | duration | + | 2호선 | green | 교대역 | 강남역 | 10 | 1 | + | 신분당선 | red | 강남역 | 양재역 | 10 | 1 | + | 3호선 | orange | 교대역 | 남부터미널역 | 2 | 20 | And 지하철 구간을 등록 요청하고 - | lineName | upStation | downStation | distance | - | 3호선 | 남부터미널역 | 양재역 | 3 | + | lineName | upStation | downStation | distance | duration | + | 3호선 | 남부터미널역 | 양재역 | 3 | 30 | - Scenario: 지하철역 최단 경로를 조회한다. - When "교대역"과 "양재역"의 경로를 조회하면 - Then 거리가 5인 "교대역,남부터미널역,양재역"경로가 조회된다 + Scenario: 지하철역 최단 거리 경로를 조회한다. + When "교대역"에서 "양재역"까지의 "최소 거리" 기준으로 경로 조회를 요청하면 + Then "최소 거리" 기준 "교대역,남부터미널역,양재역" 경로를 응답 + And 총 거리 5와 소요 시간 50을 함께 응답함 + + Scenario: 지하철역 최단 시간 경로를 조회한다. + When "양재역"에서 "교대역"까지의 "최소 시간" 기준으로 경로 조회를 요청하면 + Then "최소 시간" 기준 "양재역,강남역,교대역" 경로를 응답 + And 총 거리 20와 소요 시간 2을 함께 응답함