szczanieckiej.git

commit 9cc7ad838e9c3db0345b78244a726cd3934589c6

Author: Adam Evyčędo <git@apiote.xyz>

adapt API to new realtime

 api/api.go | 105 +++++++++++++----------------------------
 traffic/access.go | 6 +-
 traffic/realtime.go | 21 ++++++--
 traffic/realtime_gtfs.go | 2 
 traffic/structs.go | 5 +


diff --git a/api/api.go b/api/api.go
index e798463f1504a2cdcf9c4b3dd6975701e8231039..f3b950de9b401a75d64da8dc73582b8ddb74b993 100644
--- a/api/api.go
+++ b/api/api.go
@@ -153,9 +153,9 @@ 		return VehicleV1{}, fmt.Errorf("while getting line %s: %w", vehicle.LineName, err)
 	}
 	log.Printf("convertTrafficVehicle:: trafficVehicle: %+v, line: %+v\n", vehicle, line)
 	return VehicleV1{
-		Id:           string(vehicle.Id),
-		Position:     PositionV1{vehicle.Position.Lat, vehicle.Position.Lon},
-		Capabilities: vehicle.Capabilities,
+		Id:           string(vehicle.VehicleID),
+		Position:     PositionV1{vehicle.Latitude, vehicle.Longitude},
+		Capabilities: t.Vehicles[string(context.Version)][traffic.Validity(context.FeedID)][vehicle.VehicleID].Capabilities,
 		Speed:        vehicle.Speed,
 		Line:         LineStubV1{Name: line.Name, Kind: makeLineTypeV1(line), Colour: fromColor(line.Colour)},
 		Headsign:     vehicle.Headsign,
@@ -173,9 +173,9 @@ 		return VehicleV2{}, fmt.Errorf("while getting line %s: %w", vehicle.LineName, err)
 	}
 	log.Printf("convertTrafficVehicle:: trafficVehicle: %+v, line: %+v\n", vehicle, line)
 	return VehicleV2{
-		Id:           string(vehicle.Id),
-		Position:     PositionV1{vehicle.Position.Lat, vehicle.Position.Lon},
-		Capabilities: vehicle.Capabilities,
+		Id:           string(vehicle.VehicleID),
+		Position:     PositionV1{vehicle.Latitude, vehicle.Longitude},
+		Capabilities: t.Vehicles[string(context.Version)][traffic.Validity(context.FeedID)][vehicle.VehicleID].Capabilities,
 		Speed:        vehicle.Speed,
 		Line:         LineStubV2{Name: line.Name, Kind: makeLineTypeV2(line), Colour: fromColor(line.Colour)},
 		Headsign:     vehicle.Headsign,
@@ -193,9 +193,9 @@ 		return VehicleV3{}, fmt.Errorf("while getting line %s: %w", vehicle.LineName, err)
 	}
 	log.Printf("convertTrafficVehicle:: trafficVehicle: %+v, line: %+v\n", vehicle, line)
 	return VehicleV3{
-		Id:           string(vehicle.Id),
-		Position:     PositionV1{vehicle.Position.Lat, vehicle.Position.Lon},
-		Capabilities: vehicle.Capabilities,
+		Id:           string(vehicle.VehicleID),
+		Position:     PositionV1{vehicle.Latitude, vehicle.Longitude},
+		Capabilities: t.Vehicles[string(context.Version)][traffic.Validity(context.FeedID)][vehicle.VehicleID].Capabilities,
 		Speed:        vehicle.Speed,
 		Line:         LineStubV3{Name: line.Name, Kind: makeLineTypeV3(line), Colour: fromColor(line.Colour)},
 		Headsign:     vehicle.Headsign,
@@ -499,7 +499,7 @@ 			success.Locatables = append(success.Locatables, LocatableV1(s))
 		} 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)
+				return success, fmt.Errorf("while converting Traffic Vehicle %s: %w", vehicle.VehicleID, err)
 			}
 			success.Locatables = append(success.Locatables, LocatableV1(v))
 		}
