aboutsummaryrefslogtreecommitdiff
path: root/src/Costasdev.Busurbano.Backend/Controllers
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-12-22 22:06:06 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2025-12-22 22:06:06 +0100
commitbed48c3d7e49b1736d50ce42d92bb6c18cf02504 (patch)
tree475571ad6fa8c7aa1f8e81520689bf1eb425164c /src/Costasdev.Busurbano.Backend/Controllers
parent68f49dec91d68579803d6d579b1f1ecb4fc1dd1f (diff)
Refactor arrivals handling and improve type definitions; reorganise components
Diffstat (limited to 'src/Costasdev.Busurbano.Backend/Controllers')
-rw-r--r--src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs29
-rw-r--r--src/Costasdev.Busurbano.Backend/Controllers/TileController.cs98
2 files changed, 88 insertions, 39 deletions
diff --git a/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs b/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs
index 5dee48d..7158137 100644
--- a/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs
+++ b/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs
@@ -1,7 +1,6 @@
using System.Net;
using Costasdev.Busurbano.Backend.GraphClient;
using Costasdev.Busurbano.Backend.GraphClient.App;
-using Costasdev.Busurbano.Backend.Types;
using Costasdev.Busurbano.Backend.Types.Arrivals;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
@@ -37,7 +36,14 @@ public partial class ArrivalsController : ControllerBase
var nowLocal = TimeZoneInfo.ConvertTime(DateTime.UtcNow, tz);
var todayLocal = nowLocal.Date;
- var requestContent = ArrivalsAtStopContent.Query(new(id, reduced ? 4 : 10));
+ var requestContent = ArrivalsAtStopContent.Query(
+ new ArrivalsAtStopContent.Args(
+ id,
+ reduced ? 4 : 10,
+ ShouldFetchPastArrivals(id)
+ )
+ );
+
var request = new HttpRequestMessage(HttpMethod.Post, "http://100.67.54.115:3957/otp/gtfs/v1");
request.Content = JsonContent.Create(new GraphClientRequest
{
@@ -61,13 +67,20 @@ public partial class ArrivalsController : ControllerBase
var minutesToArrive = (int)(departureTime - nowLocal).TotalMinutes;
//var isRunning = departureTime < nowLocal;
+ // TODO: Handle this properly, since many times it's "tomorrow" but not handled properly
+ if (minutesToArrive < ArrivalsAtStopContent.PastArrivalMinutesIncluded)
+ {
+ continue;
+ }
+
Arrival arrival = new()
{
+ TripId = item.Trip.GtfsId,
Route = new RouteInfo
{
ShortName = item.Trip.RouteShortName,
- Colour = item.Trip.Route.Color,
- TextColour = item.Trip.Route.TextColor
+ Colour = item.Trip.Route.Color ?? "FFFFFF",
+ TextColour = item.Trip.Route.TextColor ?? "000000"
},
Headsign = new HeadsignInfo
{
@@ -76,7 +89,7 @@ public partial class ArrivalsController : ControllerBase
Estimate = new ArrivalDetails
{
Minutes = minutesToArrive,
- Precission = departureTime < nowLocal ? ArrivalPrecission.Past : ArrivalPrecission.Scheduled
+ Precision = departureTime < nowLocal ? ArrivalPrecision.Past : ArrivalPrecision.Scheduled
}
};
@@ -91,6 +104,12 @@ public partial class ArrivalsController : ControllerBase
});
}
+ private static bool ShouldFetchPastArrivals(string id)
+ {
+ string feedId = id.Split(':', 2)[0];
+ return feedId == "xunta";
+ }
+
[LoggerMessage(LogLevel.Error, "Error fetching stop data, received {statusCode} {responseBody}")]
partial void LogErrorFetchingStopData(HttpStatusCode statusCode, string responseBody);
}
diff --git a/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs b/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs
index fad18e7..6354d67 100644
--- a/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs
+++ b/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs
@@ -46,9 +46,9 @@ public class TileController : ControllerBase
[HttpGet("stops/{z:int}/{x:int}/{y:int}")]
public async Task<IActionResult> Stops(int z, int x, int y)
{
- if (z < 9 || z > 16)
+ if (z is < 9 or > 20)
{
- return BadRequest("Zoom level out of range (9-16)");
+ return BadRequest("Zoom level out of range (9-20)");
}
var cacheHit = _cache.TryGetValue($"stops-tile-{z}-{x}-{y}", out byte[]? cachedTile);
@@ -96,10 +96,11 @@ public class TileController : ControllerBase
responseBody.Data?.StopsByBbox?.ForEach(stop =>
{
var idParts = stop.GtfsId.Split(':', 2);
+ string feedId = idParts[0];
string codeWithinFeed = stop.Code ?? string.Empty;
// TODO: Refactor this, maybe do it client-side or smth
- if (idParts[0] == "vitrasa")
+ if (feedId == "vitrasa")
{
var digits = new string(codeWithinFeed.Where(char.IsDigit).ToArray());
if (int.TryParse(digits, out int code))
@@ -108,12 +109,13 @@ public class TileController : ControllerBase
}
}
- if (HiddenStops.Contains($"{idParts[0]}:{codeWithinFeed}"))
+ if (HiddenStops.Contains($"{feedId}:{codeWithinFeed}"))
{
return;
}
- var fallbackColours = GetFallbackColourForFeed(idParts[0]);
+ var (Color, TextColor) = GetFallbackColourForFeed(idParts[0]);
+ var distinctRoutes = GetDistinctRoutes(feedId, stop.Routes ?? []);
Feature feature = new()
{
@@ -129,36 +131,34 @@ public class TileController : ControllerBase
// The name of the stop
{ "name", stop.Name },
// Routes
- { "routes", JsonSerializer.Serialize(stop.Routes?
- .DistinctBy(r => r.ShortName)
- .OrderBy(
- r => r.ShortName,
- Comparer<string?>.Create(SortingHelper.SortRouteShortNames)
- ).Select(r => {
- var colour = r.Color ?? fallbackColours.Color;
- string textColour;
+ { "routes", JsonSerializer
+ .Serialize(
+ distinctRoutes.Select(r => {
+ var colour = r.Color ?? Color;
+ string textColour;
- if (r.Color is null) // None is present, use fallback
- {
- textColour = fallbackColours.TextColor;
- }
- else if (r.TextColor is null || r.TextColor.EndsWith("000000"))
- {
- // Text colour not provided, or default-black; check the better contrasting
- textColour = ContrastHelper.GetBestTextColour(colour);
- }
- else
- {
- // Use provided text colour
- textColour = r.TextColor;
- }
+ if (r.Color is null) // None is present, use fallback
+ {
+ textColour = TextColor;
+ }
+ else if (r.TextColor is null || r.TextColor.EndsWith("000000"))
+ {
+ // Text colour not provided, or default-black; check the better contrasting
+ textColour = ContrastHelper.GetBestTextColour(colour);
+ }
+ else
+ {
+ // Use provided text colour
+ textColour = r.TextColor;
+ }
- return new {
- shortName = r.ShortName,
- colour,
- textColour
- };
- })) }
+ return new {
+ shortName = r.ShortName,
+ colour,
+ textColour
+ };
+ }))
+ }
}
};
@@ -176,6 +176,37 @@ public class TileController : ControllerBase
return File(ms.ToArray(), "application/x-protobuf");
}
+ private static List<StopTileResponse.Route> GetDistinctRoutes(string feedId, List<StopTileResponse.Route> routes)
+ {
+ List<StopTileResponse.Route> distinctRoutes = [];
+ HashSet<string> seen = new();
+
+ foreach (var route in routes)
+ {
+ var seenId = route.ShortName;
+ if (feedId == "xunta")
+ {
+ // For Xunta routes we take only the contract number (XG123, for example)
+ seenId = seenId.Substring(0, 5);
+
+ route.ShortName = seenId;
+ }
+
+ if (seen.Contains(seenId))
+ {
+ continue;
+ }
+
+ seen.Add(seenId);
+ distinctRoutes.Add(route);
+ }
+
+ return [.. distinctRoutes.OrderBy(
+ r => r.ShortName,
+ Comparer<string?>.Create(SortingHelper.SortRouteShortNames)
+ )];
+ }
+
private static (string Color, string TextColor) GetFallbackColourForFeed(string feed)
{
return feed switch
@@ -190,5 +221,4 @@ public class TileController : ControllerBase
};
}
-
}