getPatterns() {
private int[] stopBoardAlightCost() {
// Not implemented, no test for this yet.
- return null;
+ return stopBoardAlightCosts;
}
private void expandNumOfStops(int stopIndex) {
diff --git a/src/test/java/org/opentripplanner/raptor/moduletests/B05_EgressStopTransferCostTest.java b/src/test/java/org/opentripplanner/raptor/moduletests/B05_EgressStopTransferCostTest.java
new file mode 100644
index 00000000000..21c1dd2a755
--- /dev/null
+++ b/src/test/java/org/opentripplanner/raptor/moduletests/B05_EgressStopTransferCostTest.java
@@ -0,0 +1,76 @@
+package org.opentripplanner.raptor.moduletests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.opentripplanner.raptor._data.transit.TestRoute.route;
+import static org.opentripplanner.raptor._data.transit.TestTripSchedule.schedule;
+import static org.opentripplanner.raptor.moduletests.support.RaptorModuleTestConfig.multiCriteria;
+
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.opentripplanner.raptor.RaptorService;
+import org.opentripplanner.raptor._data.RaptorTestConstants;
+import org.opentripplanner.raptor._data.transit.TestAccessEgress;
+import org.opentripplanner.raptor._data.transit.TestTransitData;
+import org.opentripplanner.raptor._data.transit.TestTripSchedule;
+import org.opentripplanner.raptor.api.request.RaptorRequestBuilder;
+import org.opentripplanner.raptor.configure.RaptorConfig;
+import org.opentripplanner.raptor.moduletests.support.ModuleTestDebugLogging;
+import org.opentripplanner.raptor.moduletests.support.RaptorModuleTestCase;
+
+/**
+ * FEATURE UNDER TEST
+ *
+ * This verifies that the stopTransferCost is not applied for egress legs. If this is not correctly
+ * handled by the heuristics optimization, the cheapest journey could be discarded.
+ */
+public class B05_EgressStopTransferCostTest implements RaptorTestConstants {
+
+ private final TestTransitData data = new TestTransitData();
+ private final RaptorRequestBuilder requestBuilder = new RaptorRequestBuilder<>();
+ private final RaptorService raptorService = new RaptorService<>(
+ RaptorConfig.defaultConfigForTest()
+ );
+
+ @BeforeEach
+ void setup() {
+ data
+ .withRoute(route("R1", STOP_B, STOP_C).withTimetable(schedule("0:10, 0:14")))
+ .withRoute(route("R2", STOP_C, STOP_D).withTimetable(schedule("0:18, 0:20")));
+
+ data.mcCostParamsBuilder().transferCost(0).boardCost(0);
+ data.withStopBoardAlightCost(STOP_D, 60000);
+
+ requestBuilder
+ .searchParams()
+ .addAccessPaths(TestAccessEgress.free(STOP_B))
+ .addEgressPaths(
+ TestAccessEgress.walk(STOP_C, D5m), // This will be the fastest
+ TestAccessEgress.walk(STOP_D, D20s) // This will be the cheapest
+ )
+ .earliestDepartureTime(T00_00)
+ .latestArrivalTime(T00_30);
+
+ ModuleTestDebugLogging.setupDebugLogging(data, requestBuilder);
+ }
+
+ static List testCases() {
+ return RaptorModuleTestCase
+ .of()
+ .add(
+ multiCriteria(),
+ // We should get both the fastest and the c1-cheapest results
+ // The stopTransferCost should not be applied to the egress leg from STOP_D
+ "B ~ BUS R1 0:10 0:14 ~ C ~ Walk 5m [0:10 0:19 9m Tₓ0 C₁840]",
+ "B ~ BUS R1 0:10 0:14 ~ C ~ BUS R2 0:18 0:20 ~ D ~ Walk 20s [0:10 0:20:20 10m20s Tₓ1 C₁640]"
+ )
+ .build();
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testRaptor(RaptorModuleTestCase testCase) {
+ assertEquals(testCase.expected(), testCase.run(raptorService, data, requestBuilder));
+ }
+}
diff --git a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/DefaultCostCalculatorTest.java b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/DefaultCostCalculatorTest.java
index 7b7ba23499c..3570d92bdbe 100644
--- a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/DefaultCostCalculatorTest.java
+++ b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/DefaultCostCalculatorTest.java
@@ -76,22 +76,28 @@ public void calculateMinCost() {
// - Transit factor: 80 (min of 80 and 100)
// Board cost is 500:
- assertEquals(500, subject.calculateMinCost(0, 0));
+ assertEquals(500, subject.calculateRemainingMinCost(0, 0, 0));
// The transfer 1s * 80 = 80 + board cost 500
- assertEquals(580, subject.calculateMinCost(1, 0));
+ assertEquals(580, subject.calculateRemainingMinCost(1, 0, 0));
// Board 2 times and transfer 1: 2 * 500 + 200
- assertEquals(1200, subject.calculateMinCost(0, 1));
+ assertEquals(1200, subject.calculateRemainingMinCost(0, 1, 0));
// Transit 200s * 80 + Board 4 * 500 + Transfer 3 * 200
- assertEquals(18_600, subject.calculateMinCost(200, 3));
+ assertEquals(18_600, subject.calculateRemainingMinCost(200, 3, 0));
+
+ // Cost of egress should subtract the stop transfer cost 25
+ assertEquals(-25, subject.calculateRemainingMinCost(0, -1, 1));
}
@Test
public void testConvertBetweenRaptorAndMainOtpDomainModel() {
- assertEquals(RaptorCostConverter.toRaptorCost(BOARD_COST_SEC), subject.calculateMinCost(0, 0));
+ assertEquals(
+ RaptorCostConverter.toRaptorCost(BOARD_COST_SEC),
+ subject.calculateRemainingMinCost(0, 0, 0)
+ );
assertEquals(
RaptorCostConverter.toRaptorCost(0.8 * 20 + BOARD_COST_SEC),
- subject.calculateMinCost(20, 0)
+ subject.calculateRemainingMinCost(20, 0, 0)
);
}