Skip to content

Commit

Permalink
Merge pull request #2 from skyqrose/80
Browse files Browse the repository at this point in the history
remove run_events.trip_service_id from spec and trim examples
  • Loading branch information
jeffkessler-keolis authored Nov 11, 2024
2 parents ee99911 + 6778a93 commit ada3f66
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 203 deletions.
271 changes: 74 additions & 197 deletions docs/spec/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,268 +169,145 @@ weekday,10000,30,BLOCK-A,run-as-directed,,stop-1,09:00:00,stop-1,12:00:00
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.

### Extra staffing for a special event
## Jobs of entirely nonrevenue operations

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`
A track inspection train operates once per week, with a separate crew. It's scheduled and operated separately from other service, so is given its own service ID separate from any trips in the public GTFS file. In this example, the route and stops are assumed to be defined in the public GTFS.

_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)`._
### `calendar_supplement.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
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
inspection_train,0,0,0,0,0,0,1,20240601,20241231
```

#### `calendar_dates_supplement.txt`

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

```csv
service_id,date,exception_type
gameday,20240820,1
gameday,20240821,1
gameday,20240827,1
gameday,20240903,1
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
```

### 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`
### `stop_times_supplement.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
trip_id,stop_id,arrival_time
inspection_line1_ob,downtown,01:00:00
inspection_line1_ob,anytown,01:45:00
inspection_line1_ib,anytown,02:00:00
inspection_line1_ib,downtown,02:45:00
```

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

Assume these trips run daily on weekdays in the defined date range.
This file references the service ID and trip ID defined in the other supplement files.

```csv
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
weekday,1,1,1,1,1,0,0,20240101,20241231
service_id,run_id,event_sequence,event_type,trip_id,start_location,start_time,end_location,end_time
inspection_train ,1 ,1 ,sign-in , ,main_terminal ,00:45:00 ,main_terminal ,00:45:00
inspection_train ,1 ,2 ,operator ,inspection_line1_ob ,downtown ,01:00:00 ,anytown ,01:45:00
inspection_train ,1 ,3 ,operator ,inspection_line1_ib ,anytown ,02:00:00 ,downtown ,02:45:00
inspection_train ,1 ,4 ,sign-off , ,main_terminal ,03:00:00 ,main_terminal ,03:00:00
```

#### `run_events.txt`
## Distinct Crew and Trip schedule scenarios

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.
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.

```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
```
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`.

#### `calendar_supplement.txt`
### Extra staffing for a special event

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`:
Due to a baseball game, an additional ticket collector will be assigned to supplement the existing crew on train 101, serving the ballpark.

#### `calendar.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
weekday,1,1,1,1,1,0,0,20240101,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.

#### `trips.txt`

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`.

```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
route_id,service_id,trip_id,block_id
route,weekday,101,BLOCK-A
```

#### `calendar.txt`

Assume these trips run daily on weekdays in the defined date range.
#### `calendar_dates_supplement.txt`

```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
service_id,date,exception_type
gameday,20240820,1
gameday,20240821,1
gameday,20240827,1
gameday,20240903,1
```

#### `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`.

```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
```

#### `calendar_supplement.txt`

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
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
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
gameday,2,2,BLOCK-A,collector,extra collector,101,main_terminal,14:45:00,ballpark ,15:30:00
```

### Jobs of entirely nonrevenue operations
### Trip worked by different runs on different dates

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`
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.

```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
```
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.

#### `stop_times_supplement.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
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
```
![Diagram showing four trips on two runs, with the assignments rearranged in the fall.](different-runs-same-trips.png)

#### `calendar_dates_supplement.txt`
#### `calendar.txt`

```csv
service_id,date,exception_type
inspection_train,20240901
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
weekday,1,1,1,1,1,0,0,20240601,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`.
#### `trips.txt`

```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
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
```

### Activating a storm schedule

Assume a public GTFS file includes a set of trips with service_id `storm_schedule`, with no normal assignment in the calendar.
#### `calendar_supplement.txt`

#### `calendar.txt`
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
normal,1,1,1,1,1,0,0,20240101,20241231
storm_schedule,0,0,0,0,0,0,0,20240101,20241231
summer,1,1,1,1,1,0,0,20240601,20240831
fall ,1,1,1,1,1,0,0,20240901,20241231
```

#### `calendar_dates.txt`
#### `run_events.txt`

This storm schedule could be activated whenever inclement weather is encountered by updating `calendar_dates.txt` to include:
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,date,exception_type
normal,20240901,2
storm_schedule,20240901,1
```
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
#### `calendar_dates_supplement.txt`
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
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.
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
```csv
service_id,date,exception_type
normal,20240901,2
storm_schedule,20240901,1
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
```

(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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ada3f66

Please sign in to comment.