From ee4230b034920c779e3c1683aea32f12ed2f0e6f Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 00:31:27 +0800 Subject: [PATCH 01/20] feat: add canonical station exit layouts --- data/station/ADM.json | 49 +++++++++++ data/station/ALJ.json | 28 ++++++ data/station/AMK.json | 55 ++++++++++++ data/station/BAK.json | 27 +++++- data/station/BBS.json | 49 +++++++++++ data/station/BBT.json | 40 +++++++++ data/station/BCL.json | 33 +++++++ data/station/BDK.json | 43 +++++++++ data/station/BDL.json | 40 +++++++++ data/station/BDM.json | 27 ++++++ data/station/BDN.json | 37 ++++++++ data/station/BDR.json | 27 ++++++ data/station/BFT.json | 56 ++++++++++++ data/station/BGB.json | 37 ++++++++ data/station/BGK.json | 27 ++++++ data/station/BGS.json | 52 +++++++++++ data/station/BLY.json | 31 +++++++ data/station/BNK.json | 35 ++++++++ data/station/BNL.json | 49 +++++++++++ data/station/BNV.json | 40 +++++++++ data/station/BRH.json | 43 +++++++++ data/station/BSH.json | 49 +++++++++++ data/station/BSR.json | 52 +++++++++++ data/station/BTN.json | 26 ++++++ data/station/BTW.json | 37 ++++++++ data/station/CBR.json | 43 +++++++++ data/station/CCK.json | 37 ++++++++ data/station/CDT.json | 51 ++++++++++- data/station/CGL.json | 21 ++++- data/station/CLE.json | 55 ++++++++++++ data/station/CNG.json | 40 +++++++++ data/station/COM.json | 55 ++++++++++++ data/station/COV.json | 21 ++++- data/station/CPV.json | 27 +++++- data/station/CRE.json | 21 ++++- data/station/CRQ.json | 50 +++++++++++ data/station/CSW.json | 17 ++++ data/station/CTH.json | 37 ++++++++ data/station/CTN.json | 51 +++++++++++ data/station/DAM.json | 21 ++++- data/station/DBG.json | 52 +++++++++++ data/station/DKT.json | 31 +++++++ data/station/DTN.json | 50 +++++++++++ data/station/DVR.json | 31 +++++++ data/station/EPN.json | 58 +++++++++++++ data/station/EUN.json | 31 +++++++ data/station/FCN.json | 27 ++++++ data/station/FMW.json | 27 +++++- data/station/FNV.json | 21 ++++- data/station/FRP.json | 67 ++++++++++++++ data/station/FRR.json | 31 +++++++ data/station/GCL.json | 25 ++++++ data/station/GLB.json | 27 ++++++ data/station/GRB.json | 34 ++++++++ data/station/GRW.json | 58 +++++++++++++ data/station/HBF.json | 49 +++++++++++ data/station/HGN.json | 32 +++++++ data/station/HLV.json | 31 +++++++ data/station/HME.json | 19 ++++ data/station/HPV.json | 19 ++++ data/station/HVL.json | 52 +++++++++++ data/station/HVW.json | 27 ++++++ data/station/JKN.json | 31 +++++++ data/station/JLB.json | 27 ++++++ data/station/JUR.json | 43 +++++++++ data/station/KAL.json | 28 ++++++ data/station/KAP.json | 27 ++++++ data/station/KDL.json | 21 ++++- data/station/KEM.json | 31 +++++++ data/station/KGK.json | 27 +++++- data/station/KKB.json | 27 ++++++ data/station/KPG.json | 29 ++++++- data/station/KRG.json | 40 +++++++++ data/station/KRJ.json | 40 +++++++++ data/station/KTB.json | 52 +++++++++++ data/station/KVN.json | 33 +++++++ data/station/LBD.json | 16 ++++ data/station/LKS.json | 31 +++++++ data/station/LRC.json | 25 ++++++ data/station/LTI.json | 59 +++++++++++++ data/station/LTR.json | 52 +++++++++++ data/station/LVR.json | 31 +++++++ data/station/LYR.json | 27 +++++- data/station/MAX.json | 34 ++++++++ data/station/MBT.json | 31 +++++++ data/station/MFL.json | 70 +++++++++++++++ data/station/MPS.json | 53 ++++++++++++ data/station/MRD.json | 21 ++++- data/station/MRM.json | 22 +++++ data/station/MSL.json | 52 +++++++++++ data/station/MSP.json | 31 +++++++ data/station/MTR.json | 27 ++++++ data/station/NBG.json | 21 ++++- data/station/NCH.json | 25 ++++++ data/station/NEW.json | 36 ++++++++ data/station/NOV.json | 31 +++++++ data/station/NPR.json | 25 ++++++ data/station/OAS.json | 21 ++++- data/station/OBV.json | 25 ++++++ data/station/ONH.json | 37 ++++++++ data/station/ORC.json | 106 +++++++++++++++++++++++ data/station/OTP.json | 67 ++++++++++++++ data/station/PGC.json | 27 ++++++ data/station/PGL.json | 43 +++++++++ data/station/PGP.json | 29 ++++++- data/station/PMN.json | 28 ++++++ data/station/PNR.json | 31 +++++++ data/station/PPJ.json | 19 ++++ data/station/PSR.json | 25 ++++++ data/station/PTP.json | 36 ++++++++ data/station/PYL.json | 52 +++++++++++ data/station/QUE.json | 37 ++++++++ data/station/RCR.json | 27 ++++++ data/station/RDH.json | 28 ++++++ data/station/RFP.json | 85 ++++++++++++++++++ data/station/RIV.json | 21 ++++- data/station/RMB.json | 27 +++++- data/station/RNG.json | 27 +++++- data/station/RNJ.json | 27 +++++- data/station/SAV.json | 27 ++++++ data/station/SBW.json | 52 +++++++++++ data/station/SDM.json | 19 ++++ data/station/SER.json | 71 +++++++++++++++ data/station/SHW.json | 52 +++++++++++ data/station/SIM.json | 19 ++++ data/station/SKG.json | 37 ++++++++ data/station/SMD.json | 29 ++++++- data/station/SMG.json | 27 +++++- data/station/SMK.json | 21 ++++- data/station/SOM.json | 37 ++++++++ data/station/SPL.json | 43 +++++++++ data/station/STK.json | 21 ++++- data/station/STV.json | 49 +++++++++++ data/station/TAM.json | 49 +++++++++++ data/station/TAP.json | 31 +++++++ data/station/TCR.json | 31 +++++++ data/station/TIB.json | 28 ++++++ data/station/TKG.json | 27 +++++- data/station/TKK.json | 27 ++++++ data/station/TKL.json | 27 +++++- data/station/TLA.json | 29 +++++++ data/station/TLB.json | 19 ++++ data/station/TLK.json | 31 +++++++ data/station/TNG.json | 21 ++++- data/station/TPE.json | 47 ++++++++++ data/station/TPG.json | 67 ++++++++++++++ data/station/TPW.json | 27 ++++++ data/station/TSG.json | 40 +++++++++ data/station/TWR.json | 31 +++++++ data/station/UBI.json | 27 ++++++ data/station/UPC.json | 47 ++++++++++ data/station/UTS.json | 67 ++++++++++++++ data/station/WDL.json | 61 +++++++++++++ data/station/WDN.json | 25 ++++++ data/station/WDS.json | 52 +++++++++++ data/station/WLH.json | 33 +++++++ data/station/XPO.json | 68 +++++++++++++++ data/station/YCK.json | 34 ++++++++ data/station/YIS.json | 61 +++++++++++++ data/station/YWT.json | 52 +++++++++++ packages/core/src/schema/Station.test.ts | 3 + packages/core/src/schema/Station.ts | 2 + packages/fs/src/index.test.ts | 35 ++++++++ packages/fs/src/validate.ts | 6 +- scripts/generate-fixtures.mjs | 3 + 165 files changed, 5919 insertions(+), 29 deletions(-) diff --git a/data/station/ADM.json b/data/station/ADM.json index 0b228b65..89492f97 100644 --- a/data/station/ADM.json +++ b/data/station/ADM.json @@ -62,5 +62,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "ADM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 7" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ADM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 7" + ], + "paidArea": false + }, + { + "id": "ADM_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 7" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ADM_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 7" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/ALJ.json b/data/station/ALJ.json index 0d9c659a..01e03169 100644 --- a/data/station/ALJ.json +++ b/data/station/ALJ.json @@ -61,5 +61,33 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "ALJ_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sims Avenue" + ], + "paidArea": false + }, + { + "id": "ALJ_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sims Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/AMK.json b/data/station/AMK.json index dc898b9f..f49b549d 100644 --- a/data/station/AMK.json +++ b/data/station/AMK.json @@ -69,5 +69,60 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "AMK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Ang Mo Kio Avenue 8" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "AMK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Ang Mo Kio Avenue 8" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "AMK_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Ang Mo Kio Avenue 8" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "AMK_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Ang Mo Kio Avenue 8" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BAK.json b/data/station/BAK.json index 4f9c5f1f..726776b6 100644 --- a/data/station/BAK.json +++ b/data/station/BAK.json @@ -24,5 +24,30 @@ "sengkang-sports-complex", "sengkang-grand-mall" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "BAK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BAK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/BBS.json b/data/station/BBS.json index 681dbc4e..3b8cd8b3 100644 --- a/data/station/BBS.json +++ b/data/station/BBS.json @@ -62,5 +62,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BBS_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BBS_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BBS_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BBS_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BBS_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BBS_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BBT.json b/data/station/BBT.json index 5dba5735..9168149a 100644 --- a/data/station/BBT.json +++ b/data/station/BBT.json @@ -61,5 +61,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BBT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "BBT_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BBT_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BBT_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BCL.json b/data/station/BCL.json index 22c8a6a9..bd6c967b 100644 --- a/data/station/BCL.json +++ b/data/station/BCL.json @@ -62,5 +62,38 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BCL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BCL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BCL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BDK.json b/data/station/BDK.json index 78b3fca1..42fbdd4c 100644 --- a/data/station/BDK.json +++ b/data/station/BDK.json @@ -62,5 +62,48 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BDK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "New Upper Changi Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BDK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "New Upper Changi Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BDK_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "New Upper Changi Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BDL.json b/data/station/BDL.json index 636f3d1b..75d64949 100644 --- a/data/station/BDL.json +++ b/data/station/BDL.json @@ -62,5 +62,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BDL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Lorong 1 Toa Payoh" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BDL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Lorong 1 Toa Payoh" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BDL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Lorong 1 Toa Payoh" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BDM.json b/data/station/BDM.json index f4dfa202..d6afbd28 100644 --- a/data/station/BDM.json +++ b/data/station/BDM.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BDM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BDM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BDN.json b/data/station/BDN.json index 56282dd7..9a124639 100644 --- a/data/station/BDN.json +++ b/data/station/BDN.json @@ -62,5 +62,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BDN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BDN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BDN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BDR.json b/data/station/BDR.json index 18702472..389fe394 100644 --- a/data/station/BDR.json +++ b/data/station/BDR.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BDR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BDR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BFT.json b/data/station/BFT.json index 007dd51f..cfe5e2b1 100644 --- a/data/station/BFT.json +++ b/data/station/BFT.json @@ -110,5 +110,61 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BFT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BFT_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BFT_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BFT_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BFT_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BGB.json b/data/station/BGB.json index 3963fc5f..bddff86a 100644 --- a/data/station/BGB.json +++ b/data/station/BGB.json @@ -62,5 +62,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BGB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BGB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BGB_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BGB_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BGK.json b/data/station/BGK.json index e49491ff..68c01069 100644 --- a/data/station/BGK.json +++ b/data/station/BGK.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BGK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BGK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BGS.json b/data/station/BGS.json index 205af782..2cf01ed5 100644 --- a/data/station/BGS.json +++ b/data/station/BGS.json @@ -106,5 +106,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BGS_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BGS_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BGS_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BGS_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BGS_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BGS_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BLY.json b/data/station/BLY.json index 256fab61..27d2a0c3 100644 --- a/data/station/BLY.json +++ b/data/station/BLY.json @@ -61,5 +61,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BLY_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Bartley Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BLY_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Bartley Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BNK.json b/data/station/BNK.json index 9899051f..c827c060 100644 --- a/data/station/BNK.json +++ b/data/station/BNK.json @@ -61,5 +61,40 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BNK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BNK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "BNK_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BNL.json b/data/station/BNL.json index c333e8da..35b8faab 100644 --- a/data/station/BNL.json +++ b/data/station/BNL.json @@ -69,5 +69,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BNL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BNL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BNL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BNL_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "BNL_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BNL_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BNV.json b/data/station/BNV.json index 82cdb021..e86ac8ab 100644 --- a/data/station/BNV.json +++ b/data/station/BNV.json @@ -103,5 +103,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BNV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BNV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "BNV_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BNV_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BRH.json b/data/station/BRH.json index a9a1858b..1030e142 100644 --- a/data/station/BRH.json +++ b/data/station/BRH.json @@ -68,5 +68,48 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BRH_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BRH_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BRH_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BRH_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BSH.json b/data/station/BSH.json index 5508eba6..1584cb5e 100644 --- a/data/station/BSH.json +++ b/data/station/BSH.json @@ -103,5 +103,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BSH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSH_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSH_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSH_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BSR.json b/data/station/BSR.json index 2874c076..4c4731a6 100644 --- a/data/station/BSR.json +++ b/data/station/BSR.json @@ -44,5 +44,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BSR_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSR_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSR_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSR_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BSR_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BTN.json b/data/station/BTN.json index 72691671..5b1b9f60 100644 --- a/data/station/BTN.json +++ b/data/station/BTN.json @@ -103,5 +103,31 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BTN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "BTN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/BTW.json b/data/station/BTW.json index 239aa88e..62e82d95 100644 --- a/data/station/BTW.json +++ b/data/station/BTW.json @@ -61,5 +61,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "BTW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BTW_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BTW_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CBR.json b/data/station/CBR.json index 89a1cd01..740bc835 100644 --- a/data/station/CBR.json +++ b/data/station/CBR.json @@ -62,5 +62,48 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CBR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CBR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CBR_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CBR_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CBR_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CCK.json b/data/station/CCK.json index bb5fa488..be55fa6a 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -110,5 +110,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CCK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CCK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CCK_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CCK_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CCK_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CDT.json b/data/station/CDT.json index b222b690..da7458f8 100644 --- a/data/station/CDT.json +++ b/data/station/CDT.json @@ -105,7 +105,56 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "CDT_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Toa Payoh Rise" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CDT_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Toa Payoh Rise" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CDT_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Toa Payoh Rise" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CDT_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Toa Payoh Link" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], "platforms": [ { "id": "CCDT_A", diff --git a/data/station/CGL.json b/data/station/CGL.json index b00b366b..6f924abd 100644 --- a/data/station/CGL.json +++ b/data/station/CGL.json @@ -24,5 +24,24 @@ "compass-one", "sengkang-sports-complex" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "CGL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CGL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/CLE.json b/data/station/CLE.json index 9c95b938..e41208c0 100644 --- a/data/station/CLE.json +++ b/data/station/CLE.json @@ -69,5 +69,60 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CLE_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue West" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CLE_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue West" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CLE_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue West" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CLE_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue West" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CNG.json b/data/station/CNG.json index 98d4c003..b387def5 100644 --- a/data/station/CNG.json +++ b/data/station/CNG.json @@ -62,5 +62,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CNG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Boon Lay Way" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CNG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Boon Lay Way" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CNG_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Boon Lay Way" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/COM.json b/data/station/COM.json index 2959c331..483e8d78 100644 --- a/data/station/COM.json +++ b/data/station/COM.json @@ -61,5 +61,60 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "COM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "COM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "COM_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "COM_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/COV.json b/data/station/COV.json index 8632fd0b..f5bc4554 100644 --- a/data/station/COV.json +++ b/data/station/COV.json @@ -23,5 +23,24 @@ "punggol-waterway-park", "oasis-terraces" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "COV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "COV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/CPV.json b/data/station/CPV.json index dfdfe1eb..cb275973 100644 --- a/data/station/CPV.json +++ b/data/station/CPV.json @@ -24,5 +24,30 @@ "sengkang-riverside-park", "sengkang-general-hospital" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "CPV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CPV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/CRE.json b/data/station/CRE.json index 2dd18aa0..72c65211 100644 --- a/data/station/CRE.json +++ b/data/station/CRE.json @@ -23,5 +23,24 @@ "coral-edge-community-centre", "punggol-waterway-park" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "CRE_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CRE_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/CRQ.json b/data/station/CRQ.json index c154bed3..07e40357 100644 --- a/data/station/CRQ.json +++ b/data/station/CRQ.json @@ -62,5 +62,55 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CRQ_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CRQ_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "CRQ_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CRQ_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "CRQ_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CRQ_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CSW.json b/data/station/CSW.json index e2450aad..87545756 100644 --- a/data/station/CSW.json +++ b/data/station/CSW.json @@ -62,5 +62,22 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CSW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CTH.json b/data/station/CTH.json index 0c037ae1..dcbac432 100644 --- a/data/station/CTH.json +++ b/data/station/CTH.json @@ -104,5 +104,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CTH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CTH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "CTH_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CTH_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/CTN.json b/data/station/CTN.json index 638ef0ae..96d60053 100644 --- a/data/station/CTN.json +++ b/data/station/CTN.json @@ -108,5 +108,56 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "CTN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CTN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "CTN_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CTN_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "CTN_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "CTN_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/DAM.json b/data/station/DAM.json index eff596e8..916b3330 100644 --- a/data/station/DAM.json +++ b/data/station/DAM.json @@ -24,5 +24,24 @@ "punggol-plaza", "waterway-point" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "DAM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DAM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/DBG.json b/data/station/DBG.json index f661b64b..aaa49938 100644 --- a/data/station/DBG.json +++ b/data/station/DBG.json @@ -128,5 +128,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "DBG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DBG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DBG_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DBG_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DBG_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DBG_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DBG_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/DKT.json b/data/station/DKT.json index 70551f0b..087bb69f 100644 --- a/data/station/DKT.json +++ b/data/station/DKT.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "DKT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Old Airport Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "DKT_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Old Airport Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/DTN.json b/data/station/DTN.json index 79c966f3..d81a1cab 100644 --- a/data/station/DTN.json +++ b/data/station/DTN.json @@ -62,5 +62,55 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "DTN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DTN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "DTN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DTN_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "DTN_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "DTN_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/DVR.json b/data/station/DVR.json index 94957e64..bf4fdec1 100644 --- a/data/station/DVR.json +++ b/data/station/DVR.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "DVR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue West" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "DVR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Commonwealth Avenue West" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/EPN.json b/data/station/EPN.json index c4734621..7c030e3d 100644 --- a/data/station/EPN.json +++ b/data/station/EPN.json @@ -62,5 +62,63 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "EPN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "EPN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "EPN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "EPN_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "EPN_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "EPN_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "EPN_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/EUN.json b/data/station/EUN.json index f0813bd6..183fec91 100644 --- a/data/station/EUN.json +++ b/data/station/EUN.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "EUN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "EUN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "EUN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/FCN.json b/data/station/FCN.json index 13a6c1d6..0f070361 100644 --- a/data/station/FCN.json +++ b/data/station/FCN.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "FCN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "FCN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/FMW.json b/data/station/FMW.json index 57f3f79e..8bbdb42f 100644 --- a/data/station/FMW.json +++ b/data/station/FMW.json @@ -24,5 +24,30 @@ "anchorvale-community-club", "sengkang-sports-centre" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "FMW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "FMW_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/FNV.json b/data/station/FNV.json index fd8fda84..94866e7f 100644 --- a/data/station/FNV.json +++ b/data/station/FNV.json @@ -24,5 +24,24 @@ "compass-one", "fernvale-point" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "FNV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FNV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/FRP.json b/data/station/FRP.json index a48ed501..e8eda746 100644 --- a/data/station/FRP.json +++ b/data/station/FRP.json @@ -62,5 +62,72 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "FRP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "FRP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FRP_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FRP_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "FRP_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FRP_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FRP_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FRP_EXIT_H", + "label": "H", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "FRP_EXIT_I", + "label": "I", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/FRR.json b/data/station/FRR.json index e9f30587..03c3b5ba 100644 --- a/data/station/FRR.json +++ b/data/station/FRR.json @@ -60,5 +60,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "FRR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Farrer Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "FRR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Farrer Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/GCL.json b/data/station/GCL.json index bd66ec77..b5486b6d 100644 --- a/data/station/GCL.json +++ b/data/station/GCL.json @@ -65,5 +65,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "GCL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GCL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/GLB.json b/data/station/GLB.json index 92eff089..b901536a 100644 --- a/data/station/GLB.json +++ b/data/station/GLB.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "GLB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "GLB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/GRB.json b/data/station/GRB.json index c4b4fa8d..4ab5fcf3 100644 --- a/data/station/GRB.json +++ b/data/station/GRB.json @@ -62,5 +62,39 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "GRB_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GRB_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GRB_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/GRW.json b/data/station/GRW.json index 4af8e93c..083bf0ab 100644 --- a/data/station/GRW.json +++ b/data/station/GRW.json @@ -61,5 +61,63 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "GRW_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GRW_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "GRW_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GRW_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GRW_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "GRW_EXIT_6", + "label": "6", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HBF.json b/data/station/HBF.json index bfbe359d..81f641de 100644 --- a/data/station/HBF.json +++ b/data/station/HBF.json @@ -69,5 +69,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HBF_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "HBF_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "HBF_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "HBF_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "HBF_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HGN.json b/data/station/HGN.json index 97a6e56f..2967febd 100644 --- a/data/station/HGN.json +++ b/data/station/HGN.json @@ -69,5 +69,37 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HGN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "HGN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "HGN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HLV.json b/data/station/HLV.json index 23a6863a..59e959cc 100644 --- a/data/station/HLV.json +++ b/data/station/HLV.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HLV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "HLV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "HLV_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HME.json b/data/station/HME.json index b399f33e..5e031782 100644 --- a/data/station/HME.json +++ b/data/station/HME.json @@ -60,5 +60,24 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HME_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "HME_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HPV.json b/data/station/HPV.json index 21dbb8e8..635e61ab 100644 --- a/data/station/HPV.json +++ b/data/station/HPV.json @@ -60,5 +60,24 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HPV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "West Coast Highway" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HVL.json b/data/station/HVL.json index 20541a7a..992c22a3 100644 --- a/data/station/HVL.json +++ b/data/station/HVL.json @@ -62,5 +62,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HVL_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "HVL_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "HVL_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "HVL_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "HVL_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/HVW.json b/data/station/HVW.json index 5214ac37..ede99298 100644 --- a/data/station/HVW.json +++ b/data/station/HVW.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "HVW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "HVW_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/JKN.json b/data/station/JKN.json index 9e757276..7d475374 100644 --- a/data/station/JKN.json +++ b/data/station/JKN.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "JKN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "JKN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "JKN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/JLB.json b/data/station/JLB.json index b6e3f396..b770359c 100644 --- a/data/station/JLB.json +++ b/data/station/JLB.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "JLB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "JLB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/JUR.json b/data/station/JUR.json index 096d48fb..d7f02766 100644 --- a/data/station/JUR.json +++ b/data/station/JUR.json @@ -93,5 +93,48 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "JUR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "JUR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "JUR_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "JUR_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KAL.json b/data/station/KAL.json index 91d1c3ce..d4f858b2 100644 --- a/data/station/KAL.json +++ b/data/station/KAL.json @@ -62,5 +62,33 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KAL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sims Avenue" + ], + "paidArea": false + }, + { + "id": "KAL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sims Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KAP.json b/data/station/KAP.json index 03df602e..87b030b3 100644 --- a/data/station/KAP.json +++ b/data/station/KAP.json @@ -68,5 +68,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KAP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "KAP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KDL.json b/data/station/KDL.json index d1d8bb7c..df28ce9e 100644 --- a/data/station/KDL.json +++ b/data/station/KDL.json @@ -24,5 +24,24 @@ "punggol-waterway-park", "punggol-town-hub" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "KDL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "KDL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/KEM.json b/data/station/KEM.json index 7273fb45..509b65cd 100644 --- a/data/station/KEM.json +++ b/data/station/KEM.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KEM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sims Avenue East" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KEM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sims Avenue East" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KGK.json b/data/station/KGK.json index 18c7151c..564d379d 100644 --- a/data/station/KGK.json +++ b/data/station/KGK.json @@ -24,5 +24,30 @@ "compass-one", "sengkang-riverside-park" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "KGK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KGK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/KKB.json b/data/station/KKB.json index 0768a241..9c34e113 100644 --- a/data/station/KKB.json +++ b/data/station/KKB.json @@ -60,5 +60,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KKB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "KKB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KPG.json b/data/station/KPG.json index e654a925..e7268153 100644 --- a/data/station/KPG.json +++ b/data/station/KPG.json @@ -24,5 +24,32 @@ "sengkang-general-hospital", "sengkang-sports-centre" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "KPG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "KPG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/KRG.json b/data/station/KRG.json index 3bca1066..20b0b087 100644 --- a/data/station/KRG.json +++ b/data/station/KRG.json @@ -62,5 +62,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KRG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KRG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "KRG_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KRG_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KRJ.json b/data/station/KRJ.json index 5b3f833a..819b7db8 100644 --- a/data/station/KRJ.json +++ b/data/station/KRJ.json @@ -62,5 +62,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KRJ_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KRJ_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KRJ_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KRJ_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KTB.json b/data/station/KTB.json index e16360f7..2238fc4c 100644 --- a/data/station/KTB.json +++ b/data/station/KTB.json @@ -62,5 +62,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KTB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KTB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "KTB_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false + }, + { + "id": "KTB_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/KVN.json b/data/station/KVN.json index 104a3783..2e1ccd80 100644 --- a/data/station/KVN.json +++ b/data/station/KVN.json @@ -61,5 +61,38 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "KVN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "KVN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "KVN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LBD.json b/data/station/LBD.json index 0182b005..3cd4a42c 100644 --- a/data/station/LBD.json +++ b/data/station/LBD.json @@ -62,5 +62,21 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "LBD_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LKS.json b/data/station/LKS.json index 1d0f5e9e..84b47314 100644 --- a/data/station/LKS.json +++ b/data/station/LKS.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "LKS_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LKS_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "LKS_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LRC.json b/data/station/LRC.json index 397219a8..849c9151 100644 --- a/data/station/LRC.json +++ b/data/station/LRC.json @@ -61,5 +61,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "LRC_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LRC_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LTI.json b/data/station/LTI.json index 71051874..5398fbe1 100644 --- a/data/station/LTI.json +++ b/data/station/LTI.json @@ -103,5 +103,64 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "LTI_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "LTI_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "LTI_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "LTI_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "LTI_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "LTI_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LTR.json b/data/station/LTR.json index 6501162b..2c02612a 100644 --- a/data/station/LTR.json +++ b/data/station/LTR.json @@ -60,5 +60,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "LTR_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LTR_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LTR_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LTR_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LTR_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LVR.json b/data/station/LVR.json index 41cacd28..58379420 100644 --- a/data/station/LVR.json +++ b/data/station/LVR.json @@ -60,5 +60,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "LVR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Kallang Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LVR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Kallang Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/LYR.json b/data/station/LYR.json index 9389c43c..b698e66b 100644 --- a/data/station/LYR.json +++ b/data/station/LYR.json @@ -24,5 +24,30 @@ "the-rivervale-mall", "sengkang-community-hospital" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "LYR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "LYR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/MAX.json b/data/station/MAX.json index 24e84397..8073ec8c 100644 --- a/data/station/MAX.json +++ b/data/station/MAX.json @@ -62,5 +62,39 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MAX_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MAX_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MAX_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MBT.json b/data/station/MBT.json index f28ce96b..65b781d7 100644 --- a/data/station/MBT.json +++ b/data/station/MBT.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MBT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Old Airport Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MBT_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Old Airport Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MFL.json b/data/station/MFL.json index 07548312..3efa1950 100644 --- a/data/station/MFL.json +++ b/data/station/MFL.json @@ -61,5 +61,75 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MFL_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MFL_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MFL_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MFL_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MFL_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MFL_EXIT_6", + "label": "6", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MFL_EXIT_7", + "label": "7", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MPS.json b/data/station/MPS.json index 2db6a6a6..f5632ef9 100644 --- a/data/station/MPS.json +++ b/data/station/MPS.json @@ -102,5 +102,58 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MPS_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "MPS_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "MPS_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "MPS_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "MPS_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MRD.json b/data/station/MRD.json index ec6b5b7e..240aa005 100644 --- a/data/station/MRD.json +++ b/data/station/MRD.json @@ -23,5 +23,24 @@ "punggol-waterway-park", "punggol-beach" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "MRD_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "MRD_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/MRM.json b/data/station/MRM.json index 4c953d1b..7b599973 100644 --- a/data/station/MRM.json +++ b/data/station/MRM.json @@ -62,5 +62,27 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MRM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MRM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MSL.json b/data/station/MSL.json index dfaf87b7..5958db65 100644 --- a/data/station/MSL.json +++ b/data/station/MSL.json @@ -62,5 +62,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MSL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 3" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MSL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 3" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MSL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 3" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MSL_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Woodlands Avenue 3" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MSP.json b/data/station/MSP.json index 35c9b590..f2c6ce19 100644 --- a/data/station/MSP.json +++ b/data/station/MSP.json @@ -44,5 +44,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MSP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Marina Coastal Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MSP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Marina Coastal Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/MTR.json b/data/station/MTR.json index bba57493..832182d8 100644 --- a/data/station/MTR.json +++ b/data/station/MTR.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "MTR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "MTR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/NBG.json b/data/station/NBG.json index b2871f68..4be9eb25 100644 --- a/data/station/NBG.json +++ b/data/station/NBG.json @@ -24,5 +24,24 @@ "waterway-point", "coney-island" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "NBG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "NBG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/NCH.json b/data/station/NCH.json index 4c9f5a17..4bbe3a33 100644 --- a/data/station/NCH.json +++ b/data/station/NCH.json @@ -96,5 +96,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "NCH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "NCH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/NEW.json b/data/station/NEW.json index 0de195b4..ebb61fa7 100644 --- a/data/station/NEW.json +++ b/data/station/NEW.json @@ -103,5 +103,41 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "NEW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "NEW_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "NEW_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/NOV.json b/data/station/NOV.json index 41b412ad..277afc7b 100644 --- a/data/station/NOV.json +++ b/data/station/NOV.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "NOV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "NOV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "NOV_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/NPR.json b/data/station/NPR.json index 23d1aa80..a6fb8e00 100644 --- a/data/station/NPR.json +++ b/data/station/NPR.json @@ -62,5 +62,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "NPR_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "NPR_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/OAS.json b/data/station/OAS.json index 4b203ee2..fd7f4044 100644 --- a/data/station/OAS.json +++ b/data/station/OAS.json @@ -24,5 +24,24 @@ "punggol-waterway-park", "waterway-point" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "OAS_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "OAS_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/OBV.json b/data/station/OBV.json index 815180c3..a251c511 100644 --- a/data/station/OBV.json +++ b/data/station/OBV.json @@ -62,5 +62,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "OBV_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "OBV_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/ONH.json b/data/station/ONH.json index 038697f0..89b5b3a6 100644 --- a/data/station/ONH.json +++ b/data/station/ONH.json @@ -62,5 +62,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "ONH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "ONH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ONH_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ONH_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/ORC.json b/data/station/ORC.json index bb1ec825..6b835c70 100644 --- a/data/station/ORC.json +++ b/data/station/ORC.json @@ -103,5 +103,111 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "ORC_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ORC_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ORC_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "ORC_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "ORC_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "ORC_EXIT_6", + "label": "6", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "ORC_EXIT_7", + "label": "7", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ORC_EXIT_8", + "label": "8", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "ORC_EXIT_9", + "label": "9", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "ORC_EXIT_10", + "label": "10", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ORC_EXIT_11", + "label": "11", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ORC_EXIT_12", + "label": "12", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "ORC_EXIT_13", + "label": "13", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/OTP.json b/data/station/OTP.json index 244ac493..6e96503b 100644 --- a/data/station/OTP.json +++ b/data/station/OTP.json @@ -145,5 +145,72 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "OTP_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "OTP_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "OTP_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "OTP_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "OTP_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "OTP_EXIT_6", + "label": "6", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "OTP_EXIT_7", + "label": "7", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "OTP_EXIT_8", + "label": "8", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PGC.json b/data/station/PGC.json index 0915fd98..d8f95637 100644 --- a/data/station/PGC.json +++ b/data/station/PGC.json @@ -45,5 +45,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PGC_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "PGC_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PGL.json b/data/station/PGL.json index ae489b78..c1c52139 100644 --- a/data/station/PGL.json +++ b/data/station/PGL.json @@ -76,5 +76,48 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PGL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "PGL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "PGL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "PGL_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PGP.json b/data/station/PGP.json index f7e39c90..6a421fff 100644 --- a/data/station/PGP.json +++ b/data/station/PGP.json @@ -24,5 +24,32 @@ "punggol-waterway-park", "punggol-point-park" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "PGP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "PGP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/PMN.json b/data/station/PMN.json index 54ca6dd3..6e709594 100644 --- a/data/station/PMN.json +++ b/data/station/PMN.json @@ -137,5 +137,33 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PMN_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PMN_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "PMN_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PNR.json b/data/station/PNR.json index 4db33982..e9a3afc4 100644 --- a/data/station/PNR.json +++ b/data/station/PNR.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PNR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Jurong West Street 63" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PNR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Jurong West Street 63" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PPJ.json b/data/station/PPJ.json index 7bd7401d..7303ede9 100644 --- a/data/station/PPJ.json +++ b/data/station/PPJ.json @@ -61,5 +61,24 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PPJ_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Pasir Panjang Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PSR.json b/data/station/PSR.json index 5d3999b2..674f6404 100644 --- a/data/station/PSR.json +++ b/data/station/PSR.json @@ -59,5 +59,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PSR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PSR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PTP.json b/data/station/PTP.json index 9c8c0325..293cef03 100644 --- a/data/station/PTP.json +++ b/data/station/PTP.json @@ -61,5 +61,41 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PTP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PTP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "PTP_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/PYL.json b/data/station/PYL.json index 6ce12e3c..41cfce58 100644 --- a/data/station/PYL.json +++ b/data/station/PYL.json @@ -103,5 +103,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "PYL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "PYL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PYL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PYL_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "PYL_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "PYL_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/QUE.json b/data/station/QUE.json index fa683f52..bca9ac2f 100644 --- a/data/station/QUE.json +++ b/data/station/QUE.json @@ -62,5 +62,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "QUE_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "QUE_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "QUE_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "QUE_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/RCR.json b/data/station/RCR.json index d0697442..b894785f 100644 --- a/data/station/RCR.json +++ b/data/station/RCR.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "RCR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "RCR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/RDH.json b/data/station/RDH.json index e861e502..19bbfce2 100644 --- a/data/station/RDH.json +++ b/data/station/RDH.json @@ -61,5 +61,33 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "RDH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Tiong Bahru Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "RDH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Tiong Bahru Road" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/RFP.json b/data/station/RFP.json index 970586fb..ecb7189a 100644 --- a/data/station/RFP.json +++ b/data/station/RFP.json @@ -104,5 +104,90 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "RFP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_H", + "label": "H", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_I", + "label": "I", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_J", + "label": "J", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_K", + "label": "K", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_L", + "label": "L", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "RFP_EXIT_M", + "label": "M", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/RIV.json b/data/station/RIV.json index cb31c294..b18cd104 100644 --- a/data/station/RIV.json +++ b/data/station/RIV.json @@ -30,5 +30,24 @@ "punggol-waterway-park", "punggol-plaza" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "RIV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "RIV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/RMB.json b/data/station/RMB.json index 08cd9feb..01315852 100644 --- a/data/station/RMB.json +++ b/data/station/RMB.json @@ -23,5 +23,30 @@ "sengkang-sports-and-recreation-centre", "compass-one" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "RMB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "RMB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/RNG.json b/data/station/RNG.json index c76fda4f..66db5e05 100644 --- a/data/station/RNG.json +++ b/data/station/RNG.json @@ -24,5 +24,30 @@ "sengkang-sports-complex", "sengkang-general-hospital" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "RNG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "RNG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/RNJ.json b/data/station/RNJ.json index ca6d6639..c2589ce1 100644 --- a/data/station/RNJ.json +++ b/data/station/RNJ.json @@ -24,5 +24,30 @@ "compass-one", "anchorvale-community-club" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "RNJ_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "RNJ_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/SAV.json b/data/station/SAV.json index f37bede8..a6aefeee 100644 --- a/data/station/SAV.json +++ b/data/station/SAV.json @@ -60,5 +60,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SAV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "SAV_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SBW.json b/data/station/SBW.json index 58672f64..0dbfcca0 100644 --- a/data/station/SBW.json +++ b/data/station/SBW.json @@ -62,5 +62,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SBW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sembawang Way" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SBW_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sembawang Way" + ], + "paidArea": false + }, + { + "id": "SBW_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sembawang Way" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SBW_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Sembawang Way" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SDM.json b/data/station/SDM.json index e25bc817..4accee96 100644 --- a/data/station/SDM.json +++ b/data/station/SDM.json @@ -79,5 +79,24 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SDM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "SDM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SER.json b/data/station/SER.json index c0ec9ff6..03116699 100644 --- a/data/station/SER.json +++ b/data/station/SER.json @@ -103,5 +103,76 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SER_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "SER_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "SER_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "SER_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "SER_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "SER_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "SER_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "SER_EXIT_H", + "label": "H", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SHW.json b/data/station/SHW.json index 11142fd4..3854e2b1 100644 --- a/data/station/SHW.json +++ b/data/station/SHW.json @@ -62,5 +62,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SHW_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SHW_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SHW_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SHW_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "SHW_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "SHW_EXIT_6", + "label": "6", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SIM.json b/data/station/SIM.json index b09a9655..fb204902 100644 --- a/data/station/SIM.json +++ b/data/station/SIM.json @@ -61,5 +61,24 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SIM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Simei Street 3" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SKG.json b/data/station/SKG.json index 66d8961d..7399ca1f 100644 --- a/data/station/SKG.json +++ b/data/station/SKG.json @@ -71,5 +71,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SKG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "SKG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "SKG_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "SKG_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SMD.json b/data/station/SMD.json index 3b9eaa5f..a056ea4f 100644 --- a/data/station/SMD.json +++ b/data/station/SMD.json @@ -24,5 +24,32 @@ "punggol-town-hub", "coney-island-park" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "SMD_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "SMD_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/SMG.json b/data/station/SMG.json index 042a7136..20a485a2 100644 --- a/data/station/SMG.json +++ b/data/station/SMG.json @@ -24,5 +24,30 @@ "punggol-digital-district", "seaside-walk" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "SMG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SMG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/SMK.json b/data/station/SMK.json index c6cd7300..87e37e4e 100644 --- a/data/station/SMK.json +++ b/data/station/SMK.json @@ -24,5 +24,24 @@ "punggol-plaza", "waterway-point" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "SMK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "SMK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/SOM.json b/data/station/SOM.json index afe3b7d2..a8516399 100644 --- a/data/station/SOM.json +++ b/data/station/SOM.json @@ -62,5 +62,42 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SOM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SOM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SOM_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "SOM_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/SPL.json b/data/station/SPL.json index 2433dac4..f9ad7205 100644 --- a/data/station/SPL.json +++ b/data/station/SPL.json @@ -60,5 +60,48 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "SPL_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SPL_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "SPL_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/STK.json b/data/station/STK.json index 3532b19e..b0b9f62c 100644 --- a/data/station/STK.json +++ b/data/station/STK.json @@ -24,5 +24,24 @@ "punggol-plaza", "waterway-point" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "STK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "STK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/STV.json b/data/station/STV.json index 0b12e1b7..f46218b8 100644 --- a/data/station/STV.json +++ b/data/station/STV.json @@ -103,5 +103,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "STV_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "STV_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "STV_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "STV_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "STV_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TAM.json b/data/station/TAM.json index e42e25ae..7f900c04 100644 --- a/data/station/TAM.json +++ b/data/station/TAM.json @@ -103,5 +103,54 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TAM_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "TAM_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "TAM_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "TAM_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "TAM_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "TAM_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "TAM_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TAP.json b/data/station/TAP.json index 123efce3..78096e9d 100644 --- a/data/station/TAP.json +++ b/data/station/TAP.json @@ -61,5 +61,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TAP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TAP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TAP_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TAP_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TCR.json b/data/station/TCR.json index fb817786..90d054c0 100644 --- a/data/station/TCR.json +++ b/data/station/TCR.json @@ -62,5 +62,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TCR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Pioneer Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TCR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Pioneer Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TIB.json b/data/station/TIB.json index 6959a309..0d225452 100644 --- a/data/station/TIB.json +++ b/data/station/TIB.json @@ -62,5 +62,33 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TIB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Tiong Bahru Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TIB_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Tiong Bahru Road" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TKG.json b/data/station/TKG.json index fbf39561..aaf8f2ea 100644 --- a/data/station/TKG.json +++ b/data/station/TKG.json @@ -24,5 +24,30 @@ "sengkang-general-hospital", "sengkang-sports-centre" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "TKG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TKG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/TKK.json b/data/station/TKK.json index b5a6d720..eaa89911 100644 --- a/data/station/TKK.json +++ b/data/station/TKK.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TKK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "TKK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TKL.json b/data/station/TKL.json index 3386d450..5d3ee7c0 100644 --- a/data/station/TKL.json +++ b/data/station/TKL.json @@ -24,5 +24,30 @@ "waterway-point", "punggol-plaza" ], - "townId": "punggol" + "townId": "punggol", + "layout": { + "levels": [], + "exits": [ + { + "id": "TKL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + }, + { + "id": "TKL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/TLA.json b/data/station/TLA.json index b0b68e3d..9cccf578 100644 --- a/data/station/TLA.json +++ b/data/station/TLA.json @@ -63,5 +63,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TLA_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "TLA_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "TLA_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TLB.json b/data/station/TLB.json index a7e1a6bc..475cd3ad 100644 --- a/data/station/TLB.json +++ b/data/station/TLB.json @@ -62,5 +62,24 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TLB_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Telok Blangah Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TLK.json b/data/station/TLK.json index f81ca693..caf10c9b 100644 --- a/data/station/TLK.json +++ b/data/station/TLK.json @@ -44,5 +44,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TLK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Tuas West Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TLK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Tuas West Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TNG.json b/data/station/TNG.json index 4bf2627c..e4a608f5 100644 --- a/data/station/TNG.json +++ b/data/station/TNG.json @@ -24,5 +24,24 @@ "compass-one", "sengkang-sports-complex" ], - "townId": "sengkang" + "townId": "sengkang", + "layout": { + "levels": [], + "exits": [ + { + "id": "TNG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "TNG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] + } } diff --git a/data/station/TPE.json b/data/station/TPE.json index b7fbd11b..8057fb1f 100644 --- a/data/station/TPE.json +++ b/data/station/TPE.json @@ -62,5 +62,52 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TPE_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "TPE_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "TPE_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "TPE_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TPG.json b/data/station/TPG.json index 13a34e11..23713179 100644 --- a/data/station/TPG.json +++ b/data/station/TPG.json @@ -62,5 +62,72 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TPG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_H", + "label": "H", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_J", + "label": "J", + "lastUpdated": "2026-07-16", + "paidArea": false + }, + { + "id": "TPG_EXIT_K", + "label": "K", + "lastUpdated": "2026-07-16", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TPW.json b/data/station/TPW.json index 32f1d47b..a1614549 100644 --- a/data/station/TPW.json +++ b/data/station/TPW.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TPW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "TPW_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TSG.json b/data/station/TSG.json index f1ba6937..02c4ff2b 100644 --- a/data/station/TSG.json +++ b/data/station/TSG.json @@ -61,5 +61,45 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TSG_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Paya Lebar Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TSG_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Paya Lebar Road" + ], + "paidArea": false + }, + { + "id": "TSG_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Paya Lebar Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/TWR.json b/data/station/TWR.json index 1305c699..108e32a7 100644 --- a/data/station/TWR.json +++ b/data/station/TWR.json @@ -61,5 +61,36 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "TWR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Pioneer Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TWR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Pioneer Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/UBI.json b/data/station/UBI.json index 7e901d91..358c03a1 100644 --- a/data/station/UBI.json +++ b/data/station/UBI.json @@ -60,5 +60,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "UBI_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "UBI_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/UPC.json b/data/station/UPC.json index 272561c5..dff8a7c5 100644 --- a/data/station/UPC.json +++ b/data/station/UPC.json @@ -61,5 +61,52 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "UPC_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "UPC_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "UPC_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "UPC_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/UTS.json b/data/station/UTS.json index 5b1634ce..2f0128e6 100644 --- a/data/station/UTS.json +++ b/data/station/UTS.json @@ -62,5 +62,72 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "UTS_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "UTS_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "UTS_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "UTS_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "UTS_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Upper Thomson Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/WDL.json b/data/station/WDL.json index 16fb9d2d..eb1549f7 100644 --- a/data/station/WDL.json +++ b/data/station/WDL.json @@ -103,5 +103,66 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "WDL_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "WDL_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "WDL_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "WDL_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDL_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDL_EXIT_6", + "label": "6", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDL_EXIT_7", + "label": "7", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/WDN.json b/data/station/WDN.json index decc8338..3991067b 100644 --- a/data/station/WDN.json +++ b/data/station/WDN.json @@ -45,5 +45,30 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "WDN_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDN_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/WDS.json b/data/station/WDS.json index eac73087..2b86a044 100644 --- a/data/station/WDS.json +++ b/data/station/WDS.json @@ -62,5 +62,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "WDS_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDS_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDS_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDS_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "WDS_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/WLH.json b/data/station/WLH.json index 511f8abf..94e24176 100644 --- a/data/station/WLH.json +++ b/data/station/WLH.json @@ -62,5 +62,38 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "WLH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "WLH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "WLH_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/XPO.json b/data/station/XPO.json index d3e4ab70..fdab2829 100644 --- a/data/station/XPO.json +++ b/data/station/XPO.json @@ -92,5 +92,73 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "XPO_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "XPO_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "XPO_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "XPO_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "XPO_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-17", + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "XPO_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-17", + "paidArea": false + }, + { + "id": "XPO_EXIT_G", + "label": "G", + "lastUpdated": "2026-07-17", + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/YCK.json b/data/station/YCK.json index 67eb14be..4ff7b5e0 100644 --- a/data/station/YCK.json +++ b/data/station/YCK.json @@ -61,5 +61,39 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "YCK_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YCK_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YCK_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/YIS.json b/data/station/YIS.json index a0c9afc3..44672624 100644 --- a/data/station/YIS.json +++ b/data/station/YIS.json @@ -62,5 +62,66 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "YIS_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YIS_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YIS_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false + }, + { + "id": "YIS_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YIS_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Yishun Avenue 2" + ], + "paidArea": false + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/data/station/YWT.json b/data/station/YWT.json index f22c13d3..bb7cb2ba 100644 --- a/data/station/YWT.json +++ b/data/station/YWT.json @@ -61,5 +61,57 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [ + { + "id": "YWT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Choa Chu Kang Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YWT_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Choa Chu Kang Drive" + ], + "paidArea": false + }, + { + "id": "YWT_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Choa Chu Kang Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "YWT_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-16", + "roadNames": [ + "Choa Chu Kang Drive" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], + "platforms": [], + "transferPaths": [] } } diff --git a/packages/core/src/schema/Station.test.ts b/packages/core/src/schema/Station.test.ts index 251787ef..53259440 100644 --- a/packages/core/src/schema/Station.test.ts +++ b/packages/core/src/schema/Station.test.ts @@ -192,6 +192,7 @@ describe('StationSchema', () => { { id: 'KET_EXIT_A', label: 'A', + lastUpdated: '2026-07-18', levelId: 'B2', paidArea: false, }, @@ -222,10 +223,12 @@ describe('StationSchema', () => { from: { kind: 'platform', id: 'KET_ISL_A', + lastUpdated: '2026-07-18', }, to: { kind: 'level', id: 'B2', + lastUpdated: '2026-07-18', }, paidArea: true, modes: ['walk', 'escalator'], diff --git a/packages/core/src/schema/Station.ts b/packages/core/src/schema/Station.ts index 60e2c885..3c3415e3 100644 --- a/packages/core/src/schema/Station.ts +++ b/packages/core/src/schema/Station.ts @@ -143,6 +143,7 @@ export type StationLayoutLevel = z.infer; export const StationLayoutExitSchema = z.object({ id: z.string(), label: z.string(), + lastUpdated: z.iso.date(), levelId: z.string().optional(), geo: z .object({ @@ -188,6 +189,7 @@ export type StationLayoutPlatform = z.infer; export const StationLayoutTransferEndpointSchema = z.object({ kind: StationLayoutTransferEndpointKindSchema, id: z.string(), + lastUpdated: z.iso.date(), }); export type StationLayoutTransferEndpoint = z.infer< typeof StationLayoutTransferEndpointSchema diff --git a/packages/fs/src/index.test.ts b/packages/fs/src/index.test.ts index b4e342ae..ee7230a9 100644 --- a/packages/fs/src/index.test.ts +++ b/packages/fs/src/index.test.ts @@ -2904,6 +2904,7 @@ describe('@mrtdown/fs', () => { { id: 'KET_EXIT_A', label: 'A', + lastUpdated: '2026-07-18', levelId: 'MISSING', nearbyLandmarkIds: ['missing-landmark'], paidArea: false, @@ -2911,6 +2912,7 @@ describe('@mrtdown/fs', () => { { id: 'KET_EXIT_B', label: 'a', + lastUpdated: '2026-07-18', paidArea: false, }, ], @@ -2952,10 +2954,12 @@ describe('@mrtdown/fs', () => { from: { kind: 'platform', id: 'MISSING_PLATFORM', + lastUpdated: '2026-07-18', }, to: { kind: 'access_point', id: 'MISSING_ACCESS_POINT', + lastUpdated: '2026-07-18', }, paidArea: true, modes: ['walk'], @@ -3071,6 +3075,37 @@ describe('@mrtdown/fs', () => { ); }); + it('allows exit-only station layouts with first/last train data', async () => { + const dataDir = await mkdtemp(join(tmpdir(), 'mrtdown-fs-')); + await cp(fixtureDataDir, dataDir, { recursive: true }); + const stationPath = join(dataDir, 'station/KET.json'); + const station = JSON.parse(await readFile(stationPath, 'utf8')); + station.layout = { + levels: [], + exits: [ + { + id: 'KET_EXIT_A', + label: 'A', + lastUpdated: '2026-07-18', + roadNames: ['Rock Hill Street'], + paidArea: false, + accessibility: { + stepFree: true, + }, + }, + ], + platforms: [], + transferPaths: [], + }; + await writeFile(stationPath, `${JSON.stringify(station, null, 2)}\n`); + + const result = await validateDataRoot(dataDir, ['station']); + + expect(result.ok).toBe(true); + expect(result.errors).toEqual([]); + expect(result.checked.station).toBe(fixtureMeta.counts.station); + }); + it('rejects service revisions outside station code active windows', async () => { const dataDir = await mkdtemp(join(tmpdir(), 'mrtdown-fs-')); await mkdir(join(dataDir, 'line'), { recursive: true }); diff --git a/packages/fs/src/validate.ts b/packages/fs/src/validate.ts index affd4ada..3d7d8328 100644 --- a/packages/fs/src/validate.ts +++ b/packages/fs/src/validate.ts @@ -459,7 +459,11 @@ async function validateStationReferences( seenFirstLastTrainServices.set(serviceTiming.serviceId, index); } - if (layout && !layoutPlatformServiceIds.has(serviceTiming.serviceId)) { + if ( + layout && + layout.platforms.length > 0 && + !layoutPlatformServiceIds.has(serviceTiming.serviceId) + ) { errors.push( `${station.path}: firstLastTrain.services.${index}.serviceId ${serviceTiming.serviceId} is not served by any layout platform`, ); diff --git a/scripts/generate-fixtures.mjs b/scripts/generate-fixtures.mjs index 5b3691c6..55585e06 100644 --- a/scripts/generate-fixtures.mjs +++ b/scripts/generate-fixtures.mjs @@ -370,6 +370,7 @@ function buildStaticEntities() { { id: 'KET_EXIT_A', label: 'A', + lastUpdated: '2026-07-18', levelId: 'B2', roadNames: ['Rock Hill Street'], paidArea: false, @@ -414,10 +415,12 @@ function buildStaticEntities() { from: { kind: 'platform', id: 'KET_ISL_E', + lastUpdated: '2026-07-18', }, to: { kind: 'platform', id: 'KET_ISL_W', + lastUpdated: '2026-07-18', }, paidArea: true, modes: ['walk'], From a66956a4eb0841997704f85d5b939e2f795ecff6 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 00:57:04 +0800 Subject: [PATCH 02/20] feat: add layout record update dates --- data/station/CDT.json | 8 ++++++++ packages/core/src/schema/Station.test.ts | 5 +++++ packages/core/src/schema/Station.ts | 4 ++++ packages/fs/src/index.test.ts | 7 +++++++ scripts/generate-fixtures.mjs | 5 +++++ 5 files changed, 29 insertions(+) diff --git a/data/station/CDT.json b/data/station/CDT.json index da7458f8..0e77adf6 100644 --- a/data/station/CDT.json +++ b/data/station/CDT.json @@ -159,39 +159,47 @@ { "id": "CCDT_A", "label": "A", + "lastUpdated": "2026-07-18", "lineId": "CCL", "serviceIds": [ "CCL_BRANCH_CCW", "CCL_LOOP_CCW" ], + "doorCount": 12, "accessPoints": [] }, { "id": "CCDT_B", "label": "B", + "lastUpdated": "2026-07-18", "lineId": "CCL", "serviceIds": [ "CCL_BRANCH_CW", "CCL_LOOP_CW" ], + "doorCount": 12, "accessPoints": [] }, { "id": "TCDT_D", "label": "D", + "lastUpdated": "2026-07-18", "lineId": "TEL", "serviceIds": [ "TEL_MAIN_N" ], + "doorCount": 20, "accessPoints": [] }, { "id": "TCDT_C", "label": "C", + "lastUpdated": "2026-07-18", "lineId": "TEL", "serviceIds": [ "TEL_MAIN_S" ], + "doorCount": 20, "accessPoints": [] } ], diff --git a/packages/core/src/schema/Station.test.ts b/packages/core/src/schema/Station.test.ts index 53259440..6476d9cf 100644 --- a/packages/core/src/schema/Station.test.ts +++ b/packages/core/src/schema/Station.test.ts @@ -180,6 +180,7 @@ describe('StationSchema', () => { { id: 'B2', index: -2, + lastUpdated: '2026-07-18', name: { 'en-SG': 'Platforms', 'zh-Hans': null, @@ -201,6 +202,7 @@ describe('StationSchema', () => { { id: 'KET_ISL_A', label: 'A', + lastUpdated: '2026-07-18', lineId: 'ISL', levelId: 'B2', serviceIds: ['ISL_MAIN_E'], @@ -209,6 +211,7 @@ describe('StationSchema', () => { { id: 'KET_ISL_A_ESC_01', kind: 'escalator', + lastUpdated: '2026-07-18', nearestDoor: '12', position: 'middle', connectsToLevelId: 'B2', @@ -220,6 +223,7 @@ describe('StationSchema', () => { transferPaths: [ { id: 'KET_TRANSFER', + lastUpdated: '2026-07-18', from: { kind: 'platform', id: 'KET_ISL_A', @@ -253,6 +257,7 @@ describe('StationSchema', () => { { id: 'KET_ISL_A', label: 'A', + lastUpdated: '2026-07-18', lineId: 'ISL', serviceIds: [], accessPoints: [], diff --git a/packages/core/src/schema/Station.ts b/packages/core/src/schema/Station.ts index 3c3415e3..bfeeb5cd 100644 --- a/packages/core/src/schema/Station.ts +++ b/packages/core/src/schema/Station.ts @@ -137,6 +137,7 @@ export const StationLayoutLevelSchema = z.object({ id: z.string(), index: z.number().int(), name: TranslationsSchema, + lastUpdated: z.iso.date(), }); export type StationLayoutLevel = z.infer; @@ -166,6 +167,7 @@ export type StationLayoutExit = z.infer; export const StationLayoutAccessPointSchema = z.object({ id: z.string(), kind: StationLayoutAccessPointKindSchema, + lastUpdated: z.iso.date(), nearestDoor: z.string().optional(), position: StationLayoutAccessPointPositionSchema, connectsToLevelId: z.string().optional(), @@ -178,6 +180,7 @@ export type StationLayoutAccessPoint = z.infer< export const StationLayoutPlatformSchema = z.object({ id: z.string(), label: z.string(), + lastUpdated: z.iso.date(), lineId: z.string(), levelId: z.string().optional(), serviceIds: z.array(z.string()).nonempty(), @@ -197,6 +200,7 @@ export type StationLayoutTransferEndpoint = z.infer< export const StationLayoutTransferPathSchema = z.object({ id: z.string(), + lastUpdated: z.iso.date(), from: StationLayoutTransferEndpointSchema, to: StationLayoutTransferEndpointSchema, paidArea: z.boolean(), diff --git a/packages/fs/src/index.test.ts b/packages/fs/src/index.test.ts index ee7230a9..48912843 100644 --- a/packages/fs/src/index.test.ts +++ b/packages/fs/src/index.test.ts @@ -2882,6 +2882,7 @@ describe('@mrtdown/fs', () => { { id: 'B2', index: -2, + lastUpdated: '2026-07-18', name: { 'en-SG': 'Platforms', 'zh-Hans': null, @@ -2892,6 +2893,7 @@ describe('@mrtdown/fs', () => { { id: 'B2', index: -2, + lastUpdated: '2026-07-18', name: { 'en-SG': 'Duplicate platforms', 'zh-Hans': null, @@ -2920,6 +2922,7 @@ describe('@mrtdown/fs', () => { { id: 'KET_ISL_A', label: 'A', + lastUpdated: '2026-07-18', lineId: 'ISL', levelId: 'MISSING', serviceIds: ['MISSING_SERVICE'], @@ -2928,6 +2931,7 @@ describe('@mrtdown/fs', () => { { id: 'KET_AP_DUP', kind: 'escalator', + lastUpdated: '2026-07-18', nearestDoor: '25', position: 'middle', connectsToLevelId: 'MISSING', @@ -2937,12 +2941,14 @@ describe('@mrtdown/fs', () => { { id: 'KET_TWL_A', label: 'A', + lastUpdated: '2026-07-18', lineId: 'ISL', serviceIds: ['TWL_MAIN_N', 'ISL_SKIP_KET'], accessPoints: [ { id: 'KET_AP_DUP', kind: 'stairs', + lastUpdated: '2026-07-18', position: 'front', }, ], @@ -2951,6 +2957,7 @@ describe('@mrtdown/fs', () => { transferPaths: [ { id: 'KET_TRANSFER', + lastUpdated: '2026-07-18', from: { kind: 'platform', id: 'MISSING_PLATFORM', diff --git a/scripts/generate-fixtures.mjs b/scripts/generate-fixtures.mjs index 55585e06..8c94cf09 100644 --- a/scripts/generate-fixtures.mjs +++ b/scripts/generate-fixtures.mjs @@ -363,6 +363,7 @@ function buildStaticEntities() { { id: 'B2', index: -2, + lastUpdated: '2026-07-18', name: translations('Platforms'), }, ], @@ -384,6 +385,7 @@ function buildStaticEntities() { { id: 'KET_ISL_E', label: '1', + lastUpdated: '2026-07-18', lineId: 'ISL', levelId: 'B2', serviceIds: ['ISL_MAIN_E'], @@ -392,6 +394,7 @@ function buildStaticEntities() { { id: 'KET_ISL_E_LIFT_01', kind: 'lift', + lastUpdated: '2026-07-18', nearestDoor: '12', position: 'middle', connectsToLevelId: 'B2', @@ -402,6 +405,7 @@ function buildStaticEntities() { { id: 'KET_ISL_W', label: '2', + lastUpdated: '2026-07-18', lineId: 'ISL', levelId: 'B2', serviceIds: ['ISL_MAIN_W'], @@ -412,6 +416,7 @@ function buildStaticEntities() { transferPaths: [ { id: 'KET_ISL_CROSS_PLATFORM', + lastUpdated: '2026-07-18', from: { kind: 'platform', id: 'KET_ISL_E', From 59c793173d00af03f0e12547069ebc3b03c8d5a7 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:05:37 +0800 Subject: [PATCH 03/20] feat: add standard SMRT platform layouts --- data/station/ADM.json | 25 ++++++++++++++++++++++++- data/station/ALJ.json | 25 ++++++++++++++++++++++++- data/station/AMK.json | 25 ++++++++++++++++++++++++- data/station/BBS.json | 25 ++++++++++++++++++++++++- data/station/BBT.json | 25 ++++++++++++++++++++++++- data/station/BDK.json | 25 ++++++++++++++++++++++++- data/station/BDL.json | 25 ++++++++++++++++++++++++- data/station/BGB.json | 25 ++++++++++++++++++++++++- data/station/BLY.json | 27 ++++++++++++++++++++++++++- data/station/BNL.json | 25 ++++++++++++++++++++++++- data/station/BRH.json | 25 ++++++++++++++++++++++++- data/station/CBR.json | 25 ++++++++++++++++++++++++- data/station/CLE.json | 25 ++++++++++++++++++++++++- data/station/CNG.json | 25 ++++++++++++++++++++++++- data/station/COM.json | 25 ++++++++++++++++++++++++- data/station/DKT.json | 27 ++++++++++++++++++++++++++- data/station/DVR.json | 25 ++++++++++++++++++++++++- data/station/EPN.json | 25 ++++++++++++++++++++++++- data/station/EUN.json | 25 ++++++++++++++++++++++++- data/station/FRR.json | 27 ++++++++++++++++++++++++++- data/station/GCL.json | 25 ++++++++++++++++++++++++- data/station/GRW.json | 25 ++++++++++++++++++++++++- data/station/HLV.json | 27 ++++++++++++++++++++++++++- data/station/HPV.json | 27 ++++++++++++++++++++++++++- data/station/HVL.json | 25 ++++++++++++++++++++++++- data/station/JKN.json | 25 ++++++++++++++++++++++++- data/station/KAL.json | 25 ++++++++++++++++++++++++- data/station/KEM.json | 25 ++++++++++++++++++++++++- data/station/KRG.json | 27 ++++++++++++++++++++++++++- data/station/KRJ.json | 25 ++++++++++++++++++++++++- data/station/KTB.json | 25 ++++++++++++++++++++++++- data/station/LBD.json | 27 ++++++++++++++++++++++++++- data/station/LKS.json | 25 ++++++++++++++++++++++++- data/station/LRC.json | 27 ++++++++++++++++++++++++++- data/station/LTR.json | 25 ++++++++++++++++++++++++- data/station/LVR.json | 25 ++++++++++++++++++++++++- data/station/MAX.json | 25 ++++++++++++++++++++++++- data/station/MBT.json | 27 ++++++++++++++++++++++++++- data/station/MFL.json | 25 ++++++++++++++++++++++++- data/station/MRM.json | 27 ++++++++++++++++++++++++++- data/station/MSL.json | 25 ++++++++++++++++++++++++- data/station/NCH.json | 27 ++++++++++++++++++++++++++- data/station/NOV.json | 25 ++++++++++++++++++++++++- data/station/NPR.json | 25 ++++++++++++++++++++++++- data/station/OBV.json | 25 ++++++++++++++++++++++++- data/station/ONH.json | 27 ++++++++++++++++++++++++++- data/station/PNR.json | 25 ++++++++++++++++++++++++- data/station/PPJ.json | 27 ++++++++++++++++++++++++++- data/station/QUE.json | 25 ++++++++++++++++++++++++- data/station/RDH.json | 25 ++++++++++++++++++++++++- data/station/SBW.json | 25 ++++++++++++++++++++++++- data/station/SDM.json | 27 ++++++++++++++++++++++++++- data/station/SHW.json | 25 ++++++++++++++++++++++++- data/station/SIM.json | 25 ++++++++++++++++++++++++- data/station/SOM.json | 25 ++++++++++++++++++++++++- data/station/SPL.json | 25 ++++++++++++++++++++++++- data/station/TAP.json | 25 ++++++++++++++++++++++++- data/station/TCR.json | 25 ++++++++++++++++++++++++- data/station/TIB.json | 25 ++++++++++++++++++++++++- data/station/TLB.json | 27 ++++++++++++++++++++++++++- data/station/TPG.json | 25 ++++++++++++++++++++++++- data/station/TSG.json | 27 ++++++++++++++++++++++++++- data/station/TWR.json | 25 ++++++++++++++++++++++++- data/station/UTS.json | 25 ++++++++++++++++++++++++- data/station/WDS.json | 25 ++++++++++++++++++++++++- data/station/YCK.json | 25 ++++++++++++++++++++++++- data/station/YIS.json | 25 ++++++++++++++++++++++++- data/station/YWT.json | 25 ++++++++++++++++++++++++- 68 files changed, 1664 insertions(+), 68 deletions(-) diff --git a/data/station/ADM.json b/data/station/ADM.json index 89492f97..616744a2 100644 --- a/data/station/ADM.json +++ b/data/station/ADM.json @@ -109,7 +109,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "ADM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "ADM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/ALJ.json b/data/station/ALJ.json index 01e03169..16af65fa 100644 --- a/data/station/ALJ.json +++ b/data/station/ALJ.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "ALJ_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "ALJ_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/AMK.json b/data/station/AMK.json index f49b549d..2ec507ad 100644 --- a/data/station/AMK.json +++ b/data/station/AMK.json @@ -122,7 +122,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "AMK_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "AMK_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BBS.json b/data/station/BBS.json index 3b8cd8b3..064b666e 100644 --- a/data/station/BBS.json +++ b/data/station/BBS.json @@ -109,7 +109,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CBBS_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CBBS_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BBT.json b/data/station/BBT.json index 9168149a..be90325d 100644 --- a/data/station/BBT.json +++ b/data/station/BBT.json @@ -99,7 +99,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BBT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BBT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BDK.json b/data/station/BDK.json index 42fbdd4c..11660cbd 100644 --- a/data/station/BDK.json +++ b/data/station/BDK.json @@ -103,7 +103,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BDK_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BDK_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BDL.json b/data/station/BDL.json index 75d64949..eb8fa576 100644 --- a/data/station/BDL.json +++ b/data/station/BDL.json @@ -100,7 +100,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "BDL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BDL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BGB.json b/data/station/BGB.json index bddff86a..541e1e3b 100644 --- a/data/station/BGB.json +++ b/data/station/BGB.json @@ -97,7 +97,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BGB_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BGB_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BLY.json b/data/station/BLY.json index 27d2a0c3..68a62662 100644 --- a/data/station/BLY.json +++ b/data/station/BLY.json @@ -90,7 +90,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CBLY_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CBLY_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BNL.json b/data/station/BNL.json index 35b8faab..c74ceeb6 100644 --- a/data/station/BNL.json +++ b/data/station/BNL.json @@ -116,7 +116,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "BNL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BNL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BRH.json b/data/station/BRH.json index 1030e142..9c5fd5c8 100644 --- a/data/station/BRH.json +++ b/data/station/BRH.json @@ -109,7 +109,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TBRH_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TBRH_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CBR.json b/data/station/CBR.json index 740bc835..201b4cf9 100644 --- a/data/station/CBR.json +++ b/data/station/CBR.json @@ -103,7 +103,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CBR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CBR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CLE.json b/data/station/CLE.json index e41208c0..799f3689 100644 --- a/data/station/CLE.json +++ b/data/station/CLE.json @@ -122,7 +122,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CLE_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CLE_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CNG.json b/data/station/CNG.json index b387def5..ea04cfdf 100644 --- a/data/station/CNG.json +++ b/data/station/CNG.json @@ -100,7 +100,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CNG_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CNG_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/COM.json b/data/station/COM.json index 483e8d78..e728dc65 100644 --- a/data/station/COM.json +++ b/data/station/COM.json @@ -114,7 +114,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "COM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "COM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/DKT.json b/data/station/DKT.json index 087bb69f..08f3a531 100644 --- a/data/station/DKT.json +++ b/data/station/DKT.json @@ -91,7 +91,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CDKT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CDKT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/DVR.json b/data/station/DVR.json index bf4fdec1..9131ce5e 100644 --- a/data/station/DVR.json +++ b/data/station/DVR.json @@ -91,7 +91,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "DVR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "DVR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/EPN.json b/data/station/EPN.json index 7c030e3d..c6afb95d 100644 --- a/data/station/EPN.json +++ b/data/station/EPN.json @@ -118,7 +118,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CEPN_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CEPN_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/EUN.json b/data/station/EUN.json index 183fec91..7da66fde 100644 --- a/data/station/EUN.json +++ b/data/station/EUN.json @@ -91,7 +91,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "EUN_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "EUN_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/FRR.json b/data/station/FRR.json index 03c3b5ba..ec805ee9 100644 --- a/data/station/FRR.json +++ b/data/station/FRR.json @@ -89,7 +89,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CFRR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CFRR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/GCL.json b/data/station/GCL.json index b5486b6d..300724a2 100644 --- a/data/station/GCL.json +++ b/data/station/GCL.json @@ -88,7 +88,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "GCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "GCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/GRW.json b/data/station/GRW.json index 083bf0ab..b97810e2 100644 --- a/data/station/GRW.json +++ b/data/station/GRW.json @@ -117,7 +117,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TGRW_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TGRW_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HLV.json b/data/station/HLV.json index 59e959cc..8960f66f 100644 --- a/data/station/HLV.json +++ b/data/station/HLV.json @@ -91,7 +91,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CHLV_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CHLV_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HPV.json b/data/station/HPV.json index 635e61ab..d35add14 100644 --- a/data/station/HPV.json +++ b/data/station/HPV.json @@ -77,7 +77,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CHPV_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CHPV_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HVL.json b/data/station/HVL.json index 992c22a3..fdc534a1 100644 --- a/data/station/HVL.json +++ b/data/station/HVL.json @@ -112,7 +112,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "THVL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "THVL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/JKN.json b/data/station/JKN.json index 7d475374..277e6f44 100644 --- a/data/station/JKN.json +++ b/data/station/JKN.json @@ -91,7 +91,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "JKN_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "JKN_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KAL.json b/data/station/KAL.json index d4f858b2..90ace1b9 100644 --- a/data/station/KAL.json +++ b/data/station/KAL.json @@ -88,7 +88,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KAL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "KAL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KEM.json b/data/station/KEM.json index 509b65cd..93f080a2 100644 --- a/data/station/KEM.json +++ b/data/station/KEM.json @@ -91,7 +91,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KEM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "KEM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KRG.json b/data/station/KRG.json index 20b0b087..c925aab7 100644 --- a/data/station/KRG.json +++ b/data/station/KRG.json @@ -100,7 +100,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CKRG_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CKRG_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KRJ.json b/data/station/KRJ.json index 819b7db8..7df87fe8 100644 --- a/data/station/KRJ.json +++ b/data/station/KRJ.json @@ -100,7 +100,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "KRJ_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "KRJ_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KTB.json b/data/station/KTB.json index 2238fc4c..4a5b3cb2 100644 --- a/data/station/KTB.json +++ b/data/station/KTB.json @@ -112,7 +112,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KTB_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "KTB_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/LBD.json b/data/station/LBD.json index 3cd4a42c..e7a0ce6f 100644 --- a/data/station/LBD.json +++ b/data/station/LBD.json @@ -76,7 +76,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CLBD_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CLBD_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/LKS.json b/data/station/LKS.json index 84b47314..2b224ae0 100644 --- a/data/station/LKS.json +++ b/data/station/LKS.json @@ -91,7 +91,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "LKS_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "LKS_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/LRC.json b/data/station/LRC.json index 849c9151..f05fa4dc 100644 --- a/data/station/LRC.json +++ b/data/station/LRC.json @@ -84,7 +84,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CLRC_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CLRC_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/LTR.json b/data/station/LTR.json index 2c02612a..f8a53086 100644 --- a/data/station/LTR.json +++ b/data/station/LTR.json @@ -110,7 +110,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TLTR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TLTR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/LVR.json b/data/station/LVR.json index 58379420..eb855d24 100644 --- a/data/station/LVR.json +++ b/data/station/LVR.json @@ -89,7 +89,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "LVR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "LVR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MAX.json b/data/station/MAX.json index 8073ec8c..bad1f065 100644 --- a/data/station/MAX.json +++ b/data/station/MAX.json @@ -94,7 +94,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TMAX_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TMAX_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MBT.json b/data/station/MBT.json index 65b781d7..468d98e5 100644 --- a/data/station/MBT.json +++ b/data/station/MBT.json @@ -91,7 +91,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CMBT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CMBT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MFL.json b/data/station/MFL.json index 3efa1950..c4ea49cb 100644 --- a/data/station/MFL.json +++ b/data/station/MFL.json @@ -129,7 +129,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TMFL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TMFL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MRM.json b/data/station/MRM.json index 7b599973..6c70fff1 100644 --- a/data/station/MRM.json +++ b/data/station/MRM.json @@ -82,7 +82,32 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CMRM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CMRM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MSL.json b/data/station/MSL.json index 5958db65..a9e3e6d7 100644 --- a/data/station/MSL.json +++ b/data/station/MSL.json @@ -112,7 +112,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "MSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "MSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/NCH.json b/data/station/NCH.json index 4bbe3a33..74376514 100644 --- a/data/station/NCH.json +++ b/data/station/NCH.json @@ -119,7 +119,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CNCH_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CNCH_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/NOV.json b/data/station/NOV.json index 277afc7b..4318ba76 100644 --- a/data/station/NOV.json +++ b/data/station/NOV.json @@ -91,7 +91,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "NOV_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "NOV_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/NPR.json b/data/station/NPR.json index a6fb8e00..c0ed5963 100644 --- a/data/station/NPR.json +++ b/data/station/NPR.json @@ -85,7 +85,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TNPR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TNPR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/OBV.json b/data/station/OBV.json index a251c511..de52e456 100644 --- a/data/station/OBV.json +++ b/data/station/OBV.json @@ -85,7 +85,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TOBV_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TOBV_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/ONH.json b/data/station/ONH.json index 89b5b3a6..01c8972e 100644 --- a/data/station/ONH.json +++ b/data/station/ONH.json @@ -97,7 +97,32 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CONH_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CONH_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PNR.json b/data/station/PNR.json index e9a3afc4..8861f801 100644 --- a/data/station/PNR.json +++ b/data/station/PNR.json @@ -91,7 +91,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "PNR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PNR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PPJ.json b/data/station/PPJ.json index 7303ede9..030c00ed 100644 --- a/data/station/PPJ.json +++ b/data/station/PPJ.json @@ -78,7 +78,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CPPJ_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CPPJ_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/QUE.json b/data/station/QUE.json index bca9ac2f..16ef6167 100644 --- a/data/station/QUE.json +++ b/data/station/QUE.json @@ -97,7 +97,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "QUE_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "QUE_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/RDH.json b/data/station/RDH.json index 19bbfce2..7d15112c 100644 --- a/data/station/RDH.json +++ b/data/station/RDH.json @@ -87,7 +87,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "RDH_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "RDH_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SBW.json b/data/station/SBW.json index 0dbfcca0..66906f68 100644 --- a/data/station/SBW.json +++ b/data/station/SBW.json @@ -112,7 +112,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "SBW_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SBW_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SDM.json b/data/station/SDM.json index 4accee96..4b023aa3 100644 --- a/data/station/SDM.json +++ b/data/station/SDM.json @@ -96,7 +96,32 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CSDM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CSDM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SHW.json b/data/station/SHW.json index 3854e2b1..1e079f75 100644 --- a/data/station/SHW.json +++ b/data/station/SHW.json @@ -112,7 +112,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TSHW_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TSHW_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SIM.json b/data/station/SIM.json index fb204902..70dd8c63 100644 --- a/data/station/SIM.json +++ b/data/station/SIM.json @@ -78,7 +78,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "SIM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SIM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SOM.json b/data/station/SOM.json index a8516399..75fe21e3 100644 --- a/data/station/SOM.json +++ b/data/station/SOM.json @@ -97,7 +97,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "SOM_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SOM_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SPL.json b/data/station/SPL.json index f9ad7205..e3507819 100644 --- a/data/station/SPL.json +++ b/data/station/SPL.json @@ -101,7 +101,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TSPL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TSPL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TAP.json b/data/station/TAP.json index 78096e9d..e6c00e57 100644 --- a/data/station/TAP.json +++ b/data/station/TAP.json @@ -90,7 +90,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TAP_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TAP_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TCR.json b/data/station/TCR.json index 90d054c0..2623193c 100644 --- a/data/station/TCR.json +++ b/data/station/TCR.json @@ -91,7 +91,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TCR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TCR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TIB.json b/data/station/TIB.json index 0d225452..9b1f60f1 100644 --- a/data/station/TIB.json +++ b/data/station/TIB.json @@ -88,7 +88,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TIB_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TIB_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TLB.json b/data/station/TLB.json index 475cd3ad..6ef709b1 100644 --- a/data/station/TLB.json +++ b/data/station/TLB.json @@ -79,7 +79,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CTLB_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CTLB_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TPG.json b/data/station/TPG.json index 23713179..10ee29bd 100644 --- a/data/station/TPG.json +++ b/data/station/TPG.json @@ -127,7 +127,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TPG_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TPG_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TSG.json b/data/station/TSG.json index 02c4ff2b..ef86067f 100644 --- a/data/station/TSG.json +++ b/data/station/TSG.json @@ -99,7 +99,32 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CTSG_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CTSG_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TWR.json b/data/station/TWR.json index 108e32a7..ee556363 100644 --- a/data/station/TWR.json +++ b/data/station/TWR.json @@ -90,7 +90,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TWR_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TWR_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/UTS.json b/data/station/UTS.json index 2f0128e6..7c4c3e59 100644 --- a/data/station/UTS.json +++ b/data/station/UTS.json @@ -127,7 +127,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TUTS_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TUTS_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/WDS.json b/data/station/WDS.json index 2b86a044..f601b260 100644 --- a/data/station/WDS.json +++ b/data/station/WDS.json @@ -112,7 +112,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TWDS_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TWDS_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/YCK.json b/data/station/YCK.json index 4ff7b5e0..414cd94a 100644 --- a/data/station/YCK.json +++ b/data/station/YCK.json @@ -93,7 +93,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "YCK_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "YCK_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/YIS.json b/data/station/YIS.json index 44672624..04767848 100644 --- a/data/station/YIS.json +++ b/data/station/YIS.json @@ -121,7 +121,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "YIS_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "YIS_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/YWT.json b/data/station/YWT.json index bb7cb2ba..704b746f 100644 --- a/data/station/YWT.json +++ b/data/station/YWT.json @@ -111,7 +111,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "YWT_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "YWT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } From 4d4a65f712e2e026604d0c398ef59fa9af9f2590 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:09:20 +0800 Subject: [PATCH 04/20] feat: add standard SBS MRT platform layouts --- data/station/BCL.json | 25 ++++++++++++++++++++++++- data/station/BDM.json | 25 ++++++++++++++++++++++++- data/station/BDN.json | 25 ++++++++++++++++++++++++- data/station/BDR.json | 25 ++++++++++++++++++++++++- data/station/BGK.json | 25 ++++++++++++++++++++++++- data/station/BNK.json | 25 ++++++++++++++++++++++++- data/station/BTW.json | 25 ++++++++++++++++++++++++- data/station/CRQ.json | 25 ++++++++++++++++++++++++- data/station/CSW.json | 25 ++++++++++++++++++++++++- data/station/DTN.json | 25 ++++++++++++++++++++++++- data/station/FCN.json | 25 ++++++++++++++++++++++++- data/station/FRP.json | 25 ++++++++++++++++++++++++- data/station/GLB.json | 25 ++++++++++++++++++++++++- data/station/HGN.json | 25 ++++++++++++++++++++++++- data/station/HME.json | 25 ++++++++++++++++++++++++- data/station/HVW.json | 25 ++++++++++++++++++++++++- data/station/JLB.json | 25 ++++++++++++++++++++++++- data/station/KAP.json | 25 ++++++++++++++++++++++++- data/station/KKB.json | 25 ++++++++++++++++++++++++- data/station/KVN.json | 25 ++++++++++++++++++++++++- data/station/MTR.json | 25 ++++++++++++++++++++++++- data/station/PGC.json | 25 ++++++++++++++++++++++++- data/station/PTP.json | 25 ++++++++++++++++++++++++- data/station/RCR.json | 25 ++++++++++++++++++++++++- data/station/SAV.json | 25 ++++++++++++++++++++++++- data/station/TKK.json | 25 ++++++++++++++++++++++++- data/station/TLA.json | 25 ++++++++++++++++++++++++- data/station/TPE.json | 25 ++++++++++++++++++++++++- data/station/TPW.json | 25 ++++++++++++++++++++++++- data/station/UBI.json | 25 ++++++++++++++++++++++++- data/station/UPC.json | 25 ++++++++++++++++++++++++- data/station/WLH.json | 25 ++++++++++++++++++++++++- 32 files changed, 768 insertions(+), 32 deletions(-) diff --git a/data/station/BCL.json b/data/station/BCL.json index bd6c967b..a0105c54 100644 --- a/data/station/BCL.json +++ b/data/station/BCL.json @@ -93,7 +93,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "BCL_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BCL_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BDM.json b/data/station/BDM.json index d6afbd28..aeb24340 100644 --- a/data/station/BDM.json +++ b/data/station/BDM.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BDM_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BDM_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BDN.json b/data/station/BDN.json index 9a124639..b1f5e1db 100644 --- a/data/station/BDN.json +++ b/data/station/BDN.json @@ -97,7 +97,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BDN_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BDN_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BDR.json b/data/station/BDR.json index 389fe394..58bd4664 100644 --- a/data/station/BDR.json +++ b/data/station/BDR.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BDR_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BDR_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BGK.json b/data/station/BGK.json index 68c01069..5ee5fc22 100644 --- a/data/station/BGK.json +++ b/data/station/BGK.json @@ -86,7 +86,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BGK_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BGK_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BNK.json b/data/station/BNK.json index c827c060..75a046b0 100644 --- a/data/station/BNK.json +++ b/data/station/BNK.json @@ -94,7 +94,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BNK_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BNK_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BTW.json b/data/station/BTW.json index 62e82d95..ab525d99 100644 --- a/data/station/BTW.json +++ b/data/station/BTW.json @@ -96,7 +96,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BTW_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BTW_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CRQ.json b/data/station/CRQ.json index 07e40357..218cf34d 100644 --- a/data/station/CRQ.json +++ b/data/station/CRQ.json @@ -110,7 +110,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CRQ_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CRQ_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CSW.json b/data/station/CSW.json index 87545756..9267c12d 100644 --- a/data/station/CSW.json +++ b/data/station/CSW.json @@ -77,7 +77,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CSW_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CSW_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/DTN.json b/data/station/DTN.json index d81a1cab..f22c4f23 100644 --- a/data/station/DTN.json +++ b/data/station/DTN.json @@ -110,7 +110,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "DTN_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "DTN_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/FCN.json b/data/station/FCN.json index 0f070361..01863223 100644 --- a/data/station/FCN.json +++ b/data/station/FCN.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "FCN_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "FCN_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/FRP.json b/data/station/FRP.json index e8eda746..c76cb81d 100644 --- a/data/station/FRP.json +++ b/data/station/FRP.json @@ -127,7 +127,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "FRP_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "FRP_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/GLB.json b/data/station/GLB.json index b901536a..208d3c5f 100644 --- a/data/station/GLB.json +++ b/data/station/GLB.json @@ -86,7 +86,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "GLB_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "GLB_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HGN.json b/data/station/HGN.json index 2967febd..34ddf3af 100644 --- a/data/station/HGN.json +++ b/data/station/HGN.json @@ -99,7 +99,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "HGN_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "HGN_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HME.json b/data/station/HME.json index 5e031782..be344a28 100644 --- a/data/station/HME.json +++ b/data/station/HME.json @@ -77,7 +77,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "HME_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "HME_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HVW.json b/data/station/HVW.json index ede99298..8d4fb1d0 100644 --- a/data/station/HVW.json +++ b/data/station/HVW.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "HVW_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "HVW_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/JLB.json b/data/station/JLB.json index b770359c..167b5b61 100644 --- a/data/station/JLB.json +++ b/data/station/JLB.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "JLB_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "JLB_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KAP.json b/data/station/KAP.json index 87b030b3..846c466a 100644 --- a/data/station/KAP.json +++ b/data/station/KAP.json @@ -93,7 +93,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KAP_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "KAP_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KKB.json b/data/station/KKB.json index 9c34e113..fce76f8d 100644 --- a/data/station/KKB.json +++ b/data/station/KKB.json @@ -85,7 +85,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KKB_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "KKB_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KVN.json b/data/station/KVN.json index 2e1ccd80..136d560c 100644 --- a/data/station/KVN.json +++ b/data/station/KVN.json @@ -92,7 +92,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KVN_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "KVN_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MTR.json b/data/station/MTR.json index 832182d8..be655ff8 100644 --- a/data/station/MTR.json +++ b/data/station/MTR.json @@ -86,7 +86,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "MTR_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "MTR_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PGC.json b/data/station/PGC.json index d8f95637..334343c5 100644 --- a/data/station/PGC.json +++ b/data/station/PGC.json @@ -70,7 +70,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "PGC_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PGC_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PTP.json b/data/station/PTP.json index 293cef03..1e08b0bc 100644 --- a/data/station/PTP.json +++ b/data/station/PTP.json @@ -95,7 +95,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "PTP_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PTP_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/RCR.json b/data/station/RCR.json index b894785f..ed402cb5 100644 --- a/data/station/RCR.json +++ b/data/station/RCR.json @@ -86,7 +86,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "RCR_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "RCR_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SAV.json b/data/station/SAV.json index a6aefeee..7341dbf5 100644 --- a/data/station/SAV.json +++ b/data/station/SAV.json @@ -85,7 +85,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "SAV_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "SAV_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TKK.json b/data/station/TKK.json index eaa89911..13f25950 100644 --- a/data/station/TKK.json +++ b/data/station/TKK.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TKK_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "TKK_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TLA.json b/data/station/TLA.json index 9cccf578..30a9ace9 100644 --- a/data/station/TLA.json +++ b/data/station/TLA.json @@ -90,7 +90,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TLA_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "TLA_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TPE.json b/data/station/TPE.json index 8057fb1f..b6e3689e 100644 --- a/data/station/TPE.json +++ b/data/station/TPE.json @@ -107,7 +107,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TPE_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "TPE_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TPW.json b/data/station/TPW.json index a1614549..bd5c27b8 100644 --- a/data/station/TPW.json +++ b/data/station/TPW.json @@ -87,7 +87,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TPW_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "TPW_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/UBI.json b/data/station/UBI.json index 358c03a1..2ff813b0 100644 --- a/data/station/UBI.json +++ b/data/station/UBI.json @@ -85,7 +85,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "UBI_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "UBI_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/UPC.json b/data/station/UPC.json index dff8a7c5..9e62e987 100644 --- a/data/station/UPC.json +++ b/data/station/UPC.json @@ -106,7 +106,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "UPC_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "UPC_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/WLH.json b/data/station/WLH.json index 94e24176..92986068 100644 --- a/data/station/WLH.json +++ b/data/station/WLH.json @@ -93,7 +93,30 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "WLH_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "WLH_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } From 3f0f5833e056682609520441f6437ccf7a0cf756 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:12:26 +0800 Subject: [PATCH 05/20] feat: add verified interchange platform layouts --- data/station/BFT.json | 94 ++++++++++++++++++++++++++++++++++++++++++- data/station/BGS.json | 47 +++++++++++++++++++++- data/station/BNV.json | 49 +++++++++++++++++++++- data/station/BSH.json | 49 +++++++++++++++++++++- data/station/BTN.json | 49 +++++++++++++++++++++- data/station/CTH.json | 94 ++++++++++++++++++++++++++++++++++++++++++- data/station/CTN.json | 47 +++++++++++++++++++++- data/station/DBG.json | 69 ++++++++++++++++++++++++++++++- 8 files changed, 488 insertions(+), 10 deletions(-) diff --git a/data/station/BFT.json b/data/station/BFT.json index cfe5e2b1..7811a93f 100644 --- a/data/station/BFT.json +++ b/data/station/BFT.json @@ -164,7 +164,97 @@ } } ], - "platforms": [], - "transferPaths": [] + "platforms": [ + { + "id": "BFT_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BFT_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BFT_DTL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BFT_CCL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], + "transferPaths": [ + { + "id": "BFT_XFER_A_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BFT_DTL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BFT_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BFT_XFER_C_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BFT_DTL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BFT_CCL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/BGS.json b/data/station/BGS.json index 2cf01ed5..c59ab50a 100644 --- a/data/station/BGS.json +++ b/data/station/BGS.json @@ -156,7 +156,52 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "BGS_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BGS_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BGS_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BGS_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BNV.json b/data/station/BNV.json index e86ac8ab..52b784b4 100644 --- a/data/station/BNV.json +++ b/data/station/BNV.json @@ -141,7 +141,54 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BNV_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BNV_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BNV_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BNV_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BSH.json b/data/station/BSH.json index 1584cb5e..68149227 100644 --- a/data/station/BSH.json +++ b/data/station/BSH.json @@ -150,7 +150,54 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "BSH_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BSH_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "BSH_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BSH_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BTN.json b/data/station/BTN.json index 5b1b9f60..ad2b979e 100644 --- a/data/station/BTN.json +++ b/data/station/BTN.json @@ -127,7 +127,54 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BTN_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BTN_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BTN_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BTN_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CTH.json b/data/station/CTH.json index dcbac432..d75dc3f3 100644 --- a/data/station/CTH.json +++ b/data/station/CTH.json @@ -139,7 +139,97 @@ "paidArea": false } ], - "platforms": [], - "transferPaths": [] + "platforms": [ + { + "id": "CTH_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CTH_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CTH_NSL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CTH_EWL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + } + ], + "transferPaths": [ + { + "id": "CTH_XFER_A_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTH_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTH_EWL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CTH_XFER_C_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTH_NSL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTH_EWL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/CTN.json b/data/station/CTN.json index 96d60053..d45f7880 100644 --- a/data/station/CTN.json +++ b/data/station/CTN.json @@ -157,7 +157,52 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CTN_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CTN_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CTN_DTL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CTN_DTL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/DBG.json b/data/station/DBG.json index aaa49938..a51aecd0 100644 --- a/data/station/DBG.json +++ b/data/station/DBG.json @@ -178,7 +178,74 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "DBG_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "DBG_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "DBG_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "DBG_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "DBG_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "DBG_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } From becf0ea96c3bedcd4cbd01d0f2dc80f407d593ff Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:18:04 +0800 Subject: [PATCH 06/20] feat: add special station platform layouts --- data/station/BSR.json | 25 +++++++- data/station/CCK.json | 69 ++++++++++++++++++++- data/station/GRB.json | 25 +++++++- data/station/HBF.json | 49 ++++++++++++++- data/station/JUR.json | 138 +++++++++++++++++++++++++++++++++++++++++- data/station/LTI.json | 47 +++++++++++++- data/station/MPS.json | 49 ++++++++++++++- data/station/MSP.json | 25 +++++++- data/station/NEW.json | 47 +++++++++++++- data/station/ORC.json | 47 +++++++++++++- data/station/OTP.json | 69 ++++++++++++++++++++- data/station/PGL.json | 47 +++++++++++++- data/station/PMN.json | 49 ++++++++++++++- data/station/PSR.json | 25 +++++++- data/station/PYL.json | 73 +++++++++++++++++++++- data/station/RFP.json | 94 +++++++++++++++++++++++++++- data/station/SER.json | 49 ++++++++++++++- data/station/SKG.json | 47 +++++++++++++- data/station/STV.json | 47 +++++++++++++- data/station/TAM.json | 47 +++++++++++++- data/station/TLK.json | 25 +++++++- data/station/WDL.json | 47 +++++++++++++- data/station/WDN.json | 25 +++++++- data/station/XPO.json | 47 +++++++++++++- 24 files changed, 1186 insertions(+), 26 deletions(-) diff --git a/data/station/BSR.json b/data/station/BSR.json index 4c4731a6..4b731fa0 100644 --- a/data/station/BSR.json +++ b/data/station/BSR.json @@ -94,7 +94,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BSR_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "BSR_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CCK.json b/data/station/CCK.json index be55fa6a..31d4a720 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -145,7 +145,74 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CCK_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CCK_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CCK_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "CCK_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "CCK_BPLRT_3", + "label": "3", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "CCK_BPLRT_4", + "label": "4", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/GRB.json b/data/station/GRB.json index 4ab5fcf3..5f07f7c5 100644 --- a/data/station/GRB.json +++ b/data/station/GRB.json @@ -94,7 +94,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "GRB_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "GRB_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/HBF.json b/data/station/HBF.json index 81f641de..0d24c528 100644 --- a/data/station/HBF.json +++ b/data/station/HBF.json @@ -116,7 +116,54 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "HBF_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "HBF_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "HBF_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "HBF_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/JUR.json b/data/station/JUR.json index d7f02766..be45fccf 100644 --- a/data/station/JUR.json +++ b/data/station/JUR.json @@ -134,7 +134,141 @@ } } ], - "platforms": [], - "transferPaths": [] + "platforms": [ + { + "id": "JUR_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "JUR_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "JUR_EWL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "JUR_NSL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "JUR_NSL_E", + "label": "E", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "JUR_EWL_F", + "label": "F", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], + "transferPaths": [ + { + "id": "JUR_XFER_A_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_EWL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_C_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_EWL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_NSL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_E_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_NSL_E", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_EWL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/LTI.json b/data/station/LTI.json index 5398fbe1..42947d23 100644 --- a/data/station/LTI.json +++ b/data/station/LTI.json @@ -160,7 +160,52 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "LTI_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "LTI_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "LTI_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "LTI_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MPS.json b/data/station/MPS.json index f5632ef9..29d375ab 100644 --- a/data/station/MPS.json +++ b/data/station/MPS.json @@ -153,7 +153,54 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "MPS_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "MPS_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "MPS_DTL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "MPS_DTL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MSP.json b/data/station/MSP.json index f2c6ce19..0f445ee7 100644 --- a/data/station/MSP.json +++ b/data/station/MSP.json @@ -73,7 +73,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "MSP_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "MSP_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/NEW.json b/data/station/NEW.json index ebb61fa7..4bbafff1 100644 --- a/data/station/NEW.json +++ b/data/station/NEW.json @@ -137,7 +137,52 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "NEW_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "NEW_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "NEW_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "NEW_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/ORC.json b/data/station/ORC.json index 6b835c70..4f4ac9d5 100644 --- a/data/station/ORC.json +++ b/data/station/ORC.json @@ -207,7 +207,52 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "ORC_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "ORC_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "ORC_TEL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "ORC_TEL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/OTP.json b/data/station/OTP.json index 6e96503b..e536fc5f 100644 --- a/data/station/OTP.json +++ b/data/station/OTP.json @@ -210,7 +210,74 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "OTP_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "OTP_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "OTP_NEL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "OTP_NEL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "OTP_TEL_E", + "label": "E", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "OTP_TEL_F", + "label": "F", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PGL.json b/data/station/PGL.json index c1c52139..d1a2bcf8 100644 --- a/data/station/PGL.json +++ b/data/station/PGL.json @@ -117,7 +117,52 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "PGL_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PGL_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PGL_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW", + "PGLRT_E_CCW" + ], + "accessPoints": [] + }, + { + "id": "PGL_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW", + "PGLRT_E_CW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PMN.json b/data/station/PMN.json index 6e709594..3891777e 100644 --- a/data/station/PMN.json +++ b/data/station/PMN.json @@ -163,7 +163,54 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "PMN_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PMN_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PMN_DTL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PMN_DTL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PSR.json b/data/station/PSR.json index 674f6404..a30096bf 100644 --- a/data/station/PSR.json +++ b/data/station/PSR.json @@ -82,7 +82,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "PSR_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PSR_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PYL.json b/data/station/PYL.json index 41cfce58..8643b76c 100644 --- a/data/station/PYL.json +++ b/data/station/PYL.json @@ -153,7 +153,78 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "PYL_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PYL_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "PYL_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PYL_CCL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PYL_CCL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PYL_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/RFP.json b/data/station/RFP.json index ecb7189a..f7c11454 100644 --- a/data/station/RFP.json +++ b/data/station/RFP.json @@ -187,7 +187,97 @@ "paidArea": false } ], - "platforms": [], - "transferPaths": [] + "platforms": [ + { + "id": "RFP_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "RFP_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "RFP_EWL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "RFP_NSL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + } + ], + "transferPaths": [ + { + "id": "RFP_XFER_A_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "RFP_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "RFP_NSL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "RFP_XFER_C_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "RFP_EWL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "RFP_NSL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": 0, + "classification": "same_platform", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/SER.json b/data/station/SER.json index 03116699..3ddafdc0 100644 --- a/data/station/SER.json +++ b/data/station/SER.json @@ -172,7 +172,54 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "SER_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SER_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SER_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "SER_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SKG.json b/data/station/SKG.json index 7399ca1f..ed7a2a78 100644 --- a/data/station/SKG.json +++ b/data/station/SKG.json @@ -106,7 +106,52 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "SKG_NEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SKG_NEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NEL", + "serviceIds": [ + "NEL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "SKG_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CCW", + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "SKG_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CW", + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/STV.json b/data/station/STV.json index f46218b8..77517b58 100644 --- a/data/station/STV.json +++ b/data/station/STV.json @@ -150,7 +150,52 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "STV_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "STV_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "STV_TEL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "STV_TEL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TAM.json b/data/station/TAM.json index 7f900c04..6c3b0d6b 100644 --- a/data/station/TAM.json +++ b/data/station/TAM.json @@ -150,7 +150,52 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TAM_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TAM_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TAM_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "TAM_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TLK.json b/data/station/TLK.json index caf10c9b..dc917ee2 100644 --- a/data/station/TLK.json +++ b/data/station/TLK.json @@ -73,7 +73,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TLK_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TLK_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/WDL.json b/data/station/WDL.json index eb1549f7..1227a713 100644 --- a/data/station/WDL.json +++ b/data/station/WDL.json @@ -162,7 +162,52 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "WDL_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "WDL_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "WDL_TEL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "WDL_TEL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/WDN.json b/data/station/WDN.json index 3991067b..645f2d80 100644 --- a/data/station/WDN.json +++ b/data/station/WDN.json @@ -68,7 +68,30 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "WDN_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "WDN_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/XPO.json b/data/station/XPO.json index fdab2829..54c94ae5 100644 --- a/data/station/XPO.json +++ b/data/station/XPO.json @@ -158,7 +158,52 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "XPO_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_CG_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "XPO_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_CG_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "XPO_DTL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_W" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "XPO_DTL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], "transferPaths": [] } } From 9c2cfb99d92359136a06516f8bfb3b528647122d Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:25:34 +0800 Subject: [PATCH 07/20] feat: complete operational MRT platform layouts --- data/station/AMK.json | 22 +++++++++++++ data/station/BKP.json | 51 ++++++++++++++++++++++++++++++ data/station/CGA.json | 29 +++++++++++++++++ data/station/CTM.json | 33 ++++++++++++++++++- data/station/KPL.json | 33 ++++++++++++++++++- data/station/KTP.json | 29 +++++++++++++++++ data/station/MPR.json | 29 +++++++++++++++++ data/station/MRB.json | 73 +++++++++++++++++++++++++++++++++++++++++++ data/station/MTC.json | 29 +++++++++++++++++ data/station/PER.json | 33 ++++++++++++++++++- data/station/SGL.json | 29 +++++++++++++++++ data/station/TKT.json | 29 +++++++++++++++++ data/station/TNM.json | 51 ++++++++++++++++++++++++++++++ data/station/TRH.json | 29 +++++++++++++++++ 14 files changed, 496 insertions(+), 3 deletions(-) diff --git a/data/station/AMK.json b/data/station/AMK.json index 2ec507ad..afbb11e1 100644 --- a/data/station/AMK.json +++ b/data/station/AMK.json @@ -134,6 +134,28 @@ "doorCount": 24, "accessPoints": [] }, + { + "id": "AMK_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "AMK_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, { "id": "AMK_B", "label": "B", diff --git a/data/station/BKP.json b/data/station/BKP.json index d12f5ce2..6bd27fed 100644 --- a/data/station/BKP.json +++ b/data/station/BKP.json @@ -85,5 +85,56 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "BKP_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "BKP_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "BKP_DTL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "BKP_DTL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "DTL", + "serviceIds": [ + "DTL_MAIN_E" + ], + "doorCount": 12, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/CGA.json b/data/station/CGA.json index 8d131d35..b827b162 100644 --- a/data/station/CGA.json +++ b/data/station/CGA.json @@ -52,5 +52,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "CGA_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_CG_W" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "CGA_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_CG_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/CTM.json b/data/station/CTM.json index ba6cc8d2..6aa8dd55 100644 --- a/data/station/CTM.json +++ b/data/station/CTM.json @@ -24,5 +24,36 @@ "public-transport-security-command", "cantonment-police-complex" ], - "townId": "outram" + "townId": "outram", + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "CTM_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "CTM_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], + "transferPaths": [] + } } diff --git a/data/station/KPL.json b/data/station/KPL.json index 4ed1115b..d8a01b77 100644 --- a/data/station/KPL.json +++ b/data/station/KPL.json @@ -24,5 +24,36 @@ "harbourfront-centre", "sentosa-gateway" ], - "townId": "bukit-merah" + "townId": "bukit-merah", + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "KPL_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "KPL_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], + "transferPaths": [] + } } diff --git a/data/station/KTP.json b/data/station/KTP.json index fbd656f8..0e58d68d 100644 --- a/data/station/KTP.json +++ b/data/station/KTP.json @@ -62,5 +62,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "KTP_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "KTP_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/MPR.json b/data/station/MPR.json index ba1e8f67..1c62adff 100644 --- a/data/station/MPR.json +++ b/data/station/MPR.json @@ -62,5 +62,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "MPR_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "MPR_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/MRB.json b/data/station/MRB.json index 4cc3a0ed..87e5db2e 100644 --- a/data/station/MRB.json +++ b/data/station/MRB.json @@ -134,5 +134,78 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "MRB_NSL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_N" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "MRB_NSL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "NSL", + "serviceIds": [ + "NSL_MAIN_S" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "MRB_CCL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "MRB_CCL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "MRB_TEL_E", + "label": "E", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "MRB_TEL_F", + "label": "F", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/MTC.json b/data/station/MTC.json index f8e81012..d6424f04 100644 --- a/data/station/MTC.json +++ b/data/station/MTC.json @@ -62,5 +62,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "MTC_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "MTC_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/PER.json b/data/station/PER.json index 0a9427f4..f34650c1 100644 --- a/data/station/PER.json +++ b/data/station/PER.json @@ -25,5 +25,36 @@ "chinatown", "pearls-hill-city-park" ], - "townId": "downtown-core" + "townId": "downtown-core", + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "PER_CCL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CCW", + "CCL_LOOP_CCW" + ], + "doorCount": 12, + "accessPoints": [] + }, + { + "id": "PER_CCL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "CCL", + "serviceIds": [ + "CCL_BRANCH_CW", + "CCL_LOOP_CW" + ], + "doorCount": 12, + "accessPoints": [] + } + ], + "transferPaths": [] + } } diff --git a/data/station/SGL.json b/data/station/SGL.json index 6984d3c0..82002cce 100644 --- a/data/station/SGL.json +++ b/data/station/SGL.json @@ -61,5 +61,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "SGL_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "SGL_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/TKT.json b/data/station/TKT.json index 230dec89..44c9625c 100644 --- a/data/station/TKT.json +++ b/data/station/TKT.json @@ -62,5 +62,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "TKT_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TKT_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/TNM.json b/data/station/TNM.json index 53ff880c..d97e828f 100644 --- a/data/station/TNM.json +++ b/data/station/TNM.json @@ -75,5 +75,56 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "TNM_EWL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TNM_EWL_D", + "label": "D", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_CG_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TNM_EWL_E", + "label": "E", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_CG_E" + ], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TNM_EWL_F", + "label": "F", + "lastUpdated": "2026-07-18", + "lineId": "EWL", + "serviceIds": [ + "EWL_MAIN_W" + ], + "doorCount": 24, + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/TRH.json b/data/station/TRH.json index c939fe6a..f28f11b1 100644 --- a/data/station/TRH.json +++ b/data/station/TRH.json @@ -62,5 +62,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "TRH_TEL_A", + "label": "A", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_S" + ], + "doorCount": 20, + "accessPoints": [] + }, + { + "id": "TRH_TEL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "lineId": "TEL", + "serviceIds": [ + "TEL_MAIN_N" + ], + "doorCount": 20, + "accessPoints": [] + } + ], + "transferPaths": [] } } From f083fa1e7200a41bbe68ea6dea8071047b95ca86 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:30:13 +0800 Subject: [PATCH 08/20] feat: add canonical LRT platform layouts --- data/station/BAK.json | 23 ++++++++++++++++++++++- data/station/BKT.json | 27 +++++++++++++++++++++++++++ data/station/CGL.json | 23 ++++++++++++++++++++++- data/station/COV.json | 23 ++++++++++++++++++++++- data/station/CPV.json | 23 ++++++++++++++++++++++- data/station/CRE.json | 23 ++++++++++++++++++++++- data/station/DAM.json | 23 ++++++++++++++++++++++- data/station/FJR.json | 27 +++++++++++++++++++++++++++ data/station/FMW.json | 23 ++++++++++++++++++++++- data/station/FNV.json | 23 ++++++++++++++++++++++- data/station/JLP.json | 27 +++++++++++++++++++++++++++ data/station/KDL.json | 23 ++++++++++++++++++++++- data/station/KGK.json | 23 ++++++++++++++++++++++- data/station/KPG.json | 23 ++++++++++++++++++++++- data/station/KTH.json | 29 +++++++++++++++++++++++++++++ data/station/LYR.json | 23 ++++++++++++++++++++++- data/station/MRD.json | 23 ++++++++++++++++++++++- data/station/NBG.json | 23 ++++++++++++++++++++++- data/station/OAS.json | 23 ++++++++++++++++++++++- data/station/PGP.json | 23 ++++++++++++++++++++++- data/station/PND.json | 27 +++++++++++++++++++++++++++ data/station/PNX.json | 29 +++++++++++++++++++++++++++++ data/station/PTR.json | 27 +++++++++++++++++++++++++++ data/station/RIV.json | 23 ++++++++++++++++++++++- data/station/RMB.json | 23 ++++++++++++++++++++++- data/station/RNG.json | 23 ++++++++++++++++++++++- data/station/RNJ.json | 23 ++++++++++++++++++++++- data/station/SGR.json | 27 +++++++++++++++++++++++++++ data/station/SHV.json | 29 +++++++++++++++++++++++++++++ data/station/SMD.json | 23 ++++++++++++++++++++++- data/station/SMG.json | 23 ++++++++++++++++++++++- data/station/SMK.json | 23 ++++++++++++++++++++++- data/station/SNJ.json | 27 +++++++++++++++++++++++++++ data/station/STK.json | 23 ++++++++++++++++++++++- data/station/TKG.json | 23 ++++++++++++++++++++++- data/station/TKL.json | 23 ++++++++++++++++++++++- data/station/TKW.json | 29 +++++++++++++++++++++++++++++ data/station/TNG.json | 23 ++++++++++++++++++++++- 38 files changed, 899 insertions(+), 27 deletions(-) diff --git a/data/station/BAK.json b/data/station/BAK.json index 726776b6..640b1393 100644 --- a/data/station/BAK.json +++ b/data/station/BAK.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "BAK_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "BAK_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/BKT.json b/data/station/BKT.json index 10036972..1dc964f9 100644 --- a/data/station/BKT.json +++ b/data/station/BKT.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "BKT_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "BKT_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/CGL.json b/data/station/CGL.json index 6f924abd..724c1081 100644 --- a/data/station/CGL.json +++ b/data/station/CGL.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CGL_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "CGL_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/COV.json b/data/station/COV.json index f5bc4554..2776cb4a 100644 --- a/data/station/COV.json +++ b/data/station/COV.json @@ -40,7 +40,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "COV_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "COV_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CPV.json b/data/station/CPV.json index cb275973..21c95e66 100644 --- a/data/station/CPV.json +++ b/data/station/CPV.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "CPV_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "CPV_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/CRE.json b/data/station/CRE.json index 72c65211..1c13422a 100644 --- a/data/station/CRE.json +++ b/data/station/CRE.json @@ -40,7 +40,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "CRE_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "CRE_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/DAM.json b/data/station/DAM.json index 916b3330..93128e97 100644 --- a/data/station/DAM.json +++ b/data/station/DAM.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "DAM_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "DAM_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/FJR.json b/data/station/FJR.json index 0cba3467..af106e8e 100644 --- a/data/station/FJR.json +++ b/data/station/FJR.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "FJR_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "FJR_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/FMW.json b/data/station/FMW.json index 8bbdb42f..a907a8e5 100644 --- a/data/station/FMW.json +++ b/data/station/FMW.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "FMW_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "FMW_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/FNV.json b/data/station/FNV.json index 94866e7f..d8330edf 100644 --- a/data/station/FNV.json +++ b/data/station/FNV.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "FNV_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "FNV_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/JLP.json b/data/station/JLP.json index 3baaabaf..dffbefb4 100644 --- a/data/station/JLP.json +++ b/data/station/JLP.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "JLP_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "JLP_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/KDL.json b/data/station/KDL.json index df28ce9e..1e99a949 100644 --- a/data/station/KDL.json +++ b/data/station/KDL.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "KDL_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "KDL_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KGK.json b/data/station/KGK.json index 564d379d..91b4ead0 100644 --- a/data/station/KGK.json +++ b/data/station/KGK.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KGK_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "KGK_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KPG.json b/data/station/KPG.json index e7268153..6f178b74 100644 --- a/data/station/KPG.json +++ b/data/station/KPG.json @@ -49,7 +49,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "KPG_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "KPG_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/KTH.json b/data/station/KTH.json index cafd21ff..71a4853b 100644 --- a/data/station/KTH.json +++ b/data/station/KTH.json @@ -60,5 +60,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "KTH_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "KTH_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/LYR.json b/data/station/LYR.json index b698e66b..00d05fa7 100644 --- a/data/station/LYR.json +++ b/data/station/LYR.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "LYR_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "LYR_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/MRD.json b/data/station/MRD.json index 240aa005..b9ecfc30 100644 --- a/data/station/MRD.json +++ b/data/station/MRD.json @@ -40,7 +40,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "MRD_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "MRD_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/NBG.json b/data/station/NBG.json index 4be9eb25..c5637437 100644 --- a/data/station/NBG.json +++ b/data/station/NBG.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "NBG_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "NBG_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/OAS.json b/data/station/OAS.json index fd7f4044..e174051d 100644 --- a/data/station/OAS.json +++ b/data/station/OAS.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "OAS_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "OAS_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PGP.json b/data/station/PGP.json index 6a421fff..410083f9 100644 --- a/data/station/PGP.json +++ b/data/station/PGP.json @@ -49,7 +49,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "PGP_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "PGP_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/PND.json b/data/station/PND.json index 4cb74b44..d21ae9c8 100644 --- a/data/station/PND.json +++ b/data/station/PND.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "PND_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "PND_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/PNX.json b/data/station/PNX.json index 062ca786..79ee9590 100644 --- a/data/station/PNX.json +++ b/data/station/PNX.json @@ -60,5 +60,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "PNX_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "PNX_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/PTR.json b/data/station/PTR.json index 0be76773..f518c2f4 100644 --- a/data/station/PTR.json +++ b/data/station/PTR.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "PTR_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "PTR_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/RIV.json b/data/station/RIV.json index b18cd104..239c6c5b 100644 --- a/data/station/RIV.json +++ b/data/station/RIV.json @@ -47,7 +47,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "RIV_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "RIV_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/RMB.json b/data/station/RMB.json index 01315852..edcad55d 100644 --- a/data/station/RMB.json +++ b/data/station/RMB.json @@ -46,7 +46,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "RMB_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "RMB_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/RNG.json b/data/station/RNG.json index 66db5e05..6e0e0557 100644 --- a/data/station/RNG.json +++ b/data/station/RNG.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "RNG_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CW" + ], + "accessPoints": [] + }, + { + "id": "RNG_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_E_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/RNJ.json b/data/station/RNJ.json index c2589ce1..8f9b098b 100644 --- a/data/station/RNJ.json +++ b/data/station/RNJ.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "RNJ_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "RNJ_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SGR.json b/data/station/SGR.json index e3fdda58..0ef78c85 100644 --- a/data/station/SGR.json +++ b/data/station/SGR.json @@ -62,5 +62,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "SGR_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "SGR_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/SHV.json b/data/station/SHV.json index 0a760137..e07d03de 100644 --- a/data/station/SHV.json +++ b/data/station/SHV.json @@ -62,5 +62,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "SHV_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "SHV_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/SMD.json b/data/station/SMD.json index a056ea4f..afa6c341 100644 --- a/data/station/SMD.json +++ b/data/station/SMD.json @@ -49,7 +49,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "SMD_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "SMD_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SMG.json b/data/station/SMG.json index 20a485a2..9319917b 100644 --- a/data/station/SMG.json +++ b/data/station/SMG.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "SMG_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "SMG_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SMK.json b/data/station/SMK.json index 87e37e4e..dea232be 100644 --- a/data/station/SMK.json +++ b/data/station/SMK.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "SMK_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "SMK_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/SNJ.json b/data/station/SNJ.json index b5433002..3cc7bc66 100644 --- a/data/station/SNJ.json +++ b/data/station/SNJ.json @@ -61,5 +61,32 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "SNJ_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "SNJ_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/STK.json b/data/station/STK.json index b0b9f62c..593866e5 100644 --- a/data/station/STK.json +++ b/data/station/STK.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "STK_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "STK_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TKG.json b/data/station/TKG.json index aaf8f2ea..e3a5cd54 100644 --- a/data/station/TKG.json +++ b/data/station/TKG.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TKG_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "TKG_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TKL.json b/data/station/TKL.json index 5d3ee7c0..558a1e42 100644 --- a/data/station/TKL.json +++ b/data/station/TKL.json @@ -47,7 +47,28 @@ } } ], - "platforms": [], + "platforms": [ + { + "id": "TKL_PGLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "TKL_PGLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "PGLRT", + "serviceIds": [ + "PGLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } diff --git a/data/station/TKW.json b/data/station/TKW.json index e571906f..bc6f8913 100644 --- a/data/station/TKW.json +++ b/data/station/TKW.json @@ -61,5 +61,34 @@ } } ] + }, + "layout": { + "levels": [], + "exits": [], + "platforms": [ + { + "id": "TKW_BPLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + }, + { + "id": "TKW_BPLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "BPLRT", + "serviceIds": [ + "BPLRT_A", + "BPLRT_B" + ], + "accessPoints": [] + } + ], + "transferPaths": [] } } diff --git a/data/station/TNG.json b/data/station/TNG.json index e4a608f5..128d32e7 100644 --- a/data/station/TNG.json +++ b/data/station/TNG.json @@ -41,7 +41,28 @@ "paidArea": false } ], - "platforms": [], + "platforms": [ + { + "id": "TNG_SKLRT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CW" + ], + "accessPoints": [] + }, + { + "id": "TNG_SKLRT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "lineId": "SKLRT", + "serviceIds": [ + "SKLRT_W_CCW" + ], + "accessPoints": [] + } + ], "transferPaths": [] } } From ecc42e6e3d8f2826c522e1df5c7b5a88d1b8c031 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 01:34:42 +0800 Subject: [PATCH 09/20] feat: add canonical interchange transfer paths --- data/station/BFT.json | 44 +++++++ data/station/BGS.json | 91 +++++++++++++- data/station/BKP.json | 91 +++++++++++++- data/station/BNV.json | 91 +++++++++++++- data/station/BSH.json | 91 +++++++++++++- data/station/BTN.json | 91 +++++++++++++- data/station/CCK.json | 179 +++++++++++++++++++++++++++- data/station/CDT.json | 91 +++++++++++++- data/station/CTH.json | 44 +++++++ data/station/CTN.json | 91 +++++++++++++- data/station/DBG.json | 267 +++++++++++++++++++++++++++++++++++++++++- data/station/HBF.json | 91 +++++++++++++- data/station/JUR.json | 132 +++++++++++++++++++++ data/station/LTI.json | 91 +++++++++++++- data/station/MPS.json | 91 +++++++++++++- data/station/MRB.json | 267 +++++++++++++++++++++++++++++++++++++++++- data/station/NEW.json | 91 +++++++++++++- data/station/ORC.json | 91 +++++++++++++- data/station/OTP.json | 267 +++++++++++++++++++++++++++++++++++++++++- data/station/PGL.json | 91 +++++++++++++- data/station/PMN.json | 91 +++++++++++++- data/station/PYL.json | 179 +++++++++++++++++++++++++++- data/station/RFP.json | 44 +++++++ data/station/SER.json | 91 +++++++++++++- data/station/SKG.json | 91 +++++++++++++- data/station/STV.json | 91 +++++++++++++- data/station/TAM.json | 91 +++++++++++++- data/station/WDL.json | 91 +++++++++++++- data/station/XPO.json | 91 +++++++++++++- 29 files changed, 3218 insertions(+), 25 deletions(-) diff --git a/data/station/BFT.json b/data/station/BFT.json index 7811a93f..66e1ead7 100644 --- a/data/station/BFT.json +++ b/data/station/BFT.json @@ -254,6 +254,50 @@ "classification": "same_platform", "estimatedTraversalSeconds": null, "distanceMeters": null + }, + { + "id": "BFT_XFER_DTL_A_CCL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BFT_DTL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BFT_CCL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BFT_XFER_CCL_B_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BFT_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BFT_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null } ] } diff --git a/data/station/BGS.json b/data/station/BGS.json index c59ab50a..c936eaee 100644 --- a/data/station/BGS.json +++ b/data/station/BGS.json @@ -202,6 +202,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "BGS_XFER_EWL_A_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BGS_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BGS_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BGS_XFER_EWL_A_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BGS_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BGS_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BGS_XFER_EWL_B_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BGS_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BGS_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BGS_XFER_EWL_B_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BGS_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BGS_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/BKP.json b/data/station/BKP.json index 6bd27fed..8b8cc79f 100644 --- a/data/station/BKP.json +++ b/data/station/BKP.json @@ -135,6 +135,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "BKP_XFER_BPLRT_1_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BKP_BPLRT_1", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BKP_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BKP_XFER_BPLRT_1_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BKP_BPLRT_1", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BKP_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BKP_XFER_BPLRT_2_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BKP_BPLRT_2", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BKP_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BKP_XFER_BPLRT_2_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BKP_BPLRT_2", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BKP_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/BNV.json b/data/station/BNV.json index 52b784b4..f7a07911 100644 --- a/data/station/BNV.json +++ b/data/station/BNV.json @@ -189,6 +189,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "BNV_XFER_EWL_A_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BNV_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BNV_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BNV_XFER_EWL_A_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BNV_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BNV_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BNV_XFER_EWL_B_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BNV_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BNV_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BNV_XFER_EWL_B_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BNV_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BNV_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/BSH.json b/data/station/BSH.json index 68149227..a9b3a391 100644 --- a/data/station/BSH.json +++ b/data/station/BSH.json @@ -198,6 +198,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "BSH_XFER_NSL_A_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BSH_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BSH_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BSH_XFER_NSL_A_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BSH_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BSH_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BSH_XFER_NSL_B_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BSH_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BSH_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BSH_XFER_NSL_B_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BSH_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BSH_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/BTN.json b/data/station/BTN.json index ad2b979e..c058fcda 100644 --- a/data/station/BTN.json +++ b/data/station/BTN.json @@ -175,6 +175,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "BTN_XFER_CCL_A_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BTN_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BTN_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BTN_XFER_CCL_A_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BTN_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BTN_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BTN_XFER_CCL_B_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BTN_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BTN_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "BTN_XFER_CCL_B_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "BTN_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "BTN_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/CCK.json b/data/station/CCK.json index 31d4a720..7d1d9ff4 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -213,6 +213,183 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "CCK_XFER_NSL_A_BPLRT_1", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_1", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_A_BPLRT_2", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_2", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_A_BPLRT_3", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_3", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_A_BPLRT_4", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_4", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_B_BPLRT_1", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_1", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_B_BPLRT_2", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_2", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_B_BPLRT_3", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_3", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_NSL_B_BPLRT_4", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCK_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CCK_BPLRT_4", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/CDT.json b/data/station/CDT.json index 0e77adf6..85ed309e 100644 --- a/data/station/CDT.json +++ b/data/station/CDT.json @@ -203,6 +203,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "CDT_XFER_CCL_A_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCDT_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TCDT_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CDT_XFER_CCL_A_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCDT_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TCDT_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CDT_XFER_CCL_B_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCDT_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TCDT_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CDT_XFER_CCL_B_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CCDT_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TCDT_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/CTH.json b/data/station/CTH.json index d75dc3f3..e0d7734d 100644 --- a/data/station/CTH.json +++ b/data/station/CTH.json @@ -229,6 +229,50 @@ "classification": "same_platform", "estimatedTraversalSeconds": null, "distanceMeters": null + }, + { + "id": "CTH_XFER_NSL_A_EWL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTH_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTH_EWL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CTH_XFER_EWL_B_NSL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTH_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTH_NSL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null } ] } diff --git a/data/station/CTN.json b/data/station/CTN.json index d45f7880..08822c3a 100644 --- a/data/station/CTN.json +++ b/data/station/CTN.json @@ -203,6 +203,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "CTN_XFER_NEL_A_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTN_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTN_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CTN_XFER_NEL_A_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTN_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTN_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CTN_XFER_NEL_B_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTN_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTN_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CTN_XFER_NEL_B_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "CTN_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "CTN_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/DBG.json b/data/station/DBG.json index a51aecd0..cebacb8f 100644 --- a/data/station/DBG.json +++ b/data/station/DBG.json @@ -246,6 +246,271 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "DBG_XFER_NSL_A_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_A_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_A_NEL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_A_NEL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_B_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_B_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_B_NEL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_NSL_B_NEL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_CCL_A_NEL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_CCL_A_NEL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_CCL_B_NEL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "DBG_XFER_CCL_B_NEL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "DBG_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "DBG_NEL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/HBF.json b/data/station/HBF.json index 0d24c528..19406466 100644 --- a/data/station/HBF.json +++ b/data/station/HBF.json @@ -164,6 +164,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "HBF_XFER_NEL_A_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "HBF_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "HBF_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "HBF_XFER_NEL_A_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "HBF_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "HBF_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "HBF_XFER_NEL_B_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "HBF_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "HBF_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "HBF_XFER_NEL_B_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "HBF_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "HBF_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/JUR.json b/data/station/JUR.json index be45fccf..e09fe7ac 100644 --- a/data/station/JUR.json +++ b/data/station/JUR.json @@ -268,6 +268,138 @@ "classification": "same_platform", "estimatedTraversalSeconds": null, "distanceMeters": null + }, + { + "id": "JUR_XFER_NSL_A_EWL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_EWL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_NSL_A_EWL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_EWL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_EWL_B_NSL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_NSL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_EWL_B_NSL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_NSL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_EWL_C_NSL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_EWL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_NSL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "JUR_XFER_NSL_D_EWL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "JUR_NSL_D", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "JUR_EWL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null } ] } diff --git a/data/station/LTI.json b/data/station/LTI.json index 42947d23..4bc6fcf6 100644 --- a/data/station/LTI.json +++ b/data/station/LTI.json @@ -206,6 +206,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "LTI_XFER_NEL_A_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "LTI_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "LTI_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "LTI_XFER_NEL_A_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "LTI_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "LTI_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "LTI_XFER_NEL_B_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "LTI_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "LTI_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "LTI_XFER_NEL_B_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "LTI_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "LTI_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/MPS.json b/data/station/MPS.json index 29d375ab..bbf2df17 100644 --- a/data/station/MPS.json +++ b/data/station/MPS.json @@ -201,6 +201,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "MPS_XFER_CCL_A_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MPS_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MPS_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MPS_XFER_CCL_A_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MPS_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MPS_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MPS_XFER_CCL_B_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MPS_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MPS_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MPS_XFER_CCL_B_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MPS_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MPS_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/MRB.json b/data/station/MRB.json index 87e5db2e..bd5f1206 100644 --- a/data/station/MRB.json +++ b/data/station/MRB.json @@ -206,6 +206,271 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "MRB_XFER_NSL_A_CCL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_CCL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_A_CCL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_CCL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_A_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_A_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_B_CCL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_CCL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_B_CCL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_CCL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_B_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_NSL_B_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_CCL_C_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_CCL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_CCL_C_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_CCL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_CCL_D_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_CCL_D", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "MRB_XFER_CCL_D_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "MRB_CCL_D", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "MRB_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/NEW.json b/data/station/NEW.json index 4bbafff1..f3d42cd4 100644 --- a/data/station/NEW.json +++ b/data/station/NEW.json @@ -183,6 +183,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "NEW_XFER_NSL_A_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "NEW_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "NEW_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "NEW_XFER_NSL_A_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "NEW_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "NEW_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "NEW_XFER_NSL_B_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "NEW_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "NEW_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "NEW_XFER_NSL_B_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "NEW_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "NEW_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/ORC.json b/data/station/ORC.json index 4f4ac9d5..933cfcdd 100644 --- a/data/station/ORC.json +++ b/data/station/ORC.json @@ -253,6 +253,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "ORC_XFER_NSL_A_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "ORC_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "ORC_TEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "ORC_XFER_NSL_A_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "ORC_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "ORC_TEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "ORC_XFER_NSL_B_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "ORC_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "ORC_TEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "ORC_XFER_NSL_B_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "ORC_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "ORC_TEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/OTP.json b/data/station/OTP.json index e536fc5f..43af8e64 100644 --- a/data/station/OTP.json +++ b/data/station/OTP.json @@ -278,6 +278,271 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "OTP_XFER_EWL_A_NEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_NEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_A_NEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_NEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_A_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_A_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_B_NEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_NEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_B_NEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_NEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_B_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_EWL_B_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_NEL_C_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_NEL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_NEL_C_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_NEL_C", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_NEL_D_TEL_E", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_NEL_D", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_E", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "OTP_XFER_NEL_D_TEL_F", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "OTP_NEL_D", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "OTP_TEL_F", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/PGL.json b/data/station/PGL.json index d1a2bcf8..eb023946 100644 --- a/data/station/PGL.json +++ b/data/station/PGL.json @@ -163,6 +163,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "PGL_XFER_NEL_A_PGLRT_1", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PGL_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PGL_PGLRT_1", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PGL_XFER_NEL_A_PGLRT_2", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PGL_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PGL_PGLRT_2", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PGL_XFER_NEL_B_PGLRT_1", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PGL_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PGL_PGLRT_1", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PGL_XFER_NEL_B_PGLRT_2", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PGL_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PGL_PGLRT_2", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/PMN.json b/data/station/PMN.json index 3891777e..f4b7ace7 100644 --- a/data/station/PMN.json +++ b/data/station/PMN.json @@ -211,6 +211,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "PMN_XFER_CCL_A_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PMN_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PMN_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PMN_XFER_CCL_A_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PMN_CCL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PMN_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PMN_XFER_CCL_B_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PMN_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PMN_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PMN_XFER_CCL_B_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PMN_CCL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PMN_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/PYL.json b/data/station/PYL.json index 8643b76c..9804c586 100644 --- a/data/station/PYL.json +++ b/data/station/PYL.json @@ -225,6 +225,183 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "PYL_XFER_EWL_A_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_A_CCL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_A_CCL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_A_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_B_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_B_CCL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_B_CCL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "PYL_XFER_EWL_B_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "PYL_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "PYL_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/RFP.json b/data/station/RFP.json index f7c11454..d2f8e39a 100644 --- a/data/station/RFP.json +++ b/data/station/RFP.json @@ -277,6 +277,50 @@ "classification": "same_platform", "estimatedTraversalSeconds": null, "distanceMeters": null + }, + { + "id": "RFP_XFER_EWL_A_NSL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "RFP_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "RFP_NSL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "RFP_XFER_NSL_B_EWL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "RFP_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "RFP_EWL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null } ] } diff --git a/data/station/SER.json b/data/station/SER.json index 3ddafdc0..846a1c5d 100644 --- a/data/station/SER.json +++ b/data/station/SER.json @@ -220,6 +220,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "SER_XFER_NEL_A_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SER_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SER_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "SER_XFER_NEL_A_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SER_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SER_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "SER_XFER_NEL_B_CCL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SER_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SER_CCL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "SER_XFER_NEL_B_CCL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SER_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SER_CCL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/SKG.json b/data/station/SKG.json index ed7a2a78..c92ec782 100644 --- a/data/station/SKG.json +++ b/data/station/SKG.json @@ -152,6 +152,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "SKG_XFER_NEL_A_SKLRT_1", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SKG_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SKG_SKLRT_1", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "SKG_XFER_NEL_A_SKLRT_2", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SKG_NEL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SKG_SKLRT_2", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "SKG_XFER_NEL_B_SKLRT_1", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SKG_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SKG_SKLRT_1", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "SKG_XFER_NEL_B_SKLRT_2", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "SKG_NEL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "SKG_SKLRT_2", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/STV.json b/data/station/STV.json index 77517b58..d0a475be 100644 --- a/data/station/STV.json +++ b/data/station/STV.json @@ -196,6 +196,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "STV_XFER_DTL_A_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "STV_DTL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "STV_TEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "STV_XFER_DTL_A_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "STV_DTL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "STV_TEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "STV_XFER_DTL_B_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "STV_DTL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "STV_TEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "STV_XFER_DTL_B_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "STV_DTL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "STV_TEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/TAM.json b/data/station/TAM.json index 6c3b0d6b..70105c54 100644 --- a/data/station/TAM.json +++ b/data/station/TAM.json @@ -196,6 +196,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "TAM_XFER_EWL_A_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "TAM_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TAM_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "TAM_XFER_EWL_A_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "TAM_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TAM_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "TAM_XFER_EWL_B_DTL_A", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "TAM_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TAM_DTL_A", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "TAM_XFER_EWL_B_DTL_B", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "TAM_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "TAM_DTL_B", + "lastUpdated": "2026-07-18" + }, + "paidArea": false, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "out_of_station", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/WDL.json b/data/station/WDL.json index 1227a713..b62cb7c1 100644 --- a/data/station/WDL.json +++ b/data/station/WDL.json @@ -208,6 +208,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "WDL_XFER_NSL_A_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "WDL_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "WDL_TEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "WDL_XFER_NSL_A_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "WDL_NSL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "WDL_TEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "WDL_XFER_NSL_B_TEL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "WDL_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "WDL_TEL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "WDL_XFER_NSL_B_TEL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "WDL_NSL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "WDL_TEL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } diff --git a/data/station/XPO.json b/data/station/XPO.json index 54c94ae5..584eacda 100644 --- a/data/station/XPO.json +++ b/data/station/XPO.json @@ -204,6 +204,95 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "XPO_XFER_EWL_A_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "XPO_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "XPO_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "XPO_XFER_EWL_A_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "XPO_EWL_A", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "XPO_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "XPO_XFER_EWL_B_DTL_C", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "XPO_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "XPO_DTL_C", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "XPO_XFER_EWL_B_DTL_D", + "lastUpdated": "2026-07-18", + "from": { + "kind": "platform", + "id": "XPO_EWL_B", + "lastUpdated": "2026-07-18" + }, + "to": { + "kind": "platform", + "id": "XPO_DTL_D", + "lastUpdated": "2026-07-18" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } From 48f45e31c892d644ab480c8fa60b296d13441ec6 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 14:41:05 +0800 Subject: [PATCH 10/20] fix: model temporarily closed station exits --- .changeset/closed-exits-update.md | 7 +++++++ data/station/AMK.json | 3 ++- data/station/CCK.json | 1 + docs/plans/active/station-layout-data.md | 10 +++++++-- packages/core/src/schema/Station.test.ts | 26 ++++++++++++++++++++++++ packages/core/src/schema/Station.ts | 8 ++++++++ 6 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 .changeset/closed-exits-update.md diff --git a/.changeset/closed-exits-update.md b/.changeset/closed-exits-update.md new file mode 100644 index 00000000..b146352e --- /dev/null +++ b/.changeset/closed-exits-update.md @@ -0,0 +1,7 @@ +--- +"@mrtdown/core": major +"@mrtdown/fs": patch +--- + +Require provenance dates on station layout records and add temporary exit +closure status so consumers can avoid unavailable station access points. diff --git a/data/station/AMK.json b/data/station/AMK.json index afbb11e1..86e496d7 100644 --- a/data/station/AMK.json +++ b/data/station/AMK.json @@ -112,7 +112,8 @@ { "id": "AMK_EXIT_D", "label": "D", - "lastUpdated": "2026-07-16", + "lastUpdated": "2026-07-18", + "operationalStatus": "temporarily_closed", "roadNames": [ "Ang Mo Kio Avenue 8" ], diff --git a/data/station/CCK.json b/data/station/CCK.json index 7d1d9ff4..94c70907 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -136,6 +136,7 @@ "id": "CCK_EXIT_D", "label": "D", "lastUpdated": "2026-07-18", + "operationalStatus": "temporarily_closed", "paidArea": false }, { diff --git a/docs/plans/active/station-layout-data.md b/docs/plans/active/station-layout-data.md index 8c024019..392a5be8 100644 --- a/docs/plans/active/station-layout-data.md +++ b/docs/plans/active/station-layout-data.md @@ -52,7 +52,8 @@ Related references: - This plan does not attempt detailed CAD geometry or public wayfinding map rendering. - This plan does not model temporary works, temporary platform closures, or - incident-specific access restrictions as static station layout. + incident-specific access restrictions as static station layout, except for + the current operational status of a durable public exit. - This plan does not add hand-authored page titles or meta descriptions. The site should continue deriving them from canonical station facts. @@ -176,6 +177,9 @@ Initial fields: - `id`: station-local id. - `label`: public exit label such as `A`, `B`, `1`, or `Exit A`. +- `operationalStatus`: optional exceptional current state. Absence means the + exit is open; `temporarily_closed` preserves the exit identity while keeping + wayfinding consumers from routing passengers through it. - `levelId`: optional reference to `layout.levels`. - `geo`: optional exit coordinate when a reviewed source provides it. - `nearbyLandmarkIds`: optional references to existing landmark records. @@ -190,7 +194,9 @@ Rules: - Use `nearbyLandmarkIds` for landmarks already modeled in `data/landmark`; use `roadNames` for roads that are not landmarks. - Keep exit labels as strings because public labels are not always numeric. -- Do not model temporary construction diversions as static exits. +- Keep durable exits in the layout while they are temporarily closed and mark + them with `operationalStatus`; do not model temporary construction diversion + routes as static exits. ## Platforms diff --git a/packages/core/src/schema/Station.test.ts b/packages/core/src/schema/Station.test.ts index 6476d9cf..df36f1e5 100644 --- a/packages/core/src/schema/Station.test.ts +++ b/packages/core/src/schema/Station.test.ts @@ -194,6 +194,7 @@ describe('StationSchema', () => { id: 'KET_EXIT_A', label: 'A', lastUpdated: '2026-07-18', + operationalStatus: 'temporarily_closed', levelId: 'B2', paidArea: false, }, @@ -247,6 +248,31 @@ describe('StationSchema', () => { ).not.toThrow(); }); + it('rejects unknown station exit operational statuses', () => { + const result = StationSchema.safeParse({ + ...minimalStation(), + layout: { + levels: [], + exits: [ + { + id: 'KET_EXIT_A', + label: 'A', + lastUpdated: '2026-07-18', + operationalStatus: 'permanently_closed', + paidArea: false, + }, + ], + platforms: [], + transferPaths: [], + }, + }); + + expect(result.success).toBe(false); + expect(result.error?.issues[0]?.path.join('.')).toBe( + 'layout.exits.0.operationalStatus', + ); + }); + it('rejects layout platforms without service ids', () => { const result = StationSchema.safeParse({ ...minimalStation(), diff --git a/packages/core/src/schema/Station.ts b/packages/core/src/schema/Station.ts index bfeeb5cd..dd96f870 100644 --- a/packages/core/src/schema/Station.ts +++ b/packages/core/src/schema/Station.ts @@ -141,10 +141,18 @@ export const StationLayoutLevelSchema = z.object({ }); export type StationLayoutLevel = z.infer; +export const StationLayoutExitOperationalStatusSchema = z.enum([ + 'temporarily_closed', +]); +export type StationLayoutExitOperationalStatus = z.infer< + typeof StationLayoutExitOperationalStatusSchema +>; + export const StationLayoutExitSchema = z.object({ id: z.string(), label: z.string(), lastUpdated: z.iso.date(), + operationalStatus: StationLayoutExitOperationalStatusSchema.optional(), levelId: z.string().optional(), geo: z .object({ From 2d8a54ddc1354064960ee612ad08c8bdea60ab8f Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 15:23:58 +0800 Subject: [PATCH 11/20] fix: address station layout review feedback --- .changeset/closed-exits-update.md | 5 +- data/station/BFT.json | 24 ++---- data/station/BGS.json | 24 ++---- data/station/BKP.json | 24 ++---- data/station/BNV.json | 24 ++---- data/station/BSH.json | 24 ++---- data/station/BSR.json | 5 +- data/station/BTN.json | 24 ++---- data/station/CCK.json | 48 ++++-------- data/station/CDT.json | 24 ++---- data/station/CTH.json | 24 ++---- data/station/CTN.json | 24 ++---- data/station/DBG.json | 72 ++++++------------ data/station/HBF.json | 24 ++---- data/station/JUR.json | 54 +++++--------- data/station/LTI.json | 24 ++---- data/station/MPS.json | 24 ++---- data/station/MRB.json | 93 +++++++++++------------- data/station/MSP.json | 5 +- data/station/NEW.json | 24 ++---- data/station/ORC.json | 24 ++---- data/station/OTP.json | 72 ++++++------------ data/station/PGL.json | 24 ++---- data/station/PMN.json | 24 ++---- data/station/PYL.json | 48 ++++-------- data/station/RFP.json | 24 ++---- data/station/SER.json | 24 ++---- data/station/SKG.json | 24 ++---- data/station/STV.json | 24 ++---- data/station/TAM.json | 24 ++---- data/station/WDL.json | 24 ++---- data/station/XPO.json | 29 +++----- docs/plans/active/station-layout-data.md | 9 ++- packages/core/src/schema/Station.test.ts | 26 ++++++- packages/core/src/schema/Station.ts | 43 ++++++++--- packages/fs/src/index.test.ts | 2 - 36 files changed, 399 insertions(+), 640 deletions(-) diff --git a/.changeset/closed-exits-update.md b/.changeset/closed-exits-update.md index b146352e..04bf1ef1 100644 --- a/.changeset/closed-exits-update.md +++ b/.changeset/closed-exits-update.md @@ -3,5 +3,6 @@ "@mrtdown/fs": patch --- -Require provenance dates on station layout records and add temporary exit -closure status so consumers can avoid unavailable station access points. +Require provenance dates on durable station layout records, add temporary exit +closure and alighting-only platform statuses, and keep transfer endpoints as +lightweight references. diff --git a/data/station/BFT.json b/data/station/BFT.json index 66e1ead7..c4be6362 100644 --- a/data/station/BFT.json +++ b/data/station/BFT.json @@ -216,13 +216,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BFT_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BFT_DTL_A" }, "to": { "kind": "platform", - "id": "BFT_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BFT_CCL_B" }, "paidArea": true, "modes": [ @@ -238,13 +236,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BFT_DTL_C", - "lastUpdated": "2026-07-18" + "id": "BFT_DTL_C" }, "to": { "kind": "platform", - "id": "BFT_CCL_D", - "lastUpdated": "2026-07-18" + "id": "BFT_CCL_D" }, "paidArea": true, "modes": [ @@ -260,13 +256,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BFT_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BFT_DTL_A" }, "to": { "kind": "platform", - "id": "BFT_CCL_D", - "lastUpdated": "2026-07-18" + "id": "BFT_CCL_D" }, "paidArea": true, "modes": [ @@ -282,13 +276,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BFT_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BFT_CCL_B" }, "to": { "kind": "platform", - "id": "BFT_DTL_C", - "lastUpdated": "2026-07-18" + "id": "BFT_DTL_C" }, "paidArea": true, "modes": [ diff --git a/data/station/BGS.json b/data/station/BGS.json index c936eaee..1068832b 100644 --- a/data/station/BGS.json +++ b/data/station/BGS.json @@ -208,13 +208,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BGS_EWL_A", - "lastUpdated": "2026-07-18" + "id": "BGS_EWL_A" }, "to": { "kind": "platform", - "id": "BGS_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BGS_DTL_A" }, "paidArea": true, "modes": [ @@ -230,13 +228,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BGS_EWL_A", - "lastUpdated": "2026-07-18" + "id": "BGS_EWL_A" }, "to": { "kind": "platform", - "id": "BGS_DTL_B", - "lastUpdated": "2026-07-18" + "id": "BGS_DTL_B" }, "paidArea": true, "modes": [ @@ -252,13 +248,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BGS_EWL_B", - "lastUpdated": "2026-07-18" + "id": "BGS_EWL_B" }, "to": { "kind": "platform", - "id": "BGS_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BGS_DTL_A" }, "paidArea": true, "modes": [ @@ -274,13 +268,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BGS_EWL_B", - "lastUpdated": "2026-07-18" + "id": "BGS_EWL_B" }, "to": { "kind": "platform", - "id": "BGS_DTL_B", - "lastUpdated": "2026-07-18" + "id": "BGS_DTL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/BKP.json b/data/station/BKP.json index 8b8cc79f..b33e52da 100644 --- a/data/station/BKP.json +++ b/data/station/BKP.json @@ -141,13 +141,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BKP_BPLRT_1", - "lastUpdated": "2026-07-18" + "id": "BKP_BPLRT_1" }, "to": { "kind": "platform", - "id": "BKP_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BKP_DTL_A" }, "paidArea": false, "modes": [ @@ -163,13 +161,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BKP_BPLRT_1", - "lastUpdated": "2026-07-18" + "id": "BKP_BPLRT_1" }, "to": { "kind": "platform", - "id": "BKP_DTL_B", - "lastUpdated": "2026-07-18" + "id": "BKP_DTL_B" }, "paidArea": false, "modes": [ @@ -185,13 +181,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BKP_BPLRT_2", - "lastUpdated": "2026-07-18" + "id": "BKP_BPLRT_2" }, "to": { "kind": "platform", - "id": "BKP_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BKP_DTL_A" }, "paidArea": false, "modes": [ @@ -207,13 +201,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BKP_BPLRT_2", - "lastUpdated": "2026-07-18" + "id": "BKP_BPLRT_2" }, "to": { "kind": "platform", - "id": "BKP_DTL_B", - "lastUpdated": "2026-07-18" + "id": "BKP_DTL_B" }, "paidArea": false, "modes": [ diff --git a/data/station/BNV.json b/data/station/BNV.json index f7a07911..50bcb0cc 100644 --- a/data/station/BNV.json +++ b/data/station/BNV.json @@ -195,13 +195,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BNV_EWL_A", - "lastUpdated": "2026-07-18" + "id": "BNV_EWL_A" }, "to": { "kind": "platform", - "id": "BNV_CCL_A", - "lastUpdated": "2026-07-18" + "id": "BNV_CCL_A" }, "paidArea": true, "modes": [ @@ -217,13 +215,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BNV_EWL_A", - "lastUpdated": "2026-07-18" + "id": "BNV_EWL_A" }, "to": { "kind": "platform", - "id": "BNV_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BNV_CCL_B" }, "paidArea": true, "modes": [ @@ -239,13 +235,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BNV_EWL_B", - "lastUpdated": "2026-07-18" + "id": "BNV_EWL_B" }, "to": { "kind": "platform", - "id": "BNV_CCL_A", - "lastUpdated": "2026-07-18" + "id": "BNV_CCL_A" }, "paidArea": true, "modes": [ @@ -261,13 +255,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BNV_EWL_B", - "lastUpdated": "2026-07-18" + "id": "BNV_EWL_B" }, "to": { "kind": "platform", - "id": "BNV_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BNV_CCL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/BSH.json b/data/station/BSH.json index a9b3a391..f1c464d9 100644 --- a/data/station/BSH.json +++ b/data/station/BSH.json @@ -204,13 +204,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BSH_NSL_A", - "lastUpdated": "2026-07-18" + "id": "BSH_NSL_A" }, "to": { "kind": "platform", - "id": "BSH_CCL_A", - "lastUpdated": "2026-07-18" + "id": "BSH_CCL_A" }, "paidArea": true, "modes": [ @@ -226,13 +224,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BSH_NSL_A", - "lastUpdated": "2026-07-18" + "id": "BSH_NSL_A" }, "to": { "kind": "platform", - "id": "BSH_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BSH_CCL_B" }, "paidArea": true, "modes": [ @@ -248,13 +244,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BSH_NSL_B", - "lastUpdated": "2026-07-18" + "id": "BSH_NSL_B" }, "to": { "kind": "platform", - "id": "BSH_CCL_A", - "lastUpdated": "2026-07-18" + "id": "BSH_CCL_A" }, "paidArea": true, "modes": [ @@ -270,13 +264,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BSH_NSL_B", - "lastUpdated": "2026-07-18" + "id": "BSH_NSL_B" }, "to": { "kind": "platform", - "id": "BSH_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BSH_CCL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/BSR.json b/data/station/BSR.json index 4b731fa0..0b934493 100644 --- a/data/station/BSR.json +++ b/data/station/BSR.json @@ -99,10 +99,9 @@ "id": "BSR_TEL_A", "label": "A", "lastUpdated": "2026-07-18", + "boardingStatus": "alighting_only", "lineId": "TEL", - "serviceIds": [ - "TEL_MAIN_S" - ], + "serviceIds": [], "doorCount": 20, "accessPoints": [] }, diff --git a/data/station/BTN.json b/data/station/BTN.json index c058fcda..98e05320 100644 --- a/data/station/BTN.json +++ b/data/station/BTN.json @@ -181,13 +181,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BTN_CCL_A", - "lastUpdated": "2026-07-18" + "id": "BTN_CCL_A" }, "to": { "kind": "platform", - "id": "BTN_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BTN_DTL_A" }, "paidArea": true, "modes": [ @@ -203,13 +201,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BTN_CCL_A", - "lastUpdated": "2026-07-18" + "id": "BTN_CCL_A" }, "to": { "kind": "platform", - "id": "BTN_DTL_B", - "lastUpdated": "2026-07-18" + "id": "BTN_DTL_B" }, "paidArea": true, "modes": [ @@ -225,13 +221,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BTN_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BTN_CCL_B" }, "to": { "kind": "platform", - "id": "BTN_DTL_A", - "lastUpdated": "2026-07-18" + "id": "BTN_DTL_A" }, "paidArea": true, "modes": [ @@ -247,13 +241,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "BTN_CCL_B", - "lastUpdated": "2026-07-18" + "id": "BTN_CCL_B" }, "to": { "kind": "platform", - "id": "BTN_DTL_B", - "lastUpdated": "2026-07-18" + "id": "BTN_DTL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/CCK.json b/data/station/CCK.json index 94c70907..323072c5 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -220,13 +220,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_A", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_A" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_1", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_1" }, "paidArea": true, "modes": [ @@ -242,13 +240,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_A", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_A" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_2", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_2" }, "paidArea": true, "modes": [ @@ -264,13 +260,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_A", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_A" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_3", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_3" }, "paidArea": true, "modes": [ @@ -286,13 +280,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_A", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_A" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_4", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_4" }, "paidArea": true, "modes": [ @@ -308,13 +300,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_B", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_B" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_1", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_1" }, "paidArea": true, "modes": [ @@ -330,13 +320,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_B", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_B" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_2", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_2" }, "paidArea": true, "modes": [ @@ -352,13 +340,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_B", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_B" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_3", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_3" }, "paidArea": true, "modes": [ @@ -374,13 +360,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCK_NSL_B", - "lastUpdated": "2026-07-18" + "id": "CCK_NSL_B" }, "to": { "kind": "platform", - "id": "CCK_BPLRT_4", - "lastUpdated": "2026-07-18" + "id": "CCK_BPLRT_4" }, "paidArea": true, "modes": [ diff --git a/data/station/CDT.json b/data/station/CDT.json index 85ed309e..fb2ee548 100644 --- a/data/station/CDT.json +++ b/data/station/CDT.json @@ -209,13 +209,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCDT_A", - "lastUpdated": "2026-07-18" + "id": "CCDT_A" }, "to": { "kind": "platform", - "id": "TCDT_D", - "lastUpdated": "2026-07-18" + "id": "TCDT_D" }, "paidArea": true, "modes": [ @@ -231,13 +229,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCDT_A", - "lastUpdated": "2026-07-18" + "id": "CCDT_A" }, "to": { "kind": "platform", - "id": "TCDT_C", - "lastUpdated": "2026-07-18" + "id": "TCDT_C" }, "paidArea": true, "modes": [ @@ -253,13 +249,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCDT_B", - "lastUpdated": "2026-07-18" + "id": "CCDT_B" }, "to": { "kind": "platform", - "id": "TCDT_D", - "lastUpdated": "2026-07-18" + "id": "TCDT_D" }, "paidArea": true, "modes": [ @@ -275,13 +269,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CCDT_B", - "lastUpdated": "2026-07-18" + "id": "CCDT_B" }, "to": { "kind": "platform", - "id": "TCDT_C", - "lastUpdated": "2026-07-18" + "id": "TCDT_C" }, "paidArea": true, "modes": [ diff --git a/data/station/CTH.json b/data/station/CTH.json index e0d7734d..caa47ed6 100644 --- a/data/station/CTH.json +++ b/data/station/CTH.json @@ -191,13 +191,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTH_NSL_A", - "lastUpdated": "2026-07-18" + "id": "CTH_NSL_A" }, "to": { "kind": "platform", - "id": "CTH_EWL_B", - "lastUpdated": "2026-07-18" + "id": "CTH_EWL_B" }, "paidArea": true, "modes": [ @@ -213,13 +211,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTH_NSL_C", - "lastUpdated": "2026-07-18" + "id": "CTH_NSL_C" }, "to": { "kind": "platform", - "id": "CTH_EWL_D", - "lastUpdated": "2026-07-18" + "id": "CTH_EWL_D" }, "paidArea": true, "modes": [ @@ -235,13 +231,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTH_NSL_A", - "lastUpdated": "2026-07-18" + "id": "CTH_NSL_A" }, "to": { "kind": "platform", - "id": "CTH_EWL_D", - "lastUpdated": "2026-07-18" + "id": "CTH_EWL_D" }, "paidArea": true, "modes": [ @@ -257,13 +251,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTH_EWL_B", - "lastUpdated": "2026-07-18" + "id": "CTH_EWL_B" }, "to": { "kind": "platform", - "id": "CTH_NSL_C", - "lastUpdated": "2026-07-18" + "id": "CTH_NSL_C" }, "paidArea": true, "modes": [ diff --git a/data/station/CTN.json b/data/station/CTN.json index 08822c3a..56583281 100644 --- a/data/station/CTN.json +++ b/data/station/CTN.json @@ -209,13 +209,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTN_NEL_A", - "lastUpdated": "2026-07-18" + "id": "CTN_NEL_A" }, "to": { "kind": "platform", - "id": "CTN_DTL_C", - "lastUpdated": "2026-07-18" + "id": "CTN_DTL_C" }, "paidArea": true, "modes": [ @@ -231,13 +229,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTN_NEL_A", - "lastUpdated": "2026-07-18" + "id": "CTN_NEL_A" }, "to": { "kind": "platform", - "id": "CTN_DTL_D", - "lastUpdated": "2026-07-18" + "id": "CTN_DTL_D" }, "paidArea": true, "modes": [ @@ -253,13 +249,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTN_NEL_B", - "lastUpdated": "2026-07-18" + "id": "CTN_NEL_B" }, "to": { "kind": "platform", - "id": "CTN_DTL_C", - "lastUpdated": "2026-07-18" + "id": "CTN_DTL_C" }, "paidArea": true, "modes": [ @@ -275,13 +269,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "CTN_NEL_B", - "lastUpdated": "2026-07-18" + "id": "CTN_NEL_B" }, "to": { "kind": "platform", - "id": "CTN_DTL_D", - "lastUpdated": "2026-07-18" + "id": "CTN_DTL_D" }, "paidArea": true, "modes": [ diff --git a/data/station/DBG.json b/data/station/DBG.json index cebacb8f..9d674c2c 100644 --- a/data/station/DBG.json +++ b/data/station/DBG.json @@ -252,13 +252,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_A" }, "to": { "kind": "platform", - "id": "DBG_CCL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_A" }, "paidArea": true, "modes": [ @@ -274,13 +272,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_A" }, "to": { "kind": "platform", - "id": "DBG_CCL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_B" }, "paidArea": true, "modes": [ @@ -296,13 +292,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_A" }, "to": { "kind": "platform", - "id": "DBG_NEL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_A" }, "paidArea": true, "modes": [ @@ -318,13 +312,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_A" }, "to": { "kind": "platform", - "id": "DBG_NEL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_B" }, "paidArea": true, "modes": [ @@ -340,13 +332,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_B" }, "to": { "kind": "platform", - "id": "DBG_CCL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_A" }, "paidArea": true, "modes": [ @@ -362,13 +352,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_B" }, "to": { "kind": "platform", - "id": "DBG_CCL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_B" }, "paidArea": true, "modes": [ @@ -384,13 +372,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_B" }, "to": { "kind": "platform", - "id": "DBG_NEL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_A" }, "paidArea": true, "modes": [ @@ -406,13 +392,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_NSL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NSL_B" }, "to": { "kind": "platform", - "id": "DBG_NEL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_B" }, "paidArea": true, "modes": [ @@ -428,13 +412,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_CCL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_A" }, "to": { "kind": "platform", - "id": "DBG_NEL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_A" }, "paidArea": true, "modes": [ @@ -450,13 +432,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_CCL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_A" }, "to": { "kind": "platform", - "id": "DBG_NEL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_B" }, "paidArea": true, "modes": [ @@ -472,13 +452,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_CCL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_B" }, "to": { "kind": "platform", - "id": "DBG_NEL_A", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_A" }, "paidArea": true, "modes": [ @@ -494,13 +472,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "DBG_CCL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_CCL_B" }, "to": { "kind": "platform", - "id": "DBG_NEL_B", - "lastUpdated": "2026-07-18" + "id": "DBG_NEL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/HBF.json b/data/station/HBF.json index 19406466..b91145bb 100644 --- a/data/station/HBF.json +++ b/data/station/HBF.json @@ -170,13 +170,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "HBF_NEL_A", - "lastUpdated": "2026-07-18" + "id": "HBF_NEL_A" }, "to": { "kind": "platform", - "id": "HBF_CCL_A", - "lastUpdated": "2026-07-18" + "id": "HBF_CCL_A" }, "paidArea": true, "modes": [ @@ -192,13 +190,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "HBF_NEL_A", - "lastUpdated": "2026-07-18" + "id": "HBF_NEL_A" }, "to": { "kind": "platform", - "id": "HBF_CCL_B", - "lastUpdated": "2026-07-18" + "id": "HBF_CCL_B" }, "paidArea": true, "modes": [ @@ -214,13 +210,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "HBF_NEL_B", - "lastUpdated": "2026-07-18" + "id": "HBF_NEL_B" }, "to": { "kind": "platform", - "id": "HBF_CCL_A", - "lastUpdated": "2026-07-18" + "id": "HBF_CCL_A" }, "paidArea": true, "modes": [ @@ -236,13 +230,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "HBF_NEL_B", - "lastUpdated": "2026-07-18" + "id": "HBF_NEL_B" }, "to": { "kind": "platform", - "id": "HBF_CCL_B", - "lastUpdated": "2026-07-18" + "id": "HBF_CCL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/JUR.json b/data/station/JUR.json index e09fe7ac..422352dd 100644 --- a/data/station/JUR.json +++ b/data/station/JUR.json @@ -208,13 +208,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_NSL_A", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_A" }, "to": { "kind": "platform", - "id": "JUR_EWL_B", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_B" }, "paidArea": true, "modes": [ @@ -230,13 +228,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_EWL_C", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_C" }, "to": { "kind": "platform", - "id": "JUR_NSL_D", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_D" }, "paidArea": true, "modes": [ @@ -252,13 +248,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_NSL_E", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_E" }, "to": { "kind": "platform", - "id": "JUR_EWL_F", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_F" }, "paidArea": true, "modes": [ @@ -274,13 +268,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_NSL_A", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_A" }, "to": { "kind": "platform", - "id": "JUR_EWL_C", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_C" }, "paidArea": true, "modes": [ @@ -296,13 +288,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_NSL_A", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_A" }, "to": { "kind": "platform", - "id": "JUR_EWL_F", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_F" }, "paidArea": true, "modes": [ @@ -318,13 +308,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_EWL_B", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_B" }, "to": { "kind": "platform", - "id": "JUR_NSL_D", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_D" }, "paidArea": true, "modes": [ @@ -340,13 +328,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_EWL_B", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_B" }, "to": { "kind": "platform", - "id": "JUR_NSL_E", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_E" }, "paidArea": true, "modes": [ @@ -362,13 +348,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_EWL_C", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_C" }, "to": { "kind": "platform", - "id": "JUR_NSL_E", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_E" }, "paidArea": true, "modes": [ @@ -384,13 +368,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "JUR_NSL_D", - "lastUpdated": "2026-07-18" + "id": "JUR_NSL_D" }, "to": { "kind": "platform", - "id": "JUR_EWL_F", - "lastUpdated": "2026-07-18" + "id": "JUR_EWL_F" }, "paidArea": true, "modes": [ diff --git a/data/station/LTI.json b/data/station/LTI.json index 4bc6fcf6..7be69b26 100644 --- a/data/station/LTI.json +++ b/data/station/LTI.json @@ -212,13 +212,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "LTI_NEL_A", - "lastUpdated": "2026-07-18" + "id": "LTI_NEL_A" }, "to": { "kind": "platform", - "id": "LTI_DTL_A", - "lastUpdated": "2026-07-18" + "id": "LTI_DTL_A" }, "paidArea": true, "modes": [ @@ -234,13 +232,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "LTI_NEL_A", - "lastUpdated": "2026-07-18" + "id": "LTI_NEL_A" }, "to": { "kind": "platform", - "id": "LTI_DTL_B", - "lastUpdated": "2026-07-18" + "id": "LTI_DTL_B" }, "paidArea": true, "modes": [ @@ -256,13 +252,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "LTI_NEL_B", - "lastUpdated": "2026-07-18" + "id": "LTI_NEL_B" }, "to": { "kind": "platform", - "id": "LTI_DTL_A", - "lastUpdated": "2026-07-18" + "id": "LTI_DTL_A" }, "paidArea": true, "modes": [ @@ -278,13 +272,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "LTI_NEL_B", - "lastUpdated": "2026-07-18" + "id": "LTI_NEL_B" }, "to": { "kind": "platform", - "id": "LTI_DTL_B", - "lastUpdated": "2026-07-18" + "id": "LTI_DTL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/MPS.json b/data/station/MPS.json index bbf2df17..e7887b86 100644 --- a/data/station/MPS.json +++ b/data/station/MPS.json @@ -207,13 +207,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MPS_CCL_A", - "lastUpdated": "2026-07-18" + "id": "MPS_CCL_A" }, "to": { "kind": "platform", - "id": "MPS_DTL_C", - "lastUpdated": "2026-07-18" + "id": "MPS_DTL_C" }, "paidArea": true, "modes": [ @@ -229,13 +227,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MPS_CCL_A", - "lastUpdated": "2026-07-18" + "id": "MPS_CCL_A" }, "to": { "kind": "platform", - "id": "MPS_DTL_D", - "lastUpdated": "2026-07-18" + "id": "MPS_DTL_D" }, "paidArea": true, "modes": [ @@ -251,13 +247,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MPS_CCL_B", - "lastUpdated": "2026-07-18" + "id": "MPS_CCL_B" }, "to": { "kind": "platform", - "id": "MPS_DTL_C", - "lastUpdated": "2026-07-18" + "id": "MPS_DTL_C" }, "paidArea": true, "modes": [ @@ -273,13 +267,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MPS_CCL_B", - "lastUpdated": "2026-07-18" + "id": "MPS_CCL_B" }, "to": { "kind": "platform", - "id": "MPS_DTL_D", - "lastUpdated": "2026-07-18" + "id": "MPS_DTL_D" }, "paidArea": true, "modes": [ diff --git a/data/station/MRB.json b/data/station/MRB.json index bd5f1206..236cc9a5 100644 --- a/data/station/MRB.json +++ b/data/station/MRB.json @@ -137,7 +137,26 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "MRB_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "MRB_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "MRB_EXIT_5", + "label": "5", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], "platforms": [ { "id": "MRB_NSL_A", @@ -212,13 +231,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_A", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_A" }, "to": { "kind": "platform", - "id": "MRB_CCL_C", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_C" }, "paidArea": true, "modes": [ @@ -234,13 +251,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_A", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_A" }, "to": { "kind": "platform", - "id": "MRB_CCL_D", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_D" }, "paidArea": true, "modes": [ @@ -256,13 +271,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_A", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_A" }, "to": { "kind": "platform", - "id": "MRB_TEL_E", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_E" }, "paidArea": true, "modes": [ @@ -278,13 +291,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_A", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_A" }, "to": { "kind": "platform", - "id": "MRB_TEL_F", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_F" }, "paidArea": true, "modes": [ @@ -300,13 +311,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_B", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_B" }, "to": { "kind": "platform", - "id": "MRB_CCL_C", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_C" }, "paidArea": true, "modes": [ @@ -322,13 +331,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_B", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_B" }, "to": { "kind": "platform", - "id": "MRB_CCL_D", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_D" }, "paidArea": true, "modes": [ @@ -344,13 +351,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_B", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_B" }, "to": { "kind": "platform", - "id": "MRB_TEL_E", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_E" }, "paidArea": true, "modes": [ @@ -366,13 +371,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_NSL_B", - "lastUpdated": "2026-07-18" + "id": "MRB_NSL_B" }, "to": { "kind": "platform", - "id": "MRB_TEL_F", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_F" }, "paidArea": true, "modes": [ @@ -388,13 +391,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_CCL_C", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_C" }, "to": { "kind": "platform", - "id": "MRB_TEL_E", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_E" }, "paidArea": true, "modes": [ @@ -410,13 +411,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_CCL_C", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_C" }, "to": { "kind": "platform", - "id": "MRB_TEL_F", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_F" }, "paidArea": true, "modes": [ @@ -432,13 +431,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_CCL_D", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_D" }, "to": { "kind": "platform", - "id": "MRB_TEL_E", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_E" }, "paidArea": true, "modes": [ @@ -454,13 +451,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "MRB_CCL_D", - "lastUpdated": "2026-07-18" + "id": "MRB_CCL_D" }, "to": { "kind": "platform", - "id": "MRB_TEL_F", - "lastUpdated": "2026-07-18" + "id": "MRB_TEL_F" }, "paidArea": true, "modes": [ diff --git a/data/station/MSP.json b/data/station/MSP.json index 0f445ee7..773f2791 100644 --- a/data/station/MSP.json +++ b/data/station/MSP.json @@ -89,10 +89,9 @@ "id": "MSP_NSL_B", "label": "B", "lastUpdated": "2026-07-18", + "boardingStatus": "alighting_only", "lineId": "NSL", - "serviceIds": [ - "NSL_MAIN_S" - ], + "serviceIds": [], "doorCount": 24, "accessPoints": [] } diff --git a/data/station/NEW.json b/data/station/NEW.json index f3d42cd4..d7047268 100644 --- a/data/station/NEW.json +++ b/data/station/NEW.json @@ -189,13 +189,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "NEW_NSL_A", - "lastUpdated": "2026-07-18" + "id": "NEW_NSL_A" }, "to": { "kind": "platform", - "id": "NEW_DTL_A", - "lastUpdated": "2026-07-18" + "id": "NEW_DTL_A" }, "paidArea": false, "modes": [ @@ -211,13 +209,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "NEW_NSL_A", - "lastUpdated": "2026-07-18" + "id": "NEW_NSL_A" }, "to": { "kind": "platform", - "id": "NEW_DTL_B", - "lastUpdated": "2026-07-18" + "id": "NEW_DTL_B" }, "paidArea": false, "modes": [ @@ -233,13 +229,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "NEW_NSL_B", - "lastUpdated": "2026-07-18" + "id": "NEW_NSL_B" }, "to": { "kind": "platform", - "id": "NEW_DTL_A", - "lastUpdated": "2026-07-18" + "id": "NEW_DTL_A" }, "paidArea": false, "modes": [ @@ -255,13 +249,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "NEW_NSL_B", - "lastUpdated": "2026-07-18" + "id": "NEW_NSL_B" }, "to": { "kind": "platform", - "id": "NEW_DTL_B", - "lastUpdated": "2026-07-18" + "id": "NEW_DTL_B" }, "paidArea": false, "modes": [ diff --git a/data/station/ORC.json b/data/station/ORC.json index 933cfcdd..ddaf1919 100644 --- a/data/station/ORC.json +++ b/data/station/ORC.json @@ -259,13 +259,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "ORC_NSL_A", - "lastUpdated": "2026-07-18" + "id": "ORC_NSL_A" }, "to": { "kind": "platform", - "id": "ORC_TEL_C", - "lastUpdated": "2026-07-18" + "id": "ORC_TEL_C" }, "paidArea": true, "modes": [ @@ -281,13 +279,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "ORC_NSL_A", - "lastUpdated": "2026-07-18" + "id": "ORC_NSL_A" }, "to": { "kind": "platform", - "id": "ORC_TEL_D", - "lastUpdated": "2026-07-18" + "id": "ORC_TEL_D" }, "paidArea": true, "modes": [ @@ -303,13 +299,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "ORC_NSL_B", - "lastUpdated": "2026-07-18" + "id": "ORC_NSL_B" }, "to": { "kind": "platform", - "id": "ORC_TEL_C", - "lastUpdated": "2026-07-18" + "id": "ORC_TEL_C" }, "paidArea": true, "modes": [ @@ -325,13 +319,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "ORC_NSL_B", - "lastUpdated": "2026-07-18" + "id": "ORC_NSL_B" }, "to": { "kind": "platform", - "id": "ORC_TEL_D", - "lastUpdated": "2026-07-18" + "id": "ORC_TEL_D" }, "paidArea": true, "modes": [ diff --git a/data/station/OTP.json b/data/station/OTP.json index 43af8e64..38a68d1c 100644 --- a/data/station/OTP.json +++ b/data/station/OTP.json @@ -284,13 +284,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_A", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_A" }, "to": { "kind": "platform", - "id": "OTP_NEL_C", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_C" }, "paidArea": true, "modes": [ @@ -306,13 +304,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_A", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_A" }, "to": { "kind": "platform", - "id": "OTP_NEL_D", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_D" }, "paidArea": true, "modes": [ @@ -328,13 +324,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_A", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_A" }, "to": { "kind": "platform", - "id": "OTP_TEL_E", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_E" }, "paidArea": true, "modes": [ @@ -350,13 +344,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_A", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_A" }, "to": { "kind": "platform", - "id": "OTP_TEL_F", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_F" }, "paidArea": true, "modes": [ @@ -372,13 +364,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_B", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_B" }, "to": { "kind": "platform", - "id": "OTP_NEL_C", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_C" }, "paidArea": true, "modes": [ @@ -394,13 +384,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_B", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_B" }, "to": { "kind": "platform", - "id": "OTP_NEL_D", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_D" }, "paidArea": true, "modes": [ @@ -416,13 +404,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_B", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_B" }, "to": { "kind": "platform", - "id": "OTP_TEL_E", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_E" }, "paidArea": true, "modes": [ @@ -438,13 +424,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_EWL_B", - "lastUpdated": "2026-07-18" + "id": "OTP_EWL_B" }, "to": { "kind": "platform", - "id": "OTP_TEL_F", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_F" }, "paidArea": true, "modes": [ @@ -460,13 +444,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_NEL_C", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_C" }, "to": { "kind": "platform", - "id": "OTP_TEL_E", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_E" }, "paidArea": true, "modes": [ @@ -482,13 +464,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_NEL_C", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_C" }, "to": { "kind": "platform", - "id": "OTP_TEL_F", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_F" }, "paidArea": true, "modes": [ @@ -504,13 +484,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_NEL_D", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_D" }, "to": { "kind": "platform", - "id": "OTP_TEL_E", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_E" }, "paidArea": true, "modes": [ @@ -526,13 +504,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "OTP_NEL_D", - "lastUpdated": "2026-07-18" + "id": "OTP_NEL_D" }, "to": { "kind": "platform", - "id": "OTP_TEL_F", - "lastUpdated": "2026-07-18" + "id": "OTP_TEL_F" }, "paidArea": true, "modes": [ diff --git a/data/station/PGL.json b/data/station/PGL.json index eb023946..75251f61 100644 --- a/data/station/PGL.json +++ b/data/station/PGL.json @@ -169,13 +169,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PGL_NEL_A", - "lastUpdated": "2026-07-18" + "id": "PGL_NEL_A" }, "to": { "kind": "platform", - "id": "PGL_PGLRT_1", - "lastUpdated": "2026-07-18" + "id": "PGL_PGLRT_1" }, "paidArea": true, "modes": [ @@ -191,13 +189,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PGL_NEL_A", - "lastUpdated": "2026-07-18" + "id": "PGL_NEL_A" }, "to": { "kind": "platform", - "id": "PGL_PGLRT_2", - "lastUpdated": "2026-07-18" + "id": "PGL_PGLRT_2" }, "paidArea": true, "modes": [ @@ -213,13 +209,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PGL_NEL_B", - "lastUpdated": "2026-07-18" + "id": "PGL_NEL_B" }, "to": { "kind": "platform", - "id": "PGL_PGLRT_1", - "lastUpdated": "2026-07-18" + "id": "PGL_PGLRT_1" }, "paidArea": true, "modes": [ @@ -235,13 +229,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PGL_NEL_B", - "lastUpdated": "2026-07-18" + "id": "PGL_NEL_B" }, "to": { "kind": "platform", - "id": "PGL_PGLRT_2", - "lastUpdated": "2026-07-18" + "id": "PGL_PGLRT_2" }, "paidArea": true, "modes": [ diff --git a/data/station/PMN.json b/data/station/PMN.json index f4b7ace7..e56abe20 100644 --- a/data/station/PMN.json +++ b/data/station/PMN.json @@ -217,13 +217,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PMN_CCL_A", - "lastUpdated": "2026-07-18" + "id": "PMN_CCL_A" }, "to": { "kind": "platform", - "id": "PMN_DTL_C", - "lastUpdated": "2026-07-18" + "id": "PMN_DTL_C" }, "paidArea": true, "modes": [ @@ -239,13 +237,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PMN_CCL_A", - "lastUpdated": "2026-07-18" + "id": "PMN_CCL_A" }, "to": { "kind": "platform", - "id": "PMN_DTL_D", - "lastUpdated": "2026-07-18" + "id": "PMN_DTL_D" }, "paidArea": true, "modes": [ @@ -261,13 +257,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PMN_CCL_B", - "lastUpdated": "2026-07-18" + "id": "PMN_CCL_B" }, "to": { "kind": "platform", - "id": "PMN_DTL_C", - "lastUpdated": "2026-07-18" + "id": "PMN_DTL_C" }, "paidArea": true, "modes": [ @@ -283,13 +277,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PMN_CCL_B", - "lastUpdated": "2026-07-18" + "id": "PMN_CCL_B" }, "to": { "kind": "platform", - "id": "PMN_DTL_D", - "lastUpdated": "2026-07-18" + "id": "PMN_DTL_D" }, "paidArea": true, "modes": [ diff --git a/data/station/PYL.json b/data/station/PYL.json index 9804c586..1f85b79a 100644 --- a/data/station/PYL.json +++ b/data/station/PYL.json @@ -231,13 +231,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_A", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_A" }, "to": { "kind": "platform", - "id": "PYL_CCL_A", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_A" }, "paidArea": true, "modes": [ @@ -253,13 +251,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_A", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_A" }, "to": { "kind": "platform", - "id": "PYL_CCL_C", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_C" }, "paidArea": true, "modes": [ @@ -275,13 +271,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_A", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_A" }, "to": { "kind": "platform", - "id": "PYL_CCL_D", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_D" }, "paidArea": true, "modes": [ @@ -297,13 +291,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_A", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_A" }, "to": { "kind": "platform", - "id": "PYL_CCL_B", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_B" }, "paidArea": true, "modes": [ @@ -319,13 +311,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_B", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_B" }, "to": { "kind": "platform", - "id": "PYL_CCL_A", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_A" }, "paidArea": true, "modes": [ @@ -341,13 +331,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_B", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_B" }, "to": { "kind": "platform", - "id": "PYL_CCL_C", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_C" }, "paidArea": true, "modes": [ @@ -363,13 +351,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_B", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_B" }, "to": { "kind": "platform", - "id": "PYL_CCL_D", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_D" }, "paidArea": true, "modes": [ @@ -385,13 +371,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "PYL_EWL_B", - "lastUpdated": "2026-07-18" + "id": "PYL_EWL_B" }, "to": { "kind": "platform", - "id": "PYL_CCL_B", - "lastUpdated": "2026-07-18" + "id": "PYL_CCL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/RFP.json b/data/station/RFP.json index d2f8e39a..f3207274 100644 --- a/data/station/RFP.json +++ b/data/station/RFP.json @@ -239,13 +239,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "RFP_EWL_A", - "lastUpdated": "2026-07-18" + "id": "RFP_EWL_A" }, "to": { "kind": "platform", - "id": "RFP_NSL_B", - "lastUpdated": "2026-07-18" + "id": "RFP_NSL_B" }, "paidArea": true, "modes": [ @@ -261,13 +259,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "RFP_EWL_C", - "lastUpdated": "2026-07-18" + "id": "RFP_EWL_C" }, "to": { "kind": "platform", - "id": "RFP_NSL_D", - "lastUpdated": "2026-07-18" + "id": "RFP_NSL_D" }, "paidArea": true, "modes": [ @@ -283,13 +279,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "RFP_EWL_A", - "lastUpdated": "2026-07-18" + "id": "RFP_EWL_A" }, "to": { "kind": "platform", - "id": "RFP_NSL_D", - "lastUpdated": "2026-07-18" + "id": "RFP_NSL_D" }, "paidArea": true, "modes": [ @@ -305,13 +299,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "RFP_NSL_B", - "lastUpdated": "2026-07-18" + "id": "RFP_NSL_B" }, "to": { "kind": "platform", - "id": "RFP_EWL_C", - "lastUpdated": "2026-07-18" + "id": "RFP_EWL_C" }, "paidArea": true, "modes": [ diff --git a/data/station/SER.json b/data/station/SER.json index 846a1c5d..6b7f338c 100644 --- a/data/station/SER.json +++ b/data/station/SER.json @@ -226,13 +226,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SER_NEL_A", - "lastUpdated": "2026-07-18" + "id": "SER_NEL_A" }, "to": { "kind": "platform", - "id": "SER_CCL_A", - "lastUpdated": "2026-07-18" + "id": "SER_CCL_A" }, "paidArea": true, "modes": [ @@ -248,13 +246,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SER_NEL_A", - "lastUpdated": "2026-07-18" + "id": "SER_NEL_A" }, "to": { "kind": "platform", - "id": "SER_CCL_B", - "lastUpdated": "2026-07-18" + "id": "SER_CCL_B" }, "paidArea": true, "modes": [ @@ -270,13 +266,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SER_NEL_B", - "lastUpdated": "2026-07-18" + "id": "SER_NEL_B" }, "to": { "kind": "platform", - "id": "SER_CCL_A", - "lastUpdated": "2026-07-18" + "id": "SER_CCL_A" }, "paidArea": true, "modes": [ @@ -292,13 +286,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SER_NEL_B", - "lastUpdated": "2026-07-18" + "id": "SER_NEL_B" }, "to": { "kind": "platform", - "id": "SER_CCL_B", - "lastUpdated": "2026-07-18" + "id": "SER_CCL_B" }, "paidArea": true, "modes": [ diff --git a/data/station/SKG.json b/data/station/SKG.json index c92ec782..caeae033 100644 --- a/data/station/SKG.json +++ b/data/station/SKG.json @@ -158,13 +158,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SKG_NEL_A", - "lastUpdated": "2026-07-18" + "id": "SKG_NEL_A" }, "to": { "kind": "platform", - "id": "SKG_SKLRT_1", - "lastUpdated": "2026-07-18" + "id": "SKG_SKLRT_1" }, "paidArea": true, "modes": [ @@ -180,13 +178,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SKG_NEL_A", - "lastUpdated": "2026-07-18" + "id": "SKG_NEL_A" }, "to": { "kind": "platform", - "id": "SKG_SKLRT_2", - "lastUpdated": "2026-07-18" + "id": "SKG_SKLRT_2" }, "paidArea": true, "modes": [ @@ -202,13 +198,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SKG_NEL_B", - "lastUpdated": "2026-07-18" + "id": "SKG_NEL_B" }, "to": { "kind": "platform", - "id": "SKG_SKLRT_1", - "lastUpdated": "2026-07-18" + "id": "SKG_SKLRT_1" }, "paidArea": true, "modes": [ @@ -224,13 +218,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "SKG_NEL_B", - "lastUpdated": "2026-07-18" + "id": "SKG_NEL_B" }, "to": { "kind": "platform", - "id": "SKG_SKLRT_2", - "lastUpdated": "2026-07-18" + "id": "SKG_SKLRT_2" }, "paidArea": true, "modes": [ diff --git a/data/station/STV.json b/data/station/STV.json index d0a475be..393081e1 100644 --- a/data/station/STV.json +++ b/data/station/STV.json @@ -202,13 +202,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "STV_DTL_A", - "lastUpdated": "2026-07-18" + "id": "STV_DTL_A" }, "to": { "kind": "platform", - "id": "STV_TEL_C", - "lastUpdated": "2026-07-18" + "id": "STV_TEL_C" }, "paidArea": true, "modes": [ @@ -224,13 +222,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "STV_DTL_A", - "lastUpdated": "2026-07-18" + "id": "STV_DTL_A" }, "to": { "kind": "platform", - "id": "STV_TEL_D", - "lastUpdated": "2026-07-18" + "id": "STV_TEL_D" }, "paidArea": true, "modes": [ @@ -246,13 +242,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "STV_DTL_B", - "lastUpdated": "2026-07-18" + "id": "STV_DTL_B" }, "to": { "kind": "platform", - "id": "STV_TEL_C", - "lastUpdated": "2026-07-18" + "id": "STV_TEL_C" }, "paidArea": true, "modes": [ @@ -268,13 +262,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "STV_DTL_B", - "lastUpdated": "2026-07-18" + "id": "STV_DTL_B" }, "to": { "kind": "platform", - "id": "STV_TEL_D", - "lastUpdated": "2026-07-18" + "id": "STV_TEL_D" }, "paidArea": true, "modes": [ diff --git a/data/station/TAM.json b/data/station/TAM.json index 70105c54..1eb94dba 100644 --- a/data/station/TAM.json +++ b/data/station/TAM.json @@ -202,13 +202,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "TAM_EWL_A", - "lastUpdated": "2026-07-18" + "id": "TAM_EWL_A" }, "to": { "kind": "platform", - "id": "TAM_DTL_A", - "lastUpdated": "2026-07-18" + "id": "TAM_DTL_A" }, "paidArea": false, "modes": [ @@ -224,13 +222,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "TAM_EWL_A", - "lastUpdated": "2026-07-18" + "id": "TAM_EWL_A" }, "to": { "kind": "platform", - "id": "TAM_DTL_B", - "lastUpdated": "2026-07-18" + "id": "TAM_DTL_B" }, "paidArea": false, "modes": [ @@ -246,13 +242,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "TAM_EWL_B", - "lastUpdated": "2026-07-18" + "id": "TAM_EWL_B" }, "to": { "kind": "platform", - "id": "TAM_DTL_A", - "lastUpdated": "2026-07-18" + "id": "TAM_DTL_A" }, "paidArea": false, "modes": [ @@ -268,13 +262,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "TAM_EWL_B", - "lastUpdated": "2026-07-18" + "id": "TAM_EWL_B" }, "to": { "kind": "platform", - "id": "TAM_DTL_B", - "lastUpdated": "2026-07-18" + "id": "TAM_DTL_B" }, "paidArea": false, "modes": [ diff --git a/data/station/WDL.json b/data/station/WDL.json index b62cb7c1..6ba9a26a 100644 --- a/data/station/WDL.json +++ b/data/station/WDL.json @@ -214,13 +214,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "WDL_NSL_A", - "lastUpdated": "2026-07-18" + "id": "WDL_NSL_A" }, "to": { "kind": "platform", - "id": "WDL_TEL_C", - "lastUpdated": "2026-07-18" + "id": "WDL_TEL_C" }, "paidArea": true, "modes": [ @@ -236,13 +234,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "WDL_NSL_A", - "lastUpdated": "2026-07-18" + "id": "WDL_NSL_A" }, "to": { "kind": "platform", - "id": "WDL_TEL_D", - "lastUpdated": "2026-07-18" + "id": "WDL_TEL_D" }, "paidArea": true, "modes": [ @@ -258,13 +254,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "WDL_NSL_B", - "lastUpdated": "2026-07-18" + "id": "WDL_NSL_B" }, "to": { "kind": "platform", - "id": "WDL_TEL_C", - "lastUpdated": "2026-07-18" + "id": "WDL_TEL_C" }, "paidArea": true, "modes": [ @@ -280,13 +274,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "WDL_NSL_B", - "lastUpdated": "2026-07-18" + "id": "WDL_NSL_B" }, "to": { "kind": "platform", - "id": "WDL_TEL_D", - "lastUpdated": "2026-07-18" + "id": "WDL_TEL_D" }, "paidArea": true, "modes": [ diff --git a/data/station/XPO.json b/data/station/XPO.json index 584eacda..c2c9d0f9 100644 --- a/data/station/XPO.json +++ b/data/station/XPO.json @@ -196,10 +196,9 @@ "id": "XPO_DTL_D", "label": "D", "lastUpdated": "2026-07-18", + "boardingStatus": "alighting_only", "lineId": "DTL", - "serviceIds": [ - "DTL_MAIN_E" - ], + "serviceIds": [], "doorCount": 12, "accessPoints": [] } @@ -210,13 +209,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "XPO_EWL_A", - "lastUpdated": "2026-07-18" + "id": "XPO_EWL_A" }, "to": { "kind": "platform", - "id": "XPO_DTL_C", - "lastUpdated": "2026-07-18" + "id": "XPO_DTL_C" }, "paidArea": true, "modes": [ @@ -232,13 +229,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "XPO_EWL_A", - "lastUpdated": "2026-07-18" + "id": "XPO_EWL_A" }, "to": { "kind": "platform", - "id": "XPO_DTL_D", - "lastUpdated": "2026-07-18" + "id": "XPO_DTL_D" }, "paidArea": true, "modes": [ @@ -254,13 +249,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "XPO_EWL_B", - "lastUpdated": "2026-07-18" + "id": "XPO_EWL_B" }, "to": { "kind": "platform", - "id": "XPO_DTL_C", - "lastUpdated": "2026-07-18" + "id": "XPO_DTL_C" }, "paidArea": true, "modes": [ @@ -276,13 +269,11 @@ "lastUpdated": "2026-07-18", "from": { "kind": "platform", - "id": "XPO_EWL_B", - "lastUpdated": "2026-07-18" + "id": "XPO_EWL_B" }, "to": { "kind": "platform", - "id": "XPO_DTL_D", - "lastUpdated": "2026-07-18" + "id": "XPO_DTL_D" }, "paidArea": true, "modes": [ diff --git a/docs/plans/active/station-layout-data.md b/docs/plans/active/station-layout-data.md index 392a5be8..83b12f8f 100644 --- a/docs/plans/active/station-layout-data.md +++ b/docs/plans/active/station-layout-data.md @@ -201,7 +201,9 @@ Rules: ## Platforms Platforms represent public boarding areas. They should reference full scheduled -service patterns through `serviceIds`. +service patterns through `serviceIds`. A terminal platform used only to unload +arriving passengers remains part of the layout with `boardingStatus` set to +`alighting_only`. ```json { @@ -220,6 +222,8 @@ Rules: - Use `serviceIds`, not `towardsStationId`. The service path is the source of truth for direction, stopping pattern, and terminal. - Use an array because platforms can host multiple scheduled patterns. +- `serviceIds` must not be empty unless `boardingStatus` is `alighting_only`. + Alighting-only platforms do not advertise an arriving service as boardable. - `doorCount` is preferred over enumerating every door when doors have no individual metadata. - Keep `lineId` for simple validation and authoring, even though it can be @@ -319,6 +323,9 @@ Initial `classification` values: The classification is intentionally coarse. It is useful for routing and user interfaces without pretending that all stations have measured distance data. +Transfer endpoint objects are lightweight references and therefore contain only +`kind` and `id`; provenance belongs to the transfer path and referenced layout +record rather than being duplicated on each reference. ## Validation diff --git a/packages/core/src/schema/Station.test.ts b/packages/core/src/schema/Station.test.ts index df36f1e5..fc3d9833 100644 --- a/packages/core/src/schema/Station.test.ts +++ b/packages/core/src/schema/Station.test.ts @@ -228,12 +228,10 @@ describe('StationSchema', () => { from: { kind: 'platform', id: 'KET_ISL_A', - lastUpdated: '2026-07-18', }, to: { kind: 'level', id: 'B2', - lastUpdated: '2026-07-18', }, paidArea: true, modes: ['walk', 'escalator'], @@ -298,4 +296,28 @@ describe('StationSchema', () => { 'layout.platforms.0.serviceIds', ); }); + + it('accepts alighting-only platforms without service ids', () => { + expect(() => + StationSchema.parse({ + ...minimalStation(), + layout: { + levels: [], + exits: [], + platforms: [ + { + id: 'KET_ISL_A', + label: 'A', + lastUpdated: '2026-07-18', + boardingStatus: 'alighting_only', + lineId: 'ISL', + serviceIds: [], + accessPoints: [], + }, + ], + transferPaths: [], + }, + }), + ).not.toThrow(); + }); }); diff --git a/packages/core/src/schema/Station.ts b/packages/core/src/schema/Station.ts index dd96f870..3e47d8ba 100644 --- a/packages/core/src/schema/Station.ts +++ b/packages/core/src/schema/Station.ts @@ -185,22 +185,43 @@ export type StationLayoutAccessPoint = z.infer< typeof StationLayoutAccessPointSchema >; -export const StationLayoutPlatformSchema = z.object({ - id: z.string(), - label: z.string(), - lastUpdated: z.iso.date(), - lineId: z.string(), - levelId: z.string().optional(), - serviceIds: z.array(z.string()).nonempty(), - doorCount: z.number().int().positive().optional(), - accessPoints: z.array(StationLayoutAccessPointSchema), -}); +export const StationLayoutPlatformBoardingStatusSchema = z.enum([ + 'alighting_only', +]); +export type StationLayoutPlatformBoardingStatus = z.infer< + typeof StationLayoutPlatformBoardingStatusSchema +>; + +export const StationLayoutPlatformSchema = z + .object({ + id: z.string(), + label: z.string(), + lastUpdated: z.iso.date(), + boardingStatus: StationLayoutPlatformBoardingStatusSchema.optional(), + lineId: z.string(), + levelId: z.string().optional(), + serviceIds: z.array(z.string()), + doorCount: z.number().int().positive().optional(), + accessPoints: z.array(StationLayoutAccessPointSchema), + }) + .superRefine((platform, context) => { + if ( + platform.serviceIds.length === 0 && + platform.boardingStatus !== 'alighting_only' + ) { + context.addIssue({ + code: 'custom', + message: + 'serviceIds must not be empty unless the platform is alighting-only', + path: ['serviceIds'], + }); + } + }); export type StationLayoutPlatform = z.infer; export const StationLayoutTransferEndpointSchema = z.object({ kind: StationLayoutTransferEndpointKindSchema, id: z.string(), - lastUpdated: z.iso.date(), }); export type StationLayoutTransferEndpoint = z.infer< typeof StationLayoutTransferEndpointSchema diff --git a/packages/fs/src/index.test.ts b/packages/fs/src/index.test.ts index 48912843..1bef1b82 100644 --- a/packages/fs/src/index.test.ts +++ b/packages/fs/src/index.test.ts @@ -2961,12 +2961,10 @@ describe('@mrtdown/fs', () => { from: { kind: 'platform', id: 'MISSING_PLATFORM', - lastUpdated: '2026-07-18', }, to: { kind: 'access_point', id: 'MISSING_ACCESS_POINT', - lastUpdated: '2026-07-18', }, paidArea: true, modes: ['walk'], From 2fb6ccd12486ef71090f29bbd509d39a673d240e Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 15:55:26 +0800 Subject: [PATCH 12/20] fix: model non-boardable station platforms --- .changeset/closed-exits-update.md | 2 +- data/station/CCK.json | 92 ++---------------------- data/station/PER.json | 1 - data/station/PYL.json | 92 ++---------------------- data/station/TNM.json | 47 +++++++++++- docs/plans/active/station-layout-data.md | 9 ++- packages/core/src/schema/Station.test.ts | 27 +++++++ packages/core/src/schema/Station.ts | 16 +++-- 8 files changed, 99 insertions(+), 187 deletions(-) diff --git a/.changeset/closed-exits-update.md b/.changeset/closed-exits-update.md index 04bf1ef1..d7aea615 100644 --- a/.changeset/closed-exits-update.md +++ b/.changeset/closed-exits-update.md @@ -4,5 +4,5 @@ --- Require provenance dates on durable station layout records, add temporary exit -closure and alighting-only platform statuses, and keep transfer endpoints as +closure and non-boardable platform statuses, and keep transfer endpoints as lightweight references. diff --git a/data/station/CCK.json b/data/station/CCK.json index 323072c5..57d284ce 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -195,22 +195,18 @@ "id": "CCK_BPLRT_3", "label": "3", "lastUpdated": "2026-07-18", + "boardingStatus": "alighting_only", "lineId": "BPLRT", - "serviceIds": [ - "BPLRT_A", - "BPLRT_B" - ], + "serviceIds": [], "accessPoints": [] }, { "id": "CCK_BPLRT_4", "label": "4", "lastUpdated": "2026-07-18", + "boardingStatus": "alighting_only", "lineId": "BPLRT", - "serviceIds": [ - "BPLRT_A", - "BPLRT_B" - ], + "serviceIds": [], "accessPoints": [] } ], @@ -255,46 +251,6 @@ "estimatedTraversalSeconds": null, "distanceMeters": null }, - { - "id": "CCK_XFER_NSL_A_BPLRT_3", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "CCK_NSL_A" - }, - "to": { - "kind": "platform", - "id": "CCK_BPLRT_3" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, - { - "id": "CCK_XFER_NSL_A_BPLRT_4", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "CCK_NSL_A" - }, - "to": { - "kind": "platform", - "id": "CCK_BPLRT_4" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, { "id": "CCK_XFER_NSL_B_BPLRT_1", "lastUpdated": "2026-07-18", @@ -334,46 +290,6 @@ "classification": "unknown", "estimatedTraversalSeconds": null, "distanceMeters": null - }, - { - "id": "CCK_XFER_NSL_B_BPLRT_3", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "CCK_NSL_B" - }, - "to": { - "kind": "platform", - "id": "CCK_BPLRT_3" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, - { - "id": "CCK_XFER_NSL_B_BPLRT_4", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "CCK_NSL_B" - }, - "to": { - "kind": "platform", - "id": "CCK_BPLRT_4" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null } ] } diff --git a/data/station/PER.json b/data/station/PER.json index f34650c1..27d76fa9 100644 --- a/data/station/PER.json +++ b/data/station/PER.json @@ -36,7 +36,6 @@ "lastUpdated": "2026-07-18", "lineId": "CCL", "serviceIds": [ - "CCL_BRANCH_CCW", "CCL_LOOP_CCW" ], "doorCount": 12, diff --git a/data/station/PYL.json b/data/station/PYL.json index 1f85b79a..191038ef 100644 --- a/data/station/PYL.json +++ b/data/station/PYL.json @@ -192,11 +192,9 @@ "id": "PYL_CCL_C", "label": "C", "lastUpdated": "2026-07-18", + "boardingStatus": "not_in_service", "lineId": "CCL", - "serviceIds": [ - "CCL_BRANCH_CCW", - "CCL_LOOP_CCW" - ], + "serviceIds": [], "doorCount": 12, "accessPoints": [] }, @@ -204,11 +202,9 @@ "id": "PYL_CCL_D", "label": "D", "lastUpdated": "2026-07-18", + "boardingStatus": "not_in_service", "lineId": "CCL", - "serviceIds": [ - "CCL_BRANCH_CCW", - "CCL_LOOP_CCW" - ], + "serviceIds": [], "doorCount": 12, "accessPoints": [] }, @@ -246,46 +242,6 @@ "estimatedTraversalSeconds": null, "distanceMeters": null }, - { - "id": "PYL_XFER_EWL_A_CCL_C", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "PYL_EWL_A" - }, - "to": { - "kind": "platform", - "id": "PYL_CCL_C" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, - { - "id": "PYL_XFER_EWL_A_CCL_D", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "PYL_EWL_A" - }, - "to": { - "kind": "platform", - "id": "PYL_CCL_D" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, { "id": "PYL_XFER_EWL_A_CCL_B", "lastUpdated": "2026-07-18", @@ -326,46 +282,6 @@ "estimatedTraversalSeconds": null, "distanceMeters": null }, - { - "id": "PYL_XFER_EWL_B_CCL_C", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "PYL_EWL_B" - }, - "to": { - "kind": "platform", - "id": "PYL_CCL_C" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, - { - "id": "PYL_XFER_EWL_B_CCL_D", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "PYL_EWL_B" - }, - "to": { - "kind": "platform", - "id": "PYL_CCL_D" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, { "id": "PYL_XFER_EWL_B_CCL_B", "lastUpdated": "2026-07-18", diff --git a/data/station/TNM.json b/data/station/TNM.json index d97e828f..f72d45fc 100644 --- a/data/station/TNM.json +++ b/data/station/TNM.json @@ -78,7 +78,32 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "TNM_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "roadNames": [ + "New Upper Changi Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "TNM_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "roadNames": [ + "New Upper Changi Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + } + ], "platforms": [ { "id": "TNM_EWL_A", @@ -91,6 +116,26 @@ "doorCount": 24, "accessPoints": [] }, + { + "id": "TNM_EWL_B", + "label": "B", + "lastUpdated": "2026-07-18", + "boardingStatus": "not_in_service", + "lineId": "EWL", + "serviceIds": [], + "doorCount": 24, + "accessPoints": [] + }, + { + "id": "TNM_EWL_C", + "label": "C", + "lastUpdated": "2026-07-18", + "boardingStatus": "not_in_service", + "lineId": "EWL", + "serviceIds": [], + "doorCount": 24, + "accessPoints": [] + }, { "id": "TNM_EWL_D", "label": "D", diff --git a/docs/plans/active/station-layout-data.md b/docs/plans/active/station-layout-data.md index 83b12f8f..bb2d54e7 100644 --- a/docs/plans/active/station-layout-data.md +++ b/docs/plans/active/station-layout-data.md @@ -203,7 +203,8 @@ Rules: Platforms represent public boarding areas. They should reference full scheduled service patterns through `serviceIds`. A terminal platform used only to unload arriving passengers remains part of the layout with `boardingStatus` set to -`alighting_only`. +`alighting_only`. A platform that exists physically but is unavailable for +ordinary passenger service uses `not_in_service`. ```json { @@ -222,8 +223,10 @@ Rules: - Use `serviceIds`, not `towardsStationId`. The service path is the source of truth for direction, stopping pattern, and terminal. - Use an array because platforms can host multiple scheduled patterns. -- `serviceIds` must not be empty unless `boardingStatus` is `alighting_only`. - Alighting-only platforms do not advertise an arriving service as boardable. +- `serviceIds` must be non-empty for ordinary boarding platforms and empty when + `boardingStatus` is `alighting_only` or `not_in_service`. Non-boardable + platforms do not advertise arriving, occasional, or inactive services as + boardable. - `doorCount` is preferred over enumerating every door when doors have no individual metadata. - Keep `lineId` for simple validation and authoring, even though it can be diff --git a/packages/core/src/schema/Station.test.ts b/packages/core/src/schema/Station.test.ts index fc3d9833..baefa1ec 100644 --- a/packages/core/src/schema/Station.test.ts +++ b/packages/core/src/schema/Station.test.ts @@ -320,4 +320,31 @@ describe('StationSchema', () => { }), ).not.toThrow(); }); + + it('rejects service ids on non-boardable platforms', () => { + const result = StationSchema.safeParse({ + ...minimalStation(), + layout: { + levels: [], + exits: [], + platforms: [ + { + id: 'KET_ISL_A', + label: 'A', + lastUpdated: '2026-07-18', + boardingStatus: 'alighting_only', + lineId: 'ISL', + serviceIds: ['ISL_MAIN_E'], + accessPoints: [], + }, + ], + transferPaths: [], + }, + }); + + expect(result.success).toBe(false); + expect(result.error?.issues[0]?.path.join('.')).toBe( + 'layout.platforms.0.serviceIds', + ); + }); }); diff --git a/packages/core/src/schema/Station.ts b/packages/core/src/schema/Station.ts index 3e47d8ba..c0c4684e 100644 --- a/packages/core/src/schema/Station.ts +++ b/packages/core/src/schema/Station.ts @@ -187,6 +187,7 @@ export type StationLayoutAccessPoint = z.infer< export const StationLayoutPlatformBoardingStatusSchema = z.enum([ 'alighting_only', + 'not_in_service', ]); export type StationLayoutPlatformBoardingStatus = z.infer< typeof StationLayoutPlatformBoardingStatusSchema @@ -205,14 +206,19 @@ export const StationLayoutPlatformSchema = z accessPoints: z.array(StationLayoutAccessPointSchema), }) .superRefine((platform, context) => { - if ( - platform.serviceIds.length === 0 && - platform.boardingStatus !== 'alighting_only' - ) { + if (platform.serviceIds.length === 0 && !platform.boardingStatus) { context.addIssue({ code: 'custom', message: - 'serviceIds must not be empty unless the platform is alighting-only', + 'serviceIds must not be empty unless the platform is non-boardable', + path: ['serviceIds'], + }); + } + + if (platform.serviceIds.length > 0 && platform.boardingStatus) { + context.addIssue({ + code: 'custom', + message: 'non-boardable platforms must not advertise serviceIds', path: ['serviceIds'], }); } From 1efa17b4b8d6ea243dbc7eddd288080a57e8870f Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 16:22:45 +0800 Subject: [PATCH 13/20] fix: disambiguate station platform services --- .changeset/closed-exits-update.md | 5 +- data/station/BKP.json | 65 +++++++++++++++++++- data/station/CCK.json | 8 +++ data/station/HBF.json | 6 ++ data/station/KTH.json | 8 +++ data/station/MRB.json | 26 ++++++++ data/station/PGL.json | 8 +++ data/station/PNX.json | 8 +++ data/station/SHV.json | 8 +++ data/station/SKG.json | 8 +++ data/station/TKW.json | 8 +++ data/station/XPO.json | 40 ------------ docs/plans/active/station-layout-data.md | 6 ++ packages/core/src/schema/Station.test.ts | 29 +++++++++ packages/core/src/schema/Station.ts | 15 +++++ packages/fs/src/index.test.ts | 78 +++++++++++++++++++++++- packages/fs/src/validate.ts | 38 +++++++++++- 17 files changed, 317 insertions(+), 47 deletions(-) diff --git a/.changeset/closed-exits-update.md b/.changeset/closed-exits-update.md index d7aea615..50583fad 100644 --- a/.changeset/closed-exits-update.md +++ b/.changeset/closed-exits-update.md @@ -4,5 +4,6 @@ --- Require provenance dates on durable station layout records, add temporary exit -closure and non-boardable platform statuses, and keep transfer endpoints as -lightweight references. +closure and non-boardable platform statuses, disambiguate repeated service +stops, validate platform mappings against open service revisions, and keep +transfer endpoints as lightweight references. diff --git a/data/station/BKP.json b/data/station/BKP.json index b33e52da..2a55b61b 100644 --- a/data/station/BKP.json +++ b/data/station/BKP.json @@ -88,7 +88,62 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "BKP_EXIT_A1", + "label": "A1", + "lastUpdated": "2026-07-18", + "roadNames": [ + "Upper Bukit Timah Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BKP_EXIT_A2", + "label": "A2", + "lastUpdated": "2026-07-18", + "roadNames": [ + "Upper Bukit Timah Road" + ], + "paidArea": false + }, + { + "id": "BKP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-18", + "roadNames": [ + "Upper Bukit Timah Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BKP_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-18", + "roadNames": [ + "Bukit Panjang Road" + ], + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, + { + "id": "BKP_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], "platforms": [ { "id": "BKP_BPLRT_1", @@ -99,6 +154,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 1, + "BPLRT_B": 1 + }, "accessPoints": [] }, { @@ -110,6 +169,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] }, { diff --git a/data/station/CCK.json b/data/station/CCK.json index 57d284ce..68de647d 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -178,6 +178,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] }, { @@ -189,6 +193,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] }, { diff --git a/data/station/HBF.json b/data/station/HBF.json index b91145bb..469ca23b 100644 --- a/data/station/HBF.json +++ b/data/station/HBF.json @@ -148,6 +148,9 @@ "CCL_BRANCH_CCW", "CCL_LOOP_CCW" ], + "serviceStopOccurrences": { + "CCL_LOOP_CCW": 0 + }, "doorCount": 12, "accessPoints": [] }, @@ -160,6 +163,9 @@ "CCL_BRANCH_CW", "CCL_LOOP_CW" ], + "serviceStopOccurrences": { + "CCL_LOOP_CW": 0 + }, "doorCount": 12, "accessPoints": [] } diff --git a/data/station/KTH.json b/data/station/KTH.json index 71a4853b..dcf75e5a 100644 --- a/data/station/KTH.json +++ b/data/station/KTH.json @@ -74,6 +74,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 1, + "BPLRT_B": 1 + }, "accessPoints": [] }, { @@ -85,6 +89,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] } ], diff --git a/data/station/MRB.json b/data/station/MRB.json index 236cc9a5..f2bd1537 100644 --- a/data/station/MRB.json +++ b/data/station/MRB.json @@ -150,6 +150,32 @@ "lastUpdated": "2026-07-18", "paidArea": false }, + { + "id": "MRB_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-18", + "roadNames": [ + "Bayfront Avenue", + "Park Street" + ], + "paidArea": false, + "accessibility": { + "stepFree": true + } + }, + { + "id": "MRB_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-18", + "roadNames": [ + "Sheares Avenue" + ], + "paidArea": false, + "accessibility": { + "stepFree": true, + "lift": true + } + }, { "id": "MRB_EXIT_5", "label": "5", diff --git a/data/station/PGL.json b/data/station/PGL.json index 75251f61..fcb8c454 100644 --- a/data/station/PGL.json +++ b/data/station/PGL.json @@ -149,6 +149,10 @@ "PGLRT_W_CW", "PGLRT_E_CCW" ], + "serviceStopOccurrences": { + "PGLRT_W_CW": 0, + "PGLRT_E_CCW": 0 + }, "accessPoints": [] }, { @@ -160,6 +164,10 @@ "PGLRT_W_CCW", "PGLRT_E_CW" ], + "serviceStopOccurrences": { + "PGLRT_W_CCW": 0, + "PGLRT_E_CW": 0 + }, "accessPoints": [] } ], diff --git a/data/station/PNX.json b/data/station/PNX.json index 79ee9590..7d2490dc 100644 --- a/data/station/PNX.json +++ b/data/station/PNX.json @@ -74,6 +74,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 1, + "BPLRT_B": 1 + }, "accessPoints": [] }, { @@ -85,6 +89,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] } ], diff --git a/data/station/SHV.json b/data/station/SHV.json index e07d03de..6f21f942 100644 --- a/data/station/SHV.json +++ b/data/station/SHV.json @@ -76,6 +76,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 1, + "BPLRT_B": 1 + }, "accessPoints": [] }, { @@ -87,6 +91,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] } ], diff --git a/data/station/SKG.json b/data/station/SKG.json index caeae033..7ce62beb 100644 --- a/data/station/SKG.json +++ b/data/station/SKG.json @@ -138,6 +138,10 @@ "SKLRT_E_CCW", "SKLRT_W_CW" ], + "serviceStopOccurrences": { + "SKLRT_E_CCW": 0, + "SKLRT_W_CW": 0 + }, "accessPoints": [] }, { @@ -149,6 +153,10 @@ "SKLRT_E_CW", "SKLRT_W_CCW" ], + "serviceStopOccurrences": { + "SKLRT_E_CW": 0, + "SKLRT_W_CCW": 0 + }, "accessPoints": [] } ], diff --git a/data/station/TKW.json b/data/station/TKW.json index bc6f8913..c7ca6d3d 100644 --- a/data/station/TKW.json +++ b/data/station/TKW.json @@ -75,6 +75,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 1, + "BPLRT_B": 1 + }, "accessPoints": [] }, { @@ -86,6 +90,10 @@ "BPLRT_A", "BPLRT_B" ], + "serviceStopOccurrences": { + "BPLRT_A": 0, + "BPLRT_B": 0 + }, "accessPoints": [] } ], diff --git a/data/station/XPO.json b/data/station/XPO.json index c2c9d0f9..d96ba377 100644 --- a/data/station/XPO.json +++ b/data/station/XPO.json @@ -224,26 +224,6 @@ "estimatedTraversalSeconds": null, "distanceMeters": null }, - { - "id": "XPO_XFER_EWL_A_DTL_D", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "XPO_EWL_A" - }, - "to": { - "kind": "platform", - "id": "XPO_DTL_D" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null - }, { "id": "XPO_XFER_EWL_B_DTL_C", "lastUpdated": "2026-07-18", @@ -263,26 +243,6 @@ "classification": "unknown", "estimatedTraversalSeconds": null, "distanceMeters": null - }, - { - "id": "XPO_XFER_EWL_B_DTL_D", - "lastUpdated": "2026-07-18", - "from": { - "kind": "platform", - "id": "XPO_EWL_B" - }, - "to": { - "kind": "platform", - "id": "XPO_DTL_D" - }, - "paidArea": true, - "modes": [ - "walk" - ], - "levelChange": null, - "classification": "unknown", - "estimatedTraversalSeconds": null, - "distanceMeters": null } ] } diff --git a/docs/plans/active/station-layout-data.md b/docs/plans/active/station-layout-data.md index bb2d54e7..a89bec03 100644 --- a/docs/plans/active/station-layout-data.md +++ b/docs/plans/active/station-layout-data.md @@ -223,6 +223,10 @@ Rules: - Use `serviceIds`, not `towardsStationId`. The service path is the source of truth for direction, stopping pattern, and terminal. - Use an array because platforms can host multiple scheduled patterns. +- `serviceStopOccurrences` optionally maps a service id to the zero-based + occurrence of this station in the current service path. It is required when + a loop service visits the station more than once, so consumers can derive the + correct next stop for each platform. - `serviceIds` must be non-empty for ordinary boarding platforms and empty when `boardingStatus` is `alighting_only` or `not_in_service`. Non-boardable platforms do not advertise arriving, occasional, or inactive services as @@ -344,6 +348,8 @@ Add validation that catches: - platform `lineId` values that do not exist; - platform `levelId` values that do not exist in `layout.levels`; - platform `serviceIds` values that do not exist; +- platform services that omit or exceed a required repeated-stop occurrence in + an open service revision; - services whose `lineId` differs from the platform `lineId`; - transfer endpoints that do not reference an existing level, platform, or access point; diff --git a/packages/core/src/schema/Station.test.ts b/packages/core/src/schema/Station.test.ts index baefa1ec..958a88bd 100644 --- a/packages/core/src/schema/Station.test.ts +++ b/packages/core/src/schema/Station.test.ts @@ -347,4 +347,33 @@ describe('StationSchema', () => { 'layout.platforms.0.serviceIds', ); }); + + it('rejects stop occurrences for services not served by the platform', () => { + const result = StationSchema.safeParse({ + ...minimalStation(), + layout: { + levels: [], + exits: [], + platforms: [ + { + id: 'KET_ISL_A', + label: 'A', + lastUpdated: '2026-07-18', + lineId: 'ISL', + serviceIds: ['ISL_MAIN_E'], + serviceStopOccurrences: { + ISL_MAIN_W: 1, + }, + accessPoints: [], + }, + ], + transferPaths: [], + }, + }); + + expect(result.success).toBe(false); + expect(result.error?.issues[0]?.path.join('.')).toBe( + 'layout.platforms.0.serviceStopOccurrences.ISL_MAIN_W', + ); + }); }); diff --git a/packages/core/src/schema/Station.ts b/packages/core/src/schema/Station.ts index c0c4684e..edbd45b7 100644 --- a/packages/core/src/schema/Station.ts +++ b/packages/core/src/schema/Station.ts @@ -202,6 +202,9 @@ export const StationLayoutPlatformSchema = z lineId: z.string(), levelId: z.string().optional(), serviceIds: z.array(z.string()), + serviceStopOccurrences: z + .record(z.string(), z.number().int().nonnegative()) + .optional(), doorCount: z.number().int().positive().optional(), accessPoints: z.array(StationLayoutAccessPointSchema), }) @@ -222,6 +225,18 @@ export const StationLayoutPlatformSchema = z path: ['serviceIds'], }); } + + for (const serviceId of Object.keys( + platform.serviceStopOccurrences ?? {}, + )) { + if (!platform.serviceIds.includes(serviceId)) { + context.addIssue({ + code: 'custom', + message: 'service stop occurrences must reference a serviceId', + path: ['serviceStopOccurrences', serviceId], + }); + } + } }); export type StationLayoutPlatform = z.infer; diff --git a/packages/fs/src/index.test.ts b/packages/fs/src/index.test.ts index 1bef1b82..cad03b67 100644 --- a/packages/fs/src/index.test.ts +++ b/packages/fs/src/index.test.ts @@ -2943,7 +2943,7 @@ describe('@mrtdown/fs', () => { label: 'A', lastUpdated: '2026-07-18', lineId: 'ISL', - serviceIds: ['TWL_MAIN_N', 'ISL_SKIP_KET'], + serviceIds: ['TWL_MAIN_N', 'ISL_SKIP_KET', 'ISL_REPEAT_KET'], accessPoints: [ { id: 'KET_AP_DUP', @@ -2992,6 +2992,71 @@ describe('@mrtdown/fs', () => { ta: null, }, lineId: 'ISL', + revisions: [ + { + id: 'r_historical', + startAt: '1979-10-01', + endAt: '1980-01-01', + path: { + stations: [ + { + stationId: 'KET', + displayCode: 'ISL1', + }, + ], + }, + operatingHours: { + weekdays: { + start: '05:30', + end: '00:30', + }, + weekends: { + start: '05:30', + end: '00:30', + }, + }, + }, + { + id: 'r_current', + startAt: '1980-01-01', + endAt: null, + path: { + stations: [ + { + stationId: 'HKU', + displayCode: 'ISL2', + }, + ], + }, + operatingHours: { + weekdays: { + start: '05:30', + end: '00:30', + }, + weekends: { + start: '05:30', + end: '00:30', + }, + }, + }, + ], + }, + null, + 2, + )}\n`, + ); + await writeFile( + join(dataDir, 'service/ISL_REPEAT_KET.json'), + `${JSON.stringify( + { + id: 'ISL_REPEAT_KET', + name: { + 'en-SG': 'Kennedy Town Loop Service', + 'zh-Hans': null, + ms: null, + ta: null, + }, + lineId: 'ISL', revisions: [ { id: 'r_current', @@ -2999,10 +3064,18 @@ describe('@mrtdown/fs', () => { endAt: null, path: { stations: [ + { + stationId: 'KET', + displayCode: 'ISL1', + }, { stationId: 'HKU', displayCode: 'ISL2', }, + { + stationId: 'KET', + displayCode: 'ISL1', + }, ], }, operatingHours: { @@ -3070,7 +3143,8 @@ describe('@mrtdown/fs', () => { 'station/KET.json: layout.platforms.0.levelId MISSING does not exist in layout.levels', 'station/KET.json: layout.platforms.0.serviceIds.0 MISSING_SERVICE does not exist in service/', 'station/KET.json: layout.platforms.1.serviceIds.0 TWL_MAIN_N belongs to line TWL, not ISL', - 'station/KET.json: layout.platforms.1.serviceIds.1 ISL_SKIP_KET does not include station KET in any service revision', + 'station/KET.json: layout.platforms.1.serviceIds.1 ISL_SKIP_KET revision r_current does not include station KET in its open service path', + 'station/KET.json: layout.platforms.1.serviceIds.2 ISL_REPEAT_KET visits station KET 2 times in open revision r_current; serviceStopOccurrences.ISL_REPEAT_KET is required', 'station/KET.json: layout.platforms.0.accessPoints.0.connectsToLevelId MISSING does not exist in layout.levels', 'station/KET.json: layout.platforms.0.accessPoints.0.nearestDoor 25 is outside doorCount 24', 'station/KET.json: layout.transferPaths.0.from platform MISSING_PLATFORM does not exist in layout', diff --git a/packages/fs/src/validate.ts b/packages/fs/src/validate.ts index 3d7d8328..eabbc78f 100644 --- a/packages/fs/src/validate.ts +++ b/packages/fs/src/validate.ts @@ -412,10 +412,44 @@ async function validateStationReferences( continue; } - if (!serviceIncludesStation(service.value, station.value.id)) { + const openRevisions = service.value.revisions.filter( + (revision) => revision.endAt === null, + ); + if (openRevisions.length === 0) { errors.push( - `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} does not include station ${station.value.id} in any service revision`, + `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} does not have an open service revision`, ); + continue; + } + + for (const revision of openRevisions) { + const stationOccurrenceCount = revision.path.stations.filter( + (serviceStation) => serviceStation.stationId === station.value.id, + ).length; + if (stationOccurrenceCount === 0) { + errors.push( + `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} revision ${revision.id} does not include station ${station.value.id} in its open service path`, + ); + continue; + } + + const selectedOccurrence = + platform.serviceStopOccurrences?.[serviceId]; + if ( + stationOccurrenceCount > 1 && + selectedOccurrence === undefined + ) { + errors.push( + `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} visits station ${station.value.id} ${stationOccurrenceCount} times in open revision ${revision.id}; serviceStopOccurrences.${serviceId} is required`, + ); + } else if ( + selectedOccurrence !== undefined && + selectedOccurrence >= stationOccurrenceCount + ) { + errors.push( + `${station.path}: layout.platforms.${platformIndex}.serviceStopOccurrences.${serviceId} ${selectedOccurrence} is outside ${stationOccurrenceCount} station occurrences in open revision ${revision.id}`, + ); + } } } } From f9e5031541c696732c85e97dda8e2a0ec3a21042 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 17:34:50 +0800 Subject: [PATCH 14/20] fix: add operator-verified station exits --- data/station/CGA.json | 21 ++++++++++++++++++++- data/station/CTM.json | 27 ++++++++++++++++++++++++++- data/station/KPL.json | 15 ++++++++++++++- data/station/PER.json | 15 ++++++++++++++- 4 files changed, 74 insertions(+), 4 deletions(-) diff --git a/data/station/CGA.json b/data/station/CGA.json index b827b162..1628a743 100644 --- a/data/station/CGA.json +++ b/data/station/CGA.json @@ -55,7 +55,26 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "CGA_EXIT_TERMINAL_2", + "label": "Terminal 2", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CGA_EXIT_TERMINAL_2_3", + "label": "Terminal 2/3", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CGA_EXIT_TERMINAL_3", + "label": "Terminal 3", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], "platforms": [ { "id": "CGA_EWL_A", diff --git a/data/station/CTM.json b/data/station/CTM.json index 6aa8dd55..367b9208 100644 --- a/data/station/CTM.json +++ b/data/station/CTM.json @@ -27,7 +27,32 @@ "townId": "outram", "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "CTM_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CTM_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CTM_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "CTM_EXIT_4", + "label": "4", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], "platforms": [ { "id": "CTM_CCL_A", diff --git a/data/station/KPL.json b/data/station/KPL.json index d8a01b77..84700845 100644 --- a/data/station/KPL.json +++ b/data/station/KPL.json @@ -27,7 +27,20 @@ "townId": "bukit-merah", "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "KPL_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "KPL_EXIT_3", + "label": "3", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], "platforms": [ { "id": "KPL_CCL_A", diff --git a/data/station/PER.json b/data/station/PER.json index 27d76fa9..a72ddb99 100644 --- a/data/station/PER.json +++ b/data/station/PER.json @@ -28,7 +28,20 @@ "townId": "downtown-core", "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "PER_EXIT_1", + "label": "1", + "lastUpdated": "2026-07-18", + "paidArea": false + }, + { + "id": "PER_EXIT_2", + "label": "2", + "lastUpdated": "2026-07-18", + "paidArea": false + } + ], "platforms": [ { "id": "PER_CCL_A", From 5572439eab7a5976e867b4d300eed02e0dd7329b Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sat, 18 Jul 2026 18:05:31 +0800 Subject: [PATCH 15/20] fix: validate date-active service revisions --- .changeset/closed-exits-update.md | 5 +++-- packages/fs/src/index.test.ts | 18 ++++++++++++++++-- packages/fs/src/validate.ts | 19 +++++++++++-------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/.changeset/closed-exits-update.md b/.changeset/closed-exits-update.md index 50583fad..cd77293c 100644 --- a/.changeset/closed-exits-update.md +++ b/.changeset/closed-exits-update.md @@ -5,5 +5,6 @@ Require provenance dates on durable station layout records, add temporary exit closure and non-boardable platform statuses, disambiguate repeated service -stops, validate platform mappings against open service revisions, and keep -transfer endpoints as lightweight references. +stops, validate platform mappings against service revisions active on each +platform's provenance date, and keep transfer endpoints as lightweight +references. diff --git a/packages/fs/src/index.test.ts b/packages/fs/src/index.test.ts index cad03b67..cb2d6b37 100644 --- a/packages/fs/src/index.test.ts +++ b/packages/fs/src/index.test.ts @@ -3143,8 +3143,8 @@ describe('@mrtdown/fs', () => { 'station/KET.json: layout.platforms.0.levelId MISSING does not exist in layout.levels', 'station/KET.json: layout.platforms.0.serviceIds.0 MISSING_SERVICE does not exist in service/', 'station/KET.json: layout.platforms.1.serviceIds.0 TWL_MAIN_N belongs to line TWL, not ISL', - 'station/KET.json: layout.platforms.1.serviceIds.1 ISL_SKIP_KET revision r_current does not include station KET in its open service path', - 'station/KET.json: layout.platforms.1.serviceIds.2 ISL_REPEAT_KET visits station KET 2 times in open revision r_current; serviceStopOccurrences.ISL_REPEAT_KET is required', + 'station/KET.json: layout.platforms.1.serviceIds.1 ISL_SKIP_KET revision r_current does not include station KET in its active service path', + 'station/KET.json: layout.platforms.1.serviceIds.2 ISL_REPEAT_KET visits station KET 2 times in active revision r_current; serviceStopOccurrences.ISL_REPEAT_KET is required', 'station/KET.json: layout.platforms.0.accessPoints.0.connectsToLevelId MISSING does not exist in layout.levels', 'station/KET.json: layout.platforms.0.accessPoints.0.nearestDoor 25 is outside doorCount 24', 'station/KET.json: layout.transferPaths.0.from platform MISSING_PLATFORM does not exist in layout', @@ -3154,6 +3154,20 @@ describe('@mrtdown/fs', () => { ); }); + it('accepts a platform service revision with a scheduled future end', async () => { + const dataDir = await mkdtemp(join(tmpdir(), 'mrtdown-fs-')); + await cp(fixtureDataDir, dataDir, { recursive: true }); + const servicePath = join(dataDir, 'service/ISL_MAIN_E.json'); + const service = JSON.parse(await readFile(servicePath, 'utf8')); + service.revisions[0].endAt = '2026-08-01'; + await writeFile(servicePath, `${JSON.stringify(service, null, 2)}\n`); + + const result = await validateDataRoot(dataDir, ['station']); + + expect(result.ok).toBe(true); + expect(result.errors).toEqual([]); + }); + it('allows exit-only station layouts with first/last train data', async () => { const dataDir = await mkdtemp(join(tmpdir(), 'mrtdown-fs-')); await cp(fixtureDataDir, dataDir, { recursive: true }); diff --git a/packages/fs/src/validate.ts b/packages/fs/src/validate.ts index eabbc78f..87db5c1e 100644 --- a/packages/fs/src/validate.ts +++ b/packages/fs/src/validate.ts @@ -412,23 +412,26 @@ async function validateStationReferences( continue; } - const openRevisions = service.value.revisions.filter( - (revision) => revision.endAt === null, + const activeRevisions = service.value.revisions.filter( + (revision) => + revision.startAt <= platform.lastUpdated && + (revision.endAt === null || + platform.lastUpdated < revision.endAt), ); - if (openRevisions.length === 0) { + if (activeRevisions.length === 0) { errors.push( - `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} does not have an open service revision`, + `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} does not have a service revision active on ${platform.lastUpdated}`, ); continue; } - for (const revision of openRevisions) { + for (const revision of activeRevisions) { const stationOccurrenceCount = revision.path.stations.filter( (serviceStation) => serviceStation.stationId === station.value.id, ).length; if (stationOccurrenceCount === 0) { errors.push( - `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} revision ${revision.id} does not include station ${station.value.id} in its open service path`, + `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} revision ${revision.id} does not include station ${station.value.id} in its active service path`, ); continue; } @@ -440,14 +443,14 @@ async function validateStationReferences( selectedOccurrence === undefined ) { errors.push( - `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} visits station ${station.value.id} ${stationOccurrenceCount} times in open revision ${revision.id}; serviceStopOccurrences.${serviceId} is required`, + `${station.path}: layout.platforms.${platformIndex}.serviceIds.${serviceIndex} ${serviceId} visits station ${station.value.id} ${stationOccurrenceCount} times in active revision ${revision.id}; serviceStopOccurrences.${serviceId} is required`, ); } else if ( selectedOccurrence !== undefined && selectedOccurrence >= stationOccurrenceCount ) { errors.push( - `${station.path}: layout.platforms.${platformIndex}.serviceStopOccurrences.${serviceId} ${selectedOccurrence} is outside ${stationOccurrenceCount} station occurrences in open revision ${revision.id}`, + `${station.path}: layout.platforms.${platformIndex}.serviceStopOccurrences.${serviceId} ${selectedOccurrence} is outside ${stationOccurrenceCount} station occurrences in active revision ${revision.id}`, ); } } From 4ec08ad5b63f80a64aca03bc90079b95486d6007 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sun, 19 Jul 2026 00:13:25 +0800 Subject: [PATCH 16/20] fix: add verified station access routes --- data/station/MPR.json | 50 ++++++++++++++++++++++++++++++++++++++++++- data/station/SNJ.json | 9 +++++++- data/station/TNM.json | 47 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 103 insertions(+), 3 deletions(-) diff --git a/data/station/MPR.json b/data/station/MPR.json index 1c62adff..1c66dacb 100644 --- a/data/station/MPR.json +++ b/data/station/MPR.json @@ -65,7 +65,55 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "MPR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "roadNames": [ + "Marine Parade Road" + ], + "paidArea": false + }, + { + "id": "MPR_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-19", + "roadNames": [ + "Marine Parade Road" + ], + "paidArea": false + }, + { + "id": "MPR_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-19", + "roadNames": [ + "Joo Chiat Road", + "Marine Parade Road" + ], + "paidArea": false + }, + { + "id": "MPR_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-19", + "roadNames": [ + "Marine Parade Road" + ], + "paidArea": false + }, + { + "id": "MPR_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-19", + "roadNames": [ + "Marine Parade Road", + "Still Road South" + ], + "paidArea": false + } + ], "platforms": [ { "id": "MPR_TEL_A", diff --git a/data/station/SNJ.json b/data/station/SNJ.json index 3cc7bc66..343cb430 100644 --- a/data/station/SNJ.json +++ b/data/station/SNJ.json @@ -64,7 +64,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "SNJ_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "SNJ_BPLRT_1", diff --git a/data/station/TNM.json b/data/station/TNM.json index f72d45fc..3d50fd4f 100644 --- a/data/station/TNM.json +++ b/data/station/TNM.json @@ -170,6 +170,51 @@ "accessPoints": [] } ], - "transferPaths": [] + "transferPaths": [ + { + "id": "TNM_XFER_EWL_A_D", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "TNM_EWL_A" + }, + "to": { + "kind": "platform", + "id": "TNM_EWL_D" + }, + "paidArea": true, + "modes": [ + "walk", + "escalator", + "lift" + ], + "levelChange": 0, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "TNM_XFER_EWL_D_A", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "TNM_EWL_D" + }, + "to": { + "kind": "platform", + "id": "TNM_EWL_A" + }, + "paidArea": true, + "modes": [ + "walk", + "escalator", + "lift" + ], + "levelChange": 0, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + } + ] } } From 6083574f9ee993e2ae7611bb60556fff541eebcd Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sun, 19 Jul 2026 00:46:54 +0800 Subject: [PATCH 17/20] fix: add operator-verified station exits --- data/station/BKT.json | 9 ++++++++- data/station/FJR.json | 9 ++++++++- data/station/JLP.json | 9 ++++++++- data/station/KTH.json | 9 ++++++++- data/station/KTP.json | 15 ++++++++++++++- data/station/MTC.json | 39 ++++++++++++++++++++++++++++++++++++++- data/station/PND.json | 9 ++++++++- data/station/PNX.json | 9 ++++++++- data/station/PTR.json | 9 ++++++++- data/station/SGL.json | 27 ++++++++++++++++++++++++++- data/station/SGR.json | 9 ++++++++- data/station/SHV.json | 9 ++++++++- data/station/TKT.json | 21 ++++++++++++++++++++- data/station/TKW.json | 9 ++++++++- data/station/TRH.json | 15 ++++++++++++++- 15 files changed, 192 insertions(+), 15 deletions(-) diff --git a/data/station/BKT.json b/data/station/BKT.json index 1dc964f9..b40c1b3c 100644 --- a/data/station/BKT.json +++ b/data/station/BKT.json @@ -64,7 +64,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "BKT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "BKT_BPLRT_1", diff --git a/data/station/FJR.json b/data/station/FJR.json index af106e8e..236592b0 100644 --- a/data/station/FJR.json +++ b/data/station/FJR.json @@ -64,7 +64,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "FJR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "FJR_BPLRT_1", diff --git a/data/station/JLP.json b/data/station/JLP.json index dffbefb4..81a4f20b 100644 --- a/data/station/JLP.json +++ b/data/station/JLP.json @@ -65,7 +65,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "JLP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "JLP_BPLRT_1", diff --git a/data/station/KTH.json b/data/station/KTH.json index dcf75e5a..d57b1f3d 100644 --- a/data/station/KTH.json +++ b/data/station/KTH.json @@ -63,7 +63,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "KTH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "KTH_BPLRT_1", diff --git a/data/station/KTP.json b/data/station/KTP.json index 0e58d68d..574b455e 100644 --- a/data/station/KTP.json +++ b/data/station/KTP.json @@ -65,7 +65,20 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "KTP_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "KTP_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "KTP_TEL_A", diff --git a/data/station/MTC.json b/data/station/MTC.json index d6424f04..8292fe27 100644 --- a/data/station/MTC.json +++ b/data/station/MTC.json @@ -65,7 +65,44 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "MTC_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "MTC_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "MTC_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "MTC_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "MTC_EXIT_E", + "label": "E", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "MTC_EXIT_F", + "label": "F", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "MTC_TEL_A", diff --git a/data/station/PND.json b/data/station/PND.json index d21ae9c8..8189bb39 100644 --- a/data/station/PND.json +++ b/data/station/PND.json @@ -64,7 +64,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "PND_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "PND_BPLRT_1", diff --git a/data/station/PNX.json b/data/station/PNX.json index 7d2490dc..76c5dc61 100644 --- a/data/station/PNX.json +++ b/data/station/PNX.json @@ -63,7 +63,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "PNX_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "PNX_BPLRT_1", diff --git a/data/station/PTR.json b/data/station/PTR.json index f518c2f4..5b602ab3 100644 --- a/data/station/PTR.json +++ b/data/station/PTR.json @@ -65,7 +65,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "PTR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "PTR_BPLRT_1", diff --git a/data/station/SGL.json b/data/station/SGL.json index 82002cce..3091dd47 100644 --- a/data/station/SGL.json +++ b/data/station/SGL.json @@ -64,7 +64,32 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "SGL_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "SGL_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "SGL_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "SGL_EXIT_D", + "label": "D", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "SGL_TEL_A", diff --git a/data/station/SGR.json b/data/station/SGR.json index 0ef78c85..de819b9e 100644 --- a/data/station/SGR.json +++ b/data/station/SGR.json @@ -65,7 +65,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "SGR_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "SGR_BPLRT_1", diff --git a/data/station/SHV.json b/data/station/SHV.json index 6f21f942..1634681c 100644 --- a/data/station/SHV.json +++ b/data/station/SHV.json @@ -65,7 +65,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "SHV_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "SHV_BPLRT_1", diff --git a/data/station/TKT.json b/data/station/TKT.json index 44c9625c..d5756fac 100644 --- a/data/station/TKT.json +++ b/data/station/TKT.json @@ -65,7 +65,26 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "TKT_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "TKT_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "TKT_EXIT_C", + "label": "C", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "TKT_TEL_A", diff --git a/data/station/TKW.json b/data/station/TKW.json index c7ca6d3d..9b0ac3d6 100644 --- a/data/station/TKW.json +++ b/data/station/TKW.json @@ -64,7 +64,14 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "TKW_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "TKW_BPLRT_1", diff --git a/data/station/TRH.json b/data/station/TRH.json index f28f11b1..8874a4ac 100644 --- a/data/station/TRH.json +++ b/data/station/TRH.json @@ -65,7 +65,20 @@ }, "layout": { "levels": [], - "exits": [], + "exits": [ + { + "id": "TRH_EXIT_A", + "label": "A", + "lastUpdated": "2026-07-19", + "paidArea": false + }, + { + "id": "TRH_EXIT_B", + "label": "B", + "lastUpdated": "2026-07-19", + "paidArea": false + } + ], "platforms": [ { "id": "TRH_TEL_A", From 119cc78f2b8c62bef493fb810b8e37177f3f934d Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sun, 19 Jul 2026 01:11:13 +0800 Subject: [PATCH 18/20] fix: complete interchange transfer paths --- data/station/CCK.json | 80 ++++++++++++++++++++++++ data/station/TNM.json | 26 +++++++- docs/plans/active/station-layout-data.md | 4 ++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/data/station/CCK.json b/data/station/CCK.json index 68de647d..f95f34af 100644 --- a/data/station/CCK.json +++ b/data/station/CCK.json @@ -298,6 +298,86 @@ "classification": "unknown", "estimatedTraversalSeconds": null, "distanceMeters": null + }, + { + "id": "CCK_XFER_BPLRT_3_NSL_A", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "CCK_BPLRT_3" + }, + "to": { + "kind": "platform", + "id": "CCK_NSL_A" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_BPLRT_3_NSL_B", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "CCK_BPLRT_3" + }, + "to": { + "kind": "platform", + "id": "CCK_NSL_B" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_BPLRT_4_NSL_A", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "CCK_BPLRT_4" + }, + "to": { + "kind": "platform", + "id": "CCK_NSL_A" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "CCK_XFER_BPLRT_4_NSL_B", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "CCK_BPLRT_4" + }, + "to": { + "kind": "platform", + "id": "CCK_NSL_B" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null } ] } diff --git a/data/station/TNM.json b/data/station/TNM.json index 3d50fd4f..203180aa 100644 --- a/data/station/TNM.json +++ b/data/station/TNM.json @@ -194,15 +194,37 @@ "distanceMeters": null }, { - "id": "TNM_XFER_EWL_D_A", + "id": "TNM_XFER_EWL_F_D", "lastUpdated": "2026-07-19", "from": { + "kind": "platform", + "id": "TNM_EWL_F" + }, + "to": { "kind": "platform", "id": "TNM_EWL_D" }, + "paidArea": true, + "modes": [ + "walk", + "escalator", + "lift" + ], + "levelChange": 0, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "TNM_XFER_EWL_F_E", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "TNM_EWL_F" + }, "to": { "kind": "platform", - "id": "TNM_EWL_A" + "id": "TNM_EWL_E" }, "paidArea": true, "modes": [ diff --git a/docs/plans/active/station-layout-data.md b/docs/plans/active/station-layout-data.md index a89bec03..6fb1b3e1 100644 --- a/docs/plans/active/station-layout-data.md +++ b/docs/plans/active/station-layout-data.md @@ -281,6 +281,10 @@ Rules: ## Transfer Paths Transfer paths describe public movement between platforms or access points. +They are bidirectional: `from` and `to` provide a stable ordering for the two +endpoints and do not restrict traversal direction. Store one record per known +physical path rather than duplicating it in reverse. Direction-specific paths +can be introduced later if the schema gains explicit directionality metadata. ```json { From fc05bd48dba43ceaa7f657a423d95587f1aaf667 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sun, 19 Jul 2026 02:07:27 +0800 Subject: [PATCH 19/20] fix: correct terminal platform transfers --- data/station/DBG.json | 9 ++++----- data/station/XPO.json | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/data/station/DBG.json b/data/station/DBG.json index 9d674c2c..f01b0bd2 100644 --- a/data/station/DBG.json +++ b/data/station/DBG.json @@ -204,7 +204,7 @@ { "id": "DBG_CCL_A", "label": "A", - "lastUpdated": "2026-07-18", + "lastUpdated": "2026-07-19", "lineId": "CCL", "serviceIds": [ "CCL_BRANCH_CCW" @@ -215,11 +215,10 @@ { "id": "DBG_CCL_B", "label": "B", - "lastUpdated": "2026-07-18", + "lastUpdated": "2026-07-19", + "boardingStatus": "alighting_only", "lineId": "CCL", - "serviceIds": [ - "CCL_BRANCH_CCW" - ], + "serviceIds": [], "doorCount": 12, "accessPoints": [] }, diff --git a/data/station/XPO.json b/data/station/XPO.json index d96ba377..2a13c222 100644 --- a/data/station/XPO.json +++ b/data/station/XPO.json @@ -243,6 +243,46 @@ "classification": "unknown", "estimatedTraversalSeconds": null, "distanceMeters": null + }, + { + "id": "XPO_XFER_DTL_D_EWL_A", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "XPO_DTL_D" + }, + "to": { + "kind": "platform", + "id": "XPO_EWL_A" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, + { + "id": "XPO_XFER_DTL_D_EWL_B", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "XPO_DTL_D" + }, + "to": { + "kind": "platform", + "id": "XPO_EWL_B" + }, + "paidArea": true, + "modes": [ + "walk" + ], + "levelChange": null, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null } ] } From 8f339c455cd8a6fb7be122a2623d1255f003b2f2 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sun, 19 Jul 2026 10:20:57 +0800 Subject: [PATCH 20/20] fix: align layout provenance and transfers --- data/station/TNM.json | 22 ++++++++++++++++++++++ docs/plans/active/station-layout-data.md | 10 ++++++++++ scripts/generate-fixtures.mjs | 2 -- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/data/station/TNM.json b/data/station/TNM.json index 203180aa..189a1761 100644 --- a/data/station/TNM.json +++ b/data/station/TNM.json @@ -193,6 +193,28 @@ "estimatedTraversalSeconds": null, "distanceMeters": null }, + { + "id": "TNM_XFER_EWL_A_E", + "lastUpdated": "2026-07-19", + "from": { + "kind": "platform", + "id": "TNM_EWL_A" + }, + "to": { + "kind": "platform", + "id": "TNM_EWL_E" + }, + "paidArea": true, + "modes": [ + "walk", + "escalator", + "lift" + ], + "levelChange": 0, + "classification": "unknown", + "estimatedTraversalSeconds": null, + "distanceMeters": null + }, { "id": "TNM_XFER_EWL_F_D", "lastUpdated": "2026-07-19", diff --git a/docs/plans/active/station-layout-data.md b/docs/plans/active/station-layout-data.md index 6fb1b3e1..c508197c 100644 --- a/docs/plans/active/station-layout-data.md +++ b/docs/plans/active/station-layout-data.md @@ -123,6 +123,11 @@ Layout data is current state. If a station changes, update the embedded layout to the new current state in the same way the canonical station record is updated. +Every level, exit, platform, access point, and transfer path requires a +`lastUpdated` date in `YYYY-MM-DD` form. It records when that individual layout +fact was last verified against its source; update it when the fact is reviewed +or changed, rather than whenever the containing station file is edited. + ## Levels Levels identify station floors for platforms and access points. @@ -130,6 +135,7 @@ Levels identify station floors for platforms and access points. ```json { "id": "B2", + "lastUpdated": "2026-07-19", "index": -2, "name": { "en-SG": "EWL and TEL platforms", @@ -158,6 +164,7 @@ access routing are part of the passenger-facing station layout. { "id": "TAM_EXIT_A", "label": "A", + "lastUpdated": "2026-07-19", "levelId": "L1", "geo": { "latitude": 1.35395, @@ -210,6 +217,7 @@ ordinary passenger service uses `not_in_service`. { "id": "OTP_EWL_A", "label": "A", + "lastUpdated": "2026-07-19", "lineId": "EWL", "levelId": "B2", "serviceIds": ["EWL_MAIN_E"], @@ -245,6 +253,7 @@ wayfinding. They are anchored to doors when possible. { "id": "OTP_EWL_A_ESC_01", "kind": "escalator", + "lastUpdated": "2026-07-19", "nearestDoor": "12", "position": "middle", "connectsToLevelId": "B1", @@ -289,6 +298,7 @@ can be introduced later if the schema gains explicit directionality metadata. ```json { "id": "OTP_EWL_TEL_PAID_LINK", + "lastUpdated": "2026-07-19", "from": { "kind": "platform", "id": "OTP_EWL_A" diff --git a/scripts/generate-fixtures.mjs b/scripts/generate-fixtures.mjs index 8c94cf09..952a34bc 100644 --- a/scripts/generate-fixtures.mjs +++ b/scripts/generate-fixtures.mjs @@ -420,12 +420,10 @@ function buildStaticEntities() { from: { kind: 'platform', id: 'KET_ISL_E', - lastUpdated: '2026-07-18', }, to: { kind: 'platform', id: 'KET_ISL_W', - lastUpdated: '2026-07-18', }, paidArea: true, modes: ['walk'],