blob: 28b38a9fea16cf4e07ca7a948d4b78ae3e67ab63 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
using Enmarcha.Sources.OpenTripPlannerGql.Queries;
using Enmarcha.Sources.TranviasCoruna;
using Enmarcha.Backend.Types;
using Enmarcha.Backend.Types.Arrivals;
using Enmarcha.Sources.Tussa;
using Arrival = Enmarcha.Backend.Types.Arrivals.Arrival;
namespace Enmarcha.Backend.Services.Processors;
public class SantiagoRealTimeProcessor : AbstractRealTimeProcessor
{
private readonly SantiagoRealtimeEstimatesProvider _realtime;
private readonly FeedService _feedService;
private readonly ILogger<SantiagoRealTimeProcessor> _logger;
public SantiagoRealTimeProcessor(
HttpClient http,
FeedService feedService,
ILogger<SantiagoRealTimeProcessor> logger)
{
_realtime = new SantiagoRealtimeEstimatesProvider(http);
_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);
var usedTripIds = new HashSet<string>();
var newArrivals = new List<Arrival>();
foreach (var estimate in realtime)
{
var bestMatch = context.Arrivals
.Where(a => !usedTripIds.Contains(a.TripId))
.Where(a => a.Route.RouteIdInGtfs.Trim() == estimate.RouteId.Trim())
.Select(a =>
{
return new
{
Arrival = a,
TimeDiff = estimate.Minutes - a.Estimate.Minutes, // RealTime - Schedule
RouteMatch = true
};
})
.Where(x => x.RouteMatch) // Strict route matching
.Where(x => x.TimeDiff >= -7 && x.TimeDiff <= 75) // Allow 7m early (RealTime < Schedule) or 75m late (RealTime > Schedule)
.OrderBy(x => Math.Abs(x.TimeDiff)) // Best time fit
.FirstOrDefault();
if (bestMatch == null)
{
continue;
}
var arrival = bestMatch.Arrival;
var scheduledMinutes = arrival.Estimate.Minutes;
arrival.Estimate.Minutes = estimate.Minutes;
arrival.Estimate.Precision = ArrivalPrecision.Confident;
// Calculate delay badge
var delayMinutes = estimate.Minutes - scheduledMinutes;
if (delayMinutes != 0)
{
arrival.Delay = new DelayBadge { Minutes = delayMinutes };
}
usedTripIds.Add(arrival.TripId);
}
context.Arrivals.AddRange(newArrivals);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching Vitrasa real-time data for stop {StopId}", context.StopId);
}
}
}
|