From 5a743bf079caa471bbb1421dec7416691bcd860b Mon Sep 17 00:00:00 2001 From: davd-gzl <60177543+davd-gzl@users.noreply.github.com> Date: Wed, 30 Sep 2026 19:35:59 +0900 Subject: [PATCH 1/4] Map: out-of-town stations sit at the station, not the city centre --- data/stations.json | 13 +++++++++++-- public/data/stations.json | 13 +++++++++++-- src/data/cities.ts | 8 ++++---- tests/stations.test.ts | 10 ++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/data/stations.json b/data/stations.json index c3eea99..5eb3513 100644 --- a/data/stations.json +++ b/data/stations.json @@ -32,7 +32,7 @@ { "id": "GRENOBLE", "label": "Grenoble", "city": "Grenoble", "lat": 45.1910, "lng": 5.7146, "region": "Auvergne-Rhône-Alpes" }, { "id": "CHAMBERY CHALLES LES EAUX", "label": "Chambéry", "city": "Chambéry", "lat": 45.5710, "lng": 5.9203, "region": "Auvergne-Rhône-Alpes", "aliases": ["chambery"] }, { "id": "ANNECY", "label": "Annecy", "city": "Annecy", "lat": 45.9020, "lng": 6.1206, "region": "Auvergne-Rhône-Alpes" }, - { "id": "VALENCE TGV", "label": "Valence TGV", "city": "Valence", "lat": 44.9333, "lng": 4.9783, "region": "Auvergne-Rhône-Alpes", "aliases": ["valence"] }, + { "id": "VALENCE TGV", "label": "Valence TGV", "city": "Valence", "lat": 44.9915, "lng": 4.9787, "region": "Auvergne-Rhône-Alpes", "aliases": ["valence"] }, { "id": "PERPIGNAN", "label": "Perpignan", "city": "Perpignan", "lat": 42.6970, "lng": 2.8796, "region": "Occitanie" }, { "id": "BREST", "label": "Brest", "city": "Brest", "lat": 48.3904, "lng": -4.4861, "region": "Bretagne" }, { "id": "QUIMPER", "label": "Quimper", "city": "Quimper", "lat": 47.9960, "lng": -4.0916, "region": "Bretagne" }, @@ -43,5 +43,14 @@ { "id": "BAYONNE", "label": "Bayonne", "city": "Bayonne", "lat": 43.4960, "lng": -1.4730, "region": "Nouvelle-Aquitaine" }, { "id": "PAU", "label": "Pau", "city": "Pau", "lat": 43.2951, "lng": -0.3708, "region": "Nouvelle-Aquitaine" }, { "id": "BELFORT MONTBELIARD TGV", "label": "Belfort-Montbéliard TGV", "city": "Belfort", "lat": 47.5862, "lng": 6.8997, "region": "Bourgogne-Franche-Comté" }, - { "id": "LE CREUSOT MONTCEAU MONTCHANIN", "label": "Le Creusot TGV", "city": "Le Creusot", "lat": 46.7903, "lng": 4.4250, "region": "Bourgogne-Franche-Comté" } + { "id": "LE CREUSOT MONTCEAU MONTCHANIN", "label": "Le Creusot TGV", "city": "Le Creusot", "lat": 46.7653, "lng": 4.4995, "region": "Bourgogne-Franche-Comté" }, + { "id": "LYON ST EXUPERY TGV.", "label": "Lyon St-Exupéry TGV", "city": "Lyon", "lat": 45.7211, "lng": 5.0750, "region": "Auvergne-Rhône-Alpes" }, + { "id": "VALENCE VILLE", "label": "Valence Ville", "city": "Valence", "lat": 44.9280, "lng": 4.8933, "region": "Auvergne-Rhône-Alpes" }, + { "id": "AVIGNON CENTRE", "label": "Avignon Centre", "city": "Avignon", "lat": 43.9419, "lng": 4.8053, "region": "Provence-Alpes-Côte d'Azur" }, + { "id": "LES ARCS DRAGUIGNAN", "label": "Les Arcs-Draguignan", "city": "Draguignan", "lat": 43.4555, "lng": 6.4825, "region": "Provence-Alpes-Côte d'Azur" }, + { "id": "NIMES PONT DU GARD", "label": "Nîmes Pont-du-Gard", "city": "Nîmes", "lat": 43.8168, "lng": 4.5077, "region": "Occitanie" }, + { "id": "MONTPELLIER SUD DE FRANCE", "label": "Montpellier Sud-de-France", "city": "Montpellier", "lat": 43.5948, "lng": 3.9246, "region": "Occitanie" }, + { "id": "BESANCON FRANCHE COMTE TGV", "label": "Besançon Franche-Comté TGV", "city": "Besançon", "lat": 47.3074, "lng": 5.9532, "region": "Bourgogne-Franche-Comté" }, + { "id": "MACON LOCHE TGV", "label": "Mâcon-Loché TGV", "city": "Mâcon", "lat": 46.2829, "lng": 4.7789, "region": "Bourgogne-Franche-Comté" }, + { "id": "CALAIS FRETHUN", "label": "Calais-Fréthun", "city": "Calais", "lat": 50.9012, "lng": 1.8109, "region": "Hauts-de-France" } ] diff --git a/public/data/stations.json b/public/data/stations.json index c3eea99..5eb3513 100644 --- a/public/data/stations.json +++ b/public/data/stations.json @@ -32,7 +32,7 @@ { "id": "GRENOBLE", "label": "Grenoble", "city": "Grenoble", "lat": 45.1910, "lng": 5.7146, "region": "Auvergne-Rhône-Alpes" }, { "id": "CHAMBERY CHALLES LES EAUX", "label": "Chambéry", "city": "Chambéry", "lat": 45.5710, "lng": 5.9203, "region": "Auvergne-Rhône-Alpes", "aliases": ["chambery"] }, { "id": "ANNECY", "label": "Annecy", "city": "Annecy", "lat": 45.9020, "lng": 6.1206, "region": "Auvergne-Rhône-Alpes" }, - { "id": "VALENCE TGV", "label": "Valence TGV", "city": "Valence", "lat": 44.9333, "lng": 4.9783, "region": "Auvergne-Rhône-Alpes", "aliases": ["valence"] }, + { "id": "VALENCE TGV", "label": "Valence TGV", "city": "Valence", "lat": 44.9915, "lng": 4.9787, "region": "Auvergne-Rhône-Alpes", "aliases": ["valence"] }, { "id": "PERPIGNAN", "label": "Perpignan", "city": "Perpignan", "lat": 42.6970, "lng": 2.8796, "region": "Occitanie" }, { "id": "BREST", "label": "Brest", "city": "Brest", "lat": 48.3904, "lng": -4.4861, "region": "Bretagne" }, { "id": "QUIMPER", "label": "Quimper", "city": "Quimper", "lat": 47.9960, "lng": -4.0916, "region": "Bretagne" }, @@ -43,5 +43,14 @@ { "id": "BAYONNE", "label": "Bayonne", "city": "Bayonne", "lat": 43.4960, "lng": -1.4730, "region": "Nouvelle-Aquitaine" }, { "id": "PAU", "label": "Pau", "city": "Pau", "lat": 43.2951, "lng": -0.3708, "region": "Nouvelle-Aquitaine" }, { "id": "BELFORT MONTBELIARD TGV", "label": "Belfort-Montbéliard TGV", "city": "Belfort", "lat": 47.5862, "lng": 6.8997, "region": "Bourgogne-Franche-Comté" }, - { "id": "LE CREUSOT MONTCEAU MONTCHANIN", "label": "Le Creusot TGV", "city": "Le Creusot", "lat": 46.7903, "lng": 4.4250, "region": "Bourgogne-Franche-Comté" } + { "id": "LE CREUSOT MONTCEAU MONTCHANIN", "label": "Le Creusot TGV", "city": "Le Creusot", "lat": 46.7653, "lng": 4.4995, "region": "Bourgogne-Franche-Comté" }, + { "id": "LYON ST EXUPERY TGV.", "label": "Lyon St-Exupéry TGV", "city": "Lyon", "lat": 45.7211, "lng": 5.0750, "region": "Auvergne-Rhône-Alpes" }, + { "id": "VALENCE VILLE", "label": "Valence Ville", "city": "Valence", "lat": 44.9280, "lng": 4.8933, "region": "Auvergne-Rhône-Alpes" }, + { "id": "AVIGNON CENTRE", "label": "Avignon Centre", "city": "Avignon", "lat": 43.9419, "lng": 4.8053, "region": "Provence-Alpes-Côte d'Azur" }, + { "id": "LES ARCS DRAGUIGNAN", "label": "Les Arcs-Draguignan", "city": "Draguignan", "lat": 43.4555, "lng": 6.4825, "region": "Provence-Alpes-Côte d'Azur" }, + { "id": "NIMES PONT DU GARD", "label": "Nîmes Pont-du-Gard", "city": "Nîmes", "lat": 43.8168, "lng": 4.5077, "region": "Occitanie" }, + { "id": "MONTPELLIER SUD DE FRANCE", "label": "Montpellier Sud-de-France", "city": "Montpellier", "lat": 43.5948, "lng": 3.9246, "region": "Occitanie" }, + { "id": "BESANCON FRANCHE COMTE TGV", "label": "Besançon Franche-Comté TGV", "city": "Besançon", "lat": 47.3074, "lng": 5.9532, "region": "Bourgogne-Franche-Comté" }, + { "id": "MACON LOCHE TGV", "label": "Mâcon-Loché TGV", "city": "Mâcon", "lat": 46.2829, "lng": 4.7789, "region": "Bourgogne-Franche-Comté" }, + { "id": "CALAIS FRETHUN", "label": "Calais-Fréthun", "city": "Calais", "lat": 50.9012, "lng": 1.8109, "region": "Hauts-de-France" } ] diff --git a/src/data/cities.ts b/src/data/cities.ts index 36e50a4..9b59b87 100644 --- a/src/data/cities.ts +++ b/src/data/cities.ts @@ -24,7 +24,7 @@ export const CITY_REFERENCE: CityRef[] = [ { name: "Douai", lat: 50.38, lng: 3.083, region: "Hauts-de-France" }, { name: "Valenciennes", lat: 50.358, lng: 3.516, region: "Hauts-de-France" }, { name: "Dunkerque", lat: 51.035, lng: 2.371, region: "Hauts-de-France" }, - { name: "Calais", lat: 50.951, lng: 1.857, region: "Hauts-de-France", aliases: ["calais frethun"] }, + { name: "Calais", lat: 50.951, lng: 1.857, region: "Hauts-de-France" }, { name: "Béthune", lat: 50.53, lng: 2.641, region: "Hauts-de-France" }, { name: "Lens", lat: 50.432, lng: 2.831, region: "Hauts-de-France" }, { name: "Saint-Quentin", lat: 49.848, lng: 3.287, region: "Hauts-de-France" }, @@ -62,7 +62,7 @@ export const CITY_REFERENCE: CityRef[] = [ { name: "Meuse", lat: 48.971, lng: 5.27, region: "Grand Est", aliases: ["meuse tgv"] }, // --- Bourgogne-Franche-Comté ---------------------------------------------- { name: "Chalon-sur-Saône", lat: 46.781, lng: 4.853, region: "Bourgogne-Franche-Comté" }, - { name: "Mâcon", lat: 46.307, lng: 4.829, region: "Bourgogne-Franche-Comté", aliases: ["macon loche", "macon ville"] }, + { name: "Mâcon", lat: 46.307, lng: 4.829, region: "Bourgogne-Franche-Comté", aliases: ["macon ville"] }, { name: "Montbard", lat: 47.622, lng: 4.337, region: "Bourgogne-Franche-Comté" }, { name: "Dole", lat: 47.092, lng: 5.49, region: "Bourgogne-Franche-Comté" }, { name: "Vesoul", lat: 47.621, lng: 6.155, region: "Bourgogne-Franche-Comté" }, @@ -196,7 +196,7 @@ export const CITY_REFERENCE: CityRef[] = [ // --- additional French stations (coverage gaps from the real dataset) ------ { name: "La Souterraine", lat: 46.237, lng: 1.486, region: "Nouvelle-Aquitaine" }, { name: "Moulins", lat: 46.565, lng: 3.333, region: "Auvergne-Rhône-Alpes", aliases: ["moulins sur allier"] }, - { name: "Draguignan", lat: 43.537, lng: 6.467, region: "Provence-Alpes-Côte d'Azur", aliases: ["les arcs draguignan", "les arcs"] }, + { name: "Draguignan", lat: 43.537, lng: 6.467, region: "Provence-Alpes-Côte d'Azur" }, { name: "Cahors", lat: 44.448, lng: 1.435, region: "Occitanie" }, { name: "Gourdon", lat: 44.738, lng: 1.384, region: "Occitanie" }, { name: "Souillac", lat: 44.895, lng: 1.471, region: "Occitanie" }, @@ -281,7 +281,7 @@ export const CITY_REFERENCE: CityRef[] = [ { name: "Die", lat: 44.754, lng: 5.37, region: "Auvergne-Rhône-Alpes" }, { name: "Landry", lat: 45.573, lng: 6.736, region: "Auvergne-Rhône-Alpes" }, { name: "Luc-en-Diois", lat: 44.614, lng: 5.446, region: "Auvergne-Rhône-Alpes" }, - { name: "Nurieux", lat: 46.18, lng: 5.47, region: "Auvergne-Rhône-Alpes" }, + { name: "Nurieux", lat: 46.184, lng: 5.533, region: "Auvergne-Rhône-Alpes" }, { name: "Saint-Avre-La Chambre", lat: 45.38, lng: 6.3, region: "Auvergne-Rhône-Alpes" }, { name: "Saint-Jean-de-Maurienne", lat: 45.276, lng: 6.346, region: "Auvergne-Rhône-Alpes", aliases: ["saint jean de maurienne arvan"] }, { name: "Saint-Michel-Valloire", lat: 45.218, lng: 6.47, region: "Auvergne-Rhône-Alpes" }, diff --git a/tests/stations.test.ts b/tests/stations.test.ts index 2c9affe..f02e5f9 100644 --- a/tests/stations.test.ts +++ b/tests/stations.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect } from "vitest"; import type { Station } from "../src/types"; import { StationRegistry, normalizeText, prettyLabel, isAirportStation } from "../src/data/stations"; +import { haversineKm } from "../src/util/geo"; import stationData from "../data/stations.json"; const registry = new StationRegistry(stationData as Station[]); @@ -79,6 +80,15 @@ describe("StationRegistry.addMissing", () => { expect(r.city("TGV HAUTE PICARDIE")).toBe("Haute-Picardie"); }); + it("plots an out-of-town station at the station, not at its city centre", () => { + const r = new StationRegistry(stationData as Station[]); + r.addMissing(["LYON ST EXUPERY TGV.", "LYON (intramuros)", "VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE"]); + const km = (a: string, b: string): number => haversineKm(r.coords(a)!, r.coords(b)!); + expect(km("LYON ST EXUPERY TGV.", "LYON (intramuros)")).toBeGreaterThan(15); + expect(km("VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE")).toBeGreaterThan(8); + expect(r.city("LYON ST EXUPERY TGV.")).toBe("Lyon"); // guide link still opens the city + }); + it("dedupes label collisions, preferring the id present in the dataset", () => { const r = new StationRegistry(stationData as Station[]); // The curated registry has id "LILLE"; a dataset variant renders the same. From 731d50c5ba1913a58628011ce19c8e93cba42a83 Mon Sep 17 00:00:00 2001 From: davd-gzl <60177543+davd-gzl@users.noreply.github.com> Date: Wed, 30 Sep 2026 20:08:55 +0900 Subject: [PATCH 2/4] Map: drop the Calais and Draguignan city rows the new station entries shadow --- src/data/cities.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/data/cities.ts b/src/data/cities.ts index 9b59b87..83a179a 100644 --- a/src/data/cities.ts +++ b/src/data/cities.ts @@ -24,7 +24,6 @@ export const CITY_REFERENCE: CityRef[] = [ { name: "Douai", lat: 50.38, lng: 3.083, region: "Hauts-de-France" }, { name: "Valenciennes", lat: 50.358, lng: 3.516, region: "Hauts-de-France" }, { name: "Dunkerque", lat: 51.035, lng: 2.371, region: "Hauts-de-France" }, - { name: "Calais", lat: 50.951, lng: 1.857, region: "Hauts-de-France" }, { name: "Béthune", lat: 50.53, lng: 2.641, region: "Hauts-de-France" }, { name: "Lens", lat: 50.432, lng: 2.831, region: "Hauts-de-France" }, { name: "Saint-Quentin", lat: 49.848, lng: 3.287, region: "Hauts-de-France" }, @@ -196,7 +195,6 @@ export const CITY_REFERENCE: CityRef[] = [ // --- additional French stations (coverage gaps from the real dataset) ------ { name: "La Souterraine", lat: 46.237, lng: 1.486, region: "Nouvelle-Aquitaine" }, { name: "Moulins", lat: 46.565, lng: 3.333, region: "Auvergne-Rhône-Alpes", aliases: ["moulins sur allier"] }, - { name: "Draguignan", lat: 43.537, lng: 6.467, region: "Provence-Alpes-Côte d'Azur" }, { name: "Cahors", lat: 44.448, lng: 1.435, region: "Occitanie" }, { name: "Gourdon", lat: 44.738, lng: 1.384, region: "Occitanie" }, { name: "Souillac", lat: 44.895, lng: 1.471, region: "Occitanie" }, From 016bfe5e06c805ca28ff44f34813e9b7dfc1edd3 Mon Sep 17 00:00:00 2001 From: davd-gzl <60177543+davd-gzl@users.noreply.github.com> Date: Wed, 30 Sep 2026 20:22:39 +0900 Subject: [PATCH 3/4] =?UTF-8?q?Map:=20keep=20Calais=20Ville=20at=20the=20t?= =?UTF-8?q?own=20now=20Calais-Fr=C3=A9thun=20claims=20the=20calais=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/data/cities.ts | 1 + tests/stations.test.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/data/cities.ts b/src/data/cities.ts index 83a179a..21ad4d2 100644 --- a/src/data/cities.ts +++ b/src/data/cities.ts @@ -24,6 +24,7 @@ export const CITY_REFERENCE: CityRef[] = [ { name: "Douai", lat: 50.38, lng: 3.083, region: "Hauts-de-France" }, { name: "Valenciennes", lat: 50.358, lng: 3.516, region: "Hauts-de-France" }, { name: "Dunkerque", lat: 51.035, lng: 2.371, region: "Hauts-de-France" }, + { name: "Calais", lat: 50.951, lng: 1.857, region: "Hauts-de-France", aliases: ["calais ville"] }, { name: "Béthune", lat: 50.53, lng: 2.641, region: "Hauts-de-France" }, { name: "Lens", lat: 50.432, lng: 2.831, region: "Hauts-de-France" }, { name: "Saint-Quentin", lat: 49.848, lng: 3.287, region: "Hauts-de-France" }, diff --git a/tests/stations.test.ts b/tests/stations.test.ts index f02e5f9..c65d582 100644 --- a/tests/stations.test.ts +++ b/tests/stations.test.ts @@ -82,10 +82,11 @@ describe("StationRegistry.addMissing", () => { it("plots an out-of-town station at the station, not at its city centre", () => { const r = new StationRegistry(stationData as Station[]); - r.addMissing(["LYON ST EXUPERY TGV.", "LYON (intramuros)", "VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE"]); + r.addMissing(["LYON ST EXUPERY TGV.", "LYON (intramuros)", "VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE", "CALAIS FRETHUN", "CALAIS VILLE"]); const km = (a: string, b: string): number => haversineKm(r.coords(a)!, r.coords(b)!); expect(km("LYON ST EXUPERY TGV.", "LYON (intramuros)")).toBeGreaterThan(15); expect(km("VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE")).toBeGreaterThan(8); + expect(km("CALAIS FRETHUN", "CALAIS VILLE")).toBeGreaterThan(5); expect(r.city("LYON ST EXUPERY TGV.")).toBe("Lyon"); // guide link still opens the city }); From 1cad31c49e3eaa4515adffc100e14bf7495d80b7 Mon Sep 17 00:00:00 2001 From: davd-gzl <60177543+davd-gzl@users.noreply.github.com> Date: Wed, 30 Sep 2026 20:30:11 +0900 Subject: [PATCH 4/4] Map: St-Pierre-des-Corps, Marseille Blancarde and Les Aubrais sit at their own station --- data/stations.json | 7 +++++-- public/data/stations.json | 7 +++++-- src/data/cities.ts | 1 - tests/stations.test.ts | 6 +++++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/data/stations.json b/data/stations.json index 5eb3513..7c28a8f 100644 --- a/data/stations.json +++ b/data/stations.json @@ -19,7 +19,7 @@ { "id": "TOULON", "label": "Toulon", "city": "Toulon", "lat": 43.1283, "lng": 5.9300, "region": "Provence-Alpes-Côte d'Azur" }, { "id": "ANGERS SAINT LAUD", "label": "Angers St-Laud", "city": "Angers", "lat": 47.4647, "lng": -0.5566, "region": "Pays de la Loire", "aliases": ["angers"] }, { "id": "LE MANS", "label": "Le Mans", "city": "Le Mans", "lat": 47.9957, "lng": 0.1929, "region": "Pays de la Loire" }, - { "id": "TOURS", "label": "Tours", "city": "Tours", "lat": 47.3900, "lng": 0.6940, "region": "Centre-Val de Loire", "aliases": ["saint pierre des corps"] }, + { "id": "TOURS", "label": "Tours", "city": "Tours", "lat": 47.3900, "lng": 0.6940, "region": "Centre-Val de Loire" }, { "id": "POITIERS", "label": "Poitiers", "city": "Poitiers", "lat": 46.5802, "lng": 0.3338, "region": "Nouvelle-Aquitaine" }, { "id": "ANGOULEME", "label": "Angoulême", "city": "Angoulême", "lat": 45.6519, "lng": 0.1640, "region": "Nouvelle-Aquitaine" }, { "id": "LA ROCHELLE VILLE", "label": "La Rochelle", "city": "La Rochelle", "lat": 46.1530, "lng": -1.1455, "region": "Nouvelle-Aquitaine", "aliases": ["la rochelle"] }, @@ -52,5 +52,8 @@ { "id": "MONTPELLIER SUD DE FRANCE", "label": "Montpellier Sud-de-France", "city": "Montpellier", "lat": 43.5948, "lng": 3.9246, "region": "Occitanie" }, { "id": "BESANCON FRANCHE COMTE TGV", "label": "Besançon Franche-Comté TGV", "city": "Besançon", "lat": 47.3074, "lng": 5.9532, "region": "Bourgogne-Franche-Comté" }, { "id": "MACON LOCHE TGV", "label": "Mâcon-Loché TGV", "city": "Mâcon", "lat": 46.2829, "lng": 4.7789, "region": "Bourgogne-Franche-Comté" }, - { "id": "CALAIS FRETHUN", "label": "Calais-Fréthun", "city": "Calais", "lat": 50.9012, "lng": 1.8109, "region": "Hauts-de-France" } + { "id": "CALAIS FRETHUN", "label": "Calais-Fréthun", "city": "Calais", "lat": 50.9012, "lng": 1.8109, "region": "Hauts-de-France" }, + { "id": "ST PIERRE DES CORPS", "label": "St-Pierre-des-Corps", "city": "Tours", "lat": 47.3861, "lng": 0.7236, "region": "Centre-Val de Loire", "aliases": ["saint pierre des corps"] }, + { "id": "MARSEILLE BLANCARDE", "label": "Marseille Blancarde", "city": "Marseille", "lat": 43.2961, "lng": 5.4066, "region": "Provence-Alpes-Côte d'Azur" }, + { "id": "LES AUBRAIS ORLEANS", "label": "Les Aubrais-Orléans", "city": "Orléans", "lat": 47.9268, "lng": 1.9066, "region": "Centre-Val de Loire" } ] diff --git a/public/data/stations.json b/public/data/stations.json index 5eb3513..7c28a8f 100644 --- a/public/data/stations.json +++ b/public/data/stations.json @@ -19,7 +19,7 @@ { "id": "TOULON", "label": "Toulon", "city": "Toulon", "lat": 43.1283, "lng": 5.9300, "region": "Provence-Alpes-Côte d'Azur" }, { "id": "ANGERS SAINT LAUD", "label": "Angers St-Laud", "city": "Angers", "lat": 47.4647, "lng": -0.5566, "region": "Pays de la Loire", "aliases": ["angers"] }, { "id": "LE MANS", "label": "Le Mans", "city": "Le Mans", "lat": 47.9957, "lng": 0.1929, "region": "Pays de la Loire" }, - { "id": "TOURS", "label": "Tours", "city": "Tours", "lat": 47.3900, "lng": 0.6940, "region": "Centre-Val de Loire", "aliases": ["saint pierre des corps"] }, + { "id": "TOURS", "label": "Tours", "city": "Tours", "lat": 47.3900, "lng": 0.6940, "region": "Centre-Val de Loire" }, { "id": "POITIERS", "label": "Poitiers", "city": "Poitiers", "lat": 46.5802, "lng": 0.3338, "region": "Nouvelle-Aquitaine" }, { "id": "ANGOULEME", "label": "Angoulême", "city": "Angoulême", "lat": 45.6519, "lng": 0.1640, "region": "Nouvelle-Aquitaine" }, { "id": "LA ROCHELLE VILLE", "label": "La Rochelle", "city": "La Rochelle", "lat": 46.1530, "lng": -1.1455, "region": "Nouvelle-Aquitaine", "aliases": ["la rochelle"] }, @@ -52,5 +52,8 @@ { "id": "MONTPELLIER SUD DE FRANCE", "label": "Montpellier Sud-de-France", "city": "Montpellier", "lat": 43.5948, "lng": 3.9246, "region": "Occitanie" }, { "id": "BESANCON FRANCHE COMTE TGV", "label": "Besançon Franche-Comté TGV", "city": "Besançon", "lat": 47.3074, "lng": 5.9532, "region": "Bourgogne-Franche-Comté" }, { "id": "MACON LOCHE TGV", "label": "Mâcon-Loché TGV", "city": "Mâcon", "lat": 46.2829, "lng": 4.7789, "region": "Bourgogne-Franche-Comté" }, - { "id": "CALAIS FRETHUN", "label": "Calais-Fréthun", "city": "Calais", "lat": 50.9012, "lng": 1.8109, "region": "Hauts-de-France" } + { "id": "CALAIS FRETHUN", "label": "Calais-Fréthun", "city": "Calais", "lat": 50.9012, "lng": 1.8109, "region": "Hauts-de-France" }, + { "id": "ST PIERRE DES CORPS", "label": "St-Pierre-des-Corps", "city": "Tours", "lat": 47.3861, "lng": 0.7236, "region": "Centre-Val de Loire", "aliases": ["saint pierre des corps"] }, + { "id": "MARSEILLE BLANCARDE", "label": "Marseille Blancarde", "city": "Marseille", "lat": 43.2961, "lng": 5.4066, "region": "Provence-Alpes-Côte d'Azur" }, + { "id": "LES AUBRAIS ORLEANS", "label": "Les Aubrais-Orléans", "city": "Orléans", "lat": 47.9268, "lng": 1.9066, "region": "Centre-Val de Loire" } ] diff --git a/src/data/cities.ts b/src/data/cities.ts index 21ad4d2..53c1832 100644 --- a/src/data/cities.ts +++ b/src/data/cities.ts @@ -130,7 +130,6 @@ export const CITY_REFERENCE: CityRef[] = [ { name: "Redon", lat: 47.651, lng: -2.085, region: "Bretagne" }, { name: "Auray", lat: 47.668, lng: -2.985, region: "Bretagne" }, // --- Centre-Val de Loire --------------------------------------------------- - { name: "Orléans", lat: 47.902, lng: 1.905, region: "Centre-Val de Loire" }, { name: "Blois", lat: 47.587, lng: 1.333, region: "Centre-Val de Loire", aliases: ["blois chambord"] }, { name: "Bourges", lat: 47.084, lng: 2.396, region: "Centre-Val de Loire" }, { name: "Châteauroux", lat: 46.811, lng: 1.69, region: "Centre-Val de Loire" }, diff --git a/tests/stations.test.ts b/tests/stations.test.ts index c65d582..5331956 100644 --- a/tests/stations.test.ts +++ b/tests/stations.test.ts @@ -82,12 +82,16 @@ describe("StationRegistry.addMissing", () => { it("plots an out-of-town station at the station, not at its city centre", () => { const r = new StationRegistry(stationData as Station[]); - r.addMissing(["LYON ST EXUPERY TGV.", "LYON (intramuros)", "VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE", "CALAIS FRETHUN", "CALAIS VILLE"]); + r.addMissing(["LYON ST EXUPERY TGV.", "LYON (intramuros)", "VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE", "CALAIS FRETHUN", "CALAIS VILLE", "TOURS", "ST PIERRE DES CORPS", "MARSEILLE ST CHARLES", "MARSEILLE BLANCARDE", "LES AUBRAIS ORLEANS"]); const km = (a: string, b: string): number => haversineKm(r.coords(a)!, r.coords(b)!); expect(km("LYON ST EXUPERY TGV.", "LYON (intramuros)")).toBeGreaterThan(15); expect(km("VALENCE TGV AUVERGNE RHONE ALPES", "VALENCE VILLE")).toBeGreaterThan(8); expect(km("CALAIS FRETHUN", "CALAIS VILLE")).toBeGreaterThan(5); + // Two stations of one town on one point hide each other from the nearby search. + expect(km("TOURS", "ST PIERRE DES CORPS")).toBeGreaterThan(2); + expect(km("MARSEILLE ST CHARLES", "MARSEILLE BLANCARDE")).toBeGreaterThan(2); expect(r.city("LYON ST EXUPERY TGV.")).toBe("Lyon"); // guide link still opens the city + expect(r.city("LES AUBRAIS ORLEANS")).toBe("Orléans"); }); it("dedupes label collisions, preferring the id present in the dataset", () => {