Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to specify delay or skipped stops on ADDED or REPLACEMENT trips in GTFS-RT #6028

Draft
wants to merge 34 commits into
base: dev-2.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fbcbe5d
implement delay and skipped stops on added / replacement trips
miklcct Aug 14, 2024
d7f506f
strengthen test case
miklcct Aug 31, 2024
7affd6c
Skipped stops should always have PickDrop = CANCELLED
miklcct Aug 31, 2024
4240da2
use "var" instead of specifying types
miklcct Sep 3, 2024
30e70fb
add overloads of TripUpdateBuilder.addSkippedStop to specify skipped …
miklcct Sep 3, 2024
979a656
move checks against StopTimeUpdate to AddedStopTime
miklcct Sep 3, 2024
dddd6fe
store the original StopTimeUpdate in AddedStopTime
miklcct Sep 4, 2024
ef9145e
Merge tag 'v2.6.0' into delay_on_added_trips
miklcct Sep 18, 2024
035fcca
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Sep 27, 2024
f34b149
Merge remote-tracking branch 'upstream/dev-2.x' into delay_on_added_t…
miklcct Sep 27, 2024
f097243
fix test cases
miklcct Sep 30, 2024
2168858
consistency in getter naming
miklcct Sep 30, 2024
86bc0e5
assume that the delay is 0 when it is missing
miklcct Sep 30, 2024
8c72fba
formatting
miklcct Oct 1, 2024
449f18d
Merge remote-tracking branch 'upstream/dev-2.x' into delay_on_added_t…
miklcct Oct 15, 2024
3dbb6ef
Merge remote-tracking branch 'upstream/dev-2.x' into delay_on_added_t…
miklcct Oct 21, 2024
6e21264
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Nov 5, 2024
f3792b1
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Nov 26, 2024
25c9d65
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Dec 4, 2024
b5c16aa
update proto file
miklcct Dec 4, 2024
fe83e7d
process pickup / drop off in StopTimeProperties
miklcct Dec 4, 2024
cafa318
process stop headsign
miklcct Dec 4, 2024
5236c7e
process trip headsign for added trips
miklcct Dec 4, 2024
18adc11
process scheduled time in added trips
miklcct Dec 4, 2024
513eca4
handle replacement trip headsign
miklcct Dec 4, 2024
f0fc986
move modified test into its own module
miklcct Dec 4, 2024
876539d
integrate headsign test into the modified trip test
miklcct Dec 4, 2024
ee933f0
renamed ReplacementTest to ModifiedTest
miklcct Dec 4, 2024
16c4dc6
use seconds from midnight instead of minutes for test
miklcct Dec 4, 2024
331b0c6
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Dec 17, 2024
f4860c5
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Jan 9, 2025
591f909
Merge branch 'dev-2.x' into delay_on_added_trips
miklcct Jan 9, 2025
c43c11c
add NEW enum specified for google/transit#504
miklcct Jan 21, 2025
8fcd859
reformat code
miklcct Jan 21, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.google.transit.realtime.GtfsRealtime;
import de.mfdz.MfdzRealtimeExtensions;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import javax.annotation.Nullable;
import org.opentripplanner.gtfs.mapping.PickDropMapper;
import org.opentripplanner.model.PickDrop;
Expand All @@ -13,49 +15,125 @@
*/
final class AddedStopTime {

@Nullable
private final PickDrop pickup;
private final GtfsRealtime.TripUpdate.StopTimeUpdate stopTimeUpdate;

@Nullable
private final PickDrop dropOff;

public static final PickDrop DEFAULT_PICK_DROP = PickDrop.SCHEDULED;

AddedStopTime(@Nullable PickDrop pickup, @Nullable PickDrop dropOff) {
this.pickup = pickup;
this.dropOff = dropOff;
AddedStopTime(GtfsRealtime.TripUpdate.StopTimeUpdate stopTimeUpdate) {
this.stopTimeUpdate = stopTimeUpdate;
}

PickDrop pickup() {
return Objects.requireNonNullElse(pickup, DEFAULT_PICK_DROP);
return getPickDrop(
getStopTimeProperties()
.map(properties -> properties.hasPickupType() ? properties.getPickupType() : null)
.orElse(null),
getStopTimePropertiesExtension()
.map(properties -> properties.hasPickupType() ? properties.getPickupType() : null)
.orElse(null)
);
}

PickDrop dropOff() {
return Objects.requireNonNullElse(dropOff, DEFAULT_PICK_DROP);
}

static AddedStopTime ofStopTime(GtfsRealtime.TripUpdate.StopTimeUpdate props) {
if (props.getStopTimeProperties().hasExtension(MfdzRealtimeExtensions.stopTimeProperties)) {
var ext = props
.getStopTimeProperties()
.getExtension(MfdzRealtimeExtensions.stopTimeProperties);
var pickup = ext.getPickupType();
var dropOff = ext.getDropoffType();
var dropOffType = PickDropMapper.map(dropOff.getNumber());
var pickupType = PickDropMapper.map(pickup.getNumber());
return new AddedStopTime(pickupType, dropOffType);
} else {
var pickDrop = toPickDrop(props.getScheduleRelationship());
return new AddedStopTime(pickDrop, pickDrop);
}
return getPickDrop(
getStopTimeProperties()
.map(properties -> properties.hasDropOffType() ? properties.getDropOffType() : null)
.orElse(null),
getStopTimePropertiesExtension()
.map(properties -> properties.hasDropoffType() ? properties.getDropoffType() : null)
.orElse(null)
);
}

private static PickDrop toPickDrop(
GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship scheduleRelationship
private PickDrop getPickDrop(
@Nullable GtfsRealtime.TripUpdate.StopTimeUpdate.StopTimeProperties.DropOffPickupType dropOffPickupType,
@Nullable MfdzRealtimeExtensions.StopTimePropertiesExtension.DropOffPickupType extensionDropOffPickup
) {
return switch (scheduleRelationship) {
case SCHEDULED, NO_DATA, UNSCHEDULED -> PickDrop.SCHEDULED;
case SKIPPED -> PickDrop.CANCELLED;
};
if (isSkipped()) {
return PickDrop.CANCELLED;
}

if (dropOffPickupType != null) {
return PickDropMapper.map(dropOffPickupType.getNumber());
}

if (extensionDropOffPickup != null) {
return PickDropMapper.map(extensionDropOffPickup.getNumber());
}

return PickDrop.SCHEDULED;
}

private Optional<GtfsRealtime.TripUpdate.StopTimeUpdate.StopTimeProperties> getStopTimeProperties() {
return stopTimeUpdate.hasStopTimeProperties()
? Optional.of(stopTimeUpdate.getStopTimeProperties())
: Optional.empty();
}

private Optional<MfdzRealtimeExtensions.StopTimePropertiesExtension> getStopTimePropertiesExtension() {
return getStopTimeProperties()
.map(stopTimeProperties ->
stopTimeProperties.hasExtension(MfdzRealtimeExtensions.stopTimeProperties)
? stopTimeProperties.getExtension(MfdzRealtimeExtensions.stopTimeProperties)
: null
);
}

OptionalLong arrivalTime() {
return stopTimeUpdate.hasArrival()
? getTime(stopTimeUpdate.getArrival())
: OptionalLong.empty();
}

OptionalLong departureTime() {
return stopTimeUpdate.hasDeparture()
? getTime(stopTimeUpdate.getDeparture())
: OptionalLong.empty();
}

private OptionalLong getTime(GtfsRealtime.TripUpdate.StopTimeEvent stopTimeEvent) {
return stopTimeEvent.hasTime()
? OptionalLong.of(stopTimeEvent.getTime())
: OptionalLong.empty();
}

int arrivalDelay() {
return stopTimeUpdate.hasArrival() ? getDelay(stopTimeUpdate.getArrival()) : 0;
}

int departureDelay() {
return stopTimeUpdate.hasDeparture() ? getDelay(stopTimeUpdate.getDeparture()) : 0;
}

private int getDelay(GtfsRealtime.TripUpdate.StopTimeEvent stopTimeEvent) {
return stopTimeEvent.hasDelay()
? stopTimeEvent.getDelay()
: stopTimeEvent.hasScheduledTime()
? (int) (stopTimeEvent.getTime() - stopTimeEvent.getScheduledTime())
: 0;
}

boolean isSkipped() {
return (
stopTimeUpdate.getScheduleRelationship() ==
GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship.SKIPPED
);
}

OptionalInt stopSequence() {
return stopTimeUpdate.hasStopSequence()
? OptionalInt.of(stopTimeUpdate.getStopSequence())
: OptionalInt.empty();
}

Optional<String> stopId() {
return stopTimeUpdate.hasStopId() ? Optional.of(stopTimeUpdate.getStopId()) : Optional.empty();
}

Optional<String> stopHeadsign() {
return (
stopTimeUpdate.hasStopTimeProperties() &&
stopTimeUpdate.getStopTimeProperties().hasStopHeadsign()
)
? Optional.of(stopTimeUpdate.getStopTimeProperties().getStopHeadsign())
: Optional.empty();
}
}
Loading
Loading