ctucx.git: trainsearch

web based trip-planner, fork of https://cyberchaos.dev/yuka/trainsearch

commit 6ddbcd9c68ce1f656b8043304ac028014e3dc906
parent 3a26aa2809103d7b07db30f71cc25801677787f9
Author: Yureka <yuka@yuka.dev>
Date: Sat, 23 Jul 2022 12:02:48 +0200

new train types with wagenreihung api - thanks to marudor :)
3 files changed, 75 insertions(+), 14 deletions(-)
M
package-lock.json
|
34
++++++++++++++++++++++++++++++++++
M
package.json
|
1
+
M
src/canvas.js
|
54
++++++++++++++++++++++++++++++++++++++++--------------
diff --git a/package-lock.json b/package-lock.json
@@ -11,6 +11,7 @@
       "dependencies": {
         "assert": "^2.0.0",
         "buffer": "^6.0.3",
+        "date-fns-tz": "^1.3.6",
         "hafas-client": "https://github.com/yu-re-ka/hafas-client#master",
         "idb": "^7.0.1",
         "lit-html": "^2.2.5",

@@ -1176,6 +1177,27 @@
       "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
       "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
     },
+    "node_modules/date-fns": {
+      "version": "2.29.1",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.1.tgz",
+      "integrity": "sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.11"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/date-fns"
+      }
+    },
+    "node_modules/date-fns-tz": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.3.6.tgz",
+      "integrity": "sha512-C8q7mErvG4INw1ZwAFmPlGjEo5Sv4udjKVbTc03zpP9cu6cp5AemFzKhz0V68LGcWEtX5mJudzzg3G04emIxLA==",
+      "peerDependencies": {
+        "date-fns": ">=2.0.0"
+      }
+    },
     "node_modules/debug": {
       "version": "4.3.4",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",

@@ -5562,6 +5584,18 @@
       "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
       "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
     },
+    "date-fns": {
+      "version": "2.29.1",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.1.tgz",
+      "integrity": "sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==",
+      "peer": true
+    },
+    "date-fns-tz": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.3.6.tgz",
+      "integrity": "sha512-C8q7mErvG4INw1ZwAFmPlGjEo5Sv4udjKVbTc03zpP9cu6cp5AemFzKhz0V68LGcWEtX5mJudzzg3G04emIxLA==",
+      "requires": {}
+    },
     "debug": {
       "version": "4.3.4",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
diff --git a/package.json b/package.json
@@ -12,6 +12,7 @@
   "dependencies": {
     "assert": "^2.0.0",
     "buffer": "^6.0.3",
+    "date-fns-tz": "^1.3.6",
     "hafas-client": "https://github.com/yu-re-ka/hafas-client#master",
     "idb": "^7.0.1",
     "lit-html": "^2.2.5",
diff --git a/src/canvas.js b/src/canvas.js
@@ -1,19 +1,13 @@
 import { moreJourneys } from './journeysView.js';
 import { go } from './router.js';
 import { padZeros } from './helpers.js';
+import { cachedCoachSequence, coachSequenceCache, coachSequenceCacheKey } from './reihung';
 
 const formatTime = (date) => {
 	return `${padZeros(date.getHours())}:${padZeros(date.getMinutes())}`;
 };
 
 const textFor = (leg) => leg.line && leg.line.name || '';
-const typeTextFor = (leg) => {
-	let res = '(' + leg.line.trainType + ')';
-	while (res.length < 12) {
-		res = ' ' + res + ' ';
-	}
-	return res;
-};
 const colorFor = (leg, type) => {
 	const product = leg.line && leg.line.product || 'walk';
 	return colors[type][product] || colors[type].default;

@@ -66,14 +60,44 @@ const textCache = {};
 let textCacheWidth;
 let textCacheDpr;
 
+const typeTextFor = leg => {
+	const fahrtNr = leg.line?.fahrtNr;
+	if (!fahrtNr) return;
+	const key = coachSequenceCacheKey(fahrtNr, leg.plannedDeparture);
+	if (!key) return;
+	const info = coachSequenceCache[key];
+	if (!info || info instanceof Promise) {
+		return;
+	}
+	let text = info.sequence?.groups[0]?.baureihe?.name;
+	if (!text) return;
+	while (text.length < 12) {
+		text = ' ' + text + ' ';
+	}
+	return text;
+};
+
 export const setupCanvas = (data, isUpdate) => {
 	if (!isUpdate) canvasState.offsetX = (window.innerWidth / dpr) > 600 ? 140 : 80;
 	canvas = document.getElementById('canvas');
 	ctx = canvas.getContext('2d');
-	canvasState.indexOffset = data.indexOffset;
-	canvasState.journeys = Object.keys(data.journeys).sort((a, b) => Number(a) - Number(b)).map(k => data.journeys[k]);
-	canvasState.slug = data.slug;
-	canvasState.profile = data.profile || "db";
+	if (data) {
+		canvasState.indexOffset = data.indexOffset;
+		canvasState.journeys = Object.keys(data.journeys).sort((a, b) => Number(a) - Number(b)).map(k => data.journeys[k]);
+		canvasState.slug = data.slug;
+		canvasState.profile = data.profile || "db";
+
+		(async () => {
+		for (const journey of canvasState.journeys) {
+			for (const leg of journey.legs) {
+				const fahrtNr = leg.line?.fahrtNr;
+				if (!fahrtNr) continue;
+				await cachedCoachSequence(fahrtNr, leg.plannedDeparture);
+				setupCanvas(null, true);
+			}
+		}
+		}) ();
+	}
 
 	canvas.addEventListener('mousedown', mouseDownHandler, {passive: true});
 	canvas.addEventListener('touchstart', mouseDownHandler, {passive: true});

@@ -132,7 +156,8 @@ const updateTextCache = () => {
 	for (const journey of canvasState.journeys) {
 		for (const leg of journey.legs) {
 			addTextToCache(textFor(leg), colorFor(leg, 'text'));
-			if (leg.line && leg.line.trainType) addTextToCache(typeTextFor(leg), '#555');
+			const typeText = typeTextFor(leg);
+			if (typeText) addTextToCache(typeText, '#555');
 
 			const times = [];
 

@@ -262,8 +287,9 @@ const renderJourneys = () => {
 				ctx.drawImage(preRenderedText, dpr * (x + 5), Math.floor(dpr * (y + duration / 2) - preRenderedText.height / 2.3));
 				ctx.scale(dpr, dpr);
 			}
-			if (leg.line && leg.line.trainType) {
-				const preRenderedTypeText = textCache[typeTextFor(leg)];
+			const typeText = typeTextFor(leg);
+			if (typeText) {
+				const preRenderedTypeText = textCache[typeText];
 				if ((preRenderedTypeText.height / dpr + preRenderedText.height / dpr) < duration - 5) {
 					ctx.scale(1 / dpr, 1 / dpr);
 					ctx.drawImage(preRenderedTypeText, dpr * (x + 5), Math.floor(dpr * (y + duration / 2 + preRenderedText.height / 2 + 10) - preRenderedTypeText.height / 2.3));