From 0527cad3a0c5d6e83fb73f7ef216def85d4b0ea6 Mon Sep 17 00:00:00 2001 From: Mats Linander Date: Sat, 6 Jan 2024 13:13:53 -0500 Subject: [PATCH 1/5] move model from storage to gtfs/model --- cmd/departures.go | 4 +- {storage => model}/model.go | 11 +- parse/agency.go | 3 +- parse/agency_test.go | 13 +- parse/calendar.go | 3 +- parse/calendar_dates.go | 3 +- parse/calendar_dates_test.go | 15 ++- parse/calendar_test.go | 9 +- parse/parse_test.go | 17 +-- parse/routes.go | 9 +- parse/routes_test.go | 17 +-- parse/stop_times.go | 5 +- parse/stop_times_test.go | 17 +-- parse/stops.go | 7 +- parse/stops_test.go | 27 ++-- parse/trips.go | 3 +- parse/trips_test.go | 13 +- realtime.go | 3 +- realtime_test.go | 10 +- static.go | 9 +- static_integration_test.go | 6 +- storage/postgres.go | 106 +++++++-------- storage/sqlite.go | 102 +++++++------- storage/storage.go | 55 ++++---- storage/storage_test.go | 251 ++++++++++++++++++----------------- storage/util_test.go | 4 +- 26 files changed, 374 insertions(+), 348 deletions(-) rename {storage => model}/model.go (90%) diff --git a/cmd/departures.go b/cmd/departures.go index c815bf8..ed78fb8 100644 --- a/cmd/departures.go +++ b/cmd/departures.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "tidbyt.dev/gtfs" - "tidbyt.dev/gtfs/storage" + "tidbyt.dev/gtfs/model" ) var departuresCmd = &cobra.Command{ @@ -35,7 +35,7 @@ func departures(cmd *cobra.Command, args []string) error { stopID := args[0] type DepartureProvider interface { - Departures(string, time.Time, time.Duration, int, string, int8, []storage.RouteType) ([]gtfs.Departure, error) + Departures(string, time.Time, time.Duration, int, string, int8, []model.RouteType) ([]gtfs.Departure, error) } var provider DepartureProvider diff --git a/storage/model.go b/model/model.go similarity index 90% rename from storage/model.go rename to model/model.go index 341aad5..e3413f1 100644 --- a/storage/model.go +++ b/model/model.go @@ -1,4 +1,4 @@ -package storage +package model import ( "strconv" @@ -107,3 +107,12 @@ type CalendarDate struct { ExceptionType int8 // TODO: Enum for exception types? } + +// Holds all Headsigns for trips passing through a stop, for a given +// route and direction. +type RouteDirection struct { + StopID string + RouteID string + DirectionID int8 + Headsigns []string +} diff --git a/parse/agency.go b/parse/agency.go index ecc6a22..2584aa2 100644 --- a/parse/agency.go +++ b/parse/agency.go @@ -7,6 +7,7 @@ import ( "github.com/gocarina/gocsv" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -65,7 +66,7 @@ func ParseAgency(writer storage.FeedWriter, data io.Reader) (map[string]bool, st return nil, "", fmt.Errorf("missing agency_url") } - writer.WriteAgency(&storage.Agency{ + writer.WriteAgency(&model.Agency{ ID: a.ID, Name: a.Name, URL: a.URL, diff --git a/parse/agency_test.go b/parse/agency_test.go index 87491e0..4224c39 100644 --- a/parse/agency_test.go +++ b/parse/agency_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -17,7 +18,7 @@ func TestParseAgency(t *testing.T) { content string agencyIDs map[string]bool timezone string - agencies []*storage.Agency + agencies []*model.Agency err bool }{ { @@ -27,7 +28,7 @@ agency_name,agency_url,agency_timezone Agency Name,http://www.example.com,America/New_York`, map[string]bool{"": true}, "America/New_York", - []*storage.Agency{&storage.Agency{ + []*model.Agency{&model.Agency{ Name: "Agency Name", URL: "http://www.example.com", Timezone: "America/New_York", @@ -44,20 +45,20 @@ agency_id,agency_name,agency_url,agency_timezone 3,Agency Three,http://www.example.com/three,America/New_York`, map[string]bool{"1": true, "2": true, "3": true}, "America/New_York", - []*storage.Agency{ - &storage.Agency{ + []*model.Agency{ + &model.Agency{ ID: "1", Name: "Agency One", URL: "http://www.example.com/one", Timezone: "America/New_York", }, - &storage.Agency{ + &model.Agency{ ID: "2", Name: "Agency Two", URL: "http://www.example.com/two", Timezone: "America/New_York", }, - &storage.Agency{ + &model.Agency{ ID: "3", Name: "Agency Three", URL: "http://www.example.com/three", diff --git a/parse/calendar.go b/parse/calendar.go index e6455bc..a447cfc 100644 --- a/parse/calendar.go +++ b/parse/calendar.go @@ -7,6 +7,7 @@ import ( "github.com/gocarina/gocsv" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -99,7 +100,7 @@ func ParseCalendar(writer storage.FeedWriter, data io.Reader) (map[string]bool, maxDate = c.EndDate } - err = writer.WriteCalendar(&storage.Calendar{ + err = writer.WriteCalendar(&model.Calendar{ ServiceID: c.ServiceID, StartDate: c.StartDate, EndDate: c.EndDate, diff --git a/parse/calendar_dates.go b/parse/calendar_dates.go index 30bf55b..fac10cb 100644 --- a/parse/calendar_dates.go +++ b/parse/calendar_dates.go @@ -7,6 +7,7 @@ import ( "github.com/gocarina/gocsv" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -54,7 +55,7 @@ func ParseCalendarDates( maxDate = cd.Date } - writer.WriteCalendarDate(&storage.CalendarDate{ + writer.WriteCalendarDate(&model.CalendarDate{ ServiceID: cd.ServiceID, Date: cd.Date, ExceptionType: cd.ExceptionType, diff --git a/parse/calendar_dates_test.go b/parse/calendar_dates_test.go index 99bb328..4148ead 100644 --- a/parse/calendar_dates_test.go +++ b/parse/calendar_dates_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -15,7 +16,7 @@ func TestCalendarDates(t *testing.T) { for _, tc := range []struct { name string content string - expected []*storage.CalendarDate + expected []*model.CalendarDate minDate string maxDate string err bool @@ -25,8 +26,8 @@ func TestCalendarDates(t *testing.T) { ` service_id,date,exception_type s1,20170101,1`, - []*storage.CalendarDate{ - &storage.CalendarDate{ + []*model.CalendarDate{ + &model.CalendarDate{ ServiceID: "s1", Date: "20170101", ExceptionType: 1, @@ -44,18 +45,18 @@ service_id,date,exception_type s1,20170101,1 s1,20170102,2 s2,20170103,1`, - []*storage.CalendarDate{ - &storage.CalendarDate{ + []*model.CalendarDate{ + &model.CalendarDate{ ServiceID: "s1", Date: "20170101", ExceptionType: 1, }, - &storage.CalendarDate{ + &model.CalendarDate{ ServiceID: "s1", Date: "20170102", ExceptionType: 2, }, - &storage.CalendarDate{ + &model.CalendarDate{ ServiceID: "s2", Date: "20170103", ExceptionType: 1, diff --git a/parse/calendar_test.go b/parse/calendar_test.go index f830541..3e93835 100644 --- a/parse/calendar_test.go +++ b/parse/calendar_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -16,7 +17,7 @@ func TestCalendar(t *testing.T) { for _, tc := range []struct { name string content string - expected []*storage.Calendar + expected []*model.Calendar minDate string maxDate string err bool @@ -27,7 +28,7 @@ func TestCalendar(t *testing.T) { service_id,start_date,end_date s,20170101,20170131`, - []*storage.Calendar{ + []*model.Calendar{ { ServiceID: "s", Weekday: 0, @@ -45,7 +46,7 @@ s,20170101,20170131`, ` service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date s,1,1,1,1,1,1,1,20170101,20170131`, - []*storage.Calendar{ + []*model.Calendar{ { ServiceID: "s", Weekday: 127, @@ -65,7 +66,7 @@ service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,e s1,1,1,1,1,1,1,1,20170101,20170131 s2,1,1,1,1,1,0,0,20171001,20180201 s3,1,1,0,1,1,0,1,20161225,20170202`, - []*storage.Calendar{ + []*model.Calendar{ { ServiceID: "s1", Weekday: 127, diff --git a/parse/parse_test.go b/parse/parse_test.go index b022480..4a382dc 100644 --- a/parse/parse_test.go +++ b/parse/parse_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -80,7 +81,7 @@ func TestParseValidFeed(t *testing.T) { agencies, err := reader.Agencies() assert.NoError(t, err) - assert.Equal(t, []*storage.Agency{&storage.Agency{ + assert.Equal(t, []*model.Agency{&model.Agency{ Timezone: "America/Los_Angeles", Name: "Fake Agency", URL: "http://agency/index.html", @@ -88,7 +89,7 @@ func TestParseValidFeed(t *testing.T) { routes, err := reader.Routes() assert.NoError(t, err) - assert.Equal(t, []*storage.Route{&storage.Route{ + assert.Equal(t, []*model.Route{&model.Route{ ID: "r", ShortName: "R", Type: 3, @@ -98,7 +99,7 @@ func TestParseValidFeed(t *testing.T) { calendar, err := reader.Calendars() assert.NoError(t, err) - assert.Equal(t, []*storage.Calendar{&storage.Calendar{ + assert.Equal(t, []*model.Calendar{&model.Calendar{ ServiceID: "mondays", Weekday: 1 << time.Monday, StartDate: "20190101", @@ -107,7 +108,7 @@ func TestParseValidFeed(t *testing.T) { calendarDates, err := reader.CalendarDates() assert.NoError(t, err) - assert.Equal(t, []*storage.CalendarDate{&storage.CalendarDate{ + assert.Equal(t, []*model.CalendarDate{&model.CalendarDate{ ServiceID: "mondays", Date: "20190302", ExceptionType: 1, @@ -115,7 +116,7 @@ func TestParseValidFeed(t *testing.T) { trips, err := reader.Trips() assert.NoError(t, err) - assert.Equal(t, []*storage.Trip{&storage.Trip{ + assert.Equal(t, []*model.Trip{&model.Trip{ ID: "t", RouteID: "r", ServiceID: "mondays", @@ -123,7 +124,7 @@ func TestParseValidFeed(t *testing.T) { stops, err := reader.Stops() assert.NoError(t, err) - assert.Equal(t, []*storage.Stop{&storage.Stop{ + assert.Equal(t, []*model.Stop{&model.Stop{ ID: "s", Name: "S", Lat: 12, @@ -132,7 +133,7 @@ func TestParseValidFeed(t *testing.T) { stopTimes, err := reader.StopTimes() assert.NoError(t, err) - assert.Equal(t, []*storage.StopTime{&storage.StopTime{ + assert.Equal(t, []*model.StopTime{&model.StopTime{ TripID: "t", Arrival: "120000", Departure: "120000", @@ -262,7 +263,7 @@ func TestParseUnorthodoxArchiveStructure(t *testing.T) { agency, err := reader.Agencies() assert.NoError(t, err) - assert.Equal(t, []*storage.Agency{&storage.Agency{ + assert.Equal(t, []*model.Agency{&model.Agency{ Timezone: "America/Los_Angeles", Name: "Fake Agency", URL: "http://agency/index.html", diff --git a/parse/routes.go b/parse/routes.go index 62e89d7..92b38ef 100644 --- a/parse/routes.go +++ b/parse/routes.go @@ -8,6 +8,7 @@ import ( "github.com/gocarina/gocsv" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -26,7 +27,7 @@ type RouteCSV struct { // ContinuousDropOff string `csv:"continuous_drop_off"` } -func legalRouteType(t storage.RouteType) bool { +func legalRouteType(t model.RouteType) bool { if t >= 0 && t <= 7 { return true } @@ -92,7 +93,7 @@ func ParseRoutes(writer storage.FeedWriter, data io.Reader, agency map[string]bo } // RouteType must be valid - if !legalRouteType(storage.RouteType(routeType)) { + if !legalRouteType(model.RouteType(routeType)) { return nil, fmt.Errorf("route_id '%s' has invalid route_type: %d", r.ID, routeType) } @@ -108,13 +109,13 @@ func ParseRoutes(writer storage.FeedWriter, data io.Reader, agency map[string]bo return nil, fmt.Errorf("route_id '%s' has invalid route_text_color: %s", r.ID, r.TextColor) } - err = writer.WriteRoute(&storage.Route{ + err = writer.WriteRoute(&model.Route{ ID: r.ID, AgencyID: r.AgencyID, ShortName: r.ShortName, LongName: r.LongName, Desc: r.Desc, - Type: storage.RouteType(routeType), + Type: model.RouteType(routeType), URL: r.URL, Color: r.Color, TextColor: r.TextColor, diff --git a/parse/routes_test.go b/parse/routes_test.go index 36655d3..3784919 100644 --- a/parse/routes_test.go +++ b/parse/routes_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -16,7 +17,7 @@ func TestParseRoutes(t *testing.T) { name string content string agencies map[string]bool - routes []*storage.Route + routes []*model.Route err bool }{ { @@ -25,7 +26,7 @@ func TestParseRoutes(t *testing.T) { route_id,route_short_name,route_type 1,1,3`, map[string]bool{}, - []*storage.Route{&storage.Route{ + []*model.Route{&model.Route{ ID: "1", ShortName: "1", Type: 3, @@ -41,7 +42,7 @@ route_id,route_short_name,route_type route_id,route_long_name,route_type 1,Route One,3`, map[string]bool{}, - []*storage.Route{&storage.Route{ + []*model.Route{&model.Route{ ID: "1", LongName: "Route One", Type: 3, @@ -58,25 +59,25 @@ route_id,agency_id,route_short_name,route_long_name,route_desc,route_type,route_ r1,a1,one,Route One,Description1,3,http://one/,FFFFF0,00000F r2,a2,two,Route Two,Description2,3,http://two/,FFFFF1,00000E`, map[string]bool{"a1": true, "a2": true}, - []*storage.Route{ - &storage.Route{ + []*model.Route{ + &model.Route{ ID: "r1", AgencyID: "a1", ShortName: "one", LongName: "Route One", Desc: "Description1", - Type: storage.RouteType(3), + Type: model.RouteType(3), URL: "http://one/", Color: "FFFFF0", TextColor: "00000F", }, - &storage.Route{ + &model.Route{ ID: "r2", AgencyID: "a2", ShortName: "two", LongName: "Route Two", Desc: "Description2", - Type: storage.RouteType(3), + Type: model.RouteType(3), URL: "http://two/", Color: "FFFFF1", TextColor: "00000E", diff --git a/parse/stop_times.go b/parse/stop_times.go index 697b476..d086d52 100644 --- a/parse/stop_times.go +++ b/parse/stop_times.go @@ -10,6 +10,7 @@ import ( "github.com/gocarina/gocsv" "github.com/pkg/errors" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -59,7 +60,7 @@ func ParseStopTimes( stops map[string]bool, ) (string, string, error) { - stopTimes := []storage.StopTime{} + stopTimes := []model.StopTime{} stopSeq := map[string][]int{} @@ -98,7 +99,7 @@ func ParseStopTimes( maxDeparture = departureTime } - stopTime := storage.StopTime{ + stopTime := model.StopTime{ TripID: st.TripID, StopID: st.StopID, Headsign: st.Headsign, diff --git a/parse/stop_times_test.go b/parse/stop_times_test.go index 61c4f93..ff7e913 100644 --- a/parse/stop_times_test.go +++ b/parse/stop_times_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -17,7 +18,7 @@ func TestParseStopTimes(t *testing.T) { trips map[string]bool stops map[string]bool err bool - stopTimes []*storage.StopTime + stopTimes []*model.StopTime }{ { "minimal", @@ -27,8 +28,8 @@ t,10:00:00,10:00:01,s,1`, map[string]bool{"t": true}, map[string]bool{"s": true}, false, - []*storage.StopTime{ - &storage.StopTime{ + []*model.StopTime{ + &model.StopTime{ TripID: "t", Arrival: "100000", Departure: "100001", @@ -48,8 +49,8 @@ t,10:00:02,10:00:03,s2,2,sh2 map[string]bool{"t": true}, map[string]bool{"s1": true, "s2": true}, false, - []*storage.StopTime{ - &storage.StopTime{ + []*model.StopTime{ + &model.StopTime{ TripID: "t", Arrival: "100000", Departure: "100001", @@ -57,7 +58,7 @@ t,10:00:02,10:00:03,s2,2,sh2 StopSequence: 1, Headsign: "sh1", }, - &storage.StopTime{ + &model.StopTime{ TripID: "t", Arrival: "100002", Departure: "100003", @@ -76,8 +77,8 @@ t,25:00:00,25:00:01,s,1`, map[string]bool{"t": true}, map[string]bool{"s": true}, false, - []*storage.StopTime{ - &storage.StopTime{ + []*model.StopTime{ + &model.StopTime{ TripID: "t", Arrival: "250000", Departure: "250001", diff --git a/parse/stops.go b/parse/stops.go index ae10587..9ee89da 100644 --- a/parse/stops.go +++ b/parse/stops.go @@ -6,6 +6,7 @@ import ( "github.com/gocarina/gocsv" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -44,9 +45,9 @@ func ParseStops(writer storage.FeedWriter, data io.Reader) (map[string]bool, err return nil, fmt.Errorf("empty stop_id") } - locationType := storage.LocationType(st.LocationType) + locationType := model.LocationType(st.LocationType) - if locationType != storage.LocationTypeGenericNode && locationType != storage.LocationTypeBoardingArea { + if locationType != model.LocationTypeGenericNode && locationType != model.LocationTypeBoardingArea { // stop_name is "[o]ptional for locations which are // generic nodes (location_type=3) or boarding areas // (location_type=4)" and otherwise required @@ -63,7 +64,7 @@ func ParseStops(writer storage.FeedWriter, data io.Reader) (map[string]bool, err } } - stop := storage.Stop{ + stop := model.Stop{ ID: st.ID, Code: st.Code, Name: st.Name, diff --git a/parse/stops_test.go b/parse/stops_test.go index 422a9da..ede88ed 100644 --- a/parse/stops_test.go +++ b/parse/stops_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -15,7 +16,7 @@ func TestParseStops(t *testing.T) { for _, tc := range []struct { name string content string - stops []*storage.Stop + stops []*model.Stop err bool }{ { @@ -23,7 +24,7 @@ func TestParseStops(t *testing.T) { ` stop_id,stop_name,stop_lat,stop_lon s,name,1.1,2.2`, - []*storage.Stop{&storage.Stop{ + []*model.Stop{&model.Stop{ ID: "s", Name: "name", Lat: 1.1, @@ -42,17 +43,17 @@ location_type,stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,stop_url,p 3,g,code_g,Generic,desc_g,,,url_g,ps, 4,b,code_b,Boarding,desc_b,,,url_b,ps, `, - []*storage.Stop{ - &storage.Stop{ + []*model.Stop{ + &model.Stop{ ID: "b", Code: "code_b", Name: "Boarding", Desc: "desc_b", URL: "url_b", ParentStation: "ps", - LocationType: storage.LocationTypeBoardingArea, + LocationType: model.LocationTypeBoardingArea, }, - &storage.Stop{ + &model.Stop{ ID: "e", Code: "code_e", Name: "Entrance", @@ -61,18 +62,18 @@ location_type,stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,stop_url,p Lon: 6.6, URL: "url_se", ParentStation: "ps", - LocationType: storage.LocationTypeEntranceExit, + LocationType: model.LocationTypeEntranceExit, }, - &storage.Stop{ + &model.Stop{ ID: "g", Code: "code_g", Name: "Generic", Desc: "desc_g", URL: "url_g", ParentStation: "ps", - LocationType: storage.LocationTypeGenericNode, + LocationType: model.LocationTypeGenericNode, }, - &storage.Stop{ + &model.Stop{ ID: "ps", Code: "code_ps", Name: "Station", @@ -80,9 +81,9 @@ location_type,stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,stop_url,p Lat: 3.3, Lon: 4.4, URL: "url_ps", - LocationType: storage.LocationTypeStation, + LocationType: model.LocationTypeStation, }, - &storage.Stop{ + &model.Stop{ ID: "s", Code: "code_s", Name: "Stop", @@ -92,7 +93,7 @@ location_type,stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,stop_url,p URL: "url_s", ParentStation: "ps", PlatformCode: "platform", - LocationType: storage.LocationTypeStop, + LocationType: model.LocationTypeStop, }, }, false, diff --git a/parse/trips.go b/parse/trips.go index 758f030..7698d4b 100644 --- a/parse/trips.go +++ b/parse/trips.go @@ -6,6 +6,7 @@ import ( "github.com/gocarina/gocsv" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -58,7 +59,7 @@ func ParseTrips( return nil, fmt.Errorf("invalid direction_id '%d'", t.DirectionID) } - err := writer.WriteTrip(&storage.Trip{ + err := writer.WriteTrip(&model.Trip{ ID: t.ID, RouteID: t.RouteID, ServiceID: t.ServiceID, diff --git a/parse/trips_test.go b/parse/trips_test.go index 8dbfe20..944d841 100644 --- a/parse/trips_test.go +++ b/parse/trips_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -17,7 +18,7 @@ func TestParseTrips(t *testing.T) { content string routes map[string]bool services map[string]bool - trips []*storage.Trip + trips []*model.Trip err bool }{ { @@ -27,7 +28,7 @@ trip_id,route_id,service_id t,r,s`, map[string]bool{"r": true}, map[string]bool{"s": true}, - []*storage.Trip{&storage.Trip{ + []*model.Trip{&model.Trip{ ID: "t", RouteID: "r", ServiceID: "s", @@ -42,7 +43,7 @@ trip_id,route_id,service_id,trip_headsign,trip_short_name,direction_id t,r,s,head,short,1`, map[string]bool{"r": true}, map[string]bool{"s": true}, - []*storage.Trip{&storage.Trip{ + []*model.Trip{&model.Trip{ ID: "t", RouteID: "r", ServiceID: "s", @@ -61,14 +62,14 @@ t1,r1,s2,0 t2,r2,s1,1`, map[string]bool{"r1": true, "r2": true}, map[string]bool{"s1": true, "s2": true}, - []*storage.Trip{ - &storage.Trip{ + []*model.Trip{ + &model.Trip{ ID: "t1", RouteID: "r1", ServiceID: "s2", DirectionID: 0, }, - &storage.Trip{ + &model.Trip{ ID: "t2", RouteID: "r2", ServiceID: "s1", diff --git a/realtime.go b/realtime.go index 82d950a..322a472 100644 --- a/realtime.go +++ b/realtime.go @@ -6,6 +6,7 @@ import ( "sort" "time" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/parse" "tidbyt.dev/gtfs/storage" ) @@ -105,7 +106,7 @@ func (rt *Realtime) Departures( numDepartures int, routeID string, directionID int8, - routeTypes []storage.RouteType) ([]Departure, error) { + routeTypes []model.RouteType) ([]Departure, error) { // Get the scheduled departures. Extend the window so that // delayed (or early) departures are included. diff --git a/realtime_test.go b/realtime_test.go index f4191a6..3762f3f 100644 --- a/realtime_test.go +++ b/realtime_test.go @@ -12,7 +12,7 @@ import ( proto "google.golang.org/protobuf/proto" "tidbyt.dev/gtfs" - "tidbyt.dev/gtfs/storage" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/testutil" ) @@ -1157,12 +1157,12 @@ func TestRealtimeDepartureFiltering(t *testing.T) { assert.Equal(t, nil, err) assert.Equal(t, []gtfs.Departure{}, departures) - // And we can filter on storage.RouteType + // And we can filter on model.RouteType departures, err = rt.Departures( "center", time.Date(2020, 1, 16, 0, 0, 0, 0, time.UTC), 10*time.Hour, - -1, "", -1, []storage.RouteType{storage.RouteTypeBus}) + -1, "", -1, []model.RouteType{model.RouteTypeBus}) assert.NoError(t, err) assert.Equal(t, []gtfs.Departure{ { @@ -1178,7 +1178,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { "center", time.Date(2020, 1, 16, 0, 0, 0, 0, time.UTC), 10*time.Hour, - -1, "", -1, []storage.RouteType{storage.RouteTypeRail}) + -1, "", -1, []model.RouteType{model.RouteTypeRail}) assert.NoError(t, err) assert.Equal(t, []gtfs.Departure{ { @@ -1193,7 +1193,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { "center", time.Date(2020, 1, 16, 0, 0, 0, 0, time.UTC), 10*time.Hour, - -1, "", -1, []storage.RouteType{storage.RouteTypeMonorail}) + -1, "", -1, []model.RouteType{model.RouteTypeMonorail}) assert.NoError(t, err) assert.Equal(t, []gtfs.Departure{}, departures) diff --git a/static.go b/static.go index 3f99399..616d888 100644 --- a/static.go +++ b/static.go @@ -6,6 +6,7 @@ import ( "strconv" "time" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/storage" ) @@ -52,12 +53,12 @@ func NewStatic(reader storage.FeedReader, metadata *storage.FeedMetadata) (*Stat // If limit is >0, at most limit stops are returned. // // If types is provided, then only stops along routes of at least one -// of the types is returned. E.g., pass []storage.RouteType{storage.RouteTypeBus} to +// of the types is returned. E.g., pass []model.RouteType{model.RouteTypeBus} to // only receive bus stops. // // Only stations (location_type=1) and stops (location_type=0) // _without_ parent station are returned. -func (s Static) NearbyStops(lat float64, lon float64, limit int, types []storage.RouteType) ([]storage.Stop, error) { +func (s Static) NearbyStops(lat float64, lon float64, limit int, types []model.RouteType) ([]model.Stop, error) { stops, err := s.Reader.NearbyStops(lat, lon, limit, types) if err != nil { return nil, fmt.Errorf("getting nearby stops: %w", err) @@ -73,7 +74,7 @@ func (s Static) NearbyStops(lat float64, lon float64, limit int, types []storage // // NOTE: Headsign can also be set on stop_time, which messes this up // quite a bit. -func (s Static) RouteDirections(stopID string) ([]*storage.RouteDirection, error) { +func (s Static) RouteDirections(stopID string) ([]*model.RouteDirection, error) { rds, err := s.Reader.RouteDirections(stopID) if err != nil { return nil, err @@ -180,7 +181,7 @@ func (s Static) Departures( numDepartures int, routeID string, directionID int8, - routeTypes []storage.RouteType, + routeTypes []model.RouteType, ) ([]Departure, error) { departures := []Departure{} diff --git a/static_integration_test.go b/static_integration_test.go index d68679c..f29ff0f 100644 --- a/static_integration_test.go +++ b/static_integration_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "tidbyt.dev/gtfs" - "tidbyt.dev/gtfs/storage" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/testutil" ) @@ -26,11 +26,11 @@ func testGTFSStaticIntegrationNearbyStops(t *testing.T, backend string) { // station. stops, err := g.NearbyStops(40.6968986, -73.955555, 4, nil) assert.NoError(t, err) - stopMap := make(map[string]storage.Stop) + stopMap := make(map[string]model.Stop) for _, s := range stops { stopMap[s.ID] = s } - assert.Equal(t, map[string]storage.Stop{ + assert.Equal(t, map[string]model.Stop{ "G31": { ID: "G31", Lat: 40.700377, diff --git a/storage/postgres.go b/storage/postgres.go index e3fbd6b..28782bc 100644 --- a/storage/postgres.go +++ b/storage/postgres.go @@ -8,6 +8,8 @@ import ( "time" "github.com/lib/pq" + + "tidbyt.dev/gtfs/model" ) const ( @@ -22,8 +24,8 @@ type PSQLStorage struct { type PSQLFeedWriter struct { id string db *sql.DB - tripBuf []*Trip - stopTimeBuf []*StopTime + tripBuf []*model.Trip + stopTimeBuf []*model.StopTime } type PSQLFeedReader struct { @@ -449,7 +451,7 @@ CREATE TABLE IF NOT EXISTS calendar_dates ( }, nil } -func (w *PSQLFeedWriter) WriteAgency(a *Agency) error { +func (w *PSQLFeedWriter) WriteAgency(a *model.Agency) error { _, err := w.db.Exec(` INSERT INTO agency (hash, id, name, url, timezone) VALUES ($1, $2, $3, $4, $5)`, @@ -465,7 +467,7 @@ VALUES ($1, $2, $3, $4, $5)`, return nil } -func (w *PSQLFeedWriter) WriteStop(stop *Stop) error { +func (w *PSQLFeedWriter) WriteStop(stop *model.Stop) error { var parentStation sql.NullString if stop.ParentStation != "" { parentStation = sql.NullString{ @@ -494,7 +496,7 @@ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, return nil } -func (w *PSQLFeedWriter) WriteRoute(route *Route) error { +func (w *PSQLFeedWriter) WriteRoute(route *model.Route) error { _, err := w.db.Exec(` INSERT INTO routes (hash, id, agency_id, short_name, long_name, description, type, url, color, text_color) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, @@ -519,7 +521,7 @@ func (w *PSQLFeedWriter) BeginTrips() error { return nil } -func (w *PSQLFeedWriter) WriteTrip(trip *Trip) error { +func (w *PSQLFeedWriter) WriteTrip(trip *model.Trip) error { w.tripBuf = append(w.tripBuf, trip) if len(w.tripBuf) >= PSQLTripBatchSize { @@ -581,7 +583,7 @@ func (w *PSQLFeedWriter) flushTrips() error { return nil } -func (w *PSQLFeedWriter) WriteCalendar(cal *Calendar) error { +func (w *PSQLFeedWriter) WriteCalendar(cal *model.Calendar) error { mon, tue, wed, thu, fri, sat, sun := 0, 0, 0, 0, 0, 0, 0 if cal.Weekday&(1<= PSQLStopTimeBatchSize { @@ -714,7 +716,7 @@ func (s *PSQLFeedWriter) Close() error { return nil } -func (r *PSQLFeedReader) Agencies() ([]*Agency, error) { +func (r *PSQLFeedReader) Agencies() ([]*model.Agency, error) { rows, err := r.db.Query(` SELECT id, name, url, timezone FROM agency @@ -724,9 +726,9 @@ WHERE hash = $1`, r.id) } defer rows.Close() - agencies := []*Agency{} + agencies := []*model.Agency{} for rows.Next() { - a := &Agency{} + a := &model.Agency{} err := rows.Scan(&a.ID, &a.Name, &a.URL, &a.Timezone) if err != nil { return nil, fmt.Errorf("scanning agency: %w", err) @@ -737,7 +739,7 @@ WHERE hash = $1`, r.id) return agencies, nil } -func (r *PSQLFeedReader) Stops() ([]*Stop, error) { +func (r *PSQLFeedReader) Stops() ([]*model.Stop, error) { rows, err := r.db.Query(` SELECT id, code, name, description, lat, lon, url, location_type, parent_station, platform_code FROM stops @@ -747,9 +749,9 @@ WHERE hash = $1`, r.id) } defer rows.Close() - stops := []*Stop{} + stops := []*model.Stop{} for rows.Next() { - s := &Stop{} + s := &model.Stop{} parentStation := sql.NullString{} err := rows.Scan( &s.ID, @@ -777,7 +779,7 @@ WHERE hash = $1`, r.id) return stops, nil } -func (r *PSQLFeedReader) Routes() ([]*Route, error) { +func (r *PSQLFeedReader) Routes() ([]*model.Route, error) { rows, err := r.db.Query(` SELECT id, agency_id, short_name, long_name, description, type, url, color, text_color FROM routes @@ -787,9 +789,9 @@ WHERE hash = $1`, r.id) } defer rows.Close() - routes := []*Route{} + routes := []*model.Route{} for rows.Next() { - route := &Route{} + route := &model.Route{} err := rows.Scan( &route.ID, &route.AgencyID, @@ -810,7 +812,7 @@ WHERE hash = $1`, r.id) return routes, nil } -func (r *PSQLFeedReader) Trips() ([]*Trip, error) { +func (r *PSQLFeedReader) Trips() ([]*model.Trip, error) { rows, err := r.db.Query(` SELECT id, route_id, service_id, headsign, short_name, direction_id FROM trips @@ -820,9 +822,9 @@ WHERE hash = $1`, r.id) } defer rows.Close() - trips := []*Trip{} + trips := []*model.Trip{} for rows.Next() { - t := &Trip{} + t := &model.Trip{} err := rows.Scan( &t.ID, &t.RouteID, @@ -840,7 +842,7 @@ WHERE hash = $1`, r.id) return trips, nil } -func (r *PSQLFeedReader) StopTimes() ([]*StopTime, error) { +func (r *PSQLFeedReader) StopTimes() ([]*model.StopTime, error) { rows, err := r.db.Query(` SELECT trip_id, stop_id, headsign, stop_sequence, arrival_time, departure_time FROM stop_times @@ -850,9 +852,9 @@ WHERE hash = $1`, r.id) } defer rows.Close() - stopTimes := []*StopTime{} + stopTimes := []*model.StopTime{} for rows.Next() { - st := &StopTime{} + st := &model.StopTime{} err := rows.Scan( &st.TripID, &st.StopID, @@ -870,7 +872,7 @@ WHERE hash = $1`, r.id) return stopTimes, nil } -func (r *PSQLFeedReader) Calendars() ([]*Calendar, error) { +func (r *PSQLFeedReader) Calendars() ([]*model.Calendar, error) { rows, err := r.db.Query(` SELECT service_id, start_date, end_date, monday, tuesday, wednesday, thursday, friday, saturday, sunday FROM calendar @@ -880,7 +882,7 @@ WHERE hash = $1`, r.id) } defer rows.Close() - calendars := []*Calendar{} + calendars := []*model.Calendar{} for rows.Next() { var serviceID, startDate, endDate string var monday, tuesday, wednesday, thursday, friday, saturday, sunday bool @@ -921,7 +923,7 @@ WHERE hash = $1`, r.id) if sunday { weekday |= 1 << time.Sunday } - calendars = append(calendars, &Calendar{ + calendars = append(calendars, &model.Calendar{ ServiceID: serviceID, StartDate: startDate, EndDate: endDate, @@ -932,7 +934,7 @@ WHERE hash = $1`, r.id) return calendars, nil } -func (r *PSQLFeedReader) CalendarDates() ([]*CalendarDate, error) { +func (r *PSQLFeedReader) CalendarDates() ([]*model.CalendarDate, error) { rows, err := r.db.Query(` SELECT service_id, date, exception_type FROM calendar_dates @@ -942,9 +944,9 @@ WHERE hash = $1`, r.id) } defer rows.Close() - calendarDates := []*CalendarDate{} + calendarDates := []*model.CalendarDate{} for rows.Next() { - cd := &CalendarDate{} + cd := &model.CalendarDate{} err := rows.Scan( &cd.ServiceID, &cd.Date, @@ -1197,10 +1199,10 @@ WHERE stop_times.hash = $1 AND events := []*StopTimeEvent{} for rows.Next() { - stop := &Stop{} - stopTime := &StopTime{} - trip := &Trip{} - route := &Route{} + stop := &model.Stop{} + stopTime := &model.StopTime{} + trip := &model.Trip{} + route := &model.Route{} parentStation := sql.NullString{} err = rows.Scan( @@ -1257,14 +1259,14 @@ WHERE stop_times.hash = $1 AND // NOTE: this used to be done in the main query as a left // outer join, but performance was awful. May not even need to // retrieve this data at all. - parents := map[string]*Stop{} + parents := map[string]*model.Stop{} for _, event := range events { if event.Stop.ParentStation == "" { continue } if _, ok := parents[event.Stop.ParentStation]; !ok { - parents[event.Stop.ParentStation] = &Stop{} + parents[event.Stop.ParentStation] = &model.Stop{} } } @@ -1293,7 +1295,7 @@ WHERE hash = $1 AND defer rows.Close() for rows.Next() { - stop := &Stop{} + stop := &model.Stop{} err = rows.Scan( &stop.ID, &stop.Code, @@ -1319,7 +1321,7 @@ WHERE hash = $1 AND return events, nil } -func (r *PSQLFeedReader) RouteDirections(stopID string) ([]*RouteDirection, error) { +func (r *PSQLFeedReader) RouteDirections(stopID string) ([]*model.RouteDirection, error) { rows, err := r.db.Query(` SELECT trips.route_id, trips.direction_id, trips.headsign, stop_times.headsign FROM stop_times @@ -1364,13 +1366,13 @@ WHERE stop_times.hash = $1 AND deduped[key][headsign] = true } - routeDirections := []*RouteDirection{} + routeDirections := []*model.RouteDirection{} for key, headsignSet := range deduped { headsigns := []string{} for headsign := range headsignSet { headsigns = append(headsigns, headsign) } - routeDirections = append(routeDirections, &RouteDirection{ + routeDirections = append(routeDirections, &model.RouteDirection{ StopID: stopID, RouteID: key.RouteID, DirectionID: key.DirectionID, @@ -1381,7 +1383,7 @@ WHERE stop_times.hash = $1 AND return routeDirections, nil } -func (r *PSQLFeedReader) getStops() ([]*Stop, error) { +func (r *PSQLFeedReader) getStops() ([]*model.Stop, error) { row, err := r.db.Query(` SELECT stops.id, @@ -1405,9 +1407,9 @@ WHERE return nil, fmt.Errorf("querying for nearby stops: %w", err) } - stops := []*Stop{} + stops := []*model.Stop{} for row.Next() { - stop := &Stop{} + stop := &model.Stop{} parentStation := sql.NullString{} err = row.Scan( &stop.ID, @@ -1435,7 +1437,7 @@ WHERE return stops, nil } -func (r *PSQLFeedReader) getStopsByRouteType(routeTypes []RouteType) ([]*Stop, error) { +func (r *PSQLFeedReader) getStopsByRouteType(routeTypes []model.RouteType) ([]*model.Stop, error) { queryValues := []interface{}{r.id} for _, rt := range routeTypes { queryValues = append(queryValues, rt) @@ -1486,9 +1488,9 @@ WHERE } defer rows.Close() - allStops := map[string]*Stop{} + allStops := map[string]*model.Stop{} for rows.Next() { - s := &Stop{} + s := &model.Stop{} stopParentStation := sql.NullString{} parentID := sql.NullString{} parentCode := sql.NullString{} @@ -1529,7 +1531,7 @@ WHERE } if parentID.Valid { - allStops[parentID.String] = &Stop{ + allStops[parentID.String] = &model.Stop{ ID: parentID.String, Code: parentCode.String, Name: parentName.String, @@ -1537,7 +1539,7 @@ WHERE Lat: parentLat.Float64, Lon: parentLon.Float64, URL: parentURL.String, - LocationType: LocationType(parentLocationType.Int64), + LocationType: model.LocationType(parentLocationType.Int64), PlatformCode: parentPlatformCode.String, } } else { @@ -1545,7 +1547,7 @@ WHERE } } - stops := []*Stop{} + stops := []*model.Stop{} for _, s := range allStops { stops = append(stops, s) } @@ -1553,8 +1555,8 @@ WHERE return stops, nil } -func (r *PSQLFeedReader) NearbyStops(lat float64, lng float64, limit int, routeTypes []RouteType) ([]Stop, error) { - var stops []*Stop +func (r *PSQLFeedReader) NearbyStops(lat float64, lng float64, limit int, routeTypes []model.RouteType) ([]model.Stop, error) { + var stops []*model.Stop var err error // TODO: Look into using postgis for this. @@ -1586,7 +1588,7 @@ func (r *PSQLFeedReader) NearbyStops(lat float64, lng float64, limit int, routeT stops = stops[:limit] } - res := []Stop{} + res := []model.Stop{} for _, s := range stops { res = append(res, *s) } diff --git a/storage/sqlite.go b/storage/sqlite.go index 1e0dff4..505fc08 100644 --- a/storage/sqlite.go +++ b/storage/sqlite.go @@ -9,6 +9,8 @@ import ( "time" _ "github.com/mattn/go-sqlite3" + + "tidbyt.dev/gtfs/model" ) type SQLiteConfig struct { @@ -443,7 +445,7 @@ CREATE TABLE calendar_dates ( }, nil } -func (f *SQLiteFeedWriter) WriteAgency(a *Agency) error { +func (f *SQLiteFeedWriter) WriteAgency(a *model.Agency) error { _, err := f.db.Exec(` INSERT INTO agency (id, name, url, timezone) VALUES (?, ?, ?, ?)`, @@ -458,7 +460,7 @@ VALUES (?, ?, ?, ?)`, return nil } -func (f *SQLiteFeedWriter) WriteStop(stop *Stop) error { +func (f *SQLiteFeedWriter) WriteStop(stop *model.Stop) error { _, err := f.db.Exec(` INSERT INTO stops (id, code, name, desc, lat, lon, url, location_type, parent_station, platform_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, @@ -479,7 +481,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, return nil } -func (f *SQLiteFeedWriter) WriteRoute(route *Route) error { +func (f *SQLiteFeedWriter) WriteRoute(route *model.Route) error { _, err := f.db.Exec(` INSERT INTO routes (id, agency_id, short_name, long_name, desc, type, url, color, text_color) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, @@ -503,7 +505,7 @@ func (f *SQLiteFeedWriter) BeginTrips() error { return nil } -func (f *SQLiteFeedWriter) WriteTrip(trip *Trip) error { +func (f *SQLiteFeedWriter) WriteTrip(trip *model.Trip) error { _, err := f.db.Exec(` INSERT INTO trips (id, route_id, service_id, headsign, short_name, direction_id) VALUES (?, ?, ?, ?, ?, ?)`, @@ -544,7 +546,7 @@ VALUES (?, ?, ?, ?, ?, ? ,?)`) return nil } -func (f *SQLiteFeedWriter) WriteStopTime(stopTime *StopTime) error { +func (f *SQLiteFeedWriter) WriteStopTime(stopTime *model.StopTime) error { _, err := f.stopTimeInsertQuery.Exec( stopTime.TripID, stopTime.StopID, @@ -578,7 +580,7 @@ func (f *SQLiteFeedWriter) EndStopTimes() error { return nil } -func (f *SQLiteFeedWriter) WriteCalendar(cal *Calendar) error { +func (f *SQLiteFeedWriter) WriteCalendar(cal *model.Calendar) error { mon, tue, wed, thu, fri, sat, sun := 0, 0, 0, 0, 0, 0, 0 if cal.Weekday&(1< strings.Compare( fmt.Sprintf( @@ -1436,7 +1437,7 @@ func testRouteDirections(t *testing.T, sb StorageBuilder) { // stop alpha rds, err := reader.RouteDirections("alpha") assert.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{ + assert.Equal(t, []*model.RouteDirection{ { StopID: "alpha", RouteID: "RouteA", @@ -1460,7 +1461,7 @@ func testRouteDirections(t *testing.T, sb StorageBuilder) { // stop beta rds, err = reader.RouteDirections("beta") assert.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{ + assert.Equal(t, []*model.RouteDirection{ { StopID: "beta", RouteID: "RouteA", @@ -1484,7 +1485,7 @@ func testRouteDirections(t *testing.T, sb StorageBuilder) { // stop gamma rds, err = reader.RouteDirections("gamma") assert.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{ + assert.Equal(t, []*model.RouteDirection{ { StopID: "gamma", RouteID: "RouteA", @@ -1502,7 +1503,7 @@ func testRouteDirections(t *testing.T, sb StorageBuilder) { // stop delta rds, err = reader.RouteDirections("delta") assert.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{ + assert.Equal(t, []*model.RouteDirection{ { StopID: "delta", RouteID: "RouteA", @@ -1521,7 +1522,7 @@ func testRouteDirections(t *testing.T, sb StorageBuilder) { // No directions here, since nothing ever departs from epsilon. rds, err = reader.RouteDirections("epsilon") assert.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{}, rds) + assert.Equal(t, []*model.RouteDirection{}, rds) } func testNearbyStops(t *testing.T, sb StorageBuilder) { @@ -1538,27 +1539,27 @@ func testNearbyStops(t *testing.T, sb StorageBuilder) { }, }) - stop := func(id string, lat, lng float64) storage.Stop { - return storage.Stop{ID: id, Name: id, Lat: lat, Lon: lng} + stop := func(id string, lat, lng float64) model.Stop { + return model.Stop{ID: id, Name: id, Lat: lat, Lon: lng} } for _, tc := range []struct { Lat, Lon float64 Limit int Msg string - Expected []storage.Stop + Expected []model.Stop }{ // Centered around NYC, increasing limit - {40.0, -74.0, 1, "1 stop near nyc", []storage.Stop{stop("nyc", 40.7, -74.1)}}, - {40.0, -74.0, 2, "2 stops near nyc", []storage.Stop{stop("nyc", 40.7, -74.1), stop("philly", 40.0, -75.2)}}, - {40.0, -74.0, 5, "5 stops near nyc", []storage.Stop{ + {40.0, -74.0, 1, "1 stop near nyc", []model.Stop{stop("nyc", 40.7, -74.1)}}, + {40.0, -74.0, 2, "2 stops near nyc", []model.Stop{stop("nyc", 40.7, -74.1), stop("philly", 40.0, -75.2)}}, + {40.0, -74.0, 5, "5 stops near nyc", []model.Stop{ stop("nyc", 40.7, -74.1), stop("philly", 40.0, -75.2), stop("la", 34.0, -118.5), stop("sf", 37.8, -122.5), stop("rey", 64.1, -21.9), }}, - {40.0, -74.0, 7, "7 stops near nyc", []storage.Stop{ + {40.0, -74.0, 7, "7 stops near nyc", []model.Stop{ stop("nyc", 40.7, -74.1), stop("philly", 40.0, -75.2), stop("la", 34.0, -118.5), @@ -1567,7 +1568,7 @@ func testNearbyStops(t *testing.T, sb StorageBuilder) { stop("lon", 51.5, -0.2), stop("sto", 59.3, 17.9), }}, - {40.0, -74.0, 0, "unlimited stops near nyc", []storage.Stop{ + {40.0, -74.0, 0, "unlimited stops near nyc", []model.Stop{ stop("nyc", 40.7, -74.1), stop("philly", 40.0, -75.2), stop("la", 34.0, -118.5), @@ -1576,7 +1577,7 @@ func testNearbyStops(t *testing.T, sb StorageBuilder) { stop("lon", 51.5, -0.2), stop("sto", 59.3, 17.9), }}, - {40.0, -74.0, 1000000, "100000 stops near nyc", []storage.Stop{ + {40.0, -74.0, 1000000, "100000 stops near nyc", []model.Stop{ stop("nyc", 40.7, -74.1), stop("philly", 40.0, -75.2), stop("la", 34.0, -118.5), @@ -1587,13 +1588,13 @@ func testNearbyStops(t *testing.T, sb StorageBuilder) { }}, // Centered around Reykjavik - {64.0, -22.0, 4, "4 stops near rey", []storage.Stop{ + {64.0, -22.0, 4, "4 stops near rey", []model.Stop{ stop("rey", 64.1, -21.9), stop("lon", 51.5, -0.2), stop("sto", 59.3, 17.9), stop("nyc", 40.7, -74.1), }}, - {64.0, -22.0, 0, "unlimited stops near rey", []storage.Stop{ + {64.0, -22.0, 0, "unlimited stops near rey", []model.Stop{ stop("rey", 64.1, -21.9), stop("lon", 51.5, -0.2), stop("sto", 59.3, 17.9), @@ -1604,20 +1605,20 @@ func testNearbyStops(t *testing.T, sb StorageBuilder) { }}, // Centered around Stockholm - {59.0, 18.0, 1, "1 stop near sto", []storage.Stop{stop("sto", 59.3, 17.9)}}, - {59.0, 18.0, 2, "2 stops near sto", []storage.Stop{stop("sto", 59.3, 17.9), stop("lon", 51.5, -0.2)}}, - {59.0, 18.0, 3, "3 stops near sto", []storage.Stop{ + {59.0, 18.0, 1, "1 stop near sto", []model.Stop{stop("sto", 59.3, 17.9)}}, + {59.0, 18.0, 2, "2 stops near sto", []model.Stop{stop("sto", 59.3, 17.9), stop("lon", 51.5, -0.2)}}, + {59.0, 18.0, 3, "3 stops near sto", []model.Stop{ stop("sto", 59.3, 17.9), stop("lon", 51.5, -0.2), stop("rey", 64.1, -21.9), }}, - {59.0, 18.0, 4, "4 stops near sto", []storage.Stop{ + {59.0, 18.0, 4, "4 stops near sto", []model.Stop{ stop("sto", 59.3, 17.9), stop("lon", 51.5, -0.2), stop("rey", 64.1, -21.9), stop("nyc", 40.7, -74.1), }}, - {59.0, 18.0, 0, "unlimited stops near sto", []storage.Stop{ + {59.0, 18.0, 0, "unlimited stops near sto", []model.Stop{ stop("sto", 59.3, 17.9), stop("lon", 51.5, -0.2), stop("rey", 64.1, -21.9), @@ -2229,7 +2230,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // Verify agency records agencies1, err := first.Agencies() require.NoError(t, err) - assert.Equal(t, []*storage.Agency{{ + assert.Equal(t, []*model.Agency{{ ID: "agency1", Name: "Agency 1", URL: "http://example.com", @@ -2238,7 +2239,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { agencies2, err := second.Agencies() require.NoError(t, err) - assert.Equal(t, []*storage.Agency{{ + assert.Equal(t, []*model.Agency{{ ID: "agency2", Name: "Agency 2", URL: "http://example2.com", @@ -2253,7 +2254,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { stops1, err := first.Stops() require.NoError(t, err) sort.Slice(stops1, func(i, j int) bool { return stops1[i].ID < stops1[j].ID }) - assert.Equal(t, []*storage.Stop{{ + assert.Equal(t, []*model.Stop{{ ID: "station_a", Name: "Station A", Lat: 5, @@ -2279,7 +2280,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { stops2, err := second.Stops() require.NoError(t, err) sort.Slice(stops2, func(i, j int) bool { return stops2[i].ID < stops2[j].ID }) - assert.Equal(t, []*storage.Stop{{ + assert.Equal(t, []*model.Stop{{ ID: "station_b", Name: "Station B", Lat: 11, @@ -2310,7 +2311,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // Routes routes1, err := first.Routes() require.NoError(t, err) - assert.Equal(t, []*storage.Route{{ + assert.Equal(t, []*model.Route{{ ID: "r1", ShortName: "R1", Type: 3, @@ -2320,7 +2321,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { routes2, err := second.Routes() require.NoError(t, err) - assert.Equal(t, []*storage.Route{{ + assert.Equal(t, []*model.Route{{ ID: "r2", ShortName: "R2", Type: 3, @@ -2335,7 +2336,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // Trips trips1, err := first.Trips() require.NoError(t, err) - assert.Equal(t, []*storage.Trip{{ + assert.Equal(t, []*model.Trip{{ ID: "t1", ServiceID: "svc1", RouteID: "r1", @@ -2343,7 +2344,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { trips2, err := second.Trips() require.NoError(t, err) - assert.Equal(t, []*storage.Trip{{ + assert.Equal(t, []*model.Trip{{ ID: "t2", ServiceID: "svc2", RouteID: "r2", @@ -2357,7 +2358,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // StopTimes stopTimes1, err := first.StopTimes() require.NoError(t, err) - assert.Equal(t, []*storage.StopTime{{ + assert.Equal(t, []*model.StopTime{{ TripID: "t1", StopID: "stop1", StopSequence: 1, @@ -2373,7 +2374,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { stopTimes2, err := second.StopTimes() require.NoError(t, err) - assert.Equal(t, []*storage.StopTime{{ + assert.Equal(t, []*model.StopTime{{ TripID: "t2", StopID: "stop3", StopSequence: 1, @@ -2394,7 +2395,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // Calendar calendar1, err := first.Calendars() require.NoError(t, err) - assert.Equal(t, []*storage.Calendar{{ + assert.Equal(t, []*model.Calendar{{ ServiceID: "svc1", Weekday: 1 << time.Monday, StartDate: "20170101", @@ -2403,7 +2404,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { calendar2, err := second.Calendars() require.NoError(t, err) - assert.Equal(t, []*storage.Calendar{{ + assert.Equal(t, []*model.Calendar{{ ServiceID: "svc2", Weekday: 1 << time.Tuesday, StartDate: "20170601", @@ -2417,7 +2418,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // CalendarDates calendarDates1, err := first.CalendarDates() require.NoError(t, err) - assert.Equal(t, []*storage.CalendarDate{{ + assert.Equal(t, []*model.CalendarDate{{ ServiceID: "svc1", Date: "20170101", ExceptionType: 1, @@ -2425,7 +2426,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { calendarDates2, err := second.CalendarDates() require.NoError(t, err) - assert.Equal(t, []*storage.CalendarDate{{ + assert.Equal(t, []*model.CalendarDate{{ ServiceID: "svc2", Date: "20171226", ExceptionType: 2, @@ -2438,7 +2439,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // RouteDirections routeDirections1, err := first.RouteDirections("stop1") require.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{{ + assert.Equal(t, []*model.RouteDirection{{ StopID: "stop1", RouteID: "r1", DirectionID: 0, @@ -2447,7 +2448,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { routeDirections2, err := second.RouteDirections("stop3") require.NoError(t, err) - assert.Equal(t, []*storage.RouteDirection{{ + assert.Equal(t, []*model.RouteDirection{{ StopID: "stop3", RouteID: "r2", DirectionID: 1, @@ -2457,7 +2458,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { // NearbyStops without route type nearbyStops1, err := first.NearbyStops(1, 2, 1, nil) require.NoError(t, err) - assert.Equal(t, []storage.Stop{{ + assert.Equal(t, []model.Stop{{ ID: "stop2", Name: "Stop 2", Lat: 3, @@ -2466,7 +2467,7 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { nearbyStops2, err := second.NearbyStops(3, 4, 1, nil) require.NoError(t, err) - assert.Equal(t, []storage.Stop{{ + assert.Equal(t, []model.Stop{{ ID: "stop4", Name: "Stop 4", Lat: 9, @@ -2478,15 +2479,15 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { assert.Equal(t, nearbyStops2, nearbyStops3) // NearbyStops with route type - nearbyStopsRoute1, err := first.NearbyStops(1, 2, 1, []storage.RouteType{storage.RouteTypeBus}) + nearbyStopsRoute1, err := first.NearbyStops(1, 2, 1, []model.RouteType{model.RouteTypeBus}) require.NoError(t, err) assert.Equal(t, nearbyStops1, nearbyStopsRoute1) - nearbyStopsRoute2, err := second.NearbyStops(3, 4, 1, []storage.RouteType{storage.RouteTypeBus}) + nearbyStopsRoute2, err := second.NearbyStops(3, 4, 1, []model.RouteType{model.RouteTypeBus}) require.NoError(t, err) assert.Equal(t, nearbyStops2, nearbyStopsRoute2) - nearbyStopsRoute3, err := third.NearbyStops(3, 4, 1, []storage.RouteType{storage.RouteTypeBus}) + nearbyStopsRoute3, err := third.NearbyStops(3, 4, 1, []model.RouteType{model.RouteTypeBus}) require.NoError(t, err) assert.Equal(t, nearbyStopsRoute2, nearbyStopsRoute3) @@ -2495,33 +2496,33 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { require.NoError(t, err) require.Equal(t, 2, len(events1)) assert.Equal(t, &storage.StopTimeEvent{ - StopTime: &storage.StopTime{ + StopTime: &model.StopTime{ TripID: "t1", StopID: "stop1", StopSequence: 1, Arrival: "010000", Departure: "010115", }, - Trip: &storage.Trip{ + Trip: &model.Trip{ ID: "t1", RouteID: "r1", ServiceID: "svc1", }, - Route: &storage.Route{ + Route: &model.Route{ ID: "r1", - Type: storage.RouteTypeBus, + Type: model.RouteTypeBus, ShortName: "R1", Color: "FFFFFF", TextColor: "000000", }, - Stop: &storage.Stop{ + Stop: &model.Stop{ ID: "stop1", Name: "Stop 1", Lat: 1, Lon: 2, ParentStation: "station_a", }, - ParentStation: &storage.Stop{ + ParentStation: &model.Stop{ ID: "station_a", Name: "Station A", Lat: 5, @@ -2534,34 +2535,34 @@ func testMultipleFeedsInStorage(t *testing.T, sb StorageBuilder) { require.NoError(t, err) require.Equal(t, 2, len(events2)) assert.Equal(t, &storage.StopTimeEvent{ - StopTime: &storage.StopTime{ + StopTime: &model.StopTime{ TripID: "t2", StopID: "stop3", StopSequence: 1, Arrival: "010000", Departure: "010115", }, - Trip: &storage.Trip{ + Trip: &model.Trip{ ID: "t2", RouteID: "r2", ServiceID: "svc2", DirectionID: 1, }, - Route: &storage.Route{ + Route: &model.Route{ ID: "r2", - Type: storage.RouteTypeBus, + Type: model.RouteTypeBus, ShortName: "R2", Color: "FFFFFF", TextColor: "000000", }, - Stop: &storage.Stop{ + Stop: &model.Stop{ ID: "stop3", Name: "Stop 3", Lat: 7, Lon: 8, ParentStation: "station_b", }, - ParentStation: &storage.Stop{ + ParentStation: &model.Stop{ ID: "station_b", Name: "Station B", Lat: 11, diff --git a/storage/util_test.go b/storage/util_test.go index 2c8bc0f..5f281aa 100644 --- a/storage/util_test.go +++ b/storage/util_test.go @@ -4,10 +4,12 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "tidbyt.dev/gtfs/model" ) func TestHaversineDistance(t *testing.T) { - var loc = map[string]Stop{ + var loc = map[string]model.Stop{ "nyc": {ID: "nyc", Lat: 40.700000, Lon: -74.100000}, "philly": {ID: "philly", Lat: 40.000000, Lon: -75.200000}, "sf": {ID: "sf", Lat: 37.800000, Lon: -122.500000}, From 1d3153b2e185b8824d0ddf3935fc4f58b7a7847b Mon Sep 17 00:00:00 2001 From: Mats Linander Date: Sat, 6 Jan 2024 13:24:34 -0500 Subject: [PATCH 2/5] Departure to model --- cmd/departures.go | 3 +- model/model.go | 11 +++++ realtime.go | 6 +-- realtime_integration_test.go | 16 +++---- realtime_test.go | 92 ++++++++++++++++++------------------ static.go | 17 ++----- static_integration_test.go | 9 ++-- static_test.go | 78 +++++++++++++++--------------- 8 files changed, 115 insertions(+), 117 deletions(-) diff --git a/cmd/departures.go b/cmd/departures.go index ed78fb8..c78b797 100644 --- a/cmd/departures.go +++ b/cmd/departures.go @@ -6,7 +6,6 @@ import ( "github.com/spf13/cobra" - "tidbyt.dev/gtfs" "tidbyt.dev/gtfs/model" ) @@ -35,7 +34,7 @@ func departures(cmd *cobra.Command, args []string) error { stopID := args[0] type DepartureProvider interface { - Departures(string, time.Time, time.Duration, int, string, int8, []model.RouteType) ([]gtfs.Departure, error) + Departures(string, time.Time, time.Duration, int, string, int8, []model.RouteType) ([]model.Departure, error) } var provider DepartureProvider diff --git a/model/model.go b/model/model.go index e3413f1..064e900 100644 --- a/model/model.go +++ b/model/model.go @@ -116,3 +116,14 @@ type RouteDirection struct { DirectionID int8 Headsigns []string } + +type Departure struct { + StopID string + RouteID string + TripID string + StopSequence uint32 + DirectionID int8 + Time time.Time + Headsign string + Delay time.Duration +} diff --git a/realtime.go b/realtime.go index 322a472..3367683 100644 --- a/realtime.go +++ b/realtime.go @@ -106,7 +106,7 @@ func (rt *Realtime) Departures( numDepartures int, routeID string, directionID int8, - routeTypes []model.RouteType) ([]Departure, error) { + routeTypes []model.RouteType) ([]model.Departure, error) { // Get the scheduled departures. Extend the window so that // delayed (or early) departures are included. @@ -124,7 +124,7 @@ func (rt *Realtime) Departures( } // Process each scheduled departure, applying realtime updates - departures := []Departure{} + departures := []model.Departure{} for _, dep := range scheduled { // If trip is cancelled, the the departure is too @@ -198,7 +198,7 @@ func (rt *Realtime) Departures( // Filter out departures outside of the requested time // window. Sort by time. Done. - result := []Departure{} + result := []model.Departure{} for _, dep := range departures { if dep.Time.Before(windowStart) || dep.Time.After(windowStart.Add(windowLength)) { continue diff --git a/realtime_integration_test.go b/realtime_integration_test.go index cb1d5c4..c82a3e5 100644 --- a/realtime_integration_test.go +++ b/realtime_integration_test.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "tidbyt.dev/gtfs" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/testutil" ) @@ -53,7 +53,7 @@ func TestRealtimeIntegrationNYCFerryDelaysOnER(t *testing.T) { 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { // delayed 391s RouteID: "ER", TripID: "321", @@ -79,7 +79,7 @@ func TestRealtimeIntegrationNYCFerryDelaysOnER(t *testing.T) { -1, "", -1, nil) assert.NoError(t, err) require.Equal(t, 1, len(departures)) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { // delayed 391s RouteID: "ER", TripID: "321", @@ -131,7 +131,7 @@ func TestRealtimeIntegrationNYCFerryDelayWithRecoveryOnSB(t *testing.T) { 5*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "SB", TripID: "526", @@ -158,7 +158,7 @@ func TestRealtimeIntegrationNYCFerryDelayWithRecoveryOnSB(t *testing.T) { 2*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "SB", TripID: "526", @@ -271,7 +271,7 @@ func TestRealtimeIntegrationWMATADelaysAlongATrip(t *testing.T) { expectedTime := staticTime.Add(realtimeDelay) - var d *gtfs.Departure + var d *model.Departure deps, err := rt.Departures(tc.StopID, expectedTime.Add(-1*time.Minute), 2*time.Minute, -1, "", -1, nil) require.NoError(t, err) for _, dep := range deps { @@ -338,7 +338,7 @@ func TestRealtimeIntegrationWMATASkippedStops(t *testing.T) { {"PF_D06_C", "2024-01-03 16:04:05 -0500 EST"}, {"PF_D05_C", "2024-01-03 16:05:39 -0500 EST"}, } { - var d *gtfs.Departure + var d *model.Departure deps, err := rt.Departures(tc.StopID, time.Date(2024, 1, 3, 15, 50, 0, 0, tzET), 80*time.Minute, -1, "", -1, nil) require.NoError(t, err) for _, dep := range deps { @@ -418,7 +418,7 @@ func TestRealtimeIntegrationBART(t *testing.T) { {"PCTR", time.Date(2024, 1, 4, 11, 45, 29, 0, tzSF), "1m29s"}, // propagated // No departure from ANTC, as it's the final stop on the trip } { - var d *gtfs.Departure + var d *model.Departure deps, err := rt.Departures(tc.StopID, tc.ExpectedTime.Add(-time.Minute), 2*time.Minute, -1, "", -1, nil) require.NoError(t, err) for _, dep := range deps { diff --git a/realtime_test.go b/realtime_test.go index 3762f3f..bd0f2fb 100644 --- a/realtime_test.go +++ b/realtime_test.go @@ -199,7 +199,7 @@ func TestRealtimeNoChanges(t *testing.T) { // Check s1 departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -219,7 +219,7 @@ func TestRealtimeNoChanges(t *testing.T) { // Check s2 departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -239,7 +239,7 @@ func TestRealtimeNoChanges(t *testing.T) { // Check s3 departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -259,13 +259,13 @@ func TestRealtimeNoChanges(t *testing.T) { // No departures from s4 since it's the final stop departures, err = rt.Departures("s4", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) // And z1 for good measure. This one definitely shouldn't have // changed. departures, err = rt.Departures("z1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R2", TripID: "t3", @@ -278,7 +278,7 @@ func TestRealtimeNoChanges(t *testing.T) { // And no departures from z3 since it's the final stop departures, err = rt.Departures("z3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) } // Realtime data where updates are expected to propagate along a trip @@ -320,7 +320,7 @@ func TestRealtimeDelayWithPropagation(t *testing.T) { // Check s1 departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -340,7 +340,7 @@ func TestRealtimeDelayWithPropagation(t *testing.T) { // Check s2. Expecting delays on both trips. departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -362,7 +362,7 @@ func TestRealtimeDelayWithPropagation(t *testing.T) { // Check s3. Expecting delay on t1, but t2 back on schedule. departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -442,7 +442,7 @@ func TestRealtimeNoData(t *testing.T) { // Check s1 departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -463,7 +463,7 @@ func TestRealtimeNoData(t *testing.T) { // Check s2 departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -485,7 +485,7 @@ func TestRealtimeNoData(t *testing.T) { // Check s3 departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -551,7 +551,7 @@ func TestRealtimeSkippedStop(t *testing.T) { // Check s1. Expect t1 to skip past. t2 is delayed 30s. departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t2", @@ -565,7 +565,7 @@ func TestRealtimeSkippedStop(t *testing.T) { // Check s2. Expect t2 to skip. t1 is on time. departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -578,7 +578,7 @@ func TestRealtimeSkippedStop(t *testing.T) { // Check s3. Expect t1 to skip, and t2 to remain 30s delayed. departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t2", @@ -616,7 +616,7 @@ func TestRealtimeCanceledTrip(t *testing.T) { departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t2", @@ -628,7 +628,7 @@ func TestRealtimeCanceledTrip(t *testing.T) { departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t2", @@ -641,7 +641,7 @@ func TestRealtimeCanceledTrip(t *testing.T) { departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t2", @@ -654,7 +654,7 @@ func TestRealtimeCanceledTrip(t *testing.T) { departures, err = rt.Departures("z1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R2", TripID: "t3", @@ -684,19 +684,19 @@ func TestRealtimeCanceledTrip(t *testing.T) { departures, err = rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = rt.Departures("s31", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = rt.Departures("z1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = rt.Departures("z2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) } // Check that the time parameters are respected @@ -748,7 +748,7 @@ func TestRealtimeTimeWindowing(t *testing.T) { -1, "", -1, nil, ) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -767,7 +767,7 @@ func TestRealtimeTimeWindowing(t *testing.T) { -1, "", -1, nil, ) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -794,7 +794,7 @@ func TestRealtimeTimeWindowing(t *testing.T) { -1, "", -1, nil, ) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t2", @@ -883,7 +883,7 @@ func TestRealtimeTripWithLoop(t *testing.T) { departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -895,7 +895,7 @@ func TestRealtimeTripWithLoop(t *testing.T) { departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -907,7 +907,7 @@ func TestRealtimeTripWithLoop(t *testing.T) { departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -935,7 +935,7 @@ func TestRealtimeTripWithLoop(t *testing.T) { departures, err = rt.Departures("s4", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -963,7 +963,7 @@ func TestRealtimeTripWithLoop(t *testing.T) { departures, err = rt.Departures("s5", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 10*time.Minute, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -1063,7 +1063,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "BusSouth", TripID: "ts", @@ -1088,7 +1088,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, 1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "BusSouth", TripID: "ts", @@ -1106,7 +1106,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, 1, "RailEast", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "RailEast", TripID: "te", @@ -1121,7 +1121,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "BusSouth", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "BusSouth", TripID: "ts", @@ -1139,7 +1139,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "BusSouth", 0, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "BusSouth", TripID: "ts", @@ -1155,7 +1155,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "BusSouth", 1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) // And we can filter on model.RouteType departures, err = rt.Departures( @@ -1164,7 +1164,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "", -1, []model.RouteType{model.RouteTypeBus}) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "BusSouth", TripID: "ts", @@ -1180,7 +1180,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "", -1, []model.RouteType{model.RouteTypeRail}) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "RailEast", TripID: "te", @@ -1195,7 +1195,7 @@ func TestRealtimeDepartureFiltering(t *testing.T) { 10*time.Hour, -1, "", -1, []model.RouteType{model.RouteTypeMonorail}) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) } @@ -1359,7 +1359,7 @@ func TestRealtimeArrivalRecovery(t *testing.T) { // Check the delays on the first stop departures, err := rt.Departures("s1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -1380,7 +1380,7 @@ func TestRealtimeArrivalRecovery(t *testing.T) { departures, err = rt.Departures("z1", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R2", TripID: "t3", @@ -1394,7 +1394,7 @@ func TestRealtimeArrivalRecovery(t *testing.T) { // And verify they've all recovered on the second stop departures, err = rt.Departures("s2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", @@ -1413,7 +1413,7 @@ func TestRealtimeArrivalRecovery(t *testing.T) { departures, err = rt.Departures("z2", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R2", TripID: "t3", @@ -1427,7 +1427,7 @@ func TestRealtimeArrivalRecovery(t *testing.T) { // for subsequent stops. departures, err = rt.Departures("s3", time.Date(2020, 1, 15, 23, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { RouteID: "R1", TripID: "t1", diff --git a/static.go b/static.go index 616d888..7071627 100644 --- a/static.go +++ b/static.go @@ -82,17 +82,6 @@ func (s Static) RouteDirections(stopID string) ([]*model.RouteDirection, error) return rds, nil } -type Departure struct { - StopID string - RouteID string - TripID string - StopSequence uint32 - DirectionID int8 - Time time.Time - Headsign string - Delay time.Duration -} - // Translates a time offset into a GTFS style HHMMSS string. func gtfsDate(offset time.Duration) string { h := int(offset.Hours()) @@ -182,9 +171,9 @@ func (s Static) Departures( routeID string, directionID int8, routeTypes []model.RouteType, -) ([]Departure, error) { +) ([]model.Departure, error) { - departures := []Departure{} + departures := []model.Departure{} if numDepartures == 0 { return departures, nil @@ -251,7 +240,7 @@ func (s Static) Departures( } if !startTime.After(departureTime) { - departures = append(departures, Departure{ + departures = append(departures, model.Departure{ StopID: event.Stop.ID, RouteID: event.Trip.RouteID, TripID: event.Trip.ID, diff --git a/static_integration_test.go b/static_integration_test.go index f29ff0f..14351bd 100644 --- a/static_integration_test.go +++ b/static_integration_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "tidbyt.dev/gtfs" "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/testutil" ) @@ -116,7 +115,7 @@ func testGTFSStaticIntegrationDepartures(t *testing.T, backend string) { // Feb 3rd is a Monday departures, _ := g.Departures("G33S", time.Date(2020, 2, 3, 22, 50, 0, 0, tz), 10*time.Minute, -1, "", -1, nil) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "G33S", RouteID: "G", @@ -139,7 +138,7 @@ func testGTFSStaticIntegrationDepartures(t *testing.T, backend string) { // Feb 17 is also a Monday, but President's Day departures, _ = g.Departures("G33S", time.Date(2020, 2, 17, 22, 50, 0, 0, tz), 10*time.Minute, -1, "", -1, nil) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "G33S", RouteID: "G", @@ -155,7 +154,7 @@ func testGTFSStaticIntegrationDepartures(t *testing.T, backend string) { // reverse order in stop_times.txt, but will be still be // returned ordered by departure time. departures, _ = g.Departures("G33S", time.Date(2020, 2, 17, 22, 50, 0, 0, tz), 13*time.Minute, -1, "", -1, nil) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "G33S", RouteID: "G", @@ -178,7 +177,7 @@ func testGTFSStaticIntegrationDepartures(t *testing.T, backend string) { // Feb 16 is a Sunday departures, _ = g.Departures("G33S", time.Date(2020, 2, 16, 22, 50, 0, 0, tz), 10*time.Minute, -1, "", -1, nil) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "G33S", RouteID: "G", diff --git a/static_test.go b/static_test.go index 3078d7b..70afe5b 100644 --- a/static_test.go +++ b/static_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "tidbyt.dev/gtfs" + "tidbyt.dev/gtfs/model" "tidbyt.dev/gtfs/testutil" ) @@ -74,7 +74,7 @@ func testStaticDeparturesWindowing(t *testing.T, backend string) { // station should have 2 L train departures departures, err := g.Departures("14", time.Date(2020, 2, 4, 6, 0, 0, 0, time.UTC), 30*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "14", RouteID: "L", @@ -96,7 +96,7 @@ func testStaticDeparturesWindowing(t *testing.T, backend string) { // boundary of the window. departures, err = g.Departures("14", time.Date(2020, 2, 4, 6, 10, 0, 0, time.UTC), 50*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "14", RouteID: "L", @@ -144,7 +144,7 @@ func testStaticDeparturesWindowing(t *testing.T, backend string) { // Start window at 6:30 and earlier departures are cut departures, err = g.Departures("14", time.Date(2020, 2, 4, 6, 30, 0, 0, time.UTC), 50*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "14", RouteID: "L", @@ -178,17 +178,17 @@ func testStaticDeparturesWindowing(t *testing.T, backend string) { // Push window past last departure and we get nothing departures, err = g.Departures("14", time.Date(2020, 2, 4, 6, 51, 0, 0, time.UTC), 50*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) // Non-existent stop also gives us nothing departures, err = g.Departures("FOO", time.Date(2020, 2, 4, 6, 30, 0, 0, time.UTC), 50*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) // But a large enough window reaches next day's departures. departures, err = g.Departures("14", time.Date(2020, 2, 4, 6, 51, 0, 0, time.UTC), duration(23, 50, 0), -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "14", RouteID: "L", @@ -222,7 +222,7 @@ func testStaticDeparturesWindowing(t *testing.T, backend string) { // Outside of calendar, we get nothing (Jan 1st 2021 was a Friday) departures, err = g.Departures("14", time.Date(2021, 1, 1, 6, 30, 0, 0, time.UTC), 50*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) } func testStaticDeparturesWeekendSchedule(t *testing.T, backend string) { @@ -271,7 +271,7 @@ func testStaticDeparturesWeekendSchedule(t *testing.T, backend string) { // Feb 14th is a Friday, so weekday schedule applies. departures, err := g.Departures("6a", time.Date(2020, 2, 14, 9, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "6a", RouteID: "L", @@ -285,7 +285,7 @@ func testStaticDeparturesWeekendSchedule(t *testing.T, backend string) { // Feb 15th will be on weekend schedule departures, err = g.Departures("6a", time.Date(2020, 2, 15, 9, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "6a", RouteID: "L", @@ -299,7 +299,7 @@ func testStaticDeparturesWeekendSchedule(t *testing.T, backend string) { // Window spanning from 14th into 15th can capture stops from both days departures, err = g.Departures("6a", time.Date(2020, 2, 14, 9, 29, 0, 0, time.UTC), 24*time.Hour-1*time.Second, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "6a", RouteID: "L", @@ -356,7 +356,7 @@ func testStaticDeparturesTimezones(t *testing.T, backend string) { // Querying using the transit agency's time zone departures, err := g.Departures("6a", time.Date(2020, 2, 3, 9, 0, 0, 0, tzNYC), 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "6a", RouteID: "L", @@ -370,7 +370,7 @@ func testStaticDeparturesTimezones(t *testing.T, backend string) { // Querying using UTC, which in February 2020 is NYC+5 departures, err = g.Departures("6a", time.Date(2020, 2, 3, 14, 0, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "6a", RouteID: "L", @@ -385,7 +385,7 @@ func testStaticDeparturesTimezones(t *testing.T, backend string) { // large enough window departures, err = g.Departures("6a", time.Date(2020, 2, 2, 22, 0, 0, 0, time.UTC), 20*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "6a", RouteID: "L", @@ -433,7 +433,7 @@ func testStaticDeparturesOvernightTrip(t *testing.T, backend string) { // but is still part of the feb 9 trip. departures, err := g.Departures("3a", time.Date(2020, 2, 9, 23, 30, 0, 0, tzNYC), 2*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "3a", RouteID: "L", @@ -447,7 +447,7 @@ func testStaticDeparturesOvernightTrip(t *testing.T, backend string) { // It's also there if we query for departures on the 10th departures, err = g.Departures("3a", time.Date(2020, 2, 10, 0, 15, 0, 0, tzNYC), 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "3a", RouteID: "L", @@ -462,7 +462,7 @@ func testStaticDeparturesOvernightTrip(t *testing.T, backend string) { // NYC+5) departures, err = g.Departures("3a", time.Date(2020, 2, 10, 4, 30, 0, 0, time.UTC), 2*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "3a", RouteID: "L", @@ -474,7 +474,7 @@ func testStaticDeparturesOvernightTrip(t *testing.T, backend string) { }, departures) departures, err = g.Departures("3a", time.Date(2020, 2, 10, 5, 15, 0, 0, time.UTC), 20*time.Minute, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "3a", RouteID: "L", @@ -533,7 +533,7 @@ func testStaticDeparturesCalendarDateOverride(t *testing.T, backend string) { // disabled. departures, err := g.Departures("8a", time.Date(2020, 2, 9, 22, 0, 0, 0, tzNYC), 2*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "8a", RouteID: "L", @@ -544,24 +544,24 @@ func testStaticDeparturesCalendarDateOverride(t *testing.T, backend string) { }, departures) departures, err = g.Departures("8a", time.Date(2020, 2, 8, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = g.Departures("3a", time.Date(2020, 2, 8, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) // The trips from the 16th are also disabled, including spill // over into the 17th. The 15th is still up though, including // spill over into the 16th. departures, err = g.Departures("8a", time.Date(2020, 2, 16, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = g.Departures("3a", time.Date(2020, 2, 16, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = g.Departures("8a", time.Date(2020, 2, 15, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "8a", RouteID: "L", @@ -572,7 +572,7 @@ func testStaticDeparturesCalendarDateOverride(t *testing.T, backend string) { }, departures) departures, err = g.Departures("3a", time.Date(2020, 2, 15, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "3a", RouteID: "L", @@ -586,7 +586,7 @@ func testStaticDeparturesCalendarDateOverride(t *testing.T, backend string) { // into the the 25th. 25th remains disabled. departures, err = g.Departures("8a", time.Date(2020, 2, 24, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "8a", RouteID: "L", @@ -597,7 +597,7 @@ func testStaticDeparturesCalendarDateOverride(t *testing.T, backend string) { }, departures) departures, err = g.Departures("3a", time.Date(2020, 2, 24, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "3a", RouteID: "L", @@ -608,7 +608,7 @@ func testStaticDeparturesCalendarDateOverride(t *testing.T, backend string) { }, departures) departures, err = g.Departures("8a", time.Date(2020, 2, 25, 22, 0, 0, 0, tzNYC), 5*time.Hour, -1, "", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) } // Real world schedules seem to provide departure_time for all stops, @@ -652,7 +652,7 @@ func testStaticDeparturesNoDepartureFromFinalStop(t *testing.T, backend string) assert.Equal(t, nil, err) assert.Equal(t, 1, len(departures)) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "14", RouteID: "L", @@ -664,7 +664,7 @@ func testStaticDeparturesNoDepartureFromFinalStop(t *testing.T, backend string) departures, err = g.Departures("3a", time.Date(2020, 2, 9, 23, 0, 0, 0, tzNYC), 2*time.Hour, -1, "", -1, nil) assert.Equal(t, nil, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) } func testStaticDeparturesFiltering(t *testing.T, backend string) { @@ -730,7 +730,7 @@ func testStaticDeparturesFiltering(t *testing.T, backend string) { departures, err := g.Departures("alpha", time.Date(2020, 3, 14, 0, 0, 0, 0, tzNYC), longDuration, 1, "", -1, nil) assert.NoError(t, err) assert.Equal(t, 1, len(departures)) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "alpha", RouteID: "RouteA", @@ -743,18 +743,18 @@ func testStaticDeparturesFiltering(t *testing.T, backend string) { // Specifying non-existent route and/or direction -> no results departures, err = g.Departures("alpha", time.Date(2020, 3, 14, 0, 0, 0, 0, tzNYC), longDuration, 1, "", 1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = g.Departures("alpha", time.Date(2020, 3, 14, 0, 0, 0, 0, tzNYC), longDuration, 1, "RouteC", 0, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) departures, err = g.Departures("alpha", time.Date(2020, 3, 14, 0, 0, 0, 0, tzNYC), longDuration, 1, "RouteC", -1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{}, departures) + assert.Equal(t, []model.Departure{}, departures) // The beta stop has departures in 2 direction departures, err = g.Departures("beta", time.Date(2020, 3, 14, 0, 0, 0, 0, tzNYC), longDuration, 1, "", 0, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "beta", RouteID: "RouteA", @@ -766,7 +766,7 @@ func testStaticDeparturesFiltering(t *testing.T, backend string) { departures, err = g.Departures("beta", time.Date(2020, 3, 14, 0, 0, 0, 0, tzNYC), longDuration, 1, "", 1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "beta", RouteID: "RouteA", @@ -779,7 +779,7 @@ func testStaticDeparturesFiltering(t *testing.T, backend string) { // Pushing start time back discards earlier departures departures, err = g.Departures("beta", time.Date(2020, 3, 14, 12, 0, 0, 0, tzNYC), longDuration, 1, "", 0, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "beta", RouteID: "RouteA", @@ -790,7 +790,7 @@ func testStaticDeparturesFiltering(t *testing.T, backend string) { }, departures) departures, err = g.Departures("beta", time.Date(2020, 3, 14, 12, 0, 0, 0, tzNYC), longDuration, 1, "RouteA", 1, nil) assert.NoError(t, err) - assert.Equal(t, []gtfs.Departure{ + assert.Equal(t, []model.Departure{ { StopID: "beta", RouteID: "RouteA", @@ -915,7 +915,7 @@ func testStaticDeparturesWithParentStations(t *testing.T, backend string) { }, }) - getDeps := func(stopID string) []gtfs.Departure { + getDeps := func(stopID string) []model.Departure { // Feb 3rd is a Monday. departures, err := g.Departures( stopID, From 0e89916106e45168405f0652c8926bd5f5266f83 Mon Sep 17 00:00:00 2001 From: Mats Linander Date: Sat, 6 Jan 2024 13:33:38 -0500 Subject: [PATCH 3/5] reorder --- model/model.go | 105 +++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/model/model.go b/model/model.go index 064e900..c5753d9 100644 --- a/model/model.go +++ b/model/model.go @@ -5,6 +5,33 @@ import ( "time" ) +// Holds all external facing types and constants. + +type LocationType int + +const ( + LocationTypeStop LocationType = iota + LocationTypeStation + LocationTypeEntranceExit + LocationTypeGenericNode + LocationTypeBoardingArea +) + +type RouteType int + +const ( + RouteTypeTram RouteType = 0 + RouteTypeSubway = 1 + RouteTypeRail = 2 + RouteTypeBus = 3 + RouteTypeFerry = 4 + RouteTypeCable = 5 + RouteTypeAerial = 6 + RouteTypeFunicular = 7 + RouteTypeTrolleybus = 11 + RouteTypeMonorail = 12 +) + type Agency struct { ID string Name string @@ -12,6 +39,20 @@ type Agency struct { Timezone string } +type Calendar struct { + ServiceID string + StartDate string + EndDate string + Weekday int8 +} + +type CalendarDate struct { + ServiceID string + Date string + ExceptionType int8 + // TODO: Enum for exception types? +} + type Stop struct { ID string Code string @@ -25,16 +66,6 @@ type Stop struct { PlatformCode string } -type LocationType int - -const ( - LocationTypeStop LocationType = iota - LocationTypeStation - LocationTypeEntranceExit - LocationTypeGenericNode - LocationTypeBoardingArea -) - type Trip struct { ID string RouteID string @@ -44,6 +75,18 @@ type Trip struct { DirectionID int8 } +type Route struct { + ID string + AgencyID string + ShortName string + LongName string + Desc string + Type RouteType + URL string + Color string + TextColor string +} + type StopTime struct { TripID string StopID string @@ -67,47 +110,6 @@ func (st *StopTime) DepartureTime() time.Duration { return time.Duration(h)*time.Hour + time.Duration(m)*time.Minute + time.Duration(s)*time.Second } -type Route struct { - ID string - AgencyID string - ShortName string - LongName string - Desc string - Type RouteType - URL string - Color string - TextColor string -} - -type RouteType int - -const ( - RouteTypeTram RouteType = 0 - RouteTypeSubway = 1 - RouteTypeRail = 2 - RouteTypeBus = 3 - RouteTypeFerry = 4 - RouteTypeCable = 5 - RouteTypeAerial = 6 - RouteTypeFunicular = 7 - RouteTypeTrolleybus = 11 - RouteTypeMonorail = 12 -) - -type Calendar struct { - ServiceID string - StartDate string - EndDate string - Weekday int8 -} - -type CalendarDate struct { - ServiceID string - Date string - ExceptionType int8 - // TODO: Enum for exception types? -} - // Holds all Headsigns for trips passing through a stop, for a given // route and direction. type RouteDirection struct { @@ -117,6 +119,7 @@ type RouteDirection struct { Headsigns []string } +// A vehicle departing from a stop. type Departure struct { StopID string RouteID string From b7a85ebb1891adba109ce30500713a2601fc80c7 Mon Sep 17 00:00:00 2001 From: Mats Linander Date: Sat, 6 Jan 2024 13:51:23 -0500 Subject: [PATCH 4/5] enum for ExceptionType --- model/model.go | 9 ++++++++- parse/calendar_dates.go | 2 +- parse/calendar_dates_test.go | 8 ++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/model/model.go b/model/model.go index c5753d9..2638865 100644 --- a/model/model.go +++ b/model/model.go @@ -32,6 +32,13 @@ const ( RouteTypeMonorail = 12 ) +type ExceptionType int + +const ( + ExceptionTypeAdded ExceptionType = 1 + ExceptionTypeRemoved = 2 +) + type Agency struct { ID string Name string @@ -49,7 +56,7 @@ type Calendar struct { type CalendarDate struct { ServiceID string Date string - ExceptionType int8 + ExceptionType ExceptionType // TODO: Enum for exception types? } diff --git a/parse/calendar_dates.go b/parse/calendar_dates.go index fac10cb..99cf27d 100644 --- a/parse/calendar_dates.go +++ b/parse/calendar_dates.go @@ -58,7 +58,7 @@ func ParseCalendarDates( writer.WriteCalendarDate(&model.CalendarDate{ ServiceID: cd.ServiceID, Date: cd.Date, - ExceptionType: cd.ExceptionType, + ExceptionType: model.ExceptionType(cd.ExceptionType), }) } diff --git a/parse/calendar_dates_test.go b/parse/calendar_dates_test.go index 4148ead..dd4731c 100644 --- a/parse/calendar_dates_test.go +++ b/parse/calendar_dates_test.go @@ -30,7 +30,7 @@ s1,20170101,1`, &model.CalendarDate{ ServiceID: "s1", Date: "20170101", - ExceptionType: 1, + ExceptionType: model.ExceptionTypeAdded, }, }, "20170101", @@ -49,17 +49,17 @@ s2,20170103,1`, &model.CalendarDate{ ServiceID: "s1", Date: "20170101", - ExceptionType: 1, + ExceptionType: model.ExceptionTypeAdded, }, &model.CalendarDate{ ServiceID: "s1", Date: "20170102", - ExceptionType: 2, + ExceptionType: model.ExceptionTypeRemoved, }, &model.CalendarDate{ ServiceID: "s2", Date: "20170103", - ExceptionType: 1, + ExceptionType: model.ExceptionTypeAdded, }, }, "20170101", From ccccc6324d158445f454e632e26bbe4baf31eb7e Mon Sep 17 00:00:00 2001 From: Mats Linander Date: Sat, 6 Jan 2024 13:52:17 -0500 Subject: [PATCH 5/5] TODO DONE --- model/model.go | 1 - 1 file changed, 1 deletion(-) diff --git a/model/model.go b/model/model.go index 2638865..4da5ed8 100644 --- a/model/model.go +++ b/model/model.go @@ -57,7 +57,6 @@ type CalendarDate struct { ServiceID string Date string ExceptionType ExceptionType - // TODO: Enum for exception types? } type Stop struct {