3
3
import static java .lang .Boolean .TRUE ;
4
4
import static org .opentripplanner .updater .spi .UpdateError .UpdateErrorType .INVALID_STOP_SEQUENCE ;
5
5
import static org .opentripplanner .updater .spi .UpdateError .UpdateErrorType .NO_START_DATE ;
6
+ import static org .opentripplanner .updater .spi .UpdateError .UpdateErrorType .STOP_MISMATCH ;
6
7
import static org .opentripplanner .updater .spi .UpdateError .UpdateErrorType .UNKNOWN_STOP ;
7
8
8
9
import java .time .LocalDate ;
18
19
import org .opentripplanner .transit .model .framework .Result ;
19
20
import org .opentripplanner .transit .model .network .StopPattern ;
20
21
import org .opentripplanner .transit .model .network .TripPattern ;
22
+ import org .opentripplanner .transit .model .site .StopLocation ;
21
23
import org .opentripplanner .transit .model .timetable .RealTimeState ;
22
24
import org .opentripplanner .transit .model .timetable .RealTimeTripTimes ;
23
25
import org .opentripplanner .transit .model .timetable .Trip ;
@@ -73,8 +75,11 @@ class ExtraCallTripBuilder {
73
75
}
74
76
75
77
Result <TripUpdate , UpdateError > build () {
76
- if (calls .size () <= transitService .findPattern (trip ).numberOfStops ()) {
77
- // An extra call trip update is expected to have at least one more stop than the scheduled trip
78
+ TripPattern originalPattern = transitService .findPattern (trip );
79
+ long numExtraCalls = calls .stream ().filter (CallWrapper ::isExtraCall ).count ();
80
+ if (calls .size () - numExtraCalls != originalPattern .numberOfStops ()) {
81
+ // A trip update with extra calls is expected to have the same number of non-extra calls as
82
+ // the number of stops in the original scheduled trip
78
83
return UpdateError .result (trip .getId (), INVALID_STOP_SEQUENCE , dataSource );
79
84
}
80
85
@@ -90,13 +95,17 @@ Result<TripUpdate, UpdateError> build() {
90
95
ZonedDateTime departureDate = serviceDate .atStartOfDay (timeZone );
91
96
92
97
// Create the "scheduled version" of the trip
98
+ // We do not reuse the trip times of the original scheduled trip
99
+ // since adding extra stops change the timings of later stops in the trip pattern.
93
100
var aimedStopTimes = new ArrayList <StopTime >();
101
+ int extraCallCounter = 0 ;
94
102
for (int stopSequence = 0 ; stopSequence < calls .size (); stopSequence ++) {
103
+ CallWrapper call = calls .get (stopSequence );
95
104
StopTime stopTime = stopTimesMapper .createAimedStopTime (
96
105
trip ,
97
106
departureDate ,
98
107
stopSequence ,
99
- calls . get ( stopSequence ) ,
108
+ call ,
100
109
stopSequence == 0 ,
101
110
stopSequence == (calls .size () - 1 )
102
111
);
@@ -106,6 +115,23 @@ Result<TripUpdate, UpdateError> build() {
106
115
return UpdateError .result (trip .getId (), UNKNOWN_STOP , dataSource );
107
116
}
108
117
118
+ // Drop this update if it replaces scheduled stops from the original pattern.
119
+ // Only changes within the same parent station are allowed.
120
+ if (call .isExtraCall ()) {
121
+ extraCallCounter ++;
122
+ } else {
123
+ StopLocation stopInOriginalPattern = originalPattern .getStop (
124
+ stopSequence - extraCallCounter
125
+ );
126
+ StopLocation stopInNewPattern = stopTime .getStop ();
127
+ if (
128
+ !stopInNewPattern .equals (stopInOriginalPattern ) &&
129
+ !stopInNewPattern .isPartOfSameStationAs (stopInOriginalPattern )
130
+ ) {
131
+ return UpdateError .result (trip .getId (), STOP_MISMATCH , dataSource );
132
+ }
133
+ }
134
+
109
135
aimedStopTimes .add (stopTime );
110
136
}
111
137
0 commit comments