From ea68e415925946b44fa645bbf3f6087f48fe63cf Mon Sep 17 00:00:00 2001 From: 7222e800-c703-472d-a787-71b6b5cba4ef Date: Sun, 14 Sep 2025 17:20:55 +0000 Subject: refactor: Move a lot of inline shit out of Timetable.svelte --- src/lib/RenderUtil.ts | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/Timetable.svelte | 80 ++++++--------------------------------------- 2 files changed, 95 insertions(+), 70 deletions(-) create mode 100644 src/lib/RenderUtil.ts (limited to 'src/lib') diff --git a/src/lib/RenderUtil.ts b/src/lib/RenderUtil.ts new file mode 100644 index 0000000..c6963bc --- /dev/null +++ b/src/lib/RenderUtil.ts @@ -0,0 +1,85 @@ +import { Mode, type StopTime } from './motis-types'; +import { m } from './paraglide/messages'; + +export const getPictogram = (mode: Mode) => { + switch (true) { + case mode === Mode.Bike: + return 'Velo_l'; + case mode === Mode.ODM: + case mode === Mode.Rental: + return 'Taxi_l'; + case mode === Mode.Car: + case mode === Mode.CarDropoff: + case mode === Mode.CarParking: + return 'Auto_l'; + + // Transit // + case mode === Mode.Airplane: + return 'Abflug_l'; + case mode === Mode.LongDistanceRail: + case mode === Mode.RegionalFastRail: + case mode === Mode.RegionalRail: + case mode === Mode.Metro: + case mode === Mode.HighspeedRail: + return 'Zug_l'; + case mode === Mode.NightRail: + return 'Schlafwagen'; + case mode === Mode.Subway: + return 'Metro_l_' + (m.lang_short() === 'en' ? 'de' : m.lang_short()); + case mode === Mode.Bus: + return 'Bus_l'; + case mode === Mode.Coach: + return 'Fernbus_l'; + case mode === Mode.Tram: + case mode === Mode.CableTram: + return 'Tram_l'; + case mode === Mode.Funicular: + return 'Zahnradbahn_l'; + case mode === Mode.AerialLift: + // return 'Gondelbahn_l'; + return 'Luftseilbahn_l'; + case mode === Mode.Ferry: + return 'Schiff_l'; + case mode === Mode.Other: + default: + return 'Licht'; + } +}; +export const stopTimeToShortName = (stopTime: StopTime) => { + let n = stopTime.routeShortName; + if (n.startsWith('EC ')) n = n.replace('EC ', 'EC'); + if (stopTime.mode === 'TRAM' && !isNaN(parseInt(n))) n = 'T ' + n; + if (stopTime.mode === 'BUS' && !isNaN(parseInt(n))) n = 'B ' + n; + if ( + stopTime.routeShortName === 'European Sleeper' && + stopTime.agencyName === 'Eu Sleeper' + ) + n = 'EN'; // TODO: validate these are real euronights + if (n === '?') n = ''; + if (n.startsWith('FlixTrain ')) n = n.substring(10); + // Note: may also catch ECs/ICs/EXTs operated by DB + if ( + stopTime.agencyId === '12681' && + stopTime.agencyName === 'DB Fernverkehr AG' && + stopTime.mode === 'HIGHSPEED_RAIL' && + stopTime.source.startsWith('de_DELFI.gtfs.zip/') && + !isNaN(parseInt(n)) + ) + n = `ICE ${n}`; + return n; +}; +export const stopTimeShouldRenderGlyph = ( + stopTime: StopTime, + routeShortName: string +) => + ([ + Mode.NightRail, + Mode.HighspeedRail, + Mode.LongDistanceRail, + Mode.RegionalFastRail, + Mode.RegionalRail, + ].includes(stopTime.mode) || + (stopTime.mode === 'BUS' && routeShortName.startsWith('EV')) || + (stopTime.mode === 'METRO' && stopTime.routeShortName.startsWith('S'))) && + !stopTime.routeShortName.startsWith('FlixTrain'); +export const blacklistedAgencyURLs = ['http://www.rta.ae']; diff --git a/src/lib/Timetable.svelte b/src/lib/Timetable.svelte index f6f4a4e..1ed0900 100644 --- a/src/lib/Timetable.svelte +++ b/src/lib/Timetable.svelte @@ -7,6 +7,12 @@ import Pictogram from './assets/Pictogram.svelte'; import { Mode, type StoptimesResponse } from './motis-types'; import { m } from './paraglide/messages'; + import { + blacklistedAgencyURLs, + getPictogram, + stopTimeShouldRenderGlyph, + stopTimeToShortName, + } from './RenderUtil'; let relativeSecondPrecision = $derived( ['seconds', 'second', 'sec', 'secs', 's', '2'].includes( @@ -142,7 +148,7 @@ {#if stopTimes} {#each stopTimes.stopTimes // garbage data - .filter((v) => v.agencyUrl !== 'http://www.rta.ae') as departure} + .filter((v) => !blacklistedAgencyURLs.includes(v.agencyUrl)) as departure} {@const expectedTime = new Date( (isArrivals @@ -159,74 +165,8 @@ 1000 / 60} {@const delayMinutes = receivedTime - expectedTime} - {@const avoidGlyph = departure.routeShortName.startsWith('FlixTrain')} - {@const routeShortName = (() => { - let n = departure.routeShortName; - if (n.startsWith('EC ')) n = n.replace('EC ', 'EC'); - if (departure.mode === 'TRAM' && !isNaN(parseInt(n))) n = 'T ' + n; - if (departure.mode === 'BUS' && !isNaN(parseInt(n))) n = 'B ' + n; - if ( - departure.routeShortName === 'European Sleeper' && - departure.agencyName === 'Eu Sleeper' - ) - n = 'EN'; // TODO: validate these are real euronights - if (n === '?') n = ''; - if (n.startsWith('FlixTrain ')) n = n.substring(10); - // Note: may also catch ECs/ICs/EXTs operated by DB - if ( - departure.agencyId === '12681' && - departure.agencyName === 'DB Fernverkehr AG' && - departure.mode === 'HIGHSPEED_RAIL' && - departure.source.startsWith('de_DELFI.gtfs.zip/') && - !isNaN(parseInt(n)) - ) - n = `ICE ${n}`; - return n; - })()} - {@const pictogram = (() => { - switch (true) { - case departure.mode === Mode.Bike: - return 'Velo_l'; - case departure.mode === Mode.ODM: - case departure.mode === Mode.Rental: - return 'Taxi_l'; - case departure.mode === Mode.Car: - case departure.mode === Mode.CarDropoff: - case departure.mode === Mode.CarParking: - return 'Auto_l'; - - // Transit // - case departure.mode === Mode.Airplane: - return 'Abflug_l'; - case departure.mode === Mode.LongDistanceRail: - case departure.mode === Mode.RegionalFastRail: - case departure.mode === Mode.RegionalRail: - case departure.mode === Mode.Metro: - case departure.mode === Mode.HighspeedRail: - return 'Zug_l'; - case departure.mode === Mode.NightRail: - return 'Schlafwagen'; - case departure.mode === Mode.Subway: - return 'Metro_l_' + (m.lang_short() === 'en' ? 'de' : m.lang_short()); - case departure.mode === Mode.Bus: - return 'Bus_l'; - case departure.mode === Mode.Coach: - return 'Fernbus_l'; - case departure.mode === Mode.Tram: - case departure.mode === Mode.CableTram: - return 'Tram_l'; - case departure.mode === Mode.Funicular: - return 'Zahnradbahn_l'; - case departure.mode === Mode.AerialLift: - // return 'Gondelbahn_l'; - return 'Luftseilbahn_l'; - case departure.mode === Mode.Ferry: - return 'Schiff_l'; - case departure.mode === Mode.Other: - default: - return 'Licht'; - } - })()} + {@const routeShortName = stopTimeToShortName(departure)} + {@const pictogram = getPictogram(departure.mode)} {@const notices = (() => { let notices = [] as [pictogram: string[], content: string][]; if (departure.cancelled) @@ -267,7 +207,7 @@ {#if pictogram} {/if} - {#if ([Mode.NightRail, Mode.HighspeedRail, Mode.LongDistanceRail, Mode.RegionalFastRail, Mode.RegionalRail].includes(departure.mode) || (departure.mode === 'BUS' && routeShortName.startsWith('EV')) || (departure.mode === 'METRO' && departure.routeShortName.startsWith('S'))) && !avoidGlyph} + {#if stopTimeShouldRenderGlyph(departure, routeShortName)}