diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-24 21:06:07 +0100 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-24 21:06:07 +0100 |
| commit | fcd3c6f37ea7d707b05f00af3006dc8a4bd1ec2e (patch) | |
| tree | 07c199faa1c484d06ae44915be454ce3153f506d | |
| parent | 6671f34a2503cd29aa3bf15216f3a0e2c7af73cf (diff) | |
Refactor this huge blob of code to make it A BIT more readable, actually fix the precision indicator.
| -rw-r--r-- | src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs | 212 |
1 files changed, 109 insertions, 103 deletions
diff --git a/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs b/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs index 43a215b..cc716ee 100644 --- a/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs +++ b/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs @@ -116,69 +116,100 @@ public class VitrasaRealTimeProcessor : AbstractRealTimeProcessor .OrderBy(x => Math.Abs(x.TimeDiff)) // Best time fit .FirstOrDefault(); - if (bestMatch != null) + if (bestMatch is null) { - var arrival = bestMatch.Arrival; - - var scheduledMinutes = arrival.Estimate.Minutes; - arrival.Estimate.Minutes = estimate.Minutes; - - // Calculate delay badge - var delayMinutes = estimate.Minutes - scheduledMinutes; - arrival.Delay = new DelayBadge { Minutes = delayMinutes }; + _logger.LogInformation("Adding unmatched Vitrasa real-time arrival for line {Line} in {Minutes}m", + estimate.Line, estimate.Minutes); - string scheduledHeadsign = arrival.Headsign.Destination; - if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArr && !string.IsNullOrWhiteSpace(otpArr.Trip.TripHeadsign)) - { - scheduledHeadsign = otpArr.Trip.TripHeadsign; - } + // Try to find a "template" arrival with the same line to copy colors from + var template = context.Arrivals + .FirstOrDefault(a => a.Route.ShortName.Trim() == estimate.Line.Trim()); - // Prefer real-time headsign UNLESS it's just the last stop name (which is less informative) - if (!string.IsNullOrWhiteSpace(estimate.Route)) + newArrivals.Add(new Arrival { - bool isJustLastStop = false; - - if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArrival) + TripId = $"vitrasa:rt:{estimate.Line}:{estimate.Route}:{estimate.Minutes}", + Route = new RouteInfo { - var lastStop = otpArrival.Trip.Stoptimes.LastOrDefault(); - if (lastStop != null) - { - var arrivalLastStopNormalized = _feedService.NormalizeRouteNameForMatching(lastStop.Stop.Name); - isJustLastStop = estimateRouteNormalized == arrivalLastStopNormalized; - } + GtfsId = $"vitrasa:{estimate.Line}", + ShortName = estimate.Line, + Colour = template?.Route.Colour ?? "FFFFFF", + TextColour = template?.Route.TextColour ?? "000000", + }, + Headsign = new HeadsignInfo + { + Destination = estimate.Route + }, + Estimate = new ArrivalDetails + { + Minutes = estimate.Minutes, + Precision = ArrivalPrecision.Confident } + }); + + continue; + } + + var arrival = bestMatch.Arrival; + + var scheduledMinutes = arrival.Estimate.Minutes; + arrival.Estimate.Minutes = estimate.Minutes; + + // Calculate delay badge + var delayMinutes = estimate.Minutes - scheduledMinutes; + arrival.Delay = new DelayBadge { Minutes = delayMinutes }; - // Use real-time headsign unless it's just the final stop name - if (!isJustLastStop) + string scheduledHeadsign = arrival.Headsign.Destination; + if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArr && !string.IsNullOrWhiteSpace(otpArr.Trip.TripHeadsign)) + { + scheduledHeadsign = otpArr.Trip.TripHeadsign; + } + + // Prefer real-time headsign UNLESS it's just the last stop name (which is less informative) + if (!string.IsNullOrWhiteSpace(estimate.Route)) + { + bool isJustLastStop = false; + + if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArrival) + { + var lastStop = otpArrival.Trip.Stoptimes.LastOrDefault(); + if (lastStop != null) { - arrival.Headsign.Destination = estimate.Route; + var arrivalLastStopNormalized = _feedService.NormalizeRouteNameForMatching(lastStop.Stop.Name); + isJustLastStop = estimateRouteNormalized == arrivalLastStopNormalized; } } - // Calculate position - if (stopLocation != null) + // Use real-time headsign unless it's just the final stop name + if (!isJustLastStop) { - Position? currentPosition = null; + arrival.Headsign.Destination = estimate.Route; + } + } - if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArrival && - otpArrival.Trip.Geometry?.Points != null) - { - var decodedPoints = Decode(otpArrival.Trip.Geometry.Points) - .Select(p => new Position { Latitude = p.Lat, Longitude = p.Lon }) - .ToList(); + // Calculate position + if (stopLocation != null) + { + Position? currentPosition = null; + + if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArrival && + otpArrival.Trip.Geometry?.Points != null) + { + var decodedPoints = Decode(otpArrival.Trip.Geometry.Points) + .Select(p => new Position { Latitude = p.Lat, Longitude = p.Lon }) + .ToList(); - var shape = _shapeService.CreateShapeFromWgs84(decodedPoints); + var shape = _shapeService.CreateShapeFromWgs84(decodedPoints); - // Ensure meters is positive - var meters = Math.Max(0, estimate.Meters); - var result = _shapeService.GetBusPosition(shape, stopLocation, meters); + // Ensure meters is positive + var meters = Math.Max(0, estimate.Meters); + var result = _shapeService.GetBusPosition(shape, stopLocation, meters); - currentPosition = result.BusPosition; + currentPosition = result.BusPosition; - // Populate Shape GeoJSON - if (!context.IsReduced && currentPosition != null) - { - var features = new List<object> + // Populate Shape GeoJSON + if (!context.IsReduced && currentPosition != null) + { + var features = new List<object> { new { @@ -192,74 +223,49 @@ public class VitrasaRealTimeProcessor : AbstractRealTimeProcessor } }; - // Add stops if available - if (otpArrival.Trip.Stoptimes != null) + // Add stops if available + if (otpArrival.Trip.Stoptimes != null) + { + foreach (var stoptime in otpArrival.Trip.Stoptimes) { - foreach (var stoptime in otpArrival.Trip.Stoptimes) + features.Add(new { - features.Add(new + type = "Feature", + geometry = new { - type = "Feature", - geometry = new - { - type = "Point", - coordinates = new[] { stoptime.Stop.Lon, stoptime.Stop.Lat } - }, - properties = new - { - type = "stop", - name = stoptime.Stop.Name - } - }); - } + type = "Point", + coordinates = new[] { stoptime.Stop.Lon, stoptime.Stop.Lat } + }, + properties = new + { + type = "stop", + name = stoptime.Stop.Name + } + }); } - - arrival.Shape = new - { - type = "FeatureCollection", - features = features - }; } - } - if (currentPosition != null) - { - arrival.CurrentPosition = currentPosition; + arrival.Shape = new + { + type = "FeatureCollection", + features = features + }; } } - usedTripIds.Add(arrival.TripId); - } - else - { - _logger.LogInformation("Adding unmatched Vitrasa real-time arrival for line {Line} in {Minutes}m", - estimate.Line, estimate.Minutes); - - // Try to find a "template" arrival with the same line to copy colors from - var template = context.Arrivals - .FirstOrDefault(a => a.Route.ShortName.Trim() == estimate.Line.Trim()); - - newArrivals.Add(new Arrival + if (currentPosition != null) { - TripId = $"vitrasa:rt:{estimate.Line}:{estimate.Route}:{estimate.Minutes}", - Route = new RouteInfo - { - GtfsId = $"vitrasa:{estimate.Line}", - ShortName = estimate.Line, - Colour = template?.Route.Colour ?? "FFFFFF", - TextColour = template?.Route.TextColour ?? "000000", - }, - Headsign = new HeadsignInfo - { - Destination = estimate.Route - }, - Estimate = new ArrivalDetails - { - Minutes = estimate.Minutes, - Precision = ArrivalPrecision.Confident - } - }); + arrival.CurrentPosition = currentPosition; + arrival.Estimate.Precision = ArrivalPrecision.Confident; + } + else + { + // If we can't calculate a position, degrade precision to "Unsure" to indicate less confidence + arrival.Estimate.Precision = ArrivalPrecision.Unsure; + } } + + usedTripIds.Add(arrival.TripId); } context.Arrivals.AddRange(newArrivals); |
