From ef2df90ffb195edcddd701511dc5953c7baa63af Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Fri, 26 Dec 2025 15:56:09 +0100 Subject: Move OpenTripPlanner source to separate package --- .../Controllers/ArrivalsController.cs | 4 +- .../Controllers/TileController.cs | 5 +- .../Costasdev.Busurbano.Backend.csproj | 17 +- .../GraphClient/App/ArrivalsAtStop.cs | 198 -------------------- .../GraphClient/App/StopTile.cs | 76 -------- .../GraphClient/ResponseTypes.cs | 36 ---- .../Services/Processors/CorunaRealTimeProcessor.cs | 5 +- .../Services/Processors/NextStopsProcessor.cs | 2 +- .../Services/Processors/ShapeProcessor.cs | 2 +- .../Processors/VitrasaRealTimeProcessor.cs | 2 +- .../Costasdev.Busurbano.ServiceViewer.csproj | 56 +----- ...dev.Busurbano.Sources.OpenTripPlannerGql.csproj | 13 ++ .../OpenTripPlannerClient.cs | 47 +++++ .../Queries/ArrivalsAtStop.cs | 199 +++++++++++++++++++++ .../Queries/StopTile.cs | 76 ++++++++ .../ResponseTypes.cs | 36 ++++ 16 files changed, 393 insertions(+), 381 deletions(-) delete mode 100644 src/Costasdev.Busurbano.Backend/GraphClient/App/ArrivalsAtStop.cs delete mode 100644 src/Costasdev.Busurbano.Backend/GraphClient/App/StopTile.cs delete mode 100644 src/Costasdev.Busurbano.Backend/GraphClient/ResponseTypes.cs create mode 100644 src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Costasdev.Busurbano.Sources.OpenTripPlannerGql.csproj create mode 100644 src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/OpenTripPlannerClient.cs create mode 100644 src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs create mode 100644 src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/StopTile.cs create mode 100644 src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/ResponseTypes.cs (limited to 'src') diff --git a/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs b/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs index b4d8c96..957668a 100644 --- a/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs +++ b/src/Costasdev.Busurbano.Backend/Controllers/ArrivalsController.cs @@ -1,11 +1,11 @@ using System.Net; using Costasdev.Busurbano.Backend.Configuration; -using Costasdev.Busurbano.Backend.GraphClient; -using Costasdev.Busurbano.Backend.GraphClient.App; using Costasdev.Busurbano.Backend.Helpers; using Costasdev.Busurbano.Backend.Services; using Costasdev.Busurbano.Backend.Types; using Costasdev.Busurbano.Backend.Types.Arrivals; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; diff --git a/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs b/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs index e7efc09..0e550a3 100644 --- a/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs +++ b/src/Costasdev.Busurbano.Backend/Controllers/TileController.cs @@ -1,6 +1,3 @@ -using Costasdev.Busurbano.Backend.GraphClient; -using Costasdev.Busurbano.Backend.GraphClient.App; - using NetTopologySuite.Features; using NetTopologySuite.IO.VectorTiles; using NetTopologySuite.IO.VectorTiles.Mapbox; @@ -12,6 +9,8 @@ using System.Text.Json; using Costasdev.Busurbano.Backend.Helpers; using Costasdev.Busurbano.Backend.Services; using Costasdev.Busurbano.Backend.Configuration; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; using Microsoft.Extensions.Options; namespace Costasdev.Busurbano.Backend.Controllers; diff --git a/src/Costasdev.Busurbano.Backend/Costasdev.Busurbano.Backend.csproj b/src/Costasdev.Busurbano.Backend/Costasdev.Busurbano.Backend.csproj index 5e2283c..1f81e88 100644 --- a/src/Costasdev.Busurbano.Backend/Costasdev.Busurbano.Backend.csproj +++ b/src/Costasdev.Busurbano.Backend/Costasdev.Busurbano.Backend.csproj @@ -12,16 +12,21 @@ - - - + + + - - - + + + + + + + + diff --git a/src/Costasdev.Busurbano.Backend/GraphClient/App/ArrivalsAtStop.cs b/src/Costasdev.Busurbano.Backend/GraphClient/App/ArrivalsAtStop.cs deleted file mode 100644 index 10235de..0000000 --- a/src/Costasdev.Busurbano.Backend/GraphClient/App/ArrivalsAtStop.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System.Globalization; -using System.Text.Json.Serialization; - -namespace Costasdev.Busurbano.Backend.GraphClient.App; - -public class ArrivalsAtStopContent : IGraphRequest -{ - public record Args(string Id, bool Reduced); - - public static string Query(Args args) - { - var startTime = DateTimeOffset.UtcNow.AddMinutes(-75); - var startTimeUnix = startTime.ToUnixTimeSeconds(); - var geometryField = args.Reduced ? "" : @"tripGeometry { points }"; - - return string.Create(CultureInfo.InvariantCulture, $@" - query Query {{ - stop(id:""{args.Id}"") {{ - code - name - lat - lon - routes {{ - gtfsId - shortName - color - textColor - }} - arrivals: stoptimesWithoutPatterns(numberOfDepartures: 100, startTime: {startTimeUnix}, timeRange: 14400) {{ - headsign - scheduledDeparture - serviceDay - pickupType - - trip {{ - gtfsId - serviceId - routeShortName - route {{ - gtfsId - color - textColor - longName - }} - departureStoptime {{ - scheduledDeparture - }} - {geometryField} - stoptimes {{ - stop {{ - name - lat - lon - }} - scheduledDeparture - }} - }} - }} - }} - }} - "); - } -} - -public class ArrivalsAtStopResponse : AbstractGraphResponse -{ - [JsonPropertyName("stop")] public required StopItem Stop { get; set; } - - public class StopItem - { - [JsonPropertyName("code")] public required string Code { get; set; } - - [JsonPropertyName("name")] public required string Name { get; set; } - - [JsonPropertyName("lat")] public double Lat { get; set; } - - [JsonPropertyName("lon")] public double Lon { get; set; } - - [JsonPropertyName("routes")] public List Routes { get; set; } = []; - - [JsonPropertyName("arrivals")] public List Arrivals { get; set; } = []; - } - - public class Arrival - { - [JsonPropertyName("headsign")] public required string Headsign { get; set; } - - [JsonPropertyName("scheduledDeparture")] - public int ScheduledDepartureSeconds { get; set; } - - [JsonPropertyName("serviceDay")] - public long ServiceDay { get; set; } - - [JsonPropertyName("pickupType")] public required string PickupTypeOriginal { get; set; } - - public PickupType PickupTypeParsed => PickupType.Parse(PickupTypeOriginal); - - [JsonPropertyName("trip")] public required TripDetails Trip { get; set; } - } - - public class TripDetails - { - [JsonPropertyName("gtfsId")] public required string GtfsId { get; set; } - - [JsonPropertyName("serviceId")] public required string ServiceId { get; set; } - - [JsonPropertyName("routeShortName")] public required string RouteShortName { get; set; } - - [JsonPropertyName("departureStoptime")] - public required DepartureStoptime DepartureStoptime { get; set; } - - [JsonPropertyName("route")] public required RouteDetails Route { get; set; } - - [JsonPropertyName("tripGeometry")] public GeometryDetails? Geometry { get; set; } - - [JsonPropertyName("stoptimes")] public List Stoptimes { get; set; } = []; - } - - public class GeometryDetails - { - [JsonPropertyName("points")] public string? Points { get; set; } - } - - public class StoptimeDetails - { - [JsonPropertyName("stop")] public required StopDetails Stop { get; set; } - [JsonPropertyName("scheduledDeparture")] public int ScheduledDeparture { get; set; } - } - - public class StopDetails - { - [JsonPropertyName("name")] public required string Name { get; set; } - [JsonPropertyName("lat")] public double Lat { get; set; } - [JsonPropertyName("lon")] public double Lon { get; set; } - } - - public class DepartureStoptime - { - [JsonPropertyName("scheduledDeparture")] - public int ScheduledDeparture { get; set; } - } - - public class RouteDetails - { - [JsonPropertyName("gtfsId")] public required string GtfsId { get; set; } - public string GtfsIdValue => GtfsId.Split(':', 2)[1]; - - [JsonPropertyName("shortName")] public string? ShortName { get; set; } - - [JsonPropertyName("color")] public string? Color { get; set; } - - [JsonPropertyName("textColor")] public string? TextColor { get; set; } - - [JsonPropertyName("longName")] public string? LongName { get; set; } - } - - public class PickupType - { - private readonly string _value; - - private PickupType(string value) - { - _value = value; - } - - public static PickupType Parse(string value) - { - return value switch - { - "SCHEDULED" => Scheduled, - "NONE" => None, - "CALL_AGENCY" => CallAgency, - "COORDINATE_WITH_DRIVER" => CoordinateWithDriver, - _ => throw new ArgumentException("Unsupported pickup type ", value) - }; - } - - public static readonly PickupType Scheduled = new PickupType("SCHEDULED"); - public static readonly PickupType None = new PickupType("NONE"); - public static readonly PickupType CallAgency = new PickupType("CALL_AGENCY"); - public static readonly PickupType CoordinateWithDriver = new PickupType("COORDINATE_WITH_DRIVER"); - - public override bool Equals(object? other) - { - if (other is not PickupType otherPt) - { - return false; - } - - return otherPt._value == _value; - } - - public override int GetHashCode() - { - return _value.GetHashCode(); - } - } -} diff --git a/src/Costasdev.Busurbano.Backend/GraphClient/App/StopTile.cs b/src/Costasdev.Busurbano.Backend/GraphClient/App/StopTile.cs deleted file mode 100644 index 802de9a..0000000 --- a/src/Costasdev.Busurbano.Backend/GraphClient/App/StopTile.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Globalization; -using System.Text.Json.Serialization; - -namespace Costasdev.Busurbano.Backend.GraphClient.App; - -public class StopTileRequestContent : IGraphRequest -{ - public record Bbox(double MinLon, double MinLat, double MaxLon, double MaxLat); - - public static string Query(Bbox bbox) - { - return string.Create(CultureInfo.InvariantCulture, $@" - query Query {{ - stopsByBbox( - minLat: {bbox.MinLat:F6} - minLon: {bbox.MinLon:F6} - maxLon: {bbox.MaxLon:F6} - maxLat: {bbox.MaxLat:F6} - ) {{ - gtfsId - code - name - lat - lon - routes {{ - gtfsId - shortName - color - textColor - }} - }} - }} - "); - } -} - -public class StopTileResponse : AbstractGraphResponse -{ - [JsonPropertyName("stopsByBbox")] - public List? StopsByBbox { get; set; } - - public record Stop - { - [JsonPropertyName("gtfsId")] - public required string GtfsId { get; set; } - - [JsonPropertyName("code")] - public string? Code { get; set; } - - [JsonPropertyName("name")] - public required string Name { get; set; } - - [JsonPropertyName("lat")] - public required double Lat { get; set; } - - [JsonPropertyName("lon")] - public required double Lon { get; set; } - - [JsonPropertyName("routes")] - public List? Routes { get; set; } - } - - public record Route - { - [JsonPropertyName("gtfsId")] - public required string GtfsId { get; set; } - [JsonPropertyName("shortName")] - public required string ShortName { get; set; } - - [JsonPropertyName("color")] - public string? Color { get; set; } - - [JsonPropertyName("textColor")] - public string? TextColor { get; set; } - } -} diff --git a/src/Costasdev.Busurbano.Backend/GraphClient/ResponseTypes.cs b/src/Costasdev.Busurbano.Backend/GraphClient/ResponseTypes.cs deleted file mode 100644 index 2d4d5df..0000000 --- a/src/Costasdev.Busurbano.Backend/GraphClient/ResponseTypes.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Costasdev.Busurbano.Backend.GraphClient; - -public class GraphClientRequest -{ - public string OperationName { get; set; } = "Query"; - public required string Query { get; set; } -} - -public class GraphClientResponse where T : AbstractGraphResponse -{ - [JsonPropertyName("data")] - public T? Data { get; set; } - - [JsonPropertyName("errors")] - public List? Errors { get; set; } - - public bool IsSuccess => Errors == null || Errors.Count == 0; -} - -public interface IGraphRequest -{ - static abstract string Query(T parameters); -} - -public class AbstractGraphResponse -{ -} - -public class GraphClientError -{ - [JsonPropertyName("message")] - public required string Message { get; set; } -} - diff --git a/src/Costasdev.Busurbano.Backend/Services/Processors/CorunaRealTimeProcessor.cs b/src/Costasdev.Busurbano.Backend/Services/Processors/CorunaRealTimeProcessor.cs index 2ac1554..ee98a1f 100644 --- a/src/Costasdev.Busurbano.Backend/Services/Processors/CorunaRealTimeProcessor.cs +++ b/src/Costasdev.Busurbano.Backend/Services/Processors/CorunaRealTimeProcessor.cs @@ -1,10 +1,7 @@ -using Costasdev.Busurbano.Backend.Configuration; -using Costasdev.Busurbano.Backend.GraphClient.App; using Costasdev.Busurbano.Backend.Types; using Costasdev.Busurbano.Backend.Types.Arrivals; -using Costasdev.VigoTransitApi; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; using Costasdev.Busurbano.Sources.TranviasCoruna; -using Microsoft.Extensions.Options; using Arrival = Costasdev.Busurbano.Backend.Types.Arrivals.Arrival; namespace Costasdev.Busurbano.Backend.Services.Processors; diff --git a/src/Costasdev.Busurbano.Backend/Services/Processors/NextStopsProcessor.cs b/src/Costasdev.Busurbano.Backend/Services/Processors/NextStopsProcessor.cs index 6273e0d..a00a68a 100644 --- a/src/Costasdev.Busurbano.Backend/Services/Processors/NextStopsProcessor.cs +++ b/src/Costasdev.Busurbano.Backend/Services/Processors/NextStopsProcessor.cs @@ -1,4 +1,4 @@ -using Costasdev.Busurbano.Backend.GraphClient.App; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; namespace Costasdev.Busurbano.Backend.Services.Processors; diff --git a/src/Costasdev.Busurbano.Backend/Services/Processors/ShapeProcessor.cs b/src/Costasdev.Busurbano.Backend/Services/Processors/ShapeProcessor.cs index 93e4a4f..40bc508 100644 --- a/src/Costasdev.Busurbano.Backend/Services/Processors/ShapeProcessor.cs +++ b/src/Costasdev.Busurbano.Backend/Services/Processors/ShapeProcessor.cs @@ -1,4 +1,4 @@ -using Costasdev.Busurbano.Backend.GraphClient.App; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; namespace Costasdev.Busurbano.Backend.Services.Processors; diff --git a/src/Costasdev.Busurbano.Backend/Services/Processors/VitrasaRealTimeProcessor.cs b/src/Costasdev.Busurbano.Backend/Services/Processors/VitrasaRealTimeProcessor.cs index 7a1d6ea..5e0783d 100644 --- a/src/Costasdev.Busurbano.Backend/Services/Processors/VitrasaRealTimeProcessor.cs +++ b/src/Costasdev.Busurbano.Backend/Services/Processors/VitrasaRealTimeProcessor.cs @@ -1,7 +1,7 @@ using Costasdev.Busurbano.Backend.Configuration; -using Costasdev.Busurbano.Backend.GraphClient.App; using Costasdev.Busurbano.Backend.Types; using Costasdev.Busurbano.Backend.Types.Arrivals; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; using Costasdev.VigoTransitApi; using Microsoft.Extensions.Options; diff --git a/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj b/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj index afa2489..426621c 100644 --- a/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj +++ b/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj @@ -9,59 +9,9 @@ - + - - - - - - - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.Build.Locator.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.deps.json" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll.config" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.runtimeconfig.json" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Newtonsoft.Json.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\System.Collections.Immutable.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\System.CommandLine.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\cs\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\de\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\es\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\fr\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\it\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ja\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ko\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\pl\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\pt-BR\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ru\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\tr\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\zh-Hans\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\zh-Hant\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.Build.Locator.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe.config" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.IO.Redist.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Newtonsoft.Json.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Buffers.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Collections.Immutable.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.CommandLine.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Memory.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Numerics.Vectors.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Runtime.CompilerServices.Unsafe.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Threading.Tasks.Extensions.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\cs\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\de\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\es\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\fr\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\it\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ja\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ko\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\pl\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\pt-BR\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ru\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\tr\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\zh-Hans\System.CommandLine.resources.dll" /> - <_ContentIncludedByDefault Remove="C:\Users\ariel\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\zh-Hant\System.CommandLine.resources.dll" /> + + diff --git a/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Costasdev.Busurbano.Sources.OpenTripPlannerGql.csproj b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Costasdev.Busurbano.Sources.OpenTripPlannerGql.csproj new file mode 100644 index 0000000..6d78b55 --- /dev/null +++ b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Costasdev.Busurbano.Sources.OpenTripPlannerGql.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + enable + enable + + + + + + + diff --git a/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/OpenTripPlannerClient.cs b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/OpenTripPlannerClient.cs new file mode 100644 index 0000000..eed78d6 --- /dev/null +++ b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/OpenTripPlannerClient.cs @@ -0,0 +1,47 @@ +using System.Net.Http.Json; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; +using Microsoft.Extensions.Logging; + +namespace Costasdev.Busurbano.Sources.OpenTripPlannerGql; + +public class OpenTripPlannerClient +{ + private readonly HttpClient _httpClient; + private readonly string _baseUrl; + private readonly ILogger _logger; + + public OpenTripPlannerClient( + HttpClient httpClient, + string baseUrl, + ILogger logger + ) + { + _httpClient = httpClient; + _baseUrl = baseUrl; + _logger = logger; + } + + public async Task GetStopsInBbox(double minLat, double minLon, double maxLat, double maxLon) + { + var requestContent = + StopTileRequestContent.Query(new StopTileRequestContent.Bbox(minLon, minLat, maxLon, maxLat)); + + var request = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/gtfs/v1"); + request.Content = JsonContent.Create(new GraphClientRequest + { + Query = requestContent + }); + + var response = await _httpClient.SendAsync(request); + var responseBody = await response.Content.ReadFromJsonAsync>(); + + if (responseBody is not { IsSuccess: true }) + { + _logger.LogError( + "Error fetching stop data, received {StatusCode} {ResponseBody}", + response.StatusCode, + await response.Content.ReadAsStringAsync() + ); + } + } +} diff --git a/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs new file mode 100644 index 0000000..bbf2c08 --- /dev/null +++ b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs @@ -0,0 +1,199 @@ +using System.Globalization; +using System.Text.Json.Serialization; +using Costasdev.Busurbano.Sources.OpenTripPlannerGql; + +namespace Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; + +public class ArrivalsAtStopContent : IGraphRequest +{ + public record Args(string Id, bool Reduced); + + public static string Query(Args args) + { + var startTime = DateTimeOffset.UtcNow.AddMinutes(-75); + var startTimeUnix = startTime.ToUnixTimeSeconds(); + var geometryField = args.Reduced ? "" : @"tripGeometry { points }"; + + return string.Create(CultureInfo.InvariantCulture, $@" + query Query {{ + stop(id:""{args.Id}"") {{ + code + name + lat + lon + routes {{ + gtfsId + shortName + color + textColor + }} + arrivals: stoptimesWithoutPatterns(numberOfDepartures: 100, startTime: {startTimeUnix}, timeRange: 14400) {{ + headsign + scheduledDeparture + serviceDay + pickupType + + trip {{ + gtfsId + serviceId + routeShortName + route {{ + gtfsId + color + textColor + longName + }} + departureStoptime {{ + scheduledDeparture + }} + {geometryField} + stoptimes {{ + stop {{ + name + lat + lon + }} + scheduledDeparture + }} + }} + }} + }} + }} + "); + } +} + +public class ArrivalsAtStopResponse : AbstractGraphResponse +{ + [JsonPropertyName("stop")] public required StopItem Stop { get; set; } + + public class StopItem + { + [JsonPropertyName("code")] public required string Code { get; set; } + + [JsonPropertyName("name")] public required string Name { get; set; } + + [JsonPropertyName("lat")] public double Lat { get; set; } + + [JsonPropertyName("lon")] public double Lon { get; set; } + + [JsonPropertyName("routes")] public List Routes { get; set; } = []; + + [JsonPropertyName("arrivals")] public List Arrivals { get; set; } = []; + } + + public class Arrival + { + [JsonPropertyName("headsign")] public required string Headsign { get; set; } + + [JsonPropertyName("scheduledDeparture")] + public int ScheduledDepartureSeconds { get; set; } + + [JsonPropertyName("serviceDay")] + public long ServiceDay { get; set; } + + [JsonPropertyName("pickupType")] public required string PickupTypeOriginal { get; set; } + + public PickupType PickupTypeParsed => PickupType.Parse(PickupTypeOriginal); + + [JsonPropertyName("trip")] public required TripDetails Trip { get; set; } + } + + public class TripDetails + { + [JsonPropertyName("gtfsId")] public required string GtfsId { get; set; } + + [JsonPropertyName("serviceId")] public required string ServiceId { get; set; } + + [JsonPropertyName("routeShortName")] public required string RouteShortName { get; set; } + + [JsonPropertyName("departureStoptime")] + public required DepartureStoptime DepartureStoptime { get; set; } + + [JsonPropertyName("route")] public required RouteDetails Route { get; set; } + + [JsonPropertyName("tripGeometry")] public GeometryDetails? Geometry { get; set; } + + [JsonPropertyName("stoptimes")] public List Stoptimes { get; set; } = []; + } + + public class GeometryDetails + { + [JsonPropertyName("points")] public string? Points { get; set; } + } + + public class StoptimeDetails + { + [JsonPropertyName("stop")] public required StopDetails Stop { get; set; } + [JsonPropertyName("scheduledDeparture")] public int ScheduledDeparture { get; set; } + } + + public class StopDetails + { + [JsonPropertyName("name")] public required string Name { get; set; } + [JsonPropertyName("lat")] public double Lat { get; set; } + [JsonPropertyName("lon")] public double Lon { get; set; } + } + + public class DepartureStoptime + { + [JsonPropertyName("scheduledDeparture")] + public int ScheduledDeparture { get; set; } + } + + public class RouteDetails + { + [JsonPropertyName("gtfsId")] public required string GtfsId { get; set; } + public string GtfsIdValue => GtfsId.Split(':', 2)[1]; + + [JsonPropertyName("shortName")] public string? ShortName { get; set; } + + [JsonPropertyName("color")] public string? Color { get; set; } + + [JsonPropertyName("textColor")] public string? TextColor { get; set; } + + [JsonPropertyName("longName")] public string? LongName { get; set; } + } + + public class PickupType + { + private readonly string _value; + + private PickupType(string value) + { + _value = value; + } + + public static PickupType Parse(string value) + { + return value switch + { + "SCHEDULED" => Scheduled, + "NONE" => None, + "CALL_AGENCY" => CallAgency, + "COORDINATE_WITH_DRIVER" => CoordinateWithDriver, + _ => throw new ArgumentException("Unsupported pickup type ", value) + }; + } + + public static readonly PickupType Scheduled = new PickupType("SCHEDULED"); + public static readonly PickupType None = new PickupType("NONE"); + public static readonly PickupType CallAgency = new PickupType("CALL_AGENCY"); + public static readonly PickupType CoordinateWithDriver = new PickupType("COORDINATE_WITH_DRIVER"); + + public override bool Equals(object? other) + { + if (other is not PickupType otherPt) + { + return false; + } + + return otherPt._value == _value; + } + + public override int GetHashCode() + { + return _value.GetHashCode(); + } + } +} diff --git a/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/StopTile.cs b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/StopTile.cs new file mode 100644 index 0000000..792d19e --- /dev/null +++ b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/Queries/StopTile.cs @@ -0,0 +1,76 @@ +using System.Globalization; +using System.Text.Json.Serialization; + +namespace Costasdev.Busurbano.Sources.OpenTripPlannerGql.Queries; + +public class StopTileRequestContent : IGraphRequest +{ + public record Bbox(double MinLon, double MinLat, double MaxLon, double MaxLat); + + public static string Query(Bbox bbox) + { + return string.Create(CultureInfo.InvariantCulture, $@" + query Query {{ + stopsByBbox( + minLat: {bbox.MinLat:F6} + minLon: {bbox.MinLon:F6} + maxLon: {bbox.MaxLon:F6} + maxLat: {bbox.MaxLat:F6} + ) {{ + gtfsId + code + name + lat + lon + routes {{ + gtfsId + shortName + color + textColor + }} + }} + }} + "); + } +} + +public class StopTileResponse : AbstractGraphResponse +{ + [JsonPropertyName("stopsByBbox")] + public List? StopsByBbox { get; set; } + + public record Stop + { + [JsonPropertyName("gtfsId")] + public required string GtfsId { get; set; } + + [JsonPropertyName("code")] + public string? Code { get; set; } + + [JsonPropertyName("name")] + public required string Name { get; set; } + + [JsonPropertyName("lat")] + public required double Lat { get; set; } + + [JsonPropertyName("lon")] + public required double Lon { get; set; } + + [JsonPropertyName("routes")] + public List? Routes { get; set; } + } + + public record Route + { + [JsonPropertyName("gtfsId")] + public required string GtfsId { get; set; } + [JsonPropertyName("shortName")] + public required string ShortName { get; set; } + + [JsonPropertyName("color")] + public string? Color { get; set; } + + [JsonPropertyName("textColor")] + public string? TextColor { get; set; } + } +} diff --git a/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/ResponseTypes.cs b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/ResponseTypes.cs new file mode 100644 index 0000000..237537f --- /dev/null +++ b/src/Costasdev.Busurbano.Sources.OpenTripPlannerGql/ResponseTypes.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; + +namespace Costasdev.Busurbano.Sources.OpenTripPlannerGql; + +public class GraphClientRequest +{ + public string OperationName { get; set; } = "Query"; + public required string Query { get; set; } +} + +public class GraphClientResponse where T : AbstractGraphResponse +{ + [JsonPropertyName("data")] + public T? Data { get; set; } + + [JsonPropertyName("errors")] + public List? Errors { get; set; } + + public bool IsSuccess => Errors == null || Errors.Count == 0; +} + +public interface IGraphRequest +{ + static abstract string Query(T parameters); +} + +public class AbstractGraphResponse +{ +} + +public class GraphClientError +{ + [JsonPropertyName("message")] + public required string Message { get; set; } +} + -- cgit v1.3