From 86fbd8d505167f25597c329c6990a4a8bf6d1874 Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Wed, 3 Jan 2024 11:16:37 -0500 Subject: [PATCH 01/16] Editorial change: update text in networks.txt and routes_networks.txt (#414) * update test for routes.txt and routes_networks.txt * Remove requirement for levels at the file level * Change defined -> exists * Add a reference to what "field exists" means --- gtfs/spec/en/reference.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 8ba412f0..7a9b1058 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -47,7 +47,7 @@ This section defines terms that are used throughout this document. * **Dataset** - A complete set of files defined by this specification reference. Altering the dataset creates a new version of the dataset. Datasets should be published at a public, permanent URL, including the zip file name. (e.g., https://www.agency.org/gtfs/gtfs.zip). * **Record** - A basic data structure comprised of a number of different field values describing a single entity (e.g. transit agency, stop, route, etc.). Represented, in a table, as a row. -* **Field** - A property of an object or entity. Represented, in a table, as a column. +* **Field** - A property of an object or entity. Represented, in a table, as a column. The field exists if added in a file as a header. It may or may not have field values defined. * **Field value** - An individual entry in a field. Represented, in a table, as a single cell. * **Service day** - A service day is a time period used to indicate route scheduling. The exact definition of service day varies from agency to agency but service days often do not correspond with calendar days. A service day may exceed 24:00:00 if service begins on one day and ends on a following day. For example, service that runs from 08:00:00 on Friday to 02:00:00 on Saturday, could be denoted as running from 08:00:00 to 26:00:00 on a single service day. * **Text-to-speech field** - The field should contain the same information than its parent field (on which it falls back if it is empty). It is aimed to be read as text-to-speech, therefore, abbreviation should be either removed ("St" should be either read as "Street" or "Saint"; "Elizabeth I" should be "Elizabeth the first") or kept to be read as it ("JFK Airport" is said abbreviated). @@ -121,8 +121,8 @@ 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 `routes.network_id` field exists.
- Optional otherwise. | -| [route_networks.txt](#route_networkstxt) | **Conditionally Forbidden** | Rules to assign routes to networks.

Conditionally Forbidden:
- **Forbidden** if `routes.network_id` field exists.
- Optional otherwise. | +| [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. | | [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. | @@ -529,7 +529,7 @@ File: **Conditionally Forbidden** Primary key (`network_id`) -Defines network identifiers that apply for fare leg rules. Forbidden if `routes.network_id` field exists. +Defines network identifiers that apply for fare leg rules. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | @@ -542,7 +542,7 @@ File: **Conditionally Forbidden** Primary key (`route_id`) -Assigns routes from [routes.txt](#routestxt) to networks. Forbidden if `routes.network_id` field exists. +Assigns routes from [routes.txt](#routestxt) to networks. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | @@ -678,7 +678,7 @@ File: **Conditionally Required** Primary key (`level_id`) -Describes levels in a station. Useful in conjunction with `pathways.txt`, and is required for navigating pathways with elevators (`pathway_mode=5`). +Describes levels in a station. Useful in conjunction with `pathways.txt`. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | From eee97f7fca252019ef75995704a40edf62d5199b Mon Sep 17 00:00:00 2001 From: Emma Blue <90632321+emmambd@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:29:59 -0500 Subject: [PATCH 02/16] [Governance] Phase 1: Issue Templates (#417) * issue templates add * Fix config.yml * Update link labels --------- Co-authored-by: isabelle-dr --- .github/ISSUE_TEMPLATE/config.yml | 13 +++++++++ .github/ISSUE_TEMPLATE/question.yml | 21 +++++++++++++++ .github/ISSUE_TEMPLATE/spec_change.yml | 37 ++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/question.yml create mode 100644 .github/ISSUE_TEMPLATE/spec_change.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..05ca3383 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,13 @@ +contact_links: + - name: GTFS Documentation + url: https://gtfs.org/ + about: The official reference for GTFS documentation. + - name: GTFS Changes Mailing List + url: https://groups.google.com/g/gtfs-changes + about: Follow this group to get announcement on votes on the GTFS Schedule specification. + - name: GTFS Realtime Mailing List + url: https://groups.google.com/g/gtfs-realtime + about: This group is the forum for discussing the GTFS Realtime specification, asking questions, and proposing changes. + - name: GTFS Slack Channel + url: https://share.mobilitydata.org/slack + about: Join the gtfs channel to discuss with other community members, and receive updates. diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 00000000..af28b569 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,21 @@ +name: Question +description: Ask a question or raise a problem without a proposed solution. +labels: ['question'] + +body: + - type: markdown + attributes: + value: > + #### Before submitting a question, please make sure there isn't an already [existing issue for it](https://github.com/google/transit/issues?q=+is%3Aissue+label%3Aquestion+). + - type: textarea + attributes: + label: Introduce yourself + description: > + If you are new to the specification, please introduce yourself (name and organization/link to your GTFS feed)! + validations: + required: false + - type: textarea + attributes: + label: Ask a question + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/spec_change.yml b/.github/ISSUE_TEMPLATE/spec_change.yml new file mode 100644 index 00000000..81a64368 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/spec_change.yml @@ -0,0 +1,37 @@ +name: Specification change +description: Propose a change to the specification. +labels: ['spec-change'] + +body: + - type: markdown + attributes: + value: > + #### Before submitting a new change, please make sure the same one isn't already [proposed in an issue](https://github.com/google/transit/issues). + - type: textarea + attributes: + label: Describe the problem + description: > + Describe what you are trying to achieve. + validations: + required: true + - type: textarea + attributes: + label: Use cases + description: > + Share examples of the scenarios you want the proposal to address, e.g GTFS-Fares v2 makes it possible to display the cost of a monthly pass. Show visuals of how it will appear to riders where relevant. [Here's a great example of communicating a complex use case](https://github.com/google/transit/pull/352#issuecomment-1284756181). + validations: + required: true + - type: textarea + attributes: + label: Proposed solution + description: > + A clear description of what you want to happen. + validations: + required: true + - type: textarea + attributes: + label: Additional information + description: > + Additional information that can help the community better understand your need. + validations: + required: false From e19188031d4cbf6b070759c431c45fd636582f7d Mon Sep 17 00:00:00 2001 From: Elias Gino Cripotos <130911698+eliasmbd@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:33:38 -0500 Subject: [PATCH 03/16] Stale Bot Fix - Removal of automatic closing of stale issues and PRs (#416) - Removal of automatic closing items of stale issues and PRs. - Change of stale label for PRs from 23 to 90 days --- .github/workflows/stale.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 192434f3..1bfe4ab8 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: 'Close stale issues and PRs' on: schedule: - - cron: '0 0 * * *' + - cron: '0 4 * * *' permissions: issues: write @@ -11,15 +11,11 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v4 + - uses: actions/stale@v9.0.0 with: - stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' - close-issue-message: 'This issue has been closed due to inactivity. Issues can always be reopened after they have been closed.' + stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It may be closed manually after one month of inactivity. Thank you for your contributions.' stale-issue-label: 'stale' days-before-issue-stale: 365 - days-before-issue-close: 14 - stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' - close-pr-message: 'This pull request has been closed due to inactivity. Pull requests can always be reopened after they have been closed. See the Specification Amendment Process.' + stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It may be closed manually after one month of inactivity. Thank you for your contributions.' stale-pr-label: 'stale' - days-before-pr-stale: 23 - days-before-pr-close: 7 \ No newline at end of file + days-before-pr-stale: 90 From 7a44805686ef630de9a702ba6266de37a6cbc9bd Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Mon, 15 Jan 2024 14:26:30 -0500 Subject: [PATCH 04/16] Editorial changes to Reference.md (#422) * Add dataset publishing in index * Fix link * Clarify stop_timezone description * Make references to other files consistent * fix link in Dataset Publishing Guidelines * Fix links --- gtfs/spec/en/reference.md | 63 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 7a9b1058..1602678f 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) @@ -121,8 +122,8 @@ 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. | @@ -162,7 +163,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 @@ -193,16 +194,16 @@ Primary key (`stop_id`) | ------ | ------ | ------ | ------ | | `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_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 +227,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 | Optional | 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. | +| `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](#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. | +| `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 +246,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).
*Example: The `trip_headsign` and `direction_id` fields may be used together to assign a name to travel in each direction for a set of trips. A [trips.txt](#tripstxt) file could contain these records for use in time tables:*
`trip_id,...,trip_headsign,direction_id`
`1234,...,Airport,0`
`1505,...,Downtown,1` | | `block_id` | ID | Optional | Identifies the block to which the trip belongs. A block consists of a single trip or many sequential trips made using the same vehicle, defined by shared service days and `block_id`. A `block_id` may have trips with different service days, making distinct blocks. See the [example below](#example-blocks-and-service-day). To provide in-seat transfers information, [transfers](#transferstxt) of `transfer_type` `4` should be provided instead. | -| `shape_id` | Foreign ID referencing `shapes.shape_id` | **Conditionally Required** | Identifies a geospatial shape describing the vehicle travel path for a trip.

Conditionally Required:
- **Required** if the trip has a continuous pickup or drop-off behavior defined either in `routes.txt` or in `stop_times.txt`.
- Optional otherwise. | +| `shape_id` | Foreign ID referencing `shapes.shape_id` | **Conditionally Required** | Identifies a geospatial shape describing the vehicle travel path for a trip.

Conditionally Required:
- **Required** if the trip has a continuous pickup or drop-off behavior defined either in [routes.txt](#routestxt) or in [stop_times.txt](#stop_timestxt).
- Optional otherwise. | | `wheelchair_accessible` | Enum | Optional | Indicates wheelchair accessibility. Valid options are:

`0` or empty - No accessibility information for the trip.
`1` - Vehicle being used on this particular trip can accommodate at least one rider in a wheelchair.
`2` - No riders in wheelchairs can be accommodated on this trip. | | `bikes_allowed` | Enum | Optional | Indicates whether bikes are allowed. Valid options are:

`0` or empty - No bike information for the trip.
`1` - Vehicle being used on this particular trip can accommodate at least one bicycle.
`2` - No bicycles are allowed on this trip. | @@ -282,8 +283,8 @@ Primary key (`trip_id`, `stop_sequence`) | `stop_headsign` | Text | Optional | Text that appears on signage identifying the trip's destination to riders. This field overrides the default `trips.trip_headsign` when the headsign changes between stops. If the headsign is displayed for an entire trip, `trips.trip_headsign` should be used instead.

A `stop_headsign` value specified for one `stop_time` does not apply to subsequent `stop_time`s in the same trip. If you want to override the `trip_headsign` for multiple `stop_time`s in the same trip, the `stop_headsign` value must be repeated in each `stop_time` row. | | `pickup_type` | Enum | Optional | Indicates pickup method. Valid options are:

`0` or empty - Regularly scheduled pickup.
`1` - No pickup available.
`2` - Must phone agency to arrange pickup.
`3` - Must coordinate with driver to arrange pickup. | | `drop_off_type` | Enum | Optional | Indicates drop off method. Valid options are:

`0` or empty - Regularly scheduled drop off.
`1` - No drop off available.
`2` - Must phone agency to arrange drop off.
`3` - Must coordinate with driver to arrange drop off. | -| `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`, from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

If this field is populated, it overrides any continuous pickup behavior defined in `routes.txt`. If this field is empty, the `stop_time` inherits any continuous pickup behavior defined in `routes.txt`. | -| `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`, from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

If this field is populated, it overrides any continuous drop-off behavior defined in `routes.txt`. If this field is empty, the `stop_time` inherits any continuous drop-off behavior defined in `routes.txt`. | +| `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](#shapestxt), from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

If this field is populated, it overrides any continuous pickup behavior defined in [routes.txt](#routestxt). If this field is empty, the `stop_time` inherits any continuous pickup behavior defined in [routes.txt](#routestxt). | +| `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](#shapestxt), from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

If this field is populated, it overrides any continuous drop-off behavior defined in [routes.txt](#routestxt). If this field is empty, the `stop_time` inherits any continuous drop-off behavior defined in [routes.txt](#routestxt). | | `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the associated shape, from the first stop to the stop specified in this record. This field specifies how much of the shape to draw between any two stops during a trip. Must be in the same units used in [shapes.txt](#shapestxt). Values used for `shape_dist_traveled` must increase along with `stop_sequence`; they must not be used to show reverse travel along a route.

Recommended for routes that have looping or inlining (the vehicle crosses or travels over the same portion of alignment in one trip). See [`shapes.shape_dist_traveled`](#shapestxt).
*Example: If a bus travels a distance of 5.25 kilometers from the start of the shape to the stop,`shape_dist_traveled`=`5.25`.*| | `timepoint` | Enum | Recommended | Indicates if arrival and departure times for a stop are strictly adhered to by the vehicle or if they are instead approximate and/or interpolated times. This field allows a GTFS producer to provide interpolated stop-times, while indicating that the times are approximate. Valid options are:

`0` - Times are considered approximate.
`1` or empty - Times are considered exact. | @@ -295,7 +296,7 @@ Primary key (`service_id`) | Field Name | Type | Presence | Description | | ------ | ------ | ------ |------ | -| `service_id` | Unique ID | **Required** | Identifies a set of dates when service is available for one or more routes. Each `service_id` value must be unique in a [calendar.txt](#calendartxt) file. | +| `service_id` | Unique ID | **Required** | Identifies a set of dates when service is available for one or more routes. | | `monday` | Enum | **Required** | Indicates whether the service operates on all Mondays in the date range specified by the `start_date` and `end_date` fields. Note that exceptions for particular dates may be listed in [calendar_dates.txt](#calendar_datestxt). Valid options are:

`1` - Service is available for all Mondays in the date range.
`0` - Service is not available for Mondays in the date range. | | `tuesday` | Enum | **Required** | Functions in the same way as `monday` except applies to Tuesdays | | `wednesday` | Enum | **Required** | Functions in the same way as `monday` except applies to Wednesdays | @@ -341,7 +342,7 @@ There are two modelling options for describing fares. GTFS-Fares V1 is the legac | `currency_type` | Currency code | **Required** | Currency used to pay the fare. | | `payment_method` | Enum | **Required** | Indicates when the fare must be paid. Valid options are:

`0` - Fare is paid on board.
`1` - Fare must be paid before boarding. | | `transfers` | Enum | **Required** | Indicates the number of transfers permitted on this fare. Valid options are:

`0` - No transfers permitted on this fare.
`1` - Riders may transfer once.
`2` - Riders may transfer twice.
empty - Unlimited transfers are permitted. | -| `agency_id` | Foreign ID referencing `agency.agency_id` | **Conditionally Required** | Identifies the relevant agency for a fare.

Conditionally Required:
- **Required** if multiple agencies are defined in `agency.txt`.
- Recommended otherwise. | +| `agency_id` | Foreign ID referencing `agency.agency_id` | **Conditionally Required** | Identifies the relevant agency for a fare.

Conditionally Required:
- **Required** if multiple agencies are defined in [agency.txt](#agencytxt).
- Recommended otherwise. | | `transfer_duration` | Non-negative integer | Optional | Length of time in seconds before a transfer expires. When `transfers`=`0` this field may be used to indicate how long a ticket is valid for or it may be left empty. | ### fare_rules.txt @@ -372,7 +373,7 @@ File: **Optional** Primary key (*) -Used to describe fares that can vary based on the time of day, the day of the week, or a particular day in the year. Timeframes can be associated with fare products in `fare_leg_rules.txt`.
+Used to describe fares that can vary based on the time of day, the day of the week, or a particular day in the year. Timeframes can be associated with fare products in [fare_leg_rules.txt](#fare_leg_rulestxt).
There must not be overlapping time intervals for the same `timeframe_group_id` and `service_id` values. | Field Name | Type | Presence | Description | @@ -383,7 +384,7 @@ There must not be overlapping time intervals for the same `timeframe_group_id` a | `service_id` | Foreign ID referencing `calendar.service_id` or `calendar_dates.service_id` | **Required** | Identifies a set of dates that a timeframe is in effect. | #### Timeframe Local Time Semantics -- When evaluating a fare event’s time against `timeframes.txt`, the event time is computed in local time using the local timezone, as determined by the `stop_timezone`, if specified, of the stop or parent station for the fare event. If not specified, the feed’s agency timezone should be used instead. +- When evaluating a fare event’s time against [timeframes.txt](#timeframestxt), the event time is computed in local time using the local timezone, as determined by the `stop_timezone`, if specified, of the stop or parent station for the fare event. If not specified, the feed’s agency timezone should be used instead. - The “current day” is the current date of the fare event’s time, computed relative to the local timezone. The “current day” may be different from the service day of a fare leg’s trip, especially for trips that extend past midnight. - The “time-of-day” for the fare event is computed relative to “current day” using GTFS Time field-type semantics. @@ -430,7 +431,7 @@ Fares in [`fare_leg_rules.txt`](#fare_leg_rulestxt) must be queried by filtering To process the cost of a leg: -1. The file `fare_leg_rules.txt` must be filtered by the fields that define the characteristics of travel, these fields are: +1. The file [fare_leg_rules.txt](#fare_leg_rulestxt) must be filtered by the fields that define the characteristics of travel, these fields are: - `fare_leg_rules.network_id` - `fare_leg_rules.from_area_id` - `fare_leg_rules.to_area_id` @@ -438,11 +439,11 @@ To process the cost of a leg: - `fare_leg_rules.to_timeframe_group_id`

-2. If the leg exactly matches a record in `fare_leg_rules.txt` based on the characteristics of travel, that record must be processed to determine the cost of the leg. +2. If the leg exactly matches a record in [fare_leg_rules.txt](#fare_leg_rulestxt) based on the characteristics of travel, that record must be processed to determine the cost of the leg.
3. If no exact matches are found, then empty entries in `fare_leg_rules.network_id`, `fare_leg_rules.from_area_id`, and `fare_leg_rules.to_area_id` must be checked to process the cost of the leg: - - An empty entry in `fare_leg_rules.network_id` corresponds to all networks defined in `routes.txt` excluding the ones listed under `fare_leg_rules.network_id` + - An empty entry in `fare_leg_rules.network_id` corresponds to all networks defined in [routes.txt](#routestxt) or [networks.txt](#networkstxt) excluding the ones listed under `fare_leg_rules.network_id` - An empty entry in `fare_leg_rules.from_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.from_area_id` - An empty entry in `fare_leg_rules.to_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.to_area_id`
@@ -454,11 +455,11 @@ To process the cost of a leg: | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | | `leg_group_id` | ID | Optional | Identifies a group of entries in [fare_leg_rules.txt](#fare_leg_rulestxt).

Used to describe fare transfer rules between `fare_transfer_rules.from_leg_group_id` and `fare_transfer_rules.to_leg_group_id`.

Multiple entries in [fare_leg_rules.txt](#fare_leg_rulestxt) may belong to the same `fare_leg_rules.leg_group_id`.

The same entry in [fare_leg_rules.txt](#fare_leg_rulestxt) (not including `fare_leg_rules.leg_group_id`) must not belong to multiple `fare_leg_rules.leg_group_id`.| -| `network_id` | Foreign ID referencing `routes.network_id` or `networks.network_id`| Optional | Identifies a route network that applies for the fare leg rule.

If there are no matching `fare_leg_rules.network_id` values to the `network_id` being filtered, empty `fare_leg_rules.network_id` will be matched by default.

An empty entry in `fare_leg_rules.network_id` corresponds to all networks defined in `routes.txt` or `networks.txt` excluding the ones listed under `fare_leg_rules.network_id` | +| `network_id` | Foreign ID referencing `routes.network_id` or `networks.network_id`| Optional | Identifies a route network that applies for the fare leg rule.

If there are no matching `fare_leg_rules.network_id` values to the `network_id` being filtered, empty `fare_leg_rules.network_id` will be matched by default.

An empty entry in `fare_leg_rules.network_id` corresponds to all networks defined in [routes.txt](#routestxt) or [networks.txt](#networkstxt) excluding the ones listed under `fare_leg_rules.network_id` | | `from_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies a departure area.

If there are no matching `fare_leg_rules.from_area_id` values to the `area_id` being filtered, empty `fare_leg_rules.from_area_id` will be matched by default.

An empty entry in `fare_leg_rules.from_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.from_area_id` | | `to_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies an arrival area.

If there are no matching `fare_leg_rules.to_area_id` values to the `area_id` being filtered, empty `fare_leg_rules.to_area_id` will be matched by default.

An empty entry in `fare_leg_rules.to_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.to_area_id` | -| `from_timeframe_group_id` | Foreign ID referencing `timeframes.timeframe_group_id` | Optional | Defines the timeframe for the fare validation event at the start of the fare leg.

The “start time” of the fare leg is the time at which the event is scheduled to occur. For example, the time could be the scheduled departure time of a bus at the start of a fare leg where the rider boards and validates their fare. For the rule matching semantics below, the start time is computed in local time, as determined by [Local Time Semantics](#localtimesemantics) of [timeframes.txt](#timeframestxt). The stop or station of the fare leg’s departure event should be used for timezone resolution, where appropriate.

For a fare leg rule that specifies a `from_timeframe_group_id`, that rule will match a particular leg if there exists at least one record in `timeframes.txt` where all of the following conditions are true
- The value of `timeframe_group_id` is equal to the `from_timeframe_group_id` value.
- The set of days identified by the record’s `service_id` contains the “current day” of the fare leg’s start time.
- The “time-of-day” of the fare leg's start time is greater than or equal to the record’s `timeframes.start_time` value and less than the `timeframes.end_time` value.

An empty `fare_leg_rules.from_timeframe_group_id` indicates that the start time of the leg does not affect the matching of this rule. | -| `to_timeframe_group_id` | Foreign ID referencing `timeframes.timeframe_group_id` | Optional | Defines the timeframe for the fare validation event at the end of the fare leg.

The “end time” of the fare leg is the time at which the event is scheduled to occur. For example, the time could be the scheduled arrival time of a bus at the end of a fare leg where the rider gets off and validates their fare. For the rule matching semantics below, the end time is computed in local time, as determined by [Local Time Semantics](#localtimesemantics) of [timeframes.txt](#timeframestxt). The stop or station of the fare leg’s arrival event should be used for timezone resolution, where appropriate.

For a fare leg rule that specifies a `to_timeframe_group_id`, that rule will match a particular leg if there exists at least one record in `timeframes.txt` where all of the following conditions are true
- The value of `timeframe_group_id` is equal to the `to_timeframe_group_id` value.
- The set of days identified by the record’s `service_id` contains the “current day” of the fare leg’s end time.
- The “time-of-day” of the fare leg's end time is greater than or equal to the record’s `timeframes.start_time` value and less than the `timeframes.end_time` value.

An empty `fare_leg_rules.to_timeframe_group_id` indicates that the end time of the leg does not affect the matching of this rule. | +| `from_timeframe_group_id` | Foreign ID referencing `timeframes.timeframe_group_id` | Optional | Defines the timeframe for the fare validation event at the start of the fare leg.

The “start time” of the fare leg is the time at which the event is scheduled to occur. For example, the time could be the scheduled departure time of a bus at the start of a fare leg where the rider boards and validates their fare. For the rule matching semantics below, the start time is computed in local time, as determined by [Local Time Semantics](#localtimesemantics) of [timeframes.txt](#timeframestxt). The stop or station of the fare leg’s departure event should be used for timezone resolution, where appropriate.

For a fare leg rule that specifies a `from_timeframe_group_id`, that rule will match a particular leg if there exists at least one record in [timeframes.txt](#timeframestxt) where all of the following conditions are true
- The value of `timeframe_group_id` is equal to the `from_timeframe_group_id` value.
- The set of days identified by the record’s `service_id` contains the “current day” of the fare leg’s start time.
- The “time-of-day” of the fare leg's start time is greater than or equal to the record’s `timeframes.start_time` value and less than the `timeframes.end_time` value.

An empty `fare_leg_rules.from_timeframe_group_id` indicates that the start time of the leg does not affect the matching of this rule. | +| `to_timeframe_group_id` | Foreign ID referencing `timeframes.timeframe_group_id` | Optional | Defines the timeframe for the fare validation event at the end of the fare leg.

The “end time” of the fare leg is the time at which the event is scheduled to occur. For example, the time could be the scheduled arrival time of a bus at the end of a fare leg where the rider gets off and validates their fare. For the rule matching semantics below, the end time is computed in local time, as determined by [Local Time Semantics](#localtimesemantics) of [timeframes.txt](#timeframestxt). The stop or station of the fare leg’s arrival event should be used for timezone resolution, where appropriate.

For a fare leg rule that specifies a `to_timeframe_group_id`, that rule will match a particular leg if there exists at least one record in [timeframes.txt](#timeframestxt) where all of the following conditions are true
- The value of `timeframe_group_id` is equal to the `to_timeframe_group_id` value.
- The set of days identified by the record’s `service_id` contains the “current day” of the fare leg’s end time.
- The “time-of-day” of the fare leg's end time is greater than or equal to the record’s `timeframes.start_time` value and less than the `timeframes.end_time` value.

An empty `fare_leg_rules.to_timeframe_group_id` indicates that the end time of the leg does not affect the matching of this rule. | | `fare_product_id` | Foreign ID referencing `fare_products.fare_product_id` | **Required** | The fare product required to travel the leg. | ### fare_transfer_rules.txt @@ -472,12 +473,12 @@ Fare rules for transfers between legs of travel defined in [`fare_leg_rules.txt` To process the cost of a multi-leg journey: 1. The applicable fare leg groups defined in `fare_leg_rules.txt` should be determined for all individual legs of travel based on the rider’s journey. -2. The file `fare_transfer_rules.txt` must be filtered by the fields that define the characteristics of the transfer, these fields are: +2. The file [fare_transfer_rules.txt](#fare_transfer_rulestxt) must be filtered by the fields that define the characteristics of the transfer, these fields are: - `fare_transfer_rules.from_leg_group_id` - `fare_transfer_rules.to_leg_group_id`

-3. If the transfer exactly matches a record in `fare_transfer_rules.txt` based on the characteristics of the transfer, then that record must be processed to determine the transfer cost. +3. If the transfer exactly matches a record in [fare_transfer_rules.txt](#fare_transfer_rulestxt) based on the characteristics of the transfer, then that record must be processed to determine the transfer cost. 4. If no exact matches are found, then empty entries in `from_leg_group_id` or in `to_leg_group_id` must be checked to process the transfer cost: - An empty entry in `fare_transfer_rules.from_leg_group_id` corresponds to all leg groups defined under `fare_leg_rules.leg_group_id` excluding the ones listed under `fare_transfer_rules.from_leg_group_id` - An empty entry in `fare_transfer_rules.to_leg_group_id` corresponds to all leg groups defined under `fare_leg_rules.leg_group_id` excluding the ones listed under `fare_transfer_rules.to_leg_group_id`
@@ -563,7 +564,7 @@ Shapes describe the path that a vehicle travels along a route alignment, and are | `shape_pt_lat` | Latitude | **Required** | Latitude of a shape point. Each record in [shapes.txt](#shapestxt) represents a shape point used to define the shape. | | `shape_pt_lon` | Longitude | **Required** | Longitude of a shape point. | | `shape_pt_sequence` | Non-negative integer | **Required** | Sequence in which the shape points connect to form the shape. Values must increase along the trip but do not need to be consecutive.
*Example: If the shape "A_shp" has three points in its definition, the [shapes.txt](#shapestxt) file might contain these records to define the shape:*
`shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence`
`A_shp,37.61956,-122.48161,0`
`A_shp,37.64430,-122.41070,6`
`A_shp,37.65863,-122.30839,11` | -| `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the shape from the first shape point to the point specified in this record. Used by trip planners to show the correct portion of the shape on a map. Values must increase along with `shape_pt_sequence`; they must not be used to show reverse travel along a route. Distance units must be consistent with those used in [stop_times.txt](#stop_timestxt).

Recommended for routes that have looping or inlining (the vehicle crosses or travels over the same portion of alignment in one trip).

If a vehicle retraces or crosses the route alignment at points in the course of a trip, `shape_dist_traveled` is important to clarify how portions of the points in `shapes.txt` line up correspond with records in `stop_times.txt`.
*Example: If a bus travels along the three points defined above for A_shp, the additional `shape_dist_traveled` values (shown here in kilometers) would look like this:*
`shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence,shape_dist_traveled`
`A_shp,37.61956,-122.48161,0,0`
`A_shp,37.64430,-122.41070,6,6.8310`
`A_shp,37.65863,-122.30839,11,15.8765` | +| `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the shape from the first shape point to the point specified in this record. Used by trip planners to show the correct portion of the shape on a map. Values must increase along with `shape_pt_sequence`; they must not be used to show reverse travel along a route. Distance units must be consistent with those used in [stop_times.txt](#stop_timestxt).

Recommended for routes that have looping or inlining (the vehicle crosses or travels over the same portion of alignment in one trip).

If a vehicle retraces or crosses the route alignment at points in the course of a trip, `shape_dist_traveled` is important to clarify how portions of the points in [shapes.txt](#shapestxt) line up correspond with records in [stop_times.txt](#stop_timestxt).
*Example: If a bus travels along the three points defined above for A_shp, the additional `shape_dist_traveled` values (shown here in kilometers) would look like this:*
`shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence,shape_dist_traveled`
`A_shp,37.61956,-122.48161,0,0`
`A_shp,37.64430,-122.41070,6,6.8310`
`A_shp,37.65863,-122.30839,11,15.8765` | ### frequencies.txt @@ -678,7 +679,7 @@ File: **Conditionally Required** Primary key (`level_id`) -Describes levels in a station. Useful in conjunction with `pathways.txt`. +Describes levels in a station. Useful in conjunction with [pathways.txt](#pathwaystxt). | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | @@ -703,13 +704,13 @@ If both referencing methods (`record_id`, `record_sub_id`) and `field_value` are | `field_name` | Text | **Required** | Name of the field to be translated. Fields with type `Text` may be translated, fields with type `URL`, `Email` and `Phone number` may also be “translated” to provide resources in the correct language. Fields with other types should not be translated. | | `language` | Language code | **Required** | Language of translation.

If the language is the same as in `feed_info.feed_lang`, the original value of the field will be assumed to be the default value to use in languages without specific translations (if `default_lang` doesn't specify otherwise).
_Example: In Switzerland, a city in an officially bilingual canton is officially called “Biel/Bienne”, but would simply be called “Bienne” in French and “Biel” in German._ | | `translation` | Text or URL or Email or Phone number | **Required** | Translated value. | -| `record_id` | Foreign ID | **Conditionally Required** | Defines the record that corresponds to the field to be translated. The value in `record_id` must be the first or only field of a table's primary key, as defined in the primary key attribute for each table and below:

- `agency_id` for `agency.txt`
- `stop_id` for `stops.txt`;
- `route_id` for `routes.txt`;
- `trip_id` for `trips.txt`;
- `trip_id` for `stop_times.txt`;
- `pathway_id` for `pathways.txt`;
- `level_id` for `levels.txt`;
- `attribution_id` for `attribution.txt`.

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_id` for those tables:

- `service_id` for `calendar.txt`;
- `service_id` for `calendar_dates.txt`;
- `fare_id` for `fare_attributes.txt`;
- `fare_id` for `fare_rules.txt`;
- `shape_id` for `shapes.txt`;
- `trip_id` for `frequencies.txt`;
- `from_stop_id` for `transfers.txt`.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `field_value` is empty. | -| `record_sub_id` | Foreign ID | **Conditionally Required** | Helps the record that contains the field to be translated when the table doesn’t have a unique ID. Therefore, the value in `record_sub_id` is the secondary ID of the table, as defined by the table below:

- None for `agency.txt`;
- None for `stops.txt`;
- None for `routes.txt`;
- None for `trips.txt`;
- `stop_sequence` for `stop_times.txt`;
- None for `pathways.txt`;
- None for `levels.txt`;
- None for `attributions.txt`.

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_sub_id` for those tables:

- None for `calendar.txt`;
- `date` for `calendar_dates.txt`;
- None for `fare_attributes.txt`;
- `route_id` for `fare_rules.txt`;
- None for `shapes.txt`;
- `start_time` for `frequencies.txt`;
- `to_stop_id` for `transfers.txt`.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `table_name=stop_times` and `record_id` is defined. | +| `record_id` | Foreign ID | **Conditionally Required** | Defines the record that corresponds to the field to be translated. The value in `record_id` must be the first or only field of a table's primary key, as defined in the primary key attribute for each table and below:

- `agency_id` for [agency.txt](#agencytxt)`
- `stop_id` for [stops.txt](#stopstxt);
- `route_id` for [routes.txt](#routestxt);
- `trip_id` for [trips.txt](#tripstxt);
- `trip_id` for [stop_times.txt](#stop_timestxt);
- `pathway_id` for [pathways.txt](#pathwaystxt);
- `level_id` for [levels.txt](#levelstxt);
- `attribution_id` for [attributions.txt](#attributionstxt).

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_id` for those tables:

- `service_id` for [calendar.txt](#calendartxt);
- `service_id` for [calendar_dates.txt](#calendar_datestxt);
- `fare_id` for [fare_attributes.txt](#fare_attributestxt);
- `fare_id` for [fare_rules.txt](#fare_rulestxt);
- `shape_id` for [shapes.txt](#shapestxt);
- `trip_id` for [frequencies.txt](#frequenciestxt);
- `from_stop_id` for `transfers.txt`.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `field_value` is empty. | +| `record_sub_id` | Foreign ID | **Conditionally Required** | Helps the record that contains the field to be translated when the table doesn’t have a unique ID. Therefore, the value in `record_sub_id` is the secondary ID of the table, as defined by the table below:

- None for [agency.txt](#agencytxt);
- None for [stops.txt](#stopstxt);
- None for [routes.txt](#routestxt);
- None for [trips.txt](#tripstxt);
- `stop_sequence` for [stop_times.txt](#stop_timestxt);
- None for [pathways.txt](#pathwaystxt);
- None for [levels.txt](#levelstxt);
- None for [attributions.txt](#attributionstxt).

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_sub_id` for those tables:

- None for [calendar.txt](#calendartxt);
- `date` for [calendar_dates.txt](#calendar_datestxt);
- None for [fare_attributes.txt](#fare_attributestxt);
- `route_id` for [fare_rules.txt](#fare_rulestxt);
- None for [shapes.txt](#shapestxt);
- `start_time` for [frequencies.txt](#frequenciestxt);
- `to_stop_id` for [transfers.txt](#transferstxt).

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `table_name=stop_times` and `record_id` is defined. | | `field_value` | Text or URL or Email or Phone number | **Conditionally Required** | Instead of defining which record should be translated by using `record_id` and `record_sub_id`, this field can be used to define the value which should be translated. When used, the translation will be applied when the fields identified by `table_name` and `field_name` contains the exact same value defined in field_value.

The field must have **exactly** the value defined in `field_value`. If only a subset of the value matches `field_value`, the translation won’t be applied.

If two translation rules match the same record (one with `field_value`, and the other one with `record_id`), the rule with `record_id` takes precedence.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `record_id` is defined.
- **Required** if `record_id` is empty. | ### feed_info.txt -File: **Recommended** (**Required** if `translations.txt` is provided) +File: **Recommended** (**Required** if [translations.txt](#translations) is provided) Primary key (none) From d523e3f8ca911fbaf206793d5137206be5ad0324 Mon Sep 17 00:00:00 2001 From: Kayla Firestack Date: Mon, 12 Feb 2024 12:35:27 -0500 Subject: [PATCH 05/16] fix(gtfs/spec/reference): remove extra backtick in`record_id` description (#431) --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 1602678f..9571e46b 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -704,7 +704,7 @@ If both referencing methods (`record_id`, `record_sub_id`) and `field_value` are | `field_name` | Text | **Required** | Name of the field to be translated. Fields with type `Text` may be translated, fields with type `URL`, `Email` and `Phone number` may also be “translated” to provide resources in the correct language. Fields with other types should not be translated. | | `language` | Language code | **Required** | Language of translation.

If the language is the same as in `feed_info.feed_lang`, the original value of the field will be assumed to be the default value to use in languages without specific translations (if `default_lang` doesn't specify otherwise).
_Example: In Switzerland, a city in an officially bilingual canton is officially called “Biel/Bienne”, but would simply be called “Bienne” in French and “Biel” in German._ | | `translation` | Text or URL or Email or Phone number | **Required** | Translated value. | -| `record_id` | Foreign ID | **Conditionally Required** | Defines the record that corresponds to the field to be translated. The value in `record_id` must be the first or only field of a table's primary key, as defined in the primary key attribute for each table and below:

- `agency_id` for [agency.txt](#agencytxt)`
- `stop_id` for [stops.txt](#stopstxt);
- `route_id` for [routes.txt](#routestxt);
- `trip_id` for [trips.txt](#tripstxt);
- `trip_id` for [stop_times.txt](#stop_timestxt);
- `pathway_id` for [pathways.txt](#pathwaystxt);
- `level_id` for [levels.txt](#levelstxt);
- `attribution_id` for [attributions.txt](#attributionstxt).

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_id` for those tables:

- `service_id` for [calendar.txt](#calendartxt);
- `service_id` for [calendar_dates.txt](#calendar_datestxt);
- `fare_id` for [fare_attributes.txt](#fare_attributestxt);
- `fare_id` for [fare_rules.txt](#fare_rulestxt);
- `shape_id` for [shapes.txt](#shapestxt);
- `trip_id` for [frequencies.txt](#frequenciestxt);
- `from_stop_id` for `transfers.txt`.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `field_value` is empty. | +| `record_id` | Foreign ID | **Conditionally Required** | Defines the record that corresponds to the field to be translated. The value in `record_id` must be the first or only field of a table's primary key, as defined in the primary key attribute for each table and below:

- `agency_id` for [agency.txt](#agencytxt)
- `stop_id` for [stops.txt](#stopstxt);
- `route_id` for [routes.txt](#routestxt);
- `trip_id` for [trips.txt](#tripstxt);
- `trip_id` for [stop_times.txt](#stop_timestxt);
- `pathway_id` for [pathways.txt](#pathwaystxt);
- `level_id` for [levels.txt](#levelstxt);
- `attribution_id` for [attributions.txt](#attributionstxt).

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_id` for those tables:

- `service_id` for [calendar.txt](#calendartxt);
- `service_id` for [calendar_dates.txt](#calendar_datestxt);
- `fare_id` for [fare_attributes.txt](#fare_attributestxt);
- `fare_id` for [fare_rules.txt](#fare_rulestxt);
- `shape_id` for [shapes.txt](#shapestxt);
- `trip_id` for [frequencies.txt](#frequenciestxt);
- `from_stop_id` for `transfers.txt`.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `field_value` is empty. | | `record_sub_id` | Foreign ID | **Conditionally Required** | Helps the record that contains the field to be translated when the table doesn’t have a unique ID. Therefore, the value in `record_sub_id` is the secondary ID of the table, as defined by the table below:

- None for [agency.txt](#agencytxt);
- None for [stops.txt](#stopstxt);
- None for [routes.txt](#routestxt);
- None for [trips.txt](#tripstxt);
- `stop_sequence` for [stop_times.txt](#stop_timestxt);
- None for [pathways.txt](#pathwaystxt);
- None for [levels.txt](#levelstxt);
- None for [attributions.txt](#attributionstxt).

Fields in tables not defined above should not be translated. However producers sometimes add extra fields that are outside the official specification and these unofficial fields may be translated. Below is the recommended way to use `record_sub_id` for those tables:

- None for [calendar.txt](#calendartxt);
- `date` for [calendar_dates.txt](#calendar_datestxt);
- None for [fare_attributes.txt](#fare_attributestxt);
- `route_id` for [fare_rules.txt](#fare_rulestxt);
- None for [shapes.txt](#shapestxt);
- `start_time` for [frequencies.txt](#frequenciestxt);
- `to_stop_id` for [transfers.txt](#transferstxt).

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `field_value` is defined.
- **Required** if `table_name=stop_times` and `record_id` is defined. | | `field_value` | Text or URL or Email or Phone number | **Conditionally Required** | Instead of defining which record should be translated by using `record_id` and `record_sub_id`, this field can be used to define the value which should be translated. When used, the translation will be applied when the fields identified by `table_name` and `field_name` contains the exact same value defined in field_value.

The field must have **exactly** the value defined in `field_value`. If only a subset of the value matches `field_value`, the translation won’t be applied.

If two translation rules match the same record (one with `field_value`, and the other one with `record_id`), the rule with `record_id` takes precedence.

Conditionally Required:
- **Forbidden** if `table_name` is `feed_info`.
- **Forbidden** if `record_id` is defined.
- **Required** if `record_id` is empty. | From 7cd3c639975b5f240c5870c1d0b0a068a73967e8 Mon Sep 17 00:00:00 2001 From: Guillaume Campagna Date: Mon, 11 Mar 2024 10:26:09 -0400 Subject: [PATCH 06/16] GTFS Trip-Modifications (#403) * Add Trip-Modification, make shape non-experimental Fix typo Add images Update image width Add newlines Add newlines Update images Italic for image description Update SLO travel_time_to_stop is optional Proto : all feild optional Add references to GTFS-Static * Create a page for TripModifications entities for consistency with TU and VP * Clarify providing TUs for modified trips and ReplacementStop time interpolation Less strong requirement to interpolate * Fix first_stop_reference.png not having the right image + optimize image size. * Fix optional/require for Stop message * Clarify behaviour and linkage to TripUpdates * Apply Modification clarification proposed changes Co-authored-by: Paul Swartz * Use ModifiedTripSelector instead of concatenation of IDs Update langage Update namign * Add details on behavior when is provided * Remove modifications_id * Fix after comments from @bdferris-v2 * Add note about producer needed the two versions of trip updates * Fix bad relationship mentionned, + force no other entity when using ModifiedTripSelector * Changes after Jan 10 call * Add experimental notices * Remove mention of stop pattern * Use stop selector instead of stop sequence only * Update to end_stop_selector * Update proto with start/end stop selector * Add selected trips * Update reference with SelectedTrips * Update trip modif doc * Add last_modified_time * Add missing start_times in pb * Fix typos, fix description of selected trips * Fix typos Co-authored-by: Nicholas Paun * Update reference for clarity * Clarify and remove duplicated information * Consistancy * Revert correctly shape experimental * Editorial, formatting clarifications * Apply suggestions from @sam-hickey-ibigroup Co-authored-by: Sam Hickey * Update documentation images with new fields, add source files * Clarifies behavior of propagated_modification_delay when no stop_time is cancelled * Remove extra word * Sync .proto and reference files --------- Co-authored-by: Nicholas Paun Co-authored-by: Paul Swartz Co-authored-by: Nicholas Paun Co-authored-by: Joshua Fabian Co-authored-by: Sam Hickey --- gtfs-realtime/proto/gtfs-realtime.proto | 156 ++ gtfs-realtime/spec/en/README.md | 1 + gtfs-realtime/spec/en/feed-entities.md | 12 + gtfs-realtime/spec/en/images/README.md | 5 + .../en/images/first_stop_reference.excalidraw | 569 ++++++ .../spec/en/images/first_stop_reference.png | Bin 0 -> 35767 bytes .../en/images/propagated_delay.excalidraw | 893 +++++++++ .../spec/en/images/propagated_delay.png | Bin 0 -> 45288 bytes .../en/images/trip_modification.excalidraw | 1629 +++++++++++++++++ .../spec/en/images/trip_modification.png | Bin 0 -> 102217 bytes gtfs-realtime/spec/en/reference.md | 130 +- gtfs-realtime/spec/en/trip-modifications.md | 60 + 12 files changed, 3453 insertions(+), 2 deletions(-) create mode 100644 gtfs-realtime/spec/en/images/README.md create mode 100644 gtfs-realtime/spec/en/images/first_stop_reference.excalidraw create mode 100644 gtfs-realtime/spec/en/images/first_stop_reference.png create mode 100644 gtfs-realtime/spec/en/images/propagated_delay.excalidraw create mode 100644 gtfs-realtime/spec/en/images/propagated_delay.png create mode 100644 gtfs-realtime/spec/en/images/trip_modification.excalidraw create mode 100644 gtfs-realtime/spec/en/images/trip_modification.png create mode 100644 gtfs-realtime/spec/en/trip-modifications.md diff --git a/gtfs-realtime/proto/gtfs-realtime.proto b/gtfs-realtime/proto/gtfs-realtime.proto index bcd7d882..d3cfe529 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 cca1c6b5..9fde0b9d 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 a5affaf4..f7ca62e9 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 00000000..a0bac25a --- /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 00000000..bf5f9bb9 --- /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 0000000000000000000000000000000000000000..72442ebbcfe3619b1910e6ae74e62ebd6aed8bd7 GIT binary patch literal 35767 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
  • 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 literal 0 HcmV?d00001 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 00000000..8437fa01 --- /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 0000000000000000000000000000000000000000..5498d8e091d36bfb5ead8d9fe643c5d2ccfc9ea2 GIT binary patch literal 45288 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Ξ|4lVP>7FYq)QEtL+kJkp8i1P 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 literal 0 HcmV?d00001 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 00000000..d3497ce1 --- /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 0000000000000000000000000000000000000000..3d57181b6817a3ac4e8a66d3f0d3b673a7b1f415 GIT binary patch literal 102217 zcmeFYbx>Sg*Dpvy2myiyCqRHS1PE>cf_vj0oZ#-RNeI%o6Fj)n!5xCTySvj6T$`RI z$@6~CcWbI*RbQgM59F#8#P4dL;3Xb$y3??SM<=+x>YKN_=+UxoX9o&KC&Xdc-po(rCJdH%6f?4tt z?jw>@73JxXo~vwby)K$uVjg64MqIK#G9w5ApCBwE8mcqO-|u8bGA)xIUt|E;E?vlq zpj{$S!N$cd!1a2SJGvVP}V&@0<5t)em7~ zP61Eqi}>?`qRf7r5UuU{4pSYgI)}%@R|ku$-XiNJjA7yOKIg5^JiDgbLk8Y|7nCGe zCrekUwo-l z-K9r|+wwX5I&@`?7mL?!xw+atM5#&ly)4TI6>y{2<>uzKkIC;j1=FkO8Eol#->x`% zo`5x+t)|QBLA|tWu>5jUp*+#k6`{XuW{V>Hni$e1!MR)A6!C6fzbJ}UZqjQOX!9x3 z33)CF!vA~Ur`Tr*HxgX}zQaCRViU6hdrROR@n-}~QtY2c`Nb0_Q)zggZs&Wa_*B>D z2vih08hMSSNa!GD`JXRdJ1_cWz32iTer5@4&afX;DVumK3EFDUs!?&v=6MZ$#13=i zHTmQB2ylLWa1?Y=KN&t6s?gBY5{VLSp_py@~g( z>PH(<$)1Bn1N-v+$S`qBFtG>wcF3hqq*VdUQmSnpeZ1K|X_-K@%9zE=4Y+6M%A3+O z&@Nv0A!4U-(`6Q#?KN1LM>l~Z7*Ve`9qqgO=0Y)p7Y>ZVzTT zW)lXq_?UrpKeinCQgM!rwx+uOK5q?m{Z*f)wuF1SRl#XmY6V^W0kXVkL&W5uja2c4 z=B`0j0?|6$->arduBWrI_AzpPrGV*u=zsP|4h&>m% zzmn1^B{szFT$UzRtxI2$+NqbZJELC@>*!)KX-d*6ev06~ij@@E6m9ld<&6*zlb1;p z{Ik@9g?~kGg?lXhfNc~Iu8TNc{@`623Ebn)JMJEb?wl#_!E)n`3ojI4H63eH0!jD~ot&$=K&gWbQiw;}ocZ`N;(3JZ z99RVfR|c3(3ObPIYvEe1-D%rm1SpxXvGcG{Rh2`I7&TMO9$zGkqmMJ{M%U^qW&R}h z{zW^wx5K)A5}1HFi;@b>diuwVuKCyGVca(bVEgv;5$_OC1trB zX^+*&$d-6(wkXLu{eecgWqoLf=IWph@NAeXf;izw;P5o5WY;`v0nk#)TTshUQ!Pz8 zMmC>jNS}$X1l)j)4jTZog zyp2&FzdsGofLq~IVP(4bCL^%MXx5Ox3ur_Ry_N#WIb#qdY>aX8u0pdW|E;b1+tla7 z4d?Pp*qr$#u8mS}ZK}X4uGtee!KhXTECjSsY_7W`#OcGdqxCZmro?ACw-|R9{!h+} z$HPVSeBU^%=7?VCGU@|yljn_SzUHQ~|IRz$Y{Q{OMpiyTUdFrvdcSIKO)@?zFgM3L zHpAgmZm1wzNtb-vPwW{&;!#;8BPXkFqH1a(c3W1?i9{2KrUeJ2i6uJL+ll+or%lOI z^hc@P7BzrrE4gByOUX&CKsv4t_2MuFJv^Q2HT~VOplGg3f);$WGoaaO$SvyG+HK;Z zyF6sT+dyK-aNdDzHVOJG-ip*_h)E~ZyNN7X)3(vw%rQRIF+0CgUFEyJ;h_>G!}q4A ze6jAyI0Zvesv2p-RommO2g)xBy&Oi?G2Q}#f63g=TS^SPtVqaKT;?~sL%Sax76MiR z%I4%G!3WHz$bU=)kE>@GVU`i`n9~%Ty7eajyROY9D%Dd8 zfKszrgi^V&wu&OIBrqGM=$7lfJ^F^NTTMJwY9%^YYug=|Juy|g18b@^$iDuIlkokQ zwh%?4FW%<%(YBepWdd{1(ZbkdKE~1nSMwn{HdW`jZW7mF(JBgg*EBuP0nx!&F&xI{ zUcgs`!(N31Up>S8J4rR??QVSkr_ngGs*_$?yc`lLD5l`+EoYi7ci@?taE?7z9MpU5 zLctSI?PjU_NAYln`^38}M{|#2mmOQ3cq(mu=%h=6Tfn9}+MAX!3VN{#aczt{yaO^^ zvFqWEnIV!4D@d~se;r*<|A6AH#F=?s)eP~_M_pjFBf`=A{ z+rED(_1I}DL)?9LvJnOQMTZ0MUXziQ3Uyf08Lwy5u zaah;fsb7dxhk&BhIg;>|b-!Cnzjz zt8U#=F_xp08W`$KES17In|xtrRX*2{_BdP8!i89cGKyy5JS`HfX6jrkXQ$c1d?g5D z#oKaGf{NFfM#rBGbY}Kf#lZe}O~h(f@QBh+;m_oc+gJ-;@oyr&9=1H_^*!|Mu4p)A zPqTkMOfw7_8h%K&-FFlC zNkmJEC=iaS)rRw-wLNuggP}?!c->EYx~!#Ib44c^plpwy^H$Qt7aHN#UrB+A``<$s z8pHP0$k{3i3oLgmF>m_qRW)%tvM|?#YLzIVEg0a_7N_OUu=0+F!VpgIT__lury|4G zQK=WsHd$-n?qFpTV~-_fd9Qa|m-qMx7m%|4P!jA1T8QX`6QR8Nl=C&@+W zQ5qj`6WFy12bIt1iqOmV66m2aJ8utp==SsEyFHqrr$vE~Ko{3cEw1djLW1F|_5Q%{ zxT;;Pl0sN)&y*XjWo1+}sh&6US{a1fq`Dw*etq7t`TCa-xIbEX9`7&Pne`Ws#3}@Q zIfr~QJ<6ryU(dP({b3#fUg_K=R7S{|8y+2>Tm%dWvFVx5zqY>4f;d(#M{K{C%$c1L zd=!z0tdg;*AypN@JIQS%pgxpQWxWp_E|sQQkFnU=g4wHZURu@^X0J^x%rV~bI!f4w zlyVnjtA0)?)h?fmdH&b^=-v@O{`uxDrq@Y0a}JVjHBkM%U_7Cc!+(T<|LZ{?|Ij~+ z!_Obq|A+qJ8h-x3_+NUcJ^rEp=~F)lphW(G>^1>;foeYyeXBi#o27fn*;B3HuRb2w z6YBG{b{vvEs+BlS;ycIg)$vzVei5@Jtju1%uMBgFXjkXA=6`7+5l)R|%R%`@vras1w zO5voQ&33f3qeuzYXHPw)s7U$#CTj3K@d+lcocZf$G16`{D=lL#^~aI+whYL{_abv> z0hLW4-^V}J%;i6}fm=fo6s&g0ijgS`GPw6jPqn)WrjY{OQT<~ZxQzM~*`lly6JTc9uy`XgK^AjCLw(d<|azGi_j^UL>vaa^B>Wb$RGgsQ#qA^*9S*cBiO^EA=A~!YH zwz3!zE(sI)xfc0lI+vDrXeP$FdAAnC^A$iEiLN0nV0MfJ=*BXc$DyCsq0i}2mX7y$ zjIv__jyaKY=IEi%3+9GwL>jG1{&t2`M~8p<6L5b~qLga#txH|^p#>)#h!tJtZ%f7d{( zI2ryy)+G(FC4Xu1zO0&`(%r*?CsHRW+Qx@=Ew5&8>LB6(da_A#sFV4Aow1-XhFB54e%U9lCGKWrLAcx?Ys&#iF~C+ctUm1PCu90?*R%jwAxSFK^ho z?^mc9qE6CQZ2s0r4nJ>ym&GO{@)S z$PGkCH)7D!x?<4wi#!N50rJZ^ip95XdDus~@Ln;0U5?;DK`HZj`-4O&p**F(dih{K zBWw%ih`8X%JPrZ$J1m3Sr5Rs4{mHvAG7aOGqQjMLgJgR91y>{cC7X?B;ig~GJauLi z!QJ9_2UBU~^{@UrlbJ~*yr%he?X&0mD`1;T*gbT`_An(am1#m0CdZfJ_GPNGdLV#ovN#LC)vBsMpm1Aj)P z4$udq(EOYht*J*F70?IrB5i;La><6tKXLwV9wP18^)>zQFlWeoFLUcWtc54L;FSos zgs-(B^s~`q^A)P670^ie^8vxq6b6e&%d)a&f>VG01--Ld1vfB~HmbCcq3Q=WZ5|6n z*1e!o?+w=ZoB30JX-HkTF09esTyDTc*Wy5rJRhAe^UyIYkS$It|5v9^T=@H>!mW;% z5MpCY#gr*^?>@Hh#p3|JMuw6eADckPV^ddWRM>sk(76gERxX2;cH3aj_NO|~h(IDj zP(3GOjMDU6_5ASa`+u{7QIS@P^?0RYDAdBiX&_g^Lv~qj-smMR=1i&~rEgh}JTUv- zkgd=TL+>~nss@t#MH`ij{vPB02E(&-bZCjFX*5=R##S{f+ma357TT(lfHY@;zi20B zbX_c_H_V*6&(wfPZ6HZyQN!@9zq;Jedg{khwI=8o&YHfY&t#sR)twSX{Cw`Z%-3Dt zOTWiwQho9}>9>QLRCm0?*dBbJuuF7eWPjfw)Dp*Lp+6z-AvV%R?Y*Cv8em(4odyWqNQOvdtc8VT66Q3o*E22h;1zHR00_~@aZJSlEMF9+f_3eD zd`j*XpTS*f?{jEKU$nNl-cPQ-&;<{fuK*`(XVpyO*BznfUX zIl-eNBH*Y})&N=ab2iXMdDIrvN(?S&%H!^kTkvij!nSO<5-x8{*7Zi{4YR1i!WSIY zqg&kei}OT}3Ha8$`cM+ymp&Ia4=yjNll&cut#!0o zl&X(+zfk%3B&W~6oyD?vsWN2HQn(bOe~0E_92+u&Y2Cn`S4dh`k%nU~O$I^R)D3RZ ztCz`hzNI^#qs$t58>s>+)dfs|^Nbe@%2Q7iI7d>?AgBjA~HOV7S(s7&# zrp@xmJ;xA~DLwr--F`9k#EquOUx0lmqJpM2b((G*qlRL6xx1 z#Hf_{%&6$RjOkY5lJ3(<78w!nrz(vhU-5czdr$GQi)(cW+Aw%*4}TfvkgA!y>bj-w zVveg)NTI5(SQU*J1`j?E%5i12X)Rq?x}v?37~38WeA^bb4eE>R zuM||nLc3h5Xh|#%U)t=d40cOuT}paJ=tf02U4*-wn+M*NrQMe;eJ*Pj>ZDjlZ1=e2 zV|iaFZW@!du59?i!kL4Qg`1B94x8IrK$S{|1p9YBmjliE@~B@MjuX+J#l^KL zHd^P_lFpbnFE-ynD>U_c{=5IiH`Ym2(On?mIZ4+*daR_%*vA%CP$*c(sB$_Sqh5F?O4XOjPXWD(LE<+Luz71Sqcl6bYd=DN( z4h!k4+u{T`Ec#n>=l3zJ%N{4O^~M)M2WDTxZt(%IRjpdsKHIA_J=Y+5?ABZ@F zD+BZK(s)OJ&F68ai8#A;`D@*d_1=0-ZEjg(T%J}!b5*}yZZYA{Ey?x<2OLh`FE!XolkXL zcd#c3XU&m)9rHYb%#mp!xRY*gvh1$qAWp`ndjb#{2$XGX$y(YU*XkX3qr>b+E{pcx;7907r~%3hpiP4ip6h5N@v=ne10&HiZtNQ$o< zQJ}fgr>L8B1AU19KRVl?E4(0&WPV5@qTJ(g%nf}_W!4rxN{*3fx=-Ei4U{}I?1jm- zW%X@ z7iG##)f=ebJuB2I!8nE!ECLFrfmPuCN;!859`VW*B~HIjU_dA*PrKjfgGZee+kXek z!L%o;C@<^wcH7l0-aB6f!$@zsRprT#LyOY69R}GX!0u|};kuV8N--TIx+C;g*~z*x z_16Fn{v-{BF^lC9AVz~ltC~4&*yA@^W=xzGLBy2)n9`+9LfeR&vORV|Tdoh&bC{xI@vEhnWDdZS%d zWHxET(MhLK12*!O-0d0}lU?;F(77LaWZkQLd@nQ^rD79OI!C5l#a8N}-e{9&vi#AS zMw!G##hKz9IeMQ;Sq0CYb8O&zl4Y&Fw4Z$GcH@0b=zROaJ4e)`_Rtkt z&Dt#Kdx#v!GAleR?gS~PqPfDp%k-5ZSX`LqSJ+HU@YqUc`sv| zLyUfr5S}lL!a+h1C-#o3ns7NFiKngEF*Uv2)ahFJJmP+OTUVasE`O&l=qR?Q8Y_iG zxY;MJgd(|<Fl>@$swE#}A4_G#4gg(TrE_>2h z<6uNpq_y|{N<8uv90C(f4BMTqDkZGzp?l`JW_IGN8DHf+UvcL_-~|sVMqXDJ{Zhmk z+!vvVxYhwar^H|uKNkvCGNF=ChNZr#W>HT1vGGxS{$PqpW^1_LLB4KqWLE4ut}Oxj zbgWn+nJn((;U(&1B9ao5@e#`f6XrWAb{$ap$8&$SH7)>gzO7;h$$2s_godt0X{I>d zPiR5k?k~Q;>wSgu2u-v?U7+`#3Uv;_CD1JNN)9B)g`7Ob>rI+(Z8%hAom8Eu=pMgU z$#Y6qsUCSO^zqZ4W+ieoYF%YUIOC)m+Ah!eq?sxBq9l#Y;!vIzv zRQN@|o|~@flUw3#6(Z1SGS?;n?{BRa6WZ)gX;gj!+Bhl0FLC9dXIB2$dbykHRC}l> zkmGq!^3I%TiJqZ~>??-iFGG>mid@kP?0t80mUFawrgK=CDKa6#Vykg8 zni_-tOG4JS+!d2K-bn9d_d3ki+LP-m@S)r;_cvqT6dl-xIqqT0P#8Y zm}M2Jao<_920GJBrA=9fcG1x9bP*hb6fnC}mQaG-^+1bB)I4*X6MlvzuBvb3a0Ds9@OmMab%b5MpU~;^G_PRiAFugsMz-Di(TfkWk!DcEL^DHtrwzYq=UGp( zc~f|fAaP~QxyAXpS*pZ7&lkW1dXBpEVt5$4oiW?ZIqIb!&f_?Vo?1^KCbGyM>A5Tv zPjA}i9*571H_fs!X#}qm?K*GH*{OA2rXDa`Mc=YG0vO3(HqjfN;9_8ABfE_T0SW}O;TKo@vIr%-Pw=2 zAMy!F@tC*v(`|Gg2P?_s)3H`9HX8?QF&8af1dk`Nw5JhK$mP;T@Qb4i&oS`HAL_7H zDyvySalA%wGw^CANCbvx9hZrBW2!G)c-j9JtPdXr=mSBNeGZ#P7XBmOXh$y}-HJy5 zj0Pj$IWO^gKt~tR&Vzy3*&2}2Tsr?jXC?Q3=cX;@xbRS#1I6UFUFcyQ=miioX3;Mr ze>dQH`%RtOxD!1cCyayta&~p($=_NAUW0z31y~&JHahOV)#zaJ0IJL`dEFgMt18|g zhOnY0Ss2ot= z15BB21o^}u+wrP;8dGy0CYOrW5;yj6U~OmhL-4mDKTQU03r7QwyIB`2ysIaS^J$aS zkm9O2U$UL5PBJBLkq(506}{Ddam2*CyX!p5FQ-H~{?xuMY_iD@TELOxYMX4m;89x8 z&>n^Iw_JVb`8onC1*kOP@6VWlKqGC&(}mA?oDDi`4+c%q!CGZJ@4k3D7DB)X{XklH z*ZwV}akX3yPc@e^PDG9o)9hb+X6i=Do*KxXuGy7r8KG6(%f5oOfdJ^2l|oPo&Rptpf>|OM;GB_(rkm z^tcVW`W@PhN0%(Zea(SRTLbbjzE<_PCq7NVH z@uR%>i`{Uy6^z6o@|_zgI9)p2s|k(8DM%eWTZ8g$S+v*LuQQb^CgV{y=DkK zQ}9)k{s?!9jHCEmk7l$PdOk=z+2F?nvheRlDP=2*>M2uJGSB<0i{l5^s96Bf-(8e=ey>r zyZEZDi>3^6H$EvvBYsyB804(0k3m8I z5G^)#V%x>fa1@qjC<>J00^C#F{0ppOdIB?k-!dxms=gP|<~7~RSq`4(28W#Im|BLE z7oIT3KP`}QIxY!nBOx^uiI4(55eRaPV+pVUPVlh4;tGqW2Gma~Fw-eF0fkD&A5={zIW)r{)n^SII;ZJHGqltn2X)F-7IG^PxLCQ|FWgsGG@d~El23+ zY^gXIXEop%AGyNh^HnR^+MhJo{~={c%JMk~8`|l*BU=xr2etT|1oCl8lgsy_#+s7+ zBJP^3k1WvzjT1izdsViX#8|l$t8pSdQP#Ca4hMGCrlLr8Z^5|-^|3!Tg%55jqF_9D z7t_Tn0@=4Po=IfPeP6<(3kYEzSc3Fc>FT2>H96+o=|@=V(dl9U!U{wDIoMU}6u9l% zxY41fXLly=hToEOE`C|{=E_Y*DRZ0yX>XQ$F4k-?Ld8RJ!w{|s$?j8$#6*sZZl)p^OhK{`1v5L06 zGPqjZj>T!3E%zxPT4|A~7wo2@{D*QyMV}Ee_bzkYe(5&gbiDGITcVe8%WOKeEinOzH|?AI8iG!wg@oqj|Xz-v6Bdejiv*Env;rj$5cSK>ZtKzHiJT?(Vs z>?tFQiS4ndp}j`OH(+)KW@}A<`A}M1V_i4NJV75n@Bv1U>9)jMR9W5rgfw*6eHYZS zHsf$qd?$97{;XTDOkLdgP(a?ldE-jY*)r{Q=mm?-6Vu2|{d2icR0XM`o+$7=3zhyR z?dX?9Y8XU-sBtHqC@r*niEUqz9Teb5kKB*$Dm>bl-GjBRxXc3^x);fW{iIw?%LdvXh z$vezT-fNfi_|1;)n`M~VF#5OE*YVmmZ`#2<>Z53iTma!mSemCOaoox0MTNh1e^#lm zF^(MnvnhjuXt75V=Y**RBec`e_599=p|iek9bueL!{XwzD0ON7Grj+V7iw7_spb9dmdBcgdn)=*X%=%0zYZ z;|oNejo~KCM5PS4k0%@nIRx~onr+1|>ISx|U*TjMV;XzzuwFXkwG{YKwxooxbk-hV~SLg3YaNe3>P2OO+Ak6}I1^yM1vq-B9A5bvwu9UhElSjEE|` zbXbKF*0Kbt*lgn0T0Uw(AGhZ}Xn9c)!dyn4fwV>FO>HEQ*5b>5FhbCdNmV0=^fc{c zor2ed)SG7N+S8sVt9=%K$}-Q`aacuMScww1nJ`=Q6MLJRVC>p#$&UC>U*o~i`4Rrl;>7X%9)tgM}n=9ho&tg`=K~Rle(||vt?KSl$5Bw zEp(=6VZ*X$ct7rZGnE&YY1x@syU<BAyrzWUyMxWsu>k6+wFKHl?yO)lrF&> zO};a?Pj)%X!ekrlhFYY~xm9&O-6;_YHxXD&I9cZXU^@HGf3Pm(X=k{}YfqhTMGrB@ zi`E66RlM%6%0-QBE*QQWj6bhcuSRxx!8r0Cb%;J->9a@T{gS?No_shMPUiFn7Q(-% z$Pm9R_zCgn*VWBxI~Qb}`Dl>_T&i3+>wg+?9F(KpGWo@4h9B5R6N=WiZ}yXG9=&MI zqy!DH$Z(|s)sMJI?V^n;Zld3@62>?qzc@$={RsahKz{dLVb~3Av9a!#$B(tlFj_8C zKPSU%i7_01zix!rp@b?mf65bh8TqGz`;PMn{`XMaz|a3rE}hyJsAdk@B>zs!;ZM=q z-w0r~NYv>OZ~m@`{?>t?fPWI8|6RtvG9mo$HvX?J-~Y$;|C;Zw<$pWDzs>qT`}+Sb z?(;wL@&CKgZ?E{j>_Yu&G*Z<^2wxDMACPMxF(dK|9HGAbiD38lQ=tD@)b^Ey#3U~TV49QY^sLHNem|6 zhK0eH!iLPpKgiolGBdMmX?{DAue=RmBmqy~uAbqMr?hO1-wwd8d#2wuRH+@P_A8|O zXzuXp25{{_-MacPkJzE7{etw#3$>tG^D=cIJnj~WcLFvQcMFs0+V%JS+bPrFpvzwC zq8Adxa3u@=38bGII}9W7U9JPbMy!>2$KFAyGk(#fTcicihi+XylOr2fX`FG_BR1-( z6?=x@XeWEohZqiTTs)9&{O!!J41nE}$V5X?Si(elaA`f~mf;>kMmpxLXLFR?hb9$2 z%d+8XrDU`?N0M?W_Jl^)rtg2Ex1h-XGhURq03dIA>KOAF$98N?}R>9)Hp> zVG-7$Ace*0#dDR#H+5FeU#XX;y6xG)9A6wS zgm$=+3RrdeoB6(+*O68sm~r}0=ZQ9TBS198I34ZRA1^HQk>25z+l^#J&*ldOZL}kA zD@|d_7*3{cFp{mW*L`pMRcqu_#2|TtfvXNyCg?NSxNWBw{2P(XPJwDtKEjvD7zgD9 zw@2cx=;xoQ6m5Pc&*|8v=F3)7O|A-ew8RfpKXRi+LYB|B2Aa*#BEi{)^PY`^0zVie zhM}{j;{_f>0yhNqO>~73Y3Fr!<*!bg$j5L7U+Sz(Wg%-aB?awEEg>5Bx})%x2fSz- z7yaq&5;Yy)nBHQ`ZFyQ4oJ#P)l^cyPGA$a*izh9i>lMpsv z;BbnSI?uHhV!D+wE6b&7t3>^B9El(gZQR<uogd0+Exav-OsOnOBfMMyS{8$p5Ao1MM|No6s-^=kd&NbED@p`?M2(> zUpgfV0B}uwe|K^}4U?ve5qrMqKwT~z-7^M-x7VNWSNi=WL*+?rjDZSh#`mUa^_N8b3M+@UGQK6X@M_=vlvT zab5L&@h<~J0$=kUn`Gm(ZuvD_kG;HfSX(h=(iy=S#MfCl+k<~h1z?T9KQ*ZHz37qK zRJKhSgKaY0A99s#`5D5$O>Q|y)H(WD9D?dRv3^1%rZ&Oy;_I()p{b?O<1OUv&|tmA z4U*Y!7{@si*y_$Y5ShON74fVhfEMEFkGE zWRtTA0%G!2vZ?)f6s&*U<&T1uK&*mvijLyaDs)jOYy#vd?_LKhWQtDPJm& zF}%BZn{KI9uq@fO(7?NF!DkDxTkkYYyT4yin^JbS!}M&`np@Tf;=~amzdMc#pjEuS zpu62pPl+S-VonI$0Io*;>`46Hf1;eB@o#VVGG@eGJ20&$5J^y5M#ZpA!mBhOy%+_1h@Mow_{&` z|6~1)A9nlHZAPM{HRQZz_N7*;l!wu&+?UH3-HjcNtu!0{E)mHZ${VdTt3D>z&%D=i zH;wdXkPosou-wysn9qhA21eUrr0p4Uy(O#8b?Q8g0lNE5E`9xLH|%sQ@n zC>2AUFc?2URspirYnwN%k0NSgpE-oydA}k~+s{i$m|T3Uk8j1~ z6-~_IC!Bpvqpvw>v9U@}zd(8-gl62c$mjTmk1t`UkHPtZax^e)_`>67*Dp0pEa#JW zPR!R%)E;YkoZ^~^4f#z?>$1``3_bp=GgqW} zAA?|-W*pRMSJG55KKP{PU5)~|xB5Uu)H2Be-MdD=wxV8!ApR^)@nVLoX!#|3z4;r9 z6wi03a21EF0l12usoWh7sN_fBqje_>p=F4(rLU0TJZUlAVouIV;J@a={f_n7?6@c@ zbtcL5@&xjkp=YMY4J00yR6OyGqd7|ATOCfKY1Xtlvjnayom1Mh%t6d55@oo@Jl#Zs zt8+czNFx_ZEv>l+Q7np!v9PDhmikSVm|BWqQCKl|BU1+1qTy+`rtfs{?i8#jigX>t z!#mm13L)CX&_p4~=_ACQ{#A3%57}nM1p%6~OynM}wdBy$VG~jf7i{?=$WH%=HJ`_; zOLaoAL`-UjXlCCmZ-#~y1aY5?;dahf_v5giDN)asgdV^|_*sD{JTi+`__0Sl70Xwz zv!lC4ojNKhIfmuCE}N?sS?TdZB9Ps%-wY+b`mwo4@Yc4sJ#dCIKr)fQ=gNs^w(q{d zPc!YEFSSTqP&$JTWqz*eZ`EOD?)kf1YlD%!zeQi( zekHzNUhk%o9j7D*#MMjXeo9LB687}EuYJyhg+BaLo3E^9(mI4ZILlOiUiW2vPfR7p zh+EvwO)u2y^%S)A5m$#66`0`37S{2$J)acs@v63;=Q}^>R&-UbC$*Y^yI0( zH!X?r?TvgyiN*-0%`)*-HbgqEZUYf&<#xMK{1~VXkeK>$kAYFB2p}JI=>-DXzGPm3 zg2t)%C(Yu51~8lXF83bK>i8gVGV_P@j8&s@R3i5!8CQvh&F7-mALxGY`x-0wUXnjv z78pRVqnf$la(mV~TPXT+V&HUn=8y-?ZoOs9u=nk}X!v&~=PP*5aBwLViiS;CHuFih ze~aDZslO!YRCP%u95F79g-gp~5DfMB@A<0RqcH#5O9FX5@AnZEkI)W)|=G|_fbLV*(*wbI|PdBYng?>sqQy4vFV zE*rgC#0ZA9R4&WzQg)Pj+_%+kv^Qg?omqJ~NcNEvr7pl$!49D>(s~oCEK&q(_G$5a zO*^MzaQ8mB-VyAbA~Pd$1GZItN%|)OJqyzu90;%bfDOmxG7V3MqfjK@yH9L+_=#0o zvfOXv05^*}jAt_{bI1oX_geD3)q}c;zcvH%6~20W<{gck1Q?Od=4$0)3|N3PQIoti zH@te#$VkAW9hUOAkuM25^F7EON;V^a3r%7WAEQmF!O&hwudYCU{18=H* zzo&Z3h66D&Jl{MqBWM zpcYTDJ?=OKB8{k{z~?hP$Jn=Sg=~ zuBlQ==Y7*{nj^r>Mo#SZc#G9?xuJO2BKvhxkWDuHHO`Br+Ib?z(d69cKXmf_&AuQP z&**Fy?d2$uW0Fqzj30g+umAZ05InGla_(VSrWQi|wUSmBP_Cpd;M_&mtixL%Z@r;@ zmSN*MhcL#ZFn!0ke|aQGe?k;VJNO-o_EV-|2(!;;Og*hVw9lC@=5q_;=%tv;WvC9i ztzPW0G8+4z#54z-Y>?$|U-StB*5rNvtqF>_H^Zl&B9#x?Qa>5vVxM4OXE)A((aUEv zUSCu?K1KQD>*o!SeJc2tKe4cN_TIKoRK_3;7+bU~W}W!~U=Un#nwHou+(9J=5n=DM z1Knun=P9(IE}Je)i)0Du9cwVb^9tav0+@$8^wF#`o+&qvVRpp^ zIa|WA4~#U~-iSusbvUf!kldIBnd$LxyECO>=r$f_8TkUxs>m^|E!P8k#? z!0&t30@*IrTbve$v`Rb8Ll_+%LG|oHdyILChmDf?AFmb51x~>`DdalUh)_dh{wiZEU zkUemt(=~OuOB-zu$;gdV zr#_2TG$psxS!CrZ+F=fdpD-@Uo>hjiN#}d1zUN3g)ouZRCJnaaQsKF~!xs`)w|GYe z4(2J`fxQ|h?nyEvg8#xGyti9_L+dF7xtplgSFA^tP2~hk?z48jVbNPp5->=6_z%zIz z{6+ESTwn!9-pv|`lt7pYs8&#TmD(?H79&f~{H8Vrg`Q(i^_ zqANdFA=bi$b`8(YeKNP3&X@2l#EsoPcjk-26ZWhe>W)OI-a)5S@j_Al_3gsPsO)Qz zVJyfAmed!t8?pHNea{kU2lU&qztBbPUqJM8D7qAoqPTwco|=k?2%c-V_#zVtsF_w> z6-I2V7~uC$At7>yahbZ7>;ZVH) zD*9}Fjm9>eBIbFlDgRehpK_pRM_;qw7D10pIU861;n(7zxQ3eI#hNCCBJM`8!t2B9 zvz;!61&lztsRv1S0maOP?dlk#@(1 zkQmc1mrs?~{e*wa_N9f%ixY$#0WDUc?6a8tA%Ui{%u2&XJS%thvt90q0eavwJ=YKf zZ&bFKV(i}?gMZ*&umu#NoKuS9j+g;YK!WjJdD%p(Qo0$mz9V5XuqL`+x{!Y_Cfva! z;Z*qusy2W*jPg?9tq#iQ8*Qmy{Kq!*va$e8$i(CFTDxxZa_KWmIpG~bJbV%5%90(_ zRn&F*YDLK~`KyY0K`@SY)v_Ul!PwR&=cn%Ou@fwnVB2RYaKG%b`EVesEd0cHd1-2u znxtZPwxhw_nWVAUa&mR8KQ9R%=m_U~;lK0kX4tTA(4X$4npqBsZEM_$S~->0c>f1RS?={E1 zwQfcHg}6UCb_W;o`(49wH%|rA0s{$EcxFRroK^MxcxD9-G`o4&q8BD~XB)(FPbt<` zc3;`pD+dl|=<~b1|!${n9l-y-_{Q^;q@k6Ea zi;sF1BeF%Biv?bEd>PERTjh&-i+glK*6?EPLs}($YN$6?PMNTWK5S(;9@P_GbFF<4 z?L~oR-BdCp;=WW3ys&Hc&fO>IS5JFcP&~civE7|-8&`41uoDA>8?@W{B30s{(B+i0f!U=mhj9>XG$ zVfa7D`sV1!mhSCAoJ>5i?M$qRZQHi(iPN!dJDJ$FZQGdGUuW*UzxA&5)#{Z$x;y8b zs@i)$Pi-~XEG+)rPv|AI8{{Rj$px2q2rsVI9>Yk%t?IIbB3%k2K7My-)2jR3DFS03 z(6l+w6tTEf2@Ob7o7Y`0L2SA|qA6-k^scRt4N6w9zraCmDP1dpfS0-s!|eT!34!Mm zAw~o~a7F4Y3;vI%nyoX;O2p_EeqUeQBYRMrHxVU3nO?kfeAb82+=U6~j`Fy~50PP7 zwb;Ot;aWNI;d}O~Sn$JFgm8_`inXa{{b^W=sGDPdQp-EEtbXvv6lglDo?KX@j&LJu z-OR}YpGEH|jG&?<=v#sCH>z4PdHwL(RUVPX7N0FDL_CN|nm`^#!$j@#?hx6GMVtjhT zib!s%edYeW#kjDh@~vV5bM#K1hv!uf!j75Rr?Kxz51P7(meE22=S~hL6x>n?%&D@4 z55gg%=F`c&075bi-?};{umhGw7PnvgrVg*u5Bk3(pHmJ-+mORw}A;N)P$|Gne;4F3n1lD)k z(=)CC$?yZBNAbAMweY`K_m6LCd-t)14HfIBtPPZEb4?)J^-v+?kq=Rg)dp;Y@7Vy* zkx6BuZtsHoMut{_#o_!k+6R4vGpj%o5q!$)k%o-^$8NOzpjyM_3DHXERGbH09?5(E z7oGHP-*Dm|#NCnl9RA!;NOUzu-wLSE-ggl_Q;S1z-1L3d2JNihV10J`J>sn^_0E&%=k2Me4eWe=iy7Q$mKiHC{V_0!v9WFn z|LMj^6MN53hEWaYI{KdJ>Hf>{4Cq|Pnh^TAa^<@OZG_onakBK00BpIkFPQp{v6gnA zcX;&Nt}qZbPAi$-(?i_11=6I!3-qD`Gpv7MVf1*9B-?^Ymwki>K0Gn`=?DdX2G<7Q_F#&gUTt+98j{?g;+~UNv)2by|Dj2+ofFM@)1b( z2!)r8V|=7Ed-3XF2JlIPWj|*7>)wrt%k;suK{+=>-`zQdMfWtNZ^X%J-Tg)eB71LC zwh&6N(y3fNMg%x@ym!ivWbfJ}w&ULQYp038(0Xf_LT1CBKb7DO9387G1Jn-|&m{l@ zdf>M}Re>w|D@H)CyE&hMrF`9Uck`wEgx`YKl-|~IOgcCDVEkzVR)w81&v?X#Qya#@ zUW3f7z%xF^02pQY1p2Wbzv|qb!Zd4KI;T~O7lPVS6F9$dcdT+0Pdul--l?QQ(K=P! zj&0sq8b_{GSt|!aJ~)Xyn{2vvDDMyw_u=#NCrq?8jVDgsuFh??0I%8mH`PHfpLlQJ zrnT;TVQOIGsCE5N%lkZ`4!@(T*HJw8{!G|2CBVXxv+;gv{(FvjDSd@?F!?_#-1+sU z1;ZoJ6gQ;(SP~uU58BU-VxyY~$@q*Yzwa&e8VXx$hfvDr%NX0hCW{|3r88N*)O3?w zy+BLY?B5CkT!e`AQtNvQG&?0vzV}1+4)kfRUSKZ&hXieE3mn9|bG#xusP@6(SUfHi z7rc$FYYH_)8>)YL;~4#EYGibdBgMebE5$xKYGPE7l$@N*YZL{%q zx_rd6V#uUS%#uvHgfhI8Jfwo6mnVJlPis_lTIaOIdyK@!HcV!YL!~%DWVb?tFLL6G zL1C-FXi9f=NA;=Q_HPT?O4iiVkr8$dlo1k+d1emScgV;tKkRG7^gl6a*RdKl0v9zLtbig2?y1!qCk-g5s-wM3j(`5`0Xx;^}pTbl> zu1{=pSjSGRedBVN@*0tS#jO{sR7>|9f7wMM5yoNsX%o4=?zqhHUet8PVwOsbkv{a! z2XoDFOYJ?iY};_20sam4rNOIrdIqn;qqY0@)uPPiBhM4d)}{CDa~*Ys>#VGA zJ9RR9`czO2qanP$0cbE?i|OnweFLrh#>x|ilZ&%?cy$NVQeqj@>m*u`+(@qMZFlU*3W=wsr%y#e)1t&MV9iMPk|?-Vwhf~ z?V#CHghD}DRjdI9=bpypm7L-A59&A&j;u&K+0ke^F*rUkJ+P$6axdfan5nMnC>{dNSdYTFD zu`n)!KWEVnB-NPRur$47q`>3&5Lp9fms3c)QD);&xwDL*;;??d@cHywI0kkBiAJbe zhvG(o`$Sl(f2C>w zSKE2)U3PR`A~@^eD+;V*0U7byh!5ykLedL*_aE5o;`mYy{E{VfRX0NYgSNm)tEAUH z6qk`nR#0;q?N69Xac-x%KFHRCyvO?7CpU1WwC`&D+4(pWzcc7Kd}jKGxOJ*YjW?fBWm3g6L=aFsqnX32C5)qtvmG%*X2(MOsRwS&3a9 znZSX-X}eTBv>ghW&(eZctAjSs4z;RhRVVQn=N^09Fx&oxqOj8k&LFl}( za1EeBFSxU=LZZXSC4{%{yTGKpd2W^kjC8Q4Kt#jwA!D6sy|%GZiM88!026~5s0Pp% zC*r<)m*2hOGS+X!T+D0)!9Y5ro`VZ$zgNo(&H5inCT;m=opeZ>F2W%JCP`r1K1T{S z69n>}=O5}jRjz9dr8GS&Il1#_uzq1!WgDD}YEBQaW08RF<3P6WhFUpZ0ed!@JdOC9 zGz&~)2aafos;EPtuKQAfB<_h=Idz=mC2J@LK7g+^Odg-vG+vWv+go@LKJx5exrb9z zS~|ZCh+)2E{r-;dD9ZDIr+ElTgo{}@A+k)L`?iuaa8HtR>+~52CaSN(3|BqGf!b;H%JtZe{;>x%5xAp(lyFu|>L!JN3K>f?;NXi+7? zztj15hnw4@{%8zg8_#M%gwnBcsjbZ<%*!Ciq!`A3&rR73l6_wk5;pV2F`>l&#FGqR zCiBAvLKp5>s{Q7N07LDFsB{>q)b}}36TiTxjD_-v+*R<@Hxt{y?f3xP%ur~*vh(>h zKYvKs*az+Qy`n%KWK#mS8_P>(&ka>*HUh+@4zr8K_+rE_;*2-~5}|T=HFOyX$#mI! zO^@Y{nuLD;D~mZyu*&&P(rr;eoWLY} ze=lc|XP}L)q++1zD;>EH3fTTm_3{nJj}(`4<5K<*K3G*)SqT2f`?w&eXM58{^Ri{# zPUbzb?U>s#-WIk}HNEF?v&_bdwPzpg#H=CJaCa&B)-HF}3&sXL9rfmOhdt0m2avAXos zDm^I!@vrbE{bLTxK}C>>z&o?_=SaBicfrZZc-L*9jVH)-Hn0TY-hp{c{lD6^NOM-5 zK-36-tGxHf^T@nK*|bk`iEB&)J82!4$aC>PAqT^kI--qv9WPd&@fYhlqMNr zcVYL2aeDaecl7wyXAM@pk?L_2iM=7K3Mq3k=_2ZgGAf=Rejs&$Ipv-8IgsIILY^RH z@52stSVJ|7L!37V#8z+uH(^533YPT1a zzZEi749JMiE_k!@w>j(&%;plwfaln{Wf}>dm4X%6^#3gAvZJGdAcT^Q1;tPV|AsI6 z3W(`GYg4|MT?%MHZbFzQ%+q6?sB8;+vnuspF4Hcuh_gHfM7TD3NbJ%h1Q2#p9hqRL zL*BD}DE`0fBBwr^OMurWf2k;+75glLOXs~_-gWR2Z`dKhI_PP^Y-2|`%V+W6{7K}O z%vXO{wL{P#FukN>@0A{$)0oPc^~d0;>_nOjE$hkd0*2u_JoE__ z4M|xe`S10uK(^o}6hyMuu!G{Ni72{`e^uA#J1a94fTu)BF7szFs2eMqWP2jX^A?bb z)BKX%fMe$1Rq7@F%$TEc3>iz9gj7GZ0CVfw;%gx*6TrY5A5-Q9%Jq4&0saViUFJ|# zd1HYb{(q*W2K%tj1r~%iXEP`%1GpEo?NN_7j>N!yYmx{BBXXZyv#xq~Jh_JOxeHv( zPTJ=rm5c+?J)W>UnhCg8Ev$j=QFy!S$QF3!JEe=ojpt-u`n@iAB&!&JE~&VuNp0!p zX(CVZ3nV8Z+iQpe$}a^3y=#rkbr%zPDQmpUu?nu3C?r8E@nyqEz_n>$bfFbr*LPV`)i?;*9~p z-4uWJSBsq3u6!MS0hU}sHbCS8cEr=rdwIq0uIjr-Wi+K=ieZ{Y9_fTo)2LG%0|G+!Kvcz|1#(=nk zlwg7%}JLi{$4MYAaLFut94`7D3!Q7wxciuZ@*wrGvDovNCR8aDxy1fNcEg9F6uLOHF*QbV zQ)ouX%c9%avMHqH{H9&Q9u(n3pY|5eT>xZv_26o+GfJ*&a+GN{@UztDq1~~^V&E#Q zBL8EqZc|c{X-+I4sVDj(NWl&^#qZ%TaH8fiPW`~ZWypRZ@Gd6w-9If*t1pm`HVlAd z-QJa8dPqbHuI$>y}8_O}@zl0SWG;)1P|`_5AmnhuD3mn+ky+FYPt+ zui`0=H*rUFvr2k;@*b9Sl&~KKf&amf#;s?%$-M#alme9vr%{W`#7-0&wU6K9m!uzA zdC+lC_SiTSy@!T;BR(f-&+J5JrZp?$)3&oUWXo#?F+>y@`Ksq*V#p)k_;>-4TU!-C z+Le?PK+bC)VM8-7uJYO}3}&xxCQE2Y1jYY2WehZ5kw3~rhGPhC+7xc++*f2@Vbe83 zU#}9WqzP@EhombG&AwYfe~9hB+UCEV!-^qAPHlO+tn1Xk9ri93TRClU^g5@aVBHZWs(fv0U5yFz(bR zdR^2Eguvqs4{B$1#FZQIZ+cVh$wtc1c!g+sT`Mo?p$V?TL{!_pZP-trqT#5dX2!CO zG2sN521i5*b?7w}{bmx}G4T`qFk!$NqK}baq~k%v zPk`jssnZcR;(+$vF@{a(`cbxu691rrO(o?hgepdvgURTxB!QT6K! z9~3VNeQL>mrnib<22X7_>prpAW4}gWjk#1Qd-nk%`yW*!AzT=HfzYOw+dHcAll{bu zzzHDaGxGT?xPdF~xnwq`&Djn_j#mrqfgS!$V|$ zPN$mAN(VXv1iSt3lu*!Riyn9hk<4;qccRMn~t>de?*XMDxaN_65>L+zJ>qJvs*E ztRvw0Num=PbM4~g6ZF89`|(OxZh!Z!qPx&Dcg<(Gh{u;*5%WYm>)rP+#C0UQ+srM^ z>^0(`N1G6=<4nrhqUCs;|EiIa%w-nb5spQAbGza zPGKP294C|(gE?g`Jb)%>-LyQ3P*nzTWn!VBpcGK&^Sr3j)J5#Z6W1G)QhVT6`J8wgpW>D};`?pX#)VZ)89;URiREE# zr$}RjPl?cwaKAMxt#QNQA8kB&0#}CBRoS8wjORVmN^ou@ZEN407#r$ATYWAL+p$8j z1K+w|Asex02ILxPxS6=-Sy`41o+k4N$obaAmNd6 z1>^*VR7CUYI#!Q{HFa^F0*}s_k+&h0)cyCb0p_-p5?$k`OojCjrAP?N+{|~*x#tE3 zb{dW4CT2z$xK;f*HptFgCN?@gxKk7AX|1Nak?){~1t7{f4l%(7mSv^Vt=Y+r%f94O zVvU{qNfK9~h%f#1py%}Z!s;*bi_7E6&P8xy$Ae@-0RC`g32V`C8_(zqY{Ykqa_h9! z)tu>%spmPA1DdwuZAS&h<#U#n#13pOgxk|_AN@P(q?5pNJ1#G-v@08??~bzZ0RKop zIolcktL}GK6M`W0{m^ohr{wDGQYB-cC#PB5`F@%nKTKU4$i=Nh(DHm{fbQY%yP@)4 z(|j30iPRHWMu!$*r0sypgw6Min*G-W(?e&*Zb3YP7^Xbu_C9prv2XI#8b4DlxHFTH z&28owXzj^tk4S-Mg_sdwKU$-D8a#a4Sb8ml*)9m^UuW)DCx`E4eBOe7RcQR*EStob zAwy83NOgtPwX9^1XrsudH1?c$?a~mxvD6QEIzFZ7MsCb(5L?Tm?u#xJ6DN;v(-p1s zJWvjGw~GzP{KFS(Nembjlk+R;pDbFvlijLX~d&J_4YiNa{1Rw!ckyk{8I2ON_or>EFG8CJR5WsQ7#W3@F;K!A~%5mHLtEzt-h>MXB$ zPr3W`m|n6v6HRE+urx7|SDOz7-o{QxChGTy&iBji&340=OqT&S`zbis7flLt+Doh) zoHY^$0MY$L#k51*6fBIc4d_r7HdbF#M!&i-Xiwu?SUugJ{j-;76tY%VC@=57o#(q8 zuT^m0oPi++;BeM9>c69A01o^5q=HdNc`N=s8+=2f>HAUVmV-GBwh(<%_n9+Sp&3!b zr33?2=lvItaows>?&P0I?}J~V>xXA01++&L$IprTV~2m50^B_hhH;u8LOdW>?R zqy+J5aQvKFH;jcw6OfJAw*ey$XKvT`mD<3Bf$MbwJAGiwv~kj+l)Eelm!G*^gF0C-1~8A#h^oHg61W7_*IgH z6vU@AxSPKQ>~yH9mNhjvyA9*&Gk9Jw+b3r2-leCA2z2byetW!Vw}m$HzP6>yAA22_ z$2`94?o4r*9}ZHt5789cFPAh>%Dne8-n&W8?BH%05IBAFVP-A!g7&`pb0ht7CbcuM zE?gh;RUT#FtnlkXUN|xrv-V9(b80FaiFDWoR|Fk<;X>Yxb}Q9X2rI(QPPzF)gELn8 zA)LG}*1pH{P~N5pk=n!w_ZgpPlWk`K?F{QlDBPgxC=AokUTNedpbc_+G(+!P&)ZX) zK63Bf%*kV<0^)0#7DB#Gf3?8-(1|@2Wui9{>Vc`=BXvfbSi)EB=*FO&<*@phK;vRWhC$hCwDu(Q8Mr~1a82IDJA!(R4x-QMr`pE4O zp}TC2OABfj;G;l0HTX5GN;&K6mP1UVi>eSwNep&f7`fU*sdC>)9tN+tj%%LhQ8tJ5 z1}cuu+mtycMReJ8s}I9qfgcJ%dfNNWL4z}f-z>5=aYzk%PQhU8@~lA?WMH~?F5?I; zBSW?#?VG-*Rz;NI*|laEDBSt2;oVTj2>o5`6|i|V3ZLn;EWOUqRJo-P$Z%9XG{chI zF1{GT?-0@)is*l2CC2SR2y-Ca_yFde?;Q+ZFqp;3B~4<78*8ed46-18_-Ziq$VKY>{TO!U<*B|)rCV*z)rxYe zTBPrCbd|U6T8|2@2}Vyw#1~zvAIHRXLuV}C+>6kP&#Hgxdh35Ca=s!$(|(t8*1+1n zmmfT1=(D8C4yyW>^X>`)sEp70+^)3f7`J(Pz5$ z0o<$ufPZGV>xTEf)H8RWS>)5+I%U{BT0J(iilS*E?u_eT-Fd%Ty2&GzW$vD!>u ztT%V|iSg5X%k{12L171L*4FFH)7_B71c#cD87I&zC|hd`bU}0|(oZ}xl!DHC7ihPw zpP;6-xGl|EDG(zLM1+*-+jl(AmY=Zvq(G31N;T5>!@sDc|MP3_sfw)XyIuq9>y65f zuQgfVZU+YK)44hFHXdE^*#t|U7Es;~FRhBTkUXZ!zQ^_(Q1p@ ziDvg(@vu_q^VYk*AO3hk!lc;#WX?m3D2*Mq##Dm1m5XFFhCHE~?n{i}`D^MPN){mS zSajH1OUq5P9z=&Pp^?QyW8R5fHt2Z7?LNiL^K%RSjG$EDiiKZ6$h0#Rjcj6bjGP_H zFQga|Ayn?z7Ea9K2xPlw%k;e$MxlsuKpGrOHm;_=7R$_+#}PU%x-q~QP(YO(T_W(; zT#|_`EyczQSX(>+IxOaFW8d@Y{Y4xR^QcP^Xh2)C=PpS)0}R-q_kdJd4vD zj|L&-24!rX;lU9IsC1tWs3cs3=PgjN1FEe(n$ud0XEoGu29G!cO!#UiJn9N(#n*$A zUgMBi1=w~_f)Xrgk{gT`CK(BMmoivf(i#gVSyoIUrea+L{O`629Xc$2nWiq92s6~c zRW7U5vz~PB3NEdYX8A7W7Wi0_8<8OOF%RsJ;@`@NxDqS{?m7vW)(r45mWP5zrZ4_> zwy)`ulg88|?!(pbh!571m1nhYnuXU4Nnw(9jKlaTa{5CCa!Rn({&Gdfbu-5YHF~zv zwLspHlXrV6n{6qe(>7yi6Ogu~Y0)6;BT`G+n5-byw7t7tXzldX_Te&=OjyY}*N2nA z#0Mry+3&tDBh8W4L2?Z-oU7BsJ)lTHE=p*4!8mshSwh`RdZa@4oq3K|>9zfCzSpX! zrJn?lhi_H{Q%~?1OJ?i>GA)`w^ZBQxs|D_|ghxEtv609jvupg~IYUpk0Vm zX9>g0TEyPZGxtcsD@&zCGpnn8gLYh+y52=@PIq9m?sQ-aSz~znv{NdOe{^!T=Yu4) zZJP601apPXd3gtrCIOFa3HS6vRY-=Q9Z`LCy>5(3X_J(;R~bNH9ViM_aZ)R+(y;*ENHo$L=x9g^pYquB{AGjC zXhkYF;Fvr}WvCuC?gcEHc%)w6-6XrmReK^uSdl;wsARIphAUg$=jI1*Mj8h{Na~%P zJ@2ez-MzA&q46c{a4$3uv}c}xyv6v)=QK8P9P{IUin)|f&q``^PM=%a;I$~9fD9;> ziCEoI5#aPqlmV8N%%v>IDGuk)0jc2^XYL;j9qa?nycnUOF^lR~{lOd3+#WhKg;-<5 zOep9bUW(JTjk?7TIX_c^t8Xg95sk}TvIISlT6?jOu3(-U&CO879i%RXm^eEx>n&sf zB2IR~lgHfDlZe#hS!DUp^R6(%?gOKd+?~snh)uFhF1__GB%7bQ2w0-3|Ju4cpsgbc zM=wr|5x@q(HoUx{%*8~DSP4gv?fi0<+SIw?uDK?472wctg#e%cNkBdNm$ii4mE~{= z_U4!NeE|O;o5eE;vw7wjRYMQD_#KNucAhezD8>#2Rz)tdGzY{hZU#ZA2ID3c!&We+ zI02VF`7A~7zr_u>w6b@$bT#ZkLu6JklX16RICx|H%|UL-hq39!SS{%n1}Se(50^&8 z!W8)dPNTys50%B9-R6Qs6Dw{-on&-tsT8!NFt8p)??5T}CM@u-1mR!S!4FA#6EfpAfpBrV3il=y6hDAn$xHiG6 zc9(*|pqd`(?}QKaIZyKE3avyGT!H!AfH|}yILM`i%ho$8{l2@g))^R$up}yGl&%%* zJNvb3W1eeaiAyYt?bxR?UQU!%%>5)QDmobBj;Hu{ul{<$nOx>zg@BF(!5>W;?&AM= zmfY(phpmCmd`^eNF+#uZ-HB~F*W!+#H|7xf8<1hSSENp`tQCh47Jk^AfWinTwcCpc zHC&zt@e#wBij8K|IJI2FXqjGC9rBu7NLK{{iEzd0B0X|u*xp}ueHlrwy<@)5)Wa zOfdKG>HI&HCf&J;MBWhH#PNZize^bFi`-s(6k z3n^Ao^&)l|j7+V>{g~mE$X8!8p}z|63*zsf@$|3)fI>?Q+nBF2?vF0By4uX+y-J(2 zvf<{!$O_~a8F_K;FMNx35pGn=`OGAecgGZ)M@|kzcZ7R#je7;+kkEg~Q1z>g?7>`( z_m3RM{JU!FZuDW5>}Ocaxfl{i%<@t(*>QTH$zz;}Lg(^r!NE#;M zYH2x<7deH3)<@?Qh)d}IVK2kY+iPQqQm@BZ{qY4DPkl+Sx)P?DC(7?fOZ>u?n$g~6 zqaW)dc4lO#yWYb9?*HiH?)r8pzEFvtuT&!7FKE}X?4(HWoBVl+Q?LHL$3Es#+%IC5x=ui5}1gKZ*#K;3|8*T)$O@E@95n>(LGJGjV;J!m)2Nf(yRDbo1Zn7b@f^0E1rJ+0J>wTZ@MRQpWIm=1e5vL?r_dz-S@ODl zMfq(FYkCJ*ckF(E;f!W>8Lf{8mx}+38%-;N+)hI>(kq ztF1c9i{wRT>0E?vNMA800ioYYvm@F8iZ_jdJ}d+q-Tu8ClO@~_#HxD|>u|yMY>{=d zVvD6qKP3)*6Vn^%%jxFZ?jv8`=K^3YSH=lsxsh=|S01M4FXvP-|9#`GSPifGOR&z+gC{%MfVXI)^&WQ|8jB8!iUPzBUXUA@aNpbn@g^{jVWDLsgY z6GVKY=+Ij1233~N)vQEK*?aM*1zC z%s>=nf@#8`WblU>E=5M$u;c}Ao4E;B3lK&gvAB-PkXG(R^x&j_wFh*#sCKi9N_oMd ziJDTK3mk;PqQfD8C7H!Tus|1UKQ;8TRBF^@wxkP#bmSas+kVM(~SAv z|DleZ10I-1j&ezcN1!h`sQ%6=c_>m;2-Wfx`1lBrMLzjO|izIk3HCxJe7(3({6#9B|TeO?V@BoYd8GOQ?pl;NTC#Hzy<;AQp!L9F8Q_3ws|DER^*C<_0H znAKW4CpGCcuDshbBCMn9ow;A?gQf1p#as7|sUPX7iv7cj>0i5k|4AU>xhr@+16P=! znuasVH;V@7G_&L)sVXfTCvFEBP$2CpCi4iE(YU=`EJP ztwS2$$7^x8ZygWSBt1MHW{i^(uc&x=Lt~71Hq@j0fbm0+!`hnXA?L)>u@efQ=^QKM zoS@Qd-RrA|k1QBx(z0u$w0oU9XV~TWHhwjjHXs&HeqQ5XQF|CsK6T3w2Oi8Kh}U4T z6`F-7&iLyge0F)hy4S(qLgxo5`*rK}|I(uOrlzZw`~AUry0xPD;vtlNPIiyK1<0ks zGe7V*V~_!U$DHMczN_F0#@3Bd>@`(I$5;cX%mMkBgMEGjr<4ZHnVlAwH&YdZm3|2* z-VC+bbXNS%>x}~|fPzMIlaykmK{}FGT{lRAVXj|%qweW%p^1C&12j6X*WYUghKzI8N@eD)XP?4+m7*L+zVT~@Evm%RA{W#3vT5cau6RS4n{ zXGCGPV<3B|?XWvIqVwRLLsjm#?`N30=jB%qkjdz*+Tq%n})0u_&Me)mXY2@ON!cU6sajP9p`%v6p zww-Fj#e(#E@5Yf^is3D3#XKHd)shP>OqN&GJbj`0^2D_)th*F zRF^KD>iIdz2=9doR8xl^9??7{V&B%!Gkw2FL}`{eJ?e#t`5^V_ja|M+Z#R`n!f!JV zXuceq-i%Ft&aBBZLhmTnH~YkF?;5$kDa)QidnQr#5SJ^i}hgif)`_o}S&0qXNhE9rUd;7YkU3O@E zGo|Vm{KqWrJw(hQJI}*-;fe_RH@{=KOV!@vHetVSk&>4=21+x$Y&}gZ;;IvJ=d@%3 zECH%0N(gW%eSBcWdw&4x1gQ$t7b@sWmu3)A&JOI{*Mgqe7a<_$3Qj!}0wkG=r;^0ymT0+ZC=mvHdjWz^I`%?S=h zVT>Yzrn=C;pO%{s>jm#oqQri21Mb?C1zw5RdeC;Be`^7%^xEUoEgxUO%O z*7i>Fu*$n#k<;L*|CDA0nlH`Ua9q$57=c*ro3*+nm>CGt zQS0=v;|jgln`^L7#G$QebJb4Z-cfx)#0GdkPco>xAfpUnNo_qs2t^9K+hAJMu_(P} zv{~@uu1pe3y@bo+`Nj8K;RxNNJRZl%#z`yK9cK<+(y{U`coAXt< zcj^<5``!^A-C4yE9h<23$Tpe*u*&O`4GF{BL8{Rcj7YL~&eHSKb48zUOa-to@6d!{ z;{5(`?>QTkA4&WVr~!aIGoo<;|BQWkZA0NY9rvZJAfh+>6HkyrfY%)^m-a8xx1a0y z3~hrSrFff4vf~~1RM+T1Pn*8@To>MELxXGwuzL#%B89+@)hpBQ8FEb|K5uk?T=%GC z_ZsTiiW~c#W*qd>tt&C`YSBHY^-PSAf3N1?IA&R{-_!62!_CQE6FKqRvBrMS!xskJ z1@~=%-_(=Avk(a*y79_$y>Y+*@awdyMjgcf@<)r0p8aEFqur+@=fk zI-$NLBWXEZJ4#1hLH)Lz38@vX=Z4|A7YBG<)sOPQym-_%qZ6#>s@!7S6esrD{BlJb zZGtdZGU~FXofV7Aty>yf(N49M6-2Q=u*ChQXX9lx;C$ACM=$m6tvvuz=Z!1*b2|dw z%VLwFXRkqni|edpN1)K)eW=|hZ@z6QPOiFCVVR?Nw%0a7Nx}##in4O#)d7fH%%eTQ zw!2CUTZiik%)}gf`8q;*N&8$W%VKNO@d~OrF=9`}FeTsORBN=Z6GY2L;(U!PRVyr@XsMN~dGpB!0G>UdLX zY0_fv757E6LfLCwDaC7?@RJj|pn0DC3d3Opk z27b;_?iEJo4eAeuFPj*@Spsymru}Tx4<=t?eOl8)b5sNQsDQ)~Ud7R8P6daJReo*E?T(#qHA< zro-Oi9N(4KA=N_b6`oJ7Ojdm}y1MPQX!~l>?l#XMi=3KB!wW1r{cCl81!8#rHZAa! z4FKa@=u1a-F!Y}qdvPjv`lDKFVAU;JJF_f5YXye7&M??^-jw?F`K&o zqQE@=ShhA5mOIcj4<~d`ubf=sdIePhEsU+j2}zP3S5W3`ra6m zd3BVZTQ-#wMCzX4`~uX`nPq5AWL<}HIeKj5XIu?R-mlpWIit~yN=b&^qoc#v3$(!j zby8BsFNdk}Rt+@gaVR;eaCec+61S?+_1FDP^>;szEr3D+OVZCpSKh)Tb+cX8juV{=irNFBiK~0l zmOyH;@XY&_J#*vL-rG>hyD7G?@ZN!T-Ek*Ig(!Z%!y@^mlJxO5IGr6zT%cCMxOZx7 z9{6iG#Dvnuy`i*jn`=wM6I9r1zd0Cfy`Rk|#zYW4`yDds;?8;={HLuJ&364Evqj_OY!-Lj9JuBlB#)&W@hG0K}1wX)vHo7u?0b?&(ruSp)@#;d;6+5 zeTj3Dx7!1k4Hyh&s?y-+GKIdJ7IIZ@w3eI)TrWHdQc#`;zNr7oUDeOyM$aEtKx}T_ zdA9k~eRxYfM&ft_#8b0WOeVhOhv}*FY|3_2dR3$xwYfZRn$HdgrY4rm2fEWkoO+Zs zIlWZvT1nJe(<7m8zuf_*nunfkD8FZnOcIWNTj#sy?@Myn1eKpzK0R;Si>GitO@~~4 zg)QgEunQkjS5iU1KDSjv(PaN%KYtAZmi7D+FgG#>2*XfV{y(0&{1e!tXsjdFw2`IjUgF%7NeHO=~gvFWaDQ>;}srNlu)#9Hhf9@peJt5xX_z12~c%o z4fgwUMC!Q$A55~A{=eGcL2z@@&ZvoBlyw&A5l*k zR%O%lL6lGd0TF450|33tq>+~Hj&F(Qd;Q^c9cFiD zc6M@i@7YUnq1xjw?p7+tJljf@WP5*BbyNxC4&GW{zvaMwoIsMD*L|TorpZln_3r~6 zwPK5aZ{f-O6rw9uw-MHKzQvYI&^Q8i(Px)z^1RzfYtq2mJrVwIN$*If@B zi12z|t7r~P79|2%zB3-dsY}=uC`56CJ!d>jC!oHk*T81Y2#}td^M#2LvAO4?UQ6rf z94!H;HS|xC5(o0Db2Utj0{BXT%bGZ1N&!_iv z+J4R^qw`35v99@)yT%m6boYyifYPJN&x0m$6@BO)%w8_|6#*%I@*LE$+M*~3_It+K z^2O^qsoIC)dQyjebY4tY!lW4@Mp-JiE(Wlhnti% zGj!=?9qacX+tAG7yz%1KvV$R8+>5DI2`)iG?OkLFyAP03&$QF_@1%IPts||}2KCiz zOxCi_^-Bsczqhk$48Pt?x*VGNZ112=uEe%f_*+BiJaXZf#++ABP0cL+pU>)wPL2cT zD=2%>B)E9>5?|qw(lt9J?XDZx|L_#niqv{#Yh3Sj?k*EQV#0cWh+K!YwEMsXL~2}H z7iMFhqASTDlf|0-hsaa}H}IFJ7! z9XsYHS8d{AjC-QuH30M=hDl0ty`KI|f&iwwCxweVaz<7%SE0HR=hOJ^s?I+4n2nLG zYmCH>xvWf7%ilP^JLSzb1Kag)?cKh}p&+*UG6p-=osYh!k%Z1wc)af=mPn(b|N3A* zg{1%|P}Dp1@~G}=#Yrkevp$=3Ei1n;@kXC`$3~AEaoyqCQnm5OVm#=alm_)e4y)@x zv~f@(!7#&MpK^HRyn^!PMumdK)Km*Ce=Gv)6B7Me3%$FAd}qMnWBKB-Ki)tOtjyb)WT3<`$q{zOZjz1q@LE+*K%-t1_o zw=>!89qjVEHJH^&RV!$xPqMCEk1>$xUj>@S&5dg&tI!V~qsNApdMf`iN}3&wl-GLS5-XZ~OYs^enHAm7e^QAp(!vE5(rhO& zG}dArzWQ+U6v*rNkeG|mW301rcMaU~SL==AQE^VU9$UTfmzR?J`yC>S81i3_y#|<^ zuGVQvBr?ApIvLqDC>x*+GqZ?V!h2+fwG|W#Z@vPyzVV+5UfgeYrr#OgOp6$%vop-l zEU1c6=K+H+(43F^^^OS|wOyuNH|^AGYPO6g1Izr)DB}Ng{3$m(pD1TKCYqHE%&zZS zk$35HbUU$!hZJ@l?flBbBu`rjE@o=ElvVMV&}N%eu1lNyy^<@8y_hf~A0bae5Qy~# z(zxIgWnKRe;=!7cYiOeO^X&_-tRBIifqA}fd7)?aVChd-Pj|fhR*SfJ&~Qe6M}ob)xYKP<iJ8;X)>Plpwdh$w1<4cy zGKB2Kf4r&sJpNgLRUd%Ax{BfO;iyRHby{AJT}+!&bYGixAAgsXag&W+=;UR$o}$rQ7=iGWE~m@`F>A8@!$A+kIr%@~%}MqNJe$={Ge*JQ^mg+r}hg zd|xak+|<$6@1D1v{jnMUCyI4g=@o#Vyf`|^Fv2REwMhOz-RZK|RkUef#xHYIFs5-< z*Gzd3%oQe!2TGE7D62%db2C$DaQ@H$BUS#gC=bB!&u^IEY|0nh+rYi;qM0u<$TO~L zy=i=tnbV0S;{Gef7L2eG2ft3Rl7F$=<$gcwk{Bva+gNGXoVFi_4$0iKyu#>{+8dqP z9hCud)smd4u4Q4SQh1^99Kguu8B_!n{f+C#>CI^K&h?_RYGF5(bao6T)MA;nNzS861H+NL=!@)y+L|LabIXh)7{1o(;`W!IBdeGSE&>tCd z04(<8rH1xR+DFJ%$yiQ1cou&%Qyip;>A_O}>SQ~~#DF#I4TTrXH}zy7%Uhn!o|p=0 z2VY)jyMf=Mk>stTEy5psysil#kY@xTLZo54A00Sf`k#1eYrfhz^qHy;?ZUHh`ig4b zxcpct(Ji3K;^%oFbMmjX5#?Hy2w|OroTuiQGll(Ciz?A_3z0dApUU_%tO8$erawOS zof_sIc4w@bkFb?3P3xv;FjXtpj8o9w#Fq8b2Yh;!n(g*mp!C&BDV+tNrjTl&n8kb0 z`~{>Ni`UEdAzzs4qu+Q|PG65qPXFpVSE3Uhu>AI%aL8wGFJ%dD3YwuKsX*&6^&B+8 z`ZYoQ^B^#`MyQ*hY3#Ar58KB6DGS53A(n&HwQ5@?^@%l93B8)ES_$>hG%6znET-2_ z@SdL@`cJVtN(Q~jR{`=SQ5>2PB^KV*><69q`ZOR9Ie{QvrIab-(@6@od!o z+NkxVLBpd#-MwDbwO-k!PRY4e!Kqf>p+?reTE?#WqivOxO_hXIrTFIxQOk-C7Uja` z>iyu*{lTX5omKlgvsN*aW)Xu%5xsihJGH{MDh0I4 z1#gt{sTK2HE96ni=aS3iLS=GDrE^F=W)n+oBzi`Z&c65-y?a2x3Cd34>45*@J1Wia z-q(1Ro0ZJeSHa>$t6NWu+}H6+Jl9kVW=qQd!8Ztt>}O$wAjqa=-_}mmb+B0^MZ}g2 z^yPNYa&vYszO4_pM}M+0ury)T`fK>vw`Y7agMp+)FNf^Nhrc2Jp!tiZI9zcs${Yao z>qIaWv4M@8>0&)1$v5n=t@x8jqu@i4LuuOi(bFFRT~29zUiV{|GG?qaL2x8V85LO- zJ<@BzPmg5$ok=n&_p_dFnf%?NP8E5bfQ>Hwki8e-MBuq__obqs-pPczS~n5psQ}2)~XbrTK>V`Rh$Qu?r)4 zMtZ;5w~7pYnj{fQFONzdY4hwp#NbItN5GgB0#zg9h1x0SdHy`A3ZR@H;%4(Y<#%Uv z--+c%67{TSD%?3SdqejQ>V$t=hHesL3x^gXc25TDhBu+n&DDk_cJaHH`&Vtw$olnL zCfXAYV~)iApC#>)E*GbNFU(l4TJ<{bWW7AxYM_-&-##Q1nYC5!cCq*UQB2S_Sn+$G zHGy`efe&AL79yoOnv790S4J_iu$KRKw?KYJX}ME}wVJls<0UOe!VkHa`o&Po-S?Ee zB~9Nf-6tOWt7pWwi0+-FPIz*h(fy@HR$t6MQ>(s!%{qJSX(j0gcJ*p5qqyaAvZv{n z2@fjHIB?9v$VI?ccFHFW!Y8v5m_hFQu{&S6*P4>ara#Rs`jF#R%G-A8B<_%r|1uif z{rz38*`ym$CHPjhn16H@J;)spBww*Ky~N|ny(N>37BsAvUzO05b(CDqevBEQ?N=x?3nSBW2d=aeE`%iEbD7dWMbr9m(0^U+6+-(oEwxr33&Ww_;caTwk{OB--@xwpzw6nMIy7t>JWcX>Wh>0T6aeT*O- z!f3=W;Vn?ne?XA)h;RG3aZbPJw>&CFMZGs%kv}$&CJH~=!RnSDihlp-`%V8%sqT2W zI)p!+#@biCV?Fmd19H^b+NlBauUK}|VpKXaV!fZY@rmlHU#+C8yaFcDKQ@n?hmr9o~$#V}N99nu_z>!9`a0@8ylO7y0QUTgF|s z6-&|O*ip966>Zq5Ii^R{GnuBBY`I{Ebt6G_WfHE3G?zhzmlB)sG>M*O>ih&;P3m<` zT$iM-@agdUI{ZyKr0EMfI-QeG_>hc#yjb{(e-uHnJ?DLC3P-z8xrl0i{5s^zYxElh zYrlBDCauR4m0e@}StN9?B zBv8!OKw2l-UV4G|?2~#qaXF);3Uk7dsZqj^nUUHd0$$dGX@BnpQx8mPTx@hxEgn+w zEdyW7c~&g9w}jaZ)bL@(WX`fd;`mFg#9L<%P58s>h@lnlXo_E_r?BOJAD5Z>WL>^o z`7zJSI5RkH4;7Ilh-y|OeH_!M6ot|LX}KM0xjmZgk(NHoAP3z9&uRyQ5MhMDO{Lls z8=YA@IN^s$_^6jQ+}umHtW=TN_mlNqLJtrimWCTgzpe|DAJB9kZLDj;3@>{IlgMzw#Q> z;Tcm&egy|%RjV>;Nxu|paGSmkGnImPgC_qH@?oxbn?f~}{wf|%b!m1td-3H@>}VG0yov~0=g z{q|_DiuUk9z!?HKk#15Kn)t8P)vsCFqS?)lEm;m*H{}$??9Gbee7XM|9kEt`u-{BQ z9-j&W0mcE zH+YJ}h|v{{hwW9EX-)2O9d%9UBjkD(o*Cp!s8&YYivse(x$g0jVsj@wD)hR_zffT* z{3j3(>#dT+?YE}kM2F5~{zQ=P?z@=RfQgPPZLGTcyu2?>=syD<~yO#8%8ziy0(f2;N!M6e*uUIIsUr~et z@z_sYScnKO(H%;ylU{^)=+vMEo-MYxhw$rg+dH0eZB|IcxF>}W+~jEG1Z*Ff&|S-% zFCh?CDZrBmHS%<-&Kq29$3!!nPRqZr)=4RDm>y*{CM>{#f~lX0K; zo@0GmiL?>BhC4=7;BAikzyM|&P=^ag_w~ug3yUl8ghADhAUAI#%56e3rwO0ssRz0x zu;3t;^#trkHdbj<97bCA;JL{<+-!`28kHIRQ;=U~g|9!RUNQh=v%}qzz2SUjID+SA z?pz?X2oGsgtmctZdQD{Ju6S3a(>Cq;=QtStASj=d2m+xc82IsBMq_X%{H{XiTC-r& z1Q=C)yb|e%al$ z#g!@wjG%?^c7M`5Nx(9PI+8P4sP90|oS<$f1%kV<{=ibX>%WKgvwyX+Nk-ZVdI3s2gaezK|vAP`!@gSyNf!cTZj)WlI za^)jK1I`qcyq_CWj@}{$r13x^e|`B~)t#VnsLn*@3D7J@3emzr-b|LURjJ}i5`nD| zV8M7%Ou1?s)=~wmD+>J79zgzBIcQo{OsP#!-=W2QDKDLLC*}W23`n9Okl-W-ayE5Z z!WrWG77kjSp>ohOnK2&WU^qx^&aakl|MrHipm$6iZVWl&3eOW@b2ohgX^a;wq85)X zwkrm5bBn#U>=Y$eblABgu>Bpx1FgKOj!vC>;;JZz_LiwyD-k|2eyeYbmue~m!00Yn z`E7ehzz0=$ih}9-c6Itg54X|QZuVYPTM^PIbghiFWIT;J(Pjv zOn*fV13MFnAzN|ybk0fa7$XmECAGG8cPUqt5lHCG*zsb{P{i(5PiGR2JJNwM$`v?> z9;?p|5vqrSOmU^UTQwF;l+gTyztv�@Wx{0Sgm1{zXDaqo=Gl8B2F~V*Gvgl%Co) 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 WjI+0qFb*9ME7`{i&;m)rcmD@AJh6KK literal 0 HcmV?d00001 diff --git a/gtfs-realtime/spec/en/reference.md b/gtfs-realtime/spec/en/reference.md index 014bc21c..ed4c4213 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. + +![](images/trip_modification.png) +_An example showing the effect of a modification on a particular trip. This modification may also be applied to several other trips._ + +![](images/propagated_delay.png) +_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. + +![](images/first_stop_reference.png) +_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 00000000..d509e53c --- /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. + +![](images/trip_modification.png) + +_An example showing the effect of a modification on a particular trip. This modification may also be applied to several other trips._ + +![](images/propagated_delay.png) + +_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. + +![](images/first_stop_reference.png) + +_If a modification affects the first stop of the trip, that stop also serves as the reference stop of the modification._ + From 43d8bbc5bcd9feb0a53744727eca03dd0f7d8eb0 Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:53:50 -0400 Subject: [PATCH 07/16] GTFS-Flex [Voting ver.] (#433) * Add 3 "location" files and booking rules file * Modify stops.stop_id * Modify routes.continuous_pickup/drop_off * Modify stop_times.arrival/departure_time * Modify stop_times.stop_id * Add stop_times.location_group_id & location_id * Modify stop_times.stop_sequence * Add stop_times.start/end_pickup_drop_off_window * Modify pickup_type & drop_off_type * Modify stop_times.continuous_pickup/drop_off * Add pickup/drop_off_booking_rule_id * Add "On-demand Service Routing Behavior" * Modify conditions for start/end_pickup_drop_off_window * Remove unnecessary table name & editorial changes --- gtfs/spec/en/reference.md | 116 ++++++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 11 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 9571e46b..27cbf7a1 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -34,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) @@ -129,6 +133,10 @@ This specification defines the following files: | [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. | @@ -192,7 +200,7 @@ 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](#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. | @@ -227,8 +235,8 @@ 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](#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. | -| `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](#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. | +| `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 @@ -276,17 +284,27 @@ Primary key (`trip_id`, `stop_sequence`) | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | | `trip_id` | Foreign ID referencing `trips.trip_id` | **Required** | Identifies a trip. | -| `arrival_time` | Time | **Conditionally Required** | Arrival time at the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for the first and last stop in a trip (defined by `stop_times.stop_sequence`).
    - **Required** for `timepoint=1`.
    - Optional otherwise.| -| `departure_time` | Time | **Conditionally Required** | Departure time from the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for `timepoint=1`.
    - Optional otherwise.| | -| `stop_id` | Foreign ID referencing `stops.stop_id` | **Required** | Identifies the serviced stop. All stops serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Referenced locations must be stops/platforms, i.e. their `stops.location_type` value must be `0` or empty. A stop may be serviced multiple times in the same trip, and multiple trips and routes may service the same stop. | -| `stop_sequence` | Non-negative integer | **Required** | Order of stops for a particular trip. The values must increase along the trip but do not need to be consecutive.


    *Example: The first location on the trip could have a `stop_sequence`=`1`, the second location on the trip could have a `stop_sequence`=`23`, the third location could have a `stop_sequence`=`40`, and so on.* | +| `arrival_time` | Time | **Conditionally Required** | Arrival time at the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for the first and last stop in a trip (defined by `stop_times.stop_sequence`).
    - **Required** for `timepoint=1`.
    - **Forbidden** when `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise.| +| `departure_time` | Time | **Conditionally Required** | Departure time from the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for `timepoint=1`.
    - **Forbidden** when `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise.| | +| `stop_id` | Foreign ID referencing `stops.stop_id` | **Conditionally Required** | Identifies the serviced stop. All stops serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Referenced locations must be stops/platforms, i.e. their `stops.location_type` value must be `0` or empty. A stop may be serviced multiple times in the same trip, and multiple trips and routes may service the same stop.

    On-demand service using stops should be referenced in the sequence in which service is available at those stops. A data consumer should assume that travel is possible from one stop or location to any stop or location later in the trip, provided that the `pickup/drop_off_type` of each stop_time and the time constraints of each `start/end_pickup_drop_off_window` do not forbid it.

    Conditionally Required:
    - **Required** if `stop_times.location_group_id` AND `stop_times.location_id` are NOT defined.
    - **Forbidden** if `stop_times.location_group_id` or `stop_times.location_id` are defined. | +| `location_group_id` | Foreign ID referencing `location_groups.location_group_id` | **Conditionally Forbidden** | Identifies the serviced location group that indicates groups of stops where riders may request pickup or drop off. All location groups serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Multiple trips and routes may service the same location group.

    On-demand service using location groups should be referenced in the sequence in which service is available at those location groups. A data consumer should assume that travel is possible from one stop or location to any stop or location later in the trip, provided that the `pickup/drop_off_type` of each stop_time and the time constraints of each `start/end_pickup_drop_off_window` do not forbid it.

    **Conditionally Forbidden**:
    - **Forbidden** if `stop_times.stop_id` or `stop_times.location_id` are defined. | +| `location_id` | Foreign ID referencing `id` from `locations.geojson` | **Conditionally Forbidden** | Identifies the GeoJSON location that corresponds to serviced zone where riders may request pickup or drop off. All GeoJSON locations serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Multiple trips and routes may service the same GeoJSON location.

    On-demand service within locations should be referenced in the sequence in which service is available in those locations. A data consumer should assume that travel is possible from one stop or location to any stop or location later in the trip, provided that the `pickup/drop_off_type` of each stop_time and the time constraints of each `start/end_pickup_drop_off_window` do not forbid it.

    **Conditionally Forbidden**:
    - **Forbidden** if `stop_times.stop_id` or `stop_times.location_group_id` are defined. | +| `stop_sequence` | Non-negative integer | **Required** | Order of stops, location groups, or GeoJSON locations for a particular trip. The values must increase along the trip but do not need to be consecutive.
    *Example: The first location on the trip could have a `stop_sequence`=`1`, the second location on the trip could have a `stop_sequence`=`23`, the third location could have a `stop_sequence`=`40`, and so on.*

    Travel within the same location group or GeoJSON location requires two records in [stop_times.txt](#stop_timestxt) with the same `location_group_id` or `location_id`. | | `stop_headsign` | Text | Optional | Text that appears on signage identifying the trip's destination to riders. This field overrides the default `trips.trip_headsign` when the headsign changes between stops. If the headsign is displayed for an entire trip, `trips.trip_headsign` should be used instead.

    A `stop_headsign` value specified for one `stop_time` does not apply to subsequent `stop_time`s in the same trip. If you want to override the `trip_headsign` for multiple `stop_time`s in the same trip, the `stop_headsign` value must be repeated in each `stop_time` row. | -| `pickup_type` | Enum | Optional | Indicates pickup method. Valid options are:

    `0` or empty - Regularly scheduled pickup.
    `1` - No pickup available.
    `2` - Must phone agency to arrange pickup.
    `3` - Must coordinate with driver to arrange pickup. | -| `drop_off_type` | Enum | Optional | Indicates drop off method. Valid options are:

    `0` or empty - Regularly scheduled drop off.
    `1` - No drop off available.
    `2` - Must phone agency to arrange drop off.
    `3` - Must coordinate with driver to arrange drop off. | -| `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](#shapestxt), from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

    If this field is populated, it overrides any continuous pickup behavior defined in [routes.txt](#routestxt). If this field is empty, the `stop_time` inherits any continuous pickup behavior defined in [routes.txt](#routestxt). | -| `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](#shapestxt), from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

    If this field is populated, it overrides any continuous drop-off behavior defined in [routes.txt](#routestxt). If this field is empty, the `stop_time` inherits any continuous drop-off behavior defined in [routes.txt](#routestxt). | +| `start_pickup_drop_off_window` | Time | **Conditionally Required** | Time that on-demand service becomes available in a GeoJSON location, location group, or stop.

    **Conditionally Required**:
    - **Required** if `stop_times.location_group_id` or `stop_times.location_id` is defined.
    - **Required** if `end_pickup_drop_off_window` is defined.
    - **Forbidden** if `arrival_time` or `departure_time` is defined.
    - Optional otherwise. | +| `end_pickup_drop_off_window` | Time | **Conditionally Required** | Time that on-demand service ends in a GeoJSON location, location group, or stop.

    **Conditionally Required**:
    - **Required** if `stop_times.location_group_id` or `stop_times.location_id` is defined.
    - **Required** if `start_pickup_drop_off_window` is defined.
    - **Forbidden** if `arrival_time` or `departure_time` is defined.
    - Optional otherwise. | +| `pickup_type` | Enum | **Conditionally Forbidden** | Indicates pickup method. Valid options are:

    `0` or empty - Regularly scheduled pickup.
    `1` - No pickup available.
    `2` - Must phone agency to arrange pickup.
    `3` - Must coordinate with driver to arrange pickup.

    **Conditionally Forbidden**:
    - `pickup_type=0` **forbidden** if `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - `pickup_type=3` **forbidden** if `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise. | +| `drop_off_type` | Enum | **Conditionally Forbidden** | Indicates drop off method. Valid options are:

    `0` or empty - Regularly scheduled drop off.
    `1` - No drop off available.
    `2` - Must phone agency to arrange drop off.
    `3` - Must coordinate with driver to arrange drop off.

    **Conditionally Forbidden**:
    - `drop_off_type=0` **forbidden** if `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - 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), from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

    If this field is populated, it overrides any continuous pickup behavior defined in [routes.txt](#routestxt). If this field is empty, the `stop_time` inherits any continuous pickup behavior defined in [routes.txt](#routestxt).

    **Conditionally Forbidden**:
    - **Forbidden** if `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - 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), from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. 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.

    If this field is populated, it overrides any continuous drop-off behavior defined in [routes.txt](#routestxt). If this field is empty, the `stop_time` inherits any continuous drop-off behavior defined in [routes.txt](#routestxt).

    **Conditionally Forbidden**:
    - **Forbidden** if `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise. | | `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the associated shape, from the first stop to the stop specified in this record. This field specifies how much of the shape to draw between any two stops during a trip. Must be in the same units used in [shapes.txt](#shapestxt). Values used for `shape_dist_traveled` must increase along with `stop_sequence`; they must not be used to show reverse travel along a route.

    Recommended for routes that have looping or inlining (the vehicle crosses or travels over the same portion of alignment in one trip). See [`shapes.shape_dist_traveled`](#shapestxt).
    *Example: If a bus travels a distance of 5.25 kilometers from the start of the shape to the stop,`shape_dist_traveled`=`5.25`.*| | `timepoint` | Enum | Recommended | Indicates if arrival and departure times for a stop are strictly adhered to by the vehicle or if they are instead approximate and/or interpolated times. This field allows a GTFS producer to provide interpolated stop-times, while indicating that the times are approximate. Valid options are:

    `0` - Times are considered approximate.
    `1` or empty - Times are considered exact. | +| `pickup_booking_rule_id` | ID referencing `booking_rules.booking_rule_id` | Optional | Identifies the boarding booking rule at this stop time.

    Recommended when `pickup_type=2`. | +| `drop_off_booking_rule_id` | ID referencing `booking_rules.booking_rule_id` | Optional | Identifies the alighting booking rule at this stop time.

    Recommended when `drop_off_type=2`. | + +#### On-demand Service Routing Behavior +- When providing routing or travel time between the origin and destination, data consumers should ignore intermediate stop_times.txt records with the same `trip_id` that have `start_pickup_drop_off_window` and `end_pickup_drop_off_window` defined. For examples that demonstrate what should be ignored, see the data example page. +- Simultaneous overlap of locations.geojson `id` geometry, `start/end_pickup_drop_off_window` time, and `pickup_type` or `drop_off_type` between two or more stop_times.txt records with the same `trip_id` is forbidden. For examples that demonstrate what is forbidden, see the data example page. ### calendar.txt @@ -687,6 +705,82 @@ Describes levels in a station. Useful in conjunction with [pathways.txt](#pathwa | `level_index` | Float | **Required** | Numeric index of the level that indicates its relative position.

    Ground level should have index `0`, with levels above ground indicated by positive indices and levels below ground by negative indices.| | `level_name` | Text | Optional | Name of the level as seen by the rider inside the building or station.
    _Example: Take the elevator to "Mezzanine" or "Platform" or "-1"._| +### location_groups.txt + +File: **Optional** + +Primary key (`location_group_id`) + +Defines location groups, which are groups of stops where a rider may request pickup or drop off. + +| Field Name | Type | Required | Description | +| ---------- | ---- | ------------ | ----------- | +| `location_group_id` | Unique ID | **Required** | Identifies a location group. ID must be unique across all `stops.stop_id`, locations.geojson `id`, and `location_groups.location_group_id` values.

    A location group is a group of stops that together indicate locations where a rider may request pickup or drop off. | +| `location_group_name` | Text | Optional | The name of the location group as displayed to the rider. | + +### location_group_stops.txt + +File: **Optional** + +Primary key (`*`) + +Assigns stops from stops.txt to location groups. + +| Field Name | Type | Required | Description | +| ---------- | ---- | ------------ | ----------- | +| `location_group_id` | Foreign ID referencing `location_groups.location_group_id` | **Required** | Identifies a location group to which one or multiple `stop_id`s belong. The same `stop_id` may be defined in many `location_group_id`s. | +| `stop_id` | Foreign ID referencing `stops.stop_id` | **Required** | Identifies a stop belonging to the location group. | + + +### locations.geojson + +File: **Optional** + +Defines zones where riders can request either pickup or drop off by on-demand services. These zones are represented as GeoJSON polygons. +- This file uses a subset of the GeoJSON format, described in [RFC 7946](https://tools.ietf.org/html/rfc7946). +- The `locations.geojson` file must contain a `FeatureCollection`. +- A `FeatureCollection` defines various stop locations where riders may request pickup or drop off. +- Every GeoJSON `Feature` must have an `id`. The `id` must be unique across all `stops.stop_id`, locations.geojson `id`, and `location_group_id` values. +- Every GeoJSON `Feature` should have objects and associated keys according to the table below: + +| Field Name | Type | Presence | Description | +| ------ | ------ | ------ | ------ | +| - `type` | String | **Required** | `"FeatureCollection"` of locations. | +| - `features` | Array | **Required** | Collection of `"Feature"` objects describing the locations. | +|     \- `type` | String | **Required** | `"Feature"` | +|     \- `id` | String | **Required** | Identifies a location. ID must be unique across all `stops.stop_id`, locations.geojson `id`, and `location_groups.location_group_id` values. | +|     \- `properties` | Object | **Required** | Location property keys. | +|         \- `stop_name` | String | Optional | Indicates the name of the location as displayed to riders. | +|         \- `stop_desc` | String | Optional | Meaningful description of the location to help orient riders. | +|     \- `geometry` | Object | **Required** | Geometry of the location. | +|         \- `type` | String | **Required** | Must be of type:
    - `"Polygon"`
    - `"MultiPolygon"` | +|         \- `coordinates` | Array | **Required** | Geographic coordinates (latitude and longitude) defining the geometry of the location. | + +### booking_rules.txt + +File: **Optional** + +Primary key (`booking_rule_id`) + +Defines the booking rules for rider-requested services + +| Field Name | Type | Presence | Description | +| ------ | ------ | ------ | ------ | +| `booking_rule_id` | ID | **Required** | Identifies the rule. | +| `booking_type` | Enum | **Required** | Indicates how far in advance booking can be made. Valid options are:

    `0` - Real time booking.
    `1` - Up to same-day booking with advance notice.
    `2` - Up to prior day(s) booking. | +| `prior_notice_duration_min` | Integer | **Conditionally Required** | Minimum number of minutes before travel to make the request.

    **Conditionally Required**:
    - **Required** for `booking_type=1`.
    - **Forbidden** otherwise. | +| `prior_notice_duration_max` | Integer | **Conditionally Forbidden** | Maximum number of minutes before travel to make the booking request.

    **Conditionally Forbidden**:
    - **Forbidden** for `booking_type=0` and `booking_type=2`.
    - Optional for `booking_type=1`.| +| `prior_notice_last_day` | Integer | **Conditionally Required** | Last day before travel to make the booking request.

    Example: “Ride must be booked 1 day in advance before 5PM” will be encoded as `prior_notice_last_day=1`.

    **Conditionally Required**:
    - **Required** for `booking_type=2`.
    - **Forbidden** otherwise. | +| `prior_notice_last_time` | Time | **Conditionally Required** | Last time on the last day before travel to make the booking request.

    Example: “Ride must be booked 1 day in advance before 5PM” will be encoded as `prior_notice_last_time=17:00:00`.

    **Conditionally Required**:
    - **Required** if `prior_notice_last_day` is defined.
    - **Forbidden** otherwise. | +| `prior_notice_start_day` | Integer | **Conditionally Forbidden** | Earliest day before travel to make the booking request.

    Example: “Ride can be booked at the earliest one week in advance at midnight” will be encoded as `prior_notice_start_day=7`.

    **Conditionally Forbidden**:
    - **Forbidden** for `booking_type=0`.
    - **Forbidden** for `booking_type=1` if `prior_notice_duration_max` is defined.
    - Optional otherwise. | +| `prior_notice_start_time` | Time | **Conditionally Required** | Earliest time on the earliest day before travel to make the booking request.

    Example: “Ride can be booked at the earliest one week in advance at midnight” will be encoded as `prior_notice_start_time=00:00:00`.

    **Conditionally Required**:
    - **Required** if `prior_notice_start_day` is defined.
    - **Forbidden** otherwise. | +| `prior_notice_service_id` | ID referencing `calendar.service_id` | **Conditionally Forbidden** | Indicates the service days on which `prior_notice_last_day` or `prior_notice_start_day` are counted.

    Example: If empty, `prior_notice_start_day=2` will be two calendar days in advance. If defined as a `service_id` containing only business days (weekdays without holidays), `prior_notice_start_day=2` will be two business days in advance.

    **Conditionally Forbidden**:
    - Optional if `booking_type=2`.
    - **Forbidden** otherwise. | +| `message` | Text | Optional | Message to riders utilizing service at a `stop_time` when booking on-demand pickup and drop off. Meant to provide minimal information to be transmitted within a user interface about the action a rider must take in order to utilize the service. | +| `pickup_message` | Text | Optional | Functions in the same way as `message` but used when riders have on-demand pickup only. | +| `drop_off_message` | Text | Optional | Functions in the same way as `message` but used when riders have on-demand drop off only. | +| `phone_number` | Phone number | Optional | Phone number to call to make the booking request. | +| `info_url` | URL | Optional | URL providing information about the booking rule. | +| `booking_url` | URL | Optional | URL to an online interface or app where the booking request can be made. | ### translations.txt From 7e37e0a46095697ab98b2cc20187904bc50db7aa Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:33:54 -0400 Subject: [PATCH 08/16] [GTFS-Fares v2] Clarification: Fare product definition (#426) * Clarify fare product definition * fare media clarification / remove desc in amount Add explicit interaction w/ fare media, Remove individual explanation in non-primary keys * Editorial change * Update gtfs/spec/en/reference.md Co-authored-by: isabelle-dr * Update desc of fare_product_id Co-authored-by: isabelle-dr * Editorial changes for fare_product_id * change "segments" to "legs" --------- Co-authored-by: isabelle-dr --- gtfs/spec/en/reference.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 27cbf7a1..b6716ddf 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -426,14 +426,14 @@ File: **Optional** Primary Key (`fare_product_id`, `fare_media_id`) -To describe the different types of tickets or fares that can be purchased by riders. +Used to describe the range of fares available for purchase by riders or taken into account when computing the total fare for journeys with multiple legs, such as transfer costs. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | -| `fare_product_id` | ID | **Required** | Identifies a fare product. | +| `fare_product_id` | ID | **Required** | Identifies a fare product or set of fare products.

    Multiple records in [fare_products.txt](#fare_productstxt) may share the same `fare_product_id`, in which case all records with that ID will be retrieved when referenced from another file.

    Multiple records may share the same `fare_product_id` but with different `fare_media_id`s, indicating various methods available for employing the fare product, potentially at different prices. | | `fare_product_name` | Text | Optional | The name of the fare product as displayed to riders. | | `fare_media_id` | Foreign ID referencing `fare_media.fare_media_id` | Optional | Identifies a fare media that can be employed to use the fare product during the trip. When `fare_media_id` is empty, it is considered that the fare media is unknown.| -| `amount` | Currency amount | **Required** | The cost of the fare product. May be negative to represent transfer discounts. May be zero to represent a fare product that is free.| +| `amount` | Currency amount | **Required** | The cost of the fare product. May be negative to represent transfer discounts. May be zero to represent a fare product that is free. | | `currency` | Currency code | **Required** | The currency of the cost of the fare product. | From f9991ac98ca0ebf79d3e87149df5a38de86ddd85 Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Wed, 10 Apr 2024 20:11:47 +0200 Subject: [PATCH 09/16] Update CHANGES.md (#440) --- gtfs/CHANGES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gtfs/CHANGES.md b/gtfs/CHANGES.md index db45c8e0..ca5c7f46 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). From 1f6a2f57c0541eed1bf12fd98b8142e59cfe2100 Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:42:02 -0400 Subject: [PATCH 10/16] Added data example page links in stop_times (#443) --- gtfs/spec/en/reference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index b6716ddf..2d1808ad 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -303,8 +303,8 @@ Primary key (`trip_id`, `stop_sequence`) | `drop_off_booking_rule_id` | ID referencing `booking_rules.booking_rule_id` | Optional | Identifies the alighting booking rule at this stop time.

    Recommended when `drop_off_type=2`. | #### On-demand Service Routing Behavior -- When providing routing or travel time between the origin and destination, data consumers should ignore intermediate stop_times.txt records with the same `trip_id` that have `start_pickup_drop_off_window` and `end_pickup_drop_off_window` defined. For examples that demonstrate what should be ignored, see the data example page. -- Simultaneous overlap of locations.geojson `id` geometry, `start/end_pickup_drop_off_window` time, and `pickup_type` or `drop_off_type` between two or more stop_times.txt records with the same `trip_id` is forbidden. For examples that demonstrate what is forbidden, see the data example page. +- When providing routing or travel time between the origin and destination, data consumers should ignore intermediate stop_times.txt records with the same `trip_id` that have `start_pickup_drop_off_window` and `end_pickup_drop_off_window` defined. For examples that demonstrate what should be ignored, see [the data example page](https://gtfs.org/schedule/examples/flex/#ignoring-intermediate-stop-times-records-with-pickupdrop-off-windows). +- Simultaneous overlap of locations.geojson `id` geometry, `start/end_pickup_drop_off_window` time, and `pickup_type` or `drop_off_type` between two or more stop_times.txt records with the same `trip_id` is forbidden. For examples that demonstrate what is forbidden, see [the data example page](https://gtfs.org/schedule/examples/flex/#zone-overlap-constraint). ### calendar.txt From ca4b879ea9719b9f80dbd3de9ecf128d809c4c1b Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Mon, 29 Apr 2024 10:24:08 +0200 Subject: [PATCH 11/16] Editorial changes: rendering of locations.geojson description + updating booking_rule_id description (#441) * Update reference.md * Update reference.md * Update gtfs/spec/en/reference.md Co-authored-by: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> --------- Co-authored-by: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> --- gtfs/spec/en/reference.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 2d1808ad..3b990cc8 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -737,6 +737,7 @@ Assigns stops from stops.txt to location groups. File: **Optional** Defines zones where riders can request either pickup or drop off by on-demand services. These zones are represented as GeoJSON polygons. + - This file uses a subset of the GeoJSON format, described in [RFC 7946](https://tools.ietf.org/html/rfc7946). - The `locations.geojson` file must contain a `FeatureCollection`. - A `FeatureCollection` defines various stop locations where riders may request pickup or drop off. @@ -766,7 +767,7 @@ Defines the booking rules for rider-requested services | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | -| `booking_rule_id` | ID | **Required** | Identifies the rule. | +| `booking_rule_id` | Unique ID | **Required** | Identifies a rule. | | `booking_type` | Enum | **Required** | Indicates how far in advance booking can be made. Valid options are:

    `0` - Real time booking.
    `1` - Up to same-day booking with advance notice.
    `2` - Up to prior day(s) booking. | | `prior_notice_duration_min` | Integer | **Conditionally Required** | Minimum number of minutes before travel to make the request.

    **Conditionally Required**:
    - **Required** for `booking_type=1`.
    - **Forbidden** otherwise. | | `prior_notice_duration_max` | Integer | **Conditionally Forbidden** | Maximum number of minutes before travel to make the booking request.

    **Conditionally Forbidden**:
    - **Forbidden** for `booking_type=0` and `booking_type=2`.
    - Optional for `booking_type=1`.| From af0f468b72d9a95505315d0c289612171563e851 Mon Sep 17 00:00:00 2001 From: Weston Shippy <57922264+westontrillium@users.noreply.github.com> Date: Tue, 7 May 2024 19:59:35 -0700 Subject: [PATCH 12/16] Clarify stops.zone_id conditional requirement for route-based fare_rules (#432) * Clarify stops.zone_id conditional requirement for route-based fare_rules * Change stops.zone_id to optional --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 3b990cc8..ab7eff4f 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -207,7 +207,7 @@ Primary key (`stop_id`) | `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.| +| `zone_id` | ID | Optional | Identifies the fare zone for a stop. If this record represents a station or station entrance, the `zone_id` is ignored.| | `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](#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`).| From 71fc99de4aed8aa35bd0b6b04a62edab33416775 Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Thu, 9 May 2024 20:03:14 +0200 Subject: [PATCH 13/16] Remove spanish translations from GTFS Realtime (#446) * Update README.md * Delete gtfs-realtime/spec/es directory * Update README.md * Update README.md * Update README.md --- gtfs-realtime/README.md | 4 +- gtfs-realtime/spec/es/README.md | 49 -- gtfs-realtime/spec/es/examples/README.md | 4 - gtfs-realtime/spec/es/examples/alerts.asciipb | 72 --- .../es/examples/trip-updates-full.asciipb | 79 --- gtfs-realtime/spec/es/feed-types.md | 36 -- gtfs-realtime/spec/es/gtfs-realtime.proto | 569 ------------------ gtfs-realtime/spec/es/reference.md | 361 ----------- gtfs-realtime/spec/es/service-alerts.md | 56 -- gtfs-realtime/spec/es/trip-updates.md | 56 -- gtfs-realtime/spec/es/vehicle-positions.md | 59 -- 11 files changed, 1 insertion(+), 1344 deletions(-) delete mode 100644 gtfs-realtime/spec/es/README.md delete mode 100644 gtfs-realtime/spec/es/examples/README.md delete mode 100644 gtfs-realtime/spec/es/examples/alerts.asciipb delete mode 100644 gtfs-realtime/spec/es/examples/trip-updates-full.asciipb delete mode 100644 gtfs-realtime/spec/es/feed-types.md delete mode 100644 gtfs-realtime/spec/es/gtfs-realtime.proto delete mode 100644 gtfs-realtime/spec/es/reference.md delete mode 100644 gtfs-realtime/spec/es/service-alerts.md delete mode 100644 gtfs-realtime/spec/es/trip-updates.md delete mode 100644 gtfs-realtime/spec/es/vehicle-positions.md diff --git a/gtfs-realtime/README.md b/gtfs-realtime/README.md index 30322fd0..8108782c 100644 --- a/gtfs-realtime/README.md +++ b/gtfs-realtime/README.md @@ -2,8 +2,6 @@ This directory contains GTFS Realtime Specification and documentation. ### Quick links - [GTFS Realtime protocol buffer definition](proto/gtfs-realtime.proto) -- Documentation - - [English](spec/en) - - [Español](spec/es) +- [Spec Realtime Reference](spec/en/reference.md) - [How to change the specification?](CHANGES.md) diff --git a/gtfs-realtime/spec/es/README.md b/gtfs-realtime/spec/es/README.md deleted file mode 100644 index 92fffcd6..00000000 --- a/gtfs-realtime/spec/es/README.md +++ /dev/null @@ -1,49 +0,0 @@ -GTFS en tiempo real es una especificación de feed que permite que las empresas de tranporte público proporcionen actualizaciones en tiempo real sobre su flota a los programadores de la aplicación. Es una extensión de [GTFS](https://developers.google.com/transit/gtfs/reference) (Especificación general de feeds de transporte público), un formato de datos abierto para los horarios de transporte público y la información geográfica asociada. GTFS en tiempo real fue diseñado en torno a la facilidad de implementación, buena interoperabilidad GTFS y un enfoque en la información al pasajero. - -La especificación fue diseñada a través de la asociación de las empresas que eran inicialmente miembros de [Actualizaciones del transporte público en tiempo real](https://developers.google.com/transit/google-transit#LiveTransitUpdates), diferentes programadores de transporte público y Google. La especificación está publicada bajo la licencia [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). - -## ¿Cómo empiezo? - -1. Sigue leyendo el resumen general. -2. Decide qué [tipos de feed](feed-types.md) proporcionarás. -3. Consulta los [ejemplos de feeds](examples/). -4. Crea tus propios feeds mediante la [referencia](reference.md). -5. Publica tu feed. - -## Resumen general de los tipos de feed GTFS en tiempo real - -La especificación es compatible actualmente con los siguientes tipos de información: - -* **Actualizaciones de viaje**: retrasos, cancelaciones, cambios de ruta -* **Alertas del servicio**: traslados de paradas o eventos imprevistos que afectan una estación, ruta o toda la red -* **Posiciones del vehículo**: información sobre los vehículos, incluidos la ubicación y el nivel de congestión - -Las actualizaciones de cada tipo se proporcionan en un feed separado. Los feeds se muestran a través de HTTP y se actualizan con frecuencia. El archivo en sí es un archivo binario normal, por lo que cualquier tipo de servidor web puede alojar y mostrar el archivo (es posible utilizar otros protocolos de transferencia también). También se podrían utilizar servidores de aplicaciones web, los cuales devolverían el feed como una respuesta a una solicitud GET de HTTP válida. No hay limitaciones en cuanto a la frecuencia ni a los métodos exactos con los que el feed debe ser actualizado o recuperado. - -Ya que GTFS en tiempo real te permite presentar el estado _real_ de tu flota, el feed debe ser actualizado con frecuencia, preferentemente cuando se reciban nuevos datos del sistema de ubicación automática de vehículos. - -[Más información sobre los tipos de feed...](feed-types.md) - -## Formato de los datos - -El formato de intercambio de datos de GTFS en tiempo real se basa en [Búferes de protocolo](https://developers.google.com/protocol-buffers/). - -Los búferes de protocolo son un mecanismo de lenguaje y plataforma neutral para serializar datos estructurados (como XML, pero más pequeño, rápido y simple). La estructura de datos se define en un archivo [gtfs-realtime.proto](gtfs-realtime.proto), que luego se utiliza para generar el código fuente para leer y escribir fácilmente tus datos estructurados desde y hacia una variedad de flujos de datos, mediante diferentes lenguajes, por ejemplo Java, C++ o Python. - -[Más información sobre los búferes de protocolo](https://developers.google.com/protocol-buffers/)... - -## Estructura de los datos - -La jerarquía de los elementos y las definiciones de su tipo están especificadas en el archivo [gtfs-realtime.proto](gtfs-realtime.proto). - -Este archivo de texto se utiliza para generar las bibliotecas necesarias en el lenguaje de programación que se elija. Estas bibliotecas proporcionan las clases y funciones necesarias para generar feeds GTFS en tiempo real válidos. Las bibliotecas no solo hacen que la creación del feed sea más fácil, sino que también garantizan que solo se produzcan feeds válidos. - -[Más información sobre la estructura de los datos.](reference.md) - -## Obtener ayuda - -Para participar en los debates sobre GTFS en tiempo real y sugerir cambios y adiciones a la especificación, únete al [grupo de debate de GTFS en tiempo real](http://groups.google.com/group/gtfs-realtime). - -## Google Maps y Actualizaciones de transporte público en tiempo real - -Una de las posibles aplicaciones que utiliza GTFS en tiempo real es [Actualizaciones de transporte público en tiempo real](https://developers.google.com/transit/google-transit#LiveTransitUpdates), una función de Google Maps que proporciona a los usuarios información de transporte público en tiempo real. Si trabajas para una empresa de transporte público que está interesada en proporcionar actualizaciones en tiempo real para Google Maps, visita la [Página de socios de Google Transit](http://maps.google.com/help/maps/transit/partners/live-updates.html). diff --git a/gtfs-realtime/spec/es/examples/README.md b/gtfs-realtime/spec/es/examples/README.md deleted file mode 100644 index 50d3ed11..00000000 --- a/gtfs-realtime/spec/es/examples/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Los siguientes ejemplos muestran una representación textual de los feeds. Durante el desarrollo, es conveniente producir búferes de protocolo en formato ASCII para que la depuración resulte más sencilla. Puedes comparar tus archivos de texto resultantes con estos ejemplos para comprobar la validez de los datos: - -* [Alertas de Google](alerts.asciipb) -* [Actualización de viaje (conjunto de datos completo)](trip-updates-full.asciipb) diff --git a/gtfs-realtime/spec/es/examples/alerts.asciipb b/gtfs-realtime/spec/es/examples/alerts.asciipb deleted file mode 100644 index 663c405d..00000000 --- a/gtfs-realtime/spec/es/examples/alerts.asciipb +++ /dev/null @@ -1,72 +0,0 @@ -# Información del encabezado -header { - # Versión de la especificación de velocidad. Actualmente "1.0". - gtfs_realtime_version: "1.0" - - # Determina si el conjunto de datos se completó o tiene un incremento gradual. - incrementality: FULL_DATASET - - # La hora en la que se generó el conjunto de datos en el servidor - # para determinar la secuencia de feeds de alerta. - timestamp: 1284457468 -} -# Se pueden incluir varias entidades en el feed. -entity { - # Identificador único para la entidad - id: "0" - - # "Tipo" de la entidad - alert { - # Se pueden definir varios períodos cuando la alerta está activa. - active_period { - # Hora de inicio en formato epoch POSIX - start: 1284457468 - # Hora de fin en formato epoch POSIX - end: 1284468072 - } - # Selecciona qué entidades GTFS serán afectadas. - informed_entity { - # Parámetros válidos: agency_id, route_id, route_type, - # stop_id, viaje (consultar TripDescriptor) - route_id: "219" - } - # Se pueden entregar selectores múltiples (informed_entity). - informed_entity { - stop_id: "16230" - } - - # Causa de la alerta: consultar gtfs-realtime.proto para valores válidos - cause: CONSTRUCTION - # Efecto de la alerta: consultar gtfs-realtime.proto para valores reales - effect: DETOUR - - # La URL dada proporciona información adicional. - url { - # Varios idiomas/traducciones compatibles - translation { - # La página está alojada fuera de Google (en el proveedor o la empresa, etc.). - text: "http://www.sometransitagency/alerts" - language: "es" - } - } - - # El encabezado para la alerta será destacado. - header_text { - # Varios idiomas o traducciones son compatibles. - translation { - text: "La parada en Elm street está cerrada, detenerse temporalmente en Oak street" - language: "es" - } - } - - # Descripción de la alerta. Información adicional al texto del encabezado. - description_text { - # Varios idiomas o traducciones son compatibles. - translation { - text: "Debido a una construcción en Elm street, la parada está cerrada. La parada temporal se puede encontrar a 300 metros al norte de Oak street." - language: "es" - } - } - } -} - diff --git a/gtfs-realtime/spec/es/examples/trip-updates-full.asciipb b/gtfs-realtime/spec/es/examples/trip-updates-full.asciipb deleted file mode 100644 index f8e65396..00000000 --- a/gtfs-realtime/spec/es/examples/trip-updates-full.asciipb +++ /dev/null @@ -1,79 +0,0 @@ -# Información del encabezado -header { - # Especificación de la versión de la velocidad. La versión "1.0" actual - gtfs_realtime_version: "1.0" - # determina si el conjunto de datos se completó o continúa creciendo - incrementality: FULL_DATASET - # en el momento en el que se generó en el servidor. - timestamp: 1284457468 -} - -# Se pueden incluir varias entidades en el -entity { - # identificador único del feed correspondiente a la entidad - id: "simple-trip" - - # "tipo" de la entidad. - trip_update { - trip { - # Selecciona qué entidad GTFS (viaje) se verá afectada. - trip_id: "trip-1" - } - # Actualización de la información del programa - stop_time_update { - # Se selecciona qué parada se ve afectada - stop_sequence: 3 - # para que el vehículo llegue - arrival { - # cinco segundos tarde. - delay: 5 - } - } - # La demora de este vehículo se extiende a las siguientes paradas. - - # Próxima actualización de la información acerca del programa del vehículo - stop_time_update { - # según el campo stop_sequence. Se actualizará - stop_sequence: 8 - # el horario de llegada original del vehículo (programado) con una - arrival { - # demora de un segundo. - delay: 1 - } - } - # ...Asimismo, la demora se extiende a las siguientes paradas. - - # Próxima actualización de la información acerca del programa del vehículo - stop_time_update { - # según el campo stop_sequence. Se actualizará el horario de llegada del vehículo - stop_sequence: 10 - # con la demora predeterminada de cero segundos (a tiempo) y se extenderá esta actualización - # al resto de las paradas del vehículo. - } - } -} - -# Segunda entidad con información acerca de la actualización de otro viaje -entity { - id: "3" - trip_update { - trip { - # En función de su frecuencia, los viajes se definen según el - # trip_id de la especificación GTFS y el campo - trip_id: "frequency-expanded-trip" - # start_time - start_time: "11:15:35" - } - stop_time_update { - stop_sequence: 1 - arrival { - # Una demora negativa se produce cuando el vehículo se adelanta dos segundos según lo establecido en el programa. - delay: -2 - } - } - stop_time_update { - stop_sequence: 9 - } - } -} - diff --git a/gtfs-realtime/spec/es/feed-types.md b/gtfs-realtime/spec/es/feed-types.md deleted file mode 100644 index 07636f2a..00000000 --- a/gtfs-realtime/spec/es/feed-types.md +++ /dev/null @@ -1,36 +0,0 @@ -La especificación GTFS en tiempo real admite el envío de tres tipos diferentes de datos en tiempo real. Si bien la sintaxis del archivo [gtfs-realtime.proto](gtfs-realtime.proto) permite que se mezclen distintos tipos de entidades para un único feed, solo se puede usar un tipo de entidad por feed. Puedes encontrar resúmenes más abajo, teniendo la documentación completa en la sección correspondiente. - -## Actualizaciones de viaje - -#### "El autobús X tiene una demora de cinco minutos". - -Las actualizaciones de viaje ofrecen información acerca de fluctuaciones en el horario. Esperamos recibir actualizaciones de viaje de todos los viajes programados cuya duración se puede predecir en tiempo real. Estas actualizaciones ofrecerían un horario de llegada o salida para las diferentes paradas de la ruta. Las actualizaciones de viaje también pueden brindar información en situaciones más complejas, como cuando los viajes se cancelan o agregan al programa, o como cuando su trayecto se modifica. - -[Más información acerca de las Actualizaciones de viaje...](trip-updates.md) - -## Alertas de servicio - -#### "La estación Y está cerrada por tareas de construcción". - -Las alertas de servicio ofrecen información acerca de problemas más graves que puede sufrir una entidad en particular. En general, se expresan a través de una descripción textual de la interrupción. - -Pueden representar los problemas que sufren: - -* las estaciones, -* las líneas, -* la red completa, -* etc. - -Una alerta de servicio a menudo consiste en una descripción textual del problema. También permitimos que se incluyan las URL de los sitios en los que se ofrecen más detalles e información más estructurada para poder entender a quién afecta una alerta de servicio. - -[Más información acerca de las Alertas de servicio...](service-alerts.md) - -## Posiciones de los vehículos - -#### "Este autobús se encuentra en la posición X a la hora Y". - -La posición de un vehículo ofrece datos básicos acerca de un vehículo en particular de la red. - -La información más importante consiste en la latitud y longitud donde se encuentra el vehículo. Sin embargo, también podemos usar las lecturas de cuentakilómetros y velocidad actuales del vehículo. - -[Más información acerca las actualizaciones de las Posiciones de los vehículos...](vehicle-positions.md) diff --git a/gtfs-realtime/spec/es/gtfs-realtime.proto b/gtfs-realtime/spec/es/gtfs-realtime.proto deleted file mode 100644 index e8c84d42..00000000 --- a/gtfs-realtime/spec/es/gtfs-realtime.proto +++ /dev/null @@ -1,569 +0,0 @@ -// Copyright 2015 The GTFS Specifications Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Archivo de definición de protocolo para GTFS en tiempo real. -// -// GTFS en tiempo real permite que las agencias de transporte público brinden a -// los consumidores información en tiempo real acerca de las interrupciones de -// sus servicios (estaciones cerradas, líneas que no funcionan, demoras -// importantes, etc.), la ubicación de sus vehículos y los horarios de llegada -// esperados. -// -// Este protocolo se publica en: -// https://github.com/google/transit/tree/master/gtfs-realtime - -syntax = "proto2"; - -option java_package = "com.google.transit.realtime"; -package transit_realtime; - -// El contenido de un mensaje de feed -// Un feed es un flujo continuo de mensajes de feed. Cada mensaje del flujo se -// obtiene como una respuesta a una solicitud HTTP GET adecuada. -// Un feed en tiempo real siempre se define con relación a un feed GTFS -// existente. Todos los ID de entidad se resuelven con respecto al feed GTFS. -// -// Un feed depende de cierta configuración externa: -// - El feed GTFS correspondiente. -// - Aplicación del feed (actualizaciones, posiciones o alertas). Un feed solo -// debe contener elementos de una aplicación especificada; todas las demás -// entidades se ignorarán. -// - Frecuencia de sondeo. -message FeedMessage { - // Metadatos acerca de este feed y mensaje de feed - required FeedHeader header = 1; - - // Contenido del feed - repeated FeedEntity entity = 2; -} - -// Metadatos acerca de un feed, incluidos en mensajes de feed -message FeedHeader { - // Versión de la especificación de feed - // La versión actual es 1.0. - required string gtfs_realtime_version = 1; - - // Determina si la búsqueda actual es incremental. Actualmente, el modo - // DIFFERENTIAL no es admitido y no se especifica para feeds que usan este - // modo. Existen foros de debate en la lista de correo de GTFS en tiempo real - // sobre la especificación completa del comportamiento del modo DIFFERENTIAL y - // la documentación se actualizará cuando esos foros de debate finalicen. - enum Incrementality { - FULL_DATASET = 0; - DIFFERENTIAL = 1; - } - optional Incrementality incrementality = 2 [default = FULL_DATASET]; - - // Esta marca de tiempo identifica el momento en que se creó el contenido de - // este feed (en tiempo del servidor). En tiempo POSIX (es decir, la cantidad - // de segundos desde el 1.º de enero de 1970 00:00:00 UTC). - optional uint64 timestamp = 3; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Una definición (o actualización) de una entidad en el feed de transporte -// público. -message FeedEntity { - // Los ID se usan solo para proporcionar asistencia sobre el aumento - // incremental. El ID debe ser único dentro de un FeedMessage. Los - // FeedMessages consiguientes pueden contener FeedEntities con el mismo ID. En - // el caso de una actualización DIFFERENTIAL, la nueva FeedEntity con algunos - // ID reemplazará a la antigua FeedEntity con el mismo ID (o la eliminará: - // consulta is_deleted a continuación). Las entidades de GTFS reales (p. ej., - // estaciones, rutas, viajes) a las que hace referencia el feed deben estar - // especificadas por selectores explícitos (consulta EntitySelector a - // continuación para obtener más información). - required string id = 1; - - // Establece si esta entidad debe eliminarse. Relevante solo para búsquedas - // incrementales. - optional bool is_deleted = 2 [default = false]; - - // Datos acerca de la propia entidad. Exactamente uno de los siguientes campos - // debe estar presente (a menos que se esté eliminando la entidad). - optional TripUpdate trip_update = 3; - optional VehiclePosition vehicle = 4; - optional Alert alert = 5; -} - -// -// Entidades usadas en el feed. -// - -// La actualización en tiempo real del progreso de un vehículo a lo largo de un -// viaje. Dependiendo del valor de ScheduleRelationship, un TripUpdate puede -// especificar: -// - Un viaje que continúa según el programa. -// - Un viaje que continúa por la ruta, pero no tiene un programa fijo. -// - Un viaje que se agregó o eliminó con respecto al programa. -// -// Las actualizaciones pueden ser para eventos de llegada/salida futuros -// previstos o para eventos pasados que ya ocurrieron. -// Normalmente, las actualizaciones deben ser más precisas y más certeras -// (consulta incertidumbre a continuación) a medida que los eventos se acercan -// al momento actual. -// Aun cuando eso no sea posible, la información para eventos pasados debe ser -// precisa y certera. En particular, si una actualización apunta a un momento -// pasado, pero la incertidumbre de su actualización no es 0, el cliente debe -// concluir que la actualización es una predicción (errónea) y que el viaje aún -// no se ha completado. -// -// Ten en cuenta que la actualización puede describir un viaje que ya se ha -// completado. A este fin, proporcionar una actualización para la última parada -// del viaje es suficiente. Si tal momento está en el pasado, el cliente -// concluirá que todo el viaje está en el pasado (es posible, aunque ilógico, -// proporcionar también actualizaciones para las paradas precedentes). Esta -// opción es más relevante para un viaje que se ha completado con anticipación a -// lo programado, pero que, de acuerdo con el programa, el viaje todavía -// continúa en este momento. Si se eliminan las actualizaciones para este viaje, -// el cliente puede asumir que el viaje todavía continúa. Ten en cuenta que al -// proveedor del feed se le permite, pero no está obligado a, purgar -// actualizaciones pasadas: en este caso, esto sería útil en la práctica. -message TripUpdate { - // El viaje al que se aplica este mensaje. Puede haber como máximo una - // entidad TripUpdate para cada instancia de viaje real. - // Si no hay ninguna, eso significa que no hay información de predicción - // disponible. *No* significa que el viaje se está realizando de acuerdo con - // la programación. - required TripDescriptor trip = 1; - - // Información adicional sobre el vehículo que está realizando el viaje. - optional VehicleDescriptor vehicle = 3; - - // Información sobre los tiempos para un solo evento previsto (ya sea llegada - // o salida). - // Los horarios consisten en la información sobre demoras o tiempos estimados - // y la incertidumbre. La demora (delay) debe usarse cuando la predicción se - // realiza con relación a una programación existente en GTFS. - // - El tiempo (time) debe darse aunque no haya una programación prevista. Si - // se especifican tanto el tiempo como la demora, el tiempo será prioritario - // (aunque, por lo general, el tiempo, si se otorga para un viaje - // programado, debe ser igual al tiempo programado en GTFS + la demora). - // - // La incertidumbre se aplica de la misma forma tanto al tiempo como a la - // demora. La incertidumbre especifica el error esperado en una demora real - // (pero ten en cuenta, que todavía no definimos su significado estadístico - // concreto). Es posible que la incertidumbre sea 0, por ejemplo, para los - // trenes que funcionan con un control de horarios por computadora. - message StopTimeEvent { - // La demora (en segundos) puede ser positiva (significa que el vehículo - // está retrasado) o negativa (significa que el vehículo está adelantado). - // Una demora de 0 significa que el vehículo está yendo a tiempo. - optional int32 delay = 1; - - // El evento como tiempo absoluto - // En tiempo Unix (es decir, la cantidad de segundos desde el 1.º de enero - // de 1970 00:00:00 UTC). - optional int64 time = 2; - - // Si se omite la incertidumbre, se interpreta como desconocida. - // Si la predicción es desconocida o demasiado incierta, el campo demora (o - // tiempo) debe estar vacío. En tal caso, el campo incertidumbre se ignora. - // Para especificar una predicción completamente cierta, configura su - // incertidumbre en 0. - optional int32 uncertainty = 3; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; - } - - // Actualización en tiempo real para eventos de llegada o salida para una - // determinada parada en un viaje. Se pueden suministrar actualizaciones tanto - // para eventos pasados como para eventos futuros. Al productor se le - // permite, aunque no está obligado a, proporcionar eventos pasados. - message StopTimeUpdate { - // La actualización está vinculada con una parada específica ya sea mediante - // stop_sequence o stop_id, de manera que necesariamente debe configurarse - // uno de los campos que aparecen a continuación. Consulta la documentación - // en TripDescriptor para obtener más información. - - // Debe ser la misma que la de stop_times.txt en el feed GTFS - // correspondiente. - optional uint32 stop_sequence = 1; - // Debe ser el mismo que el de stops.txt en el feed GTFS correspondiente. - optional string stop_id = 4; - - optional StopTimeEvent arrival = 2; - optional StopTimeEvent departure = 3; - - // La relación entre este StopTime y el programa estático. - enum ScheduleRelationship { - // El vehículo continúa conforme a su programa estático de paradas, aunque - // no necesariamente de acuerdo a los horarios del programa. - // Se debe proporcionar al menos uno de los horarios de llegada y salida. - // Si el programa para esta parada contiene los horarios tanto de llegada - // como de salida, entonces esta actualización también debe tenerlos. Una - // actualización con solo una llegada, por ejemplo, cuando el programa - // tiene ambos, indica que el viaje está terminando temprano en esta - // parada. - SCHEDULED = 0; - - // La parada se omite, es decir, el vehículo no se detendrá en esta - // parada. La llegada y la salida son opcionales. - SKIPPED = 1; - - // No hay datos para esta parada. La intención principal de este valor es - // brindar predicciones solo para parte de un viaje, es decir, si la - // última actualización para un viaje tiene un especificador NO_DATA, - // entonces se considerará que tampoco se especifican StopTimes para el - // resto de las paradas del viaje. No se debe suministrar ni la llegada - // ni la salida. - NO_DATA = 2; - } - optional ScheduleRelationship schedule_relationship = 5 - [default = SCHEDULED]; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; - } - - // Actualizaciones a StopTimes para el viaje (tanto futuras, es decir, - // predicciones, como, en algunos casos, pasadas, es decir, aquellas que ya - // ocurrieron). - // Las actualizaciones se deben clasificar por stop_sequence y aplicarse a - // todas las paradas siguientes del viaje hasta la próxima especificada. - // - // Ejemplo 1: - // Para un viaje con 20 paradas, una StopTimeUpdate con demora de llegada y - // demora de salida de 0 para una stop_sequence de la parada actual significa - // que el viaje está llegando exactamente a horario. - // - // Ejemplo 2: - // Para la misma instancia de viaje, se proporcionan 3 StopTimeUpdates: - // - demora de 5 minutos para la stop_sequence 3 - // - demora de 1 minuto para la stop_sequence 8 - // - demora de duración no especificada para la stop_sequence 10 - // Esto se interpretará como: - // - las stop_sequences 3,4,5,6,7 tienen una demora de 5 minutos. - // - las stop_sequences 8,9 tienen una demora de 1 minuto. - // - las stop_sequences 10,... tienen una demora desconocido. - repeated StopTimeUpdate stop_time_update = 2; - - // Momento en el cual se midió el progreso en tiempo real del vehículo. En - // tiempo POSIX (es decir, la cantidad de segundos desde el 1º de enero de - // 1970 00:00:00 UTC). - optional uint64 timestamp = 4; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Información de posicionamiento en tiempo real de un vehículo dado. -message VehiclePosition { - // El viaje que este vehículo está realizando. - // Puede estar vacío o ser parcial si el vehículo no se puede identificar con - // una instancia de viaje dada. - optional TripDescriptor trip = 1; - - // Información adicional sobre el vehículo que está realizando este viaje. - optional VehicleDescriptor vehicle = 8; - - // Posición actual de este vehículo. - optional Position position = 2; - - // El índice de la secuencia de parada de la parada actual. El significado de - // current_stop_sequence (es decir, la parada a la que hace referencia) lo - // determina current_status. - // Si falta current_status, se asume IN_TRANSIT_TO. - optional uint32 current_stop_sequence = 3; - // Identifica la parada actual. El valor debe ser el mismo que el de stops.txt - // en el feed GTFS correspondiente. - optional string stop_id = 7; - - enum VehicleStopStatus { - // El vehículo está a punto de llegar a la parada (en una visualización de - // la parada, el símbolo del vehículo, por lo general, parpadea). - INCOMING_AT = 0; - - // El vehículo está detenido en la parada. - STOPPED_AT = 1; - - // El vehículo ha partido y está en tránsito hacia la siguiente parada. - IN_TRANSIT_TO = 2; - } - // El estado exacto del vehículo con respecto a la parada actual. - // Se ignora si falta el valor en current_stop_sequence. - optional VehicleStopStatus current_status = 4 [default = IN_TRANSIT_TO]; - - // Momento en el cual se midió la posición del vehículo. En tiempo POSIX (es - // decir, la cantidad de segundos desde el 1º de enero de 1970 00:00:00 UTC). - optional uint64 timestamp = 5; - - // El nivel de congestión que está afectando a este vehículo. - enum CongestionLevel { - UNKNOWN_CONGESTION_LEVEL = 0; - RUNNING_SMOOTHLY = 1; - STOP_AND_GO = 2; - CONGESTION = 3; - SEVERE_CONGESTION = 4; // Personas que dejan sus autos. - } - optional CongestionLevel congestion_level = 6; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Una alerta, que indica que existe algún tipo de incidente en la red de -// transporte público. -message Alert { - // Tiempo durante el cual la alerta debe mostrarse al usuario. Si falta, la - // alerta se mostrará durante todo el tiempo en que aparezca en el feed. - // Si se proporcionan múltiples intervalos, la alerta se mostrará durante - // todos ellos. - repeated TimeRange active_period = 1; - - // Entidades a cuyos usuarios debemos notificar esta alerta. - repeated EntitySelector informed_entity = 5; - - // Causa de esta alerta. - enum Cause { - UNKNOWN_CAUSE = 1; - OTHER_CAUSE = 2; // No representable mediante máquina. - TECHNICAL_PROBLEM = 3; - STRIKE = 4; // Los empleados de las empresas de transporte público dejaron de trabajar. - DEMONSTRATION = 5; // Las personas están bloqueando las calles. - ACCIDENT = 6; - HOLIDAY = 7; - WEATHER = 8; - MAINTENANCE = 9; - CONSTRUCTION = 10; - POLICE_ACTIVITY = 11; - MEDICAL_EMERGENCY = 12; - } - optional Cause cause = 6 [default = UNKNOWN_CAUSE]; - - // El efecto de este problema en la entidad afectada. - enum Effect { - NO_SERVICE = 1; - REDUCED_SERVICE = 2; - - // No nos preocupan las demoras NO significativas: son difíciles de - // detectar, tienen un pequeño impacto sobre el usuario y desordenarían los - // resultados ya que son demasiado frecuentes. - SIGNIFICANT_DELAYS = 3; - - DETOUR = 4; - ADDITIONAL_SERVICE = 5; - MODIFIED_SERVICE = 6; - OTHER_EFFECT = 7; - UNKNOWN_EFFECT = 8; - STOP_MOVED = 9; - } - optional Effect effect = 7 [default = UNKNOWN_EFFECT]; - - // La URL que proporciona información adicional acerca de la alerta. - optional TranslatedString url = 8; - - // Encabezado de la alerta. Contiene un breve resumen del texto de la alerta - // como texto simple. - optional TranslatedString header_text = 10; - - // Descripción completa de la alerta como texto simple. La información de la - // descripción debe agregar a la información del encabezado. - optional TranslatedString description_text = 11; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// -// Estructuras de datos de bajo nivel que se utilizaron más arriba. -// - -// Un intervalo de tiempo. El intervalo se considera activo a la hora 't' si 't' -// es mayor o igual que la hora de inicio y menor que la hora de finalización. -message TimeRange { - // Hora de inicio, en tiempo POSIX (es decir, la cantidad de segundos desde el - // 1º de enero de 1970 00:00:00 UTC). - // Si falta esta información, el intervalo comienza en el infinito negativo. - optional uint64 start = 1; - - // Hora de finalización, en tiempo POSIX (es decir, la cantidad de segundos - // desde el 1º de enero de 1970 00:00:00 UTC). - // Si falta esta información, el intervalo finaliza en el infinito positivo. - optional uint64 end = 2; -} - -// Una posición. -message Position { - // Grados al Norte, en el sistema de coordenadas WGS-84. - required float latitude = 1; - - // Grados al Este, en el sistema de coordenadas WGS-84 - required float longitude = 2; - - // Orientación, en grados, en el sentido de las agujas del reloj desde el - // Norte, es decir, 0 es Norte y 90 es Este. Esto puede ser la orientación de - // la brújula o la dirección hacia la siguiente parada o la ubicación - // intermedia. - // Esto no debe deducirse de las instrucciones de la secuencia de posiciones - // anteriores, que puede calcularse a partir de los datos anteriores. - optional float bearing = 3; - - // Valor del odómetro, en metros. - optional double odometer = 4; - // Velocidad momentánea medida por el vehículo, en metros por segundo. - optional float speed = 5; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Un descriptor que identifica una instancia de un viaje de GTFS, o todas las -// instancias de un viaje por una ruta. -// - Para especificar una sola instancia de viaje, se establece el trip_id (y, -// en caso de ser necesario, el start_time). Si también se establece el -// route_id, entonces debe ser el mismo al que corresponde el viaje dado. -// - Para especificar todos los viajes por una ruta dada, solo se debe -// establecer el route_id. Ten en cuenta que si el trip_id no se conoce, -// entonces los identificadores de secuencia de parada en TripUpdate no son -// suficientes y los stop_ids también se deben proporcionar. Además, se deben -// proporcionar las horas absolutas de llegada/salida. -message TripDescriptor { - // El trip_id del feed GTFS al cual hace referencia este selector. - // Para viajes sin frecuencia expandida, este campo es suficiente para - // identificar de forma unívoca al viaje. Para viajes con frecuencia - // expandida, start_time y start_date también podrían ser necesarios. - optional string trip_id = 1; - - // El route_id de GTFS al cual hace referencia este selector. - optional string route_id = 5; - - // La hora de inicio programada de esta instancia de viaje. - // Este campo debe proporcionarse solo si el viaje es de frecuencia expandida - // en el feed GTFS. El valor debe corresponder precisamente a la start_time - // especificada para la ruta del feed GTFS más algún múltiplo de headway_secs. - // El formato del campo es el mismo que el de GTFS/frequencies.txt/start_time, - // p. ej., 11:15:35 o 25:15:35. - optional string start_time = 2; - - // La fecha de inicio programada de esta instancia de viaje. - // Se debe proporcionar para desambiguar los viajes que están tan retrasados - // que pueden colisionar con un viaje programado para el día siguiente. Por - // ejemplo, para un tren que sale a las 8:00 y a las 20:00 todos los días, y - // que tiene una demora de 12 horas, habrá dos viajes diferentes a la misma - // hora. - // Este campo se puede proporcionar pero no es obligatorio para los programas - // en los cuales tales colisiones son imposibles: por ejemplo, un servicio que - // funciona según una programación por hora donde un vehículo que tiene una - // demora de una hora ya deja de considerarse relacionado con el programa. - // En formato AAAAMMDD. - optional string start_date = 3; - - // La relación entre este viaje y el programa estático. Si un viaje se realiza - // de acuerdo con un programa temporal, no se refleja en GTFS, entonces - // no debe marcarse como SCHEDULED, sino como ADDED. - enum ScheduleRelationship { - // Viaje que se está ejecutando de acuerdo con su programa de GTFS,o que es - // lo suficientemente parecido al viaje programado como para asociarse a él. - SCHEDULED = 0; - - // Un viaje adicional que se ha agregado a un programa en ejecución, por - // ejemplo, para reemplazar un vehículo averiado o para responder a una - // carga repentina de un pasajero. - ADDED = 1; - - // Un viaje que se está ejecutando sin ningún programa asociado, por - // ejemplo, cuando no existe ningún programa. - UNSCHEDULED = 2; - - // Un viaje que existió en el programa, pero se eliminó. - CANCELED = 3; - } - optional ScheduleRelationship schedule_relationship = 4; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Información de identificación para el vehículo que realiza el viaje. -message VehicleDescriptor { - // Identificación interna del sistema para el vehículo. Debe ser única para el - // vehículo y se puede usar para realizar un seguimiento del vehículo a medida - // que avanza en el sistema. - optional string id = 1; - - // Etiqueta visible para el usuario, es decir, algo que se debe mostrar al - // pasajero para ayudarlo a identificar el vehículo correcto. - optional string label = 2; - - // La patente del vehículo. - optional string license_plate = 3; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Un selector para una entidad en un feed GTFS. -message EntitySelector { - // Los valores de los campos deben corresponder a los campos apropiados en el - // feed GTFS. - // Se debe brindar, al menos, un especificador. Si se proporcionan varios, - // entonces el que coincide debe aplicarse a todos los especificadores dados. - optional string agency_id = 1; - optional string route_id = 2; - // corresponde a route_type en GTFS. - optional int32 route_type = 3; - optional TripDescriptor trip = 4; - optional string stop_id = 5; - - // El espacio de nombres de extensiones permite a los programadores externos - // extender la especificación de GTFS en tiempo real para agregar y evaluar - // nuevas funciones y modificaciones a la especificación. - extensions 1000 to 1999; -} - -// Un mensaje internacionalizado que contiene versiones por idioma de un -// fragmento de texto o una URL. -// Se seleccionará una de las cadenas de un mensaje. La resolución se realiza de -// la siguiente manera: -// 1. Si el idioma de la interfaz de usuario coincide con el código de idioma de -// una traducción, se elige la primera traducción coincidente. -// 2. Si un idioma de interfaz de usuario predeterminado (p. ej., inglés) -// coincide con el código de idioma de una traducción, se elige la primera -// traducción coincidente. -// 3. Si alguna traducción tiene un código de idioma no especificado, se elige -// esa traducción. -message TranslatedString { - message Translation { - // Una cadena UTF-8 que contiene el mensaje. - required string text = 1; - // Código de idioma BCP-47. Se puede omitir si el idioma es desconocido o si - // no se realiza ningún i18n para el feed. Como máximo, se permite que - // una traducción tenga una etiqueta de idioma no especificado. - optional string language = 2; - } - // Se debe proporcionar al menos una traducción. - repeated Translation translation = 1; -} diff --git a/gtfs-realtime/spec/es/reference.md b/gtfs-realtime/spec/es/reference.md deleted file mode 100644 index 6c79f80c..00000000 --- a/gtfs-realtime/spec/es/reference.md +++ /dev/null @@ -1,361 +0,0 @@ -Un feed GTFS en tiempo real permite que las empresas de transporte público brinden a los consumidores información en tiempo real acerca de las interrupciones de sus servicios (estaciones cerradas, líneas que no funcionan, demoras importantes, etc.), la ubicación de sus vehículos y tiempos de llegada esperados. - -Las especificaciones de la versión 1.0 del feed se abordan y documentan aquí. - -### Definiciones de términos - -* **obligatorio**: uno -* **repetido**: cero o más -* **mensaje**: tipo complejo -* **enum.**: lista de valores fijos -* **experimental**: campo experimental, sujeto a cambios. Podrá ser formalmente adoptado más adelante. - -## Índice de elementos - -* [FeedMessage](#mensaje-feedmessage) - * [FeedHeader](#mensaje-feedheader) - * [Incrementality](#enum-incrementality) - * [FeedEntity](#mensaje-feedentity) - * [TripUpdate](#mensaje-tripupdate) - * [TripDescriptor](#mensaje-tripdescriptor) - * [ScheduleRelationship](#enum-schedulerelationship-1) - * [VehicleDescriptor](#mensaje-vehicledescriptor) - * [StopTimeUpdate](#mensaje-stoptimeupdate) - * [StopTimeEvent](#mensaje-stoptimeevent) - * [ScheduleRelationship](#enum-schedulerelationship) - * [VehiclePosition](#mensaje-vehicleposition) - * [TripDescriptor](#mensaje-tripdescriptor) - * [ScheduleRelationship](#enum-schedulerelationship-1) - * [Position](#mensaje-position) - * [Alert](#mensaje-alert) - * [TimeRange](#mensaje-timerange) - * [EntitySelector](#mensaje-entitySelector) - * [TripDescriptor](#mensaje-tripdescriptor) - * [ScheduleRelationship](#enum-schedulerelationship-1) - * [Cause](#enum-cause) - * [Effect](#enum-effect) - * [TranslatedString](#mensaje-translatedstring) - * [Translation](#mensaje-translation) - -# Elementos - -## _mensaje_ FeedMessage - -El contenido de un mensaje de feed. Cada mensaje en el flujo de datos se obtiene como una respuesta a una solicitud HTTP GET adecuada. Un feed en tiempo real siempre se define en relación con un feed GTFS existente. Todos los ID de entidades se resuelven en relación con el feed GTFS. - -Un feed depende de algunas configuraciones externas: - -* El feed GTFS correspondiente. -* La aplicación del feed (actualizaciones, posiciones o alertas). Un feed debe contener únicamente elementos de las aplicaciones correspondientes; todas las otras entidades se ignorarán. -* Frecuencia de sondeo, controlada por min_update_delay, max_update_delay. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **header** | [FeedHeader](#mensaje-feedheader) | obligatorio | Metadatos sobre este feed y mensaje del feed | -| **entity** | [FeedEntity](#mensaje-feedentity) | repetido | Contenido del feed | - -## _mensaje_ FeedHeader - -Metadatos sobre un feed, incluido en los mensajes del feed: - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **gtfs_realtime_version** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | obligatorio | Especificación de la versión del feed. La versión actual es 1.0. | -| **incrementality** | [Incrementality](#enum-incrementality) | opcional | -| **timestamp** | [uint64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Esta marca de tiempo identifica el momento en que se ha creado el contenido de este feed (en la hora del servidor). En POSIX time (es decir, cantidad de segundos desde el 1 de enero de 1970 00:00:00 UTC). Para evitar el desvío de tiempos entre los sistemas que producen y que consumen información en tiempo real, se recomienda derivar la marca de tiempo desde un servidor de tiempo. Es completamente aceptable usar Stratum 3 o incluso servidores strata inferiores, porque diferencias de tiempo de hasta un par de segundos son tolerables. | - -## _enum._ Incrementality - -Determina si la búsqueda actual es incremental. - -* **FULL_DATASET**: la actualización de este feed sobrescribirá toda la información en tiempo real anterior para el feed. Por lo tanto, se espera que esta actualización proporcione un resumen completo de toda la información en tiempo real conocida. -* **DIFFERENTIAL**: en este momento, este modo **no tiene soporte** y su comportamiento es **indefinido** para los feeds que lo usan. Existen debates en la [lista de correo](http://groups.google.com/group/gtfs-realtime) de GTFS en tiempo real relacionados con la especificación completa del comportamiento del modo DIFFERENTIAL, y la documentación se actualizará cuando esos debates finalicen. - -### Valores - -| _**Valor**_ | -|-------------| -| **FULL_DATASET** | -| **DIFFERENTIAL** | - -## _mensaje_ FeedEntity - -La definición (o actualización) de una entidad en el feed de transporte público. Si la entidad no se elimina, uno de los campos "trip_update", "vehicle" y "alert" debe completarse. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | obligatorio | Identificador único del feed para esta entidad. Los identificadores se usan solamente para proporcionar soporte de incrementalidad. Las entidades reales a las que hace referencia el feed deben especificarse mediante selectores explícitos (ver EntitySelector más adelante para obtener más información). | -| **is_deleted** | [bool](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Establece si esta entidad debe eliminarse. Es relevante solo para las búsquedas incrementales. | -| **trip_update** | [TripUpdate](#mensaje-tripupdate) | opcional | Datos sobre las demoras de salida en tiempo real de un viaje. | -| **vehicle** | [VehiclePosition](#mensaje-vehicleposition) | opcional | Datos sobre la posición en tiempo real de un vehículo. | -| **alert** | [Alert](#mensaje-alert) | opcional | Datos sobre las alertas en tiempo real. | - -## _mensaje_ TripUpdate - -Actualización en tiempo real del progreso de un vehículo en un viaje. Consulta también el debate general del [tipo de feed de actualizaciones del viaje](./trip-updates). - -Según el valor de ScheduleRelationship, TripUpdate puede especificar lo siguiente: - -* Un viaje que avanza según la programación. -* Un viaje que avanza por una ruta, pero que no tiene una programación fija. -* Un viaje que se ha agregado o se ha quitado en relación con una programación. - -Las actualizaciones pueden ser para eventos de llegada/salida futuros y previstos, o para eventos pasados que ya ocurrieron. En la mayoría de los casos, la información sobre los eventos pasados es un valor medido, por lo tanto, se recomienda que su valor de incertidumbre sea 0\. Aunque puede haber algunos casos en que esto no sea así, por lo que se admiten valores de incertidumbre distintos de 0 para los eventos pasados. Si el valor de incertidumbre de una actualización no es 0, entonces la actualización es una predicción aproximada para un viaje que no se ha completado o la medición no es precisa o la actualización fue una predicción para el pasado que no se ha verificado después de que ocurrió el evento. - -Ten en cuenta que la actualización puede describir un viaje que ya se ha completado. En este caso, es suficiente con proporcionar una actualización para la última parada del viaje. Si el tiempo de llegada para la última parada es en el pasado, el cliente concluirá que todo el viaje es pasado (es posible, aunque inconsecuente, proporcionar también actualizaciones para las paradas anteriores). Esta opción es más relevante para un viaje que se ha completado antes de lo que establecía la programación, pero que según esta, el viaje todavía se está realizando en este momento. Quitar las actualizaciones de este viaje podría hacer que el cliente considere que el viaje todavía se está realizando. Ten en cuenta que el proveedor del feed tiene permitido, aunque no está obligado, a purgar las actualizaciones pasadas (en este caso esto sería útil). - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **trip** | [TripDescriptor](#mensaje-tripdescriptor) | obligatorio | El viaje al cual se aplica este mensaje. Puede haber una entidad de TripUpdate, como máximo, para cada instancia de viaje real. Si no hay ninguna, entonces no habrá información de predicciones disponible. *No* significa que el viaje se está realizando de acuerdo con la programación. | -| **vehicle** | [VehicleDescriptor](#VehicleDescriptor) | opcional | Información adicional sobre el vehículo con el cual se está realizando este viaje. | -| **stop_time_update** | [StopTimeUpdate](#mensaje-stoptimeupdate) | repetido | Las actualizaciones de StopTimes para el viaje (futuras, como las predicciones, y, en algunos casos, pasadas, es decir, aquellas que ya ocurrieron). Las actualizaciones deben ordenarse por secuencia de parada y deben aplicarse a todas las siguientes paradas del viaje hasta la próxima especificada. | -| **timestamp** | [uint64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Momento en el que se midió el progreso en tiempo real del vehículo. En POSIX time (es decir, la cantidad de segundos desde el 1 de enero de 1970 00:00:00 UTC). | - -## _mensaje_ StopTimeEvent - -Información de horarios para un único evento previsto (sea la llegada o la salida). Los horarios consisten en la información sobre demoras o tiempos estimados y la incertidumbre. - -* La demora (delay) debe usarse cuando la predicción se realiza con relación a una programación existente en GTFS. -* El tiempo (time) debe darse aunque no haya una programación prevista. Si se especifican tanto el tiempo como la demora, el tiempo será prioritario (aunque, por lo general, el tiempo, si se otorga para un viaje programado, debe ser igual al tiempo programado en GTFS + la demora). - -La incertidumbre se aplica de la misma forma tanto al tiempo como a la demora. La incertidumbre especifica el error esperado en una demora real (pero ten en cuenta, que todavía no definimos su significado estadístico concreto). Es posible que la incertidumbre sea 0, por ejemplo, para los trenes que funcionan con un control de horarios por computadora. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **delay** | [int32](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | La demora (en segundos) puede ser positiva (significa que el vehículo está retrasado) o negativa (significa que el vehículo está adelantado). Una demora de 0 significa que el vehículo está yendo a tiempo. | -| **time** | [int64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Evento como tiempo absoluto. En POSIX time (es decir, la cantidad de segundos desde el 1 de enero de 1970 00:00:00 UTC). | -| **uncertainty** | [int32](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Si se omite la incertidumbre, se interpreta como desconocida. Para especificar una predicción completamente certera, establece la incertidumbre en 0. | - -## _mensaje_ StopTimeUpdate - -La actualización en tiempo real para los eventos de llegada o de salida para una determinada parada de un viaje. Consulta el debate general de las actualizaciones de tiempos de parada en la documentación de [TripDescriptor](#mensaje-tripdescriptor) y [del tipo de feed de actualizaciones de viaje](./trip-updates). - -Las actualizaciones se pueden proporcionar tanto para eventos pasados como futuros. El productor tiene permitido, aunque no está obligado a, desestimar los eventos pasados. - La actualización está vinculada a una parada específica sea a través de stop_sequence o de stop_id, de manera que uno de estos campos debe definirse, necesariamente. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **stop_sequence** | [uint32](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Debe ser la misma que la de stop_times.txt en el feed GTFS correspondiente. | -| **stop_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Debe ser el mismo que el de stops.txt en el feed GTFS correspondiente. | -| **arrival** | [StopTimeEvent](#mensaje-stoptimeevent) | opcional | -| **departure** | [StopTimeEvent](#mensaje-stoptimeevent) | opcional | -| **schedule_relationship** | [ScheduleRelationship](#enum-schedulerelationship) | opcional | La relación predeterminada es SCHEDULED. | - -## _enum._ ScheduleRelationship - -La relación entre este StopTime y la programación estática - -### Valores - -| _**Valor**_ | _**Comentario**_ | -|-------------|------------------| -| **SCHEDULED** | El vehículo está avanzando según su programación estática de paradas, aunque no necesariamente de acuerdo con los tiempos de la programación. Este es el comportamiento **predeterminado**. Al menos debe proporcionarse uno de los valores de llegada y de salida. Si la programación para esta parada contiene los tiempos de llegada y de salida, entonces también debe contener estos dos valores la actualización. Una actualización son solo una salida, digamos, cuando la programación tiene ambos datos, indica que el viaje se termina antes en esta parada. | -| **SKIPPED** | La parada se omite, es decir, el vehículo no se detendrá en esta parada. Los valores de llegada y salida son opcionales. | -| **NO_DATA** | No se proporcionan datos para esta parada. Esto indica que no hay información en tiempo real disponible. Cuando se establece NO_DATA, esto se propaga en las siguientes paradas, de manera que esta es la forma recomendada de especificar desde qué parada no tienes información en tiempo real. Cuando se establece NO_DATA, no se deben proporcionar los datos de llegada ni de salida. | - -## _mensaje_ VehiclePosition - -Información de posicionamiento en tiempo real para un vehículo dado - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **trip** | [TripDescriptor](#mensaje-tripdescriptor) | opcional | El viaje que está haciendo este vehículo. Puede estar vacío o parcialmente vacío si el vehículo no puede identificarse con una instancia de viaje dada. | -| **vehicle** | [VehicleDescriptor](#VehicleDescriptor) | opcional | Información adicional sobre el vehículo que está realizando el viaje. Cada entrada debe tener un ID de vehículo **único**. | -| **position** | [Position](#mensaje-position) | opcional | Posición actual de este vehículo. | -| **current_stop_sequence** | [uint32](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | El índice de la secuencia de parada de la parada actual. El significado de current_stop_sequence (es decir, la parada a la que hace referencia) está determinado por current_status. Si falta el valor en current_status, se asume IN_TRANSIT_TO. | -| **stop_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Identifica la parada actual. El valor debe ser el mismo que el de stops.txt en el feed GTFS correspondiente. | -| **current_status** | [VehicleStopStatus](#VehicleStopStatus) | opcional | El estado exacto del vehículo con respecto a la parada actual. Se ignora si falta el valor en current_stop_sequence. | -| **timestamp** | [uint64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Momento en el cual se midió la posición del vehículo. En POSIX time (es decir, la cantidad de segundos desde el 1 de enero de 1970 00:00:00 UTC). | -| **congestion_level** | [CongestionLevel](#CongestionLevel) | opcional | - -## _enum._ VehicleStopStatus - -### Valores - -| _**Valor**_ | _**Comentario**_ | -|-------------|------------------| -| **INCOMING_AT** | El vehículo está a punto de llegar a la parada (en la visualización de la parada, el símbolo del vehículo, por lo general, parpadea). | -| **STOPPED_AT** | El vehículo está detenido en la parada. | -| **IN_TRANSIT_TO** | El vehículo ha salido de la parada anterior y está en tránsito. | - -## _enum._ CongestionLevel - -El nivel de tráfico que está afectando al vehículo. - -### Valores - -| _**Valor**_ | -|-------------| -| **UNKNOWN_CONGESTION_LEVEL** | -| **RUNNING_SMOOTHLY** | -| **STOP_AND_GO** | -| **CONGESTION** | -| **SEVERE_CONGESTION** | - -## _mensaje_ Alert - -Una alerta que indica que existe algún tipo de incidente en la red de transporte público. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **active_period** | [TimeRange](#mensaje-timerange) | repetido | Tiempo durante el cual debe mostrarse la alerta al usuario. Si falta, la alerta se mostrará durante todo el tiempo que aparezca en el feed. Si se otorgan varios intervalos, la alerta se mostrará durante todos ellos. | -| **informed_entity** | [EntitySelector](#mensaje-entitySelector) | repetido | Entidades a cuyos usuarios debemos notificar esta alerta. | -| **cause** | [Cause](#enum-cause) | opcional | -| **effect** | [Effect](#enum-effect) | opcional | -| **url** | [TranslatedString](#mensaje-translatedstring) | opcional | La URL que proporciona información adicional sobre la alerta. | -| **header_text** | [TranslatedString](#mensaje-translatedstring) | opcional | Encabezado de la alerta. Esta cadena de texto sin formato se resaltará, por ejemplo, en negrita. | -| **description_text** | [TranslatedString](#mensaje-translatedstring) | opcional | Descripción de la alerta. A esta cadena de texto sin formato se le aplicará el formato del cuerpo de la alerta (o se mostrará en una solicitud explícita de "expansión" realizada por el usuario
). La información de la descripción debe completar la información del encabezado. | - -## _enum._ Cause - -Causa de la alerta - -### Valores - -| _**Valor**_ | -|-------------| -| **UNKNOWN_CAUSE** | -| **OTHER_CAUSE** | -| **TECHNICAL_PROBLEM** | -| **STRIKE** | -| **DEMONSTRATION** | -| **ACCIDENT** | -| **HOLIDAY** | -| **WEATHER** | -| **MAINTENANCE** | -| **CONSTRUCTION** | -| **POLICE_ACTIVITY** | -| **MEDICAL_EMERGENCY** | - -## _enum._ Effect - -El efecto de este problema en la entidad afectada. - -### Valores - -| _**Valor**_ | -|-------------| -| **NO_SERVICE** | -| **REDUCED_SERVICE** | -| **SIGNIFICANT_DELAYS** | -| **DETOUR** | -| **ADDITIONAL_SERVICE** | -| **MODIFIED_SERVICE** | -| **OTHER_EFFECT** | -| **UNKNOWN_EFFECT** | -| **STOP_MOVED** | - -## _mensaje_ TimeRange - -Un intervalo de tiempo. El intervalo se considera activo `t` si `t` es mayor o igual que la hora de inicio y mejor que la hora de finalización. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **start** | [uint64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Hora de inicio, en POSIX time (es decir, la cantidad de segundos desde el 1 de enero de 1970 00:00:00 UTC). Si falta esta información, el intervalo comienza con el valor infinito negativo. | -| **end** | [uint64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Hora de finalización, en POSIX time (es decir, la cantidad de segundos desde el 1 de enero de 1970 00:00:00 UTC). Si falta esta información, el intervalo finaliza con el valor infinito positivo. | - -## _mensaje_ Position - -La posición geográfica de un vehículo - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **latitude** | [float](https://developers.google.com/protocol-buffers/docs/proto#scalar) | obligatorio | Grados norte, en el sistema de coordenadas WGS-84 | -| **longitude** | [float](https://developers.google.com/protocol-buffers/docs/proto#scalar) | obligatorio | Grados este, en el sistema de coordenadas WGS-84 | -| **bearing** | [float](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Orientación, en grados, en el sentido de las agujas del reloj desde el norte verdadero, es decir, 0 es el norte y 90 es el este. Esta puede ser la orientación de la brújula, o la dirección hacia la próxima parada o la ubicación intermedia. Esto no debe deducirse a partir de la secuencia de posiciones anteriores, que los clientes pueden calcular a partir de los datos anteriores. | -| **odometer** | [double](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | El valor del odómetro en metros. | -| **speed** | [float](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Velocidad momentánea medida por el vehículo, en metros por segundo. | - -## _mensaje_ TripDescriptor - -Un descriptor que identifica una instancia de un viaje de GTFS o todas las instancias de un viaje por una ruta. Para especificar una sola instancia de viaje, se define trip_id (y si fuera necesario, start_time). Si también se define route_id, debe ser el mismo que uno a los cuales corresponda el viaje dado. Para especificar todos los viajes de una determinada ruta, solo se debe definir route_id. Ten en cuenta que si no se conoce el trip_id, entonces los identificadores de la secuencia de la estación en TripUpdate no son suficientes y, también, se deberán proporcionar los identificadores de parada. Además, se deben proporcionar las horas absolutas de llegada/salida. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **trip_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | El identificador de viaje del feed GTFS al cual hace referencia este selector. Para los viajes sin frecuencia extendida, este campo es suficiente para identificar de forma unívoca al viaje. Para los viajes con frecuencia extendida, también podrían necesitarse start_time y start_date. | -| **route_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | El identificador de la ruta de GTFS al que hace referencia este selector. | -| **start_time** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | La hora de inicio programada de esta instancia de viaje. Este campo debe proporcionarse solo si el viaje tiene frecuencia extendida en el feed GTFS. El valor debe corresponder precisamente a la hora de inicio especificada para la ruta del feed GTFS más algunos múltiplos de headway_secs. El formato del campo es el mismo que el de GTFS/frequencies.txt/start_time, es decir, 11:15:35 o 25:15:35. | -| **start_date** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | La fecha de inicio programada de esta instancia de viaje. Este campo debe proporcionarse para desambiguar los viajes que están tan retrasados que pueden superponerse con un viaje programado para el día siguiente. Por ejemplo, para un tren que sale a las 8:00 y a las 20:00 todos los días, y está 12 horas retrasado, habrá dos viajes distintos a la misma hora. Este campo puede proporcionarse, pero no es obligatorio para las programaciones en las cuales las superposiciones son imposibles, por ejemplo, un servicio que funciona según una programación horaria donde un vehículo que está una hora retrasado deja de considerarse relacionado a la programación. En formato AAAAMMDD. | -| **schedule_relationship** | [ScheduleRelationship](#enum-schedulerelationship-1) | opcional | - -## _enum._ ScheduleRelationship - -La relación entre este viaje y la programación estática. Si un viaje se realiza de acuerdo con la programación temporal, no se refleja en GTFS, y por lo tanto, no debe marcarse como SCHEDULED, sino como ADDED. - -### Valores - -| _**Valor**_ | _**Comentario**_ | -|-------------|------------------| -| **SCHEDULED** | Viaje que se está realizando de acuerdo con su programación de GTFS, o que está realizándose tan parecido al viaje programado que se puede asociar con él. | -| **ADDED** | Un viaje adicional que se agregó además de una programación existente, por ejemplo, para reemplazar un vehículo averiado o para responder a una carga repentina de pasajeros. | -| **UNSCHEDULED** | Un viaje que se está realizando sin ninguna programación asociada, por ejemplo, cuando no existe ninguna programación. | -| **CANCELED** | Un viaje que existió en la programación, pero que luego se eliminó. | -| **REPLACEMENT** | Un viaje que reemplaza una parte de la programación estática. Si el selector de viaje identifica determinada instancia de viaje, entonces solamente esa instancia se reemplaza. Si el selector identifica una ruta, entonces todos los viajes de la ruta se reemplazan.
    El reemplazo se aplica solamente a la parte del viaje que se suministra. Por ejemplo, consideremos una ruta que pasa por las paradas A,B,C,D,E,F y un viaje REPLACEMENT proporciona datos para las paradas A,B,C. Entonces, los horarios para las paradas D,E,F todavía se toman de la programación estática.
    Un feed debe suministrar varios viajes REPLACEMENT. En este caso, la parte de la programación estática que se reemplaza es la suma de las definiciones de todos los feeds. Por lo general, todos los viajes REPLACEMENT deben corresponder a la misma ruta o a instancias de viaje individuales. | - -## _mensaje_ VehicleDescriptor - -Información de identificación para el vehículo que realiza el viaje. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Identificación interna del sistema para el vehículo. Debe ser **única** para cada vehículo y se usa para hacer un seguimiento del vehículo en la medida en que avanza en el sistema. Este identificador debe ser visible para el usuario final; para ello debes usar el campo **label** | -| **label** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Etiqueta visible para el usuario, es decir, que se debe mostrar al pasajero para ayudarlo a identificar el vehículo correcto. | - -## _mensaje_ EntitySelector - -Un selector para una entidad en un feed GTFS. Los valores de los campos deben coincidir con los campos correspondientes del feed GTFS. Debe otorgarse al menos un especificador. Si se otorgan muchos, entonces la coincidencia debe hacerse con todos los especificadores dados. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **agency_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | -| **route_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | -| **route_type** | [int32](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | -| **trip** | [TripDescriptor](#mensaje-tripdescriptor) | opcional | -| **stop_id** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | - -## _mensaje_ TranslatedString - -Un mensaje internacionalizado que contiene versiones por idioma de un fragmento de texto o una URL. Se seleccionará una de las cadenas de un mensaje. La resolución se realiza de la siguiente manera: si el idioma de la UI coincide con el código de idioma de una traducción, se elije la primera traducción coincidente. Si un idioma de UI predetermiando (por ejemplo, inglés) coincide con el código de idioma de una traducción, se elije la primera traducción coincidente. Si alguna traducción tiene un código de idioma no especificado, se elija esa traducción. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **translation** | [Translation](#mensaje-translation) | repetido | Se debe proporcionar al menos una traducción. | - -## _mensaje_ Translation - -Una cadena localizada asignada a un idioma. - -### Campos - -| _**Nombre del campo**_ | _**Tipo**_ | _**Cardinalidad**_ | _**Descripción**_ | -|------------------------|------------|--------------------|-------------------| -| **text** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | obligatorio | Una cadena UTF-8 que contiene el mensaje. | -| **language** | [string](https://developers.google.com/protocol-buffers/docs/proto#scalar) | opcional | Código de idioma BCP-47\. Se puede omitir si el idioma es desconocido o si no se realiza ninguna internacionalización para el feed. Al menos una traducción puede tener una etiqueta de idioma no especificado. | diff --git a/gtfs-realtime/spec/es/service-alerts.md b/gtfs-realtime/spec/es/service-alerts.md deleted file mode 100644 index 4161622b..00000000 --- a/gtfs-realtime/spec/es/service-alerts.md +++ /dev/null @@ -1,56 +0,0 @@ -Las alertas de servicio permiten proporcionar actualizaciones cada vez que se produce una interrupción en la red. Las demoras y cancelaciones de viajes individuales a menudo se deben comunicar a través de las [Actualizaciones de viaje](trip-updates.md). - -Se puede proporcionar la siguiente información: - -* la URL del sitio en el que se ofrecen más detalles acerca de la alerta, -* el texto del encabezado a modo de resumen de la alerta, -* la descripción completa de la alerta que se mostrará junto al encabezado (la información no debe ser la misma en ambas partes). - -### Período - -La alerta aparecerá en el momento apropiado, dentro del período establecido. Este período debe cubrir en su totalidad el lapso en el que el pasajero necesita la alerta. - -Si no se establece ningún período, mostraremos la alerta durante el tiempo en que esta se encuentre en el feed. Si se establecen varios períodos, mostraremos la alerta durante todos ellos. - -### Selector de entidad - -El selector de entidad permite especificar exactamente a qué partes de la red afecta una alerta, con el fin de poder mostrar al usuario sólo las alertas más adecuadas. Varios selectores de entidad pueden ser incluidos, para los casos en los que las alertas afecten a muchas entidades. - -Las entidades se seleccionan a través de los identificadores de la especificación GTFS, pudiéndose elegir entre: - -* Empresa: afecta toda la red. -* Ruta: afecta toda la ruta. -* Tipo de ruta: afecta cualquier ruta del tipo seleccionado; p. ej.: todos los metros. -* Viaje: afecta un viaje en particular. -* Parada: afecta una parada en particular. - -### Causa - -¿Cuál es la causa de esta alerta? Se pueden especificar cualquiera de las siguientes: - -* causa desconocida, -* otra causa (que no se ve representada por ninguna de estas opciones), -* problema técnico, -* huelga, -* manifestación, -* accidente, -* feriado, -* clima, -* tareas de mantenimiento, -* tareas de construcción, -* actividad policial, -* emergencia médica. - -### Consecuencia - -¿Qué conscuencia tiene este problema para la entidad seleccionada? Se pueden especificar cualquiera de las siguientes: - -* sin servicio, -* servicio reducido, -* demoras importantes (aquellas poco importantes se deben informar a través de las [Actualizaciones de viaje](trip-updates.md)), -* desvío, -* servicio adicional, -* servicio modificado, -* traslado de parada, -* otro efecto (que no se ve representado por ninguna de estas opciones), -* efecto desconocido. diff --git a/gtfs-realtime/spec/es/trip-updates.md b/gtfs-realtime/spec/es/trip-updates.md deleted file mode 100644 index a4d5fc5a..00000000 --- a/gtfs-realtime/spec/es/trip-updates.md +++ /dev/null @@ -1,56 +0,0 @@ -Las actualizaciones de viaje representan fluctuaciones en el horario. Se espera recibirlas de todos los viajes programados que puedan proporcionarlas en tiempo real. Estas actualizaciones brindarían un horario de llegada o salida previsto para las paradas a lo largo de la ruta. Las actualizaciones de viaje también pueden prever escenarios más complejos en los cuales se cancelen o agreguen viajes al programa, o incluso se redirijan. - -**Recordatorio:** En [GTFS](https://developers.google.com/transit/gtfs/), un viaje es una secuencia de dos o más paradas que tienen lugar a una hora específica. - -Debe haber **como máximo** una actualización de viaje para cada viaje programado. En caso de no ser así, se concluirá que no hay datos en tiempo real disponibles para dicho viaje. El consumidor de datos **no** debe asumir que el viaje se está realizando de manera puntual. - -## Actualizaciones de horario de paradas - -Una actualización de viaje comprende una o más actualizaciones de los horarios de parada del vehículo, conocidas como [StopTimeUpdates](reference.md#StopTimeUpdate). Pueden proporcionarse para horarios de paradas pasados y futuros. Se permite brindar horarios de parada pasados, pero no es obligatorio hacerlo. En el caso de que se haga, ten en cuenta que no se debe proporcionar una actualización pasada si se refiere a un viaje todavía no programado para haber terminado (es decir, que finalizó antes de lo programado), ya que, de lo contrario, se concluirá que no hay actualización de ese viaje. - -Cada [StopTimeUpdate](reference.md#StopTimeUpdate) está vinculada a una parada. Normalmente esto se puede hacer usando un GTFS stop_sequence o un GTFS stop_id. Sin embargo, en caso de que estés suministrando una actualización para un viaje sin un trip_id de GTFS, debes especificar el stop_id, ya que stop_sequence no tiene valor. El stop_id todavía debe hacer referencia a un stop_id en GTFS. - -La actualización puede proporcionar un horario exacto para la **llegada** o la **salida** en una parada en [StopTimeUpdates](reference.md#StopTimeUpdate) mediante [StopTimeEvent](reference.md#StopTimeUpdate). Este debe contener un **horario** absoluto o un **retraso** (es decir, una compensación desde el horario programado en segundos). El retraso solo se puede utilizar en caso de que la actualización de viaje se refiera a un viaje de GTFS programado, en contraposición con un viaje basado en la frecuencia. En este caso, el horario debe ser igual al horario programado + el retraso. También se debe especificar la **incertidumbre** de la predicción junto con [StopTimeEvent](reference.md#StopTimeUpdate), que se analiza más detalladamente más abajo, en la sección [Incertidumbre](#Incertidumbre). - -Para cada [StopTimeUpdate](reference.md#StopTimeUpdate), la relación de programación predeterminada es **programada**. (Ten en cuenta que ésta es diferente a la relación de programación para el viaje). Puedes cambiarla a **omitida** si la parada no se va a utilizar o a **sin datos** si solo tienes datos en tiempo real para parte del viaje. - -**Las actualizaciones se deben clasificar por stop_sequence** (o stop_id, en el orden en que tienen lugar en el viaje). - -Si faltan una o más paradas a lo largo del viaje, la actualización se propaga a todas las paradas subsiguientes. Esto significa que, en caso de no haber otra información, al actualizar un horario de parada para una cierta parada se cambiarán todas las paradas subsiguientes. - -**Ejemplo 1** - -Para un viaje con 20 paradas, una [StopTimeUpdate](reference.md#StopTimeUpdate) con retraso de llegada y retraso de salida de 0 ([StopTimeEvents](reference.md#StopTimeEvent)) para la stop_sequence de la parada actual, significa que el viaje está exactamente a horario. - -**Ejemplo 2** - -Para la misma instancia de viaje, se proporcionan tres [StopTimeUpdates](reference.md#StopTimeUpdate): - -* retraso de 300 segundos para la stop_sequence 3. -* retraso de 60 segundos para la stop_sequence 8. -* retraso de duración no especificada para la stop_sequence 10. - -Esto se interpretará como: - -* las stop_sequences 3,4,5,6,7 tienen un retraso de 300 segundos. -* las stop_sequences 8,9 tienen un retraso de 60 segundos. -* las stop_sequences 10,..,20 tienen un retraso desconocido. - -### Descriptor de viajes - -La información suministrada por el descriptor de viajes depende de la relación de programación del viaje que estás actualizando. Hay varias opciones que puedes configurar: - -| _**Valor**_ | _**Comentario**_ | -|-------------|------------------| -| **Programado** | Este viaje se está ejecutando de acuerdo con un programa de GTFS o se asemeja lo suficiente como para seguir estando asociado a él. | -| **Agregado** | Este viaje no estaba programado y se ha agregado. Por ejemplo, para satisfacer la demanda o reemplazar un vehículo averiado. | -| **Sin programar** | Este viaje está teniendo lugar, pero nunca está asociado con horario alguno. Por ejemplo, si no hay programa y los autobuses operan en un servicio de traslados. | -| **Cancelado** | Este viaje se programó pero ahora está eliminado. | - -En la mayoría de los casos, se debe proporcionar el trip_id del viaje programado en GTFS con el que se relaciona esta actualización. En caso de que no se pueda vincular esta actualización con un viaje en GTFS, se puede brindar un route_id de GTFS, y una fecha y hora de inicio para el viaje. Generalmente, este es el caso de los viajes agregados, los que están sin programar y de algunos tipos de viajes de reemplazo. - -## Incertidumbre - -La incertidumbre se aplica tanto al horario como al valor de retraso de una [StopTimeUpdate](reference.md#StopTimeUpdate). La incertidumbre especifica, en términos generales, el error esperado en el retraso real como un entero en segundos (pero ten en cuenta que el significado estadístico concreto todavía no está definido). Es posible que la incertidumbre sea 0, por ejemplo, para los trenes conducidos bajo control de horarios por computadora. - -Por ejemplo, un autobús de larga distancia que tiene un retraso estimado de 15 minutos y llega a su siguiente parada con una ventana de error de 4 minutos (es decir, +2/-2 minutos) tendrá una incertidumbre de 240. diff --git a/gtfs-realtime/spec/es/vehicle-positions.md b/gtfs-realtime/spec/es/vehicle-positions.md deleted file mode 100644 index d8191696..00000000 --- a/gtfs-realtime/spec/es/vehicle-positions.md +++ /dev/null @@ -1,59 +0,0 @@ -La posición del vehículo se utiliza para proporcionar información generada automáticamente sobre la ubicación del mismo, como la generada por un GPS a bordo. Se debe proporcionar una sola posición por cada vehículo que pueda hacerlo. - -El viaje que el vehículo está realizando actualmente se debe proporcionar a través de un [descriptor de viaje](reference.md#VehicleDescriptor). También se puede proporcionar un [descriptor de vehículo](reference.md#VehicleDescriptor) que especifique un vehículo físico concreto sobre el cual estás proporcionando actualizaciones. La documentación se proporciona más abajo. - -Se puede proporcionar una **marca de tiempo** que indique el momento en el que se tomó la lectura de la posición. Hay que tener en cuenta que esta es diferente de la marca de tiempo en el encabezado del feed, que es el tiempo en el que el servidor generó este mensaje. - -También se puede proporcionar un **paso actual** (ya sea como stop_sequence o stop_id). Este es una referencia a la parada a la que el vehículo se está dirigiendo o en la que ya se detuvo. - -## Posición - -La posición contiene los datos de ubicación (Vehicle Position) del vehículo. Los campos de latitud y longitud son obligatorios; los demás campos son opcionales. Estos tipos de datos son: - -* **Latitud**: grados Norte, en el sistema de coordenadas WGS-84. -* **Longitud**: grados Este, en el sistema de coordenadas WGS-84. -* **Rumbo**: la dirección hacia la que el vehículo está orientado. -* **Odómetro**: la distancia que el vehículo ha recorrido. -* **Velocidad**: velocidad instantánea medida por el vehículo, en metros por segundo. - -## Nivel de tráfico - -La posición del vehículo también permite que la empresa especifique el nivel de tráfico que el vehículo está experimentando en el instante actual. El tráfico se puede clasificar en las siguientes categorías: - -* Nivel de tráfico desconocido. -* Tráfico fluido. -* Tráfico intermitente. -* Atasco. -* Atrasco grave. - -A la empresa le corresponde interpretar nuestra ponderación del tráfico. Desde nuestra perspectiva, la congestión grave solo se utilizaría en situaciones en las que el tráfico está tan congestionado que las personas están abandonando sus vehículos. - -## Grado de ocupación del vehículo - -La posición del vehículo permite a la empresa especificar el grado de ocupación del vehículo, que puede ser clasificado en la siguientes categorías: - -* Vacío. -* Muchos asientos libres. -* Pocos asientos libres. -* Sitio sólo de pie. -* Sitio sólo de pie y apretados. -* Lleno. -* No admite más pasajeros. - -Este campo todavía es **experimental** y está sujeto a cambios. Podría pasar a adoptarse formalmente más adelante. - -## Estado de parada del vehículo - -El estado de parada del vehículo está más relacionado con el estado de una parada a la que se está aproximando o en la que ya está. Se puede ajustar a cualquiera de estos valores. - -* **Llegando a**: el vehículo está a punto de llegar a la parada indicada. -* **Detenido en**: el vehículo está detenido en la parada indicada. -* **En camino a**: la parada indicada es la siguiente parada para el vehículo: **predeterminado**. - -## Descriptor de vehículo - -El descriptor de vehículo describe un vehículo físico concreto y puede contener cualquiera de los siguientes atributos: - -* **ID**: sistema interno de identificación del vehículo. Debe ser único para el vehículo. -* **Identificador**: un identificador visible para el usuario, por ejemplo el nombre de un tren. -* **Matrícula**: la matrícula real del vehículo. From 08323db59b963a7d95e6519f38b8a580264a4f1e Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Sun, 12 May 2024 16:39:40 +0200 Subject: [PATCH 14/16] Add Best Practices source documentation in the google/transit repo (#447) * Add Schedule Best Practices * Add Realtime Best Practices * Update readme * Delete gtfs/best-practices/.DS_Store * Update README.md * Update README.md * Update README.md * Update README.md * fix broken link * Update README.md * small link fix * small change * Update README.md with new Realtime issue link --- gtfs-realtime/best-practices/README.md | 19 ++ .../best-practices/best-practices.md | 163 ++++++++++ gtfs/README.md | 5 +- gtfs/best-practices/README.md | 21 ++ gtfs/best-practices/best-practices.md | 300 ++++++++++++++++++ gtfs/best-practices/images/branching.svg | 1 + gtfs/best-practices/images/inlining.svg | 1 + gtfs/best-practices/images/lasso-route.svg | 1 + gtfs/best-practices/images/loop-route.svg | 1 + gtfs/best-practices/images/rmi-small.png | Bin 0 -> 7868 bytes gtfs/best-practices/images/rmi.png | Bin 0 -> 28037 bytes 11 files changed, 510 insertions(+), 2 deletions(-) create mode 100644 gtfs-realtime/best-practices/README.md create mode 100644 gtfs-realtime/best-practices/best-practices.md create mode 100644 gtfs/best-practices/README.md create mode 100644 gtfs/best-practices/best-practices.md create mode 100644 gtfs/best-practices/images/branching.svg create mode 100755 gtfs/best-practices/images/inlining.svg create mode 100755 gtfs/best-practices/images/lasso-route.svg create mode 100755 gtfs/best-practices/images/loop-route.svg create mode 100644 gtfs/best-practices/images/rmi-small.png create mode 100644 gtfs/best-practices/images/rmi.png diff --git a/gtfs-realtime/best-practices/README.md b/gtfs-realtime/best-practices/README.md new file mode 100644 index 00000000..5ef76007 --- /dev/null +++ b/gtfs-realtime/best-practices/README.md @@ -0,0 +1,19 @@ +# GTFS Realtime Best Practices + +These are recommended practices for describing real-time public transportation services in the [GTFS Realtime Reference](../spec/en/reference.md) format. These complement the explicit recommendations outlined in the GTFS Realtime Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders. +These practices have been synthesized from the experience of the [GTFS Best Practices working group members](https://gtfs.org/schedule/best-practices/#gtfs-best-practices-working-group) and application-specific GTFS practice recommendations. See the [FAQ](https://gtfs.org/schedule/best-practices/#frequently-asked-questions-faq) for more information. + +--- +⚠️ **NOTE: The GTFS Realtime Best Practices are in the process of being merged into the [GTFS Realtime Reference](../spec/en/reference.md) (see [issue #396](https://github.com/google/transit/issues/396) and [issue #451](https://github.com/google/transit/issues/451) for more information).** +**New Best Practices will be added directly to the GTFS Realtime Reference. If you'd like to suggest a new Best practice, you can:** +- **look at the existing [list of outstanding issues and PRs](https://github.com/google/transit/issues/421). If your new Best Practice idea is referenced on this list, comment on the issue** +- **[open a new issue](https://github.com/google/transit/issues/new/choose)** +- **open a Pull Request following the [GTFS Realtime Amendment Process](https://gtfs.org/realtime/process/).** +--- + +## Documentation Structure + +The GTFS Realtime Best Practices are written in Markdown and are organized by Message and by use case. + +* `field_name`: The name of the GTFS Realtime field being described +* `recommendations`: An array of the recommendations provided for each field_name diff --git a/gtfs-realtime/best-practices/best-practices.md b/gtfs-realtime/best-practices/best-practices.md new file mode 100644 index 00000000..4956a1b5 --- /dev/null +++ b/gtfs-realtime/best-practices/best-practices.md @@ -0,0 +1,163 @@ +# GTFS Realtime Best Practices + +## Introduction + +These are recommended practices for describing real-time public transportation information in the [GTFS Realtime Reference](https://gtfs.org/realtime/reference/) format. These complement the explicit recommendations outlined in the GTFS Realtime Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders. + +These practices have been synthesized from the experience of the [GTFS Best Practices working group](https://gtfs.org/schedule/best-practices/#gtfs-best-practices-working-group) members and [application-specific GTFS practice recommendations](http://www.transitwiki.org/TransitWiki/index.php/Best_practices_for_creating_GTFS). + +For further background, see the [Frequently Asked Questions](https://gtfs.org/schedule/best-practices/#frequently-asked-questions-faq). + +### Document Structure + +Recommended practices are organized into two primary sections + +* __[Practice Recommendations Organized by Message](#practice-recommendations-organized-by-message):__ Recommendations are organized by message and field in the same order described in the official GTFS Realtime reference. +* __[Practice Recommendations Organized by Case](#practice-recommendations-organized-by-case):__ With particular cases, such as frequency-based service (vs. schedule-based service), practices may need to be applied across several messages and fields as well as the corresponding GTFS schedule data. Such recommendations are consolidated in this section. + +### Feed Publishing & General Practices + +* Feeds should be published at a public, permanent URL +* The URL should be directly accessible without requiring a login to access the feed. If desired, API keys may be used but registration for API keys should be automated and available to all. +* Maintain persistent identifiers (id fields) within a GTFS Realtime feed (e.g., FeedEntity.id, VehicleDescriptor.id, CarriageDetails.id) across feed iterations. +* GTFS Realtime feeds should be refreshed at least once every 30 seconds, or whenever the information represented within the feed (position of a vehicle) changes, whichever is more frequent. VehiclePositions tend to change more frequently than other feed entities and should be updated as frequently as possible. If the content has not changed, the feed should be updated with a new `FeedHeader.timestamp` reflecting that the information is still relevant as of that timestamp. +* Data within a GTFS Realtime feed should not be older than 90 seconds for Trip Updates and Vehicle Positions and not older than 10 minutes for Service Alerts. For example, even if a producer is continuously refreshing the `FeedHeader.timestamp` timestamp every 30 seconds, the age of VehiclePositions within that feed should not be older than 90 seconds. +* The server hosting GTFS Realtime data should be reliable and consistently return validly-formatted protobuf-encoded responses. Fewer than 1% of responses should be invalid (protobuf errors or fetching errors). +* The web-server hosting GTFS Realtime data should be configured to correctly report the file modification date (see HTTP/1.1 - Request for Comments 2616, under Section 14.29) so consumers can leverage the `If-Modified-Since` HTTP header. This saves producers and consumers bandwidth by avoiding transferring feed contents that haven't changed. +* Feeds should provide protocol buffer-encoded feed content by default when queried via an HTTP request at the given URL - consumers should not need to define special HTTP accept headers to receive protocol-buffer encoded content. +* Due to how protocol buffers encode [optional values](https://developers.google.com/protocol-buffers/docs/proto#optional), before reading data from a GTFS Realtime feed consumers should check for the presence of values using the protocol buffer-generated `hasX()` methods before using that value and should only use the value if `hasX()` is true (where `X` is the name of the field). If `hasX()` returns `false`, the default value for that field defined in the `gtfs-realtime.proto` value should be assumed. If the consumer uses the value without checking the `hasX()` method first, it may be reading default data that wasn't intentionally published by the producer. +* Feeds should use HTTPS instead of HTTP (without encryption) to ensure feed integrity. +* Feeds should cover the vast majority of trips included in the companion static GTFS dataset. In particular, it should include data for high-density and high-traffic city areas and busy routes. + +## Practice Recommendations Organized by Message + +### FeedHeader + +| Field Name | Recommendation | +| --- | --- | +| `gtfs_realtime_version` | Current version is "2.0". All GTFS Realtime feeds should be "2.0" or higher, as early version of GTFS Realtime did not require all fields needed to represent various transit situations adequately. | +| `timestamp` | This timestamp should not decrease between two sequential feed iterations. | +| | This timestamp value should always change if the feed contents change - the feed contents should not change without updating the header `timestamp`.

    *Common mistakes* - If there are multiple instances of GTFS Realtime feed behind a load balancer, each instance may be pulling information from the realtime data source and publishing it to consumers slightly out of sync. If a GTFS Realtime consumer makes two back-to-back requests, and each request is served by a different GTFS Realtime feed instance, the same feed contents could potentially be returned to the consumer with different timestamps.

    *Possible solution* - Producers should provide a `Last-Modified` HTTP header, and consumers should pass their most recent `If-Modified-Since` HTTP header to avoid receiving stale data.

    *Possible solution* - If HTTP headers cannot be used, options such as sticky sessions can be used to ensure that each consumer is routed to the same producer server. | + +### FeedEntity + +All entities should only be removed from a GTFS Realtime feed when they are no longer relevant to users. Feeds are considered to be stateless, meaning that each feed reflects the entire real-time state of the transit system. If an entity is provided in one feed instance but dropped in a subsequent feed update, it should be assumed that there is no real-time information for that entity. + +| Field Name | Recommendation | +| --- | --- | +| `id` | Should be kept stable over the entire trip duration | + +### TripUpdate + +General guidelines for trip cancellations: + +* When canceling trips over a number of days, producers should provide TripUpdates referencing the given `trip_ids` and `start_dates` as `CANCELED` as well as an Alert with `NO_SERVICE` referencing the same `trip_ids` and `TimeRange` that can be shown to riders explaining the cancellation (e.g., detour). +* If no stops in a trip will be visited, the trip should be `CANCELED` instead of having all `stop_time_updates` being marked as `SKIPPED`. + +| Field Name | Recommendation | +| --- | --- | +| `trip` | Refer to [message TripDescriptor](#TripDescriptor). | +| | If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds.

    For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`. If any `TripUpdate` entity has `trip_id:4` and any `vehicle_id` other than 4, this is an error. | +| `vehicle` | Refer to [message VehicleDescriptor](#VehicleDescriptor). | +| | If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds.

    For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`. If any `TripUpdate` entity has `trip_id:4` and any `vehicle_id` other than 4, this is an error. | +| `stop_time_update` | `stop_time_updates` for a given `trip_id` should be strictly ordered by increasing `stop_sequence` and no `stop_sequence` should be repeated. | +| | While the trip is in progress, all `TripUpdates` should include at least one `stop_time_update` with a predicted arrival or departure time in the future. Note that the [GTFS Realtime spec](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/trip-updates.md#stop-time-updates) says that producers should not drop a past `StopTimeUpdate` if it refers to a stop with a scheduled arrival time in the future for the given trip (i.e. the vehicle has passed the stop ahead of schedule), as otherwise it will be concluded that there is no update for this stop. | +| `timestamp` | Should reflect the time this prediction for this trip was updated. | +| `delay` | `TripUpdate.delay` should represent schedule deviation, i.e., the observed past value for how ahead/behind schedule the vehicle is. Predictions for future stops should be provided through `StopTimeEvent.delay` or `StopTimeEvent.time`. | + +### TripDescriptor + +If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds. + +For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`. + +| Field Name | Recommendation | +| --- | --- | +| `schedule_relationship` | The behavior of `ADDED` trips are unspecified and the use of this enumeration is not recommended. | + +### VehicleDescriptor + +If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds. + +For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`. + +| Field Name | Recommendation | +| --- | --- | +| `id` | Should uniquely and stably identify a vehicle over the entire trip duration | + +### StopTimeUpdate + +| Field Name | Recommendation | +| --- | --- | +| `stop_sequence` | Provide `stop_sequence` whenever possible, as it unambiguously resolves to a GTFS stop time in `stop_times.txt` unlike `stop_id`, which can occur more than once in a trip (e.g., loop route). | +| `arrival` | Arrival times between sequential stops should increase - they should not be the same or decrease. | +| | Arrival `time` (specified in [StopTimeEvent](#StopTimeEvent)) should be before the departure `time` for the same stop if a layover or dwell time is expected - otherwise, arrival `time` should be be the same as departure `time`. | +| `departure` | Departure times between sequential stops should increase - they should not be the same or decrease. | +| | Departure `time` (specified in [StopTimeEvent](#StopTimeEvent)) should be the same as the arrival `time` for the same stop if no layover or dwell time is expected - otherwise, departure `time` should be after arrival `time` . | + +### StopTimeEvent + +| Field Name | Recommendation | +| --- | --- | +| `delay` | If only `delay` is provided in a `stop_time_update` `arrival` or `departure` (and not `time`), then the GTFS [`stop_times.txt`](https://gtfs.org/reference/static#stopstxt) should contain `arrival_times` and/or `departure_times` for these corresponding stops. A `delay` value in the realtime feed is meaningless unless you have a clock time to add it to in the GTFS `stop_times.txt` file. | + +### VehiclePosition + +Following are the recommended fields that should be included for a VehiclePostions feed to provide consumers with high-quality data (e.g., for generating predictions) + +| Field name | Notes | +| --- | --- | +| `entity.id` | Should be kept stable over the entire trip duration +| `vehicle.timestamp` | Providing the timestamp at which vehicle position was measured is strongly recommended. Otherwise, consumers must use the message timestamp, which can have misleading results for riders when the last message was updated more frequently than the individual position. +| `vehicle.vehicle.id` | Should uniquely and stably identify a vehicle over the entire trip duration | + +### Position + +The vehicle position should be within 200 meters of the GTFS `shapes.txt` data for the current trip unless there is an alert with the effect of `DETOUR` for this `trip_id`. + +### Alert + +General guidelines for alerts: + +* When `trip_id` and `start_time` are within `exact_time=1` interval, `start_time` should be later than the beginning of the interval by an exact multiple of `headway_secs`. +* When canceling trips over a number of days, producers should provide TripUpdates referencing the given `trip_ids` and `start_dates` as `CANCELED` as well as an Alert with `NO_SERVICE` referencing the same `trip_ids` and `TimeRange` that can be shown to riders explaining the cancellation (e.g., detour). +* If an alert affects all stops on a line, use a line-based alert instead of a stop-based alert. Do not apply the alert to every stop of the line. +* While there is no character limit for service alerts, transit riders will often be viewing alerts on mobile devices. Please be concise. + +| Field Name | Recommendation | +| --- | --- | +| `description_text` | Use line breaks to make your service alert easier to read. | + + +## Practice Recommendations Organized by Use Case + +### Frequency-based trips + +A frequency-based trip does not follow a fixed schedule but attempts to maintain predetermined headways. These trips are denoted in [GTFS frequency.txt](https://gtfs.org/reference/static/#frequenciestxt) by setting `exact_times=0` or omitting the `exact_times` field (note that `exact_times=1` trips are *NOT* frequency-based trips - `frequencies.txt` with `exact_times=1` is simply used as a convenience method for storing schedule-based trips in a more compact manner). There are several best practices to keep in mind when constructing GTFS Realtime feeds for frequency-based trips. + +* In [TripUpdate.StopTimeUpdate](#StopTimeUpdate), the [StopTimeEvent](#StopTimeEvent) for `arrival` and `departure` should not contain `delay` because frequency-based trips do not follow a fixed schedule. Instead, `time` should be provided to indicate arrival/departure predictions. + +* As required by the spec, when describing `trip` in [TripUpdate](#TripUpdate) or [VehiclePosition](#VehiclePosition) by using [TripDescriptor](#TripDescriptor), all of `trip_id`, `start_time`, and `start_date` must be provided. Additionally, `schedule_relationship` should be `UNSCHEDULED`. + (e.g., re-enforcement trips). + + ## About This Document + +### Objectives + +The objectives of these GTFS Best Practices are: + +* Support greater interoperability of transit data +* Improve end-user customer experience in public transportation apps +* Make it easier for software developers to deploy and scale applications, products, and services +* Facilitate the use of GTFS in various application categories (beyond its original focus on trip planning) + +### Contributing +New Best Practices are now being added directly into the [spec](https://gtfs.org/schedule/reference/) in order to gradually consolidate both documents. +If you'd like to suggest a new best practice, please go to the [GTFS Reference GitHub repository](https://github.com/google/transit/), [open an issue](https://github.com/google/transit/issues/new/choose) or create a Pull Request, or contact [specifications@mobilitydata.org](mailto:specifications@mobilitydata.org). + +### Linking to This Document + +Please link here in order to provide feed producers with guidance for correct formation of GTFS Realtime data. Each individual recommendation has an anchor link. Click the recommendation to get the URL for the in-page anchor link. + +If a GTFS Realtime-consuming application makes requirements or recommendations for GTFS Realtime data practices that are not described here, it is recommended to publish a document with those requirements or recommendations to supplement these common best practices. + diff --git a/gtfs/README.md b/gtfs/README.md index 7f67b9b1..1ef4e77c 100644 --- a/gtfs/README.md +++ b/gtfs/README.md @@ -1,5 +1,6 @@ -This directory contains GTFS Specification and documentation. +This directory contains the official General Transit Feed Specification (GTFS) Schedule reference documentation. ### Quick links -- [Documentation](spec/en) +- [GTFS Reference](spec/en) +- [GTFS Best Practices](best-practices) - [How to change the specification?](CHANGES.md) diff --git a/gtfs/best-practices/README.md b/gtfs/best-practices/README.md new file mode 100644 index 00000000..d991f849 --- /dev/null +++ b/gtfs/best-practices/README.md @@ -0,0 +1,21 @@ +# GTFS Schedule Best Practices + +These are recommended practices for describing public transportation services in the [GTFS Schedule Reference](../spec/en/reference.md) format. These complement the explicit recommendations outlined in the GTFS Schedule Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders. + +These practices have been synthesized from the experience of the [GTFS Best Practices working group members](https://gtfs.org/schedule/best-practices/#gtfs-best-practices-working-group) and application-specific GTFS practice recommendations. See the [FAQ](https://gtfs.org/schedule/best-practices/#frequently-asked-questions-faq) for more information. + +--- +⚠️ **NOTE: The GTFS Schedule Best Practices are in the process of being merged into the [GTFS Schedule Reference](../spec/en/reference.md) (see [issue #396](https://github.com/google/transit/issues/396) and [issue #451](https://github.com/google/transit/issues/451) for more information).** +**New Best Practices will be added directly to the GTFS Realtime Reference. If you'd like to suggest a new Best practice, you can:** +- **look at the existing [list of outstanding issues and PRs](https://github.com/google/transit/issues/421). If your new Best Practice idea is referenced on this list, comment on the issue** +- **[open a new issue](https://github.com/google/transit/issues/new/choose)** +- **open a Pull Request following the [GTFS Schedule Spec Amendment Process](https://gtfs.org/schedule/process/).** +--- + + +## Documentation Structure + +The GTFS Schedule Best Practices are written in Markdown and are organized by Message and by use case. + +* `field_name`: The name of the GTFS Schedule field being described +* `recommendations`: An array of the recommendations provided for each field_name diff --git a/gtfs/best-practices/best-practices.md b/gtfs/best-practices/best-practices.md new file mode 100644 index 00000000..011b35db --- /dev/null +++ b/gtfs/best-practices/best-practices.md @@ -0,0 +1,300 @@ +# GTFS Schedule Best Practices + +These are recommended practices for describing public transportation services in the [GTFS Schedule Reference](https://gtfs.org/schedule/reference/) format. These complement the explicit recommendations outlined in the GTFS Schedule Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders. + +These practices have been synthesized from the experience of the [GTFS Best Practices working group](#gtfs-best-practices-working-group) members and [application-specific GTFS practice recommendations](http://www.transitwiki.org/TransitWiki/index.php/Best_practices_for_creating_GTFS). + +For further background, see the [Frequently Asked Questions](#frequently-asked-questions-faq). + +## Document Structure + +Practices are organized into two primary sections: + +* __[Practice Recommendations Organized by File](#practice-recommendations-organized-by-file):__ Recommendations are organized by file and field in the GTFS to facilitate mapping practices back to the official GTFS reference. +* __[Practice Recommendations Organized by Case](#practice-recommendations-organized-by-case):__ With particular cases, such as loop routes, practices may need to be applied across several files and fields. Such recommendations are consolidated in this section. + +## Practice Recommendations Organized by File + +This section shows practices organized by file and field, aligning with the [GTFS reference](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md). + +### agency.txt + +| Field Name | Recommendation | +| --- | --- | +| `agency_phone` | Should be included unless no such customer service phone exists. | +| `agency_email` | Should be included unless no such customer service email exists. | +| `agency_fare_url` | Should be included unless the agency is fully fare-free. | + +__Examples:__ + +- Bus services are run by several small bus agencies. But there is one big agency that is responsible for scheduling and ticketing and from a user’s perspective responsible for the bus services.The one big agency should be defined as agency within the feed. Even if the data is split internally by different small bus operators there should only be one agency defined in the feed. + +- The feed provider runs the ticketing portal, but there are different agencies that actually operate the services and are known by users to be responsible. The agencies actually operating the services should be defined as agencies within the feed. + +### stops.txt + +| Field Name | Recommendation | +| --- | --- | +| `stop_name` | When there is not a published stop name, follow consistent stop naming conventions throughout the feed. | | +| | By default, `stop_name` should not contain generic or redundant words like “Station” or “Stop”, but some edge cases are allowed.
    • When it is actually part of the name (Union Station, Central Station
    • When the `stop_name` is too generic (such as if it is the name of the city). “Station”, “Terminal”, or other words make the meaning clear.
    | +| `stop_lat` & `stop_lon` | Stop locations should be as accurate possible. Stop locations should have an error of __no more__ than four meters when compared to the actual stop position. | +| | Stop locations should be placed very near to the pedestrian right of way where a passenger will board (i.e. correct side of the street). | +| | If a stop location is shared across separate data feeds (i.e. two agencies use exactly the same stop / boarding facility), indicate the stop is shared by using the exact same `stop_lat` and `stop_lon` for both stops. | +| `parent_station` & `location_type` | Many stations or terminals have multiple boarding facilities (depending on mode, they might be called a bus bay, platform, wharf, gate, or another term). In such cases, feed producers should describe stations, boarding facilities (also called child stops), and their relation.
    • The station or terminal should be defined as a record in `stops.txt` with `location_type = 1`.
    • Each boarding facility should be defined as a stop with `location_type = 0`. The `parent_station` field should reference the `stop_id` of the station the boarding facility is in.
    | +| | When naming the station and child stops, set names that are well-recognized by riders, and can help riders to identify the station and boarding facility (bus bay, platform, wharf, gate, etc.).
    Parent Station NameChild Stop Name
    Chicago Union StationChicago Union Station Platform 19
    San Francisco Ferry Building TerminalSan Francisco Ferry Building Terminal Gate E
    Downtown Transit CenterDowntown Transit Center Bay B
    | + +### routes.txt + +| Field Name | Recommendation | +| --- | --- | +| `route_long_name` | The definition from Specification reference: This name is generally more descriptive than the route_short_name and will often include the route's destination or stop. At least one of route_short_name or route_long_name must be specified, or potentially both if appropriate. If the route does not have a long name, please specify a route_short_name and use an empty string as the value for this field.
    Examples of types of long names are below:
    Primary Travel Path or Corridor
    Route NameFormAgency
    “N”/“Judah”route_short_name/
    route_long_name
    Muni, in San Francisco
    “6“/“ML King Jr Blvd“route_short_name/
    route_long_name
    TriMet, in Portland, Or.
    “6”/“Nation - Étoile”route_short_name/
    route_long_name
    RATP, in Paris France.
    “U2”-“Pankow – Ruhleben”route_short_name-
    route_long_name
    BVG, in Berlin, Germany
    Description of the Service
    “Hartwell Area Shuttle“
    +| | `route_long_name` should not contain the `route_short_name`. | +| | Include the full designation including a service identity when populating `route_long_name`. Examples:
    Service IdentityRecommendationExamples
    "MAX Light Rail"
    TriMet, in Portland, Oregon
    The route_long_name should include the brand (MAX) and the specific route designation"MAX Red Line" "MAX Blue Line"
    "Rapid Ride"
    ABQ Ride, in Albuquerque, New Mexico
    The route_long_name should include the brand (Rapid Ride) and the specific route designation"Rapid Ride Red Line"
    "Rapid Ride Blue Line"
    +| `route_id` | All trips on a given named route should reference the same `route_id`.
  • Different directions of a route should not be separated into different `route_id` values.
  • Different spans of operation of a route should not be separated into different `route_id` values. i.e. do not create different records in `routes.txt` for “Downtown AM” and “Downtown PM” services).
  • | +| | If a route group includes distinctly named branches (e.g. 1A and 1B), follow recommendations in the route [branches](#branches) case to determine `route_short_name` and `route_long_name`. | +| `route_color` & `route_text_color` | Should be consistent with signage and printed and online customer information (and thus not included if they do not exist in other places). | + +### trips.txt + +* __See special case for loop routes:__ Loop routes are cases where trips start and end at the same stop, as opposed to linear routes, which have two distinct termini. Loop routes must be described following specific practices. [See Loop route case.](#loop-routes) +* __See special case for lasso routes:__ Lasso routes are a hybrid of linear and loop geometries, in which vehicles travel on a loop for only a portion of the route. Lasso routes must be described following specific practices. [See Lasso route case.](#lasso-routes) + +| Field Name | Recommendation | +| --- | --- | +| `trip_headsign` | Do not provide route names (matching `route_short_name` and `route_long_name`) in the `trip_headsign` or `stop_headsign` fields. | +| | Should contain destination, direction, and/or other trip designation text shown on the headsign of the vehicle which may be used to distinguish amongst trips in a route. Consistency with direction information shown on the vehicle is the primary and overriding goal for determining headsigns supplied in GTFS datasets. Other information should be included only if it does not compromise this primary goal. If headsigns change during a trip, override `trip_headsign` with `stop_times.stop_headsign`. Below are recommendations for some possible cases: | +| |
    Route DescriptionRecommendation
    2A. Destination-onlyProvide the terminus destination. e.g. "Transit Center", “Portland City Center”, or “Jantzen Beach”>
    2B. Destinations with waypoints<destination> via <waypoint> “Highgate via Charing Cross”. If waypoint(s) are removed from the headsign show to passengers after the vehicle passes those waypoints, use stop_times.stop_headsign to set an updated headsign.>
    2C. Regional placename with local stopsIf there will be multiple stops inside the city or borough of destination, use stop_times.stop_headsign once reaching the destination city.>
    2D. Direction-onlyIndicate using terms such as “Northbound”, “Inbound”, “Clockwise,” or similar directions.>
    2E. Direction with destination<direction> to <terminus name> e.g. “Southbound to San Jose”>
    2F. Direction with destination and waypoints<direction> via <waypoint> to <destination> (“Northbound via Charing Cross to Highgate”).>
    | +| | Do not begin a headsign with the words “To” or “Towards”. | +| `direction_id` | Use values 0 and 1 consistently throughout the dataset. i.e.
    • If 1 = Outbound on the Red route, then 1 = Outbound on the Green route
    • If 1 = Northbound on Route X, then 1 = Northbound on Route Y
    • If 1 = clockwise on Route X then 1 = clockwise on Route Y
    | +| `bikes_allowed` | For ferry trips, be explicit about bikes being allowed (or not), as avoiding ferry trips due to missing data usually leads to big detours. | + +### stop_times.txt + +Loop routes: Loop routes require special `stop_times` considerations. (See: [Loop route case](#loop-routes)) + +| Field Name | Recommendation | +| --- | --- | +| `pickup_type` & `drop_off_type` | Non-revenue (deadhead) trips that do not provide passenger service should be marked with `pickup_type` and `drop_off_type` value of `1` for all `stop_times` rows. +| | On revenue trips, internal “timing points” for monitoring operational performance and other places such as garages that a passenger cannot board should be marked with `pickup_type = 1` (no pickup available) and `drop_off_type = 1` (no drop off available). | +| `arrival_time` & `departure_time` | `arrival_time` and `departure_time` fields should specify time values whenever possible, including non-binding estimated or interpolated times between timepoints. | +| `stop_headsign` | In general, headsign values should also correspond to signs in the stations.

    In the cases below, “Southbound” would mislead customers because it is not used in the station signs. +| |
    In NYC, for the 2 going Southbound:
    For stop_times.txt rows:Use stop_headsign value:
    Until Manhattan is ReachedManhattan & Brooklyn
    Until Downtown is ReachedDowntown & Brooklyn
    Until Brooklyn is ReachedBrooklyn
    Once Brooklyn is ReachedBrooklyn (New Lots Av)
    | +| |
    In Boston, for the Red Line going Southbound, for the Braintree branch:
    For stop_times.txt rows:Use stop_headsign value:
    Until Downtown is ReachedInbound to Braintree
    Once Downtown is ReachedBraintree
    After DowntownOutbound to Braintree
    | + +### calendar.txt + +| Field Name | Recommendation | +| --- | --- | +| All Fields | Including a `calendar.service_name` field can also increase the human readability of GTFS, although this is not adopted in the spec. | + +### calendar_dates.txt + +| Field Name | Recommendation | +| --- | --- | +| All Fields | Including a `calendar.service_name` field can also increase the human readability of GTFS, although this is not adopted in the spec.| + +### fare_attributes.txt + +| Field Name | Recommendation | +| --- | --- | +| | If a fare system cannot be accurately modeled, avoid further confusion and leave it blank. | +| | Include fares (`fare_attributes.txt` and `fare_rules.txt`) and model them as accurately as possible. In edge cases where fares cannot be accurately modeled, the fare should be represented as more expensive rather than less expensive so customers will not attempt to board with insufficient fare. If the vast majority of fares cannot be modeled correctly, do not include fare information in the feed. | + +### fare_rules.txt + +| Field Name | Recommendation | +| --- | --- | +| All Fields | If a fare system cannot be accurately modeled, avoid further confusion and leave it blank. | +| | Include fares (`fare_attributes.txt` and `fare_rules.txt`) and model them as accurately as possible. In edge cases where fares cannot be accurately modeled, the fare should be represented as more expensive rather than less expensive so customers will not attempt to board with insufficient fare. If the vast majority of fares cannot be modeled correctly, do not include fare information in the feed. | + +### shapes.txt + +| Field Name | Recommendation | +| --- | --- | +| All Fields | Ideally, for alignments that are shared (i.e. in a case where Routes 1 and 2 operate on the same segment of roadway or track) then the shared portion of alignment should match exactly. This helps to facilitate high-quality transit cartography. +| | Alignments should follow the centerline of the right of way on which the vehicle travels. This could be either the centerline of the street if there are no designated lanes, or the centerline of the side of the roadway that travels in the direction the vehicle moves.

    Alignments should not “jag” to a curb stop, platform, or boarding location. | +| `shape_dist_traveled` | The `shape_dist_traveled` field allows the agency to specify exactly how the stops in the `stop_times.txt` file fit into their respective shape. A common value to use for the `shape_dist_traveled` field is the distance from the beginning of the shape as traveled by the vehicle (think something like an odometer reading).
  • Route alignments (in `shapes.txt`) should be within 100 meters of stop locations which a trip serves.
  • Simplify alignments so that shapes.txt does not contain extraneous points (i.e. remove extra points on straight-line segments; see discussion of line simplification problem).
  • + +### frequencies.txt + +| Field Name | Recommendation | +| --- | --- | +| All Fields | Actual stop times are ignored for trips referenced by `frequencies.txt`; only travel time intervals between stops are significant for frequency-based trips. For clarity/human readability, it is recommended that the first stop time of a trip referenced in `frequencies.txt` should begin at 00:00:00 (first `arrival_time` value of 00:00:00). | +| `block_id` | Can be provided for frequency-based trips. | + +### transfers.txt + +`transfers.transfer_type` can be one of four values [defined in the GTFS](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md/#transferstxt). These `transfer_type` definitions are quoted from the GTFS Specification below, _in italics_, with additional practice recommendations. + +| Field Name | Recommendation | +| --- | --- | +| `transfer_type` | 0 or (empty): This is a recommended transfer point between routes.
    If there are multiple transfer opportunities that include a superior option (i.e. a transit center with additional amenities or a station with adjacent or connected boarding facilities/platforms), specify a recommended transfer point. | +| | 1: This is a timed transfer point between two routes. The departing vehicle is expected to wait for the arriving one, with sufficient time for a passenger to transfer between routes.
    This transfer type overrides a required interval to reliably make transfers. As an example, Google Maps assumes that passengers need 3 minutes to safely make a transfer. Other applications may assume other defaults. | +| | 2: This transfer requires a minimum amount of time between arrival and departure to ensure a connection. The time required to transfer is specified by min_transfer_time.
    Specify minimum transfer time if there are obstructions or other factors which increase the time to travel between stops. | +| | 3: Transfers are not possible between routes at this location.
    Specify this value if transfers are not possible because of physical barriers, or if they are made unsafe or complicated by difficult road crossings or gaps in the pedestrian network. | +| | If in-seat (block) transfers are allowed between trips, then the last stop of the arriving trip must be the same as the first stop of the departing trip. | + + +## Practice Recommendations Organized by Case + +This section covers particular cases with implications across files and fields. + +### Loop Routes + +On loop routes, vehicles’ trips begin and end at the same location (sometimes a transit or transfer center). Vehicles usually operate continuously and allow passengers to stay onboard as the vehicle continues its loop. + + + +Headsigns recommendations should therefore be applied in order to show riders the direction in which the vehicle is going. + +To indicate the changing direction of travel, provide `stop_headsigns` in the `stop_times.txt` file. The `stop_headsign` describes the direction for trips departing from the stop for which it's defined. Adding `stop_headsigns` to each stop of a trip allows you to change the headsign information along a trip. + +Don’t define one single circular trip in the stop_times.txt file for a route that operates between two endpoints (such as when the same bus goes back and forth). Instead, split the trip into two separate trip directions. + +__Examples of circular trip modeling:__ + +- Circular trip with changing headsign for each stop + +| trip_id | arrival_time | departure_time | stop_id | stop_sequence | stop_headsign | +|---------|--------------|----------------|---------|---------------|---------------| +| trip_1 | 06:10:00 | 06:10:00 | stop_A | 1 | "B" | +| trip_1 | 06:15:00 | 06:15:00 | stop_B | 2 | "C" | +| trip_1 | 06:20:00 | 06:20:00 | stop_C | 3 | "D" | +| trip_1 | 06:25:00 | 06:25:00 | stop_D | 4 | "E" | +| trip_1 | 06:30:00 | 06:30:00 | stop_E | 5 | "A" | +| trip_1 | 06:35:00 | 06:35:00 | stop_A | 6 | "" | + +- Circular trip with two headsigns + +| trip_id | arrival_time | departure_time | stop_id | stop_sequence | stop_headsign | +|---------|--------------|----------------|---------|---------------|---------------| +| trip_1 | 06:10:00 | 06:10:00 | stop_A | 1 | "outbound" | +| trip_1 | 06:15:00 | 06:15:00 | stop_B | 2 | "outbound" | +| trip_1 | 06:20:00 | 06:20:00 | stop_C | 3 | "outbound" | +| trip_1 | 06:25:00 | 06:25:00 | stop_D | 4 | "inbound" | +| trip_1 | 06:30:00 | 06:30:00 | stop_E | 5 | "inbound" | +| trip_1 | 06:35:00 | 06:35:00 | stop_F | 6 | "inbound" | +| trip_1 | 06:40:00 | 06:40:00 | stop_A | 7 | "" | + +| Field Name | Recommendation | +| --- | --- | +| `trips.trip_id `| Model the complete round-trip for the loop with a single trip. | +| `stop_times.stop_id` | Include the first/last stop twice in `stop_times.txt` for the trip that is a loop. Example below. Often, a loop route may include first and last trips that do not travel the entire loop. Include these trips as well.
    trip_idstop_idstop_sequence
    90001011
    90001022
    90001033
    90001014
    | +| `trips.direction_id` | If loop operates in opposite directions (i.e. clockwise and counterclockwise), then designate `direction_id` as `0` or `1`. | +| `trips.block_id` | Indicate continuous loop trips with the same `block_id`. | + +### Lasso Routes + +Lasso routes combine aspects of a loop route and directional route. + + + +| Examples: | +| -------- | +| Subway Routes ([Chicago](https://www.transitchicago.com/assets/1/6/ctamap_Lsystem.pdf)) | +| Bus Suburb to Downtown Routes ([St. Albert](https://stalbert.ca/uploads/PDF-infosheets/RideGuide-201-207_Revised_Oct_2017.pdf) or [Edmonton](http://webdocs.edmonton.ca/transit/route_schedules_and_maps/future/RT039.pdf)) | +| CTA Brown Line ([CTA Website](http://www.transitchicago.com/brownline/) and [TransitFeeds](https://transitfeeds.com/p/chicago-transit-authority/165/latest/route/Brn)) | + +| Field Name | Recommendation | +| --- | --- | +| `trips.trip_id` | The full extent of a “vehicle round-trip” (see illustration [above](#lasso-route-fig)) consists of travel from A to B to B and back to A. An entire vehicle round-trip may be expressed by:
  • A __single__ `trip_id` value/record in `trips.txt`
  • __Multiple__ `trip_id` values/records in `trips.txt`, with continuous travel indicated by `block_id`.
  • | +| `stop_times.stop_headsign` | The stops along the A-B section will be passed through in both directions. `stop_headsign` facilitates distinguishing travel direction. Therefore, providing `stop_headsign` is recommended for these trips.example_table:
    Examples:
    "A via B"
    "A"
    Chicago Transit Authority's Purple Line
    "Southbound to Loop"
    "Northbound via Loop"
    "Northbound to Linden"
    Edmonton Transit Service Bus Lines, here the 39
    "Rutherford"
    "Century Park"
    +| `trip.trip_headsign` | The trip headsign should be a global description of the trip, like displayed in the schedules. Could be “Linden to Linden via Loop” (Chicago example), or “A to A via B” (generic example). | + +### Branches + +Some routes may include branches. Alignment and stops are shared amongst these branches, but each also serves distinct stops and alignment sections. The relationship among branches may be indicated by route name(s), headsigns, and trip short name using the further guidelines below. + + + +| Field Name | Recommendation | +| --- | --- | +| All Fields | In naming branch routes, it is recommended to follow other passenger information materials. Below are descriptions and examples of two cases: | +| | If timetables and on-street signage represent two distinctly named routes (e.g. 1A and 1B), then present this as such in the GTFS, using the `route_short_name` and/or `route_long_name` fields. Example: GoDurham Transit [routes 2, 2A, and 2B](https://gotriangle.org/sites/default/files/brochure/godurham-route2-2a-2b_1.pdf) share a common alignment throughout the majority of the route, but they vary in several different aspects.
    • Route 2 is core service, running most hours.
    • Route 2 includes a deviation on Main Street nights, Sundays, and holidays.
    • Routes 2A and 2B operate daytime hours Monday through Saturday.
    • Route 2B serves additional stops in a deviation of the shared alignment path.
    | +| | If agency-provided information describes branches as the same named route, then utilize the `trips.trip_headsign`, `stop_times.stop_headsign`, and/or `trips.trip_short_name` fields. Example: GoTriangle [route 300](https://gotriangle.org/sites/default/files/route_300_v.1.19.pdf) travels to different locations depending on the time of day. During peak commuter hours extra legs are added onto the standard route to accommodate workers entering and leaving the city. | + +## Frequently Asked Questions (FAQ) + +### Why are these GTFS Best Practices important? + +The objectives of GTFS Best Practices are: + +* To improve end-user customer experience in public transportation apps +* Support broad data interoperability to make it easier for software developers to deploy and scale applications, products, and services +* Facilitate the use of GTFS in various application categories (beyond its original focus on trip planning) + +Without coordinated GTFS Best Practices, various GTFS-consuming applications may establish requirements and expectations in an uncoordinated way, which leads to diverging requirements and application-specific datasets and less interoperability. Prior to the release of the Best Practices, there was greater ambiguity and disagreement in what constitutes correctly-formed GTFS data. + +### How were they developed? Who developed them? + +These Best Practices were developed by a working group of 17 organizations involved in GTFS, including app providers & data consumers, transit providers, and consultants with extensive involvement in GTFS. The working group was convened and facilitated by [Rocky Mountain Institute](http://www.rmi.org/mobility). + +Working Group members voted on each Best Practice. Most Best Practices were approved by a unanimous vote. In a minority of cases, Best Practices were approved a large majority of organizations. + +Some GTFS Best Practices have been merged into the spec and have been removed from this document. + +### Why not change the GTFS Reference directly? + +Good question! +The process of examining the Specification, data usage and needs did indeed trigger some changes to the Specification. +The Best Practices were created to bring everyone's understanding of the spec into harmony with the intention for some to be added into the spec and undergo the larger governance process, and others to be moved into a "how-to" guide. +Since then, some Best Practices have been added into the spec based on their level of adoption and community consensus. +To contribute to this effort, please go to the [GTFS Reference GitHub repository](https://github.com/google/transit/), or contact [specifications@mobilitydata.org](mailto:specifications@mobilitydata.org). + +### How to check for conformance with these Best Practices? + +The Canonical GTFS Schedule Validator checks for compliance against the GTFS Best Practices that can be automatically verified. Each [warning](https://gtfs-validator.mobilitydata.org/rules.html#WARNING-table) corresponds to recommendations that are either explicitly suggested by the GTFS Schedule Reference, using the term “recommend” or “should,” or mentioned in this document. +You can find more about this validation tool on the [validate page](https://gtfs.org/schedule/validate/). + +### I represent a transit agency. What steps can I take so that our software service providers and vendors follow these Best Practices? + +Refer your vendor or software service provider to these Best Practices. We recommend referencing the GTFS Best Practices URL, as well as core Spec Reference in procurement for GTFS-producing software. + +### What should I do if I notice a GTFS data feed does not conform to the GTFS Best Practices? + +Identify the contact for the feed, using the `feed_contact_email` or `feed_contact_url` fields in [feed_info.txt](https://gtfs.org/schedule/reference/#feed_infotxt) if they are provided, or looking up contact information on the transit agency or feed producer website. When communicating the issue to the feed producer, link to the specific GTFS Best Practice that isn't being followed using this document (See ["Linking to this Document"](#linking-to-this-document)) or [the appropriate warning](https://gtfs-validator.mobilitydata.org/rules.html#WARNING-table) in the Canonical GTFS Schedule Validator if available. + +### How to propose new Best Practices? + +New Best Practices are now being added directly into the [spec](https://gtfs.org/schedule/reference/) in order to gradually consolidate both documents. +If you'd like to suggest a new best practice, please go to the [GTFS Reference GitHub repository](https://github.com/google/transit/), [open an issue](https://github.com/google/transit/issues/new/choose) or create a Pull Request, or contact [specifications@mobilitydata.org](mailto:specifications@mobilitydata.org). + +## About This Document + +### Objectives + +The objectives of these GTFS Best Practices are: + +* Support greater interoperability of transit data +* Improve end-user customer experience in public transportation apps +* Make it easier for software developers to deploy and scale applications, products, and services +* Facilitate the use of GTFS in various application categories (beyond its original focus on trip planning) + +### Linking to This Document + +Please link here in order to provide feed producers with guidance for correct formation of GTFS data. Each individual recommendation has an anchor link. Click the recommendation to get the URL for the in-page anchor link. + +If a GTFS-consuming application makes requirements or recommendations for GTFS data practices that are not described here, it is recommended to publish a document with those requirements or recommendations to supplement these common best practices. + +### GTFS Best Practices Working Group + +The GTFS Best Practices Working Group was convened by [Rocky Mountain Institute](http://rmi.org/) in 2016-17, consisting of public transportation providers, developers of GTFS-consuming applications, consultants, and academic organizations to define common practices and expectations for GTFS data. +Members of this working group included: + +* [Cambridge Systematics](https://www.camsys.com/) +* [Capital Metro](https://www.capmetro.org/) +* [Center for Urban Transportation Research at University of South Florida](https://www.cutr.usf.edu/) +* [Conveyal](http://conveyal.com/) +* [Google](https://www.google.com/) +* [IBI Group](http://www.ibigroup.com/) +* [Mapzen](https://mapzen.com/) +* [Microsoft](https://www.microsoft.com/) +* [Moovel](https://www.moovel.com/) +* [Oregon Department of Transportation](http://www.oregon.gov/odot/) +* [Swiftly](https://goswift.ly/) +* [Transit](https://transitapp.com/) +* [Trillium](http://trilliumtransit.com/) +* [TriMet](https://trimet.org/) +* [World Bank](http://www.worldbank.org/) + +Today, this document is maintained by [MobilityData](http://mobilitydata.org/). diff --git a/gtfs/best-practices/images/branching.svg b/gtfs/best-practices/images/branching.svg new file mode 100644 index 00000000..5347f2b1 --- /dev/null +++ b/gtfs/best-practices/images/branching.svg @@ -0,0 +1 @@ +Deviation branchMultiple terminiExtension branch \ No newline at end of file diff --git a/gtfs/best-practices/images/inlining.svg b/gtfs/best-practices/images/inlining.svg new file mode 100755 index 00000000..616575da --- /dev/null +++ b/gtfs/best-practices/images/inlining.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gtfs/best-practices/images/lasso-route.svg b/gtfs/best-practices/images/lasso-route.svg new file mode 100755 index 00000000..7c32dff6 --- /dev/null +++ b/gtfs/best-practices/images/lasso-route.svg @@ -0,0 +1 @@ +AB \ No newline at end of file diff --git a/gtfs/best-practices/images/loop-route.svg b/gtfs/best-practices/images/loop-route.svg new file mode 100755 index 00000000..def8b9e3 --- /dev/null +++ b/gtfs/best-practices/images/loop-route.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gtfs/best-practices/images/rmi-small.png b/gtfs/best-practices/images/rmi-small.png new file mode 100644 index 0000000000000000000000000000000000000000..e2d65e39218d5ba4271929039eb0f131639406df GIT binary patch literal 7868 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 nv%0++hx)bVg_64u52s~guYl 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 Date: Wed, 15 May 2024 23:02:19 -0400 Subject: [PATCH 15/16] Editorial changes (#453) --- gtfs/spec/en/reference.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index ab7eff4f..2e52518a 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -285,7 +285,7 @@ Primary key (`trip_id`, `stop_sequence`) | ------ | ------ | ------ | ------ | | `trip_id` | Foreign ID referencing `trips.trip_id` | **Required** | Identifies a trip. | | `arrival_time` | Time | **Conditionally Required** | Arrival time at the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for the first and last stop in a trip (defined by `stop_times.stop_sequence`).
    - **Required** for `timepoint=1`.
    - **Forbidden** when `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise.| -| `departure_time` | Time | **Conditionally Required** | Departure time from the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for `timepoint=1`.
    - **Forbidden** when `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise.| | +| `departure_time` | Time | **Conditionally Required** | Departure time from the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

    If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

    For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

    If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

    Conditionally Required:
    - **Required** for `timepoint=1`.
    - **Forbidden** when `start_pickup_drop_off_window` or `end_pickup_drop_off_window` are defined.
    - Optional otherwise. | | `stop_id` | Foreign ID referencing `stops.stop_id` | **Conditionally Required** | Identifies the serviced stop. All stops serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Referenced locations must be stops/platforms, i.e. their `stops.location_type` value must be `0` or empty. A stop may be serviced multiple times in the same trip, and multiple trips and routes may service the same stop.

    On-demand service using stops should be referenced in the sequence in which service is available at those stops. A data consumer should assume that travel is possible from one stop or location to any stop or location later in the trip, provided that the `pickup/drop_off_type` of each stop_time and the time constraints of each `start/end_pickup_drop_off_window` do not forbid it.

    Conditionally Required:
    - **Required** if `stop_times.location_group_id` AND `stop_times.location_id` are NOT defined.
    - **Forbidden** if `stop_times.location_group_id` or `stop_times.location_id` are defined. | | `location_group_id` | Foreign ID referencing `location_groups.location_group_id` | **Conditionally Forbidden** | Identifies the serviced location group that indicates groups of stops where riders may request pickup or drop off. All location groups serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Multiple trips and routes may service the same location group.

    On-demand service using location groups should be referenced in the sequence in which service is available at those location groups. A data consumer should assume that travel is possible from one stop or location to any stop or location later in the trip, provided that the `pickup/drop_off_type` of each stop_time and the time constraints of each `start/end_pickup_drop_off_window` do not forbid it.

    **Conditionally Forbidden**:
    - **Forbidden** if `stop_times.stop_id` or `stop_times.location_id` are defined. | | `location_id` | Foreign ID referencing `id` from `locations.geojson` | **Conditionally Forbidden** | Identifies the GeoJSON location that corresponds to serviced zone where riders may request pickup or drop off. All GeoJSON locations serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Multiple trips and routes may service the same GeoJSON location.

    On-demand service within locations should be referenced in the sequence in which service is available in those locations. A data consumer should assume that travel is possible from one stop or location to any stop or location later in the trip, provided that the `pickup/drop_off_type` of each stop_time and the time constraints of each `start/end_pickup_drop_off_window` do not forbid it.

    **Conditionally Forbidden**:
    - **Forbidden** if `stop_times.stop_id` or `stop_times.location_group_id` are defined. | @@ -389,7 +389,7 @@ For examples that demonstrate how to specify a fare structure with [fare_rules.t File: **Optional** -Primary key (*) +Primary key (`*`) Used to describe fares that can vary based on the time of day, the day of the week, or a particular day in the year. Timeframes can be associated with fare products in [fare_leg_rules.txt](#fare_leg_rulestxt).
    There must not be overlapping time intervals for the same `timeframe_group_id` and `service_id` values. @@ -410,7 +410,7 @@ There must not be overlapping time intervals for the same `timeframe_group_id` a File: **Optional** -Primary Key (`fare_media_id`) +Primary key (`fare_media_id`) To describe the different fare media that can be employed to use fare products. Fare media are physical or virtual holders used for the representation and/or validation of a fare product. @@ -424,7 +424,7 @@ To describe the different fare media that can be employed to use fare products. File: **Optional** -Primary Key (`fare_product_id`, `fare_media_id`) +Primary key (`fare_product_id`, `fare_media_id`) Used to describe the range of fares available for purchase by riders or taken into account when computing the total fare for journeys with multiple legs, such as transfer costs. @@ -441,7 +441,7 @@ Used to describe the range of fares available for purchase by riders or taken in File: **Optional** -Primary Key (`network_id, from_area_id, to_area_id, from_timeframe_group_id, to_timeframe_group_id, fare_product_id`) +Primary key (`network_id, from_area_id, to_area_id, from_timeframe_group_id, to_timeframe_group_id, fare_product_id`) Fare rules for individual legs of travel. @@ -484,7 +484,7 @@ To process the cost of a leg: File: **Optional** -Primary Key (`from_leg_group_id, to_leg_group_id, fare_product_id, transfer_count, duration_limit`) +Primary key (`from_leg_group_id, to_leg_group_id, fare_product_id, transfer_count, duration_limit`) Fare rules for transfers between legs of travel defined in [`fare_leg_rules.txt`](#fare_leg_rulestxt). @@ -713,7 +713,7 @@ Primary key (`location_group_id`) Defines location groups, which are groups of stops where a rider may request pickup or drop off. -| Field Name | Type | Required | Description | +| Field Name | Type | Presence | Description | | ---------- | ---- | ------------ | ----------- | | `location_group_id` | Unique ID | **Required** | Identifies a location group. ID must be unique across all `stops.stop_id`, locations.geojson `id`, and `location_groups.location_group_id` values.

    A location group is a group of stops that together indicate locations where a rider may request pickup or drop off. | | `location_group_name` | Text | Optional | The name of the location group as displayed to the rider. | @@ -726,7 +726,7 @@ Primary key (`*`) Assigns stops from stops.txt to location groups. -| Field Name | Type | Required | Description | +| Field Name | Type | Presence | Description | | ---------- | ---- | ------------ | ----------- | | `location_group_id` | Foreign ID referencing `location_groups.location_group_id` | **Required** | Identifies a location group to which one or multiple `stop_id`s belong. The same `stop_id` may be defined in many `location_group_id`s. | | `stop_id` | Foreign ID referencing `stops.stop_id` | **Required** | Identifies a stop belonging to the location group. | From 94c1a2329e7a1daed20242d096aa2720077ebd6c Mon Sep 17 00:00:00 2001 From: isabelle-dr Date: Wed, 22 May 2024 04:15:25 -0400 Subject: [PATCH 16/16] Fix formatting of bulletpoints in RT spec (#456) --- gtfs-realtime/spec/en/reference.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gtfs-realtime/spec/en/reference.md b/gtfs-realtime/spec/en/reference.md index ed4c4213..801762be 100644 --- a/gtfs-realtime/spec/en/reference.md +++ b/gtfs-realtime/spec/en/reference.md @@ -149,6 +149,7 @@ Depending on the value of ScheduleRelationship, a TripUpdate can specify: The updates can be for future, predicted arrival/departure events, or for past events that already occurred. In most cases information about past events is a measured value thus its uncertainty value is recommended to be 0\. Although there could be cases when this does not hold so it is allowed to have uncertainty value different from 0 for past events. If an update's uncertainty is not 0, either the update is an approximate prediction for a trip that has not completed or the measurement is not precise or the update was a prediction for the past that has not been verified after the event occurred. If a vehicle is serving multiple trips within the same block (for more information about trips and blocks, please refer to [GTFS trips.txt](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#tripstxt)): + * the feed should include a TripUpdate for the trip currently being served by the vehicle. Producers are encouraged to include TripUpdates for one or more trips after the current trip in this vehicle's block if the producer is confident in the quality of the predictions for these future trip(s). Including multiple TripUpdates for the same vehicle avoids prediction "pop-in" for riders as the vehicle transitions from one trip to another and also gives riders advance notice of delays that impact downstream trips (e.g., when the known delay exceeds planned layover times between trips). * the respective TripUpdate entities are not required to be added to the feed in the same order that they are scheduled in the block. For example, if there are trips with `trip_ids` 1, 2, and 3 that all belong to one block, and the vehicle travels trip 1, then trip 2, and then trip 3, the `trip_update` entities may appear in any order - for example, adding trip 2, then trip 1, and then trip 3 is allowed. @@ -437,6 +438,7 @@ A geographic position of a vehicle. A descriptor that identifies a single instance of a GTFS trip. To specify a single trip instance, in many cases a `trip_id` by itself is sufficient. However, the following cases require additional information to resolve to a single trip instance: + * For trips defined in frequencies.txt, `start_date` and `start_time` are required in addition to `trip_id` * If the trip lasts for more than 24 hours, or is delayed such that it would collide with a scheduled trip on the following day, then `start_date` is required in addition to `trip_id` * If the `trip_id` field can't be provided, then `route_id`, `direction_id`, `start_date`, and `start_time` must all be provided