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
9 changes: 7 additions & 2 deletions src/main/java/nextstep/subway/applicaion/LineService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Service
Expand All @@ -27,7 +28,7 @@ public LineService(LineRepository lineRepository, StationService stationService)

@Transactional
public LineResponse saveLine(LineRequest request) {
Line line = lineRepository.save(new Line(request.getName(), request.getColor(), request.getAdditionalFare()));
Line line = saveLine(request.getEntitySupplier());
if (request.getUpStationId() != null && request.getDownStationId() != null && request.getDistance() != 0) {
Station upStation = stationService.findById(request.getUpStationId());
Station downStation = stationService.findById(request.getDownStationId());
Expand Down Expand Up @@ -62,7 +63,7 @@ public Line findById(Long id) {
@Transactional
public void updateLine(Long id, LineRequest lineRequest) {
Line line = findById(id);
line.update(lineRequest.getName(), lineRequest.getColor(), line.getAdditionalFare());
line.update(lineRequest.getEntitySupplier());
}

@Transactional
Expand All @@ -86,4 +87,8 @@ public void deleteSection(Long lineId, Long stationId) {

line.deleteSection(station);
}

private Line saveLine(Supplier<Line> supplier) {
return lineRepository.save(supplier.get());
}
}
12 changes: 5 additions & 7 deletions src/main/java/nextstep/subway/applicaion/PathService.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package nextstep.subway.applicaion;

import nextstep.member.application.MemberService;
import nextstep.subway.domain.AgeDiscountPolicy;
import nextstep.subway.domain.PathType;
import nextstep.subway.applicaion.dto.PathResponse;
import nextstep.subway.domain.Line;
import nextstep.subway.domain.Path;
import nextstep.subway.domain.PathType;
import nextstep.subway.domain.Station;
import nextstep.subway.domain.SubwayMap;
import nextstep.subway.domain.SubwayMap.SubwayMap;
import org.springframework.stereotype.Service;
import support.auth.userdetails.User;

Expand All @@ -25,13 +24,12 @@ public PathService(LineService lineService, StationService stationService, Membe
this.memberService = memberService;
}

public PathResponse findPath(User user, Long source, Long target, PathType type) {
public PathResponse findPath(User user, Long source, Long target, PathType type, String time) {
Station upStation = stationService.findById(source);
Station downStation = stationService.findById(target);
List<Line> lines = lineService.findLines();
AgeDiscountPolicy ageDiscountPolicy = AgeDiscountPolicy.of(getCurrentUserAge(user.getUsername()));
SubwayMap subwayMap = new SubwayMap(lines);
Path path = subwayMap.findPath(upStation, downStation, type, ageDiscountPolicy);
SubwayMap subwayMap = type.getInstance(lines);
Path path = subwayMap.findPath(upStation, downStation, getCurrentUserAge(user.getUsername()), time);

return PathResponse.of(path);
}
Expand Down
42 changes: 41 additions & 1 deletion src/main/java/nextstep/subway/applicaion/dto/LineRequest.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
package nextstep.subway.applicaion.dto;

import nextstep.subway.domain.Line;

import java.time.LocalTime;
import java.util.function.Supplier;

import static java.time.format.DateTimeFormatter.ISO_TIME;

public class LineRequest {
private String name;
private String color;
private LocalTime startTime;
private LocalTime endTime;
private int intervalTime;
private int additionalFare;
private Long upStationId;
private Long downStationId;
Expand All @@ -12,9 +22,16 @@ public class LineRequest {
public LineRequest() {
}

public LineRequest(String name, String color, int additionalFare, Long upStationId, Long downStationId, int distance, int duration) {
public LineRequest(String name, String color, String startTime, String endTime, int intervalTime, int additionalFare, Long upStationId, Long downStationId, int distance, int duration) {
this.name = name;
this.color = color;
if (startTime != null) {
this.startTime = LocalTime.parse(startTime, ISO_TIME);
}
if (endTime != null) {
this.endTime = LocalTime.parse(endTime, ISO_TIME);
}
this.intervalTime = intervalTime;
this.additionalFare = additionalFare;
this.upStationId = upStationId;
this.downStationId = downStationId;
Expand Down Expand Up @@ -49,4 +66,27 @@ public int getDistance() {
public int getDuration() {
return duration;
}

public LocalTime getStartTime() {
return startTime;
}

public LocalTime getEndTime() {
return endTime;
}

public int getIntervalTime() {
return intervalTime;
}

public Supplier<Line> getEntitySupplier() {
return () -> Line.builder()
.name(this.name)
.color(this.color)
.additionalFare(this.additionalFare)
.startTime(this.startTime)
.endTime(this.endTime)
.intervalTime(this.intervalTime)
.build();
}
}
39 changes: 37 additions & 2 deletions src/main/java/nextstep/subway/applicaion/dto/LineResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,43 @@

import nextstep.subway.domain.Line;

import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

import static java.time.format.DateTimeFormatter.ISO_TIME;

public class LineResponse {
private Long id;
private String name;
private String color;
private LocalTime startTime;
private LocalTime endTime;
private int intervalTime;
private List<StationResponse> stations;

public static LineResponse of(Line line) {
List<StationResponse> stations = line.getStations().stream()
.map(StationResponse::of)
.collect(Collectors.toList());
return new LineResponse(line.getId(), line.getName(), line.getColor(), stations);
return new LineResponse(
line.getId(),
line.getName(),
line.getColor(),
line.getStartTime(),
line.getEndTime(),
line.getIntervalTime(),
stations
);
}

public LineResponse(Long id, String name, String color, List<StationResponse> stations) {
public LineResponse(Long id, String name, String color, LocalTime startTime, LocalTime endTime, int intervalTime, List<StationResponse> stations) {
this.id = id;
this.name = name;
this.color = color;
this.startTime = startTime;
this.endTime = endTime;
this.intervalTime = intervalTime;
this.stations = stations;
}

Expand All @@ -37,6 +54,24 @@ public String getColor() {
return color;
}

public String getStartTime() {
if (this.startTime == null) {
return null;
}
return startTime.format(ISO_TIME);
}

public String getEndTime() {
if (this.startTime == null) {
return null;
}
return endTime.format(ISO_TIME);
}

public int getIntervalTime() {
return intervalTime;
}

public List<StationResponse> getStations() {
return stations;
}
Expand Down
17 changes: 15 additions & 2 deletions src/main/java/nextstep/subway/applicaion/dto/PathResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@

import nextstep.subway.domain.Path;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

import static nextstep.support.entity.Formatters.DATE_TIME_PATH;

public class PathResponse {
private List<StationResponse> stations;
private int distance;
private int duration;
private int fare;
private LocalDateTime arrivalTime;

public PathResponse(List<StationResponse> stations, int distance, int duration, int fare) {
public PathResponse(List<StationResponse> stations, int distance, int duration, int fare, LocalDateTime arrivalTime) {
this.stations = stations;
this.distance = distance;
this.duration = duration;
this.fare = fare;
this.arrivalTime = arrivalTime;
}

public static PathResponse of(Path path) {
Expand All @@ -25,7 +30,8 @@ public static PathResponse of(Path path) {
int distance = path.extractDistance();
int duration = path.extractDuration();
int fare = path.getFare();
return new PathResponse(stations, distance, duration, fare);
LocalDateTime arrivalTime = path.getArrivalTime();
return new PathResponse(stations, distance, duration, fare, arrivalTime);
}

public List<StationResponse> getStations() {
Expand All @@ -43,4 +49,11 @@ public int getDuration() {
public int getFare() {
return fare;
}

public String getArrivalTime() {
if (this.arrivalTime == null) {
return "";
}
return arrivalTime.format(DATE_TIME_PATH);
}
}
109 changes: 109 additions & 0 deletions src/main/java/nextstep/subway/domain/ArrivalTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package nextstep.subway.domain;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

import static nextstep.support.entity.Formatters.DATE_TIME_PATH;

public class ArrivalTime {
private Sections sections;
private Lines lines;
private LocalDateTime dateTime;
private LocalTime startTime;

private LocalDateTime currentDateTime;
private Line currentLine = null;

public ArrivalTime(List<Section> sections, List<Line> lines, String time) {
this.sections = new Sections(sections);
this.lines = new Lines(lines);
this.dateTime = LocalDateTime.parse(time, DATE_TIME_PATH);
this.startTime = findLine(sections.get(0)).getStartTime();
}

public LocalDateTime value() {
return getTimeOfFastestPath(dateTime);
}

private LocalDateTime getTimeOfFastestPath(LocalDateTime dateTime) {
this.currentDateTime = dateTime;

for (Section section : sections.getSections()) {
if (confirmPathCondition(section)) {
return getTimeOfFirstPath();
}
}

return currentDateTime;
}

private boolean confirmPathCondition(Section section) {
Line line = findLine(section);
boolean notSameLine = !line.equals(currentLine);

setupCurrentDateTime(notSameLine, line, section);
if (notSameLine && goingLastTime(line.getEndTime())) {
return true;
}
setupCurrentLine(notSameLine, line);
return false;
}

private void setupCurrentDateTime(boolean notSameLine, Line line, Section section) {
if (notSameLine) {
this.currentDateTime = calculateTimeInBeforeStations(line, section);
}
this.currentDateTime = currentDateTime.plusMinutes(section.getDuration());
}

private void setupCurrentLine(boolean notSameLine, Line line) {
if (notSameLine) {
this.currentLine = line;
}
}

private LocalDateTime getTimeOfFirstPath() {
LocalDateTime nextDayAtStartDateTime = changeTime(dateTime.plusDays(1), startTime);
return getTimeOfFastestPath(nextDayAtStartDateTime);
}

private boolean goingLastTime(LocalTime endTime) {
return currentDateTime.isAfter(changeTime(currentDateTime, endTime));
}

private LocalDateTime calculateTimeInBeforeStations(Line currentLine, Section section) {
LocalDateTime targetTime = changeTime(currentDateTime, currentLine.getStartTime());
LocalDateTime fastestDepartureTime = findFastestDepartureTime(currentDateTime, targetTime, currentLine.getIntervalTime());
int beforeDuration = getBeforeDuration(currentLine, section);
return fastestDepartureTime.plusMinutes(beforeDuration);
}

private Line findLine(Section section) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일급 컬렉션이 구현되어있다면 lines.indexOf(section)도 가능하겠죠

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일급 컬렉션으로 구현하니 코드가 간결해지네요 ㅎㅎ

return lines.indexOf(section);
}

private LocalDateTime changeTime(LocalDateTime dateTime, LocalTime time) {
return LocalDateTime.of(dateTime.toLocalDate(), time);
}

private int getBeforeDuration(Line line, Section currentSection) {
List<Section> beforeSections = new ArrayList<>();
for (Section section : line.getSections()) {
if (section.equals(currentSection)) {
break;
}
beforeSections.add(section);
}

return new Sections(beforeSections).totalDuration();
}

private LocalDateTime findFastestDepartureTime(LocalDateTime referenceTime, LocalDateTime targetTime, int interval) {
if (referenceTime.isAfter(targetTime)) {
return findFastestDepartureTime(referenceTime, targetTime.plusMinutes(interval), interval);
}
return targetTime;
}
}
Loading