@@ -523,7 +523,7 @@ 			success.Locatables = append(success.Locatables, LocatableV2(s))
 		} 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)
+				return success, fmt.Errorf("while converting Traffic Vehicle %s: %w", vehicle.VehicleID, err)
 			}
 			success.Locatables = append(success.Locatables, LocatableV2(v))
 		}
@@ -547,7 +547,7 @@ 			success.Locatables = append(success.Locatables, LocatableV3(s))
 		} else if vehicle, ok := locatable.(traffic.VehicleStatus); ok {
 			v, err := convertTrafficVehicleV3(vehicle, context, t)
 			if err != nil {
-				return success, fmt.Errorf("while converting Traffic Vehicle %s: %w", vehicle.Id, err)
+				return success, fmt.Errorf("while converting Traffic Vehicle %s: %w", vehicle.VehicleID, err)
 			}
 			success.Locatables = append(success.Locatables, LocatableV3(v))
 		}
@@ -637,45 +637,6 @@ 		return OCCUPANCY_UNKNOWN
 	}
 }
 
-func convertVehicle(update traffic.Update, vehicles map[string]traffic.Vehicle, line traffic.Line, headsign string) VehicleV1 {
-	return VehicleV1{
-		Id:           update.VehicleID,
-		Position:     PositionV1{Lat: update.Latitude, Lon: update.Longitude},
-		Capabilities: vehicles[update.VehicleID].Capabilities,
-		Speed:        update.Speed,
-		Line:         LineStubV1{Name: line.Name, Kind: makeLineTypeV1(line), Colour: fromColor(line.Colour)},
-		Headsign:     headsign,
-		// todo CongestionLevel
-		// todo OccupancyStatus
-	}
-}
-
-func convertVehicleV2(update traffic.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[update.VehicleID].Capabilities,
-		Speed:        update.Speed,
-		Line:         LineStubV2{Name: line.Name, Kind: makeLineTypeV2(line), Colour: fromColor(line.Colour)},
-		Headsign:     headsign,
-		// todo CongestionLevel
-		// todo OccupancyStatus
-	}
-}
-
-func convertVehicleV3(update traffic.Update, vehicles map[string]traffic.Vehicle, line traffic.Line, headsign string) VehicleV3 {
-	return VehicleV3{
-		Id:           update.VehicleID,
-		Position:     PositionV1{Lat: float64(update.Latitude), Lon: float64(update.Longitude)},
-		Capabilities: vehicles[update.VehicleID].Capabilities,
-		Speed:        update.Speed,
-		Line:         LineStubV3{Name: line.Name, Kind: makeLineTypeV3(line), Colour: fromColor(line.Colour)},
-		Headsign:     headsign,
-		// todo CongestionLevel
-		// todo OccupancyStatus
-	}
-}
-
 func CreateSuccessDeparturesV1(stop traffic.Stop, departures []traffic.DepartureRealtime, date time.Time, vehicles map[string]traffic.Vehicle, alerts []traffic.Alert, ctx traffic.Context, t *traffic.Traffic, accept uint, preferredLanguages []language.Tag) (DeparturesResponse, error) {
 	d := []DepartureV1{}
 	var success DeparturesResponse
@@ -692,9 +653,9 @@ 		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Sequence)
 		if err != nil {
 			return success, err
 		}
-		line, err := traffic.GetLine(trafficDeparture.LineName, ctx, t)
+		vehicle, err := convertTrafficVehicle(trafficDeparture.Update.VehicleStatus, ctx, t)
 		if err != nil {
-			return success, fmt.Errorf("while getting line %s: %w", trafficDeparture.LineName, err)
+			return success, fmt.Errorf("while converting vehicle status: %w", err)
 		}
 		departureTime := traffic.GetTimeWithDelay(trafficDeparture)
 		departure := DepartureV1{
@@ -707,15 +668,15 @@ 				Second:    uint8(departureTime.Second()),
 				Zone:      zoneAbbr,
 			},
 			Status:     STATUS_IN_TRANSIT,
