Skip to content

Commit 9ba66b8

Browse files
committed
Refactor RoutingAccessEgress to have a list of last states instead of singular last state
1 parent 004f0e0 commit 9ba66b8

7 files changed

Lines changed: 50 additions & 30 deletions

File tree

application/src/ext/java/org/opentripplanner/ext/ridehailing/RideHailingAccessAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public final class RideHailingAccessAdapter extends DefaultAccessEgress {
1414
private final Duration arrival;
1515

1616
public RideHailingAccessAdapter(RoutingAccessEgress access, Duration arrival) {
17-
super(access.stop(), access.getLastState());
17+
super(access.stop(), access.getLastStates());
1818
this.arrival = arrival;
1919
}
2020

application/src/ext/java/org/opentripplanner/ext/ridehailing/RideHailingAccessShifter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.opentripplanner.routing.algorithm.raptoradapter.transit.RoutingAccessEgress;
1313
import org.opentripplanner.routing.api.request.RouteRequest;
1414
import org.opentripplanner.routing.api.request.StreetMode;
15+
import org.opentripplanner.street.search.state.State;
1516
import org.opentripplanner.transit.model.framework.Result;
1617
import org.slf4j.Logger;
1718
import org.slf4j.LoggerFactory;
@@ -45,7 +46,7 @@ public static List<RoutingAccessEgress> shiftAccesses(
4546
.map(ae -> {
4647
// only time-shift access legs on a car
4748
// (there could be walk-only accesses if you're close to the stop)
48-
if (isAccess && ae.getLastState().containsModeCar()) {
49+
if (isAccess && ae.getLastStates().stream().allMatch(State::containsModeCar)) {
4950
var duration = fetchArrivalDelay(services, request, now);
5051
if (duration.isSuccess()) {
5152
return new RideHailingAccessAdapter(ae, duration.successValue());

application/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,12 +489,9 @@ private boolean includeTransferInItinerary(Leg transitLegBeforeTransfer) {
489489
}
490490

491491
private Itinerary mapAccessEgressPathLeg(RaptorAccessEgress accessEgress) {
492-
return accessEgress
493-
.findOriginal(RoutingAccessEgress.class)
494-
.map(RoutingAccessEgress::getLastState)
495-
.map(GraphPath::new)
496-
.map(path -> graphPathToItineraryMapper.generateItinerary(path, request))
497-
.orElseThrow();
492+
var routingAccessEgress = accessEgress.findOriginal(RoutingAccessEgress.class).orElseThrow();
493+
var paths = routingAccessEgress.getLastStates().stream().map(GraphPath::new).toList();
494+
return graphPathToItineraryMapper.generateItinerary(paths, request);
498495
}
499496

500497
private TimeAndCost mapAccessEgressPenalty(RaptorAccessEgress accessEgress) {

application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/DefaultAccessEgress.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package org.opentripplanner.routing.algorithm.raptoradapter.transit;
22

3+
import java.util.List;
34
import java.util.Objects;
45
import org.opentripplanner.framework.model.TimeAndCost;
56
import org.opentripplanner.raptor.api.model.RaptorConstants;
67
import org.opentripplanner.raptor.api.model.RaptorCostConverter;
78
import org.opentripplanner.street.search.state.State;
9+
import org.opentripplanner.utils.collection.ListUtils;
810

911
/**
1012
* Default implementation of the RaptorAccessEgress interface.
@@ -20,9 +22,11 @@ public class DefaultAccessEgress implements RoutingAccessEgress {
2022
private final TimeAndCost penalty;
2123

2224
/**
23-
* This should be the last state both in the case of access and egress.
25+
* For access, this is a list of states starting from origin to the access stop split at via
26+
* locations visited inside the access. For egress, this is a list starting at the egress stop
27+
* ending at the destination split at the via locations visited inside the egress.
2428
*/
25-
private final State lastState;
29+
private final List<State> lastStates;
2630

2731
/**
2832
* This is public to allow unit-tests full control over the field values.
@@ -32,26 +36,32 @@ public DefaultAccessEgress(
3236
int durationInSeconds,
3337
int generalizedCost,
3438
TimeAndCost penalty,
35-
State lastState
39+
List<State> lastState
3640
) {
3741
this.stop = stop;
3842
this.durationInSeconds = durationInSeconds;
3943
this.generalizedCost = generalizedCost;
4044
this.timePenalty = penalty.isZero() ? RaptorConstants.TIME_NOT_SET : penalty.timeInSeconds();
4145
this.penalty = penalty;
42-
this.lastState = Objects.requireNonNull(lastState);
46+
this.lastStates = ListUtils.requireAtLeastNElements(lastState, 1);
4347
}
4448

45-
public DefaultAccessEgress(int stop, State lastState) {
49+
public DefaultAccessEgress(int stop, List<State> lastStates) {
4650
this(
4751
stop,
48-
(int) lastState.getElapsedTimeSeconds(),
49-
RaptorCostConverter.toRaptorCost(lastState.getWeight()),
52+
(int) lastStates.stream().mapToLong(State::getElapsedTimeSeconds).reduce(0, Long::sum),
53+
RaptorCostConverter.toRaptorCost(
54+
lastStates.stream().mapToDouble(State::getWeight).reduce(0, Double::sum)
55+
),
5056
TimeAndCost.ZERO,
51-
lastState
57+
lastStates
5258
);
5359
}
5460

61+
public DefaultAccessEgress(int stop, State lastState) {
62+
this(stop, List.of(Objects.requireNonNull(lastState)));
63+
}
64+
5565
protected DefaultAccessEgress(RoutingAccessEgress other, TimeAndCost penalty) {
5666
// In the API we have a cost associated with the time-penalty. In Raptor, there is no
5767
// association between the time-penalty and the cost. So, we add the time-penalty cost to
@@ -61,7 +71,7 @@ protected DefaultAccessEgress(RoutingAccessEgress other, TimeAndCost penalty) {
6171
other.durationInSeconds(),
6272
other.c1() + penalty.cost().toCentiSeconds(),
6373
penalty,
64-
other.getLastState()
74+
other.getLastStates()
6575
);
6676
if (other.penalty() != TimeAndCost.ZERO) {
6777
throw new IllegalStateException("Can not add penalty twice...");
@@ -94,13 +104,13 @@ public boolean hasOpeningHours() {
94104
}
95105

96106
@Override
97-
public State getLastState() {
98-
return lastState;
107+
public List<State> getLastStates() {
108+
return lastStates;
99109
}
100110

101111
@Override
102112
public boolean isWalkOnly() {
103-
return lastState.containsOnlyWalkMode();
113+
return lastStates.stream().allMatch(State::containsOnlyWalkMode);
104114
}
105115

106116
@Override

application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RoutingAccessEgress.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.opentripplanner.routing.algorithm.raptoradapter.transit;
22

3+
import java.util.List;
34
import org.opentripplanner.framework.model.TimeAndCost;
45
import org.opentripplanner.raptor.api.model.RaptorAccessEgress;
56
import org.opentripplanner.street.search.state.State;
@@ -18,9 +19,11 @@ public interface RoutingAccessEgress extends RaptorAccessEgress {
1819
RoutingAccessEgress withPenalty(TimeAndCost penalty);
1920

2021
/**
21-
* Return the last state both in the case of access and egress.
22+
* For access, this is a list of states starting from origin to the access stop split at via
23+
* locations visited inside the access. For egress, this is a list starting at the egress stop
24+
* ending at the destination split at the via locations visited inside the egress.
2225
*/
23-
State getLastState();
26+
List<State> getLastStates();
2427

2528
/**
2629
* Return true if all edges are traversed on foot.

application/src/test/java/org/opentripplanner/raptorlegacy/_data/transit/TestAccessEgress.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.opentripplanner.raptor.api.model.RaptorCostConverter.toRaptorCost;
44

5+
import java.util.List;
56
import org.opentripplanner._support.geometry.Coordinates;
67
import org.opentripplanner.core.model.i18n.I18NString;
78
import org.opentripplanner.framework.model.TimeAndCost;
@@ -109,16 +110,18 @@ Builder stopReachedOnBoard() {
109110

110111
RoutingAccessEgress build() {
111112
var stopId = "Stop:" + stop;
112-
var lastState = new State(
113-
new StreetLocation(stopId, Coordinates.BOSTON, I18NString.of(stopId)),
114-
StreetSearchRequest.of().build()
113+
var lastStates = List.of(
114+
new State(
115+
new StreetLocation(stopId, Coordinates.BOSTON, I18NString.of(stopId)),
116+
StreetSearchRequest.of().build()
117+
)
115118
);
116119
return new DefaultAccessEgress(
117120
stop,
118121
durationInSeconds,
119122
generalizedCost,
120123
TimeAndCost.ZERO,
121-
lastState
124+
lastStates
122125
) {
123126
// TODO - Use the domain type FlexAccessEgressAdapter here instead [if numberOfRides > 0]
124127
@Override

application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/DefaultAccessEgressTest.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.opentripplanner.routing.algorithm.raptoradapter.transit;
22

3+
import static com.google.common.truth.Truth.assertThat;
34
import static org.junit.jupiter.api.Assertions.assertEquals;
45
import static org.junit.jupiter.api.Assertions.assertFalse;
56
import static org.junit.jupiter.api.Assertions.assertThrows;
67
import static org.junit.jupiter.api.Assertions.assertTrue;
78

89
import java.time.Duration;
10+
import java.util.List;
911
import org.junit.jupiter.api.Test;
1012
import org.opentripplanner.framework.model.Cost;
1113
import org.opentripplanner.framework.model.TimeAndCost;
@@ -62,8 +64,8 @@ void hasOpeningHours() {
6264
}
6365

6466
@Test
65-
void getLastState() {
66-
assertEquals(LAST_STATE, subject.getLastState());
67+
void getLastStates() {
68+
assertEquals(List.of(LAST_STATE), subject.getLastStates());
6769
}
6870

6971
/**
@@ -75,7 +77,9 @@ void getLastState() {
7577
void containsDriving() {
7678
var state = TestStateBuilder.ofDriving().streetEdge().streetEdge().streetEdge().build();
7779
var access = new DefaultAccessEgress(0, state);
78-
assertTrue(access.getLastState().containsModeCar());
80+
var lastStates = access.getLastStates();
81+
assertThat(lastStates).hasSize(1);
82+
assertTrue(lastStates.getFirst().containsModeCar());
7983
}
8084

8185
/**
@@ -87,7 +91,9 @@ void containsDriving() {
8791
void walking() {
8892
var state = TestStateBuilder.ofWalking().streetEdge().streetEdge().streetEdge().build();
8993
var access = new DefaultAccessEgress(0, state);
90-
assertFalse(access.getLastState().containsModeCar());
94+
var lastStates = access.getLastStates();
95+
assertThat(lastStates).hasSize(1);
96+
assertFalse(lastStates.getFirst().containsModeCar());
9197
}
9298

9399
@Test

0 commit comments

Comments
 (0)