aboutsummaryrefslogtreecommitdiff
path: root/src/Costasdev.Busurbano.Backend/Controllers
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-12-27 16:39:09 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2025-12-27 16:39:28 +0100
commitf81ff82f2a07f87f6eb4f43de49ede64215519e5 (patch)
tree67b4f9ef1c94184e2e1a9878c6feed8dc30ebcb3 /src/Costasdev.Busurbano.Backend/Controllers
parentef2df90ffb195edcddd701511dc5953c7baa63af (diff)
Refactor route planner to use new GraphQL backend
Diffstat (limited to 'src/Costasdev.Busurbano.Backend/Controllers')
-rw-r--r--src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs17
-rw-r--r--src/Costasdev.Busurbano.Backend/Controllers/RoutePlannerController.cs53
2 files changed, 61 insertions, 9 deletions
diff --git a/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs b/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs
index 957668a..6096b53 100644
--- a/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs
+++ b/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs
@@ -75,11 +75,18 @@ public partial class ArrivalsController : ControllerBase
List<Arrival> arrivals = [];
foreach (var item in stop.Arrivals)
{
+ // Discard trip without pickup at stop
if (item.PickupTypeParsed.Equals(ArrivalsAtStopResponse.PickupType.None))
{
continue;
}
+ // Discard on last stop
+ if (item.Trip.ArrivalStoptime.Stop.GtfsId == id)
+ {
+ continue;
+ }
+
if (item.Trip.Geometry?.Points != null)
{
_logger.LogDebug("Trip {TripId} has geometry", item.Trip.GtfsId);
@@ -133,6 +140,8 @@ public partial class ArrivalsController : ControllerBase
// Time after an arrival's time to still include it in the response. This is useful without real-time data, for delayed buses.
var timeThreshold = GetThresholdForFeed(id);
+ var (fallbackColor, fallbackTextColor) = _feedService.GetFallbackColourForFeed(feedId);
+
return Ok(new StopArrivalsResponse
{
StopCode = _feedService.NormalizeStopCode(feedId, stop.Code),
@@ -151,8 +160,10 @@ public partial class ArrivalsController : ControllerBase
{
GtfsId = r.GtfsId,
ShortName = _feedService.NormalizeRouteShortName(feedId, r.ShortName ?? ""),
- Colour = r.Color ?? "FFFFFF",
- TextColour = r.TextColor ?? "000000"
+ Colour = r.Color ?? fallbackColor,
+ TextColour = r.TextColor is null or "000000" ?
+ ContrastHelper.GetBestTextColour(r.Color ?? fallbackColor) :
+ r.TextColor
})],
Arrivals = [.. arrivals.Where(a => a.Estimate.Minutes >= timeThreshold)]
});
@@ -163,7 +174,7 @@ public partial class ArrivalsController : ControllerBase
{
string feedId = id.Split(':', 2)[0];
- if (feedId == "vitrasa" || feedId == "coruna")
+ if (feedId is "vitrasa" or "coruna")
{
return 0;
}
diff --git a/src/Costasdev.Busurbano.Backend/Controllers/RoutePlannerController.cs b/src/Costasdev.Busurbano.Backend/Controllers/RoutePlannerController.cs
index efddf82..823cfa5 100644
--- a/src/Costasdev.Busurbano.Backend/Controllers/RoutePlannerController.cs
+++ b/src/Costasdev.Busurbano.Backend/Controllers/RoutePlannerController.cs
@@ -1,18 +1,34 @@
+using System.Net;
+using Costasdev.Busurbano.Backend.Configuration;
using Costasdev.Busurbano.Backend.Services;
using Costasdev.Busurbano.Backend.Types.Planner;
+using Costasdev.Busurbano.Sources.OpenTripPlannerGql;
+using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
namespace Costasdev.Busurbano.Backend.Controllers;
[ApiController]
[Route("api/planner")]
-public class RoutePlannerController : ControllerBase
+public partial class RoutePlannerController : ControllerBase
{
+ private readonly ILogger<RoutePlannerController> _logger;
private readonly OtpService _otpService;
+ private readonly AppConfiguration _config;
+ private readonly HttpClient _httpClient;
- public RoutePlannerController(OtpService otpService)
+ public RoutePlannerController(
+ ILogger<RoutePlannerController> logger,
+ OtpService otpService,
+ IOptions<AppConfiguration> config,
+ HttpClient httpClient
+ )
{
+ _logger = logger;
_otpService = otpService;
+ _config = config.Value;
+ _httpClient = httpClient;
}
[HttpGet("autocomplete")]
@@ -44,18 +60,43 @@ public class RoutePlannerController : ControllerBase
[FromQuery] double fromLon,
[FromQuery] double toLat,
[FromQuery] double toLon,
- [FromQuery] DateTime? time = null,
+ [FromQuery] DateTimeOffset time,
[FromQuery] bool arriveBy = false)
{
try
{
- var plan = await _otpService.GetRoutePlanAsync(fromLat, fromLon, toLat, toLon, time, arriveBy);
+ var requestContent = PlanConnectionContent.Query(
+ new PlanConnectionContent.Args(fromLat, fromLon, toLat, toLon, time, arriveBy)
+ );
+
+ var request = new HttpRequestMessage(HttpMethod.Post, $"{_config.OpenTripPlannerBaseUrl}/gtfs/v1");
+ request.Content = JsonContent.Create(new GraphClientRequest
+ {
+ Query = requestContent
+ });
+
+ var response = await _httpClient.SendAsync(request);
+ var responseBody = await response.Content.ReadFromJsonAsync<GraphClientResponse<PlanConnectionResponse>>();
+
+ Console.WriteLine(responseBody);
+
+ if (responseBody is not { IsSuccess: true } || responseBody.Data?.PlanConnection.Edges.Length == 0)
+ {
+ LogErrorFetchingRoutes(response.StatusCode, await response.Content.ReadAsStringAsync());
+ return StatusCode(500, "An error occurred while planning the route.");
+ }
+
+ var plan = _otpService.MapPlanResponse(responseBody.Data!);
return Ok(plan);
}
- catch (Exception)
+ catch (Exception e)
{
- // Log error
+ _logger.LogError("Exception planning route: {e}", e);
return StatusCode(500, "An error occurred while planning the route.");
}
}
+
+ [LoggerMessage(LogLevel.Error, "Error fetching route planning, received {statusCode} {responseBody}")]
+ partial void LogErrorFetchingRoutes(HttpStatusCode? statusCode, string responseBody);
+
}