diff options
Diffstat (limited to 'src/Enmarcha.Backend/Services/Processors')
| -rw-r--r-- | src/Enmarcha.Backend/Services/Processors/FeedConfigProcessor.cs | 18 | ||||
| -rw-r--r-- | src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs | 65 |
2 files changed, 64 insertions, 19 deletions
diff --git a/src/Enmarcha.Backend/Services/Processors/FeedConfigProcessor.cs b/src/Enmarcha.Backend/Services/Processors/FeedConfigProcessor.cs index 2d5f5d9..562b8f1 100644 --- a/src/Enmarcha.Backend/Services/Processors/FeedConfigProcessor.cs +++ b/src/Enmarcha.Backend/Services/Processors/FeedConfigProcessor.cs @@ -47,6 +47,8 @@ public class FeedConfigProcessor : IArrivalsProcessor { arrival.Headsign.Destination = arrival.Headsign.Destination.Replace("*", ""); + var destinationTrimmed = arrival.Headsign.Destination.TrimStart(); + if (arrival.Headsign.Destination == "FORA DE SERVIZO.G.B.") { arrival.Headsign.Destination = "García Barbón, 7 (fora de servizo)"; @@ -55,9 +57,21 @@ public class FeedConfigProcessor : IArrivalsProcessor switch (arrival.Route.ShortName) { - case "A" when arrival.Headsign.Destination.StartsWith("\"1\""): + case "A" when destinationTrimmed.StartsWith("\"1\"", StringComparison.Ordinal) || + (destinationTrimmed.Length >= 1 && destinationTrimmed[0] == '1' && + (destinationTrimmed.Length == 1 || !char.IsDigit(destinationTrimmed[1]))): arrival.Route.ShortName = "A1"; - arrival.Headsign.Destination = arrival.Headsign.Destination.Replace("\"1\"", ""); + // NormalizeStopName() removes quotes for Vitrasa, so handle both "\"1\"" and leading "1". + if (destinationTrimmed.StartsWith("\"1\"", StringComparison.Ordinal)) + { + destinationTrimmed = destinationTrimmed.Substring(3); + } + else + { + destinationTrimmed = destinationTrimmed.Substring(1); + } + + arrival.Headsign.Destination = destinationTrimmed.TrimStart(' ', '-', '.', ':'); break; case "6": arrival.Headsign.Destination = arrival.Headsign.Destination.Replace("\"", ""); diff --git a/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs b/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs index 0ce54c2..d1d1e7d 100644 --- a/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs +++ b/src/Enmarcha.Backend/Services/Processors/VitrasaRealTimeProcessor.cs @@ -66,7 +66,13 @@ public class VitrasaRealTimeProcessor : AbstractRealTimeProcessor .Where(a => a.Route.ShortName.Trim() == estimate.Line.Trim()) .Select(a => { - var arrivalRouteNormalized = _feedService.NormalizeRouteNameForMatching(a.Headsign.Destination); + // Use tripHeadsign from GTFS if available, otherwise fall back to stop-level headsign + string scheduleHeadsign = a.Headsign.Destination; + if (a.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArr && !string.IsNullOrWhiteSpace(otpArr.Trip.TripHeadsign)) + { + scheduleHeadsign = otpArr.Trip.TripHeadsign; + } + var arrivalRouteNormalized = _feedService.NormalizeRouteNameForMatching(scheduleHeadsign); string? arrivalLongNameNormalized = null; string? arrivalLastStopNormalized = null; @@ -122,10 +128,38 @@ public class VitrasaRealTimeProcessor : AbstractRealTimeProcessor var delayMinutes = estimate.Minutes - scheduledMinutes; arrival.Delay = new DelayBadge { Minutes = delayMinutes }; - // Prefer real-time headsign if available and different + string scheduledHeadsign = arrival.Headsign.Destination; + if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArr && !string.IsNullOrWhiteSpace(otpArr.Trip.TripHeadsign)) + { + scheduledHeadsign = otpArr.Trip.TripHeadsign; + } + + _logger.LogDebug("Matched RT estimate: Line {Line}, RT: {RTRoute} ({RTMin}m), Scheduled: {ScheduledRoute} ({ScheduledMin}m), Delay: {Delay}m", + estimate.Line, estimate.Route, estimate.Minutes, scheduledHeadsign, scheduledMinutes, delayMinutes); + + // Prefer real-time headsign UNLESS it's just the last stop name (which is less informative) if (!string.IsNullOrWhiteSpace(estimate.Route)) { - arrival.Headsign.Destination = estimate.Route; + bool isJustLastStop = false; + + if (arrival.RawOtpTrip is ArrivalsAtStopResponse.Arrival otpArrival) + { + var lastStop = otpArrival.Trip.Stoptimes.LastOrDefault(); + if (lastStop != null) + { + var arrivalLastStopNormalized = _feedService.NormalizeRouteNameForMatching(lastStop.Stop.Name); + isJustLastStop = estimateRouteNormalized == arrivalLastStopNormalized; + } + } + + _logger.LogDebug("Headsign: RT='{RT}' vs Scheduled='{Scheduled}', IsJustLastStop={Last}, WillUseRT={Use}", + estimate.Route, scheduledHeadsign, isJustLastStop, !isJustLastStop); + + // Use real-time headsign unless it's just the final stop name + if (!isJustLastStop) + { + arrival.Headsign.Destination = estimate.Route; + } } // Calculate position @@ -150,25 +184,22 @@ public class VitrasaRealTimeProcessor : AbstractRealTimeProcessor currentPosition = result.BusPosition; stopShapeIndex = result.StopIndex; - if (currentPosition != null) - { - _logger.LogInformation("Calculated position from OTP geometry for trip {TripId}: {Lat}, {Lon}", arrival.TripId, currentPosition.Latitude, currentPosition.Longitude); - } - // Populate Shape GeoJSON if (!context.IsReduced && currentPosition != null) { - var features = new List<object>(); - features.Add(new + var features = new List<object> { - type = "Feature", - geometry = new + new { - type = "LineString", - coordinates = decodedPoints.Select(p => new[] { p.Longitude, p.Latitude }).ToList() - }, - properties = new { type = "route" } - }); + type = "Feature", + geometry = new + { + type = "LineString", + coordinates = decodedPoints.Select(p => new[] { p.Longitude, p.Latitude }).ToList() + }, + properties = new { type = "route" } + } + }; // Add stops if available if (otpArrival.Trip.Stoptimes != null) |