-			IsRealtime: trafficDeparture.Update.Delay != nil,
-			Vehicle:    convertVehicle(trafficDeparture.Update, vehicles, line, trafficDeparture.Headsign),
+			IsRealtime: trafficDeparture.Update.TimetableRelationship != traffic.NO_TRIP_DATA && trafficDeparture.Update.TimetableRelationship != traffic.NOT_REALTIME,
+			Vehicle:    vehicle,
 			Boarding:   makeBoardingV1(trafficDeparture.Departure.Pickup, trafficDeparture.Departure.Dropoff),
 		}
 		timeToArrival := departureTime.Sub(datetime).Minutes()
 		if departure.IsRealtime {
-			departure.Status = convertVehicleStatusV1(trafficDeparture.Update.Status, timeToArrival)
-			departure.Vehicle.CongestionLevel = convertCongestionLevelV1(trafficDeparture.Update.CongestionLevel)
-			departure.Vehicle.OccupancyStatus = convertOccupancyStatusV1(trafficDeparture.Update.OccupancyStatus)
+			departure.Status = convertVehicleStatusV1(trafficDeparture.Update.VehicleStatus.Status, timeToArrival)
+			departure.Vehicle.CongestionLevel = convertCongestionLevelV1(trafficDeparture.Update.VehicleStatus.CongestionLevel)
+			departure.Vehicle.OccupancyStatus = convertOccupancyStatusV1(trafficDeparture.Update.VehicleStatus.OccupancyStatus)
 		}
 		d = append(d, departure)
 	}
@@ -743,9 +704,9 @@ 		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Sequence)
 		if err != nil {
 			return success, err
 		}
-		line, err := traffic.GetLine(trafficDeparture.LineName, ctx, t)
+		vehicle, err := convertTrafficVehicleV2(trafficDeparture.Update.VehicleStatus, ctx, t)
 		if err != nil {
-			return success, fmt.Errorf("while getting line %s: %w", trafficDeparture.LineName, err)
+			return success, fmt.Errorf("while converting vehicle status: %w", err)
 		}
 		departureTime := traffic.GetTimeWithDelay(trafficDeparture)
 		departure := DepartureV2{
@@ -758,15 +719,15 @@ 				Second:    uint8(departureTime.Second()),
 				Zone:      zoneAbbr,
 			},
 			Status:     STATUS_IN_TRANSIT,
-			IsRealtime: trafficDeparture.Update.Delay != nil,
-			Vehicle:    convertVehicleV2(trafficDeparture.Update, vehicles, line, trafficDeparture.Headsign),
+			IsRealtime: trafficDeparture.Update.TimetableRelationship != traffic.NO_TRIP_DATA && trafficDeparture.Update.TimetableRelationship != traffic.NOT_REALTIME,
+			Vehicle:    vehicle,
 			Boarding:   makeBoardingV1(trafficDeparture.Departure.Pickup, trafficDeparture.Departure.Dropoff),
 		}
 		timeToArrival := departureTime.Sub(datetime).Minutes()
 		if departure.IsRealtime {
-			departure.Status = convertVehicleStatusV1(trafficDeparture.Update.Status, timeToArrival)
-			departure.Vehicle.CongestionLevel = convertCongestionLevelV1(trafficDeparture.Update.CongestionLevel)
-			departure.Vehicle.OccupancyStatus = convertOccupancyStatusV1(trafficDeparture.Update.OccupancyStatus)
+			departure.Status = convertVehicleStatusV1(trafficDeparture.Update.VehicleStatus.Status, timeToArrival)
+			departure.Vehicle.CongestionLevel = convertCongestionLevelV1(trafficDeparture.Update.VehicleStatus.CongestionLevel)
+			departure.Vehicle.OccupancyStatus = convertOccupancyStatusV1(trafficDeparture.Update.VehicleStatus.OccupancyStatus)
 		}
 		d = append(d, departure)
 	}
