Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

remove run_events.trip_service_id from spec and trim examples #2

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 42 additions & 206 deletions docs/spec/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,28 +171,30 @@ weekday,10000,30,BLOCK-A,deadhead ,,stop-1,12:00:00,garage,12:10:00

## Distinct Crew and Trip schedule scenarios

The below examples identify how to use the distinct `trip_service_id` feature of `run_events.txt` to model instances in which crew schedules may be decoupled from trips, forming a many:1 relationship of runs and trips.
These examples show situations where the crew schedules in `run_events.txt` use different service IDs than the trips they work on, as is allowed by [the spec](/docs/spec/#service_id-crew-schedules-and-trip-schedules). Most agencies will not need to model a situation like this.

In all these cases, the trips and service IDs in the public GTFS file are not modified. New service IDs are created in the calendar supplement files, and runs that operate on those dates are described in `run_events.txt`.

### Extra staffing for a special event

Due to a baseball game, an additional ticket collector will be assigned to supplement the existing crew on train 101, serving the ballpark.

#### `run_events.txt`
#### `calendar.txt`

_Note that the `run_id` of 1 maps to the combination of `(service_id, trip_service_id)`, meaning other runs with the same `run_id` of `1` can be in effect at the same time provided they existin other combinations of `(service_id, trip_service_id)`._

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below, but I think this is an important note to reiterate; perhaps this should be moved below, though?

The key thing I want to avoid is a consumer thinking the feed is broken because there are two versions of run_id = 1, each of which have different service_id values, though.

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
weekday,1,1,1,1,1,0,0,20240101,20241231
```

#### `trips.txt`

```csv
service_id,trip_service_id,run_id,event_sequence,event_type,trip_id,start_location,start_time,end_location,end_time
gameday,weekday,1,1,signup,,main_terminal,14:00:00,main_terminal,14:15:00
gameday,weekday,1,2,collector,train_101,main_terminal,14:45:00,ballpark,15:30:00
gameday,weekday,1,3,work_as_directed,train_101,ballpark,15:30:00,main_terminal,22:00:00
gameday,weekday,1,4,signoff,,main_terminal,22:00:00,main_terminal,22:15:00
route_id,service_id,trip_id,block_id
route,weekday,101,BLOCK-A
```

#### `calendar_dates_supplement.txt`

The added position can be added on the applicable gamedays via `calendar_dates_supplement.txt`.

```csv
service_id,date,exception_type
gameday,20240820,1
Expand All @@ -201,134 +203,41 @@ gameday,20240827,1
gameday,20240903,1
```

### Different runs mapping to the same set of trips

Consider a bus network between West City, Eastland, and Northingdon. Route 1 runs between West City and Eastland via Northingdon, whereas Route 2 runs directly between the two cities.

To improve on-time performance, the driver working the 10:45am Route 1 departure and the driver of the 11am Route 2 departure will exchange these trips effective September 2024.

#### `trips.txt`

```csv
route_id,service_id,trip_id,trip_headsign,direction_id
1,weekday,10001,Eastland via Northingdon,1
2,weekday,20001,Eastland,1
1,weekday,10002,West City via Northingdon,0
2,weekday,20002,West City,0
```

#### `calendar.txt`

Assume these trips run daily on weekdays in the defined date range.

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
weekday,1,1,1,1,1,0,0,20240101,20241231
```

#### `run_events.txt`

The current runs can be modeled with service_id `current`, and mapped to the existing `weekday` trips. The future runs can be modeled with service_id `future`, also mapped to the existing `weekday` trips. The service_id `weekday` is already defined in `calendar.txt`, but neither `current` nor `future` are.

```csv
service_id ,trip_service_id ,run_id ,event_sequence ,block_id ,event_type ,trip_id ,start_location ,start_time ,end_location ,end_time
current ,weekday ,1 ,10 ,A ,report , ,garage ,08:00:00 ,garage ,08:20:00
current ,weekday ,1 ,20 ,A ,drive ,10001 ,westcity ,09:00:00 ,eastland ,10:30:00
current ,weekday ,1 ,30 ,A ,drive ,10002 ,eastland ,10:45:00 ,westcity ,12:15:00
current ,weekday ,1 ,40 ,A ,signoff , ,garage ,12:45:00 ,garage ,13:00:00

current ,weekday ,2 ,10 ,B ,report , ,garage ,08:00:00 ,garage ,08:20:00
current ,weekday ,2 ,20 ,B ,drive ,20001 ,westcity ,09:00:00 ,eastland ,10:00:00
current ,weekday ,2 ,30 ,B ,drive ,20002 ,eastland ,11:00:00 ,westcity ,12:00:00
current ,weekday ,2 ,40 ,B ,signoff , ,garage ,12:30:00 ,garage ,12:45:00

future ,weekday ,1 ,10 ,A ,report , ,garage ,08:00:00 ,garage ,08:20:00
future ,weekday ,1 ,20 ,A ,drive ,10001 ,westcity ,09:00:00 ,eastland ,10:30:00
future ,weekday ,1 ,30 ,A ,drive ,20002 ,eastland ,11:00:00 ,westcity ,12:00:00
future ,weekday ,1 ,40 ,A ,signoff , ,garage ,12:30:00 ,garage ,12:45:00

future ,weekday ,2 ,10 ,B ,report , ,garage ,08:00:00 ,garage ,08:20:00
future ,weekday ,2 ,20 ,B ,drive ,20001 ,westcity ,09:00:00 ,eastland ,10:00:00
future ,weekday ,2 ,30 ,B ,drive ,10002 ,eastland ,10:45:00 ,westcity ,12:15:00
future ,weekday ,2 ,40 ,B ,signoff , ,garage ,12:45:00 ,garage ,13:00:00
service_id,run_id,event_sequence,block_id,job_type,event_type,trip_id,start_location,start_time,end_location,end_time
weekday,1,1, ,collector,sign-in , ,main_terminal,14:00:00,main_terminal,14:15:00
weekday,1,2,BLOCK-A,collector,collector ,101,main_terminal,14:45:00,ballpark ,15:30:00
gameday,2,1, ,collector,sign-in , ,main_terminal,14:00:00,main_terminal,14:15:00
jeffkessler-keolis marked this conversation as resolved.
Show resolved Hide resolved
gameday,2,2,BLOCK-A,collector,extra collector,101,main_terminal,14:45:00,ballpark ,15:30:00
```

#### `calendar_supplement.txt`
### Trip worked by different runs on different dates

To detail the presence of the new `service_id`s and assign them to their applicable days of the week, the runs can be added to the calendar via `calendar_supplement.txt`:

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
current,1,1,1,1,1,0,0,20240101,20240831
future ,1,1,1,1,1,0,0,20240901,20241231
```

### Variations of runs by day of the week

Consider a commuter train line that operates three daily round-trips: two morning inbound trains from the suburbs to the city, two evening return trips from the city to the suburbs, plus one reverse-peak trip for day-trippers to the outlying village and back.

Every day, the same six trips are operated from the public perspective, with the crew of the earlier morning inbound rush-hour trip always working the earlier evening outbound rush-hour trip (trains 102 and 101, respectively), and the other crew working the later of the two (trains 104 and 103, respectively). To more evenly distribute fatigue and rest, the midday round-trip (trains 191 and 192) is split between the early and late crews by day-of-week, and switching halfway through the year. Whichever crew works the midday trip takes their break in the suburban village, whereas the other crew takes their break in the city.
Consider a bus network between West City, Eastland, and Northingdon. Route 1 runs between West City and Eastland via Northingdon, whereas Route 2 runs directly between the two cities.

#### `trips.txt`
To lengthen a short layover and improve on-time performance, the driver working the 10:45am Route 1 departure and the driver of the 11am Route 2 departure will exchange these trips effective September 2024.

Rather than listing these trips as varying by day-of-week in a public-facing schedule, these can indeed be maintained as a single service_id in `trips.txt`.
The public-facing schedule will not change. The trips remain on the service `weekday`. The runs are scheduled on new services `summer` and `fall`, which together cover all of the dates in `weekday`.

```csv
route_id,service_id,trip_id,trip_headsign,direction_id,trip_short_name
commuter_line,spring_train_schedule,spring-city_train_102,City ,1,102
commuter_line,spring_train_schedule,spring-city_train_104,City ,1,104
commuter_line,spring_train_schedule,spring-city_train_191,Suburbs,0,191
commuter_line,spring_train_schedule,spring-city_train_192,City ,1,192
commuter_line,spring_train_schedule,spring-city_train_101,Suburbs,0,101
commuter_line,spring_train_schedule,spring-city_train_103,Suburbs,0,103
```
![Diagram showing four trips on two runs, with the assignments rearranged in the fall.](different-runs-same-trips.png)

#### `calendar.txt`

Assume these trips run daily on weekdays in the defined date range.

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
spring_train_schedule,1,1,1,1,1,0,0,20240101,20241231
weekday,1,1,1,1,1,0,0,20240601,20241231
```

#### `run_events.txt`

The individual runs can be broken into two run-based service_ids: `spring_train_latelong` represents the days where the late job works the midday trip (and has its break in the village), whereas `spring_train_earlylong` represents the days where the early job works the midday trip.

Note that in all circumstances, the trips all reference those with `service_id` matching `spring_train_schedule`; there are not any trips defined under `service_id` `spring_train_latelong` nor `spring_train_earlylong`.
#### `trips.txt`

```csv
service_id,trip_service_id,run_id,event_sequence,block_id,event_type,trip_id,start_location,start_time,end_location,end_time

spring_train_latelong ,spring_train_schedule,early_job,10,BLOCK-A,sign-in , ,yard ,06:00:00,yard ,06:15:00
spring_train_latelong ,spring_train_schedule,early_job,20,BLOCK-A,conductor,spring-city_train_102,village,06:30:00,city ,07:30:00
spring_train_latelong ,spring_train_schedule,early_job,30,BLOCK-A,release , ,city ,07:45:00,city ,16:00:00
spring_train_latelong ,spring_train_schedule,early_job,40,BLOCK-A,conductor,spring-city_train_101,city ,16:30:00,village,17:30:00
spring_train_latelong ,spring_train_schedule,early_job,50,BLOCK-A,sign-off , ,yard ,17:30:00,yard ,17:45:00

spring_train_latelong ,spring_train_schedule,later_job,10,BLOCK-B,sign-in , ,yard ,07:00:00,yard ,07:15:00
spring_train_latelong ,spring_train_schedule,later_job,20,BLOCK-B,conductor,spring-city_train_104,village,07:30:00,city ,08:30:00
spring_train_latelong ,spring_train_schedule,later_job,30,BLOCK-B,conductor,spring-city_train_191,city ,09:00:00,village,10:00:00
spring_train_latelong ,spring_train_schedule,later_job,40,BLOCK-B,break , ,village,10:00:00,village,15:00:00
spring_train_latelong ,spring_train_schedule,later_job,50,BLOCK-B,conductor,spring-city_train_190,village,15:00:00,city ,16:00:00
spring_train_latelong ,spring_train_schedule,later_job,60,BLOCK-B,conductor,spring-city_train_103,city ,17:30:00,village,18:30:00
spring_train_latelong ,spring_train_schedule,later_job,70,BLOCK-B,sign-off , ,yard ,18:30:00,yard ,18:45:00

spring_train_earlylong,spring_train_schedule,early_job,10,BLOCK-A,sign-in , ,yard ,06:00:00,yard ,06:15:00
spring_train_earlylong,spring_train_schedule,early_job,20,BLOCK-A,conductor,spring-city_train_102,village,06:30:00,city ,07:30:00
spring_train_earlylong,spring_train_schedule,early_job,30,BLOCK-A,conductor,spring-city_train_191,city ,09:00:00,village,10:00:00
spring_train_earlylong,spring_train_schedule,early_job,40,BLOCK-A,break , ,village,10:00:00,village,15:00:00
spring_train_earlylong,spring_train_schedule,early_job,50,BLOCK-A,conductor,spring-city_train_190,village,15:00:00,city ,16:00:00
spring_train_earlylong,spring_train_schedule,early_job,60,BLOCK-A,conductor,spring-city_train_101,city ,16:30:00,village,17:30:00
spring_train_earlylong,spring_train_schedule,early_job,70,BLOCK-A,sign-off , ,yard ,17:30:00,yard ,17:45:00

spring_train_earlylong,spring_train_schedule,later_job,10,BLOCK-B,sign-in , ,yard ,07:00:00,yard ,07:15:00
spring_train_earlylong,spring_train_schedule,later_job,20,BLOCK-B,conductor,spring-city_train_104,village,07:30:00,city ,08:30:00
spring_train_earlylong,spring_train_schedule,later_job,30,BLOCK-B,release , ,city ,08:45:00,city ,17:00:00
spring_train_earlylong,spring_train_schedule,later_job,40,BLOCK-B,conductor,spring-city_train_103,city ,17:30:00,village,18:30:00
spring_train_earlylong,spring_train_schedule,later_job,50,BLOCK-B,sign-off , ,yard ,18:30:00,yard ,18:45:00

route_id,service_id,trip_id,trip_headsign,direction_id
1,weekday,101,Eastland via Northingdon,1
2,weekday,201,Eastland,1
1,weekday,102,West City via Northingdon,0
2,weekday,202,West City,0
```

#### `calendar_supplement.txt`
Expand All @@ -337,100 +246,27 @@ To detail the presence of the new `service_id`s and assign them to their applica

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
spring_train_latelong ,1,0,1,0,1,0,0,20240101,20240630
spring_train_earlylong,0,1,0,1,0,0,0,20240101,20240630
spring_train_earlylong,1,0,1,0,1,0,0,20240701,20241231
spring_train_latelong ,0,1,0,1,0,0,0,20240701,20241231
```

### Jobs of entirely nonrevenue operations

A special track inspection train is being operated on a particular day, supported by an extra crew position.

_Note: The deadhead trips themselves could be defined in their own new `service_id` even without definining corresponding run data in `run_events.txt` using the `calendar_supplement.txt` or `calendar_dates_supplement.txt` files._

#### `trips_supplement.txt`

```csv
route_id,service_id,trip_id,TODS_trip_type,direction_id
line1,inspection_train,inspection_line1_ob,deadhead,0
line1,inspection_train,inspection_line1_ib,deadhead,1
line1,inspection_train,inspection_line2_ob,deadhead,0
line1,inspection_train,inspection_line2_ib,deadhead,1
line1,inspection_train,inspection_line3_ob,deadhead,0
line1,inspection_train,inspection_line3_ib,deadhead,1
```

#### `stop_times_supplement.txt`

```csv
trip_id,arrival_time,stop_id
inspection_line1_ob,downtown,08:00:00
inspection_line1_ob,anytown,09:00:00
inspection_line1_ib,anytown,09:15:00
inspection_line1_ib,downtown,10:15:00
inspection_line2_ob,downtown,11:00:00
inspection_line2_ob,busyville,12:30:00
inspection_line2_ib,busyville,13:00:00
inspection_line2_ib,downtown,14:30:00
inspection_line3_ob,downtown,15:00:00
inspection_line3_ob,centerton,15:45:00
inspection_line3_ib,centerton,16:00:00
inspection_line3_ib,downtown,16:45:00
```

#### `calendar_dates_supplement.txt`

```csv
service_id,date,exception_type
inspection_train,20240901

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like the idea of including this as an example, because I think this is a big use case for the distinct TODS-specific modeling of non-public trips. That said, we could certainly cut this down to two trips of two stop_times each to simplify things. But open to cutting if the rest of the working group believes it to not be worthwhile.

summer,1,1,1,1,1,0,0,20240601,20240831
fall ,1,1,1,1,1,0,0,20240901,20241231
```

#### `run_events.txt`

Here a run can be defined alongside entirely deadhead trips added via `trips_supplement.txt` using the same `service_id` defined and assigned in `calendar_dates_supplement.txt`.
The current runs can be modeled with service_id `summer`, and mapped to the existing `weekday` trips. The future runs can be modeled with service_id `fall`, also mapped to the existing `weekday` trips. The service_id `weekday` is already defined in `calendar.txt`, but neither `summer` nor `fall` are.

```csv
service_id,run_id,event_sequence,event_type,trip_id,start_location,start_time,end_location,end_time
inspection_train ,1 ,1 ,signup , ,main_terminal ,07:15:00 ,main_terminal ,07:45:00
inspection_train ,1 ,2 ,operator ,inspection_line1_ob ,downtown ,08:00:00 ,anytown ,09:00:00
inspection_train ,1 ,3 ,operator ,inspection_line1_ib ,anytown ,09:15:00 ,downtown ,10:15:00
inspection_train ,1 ,4 ,operator ,inspection_line2_ob ,downtown ,11:00:00 ,busyville ,12:30:00
inspection_train ,1 ,5 ,operator ,inspection_line2_ib ,busyville ,13:00:00 ,downtown ,14:30:00
inspection_train ,1 ,6 ,operator ,inspection_line3_ob ,downtown ,15:00:00 ,centerton ,15:45:00
inspection_train ,1 ,7 ,operator ,inspection_line3_ib ,centerton ,16:00:00 ,downtown ,16:45:00
gameday ,1 ,8 ,signoff , ,main_terminal ,17:00:00 ,main_terminal ,17:30:00
service_id ,run_id ,event_sequence ,block_id ,event_type ,trip_id ,start_location ,start_time ,end_location ,end_time
summer ,1 ,20 ,A ,drive ,101 ,westcity ,09:00:00 ,eastland ,10:30:00
summer ,1 ,30 ,A ,drive ,102 ,eastland ,10:45:00 ,westcity ,12:15:00

```

### Activating a storm schedule
summer ,2 ,20 ,B ,drive ,201 ,westcity ,09:00:00 ,eastland ,10:00:00
summer ,2 ,30 ,B ,drive ,202 ,eastland ,11:00:00 ,westcity ,12:00:00

Assume a public GTFS file includes a set of trips with service_id `storm_schedule`, with no normal assignment in the calendar.
fall ,1 ,20 ,A ,drive ,101 ,westcity ,09:00:00 ,eastland ,10:30:00
fall ,1 ,30 ,A ,drive ,202 ,eastland ,11:00:00 ,westcity ,12:00:00

#### `calendar.txt`

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
normal,1,1,1,1,1,0,0,20240101,20241231
storm_schedule,0,0,0,0,0,0,0,20240101,20241231
fall ,2 ,20 ,B ,drive ,201 ,westcity ,09:00:00 ,eastland ,10:00:00
fall ,2 ,30 ,B ,drive ,102 ,eastland ,10:45:00 ,westcity ,12:15:00
```

#### `calendar_dates.txt`

This storm schedule could be activated whenever inclement weather is encountered by updating `calendar_dates.txt` to include:

```csv
service_id,date,exception_type
normal,20240901,2
storm_schedule,20240901,1
```

#### `calendar_dates_supplement.txt`

While waiting for the GTFS data to propagate through one's system, this could also be reflected in the TODS `calendar_dates_supplement.txt` file to activate the change in any operational systems, alongside any runs associated with the `storm_schedule` service_id.

```csv
service_id,date,exception_type
normal,20240901,2
storm_schedule,20240901,1
```
(In this example, block IDs are listed in `run_events.txt` but not `trips.txt` because the blocks would also change with the schedule change.)
Binary file added docs/spec/examples/different-runs-same-trips.png
skyqrose marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading