Skip to content
Open
11 changes: 9 additions & 2 deletions src/main/java/nextstep/subway/applicaion/dto/PathResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ public class PathResponse {
private List<StationResponse> stations;
private int distance;
private int duration;
private int fare;

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

public static PathResponse of(Path path) {
Expand All @@ -22,8 +24,9 @@ public static PathResponse of(Path path) {
.collect(Collectors.toList());
int distance = path.extractDistance();
int duration = path.extractDuration();
int fare = path.getFare();

return new PathResponse(stations, distance, duration);
return new PathResponse(stations, distance, duration, fare);
}

public List<StationResponse> getStations() {
Expand All @@ -37,4 +40,8 @@ public int getDistance() {
public int getDuration() {
return duration;
}

public int getFare() {
return fare;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nextstep.subway.constant;

@FunctionalInterface
public interface EdgeWeightFunction<EdgeWeight, Integer> {
Integer apply(EdgeWeight section);

}
16 changes: 9 additions & 7 deletions src/main/java/nextstep/subway/constant/FindPathType.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package nextstep.subway.constant;

import nextstep.subway.domain.Section;

public enum FindPathType {
DISTANCE("DISTANCE", "๊ฑฐ๋ฆฌ"),
DURATION("DURATION", "์‹œ๊ฐ„");
DISTANCE("DISTANCE", Section::getDistance),
DURATION("DURATION", Section::getDuration);

private final String type;
private final String description;
private final EdgeWeightFunction<Section, Integer> edgeWeightFunction;

FindPathType(String type, String description) {
FindPathType(String type, EdgeWeightFunction<Section, Integer> edgeWeightFunction) {
this.type = type;
this.description = description;
this.edgeWeightFunction = edgeWeightFunction;
}

public String getType() {
return type;
}

public String getDescription() {
return description;
public Integer getEdgeWeight(Section section) {
return edgeWeightFunction.apply(section);
}
}
16 changes: 16 additions & 0 deletions src/main/java/nextstep/subway/domain/CalculateFareFacade.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nextstep.subway.domain;

public class CalculateFareFacade {

private final int distance;

public CalculateFareFacade(int distance) {
this.distance = distance;
}

public int calculateFare() {
int calculateOverTen = new CalculateOverTen().calculate(distance);
int calculateOverFifty = new CalculateOverFifty().calculate(distance);
return calculateOverTen + calculateOverFifty;
}
}
13 changes: 13 additions & 0 deletions src/main/java/nextstep/subway/domain/CalculateOverFifty.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nextstep.subway.domain;

import static nextstep.subway.domain.Fare.ADDITIONAL_FARE;

public class CalculateOverFifty {
public int calculate(int distance) {
int overFiftyDistance = distance - 50;
if (overFiftyDistance <= 0) {
return 0;
}
return (int) Math.ceil((double) overFiftyDistance / 8) * ADDITIONAL_FARE;
}
}
13 changes: 13 additions & 0 deletions src/main/java/nextstep/subway/domain/CalculateOverTen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nextstep.subway.domain;

import static nextstep.subway.domain.Fare.ADDITIONAL_FARE;
import static nextstep.subway.domain.Fare.MAX_OVER_TEN_FARE;

public class CalculateOverTen {

public int calculate(int distance) {
int overTenDistance = distance - 10;
int fare = (int) ((Math.ceil((double) overTenDistance / 5)) * ADDITIONAL_FARE);
return Math.min(fare, MAX_OVER_TEN_FARE);
}
}
28 changes: 28 additions & 0 deletions src/main/java/nextstep/subway/domain/Fare.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package nextstep.subway.domain;

public class Fare {
private static final int DEFAULT_DISTANCE = 10;
private static final int BASE_FARE = 1250;
public static final int ADDITIONAL_FARE = 100;
public static final int MAX_OVER_TEN_FARE = 800;

private int fare;

public Fare() {}

public void init(int distance) {
this.fare = generateFare(distance);
Copy link

Choose a reason for hiding this comment

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

์ƒ์„ฑ์ž์— ์ดˆ๊ธฐํ™” ๋น„์ฆˆ๋‹ˆ์Šค๋กœ์ง์ด ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ ๋ณด๋‹ค๋Š” ๋ง ๊ทธ๋Œ€๋กœ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ๋™์ž‘(๊ฐ’ ํ• ๋‹น, ์œ ํšจ์„ฑ ๊ฒ€์ฆ ์ •๋„)๋งŒ ํ•ด์ฃผ์‹œ๋Š”๊ฑธ ๊ถŒ์žฅ๋“œ๋ ค์š”.

๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ ์ƒ์„ฑ์ž ํ˜ธ์ถœ์‹œ ์ถ”๊ฐ€์ ์ธ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์ƒ์„ฑ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ๋ณด๋‹จ ๋‹จ์ˆœํ•˜๊ฒŒ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์ด ๋  ๊ฒƒ ์ •๋„๋งŒ ์œ ์ถ”๋ฅผ ํ•  ์ˆ˜ ์žˆ์ฃ . ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๋กœ์ง๋“ค์ด ์ถ”๊ฐ€๋  ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•ด ์ •์ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜
๋ณ„๋„์˜ init๋ฉ”์„œ๋“œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค!

}

public int getFare() {
return fare;
}

private int generateFare(int distance) {
if (distance <= DEFAULT_DISTANCE) {
return BASE_FARE;
}
int additionalFare = new CalculateFareFacade(distance).calculateFare();
return BASE_FARE + additionalFare;
}
}
6 changes: 6 additions & 0 deletions src/main/java/nextstep/subway/domain/Path.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public int extractDuration() {
return sections.totalDuration();
}

public int getFare() {
Fare fare = new Fare();
fare.init(extractDistance());
return fare.getFare();
}

public List<Station> getStations() {
return sections.getStations();
}
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/nextstep/subway/domain/SectionEdge.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package nextstep.subway.domain;

import nextstep.subway.constant.FindPathType;
import org.jgrapht.graph.DefaultWeightedEdge;

public class SectionEdge extends DefaultWeightedEdge {
private Section section;

public static SectionEdge of(Section section) {
return new SectionEdge(section);
private SectionEdge(Section section) {
this.section = section;
}

public SectionEdge(Section section) {
this.section = section;
public static SectionEdge of(Section section) {
return new SectionEdge(section);
}

public Section getSection() {
Expand Down
7 changes: 1 addition & 6 deletions src/main/java/nextstep/subway/domain/SubwayMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,6 @@ public Path findPath(Station source, Station target) {
private void addEdge(SimpleDirectedWeightedGraph<Station, SectionEdge> graph, Section it) {
SectionEdge sectionEdge = SectionEdge.of(it);
graph.addEdge(it.getUpStation(), it.getDownStation(), sectionEdge);
if (type == FindPathType.DISTANCE) {
graph.setEdgeWeight(sectionEdge, it.getDistance());
}
if (type == FindPathType.DURATION) {
graph.setEdgeWeight(sectionEdge, it.getDuration());
}
graph.setEdgeWeight(sectionEdge, type.getEdgeWeight(it));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;
import nextstep.subway.constant.FindPathType;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

Expand Down
27 changes: 27 additions & 0 deletions src/test/java/nextstep/subway/acceptance/PathAcceptanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,33 @@ void findPathByDuration() {
assertThat(response.jsonPath().getInt("duration")).isEqualTo(21);
}

/**
* <pre>
* Feature: ์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ๊ฒ€์ƒ‰
* Scenario: ๋‘ ์—ญ์˜ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ฒฝ๋กœ๋ฅผ ์กฐํšŒ
* Given ์ง€ํ•˜์ฒ ์—ญ์ด ๋“ฑ๋ก๋˜์–ด์žˆ์Œ
* And ์ง€ํ•˜์ฒ  ๋…ธ์„ ์ด ๋“ฑ๋ก๋˜์–ด์žˆ์Œ
* And ์ง€ํ•˜์ฒ  ๋…ธ์„ ์— ์ง€ํ•˜์ฒ ์—ญ์ด ๋“ฑ๋ก๋˜์–ด์žˆ์Œ
* When ์ถœ๋ฐœ์—ญ์—์„œ ๋„์ฐฉ์—ญ๊นŒ์ง€์˜ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ฒฝ๋กœ ์กฐํšŒ๋ฅผ ์š”์ฒญ
* Then ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ฒฝ๋กœ๋ฅผ ์‘๋‹ต
* And ์ด ๊ฑฐ๋ฆฌ์™€ ์†Œ์š” ์‹œ๊ฐ„์„ ํ•จ๊ป˜ ์‘๋‹ตํ•จ
* And ์ง€ํ•˜์ฒ  ์ด์šฉ ์š”๊ธˆ๋„ ํ•จ๊ป˜ ์‘๋‹ตํ•จ
* </pre>
*/
@DisplayName("๋‘ ์—ญ์˜ ์ตœ์†Œ ๊ฑฐ๋ฆฌ ๊ฒฝ๋กœ๋ฅผ ์กฐํšŒํ•˜๊ณ  ์ด์šฉ ์š”๊ธˆ๋„ ํ•จ๊ป˜ ์‘๋‹ตํ•œ๋‹ค.")
@Test
void findPathByDistanceReturnFare() {
// given : ์„ ํ–‰์กฐ๊ฑด ๊ธฐ์ˆ 

// when : ๊ธฐ๋Šฅ ์ˆ˜ํ–‰
ExtractableResponse<Response> response = ๋‘_์—ญ์˜_์ตœ๋‹จ_๊ฑฐ๋ฆฌ_๊ฒฝ๋กœ_๋ฐ_์†Œ์š”์‹œ๊ฐ„_์กฐํšŒ๋ฅผ_์š”์ฒญ(๊ต๋Œ€์—ญ, ์–‘์žฌ์—ญ, FindPathType.DISTANCE.getType());

// then : ๊ฒฐ๊ณผ ํ™•์ธ
assertThat(response.jsonPath().getList("stations.id", Long.class)).containsExactly(๊ต๋Œ€์—ญ, ๋‚จ๋ถ€ํ„ฐ๋ฏธ๋„์—ญ, ์–‘์žฌ์—ญ);
assertThat(response.jsonPath().getInt("distance")).isEqualTo(5);
assertThat(response.jsonPath().getInt("fare")).isEqualTo(1250);
}

private Long ์ง€ํ•˜์ฒ _๋…ธ์„ _์ƒ์„ฑ_์š”์ฒญ(String name, String color, Long upStation, Long downStation, int distance, int duration) {
Map<String, String> lineCreateParams;
lineCreateParams = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ void path() {
Lists.newArrayList(
new StationResponse(1L, "๊ฐ•๋‚จ์—ญ"),
new StationResponse(2L, "์—ญ์‚ผ์—ญ")
), 10, 10
),
10,
10,
1250
);

when(pathService.findPath(anyLong(), anyLong(), any())).thenReturn(pathResponse);
Expand All @@ -48,7 +51,8 @@ void path() {
fieldWithPath("stations[].id").description("์—ญ ์•„์ด๋””"),
fieldWithPath("stations[].name").description("์—ญ ์ด๋ฆ„"),
fieldWithPath("distance").description("์ด ๊ฑฐ๋ฆฌ"),
fieldWithPath("duration").description("์ด ์†Œ์š” ์‹œ๊ฐ„")
fieldWithPath("duration").description("์ด ์†Œ์š” ์‹œ๊ฐ„"),
fieldWithPath("fare").description("์ด ์š”๊ธˆ")
)));

๋‘_์—ญ์˜_์ตœ๋‹จ_๊ฑฐ๋ฆฌ_๊ฒฝ๋กœ_๋ฐ_์†Œ์š”์‹œ๊ฐ„_์กฐํšŒ๋ฅผ_์š”์ฒญ_๋ฌธ์„œํ™”(1L, 2L, requestSpecification, FindPathType.DURATION.getType());
Expand Down
56 changes: 56 additions & 0 deletions src/test/java/nextstep/subway/unit/FareTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package nextstep.subway.unit;


import nextstep.subway.domain.Fare;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.assertj.core.api.Assertions.assertThat;

@DisplayName("์š”๊ธˆ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ")
class FareTest {

@DisplayName("๊ธฐ๋ณธ ์š”๊ธˆ์ผ๋•Œ ํ…Œ์ŠคํŠธ")
@Test
void defaultFare() {
// given
int distance = 10;

// when
Fare fare = new Fare();
fare.init(distance);

// then
assertThat(fare.getFare()).isEqualTo(1250);
}

@DisplayName("10km์ดˆ๊ณผ ~ 50km๊นŒ์ง€(5km๋งˆ๋‹ค 100์›์”ฉ ์ถ”๊ฐ€) ํ…Œ์ŠคํŠธ")
@ParameterizedTest
@CsvSource(value = {"15:1350","20:1450","25:1550","30:1650","35:1750","40:1850","45:1950","50:2050"}, delimiter = ':')
void additionalFare(int distance, int expectedFare) {
// given

// when
Fare fare = new Fare();
fare.init(distance);

// then
assertThat(fare.getFare()).isEqualTo(expectedFare);
}

@DisplayName("50km์ดˆ๊ณผ ~ 100km๊นŒ์ง€(8km๋งˆ๋‹ค 100์›์”ฉ ์ถ”๊ฐ€) ํ…Œ์ŠคํŠธ")
@ParameterizedTest
@CsvSource(value = {"51:2150","59:2250","66:2250","67:2350","75:2450","83:2550","90:2550","91:2650", "100:2750"}, delimiter = ':')
void additionalFare2(int distance, int expectedFare) {
// given

// when
Fare fare = new Fare();
fare.init(distance);

// then
assertThat(fare.getFare()).isEqualTo(expectedFare);
}
}
2 changes: 1 addition & 1 deletion src/test/java/nextstep/subway/unit/LineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import java.util.List;

import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;

class LineTest {

Expand Down
Loading