aboutsummaryrefslogtreecommitdiff
path: root/src/Costasdev.Busurbano.ServiceViewer
diff options
context:
space:
mode:
Diffstat (limited to 'src/Costasdev.Busurbano.ServiceViewer')
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/.gitignore264
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/AppDbContextDesignTimeFactory.cs41
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Controllers/ServicesController.cs358
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Controllers/StylesheetController.cs39
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj17
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/AppDbContext.cs59
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Extensions/TimeExtensions.cs20
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/DirectionId.cs7
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/ExceptionType.cs7
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/RouteType.cs15
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripBikesAllowed.cs8
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripWheelchairAccessible.cs8
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/WheelchairBoarding.cs8
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Feed.cs21
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsAgency.cs46
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendar.cs45
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendarDate.cs24
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsRoute.cs70
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStop.cs51
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStopTime.cs44
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsTrip.cs57
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.Designer.cs547
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.cs318
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/AppDbContextModelSnapshot.cs544
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Data/QueryExtensions/GtfsCalendarQueryExtensions.cs21
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Program.cs35
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Properties/launchSettings.json14
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml22
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml.cs7
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml63
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml.cs29
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml40
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml.cs39
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/Shared/_Layout.cshtml22
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/_ViewImports.cshtml2
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/Views/_ViewStart.cshtml3
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/appsettings.json9
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/common.css23
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/days_in_feed.css28
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/service_details.css146
-rw-r--r--src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/services_in_day.css70
41 files changed, 0 insertions, 3191 deletions
diff --git a/src/Costasdev.Busurbano.ServiceViewer/.gitignore b/src/Costasdev.Busurbano.ServiceViewer/.gitignore
deleted file mode 100644
index ff5b00c..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/.gitignore
+++ /dev/null
@@ -1,264 +0,0 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# Azure Functions localsettings file
-local.settings.json
-
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-
-# Visual Studio 2015 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# DNX
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
-# but database connection strings (with potential passwords) will be unencrypted
-#*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/packages/*
-# except build/, which is used as an MSBuild target.
-!**/packages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
-# NuGet v3's project.json files produces more ignoreable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-node_modules/
-orleans.codegen.cs
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# JetBrains Rider
-.idea/
-*.sln.iml
-
-# CodeRush
-.cr/
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc \ No newline at end of file
diff --git a/src/Costasdev.Busurbano.ServiceViewer/AppDbContextDesignTimeFactory.cs b/src/Costasdev.Busurbano.ServiceViewer/AppDbContextDesignTimeFactory.cs
deleted file mode 100644
index 919c131..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/AppDbContextDesignTimeFactory.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Costasdev.ServiceViewer.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Design;
-
-namespace Costasdev.ServiceViewer;
-
-public class AppDbContextDesignTimeFactory : IDesignTimeDbContextFactory<AppDbContext>
-{
- public AppDbContext CreateDbContext(string[] args)
- {
- IConfigurationRoot configuration = new ConfigurationBuilder()
- .AddJsonFile("appsettings.json", optional: true)
- .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",
- optional: true)
- .AddUserSecrets(typeof(AppDbContext).Assembly, optional: true)
- .AddEnvironmentVariables()
- .Build();
-
- var builder = new DbContextOptionsBuilder<AppDbContext>();
- var connectionString = configuration.GetConnectionString("Database");
- if (string.IsNullOrEmpty(connectionString))
- {
- throw new InvalidOperationException("Connection string 'Database' not found.");
- }
-
- var loggerFactory = LoggerFactory.Create(lb =>
- {
- lb
- .AddConsole()
- .SetMinimumLevel(LogLevel.Information);
- });
- builder.UseLoggerFactory(loggerFactory);
-
- builder.UseNpgsql(
- connectionString,
- options => options.UseNetTopologySuite()
- );
-
- return new AppDbContext(builder.Options);
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Controllers/ServicesController.cs b/src/Costasdev.Busurbano.ServiceViewer/Controllers/ServicesController.cs
deleted file mode 100644
index bfb2a99..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Controllers/ServicesController.cs
+++ /dev/null
@@ -1,358 +0,0 @@
-using Costasdev.ServiceViewer.Data;
-using Costasdev.ServiceViewer.Data.Gtfs;
-using Costasdev.ServiceViewer.Data.Gtfs.Enums;
-using Costasdev.ServiceViewer.Data.QueryExtensions;
-using Costasdev.ServiceViewer.Views.Services;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Controllers;
-
-[Route("")]
-public class ServicesController : Controller
-{
- private readonly AppDbContext _db;
-
- public ServicesController(AppDbContext db)
- {
- _db = db;
- }
-
- [HttpGet("")]
- public async Task<IActionResult> DaysInFeed()
- {
- // FIXME: Use calendar too, but it requires getting the feed information
- var days = await _db.CalendarDates
- .Where(cd => cd.ExceptionType == ExceptionType.Added)
- .Select(cd => cd.Date)
- .Distinct()
- .OrderBy(d => d)
- .ToListAsync();
-
- var model = new DaysInFeedModel
- {
- Days = days,
- Today = DateOnly.FromDateTime(DateTime.Now),
- };
-
- return View(model);
- }
-
- [HttpGet("{day}")]
- public IActionResult ServicesInDay(
- [FromRoute] string day
- )
- {
- var dateParsed = DateOnly.TryParseExact(day, "yyyy-MM-dd", out var dateOnly);
- if (!dateParsed)
- {
- return BadRequest("Invalid date format. Please use 'yyyy-MM-dd'.");
- }
-
- var dateTime = dateOnly.ToDateTime(TimeOnly.MinValue);
-
- // 1. Get all the calendars running that day
- var dayOfWeek = dateOnly.DayOfWeek;
-
- var calendars = _db.Calendars
- .WhereDayOfWeek(dayOfWeek)
- .ToList();
-
- var calendarDates = _db.CalendarDates
- .Where(cd => cd.Date.Date == dateTime.Date)
- .ToList();
-
- // 2. Combine the two lists
- HashSet<string> activeServiceIds = [];
- foreach (var calendar in calendars)
- {
- if (calendarDates.All(cd =>
- cd.ServiceId != calendar.ServiceId || cd.ExceptionType != ExceptionType.Removed))
- {
- activeServiceIds.Add(calendar.ServiceId);
- }
- }
-
- foreach (var calendarDate in calendarDates.Where(cd => cd.ExceptionType == ExceptionType.Added))
- {
- activeServiceIds.Add(calendarDate.ServiceId);
- }
-
- // 3. Get the trips for those services
- var tripsByService = _db.Trips
- .AsSplitQuery()
- .Include(t => t.Route)
- .Where(t => activeServiceIds.Contains(t.ServiceId))
- .GroupBy(t => t.ServiceId)
- .ToDictionary(g => g.Key, g => g.ToList());
-
- /*
- * For each shift, we extract the trip sequence number from the trip_id, order them ascending and take first
- * one's first stop_time departure_time as shift start time and last one's last stop_time arrival_time as shift end time
- * FIXME: Heuristic only for Vitrasa, not other feeds
- * A 01LP001_008001_2, A 01LP001_008001_3, A 01LP001_008001_4, A 01LP001_008001_5...
- */
- List<ServiceInformation> serviceInformations = [];
- List<string> tripsWhoseFirstStopWeWant = [];
- List<string> tripsWhoseLastStopWeWant = [];
- foreach (var (service, trips) in tripsByService)
- {
- var orderedTrips = trips
- .Select(t => new
- {
- Trip = t,
- Sequence = int.TryParse(t.Id.Split('_').LastOrDefault(), out var seq) ? seq : int.MaxValue
- })
- .OrderBy(t => t.Sequence)
- .ThenBy(t => t.Trip.TripHeadsign) // Secondary sort to ensure consistent ordering
- .Select(t => t.Trip)
- .ToList();
-
- if (orderedTrips.Count == 0)
- {
- continue;
- }
-
- tripsWhoseFirstStopWeWant.Add(orderedTrips.First().Id);
- tripsWhoseLastStopWeWant.Add(orderedTrips.Last().Id);
- serviceInformations.Add(new ServiceInformation(
- service,
- GetNameForServiceId(service),
- orderedTrips,
- orderedTrips.First(),
- orderedTrips.Last()
- ));
- }
-
- var firstStopTimePerTrip = _db.StopTimes
- .AsSplitQuery().AsNoTracking()
- .Where(st => tripsWhoseFirstStopWeWant.Contains(st.TripId))
- .OrderBy(st => st.StopSequence)
- .GroupBy(st => st.TripId)
- .Select(g => g.First())
- .ToDictionary(st => st.TripId, st => st.Departure);
-
- var lastStopTimePerTrip = _db.StopTimes
- .AsSplitQuery().AsNoTracking()
- .Where(st => tripsWhoseLastStopWeWant.Contains(st.TripId))
- .OrderByDescending(st => st.StopSequence)
- .GroupBy(st => st.TripId)
- .Select(g => g.First())
- .ToDictionary(st => st.TripId, st => st.Arrival);
-
- // 4. Create a view model
- List<ServicesInDayItem> serviceCards = [];
- foreach (var serviceInfo in serviceInformations)
- {
- // For lines 16-24 switching during the day we want (16, 2), (24,2), (16,1), (24,2)... in sequence
- // TODO: Fix getting the trip sequence for any operator
- var tripsOrdered = serviceInfo.Trips
- .OrderBy(t => int.Parse(t.Id.Split('_').LastOrDefault() ?? string.Empty))
- .ToList();
-
- List<TripGroup> tripGroups = [];
- GtfsRoute currentRoute = tripsOrdered.First().Route;
- int currentRouteCount = 1;
- foreach (var trip in tripsOrdered.Skip(1))
- {
- if (trip.Route.Id == currentRoute.Id)
- {
- currentRouteCount++;
- }
- else
- {
- tripGroups.Add(new TripGroup(currentRoute, currentRouteCount));
- currentRoute = trip.Route;
- currentRouteCount = 1;
- }
- }
-
- tripGroups.Add(new TripGroup(currentRoute, currentRouteCount));
-
- serviceCards.Add(new ServicesInDayItem(
- serviceInfo.ServiceId,
- serviceInfo.ServiceName,
- serviceInfo.Trips,
- tripGroups,
- firstStopTimePerTrip.TryGetValue(serviceInfo.FirstTrip.Id, out var shiftStart)
- ? shiftStart
- : string.Empty,
- lastStopTimePerTrip.TryGetValue(serviceInfo.LastTrip.Id, out var shiftEnd) ? shiftEnd : string.Empty
- ));
- }
-
- return View(new ServiceInDayModel
- {
- Items = serviceCards,
- Date = dateOnly
- });
- }
-
- [HttpGet("{day}/{serviceId}")]
- public IActionResult ServiceDetails(
- [FromRoute] string day,
- [FromRoute] string serviceId
- )
- {
- #region Validation
-
- var dateParsed = DateOnly.TryParseExact(day, "yyyy-MM-dd", out var dateOnly);
- if (!dateParsed)
- {
- return BadRequest("Invalid date format. Please use 'yyyy-MM-dd'.");
- }
-
- var dateTime = dateOnly.ToDateTime(TimeOnly.MinValue);
-
- // 1. Get all the calendars running that day
- var dayOfWeek = dateOnly.DayOfWeek;
-
- var calendars = _db.Calendars
- .WhereDayOfWeek(dayOfWeek)
- .ToList();
-
- var calendarDates = _db.CalendarDates
- .Where(cd => cd.Date.Date == dateTime.Date)
- .ToList();
-
- // 2. Combine the two lists
- HashSet<string> activeServiceIds = [];
- foreach (var calendar in calendars)
- {
- if (calendarDates.All(cd =>
- cd.ServiceId != calendar.ServiceId || cd.ExceptionType != ExceptionType.Removed))
- {
- activeServiceIds.Add(calendar.ServiceId);
- }
- }
-
- foreach (var calendarDate in calendarDates.Where(cd => cd.ExceptionType == ExceptionType.Added))
- {
- activeServiceIds.Add(calendarDate.ServiceId);
- }
-
- if (!activeServiceIds.Contains(serviceId))
- {
- return NotFound("Service not found for the given day.");
- }
-
- #endregion
-
- var trips = _db.Trips
- .AsSplitQuery()
- .Include(t => t.Route)
- .Where(t => t.ServiceId == serviceId)
- .ToList();
-
- var orderedTrips = trips
- .Select(t => new
- {
- Trip = t,
- Sequence = int.TryParse(t.Id.Split('_').LastOrDefault(), out var seq) ? seq : int.MaxValue
- })
- .OrderBy(t => t.Sequence)
- .ThenBy(t => t.Trip.TripHeadsign) // Secondary sort to ensure consistent ordering
- .Select(t => t.Trip)
- .ToList();
-
- List<ServiceDetailsItem> items = [];
- int totalDistance = 0;
- TimeSpan totalDrivingMinutes = TimeSpan.Zero;
- foreach (var trip in orderedTrips)
- {
- var stopTimes = _db.StopTimes
- .AsSplitQuery().AsNoTracking()
- .Include(gtfsStopTime => gtfsStopTime.GtfsStop)
- .Where(st => st.TripId == trip.Id)
- .OrderBy(st => st.StopSequence)
- .ToList();
-
- if (stopTimes.Count == 0)
- {
- continue;
- }
-
- var firstStop = stopTimes.First();
- var lastStop = stopTimes.Last();
-
- var tripDistance = (int?)(lastStop.ShapeDistTraveled - firstStop.ShapeDistTraveled);
- totalDistance += tripDistance ?? 0;
- totalDrivingMinutes += (lastStop.ArrivalTime - firstStop.DepartureTime);
-
- items.Add(new ServiceDetailsItem
- {
- TripId = trip.Id,
- SafeRouteId = trip.Route.SafeId,
- ShortName = trip.Route.ShortName,
- LongName = trip.TripHeadsign ?? trip.Route.LongName,
- TotalDistance = tripDistance.HasValue ? $"{tripDistance.Value/1_000:F2} km" : "N/A",
- FirstStopName = firstStop.GtfsStop.Name,
- FirstStopTime = firstStop.Departure,
- LastStopName = lastStop.GtfsStop.Name,
- LastStopTime = lastStop.Arrival
- });
- }
-
- return View(new ServiceDetailsModel
- {
- Date = dateOnly,
- ServiceId = serviceId,
- ServiceName = GetNameForServiceId(serviceId),
- TotalDrivingTime = totalDrivingMinutes,
- TotalDistance = totalDistance,
- Items = items
- });
- }
-
- private string GetNameForServiceId(string serviceId)
- {
- var serviceIndicator = serviceId[^6..]; // "008001" or "202006"
- if (string.IsNullOrEmpty(serviceIndicator))
- {
- return serviceId;
- }
-
- var lineNumber = int.Parse(serviceIndicator[..3]); // "008"
- var shiftNumber = int.Parse(serviceIndicator[3..]); // "001"
- var lineName = lineNumber switch
- {
- 1 => "C1",
- 3 => "C3",
- 30 => "N1",
- 33 => "N4",
- 8 => "A",
- 101 => "H",
- 201 => "U1",
- 202 => "U2",
- 150 => "REF",
- 500 => "TUR",
- _ => $"L{lineNumber}"
- };
-
- return $"Servicio {lineName}-{shiftNumber}º ({serviceId[^6..]})";
- }
-}
-
-internal class ServiceInformation
-{
- internal string ServiceId { get; }
- public string ServiceName { get; set; }
- internal List<GtfsTrip> Trips { get; }
- internal GtfsTrip FirstTrip { get; }
- internal GtfsTrip LastTrip { get; }
-
- internal ServiceInformation(
- string serviceId,
- string serviceName,
- List<GtfsTrip> trips,
- GtfsTrip firstTrip,
- GtfsTrip lastTrip
- )
- {
- ServiceId = serviceId;
- ServiceName = serviceName;
- Trips = trips;
- FirstTrip = firstTrip;
- LastTrip = lastTrip;
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Controllers/StylesheetController.cs b/src/Costasdev.Busurbano.ServiceViewer/Controllers/StylesheetController.cs
deleted file mode 100644
index 00654db..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Controllers/StylesheetController.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System.Text;
-using Costasdev.ServiceViewer.Data;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Controllers;
-
-[Controller]
-[Route("")]
-public class StylesheetController : Controller
-{
- private readonly AppDbContext _db;
- public StylesheetController(AppDbContext db)
- {
- _db = db;
- }
-
- [HttpGet("stylesheets/routecolours.css")]
- public IActionResult GetRouteColoursSheet()
- {
- var routeColours = _db.Routes
- .Select(r => new { Id = r.SafeId, r.Color, r.TextColor })
- .ToListAsync();
-
- StringBuilder sb = new();
- foreach (var route in routeColours.Result)
- {
- sb.Append($".route-{route.Id} {{");
- sb.Append($"--route-color: #{route.Color};");
- sb.Append($"--route-text: #{route.TextColor};");
- sb.Append($"--route-color-semi: #{route.Color}4d;");
- sb.Append($"--route-text-semi: #{route.TextColor}4d;");
- sb.Append('}');
- }
- sb.Append('}');
-
- return Content(sb.ToString(), "text/css", Encoding.UTF8);
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj b/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj
deleted file mode 100644
index 426621c..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Costasdev.Busurbano.ServiceViewer.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
-
- <PropertyGroup>
- <TargetFramework>net10.0</TargetFramework>
- <Nullable>enable</Nullable>
- <ImplicitUsings>enable</ImplicitUsings>
- <RootNamespace>Costasdev.ServiceViewer</RootNamespace>
- <UserSecretsId>17600c95-53dd-43b7-9116-24ed4d24eae0</UserSecretsId>
- </PropertyGroup>
-
- <ItemGroup>
- <PackageReference Include="Microsoft.EntityFrameworkCore.Design" />
-
- <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
- <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite" />
- </ItemGroup>
-</Project>
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/AppDbContext.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/AppDbContext.cs
deleted file mode 100644
index 50f0791..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/AppDbContext.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using Costasdev.ServiceViewer.Data.Gtfs;
-using Costasdev.ServiceViewer.Data.Gtfs.Enums;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data;
-
-public class AppDbContext : DbContext
-{
- public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
- {
- }
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- // Route -> Agency
- modelBuilder.Entity<GtfsRoute>()
- .HasOne(r => r.Agency)
- .WithMany()
- .HasForeignKey(r => new { r.AgencyId, r.FeedId })
- .HasPrincipalKey(a => new { a.Id, a.FeedId });
-
- // Trip -> Route
- modelBuilder.Entity<GtfsTrip>()
- .HasOne(t => t.Route)
- .WithMany()
- .HasForeignKey(t => new { t.RouteId, t.FeedId })
- .HasPrincipalKey(a => new { a.Id, a.FeedId });
-
- // Relación StopTimes -> Trip
- modelBuilder.Entity<GtfsStopTime>()
- .HasOne(st => st.GtfsTrip)
- .WithMany()
- .HasForeignKey(st => new { st.TripId, st.FeedId })
- .HasPrincipalKey(a => new { a.Id, a.FeedId });
-
- // Relación StopTimes -> Stop
- modelBuilder.Entity<GtfsStopTime>()
- .HasOne(st => st.GtfsStop)
- .WithMany()
- .HasForeignKey(st => new { st.StopId, st.FeedId })
- .HasPrincipalKey(a => new { a.Id, a.FeedId });
-
- modelBuilder.Entity<GtfsTrip>()
- .Property(t => t.TripWheelchairAccessible)
- .HasDefaultValue(TripWheelchairAccessible.Empty);
-
- modelBuilder.Entity<GtfsTrip>()
- .Property(t => t.TripBikesAllowed)
- .HasDefaultValue(TripBikesAllowed.Empty);
- }
-
- public DbSet<GtfsAgency> Agencies { get; set; }
- public DbSet<GtfsCalendar> Calendars { get; set; }
- public DbSet<GtfsCalendarDate> CalendarDates { get; set; }
- public DbSet<GtfsRoute> Routes { get; set; }
- public DbSet<GtfsStop> Stops { get; set; }
- public DbSet<GtfsStopTime> StopTimes { get; set; }
- public DbSet<GtfsTrip> Trips { get; set; }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Extensions/TimeExtensions.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Extensions/TimeExtensions.cs
deleted file mode 100644
index 7fa487d..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Extensions/TimeExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Extensions;
-
-public static class TimeExtensions
-{
- extension(TimeSpan) {
- public static TimeSpan FromGtfsTime(string gtfsTime)
- {
- var parts = gtfsTime.Split(":", 3);
-
- var hours = int.Parse(parts[0]);
- var minutes = int.Parse(parts[1]);
- var seconds = int.Parse(parts[2]);
-
- int days = hours / 24;
- int leftoverHours = hours % 24;
-
- return new TimeSpan(days, leftoverHours, minutes, seconds);
- }
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/DirectionId.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/DirectionId.cs
deleted file mode 100644
index cbcf80b..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/DirectionId.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Gtfs.Enums;
-
-public enum DirectionId
-{
- Outbound = 0,
- Inbound = 1
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/ExceptionType.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/ExceptionType.cs
deleted file mode 100644
index 0ad0345..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/ExceptionType.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Gtfs.Enums;
-
-public enum ExceptionType
-{
- Added = 1,
- Removed = 2
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/RouteType.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/RouteType.cs
deleted file mode 100644
index e19d02a..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/RouteType.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Gtfs.Enums;
-
-public enum RouteType
-{
- Tram = 0,
- Subway = 1,
- Rail = 2,
- Bus = 3,
- Ferry = 4,
- CableTram = 5,
- AerialLift = 6,
- Funicular = 7,
- Trolleybus = 11,
- Monorail = 12
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripBikesAllowed.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripBikesAllowed.cs
deleted file mode 100644
index 838bc81..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripBikesAllowed.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Gtfs.Enums;
-
-public enum TripBikesAllowed
-{
- Empty = 0,
- CanAccommodate = 1,
- NotAllowed = 2
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripWheelchairAccessible.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripWheelchairAccessible.cs
deleted file mode 100644
index e84b699..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/TripWheelchairAccessible.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Gtfs.Enums;
-
-public enum TripWheelchairAccessible
-{
- Empty = 0,
- CanAccommodate = 1,
- NotAccessible = 2
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/WheelchairBoarding.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/WheelchairBoarding.cs
deleted file mode 100644
index 3cc550f..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Enums/WheelchairBoarding.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Costasdev.ServiceViewer.Data.Gtfs.Enums;
-
-public enum WheelchairBoarding
-{
- Unknown = 0,
- SomeVehicles = 1,
- NotPossible = 2
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Feed.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Feed.cs
deleted file mode 100644
index 065250b..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/Feed.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("feeds")]
-public class Feed
-{
- /// <summary>
- /// Auto-incrementing ID value for each feed, to identify it and its version
- /// </summary>
- [Key]
- public int Id { get; set; }
-
- [MaxLength(32)] public string ShortName { get; set; }
- [MaxLength(32)] public string LongName { get; set; }
- [MaxLength(255)] public string DownloadUrl { get; set; }
- [MaxLength(32)] public string Etag { get; set; }
-
- public DateTime InsertedAt { get; set; }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsAgency.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsAgency.cs
deleted file mode 100644
index 89b5518..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsAgency.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_agencies")]
-[PrimaryKey(nameof(Id), nameof(FeedId))]
-public class GtfsAgency
-{
- [Key]
- [Column("agency_id")]
- [MaxLength(255)]
- public required string Id { get; set; }
-
- [Column("feed_id")] public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [Column("agency_name")]
- [MaxLength(255)]
- public string Name { get; set; } = string.Empty;
-
- [Column("agency_url")]
- [MaxLength(255)]
- public string Url { get; set; } = string.Empty;
-
- [Column("agency_timezone")]
- [MaxLength(50)]
- public string Timezone { get; set; } = string.Empty;
-
- [Column("agency_lang")]
- [MaxLength(5)]
- public string Language { get; set; } = string.Empty;
-
- [Column("agency_phone")]
- [MaxLength(30)]
- public string? Phone { get; set; } = string.Empty;
-
- [Column("agency_email")]
- [MaxLength(255)]
- public string? Email { get; set; } = string.Empty;
-
- [Column("agency_fare_url")]
- [MaxLength(255)]
- public string? FareUrl { get; set; } = string.Empty;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendar.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendar.cs
deleted file mode 100644
index cfb144c..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendar.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_calendar")]
-[PrimaryKey(nameof(ServiceId), nameof(FeedId))]
-public class GtfsCalendar
-{
- [Key]
- [Column("service_id")]
- [MaxLength(32)]
- public string ServiceId { get; set; } = null!;
-
- [Column("feed_id")] public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [Column("monday")]
- public bool Monday { get; set; }
-
- [Column("tuesday")]
- public bool Tuesday { get; set; }
-
- [Column("wednesday")]
- public bool Wednesday { get; set; }
-
- [Column("thursday")]
- public bool Thursday { get; set; }
-
- [Column("friday")]
- public bool Friday { get; set; }
-
- [Column("saturday")]
- public bool Saturday { get; set; }
-
- [Column("sunday")]
- public bool Sunday { get; set; }
-
- [Column("start_date")]
- public DateOnly StartDate { get; set; }
-
- [Column("end_date")]
- public DateOnly EndDate { get; set; }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendarDate.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendarDate.cs
deleted file mode 100644
index 1543ef5..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsCalendarDate.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Costasdev.ServiceViewer.Data.Gtfs.Enums;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_calendar_dates")]
-[PrimaryKey(nameof(ServiceId), nameof(Date), nameof(FeedId))]
-public class GtfsCalendarDate
-{
- [Column("service_id")]
- [MaxLength(32)]
- public required string ServiceId { get; set; }
-
- [Column("date")]
- public required DateTime Date { get; set; }
-
- [Column("feed_id")] public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [Column("exception_type")]
- public required ExceptionType ExceptionType { get; set; }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsRoute.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsRoute.cs
deleted file mode 100644
index c34353c..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsRoute.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Costasdev.ServiceViewer.Data.Gtfs.Enums;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_routes")]
-[PrimaryKey(nameof(Id), nameof(FeedId))]
-public class GtfsRoute
-{
- [Column("route_id")]
- [MaxLength(255)]
- public required string Id { get; set; }
-
- public string SafeId => Id.Replace(" ", "_").Replace("-", "_");
-
- [Column("feed_id")]public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [Column("agency_id")]
- [ForeignKey(nameof(Agency))]
- [MaxLength(255)]
- public required string AgencyId { get; set; }
-
- [ForeignKey(nameof(AgencyId))]
- public GtfsAgency Agency { get; set; } = null!;
-
- /// <summary>
- /// Short name of a route. Often a short, abstract identifier (e.g., "32", "100X", "Green")
- /// that riders use to identify a route. Both route_short_name and route_long_name may be defined.
- /// </summary>
- [Column("route_short_name")]
- [MaxLength(32)]
- public string ShortName { get; set; } = string.Empty;
-
- /// <summary>
- /// Full name of a route. This name is generally more descriptive than the route_short_name and often
- /// includes the route's destination or stop. Both route_short_name and route_long_name may be defined.
- /// </summary>
- [Column("route_long_name")]
- [MaxLength(255)]
- public string LongName { get; set; } = string.Empty;
-
- [Column("route_desc")]
- [MaxLength(255)]
- public string? Description { get; set; } = string.Empty;
-
- [Column("route_type")]
- public RouteType Type { get; set; } = RouteType.Bus;
-
- [Column("route_url")]
- [MaxLength(255)]
- public string? Url { get; set; } = string.Empty;
-
- [Column("route_color")]
- [MaxLength(7)]
- public string? Color { get; set; } = string.Empty;
-
- [Column("route_text_color")]
- [MaxLength(7)]
- public string? TextColor { get; set; } = string.Empty;
-
- /// <summary>
- /// Orders the routes in a way which is ideal for presentation to customers.
- /// Routes with smaller route_sort_order values should be displayed first.
- /// </summary>
- [Column("route_sort_order")]
- public int SortOrder { get; set; } = 1;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStop.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStop.cs
deleted file mode 100644
index f604c5f..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStop.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Costasdev.ServiceViewer.Data.Gtfs.Enums;
-using Microsoft.EntityFrameworkCore;
-using NetTopologySuite.Geometries;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_stops")]
-[PrimaryKey(nameof(Id), nameof(FeedId))]
-public class GtfsStop
-{
- [Column("stop_id")]
- [MaxLength(32)]
- public required string Id { get; set; }
-
- [Column("feed_id")]public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [Column("stop_code")]
- [MaxLength(32)]
- public string Code { get; set; } = string.Empty;
-
- [Column("stop_name")]
- [MaxLength(255)]
- public string Name { get; set; } = string.Empty;
-
- [Column("stop_desc")]
- [MaxLength(255)]
- public string? Description { get; set; }
-
- [Column("stop_pos")]
- public Point? Position { get; set; }
-
- [Column("stop_url")]
- [MaxLength(255)]
- public string? Url { get; set; }
-
- [Column("stop_timezone")]
- [MaxLength(50)]
- public string? Timezone { get; set; }
-
- [Column("wheelchair_boarding")]
- public WheelchairBoarding WheelchairBoarding { get; set; } = WheelchairBoarding.Unknown;
-
- // [Column("location_type")]
- // public int LocationType { get; set; }
- //
- // [Column("parent_station")]
- // public int? ParentStationId { get; set; }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStopTime.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStopTime.cs
deleted file mode 100644
index 9599947..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsStopTime.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Costasdev.ServiceViewer.Data.Extensions;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_stop_times")]
-[PrimaryKey(nameof(TripId), nameof(StopSequence), nameof(FeedId))]
-public class GtfsStopTime
-{
- [Column("trip_id")]
- [ForeignKey("TripId")]
- [MaxLength(32)]
- public string TripId { get; set; } = null!;
-
- [Column("feed_id")]public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [ForeignKey(nameof(TripId))] public GtfsTrip GtfsTrip { get; set; } = null!;
-
- [Column("arrival_time")] public string Arrival { get; set; }
- public TimeSpan ArrivalTime => TimeSpan.FromGtfsTime(Arrival);
-
- [Column("departure_time")] public string Departure { get; set; }
- public TimeSpan DepartureTime => TimeSpan.FromGtfsTime(Departure);
-
- [Column("stop_id")]
- [ForeignKey(nameof(GtfsStop))]
- [MaxLength(32)]
- public required string StopId { get; set; }
-
- [ForeignKey(nameof(StopId))] public GtfsStop GtfsStop { get; set; } = null!;
-
- [Column("stop_sequence")] public int StopSequence { get; set; } = 0;
-
- // [Column("pickup_type")]
- // public int? PickupType { get; set; }
- //
- // [Column("drop_off_type")]
- // public int? DropOffType { get; set; }
-
- [Column("shape_dist_traveled")] public double? ShapeDistTraveled { get; set; } = null!;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsTrip.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsTrip.cs
deleted file mode 100644
index 3614120..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Gtfs/GtfsTrip.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Costasdev.ServiceViewer.Data.Gtfs.Enums;
-using Microsoft.EntityFrameworkCore;
-
-namespace Costasdev.ServiceViewer.Data.Gtfs;
-
-[Table("gtfs_trips")]
-[PrimaryKey(nameof(Id), nameof(FeedId))]
-public class GtfsTrip
-{
- [Column("trip_id")] [MaxLength(32)] public string Id { get; set; } = null!;
-
- [Column("feed_id")] public int FeedId { get; set; }
- [ForeignKey(nameof(FeedId))] public required Feed Feed { get; set; }
-
- [Column("route_id")]
- [MaxLength(32)]
- [ForeignKey(nameof(Route))]
- public string RouteId { get; set; } = null!;
-
- [ForeignKey(nameof(RouteId))] public GtfsRoute Route { get; set; } = null!;
-
- [Column("service_id")] [MaxLength(32)] public string ServiceId { get; set; } = null!;
-
- [Column("trip_headsign")]
- [MaxLength(255)]
- public string? TripHeadsign { get; set; }
-
- [Column("trip_short_name")]
- [MaxLength(255)]
- public string? TripShortName { get; set; }
-
- [Column("direction_id")] public DirectionId DirectionId { get; set; } = DirectionId.Outbound;
-
- /// <summary>
- /// Identifies the block to which the trip belongs. A block consists of a single trip or many
- /// sequential trips made using the same vehicle, defined by shared service days and block_id.
- /// A block_id may have trips with different service days, making distinct blocks.
- /// </summary>
- [Column("block_id")]
- [MaxLength(32)]
- public string? BlockId { get; set; }
-
- /// <summary>
- /// Identifies a geospatial shape describing the vehicle travel path for a trip.
- /// </summary>
- /// <remarks>To be implemented: will be stored as a GeoJSON file instead of database records.</remarks>
- [Column("shape_id")]
- [MaxLength(32)]
- public string? ShapeId { get; set; }
-
- [Column("trip_wheelchair_accessible")]
- public TripWheelchairAccessible TripWheelchairAccessible { get; set; } = TripWheelchairAccessible.Empty;
-
- [Column("trip_bikes_allowed")] public TripBikesAllowed TripBikesAllowed { get; set; } = TripBikesAllowed.Empty;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.Designer.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.Designer.cs
deleted file mode 100644
index 79f3e87..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.Designer.cs
+++ /dev/null
@@ -1,547 +0,0 @@
-// <auto-generated />
-using System;
-using Costasdev.ServiceViewer.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NetTopologySuite.Geometries;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace Data.Migrations
-{
- [DbContext(typeof(AppDbContext))]
- [Migration("20251211153852_Initial")]
- partial class Initial
- {
- /// <inheritdoc />
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "10.0.1")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.Feed", b =>
- {
- b.Property<int>("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("integer");
-
- NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
-
- b.Property<string>("DownloadUrl")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)");
-
- b.Property<string>("Etag")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)");
-
- b.Property<DateTime>("InsertedAt")
- .HasColumnType("timestamp with time zone");
-
- b.Property<string>("LongName")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)");
-
- b.Property<string>("ShortName")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)");
-
- b.HasKey("Id");
-
- b.ToTable("feeds");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsAgency", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("Email")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_email");
-
- b.Property<string>("FareUrl")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_fare_url");
-
- b.Property<string>("Language")
- .IsRequired()
- .HasMaxLength(5)
- .HasColumnType("character varying(5)")
- .HasColumnName("agency_lang");
-
- b.Property<string>("Name")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_name");
-
- b.Property<string>("Phone")
- .HasMaxLength(30)
- .HasColumnType("character varying(30)")
- .HasColumnName("agency_phone");
-
- b.Property<string>("Timezone")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("character varying(50)")
- .HasColumnName("agency_timezone");
-
- b.Property<string>("Url")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_url");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_agencies");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendar", b =>
- {
- b.Property<string>("ServiceId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("service_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<DateOnly>("EndDate")
- .HasColumnType("date")
- .HasColumnName("end_date");
-
- b.Property<bool>("Friday")
- .HasColumnType("boolean")
- .HasColumnName("friday");
-
- b.Property<bool>("Monday")
- .HasColumnType("boolean")
- .HasColumnName("monday");
-
- b.Property<bool>("Saturday")
- .HasColumnType("boolean")
- .HasColumnName("saturday");
-
- b.Property<DateOnly>("StartDate")
- .HasColumnType("date")
- .HasColumnName("start_date");
-
- b.Property<bool>("Sunday")
- .HasColumnType("boolean")
- .HasColumnName("sunday");
-
- b.Property<bool>("Thursday")
- .HasColumnType("boolean")
- .HasColumnName("thursday");
-
- b.Property<bool>("Tuesday")
- .HasColumnType("boolean")
- .HasColumnName("tuesday");
-
- b.Property<bool>("Wednesday")
- .HasColumnType("boolean")
- .HasColumnName("wednesday");
-
- b.HasKey("ServiceId", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_calendar");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendarDate", b =>
- {
- b.Property<string>("ServiceId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("service_id");
-
- b.Property<DateTime>("Date")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("date");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<int>("ExceptionType")
- .HasColumnType("integer")
- .HasColumnName("exception_type");
-
- b.HasKey("ServiceId", "Date", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_calendar_dates");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsRoute", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("AgencyId")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_id");
-
- b.Property<string>("Color")
- .HasMaxLength(7)
- .HasColumnType("character varying(7)")
- .HasColumnName("route_color");
-
- b.Property<string>("Description")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_desc");
-
- b.Property<string>("LongName")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_long_name");
-
- b.Property<string>("ShortName")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("route_short_name");
-
- b.Property<int>("SortOrder")
- .HasColumnType("integer")
- .HasColumnName("route_sort_order");
-
- b.Property<string>("TextColor")
- .HasMaxLength(7)
- .HasColumnType("character varying(7)")
- .HasColumnName("route_text_color");
-
- b.Property<int>("Type")
- .HasColumnType("integer")
- .HasColumnName("route_type");
-
- b.Property<string>("Url")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_url");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.HasIndex("AgencyId", "FeedId");
-
- b.ToTable("gtfs_routes");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStop", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("stop_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("Code")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("stop_code");
-
- b.Property<string>("Description")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("stop_desc");
-
- b.Property<string>("Name")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("stop_name");
-
- b.Property<Point>("Position")
- .HasColumnType("geometry")
- .HasColumnName("stop_pos");
-
- b.Property<string>("Timezone")
- .HasMaxLength(50)
- .HasColumnType("character varying(50)")
- .HasColumnName("stop_timezone");
-
- b.Property<string>("Url")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("stop_url");
-
- b.Property<int>("WheelchairBoarding")
- .HasColumnType("integer")
- .HasColumnName("wheelchair_boarding");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_stops");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStopTime", b =>
- {
- b.Property<string>("TripId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("trip_id");
-
- b.Property<int>("StopSequence")
- .HasColumnType("integer")
- .HasColumnName("stop_sequence");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("Arrival")
- .IsRequired()
- .HasColumnType("text")
- .HasColumnName("arrival_time");
-
- b.Property<string>("Departure")
- .IsRequired()
- .HasColumnType("text")
- .HasColumnName("departure_time");
-
- b.Property<double?>("ShapeDistTraveled")
- .HasColumnType("double precision")
- .HasColumnName("shape_dist_traveled");
-
- b.Property<string>("StopId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("stop_id");
-
- b.HasKey("TripId", "StopSequence", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.HasIndex("StopId", "FeedId");
-
- b.HasIndex("TripId", "FeedId");
-
- b.ToTable("gtfs_stop_times");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsTrip", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("trip_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("BlockId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("block_id");
-
- b.Property<int>("DirectionId")
- .HasColumnType("integer")
- .HasColumnName("direction_id");
-
- b.Property<string>("RouteId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("route_id");
-
- b.Property<string>("ServiceId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("service_id");
-
- b.Property<string>("ShapeId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("shape_id");
-
- b.Property<int>("TripBikesAllowed")
- .ValueGeneratedOnAdd()
- .HasColumnType("integer")
- .HasDefaultValue(0)
- .HasColumnName("trip_bikes_allowed");
-
- b.Property<string>("TripHeadsign")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("trip_headsign");
-
- b.Property<string>("TripShortName")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("trip_short_name");
-
- b.Property<int>("TripWheelchairAccessible")
- .ValueGeneratedOnAdd()
- .HasColumnType("integer")
- .HasDefaultValue(0)
- .HasColumnName("trip_wheelchair_accessible");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.HasIndex("RouteId", "FeedId");
-
- b.ToTable("gtfs_trips");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsAgency", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendar", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendarDate", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsRoute", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsAgency", "Agency")
- .WithMany()
- .HasForeignKey("AgencyId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Agency");
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStop", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStopTime", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsStop", "GtfsStop")
- .WithMany()
- .HasForeignKey("StopId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsTrip", "GtfsTrip")
- .WithMany()
- .HasForeignKey("TripId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
-
- b.Navigation("GtfsStop");
-
- b.Navigation("GtfsTrip");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsTrip", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsRoute", "Route")
- .WithMany()
- .HasForeignKey("RouteId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
-
- b.Navigation("Route");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.cs
deleted file mode 100644
index 5a75d40..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/20251211153852_Initial.cs
+++ /dev/null
@@ -1,318 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-using NetTopologySuite.Geometries;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace Data.Migrations
-{
- /// <inheritdoc />
- public partial class Initial : Migration
- {
- /// <inheritdoc />
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AlterDatabase()
- .Annotation("Npgsql:PostgresExtension:postgis", ",,");
-
- migrationBuilder.CreateTable(
- name: "feeds",
- columns: table => new
- {
- Id = table.Column<int>(type: "integer", nullable: false)
- .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
- ShortName = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- LongName = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- DownloadUrl = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- Etag = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- InsertedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_feeds", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_agencies",
- columns: table => new
- {
- agency_id = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- agency_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- agency_url = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- agency_timezone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
- agency_lang = table.Column<string>(type: "character varying(5)", maxLength: 5, nullable: false),
- agency_phone = table.Column<string>(type: "character varying(30)", maxLength: 30, nullable: true),
- agency_email = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- agency_fare_url = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_agencies", x => new { x.agency_id, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_agencies_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_calendar",
- columns: table => new
- {
- service_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- monday = table.Column<bool>(type: "boolean", nullable: false),
- tuesday = table.Column<bool>(type: "boolean", nullable: false),
- wednesday = table.Column<bool>(type: "boolean", nullable: false),
- thursday = table.Column<bool>(type: "boolean", nullable: false),
- friday = table.Column<bool>(type: "boolean", nullable: false),
- saturday = table.Column<bool>(type: "boolean", nullable: false),
- sunday = table.Column<bool>(type: "boolean", nullable: false),
- start_date = table.Column<DateOnly>(type: "date", nullable: false),
- end_date = table.Column<DateOnly>(type: "date", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_calendar", x => new { x.service_id, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_calendar_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_calendar_dates",
- columns: table => new
- {
- service_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- date = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- exception_type = table.Column<int>(type: "integer", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_calendar_dates", x => new { x.service_id, x.date, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_calendar_dates_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_stops",
- columns: table => new
- {
- stop_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- stop_code = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- stop_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- stop_desc = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- stop_pos = table.Column<Point>(type: "geometry", nullable: true),
- stop_url = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- stop_timezone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
- wheelchair_boarding = table.Column<int>(type: "integer", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_stops", x => new { x.stop_id, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_stops_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_routes",
- columns: table => new
- {
- route_id = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- agency_id = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- route_short_name = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- route_long_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
- route_desc = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- route_type = table.Column<int>(type: "integer", nullable: false),
- route_url = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- route_color = table.Column<string>(type: "character varying(7)", maxLength: 7, nullable: true),
- route_text_color = table.Column<string>(type: "character varying(7)", maxLength: 7, nullable: true),
- route_sort_order = table.Column<int>(type: "integer", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_routes", x => new { x.route_id, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_routes_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- table.ForeignKey(
- name: "FK_gtfs_routes_gtfs_agencies_agency_id_feed_id",
- columns: x => new { x.agency_id, x.feed_id },
- principalTable: "gtfs_agencies",
- principalColumns: new[] { "agency_id", "feed_id" },
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_trips",
- columns: table => new
- {
- trip_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- route_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- service_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- trip_headsign = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- trip_short_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
- direction_id = table.Column<int>(type: "integer", nullable: false),
- block_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
- shape_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
- trip_wheelchair_accessible = table.Column<int>(type: "integer", nullable: false, defaultValue: 0),
- trip_bikes_allowed = table.Column<int>(type: "integer", nullable: false, defaultValue: 0)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_trips", x => new { x.trip_id, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_trips_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- table.ForeignKey(
- name: "FK_gtfs_trips_gtfs_routes_route_id_feed_id",
- columns: x => new { x.route_id, x.feed_id },
- principalTable: "gtfs_routes",
- principalColumns: new[] { "route_id", "feed_id" },
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "gtfs_stop_times",
- columns: table => new
- {
- trip_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- feed_id = table.Column<int>(type: "integer", nullable: false),
- stop_sequence = table.Column<int>(type: "integer", nullable: false),
- arrival_time = table.Column<string>(type: "text", nullable: false),
- departure_time = table.Column<string>(type: "text", nullable: false),
- stop_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
- shape_dist_traveled = table.Column<double>(type: "double precision", nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_gtfs_stop_times", x => new { x.trip_id, x.stop_sequence, x.feed_id });
- table.ForeignKey(
- name: "FK_gtfs_stop_times_feeds_feed_id",
- column: x => x.feed_id,
- principalTable: "feeds",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- table.ForeignKey(
- name: "FK_gtfs_stop_times_gtfs_stops_stop_id_feed_id",
- columns: x => new { x.stop_id, x.feed_id },
- principalTable: "gtfs_stops",
- principalColumns: new[] { "stop_id", "feed_id" },
- onDelete: ReferentialAction.Cascade);
- table.ForeignKey(
- name: "FK_gtfs_stop_times_gtfs_trips_trip_id_feed_id",
- columns: x => new { x.trip_id, x.feed_id },
- principalTable: "gtfs_trips",
- principalColumns: new[] { "trip_id", "feed_id" },
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_agencies_feed_id",
- table: "gtfs_agencies",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_calendar_feed_id",
- table: "gtfs_calendar",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_calendar_dates_feed_id",
- table: "gtfs_calendar_dates",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_routes_agency_id_feed_id",
- table: "gtfs_routes",
- columns: new[] { "agency_id", "feed_id" });
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_routes_feed_id",
- table: "gtfs_routes",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_stop_times_feed_id",
- table: "gtfs_stop_times",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_stop_times_stop_id_feed_id",
- table: "gtfs_stop_times",
- columns: new[] { "stop_id", "feed_id" });
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_stop_times_trip_id_feed_id",
- table: "gtfs_stop_times",
- columns: new[] { "trip_id", "feed_id" });
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_stops_feed_id",
- table: "gtfs_stops",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_trips_feed_id",
- table: "gtfs_trips",
- column: "feed_id");
-
- migrationBuilder.CreateIndex(
- name: "IX_gtfs_trips_route_id_feed_id",
- table: "gtfs_trips",
- columns: new[] { "route_id", "feed_id" });
- }
-
- /// <inheritdoc />
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "gtfs_calendar");
-
- migrationBuilder.DropTable(
- name: "gtfs_calendar_dates");
-
- migrationBuilder.DropTable(
- name: "gtfs_stop_times");
-
- migrationBuilder.DropTable(
- name: "gtfs_stops");
-
- migrationBuilder.DropTable(
- name: "gtfs_trips");
-
- migrationBuilder.DropTable(
- name: "gtfs_routes");
-
- migrationBuilder.DropTable(
- name: "gtfs_agencies");
-
- migrationBuilder.DropTable(
- name: "feeds");
- }
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/AppDbContextModelSnapshot.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/AppDbContextModelSnapshot.cs
deleted file mode 100644
index feb3813..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/Migrations/AppDbContextModelSnapshot.cs
+++ /dev/null
@@ -1,544 +0,0 @@
-// <auto-generated />
-using System;
-using Costasdev.ServiceViewer.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NetTopologySuite.Geometries;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace Data.Migrations
-{
- [DbContext(typeof(AppDbContext))]
- partial class AppDbContextModelSnapshot : ModelSnapshot
- {
- protected override void BuildModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "10.0.1")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.Feed", b =>
- {
- b.Property<int>("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("integer");
-
- NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
-
- b.Property<string>("DownloadUrl")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)");
-
- b.Property<string>("Etag")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)");
-
- b.Property<DateTime>("InsertedAt")
- .HasColumnType("timestamp with time zone");
-
- b.Property<string>("LongName")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)");
-
- b.Property<string>("ShortName")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)");
-
- b.HasKey("Id");
-
- b.ToTable("feeds");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsAgency", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("Email")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_email");
-
- b.Property<string>("FareUrl")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_fare_url");
-
- b.Property<string>("Language")
- .IsRequired()
- .HasMaxLength(5)
- .HasColumnType("character varying(5)")
- .HasColumnName("agency_lang");
-
- b.Property<string>("Name")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_name");
-
- b.Property<string>("Phone")
- .HasMaxLength(30)
- .HasColumnType("character varying(30)")
- .HasColumnName("agency_phone");
-
- b.Property<string>("Timezone")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("character varying(50)")
- .HasColumnName("agency_timezone");
-
- b.Property<string>("Url")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_url");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_agencies");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendar", b =>
- {
- b.Property<string>("ServiceId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("service_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<DateOnly>("EndDate")
- .HasColumnType("date")
- .HasColumnName("end_date");
-
- b.Property<bool>("Friday")
- .HasColumnType("boolean")
- .HasColumnName("friday");
-
- b.Property<bool>("Monday")
- .HasColumnType("boolean")
- .HasColumnName("monday");
-
- b.Property<bool>("Saturday")
- .HasColumnType("boolean")
- .HasColumnName("saturday");
-
- b.Property<DateOnly>("StartDate")
- .HasColumnType("date")
- .HasColumnName("start_date");
-
- b.Property<bool>("Sunday")
- .HasColumnType("boolean")
- .HasColumnName("sunday");
-
- b.Property<bool>("Thursday")
- .HasColumnType("boolean")
- .HasColumnName("thursday");
-
- b.Property<bool>("Tuesday")
- .HasColumnType("boolean")
- .HasColumnName("tuesday");
-
- b.Property<bool>("Wednesday")
- .HasColumnType("boolean")
- .HasColumnName("wednesday");
-
- b.HasKey("ServiceId", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_calendar");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendarDate", b =>
- {
- b.Property<string>("ServiceId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("service_id");
-
- b.Property<DateTime>("Date")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("date");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<int>("ExceptionType")
- .HasColumnType("integer")
- .HasColumnName("exception_type");
-
- b.HasKey("ServiceId", "Date", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_calendar_dates");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsRoute", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("AgencyId")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("agency_id");
-
- b.Property<string>("Color")
- .HasMaxLength(7)
- .HasColumnType("character varying(7)")
- .HasColumnName("route_color");
-
- b.Property<string>("Description")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_desc");
-
- b.Property<string>("LongName")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_long_name");
-
- b.Property<string>("ShortName")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("route_short_name");
-
- b.Property<int>("SortOrder")
- .HasColumnType("integer")
- .HasColumnName("route_sort_order");
-
- b.Property<string>("TextColor")
- .HasMaxLength(7)
- .HasColumnType("character varying(7)")
- .HasColumnName("route_text_color");
-
- b.Property<int>("Type")
- .HasColumnType("integer")
- .HasColumnName("route_type");
-
- b.Property<string>("Url")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("route_url");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.HasIndex("AgencyId", "FeedId");
-
- b.ToTable("gtfs_routes");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStop", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("stop_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("Code")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("stop_code");
-
- b.Property<string>("Description")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("stop_desc");
-
- b.Property<string>("Name")
- .IsRequired()
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("stop_name");
-
- b.Property<Point>("Position")
- .HasColumnType("geometry")
- .HasColumnName("stop_pos");
-
- b.Property<string>("Timezone")
- .HasMaxLength(50)
- .HasColumnType("character varying(50)")
- .HasColumnName("stop_timezone");
-
- b.Property<string>("Url")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("stop_url");
-
- b.Property<int>("WheelchairBoarding")
- .HasColumnType("integer")
- .HasColumnName("wheelchair_boarding");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.ToTable("gtfs_stops");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStopTime", b =>
- {
- b.Property<string>("TripId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("trip_id");
-
- b.Property<int>("StopSequence")
- .HasColumnType("integer")
- .HasColumnName("stop_sequence");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("Arrival")
- .IsRequired()
- .HasColumnType("text")
- .HasColumnName("arrival_time");
-
- b.Property<string>("Departure")
- .IsRequired()
- .HasColumnType("text")
- .HasColumnName("departure_time");
-
- b.Property<double?>("ShapeDistTraveled")
- .HasColumnType("double precision")
- .HasColumnName("shape_dist_traveled");
-
- b.Property<string>("StopId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("stop_id");
-
- b.HasKey("TripId", "StopSequence", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.HasIndex("StopId", "FeedId");
-
- b.HasIndex("TripId", "FeedId");
-
- b.ToTable("gtfs_stop_times");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsTrip", b =>
- {
- b.Property<string>("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("trip_id");
-
- b.Property<int>("FeedId")
- .HasColumnType("integer")
- .HasColumnName("feed_id");
-
- b.Property<string>("BlockId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("block_id");
-
- b.Property<int>("DirectionId")
- .HasColumnType("integer")
- .HasColumnName("direction_id");
-
- b.Property<string>("RouteId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("route_id");
-
- b.Property<string>("ServiceId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("service_id");
-
- b.Property<string>("ShapeId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("shape_id");
-
- b.Property<int>("TripBikesAllowed")
- .ValueGeneratedOnAdd()
- .HasColumnType("integer")
- .HasDefaultValue(0)
- .HasColumnName("trip_bikes_allowed");
-
- b.Property<string>("TripHeadsign")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("trip_headsign");
-
- b.Property<string>("TripShortName")
- .HasMaxLength(255)
- .HasColumnType("character varying(255)")
- .HasColumnName("trip_short_name");
-
- b.Property<int>("TripWheelchairAccessible")
- .ValueGeneratedOnAdd()
- .HasColumnType("integer")
- .HasDefaultValue(0)
- .HasColumnName("trip_wheelchair_accessible");
-
- b.HasKey("Id", "FeedId");
-
- b.HasIndex("FeedId");
-
- b.HasIndex("RouteId", "FeedId");
-
- b.ToTable("gtfs_trips");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsAgency", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendar", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsCalendarDate", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsRoute", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsAgency", "Agency")
- .WithMany()
- .HasForeignKey("AgencyId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Agency");
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStop", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsStopTime", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsStop", "GtfsStop")
- .WithMany()
- .HasForeignKey("StopId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsTrip", "GtfsTrip")
- .WithMany()
- .HasForeignKey("TripId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
-
- b.Navigation("GtfsStop");
-
- b.Navigation("GtfsTrip");
- });
-
- modelBuilder.Entity("Costasdev.ServiceViewer.Data.Gtfs.GtfsTrip", b =>
- {
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.Feed", "Feed")
- .WithMany()
- .HasForeignKey("FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Costasdev.ServiceViewer.Data.Gtfs.GtfsRoute", "Route")
- .WithMany()
- .HasForeignKey("RouteId", "FeedId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Feed");
-
- b.Navigation("Route");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Data/QueryExtensions/GtfsCalendarQueryExtensions.cs b/src/Costasdev.Busurbano.ServiceViewer/Data/QueryExtensions/GtfsCalendarQueryExtensions.cs
deleted file mode 100644
index f5fc2bb..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Data/QueryExtensions/GtfsCalendarQueryExtensions.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using Costasdev.ServiceViewer.Data.Gtfs;
-
-namespace Costasdev.ServiceViewer.Data.QueryExtensions;
-
-public static class GtfsCalendarQueryExtensions
-{
- public static IQueryable<GtfsCalendar> WhereDayOfWeek(this IQueryable<GtfsCalendar> query, DayOfWeek dayOfWeek)
- {
- return dayOfWeek switch
- {
- DayOfWeek.Monday => query.Where(c => c.Monday),
- DayOfWeek.Tuesday => query.Where(c => c.Tuesday),
- DayOfWeek.Wednesday => query.Where(c => c.Wednesday),
- DayOfWeek.Thursday => query.Where(c => c.Thursday),
- DayOfWeek.Friday => query.Where(c => c.Friday),
- DayOfWeek.Saturday => query.Where(c => c.Saturday),
- DayOfWeek.Sunday => query.Where(c => c.Sunday),
- _ => query
- };
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Program.cs b/src/Costasdev.Busurbano.ServiceViewer/Program.cs
deleted file mode 100644
index 847f9d5..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Program.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Costasdev.ServiceViewer;
-using Costasdev.ServiceViewer.Data;
-using Microsoft.EntityFrameworkCore;
-
-var builder = WebApplication.CreateBuilder(args);
-
-builder.Services.AddControllersWithViews();
-
-builder.Services.AddDbContext<AppDbContext>(db =>
-{
- var connectionString = builder.Configuration.GetConnectionString("Database");
- if (string.IsNullOrEmpty(connectionString))
- {
- throw new InvalidOperationException("Connection string 'Database' is not configured.");
- }
- db.UseNpgsql(connectionString, npg =>
- {
- npg.UseNetTopologySuite();
- });
-});
-
-builder.Services.AddHttpClient();
-builder.Services.AddMemoryCache();
-
-var app = builder.Build();
-
-app.UseHttpsRedirection();
-app.UseRouting();
-
-app.UseStaticFiles();
-app.MapStaticAssets();
-
-app.MapControllers();
-
-app.Run();
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Properties/launchSettings.json b/src/Costasdev.Busurbano.ServiceViewer/Properties/launchSettings.json
deleted file mode 100644
index 34eab40..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Properties/launchSettings.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/launchsettings.json",
- "profiles": {
- "https": {
- "commandName": "Project",
- "dotnetRunMessages": true,
- "launchBrowser": true,
- "applicationUrl": "https://localhost:7265;http://localhost:5154",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
- }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml b/src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml
deleted file mode 100644
index 84f30a3..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml
+++ /dev/null
@@ -1,22 +0,0 @@
-@model Costasdev.ServiceViewer.Views.Services.DaysInFeedModel
-@{
- ViewData["Title"] = "Fechas con datos";
-}
-
-@section Head
-{
- <link rel="stylesheet" href="~/styles/days_in_feed.css" />
-}
-
-<header>
- <h1>Fechas con datos</h1>
-</header>
-
-<main>
- @foreach (var day in Model.Days)
- {
- <article>
- <a asp-controller="Services" asp-action="ServicesInDay" asp-route-day="@day.ToString("yyyy-MM-dd")">@day.ToString("M")</a>
- </article>
- }
-</main>
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml.cs b/src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml.cs
deleted file mode 100644
index 02fe5b0..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/DaysInFeed.cshtml.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Costasdev.ServiceViewer.Views.Services;
-
-public class DaysInFeedModel
-{
- public List<DateTime> Days { get; set; } = [];
- public DateOnly Today { get; set; }
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml b/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml
deleted file mode 100644
index 8eae631..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml
+++ /dev/null
@@ -1,63 +0,0 @@
-@using Costasdev.ServiceViewer.Data.Gtfs
-@using Humanizer
-@using Humanizer.Localisation
-@model Costasdev.ServiceViewer.Views.Services.ServiceDetailsModel
-@{
- ViewData["Title"] = Model.ServiceName;
-}
-
-@section Head
-{
- <link rel="stylesheet" href="~/styles/service_details.css" />
- <link rel="stylesheet" href="/stylesheets/routecolours.css" />
- <style>
-
- </style>
-}
-
-<header>
- <h1>@ViewData["Title"]</h1>
-</header>
-
-<nav class="navigation-bar">
- <a asp-action="DaysInFeed">Feed Vitrasa</a>
- &gt;
- <a asp-action="ServicesInDay" asp-route-day="@Model.Date.ToString("yyyy-MM-dd")">
- @Model.Date.ToString("dd 'de' MMMM 'de' yyyy")
- </a>
- &gt;
- <span>@Model.ServiceName</span>
-</nav>
-
-<section id="service-cards">
- @foreach (ServiceDetailsItem item in Model.Items)
- {
- <article class="trip-container route-@item.SafeRouteId">
- <div class="trip-header">
- <div class="route">@item.ShortName</div>
- <div class="headsign">@item.LongName</div>
- <div class="distance">
- @item.TotalDistance
- </div>
- </div>
- <div class="trip-details">
- <div class="trip-leg">
- <div class="trip-time">@item.FirstStopTime</div>
- <div class="trip-stop">@item.FirstStopName</div>
- </div>
- <div class="trip-leg">
- <div class="trip-time">@item.LastStopTime</div>
- <div class="trip-stop">@item.LastStopName</div>
- </div>
- </div>
- <div class="trip-footer" >
- <a class="trip-details-link">Ver detalle del viaje →</a>
- </div>
- </article>
- }
-</section>
-
-<footer>
- Tiempo de conducción: @Model.TotalDrivingTime.Hours horas y @Model.TotalDrivingTime.Minutes minutos.<br />
- Distancia total: @Model.TotalDistanceKm
-</footer>
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml.cs b/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml.cs
deleted file mode 100644
index a89efae..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServiceDetails.cshtml.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace Costasdev.ServiceViewer.Views.Services;
-
-public class ServiceDetailsModel
-{
- public DateOnly Date { get; set; }
- public string ServiceId { get; set; } = string.Empty;
- public string ServiceName { get; set; } = string.Empty;
-
- public List<ServiceDetailsItem> Items { get; set; } = [];
- public TimeSpan TotalDrivingTime { get; set; }
-
- public int TotalDistance { get; set; }
- public string TotalDistanceKm => (TotalDistance / 1000.0).ToString("0.00 km");
-}
-
-public class ServiceDetailsItem
-{
- public string TripId { get; set; } = string.Empty;
- public string SafeRouteId { get; set; } = string.Empty;
- public string ShortName { get; set; } = string.Empty;
- public string LongName { get; set; } = string.Empty;
- public string TotalDistance { get; set; } = string.Empty;
-
- public string FirstStopTime { get; set; } = string.Empty;
- public string FirstStopName { get; set; } = string.Empty;
-
- public string LastStopTime { get; set; } = string.Empty;
- public string LastStopName { get; set; } = string.Empty;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml b/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml
deleted file mode 100644
index a5ac66f..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml
+++ /dev/null
@@ -1,40 +0,0 @@
-@model Costasdev.ServiceViewer.Views.Services.ServiceInDayModel
-@{
- ViewData["Title"] = "Servicios a realizar en " + Model.Date.ToString("dd 'de' MMMM 'de' yyyy");
-}
-
-@section Head
-{
- <link rel="stylesheet" href="~/styles/services_in_day.css" />
- <link rel="stylesheet" href="/stylesheets/routecolours.css" />
-}
-
-<header>
- <h1>
- @ViewData["Title"]
- </h1>
-</header>
-
-<section id="service-cards">
- @foreach (ServicesInDayItem card in Model.Items)
- {
- <article>
- <header>
- <a asp-action="ServiceDetails" asp-route-day="@Model.Date.ToString("yyyy-MM-dd")" asp-route-serviceId="@card.ServiceId">
- @card.ServiceName
- </a>
- </header>
- <main>
- @card.ShiftStart &rarr; @card.ShiftEnd
- </main>
- <footer>
- @foreach (var cardTripGroup in card.TripGroups)
- {
- <span class="route-group route-@cardTripGroup.route.SafeId">
- @cardTripGroup.route.ShortName (@cardTripGroup.count)
- </span>
- }
- </footer>
- </article>
- }
-</section>
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml.cs b/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml.cs
deleted file mode 100644
index b0c57c3..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Services/ServicesInDay.cshtml.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using Costasdev.ServiceViewer.Data.Gtfs;
-
-namespace Costasdev.ServiceViewer.Views.Services;
-
-public class ServiceInDayModel
-{
- public List<ServicesInDayItem> Items { get; set; } = [];
- public DateOnly Date { get; set; }
-}
-
-public class ServicesInDayItem
-{
- public string ServiceId { get; set; }
- public string ServiceName { get; set; }
- public List<GtfsTrip> Trips { get; set; }
- public List<TripGroup> TripGroups { get; set; }
-
- public string ShiftStart { get; set; }
- public string ShiftEnd { get; set; }
-
- public ServicesInDayItem(
- string serviceId,
- string serviceName,
- List<GtfsTrip> trips,
- List<TripGroup> tripGroups,
- string shiftStart,
- string shiftEnd
- ) {
- ServiceId = serviceId;
- ServiceName = serviceName;
- Trips = trips;
- TripGroups = tripGroups;
-
- ShiftStart = shiftStart;
- ShiftEnd = shiftEnd;
- }
-}
-
-public record TripGroup(GtfsRoute route, int count);
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/Shared/_Layout.cshtml b/src/Costasdev.Busurbano.ServiceViewer/Views/Shared/_Layout.cshtml
deleted file mode 100644
index 88d5b83..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/Shared/_Layout.cshtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html lang="es">
-<head>
- <meta charset="UTF-8">
-
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta rel="robots" content="noindex, nofollow">
-
- <meta charset="utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
- <title>@ViewData["Title"] - VentaSync</title>
-
- <link rel="stylesheet" href="https://fonts.bunny.net/css?family=inter:300,400,700">
- <link rel="stylesheet" href="~/styles/common.css" />
- @await RenderSectionAsync("Head", required: false)
-</head>
-
-<body>
-
-@RenderBody()
-</body>
-</html>
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/_ViewImports.cshtml b/src/Costasdev.Busurbano.ServiceViewer/Views/_ViewImports.cshtml
deleted file mode 100644
index 785dc40..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/_ViewImports.cshtml
+++ /dev/null
@@ -1,2 +0,0 @@
-@using Costasdev.ServiceViewer.Views.Services
-@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/src/Costasdev.Busurbano.ServiceViewer/Views/_ViewStart.cshtml b/src/Costasdev.Busurbano.ServiceViewer/Views/_ViewStart.cshtml
deleted file mode 100644
index a5f1004..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/Views/_ViewStart.cshtml
+++ /dev/null
@@ -1,3 +0,0 @@
-@{
- Layout = "_Layout";
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/appsettings.json b/src/Costasdev.Busurbano.ServiceViewer/appsettings.json
deleted file mode 100644
index 10f68b8..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/appsettings.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
- "AllowedHosts": "*"
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/common.css b/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/common.css
deleted file mode 100644
index a0e0750..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/common.css
+++ /dev/null
@@ -1,23 +0,0 @@
-body {
- font-family: 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
- padding: 2rem;
- background-color: #fff;
- max-width: 800px;
- margin: 0 auto;
- line-height: 1.5;
-}
-
-h1 {
- font-size: 1.75rem;
- margin-bottom: 1.5rem;
- text-align: center;
-}
-
-body > footer {
- text-align: center;
- font-size: 0.85rem;
- color: #666;
- margin-top: 2rem;
- padding-top: 1rem;
- border-top: 1px solid #ddd;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/days_in_feed.css b/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/days_in_feed.css
deleted file mode 100644
index b3c46d1..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/days_in_feed.css
+++ /dev/null
@@ -1,28 +0,0 @@
-main article {
- background: #f9f9f9;
- border: 1px solid #ddd;
- border-radius: 4px;
- padding: 0.75rem 1rem;
- margin: 0.5rem 0;
- text-align: center;
-}
-
-main article.current-day {
- background: #e3f2fd;
- border-color: #0074d9;
-}
-
-main article.current-day a {
- font-weight: 700;
-}
-
-main article a {
- font-size: 1rem;
- font-weight: 500;
- color: #0074d9;
- text-decoration: none;
-}
-
-main article a:hover {
- text-decoration: underline;
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/service_details.css b/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/service_details.css
deleted file mode 100644
index 570de3a..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/service_details.css
+++ /dev/null
@@ -1,146 +0,0 @@
-.navigation-bar {
- margin-bottom: 1.5rem;
- font-size: 0.9rem;
-}
-
-.trip-container {
- border: 1px solid #ddd;
- border-radius: 0.25rem;
- background-color: var(--route-color-semi, #fafafa);
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
- margin-bottom: 1.5rem;
- overflow: hidden;
-}
-
-.trip-header {
- display: flex;
- background-color: #fff;
- border-bottom: 1px solid #eee;
- padding: 0.6rem 0.8rem;
-}
-
-.trip-header .route {
- font-weight: bold;
- font-size: 1.1rem;
- min-width: 60px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-right: 1px solid #ddd;
- margin-right: 0.5rem;
- padding-right: 0.5rem;
-}
-
-.trip-header .headsign {
- flex-grow: 1;
- font-weight: 500;
-}
-
-.trip-header .distance {
- min-width: 80px;
- text-align: right;
- font-weight: 500;
-}
-
-.trip-details {
- display: flex;
- flex-wrap: wrap;
-}
-
-.trip-leg {
- flex: 1;
- min-width: 280px;
- padding: 0.75rem;
-}
-
-.trip-leg:first-child {
- border-right: 1px solid #ddd;
-}
-
-.trip-time {
- font-weight: 600;
- font-family: 'Consolas', monospace;
- font-size: 1.1rem;
-}
-
-.trip-stop {
- margin-top: 0.25rem;
- color: #333;
-}
-
-.trip-footer {
- text-align: right;
- margin: 0.5em 1em 0.5em 0;
-}
-
-.trip-details-link {
- color: #0074d9;
- text-decoration: underline;
- font-size: 0.98em;
-}
-
-/* Day change marker */
-.day-change-marker {
- background-color: #fff3cd;
- border: 2px solid #f5c86a;
- color: #856404;
- text-align: center;
- padding: 0.75rem;
- margin: 1rem 0;
- border-radius: 4px;
- font-weight: bold;
-}
-
-/* Total distance counter */
-.total-distance {
- text-align: right;
- font-weight: bold;
- padding: 0.75rem;
- margin-top: 1.5rem;
- border-top: 1px solid #ddd;
- background-color: #f9f9f9;
- border-radius: 4px;
-}
-
-/* Highlight current trip */
-.trip-container.highlight {
- box-shadow: 0 0 8px rgba(0, 116, 217, 0.6);
- border-color: #0074d9;
- padding: 1rem;
-}
-
-/* Media query for print */
-@media print {
- body {
- padding: 0;
- margin: 0;
- }
-
- .trip-container {
- page-break-inside: avoid;
- border: 1px solid #000;
- margin-bottom: 0.5rem;
- }
-
- .trip-header {
- background-color: #f5f5f5 !important;
- }
-
- .day-change-marker {
- border: 1px solid #000;
- background-color: #f5f5f5 !important;
- color: #000;
- }
-
- .navigation {
- display: none;
- }
-}
-
-.trip-line--N1 {
- background-color: rgba(191, 191, 191, 0.30);
-}
-
-.trip-line-VITRASA {
- background-color: rgba(0, 153, 0, 0.30);
-}
diff --git a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/services_in_day.css b/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/services_in_day.css
deleted file mode 100644
index ce847ef..0000000
--- a/src/Costasdev.Busurbano.ServiceViewer/wwwroot/styles/services_in_day.css
+++ /dev/null
@@ -1,70 +0,0 @@
-a {
- color: #0074d9;
- text-decoration: none;
-}
-
-a:hover {
- text-decoration: underline;
-}
-
-#service-cards {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-#service-cards article {
- background: #f9f9f9;
- border: 1px solid #ddd;
- border-radius: 4px;
- margin: 0.5rem 0;
- padding: 1rem;
-}
-
-#service-cards article header {
- font-weight: 600;
- font-size: 1.1rem;
- margin-bottom: 0.5rem;
-}
-
-#service-cards article main {
- font-size: 0.9rem;
- margin-bottom: 0.75rem;
- color: #555;
-}
-
-#service-cards article footer {
- margin-top: 0.5rem;
- display: flex;
- flex-wrap: wrap;
- gap: 0.125rem 0.75rem;
-}
-
-#service-cards article footer span.route-group {
- display: inline-block;
- padding: 0.3rem 0.6rem;
- margin: 0.25rem 0.1rem;
- font-size: 0.85rem;
- font-weight: 600;
-
- background: #FFF;
- border-bottom: 4px solid var(--route-color, #000);
- color: var(--route-text, #000);
-}
-
-/* Filter button styles */
-.filter-btn {
- padding: 0.4rem 0.8rem;
- margin: 0.2rem;
- border: 1px solid #0074d9;
- border-radius: 4px;
- background: #fff;
- color: #0074d9;
- cursor: pointer;
- transition: background 0.2s, color 0.2s;
-}
-
-.filter-btn.active {
- background: #0074d9;
- color: #fff;
-}