@@ -794,9 +755,9 @@ 		stopOrder, err := marshalStopOrder(trafficDeparture.Order.TripOffset, trafficDeparture.Order.Sequence)
 		if err != nil {
 			return success, err
 		}
-		line, err := traffic.GetLine(trafficDeparture.LineName, ctx, t)
+		vehicle, err := convertTrafficVehicleV3(trafficDeparture.Update.VehicleStatus, ctx, t)
 		if err != nil {
-			return success, fmt.Errorf("while getting line %s: %w", trafficDeparture.LineName, err)
+			return success, fmt.Errorf("while converting vehicle status: %w", err)
 		}
 		departureTime := traffic.GetTimeWithDelay(trafficDeparture)
 		departure := DepartureV3{
@@ -809,15 +770,15 @@ 				Second:    uint8(departureTime.Second()),
 				Zone:      zoneAbbr,
 			},
 			Status:     STATUS_IN_TRANSIT,
-			IsRealtime: trafficDeparture.Update.Delay != nil,
-			Vehicle:    convertVehicleV3(trafficDeparture.Update, vehicles, line, trafficDeparture.Headsign),
+			IsRealtime: trafficDeparture.Update.TimetableRelationship != traffic.NO_TRIP_DATA && trafficDeparture.Update.TimetableRelationship != traffic.NOT_REALTIME,
+			Vehicle:    vehicle,
 			Boarding:   makeBoardingV1(trafficDeparture.Departure.Pickup, trafficDeparture.Departure.Dropoff),
 		}
 		timeToArrival := departureTime.Sub(datetime).Minutes()
 		if departure.IsRealtime {
-			departure.Status = convertVehicleStatusV1(trafficDeparture.Update.Status, timeToArrival)
-			departure.Vehicle.CongestionLevel = convertCongestionLevelV1(trafficDeparture.Update.CongestionLevel)
-			departure.Vehicle.OccupancyStatus = convertOccupancyStatusV1(trafficDeparture.Update.OccupancyStatus)
+			departure.Status = convertVehicleStatusV1(trafficDeparture.Update.VehicleStatus.Status, timeToArrival)
+			departure.Vehicle.CongestionLevel = convertCongestionLevelV1(trafficDeparture.Update.VehicleStatus.CongestionLevel)
+			departure.Vehicle.OccupancyStatus = convertOccupancyStatusV1(trafficDeparture.Update.VehicleStatus.OccupancyStatus)
 		}
 		d = append(d, departure)
 	}




diff --git a/traffic/access.go b/traffic/access.go
index 6c4202848618de5e909e77fa5f62d0835f291bdd..271e5218cfad43dc678c7183034e1b1b5d92c6d1 100644
--- a/traffic/access.go
+++ b/traffic/access.go
@@ -835,8 +835,8 @@ 		return r.(_Result).FeedInfo, nil
 	}
 }
 
