szczanieckiej.git

commit b0f2f5f8dc5c9618b5026498dfae30f1928b4140

Author: Adam <git@apiote.xyz>

use traffic structs from DSL

 api/api.go | 62 ++++----
 mkfile | 9 
 server/router.go | 6 
 traffic/access.go | 81 +++++-----
 traffic/convert.go | 74 +++++----
 traffic/poznan_ztm.go | 2 
 traffic/structs.go | 83 ++++++-----
 traffic/structs_gen.go | 314 ++++++++++++++++++++++++++++++++++++++++++++


diff --git a/api/api.go b/api/api.go
index 282afc5ffb45cc568cc417d31a4a14e185c7087c..72333af3ec86c830a0c82e95b5dc7d25c48ae670 100644
--- a/api/api.go
+++ b/api/api.go
@@ -10,7 +10,7 @@
 	"encoding/hex"
 	"errors"
 	"fmt"
-	"image/color"
+	//"image/color"
 	"log"
 	"sort"
 	"time"
@@ -41,7 +41,7 @@ 	s := StopV1{
 		Code:          stop.Code,
 		Name:          stop.NodeName,
 		Zone:          stop.Zone,
-		Position:      PositionV1{Lat: stop.Coordinates.Lat, Lon: stop.Coordinates.Lon},
+		Position:      PositionV1{Lat: stop.Position.Lat, Lon: stop.Position.Lon},
 		ChangeOptions: []ChangeOptionV1{},
 	}
 	for _, option := range stop.ChangeOptions {
@@ -57,7 +57,7 @@ 		Name:          stop.Name,
 		NodeName:      stop.NodeName,
 		Zone:          stop.Zone,
 		FeedID:        feedID,
-		Position:      PositionV1{Lat: stop.Coordinates.Lat, Lon: stop.Coordinates.Lon},
+		Position:      PositionV1{Lat: stop.Position.Lat, Lon: stop.Position.Lon},
 		ChangeOptions: []ChangeOptionV1{},
 	}
 	for _, option := range stop.ChangeOptions {
@@ -173,7 +173,7 @@
 	return l, nil
 }
 
