English · Magyar
Fejlesztési napló
Az egész brit vasúthálózat egy térképen – a rég bezárt állomásokkal együtt
Vanilla JavaScriptes térkép Nagy-Britannia minden vasútvonaláról és állomásáról, elejétől a végéig nyílt adatokból. Elmesélem, hogyan állt össze, milyen adatbukfencek voltak mögötte, és mi vitte előre az egészet.
Vanilla JavaScriptes térkép Nagy-Britannia minden vasútvonaláról és állomásáról, elejétől a végéig nyílt adatokból. Elmesélem, hogyan állt össze, milyen adatbukfencek voltak mögötte, és mi vitte előre az egészet.
Egyetlen térképet szerettem volna, amin ott van a teljes brit vasúthálózat. Nem annyi, amennyit egy útvonaltervező megmutat, hanem minden: a nosztalgiavasutak, a csak tehervonatok járta összekötő vágányok, a névvel bíró alagutak és viaduktok, és az a több ezer állomás is, amelyik valamikor létezett, ma viszont már nem. (Nagyjából az az érzés, mint amikor itthon próbálod kideríteni, merre futott egy réges-rég felszedett mellékvonal – csak brit léptékben.) Ilyen térképet nem találtam, úgyhogy megcsináltam: trainmap.co.uk. Nincs hozzá app, nincs regisztráció, nincs fiók. Gyorsan betölt, és kereshetsz benne irányítószámra, állomásnévre, hárombetűs állomáskódra vagy vonalnévre.
Egy ilyen projektben a kód a kisebbik fele. Az izgalmas rész az, hogy mi minden derül ki az adatokból, ha egyszer láthatóvá teszed őket, kik használják a végén, és hányféleképpen tud a valós vasúti adat csendben ellentmondani önmagának. Ami viszont tényleg jóvá tette a térképet, az a használókkal kialakult visszajelzési kör volt: korán megmutattam, és hagytam, hogy azok mondják meg, mi a hibás, akik a legjobban ismerik a vasutat. Erről a végén részletesen is írok.
Ki mit tett hozzá
Színkóddal jelöltem meg a cikket, hogy látszódjon a valóság: melyik döntés mögött álltam én, melyik mögött az AI-ágens segítsége, és melyik mögött a közösség.
A jelölés végig ugyanaz:
- az irány, a hatókör, a mérlegelés, a technológiai döntések és a kód szerkezete.
- Ami a közösségé: hibajelzések, javítások és kérések egy vasútrajongó fórumról.
- Ami az AI-é: a feldolgozási lánc kódjának megírása az én utasításaim alapján, AI-s kódsegéddel.
Az adatprobléma
Minden vonal és állomás az OpenStreetMapről származik, az Overpass API-n keresztül lekérve. Az OSM brit vasúti lefedettsége kiváló – sokkal jobb, mint azt bárki gondolná –, mert olyan emberek gondozzák, akiknek tényleg fontos egy-egy iparvágány sorsa.
Csakhogy már az is csapda, hogy a lekérdezést „az Egyesült Királyságra” szűkítsd. Egy Nagy-Britannia köré húzott téglalapba beleesik Dublin, a Man-sziget és Észak-Franciaország aggasztóan nagy része is. ; a megoldás pedig az lett, hogy az ágens közvetlenül a GB közigazgatási határt (ISO3166-1=GB) kérte le az Overpasstől, és arra vágott. Így benne marad Észak-Írország – hiszen egyesült királyságbeli térképről van szó –, de kimarad az Ír Köztársaság, a Man-sziget és Calais, méghozzá kézzel belőtt szélességi fokok nélkül, amik amúgy is elromlanának abban a pillanatban, ahogy valaki felvisz egy új vonalat a határ közelében.
A vonalakat csempénként szedem le az Overpassról: egy durva, nagyjából harminccellás rács fedi Nagy-Britanniát, és minden cella csak a GB-határon belüli vasúti way-eket (vonalelemeket) kéri, mert egyetlen országos lekérdezés egész egyszerűen időtúllépéssel elhalna. A letöltés folytatható: a már lementett, érvényes cellákat átugorja, így egy félúton megszakadt futás csak a hiányzó darabokat pótolja. Utána egy feldolgozó lépés OSM-azonosító alapján kidobja a duplikált way-eket (a cellák a széleiken átfednek), a railway címke alapján három csoportba sorolja őket (nagyvasút, könnyűvasút, felhagyott vonal), minden koordinátát öt tizedesjegyre kerekít – ez nagyjából egy méter, vagyis komoly méretcsökkenés látható veszteség nélkül –, végül kiírja azt a GeoJSON-t, amit a térkép betölt, plusz egy kis „vonalnév → befoglaló keret” indexet, hogy vonalnévre is lehessen keresni. Az egészet néhány száz sor Python intézi.
Az állomások, amelyek füllentettek
A NaPTAN-nal kezdtem, ez a brit tömegközlekedési megállók hivatalos adatbázisa. A nagyvasúthoz remek, egy furcsasága viszont van: rengeteg nosztalgiavasúti állomást villamos vagy metró kategóriába sorol. Amikor tehát „vasútállomásokra” szűrtem, egész nosztalgiavonalak ürültek ki félig – pontosan erre célzott az a fórumtag is, aki szóvá tette, hogy a Swanage Railwaynek mindössze egyetlen állomása maradt a térképen.
Az állomások így átkerültek az OSM-re, ami viszont új gondot hozott: az OSM állomáscímkézése következetlen, vagyis . A szabályokat aztán az ágens dolgozta ki:
- Maradjanak a National Rail–metró átszállóállomások, vagyis azok, amelyek
networkcímkéjében szerepel a „National Rail” (Amersham, Harrow-on-the-Hill). A tisztán metró-, DLR- és villamosmegállók kiesnek. (Ez a lista majdnem szó szerint egy olyan fórumtagtól érkezett, aki maga vezet ezeken a vonalakon, és szépen felsorolta az összes hiányzó Chiltern-állomást.) - Maradjon minden, ami keskeny nyomtávú nosztalgiavonalon fekszik, közelség alapján kiszűrve – így marad meg a New Romney állomás a Romney, Hythe & Dymchurch vonalon akkor is, ha az OSM félig kisvasútként címkézi.
És persze a kézenfekvő szűrő, a hárombetűs ref:crs kód pont itt volt használhatatlan: a londoni metró állomásai ugyanabban a mezőben viselik a TfL „Z” kezdetű kódjait.
Nosztalgiavasutak és a Swanage-ügy
A megőrzött, nosztalgiavonalak külön színt kapnak a térképen. Az OSM-ben a railway:preserved vagy a usage=tourism címke jelöli őket – megint csak nem következetesen. A Swanage Railway üzemelő vágánya például helyenként egyszerű szárnyvonalként szerepel, így először sima National Rail vonalként jelent meg, egészen addig, míg valaki a fórumon finoman meg nem jegyezte, hogy a swanage-i szárnyvonalat nosztalgiából National Raillé léptettem elő.
A javítás egy kis heurisztika lett, ami úgy gondolkodik, ahogy egy ember olvassa a térképet: . Ha a „Swanage Railway” bármelyik darabja megőrzöttként van felvéve, az egész névvel bíró vonal lila lesz. Durva megoldás, de sokkal többször talál, mint ha szakaszonként bíznánk a címkékben.
Ez a visszatérő motívum: a nyílt adat ritkán hibás, viszont gyakran következetlen. A munka java része apró, jól olvasható szabályok írása, amelyek úgy oldják fel az ellentmondást, ahogy egy ember tenné.
Vonalak, amelyek kicsinyítéskor kiegyenesedtek
Apró hiba, de jó példa a felhasználókkal folytatott oda-vissza beszélgetésre. Egy fórumtag jelezte, hogy a Northallerton környéki pálya „töröttnek” látszik: a finom ívek bizonyos nagyítási szinteken egyenes húrokká váltak. A saját gépét már ki is zárta a gyanúsítottak közül, hat böngészőben végigpróbálva. A leírása – az északi végén ránagyítva helyreáll, kicsinyítve újra eltörik, a déli csomópont pedig egyáltalán nem áll helyre – elég volt a behatároláshoz.
Az ok az, hogy a MapLibre alapból nagyítási szintenként egyszerűsíti a GeoJSON-geometriát (Douglas–Peucker-módszerrel), hogy a nagy vektorrétegek olcsók maradjanak. A legtöbb adatnál ez teljesen ésszerű. Egy vasúti térképnél viszont épp fordítva áll a dolog: a pálya pontos alakja maga a lényeg. Az egész javítás egyetlen tulajdonság a forráson: tolerance: 0. Az ívek azóta minden nagításon hűek maradnak. A hibát jelző felhasználó vissza is igazolta, hogy ezzel az ő esete és egy másik, Low Fell közelében észrevett hiba is megoldódott. A javítás egy sor volt – a megtalálásához vezető beszélgetés viszont ennél sokkal többet ért.
Egy hiba helyén nő a következő
Ez a tolerance: 0 szép példa arra, hogyan készíti elő az egyik javítás csendben a másikat. Az egyszerűsítés kikapcsolása minden csúcspontot megtart minden nagításon – pontosság szempontjából pont ezt akarod, memória szempontjából pont ezt nem. Az egész hálózat nagyjából 28 MB GeoJSON, durván 720 000 csúcsponttal, és mindez egyszerre volt a memóriában. Laptopon rendben is van. Egy középkategóriás telefonon viszont a böngészőfül egyszerűen összeomlott, főleg ha bekapcsoltál mellé még egy nehéz réteget.
A geometriában gazdag nagyvasúti hálózatot átállítottam : így a geometria már build időben, nagyítási szintenként csempékre van vágva, a böngésző pedig HTTP range-kérésekkel csak az éppen képernyőn lévő néhány csempét szedi le. A memóriaigény innentől a látómezőt követi, nem az egész országot. Egyetlen statikus fájl, ugyanazon a tárhelyen, csempeszerver nélkül – a csempézést végző tippecanoe pedig rendesen, nagyítási szintenként végzi az egyszerűsítést, úgyhogy a vonalak mindenhol hűek maradnak, és a húrra ugró hiba sem tér vissza.
A GeoJSON megmaradt tartalékként, de innentől a csempék az alapértelmezettek. Ez az a fajta változtatás, amit észre sem veszel – egészen addig, míg egyszer csak össze nem omlik a kezed alatt.
Állomások, amelyek már nincsenek
Ez a kedvenc részem. Egy barátom szólt, hogy a wiltshire-i Box állomás hiányzik. Igaza volt: Box 1965-ben bezárt, és egész egyszerűen nincs benne az OpenStreetMapben – sem működőként, sem felhagyottként.
Honnan szerzel akkor évtizedekkel ezelőtt megszűnt állomásokat? A Wikidatából (CC0). A bökkenő az, hogy a bezárási adatai hiányosak. Box Wikidata-tételében egyáltalán nincs bezárási dátum – a mező üresen áll, ahogy sok más megszűnt állomásnál is –, miközben a Wikipédia-szócikke készségesen elárulja, hogy 1965. január 4-én zárt be. (A Wikidata azért megjelöli egy homályos „decommissioned”, vagyis üzemen kívül helyezett státusszal, csak épp dátum nélkül.) Vagyis ha a „van bezárási dátuma” szűrőre hagyatkoznánk, pont azokat az állomásokat hagynánk ki, amiket keresünk.
A bevált megközelítés végül . Lekérdeztem az összes egyesült királyságbeli vasútállomást, amiről a Wikidata tud – nagyjából 9600-at –, majd kivettem belőle azokat, amelyek még léteznek, vagyis egy mai OpenStreetMap-állomás 250 méteres körzetébe esnek. Ami marad, valamivel több mint 6100 állomás, épp az a halmaz, ami valaha létezett, ma viszont már nem. Box is köztük van. Ez most külön bekapcsolható réteg, üres körökkel rajzolva; bármelyikre kattintva eljutsz a Wikipédia-szócikkéhez.
(Lábjegyzet az érdeklődőknek: a Wikidata-lekérdezéseket a QLever tükrén futtattam, mert a hivatalos végpont túl szigorúan van sebességkorlátozva.)
Az összefűzés a nehéz
Kicsit hátrébb lépve: a feldolgozási lánc valójában néhány adathalmaz összefűzése, a bökkenő pedig az, hogy egyiknek sincs közös azonosítója a másikkal. Az OpenStreetMap adja a geometriát és a működő állomásokat, de következetlenül címkéz, és a bezárt állomásokról semmit sem tud. A bezártak a Wikidatából jönnek, gyakran – ahogy láttuk – bezárási dátum nélkül. Az irányítószámos kereséshez a postcodes.io szolgáltat adatot (a háttérben ONS-adatokból). A NaPTAN, a hivatalos megállónyilvántartás volt az állomások kiindulópontja, egészen addig, míg ki nem derült, hogy túl sok nosztalgiaállomást sorol villamos és metró alá. Mindegyik forrás valamiben mérvadó, másban pedig használhatatlan.
Mivel nincs közös kulcs az összefűzéshez, a szkriptben szinte minden érdemi döntés földrajz vagy név alapján születik:
- Egy OSM-„metróállomás” valójában National Rail átszálló? Nézd meg a
networkcímkéjét – így kerül vissza Amersham és Harrow-on-the-Hill. - Egy állomás keskeny nyomtávú nosztalgiavonalon fekszik, hiába kisvasútként van címkézve? Erre nincs címke, úgyhogy azt vizsgáljuk, hogy egy
narrow_gaugevonal nagyjából száz méteres körzetében van-e – így marad meg New Romney. - Egy egész vonal nosztalgiavonal? Terjeszd ki a
railway:preserved/usage=tourismjelölést minden azonos nevű szakaszra – ez a Swanage-javítás. - Egy wikidatás állomás még üzemel, vagy rég megszűnt? Kivonás: ha egy mai OSM-állomás 250 méteres körzetében van, mainak számít, egyébként a nagyjából 6100 bezárt egyike.
Ezek közül néhány – valljuk be – inkább következtetés, mint tény: a nosztalgiaszín és a „korábbi állomás” címke származtatott, egyik forrás sem mondja ki közvetlenül. Kitalálva semmi nincs, minden pozíció és név visszavezethető az OpenStreetMapre, a Wikidatára vagy az ONS-re, de ezek heurisztikák – egy heurisztika pedig pontosan annyit ér, amennyit teszteled.
Valójában ezért számított annyit a fórum. A szabályokat meg tudtam írni, de nem volt megbízható módszerem eldönteni, hogy jók-e: hogy a Swanage-terjesztés minden szakaszt elkap-e, hogy a keskeny nyomtávú teszt nem túl szigorú-e, hogy egy ardwicki „covered” címke valóban alagútnak számít-e. Az ottaniak viszont tudták. Minden hibajelzés gyakorlatilag egy bukott teszteset volt a feldolgozási láncra, olyanoktól, akik nálam sokkal jobban ismerték a terepet. Az adatok csak azért állnak jól össze, mert , ők pedig megmondták, mi a hibás és min lehetne javítani.
Apróságok, amiktől kész lett
- , állomásnevet, hárombetűs kódot (
PAD,YRK) – ez utóbbinál úgy nagyít, hogy a teljes útvonal ráférjen. - Névvel bíró műtárgyak. A fontosabb alagutak és viaduktok feliratozása az OSM
tunnel:nameésbridge:namecímkéiből készül: Severn-alagút, Ribblehead-viadukt és a többi. (Ez konkrét kérés volt: „a hab a tortán az lenne, ha a nagyobb alagutak és viaduktok nevet kapnának”.) - Kattints egy állomásra – mindegy, hogy ma is működik vagy rég bezárt –, és kapsz egy gombot a Wikipédia-szócikkéhez, meg egy másikat a Google Maps-beli helyéhez. A mai állomások nagyjából 92, a korábbiak 99 százalékához tartozik Wikipédia-oldal, jó részükhöz egyenesen az OSM
wikipediacímkéiből.
Hogy meg is mozduljon
A térkép hónapokig állókép volt az infrastruktúráról. A kézenfekvő kérdést szinte mindenki feltette, akinek megmutattam: jó, jó, de hol vannak a vonatok most? Én arra a régi vágású adatfolyamra készültem, amiről mindenhol írnak – egy 2005-ös protokollt beszélő üzenetsorra, gzippelt XML-lel –, ehelyett modern Kafka-streamet kaptam, JSON-nal, ami este tizenegykor percenként nagyjából 1300 üzenetet szállított. A fogyasztó, a vonatonkénti állapotkövetés és az a motor, ami az „ekkor haladt át ezen a menetrendi ponton” jelentésekből a megfelelő vágányszakaszon mozgó pöttyöt csinál, még aznap este megépült és futott.
Aztán jött az ismerős probléma: újabb adathalmaz, újabb azonosítóval, amit rajta kívül senki nem használ. A Darwin TIPLOC-kal (timing point location) nevezi meg a helyeket, a térképen viszont semmi nem beszél TIPLOC-ul. A megoldás váratlan irányból érkezett: a NaPTAN – az a megállónyilvántartás, amit az állomások miatt korábban lecseréltem, mert kisvasutakat tartott nyilván villamosként – minden vasúti megálló azonosítójába belekódolja a TIPLOC-ot: a kód szó szerint a 9100 előtag, utána a TIPLOC. Az adathalmaz, ami a nosztalgiavasutakról füllentett, keresőtáblaként törlesztette az adósságát: 2700 menetrendi pont került a helyére.
Maguk a pozíciók származtatottak, nem mértek. A vonatok nem sugároznak GPS-t; a Darwin azt jelenti, hogy egy vonat mikor érkezett meg, mikor indult el, vagy mikorra várható az egyes megállási pontokon. Az a gráf, amit korábban egy „ki lehet-e számolni az útvonalat két állomás között?” kísérlethez építettem, hirtelen maga lett a termelési motor: minden vonatot a legutóbbi és a következő megállási pontja közé teszünk, az eltelt idő arányában, a valódi vágányon. Egy kis munkafolyamat egy meglévő szerveren fogyasztja a streamet, és tizenöt másodpercenként kiír egyetlen statikus fájlt. Az oldal marad az, ami mindig is volt – fájlok egy polcon –, a térkép pedig egyszerűen azt az egy fájlt kérdezgeti, amelyik változik.
Legalább ennyit számított, hogy jól is nézzen ki. Egy pötty, ami tizenöt másodpercenként odébb teleportál, hibásnak hat, ezért minden vonat magával hozza a saját útvonalának következő kilométerét is, a böngésző pedig e mentén csúsztatja a frissítések között: a vonatok követik a kanyarokat, és a haladási irányukba néznek. Ahol az adatfolyam jelenti a szerelvény összeállítását, ott a kocsik pöttysorként húzódnak a nyíl mögött – egy nyolckocsis expressz láthatóan kígyózik a kanyarban, míg egy kétkocsis személyvonat kurta marad. A „semmit nem találunk ki” szabály a szépség kedvéért sem hajlik meg.
Aztán kitettem egy vasutas subredditre, és az a kör, ami a térkép többi részét felépítette, kétszeres sebességgel indult újra. Egy napon belül kiderült, hogy a felugró panelen látható kód a Darwin belső menetrend-azonosítója, nem vonatszám („mi az az L78543?”); hogy a „következő megálló” néha olyan állomás, amin a vonat 145-tel átrobog; hogy egy útközben lévő vonat csak az útvonala addig látott szakaszát mutatja; hogy a vonatok láthatatlanul ülnek a kiindulási állomásukon; és hogy egy Moorgate felé tartó vonat a bejelentés szerint „felfelé tolatott a Canonbury-íven, pedig a közelében sem járt”. Mindegyik órákon belül javítva lett, . Ugyanennek köszönhető a felugróban a Wikipédiára mutató „Class 802” járműtípus is.
Az a Network Rail saját nyílt adatfolyamaiban él: a TRUST nevű rendszer mozgásjelentéseiben és az országos menetrendben, ami minden tehervonati menetet tartalmaz. Egy második fogyasztó ezeket a jelentéseket illeszti a napi tehervonati menetrendekhez, és ugyanarra a térképre teszi a konténervonatokat, a kőszállítókat és a gépmeneteket – tompább, sötét szegélyű rajzolattal, .
A legvasutasabb fejlesztés maradt utoljára. A hozzászólók folyton a train describer adatfolyamot emlegették – a biztosítóberendezés saját nyilvántartását arról, ahogy a vonatok szakaszról szakaszra lépnek –, joggal figyelmeztetve, hogy a több tízezer szakasz valódi helyekhez kötése „óriási meló”. Már többnyire nem az: a Network Rail közzéteszi azt a referenciaadatot, ami a szakaszlépéseket menetrendi pontokhoz köti, és egy délelőttnyi csővezeték-építés az élő biztosítóberendezési események harmadát kemény pozíciófixszé alakította. Ahol ez a lefedettség megvan, ott a vonatok nem oda kerülnek, ahol a menetrend szerint lenniük kellene, hanem oda, ahol a jelzők utoljára látták őket – a felugró pedig mért sebességet mutat („~200 km/h”),
A térkép továbbra is őszintén megmondja, hol becsül – de nézni, ahogy egy késésben lévő, borostyánsárga vonat kifűzi magát egy pályaudvarról a zöldek között, olyan sebességgel, amiért a jelzők kezeskednek, olyan vágányon, amiről tudod, hogy valódi… Ettől érződik elevenebbnek, mint valaha.
Amitől tényleg jó lett
, mindenféle hátsó szándék nélkül, csak hogy lássam, tetszik-e bárkinek. Aztán a következő pár napot azzal töltöttem, hogy javításokat adtam ki, amíg a téma élt. Nem volt terv és nem volt ütemterv; az ütemterv az volt, amit utoljára észrevett valaki, és a legtöbb változás órákon belül élesbe került.
Ebben semmi újdonság nincs. Ez a szoftverfejlesztés legrégebbi gondolata, ugyanaz, amit az Agilis kiáltvány is lefektetett, még mielőtt az „agilis” értekezletekkel teli naptárt kezdett volna jelenteni: . A folyamatok ezt könnyen elnyelik. Egy fórumtéma, tele olyanokkal, akiknek tényleg fontos a téma, egyszerűen visszaadta nekem. Ez az a része a projektnek, amit a leginkább ajánlanék másolásra, bármit is építs éppen.
A trainmap.co.uk ingyenes és reklámmentes.
Ha hasznosnak találod, fontold meg: