aboutsummaryrefslogtreecommitdiff
path: root/src/Costasdev.Busurbano.Backend/Services/OtpService.cs
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-12-29 00:41:52 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2025-12-29 00:41:52 +0100
commita304c24b32c0327436bbd8c2853e60668e161b42 (patch)
tree08f65c05daca134cf4d2e4f779bd15d98fd66370 /src/Costasdev.Busurbano.Backend/Services/OtpService.cs
parent120a3c6bddd0fb8d9fa05df4763596956554c025 (diff)
Rename a lot of stuff, add Santiago real time
Diffstat (limited to 'src/Costasdev.Busurbano.Backend/Services/OtpService.cs')
-rw-r--r--src/Costasdev.Busurbano.Backend/Services/OtpService.cs357
1 files changed, 0 insertions, 357 deletions
diff --git a/src/Costasdev.Busurbano.Backend/Services/OtpService.cs b/src/Costasdev.Busurbano.Backend/Services/OtpService.cs
deleted file mode 100644
index fb7413c..0000000
--- a/src/Costasdev.Busurbano.Backend/Services/OtpService.cs
+++ /dev/null
@@ -1,357 +0,0 @@
-using System.Globalization;
-using Costasdev.Busurbano.Backend.Configuration;
-using Costasdev.Busurbano.Backend.Helpers;
-using Costasdev.Busurbano.Backend.Types.Otp;
-using Costasdev.Busurbano.Backend.Types.Planner;
-using Costasdev.Busurbano.Backend.Types.Transit;
-using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries;
-using Microsoft.Extensions.Caching.Memory;
-using Microsoft.Extensions.Options;
-
-namespace Costasdev.Busurbano.Backend.Services;
-
-public class OtpService
-{
- private readonly HttpClient _httpClient;
- private readonly AppConfiguration _config;
- private readonly IMemoryCache _cache;
- private readonly ILogger<OtpService> _logger;
- private readonly FareService _fareService;
- private readonly LineFormatterService _lineFormatter;
- private readonly FeedService _feedService;
-
- public OtpService(HttpClient httpClient, IOptions<AppConfiguration> config, IMemoryCache cache, ILogger<OtpService> logger, FareService fareService, LineFormatterService lineFormatter, FeedService feedService)
- {
- _httpClient = httpClient;
- _config = config.Value;
- _cache = cache;
- _logger = logger;
- _fareService = fareService;
- _lineFormatter = lineFormatter;
- _feedService = feedService;
- }
-
- public RouteDto MapRoute(RoutesListResponse.RouteItem route)
- {
- var feedId = route.GtfsId.Split(':')[0];
- return new RouteDto
- {
- Id = route.GtfsId,
- ShortName = _feedService.NormalizeRouteShortName(feedId, route.ShortName ?? string.Empty),
- LongName = route.LongName,
- Color = route.Color,
- TextColor = route.TextColor,
- SortOrder = route.SortOrder,
- AgencyName = route.Agency?.Name,
- TripCount = route.Patterns.Sum(p => p.TripsForDate.Count)
- };
- }
-
- public RouteDetailsDto MapRouteDetails(RouteDetailsResponse.RouteItem route)
- {
- var feedId = route.GtfsId?.Split(':')[0] ?? "unknown";
- return new RouteDetailsDto
- {
- ShortName = _feedService.NormalizeRouteShortName(feedId, route.ShortName ?? string.Empty),
- LongName = route.LongName,
- Color = route.Color,
- TextColor = route.TextColor,
- AgencyName = route.Agency?.Name,
- Patterns = route.Patterns.Select(p => MapPattern(p, feedId)).ToList()
- };
- }
-
- private PatternDto MapPattern(RouteDetailsResponse.PatternItem pattern, string feedId)
- {
- return new PatternDto
- {
- Id = pattern.Id,
- Name = pattern.Name,
- Headsign = pattern.Headsign,
- DirectionId = pattern.DirectionId,
- Code = pattern.Code,
- SemanticHash = pattern.SemanticHash,
- TripCount = pattern.TripsForDate.Count,
- Geometry = DecodePolyline(pattern.PatternGeometry?.Points)?.Coordinates,
- Stops = pattern.Stops.Select((s, i) => new PatternStopDto
- {
- Id = s.GtfsId,
- Code = _feedService.NormalizeStopCode(feedId, s.Code ?? string.Empty),
- Name = _feedService.NormalizeStopName(feedId, s.Name),
- Lat = s.Lat,
- Lon = s.Lon,
- ScheduledDepartures = pattern.TripsForDate
- .Select(t => t.Stoptimes.ElementAtOrDefault(i)?.ScheduledDeparture ?? -1)
- .Where(d => d != -1)
- .OrderBy(d => d)
- .ToList()
- }).ToList()
- };
- }
-
- private Leg MapLeg(OtpLeg otpLeg)
- {
- return new Leg
- {
- Mode = otpLeg.Mode,
- RouteName = otpLeg.Route,
- RouteShortName = otpLeg.RouteShortName,
- 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).UtcDateTime,
- EndTime = DateTimeOffset.FromUnixTimeMilliseconds(otpLeg.EndTime).UtcDateTime,
- DistanceMeters = otpLeg.Distance,
- Geometry = DecodePolyline(otpLeg.LegGeometry?.Points),
- Steps = otpLeg.Steps.Select(MapStep).ToList(),
- IntermediateStops = otpLeg.IntermediateStops.Select(MapPlace).Where(p => p != null).Cast<PlannerPlace>().ToList()
- };
- }
-
- private PlannerPlace? MapPlace(OtpPlace? otpPlace)
- {
- if (otpPlace == null) return null;
- var feedId = otpPlace.StopId?.Split(':')[0] ?? "unknown";
- return new PlannerPlace
- {
- Name = _feedService.NormalizeStopName(feedId, otpPlace.Name),
- Lat = otpPlace.Lat,
- Lon = otpPlace.Lon,
- StopId = otpPlace.StopId, // Use string directly
- StopCode = _feedService.NormalizeStopCode(feedId, otpPlace.StopCode ?? string.Empty)
- };
- }
-
- private Step MapStep(OtpWalkStep otpStep)
- {
- return new Step
- {
- DistanceMeters = otpStep.Distance,
- RelativeDirection = otpStep.RelativeDirection,
- AbsoluteDirection = otpStep.AbsoluteDirection,
- StreetName = otpStep.StreetName,
- Lat = otpStep.Lat,
- Lon = otpStep.Lon
- };
- }
-
- private PlannerGeometry? DecodePolyline(string? encodedPoints)
- {
- if (string.IsNullOrEmpty(encodedPoints)) return null;
-
- var coordinates = Decode(encodedPoints);
- return new PlannerGeometry
- {
- Coordinates = coordinates.Select(c => new List<double> { c.Lon, c.Lat }).ToList()
- };
- }
-
- // Polyline decoding algorithm
- private static List<(double Lat, double Lon)> Decode(string encodedPoints)
- {
- if (string.IsNullOrEmpty(encodedPoints))
- return new List<(double, double)>();
-
- var poly = new List<(double, double)>();
- char[] polylineChars = encodedPoints.ToCharArray();
- int index = 0;
-
- int currentLat = 0;
- int currentLng = 0;
- int next5bits;
- int sum;
- int shifter;
-
- while (index < polylineChars.Length)
- {
- // calculate next latitude
- sum = 0;
- shifter = 0;
- do
- {
- next5bits = (int)polylineChars[index++] - 63;
- sum |= (next5bits & 31) << shifter;
- shifter += 5;
- } while (next5bits >= 32 && index < polylineChars.Length);
-
- if (index >= polylineChars.Length)
- break;
-
- currentLat += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
-
- // calculate next longitude
- sum = 0;
- shifter = 0;
- do
- {
- next5bits = (int)polylineChars[index++] - 63;
- sum |= (next5bits & 31) << shifter;
- shifter += 5;
- } while (next5bits >= 32 && index < polylineChars.Length);
-
- currentLng += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
-
- poly.Add((Convert.ToDouble(currentLat) / 100000.0, Convert.ToDouble(currentLng) / 100000.0));
- }
-
- return poly;
- }
-
- public RoutePlan MapPlanResponse(PlanConnectionResponse response)
- {
- var itineraries = response.PlanConnection.Edges
- .Select(e => MapItinerary(e.Node))
- .ToList();
-
- return new RoutePlan
- {
- Itineraries = itineraries
- };
- }
-
- private Itinerary MapItinerary(PlanConnectionResponse.Node node)
- {
- var legs = node.Legs.Select(MapLeg).ToList();
- var fares = _fareService.CalculateFare(legs);
-
- return new Itinerary
- {
- DurationSeconds = node.DurationSeconds,
- StartTime = DateTime.Parse(node.Start8601, null, DateTimeStyles.RoundtripKind),
- EndTime = DateTime.Parse(node.End8601, null, DateTimeStyles.RoundtripKind),
- WalkDistanceMeters = node.WalkDistance,
- WalkTimeSeconds = node.WalkSeconds,
- TransitTimeSeconds = node.DurationSeconds - node.WalkSeconds - node.WaitingSeconds,
- WaitingTimeSeconds = node.WaitingSeconds,
- Legs = legs,
- CashFare = fares.CashFareEuro,
- CashFareIsTotal = fares.CashFareIsTotal,
- CardFare = fares.CardFareEuro,
- CardFareIsTotal = fares.CardFareIsTotal
- };
- }
-
- private Leg MapLeg(PlanConnectionResponse.Leg leg)
- {
- var feedId = leg.From.Stop?.GtfsId?.Split(':')[0] ?? "unknown";
- var shortName = _feedService.NormalizeRouteShortName(feedId, leg.Route?.ShortName ?? string.Empty);
- var headsign = leg.Headsign;
-
- if (feedId == "vitrasa")
- {
- headsign = headsign?.Replace("*", "");
- if (headsign == "FORA DE SERVIZO.G.B.")
- {
- headsign = "García Barbón, 7 (fora de servizo)";
- }
-
- switch (shortName)
- {
- case "A" when headsign != null && headsign.StartsWith("\"1\""):
- shortName = "A1";
- headsign = headsign.Replace("\"1\"", "");
- break;
- case "6":
- headsign = headsign?.Replace("\"", "");
- break;
- case "FUT":
- if (headsign == "CASTELAO-CAMELIAS-G.BARBÓN.M.GARRIDO")
- {
- shortName = "MAR";
- headsign = "MARCADOR ⚽: CASTELAO-CAMELIAS-G.BARBÓN.M.GARRIDO";
- }
- else if (headsign == "P. ESPAÑA-T.VIGO-S.BADÍA")
- {
- shortName = "RIO";
- headsign = "RÍO ⚽: P. ESPAÑA-T.VIGO-S.BADÍA";
- }
- else if (headsign == "NAVIA-BOUZAS-URZAIZ-G. ESPINO")
- {
- shortName = "GOL";
- headsign = "GOL ⚽: NAVIA-BOUZAS-URZAIZ-G. ESPINO";
- }
- break;
- }
- }
-
- var color = leg.Route?.Color;
- var textColor = leg.Route?.TextColor;
-
- if (string.IsNullOrEmpty(color) || color == "FFFFFF")
- {
- var (fallbackColor, fallbackTextColor) = _feedService.GetFallbackColourForFeed(feedId);
- color = fallbackColor.Replace("#", "");
- textColor = fallbackTextColor.Replace("#", "");
- }
- else if (string.IsNullOrEmpty(textColor) || textColor == "000000")
- {
- textColor = ContrastHelper.GetBestTextColour(color).Replace("#", "");
- }
-
- return new Leg
- {
- Mode = leg.Mode,
- FeedId = feedId,
- RouteId = leg.Route?.GtfsId,
- RouteName = leg.Route?.LongName,
- RouteShortName = shortName,
- RouteLongName = leg.Route?.LongName,
- Headsign = headsign,
- AgencyName = leg.Route?.Agency?.Name,
- RouteColor = color,
- RouteTextColor = textColor,
- From = MapPlace(leg.From),
- To = MapPlace(leg.To),
- StartTime = DateTime.Parse(leg.Start.ScheduledTime8601, null, DateTimeStyles.RoundtripKind),
- EndTime = DateTime.Parse(leg.End.ScheduledTime8601, null, DateTimeStyles.RoundtripKind),
- DistanceMeters = leg.Distance,
- Geometry = DecodePolyline(leg.LegGeometry?.Points),
- Steps = leg.Steps.Select(MapStep).ToList(),
- IntermediateStops = leg.StopCalls.Select(sc => MapPlace(sc.StopLocation)).ToList()
- };
- }
-
- private PlannerPlace MapPlace(PlanConnectionResponse.LegPosition pos)
- {
- var feedId = pos.Stop?.GtfsId?.Split(':')[0] ?? "unknown";
- return new PlannerPlace
- {
- Name = _feedService.NormalizeStopName(feedId, pos.Name),
- Lat = pos.Latitude,
- Lon = pos.Longitude,
- StopId = pos.Stop?.GtfsId,
- StopCode = _feedService.NormalizeStopCode(feedId, pos.Stop?.Code ?? string.Empty),
- ZoneId = pos.Stop?.ZoneId
- };
- }
-
- private PlannerPlace MapPlace(PlanConnectionResponse.StopLocation stop)
- {
- var feedId = stop.GtfsId?.Split(':')[0] ?? "unknown";
- return new PlannerPlace
- {
- Name = _feedService.NormalizeStopName(feedId, stop.Name),
- Lat = stop.Latitude,
- Lon = stop.Longitude,
- StopId = stop.GtfsId,
- StopCode = _feedService.NormalizeStopCode(feedId, stop.Code ?? string.Empty)
- };
- }
-
- private Step MapStep(PlanConnectionResponse.Step step)
- {
- return new Step
- {
- DistanceMeters = step.Distance,
- RelativeDirection = step.RelativeDirection,
- AbsoluteDirection = step.AbsoluteDirection,
- StreetName = step.StreetName,
- Lat = step.Latitude,
- Lon = step.Longitude
- };
- }
-}