From ae56c3e94c9262f9ded4a20c15f5e48bcf8a8e40 Mon Sep 17 00:00:00 2001 From: josh-willis-arcadis <168561922+josh-willis-arcadis@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:19:18 -0600 Subject: [PATCH] feat(SpeedTripValidator): check for repeated arrival times --- .../java/com/conveyal/gtfs/error/NewGTFSErrorType.java | 1 + .../com/conveyal/gtfs/validator/SpeedTripValidator.java | 5 +++++ .../conveyal/gtfs/validator/SpeedTripValidatorTest.java | 9 +++++++-- .../VTA-gtfs-multiple-trips/stop_times.txt | 5 ++++- .../VTA-gtfs-multiple-trips/trips.txt | 1 + 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java b/src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java index e73b2e514..c96fd17ed 100644 --- a/src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java +++ b/src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java @@ -44,6 +44,7 @@ public enum NewGTFSErrorType { OVERLAPPING_TRIP(Priority.MEDIUM, "Blocks?"), REFERENTIAL_INTEGRITY(Priority.HIGH, "This line references an ID that does not exist in the target table."), REQUIRED_TABLE_EMPTY(Priority.MEDIUM, "This table is required by the GTFS specification but is empty."), + REPEATED_ARRIVAL_TIME(Priority.MEDIUM, "Arrival time at current stop is equal to the previous stop."), ROUTE_DESCRIPTION_SAME_AS_NAME(Priority.LOW, "The description of a route is identical to its name, so does not add any information."), ROUTE_LONG_NAME_CONTAINS_SHORT_NAME(Priority.LOW, "The long name of a route should complement the short name, not include it."), ROUTE_SHORT_AND_LONG_NAME_MISSING(Priority.MEDIUM, "A route has neither a long nor a short name."), diff --git a/src/main/java/com/conveyal/gtfs/validator/SpeedTripValidator.java b/src/main/java/com/conveyal/gtfs/validator/SpeedTripValidator.java index 9a15d17f3..a00908eeb 100644 --- a/src/main/java/com/conveyal/gtfs/validator/SpeedTripValidator.java +++ b/src/main/java/com/conveyal/gtfs/validator/SpeedTripValidator.java @@ -48,6 +48,11 @@ public void validateTrip(Trip trip, Route route, List stopTimes, List< double distanceMeters = 0; for (int i = beginIndex + 1; i < stopTimes.size(); i++) { StopTime currStopTime = stopTimes.get(i); + // Additional check: Ensure arrival_time is not the same for consecutive stops + if (currStopTime.arrival_time == prevStopTime.arrival_time) { + registerError(currStopTime, NewGTFSErrorType.REPEATED_ARRIVAL_TIME); + } + if (currStopTime.pickup_type == 1 && currStopTime.drop_off_type == 1 && currStopTime.timepoint == 0) { // stop_time allows neither pickup or drop off and is not a timepoint, so it serves no purpose. registerError(currStopTime, NewGTFSErrorType.STOP_TIME_UNUSED); diff --git a/src/test/java/com/conveyal/gtfs/validator/SpeedTripValidatorTest.java b/src/test/java/com/conveyal/gtfs/validator/SpeedTripValidatorTest.java index b2844cd06..9818109ad 100644 --- a/src/test/java/com/conveyal/gtfs/validator/SpeedTripValidatorTest.java +++ b/src/test/java/com/conveyal/gtfs/validator/SpeedTripValidatorTest.java @@ -12,8 +12,7 @@ import static com.conveyal.gtfs.GTFS.load; import static com.conveyal.gtfs.GTFS.validate; import static com.conveyal.gtfs.TestUtils.assertThatSqlCountQueryYieldsExpectedCount; -import static com.conveyal.gtfs.error.NewGTFSErrorType.TRAVEL_TOO_FAST; -import static com.conveyal.gtfs.error.NewGTFSErrorType.TRAVEL_TOO_SLOW; +import static com.conveyal.gtfs.error.NewGTFSErrorType.*; /** * Distances recorded against each unit test have been produced using the lat/lon values from @@ -112,6 +111,12 @@ public void tripTravelingTooSlowWithMissingStopTimesHasError() { checkFeedHasError(TRAVEL_TOO_SLOW, "6", 3); } + @Test + public void tripHasDuplicateArrivalTimesHasError() { + checkFeedHasError(REPEATED_ARRIVAL_TIME,"7",2); + } + + /** * Check that the test feed has exactly one error for the given type, entityId, and entitySequence. */ diff --git a/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/stop_times.txt b/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/stop_times.txt index 8a875cb93..e0c85598b 100644 --- a/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/stop_times.txt +++ b/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/stop_times.txt @@ -23,4 +23,7 @@ trip_id,arrival_time,departure_time,stop_id,stop_sequence,stop_headsign,pickup_t 5,23:59:00,23:59:00,1562,3,,0,0,9.39290047,0 6,00:00:00,00:00:00,4957,1,,0,0,,1 6,,,1558,2,,0,0,8.34879971,0 -6,23:59:00,23:59:00,1562,3,,0,0,9.39290047,0 \ No newline at end of file +6,23:59:00,23:59:00,1562,3,,0,0,9.39290047,0 +6,23:59:00,23:59:00,1562,3,,0,0,9.39290047,0 +7,01:00:00,01:00:00,4957,1,,0,0,,0 +7,01:00:00,01:00:00,1558,2,,0,0,8.34879971,0 diff --git a/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/trips.txt b/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/trips.txt index 0e7afa8b6..fea58ec48 100644 --- a/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/trips.txt +++ b/src/test/resources/real-world-gtfs-feeds/VTA-gtfs-multiple-trips/trips.txt @@ -5,3 +5,4 @@ route_id,service_id,trip_id,trip_headsign,trip_short_name,direction_id,block_id, 23,1,4,PALO ALTO TRANSIT CTR 4,,1,2145,101395,0,0 23,1,5,PALO ALTO TRANSIT CTR 5,,1,2145,101395,0,0 23,1,6,PALO ALTO TRANSIT CTR 6,,1,2145,101395,0,0 +23,1,7,PALO ALTO TRANSIT CTR 7,,1,2145,101395,0,0 \ No newline at end of file