diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2025-12-12 16:48:14 +0100 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2025-12-12 16:48:46 +0100 |
| commit | e7eb57bf492617f2b9be88d46c1cc708a2c17af4 (patch) | |
| tree | 490e5ade4dc618760d30a8805dd94cc8dc586e2f /src/Costasdev.Busurbano.Backend/Services | |
| parent | 2f0fd3f348bb836839f4a72e3af072b56954d878 (diff) | |
Improved version of the planner feature
Diffstat (limited to 'src/Costasdev.Busurbano.Backend/Services')
| -rw-r--r-- | src/Costasdev.Busurbano.Backend/Services/OtpService.cs | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/src/Costasdev.Busurbano.Backend/Services/OtpService.cs b/src/Costasdev.Busurbano.Backend/Services/OtpService.cs index 4c22ff5..77eddd3 100644 --- a/src/Costasdev.Busurbano.Backend/Services/OtpService.cs +++ b/src/Costasdev.Busurbano.Backend/Services/OtpService.cs @@ -141,14 +141,37 @@ public class OtpService private RoutePlan MapToRoutePlan(OtpPlan otpPlan) { + // Compute time offset: OTP's "date" field is the server time in millis + var otpServerTime = DateTimeOffset.FromUnixTimeMilliseconds(otpPlan.Date); + var now = DateTimeOffset.Now; + var timeOffsetSeconds = (long)(otpServerTime - now).TotalSeconds; + return new RoutePlan { - Itineraries = otpPlan.Itineraries.Select(MapItinerary).ToList() + Itineraries = otpPlan.Itineraries.Select(MapItinerary).ToList(), + TimeOffsetSeconds = timeOffsetSeconds }; } private Itinerary MapItinerary(OtpItinerary otpItinerary) { + var legs = otpItinerary.Legs.Select(MapLeg).ToList(); + var busLegs = legs.Where(leg => leg.Mode != null && leg.Mode.ToUpper() != "WALK"); + + var cashFareEuro = busLegs.Count() * _config.FareCashPerBus; + + int cardTicketsRequired = 0; + DateTime? lastTicketPurchased = null; + + foreach (var leg in busLegs) + { + if (lastTicketPurchased == null || (leg.StartTime - lastTicketPurchased.Value).TotalMinutes > 45) + { + cardTicketsRequired++; + lastTicketPurchased = leg.StartTime; + } + } + return new Itinerary { DurationSeconds = otpItinerary.Duration, @@ -158,7 +181,9 @@ public class OtpService WalkTimeSeconds = otpItinerary.WalkTime, TransitTimeSeconds = otpItinerary.TransitTime, WaitingTimeSeconds = otpItinerary.WaitingTime, - Legs = otpItinerary.Legs.Select(MapLeg).ToList() + Legs = legs, + CashFareEuro = cashFareEuro, + CardFareEuro = cardTicketsRequired * _config.FareCardPerBus }; } @@ -172,12 +197,16 @@ public class OtpService RouteLongName = otpLeg.RouteLongName, Headsign = otpLeg.Headsign, AgencyName = otpLeg.AgencyName, + RouteColor = otpLeg.RouteColor, + RouteTextColor = otpLeg.RouteTextColor, From = MapPlace(otpLeg.From), To = MapPlace(otpLeg.To), StartTime = DateTimeOffset.FromUnixTimeMilliseconds(otpLeg.StartTime).LocalDateTime, EndTime = DateTimeOffset.FromUnixTimeMilliseconds(otpLeg.EndTime).LocalDateTime, + DistanceMeters = otpLeg.Distance, Geometry = DecodePolyline(otpLeg.LegGeometry?.Points), - Steps = otpLeg.Steps.Select(MapStep).ToList() + Steps = otpLeg.Steps.Select(MapStep).ToList(), + IntermediateStops = otpLeg.IntermediateStops.Select(MapPlace).Where(p => p != null).Cast<PlannerPlace>().ToList() }; } @@ -186,14 +215,37 @@ public class OtpService if (otpPlace == null) return null; return new PlannerPlace { - Name = otpPlace.Name, + Name = CorrectStopName(otpPlace.Name), Lat = otpPlace.Lat, Lon = otpPlace.Lon, StopId = otpPlace.StopId, // Use string directly - StopCode = otpPlace.StopCode + StopCode = CorrectStopCode(otpPlace.StopCode) }; } + private string CorrectStopCode(string? stopId) + { + if (string.IsNullOrEmpty(stopId)) return stopId ?? string.Empty; + + var sb = new StringBuilder(); + foreach (var c in stopId) + { + if (char.IsNumber(c)) + { + sb.Append(c); + } + } + + return int.Parse(sb.ToString()).ToString(); + } + + private string CorrectStopName(string? stopName) + { + if (string.IsNullOrEmpty(stopName)) return stopName ?? string.Empty; + + return stopName!.Replace(" ", ", ").Replace("\"", ""); + } + private Step MapStep(OtpWalkStep otpStep) { return new Step |
