diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-15 20:10:35 +0100 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-15 20:10:35 +0100 |
| commit | c0e758b1e793159fc86c85916130f8959360c64e (patch) | |
| tree | 7ecece46af74e324ee9ece7e649191ab28d08d5e /src/Enmarcha.Backend/Services/Processors/TussaRealTimeProcessor.cs | |
| parent | 7a52e14912b952f32e7c9d1a70d2e2ba14f9ad1a (diff) | |
Implement basic real time information for Renfe
Diffstat (limited to 'src/Enmarcha.Backend/Services/Processors/TussaRealTimeProcessor.cs')
| -rw-r--r-- | src/Enmarcha.Backend/Services/Processors/TussaRealTimeProcessor.cs | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/Enmarcha.Backend/Services/Processors/TussaRealTimeProcessor.cs b/src/Enmarcha.Backend/Services/Processors/TussaRealTimeProcessor.cs new file mode 100644 index 0000000..7808a3f --- /dev/null +++ b/src/Enmarcha.Backend/Services/Processors/TussaRealTimeProcessor.cs @@ -0,0 +1,94 @@ +using Enmarcha.Backend.Helpers; +using Enmarcha.Backend.Types.Arrivals; +using Enmarcha.Sources.Tussa; +using Arrival = Enmarcha.Backend.Types.Arrivals.Arrival; + +namespace Enmarcha.Backend.Services.Processors; + +public class TussaRealTimeProcessor : AbstractRealTimeProcessor +{ + private readonly SantiagoRealtimeEstimatesProvider _realtime; + private readonly FeedService _feedService; + private readonly ILogger<TussaRealTimeProcessor> _logger; + + public TussaRealTimeProcessor( + SantiagoRealtimeEstimatesProvider realtime, + FeedService feedService, + ILogger<TussaRealTimeProcessor> logger) + { + _realtime = realtime; + _feedService = feedService; + _logger = logger; + } + + public override async Task ProcessAsync(ArrivalsContext context) + { + if (!context.StopId.StartsWith("tussa:")) return; + + var normalizedCode = _feedService.NormalizeStopCode("tussa", context.StopCode); + if (!int.TryParse(normalizedCode, out var numericStopId)) return; + + try + { + var realtime = await _realtime.GetEstimatesForStop(numericStopId); + System.Diagnostics.Activity.Current?.SetTag("realtime.count", realtime.Count); + + var usedTripIds = new HashSet<string>(); + + foreach (var estimate in realtime) + { + var bestMatch = context.Arrivals + .Where(a => !usedTripIds.Contains(a.TripId)) + .Where(a => a.Route.RouteIdInGtfs.Trim() == estimate.Id.ToString()) + .Select(a => new + { + Arrival = a, + TimeDiff = estimate.MinutesToArrive - a.Estimate.Minutes, // RealTime - Schedule + RouteMatch = true + }) + .Where(x => x.RouteMatch) // Strict route matching + .Where(x => x.TimeDiff is >= -5 and <= 35) // Allow 2m early (RealTime < Schedule) or 25m late (RealTime > Schedule) + .OrderBy(x => Math.Abs(x.TimeDiff)) // Best time fit + .FirstOrDefault(); + + if (bestMatch is null) + { + context.Arrivals.Add(new Arrival + { + TripId = $"tussa:rt:{estimate.Id}:{estimate.MinutesToArrive}", + Route = new RouteInfo + { + GtfsId = $"tussa:{estimate.Id}", + ShortName = estimate.Sinoptico, + Colour = estimate.Colour, + TextColour = ContrastHelper.GetBestTextColour(estimate.Colour) + }, + Headsign = new HeadsignInfo + { + Badge = "T.REAL", + Destination = estimate.Name + }, + Estimate = new ArrivalDetails + { + Minutes = estimate.MinutesToArrive, + Precision = ArrivalPrecision.Confident + } + }); + continue; + } + + var arrival = bestMatch.Arrival; + + arrival.Estimate.Minutes = estimate.MinutesToArrive; + arrival.Estimate.Precision = ArrivalPrecision.Confident; + + usedTripIds.Add(arrival.TripId); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error fetching Santiago real-time data for stop {StopId}", context.StopId); + } + } + +} |
