aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Costasdev.Busurbano.Backend/Services/Providers/RenfeTransitProvider.cs9
-rw-r--r--src/frontend/app/AppContext.tsx13
-rw-r--r--src/frontend/app/components/LineIcon.css10
-rw-r--r--src/frontend/app/components/Stops/ConsolidatedCirculationCard.css1
-rw-r--r--src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx96
-rw-r--r--src/frontend/app/components/Stops/ConsolidatedCirculationList.tsx3
-rw-r--r--src/frontend/app/config/RegionConfig.ts25
-rw-r--r--src/frontend/app/routes/home.tsx10
-rw-r--r--src/frontend/app/routes/stops-$id.tsx5
-rw-r--r--src/gtfs_perstop_report/.gitignore (renamed from src/gtfs_vigo_stops/.gitignore)0
-rw-r--r--src/gtfs_perstop_report/pyproject.toml (renamed from src/gtfs_vigo_stops/pyproject.toml)0
-rw-r--r--src/gtfs_perstop_report/src/__init__.py (renamed from src/gtfs_vigo_stops/src/__init__.py)0
-rw-r--r--src/gtfs_perstop_report/src/common.py (renamed from src/gtfs_vigo_stops/src/common.py)48
-rw-r--r--src/gtfs_perstop_report/src/download.py (renamed from src/gtfs_vigo_stops/src/download.py)0
-rw-r--r--src/gtfs_perstop_report/src/logger.py (renamed from src/gtfs_vigo_stops/src/logger.py)0
-rw-r--r--src/gtfs_perstop_report/src/proto/__init__.py (renamed from src/gtfs_vigo_stops/src/proto/__init__.py)0
-rw-r--r--src/gtfs_perstop_report/src/proto/stop_schedule_pb2.py (renamed from src/gtfs_vigo_stops/src/proto/stop_schedule_pb2.py)0
-rw-r--r--src/gtfs_perstop_report/src/proto/stop_schedule_pb2.pyi (renamed from src/gtfs_vigo_stops/src/proto/stop_schedule_pb2.pyi)0
-rw-r--r--src/gtfs_perstop_report/src/providers.py (renamed from src/gtfs_vigo_stops/src/providers.py)5
-rw-r--r--src/gtfs_perstop_report/src/report_writer.py (renamed from src/gtfs_vigo_stops/src/report_writer.py)0
-rw-r--r--src/gtfs_perstop_report/src/routes.py (renamed from src/gtfs_vigo_stops/src/routes.py)0
-rw-r--r--src/gtfs_perstop_report/src/services.py (renamed from src/gtfs_vigo_stops/src/services.py)0
-rw-r--r--src/gtfs_perstop_report/src/shapes.py (renamed from src/gtfs_vigo_stops/src/shapes.py)0
-rw-r--r--src/gtfs_perstop_report/src/stop_schedule_pb2.py (renamed from src/gtfs_vigo_stops/src/stop_schedule_pb2.py)0
-rw-r--r--src/gtfs_perstop_report/src/stop_schedule_pb2.pyi (renamed from src/gtfs_vigo_stops/src/stop_schedule_pb2.pyi)0
-rw-r--r--src/gtfs_perstop_report/src/stop_times.py (renamed from src/gtfs_vigo_stops/src/stop_times.py)0
-rw-r--r--src/gtfs_perstop_report/src/stops.py (renamed from src/gtfs_vigo_stops/src/stops.py)0
-rw-r--r--src/gtfs_perstop_report/src/street_name.py (renamed from src/gtfs_vigo_stops/src/street_name.py)0
-rw-r--r--src/gtfs_perstop_report/src/trips.py (renamed from src/gtfs_vigo_stops/src/trips.py)0
-rw-r--r--src/gtfs_perstop_report/stop_report.py (renamed from src/gtfs_vigo_stops/stop_report.py)0
-rw-r--r--src/gtfs_perstop_report/uv.lock (renamed from src/gtfs_vigo_stops/uv.lock)0
31 files changed, 160 insertions, 65 deletions
diff --git a/src/Costasdev.Busurbano.Backend/Services/Providers/RenfeTransitProvider.cs b/src/Costasdev.Busurbano.Backend/Services/Providers/RenfeTransitProvider.cs
index 55e880f..f114ec3 100644
--- a/src/Costasdev.Busurbano.Backend/Services/Providers/RenfeTransitProvider.cs
+++ b/src/Costasdev.Busurbano.Backend/Services/Providers/RenfeTransitProvider.cs
@@ -28,7 +28,7 @@ public class RenfeTransitProvider : ITransitProvider
}
var now = nowLocal.AddSeconds(60 - nowLocal.Second);
- var scopeEnd = now.AddMinutes(300);
+ var scopeEnd = now.AddMinutes(8 * 60);
var scheduledWindow = stopArrivals.Arrivals
.Where(c => c.CallingDateTime(nowLocal.Date) != null)
@@ -49,11 +49,12 @@ public class RenfeTransitProvider : ITransitProvider
{
Running = sched.StartingDateTime(nowLocal.Date)!.Value <= now,
Minutes = minutes,
- TripId = sched.TripId,
- ServiceId = sched.ServiceId,
+ TripId = sched.ServiceId[(sched.ServiceId.Length - 6)..(sched.ServiceId.Length - 1)],
+ ServiceId = sched.ServiceId[(sched.ServiceId.Length - 6)..(sched.ServiceId.Length - 1)],
ShapeId = sched.ShapeId,
},
- RealTime = null
+ RealTime = null,
+ NextStreets = [.. sched.NextStreets]
});
}
diff --git a/src/frontend/app/AppContext.tsx b/src/frontend/app/AppContext.tsx
index 59f2724..12a54da 100644
--- a/src/frontend/app/AppContext.tsx
+++ b/src/frontend/app/AppContext.tsx
@@ -3,11 +3,11 @@ import { type ReactNode } from "react";
import { type RegionId } from "./config/RegionConfig";
import { MapProvider, useMap } from "./contexts/MapContext";
import {
- SettingsProvider,
- useSettings,
- type MapPositionMode,
- type TableStyle,
- type Theme,
+ SettingsProvider,
+ useSettings,
+ type MapPositionMode,
+ type TableStyle,
+ type Theme,
} from "./contexts/SettingsContext";
// Re-export types for compatibility
@@ -21,6 +21,9 @@ export const useApp = () => {
return {
...settings,
...map,
+ // Mock region support for now since we only have one region
+ region: "vigo" as RegionId,
+ setRegion: (region: RegionId) => { console.log("Set region", region); },
};
};
diff --git a/src/frontend/app/components/LineIcon.css b/src/frontend/app/components/LineIcon.css
index 6363c85..6492d39 100644
--- a/src/frontend/app/components/LineIcon.css
+++ b/src/frontend/app/components/LineIcon.css
@@ -87,6 +87,16 @@
--line-gol: hsl(208, 68%, 66%);
--line-gol-text: hsl(0, 0%, 100%);
+ --line-md: hsl(316, 99%, 27%);
+ --line-md-text: hsl(0, 0%, 100%);
+ --line-ave: hsl(316, 99%, 27%);
+ --line-ave-text: hsl(0, 0%, 100%);
+ --line-alvia: hsl(316, 99%, 27%);
+ --line-alvia-text: hsl(0, 0%, 100%);
+ --line-trencelta: hsl(135, 58%, 25%);
+ --line-trencelta-text: hsl(0, 0%, 100%);
+ --line-regional: hsl(316, 99%, 27%);
+ --line-regional-text: hsl(0, 0%, 100%);
}
.line-icon-default {
diff --git a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css
index 57d30c8..9922b03 100644
--- a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css
+++ b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css
@@ -61,7 +61,6 @@
}
.consolidated-circulation-card .route-info strong {
- font-size: 1rem;
color: var(--text-color);
overflow: hidden;
text-overflow: ellipsis;
diff --git a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx
index 635c0ce..70a9355 100644
--- a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx
+++ b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx
@@ -1,4 +1,4 @@
-import { useMemo } from "react";
+import { useEffect, useMemo, useRef, useState } from "react";
import Marquee from 'react-fast-marquee';
import { useTranslation } from "react-i18next";
import LineIcon from "~components/LineIcon";
@@ -12,6 +12,7 @@ interface ConsolidatedCirculationCardProps {
onMapClick?: () => void;
readonly?: boolean;
reduced?: boolean;
+ driver?: string;
}
// Utility function to parse service ID and get the turn number
@@ -71,9 +72,52 @@ const parseServiceId = (serviceId: string): string => {
return `${displayLine}-${turnNumber}`;
};
+const AutoMarquee = ({ text }: { text: string }) => {
+ const containerRef = useRef<HTMLDivElement>(null);
+ const [shouldScroll, setShouldScroll] = useState(false);
+
+ useEffect(() => {
+ const el = containerRef.current;
+ if (!el) return;
+
+ const checkScroll = () => {
+ // 9px per char for text-sm font-mono is a safe upper bound estimate
+ // (14px * 0.6 = 8.4px)
+ const charWidth = 9;
+ const availableWidth = el.offsetWidth;
+ const textWidth = text.length * charWidth;
+
+ setShouldScroll(textWidth > availableWidth);
+ };
+
+ checkScroll();
+
+ const observer = new ResizeObserver(checkScroll);
+ observer.observe(el);
+
+ return () => observer.disconnect();
+ }, [text]);
+
+ if (shouldScroll) {
+ return (
+ <div ref={containerRef} className="w-full overflow-hidden">
+ <Marquee speed={60} gradient={false}>
+ <div className="mr-64 text-sm font-mono">{text}</div>
+ </Marquee>
+ </div>
+ );
+ }
+
+ return (
+ <div ref={containerRef} className="w-full overflow-hidden text-sm font-mono truncate">
+ {text}
+ </div>
+ );
+};
+
export const ConsolidatedCirculationCard: React.FC<
ConsolidatedCirculationCardProps
-> = ({ estimate, onMapClick, readonly, reduced }) => {
+> = ({ estimate, onMapClick, readonly, reduced, driver }) => {
const { t } = useTranslation();
const formatDistance = (meters: number) => {
@@ -157,7 +201,7 @@ export const ConsolidatedCirculationCard: React.FC<
chips.push(delayChip);
}
- if (estimate.schedule) {
+ if (estimate.schedule && driver !== 'renfe') {
chips.push({
label: `${parseServiceId(estimate.schedule.serviceId)} · ${getTripIdDisplay(
estimate.schedule.tripId
@@ -199,14 +243,17 @@ export const ConsolidatedCirculationCard: React.FC<
// Check if bus has GPS position (live tracking)
const hasGpsPosition = !!estimate.currentPosition;
+ const isRenfe = driver === 'renfe';
+ const isClickable = hasGpsPosition;
+ const looksDisabled = !isClickable && !isRenfe;
const Tag = readonly ? "div" : "button";
const interactiveProps = readonly
? {}
: {
- onClick: onMapClick,
+ onClick: isClickable ? onMapClick : undefined,
type: "button" as const,
- disabled: !hasGpsPosition,
+ disabled: !isClickable,
};
if (reduced) {
@@ -217,12 +264,14 @@ export const ConsolidatedCirculationCard: React.FC<
bg-(--message-background-color) border border-(--border-color)
rounded-xl px-3 py-2.5 transition-all
${readonly
- ? !hasGpsPosition
+ ? looksDisabled
? "opacity-70 cursor-not-allowed"
: ""
- : hasGpsPosition
+ : isClickable
? "cursor-pointer hover:shadow-[0_4px_14px_rgba(0,0,0,0.08)] hover:border-(--button-background-color) hover:bg-[color-mix(in_oklab,var(--button-background-color)_5%,var(--message-background-color))] active:scale-[0.98]"
- : "opacity-70 cursor-not-allowed"
+ : looksDisabled
+ ? "opacity-70 cursor-not-allowed"
+ : ""
}
`.trim()}
{...interactiveProps}
@@ -232,6 +281,9 @@ export const ConsolidatedCirculationCard: React.FC<
</div>
<div className="flex-1 min-w-0 flex flex-col gap-1">
<strong className="text-base text-(--text-color) overflow-hidden text-ellipsis line-clamp-2 leading-tight">
+ {driver === 'renfe' && estimate.schedule?.tripId && (
+ <span className="font-mono text-slate-500 mr-1.5 text-sm">{estimate.schedule.tripId}</span>
+ )}
{estimate.route}
</strong>
{metaChips.length > 0 && (
@@ -295,12 +347,14 @@ export const ConsolidatedCirculationCard: React.FC<
return (
<Tag
className={`consolidated-circulation-card ${readonly
- ? !hasGpsPosition
+ ? looksDisabled
? "no-gps"
: ""
- : hasGpsPosition
+ : isClickable
? "has-gps"
- : "no-gps"
+ : looksDisabled
+ ? "no-gps"
+ : ""
}`}
{...interactiveProps}
>
@@ -310,17 +364,15 @@ export const ConsolidatedCirculationCard: React.FC<
<LineIcon line={estimate.line} mode="pill" />
</div>
<div className="route-info">
- <strong>{estimate.route}</strong>
- {estimate.nextStreets && estimate.nextStreets.length > 0 && (() => {
- const text = estimate.nextStreets.join(" — ");
- return (
- <Marquee speed={85} play={text.length > 30}>
- <div className="mr-32 font-mono">
- {text}
- </div>
- </Marquee>
- );
- })()}
+ <strong className="uppercase">
+ {driver === 'renfe' && estimate.schedule?.tripId && (
+ <span className="font-mono text-slate-500 mr-2 text-[0.9em]">{estimate.schedule.tripId}</span>
+ )}
+ {estimate.route}
+ </strong>
+ {estimate.nextStreets && estimate.nextStreets.length > 0 && (
+ <AutoMarquee text={estimate.nextStreets.join(" — ")} />
+ )}
</div>
<div className={`eta-badge ${timeClass}`}>
<div className="eta-text">
diff --git a/src/frontend/app/components/Stops/ConsolidatedCirculationList.tsx b/src/frontend/app/components/Stops/ConsolidatedCirculationList.tsx
index 088f978..ec79f1c 100644
--- a/src/frontend/app/components/Stops/ConsolidatedCirculationList.tsx
+++ b/src/frontend/app/components/Stops/ConsolidatedCirculationList.tsx
@@ -9,12 +9,14 @@ interface ConsolidatedCirculationListProps {
data: ConsolidatedCirculation[];
onCirculationClick?: (estimate: ConsolidatedCirculation, index: number) => void;
reduced?: boolean;
+ driver?: string;
}
export const ConsolidatedCirculationList: React.FC<ConsolidatedCirculationListProps> = ({
data,
onCirculationClick,
reduced,
+ driver,
}) => {
const { t } = useTranslation();
@@ -43,6 +45,7 @@ export const ConsolidatedCirculationList: React.FC<ConsolidatedCirculationListPr
{sortedData.map((estimate, idx) => (
<ConsolidatedCirculationCard
reduced={reduced}
+ driver={driver}
key={generateKey(estimate)}
estimate={estimate}
onMapClick={() => onCirculationClick?.(estimate, idx)}
diff --git a/src/frontend/app/config/RegionConfig.ts b/src/frontend/app/config/RegionConfig.ts
index 4677509..43fe70a 100644
--- a/src/frontend/app/config/RegionConfig.ts
+++ b/src/frontend/app/config/RegionConfig.ts
@@ -1,6 +1,26 @@
import type { LngLatLike } from "maplibre-gl";
-export const REGION_DATA = {
+export type RegionId = "vigo";
+
+export interface RegionData {
+ id: RegionId;
+ name: string;
+ stopsEndpoint: string;
+ estimatesEndpoint: string;
+ consolidatedCirculationsEndpoint: string;
+ timetableEndpoint: string;
+ shapeEndpoint: string;
+ defaultCenter: LngLatLike;
+ bounds: {
+ sw: LngLatLike;
+ ne: LngLatLike;
+ };
+ textColour: string;
+ defaultZoom: number;
+ showMeters: boolean;
+}
+
+export const REGION_DATA: RegionData = {
id: "vigo",
name: "Vigo",
stopsEndpoint: "/stops/vigo.json",
@@ -20,3 +40,6 @@ export const REGION_DATA = {
defaultZoom: 14,
showMeters: true,
};
+
+export const getAvailableRegions = (): RegionData[] => [REGION_DATA];
+
diff --git a/src/frontend/app/routes/home.tsx b/src/frontend/app/routes/home.tsx
index 5d56b48..f97fdf7 100644
--- a/src/frontend/app/routes/home.tsx
+++ b/src/frontend/app/routes/home.tsx
@@ -104,7 +104,7 @@ export default function StopList() {
}
if (!userLocation) {
- return [...data].sort((a, b) => a.stopId - b.stopId);
+ return [...data].sort((a, b) => a.stopId.localeCompare(b.stopId));
}
const toRadians = (value: number) => (value * Math.PI) / 180;
@@ -147,7 +147,7 @@ export default function StopList() {
})
.sort((a, b) => {
if (a.distance === b.distance) {
- return a.stop.stopId - b.stop.stopId;
+ return a.stop.stopId.localeCompare(b.stop.stopId);
}
return a.distance - b.distance;
})
@@ -216,8 +216,8 @@ export default function StopList() {
let items: Stop[];
if (isNumericSearch) {
// Direct match for stop codes
- const stopId = parseInt(searchQuery.trim(), 10);
- const exactMatch = data.filter((stop) => stop.stopId === stopId);
+ const stopId = searchQuery.trim();
+ const exactMatch = data.filter((stop) => stop.stopId === stopId || stop.stopId.endsWith(`:${stopId}`));
if (exactMatch.length > 0) {
items = exactMatch;
} else {
@@ -281,7 +281,7 @@ export default function StopList() {
{/* Favourites Gallery */}
{!loading && (
<StopGallery
- stops={favouriteStops.sort((a, b) => a.stopId - b.stopId)}
+ stops={favouriteStops.sort((a, b) => a.stopId.localeCompare(b.stopId))}
title={t("stoplist.favourites")}
emptyMessage={t("stoplist.no_favourites")}
/>
diff --git a/src/frontend/app/routes/stops-$id.tsx b/src/frontend/app/routes/stops-$id.tsx
index 5260c32..553b8e7 100644
--- a/src/frontend/app/routes/stops-$id.tsx
+++ b/src/frontend/app/routes/stops-$id.tsx
@@ -247,8 +247,8 @@ export default function Estimates() {
<div className="flex items-center gap-8">
<Star
className={`cursor-pointer transition-colors ${favourited
- ? "fill-[var(--star-color)] text-[var(--star-color)]"
- : "text-slate-500"
+ ? "fill-[var(--star-color)] text-[var(--star-color)]"
+ : "text-slate-500"
}`}
onClick={toggleFavourite}
/>
@@ -273,6 +273,7 @@ export default function Estimates() {
<ConsolidatedCirculationList
data={data}
reduced={isReducedView}
+ driver={stopData?.stopId.split(':')[0]}
onCirculationClick={(estimate, idx) => {
setSelectedCirculationId(getCirculationId(estimate));
setIsMapModalOpen(true);
diff --git a/src/gtfs_vigo_stops/.gitignore b/src/gtfs_perstop_report/.gitignore
index 2be2c5f..2be2c5f 100644
--- a/src/gtfs_vigo_stops/.gitignore
+++ b/src/gtfs_perstop_report/.gitignore
diff --git a/src/gtfs_vigo_stops/pyproject.toml b/src/gtfs_perstop_report/pyproject.toml
index 97d24a3..97d24a3 100644
--- a/src/gtfs_vigo_stops/pyproject.toml
+++ b/src/gtfs_perstop_report/pyproject.toml
diff --git a/src/gtfs_vigo_stops/src/__init__.py b/src/gtfs_perstop_report/src/__init__.py
index e69de29..e69de29 100644
--- a/src/gtfs_vigo_stops/src/__init__.py
+++ b/src/gtfs_perstop_report/src/__init__.py
diff --git a/src/gtfs_vigo_stops/src/common.py b/src/gtfs_perstop_report/src/common.py
index fcf93d5..22769e4 100644
--- a/src/gtfs_vigo_stops/src/common.py
+++ b/src/gtfs_perstop_report/src/common.py
@@ -19,27 +19,27 @@ def get_all_feed_dates(feed_dir: str) -> List[str]:
if os.path.exists(calendar_path):
with open(calendar_path, encoding="utf-8") as f:
reader = csv.DictReader(f)
- start_dates: List[str] = []
- end_dates: List[str] = []
- for row in reader:
- if row.get("start_date") and row.get("end_date"):
- start_dates.append(row["start_date"])
- end_dates.append(row["end_date"])
- if start_dates and end_dates:
- min_date = min(start_dates)
- max_date = max(end_dates)
- # Convert YYYYMMDD to YYYY-MM-DD
- start = datetime.strptime(min_date, "%Y%m%d")
- end = datetime.strptime(max_date, "%Y%m%d")
- result: List[str] = []
- while start <= end:
- result.append(start.strftime("%Y-%m-%d"))
- start += timedelta(days=1)
- return result
- else:
- # Return from today to 7 days ahead if no valid dates found
- today = datetime.now()
- return [(today + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(8)]
+ rows = list(reader)
+ if rows: # Check if there's actual data
+ start_dates: List[str] = []
+ end_dates: List[str] = []
+ for row in rows:
+ if row.get("start_date") and row.get("end_date"):
+ start_dates.append(row["start_date"])
+ end_dates.append(row["end_date"])
+ if start_dates and end_dates:
+ min_date = min(start_dates)
+ max_date = max(end_dates)
+ # Convert YYYYMMDD to YYYY-MM-DD
+ start = datetime.strptime(min_date, "%Y%m%d")
+ end = datetime.strptime(max_date, "%Y%m%d")
+ result: List[str] = []
+ while start <= end:
+ result.append(start.strftime("%Y-%m-%d"))
+ start += timedelta(days=1)
+ if len(result) > 0:
+ return result
+
# Fallback: use calendar_dates.txt
if os.path.exists(calendar_dates_path):
@@ -51,9 +51,11 @@ def get_all_feed_dates(feed_dir: str) -> List[str]:
# Convert YYYYMMDD to YYYY-MM-DD
d = row["date"]
dates.add(f"{d[:4]}-{d[4:6]}-{d[6:]}")
- return sorted(dates)
+ if len(dates) > 0:
+ return sorted(dates)
- return []
+ today = datetime.today()
+ return [(today + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(8)]
def time_to_seconds(time_str: str) -> int:
diff --git a/src/gtfs_vigo_stops/src/download.py b/src/gtfs_perstop_report/src/download.py
index 19125bc..19125bc 100644
--- a/src/gtfs_vigo_stops/src/download.py
+++ b/src/gtfs_perstop_report/src/download.py
diff --git a/src/gtfs_vigo_stops/src/logger.py b/src/gtfs_perstop_report/src/logger.py
index 9488076..9488076 100644
--- a/src/gtfs_vigo_stops/src/logger.py
+++ b/src/gtfs_perstop_report/src/logger.py
diff --git a/src/gtfs_vigo_stops/src/proto/__init__.py b/src/gtfs_perstop_report/src/proto/__init__.py
index b775c17..b775c17 100644
--- a/src/gtfs_vigo_stops/src/proto/__init__.py
+++ b/src/gtfs_perstop_report/src/proto/__init__.py
diff --git a/src/gtfs_vigo_stops/src/proto/stop_schedule_pb2.py b/src/gtfs_perstop_report/src/proto/stop_schedule_pb2.py
index cb4f336..cb4f336 100644
--- a/src/gtfs_vigo_stops/src/proto/stop_schedule_pb2.py
+++ b/src/gtfs_perstop_report/src/proto/stop_schedule_pb2.py
diff --git a/src/gtfs_vigo_stops/src/proto/stop_schedule_pb2.pyi b/src/gtfs_perstop_report/src/proto/stop_schedule_pb2.pyi
index 355798f..355798f 100644
--- a/src/gtfs_vigo_stops/src/proto/stop_schedule_pb2.pyi
+++ b/src/gtfs_perstop_report/src/proto/stop_schedule_pb2.pyi
diff --git a/src/gtfs_vigo_stops/src/providers.py b/src/gtfs_perstop_report/src/providers.py
index f6414f6..fa04261 100644
--- a/src/gtfs_vigo_stops/src/providers.py
+++ b/src/gtfs_perstop_report/src/providers.py
@@ -72,12 +72,13 @@ class RenfeProvider:
@staticmethod
def format_route(route: str, terminus_name: str) -> str:
"""Use terminus name as route if route is empty."""
- return route if route else terminus_name
+ val = route if route else terminus_name
+ return val.replace("NY", "Ñ").replace("ny", "ñ")
@staticmethod
def extract_street_name(stop_name: str) -> str:
"""Preserve full stop name for train stations."""
- return stop_name
+ return stop_name.replace("NY", "Ñ").replace("ny", "ñ")
class DefaultProvider:
diff --git a/src/gtfs_vigo_stops/src/report_writer.py b/src/gtfs_perstop_report/src/report_writer.py
index f6d8763..f6d8763 100644
--- a/src/gtfs_vigo_stops/src/report_writer.py
+++ b/src/gtfs_perstop_report/src/report_writer.py
diff --git a/src/gtfs_vigo_stops/src/routes.py b/src/gtfs_perstop_report/src/routes.py
index e67a1a4..e67a1a4 100644
--- a/src/gtfs_vigo_stops/src/routes.py
+++ b/src/gtfs_perstop_report/src/routes.py
diff --git a/src/gtfs_vigo_stops/src/services.py b/src/gtfs_perstop_report/src/services.py
index fb1110d..fb1110d 100644
--- a/src/gtfs_vigo_stops/src/services.py
+++ b/src/gtfs_perstop_report/src/services.py
diff --git a/src/gtfs_vigo_stops/src/shapes.py b/src/gtfs_perstop_report/src/shapes.py
index f49832a..f49832a 100644
--- a/src/gtfs_vigo_stops/src/shapes.py
+++ b/src/gtfs_perstop_report/src/shapes.py
diff --git a/src/gtfs_vigo_stops/src/stop_schedule_pb2.py b/src/gtfs_perstop_report/src/stop_schedule_pb2.py
index 285b057..285b057 100644
--- a/src/gtfs_vigo_stops/src/stop_schedule_pb2.py
+++ b/src/gtfs_perstop_report/src/stop_schedule_pb2.py
diff --git a/src/gtfs_vigo_stops/src/stop_schedule_pb2.pyi b/src/gtfs_perstop_report/src/stop_schedule_pb2.pyi
index aa42cdb..aa42cdb 100644
--- a/src/gtfs_vigo_stops/src/stop_schedule_pb2.pyi
+++ b/src/gtfs_perstop_report/src/stop_schedule_pb2.pyi
diff --git a/src/gtfs_vigo_stops/src/stop_times.py b/src/gtfs_perstop_report/src/stop_times.py
index f3c3f25..f3c3f25 100644
--- a/src/gtfs_vigo_stops/src/stop_times.py
+++ b/src/gtfs_perstop_report/src/stop_times.py
diff --git a/src/gtfs_vigo_stops/src/stops.py b/src/gtfs_perstop_report/src/stops.py
index bb54fa4..bb54fa4 100644
--- a/src/gtfs_vigo_stops/src/stops.py
+++ b/src/gtfs_perstop_report/src/stops.py
diff --git a/src/gtfs_vigo_stops/src/street_name.py b/src/gtfs_perstop_report/src/street_name.py
index ec6b5b6..ec6b5b6 100644
--- a/src/gtfs_vigo_stops/src/street_name.py
+++ b/src/gtfs_perstop_report/src/street_name.py
diff --git a/src/gtfs_vigo_stops/src/trips.py b/src/gtfs_perstop_report/src/trips.py
index 0cedd26..0cedd26 100644
--- a/src/gtfs_vigo_stops/src/trips.py
+++ b/src/gtfs_perstop_report/src/trips.py
diff --git a/src/gtfs_vigo_stops/stop_report.py b/src/gtfs_perstop_report/stop_report.py
index f8fdc64..f8fdc64 100644
--- a/src/gtfs_vigo_stops/stop_report.py
+++ b/src/gtfs_perstop_report/stop_report.py
diff --git a/src/gtfs_vigo_stops/uv.lock b/src/gtfs_perstop_report/uv.lock
index bf7b7bd..bf7b7bd 100644
--- a/src/gtfs_vigo_stops/uv.lock
+++ b/src/gtfs_perstop_report/uv.lock