Skip to content

Commit 5dedbe0

Browse files
authored
Parse schedule relationships for trip descriptors and stop time updates (#19)
1 parent 0cec6a1 commit 5dedbe0

File tree

7 files changed

+2990
-542
lines changed

7 files changed

+2990
-542
lines changed

hash.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ func (h *hasher) trip(t *Trip) {
4545
h.number(t.ID.HasStartTime)
4646
h.number(t.ID.StartTime)
4747
h.number(int64(len(t.StopTimeUpdates)))
48+
h.number(t.ID.ScheduleRelationship)
4849
for i := range t.StopTimeUpdates {
4950
stu := &t.StopTimeUpdates[i]
5051
hashNumberPtr(h, stu.StopSequence)
5152
h.stringPtr(stu.StopID)
5253
h.stringPtr(stu.NyctTrack)
54+
h.number(stu.ScheduleRelationship)
5355
for _, event := range []*StopTimeEvent{stu.Arrival, stu.Departure} {
5456
h.number(event == nil)
5557
if event == nil {

proto/gtfs-realtime.pb.go

Lines changed: 2349 additions & 494 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/gtfs-realtime.proto

Lines changed: 497 additions & 30 deletions
Large diffs are not rendered by default.

proto/us-ny-mta-alerts-extension.pb.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/us-ny-mta-trips-extension.pb.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

realtime.go

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package gtfs
33
import (
44
"fmt"
55
"regexp"
6+
"sort"
67
"strconv"
78
"time"
89

@@ -38,6 +39,8 @@ func (trip *Trip) GetVehicle() Vehicle {
3839
return Vehicle{}
3940
}
4041

42+
type TripScheduleRelationship = gtfsrt.TripDescriptor_ScheduleRelationship
43+
4144
type TripID struct {
4245
ID string
4346
RouteID string
@@ -48,15 +51,46 @@ type TripID struct {
4851

4952
HasStartDate bool
5053
StartDate time.Time
54+
55+
ScheduleRelationship TripScheduleRelationship
56+
}
57+
58+
// Define ordering on trip ids for test consistency
59+
func (t1 TripID) Less(t2 TripID) bool {
60+
if t1.ID != t2.ID {
61+
return t1.ID < t2.ID
62+
}
63+
if t1.RouteID != t2.RouteID {
64+
return t1.RouteID < t2.RouteID
65+
}
66+
if t1.DirectionID != t2.DirectionID {
67+
return t1.DirectionID < t2.DirectionID
68+
}
69+
if t1.HasStartTime != t2.HasStartTime {
70+
return !t1.HasStartTime && t2.HasStartTime
71+
}
72+
if t1.HasStartTime && t1.StartTime != t2.StartTime {
73+
return t1.StartTime < t2.StartTime
74+
}
75+
if t1.HasStartDate != t2.HasStartDate {
76+
return !t1.HasStartDate && t2.HasStartDate
77+
}
78+
if t1.HasStartDate && !t1.StartDate.Equal(t2.StartDate) {
79+
return t1.StartDate.Before(t2.StartDate)
80+
}
81+
return t1.ScheduleRelationship < t2.ScheduleRelationship
5182
}
5283

84+
type StopTimeUpdateScheduleRelationship = gtfsrt.TripUpdate_StopTimeUpdate_ScheduleRelationship
85+
5386
// TODO: shouldn't this just be StopTime?
5487
type StopTimeUpdate struct {
55-
StopSequence *uint32
56-
StopID *string
57-
Arrival *StopTimeEvent
58-
Departure *StopTimeEvent
59-
NyctTrack *string
88+
StopSequence *uint32
89+
StopID *string
90+
Arrival *StopTimeEvent
91+
Departure *StopTimeEvent
92+
NyctTrack *string
93+
ScheduleRelationship StopTimeUpdateScheduleRelationship
6094
}
6195

6296
func (stopTimeUpdate *StopTimeUpdate) GetArrival() StopTimeEvent {
@@ -326,6 +360,11 @@ func ParseRealtime(content []byte, opts *ParseRealtimeOptions) (*Realtime, error
326360
}
327361
result.Trips = append(result.Trips, *trip)
328362
}
363+
364+
sort.Slice(result.Trips, func(i, j int) bool {
365+
return result.Trips[i].ID.Less(result.Trips[j].ID)
366+
})
367+
329368
for vehicleID, vehicle := range vehiclesByID {
330369
if tripID, ok := vehicleIDToTripID[vehicleID]; ok {
331370
vehicle.Trip = tripsById[tripID]
@@ -363,11 +402,12 @@ func parseTripUpdate(tripUpdate *gtfsrt.TripUpdate, opts *ParseRealtimeOptions)
363402
}
364403
for _, stopTimeUpdate := range tripUpdate.StopTimeUpdate {
365404
trip.StopTimeUpdates = append(trip.StopTimeUpdates, StopTimeUpdate{
366-
StopSequence: stopTimeUpdate.StopSequence,
367-
StopID: stopTimeUpdate.StopId,
368-
Arrival: convertStopTimeEvent(stopTimeUpdate.Arrival),
369-
Departure: convertStopTimeEvent(stopTimeUpdate.Departure),
370-
NyctTrack: opts.Extension.GetTrack(stopTimeUpdate),
405+
StopSequence: stopTimeUpdate.StopSequence,
406+
StopID: stopTimeUpdate.StopId,
407+
Arrival: convertStopTimeEvent(stopTimeUpdate.Arrival),
408+
Departure: convertStopTimeEvent(stopTimeUpdate.Departure),
409+
NyctTrack: opts.Extension.GetTrack(stopTimeUpdate),
410+
ScheduleRelationship: stopTimeUpdate.GetScheduleRelationship(),
371411
})
372412
}
373413
if tripUpdate.Vehicle == nil {
@@ -453,9 +493,10 @@ func parseOptionalTripDescriptor(tripDesc *gtfsrt.TripDescriptor, opts *ParseRea
453493

454494
func parseTripDescriptor(tripDesc *gtfsrt.TripDescriptor, opts *ParseRealtimeOptions) TripID {
455495
id := TripID{
456-
ID: tripDesc.GetTripId(),
457-
RouteID: tripDesc.GetRouteId(),
458-
DirectionID: parseDirectionID_GTFSRealtime(tripDesc.DirectionId),
496+
ID: tripDesc.GetTripId(),
497+
RouteID: tripDesc.GetRouteId(),
498+
DirectionID: parseDirectionID_GTFSRealtime(tripDesc.DirectionId),
499+
ScheduleRelationship: tripDesc.GetScheduleRelationship(),
459500
}
460501
id.HasStartTime, id.StartTime = parseStartTime(tripDesc.StartTime)
461502
id.HasStartDate, id.StartDate = parseStartDate(tripDesc.StartDate, opts.timezoneOrUTC())

realtime_test.go

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ import (
1212

1313
const (
1414
tripID1 = "tripID1"
15+
tripID2 = "tripID2"
16+
tripID3 = "tripID3"
1517
vehicleID1 = "vehicleID1"
1618
stopID1 = "stopID1"
19+
stopID2 = "stopID2"
20+
stopID3 = "stopID3"
1721
)
1822

1923
var createTime time.Time = time.Unix(2<<28, 0).UTC()
@@ -41,6 +45,46 @@ func TestRealtime(t *testing.T) {
4145
// TODO: other fields
4246
},
4347
},
48+
{
49+
Id: ptr("2"),
50+
TripUpdate: &gtfsrt.TripUpdate{
51+
Trip: &gtfsrt.TripDescriptor{
52+
TripId: ptr(tripID2),
53+
ScheduleRelationship: ptr(gtfsrt.TripDescriptor_ADDED),
54+
},
55+
StopTimeUpdate: []*gtfsrt.TripUpdate_StopTimeUpdate{
56+
{
57+
StopId: ptr(stopID1),
58+
StopSequence: ptr(uint32(1)),
59+
Arrival: &gtfsrt.TripUpdate_StopTimeEvent{
60+
Time: ptr(int64(time1.Unix())),
61+
},
62+
},
63+
{
64+
StopId: ptr(stopID2),
65+
StopSequence: ptr(uint32(2)),
66+
ScheduleRelationship: ptr(gtfsrt.TripUpdate_StopTimeUpdate_SKIPPED),
67+
Arrival: &gtfsrt.TripUpdate_StopTimeEvent{
68+
Time: ptr(int64(time2.Unix())),
69+
},
70+
},
71+
{
72+
StopId: ptr(stopID3),
73+
StopSequence: ptr(uint32(3)),
74+
ScheduleRelationship: ptr(gtfsrt.TripUpdate_StopTimeUpdate_NO_DATA),
75+
},
76+
},
77+
},
78+
},
79+
{
80+
Id: ptr("3"),
81+
TripUpdate: &gtfsrt.TripUpdate{
82+
Trip: &gtfsrt.TripDescriptor{
83+
TripId: ptr(tripID3),
84+
ScheduleRelationship: ptr(gtfsrt.TripDescriptor_CANCELED),
85+
},
86+
},
87+
},
4488
},
4589
want: func() *gtfs.Realtime {
4690
trip := gtfs.Trip{
@@ -58,9 +102,48 @@ func TestRealtime(t *testing.T) {
58102
}
59103
trip.Vehicle = &vehicle
60104
vehicle.Trip = &trip
105+
106+
trip2 := gtfs.Trip{
107+
ID: gtfs.TripID{
108+
ID: tripID2,
109+
ScheduleRelationship: gtfsrt.TripDescriptor_ADDED,
110+
},
111+
StopTimeUpdates: []gtfs.StopTimeUpdate{
112+
{
113+
StopID: ptr(stopID1),
114+
StopSequence: ptr(uint32(1)),
115+
Arrival: &gtfs.StopTimeEvent{
116+
Time: &time1,
117+
},
118+
},
119+
{
120+
StopID: ptr(stopID2),
121+
StopSequence: ptr(uint32(2)),
122+
Arrival: &gtfs.StopTimeEvent{
123+
Time: &time2,
124+
},
125+
ScheduleRelationship: gtfsrt.TripUpdate_StopTimeUpdate_SKIPPED,
126+
},
127+
{
128+
StopID: ptr(stopID3),
129+
StopSequence: ptr(uint32(3)),
130+
ScheduleRelationship: gtfsrt.TripUpdate_StopTimeUpdate_NO_DATA,
131+
},
132+
},
133+
IsEntityInMessage: true,
134+
}
135+
136+
trip3 := gtfs.Trip{
137+
ID: gtfs.TripID{
138+
ID: tripID3,
139+
ScheduleRelationship: gtfsrt.TripDescriptor_CANCELED,
140+
},
141+
IsEntityInMessage: true,
142+
}
143+
61144
return &gtfs.Realtime{
62145
CreatedAt: createTime,
63-
Trips: []gtfs.Trip{trip},
146+
Trips: []gtfs.Trip{trip, trip2, trip3},
64147
Vehicles: []gtfs.Vehicle{vehicle},
65148
}
66149
}(),

0 commit comments

Comments
 (0)