diff --git a/gtfs-realtime/proto/gtfs-realtime.proto b/gtfs-realtime/proto/gtfs-realtime.proto
index bcd7d8823..d3cfe5294 100644
--- a/gtfs-realtime/proto/gtfs-realtime.proto
+++ b/gtfs-realtime/proto/gtfs-realtime.proto
@@ -106,6 +106,8 @@ message FeedEntity {
// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future.
optional Shape shape = 6;
+ optional Stop stop = 7;
+ optional TripModifications trip_modifications = 8;
// The extensions namespace allows 3rd-party developers to extend the
// GTFS Realtime Specification in order to add and evaluate new features and
@@ -840,6 +842,15 @@ message TripDescriptor {
}
optional ScheduleRelationship schedule_relationship = 4;
+ message ModifiedTripSelector {
+ // The 'id' from the FeedEntity in which the contained TripModifications object affects this trip.
+ optional string modifications_id = 1;
+
+ // The trip_id from the GTFS feed that is modified by the modifications_id
+ optional string affected_trip_id = 2;
+ }
+ optional ModifiedTripSelector modified_trip = 7;
+
// The extensions namespace allows 3rd-party developers to extend the
// GTFS Realtime Specification in order to add and evaluate new features and
// modifications to the spec.
@@ -1033,3 +1044,148 @@ message Shape {
// The following extension IDs are reserved for private use by any organization.
extensions 9000 to 9999;
}
+
+// Describes a stop which is served by trips. All fields are as described in the GTFS-Static specification.
+// NOTE: This message is still experimental, and subject to change. It may be formally adopted in the future.
+message Stop {
+ enum WheelchairBoarding {
+ UNKNOWN = 0;
+ AVAILABLE = 1;
+ NOT_AVAILABLE = 2;
+ }
+
+ optional string stop_id = 1;
+ optional TranslatedString stop_code = 2;
+ optional TranslatedString stop_name = 3;
+ optional TranslatedString tts_stop_name = 4;
+ optional TranslatedString stop_desc = 5;
+ optional float stop_lat = 6;
+ optional float stop_lon = 7;
+ optional string zone_id = 8;
+ optional TranslatedString stop_url = 9;
+ optional string parent_station = 11;
+ optional string stop_timezone = 12;
+ optional WheelchairBoarding wheelchair_boarding = 13 [default = UNKNOWN];
+ optional string level_id = 14;
+ optional TranslatedString platform_code = 15;
+
+ // The extensions namespace allows 3rd-party developers to extend the
+ // GTFS Realtime Specification in order to add and evaluate new features and
+ // modifications to the spec.
+ extensions 1000 to 1999;
+
+ // The following extension IDs are reserved for private use by any organization.
+ extensions 9000 to 9999;
+}
+
+// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future.
+message TripModifications {
+ // A `Modification` message replaces a span of n stop times from each affected trip starting at `start_stop_selector`.
+ message Modification {
+ // The stop selector of the first stop_time of the original trip that is to be affected by this modification.
+ // Used in conjuction with `end_stop_selector`.
+ // `start_stop_selector` is required and is used to define the reference stop used with `travel_time_to_stop`.
+ optional StopSelector start_stop_selector = 1;
+
+ // The stop selector of the last stop of the original trip that is to be affected by this modification.
+ // The selection is inclusive, so if only one stop_time is replaced by that modification, `start_stop_selector` and `end_stop_selector` must be equivalent.
+ // If no stop_time is replaced, `end_stop_selector` must not be provided. It's otherwise required.
+ optional StopSelector end_stop_selector = 2;
+
+ // The number of seconds of delay to add to all departure and arrival times following the end of this modification.
+ // If multiple modifications apply to the same trip, the delays accumulate as the trip advances.
+ optional int32 propagated_modification_delay = 3 [default = 0];
+
+ // A list of replacement stops, replacing those of the original trip.
+ // The length of the new stop times may be less, the same, or greater than the number of replaced stop times.
+ repeated ReplacementStop replacement_stops = 4;
+
+ // An `id` value from the `FeedEntity` message that contains the `Alert` describing this Modification for user-facing communication.
+ optional string service_alert_id = 5;
+
+ // This timestamp identifies the moment when the modification has last been changed.
+ // In POSIX time (i.e., number of seconds since January 1st 1970 00:00:00 UTC).
+ optional uint64 last_modified_time = 6;
+
+ // The extensions namespace allows 3rd-party developers to extend the
+ // GTFS Realtime Specification in order to add and evaluate new features and
+ // modifications to the spec.
+ extensions 1000 to 1999;
+
+ // The following extension IDs are reserved for private use by any organization.
+ extensions 9000 to 9999;
+ }
+
+ message SelectedTrips {
+ // A list of trips affected with this replacement that all have the same new `shape_id`.
+ repeated string trip_ids = 1;
+ // The ID of the new shape for the modified trips in this SelectedTrips.
+ // May refer to a new shape added using a GTFS-RT Shape message, or to an existing shape defined in the GTFS-Static feed’s shapes.txt.
+ optional string shape_id = 2;
+
+ // The extensions namespace allows 3rd-party developers to extend the
+ // GTFS Realtime Specification in order to add and evaluate new features and
+ // modifications to the spec.
+ extensions 1000 to 1999;
+
+ // The following extension IDs are reserved for private use by any organization.
+ extensions 9000 to 9999;
+}
+
+ // A list of selected trips affected by this TripModifications.
+ repeated SelectedTrips selected_trips = 1;
+
+ // A list of start times in the real-time trip descriptor for the trip_id defined in trip_ids.
+ // Useful to target multiple departures of a trip_id in a frequency-based trip.
+ repeated string start_times = 2;
+
+ // Dates on which the modifications occurs, in the YYYYMMDD format. Producers SHOULD only transmit detours occurring within the next week.
+ // The dates provided should not be used as user-facing information, if a user-facing start and end date needs to be provided, they can be provided in the linked service alert with `service_alert_id`
+ repeated string service_dates = 3;
+
+ // A list of modifications to apply to the affected trips.
+ repeated Modification modifications = 4;
+
+ // The extensions namespace allows 3rd-party developers to extend the
+ // GTFS Realtime Specification in order to add and evaluate new features and
+ // modifications to the spec.
+ extensions 1000 to 1999;
+
+ // The following extension IDs are reserved for private use by any organization.
+ extensions 9000 to 9999;
+}
+
+// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future.
+// Select a stop by stop sequence or by stop_id. At least one of the two values must be provided.
+message StopSelector {
+ // Must be the same as in stop_times.txt in the corresponding GTFS feed.
+ optional uint32 stop_sequence = 1;
+ // Must be the same as in stops.txt in the corresponding GTFS feed.
+ optional string stop_id = 2;
+
+ // The extensions namespace allows 3rd-party developers to extend the
+ // GTFS Realtime Specification in order to add and evaluate new features and
+ // modifications to the spec.
+ extensions 1000 to 1999;
+
+ // The following extension IDs are reserved for private use by any organization.
+ extensions 9000 to 9999;
+}
+
+// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future.
+message ReplacementStop {
+ // The difference in seconds between the arrival time at this stop and the arrival time at the reference stop. The reference stop is the stop prior to start_stop_selector. If the modification begins at the first stop of the trip, then the first stop of the trip is the reference stop.
+ // This value MUST be monotonically increasing and may only be a negative number if the first stop of the original trip is the reference stop.
+ optional int32 travel_time_to_stop = 1;
+
+ // The replacement stop ID which will now be visited by the trip. May refer to a new stop added using a GTFS-RT Stop message, or to an existing stop defined in the GTFS-Static feed’s stops.txt. The stop MUST have location_type=0 (routable stops).
+ optional string stop_id = 2;
+
+ // The extensions namespace allows 3rd-party developers to extend the
+ // GTFS Realtime Specification in order to add and evaluate new features and
+ // modifications to the spec.
+ extensions 1000 to 1999;
+
+ // The following extension IDs are reserved for private use by any organization.
+ extensions 9000 to 9999;
+}
\ No newline at end of file
diff --git a/gtfs-realtime/spec/en/README.md b/gtfs-realtime/spec/en/README.md
index cca1c6b5d..9fde0b9d8 100644
--- a/gtfs-realtime/spec/en/README.md
+++ b/gtfs-realtime/spec/en/README.md
@@ -17,6 +17,7 @@ The specification currently supports the following types of information:
* **Trip updates** - delays, cancellations, changed routes
* **Service alerts** - stop moved, unforeseen events affecting a station, route or the entire network
* **Vehicle positions** - information about the vehicles including location and congestion level
+* **Trip modifications** - information about detours affecting a set of trips
A feed may, although not required to, combine entities of different types. Feeds are served via HTTP and updated frequently. The file itself is a regular binary file, so any type of webserver can host and serve the file (other transfer protocols might be used as well). Alternatively, web application servers could also be used which as a response to a valid HTTP GET request will return the feed. There are no constraints on how frequently nor on the exact method of how the feed should be updated or retrieved.
diff --git a/gtfs-realtime/spec/en/feed-entities.md b/gtfs-realtime/spec/en/feed-entities.md
index a5affaf40..f7ca62e99 100644
--- a/gtfs-realtime/spec/en/feed-entities.md
+++ b/gtfs-realtime/spec/en/feed-entities.md
@@ -46,6 +46,18 @@ use data on current speed and odometer readings from the vehicle.
[More about Vehicle Position updates...](vehicle-positions.md)
+## Trip Modifications
+
+#### "These trips are affected by a detour on certain days"
+
+Trip modifications are used to describe detours which affect a set of trips.
+
+A trip modification can cancel certain stops, adjust the timing for trips,
+provide a new shape that trips will take and provide the location of temporary
+stops along the way.
+
+[More about Trip Modifications...](trip-modifications.md)
+
## Historical remark on feed types
Early versions of GTFS Realtime Specification required each feed to only contain
diff --git a/gtfs-realtime/spec/en/images/README.md b/gtfs-realtime/spec/en/images/README.md
new file mode 100644
index 000000000..a0bac25a9
--- /dev/null
+++ b/gtfs-realtime/spec/en/images/README.md
@@ -0,0 +1,5 @@
+# Documentation images
+
+## Excalidraw files
+
+Files with the `.excalidraw` extension can be opened and edited with https://excalidraw.com
\ No newline at end of file
diff --git a/gtfs-realtime/spec/en/images/first_stop_reference.excalidraw b/gtfs-realtime/spec/en/images/first_stop_reference.excalidraw
new file mode 100644
index 000000000..bf5f9bb94
--- /dev/null
+++ b/gtfs-realtime/spec/en/images/first_stop_reference.excalidraw
@@ -0,0 +1,569 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://excalidraw.com",
+ "elements": [
+ {
+ "type": "line",
+ "version": 281,
+ "versionNonce": 975163573,
+ "isDeleted": false,
+ "id": "PIsyTjhoyJd2fNC5CXkqq",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 314,
+ "y": 355,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 225,
+ "height": 1,
+ "seed": 379682357,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 225,
+ 1
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 331,
+ "versionNonce": 934146581,
+ "isDeleted": false,
+ "id": "wBcqG3GXIuNSR4itlTIwB",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 540,
+ "y": 355.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 209,
+ "height": 3,
+ "seed": 1573696597,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 209,
+ -3
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 73,
+ "versionNonce": 658707227,
+ "isDeleted": false,
+ "id": "b78AfwhQhHNiXADqpxyFF",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 350,
+ "y": 344,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 27,
+ "height": 26,
+ "seed": 1068109115,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "3Vx2aNLPM93I3I9avoSP8",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1661197085129,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 42,
+ "versionNonce": 363915125,
+ "isDeleted": false,
+ "id": "tePZw1wBNPfD0yEW2fgOv",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 438,
+ "y": 346,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 17,
+ "height": 20,
+ "seed": 2040228795,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 149,
+ "versionNonce": 130758235,
+ "isDeleted": false,
+ "id": "SgUHBbm03hja0WUhdgmAb",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 552.5,
+ "y": 345,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 17,
+ "height": 20,
+ "seed": 356535675,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 272,
+ "versionNonce": 376320213,
+ "isDeleted": false,
+ "id": "V_FSHLVAcflbRHaFqvqCU",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 681.5,
+ "y": 344,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 17,
+ "height": 20,
+ "seed": 864119637,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 555,
+ "versionNonce": 1936306939,
+ "isDeleted": false,
+ "id": "gWIEdxwjdFZKaBRliRfbg",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 322,
+ "y": 353,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 219,
+ "height": 104,
+ "seed": 1119701493,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 21.5,
+ -95
+ ],
+ [
+ 210,
+ -102
+ ],
+ [
+ 219,
+ 2
+ ]
+ ]
+ },
+ {
+ "type": "ellipse",
+ "version": 52,
+ "versionNonce": 393956917,
+ "isDeleted": false,
+ "id": "snXLcsoZc4irRCTGMaIhO",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 485,
+ "y": 236,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 20,
+ "height": 16,
+ "seed": 744004341,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 28,
+ "versionNonce": 995100411,
+ "isDeleted": false,
+ "id": "fmiS2tK87vEBtrIzJh-tT",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 358,
+ "y": 316.5,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 13,
+ "height": 25,
+ "seed": 362830229,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197073701,
+ "link": null,
+ "locked": false,
+ "fontSize": 20,
+ "fontFamily": 3,
+ "text": "1",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "1",
+ "lineHeight": 1.25,
+ "baseline": 19
+ },
+ {
+ "type": "text",
+ "version": 98,
+ "versionNonce": 666746773,
+ "isDeleted": false,
+ "id": "7uhm2yho1YcXqm-mc84yf",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 441.5,
+ "y": 316.5,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 13,
+ "height": 25,
+ "seed": 929967067,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197061704,
+ "link": null,
+ "locked": false,
+ "fontSize": 20,
+ "fontFamily": 3,
+ "text": "2",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "2",
+ "lineHeight": 1.25,
+ "baseline": 19
+ },
+ {
+ "type": "text",
+ "version": 23,
+ "versionNonce": 1725184565,
+ "isDeleted": false,
+ "id": "fL0A7aGZRxB4PNrk2-kUM",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 558,
+ "y": 316.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 13,
+ "height": 25,
+ "seed": 1232103899,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197073701,
+ "link": null,
+ "locked": false,
+ "fontSize": 20,
+ "fontFamily": 3,
+ "text": "3",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "3",
+ "lineHeight": 1.25,
+ "baseline": 19
+ },
+ {
+ "type": "text",
+ "version": 41,
+ "versionNonce": 1263234971,
+ "isDeleted": false,
+ "id": "dhcRkDkGkXtOOM1BrUdaB",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 682.5,
+ "y": 316.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 13,
+ "height": 25,
+ "seed": 1181462747,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661197073701,
+ "link": null,
+ "locked": false,
+ "fontSize": 20,
+ "fontFamily": 3,
+ "text": "4",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "4",
+ "lineHeight": 1.25,
+ "baseline": 19
+ },
+ {
+ "type": "arrow",
+ "version": 186,
+ "versionNonce": 456092219,
+ "isDeleted": false,
+ "id": "3Vx2aNLPM93I3I9avoSP8",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 407,
+ "y": 463,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 38,
+ "height": 82,
+ "seed": 1148776693,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661197104700,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "kqXNR2iejqk8-x3_gC894",
+ "focus": -0.9537494387067804,
+ "gap": 8
+ },
+ "endBinding": {
+ "elementId": "b78AfwhQhHNiXADqpxyFF",
+ "focus": 0.2123683316343867,
+ "gap": 11.738551627268576
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -19,
+ -27.5
+ ],
+ [
+ -38,
+ -82
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 33,
+ "versionNonce": 1584764661,
+ "isDeleted": false,
+ "id": "kqXNR2iejqk8-x3_gC894",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 415,
+ "y": 456.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 116,
+ "height": 21,
+ "seed": 1635955957,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "3Vx2aNLPM93I3I9avoSP8",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1661197129444,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "reference stop",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "reference stop",
+ "lineHeight": 1.3125,
+ "baseline": 14
+ },
+ {
+ "type": "text",
+ "version": 85,
+ "versionNonce": 1917400689,
+ "isDeleted": false,
+ "id": "P1vxRp6F2yVD7ETQYYDgo",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 413,
+ "y": 382,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 328.125,
+ "height": 39,
+ "seed": 848856149,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709605327274,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "start_stop_selector.stop_sequence=1\nend_stop_selector.stop_sequence=2",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "start_stop_selector.stop_sequence=1\nend_stop_selector.stop_sequence=2",
+ "lineHeight": 1.21875,
+ "baseline": 34
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+}
\ No newline at end of file
diff --git a/gtfs-realtime/spec/en/images/first_stop_reference.png b/gtfs-realtime/spec/en/images/first_stop_reference.png
new file mode 100644
index 000000000..72442ebbc
Binary files /dev/null and b/gtfs-realtime/spec/en/images/first_stop_reference.png differ
diff --git a/gtfs-realtime/spec/en/images/propagated_delay.excalidraw b/gtfs-realtime/spec/en/images/propagated_delay.excalidraw
new file mode 100644
index 000000000..8437fa014
--- /dev/null
+++ b/gtfs-realtime/spec/en/images/propagated_delay.excalidraw
@@ -0,0 +1,893 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://excalidraw.com",
+ "elements": [
+ {
+ "type": "line",
+ "version": 99,
+ "versionNonce": 1910799995,
+ "isDeleted": false,
+ "id": "ZwAm4QNUap84px6a12sSJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 343,
+ "y": 401.2790131507162,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 135,
+ "height": 3,
+ "seed": 1125176699,
+ "groupIds": [],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198008737,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 135,
+ -3
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 275,
+ "versionNonce": 1803877045,
+ "isDeleted": false,
+ "id": "rL7bCVgEDP_mEfd5KWqTl",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 479.5,
+ "y": 399.3457195081469,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 136,
+ "height": 0,
+ "seed": 1485864885,
+ "groupIds": [],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198008737,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 136,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 586,
+ "versionNonce": 929363739,
+ "isDeleted": false,
+ "id": "y6jzBhJV4oVTQO17ING4C",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 614.5,
+ "y": 399.98603969505984,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 141,
+ "height": 2,
+ "seed": 1533120725,
+ "groupIds": [],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198008737,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 141,
+ -2
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 776,
+ "versionNonce": 383638549,
+ "isDeleted": false,
+ "id": "2M4t-iIGooet07NTa0cOi",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 869.5,
+ "y": 395.18985824308356,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 114,
+ "height": 4,
+ "seed": 1814581493,
+ "groupIds": [],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -114,
+ 4
+ ]
+ ]
+ },
+ {
+ "type": "ellipse",
+ "version": 54,
+ "versionNonce": 458461557,
+ "isDeleted": false,
+ "id": "FZbkuw_X0ePDn-LM__LG9",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 356,
+ "y": 391,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 19,
+ "height": 19,
+ "seed": 167304539,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 117,
+ "versionNonce": 163516827,
+ "isDeleted": false,
+ "id": "Grg0QG11HcsGaHU1OWxir",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 421,
+ "y": 384,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 28,
+ "height": 26,
+ "seed": 1328061499,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 261,
+ "versionNonce": 1118349717,
+ "isDeleted": false,
+ "id": "hheVrp_ubt-j-Dh40pUmM",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 670,
+ "y": 383,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 28,
+ "height": 26,
+ "seed": 283489883,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 73,
+ "versionNonce": 415245883,
+ "isDeleted": false,
+ "id": "8XdkIRrad-idnCIfTTrXn",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 523,
+ "y": 387,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 23,
+ "height": 23,
+ "seed": 1851589851,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 260,
+ "versionNonce": 1869131509,
+ "isDeleted": false,
+ "id": "lGg3_KjAslPzScrWxKcdS",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 795.5,
+ "y": 384.5,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 23,
+ "height": 23,
+ "seed": 2073666523,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 574,
+ "versionNonce": 1507899157,
+ "isDeleted": false,
+ "id": "rorGSUcFMBYP7JXRqmk2Z",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 865.5,
+ "y": 396.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 135,
+ "height": 3,
+ "seed": 1740081115,
+ "groupIds": [],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 135,
+ -3
+ ]
+ ]
+ },
+ {
+ "type": "ellipse",
+ "version": 292,
+ "versionNonce": 989442235,
+ "isDeleted": false,
+ "id": "1bGHQN_Nf78PEPZ7-kjLg",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 890.5,
+ "y": 384.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 19,
+ "height": 19,
+ "seed": 927577941,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 341,
+ "versionNonce": 1329794165,
+ "isDeleted": false,
+ "id": "JreL5BAu5fC-ip7hqbxgV",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 970.5,
+ "y": 384.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 19,
+ "height": 19,
+ "seed": 80729211,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 18,
+ "versionNonce": 1982529019,
+ "isDeleted": false,
+ "id": "MN-wNd3xT9sptRwAmdvde",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 341,
+ "y": 419.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 20,
+ "seed": 1538657301,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "12:15",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "12:15"
+ },
+ {
+ "type": "text",
+ "version": 67,
+ "versionNonce": 344470325,
+ "isDeleted": false,
+ "id": "Xii_iKJnhFH3McyvKk6K2",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 413,
+ "y": 419.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 20,
+ "seed": 289717275,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "12:16",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "12:16"
+ },
+ {
+ "type": "text",
+ "version": 156,
+ "versionNonce": 2108655259,
+ "isDeleted": false,
+ "id": "6IABWi24b3WpiA_KQUpj2",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 494,
+ "y": 419.5,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 67,
+ "height": 20,
+ "seed": 1822706235,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶1̶2̶:̶1̶8̶",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶1̶2̶:̶1̶8̶"
+ },
+ {
+ "type": "text",
+ "version": 236,
+ "versionNonce": 468059285,
+ "isDeleted": false,
+ "id": "oeOqJwmLrOQ7TzioVxVjF",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 632,
+ "y": 419.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 67,
+ "height": 20,
+ "seed": 286160379,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶1̶2̶:̶1̶9̶",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶1̶2̶:̶1̶9̶"
+ },
+ {
+ "type": "text",
+ "version": 35,
+ "versionNonce": 14285627,
+ "isDeleted": false,
+ "id": "iJRa1CbvKH5HNFxrSKji1",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 763,
+ "y": 418.5,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 67,
+ "height": 20,
+ "seed": 2014976827,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶1̶2̶:̶2̶0̶",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶1̶2̶:̶2̶0̶"
+ },
+ {
+ "type": "text",
+ "version": 24,
+ "versionNonce": 239249909,
+ "isDeleted": false,
+ "id": "EvmDWbg_sq2UKPPZ-d68f",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 878,
+ "y": 419.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 20,
+ "seed": 1020107413,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "̶1̶2̶:̶2̶1̶",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "̶1̶2̶:̶2̶1̶"
+ },
+ {
+ "type": "text",
+ "version": 47,
+ "versionNonce": 1812782043,
+ "isDeleted": false,
+ "id": "syVVIfagpYXjv2krS0vz5",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 959,
+ "y": 419.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 20,
+ "seed": 1091471227,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "̶1̶2̶:̶2̶3̶",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "̶1̶2̶:̶2̶3̶"
+ },
+ {
+ "type": "arrow",
+ "version": 186,
+ "versionNonce": 1285792597,
+ "isDeleted": false,
+ "id": "dJKmjiJcVCgpjVBbmP587",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 615,
+ "y": 222,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 414,
+ "height": 2,
+ "seed": 239036219,
+ "groupIds": [
+ "PbV31gB7HTg_0bCOPdW19"
+ ],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198008738,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 414,
+ -2
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 105,
+ "versionNonce": 2084927785,
+ "isDeleted": false,
+ "id": "AbbdmCQZISBfKmLFiyj47",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 694,
+ "y": 226,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 321,
+ "height": 20,
+ "seed": 145973685,
+ "groupIds": [
+ "PbV31gB7HTg_0bCOPdW19"
+ ],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1666883271064,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "propagated_modification_delay=120s",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "propagated_modification_delay=120s"
+ },
+ {
+ "type": "arrow",
+ "version": 59,
+ "versionNonce": 1352891355,
+ "isDeleted": false,
+ "id": "aBi-RLWtMPuiA-ug7fPY8",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 860,
+ "y": 277,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 168,
+ "height": 0,
+ "seed": 2141213115,
+ "groupIds": [],
+ "strokeSharpness": "round",
+ "boundElements": [],
+ "updated": 1661198032343,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 168,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 52,
+ "versionNonce": 1419745703,
+ "isDeleted": false,
+ "id": "lGiXMH3khZS5qblDkzoYY",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 875,
+ "y": 283,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 312,
+ "height": 20,
+ "seed": 1411205243,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1666883279348,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "propagated_modification_delay=60s",
+ "baseline": 16,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "propagated_modification_delay=60s"
+ },
+ {
+ "type": "text",
+ "version": 28,
+ "versionNonce": 163888309,
+ "isDeleted": false,
+ "id": "_6mx4F1hn4C8pRB9eGzjV",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 655,
+ "y": 440,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 36,
+ "height": 21,
+ "seed": 70995899,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198068984,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "12:21",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "12:21"
+ },
+ {
+ "type": "text",
+ "version": 106,
+ "versionNonce": 1293957749,
+ "isDeleted": false,
+ "id": "E-Cy98GpPyLJTSorsuZQ4",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 879,
+ "y": 441.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 42,
+ "height": 21,
+ "seed": 1870288155,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198086583,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "12:24",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "12:24"
+ },
+ {
+ "type": "text",
+ "version": 153,
+ "versionNonce": 56012539,
+ "isDeleted": false,
+ "id": "aeuNTFgr4RFdzZiRqIY3L",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 961,
+ "y": 445.5,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 42,
+ "height": 21,
+ "seed": 1072599899,
+ "groupIds": [],
+ "strokeSharpness": "sharp",
+ "boundElements": [],
+ "updated": 1661198095018,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "12:26",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "12:26"
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+}
\ No newline at end of file
diff --git a/gtfs-realtime/spec/en/images/propagated_delay.png b/gtfs-realtime/spec/en/images/propagated_delay.png
new file mode 100644
index 000000000..5498d8e09
Binary files /dev/null and b/gtfs-realtime/spec/en/images/propagated_delay.png differ
diff --git a/gtfs-realtime/spec/en/images/trip_modification.excalidraw b/gtfs-realtime/spec/en/images/trip_modification.excalidraw
new file mode 100644
index 000000000..d3497ce1e
--- /dev/null
+++ b/gtfs-realtime/spec/en/images/trip_modification.excalidraw
@@ -0,0 +1,1629 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://excalidraw.com",
+ "elements": [
+ {
+ "type": "line",
+ "version": 174,
+ "versionNonce": 1768956763,
+ "isDeleted": false,
+ "id": "bA1QoeeXNasoSS_Zf8yQv",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 385,
+ "y": 450,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 248,
+ "height": 3,
+ "seed": 997957461,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196102932,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 248,
+ 3
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 512,
+ "versionNonce": 199819259,
+ "isDeleted": false,
+ "id": "WTK6UMSiY0sqDgBkh0W02",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 634,
+ "y": 452,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 370,
+ "height": 1,
+ "seed": 338142421,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196102932,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 370,
+ 1
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 394,
+ "versionNonce": 1126388021,
+ "isDeleted": false,
+ "id": "ci4kjvJ6BLdcw2SAyDr4H",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1003.9999999999998,
+ "y": 453,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 340,
+ "height": 3,
+ "seed": 403182261,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196102932,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 340,
+ 3
+ ]
+ ]
+ },
+ {
+ "type": "ellipse",
+ "version": 136,
+ "versionNonce": 1885161627,
+ "isDeleted": false,
+ "id": "MYh-_UtaPG3kO5KfgfnCM",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 415,
+ "y": 444,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 1310766907,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102932,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 371,
+ "versionNonce": 644579669,
+ "isDeleted": false,
+ "id": "yJN6iQ7TUQ7hN1sqLeMzT",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1130,
+ "y": 446,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 1742453947,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102932,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 503,
+ "versionNonce": 1283100341,
+ "isDeleted": false,
+ "id": "uHdmJTZeYpLJxlIdsHiAJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1328,
+ "y": 447,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 2117253083,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 394,
+ "versionNonce": 960668443,
+ "isDeleted": false,
+ "id": "LAqGwIGOPQzvbmWpQjCSL",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 721,
+ "y": 445,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 1376722197,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 482,
+ "versionNonce": 1812000789,
+ "isDeleted": false,
+ "id": "8ZvWOttHdlo4WeZjORR55",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 823,
+ "y": 446,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 411282965,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 550,
+ "versionNonce": 81102779,
+ "isDeleted": false,
+ "id": "4xnnLCjW0p7KkTUUxt1EG",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 946,
+ "y": 446,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 168022037,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 1223,
+ "versionNonce": 49554805,
+ "isDeleted": false,
+ "id": "FN8VfPEK-dlVmRggG_seM",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 636,
+ "y": 455,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 367,
+ "height": 150,
+ "seed": 1310643061,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 33.5,
+ -142
+ ],
+ [
+ 342,
+ -150
+ ],
+ [
+ 367,
+ -3
+ ]
+ ]
+ },
+ {
+ "type": "ellipse",
+ "version": 472,
+ "versionNonce": 882486997,
+ "isDeleted": false,
+ "id": "BRIERQvtP1Ucfvj6SKfPS",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 759.2373682450476,
+ "y": 287.24191744936536,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 1130183029,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 489,
+ "versionNonce": 1044190459,
+ "isDeleted": false,
+ "id": "tyOn5E0-ACNPDrlktKowG",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 884.3514222012016,
+ "y": 283.3286761796125,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 16,
+ "height": 16,
+ "seed": 1903340149,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 128,
+ "versionNonce": 1231469979,
+ "isDeleted": false,
+ "id": "Ef-pdDGNDggjwYO9aB1RT",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 590.9818031827291,
+ "y": 439.53403807033095,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 21.91779047407067,
+ "height": 25.570755553082503,
+ "seed": 440597397,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 198,
+ "versionNonce": 1274784859,
+ "isDeleted": false,
+ "id": "ZNnY_y01TMZtmqtOaZLei",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 301.55272065991596,
+ "y": 417.3582460076779,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 142,
+ "height": 20,
+ "seed": 894927067,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196117034,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "stop_sequence=1",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "stop_sequence=1",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 98,
+ "versionNonce": 1143478997,
+ "isDeleted": false,
+ "id": "coIG6RYInoZE-yHD-D8bS",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 596.0936634987762,
+ "y": 417.3582460076779,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 20,
+ "seed": 542117237,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196117034,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "2",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "2",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 69,
+ "versionNonce": 910005115,
+ "isDeleted": false,
+ "id": "GEtr6cdMupTIO451C_6rP",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 717.0090984086354,
+ "y": 417.3582460076779,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 2032565115,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196121925,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " 3 ",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " 3 ",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 113,
+ "versionNonce": 174585909,
+ "isDeleted": false,
+ "id": "rudWWRkuj1B5qrLjDQTmB",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 826.9701872857773,
+ "y": 417.3582460076779,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 20,
+ "seed": 1106776603,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196117034,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "4",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "4",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 148,
+ "versionNonce": 710578587,
+ "isDeleted": false,
+ "id": "ov0VM50cBgZawiXCryJ_D",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 950.3650698141546,
+ "y": 417.3582460076779,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 20,
+ "seed": 569557205,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196117034,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "5",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "5",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 173,
+ "versionNonce": 730147221,
+ "isDeleted": false,
+ "id": "HN-7W1goGtZ3sfz1T0X2Z",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1133.0133237647442,
+ "y": 417.3582460076779,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 20,
+ "seed": 787777013,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196117034,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "6",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "6",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 218,
+ "versionNonce": 434873915,
+ "isDeleted": false,
+ "id": "P3WoOe96ALI5-Sp6h2hdD",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1330.2734380313805,
+ "y": 417.3582460076779,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 20,
+ "seed": 499735061,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196117034,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "7",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "7",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 176,
+ "versionNonce": 76582235,
+ "isDeleted": false,
+ "id": "zSR_V8d14M1riBp6_LQ-m",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 277.46141272535124,
+ "y": 470.2611706056635,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 170,
+ "height": 20,
+ "seed": 383990645,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "arrival_time=08:00",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "arrival_time=08:00",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 98,
+ "versionNonce": 881707477,
+ "isDeleted": false,
+ "id": "MJYNelpqVUHEn1EknezF8",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 582.8539396895171,
+ "y": 470.2611706056635,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 20,
+ "seed": 1640182133,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nXNaWhUJqr4gV37CBU1Ta",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "08:02",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "08:02",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 337,
+ "versionNonce": 1614792501,
+ "isDeleted": false,
+ "id": "mKXVO2pzvmaXPiWIBYrOp",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 790.1597079234364,
+ "y": 470.2611706056635,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 76,
+ "height": 20,
+ "seed": 498972603,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶0̶8̶:̶0̶4",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶0̶8̶:̶0̶4",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 326,
+ "versionNonce": 434844315,
+ "isDeleted": false,
+ "id": "eHPeh98vPaXq3E_r5G-Qe",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 914.8605206098368,
+ "y": 470.2611706056635,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 85,
+ "height": 20,
+ "seed": 648954773,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶0̶8̶:̶0̶5̶ ",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶0̶8̶:̶0̶5̶ ",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 380,
+ "versionNonce": 864753813,
+ "isDeleted": false,
+ "id": "IGvsDSKAHgTK_YCijadmN",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1088.8763618628968,
+ "y": 470.2611706056635,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 85,
+ "height": 20,
+ "seed": 1297631925,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶0̶8̶:̶0̶8̶ ",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶0̶8̶:̶0̶8̶ ",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 448,
+ "versionNonce": 1891641147,
+ "isDeleted": false,
+ "id": "0_pFFDwVbuFRa7O2S8m0J",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1288.2894412085448,
+ "y": 470.2611706056635,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 85,
+ "height": 20,
+ "seed": 522139317,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶0̶8̶:̶0̶9̶ ",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶0̶8̶:̶0̶9̶ ",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 125,
+ "versionNonce": 405093877,
+ "isDeleted": false,
+ "id": "vag9ZDciEh6vTYGpKkK3d",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 683.6529650790119,
+ "y": 470.2611706056635,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 85,
+ "height": 20,
+ "seed": 502732341,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": " ̶0̶8̶:̶0̶3̶ ",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " ̶0̶8̶:̶0̶3̶ ",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 185,
+ "versionNonce": 931013877,
+ "isDeleted": false,
+ "id": "0jN-1yAMM5EZb43Aj3lsh",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 556.6804222290232,
+ "y": 262.17116189628285,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 226,
+ "height": 20,
+ "seed": 796238651,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196141896,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "travel_time_to_stop=180s",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "travel_time_to_stop=180s",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 117,
+ "versionNonce": 866753333,
+ "isDeleted": false,
+ "id": "QPpOG8iNjrOYD-jCCOrif",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 875.1984571221896,
+ "y": 257.82412697529463,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 39,
+ "height": 20,
+ "seed": 93921301,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661199759607,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "300s",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "300s",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "text",
+ "version": 42,
+ "versionNonce": 816174203,
+ "isDeleted": false,
+ "id": "-_GuWonPZeokjZpGqy_0j",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 740.7533714222121,
+ "y": 313.31267300244787,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 49,
+ "height": 21,
+ "seed": 971873877,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "08:05",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "08:05",
+ "lineHeight": 1.3125,
+ "baseline": 14
+ },
+ {
+ "type": "text",
+ "version": 80,
+ "versionNonce": 1957430453,
+ "isDeleted": false,
+ "id": "Q1Fse9Dd5k4P-VPOPr1pe",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 863.2852158524366,
+ "y": 313.05239681170684,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 21,
+ "seed": 1365039355,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196102933,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "08:07",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "08:07",
+ "lineHeight": 1.3125,
+ "baseline": 14
+ },
+ {
+ "type": "text",
+ "version": 104,
+ "versionNonce": 1515781063,
+ "isDeleted": false,
+ "id": "xK-8iyMyaZ7ybdYltWaLQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1048.5156793289552,
+ "y": 296.047847607389,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 312,
+ "height": 20,
+ "seed": 1380104885,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1666883139798,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "propagated_modification_delay=60s",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "propagated_modification_delay=60s",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "arrow",
+ "version": 621,
+ "versionNonce": 1965619175,
+ "isDeleted": false,
+ "id": "ld3F9Lzq-ACRofU51WYzw",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1051.1167321314063,
+ "y": 337.24571459980734,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 314.20235986725675,
+ "height": 2.040352709088836,
+ "seed": 1963598901,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1666883158320,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 314.20235986725675,
+ -2.040352709088836
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 181,
+ "versionNonce": 798130769,
+ "isDeleted": false,
+ "id": "c1xQW0c9ovw6H0AkWOMK-",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 695.7944761851769,
+ "y": 515.1389936178491,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 328.125,
+ "height": 39,
+ "seed": 763923355,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709605236224,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "start_stop_selector.stop_sequence=3\nend_stop_selector.stop_sequence=5",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "start_stop_selector.stop_sequence=3\nend_stop_selector.stop_sequence=5",
+ "lineHeight": 1.21875,
+ "baseline": 34
+ },
+ {
+ "type": "arrow",
+ "version": 189,
+ "versionNonce": 980870357,
+ "isDeleted": false,
+ "id": "nXNaWhUJqr4gV37CBU1Ta",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 632.9909015913646,
+ "y": 614.8763618628967,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 28.609879070669194,
+ "height": 114.46909046572421,
+ "seed": 705954587,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196102934,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "8xDH8e0kgRlrQOQ3KIykd",
+ "focus": -1.164458590347884,
+ "gap": 15.52510158580003
+ },
+ "endBinding": {
+ "elementId": "MJYNelpqVUHEn1EknezF8",
+ "focus": 0.17634179915340775,
+ "gap": 10.146100791509014
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -22.374411108947243,
+ -49.31502856665918
+ ],
+ [
+ -28.609879070669194,
+ -114.46909046572421
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 37,
+ "versionNonce": 174403771,
+ "isDeleted": false,
+ "id": "8xDH8e0kgRlrQOQ3KIykd",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 648.5160031771646,
+ "y": 612.0293269419085,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 116,
+ "height": 21,
+ "seed": 578550037,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nXNaWhUJqr4gV37CBU1Ta",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1661196127459,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "reference stop",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "reference stop",
+ "lineHeight": 1.3125,
+ "baseline": 14
+ },
+ {
+ "type": "text",
+ "version": 23,
+ "versionNonce": 1721934293,
+ "isDeleted": false,
+ "id": "FEPNnYH7-EqRvgh-yUX_0",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1116.0955332906733,
+ "y": 500.0271333018019,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 49,
+ "height": 21,
+ "seed": 1409571157,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196185502,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "08:09",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "08:09",
+ "lineHeight": 1.3125,
+ "baseline": 14
+ },
+ {
+ "type": "text",
+ "version": 60,
+ "versionNonce": 1678812795,
+ "isDeleted": false,
+ "id": "K0ppCd-wNwENOpQ_2sd9E",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1315.3396443801455,
+ "y": 499.3536158413079,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 43,
+ "height": 21,
+ "seed": 1135661563,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196194191,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "08:10",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "08:10",
+ "lineHeight": 1.3125,
+ "baseline": 14
+ },
+ {
+ "type": "line",
+ "version": 92,
+ "versionNonce": 1903820443,
+ "isDeleted": false,
+ "id": "PH_q6aN5HU4Oc1MmImUwT",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 387.32900002782173,
+ "y": 127.20552381482318,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 47.48854602715318,
+ "height": 2.842170943040401e-14,
+ "seed": 1640767259,
+ "groupIds": [
+ "j_D--fVCMYSYxAgHIJo04"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196229209,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 47.48854602715318,
+ 2.842170943040401e-14
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 92,
+ "versionNonce": 1920779163,
+ "isDeleted": false,
+ "id": "cgpoeM9Nwim_OEIlkqtVG",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 454.0412666870692,
+ "y": 114.22607619630551,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 123,
+ "height": 20,
+ "seed": 253764411,
+ "groupIds": [
+ "j_D--fVCMYSYxAgHIJo04"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196289644,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "Original trip",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "Original trip",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "line",
+ "version": 124,
+ "versionNonce": 325346229,
+ "isDeleted": false,
+ "id": "3pbedNg5Q1D837muuap51",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 388.33809843645736,
+ "y": 153.42924444691747,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 47.48854602715318,
+ "height": 2.842170943040401e-14,
+ "seed": 560182651,
+ "groupIds": [
+ "r1CVvIxmY4UkQ1H_hPQNj"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196294255,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 47.48854602715318,
+ 2.842170943040401e-14
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 189,
+ "versionNonce": 239902235,
+ "isDeleted": false,
+ "id": "nw7uEOHTopmaecY_hagcr",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 455.0503650957048,
+ "y": 140.4497968283998,
+ "strokeColor": "#a61e4d",
+ "backgroundColor": "transparent",
+ "width": 132,
+ "height": 20,
+ "seed": 1610134453,
+ "groupIds": [
+ "r1CVvIxmY4UkQ1H_hPQNj"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196294255,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "Replaced stops",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "Replaced stops",
+ "lineHeight": 1.25,
+ "baseline": 15
+ },
+ {
+ "type": "line",
+ "version": 166,
+ "versionNonce": 1021846203,
+ "isDeleted": false,
+ "id": "3gKY2uIv_mJ7Dc94bejbg",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 387.12347621299864,
+ "y": 181.73972380925878,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 47.48854602715318,
+ "height": 2.842170943040401e-14,
+ "seed": 1951418363,
+ "groupIds": [
+ "gW5hVGoMN2TB1-6CY9Irg"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1661196297455,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 47.48854602715318,
+ 2.842170943040401e-14
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 242,
+ "versionNonce": 2133637749,
+ "isDeleted": false,
+ "id": "7N570B5wQTWUZUBgEoUIZ",
+ "fillStyle": "hachure",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 453.8357428722461,
+ "y": 168.76027619074117,
+ "strokeColor": "#087f5b",
+ "backgroundColor": "transparent",
+ "width": 85,
+ "height": 20,
+ "seed": 1840548149,
+ "groupIds": [
+ "gW5hVGoMN2TB1-6CY9Irg"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1661196297455,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "New stops",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "New stops",
+ "lineHeight": 1.25,
+ "baseline": 15
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+}
\ No newline at end of file
diff --git a/gtfs-realtime/spec/en/images/trip_modification.png b/gtfs-realtime/spec/en/images/trip_modification.png
new file mode 100644
index 000000000..3d57181b6
Binary files /dev/null and b/gtfs-realtime/spec/en/images/trip_modification.png differ
diff --git a/gtfs-realtime/spec/en/reference.md b/gtfs-realtime/spec/en/reference.md
index 014bc21c5..ed4c4213e 100644
--- a/gtfs-realtime/spec/en/reference.md
+++ b/gtfs-realtime/spec/en/reference.md
@@ -72,6 +72,13 @@ Fields labeled as **experimental** are subject to change and not yet formally ad
* [TranslatedString](#message-translatedstring)
* [Translation](#message-translation)
* [SeverityLevel](#enum-severitylevel)
+ * [Shape](#message-shape)
+ * [Stop](#message-stop)
+ * [WheelchairBoarding](#enum-wheelchairboarding)
+ * [TripModifications](#message-tripmodifications)
+ * [Modification](#message-modification)
+ * [ReplacementStop](#message-replacementstop)
+
# Elements
@@ -554,9 +561,9 @@ A localized image URL mapped to a language.
## _message_ Shape
-Describes the physical path that a vehicle takes when the shape is not part of the (CSV) GTFS, such as for an ad-hoc detour. Shapes belong to Trips and consist of an encoded polyline for more efficient transmission. Shapes do not need to intercept the location of Stops exactly, but all Stops on a trip should lie within a small distance of the shape for that trip, i.e. close to straight line segments connecting the shape points
+Describes the physical path that a vehicle takes when the shape is not part of the (CSV) GTFS, such as for an ad-hoc detour. Shapes belong to Trips and consist of an encoded polyline for more efficient transmission. Shapes do not need to intercept the location of Stops exactly, but all Stops on a trip should lie within a small distance of the shape for that trip, i.e. close to straight line segments connecting the shape points.
-**Caution:** this message is still **experimental**, and subject to change. It may be formally adopted in the future.
.
+
**Caution:** this message is still **experimental**, and subject to change. It may be formally adopted in the future.
**Fields**
@@ -564,3 +571,122 @@ Describes the physical path that a vehicle takes when the shape is not part of t
|------------------|------------|----------------|-------------------|-------------------|
| **shape_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | Identifier of the shape. Must be different than any `shape_id` defined in the (CSV) GTFS.
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future. |
| **encoded_polyline** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | Encoded polyline representation of the shape. This polyline must contain at least two points. For more information about encoded polylines, see https://developers.google.com/maps/documentation/utilities/polylinealgorithm
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future. |
+
+## _message_ Stop
+
+Represents a new Stop added to the feed dynamically. All fields are as described in the (CSV) GTFS specification. The location type of the new stop is `0` (routable stop).
+
+
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+**Fields**
+
+| _**Field Name**_ | _**Type**_ | _**Required**_ | _**Cardinality**_ | _**Description**_ |
+|------------------|------------|----------------|-------------------|-------------------|
+| **stop_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | Identifier of the stop. Must be different than any `stop_id` defined in the (CSV) GTFS. |
+| **stop_code** | [TranslatedString](#message-translatedstring) | Optional | One | See definition of [stops.stop_code](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **stop_name** | [TranslatedString](#message-translatedstring) | Required | One | See definition of [stops.stop_name](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **tts_stop_name** | [TranslatedString](#message-translatedstring) | Optional | One | See definition of [stops.tts_stop_name](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **stop_desc** | [TranslatedString](#message-translatedstring) | Optional | One | See definition of [stops.stop_desc](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **stop_lat** | [float](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | See definition of [stops.stop_lat](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **stop_lon** | [float](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | See definition of [stops.stop_lon](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **zone_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | See definition of [stops.zone_id](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **stop_url** | [TranslatedString](#message-translatedstring) | Optional | One | See definition of [stops.stop_url](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **parent_station** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | See definition of [stops.parent_station](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **stop_timezone** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | See definition of [stops.stop_timezone](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **wheelchair_boarding** | [WheelchairBoarding](#enum-wheelchairboarding) | Optional | One | See definition of [stops.wheelchair_boarding](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **level_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | See definition of [stops.level_id](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+| **platform_code** | [TranslatedString](#message-translatedstring) | Optional | One | See definition of [stops.platform_code](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stopstxt) in (CSV) GTFS. |
+
+## _enum_ WheelchairBoarding
+
+**Values**
+
+| _**Value**_ | _**Comment**_ |
+|-------------|---------------|
+| **UNKNOWN** | No accessibility information for the stop. |
+| **AVAILABLE** | Some vehicles at this stop can be boarded by a rider in a wheelchair. |
+| **NOT_AVAILABLE** | Wheelchair boarding is not possible at this stop. |
+
+## _message_ TripModifications
+
+A `TripModifications` message identifies a list of similar trips which are all affected by particular modifications, such as a detour.
+
+
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+[More about Trip Modifications...](trip-modifications.md)
+
+**Fields**
+
+| _**Field Name**_ | _**Type**_ | _**Required**_ | _**Cardinality**_ | _**Description**_ |
+|------------------|------------|----------------|-------------------|-------------------|
+| **selected_trips** | [SelectedTrips](#message-selectedtrips) | Required | Many | A list of selected trips affected by this TripModifications. Needs to contain at least one `SelectedTrips`. If the value `start_times` is set, a maximum of one `SelectedTrips` with one trip_id can be listed. |
+| **start_times** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | Many | A list of start times in the real-time trip descriptor for the trip_id defined in trip_ids. Useful to target multiple departures of a trip_id in a frequency-based trip. |
+| **service_dates** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | Many | Dates on which the modification occurs, in the YYYYMMDD format. A trip_id will only be modified if it runs on a given service date; the trip IS NOT required to run on all of the service dates. Producers SHOULD only transmit detours occurring within the next week. The dates provided should not be used as user-facing information, if a user-facing start and end date need to be provided, they can be provided in the linked service alert with `service_alert_id` |
+| **modifications** | [Modification](#message-modification) | Required | Many | A list of modifications to apply to the affected trips. |
+
+## _message_ Modification
+
+A `Modification` message describes changes to each affected trip starting at `start_stop_selector`.
+
+
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+
+_An example showing the effect of a modification on a particular trip. This modification may also be applied to several other trips._
+
+
+_Propagated detour delays affect all stops following the end of a modification. If a trip has multiple modifications, the delays are accumulated._
+
+
+**Fields**
+
+| _**Field Name**_ | _**Type**_ | _**Required**_ | _**Cardinality**_ | _**Description**_ |
+|------------------|------------|----------------|-------------------|-------------------|
+| **start_stop_selector** | [StopSelector](#message-stopselector) | Required | One | The stop selector of the first stop of the original trip that is to be affected by this modification. Used in conjuction with `end_stop_selector`. `start_stop_selector` is required and is used to define the reference stop used with `travel_time_to_stop`. See [`travel_time_to_stop`](#message-replacementstop) for details |
+| **end_stop_selector** | [StopSelector](#message-stopselector) | Conditionally required | One | The stop selector of the last stop of the original trip that is to be affected by this modification. The selection is inclusive, so if only one stop_time is replaced by that modification, `start_stop_selector` and `end_stop_selector` must be equivalent. If no stop_time is replaced, `end_stop_selector` must not be provided. It's otherwise required. |
+| **propagated_modification_delay** | [int32](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | The number of seconds of delay to add to all departure and arrival times subsequent to the last stop inserted by a modification. If a modification affects only the shape (i.e. neither `end_stop_selector` nor `replacement_stops` are provided), then the delay propagation begins at the subsequent stop after `start_stop_selector`. Can be a positive or negative number. If multiple modifications apply to the same trip, the delays accumulate as the trip advances.
If the value is not supplied, consumers MAY interpolate or infer the `propagated_modification_delay` based on other data. |
+| **replacement_stops** | [ReplacementStop](#message-replacementstop) | Optional | Many | A list of replacement stops, replacing those of the original trip. The length of the new stop times may be less, the same, or greater than the number of replaced stop times. |
+| **service_alert_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | An `id` value from the `FeedEntity` message that contains the `Alert` describing this Modification for user-facing communication. |
+| **last_modified_time** | [uint64](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | This timestamp identifies the moment when the modification has last been changed. In POSIX time (i.e., number of seconds since January 1st 1970 00:00:00 UTC). |
+
+## _message_ StopSelector
+
+Selector for a stop. Either by `stop_id` or `stop_sequence`. At least one of the two values must be provided.
+
+
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+**Fields**
+
+| _**Field Name**_ | _**Type**_ | _**Required**_ | _**Cardinality**_ | _**Description**_ |
+|------------------|------------|----------------|-------------------|-------------------|
+| **stop_sequence** | [uint32](https://protobuf.dev/programming-guides/proto2/#scalar) | Conditionally Required | One | Must be the same as in stop_times.txt in the corresponding GTFS feed. Either `stop_sequence` or `stop_id` must be provided within a `StopSelector` - both fields cannot be empty. `stop_sequence` is required for trips that visit the same stop_id more than once (e.g., a loop) to disambiguate which stop the prediction is for. |
+| **stop_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Conditionally Required | One | Must be the same as in stops.txt in the corresponding GTFS feed. Either `stop_sequence` or `stop_id` must be provided within a `StopSelector` - both fields cannot be empty. |
+
+## _message_ SelectedTrips
+
+List of selected trips with an associated shape.
+
+
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+**Fields**
+
+| _**Field Name**_ | _**Type**_ | _**Required**_ | _**Cardinality**_ | _**Description**_ |
+|------------------|------------|----------------|-------------------|-------------------|
+| **trip_ids** | [uint32](https://protobuf.dev/programming-guides/proto2/#scalar) | Many | One | A list of trip_id from the original (CSV) GTFS that are affected by the containing replacement. Need to contain at least one trip_id. |
+| **shape_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | The ID of the new shape for the modified trips in this SelectedTrips. May refer to a new shape added using a GTFS-RT Shape message, or to an existing shape defined in the GTFS-Static feed’s shapes.txt. |
+
+## _message_ ReplacementStop
+
+Each `ReplacementStop` message defines a stop that will now be visited by the trip, and optionally specifies the estimated travel time to the stop.
+
+
**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+
+_If a modification affects the first stop of the trip, that stop also serves as the reference stop of the modification._
+
+
+**Fields**
+
+| _**Field Name**_ | _**Type**_ | _**Required**_ | _**Cardinality**_ | _**Description**_ |
+|------------------|------------|----------------|-------------------|-------------------|
+| **stop_id** | [string](https://protobuf.dev/programming-guides/proto2/#scalar) | Required | One | The replacement stop ID which will now be visited by the trip. May refer to a new stop added using a GTFS-RT `Stop` message, or to an existing stop defined in the (CSV) GTFS feed’s `stops.txt`. The stop MUST have `location_type=0` (routable stops). |
+| **travel_time_to_stop** | [int32](https://protobuf.dev/programming-guides/proto2/#scalar) | Optional | One | The difference in seconds between the arrival time at this stop and the arrival time at the reference stop. The reference stop is the stop prior to `start_stop_selector`. If the modification begins at the first stop of the trip, then the first stop of the trip is the reference stop.
This value MUST be monotonically increasing and may only be a negative number if the first stop of the original trip is the reference stop.
If the value is not supplied, consumers MAY interpolate or infer the `travel_time_to_stop` based on other data. |
diff --git a/gtfs-realtime/spec/en/trip-modifications.md b/gtfs-realtime/spec/en/trip-modifications.md
new file mode 100644
index 000000000..d509e53c3
--- /dev/null
+++ b/gtfs-realtime/spec/en/trip-modifications.md
@@ -0,0 +1,60 @@
+# Trip Modifications
+
+A `TripModifications` message identifies a list of similar `trip_ids` from the (CSV) GTFS which are all affected by particular modifications, such as a detour.
+
+
**Caution:** this entity is still **experimental**, and subject to change. It may be formally adopted in the future.
+
+## SLO: Service-level objective
+
+The frequency of data updates is expected to be approximately hourly (~24 times/day). Ingestion time may depend on the total number of affected trips. Consumers are expected to ingest a single TripModification within 5 minutes, and a feed with hundreds of detours within 20 minutes.
+
+## TripModifications
+
+The `TripModifications` is in effect on all of the listed service\_dates, until it is removed from the feed. On any given service date, a trip MUST NOT be assigned to more than one `TripModifications` object.
+
+There MAY be multiple `TripModifications` for a given stop pattern. It may be desirable to split the trips into multiple modifications e.g. if the `propagated_modification_delay` changes significantly, over the course of the detour.
+
+The trips created through GTFS-TripModifications modify and replace each specified `trip_id`, and don't create a copy or additional run. Modifications are applied on the schedule information, like if a static GTFS (CSV) was modified.
+
+The scheduled stop times of each replacement trip are created from those of the affected trip, by performing the changes listed in modifications. `stop_sequence` for all stop times are replaced by a new value of 1 to n, starting with 1 on the first stop_time and increasing by 1 for each stop in the trip. A `TripUpdate` message must be provided to publish real-time arrival/departure times for the replacement trip.
+
+
+## Linkage to TripUpdates
+
+* A TripUpdate SHOULD be provided using a `ModifiedTripSelector` inside the TripUpdate's `TripDescriptor`.
+ * When the TripUpdate refers to the replacement trip, the consumer should behave as if the static GTFS would have been modified with the TripModifications (e.g. `arrival_time`, `departure_time`, `stop_sequence`, `stop_id` on replacement stops).
+ * When providing a `ModifiedTripSelector`, the other fields of the `TripDescriptor` MUST be left empty, to avoid confusion by consumers that aren't looking for the `ModifiedTripSelector` value.
+ * TripUpdate feeds providing updates with `ModifiedTripSelector` SHOULD also include a TripUpdate targeting clients that don't support TripModifications. In other words, there should be two TripUpdates: one for clients with modified trips (with `TripModifications`) and one for clients with the originial unmodified GTFS (without `TripModifications`).
+ * Providing a TripUpdate with a `ModifiedTripSelector` is the only way to create predictions at replacement stops.
+* If no such TripUpdate is found, TripUpdates for the original `trip_id` will apply to the modified trip.
+ * In this case, the static GTFS information used should be from the static GTFS before any TripModifications applied.
+ * Real time information can be available to the common stops between the previous trip and the new modified trip; however, no ETA would be available at the replacement stops.
+
+## Modification
+
+A `Modification` message describes changes to each affected trip starting at `start_stop_selector`. There can be zero, one, or more than one stop time(s) replaced by a `Modification`. The spans of the modifications MUST not overlap. Spans may not be contiguous; in this case the two modifications MUST be merged into one. These stop times are replaced with a new stop time for each replacement stop described by `replacement_stops`.
+
+The sequence of `replacement_stops` may be of arbitrary length. For example, 3 stops could be replaced by 2, 4, or 0 stops as the situation may require.
+
+
+
+_An example showing the effect of a modification on a particular trip. This modification may also be applied to several other trips._
+
+
+
+_Propagated detour delays affect all stops following the end of a modification. If a trip has multiple modifications, the delays are accumulated._
+
+## ReplacementStop
+
+Each `ReplacementStop` message defines a stop that will now be visited by the trip, and optionally specifies the estimated travel time to the stop. The `ReplacementStop` message is used to construct the scheduled `stop_time` for the stop.
+
+When `travel_time_to_stop` is specified, the `arrival_time` is calculated from a reference stop in the original trip, plus the offset in `travel_time_to_stop`. Otherwise, the `arrival_time` can be be interpolated based on the total duration of the modification in the original trip.
+
+The `departure_time` always equals the `arrival_time`.
+
+The optional fields of [`stop_times.txt`](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#stop_timestxt) in the (CSV) GTFS specification are all set to their default values.
+
+
+
+_If a modification affects the first stop of the trip, that stop also serves as the reference stop of the modification._
+
diff --git a/gtfs/CHANGES.md b/gtfs/CHANGES.md
index db45c8e04..ca5c7f463 100644
--- a/gtfs/CHANGES.md
+++ b/gtfs/CHANGES.md
@@ -53,9 +53,12 @@ Every new feature adds complexity to the creation and reading of feeds. Therefor
### Revision History
+#### March 2024
+* Added GTFS Flex. See [discussion](https://github.com/google/transit/pull/433).
+
#### November 2023
* Best practices: add Dataset Publishing guidelines and Practice Recommendations for all files. See [discussion](https://github.com/google/transit/pull/406).
-* Add networks.txt & route_networks.txt. See [discussion](https://github.com/google/transit/pull/405)
+* Add networks.txt & route_networks.txt. See [discussion](https://github.com/google/transit/pull/405).
#### August 2023
* Add fare_media_type=1. See [discussion](https://github.com/google/transit/pull/385).
diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md
index 7a9b10588..2d1808ad9 100644
--- a/gtfs/spec/en/reference.md
+++ b/gtfs/spec/en/reference.md
@@ -9,7 +9,8 @@ This document defines the format and structure of the files that comprise a GTFS
1. [Document Conventions](#document-conventions)
2. [Dataset Files](#dataset-files)
3. [File Requirements](#file-requirements)
-4. [Field Definitions](#field-definitions)
+4. [Dataset Publishing & General Practices](#dataset-publishing--general-practices)
+5. [Field Definitions](#field-definitions)
- [agency.txt](#agencytxt)
- [stops.txt](#stopstxt)
- [routes.txt](#routestxt)
@@ -33,6 +34,10 @@ This document defines the format and structure of the files that comprise a GTFS
- [transfers.txt](#transferstxt)
- [pathways.txt](#pathwaystxt)
- [levels.txt](#levelstxt)
+ - [location_groups.txt](#location_groupstxt)
+ - [location_group_stops.txt](#location_group_stopstxt)
+ - [locations.geojson](#locationsgeojson)
+ - [booking_rules.txt](#booking_rulestxt)
- [translations.txt](#translationstxt)
- [feed\_info.txt](#feed_infotxt)
- [attributions.txt](#attributionstxt)
@@ -121,13 +126,17 @@ This specification defines the following files:
| [fare_transfer_rules.txt](#fare_transfer_rulestxt) | Optional | Fare rules for transfers between legs of travel.
Along with [fare_leg_rules.txt](#fare_leg_rulestxt), file [fare_transfer_rules.txt](#fare_transfer_rulestxt) provides a more detailed method for modeling fare structures. As such, the use of [fare_transfer_rules.txt](#fare_transfer_rulestxt) is entirely separate from files [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). |
| [areas.txt](#areastxt) | Optional | Area grouping of locations. |
| [stop_areas.txt](#stop_areastxt) | Optional | Rules to assign stops to areas. |
-| [networks.txt](#networkstxt) | **Conditionally Forbidden** | Network grouping of routes.
Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routes.txt).
- Optional otherwise. |
-| [route_networks.txt](#route_networkstxt) | **Conditionally Forbidden** | Rules to assign routes to networks.
Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routes.txt).
- Optional otherwise. |
+| [networks.txt](#networkstxt) | **Conditionally Forbidden** | Network grouping of routes.
Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. |
+| [route_networks.txt](#route_networkstxt) | **Conditionally Forbidden** | Rules to assign routes to networks.
Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. |
| [shapes.txt](#shapestxt) | Optional | Rules for mapping vehicle travel paths, sometimes referred to as route alignments. |
| [frequencies.txt](#frequenciestxt) | Optional | Headway (time between trips) for headway-based service or a compressed representation of fixed-schedule service. |
| [transfers.txt](#transferstxt) | Optional | Rules for making connections at transfer points between routes. |
| [pathways.txt](#pathwaystxt) | Optional | Pathways linking together locations within stations. |
| [levels.txt](#levelstxt) | **Conditionally Required** | Levels within stations.
Conditionally Required:
- **Required** when describing pathways with elevators (`pathway_mode=5`).
- Optional otherwise. |
+| [location_groups.txt](#location_groupstxt) | Optional | A group of stops that together indicate locations where a rider may request pickup or drop off. |
+| [location_group_stops.txt](#location_group_stopstxt) | Optional | Rules to assign stops to location groups. |
+| [locations.geojson](#locationsgeojson) | Optional | Zones for rider pickup or drop-off requests by on-demand services, represented as GeoJSON polygons. |
+| [booking_rules.txt](#booking_rulestxt) | Optional | Booking information for rider-requested services. |
| [translations.txt](#translationstxt) | Optional | Translations of customer-facing dataset values. |
| [feed_info.txt](#feed_infotxt) | Optional | Dataset metadata, including publisher, version, and expiration information. |
| [attributions.txt](#attributionstxt) | Optional | Dataset attributions. |
@@ -162,7 +171,7 @@ The following example demonstrates how a field value would appear in a comma-del
* If possible, the GTFS dataset should cover at least the next 30 days of service.
* Old services (expired calendars) should be removed from the feed.
* If a service modification will go into effect in 7 days or fewer, this service change should be expressed through a GTFS-realtime feed (service advisories or trip updates) rather than static GTFS dataset.
- * The web-server hosting GTFS data should be configured to correctly report the file modification date (see [HTTP/1.1 - Request for Comments 2616, under Section 14.29](https://tools.ietf.org/html/rfc2616#section-14.29)https://tools.ietf.org/html/rfc2616#section-14.29).
+ * The web-server hosting GTFS data should be configured to correctly report the file modification date (see [HTTP/1.1 - Request for Comments 2616, under Section 14.29](https://tools.ietf.org/html/rfc2616#section-14.29)).
## Field Definitions
@@ -191,18 +200,18 @@ Primary key (`stop_id`)
| Field Name | Type | Presence | Description |
| ------ | ------ | ------ | ------ |
-| `stop_id` | Unique ID | **Required** | Identifies a location: stop/platform, station, entrance/exit, generic node or boarding area (see `location_type`).
Multiple routes may use the same `stop_id`. |
+| `stop_id` | Unique ID | **Required** | Identifies a location: stop/platform, station, entrance/exit, generic node or boarding area (see `location_type`).
ID must be unique across all `stops.stop_id`, locations.geojson `id`, and `location_groups.location_group_id` values.
Multiple routes may use the same `stop_id`. |
| `stop_code` | Text | Optional | Short text or a number that identifies the location for riders. These codes are often used in phone-based transit information systems or printed on signage to make it easier for riders to get information for a particular location. The `stop_code` may be the same as `stop_id` if it is public facing. This field should be left empty for locations without a code presented to riders. |
-| `stop_name` | Text | **Conditionally Required** | Name of the location. The `stop_name` should match the agency's rider-facing name for the location as printed on a timetable, published online, or represented on signage. For translations into other languages, use `translations.txt`.
When the location is a boarding area (`location_type=4`), the `stop_name` should contains the name of the boarding area as displayed by the agency. It could be just one letter (like on some European intercity railway stations), or text like “Wheelchair boarding area” (NYC’s Subway) or “Head of short trains” (Paris’ RER).
Conditionally Required:
- **Required** for locations which are stops (`location_type=0`), stations (`location_type=1`) or entrances/exits (`location_type=2`).
- Optional for locations which are generic nodes (`location_type=3`) or boarding areas (`location_type=4`).|
+| `stop_name` | Text | **Conditionally Required** | Name of the location. The `stop_name` should match the agency's rider-facing name for the location as printed on a timetable, published online, or represented on signage. For translations into other languages, use [translations.txt](#translationstxt).
When the location is a boarding area (`location_type=4`), the `stop_name` should contains the name of the boarding area as displayed by the agency. It could be just one letter (like on some European intercity railway stations), or text like “Wheelchair boarding area” (NYC’s Subway) or “Head of short trains” (Paris’ RER).
Conditionally Required:
- **Required** for locations which are stops (`location_type=0`), stations (`location_type=1`) or entrances/exits (`location_type=2`).
- Optional for locations which are generic nodes (`location_type=3`) or boarding areas (`location_type=4`).|
| `tts_stop_name` | Text | Optional | Readable version of the `stop_name`. See "Text-to-speech field" in the [Term Definitions](#term-definitions) for more. |
| `stop_desc` | Text | Optional | Description of the location that provides useful, quality information. Should not be a duplicate of `stop_name`.|
| `stop_lat` | Latitude | **Conditionally Required** | Latitude of the location.
For stops/platforms (`location_type=0`) and boarding area (`location_type=4`), the coordinates must be the ones of the bus pole — if exists — and otherwise of where the travelers are boarding the vehicle (on the sidewalk or the platform, and not on the roadway or the track where the vehicle stops).
Conditionally Required:
- **Required** for locations which are stops (`location_type=0`), stations (`location_type=1`) or entrances/exits (`location_type=2`).
- Optional for locations which are generic nodes (`location_type=3`) or boarding areas (`location_type=4`).|
| `stop_lon` | Longitude | **Conditionally Required** | Longitude of the location.
For stops/platforms (`location_type=0`) and boarding area (`location_type=4`), the coordinates must be the ones of the bus pole — if exists — and otherwise of where the travelers are boarding the vehicle (on the sidewalk or the platform, and not on the roadway or the track where the vehicle stops).
Conditionally Required:
- **Required** for locations which are stops (`location_type=0`), stations (`location_type=1`) or entrances/exits (`location_type=2`).
- Optional for locations which are generic nodes (`location_type=3`) or boarding areas (`location_type=4`). |
| `zone_id` | ID | **Conditionally Required** | Identifies the fare zone for a stop. If this record represents a station or station entrance, the `zone_id` is ignored.
Conditionally Required:
- **Required** if providing fare information using [fare_rules.txt](#fare_rulestxt)
- Optional otherwise.|
| `stop_url` | URL | Optional | URL of a web page about the location. This should be different from the `agency.agency_url` and the `routes.route_url` field values. |
-| `location_type` | Enum | Optional | Location type. Valid options are:
`0` (or blank) - **Stop** (or **Platform**). A location where passengers board or disembark from a transit vehicle. Is called a platform when defined within a `parent_station`.
`1` - **Station**. A physical structure or area that contains one or more platform.
`2` - **Entrance/Exit**. A location where passengers can enter or exit a station from the street. If an entrance/exit belongs to multiple stations, it may be linked by pathways to both, but the data provider must pick one of them as parent.
`3` - **Generic Node**. A location within a station, not matching any other `location_type`, that may be used to link together pathways define in pathways.txt.
`4` - **Boarding Area**. A specific location on a platform, where passengers can board and/or alight vehicles.|
-| `parent_station` | Foreign ID referencing `stops.stop_id` | **Conditionally Required** | Defines hierarchy between the different locations defined in `stops.txt`. It contains the ID of the parent location, as followed:
- **Stop/platform** (`location_type=0`): the `parent_station` field contains the ID of a station.
- **Station** (`location_type=1`): this field must be empty.
- **Entrance/exit** (`location_type=2`) or **generic node** (`location_type=3`): the `parent_station` field contains the ID of a station (`location_type=1`)
- **Boarding Area** (`location_type=4`): the `parent_station` field contains ID of a platform.
Conditionally Required:
- **Required** for locations which are entrances (`location_type=2`), generic nodes (`location_type=3`) or boarding areas (`location_type=4`).
- Optional for stops/platforms (`location_type=0`).
- Forbidden for stations (`location_type=1`).|
-| `stop_timezone` | Timezone | Optional | Timezone of the location. If the location has a parent station, it inherits the parent station’s timezone instead of applying its own. Stations and parentless stops with empty `stop_timezone` inherit the timezone specified by `agency.agency_timezone`. If `stop_timezone` values are provided, the times in [stop_times.txt](#stop_timetxt) should be entered as the time since midnight in the timezone specified by `agency.agency_timezone`. This ensures that the time values in a trip always increase over the course of a trip, regardless of which timezones the trip crosses. |
+| `location_type` | Enum | Optional | Location type. Valid options are:
`0` (or blank) - **Stop** (or **Platform**). A location where passengers board or disembark from a transit vehicle. Is called a platform when defined within a `parent_station`.
`1` - **Station**. A physical structure or area that contains one or more platform.
`2` - **Entrance/Exit**. A location where passengers can enter or exit a station from the street. If an entrance/exit belongs to multiple stations, it may be linked by pathways to both, but the data provider must pick one of them as parent.
`3` - **Generic Node**. A location within a station, not matching any other `location_type`, that may be used to link together pathways define in [pathways.txt](#pathwaystxt).
`4` - **Boarding Area**. A specific location on a platform, where passengers can board and/or alight vehicles.|
+| `parent_station` | Foreign ID referencing `stops.stop_id` | **Conditionally Required** | Defines hierarchy between the different locations defined in [stops.txt](#stopstxt). It contains the ID of the parent location, as followed:
- **Stop/platform** (`location_type=0`): the `parent_station` field contains the ID of a station.
- **Station** (`location_type=1`): this field must be empty.
- **Entrance/exit** (`location_type=2`) or **generic node** (`location_type=3`): the `parent_station` field contains the ID of a station (`location_type=1`)
- **Boarding Area** (`location_type=4`): the `parent_station` field contains ID of a platform.
Conditionally Required:
- **Required** for locations which are entrances (`location_type=2`), generic nodes (`location_type=3`) or boarding areas (`location_type=4`).
- Optional for stops/platforms (`location_type=0`).
- Forbidden for stations (`location_type=1`).|
+| `stop_timezone` | Timezone | Optional | Timezone of the location. If the location has a parent station, it inherits the parent station’s timezone instead of applying its own. Stations and parentless stops with empty `stop_timezone` inherit the timezone specified by `agency.agency_timezone`. The times provided in [stop_times.txt](#stop_timestxt) are in the timezone specified by `agency.agency_timezone`, not `stop_timezone`. This ensures that the time values in a trip always increase over the course of a trip, regardless of which timezones the trip crosses. |
| `wheelchair_boarding` | Enum | Optional | Indicates whether wheelchair boardings are possible from the location. Valid options are:
For parentless stops:
`0` or empty - No accessibility information for the stop.
`1` - Some vehicles at this stop can be boarded by a rider in a wheelchair.
`2` - Wheelchair boarding is not possible at this stop.
For child stops:
`0` or empty - Stop will inherit its `wheelchair_boarding` behavior from the parent station, if specified in the parent.
`1` - There exists some accessible path from outside the station to the specific stop/platform.
`2` - There exists no accessible path from outside the station to the specific stop/platform.
For station entrances/exits:
`0` or empty - Station entrance will inherit its `wheelchair_boarding` behavior from the parent station, if specified for the parent.
`1` - Station entrance is wheelchair accessible.
`2` - No accessible path from station entrance to stops/platforms. |
| `level_id` | Foreign ID referencing `levels.level_id` | Optional | Level of the location. The same level may be used by multiple unlinked stations.|
| `platform_code` | Text | Optional | Platform identifier for a platform stop (a stop belonging to a station). This should be just the platform identifier (eg. "G" or "3"). Words like “platform” or "track" (or the feed’s language-specific equivalent) should not be included. This allows feed consumers to more easily internationalize and localize the platform identifier into other languages. |
@@ -226,9 +235,9 @@ Primary key (`route_id`)
| `route_color` | Color | Optional | Route color designation that matches public facing material. Defaults to white (`FFFFFF`) when omitted or left empty. The color difference between `route_color` and `route_text_color` should provide sufficient contrast when viewed on a black and white screen. |
| `route_text_color` | Color | Optional | Legible color to use for text drawn against a background of `route_color`. Defaults to black (`000000`) when omitted or left empty. The color difference between `route_color` and `route_text_color` should provide sufficient contrast when viewed on a black and white screen. |
| `route_sort_order` | Non-negative integer | Optional | Orders the routes in a way which is ideal for presentation to customers. Routes with smaller `route_sort_order` values should be displayed first. |
-| `continuous_pickup` | Enum | Optional | Indicates that the rider can board the transit vehicle at any point along the vehicle’s travel path as described by `shapes.txt`, on every trip of the route. Valid options are:
`0` - Continuous stopping pickup.
`1` or empty - No continuous stopping pickup.
`2` - Must phone agency to arrange continuous stopping pickup.
`3` - Must coordinate with driver to arrange continuous stopping pickup.
Values for `routes.continuous_pickup` may be overridden by defining values in `stop_times.continuous_pickup` for specific `stop_time`s along the route. |
-| `continuous_drop_off` | Enum | Optional | Indicates that the rider can alight from the transit vehicle at any point along the vehicle’s travel path as described by `shapes.txt`, on every trip of the route. Valid options are:
`0` - Continuous stopping drop off.
`1` or empty - No continuous stopping drop off.
`2` - Must phone agency to arrange continuous stopping drop off.
`3` - Must coordinate with driver to arrange continuous stopping drop off.
Values for `routes.continuous_drop_off` may be overridden by defining values in `stop_times.continuous_drop_off` for specific `stop_time`s along the route. |
-| `network_id` | ID | **Conditionally Forbidden** | Identifies a group of routes. Multiple rows in [routes.txt](#routestxt) may have the same `network_id`.
Conditionally Forbidden:
- **Forbidden** if `route_networks.txt` file exists.
- Optional otherwise.
+| `continuous_pickup` | Enum | **Conditionally Forbidden** | Indicates that the rider can board the transit vehicle at any point along the vehicle’s travel path as described by [shapes.txt](#shapestxt), on every trip of the route. Valid options are:
`0` - Continuous stopping pickup.
`1` or empty - No continuous stopping pickup.
`2` - Must phone agency to arrange continuous stopping pickup.
`3` - Must coordinate with driver to arrange continuous stopping pickup.
Values for `routes.continuous_pickup` may be overridden by defining values in `stop_times.continuous_pickup` for specific `stop_time`s along the route.
**Conditionally Forbidden**:
- **Forbidden** if `stop_times.start_pickup_drop_off_window` or `stop_times.end_pickup_drop_off_window` are defined for any trip of this route.
- Optional otherwise. |
+| `continuous_drop_off` | Enum | **Conditionally Forbidden** | Indicates that the rider can alight from the transit vehicle at any point along the vehicle’s travel path as described by [shapes.txt](#shapestxt), on every trip of the route. Valid options are:
`0` - Continuous stopping drop off.
`1` or empty - No continuous stopping drop off.
`2` - Must phone agency to arrange continuous stopping drop off.
`3` - Must coordinate with driver to arrange continuous stopping drop off.
Values for `routes.continuous_drop_off` may be overridden by defining values in `stop_times.continuous_drop_off` for specific `stop_time`s along the route.
**Conditionally Forbidden**:
- **Forbidden** if `stop_times.start_pickup_drop_off_window` or `stop_times.end_pickup_drop_off_window` are defined for any trip of this route.
- Optional otherwise. |
+| `network_id` | ID | **Conditionally Forbidden** | Identifies a group of routes. Multiple rows in [routes.txt](#routestxt) may have the same `network_id`.
Conditionally Forbidden:
- **Forbidden** if the [route_networks.txt](#route_networkstxt) file exists.
- Optional otherwise.
### trips.txt
@@ -245,7 +254,7 @@ Primary key (`trip_id`)
| `trip_short_name` | Text | Optional | Public facing text used to identify the trip to riders, for instance, to identify train numbers for commuter rail trips. If riders do not commonly rely on trip names, `trip_short_name` should be empty. A `trip_short_name` value, if provided, should uniquely identify a trip within a service day; it should not be used for destination names or limited/express designations. |
| `direction_id` | Enum | Optional | Indicates the direction of travel for a trip. This field should not be used in routing; it provides a way to separate trips by direction when publishing time tables. Valid options are:
`0` - Travel in one direction (e.g. outbound travel).
`1` - Travel in the opposite direction (e.g. inbound travel).