-func GetTripsByOffset(offsets []uint, context Context, t *Traffic, filter func(Trip) bool) ([]Trip, error) {
-	trips := []Trip{}
+func GetTripsByOffset(offsets []uint, context Context, filter func(Trip) bool) (map[uint]Trip, error) {
+	trips := map[uint]Trip{}
 	file, err := os.Open(filepath.Join(context.DataHome, context.FeedID, string(context.Version), "trips.bare"))
 	if err != nil {
 		return trips, fmt.Errorf("while opening file: %w", err)
@@ -859,7 +859,7 @@ 		if err != nil {
 			return trips, fmt.Errorf("while unmarshalling at %d: %w", offset, err)
 		}
 		if filter(trip) {
-			trips = append(trips, trip)
+			trips[offset] = trip
 		}
 	}
 	return trips, nil




diff --git a/traffic/realtime.go b/traffic/realtime.go
index ecfbbe902b7a44a3abec303fdbd77335c325226b..2a6f7f14b912703a052897956670754098d45393 100644
--- a/traffic/realtime.go
+++ b/traffic/realtime.go
@@ -19,7 +19,7 @@ 	TRIP_CANCELED
 	TRIP_DELETED
 	TRIP_ADDED
 	STOP_SKIPPED
-	NO_DATA
+	NO_TRIP_DATA
 )
 
 type Update struct {
@@ -38,6 +38,8 @@ 	Latitude        float64
 	Longitude       float64
 	Speed           float32 // m/s
 	Bearing         float64 // radians clockwise from north // TODO maybe (-π, π)
+	LineName        string
+	Headsign        string
 }
 
 type CongestionLevel uint
@@ -92,8 +94,6 @@
 var updates map[string]Update
 var alerts Alerts
 var vehicleStatuses map[string]VehicleStatus
-
-// TODO vehicles cache
 
 func getTripID(tripsFile *os.File, offset int64) (string, error) {
 	_, err := tripsFile.Seek(offset, 0)
@@ -126,21 +126,30 @@ 	}
 	midnight := time.Date(datetime.Year(), datetime.Month(),
 		datetime.Day(), 0, 0, 0, 0, timezone)
 	if departuresType == DEPARTURES_HYBRID {
+		offsets := make([]uint, len(departures))
+		for i, departure := range departures {
+			offsets[i] = departure.Order.TripOffset
+		}
+		trips, err := GetTripsByOffset(offsets, ctx, func(Trip) bool { return true })
+		if err != nil {
+			log.Printf("while getting trips: %v\n", err)
+		}
 		for i, departure := range departures {
 			if departure.Time.After(midnight) {
-				tripID, err := getTripID(tripsFile, int64(departure.Order.TripOffset))
 				if err != nil {
 					log.Printf("while getting trip id for %s -> %s (%v): %v\n", departure.LineName, departure.Headsign, departure.Time, err)
 					continue
 				}
-				update, err := enrichMethod(tripID, departure.Order.Sequence, ctx)
+				update, err := enrichMethod(trips[departure.Order.TripOffset].Id, departure.Order.Sequence, ctx)
 				if err != nil {
-					if isTimeout(err) {
+					if isTimeout(err) { // TODO or any other connection problem
 						break
 					} else {
 						log.Printf("while enriching departure %s -> %s (%v): %v\n", departure.LineName, departure.Headsign, departure.Time, err)
 					}
 				} else {
+					update.VehicleStatus.LineName = trips[departure.Order.TripOffset].LineName
+					update.VehicleStatus.Headsign = trips[departure.Order.TripOffset].Headsign
 					enrichedDepartures[i] = departure.WithUpdate(update)
 				}
 			}




diff --git a/traffic/realtime_gtfs.go b/traffic/realtime_gtfs.go
index 94a8350131bb232277698e15ab97d7af66a8e230..9aee8bd384c480f9c81ce318338fd8d1c77320a2 100644
--- a/traffic/realtime_gtfs.go
+++ b/traffic/realtime_gtfs.go
@@ -29,7 +29,7 @@
 func makeTimetableRelationshipFromStopTrip(r pb.TripUpdate_StopTimeUpdate_ScheduleRelationship) TimetableRelationship {
 	switch r {
 	case pb.TripUpdate_StopTimeUpdate_NO_DATA:
-		return NO_DATA
+		return NO_TRIP_DATA
 	case pb.TripUpdate_StopTimeUpdate_SKIPPED:
 		return STOP_SKIPPED
 	default:




diff --git a/traffic/structs.go b/traffic/structs.go
index 6cdd0a9e773a966bbad232858337ad216f86f471..6f33ff3997a3c1d24735c74695d31a7ad9db4b73 100644
--- a/traffic/structs.go
+++ b/traffic/structs.go
@@ -53,7 +53,10 @@ // 	// Congestion
 // }
 
 func (v VehicleStatus) Location() Position {
-	return v.Position
+	return Position{
+		Lat: v.Latitude,
+		Lon: v.Longitude,
+	}
 }
 
 func (k LineType) Value() uint {