summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2026-03-24 21:06:07 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2026-03-24 21:06:07 +0100
commitfcd3c6f37ea7d707b05f00af3006dc8a4bd1ec2e (patch)
tree07c199faa1c484d06ae44915be454ce3153f506d
parent6671f34a2503cd29aa3bf15216f3a0e2c7af73cf (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.cs212
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);