-func convertTrafficVehicle(vehicle traffic.Vehicle, context traffic.Context, t *traffic.Traffic) (VehicleV1, error) {
+func convertTrafficVehicle(vehicle traffic.VehicleStatus, context traffic.Context, t *traffic.Traffic) (VehicleV1, error) {
 	line, err := traffic.GetLine(vehicle.LineName, context, t)
 	if err != nil {
 		return VehicleV1{}, fmt.Errorf("while getting line %s: %w", vehicle.LineName, err)
@@ -181,7 +181,7 @@ 	}
 	log.Printf("convertTrafficVehicle:: trafficVehicle: %+v, line: %+v\n", vehicle, line)
 	return VehicleV1{
 		Id:           string(vehicle.Id),
-		Position:     PositionV1{vehicle.Coordinates.Lat, vehicle.Coordinates.Lon},
+		Position:     PositionV1{vehicle.Position.Lat, vehicle.Position.Lon},
 		Capabilities: vehicle.Capabilities,
 		Speed:        vehicle.Speed,
 		Line:         LineStubV1{Name: line.Name, Kind: makeLineTypeV1(line), Colour: fromColor(line.Colour)},
@@ -193,7 +193,7 @@ 		// todo Delay
 	}, nil
 }
 
-func convertTrafficVehicleV2(vehicle traffic.Vehicle, context traffic.Context, t *traffic.Traffic) (VehicleV2, error) {
+func convertTrafficVehicleV2(vehicle traffic.VehicleStatus, context traffic.Context, t *traffic.Traffic) (VehicleV2, error) {
 	line, err := traffic.GetLine(vehicle.LineName, context, t)
 	if err != nil {
 		return VehicleV2{}, fmt.Errorf("while getting line %s: %w", vehicle.LineName, err)
@@ -201,7 +201,7 @@ 	}
 	log.Printf("convertTrafficVehicle:: trafficVehicle: %+v, line: %+v\n", vehicle, line)
 	return VehicleV2{
 		Id:           string(vehicle.Id),
-		Position:     PositionV1{vehicle.Coordinates.Lat, vehicle.Coordinates.Lon},
+		Position:     PositionV1{vehicle.Position.Lat, vehicle.Position.Lon},
 		Capabilities: vehicle.Capabilities,
 		Speed:        vehicle.Speed,
 		Line:         LineStubV2{Name: line.Name, Kind: makeLineTypeV2(line), Colour: fromColor(line.Colour)},
@@ -229,7 +229,7 @@
 func marshalStopOrder(tripOffset uint, stopOrder int) (string, error) {
 	order := traffic.StopOrder{
 		TripOffset: tripOffset,
-		Order:      stopOrder,
+		Sequence:   stopOrder,
 	}
 	bytes, err := bare.Marshal(&order)
 	return hex.EncodeToString(bytes), err
@@ -378,7 +378,7 @@ 	for _, locatable := range locatables {
 		if stop, ok := locatable.(traffic.Stop); ok {
 			s := convertTrafficStop(stop)
 			success.Locatables = append(success.Locatables, LocatableV1(s))
-		} else if vehicle, ok := locatable.(traffic.Vehicle); ok {
+		} else if vehicle, ok := locatable.(traffic.VehicleStatus); ok {
 			v, err := convertTrafficVehicle(vehicle, context, t)
 			if err != nil {
 				return success, fmt.Errorf("while converting Traffic Vehicle %s: %w", vehicle.Id, err)
@@ -402,7 +402,7 @@ 	for _, locatable := range locatables {
 		if stop, ok := locatable.(traffic.Stop); ok {
 			s := convertTrafficStopV2(stop, context.FeedName)
 			success.Locatables = append(success.Locatables, LocatableV2(s))
-		} else if vehicle, ok := locatable.(traffic.Vehicle); ok {
+		} else if vehicle, ok := locatable.(traffic.VehicleStatus); ok {
 			v, err := convertTrafficVehicleV2(vehicle, context, t)
 			if err != nil {
 				return success, fmt.Errorf("while converting Traffic Vehicle %s: %w", vehicle.Id, err)
@@ -434,11 +434,11 @@
 	return success, nil*/
 }
 
-func convertVehicle(update gtfs_rt.Update, vehicles map[traffic.ID]traffic.Vehicle, line traffic.Line, headsign string) VehicleV1 {
+func convertVehicle(update gtfs_rt.Update, vehicles map[string]traffic.Vehicle, line traffic.Line, headsign string) VehicleV1 {
 	return VehicleV1{
 		Id:           update.VehicleID,
 		Position:     PositionV1{Lat: float64(update.Latitude), Lon: float64(update.Longitude)},
-		Capabilities: vehicles[traffic.ID(update.VehicleID)].Capabilities,
+		Capabilities: vehicles[update.VehicleID].Capabilities,
 		Speed:        update.Speed,
 		Line:         LineStubV1{Name: line.Name, Kind: makeLineTypeV1(line), Colour: fromColor(line.Colour)},
 		Headsign:     headsign,
@@ -447,11 +447,11 @@ 		// todo OccupancyStatus
 	}
 }
 
-func convertVehicleV2(update gtfs_rt.Update, vehicles map[traffic.ID]traffic.Vehicle, line traffic.Line, headsign string) VehicleV2 {
+func convertVehicleV2(update gtfs_rt.Update, vehicles map[string]traffic.Vehicle, line traffic.Line, headsign string) VehicleV2 {
 	return VehicleV2{
 		Id:           update.VehicleID,
 		Position:     PositionV1{Lat: float64(update.Latitude), Lon: float64(update.Longitude)},
-		Capabilities: vehicles[traffic.ID(update.VehicleID)].Capabilities,
+		Capabilities: vehicles[update.VehicleID].Capabilities,
 		Speed:        update.Speed,
 		Line:         LineStubV2{Name: line.Name, Kind: makeLineTypeV2(line), Colour: fromColor(line.Colour)},
 		Headsign:     headsign,
@@ -461,7 +461,7 @@ 	}
 }
 
 func CreateSuccessDeparturesV1(stop traffic.Stop, departures []traffic.DepartureRealtime,
-	date time.Time, vehicles map[traffic.ID]traffic.Vehicle, alerts []traffic.Alert, ctx traffic.Context, t *traffic.Traffic, accept uint) (DeparturesResponse, error) {
+	date time.Time, vehicles map[string]traffic.Vehicle, alerts []traffic.Alert, ctx traffic.Context, t *traffic.Traffic, accept uint) (DeparturesResponse, error) {
 	d := []DepartureV1{}
 	var success DeparturesResponse
 	now := time.Now()
@@ -473,7 +473,7 @@ 	datetime := time.Date(date.Year(), date.Month(),
 		date.Day(), now.Hour(), now.Minute(), now.Second(), 0, timezone)
 	for _, trafficDeparture := range departures {
 		zoneAbbr := trafficDeparture.Update.Time.Location().String()
-		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Order)
+		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Sequence)
 		if err != nil {
 			return success, err
 		}
@@ -546,7 +546,7 @@ 	return success, nil
 }
 
 func CreateSuccessDeparturesV2(stop traffic.Stop, departures []traffic.DepartureRealtime,
-	date time.Time, vehicles map[traffic.ID]traffic.Vehicle, alerts []traffic.Alert, ctx traffic.Context, t *traffic.Traffic, accept uint) (DeparturesResponse, error) {
+	date time.Time, vehicles map[string]traffic.Vehicle, alerts []traffic.Alert, ctx traffic.Context, t *traffic.Traffic, accept uint) (DeparturesResponse, error) {
 	d := []DepartureV2{}
 	var success DeparturesResponse
 	now := time.Now()
@@ -558,7 +558,7 @@ 	datetime := time.Date(date.Year(), date.Month(),
 		date.Day(), now.Hour(), now.Minute(), now.Second(), 0, timezone)
 	for _, trafficDeparture := range departures {
 		zoneAbbr := trafficDeparture.Update.Time.Location().String()
-		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Order)
+		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Sequence)
 		if err != nil {
 			return success, err
 		}
@@ -630,7 +630,7 @@ 	}
 	return success, nil
 }
 
-func fromColor(c color.RGBA) ColourV1 {
+func fromColor(c traffic.Colour) ColourV1 {
 	return ColourV1{
 		R: c.R,
 		G: c.G,
@@ -639,9 +639,9 @@ 	}
 }
 
 func makeLineTypeV1(line traffic.Line) LineTypeV1 {
-	if line.Type == 0 {
+	if line.Kind == traffic.TRAM {
 		return TRAM
-	} else if line.Type == 3 {
+	} else if line.Kind == traffic.BUS {
 		return BUS
 	} else {
 		return LINE_UNKNOWN
@@ -649,11 +649,11 @@ 	}
 }
 
 func makeLineTypeV2(line traffic.Line) LineTypeV2 {
-	if line.Type == 0 {
+	if line.Kind == traffic.TRAM {
 		return LINE_V2_TRAM
-	} else if line.Type == 3 {
+	} else if line.Kind == traffic.BUS {
 		return LINE_V2_BUS
-	} else if line.Type == 11 {
+	} else if line.Kind == traffic.TROLLEYBUS {
 		return LINE_V2_TROLLEYBUS
 	} else {
 		return LINE_V2_UNKNOWN
@@ -667,20 +667,20 @@ 		Headsign: option.Headsign,
 	}
 }
 
-func makeBoardingV1(pickup, dropoff uint) uint8 {
+func makeBoardingV1(pickup, dropoff traffic.Boarding) uint8 {
 	b := BOARDING_NONE
-	if pickup == 0 {
+	if pickup == traffic.REGULAR {
 		b |= ONBOARDING_REGULAR
-	} else if pickup == 2 {
+	} else if pickup == traffic.BY_PHONE {
 		b |= ONBOARDING_PHONE
-	} else if pickup == 3 {
+	} else if pickup == traffic.BY_DRIVER {
 		b |= ONBOARDING_DRIVER
 	}
-	if dropoff == 0 {
+	if dropoff == traffic.REGULAR {
 		b |= OFFBOARDING_REGULAR
-	} else if dropoff == 2 {
+	} else if dropoff == traffic.BY_PHONE {
 		b |= OFFBOARDING_PHONE
-	} else if dropoff == 3 {
+	} else if dropoff == traffic.BY_DRIVER {
 		b |= OFFBOARDING_DRIVER
 	}
 	return uint8(b)




diff --git a/mkfile b/mkfile
index db35f09ce4ce2a93d899cc44161f7ff08912200d..2117ab05ae5dfbfe4ab578399fc7ea23805fb286 100644
--- a/mkfile
+++ b/mkfile
@@ -1,13 +1,13 @@
 ALL=`echo api/* config/* file/* gtfs_rt/* main.go server/* traffic/* transformers/*`
 
-all:V: bimba_server
+all:V: szczanieckiej
 
-init:V: api/structs_gen.go
+init:V: api/structs_gen.go traffic/structs_gen.go
 
 lint:V:
 	golangci-lint -j 2 run --fast --timeout 30m --skip-files '(gtfs-realtime.pb.go|structs_gen.go)' -E asasalint -E asciicheck -E bidichk -E bodyclose -E contextcheck -E decorder -E dupl -E durationcheck -E errcheck -E errname -E errorlint -E exhaustive -E exhaustruct -E exportloopref -E gocritic -E gofmt -E goimports -E gofumpt -E gomnd -E gomoddirectives -E gosec -E gosimple -E govet -E importas -E ineffassign -E interfacer -E ireturn -E loggercheck -E misspell -E nilerr -E nilnil -E noctx -E nolintlint -E prealloc -E predeclared -E reassign -E revive -E staticcheck -E stylecheck -E tagliatelle -E unconvert -E unparam -E unused -E usestdlibvars -E wastedassign -E wrapcheck -D containedctx -D cyclop -D deadcode -D depguard -D dogsled -D dupword -D errchkjson -D execinquery -D exhaustivestruct -D forbidigo -D forcetypeassert -D funlen -D gci -D ginkgolinter -D gocheckcompilerdirectives -D gochecknoglobals -D gochecknoinits -D gocognit -D goconst -D gocyclo -D godox -D goerr113 -D goheader -D golint -D gomodguard -D goprintffuncname -D grouper -D ifshort -D interfacebloat -D lll -D maintidx -D makezero -D maligned -D musttag -D nestif -D nlreturn -D nonamedreturns -D nosnakecase -D nosprintfhostport -D paralleltest -D promlinter -D testpackage -D typecheck -D varnamelen -D whitespace -D wsl
 
-bimba_server: $ALL
+szczanieckiej: $ALL
 	go build
 
 api/structs_gen.go: ../traffic/api/api.bare
@@ -15,3 +15,6 @@ 	bare-gen -p api ../traffic/api/api.bare api/structs_gen2.go
 	awk '!seen[$0]++ || $0 !~ /func \(_ StopV1\) IsUnion\(\) \{\}/' api/structs_gen2.go >api/structs_gen3.go
 	awk '!seen[$0]++ || $0 !~ /func \(_ StopV2\) IsUnion\(\) \{\}/' api/structs_gen3.go >api/structs_gen.go
 	rm api/structs_gen2.go api/structs_gen3.go
+
+traffic/structs_gen.go: ../traffic/traffic.bare
+	bare-gen -p traffic ../traffic/traffic.bare traffic/structs_gen.go




diff --git a/server/router.go b/server/router.go
index 84c4a432f7143949bdc7e26efd85f45f7ce67a1e..da04ad0d535ffcfe19d14104742e7d4c778b5867 100644
--- a/server/router.go
+++ b/server/router.go
@@ -351,7 +351,7 @@ 				return fmt.Errorf("while creating stopsSuccess from near stops: %w", err)
 			}
 		} else {
 			ix := t.CodeIndexes[feedName][versionCode]
-			code := traffic.ID(query)
+			code := query
 			_, exists := ix[code]
 			if exists {
 				stop, err := traffic.GetStop(code, context, t)
@@ -420,7 +420,7 @@ 	err := r.ParseForm()
 	if err != nil {
 		return fmt.Errorf("while parsing form: %w", err)
 	}
-	code := traffic.ID(r.Form.Get("code"))
+	code := r.Form.Get("code")
 	if code == "" {
 		return ServerError{
 			code:  http.StatusBadRequest,
@@ -569,7 +569,7 @@ 			FeedName: feedName,
 			Version:  versionCode,
 		}
 
-		trip, err := traffic.GetTripFromStop(tripID, traffic.ID(stopCode), context, t)
+		trip, err := traffic.GetTripFromStop(tripID, stopCode, context, t)
 		if err != nil {
 			return fmt.Errorf("while getting line: %w", err)
 		}




diff --git a/traffic/access.go b/traffic/access.go
index 7fbd3560db527c48871124959d2b3b76f7a03a9b..33406a86d15997b3bc43950c83694d54c8e5a7b7 100644
--- a/traffic/access.go
+++ b/traffic/access.go
@@ -87,7 +87,7 @@ 	date := time.Format(DateFormat)
 	for _, schedule := range calendar {
 		if schedule.StartDate <= date && date <= schedule.EndDate &&
 			(schedule.Weekdays&weekday != 0) {
-			schedules[schedule.ScheduleID] = struct{}{}
+			schedules[schedule.Id] = struct{}{}
 		}
 	}
 	var err error
@@ -254,7 +254,7 @@
 func readTrips(input ...interface{}) (interface{}, error) {
 	result := input[0].(_Result)
 	trips := map[string]Trip{}
-	orders := []StopOrder{}
+	orders := map[string]StopOrder{}
 
 	for _, order := range result.Stop.Order {
 		_, err := result.TripsFile.Seek(int64(order.TripOffset), 0)
@@ -270,9 +270,9 @@
 		_, inToday := result.TodaySchedule[trip.ScheduleID]
 		_, inYesterday := result.YesterdaySchedule[trip.ScheduleID]
 		if inToday || inYesterday {
-			trips[trip.ID] = trip
-			order.TripID = trip.ID
-			orders = append(orders, order)
+			trips[trip.Id] = trip
+			order.TripID = trip.Id
+			orders[trip.Id] = order
 		}
 	}
 	result.Stop.Order = orders
@@ -318,7 +318,7 @@ 	found := false
 	departureRt := DepartureRealtime{}
 	var finalErr error
 	for _, departure := range trip.Departures {
-		if departure.StopSeq == order.Order {
+		if departure.StopSequence == order.Sequence {
 
 			departureRt.Departure = departure
 			departureRt.Headsign = trip.Headsign
@@ -336,7 +336,7 @@
 			if departureTime.After(result.Midnight) {
 				if result.DeparturesType == DEPARTURES_HYBRID && !timedOut {
 					departureRt.Update, err = getRealtimeOffset(order.TripID,
-						order.Order, feed)
+						order.Sequence, feed)
 					if err != nil {
 						if isTimeout(err) {
 							timedOut = true
@@ -359,8 +359,8 @@ 		}
 	}
 	if !found {
 		return departureRt, traffic_errors.NoStopOrder{
-			TripID: trip.ID,
-			Order:  order.Order,
+			TripID: trip.Id,
+			Order:  order.Sequence,
 		}
 	}
 	return departureRt, finalErr
@@ -439,7 +439,7 @@ 		v, err := r.ReadUint()
 		if err != nil {
 			return ix, fmt.Errorf("while reading value at %d: %w\n", i, err)
 		}
-		ix[ID(k)] = uint(v)
+		ix[k] = uint(v)
 	}
 
 	return ix, nil
@@ -619,6 +619,7 @@ 					return feedPositionIndex, fmt.Errorf("while unmarshaling: %w", err)
 				}
 			}
 			stop.Name = ""
+			stop.NodeName = ""
 			stop.ChangeOptions = nil
 			stop.Zone = ""
 			stop.Order = nil
@@ -646,6 +647,7 @@ }
 
 func Initialise(sigChan chan os.Signal, doneChan chan bool, cfg config.Config,
 	traffic *Traffic) {
+	bare.MaxMapSize(8192)
 	for {
 		sig := <-sigChan
 		if sig == os.Interrupt {
@@ -712,7 +714,7 @@ 	}
 	doneChan <- true
 }
 
-func GetDepartures(stopCode ID, lineName, dataHome, feedName string,
+func GetDepartures(stopCode string, lineName, dataHome, feedName string,
 	versionCode Validity, traffic *Traffic, date time.Time,
 	departuresType DeparturesType) ([]DepartureRealtime, error) {
 
@@ -758,7 +760,7 @@ 	}
 
 }
 
-func GetTripFromStop(tripID string, stopCode ID, context Context, traffic *Traffic) ([]TimedStopStub, error) {
+func GetTripFromStop(tripID string, stopCode string, context Context, traffic *Traffic) ([]TimedStopStub, error) {
 	stubs := []TimedStopStub{}
 
 	var (
@@ -776,12 +778,9 @@ 			return stubs, fmt.Errorf("while getting starting stop: %w", err)
 		}
 		tripOffset := -1
 		order = -1
-		for _, o := range startingStop.Order {
-			if o.TripID == tripID {
-				tripOffset = int(o.TripOffset)
-				order = o.Order
-			}
-		}
+		o := startingStop.Order[tripID]
+		tripOffset = int(o.TripOffset)
+		order = o.Sequence
 		if tripOffset == -1 {
 			return stubs, fmt.Errorf("trip for starting stop not found")
 		}
@@ -797,7 +796,7 @@ 		}
 	}
 
 	for _, departure := range trip.Departures {
-		if departure.StopSeq >= order {
+		if departure.StopSequence >= order {
 			stop, err := getStopByOffset(uint(departure.StopOffset), context, traffic)
 			if err != nil {
 				return stubs, fmt.Errorf("while getting stop: %w", err)
@@ -810,7 +809,7 @@ 				StopStub: StopStub{
 					Code:     stop.Code,
 					Name:     stop.Name,
 					Zone:     stop.Zone,
-					OnDemand: departure.Pickup == 3, // todo BAF10
+					OnDemand: departure.Pickup == BY_DRIVER || departure.Dropoff == BY_DRIVER,
 				},
 				Time: time,
 			})
@@ -892,12 +891,12 @@ 		return r.(_Result).Trip, nil
 	}
 }
 
-func GetStop(stopCode ID, context Context, traffic *Traffic) (Stop, error) {
+func GetStop(stopCode string, context Context, traffic *Traffic) (Stop, error) {
 	codeIndex := traffic.CodeIndexes[context.FeedName][context.Version]
 	return getStopByOffset(codeIndex[stopCode], context, traffic)
 }
 
-func GetStopStub(stopCode ID, lineName string, context Context, traffic *Traffic) (StopStub, error) {
+func GetStopStub(stopCode string, lineName string, context Context, traffic *Traffic) (StopStub, error) {
 	stop, err := GetStop(stopCode, context, traffic)
 	if err != nil {
 		return StopStub{}, err
@@ -909,7 +908,7 @@ 	for _, order := range stop.Order {
 		offset := order.TripOffset
 		trip, _ = GetTripByOffset(offset, context, traffic)
 		if trip.LineName == lineName {
-			stopOrder = order.Order
+			stopOrder = order.Sequence
 			break
 		}
 	}
@@ -918,7 +917,7 @@ 	stopStub := StopStub{
 		Code:     stop.Code,
 		Name:     stop.Name,
 		Zone:     stop.Zone,
-		OnDemand: trip.Departures[stopOrder].Pickup == 3, // todo BAF10
+		OnDemand: trip.Departures[stopOrder].Pickup == BY_DRIVER || trip.Departures[stopOrder].Dropoff == BY_DRIVER,
 	}
 	return stopStub, nil
 }
@@ -991,7 +990,7 @@ 	positionIndex := traffic.PositionIndexes[context.FeedName][context.Version]
 	codeIndex := traffic.CodeIndexes[context.FeedName][context.Version]
 	spatials := positionIndex.NearestNeighbors(12, rtreego.Point{location.Lat, location.Lon})
 	for _, spatial := range spatials {
-		stop, err := getStopByOffset(codeIndex[ID(spatial.(Stop).Code)], context, traffic)
+		stop, err := getStopByOffset(codeIndex[spatial.(Stop).Code], context, traffic)
 		if err != nil {
 			return stops, fmt.Errorf("while getting stop by offset for %s: %w", spatial.(Stop).Code, err)
 		}
@@ -1014,8 +1013,8 @@ 		return []Alert{}, fmt.Errorf("while geting alerts: %w", err)
 	}
 	lastUpdatedGtfsRt[feed.String()] = lastUpdated
 
-	stop, err := GetStop(ID(stopCode), context, traffic)
-	for _, pos := range gtfsAlerts.ByStop[stop.ID] {
+	stop, err := GetStop(stopCode, context, traffic)
+	for _, pos := range gtfsAlerts.ByStop[stop.Id] {
 		alertPositions[pos] = struct{}{}
 	}
 	for _, option := range stop.ChangeOptions {
@@ -1023,10 +1022,10 @@ 		line, err := GetLine(option.LineName, context, traffic)
 		if err != nil {
 			return []Alert{}, fmt.Errorf("while getting line %s: %w", option.LineName, err)
 		}
-		for _, pos := range gtfsAlerts.ByRoute[line.ID] {
+		for _, pos := range gtfsAlerts.ByRoute[line.Id] {
 			alertPositions[pos] = struct{}{}
 		}
-		for _, pos := range gtfsAlerts.ByType[line.Type] {
+		for _, pos := range gtfsAlerts.ByType[line.Kind.Value()] {
 			alertPositions[pos] = struct{}{}
 		}
 	}
@@ -1035,7 +1034,7 @@ 		trip, err := GetTripByOffset(order.TripOffset, context, traffic)
 		if err != nil {
 			return []Alert{}, fmt.Errorf("while getting trip at %d: %w", order.TripOffset, err)
 		}
-		for _, pos := range gtfsAlerts.ByTrip[trip.ID] {
+		for _, pos := range gtfsAlerts.ByTrip[trip.Id] {
 			alertPositions[pos] = struct{}{}
 		}
 	}
@@ -1132,25 +1131,25 @@ 	err = file.CleanOldVersions(FeedPath(cfg, feed), validVersionsMap)
 	return err
 }
 
-func convertVehicle(update gtfs_rt.Update, context Context, t *Traffic) (Vehicle, error) {
+func convertVehicle(update gtfs_rt.Update, context Context, t *Traffic) (VehicleStatus, error) {
 	vehicles := t.Vehicles[context.FeedName][context.Version]
 	tripID := update.TripUpdate.GetTrip().GetTripId()
 	trip, err := GetTrip(tripID, context, t)
 	if err != nil {
-		return Vehicle{}, fmt.Errorf("while converting vehicle: %w", err)
+		return VehicleStatus{}, fmt.Errorf("while converting vehicle: %w", err)
 	}
-	return Vehicle{
-		Id:           ID(update.VehicleID),
-		Coordinates:  Position{float64(update.Latitude), float64(update.Longitude)},
-		Capabilities: vehicles[ID(update.VehicleID)].Capabilities,
+	return VehicleStatus{
+		Id:           update.VehicleID,
+		Position:     Position{float64(update.Latitude), float64(update.Longitude)},
+		Capabilities: vehicles[update.VehicleID].Capabilities,
 		Speed:        update.Speed,
 		Headsign:     trip.Headsign,
 		LineName:     trip.LineName,
 	}, nil
 }
 
-func GetVehicle(tripID string, context Context, t *Traffic) (Vehicle, error) {
-	vehicle := Vehicle{}
+func GetVehicle(tripID string, context Context, t *Traffic) (VehicleStatus, error) {
+	vehicle := VehicleStatus{}
 	update, err := getRealtimeOffset(tripID, 0, t.Feeds[context.FeedName])
 	if err != nil {
 		return vehicle, fmt.Errorf("while getting realtime update: %w", err)
@@ -1173,7 +1172,7 @@ 		return stops, fmt.Errorf("while creating a rect: %w", err)
 	}
 	spatials := positionIndex.SearchIntersect(rect)
 	for _, spatial := range spatials {
-		stop, err := getStopByOffset(codeIndex[ID(spatial.(Stop).Code)], context, traffic)
+		stop, err := getStopByOffset(codeIndex[spatial.(Stop).Code], context, traffic)
 		if err != nil {
 			return stops, fmt.Errorf("while getting stop by offset for %s: %w", spatial.(Stop).Code, err)
 		}
@@ -1182,9 +1181,9 @@ 	}
 	return stops, nil
 }
 
-func GetVehiclesIn(lb, rt Position, context Context, t *Traffic) ([]Vehicle, error) {
+func GetVehiclesIn(lb, rt Position, context Context, t *Traffic) ([]VehicleStatus, error) {
 	// todo limit rect size
-	vehicles := []Vehicle{}
+	vehicles := []VehicleStatus{}
 	updates, err := getRealtimeUpdates(t.Feeds[context.FeedName])
 	if err != nil {
 		return vehicles, err




diff --git a/traffic/convert.go b/traffic/convert.go
index c8456d4d4fa983cda021547b19779cbc4fc03fb7..6c396ee7802c771c58d66051a8b23b2b1cca28c1 100644
--- a/traffic/convert.go
+++ b/traffic/convert.go
@@ -11,7 +11,7 @@ 	"bufio"
 	"encoding/csv"
 	"errors"
 	"fmt"
-	"image/color"
+	//"image/color"
 	"io"
 	"io/fs"
 	"log"
@@ -80,11 +80,11 @@ }
 
 // helper functions
 
-func hex2colour(hex string) color.RGBA {
+func hex2colour(hex string) Colour {
 	if hex[0] == '#' {
 		hex = hex[1:]
 	}
-	colour := color.RGBA{
+	colour := Colour{
 		A: 0xff,
 	}
 	hexToByte := func(b byte) byte {
@@ -305,7 +305,7 @@ 		}
 		if err != nil {
 			return c, fmt.Errorf("while reading a record: %w", err)
 		}
-		schedule.ScheduleID = record[fields["service_id"]]
+		schedule.Id = record[fields["service_id"]]
 		startDate := record[fields["start_date"]]
 		endDate := record[fields["end_date"]]
 		schedule.StartDate = startDate[:4] + "-" + startDate[4:6] + "-" + startDate[6:]
@@ -390,7 +390,7 @@ 			return c, fmt.Errorf("while reading a record: %w", err)
 		}
 		if record[fields["exception_type"]] == "1" {
 			date := record[fields["date"]]
-			schedule.ScheduleID = record[fields["service_id"]]
+			schedule.Id = record[fields["service_id"]]
 			schedule.StartDate = date[:4] + "-" + date[4:6] + "-" + date[6:]
 			schedule.EndDate = date[:4] + "-" + date[4:6] + "-" + date[6:]
 			schedule.Weekdays = 0xff
@@ -477,13 +477,13 @@
 		stopID := record[fields["stop_id"]]
 
 		tripID := record[fields["trip_id"]]
-		fmt.Sscanf(record[fields["stop_sequence"]], "%d", &departure.StopSeq)
+		fmt.Sscanf(record[fields["stop_sequence"]], "%d", &departure.StopSequence)
 		fmt.Sscanf(record[fields["pickup_type"]], "%d", &departure.Pickup)
 		fmt.Sscanf(record[fields["drop_off_type"]], "%d", &departure.Dropoff)
 
 		tripsThroughStop[stopID] = append(tripsThroughStop[stopID], StopOrder{
 			TripID: tripID,
-			Order:  departure.StopSeq,
+			Sequence:  departure.StopSequence,
 		})
 
 		if c.Feed.Flags().Headsign == HeadsignTripLastStop {
@@ -630,21 +630,21 @@ 		if err != nil {
 			return c, fmt.Errorf("while reading a record: %w", err)
 		}
 
-		trip.ID = record[fields["trip_id"]]
+		trip.Id = record[fields["trip_id"]]
 		switch c.Feed.Flags().Headsign {
 		case HeadsignTripHeadsing:
 			trip.Headsign = record[fields["trip_headsign"]]
 		case HeadsignTripLastStop:
-			trip.Headsign = c.stopNames[c.tripHeadsigns[trip.ID]]
+			trip.Headsign = c.stopNames[c.tripHeadsigns[trip.Id]]
 		}
 
-		trip.Departures = departures[trip.ID]
+		trip.Departures = departures[trip.Id]
 		trip.ScheduleID = record[fields["service_id"]]
 		trip.LineName = lineNames[record[fields["route_id"]]]
 		fmt.Sscanf(record[fields["direction_id"]], "%d", &trip.Direction)
 
-		tripChangeOpts[trip.ID] = ChangeOption{
-			LineID:   record[fields["route_id"]],
+		tripChangeOpts[trip.Id] = ChangeOption{
+			LineName:   lineNames[record[fields["route_id"]]],
 			Headsign: trip.Headsign,
 		}
 
@@ -656,7 +656,7 @@ 		b, err := result.Write(bytes)
 		if err != nil {
 			return c, fmt.Errorf("while writing: %w", err)
 		}
-		tripsOffsets[trip.ID] = offset
+		tripsOffsets[trip.Id] = offset
 		offset += uint(b)
 	}
 
@@ -668,7 +668,6 @@
 func convertStops(c feedConverter) (feedConverter, error) { // O(n:stops) ; (tripsThroughStop, lineNames, tripChangeOpts, tripOffsets -- stopsOffsetsByCode:CodeIndex, stopsOffsetsByName:map[name][]offsets >> stops)
 	path := c.TmpFeedPath
 	tripsThroughStop := c.TripsThroughStop
-	lineNames := c.LineNames
 	tripChangeOpts := c.TripChangeOpts
 	tripsOffsets := c.TripsOffsets
 
@@ -699,6 +698,8 @@ 	stopsOffsetsByName := map[string][]uint{}
 	stopsOffsetsByCode := CodeIndex{}
 	stops := map[string]Stop{}
 
+	maxStopTripsLength := 0
+
 	for {
 		stop := Stop{}
 		record, err := r.Read()
@@ -712,8 +713,12 @@
 		stopID := record[fields["stop_id"]]
 
 		stopTrips := tripsThroughStop[stopID]
+		stopTripsLength := len(stopTrips)
+		if maxStopTripsLength < stopTripsLength {
+			maxStopTripsLength = stopTripsLength
+		}
 
-		stop.ID = stopID
+		stop.Id = stopID
 
 		templates := []string{"stop_code", "stop_id", "stop_name"}
 		stop.Code = c.Feed.Flags().StopIdFormat
@@ -738,21 +743,18 @@
 		var lat, lon float64
 		fmt.Sscanf(record[fields["stop_lat"]], "%f", &lat)
 		fmt.Sscanf(record[fields["stop_lon"]], "%f", &lon)
-		stop.Coordinates = Position{lat, lon}
+		stop.Position = Position{lat, lon}
 
 		changeOptionMap := map[string]ChangeOption{}
 		stop.ChangeOptions = []ChangeOption{}
-		stop.Order = []StopOrder{}
+		stop.Order = map[string]StopOrder{}
 		for _, stopTrip := range stopTrips {
-			changeOption := ChangeOption{
-				LineName: lineNames[tripChangeOpts[stopTrip.TripID].LineID],
-				Headsign: tripChangeOpts[stopTrip.TripID].Headsign,
-			}
+			changeOption := tripChangeOpts[stopTrip.TripID]
 			stopOrder := StopOrder{
 				TripOffset: tripsOffsets[stopTrip.TripID],
-				Order:      stopTrip.Order,
+				Sequence:      stopTrip.Sequence,
 			}
-			stop.Order = append(stop.Order, stopOrder)
+			stop.Order[stopTrip.TripID] = stopOrder
 			changeOptionMap[changeOption.LineName+"->"+changeOption.Headsign] = changeOption
 		}
 		for _, option := range changeOptionMap {
@@ -782,13 +784,17 @@ 		if err != nil {
 			return c, fmt.Errorf("while writing: %w", err)
 		}
 		stopsOffsetsByName[stop.Name] = append(stopsOffsetsByName[stop.Name], offset)
-		stopsOffsetsByCode[ID(stop.Code)] = offset
+		stopsOffsetsByCode[stop.Code] = offset
 		offset += uint(b)
 	}
 
+	if maxStopTripsLength > 8192 {
+		log.Printf("maximum length of StopOrder is %d, more than 8192, which may need to be tweaked", maxStopTripsLength)
+	}
+
 	c.StopsCodeIndex = stopsOffsetsByCode
 	c.StopsNameIndex = stopsOffsetsByName
-	c.Stops = stops
+	c.Stops = stops  // todo map[stopID]stopCode
 	return c, nil
 }
 
@@ -858,7 +864,7 @@
 		if previousTripID != tripID {
 			if previousTripID != "" {
 				// last of previous trip
-				previousGraph := graphs[previousTrip.LineName][previousTrip.Direction]
+				previousGraph := graphs[previousTrip.LineName][previousTrip.Direction.Value()]
 				connectionDone := false
 				for _, n := range previousGraph.NextNodes[previous] {
 					if n == -1 {
@@ -868,11 +874,11 @@ 				}
 				if !connectionDone {
 					previousGraph.NextNodes[previous] = append(previousGraph.NextNodes[previous], -1)
 				}
-				graphs[previousTrip.LineName][previousTrip.Direction] = previousGraph
+				graphs[previousTrip.LineName][previousTrip.Direction.Value()] = previousGraph
 			}
 		}
 
-		graph := graphs[trip.LineName][trip.Direction]
+		graph := graphs[trip.LineName][trip.Direction.Value()]
 		current := -1
 		for i, code := range graph.StopCodes {
 			if code == stop.Code {
@@ -913,10 +919,10 @@ 		previous = current
 		previousTripID = tripID
 		previousTrip = trip
 
-		graphs[trip.LineName][trip.Direction] = graph
+		graphs[trip.LineName][trip.Direction.Value()] = graph
 	}
 
-	g := graphs[previousTrip.LineName][previousTrip.Direction]
+	g := graphs[previousTrip.LineName][previousTrip.Direction.Value()]
 	connectionDone := false
 	for _, n := range g.NextNodes[previous] {
 		if n == -1 {
@@ -985,16 +991,16 @@ 			colour = "ffffff"
 		}
 
 		line := Line{
-			ID:         routeID,
+			Id:         routeID,
 			Name:       lineName,
 			Colour:     hex2colour(colour),
-			Type:       kind,
+			Kind:       LineType(kind),
 			GraphThere: c.LineGraphs[lineName][0],
 			GraphBack:  c.LineGraphs[lineName][1],
 		}
 
 		if field, present := fields["agency_id"]; present {
-			line.AgencyID = ID(record[field])
+			line.AgencyID = record[field]
 		}
 
 		bytes, err := bare.Marshal(&line)
@@ -1115,7 +1121,7 @@ 			return fmt.Errorf("while reading a record: %w", err)
 		}
 
 		agency := Agency{
-			ID:       ID(record[fields["agency_id"]]),
+			Id:       record[fields["agency_id"]],
 			Name:     record[fields["agency_name"]],
 			Website:  record[fields["agency_url"]],
 			Timezone: record[fields["agency_timezone"]],




diff --git a/traffic/poznan_ztm.go b/traffic/poznan_ztm.go
index 83a1153840637fe625350d9667c25e0dae729f2f..fab3fade1b39c58903819def516c639cf9408275 100644
--- a/traffic/poznan_ztm.go
+++ b/traffic/poznan_ztm.go
@@ -94,7 +94,7 @@ 			capabilites |= 0b1000_0000
 		}
 
 		vehicle := Vehicle{
-			Id:           ID(record[0]),
+			Id:           record[0],
 			Capabilities: capabilites,
 		}
 




diff --git a/traffic/structs.go b/traffic/structs.go
index dfd36966a1a64e112b83754ed69f9e9ed9e14baf..eec7e43349a5ce8857a165ed0cf8bb076d67f0c6 100644
--- a/traffic/structs.go
+++ b/traffic/structs.go
@@ -3,7 +3,7 @@
 import (
 	"apiote.xyz/p/szczanieckiej/gtfs_rt"
 
-	"image/color"
+	//"image/color"
 	"strings"
 	"time"
 
@@ -17,14 +17,14 @@ 	DEPARTURES_HYBRID DeparturesType = iota
 	DEPARTURES_FULL
 )
 
-type Position struct {
+/*type Position struct {
 	Lat float64
 	Lon float64
-}
+}*/
 
 // todo(BAF10) change IDs to type ID, string to type OLC
 
-type Agency struct {
+/*type Agency struct {
 	ID          ID
 	Name        string
 	Website     string
@@ -33,18 +33,18 @@ 	PhoneNumber string // todo(BAF10) PhoneNumber
 	Language    string // todo(BAF10) language.Tag
 	Email       string
 	FareWebsite string
-}
+}*/
 
-type FeedInfo struct {
+/*type FeedInfo struct {
 	Name     string
 	Website  string
 	Language string // todo(BAF10) language.Tag
-}
+}*/
 
-type Vehicle struct { // todo(BAF10) two types of vehicles — descriptions ID-Capabilities, and an actual vehicle that runs on a trip
-	Id           ID
+type VehicleStatus struct { // todo(BAF10) two types of vehicles — descriptions ID-Capabilities, and an actual vehicle that runs on a trip
+	Id           string
 	Capabilities uint16
-	Coordinates  Position
+	Position     Position
 	Speed        float32
 	Delay        int32 // todo(BAF31)
 	LineName     string
@@ -54,17 +54,25 @@ 	// Occupancy
 	// Congestion
 }
 
-func (v Vehicle) Location() Position {
-	return v.Coordinates
+func (v VehicleStatus) Location() Position {
+	return v.Position
+}
+
+func (k LineType) Value() uint {
+	return uint(k)
+}
+
+func (d Direction) Value() uint {
+	return uint(d)
 }
 
-type Departure struct {
+/*type Departure struct {
 	StopSeq    int
 	Time       uint
 	Pickup     uint // todo(BAF10) enum
 	Dropoff    uint // todo(BAF10) enum
 	StopOffset uint64
-}
+}*/
 
 type DepartureRealtime struct {
 	Departure Departure
@@ -74,7 +82,7 @@ 	Order     StopOrder
 	Update    gtfs_rt.Update
 }
 
-type Trip struct {
+/*type Trip struct {
 	ID         string
 	Headsign   string
 	Direction  uint
@@ -82,13 +90,13 @@ 	LineName   string
 	ScheduleID string
 	ShapeID    ID // todo(BAF11)
 	Departures []Departure
-}
+}*/
 
-type LineGraph struct {
+/*type LineGraph struct {
 	StopCodes []string
 	NextNodes map[int][]int
 	PrevNodes map[int][]int
-}
+}*/
 
 func (g LineGraph) LastNodes() []int {
 	lastNodes := []int{}
@@ -103,7 +111,7 @@ 	}
 	return lastNodes
 }
 
-type Line struct {
+/*type Line struct {
 	ID         string
 	Name       string
 	Colour     color.RGBA
@@ -111,7 +119,7 @@ 	Type       uint // todo(BAF10) enum
 	AgencyID   ID
 	GraphThere LineGraph
 	GraphBack  LineGraph
-}
+}*/
 
 type LineStub struct {
 	Name   string
@@ -129,24 +137,23 @@ type Shape struct { // todo(BAF11)
 	Points []string // OLC
 }
 
-type Schedule struct {
+/*type Schedule struct {
 	ScheduleID string
 	Weekdays   uint8
 	StartDate  string
 	EndDate    string
-}
+}*/
 
-type StopOrder struct {
-	TripID     string `bare:"-"`
+/*type StopOrder struct {
 	TripOffset uint
 	Order      int
-}
+	TripID     string
+}*/
 
-type ChangeOption struct {
-	LineID   string `bare:"-"`
+/*type ChangeOption struct {
 	LineName string
 	Headsign string
-}
+}*/
 
 type Item interface { // todo(BAF12) name: ‘query-able’ eg.
 	IsItem()
@@ -157,7 +164,7 @@ type Locatable interface {
 	Location() Position
 }
 
-type Stop struct {
+/*type Stop struct {
 	ID            string
 	Code          string
 	Name          string
@@ -167,20 +174,20 @@ 	Zone          string
 	Coordinates   Position
 	Order         []StopOrder
 	Timezone      string
-}
+}*/
 
 func (s Stop) DisplayName() string {
 	return s.Name
 }
 
 func (s Stop) Location() Position {
-	return s.Coordinates
+	return s.Position
 }
 
 func (s Stop) Bounds() *rtreego.Rect {
 	rect, err := rtreego.NewRectFromPoints(
-		rtreego.Point{s.Coordinates.Lat, s.Coordinates.Lon},
-		rtreego.Point{s.Coordinates.Lat, s.Coordinates.Lon},
+		rtreego.Point{s.Position.Lat, s.Position.Lon},
+		rtreego.Point{s.Position.Lat, s.Position.Lon},
 	)
 	if err != nil {
 		panic(err.Error())
@@ -210,7 +217,7 @@ 	Cause       int32 // todo(BAF10)
 	Effect      int32 // todo(BAF10)
 }
 
-type ID string
+// type ID string
 type Validity string // 20060102_20060102
 func (v Validity) Start() string {
 	return strings.Split(string(v), "_")[0]
@@ -219,14 +226,14 @@ func (v Validity) End() string {
 	return strings.Split(string(v), "_")[1]
 }
 
-type CodeIndex map[ID]uint
+// type CodeIndex map[ID]uint
 type FeedCodeIndex map[Validity]CodeIndex
 type GlobalCodeIndex map[string]FeedCodeIndex
 
-type NameOffset struct {
+/*type NameOffset struct {
 	Name    string
 	Offsets []uint
-}
+}*/
 
 type NameIndex []NameOffset
 type FeedNameIndex map[Validity]NameIndex
@@ -243,7 +250,7 @@
 type FeedCalendar map[Validity][]Schedule
 type GlobalCalendar map[string]FeedCalendar
 
-type Vehicles map[ID]Vehicle
+type Vehicles map[string]Vehicle
 type FeedVehicles map[Validity]Vehicles
 type GlobalVehicles map[string]FeedVehicles
 




diff --git a/traffic/structs_gen.go b/traffic/structs_gen.go
new file mode 100644
index 0000000000000000000000000000000000000000..2a2cbfda15f7555fde3f08e186f79c976416f1e8
--- /dev/null
+++ b/traffic/structs_gen.go
@@ -0,0 +1,314 @@
+package traffic
+
+// Code generated by go-bare/cmd/gen, DO NOT EDIT.
+
+import (
+	"errors"
+	"git.sr.ht/~sircmpwn/go-bare"
+)
+
+type Trip struct {
+	Id         string      `bare:"id"`
+	Headsign   string      `bare:"headsign"`
+	Direction  Direction   `bare:"direction"`
+	LineName   string      `bare:"lineName"`
+	ScheduleID string      `bare:"scheduleID"`
+	ShapeID    string      `bare:"shapeID"`
+	Departures []Departure `bare:"departures"`
+}
+
+func (t *Trip) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Trip) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Vehicle struct {
+	Id           string `bare:"id"`
+	Capabilities uint16 `bare:"capabilities"`
+}
+
+func (t *Vehicle) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Vehicle) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Departure struct {
+	StopSequence int      `bare:"stopSequence"`
+	Time         uint     `bare:"time"`
+	Pickup       Boarding `bare:"pickup"`
+	Dropoff      Boarding `bare:"dropoff"`
+	StopOffset   uint     `bare:"stopOffset"`
+}
+
+func (t *Departure) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Departure) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Stop struct {
+	Id            string               `bare:"id"`
+	Code          string               `bare:"code"`
+	Name          string               `bare:"name"`
+	NodeName      string               `bare:"nodeName"`
+	ChangeOptions []ChangeOption       `bare:"changeOptions"`
+	Zone          string               `bare:"zone"`
+	Position      Position             `bare:"position"`
+	Order         map[string]StopOrder `bare:"order"`
+	Timezone      string               `bare:"timezone"`
+}
+
+func (t *Stop) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Stop) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type ChangeOption struct {
+	LineName string `bare:"lineName"`
+	Headsign string `bare:"headsign"`
+}
+
+func (t *ChangeOption) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *ChangeOption) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Position struct {
+	Lat float64 `bare:"lat"`
+	Lon float64 `bare:"lon"`
+}
+
+func (t *Position) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Position) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type LineGraph struct {
+	StopCodes []string      `bare:"stopCodes"`
+	NextNodes map[int][]int `bare:"nextNodes"`
+	PrevNodes map[int][]int `bare:"prevNodes"`
+}
+
+func (t *LineGraph) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *LineGraph) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type StopOrder struct {
+	TripOffset uint   `bare:"tripOffset"`
+	Sequence   int    `bare:"sequence"`
+	TripID     string `bare:"tripID"`
+}
+
+func (t *StopOrder) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *StopOrder) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Colour struct {
+	R uint8 `bare:"r"`
+	G uint8 `bare:"g"`
+	B uint8 `bare:"b"`
+	A uint8 `bare:"a"`
+}
+
+func (t *Colour) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Colour) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Line struct {
+	Id         string    `bare:"id"`
+	Name       string    `bare:"name"`
+	Colour     Colour    `bare:"colour"`
+	Kind       LineType  `bare:"kind"`
+	AgencyID   string    `bare:"agencyID"`
+	GraphThere LineGraph `bare:"graphThere"`
+	GraphBack  LineGraph `bare:"graphBack"`
+}
+
+func (t *Line) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Line) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type FeedInfo struct {
+	Name     string `bare:"name"`
+	Website  string `bare:"website"`
+	Language string `bare:"language"`
+}
+
+func (t *FeedInfo) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *FeedInfo) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Agency struct {
+	Id          string `bare:"id"`
+	Name        string `bare:"name"`
+	Website     string `bare:"website"`
+	Timezone    string `bare:"timezone"`
+	PhoneNumber string `bare:"phoneNumber"`
+	Language    string `bare:"language"`
+	Email       string `bare:"email"`
+	FareWebsite string `bare:"fareWebsite"`
+}
+
+func (t *Agency) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Agency) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type NameOffset struct {
+	Name    string `bare:"name"`
+	Offsets []uint `bare:"offsets"`
+}
+
+func (t *NameOffset) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *NameOffset) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type CodeIndex map[string]uint
+
+func (t *CodeIndex) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *CodeIndex) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Schedule struct {
+	Id        string `bare:"id"`
+	Weekdays  uint8  `bare:"weekdays"`
+	StartDate string `bare:"startDate"`
+	EndDate   string `bare:"endDate"`
+}
+
+func (t *Schedule) Decode(data []byte) error {
+	return bare.Unmarshal(data, t)
+}
+
+func (t *Schedule) Encode() ([]byte, error) {
+	return bare.Marshal(t)
+}
+
+type Direction uint
+
+const (
+	THERE Direction = 0
+	BACK  Direction = 1
+)
+
+func (t Direction) String() string {
+	switch t {
+	case THERE:
+		return "THERE"
+	case BACK:
+		return "BACK"
+	}
+	panic(errors.New("Invalid Direction value"))
+}
+
+type Boarding uint
+
+const (
+	REGULAR   Boarding = 0
+	NONE      Boarding = 1
+	BY_PHONE  Boarding = 2
+	BY_DRIVER Boarding = 3
+)
+
+func (t Boarding) String() string {
+	switch t {
+	case REGULAR:
+		return "REGULAR"
+	case NONE:
+		return "NONE"
+	case BY_PHONE:
+		return "BY_PHONE"
+	case BY_DRIVER:
+		return "BY_DRIVER"
+	}
+	panic(errors.New("Invalid Boarding value"))
+}
+
+type LineType uint
+
+const (
+	TRAM       LineType = 0
+	METRO      LineType = 1
+	RAIL       LineType = 2
+	BUS        LineType = 3
+	FERRY      LineType = 4
+	CABLE_TRAM LineType = 5
+	CABLE_CAR  LineType = 6
+	FUNICULAR  LineType = 7
+	TROLLEYBUS LineType = 11
+	MONORAIL   LineType = 12
+)
+
+func (t LineType) String() string {
+	switch t {
+	case TRAM:
+		return "TRAM"
+	case METRO:
+		return "METRO"
+	case RAIL:
+		return "RAIL"
+	case BUS:
+		return "BUS"
+	case FERRY:
+		return "FERRY"
+	case CABLE_TRAM:
+		return "CABLE_TRAM"
+	case CABLE_CAR:
+		return "CABLE_CAR"
+	case FUNICULAR:
+		return "FUNICULAR"
+	case TROLLEYBUS:
+		return "TROLLEYBUS"
+	case MONORAIL:
+		return "MONORAIL"
+	}
+	panic(errors.New("Invalid LineType value"))
+}