From 4641abb2fddbfa30660993f7dbdecf41d37f166d Mon Sep 17 00:00:00 2001 From: lennartrommeiss <61516567+lenderom@users.noreply.github.com> Date: Thu, 9 Jul 2026 22:27:28 +0200 Subject: [PATCH 1/3] feat: nighttrains --- content/nighttrains/index.de.md | 10 + content/nighttrains/index.en.md | 10 + content/nighttrains/index.fr.md | 10 + layouts/_shortcodes/nighttrains-map.html | 12 + static/nighttrains/README.md | 50 + static/nighttrains/d3.min.js | 18589 +++++++++++++++++++++ static/nighttrains/map.css | 192 + static/nighttrains/map.js | 380 + static/nighttrains/map.svg | 1820 ++ static/nighttrains/view_ontd_map.json | 4512 +++++ 10 files changed, 25585 insertions(+) create mode 100644 content/nighttrains/index.de.md create mode 100644 content/nighttrains/index.en.md create mode 100644 content/nighttrains/index.fr.md create mode 100644 layouts/_shortcodes/nighttrains-map.html create mode 100644 static/nighttrains/README.md create mode 100644 static/nighttrains/d3.min.js create mode 100644 static/nighttrains/map.css create mode 100644 static/nighttrains/map.js create mode 100644 static/nighttrains/map.svg create mode 100644 static/nighttrains/view_ontd_map.json diff --git a/content/nighttrains/index.de.md b/content/nighttrains/index.de.md new file mode 100644 index 000000000..81d24636b --- /dev/null +++ b/content/nighttrains/index.de.md @@ -0,0 +1,10 @@ +--- +title: "Nachtzugkarte" +description: "Interaktive Nachtzugkarte von Back-on-Track zur Orientierung im europaeischen Nachtzugnetz." +--- + +Hier findest du die Nachtzugkarte von Back-on-Track als lokale Kopie in unserem Projekt. + +{{< nighttrains-map >}} + +Quelle: [Back-on-Track Nachtzugkarte](https://back-on-track.eu/de/nachtzugkarte/) diff --git a/content/nighttrains/index.en.md b/content/nighttrains/index.en.md new file mode 100644 index 000000000..62d6c4f86 --- /dev/null +++ b/content/nighttrains/index.en.md @@ -0,0 +1,10 @@ +--- +title: "Night Train Map" +description: "Interactive night train map from Back-on-Track for orientation in the European night train network." +--- + +Here you can find the Back-on-Track night train map as a local copy in our project. + +{{< nighttrains-map >}} + +Source: [Back-on-Track Night Train Map](https://back-on-track.eu/night-train-map/) diff --git a/content/nighttrains/index.fr.md b/content/nighttrains/index.fr.md new file mode 100644 index 000000000..8675e455d --- /dev/null +++ b/content/nighttrains/index.fr.md @@ -0,0 +1,10 @@ +--- +title: "Carte des trains de nuit" +description: "Carte interactive des trains de nuit de Back-on-Track pour s’orienter dans le reseau europeen des trains de nuit." +--- + +Vous trouverez ici la carte des trains de nuit de Back-on-Track comme copie locale dans notre projet. + +{{< nighttrains-map >}} + +Source : [Carte des trains de nuit Back-on-Track](https://back-on-track.eu/night-train-map/) diff --git a/layouts/_shortcodes/nighttrains-map.html b/layouts/_shortcodes/nighttrains-map.html new file mode 100644 index 000000000..7d8bee1db --- /dev/null +++ b/layouts/_shortcodes/nighttrains-map.html @@ -0,0 +1,12 @@ + + +
+ {{ readFile "static/nighttrains/map.svg" | safeHTML }} +
+ +
+
+
+ + + diff --git a/static/nighttrains/README.md b/static/nighttrains/README.md new file mode 100644 index 000000000..123770ef5 --- /dev/null +++ b/static/nighttrains/README.md @@ -0,0 +1,50 @@ +# Night Train Map Local Integration + +This directory contains a local copy of the Back-on-Track night train map assets. + +## Files + +- `map.svg`: Inline SVG map used as the interactive base layer. +- `map.js`: Interaction logic (zoom, overlays, touch detection). +- `map.css`: Overlay and map styling. +- `d3.min.js`: D3 dependency required by `map.js`. +- `view_ontd_map.json`: Route and train metadata used for overlays. + +## Local adjustments + +### 1) Data source URL switched to local file + +In `map.js`, the route data source was changed from Back-on-Track to the local copy: + +- from: `https://back-on-track.eu/ontd/view_ontd_map.json` +- to: `/nighttrains/view_ontd_map.json` + +Reason: Make the integration self-contained and modifiable in this repository. + +### 2) Touch coordinate mapping fixed for embedded page layout + +In `map.js`, coordinate conversion for mobile/touch selection was adjusted: + +- before: map coordinates were derived from `event.pageX`/`event.pageY` normalized only by map width/height. +- now: coordinates are derived from viewport-relative pointer values (`clientX`/`clientY` with fallback) and corrected by subtracting the map container offset (`map_divrect.left/top`). + +Reason: In this Hugo site, the map is rendered inside the regular content container and is not positioned like the original full-width page. Without offset correction, touch points were shifted, so nearby routes were often not detected correctly. This especially affected the mobile behavior where the train list overlay (`.row.trainlist`) should appear when tapping near multiple lines. + +## Reproduction steps + +1. Refresh assets from source if needed: + - `map.css` + - `map.js` + - `d3.min.js` + - `view_ontd_map.json` + - `map.svg` extracted from Back-on-Track page source +2. Re-apply local adjustments listed above. +3. Run `hugo --gc --minify`. +4. Verify `/nighttrains` on mobile and desktop. + +## Verification checklist + +- Map renders and zoom/pan works. +- Single route tap opens route detail overlay. +- Mobile taps near route clusters can open train list overlay (`.row.trainlist`). +- Overlay detail button and route metadata are loaded from local JSON. diff --git a/static/nighttrains/d3.min.js b/static/nighttrains/d3.min.js new file mode 100644 index 000000000..2f3bdcceb --- /dev/null +++ b/static/nighttrains/d3.min.js @@ -0,0 +1,18589 @@ +// https://d3js.org v7.9.0 Copyright 2010-2023 Mike Bostock +!(function (t, n) { + "object" == typeof exports && "undefined" != typeof module + ? n(exports) + : "function" == typeof define && define.amd + ? define(["exports"], n) + : n( + ((t = "undefined" != typeof globalThis ? globalThis : t || self).d3 = + t.d3 || {}), + ); +})(this, function (t) { + "use strict"; + function n(t, n) { + return null == t || null == n + ? NaN + : t < n + ? -1 + : t > n + ? 1 + : t >= n + ? 0 + : NaN; + } + function e(t, n) { + return null == t || null == n + ? NaN + : n < t + ? -1 + : n > t + ? 1 + : n >= t + ? 0 + : NaN; + } + function r(t) { + let r, o, a; + function u(t, n, e = 0, i = t.length) { + if (e < i) { + if (0 !== r(n, n)) return i; + do { + const r = (e + i) >>> 1; + o(t[r], n) < 0 ? (e = r + 1) : (i = r); + } while (e < i); + } + return e; + } + return ( + 2 !== t.length + ? ((r = n), (o = (e, r) => n(t(e), r)), (a = (n, e) => t(n) - e)) + : ((r = t === n || t === e ? t : i), (o = t), (a = t)), + { + left: u, + center: function (t, n, e = 0, r = t.length) { + const i = u(t, n, e, r - 1); + return i > e && a(t[i - 1], n) > -a(t[i], n) ? i - 1 : i; + }, + right: function (t, n, e = 0, i = t.length) { + if (e < i) { + if (0 !== r(n, n)) return i; + do { + const r = (e + i) >>> 1; + o(t[r], n) <= 0 ? (e = r + 1) : (i = r); + } while (e < i); + } + return e; + }, + } + ); + } + function i() { + return 0; + } + function o(t) { + return null === t ? NaN : +t; + } + const a = r(n), + u = a.right, + c = a.left, + f = r(o).center; + var s = u; + const l = d(y), + h = d(function (t) { + const n = y(t); + return (t, e, r, i, o) => { + (n(t, e, (r <<= 2) + 0, (i <<= 2) + 0, (o <<= 2)), + n(t, e, r + 1, i + 1, o), + n(t, e, r + 2, i + 2, o), + n(t, e, r + 3, i + 3, o)); + }; + }); + function d(t) { + return function (n, e, r = e) { + if (!((e = +e) >= 0)) throw new RangeError("invalid rx"); + if (!((r = +r) >= 0)) throw new RangeError("invalid ry"); + let { data: i, width: o, height: a } = n; + if (!((o = Math.floor(o)) >= 0)) throw new RangeError("invalid width"); + if (!((a = Math.floor(void 0 !== a ? a : i.length / o)) >= 0)) + throw new RangeError("invalid height"); + if (!o || !a || (!e && !r)) return n; + const u = e && t(e), + c = r && t(r), + f = i.slice(); + return ( + u && c + ? (p(u, f, i, o, a), + p(u, i, f, o, a), + p(u, f, i, o, a), + g(c, i, f, o, a), + g(c, f, i, o, a), + g(c, i, f, o, a)) + : u + ? (p(u, i, f, o, a), p(u, f, i, o, a), p(u, i, f, o, a)) + : c && (g(c, i, f, o, a), g(c, f, i, o, a), g(c, i, f, o, a)), + n + ); + }; + } + function p(t, n, e, r, i) { + for (let o = 0, a = r * i; o < a; ) t(n, e, o, (o += r), 1); + } + function g(t, n, e, r, i) { + for (let o = 0, a = r * i; o < r; ++o) t(n, e, o, o + a, r); + } + function y(t) { + const n = Math.floor(t); + if (n === t) + return (function (t) { + const n = 2 * t + 1; + return (e, r, i, o, a) => { + if (!((o -= a) >= i)) return; + let u = t * r[i]; + const c = a * t; + for (let t = i, n = i + c; t < n; t += a) u += r[Math.min(o, t)]; + for (let t = i, f = o; t <= f; t += a) + ((u += r[Math.min(o, t + c)]), + (e[t] = u / n), + (u -= r[Math.max(i, t - c)])); + }; + })(t); + const e = t - n, + r = 2 * t + 1; + return (t, i, o, a, u) => { + if (!((a -= u) >= o)) return; + let c = n * i[o]; + const f = u * n, + s = f + u; + for (let t = o, n = o + f; t < n; t += u) c += i[Math.min(a, t)]; + for (let n = o, l = a; n <= l; n += u) + ((c += i[Math.min(a, n + f)]), + (t[n] = + (c + e * (i[Math.max(o, n - s)] + i[Math.min(a, n + s)])) / r), + (c -= i[Math.max(o, n - f)])); + }; + } + function v(t, n) { + let e = 0; + if (void 0 === n) for (let n of t) null != n && (n = +n) >= n && ++e; + else { + let r = -1; + for (let i of t) null != (i = n(i, ++r, t)) && (i = +i) >= i && ++e; + } + return e; + } + function _(t) { + return 0 | t.length; + } + function b(t) { + return !(t > 0); + } + function m(t) { + return "object" != typeof t || "length" in t ? t : Array.from(t); + } + function x(t, n) { + let e, + r = 0, + i = 0, + o = 0; + if (void 0 === n) + for (let n of t) + null != n && + (n = +n) >= n && + ((e = n - i), (i += e / ++r), (o += e * (n - i))); + else { + let a = -1; + for (let u of t) + null != (u = n(u, ++a, t)) && + (u = +u) >= u && + ((e = u - i), (i += e / ++r), (o += e * (u - i))); + } + if (r > 1) return o / (r - 1); + } + function w(t, n) { + const e = x(t, n); + return e ? Math.sqrt(e) : e; + } + function M(t, n) { + let e, r; + if (void 0 === n) + for (const n of t) + null != n && + (void 0 === e + ? n >= n && (e = r = n) + : (e > n && (e = n), r < n && (r = n))); + else { + let i = -1; + for (let o of t) + null != (o = n(o, ++i, t)) && + (void 0 === e + ? o >= o && (e = r = o) + : (e > o && (e = o), r < o && (r = o))); + } + return [e, r]; + } + class T { + constructor() { + ((this._partials = new Float64Array(32)), (this._n = 0)); + } + add(t) { + const n = this._partials; + let e = 0; + for (let r = 0; r < this._n && r < 32; r++) { + const i = n[r], + o = t + i, + a = Math.abs(t) < Math.abs(i) ? t - (o - i) : i - (o - t); + (a && (n[e++] = a), (t = o)); + } + return ((n[e] = t), (this._n = e + 1), this); + } + valueOf() { + const t = this._partials; + let n, + e, + r, + i = this._n, + o = 0; + if (i > 0) { + for ( + o = t[--i]; + i > 0 && ((n = o), (e = t[--i]), (o = n + e), (r = e - (o - n)), !r); + + ); + i > 0 && + ((r < 0 && t[i - 1] < 0) || (r > 0 && t[i - 1] > 0)) && + ((e = 2 * r), (n = o + e), e == n - o && (o = n)); + } + return o; + } + } + class InternMap extends Map { + constructor(t, n = N) { + if ( + (super(), + Object.defineProperties(this, { + _intern: { value: new Map() }, + _key: { value: n }, + }), + null != t) + ) + for (const [n, e] of t) this.set(n, e); + } + get(t) { + return super.get(A(this, t)); + } + has(t) { + return super.has(A(this, t)); + } + set(t, n) { + return super.set(S(this, t), n); + } + delete(t) { + return super.delete(E(this, t)); + } + } + class InternSet extends Set { + constructor(t, n = N) { + if ( + (super(), + Object.defineProperties(this, { + _intern: { value: new Map() }, + _key: { value: n }, + }), + null != t) + ) + for (const n of t) this.add(n); + } + has(t) { + return super.has(A(this, t)); + } + add(t) { + return super.add(S(this, t)); + } + delete(t) { + return super.delete(E(this, t)); + } + } + function A({ _intern: t, _key: n }, e) { + const r = n(e); + return t.has(r) ? t.get(r) : e; + } + function S({ _intern: t, _key: n }, e) { + const r = n(e); + return t.has(r) ? t.get(r) : (t.set(r, e), e); + } + function E({ _intern: t, _key: n }, e) { + const r = n(e); + return (t.has(r) && ((e = t.get(r)), t.delete(r)), e); + } + function N(t) { + return null !== t && "object" == typeof t ? t.valueOf() : t; + } + function k(t) { + return t; + } + function C(t, ...n) { + return F(t, k, k, n); + } + function P(t, ...n) { + return F(t, Array.from, k, n); + } + function z(t, n) { + for (let e = 1, r = n.length; e < r; ++e) + t = t.flatMap((t) => t.pop().map(([n, e]) => [...t, n, e])); + return t; + } + function $(t, n, ...e) { + return F(t, k, n, e); + } + function D(t, n, ...e) { + return F(t, Array.from, n, e); + } + function R(t) { + if (1 !== t.length) throw new Error("duplicate key"); + return t[0]; + } + function F(t, n, e, r) { + return (function t(i, o) { + if (o >= r.length) return e(i); + const a = new InternMap(), + u = r[o++]; + let c = -1; + for (const t of i) { + const n = u(t, ++c, i), + e = a.get(n); + e ? e.push(t) : a.set(n, [t]); + } + for (const [n, e] of a) a.set(n, t(e, o)); + return n(a); + })(t, 0); + } + function q(t, n) { + return Array.from(n, (n) => t[n]); + } + function U(t, ...n) { + if ("function" != typeof t[Symbol.iterator]) + throw new TypeError("values is not iterable"); + t = Array.from(t); + let [e] = n; + if ((e && 2 !== e.length) || n.length > 1) { + const r = Uint32Array.from(t, (t, n) => n); + return ( + n.length > 1 + ? ((n = n.map((n) => t.map(n))), + r.sort((t, e) => { + for (const r of n) { + const n = O(r[t], r[e]); + if (n) return n; + } + })) + : ((e = t.map(e)), r.sort((t, n) => O(e[t], e[n]))), + q(t, r) + ); + } + return t.sort(I(e)); + } + function I(t = n) { + if (t === n) return O; + if ("function" != typeof t) + throw new TypeError("compare is not a function"); + return (n, e) => { + const r = t(n, e); + return r || 0 === r ? r : (0 === t(e, e)) - (0 === t(n, n)); + }; + } + function O(t, n) { + return ( + (null == t || !(t >= t)) - (null == n || !(n >= n)) || + (t < n ? -1 : t > n ? 1 : 0) + ); + } + var B = Array.prototype.slice; + function Y(t) { + return () => t; + } + const L = Math.sqrt(50), + j = Math.sqrt(10), + H = Math.sqrt(2); + function X(t, n, e) { + const r = (n - t) / Math.max(0, e), + i = Math.floor(Math.log10(r)), + o = r / Math.pow(10, i), + a = o >= L ? 10 : o >= j ? 5 : o >= H ? 2 : 1; + let u, c, f; + return ( + i < 0 + ? ((f = Math.pow(10, -i) / a), + (u = Math.round(t * f)), + (c = Math.round(n * f)), + u / f < t && ++u, + c / f > n && --c, + (f = -f)) + : ((f = Math.pow(10, i) * a), + (u = Math.round(t / f)), + (c = Math.round(n / f)), + u * f < t && ++u, + c * f > n && --c), + c < u && 0.5 <= e && e < 2 ? X(t, n, 2 * e) : [u, c, f] + ); + } + function G(t, n, e) { + if (!((e = +e) > 0)) return []; + if ((t = +t) === (n = +n)) return [t]; + const r = n < t, + [i, o, a] = r ? X(n, t, e) : X(t, n, e); + if (!(o >= i)) return []; + const u = o - i + 1, + c = new Array(u); + if (r) + if (a < 0) for (let t = 0; t < u; ++t) c[t] = (o - t) / -a; + else for (let t = 0; t < u; ++t) c[t] = (o - t) * a; + else if (a < 0) for (let t = 0; t < u; ++t) c[t] = (i + t) / -a; + else for (let t = 0; t < u; ++t) c[t] = (i + t) * a; + return c; + } + function V(t, n, e) { + return X((t = +t), (n = +n), (e = +e))[2]; + } + function W(t, n, e) { + e = +e; + const r = (n = +n) < (t = +t), + i = r ? V(n, t, e) : V(t, n, e); + return (r ? -1 : 1) * (i < 0 ? 1 / -i : i); + } + function Z(t, n, e) { + let r; + for (;;) { + const i = V(t, n, e); + if (i === r || 0 === i || !isFinite(i)) return [t, n]; + (i > 0 + ? ((t = Math.floor(t / i) * i), (n = Math.ceil(n / i) * i)) + : i < 0 && ((t = Math.ceil(t * i) / i), (n = Math.floor(n * i) / i)), + (r = i)); + } + } + function K(t) { + return Math.max(1, Math.ceil(Math.log(v(t)) / Math.LN2) + 1); + } + function Q() { + var t = k, + n = M, + e = K; + function r(r) { + Array.isArray(r) || (r = Array.from(r)); + var i, + o, + a, + u = r.length, + c = new Array(u); + for (i = 0; i < u; ++i) c[i] = t(r[i], i, r); + var f = n(c), + l = f[0], + h = f[1], + d = e(c, l, h); + if (!Array.isArray(d)) { + const t = h, + e = +d; + if ( + (n === M && ([l, h] = Z(l, h, e)), + (d = G(l, h, e))[0] <= l && (a = V(l, h, e)), + d[d.length - 1] >= h) + ) + if (t >= h && n === M) { + const t = V(l, h, e); + isFinite(t) && + (t > 0 + ? (h = (Math.floor(h / t) + 1) * t) + : t < 0 && (h = (Math.ceil(h * -t) + 1) / -t)); + } else d.pop(); + } + for (var p = d.length, g = 0, y = p; d[g] <= l; ) ++g; + for (; d[y - 1] > h; ) --y; + (g || y < p) && ((d = d.slice(g, y)), (p = y - g)); + var v, + _ = new Array(p + 1); + for (i = 0; i <= p; ++i) + (((v = _[i] = []).x0 = i > 0 ? d[i - 1] : l), + (v.x1 = i < p ? d[i] : h)); + if (isFinite(a)) { + if (a > 0) + for (i = 0; i < u; ++i) + null != (o = c[i]) && + l <= o && + o <= h && + _[Math.min(p, Math.floor((o - l) / a))].push(r[i]); + else if (a < 0) + for (i = 0; i < u; ++i) + if (null != (o = c[i]) && l <= o && o <= h) { + const t = Math.floor((l - o) * a); + _[Math.min(p, t + (d[t] <= o))].push(r[i]); + } + } else + for (i = 0; i < u; ++i) + null != (o = c[i]) && l <= o && o <= h && _[s(d, o, 0, p)].push(r[i]); + return _; + } + return ( + (r.value = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : Y(n)), r) + : t; + }), + (r.domain = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : Y([t[0], t[1]])), r) + : n; + }), + (r.thresholds = function (t) { + return arguments.length + ? ((e = + "function" == typeof t ? t : Y(Array.isArray(t) ? B.call(t) : t)), + r) + : e; + }), + r + ); + } + function J(t, n) { + let e; + if (void 0 === n) + for (const n of t) + null != n && (e < n || (void 0 === e && n >= n)) && (e = n); + else { + let r = -1; + for (let i of t) + null != (i = n(i, ++r, t)) && + (e < i || (void 0 === e && i >= i)) && + (e = i); + } + return e; + } + function tt(t, n) { + let e, + r = -1, + i = -1; + if (void 0 === n) + for (const n of t) + (++i, + null != n && + (e < n || (void 0 === e && n >= n)) && + ((e = n), (r = i))); + else + for (let o of t) + null != (o = n(o, ++i, t)) && + (e < o || (void 0 === e && o >= o)) && + ((e = o), (r = i)); + return r; + } + function nt(t, n) { + let e; + if (void 0 === n) + for (const n of t) + null != n && (e > n || (void 0 === e && n >= n)) && (e = n); + else { + let r = -1; + for (let i of t) + null != (i = n(i, ++r, t)) && + (e > i || (void 0 === e && i >= i)) && + (e = i); + } + return e; + } + function et(t, n) { + let e, + r = -1, + i = -1; + if (void 0 === n) + for (const n of t) + (++i, + null != n && + (e > n || (void 0 === e && n >= n)) && + ((e = n), (r = i))); + else + for (let o of t) + null != (o = n(o, ++i, t)) && + (e > o || (void 0 === e && o >= o)) && + ((e = o), (r = i)); + return r; + } + function rt(t, n, e = 0, r = 1 / 0, i) { + if ( + ((n = Math.floor(n)), + (e = Math.floor(Math.max(0, e))), + (r = Math.floor(Math.min(t.length - 1, r))), + !(e <= n && n <= r)) + ) + return t; + for (i = void 0 === i ? O : I(i); r > e; ) { + if (r - e > 600) { + const o = r - e + 1, + a = n - e + 1, + u = Math.log(o), + c = 0.5 * Math.exp((2 * u) / 3), + f = 0.5 * Math.sqrt((u * c * (o - c)) / o) * (a - o / 2 < 0 ? -1 : 1); + rt( + t, + n, + Math.max(e, Math.floor(n - (a * c) / o + f)), + Math.min(r, Math.floor(n + ((o - a) * c) / o + f)), + i, + ); + } + const o = t[n]; + let a = e, + u = r; + for (it(t, e, n), i(t[r], o) > 0 && it(t, e, r); a < u; ) { + for (it(t, a, u), ++a, --u; i(t[a], o) < 0; ) ++a; + for (; i(t[u], o) > 0; ) --u; + } + (0 === i(t[e], o) ? it(t, e, u) : (++u, it(t, u, r)), + u <= n && (e = u + 1), + n <= u && (r = u - 1)); + } + return t; + } + function it(t, n, e) { + const r = t[n]; + ((t[n] = t[e]), (t[e] = r)); + } + function ot(t, e = n) { + let r, + i = !1; + if (1 === e.length) { + let o; + for (const a of t) { + const t = e(a); + (i ? n(t, o) > 0 : 0 === n(t, t)) && ((r = a), (o = t), (i = !0)); + } + } else + for (const n of t) + (i ? e(n, r) > 0 : 0 === e(n, n)) && ((r = n), (i = !0)); + return r; + } + function at(t, n, e) { + if ( + ((t = Float64Array.from( + (function* (t, n) { + if (void 0 === n) + for (let n of t) null != n && (n = +n) >= n && (yield n); + else { + let e = -1; + for (let r of t) + null != (r = n(r, ++e, t)) && (r = +r) >= r && (yield r); + } + })(t, e), + )), + (r = t.length) && !isNaN((n = +n))) + ) { + if (n <= 0 || r < 2) return nt(t); + if (n >= 1) return J(t); + var r, + i = (r - 1) * n, + o = Math.floor(i), + a = J(rt(t, o).subarray(0, o + 1)); + return a + (nt(t.subarray(o + 1)) - a) * (i - o); + } + } + function ut(t, n, e = o) { + if ((r = t.length) && !isNaN((n = +n))) { + if (n <= 0 || r < 2) return +e(t[0], 0, t); + if (n >= 1) return +e(t[r - 1], r - 1, t); + var r, + i = (r - 1) * n, + a = Math.floor(i), + u = +e(t[a], a, t); + return u + (+e(t[a + 1], a + 1, t) - u) * (i - a); + } + } + function ct(t, n, e = o) { + if (!isNaN((n = +n))) { + if (((r = Float64Array.from(t, (n, r) => o(e(t[r], r, t)))), n <= 0)) + return et(r); + if (n >= 1) return tt(r); + var r, + i = Uint32Array.from(t, (t, n) => n), + a = r.length - 1, + u = Math.floor(a * n); + return ( + rt(i, u, 0, a, (t, n) => O(r[t], r[n])), + (u = ot(i.subarray(0, u + 1), (t) => r[t])) >= 0 ? u : -1 + ); + } + } + function ft(t) { + return Array.from( + (function* (t) { + for (const n of t) yield* n; + })(t), + ); + } + function st(t, n) { + return [t, n]; + } + function lt(t, n, e) { + ((t = +t), + (n = +n), + (e = + (i = arguments.length) < 2 ? ((n = t), (t = 0), 1) : i < 3 ? 1 : +e)); + for ( + var r = -1, i = 0 | Math.max(0, Math.ceil((n - t) / e)), o = new Array(i); + ++r < i; + + ) + o[r] = t + r * e; + return o; + } + function ht(t, e = n) { + if (1 === e.length) return et(t, e); + let r, + i = -1, + o = -1; + for (const n of t) + (++o, (i < 0 ? 0 === e(n, n) : e(n, r) < 0) && ((r = n), (i = o))); + return i; + } + var dt = pt(Math.random); + function pt(t) { + return function (n, e = 0, r = n.length) { + let i = r - (e = +e); + for (; i; ) { + const r = (t() * i--) | 0, + o = n[i + e]; + ((n[i + e] = n[r + e]), (n[r + e] = o)); + } + return n; + }; + } + function gt(t) { + if (!(i = t.length)) return []; + for (var n = -1, e = nt(t, yt), r = new Array(e); ++n < e; ) + for (var i, o = -1, a = (r[n] = new Array(i)); ++o < i; ) a[o] = t[o][n]; + return r; + } + function yt(t) { + return t.length; + } + function vt(t) { + return t instanceof InternSet ? t : new InternSet(t); + } + function _t(t, n) { + const e = t[Symbol.iterator](), + r = new Set(); + for (const t of n) { + const n = bt(t); + if (r.has(n)) continue; + let i, o; + for (; ({ value: i, done: o } = e.next()); ) { + if (o) return !1; + const t = bt(i); + if ((r.add(t), Object.is(n, t))) break; + } + } + return !0; + } + function bt(t) { + return null !== t && "object" == typeof t ? t.valueOf() : t; + } + function mt(t) { + return t; + } + var xt = 1, + wt = 2, + Mt = 3, + Tt = 4, + At = 1e-6; + function St(t) { + return "translate(" + t + ",0)"; + } + function Et(t) { + return "translate(0," + t + ")"; + } + function Nt(t) { + return (n) => +t(n); + } + function kt(t, n) { + return ( + (n = Math.max(0, t.bandwidth() - 2 * n) / 2), + t.round() && (n = Math.round(n)), + (e) => +t(e) + n + ); + } + function Ct() { + return !this.__axis; + } + function Pt(t, n) { + var e = [], + r = null, + i = null, + o = 6, + a = 6, + u = 3, + c = "undefined" != typeof window && window.devicePixelRatio > 1 ? 0 : 0.5, + f = t === xt || t === Tt ? -1 : 1, + s = t === Tt || t === wt ? "x" : "y", + l = t === xt || t === Mt ? St : Et; + function h(h) { + var d = null == r ? (n.ticks ? n.ticks.apply(n, e) : n.domain()) : r, + p = null == i ? (n.tickFormat ? n.tickFormat.apply(n, e) : mt) : i, + g = Math.max(o, 0) + u, + y = n.range(), + v = +y[0] + c, + _ = +y[y.length - 1] + c, + b = (n.bandwidth ? kt : Nt)(n.copy(), c), + m = h.selection ? h.selection() : h, + x = m.selectAll(".domain").data([null]), + w = m.selectAll(".tick").data(d, n).order(), + M = w.exit(), + T = w.enter().append("g").attr("class", "tick"), + A = w.select("line"), + S = w.select("text"); + ((x = x.merge( + x + .enter() + .insert("path", ".tick") + .attr("class", "domain") + .attr("stroke", "currentColor"), + )), + (w = w.merge(T)), + (A = A.merge( + T.append("line") + .attr("stroke", "currentColor") + .attr(s + "2", f * o), + )), + (S = S.merge( + T.append("text") + .attr("fill", "currentColor") + .attr(s, f * g) + .attr("dy", t === xt ? "0em" : t === Mt ? "0.71em" : "0.32em"), + )), + h !== m && + ((x = x.transition(h)), + (w = w.transition(h)), + (A = A.transition(h)), + (S = S.transition(h)), + (M = M.transition(h) + .attr("opacity", At) + .attr("transform", function (t) { + return isFinite((t = b(t))) + ? l(t + c) + : this.getAttribute("transform"); + })), + T.attr("opacity", At).attr("transform", function (t) { + var n = this.parentNode.__axis; + return l((n && isFinite((n = n(t))) ? n : b(t)) + c); + })), + M.remove(), + x.attr( + "d", + t === Tt || t === wt + ? a + ? "M" + f * a + "," + v + "H" + c + "V" + _ + "H" + f * a + : "M" + c + "," + v + "V" + _ + : a + ? "M" + v + "," + f * a + "V" + c + "H" + _ + "V" + f * a + : "M" + v + "," + c + "H" + _, + ), + w.attr("opacity", 1).attr("transform", function (t) { + return l(b(t) + c); + }), + A.attr(s + "2", f * o), + S.attr(s, f * g).text(p), + m + .filter(Ct) + .attr("fill", "none") + .attr("font-size", 10) + .attr("font-family", "sans-serif") + .attr( + "text-anchor", + t === wt ? "start" : t === Tt ? "end" : "middle", + ), + m.each(function () { + this.__axis = b; + })); + } + return ( + (h.scale = function (t) { + return arguments.length ? ((n = t), h) : n; + }), + (h.ticks = function () { + return ((e = Array.from(arguments)), h); + }), + (h.tickArguments = function (t) { + return arguments.length + ? ((e = null == t ? [] : Array.from(t)), h) + : e.slice(); + }), + (h.tickValues = function (t) { + return arguments.length + ? ((r = null == t ? null : Array.from(t)), h) + : r && r.slice(); + }), + (h.tickFormat = function (t) { + return arguments.length ? ((i = t), h) : i; + }), + (h.tickSize = function (t) { + return arguments.length ? ((o = a = +t), h) : o; + }), + (h.tickSizeInner = function (t) { + return arguments.length ? ((o = +t), h) : o; + }), + (h.tickSizeOuter = function (t) { + return arguments.length ? ((a = +t), h) : a; + }), + (h.tickPadding = function (t) { + return arguments.length ? ((u = +t), h) : u; + }), + (h.offset = function (t) { + return arguments.length ? ((c = +t), h) : c; + }), + h + ); + } + var zt = { value: () => {} }; + function $t() { + for (var t, n = 0, e = arguments.length, r = {}; n < e; ++n) { + if (!(t = arguments[n] + "") || t in r || /[\s.]/.test(t)) + throw new Error("illegal type: " + t); + r[t] = []; + } + return new Dt(r); + } + function Dt(t) { + this._ = t; + } + function Rt(t, n) { + for (var e, r = 0, i = t.length; r < i; ++r) + if ((e = t[r]).name === n) return e.value; + } + function Ft(t, n, e) { + for (var r = 0, i = t.length; r < i; ++r) + if (t[r].name === n) { + ((t[r] = zt), (t = t.slice(0, r).concat(t.slice(r + 1)))); + break; + } + return (null != e && t.push({ name: n, value: e }), t); + } + Dt.prototype = $t.prototype = { + constructor: Dt, + on: function (t, n) { + var e, + r, + i = this._, + o = + ((r = i), + (t + "") + .trim() + .split(/^|\s+/) + .map(function (t) { + var n = "", + e = t.indexOf("."); + if ( + (e >= 0 && ((n = t.slice(e + 1)), (t = t.slice(0, e))), + t && !r.hasOwnProperty(t)) + ) + throw new Error("unknown type: " + t); + return { type: t, name: n }; + })), + a = -1, + u = o.length; + if (!(arguments.length < 2)) { + if (null != n && "function" != typeof n) + throw new Error("invalid callback: " + n); + for (; ++a < u; ) + if ((e = (t = o[a]).type)) i[e] = Ft(i[e], t.name, n); + else if (null == n) for (e in i) i[e] = Ft(i[e], t.name, null); + return this; + } + for (; ++a < u; ) + if ((e = (t = o[a]).type) && (e = Rt(i[e], t.name))) return e; + }, + copy: function () { + var t = {}, + n = this._; + for (var e in n) t[e] = n[e].slice(); + return new Dt(t); + }, + call: function (t, n) { + if ((e = arguments.length - 2) > 0) + for (var e, r, i = new Array(e), o = 0; o < e; ++o) + i[o] = arguments[o + 2]; + if (!this._.hasOwnProperty(t)) throw new Error("unknown type: " + t); + for (o = 0, e = (r = this._[t]).length; o < e; ++o) + r[o].value.apply(n, i); + }, + apply: function (t, n, e) { + if (!this._.hasOwnProperty(t)) throw new Error("unknown type: " + t); + for (var r = this._[t], i = 0, o = r.length; i < o; ++i) + r[i].value.apply(n, e); + }, + }; + var qt = "http://www.w3.org/1999/xhtml", + Ut = { + svg: "http://www.w3.org/2000/svg", + xhtml: qt, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/", + }; + function It(t) { + var n = (t += ""), + e = n.indexOf(":"); + return ( + e >= 0 && "xmlns" !== (n = t.slice(0, e)) && (t = t.slice(e + 1)), + Ut.hasOwnProperty(n) ? { space: Ut[n], local: t } : t + ); + } + function Ot(t) { + return function () { + var n = this.ownerDocument, + e = this.namespaceURI; + return e === qt && n.documentElement.namespaceURI === qt + ? n.createElement(t) + : n.createElementNS(e, t); + }; + } + function Bt(t) { + return function () { + return this.ownerDocument.createElementNS(t.space, t.local); + }; + } + function Yt(t) { + var n = It(t); + return (n.local ? Bt : Ot)(n); + } + function Lt() {} + function jt(t) { + return null == t + ? Lt + : function () { + return this.querySelector(t); + }; + } + function Ht(t) { + return null == t ? [] : Array.isArray(t) ? t : Array.from(t); + } + function Xt() { + return []; + } + function Gt(t) { + return null == t + ? Xt + : function () { + return this.querySelectorAll(t); + }; + } + function Vt(t) { + return function () { + return this.matches(t); + }; + } + function Wt(t) { + return function (n) { + return n.matches(t); + }; + } + var Zt = Array.prototype.find; + function Kt() { + return this.firstElementChild; + } + var Qt = Array.prototype.filter; + function Jt() { + return Array.from(this.children); + } + function tn(t) { + return new Array(t.length); + } + function nn(t, n) { + ((this.ownerDocument = t.ownerDocument), + (this.namespaceURI = t.namespaceURI), + (this._next = null), + (this._parent = t), + (this.__data__ = n)); + } + function en(t, n, e, r, i, o) { + for (var a, u = 0, c = n.length, f = o.length; u < f; ++u) + (a = n[u]) ? ((a.__data__ = o[u]), (r[u] = a)) : (e[u] = new nn(t, o[u])); + for (; u < c; ++u) (a = n[u]) && (i[u] = a); + } + function rn(t, n, e, r, i, o, a) { + var u, + c, + f, + s = new Map(), + l = n.length, + h = o.length, + d = new Array(l); + for (u = 0; u < l; ++u) + (c = n[u]) && + ((d[u] = f = a.call(c, c.__data__, u, n) + ""), + s.has(f) ? (i[u] = c) : s.set(f, c)); + for (u = 0; u < h; ++u) + ((f = a.call(t, o[u], u, o) + ""), + (c = s.get(f)) + ? ((r[u] = c), (c.__data__ = o[u]), s.delete(f)) + : (e[u] = new nn(t, o[u]))); + for (u = 0; u < l; ++u) (c = n[u]) && s.get(d[u]) === c && (i[u] = c); + } + function on(t) { + return t.__data__; + } + function an(t) { + return "object" == typeof t && "length" in t ? t : Array.from(t); + } + function un(t, n) { + return t < n ? -1 : t > n ? 1 : t >= n ? 0 : NaN; + } + function cn(t) { + return function () { + this.removeAttribute(t); + }; + } + function fn(t) { + return function () { + this.removeAttributeNS(t.space, t.local); + }; + } + function sn(t, n) { + return function () { + this.setAttribute(t, n); + }; + } + function ln(t, n) { + return function () { + this.setAttributeNS(t.space, t.local, n); + }; + } + function hn(t, n) { + return function () { + var e = n.apply(this, arguments); + null == e ? this.removeAttribute(t) : this.setAttribute(t, e); + }; + } + function dn(t, n) { + return function () { + var e = n.apply(this, arguments); + null == e + ? this.removeAttributeNS(t.space, t.local) + : this.setAttributeNS(t.space, t.local, e); + }; + } + function pn(t) { + return ( + (t.ownerDocument && t.ownerDocument.defaultView) || + (t.document && t) || + t.defaultView + ); + } + function gn(t) { + return function () { + this.style.removeProperty(t); + }; + } + function yn(t, n, e) { + return function () { + this.style.setProperty(t, n, e); + }; + } + function vn(t, n, e) { + return function () { + var r = n.apply(this, arguments); + null == r + ? this.style.removeProperty(t) + : this.style.setProperty(t, r, e); + }; + } + function _n(t, n) { + return ( + t.style.getPropertyValue(n) || + pn(t).getComputedStyle(t, null).getPropertyValue(n) + ); + } + function bn(t) { + return function () { + delete this[t]; + }; + } + function mn(t, n) { + return function () { + this[t] = n; + }; + } + function xn(t, n) { + return function () { + var e = n.apply(this, arguments); + null == e ? delete this[t] : (this[t] = e); + }; + } + function wn(t) { + return t.trim().split(/^|\s+/); + } + function Mn(t) { + return t.classList || new Tn(t); + } + function Tn(t) { + ((this._node = t), (this._names = wn(t.getAttribute("class") || ""))); + } + function An(t, n) { + for (var e = Mn(t), r = -1, i = n.length; ++r < i; ) e.add(n[r]); + } + function Sn(t, n) { + for (var e = Mn(t), r = -1, i = n.length; ++r < i; ) e.remove(n[r]); + } + function En(t) { + return function () { + An(this, t); + }; + } + function Nn(t) { + return function () { + Sn(this, t); + }; + } + function kn(t, n) { + return function () { + (n.apply(this, arguments) ? An : Sn)(this, t); + }; + } + function Cn() { + this.textContent = ""; + } + function Pn(t) { + return function () { + this.textContent = t; + }; + } + function zn(t) { + return function () { + var n = t.apply(this, arguments); + this.textContent = null == n ? "" : n; + }; + } + function $n() { + this.innerHTML = ""; + } + function Dn(t) { + return function () { + this.innerHTML = t; + }; + } + function Rn(t) { + return function () { + var n = t.apply(this, arguments); + this.innerHTML = null == n ? "" : n; + }; + } + function Fn() { + this.nextSibling && this.parentNode.appendChild(this); + } + function qn() { + this.previousSibling && + this.parentNode.insertBefore(this, this.parentNode.firstChild); + } + function Un() { + return null; + } + function In() { + var t = this.parentNode; + t && t.removeChild(this); + } + function On() { + var t = this.cloneNode(!1), + n = this.parentNode; + return n ? n.insertBefore(t, this.nextSibling) : t; + } + function Bn() { + var t = this.cloneNode(!0), + n = this.parentNode; + return n ? n.insertBefore(t, this.nextSibling) : t; + } + function Yn(t) { + return function () { + var n = this.__on; + if (n) { + for (var e, r = 0, i = -1, o = n.length; r < o; ++r) + ((e = n[r]), + (t.type && e.type !== t.type) || e.name !== t.name + ? (n[++i] = e) + : this.removeEventListener(e.type, e.listener, e.options)); + ++i ? (n.length = i) : delete this.__on; + } + }; + } + function Ln(t, n, e) { + return function () { + var r, + i = this.__on, + o = (function (t) { + return function (n) { + t.call(this, n, this.__data__); + }; + })(n); + if (i) + for (var a = 0, u = i.length; a < u; ++a) + if ((r = i[a]).type === t.type && r.name === t.name) + return ( + this.removeEventListener(r.type, r.listener, r.options), + this.addEventListener(r.type, (r.listener = o), (r.options = e)), + void (r.value = n) + ); + (this.addEventListener(t.type, o, e), + (r = { type: t.type, name: t.name, value: n, listener: o, options: e }), + i ? i.push(r) : (this.__on = [r])); + }; + } + function jn(t, n, e) { + var r = pn(t), + i = r.CustomEvent; + ("function" == typeof i + ? (i = new i(n, e)) + : ((i = r.document.createEvent("Event")), + e + ? (i.initEvent(n, e.bubbles, e.cancelable), (i.detail = e.detail)) + : i.initEvent(n, !1, !1)), + t.dispatchEvent(i)); + } + function Hn(t, n) { + return function () { + return jn(this, t, n); + }; + } + function Xn(t, n) { + return function () { + return jn(this, t, n.apply(this, arguments)); + }; + } + ((nn.prototype = { + constructor: nn, + appendChild: function (t) { + return this._parent.insertBefore(t, this._next); + }, + insertBefore: function (t, n) { + return this._parent.insertBefore(t, n); + }, + querySelector: function (t) { + return this._parent.querySelector(t); + }, + querySelectorAll: function (t) { + return this._parent.querySelectorAll(t); + }, + }), + (Tn.prototype = { + add: function (t) { + this._names.indexOf(t) < 0 && + (this._names.push(t), + this._node.setAttribute("class", this._names.join(" "))); + }, + remove: function (t) { + var n = this._names.indexOf(t); + n >= 0 && + (this._names.splice(n, 1), + this._node.setAttribute("class", this._names.join(" "))); + }, + contains: function (t) { + return this._names.indexOf(t) >= 0; + }, + })); + var Gn = [null]; + function Vn(t, n) { + ((this._groups = t), (this._parents = n)); + } + function Wn() { + return new Vn([[document.documentElement]], Gn); + } + function Zn(t) { + return "string" == typeof t + ? new Vn([[document.querySelector(t)]], [document.documentElement]) + : new Vn([[t]], Gn); + } + Vn.prototype = Wn.prototype = { + constructor: Vn, + select: function (t) { + "function" != typeof t && (t = jt(t)); + for ( + var n = this._groups, e = n.length, r = new Array(e), i = 0; + i < e; + ++i + ) + for ( + var o, a, u = n[i], c = u.length, f = (r[i] = new Array(c)), s = 0; + s < c; + ++s + ) + (o = u[s]) && + (a = t.call(o, o.__data__, s, u)) && + ("__data__" in o && (a.__data__ = o.__data__), (f[s] = a)); + return new Vn(r, this._parents); + }, + selectAll: function (t) { + t = + "function" == typeof t + ? (function (t) { + return function () { + return Ht(t.apply(this, arguments)); + }; + })(t) + : Gt(t); + for ( + var n = this._groups, e = n.length, r = [], i = [], o = 0; + o < e; + ++o + ) + for (var a, u = n[o], c = u.length, f = 0; f < c; ++f) + (a = u[f]) && (r.push(t.call(a, a.__data__, f, u)), i.push(a)); + return new Vn(r, i); + }, + selectChild: function (t) { + return this.select( + null == t + ? Kt + : (function (t) { + return function () { + return Zt.call(this.children, t); + }; + })("function" == typeof t ? t : Wt(t)), + ); + }, + selectChildren: function (t) { + return this.selectAll( + null == t + ? Jt + : (function (t) { + return function () { + return Qt.call(this.children, t); + }; + })("function" == typeof t ? t : Wt(t)), + ); + }, + filter: function (t) { + "function" != typeof t && (t = Vt(t)); + for ( + var n = this._groups, e = n.length, r = new Array(e), i = 0; + i < e; + ++i + ) + for (var o, a = n[i], u = a.length, c = (r[i] = []), f = 0; f < u; ++f) + (o = a[f]) && t.call(o, o.__data__, f, a) && c.push(o); + return new Vn(r, this._parents); + }, + data: function (t, n) { + if (!arguments.length) return Array.from(this, on); + var e = n ? rn : en, + r = this._parents, + i = this._groups; + "function" != typeof t && + (t = (function (t) { + return function () { + return t; + }; + })(t)); + for ( + var o = i.length, + a = new Array(o), + u = new Array(o), + c = new Array(o), + f = 0; + f < o; + ++f + ) { + var s = r[f], + l = i[f], + h = l.length, + d = an(t.call(s, s && s.__data__, f, r)), + p = d.length, + g = (u[f] = new Array(p)), + y = (a[f] = new Array(p)); + e(s, l, g, y, (c[f] = new Array(h)), d, n); + for (var v, _, b = 0, m = 0; b < p; ++b) + if ((v = g[b])) { + for (b >= m && (m = b + 1); !(_ = y[m]) && ++m < p; ); + v._next = _ || null; + } + } + return (((a = new Vn(a, r))._enter = u), (a._exit = c), a); + }, + enter: function () { + return new Vn(this._enter || this._groups.map(tn), this._parents); + }, + exit: function () { + return new Vn(this._exit || this._groups.map(tn), this._parents); + }, + join: function (t, n, e) { + var r = this.enter(), + i = this, + o = this.exit(); + return ( + "function" == typeof t + ? (r = t(r)) && (r = r.selection()) + : (r = r.append(t + "")), + null != n && (i = n(i)) && (i = i.selection()), + null == e ? o.remove() : e(o), + r && i ? r.merge(i).order() : i + ); + }, + merge: function (t) { + for ( + var n = t.selection ? t.selection() : t, + e = this._groups, + r = n._groups, + i = e.length, + o = r.length, + a = Math.min(i, o), + u = new Array(i), + c = 0; + c < a; + ++c + ) + for ( + var f, + s = e[c], + l = r[c], + h = s.length, + d = (u[c] = new Array(h)), + p = 0; + p < h; + ++p + ) + (f = s[p] || l[p]) && (d[p] = f); + for (; c < i; ++c) u[c] = e[c]; + return new Vn(u, this._parents); + }, + selection: function () { + return this; + }, + order: function () { + for (var t = this._groups, n = -1, e = t.length; ++n < e; ) + for (var r, i = t[n], o = i.length - 1, a = i[o]; --o >= 0; ) + (r = i[o]) && + (a && + 4 ^ r.compareDocumentPosition(a) && + a.parentNode.insertBefore(r, a), + (a = r)); + return this; + }, + sort: function (t) { + function n(n, e) { + return n && e ? t(n.__data__, e.__data__) : !n - !e; + } + t || (t = un); + for ( + var e = this._groups, r = e.length, i = new Array(r), o = 0; + o < r; + ++o + ) { + for ( + var a, u = e[o], c = u.length, f = (i[o] = new Array(c)), s = 0; + s < c; + ++s + ) + (a = u[s]) && (f[s] = a); + f.sort(n); + } + return new Vn(i, this._parents).order(); + }, + call: function () { + var t = arguments[0]; + return ((arguments[0] = this), t.apply(null, arguments), this); + }, + nodes: function () { + return Array.from(this); + }, + node: function () { + for (var t = this._groups, n = 0, e = t.length; n < e; ++n) + for (var r = t[n], i = 0, o = r.length; i < o; ++i) { + var a = r[i]; + if (a) return a; + } + return null; + }, + size: function () { + let t = 0; + for (const n of this) ++t; + return t; + }, + empty: function () { + return !this.node(); + }, + each: function (t) { + for (var n = this._groups, e = 0, r = n.length; e < r; ++e) + for (var i, o = n[e], a = 0, u = o.length; a < u; ++a) + (i = o[a]) && t.call(i, i.__data__, a, o); + return this; + }, + attr: function (t, n) { + var e = It(t); + if (arguments.length < 2) { + var r = this.node(); + return e.local ? r.getAttributeNS(e.space, e.local) : r.getAttribute(e); + } + return this.each( + (null == n + ? e.local + ? fn + : cn + : "function" == typeof n + ? e.local + ? dn + : hn + : e.local + ? ln + : sn)(e, n), + ); + }, + style: function (t, n, e) { + return arguments.length > 1 + ? this.each( + (null == n ? gn : "function" == typeof n ? vn : yn)( + t, + n, + null == e ? "" : e, + ), + ) + : _n(this.node(), t); + }, + property: function (t, n) { + return arguments.length > 1 + ? this.each((null == n ? bn : "function" == typeof n ? xn : mn)(t, n)) + : this.node()[t]; + }, + classed: function (t, n) { + var e = wn(t + ""); + if (arguments.length < 2) { + for (var r = Mn(this.node()), i = -1, o = e.length; ++i < o; ) + if (!r.contains(e[i])) return !1; + return !0; + } + return this.each(("function" == typeof n ? kn : n ? En : Nn)(e, n)); + }, + text: function (t) { + return arguments.length + ? this.each(null == t ? Cn : ("function" == typeof t ? zn : Pn)(t)) + : this.node().textContent; + }, + html: function (t) { + return arguments.length + ? this.each(null == t ? $n : ("function" == typeof t ? Rn : Dn)(t)) + : this.node().innerHTML; + }, + raise: function () { + return this.each(Fn); + }, + lower: function () { + return this.each(qn); + }, + append: function (t) { + var n = "function" == typeof t ? t : Yt(t); + return this.select(function () { + return this.appendChild(n.apply(this, arguments)); + }); + }, + insert: function (t, n) { + var e = "function" == typeof t ? t : Yt(t), + r = null == n ? Un : "function" == typeof n ? n : jt(n); + return this.select(function () { + return this.insertBefore( + e.apply(this, arguments), + r.apply(this, arguments) || null, + ); + }); + }, + remove: function () { + return this.each(In); + }, + clone: function (t) { + return this.select(t ? Bn : On); + }, + datum: function (t) { + return arguments.length + ? this.property("__data__", t) + : this.node().__data__; + }, + on: function (t, n, e) { + var r, + i, + o = (function (t) { + return t + .trim() + .split(/^|\s+/) + .map(function (t) { + var n = "", + e = t.indexOf("."); + return ( + e >= 0 && ((n = t.slice(e + 1)), (t = t.slice(0, e))), + { type: t, name: n } + ); + }); + })(t + ""), + a = o.length; + if (!(arguments.length < 2)) { + for (u = n ? Ln : Yn, r = 0; r < a; ++r) this.each(u(o[r], n, e)); + return this; + } + var u = this.node().__on; + if (u) + for (var c, f = 0, s = u.length; f < s; ++f) + for (r = 0, c = u[f]; r < a; ++r) + if ((i = o[r]).type === c.type && i.name === c.name) return c.value; + }, + dispatch: function (t, n) { + return this.each(("function" == typeof n ? Xn : Hn)(t, n)); + }, + [Symbol.iterator]: function* () { + for (var t = this._groups, n = 0, e = t.length; n < e; ++n) + for (var r, i = t[n], o = 0, a = i.length; o < a; ++o) + (r = i[o]) && (yield r); + }, + }; + var Kn = 0; + function Qn() { + return new Jn(); + } + function Jn() { + this._ = "@" + (++Kn).toString(36); + } + function te(t) { + let n; + for (; (n = t.sourceEvent); ) t = n; + return t; + } + function ne(t, n) { + if (((t = te(t)), void 0 === n && (n = t.currentTarget), n)) { + var e = n.ownerSVGElement || n; + if (e.createSVGPoint) { + var r = e.createSVGPoint(); + return ( + (r.x = t.clientX), + (r.y = t.clientY), + [(r = r.matrixTransform(n.getScreenCTM().inverse())).x, r.y] + ); + } + if (n.getBoundingClientRect) { + var i = n.getBoundingClientRect(); + return [ + t.clientX - i.left - n.clientLeft, + t.clientY - i.top - n.clientTop, + ]; + } + } + return [t.pageX, t.pageY]; + } + Jn.prototype = Qn.prototype = { + constructor: Jn, + get: function (t) { + for (var n = this._; !(n in t); ) if (!(t = t.parentNode)) return; + return t[n]; + }, + set: function (t, n) { + return (t[this._] = n); + }, + remove: function (t) { + return this._ in t && delete t[this._]; + }, + toString: function () { + return this._; + }, + }; + const ee = { passive: !1 }, + re = { capture: !0, passive: !1 }; + function ie(t) { + t.stopImmediatePropagation(); + } + function oe(t) { + (t.preventDefault(), t.stopImmediatePropagation()); + } + function ae(t) { + var n = t.document.documentElement, + e = Zn(t).on("dragstart.drag", oe, re); + "onselectstart" in n + ? e.on("selectstart.drag", oe, re) + : ((n.__noselect = n.style.MozUserSelect), + (n.style.MozUserSelect = "none")); + } + function ue(t, n) { + var e = t.document.documentElement, + r = Zn(t).on("dragstart.drag", null); + (n && + (r.on("click.drag", oe, re), + setTimeout(function () { + r.on("click.drag", null); + }, 0)), + "onselectstart" in e + ? r.on("selectstart.drag", null) + : ((e.style.MozUserSelect = e.__noselect), delete e.__noselect)); + } + var ce = (t) => () => t; + function fe( + t, + { + sourceEvent: n, + subject: e, + target: r, + identifier: i, + active: o, + x: a, + y: u, + dx: c, + dy: f, + dispatch: s, + }, + ) { + Object.defineProperties(this, { + type: { value: t, enumerable: !0, configurable: !0 }, + sourceEvent: { value: n, enumerable: !0, configurable: !0 }, + subject: { value: e, enumerable: !0, configurable: !0 }, + target: { value: r, enumerable: !0, configurable: !0 }, + identifier: { value: i, enumerable: !0, configurable: !0 }, + active: { value: o, enumerable: !0, configurable: !0 }, + x: { value: a, enumerable: !0, configurable: !0 }, + y: { value: u, enumerable: !0, configurable: !0 }, + dx: { value: c, enumerable: !0, configurable: !0 }, + dy: { value: f, enumerable: !0, configurable: !0 }, + _: { value: s }, + }); + } + function se(t) { + return !t.ctrlKey && !t.button; + } + function le() { + return this.parentNode; + } + function he(t, n) { + return null == n ? { x: t.x, y: t.y } : n; + } + function de() { + return navigator.maxTouchPoints || "ontouchstart" in this; + } + function pe(t, n, e) { + ((t.prototype = n.prototype = e), (e.constructor = t)); + } + function ge(t, n) { + var e = Object.create(t.prototype); + for (var r in n) e[r] = n[r]; + return e; + } + function ye() {} + fe.prototype.on = function () { + var t = this._.on.apply(this._, arguments); + return t === this._ ? this : t; + }; + var ve = 0.7, + _e = 1 / ve, + be = "\\s*([+-]?\\d+)\\s*", + me = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*", + xe = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*", + we = /^#([0-9a-f]{3,8})$/, + Me = new RegExp(`^rgb\\(${be},${be},${be}\\)$`), + Te = new RegExp(`^rgb\\(${xe},${xe},${xe}\\)$`), + Ae = new RegExp(`^rgba\\(${be},${be},${be},${me}\\)$`), + Se = new RegExp(`^rgba\\(${xe},${xe},${xe},${me}\\)$`), + Ee = new RegExp(`^hsl\\(${me},${xe},${xe}\\)$`), + Ne = new RegExp(`^hsla\\(${me},${xe},${xe},${me}\\)$`), + ke = { + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074, + }; + function Ce() { + return this.rgb().formatHex(); + } + function Pe() { + return this.rgb().formatRgb(); + } + function ze(t) { + var n, e; + return ( + (t = (t + "").trim().toLowerCase()), + (n = we.exec(t)) + ? ((e = n[1].length), + (n = parseInt(n[1], 16)), + 6 === e + ? $e(n) + : 3 === e + ? new qe( + ((n >> 8) & 15) | ((n >> 4) & 240), + ((n >> 4) & 15) | (240 & n), + ((15 & n) << 4) | (15 & n), + 1, + ) + : 8 === e + ? De( + (n >> 24) & 255, + (n >> 16) & 255, + (n >> 8) & 255, + (255 & n) / 255, + ) + : 4 === e + ? De( + ((n >> 12) & 15) | ((n >> 8) & 240), + ((n >> 8) & 15) | ((n >> 4) & 240), + ((n >> 4) & 15) | (240 & n), + (((15 & n) << 4) | (15 & n)) / 255, + ) + : null) + : (n = Me.exec(t)) + ? new qe(n[1], n[2], n[3], 1) + : (n = Te.exec(t)) + ? new qe( + (255 * n[1]) / 100, + (255 * n[2]) / 100, + (255 * n[3]) / 100, + 1, + ) + : (n = Ae.exec(t)) + ? De(n[1], n[2], n[3], n[4]) + : (n = Se.exec(t)) + ? De( + (255 * n[1]) / 100, + (255 * n[2]) / 100, + (255 * n[3]) / 100, + n[4], + ) + : (n = Ee.exec(t)) + ? Le(n[1], n[2] / 100, n[3] / 100, 1) + : (n = Ne.exec(t)) + ? Le(n[1], n[2] / 100, n[3] / 100, n[4]) + : ke.hasOwnProperty(t) + ? $e(ke[t]) + : "transparent" === t + ? new qe(NaN, NaN, NaN, 0) + : null + ); + } + function $e(t) { + return new qe((t >> 16) & 255, (t >> 8) & 255, 255 & t, 1); + } + function De(t, n, e, r) { + return (r <= 0 && (t = n = e = NaN), new qe(t, n, e, r)); + } + function Re(t) { + return ( + t instanceof ye || (t = ze(t)), + t ? new qe((t = t.rgb()).r, t.g, t.b, t.opacity) : new qe() + ); + } + function Fe(t, n, e, r) { + return 1 === arguments.length ? Re(t) : new qe(t, n, e, null == r ? 1 : r); + } + function qe(t, n, e, r) { + ((this.r = +t), (this.g = +n), (this.b = +e), (this.opacity = +r)); + } + function Ue() { + return `#${Ye(this.r)}${Ye(this.g)}${Ye(this.b)}`; + } + function Ie() { + const t = Oe(this.opacity); + return `${1 === t ? "rgb(" : "rgba("}${Be(this.r)}, ${Be(this.g)}, ${Be(this.b)}${1 === t ? ")" : `, ${t})`}`; + } + function Oe(t) { + return isNaN(t) ? 1 : Math.max(0, Math.min(1, t)); + } + function Be(t) { + return Math.max(0, Math.min(255, Math.round(t) || 0)); + } + function Ye(t) { + return ((t = Be(t)) < 16 ? "0" : "") + t.toString(16); + } + function Le(t, n, e, r) { + return ( + r <= 0 + ? (t = n = e = NaN) + : e <= 0 || e >= 1 + ? (t = n = NaN) + : n <= 0 && (t = NaN), + new Xe(t, n, e, r) + ); + } + function je(t) { + if (t instanceof Xe) return new Xe(t.h, t.s, t.l, t.opacity); + if ((t instanceof ye || (t = ze(t)), !t)) return new Xe(); + if (t instanceof Xe) return t; + var n = (t = t.rgb()).r / 255, + e = t.g / 255, + r = t.b / 255, + i = Math.min(n, e, r), + o = Math.max(n, e, r), + a = NaN, + u = o - i, + c = (o + i) / 2; + return ( + u + ? ((a = + n === o + ? (e - r) / u + 6 * (e < r) + : e === o + ? (r - n) / u + 2 + : (n - e) / u + 4), + (u /= c < 0.5 ? o + i : 2 - o - i), + (a *= 60)) + : (u = c > 0 && c < 1 ? 0 : a), + new Xe(a, u, c, t.opacity) + ); + } + function He(t, n, e, r) { + return 1 === arguments.length ? je(t) : new Xe(t, n, e, null == r ? 1 : r); + } + function Xe(t, n, e, r) { + ((this.h = +t), (this.s = +n), (this.l = +e), (this.opacity = +r)); + } + function Ge(t) { + return (t = (t || 0) % 360) < 0 ? t + 360 : t; + } + function Ve(t) { + return Math.max(0, Math.min(1, t || 0)); + } + function We(t, n, e) { + return ( + 255 * + (t < 60 + ? n + ((e - n) * t) / 60 + : t < 180 + ? e + : t < 240 + ? n + ((e - n) * (240 - t)) / 60 + : n) + ); + } + (pe(ye, ze, { + copy(t) { + return Object.assign(new this.constructor(), this, t); + }, + displayable() { + return this.rgb().displayable(); + }, + hex: Ce, + formatHex: Ce, + formatHex8: function () { + return this.rgb().formatHex8(); + }, + formatHsl: function () { + return je(this).formatHsl(); + }, + formatRgb: Pe, + toString: Pe, + }), + pe( + qe, + Fe, + ge(ye, { + brighter(t) { + return ( + (t = null == t ? _e : Math.pow(_e, t)), + new qe(this.r * t, this.g * t, this.b * t, this.opacity) + ); + }, + darker(t) { + return ( + (t = null == t ? ve : Math.pow(ve, t)), + new qe(this.r * t, this.g * t, this.b * t, this.opacity) + ); + }, + rgb() { + return this; + }, + clamp() { + return new qe(Be(this.r), Be(this.g), Be(this.b), Oe(this.opacity)); + }, + displayable() { + return ( + -0.5 <= this.r && + this.r < 255.5 && + -0.5 <= this.g && + this.g < 255.5 && + -0.5 <= this.b && + this.b < 255.5 && + 0 <= this.opacity && + this.opacity <= 1 + ); + }, + hex: Ue, + formatHex: Ue, + formatHex8: function () { + return `#${Ye(this.r)}${Ye(this.g)}${Ye(this.b)}${Ye(255 * (isNaN(this.opacity) ? 1 : this.opacity))}`; + }, + formatRgb: Ie, + toString: Ie, + }), + ), + pe( + Xe, + He, + ge(ye, { + brighter(t) { + return ( + (t = null == t ? _e : Math.pow(_e, t)), + new Xe(this.h, this.s, this.l * t, this.opacity) + ); + }, + darker(t) { + return ( + (t = null == t ? ve : Math.pow(ve, t)), + new Xe(this.h, this.s, this.l * t, this.opacity) + ); + }, + rgb() { + var t = (this.h % 360) + 360 * (this.h < 0), + n = isNaN(t) || isNaN(this.s) ? 0 : this.s, + e = this.l, + r = e + (e < 0.5 ? e : 1 - e) * n, + i = 2 * e - r; + return new qe( + We(t >= 240 ? t - 240 : t + 120, i, r), + We(t, i, r), + We(t < 120 ? t + 240 : t - 120, i, r), + this.opacity, + ); + }, + clamp() { + return new Xe(Ge(this.h), Ve(this.s), Ve(this.l), Oe(this.opacity)); + }, + displayable() { + return ( + ((0 <= this.s && this.s <= 1) || isNaN(this.s)) && + 0 <= this.l && + this.l <= 1 && + 0 <= this.opacity && + this.opacity <= 1 + ); + }, + formatHsl() { + const t = Oe(this.opacity); + return `${1 === t ? "hsl(" : "hsla("}${Ge(this.h)}, ${100 * Ve(this.s)}%, ${100 * Ve(this.l)}%${1 === t ? ")" : `, ${t})`}`; + }, + }), + )); + const Ze = Math.PI / 180, + Ke = 180 / Math.PI, + Qe = 0.96422, + Je = 1, + tr = 0.82521, + nr = 4 / 29, + er = 6 / 29, + rr = 3 * er * er, + ir = er * er * er; + function or(t) { + if (t instanceof ur) return new ur(t.l, t.a, t.b, t.opacity); + if (t instanceof pr) return gr(t); + t instanceof qe || (t = Re(t)); + var n, + e, + r = lr(t.r), + i = lr(t.g), + o = lr(t.b), + a = cr((0.2225045 * r + 0.7168786 * i + 0.0606169 * o) / Je); + return ( + r === i && i === o + ? (n = e = a) + : ((n = cr((0.4360747 * r + 0.3850649 * i + 0.1430804 * o) / Qe)), + (e = cr((0.0139322 * r + 0.0971045 * i + 0.7141733 * o) / tr))), + new ur(116 * a - 16, 500 * (n - a), 200 * (a - e), t.opacity) + ); + } + function ar(t, n, e, r) { + return 1 === arguments.length ? or(t) : new ur(t, n, e, null == r ? 1 : r); + } + function ur(t, n, e, r) { + ((this.l = +t), (this.a = +n), (this.b = +e), (this.opacity = +r)); + } + function cr(t) { + return t > ir ? Math.pow(t, 1 / 3) : t / rr + nr; + } + function fr(t) { + return t > er ? t * t * t : rr * (t - nr); + } + function sr(t) { + return ( + 255 * (t <= 0.0031308 ? 12.92 * t : 1.055 * Math.pow(t, 1 / 2.4) - 0.055) + ); + } + function lr(t) { + return (t /= 255) <= 0.04045 + ? t / 12.92 + : Math.pow((t + 0.055) / 1.055, 2.4); + } + function hr(t) { + if (t instanceof pr) return new pr(t.h, t.c, t.l, t.opacity); + if ((t instanceof ur || (t = or(t)), 0 === t.a && 0 === t.b)) + return new pr(NaN, 0 < t.l && t.l < 100 ? 0 : NaN, t.l, t.opacity); + var n = Math.atan2(t.b, t.a) * Ke; + return new pr( + n < 0 ? n + 360 : n, + Math.sqrt(t.a * t.a + t.b * t.b), + t.l, + t.opacity, + ); + } + function dr(t, n, e, r) { + return 1 === arguments.length ? hr(t) : new pr(t, n, e, null == r ? 1 : r); + } + function pr(t, n, e, r) { + ((this.h = +t), (this.c = +n), (this.l = +e), (this.opacity = +r)); + } + function gr(t) { + if (isNaN(t.h)) return new ur(t.l, 0, 0, t.opacity); + var n = t.h * Ze; + return new ur(t.l, Math.cos(n) * t.c, Math.sin(n) * t.c, t.opacity); + } + (pe( + ur, + ar, + ge(ye, { + brighter(t) { + return new ur( + this.l + 18 * (null == t ? 1 : t), + this.a, + this.b, + this.opacity, + ); + }, + darker(t) { + return new ur( + this.l - 18 * (null == t ? 1 : t), + this.a, + this.b, + this.opacity, + ); + }, + rgb() { + var t = (this.l + 16) / 116, + n = isNaN(this.a) ? t : t + this.a / 500, + e = isNaN(this.b) ? t : t - this.b / 200; + return new qe( + sr( + 3.1338561 * (n = Qe * fr(n)) - + 1.6168667 * (t = Je * fr(t)) - + 0.4906146 * (e = tr * fr(e)), + ), + sr(-0.9787684 * n + 1.9161415 * t + 0.033454 * e), + sr(0.0719453 * n - 0.2289914 * t + 1.4052427 * e), + this.opacity, + ); + }, + }), + ), + pe( + pr, + dr, + ge(ye, { + brighter(t) { + return new pr( + this.h, + this.c, + this.l + 18 * (null == t ? 1 : t), + this.opacity, + ); + }, + darker(t) { + return new pr( + this.h, + this.c, + this.l - 18 * (null == t ? 1 : t), + this.opacity, + ); + }, + rgb() { + return gr(this).rgb(); + }, + }), + )); + var yr = -0.14861, + vr = 1.78277, + _r = -0.29227, + br = -0.90649, + mr = 1.97294, + xr = mr * br, + wr = mr * vr, + Mr = vr * _r - br * yr; + function Tr(t, n, e, r) { + return 1 === arguments.length + ? (function (t) { + if (t instanceof Ar) return new Ar(t.h, t.s, t.l, t.opacity); + t instanceof qe || (t = Re(t)); + var n = t.r / 255, + e = t.g / 255, + r = t.b / 255, + i = (Mr * r + xr * n - wr * e) / (Mr + xr - wr), + o = r - i, + a = (mr * (e - i) - _r * o) / br, + u = Math.sqrt(a * a + o * o) / (mr * i * (1 - i)), + c = u ? Math.atan2(a, o) * Ke - 120 : NaN; + return new Ar(c < 0 ? c + 360 : c, u, i, t.opacity); + })(t) + : new Ar(t, n, e, null == r ? 1 : r); + } + function Ar(t, n, e, r) { + ((this.h = +t), (this.s = +n), (this.l = +e), (this.opacity = +r)); + } + function Sr(t, n, e, r, i) { + var o = t * t, + a = o * t; + return ( + ((1 - 3 * t + 3 * o - a) * n + + (4 - 6 * o + 3 * a) * e + + (1 + 3 * t + 3 * o - 3 * a) * r + + a * i) / + 6 + ); + } + function Er(t) { + var n = t.length - 1; + return function (e) { + var r = e <= 0 ? (e = 0) : e >= 1 ? ((e = 1), n - 1) : Math.floor(e * n), + i = t[r], + o = t[r + 1], + a = r > 0 ? t[r - 1] : 2 * i - o, + u = r < n - 1 ? t[r + 2] : 2 * o - i; + return Sr((e - r / n) * n, a, i, o, u); + }; + } + function Nr(t) { + var n = t.length; + return function (e) { + var r = Math.floor(((e %= 1) < 0 ? ++e : e) * n), + i = t[(r + n - 1) % n], + o = t[r % n], + a = t[(r + 1) % n], + u = t[(r + 2) % n]; + return Sr((e - r / n) * n, i, o, a, u); + }; + } + pe( + Ar, + Tr, + ge(ye, { + brighter(t) { + return ( + (t = null == t ? _e : Math.pow(_e, t)), + new Ar(this.h, this.s, this.l * t, this.opacity) + ); + }, + darker(t) { + return ( + (t = null == t ? ve : Math.pow(ve, t)), + new Ar(this.h, this.s, this.l * t, this.opacity) + ); + }, + rgb() { + var t = isNaN(this.h) ? 0 : (this.h + 120) * Ze, + n = +this.l, + e = isNaN(this.s) ? 0 : this.s * n * (1 - n), + r = Math.cos(t), + i = Math.sin(t); + return new qe( + 255 * (n + e * (yr * r + vr * i)), + 255 * (n + e * (_r * r + br * i)), + 255 * (n + e * (mr * r)), + this.opacity, + ); + }, + }), + ); + var kr = (t) => () => t; + function Cr(t, n) { + return function (e) { + return t + e * n; + }; + } + function Pr(t, n) { + var e = n - t; + return e + ? Cr(t, e > 180 || e < -180 ? e - 360 * Math.round(e / 360) : e) + : kr(isNaN(t) ? n : t); + } + function zr(t) { + return 1 == (t = +t) + ? $r + : function (n, e) { + return e - n + ? (function (t, n, e) { + return ( + (t = Math.pow(t, e)), + (n = Math.pow(n, e) - t), + (e = 1 / e), + function (r) { + return Math.pow(t + r * n, e); + } + ); + })(n, e, t) + : kr(isNaN(n) ? e : n); + }; + } + function $r(t, n) { + var e = n - t; + return e ? Cr(t, e) : kr(isNaN(t) ? n : t); + } + var Dr = (function t(n) { + var e = zr(n); + function r(t, n) { + var r = e((t = Fe(t)).r, (n = Fe(n)).r), + i = e(t.g, n.g), + o = e(t.b, n.b), + a = $r(t.opacity, n.opacity); + return function (n) { + return ( + (t.r = r(n)), + (t.g = i(n)), + (t.b = o(n)), + (t.opacity = a(n)), + t + "" + ); + }; + } + return ((r.gamma = t), r); + })(1); + function Rr(t) { + return function (n) { + var e, + r, + i = n.length, + o = new Array(i), + a = new Array(i), + u = new Array(i); + for (e = 0; e < i; ++e) + ((r = Fe(n[e])), + (o[e] = r.r || 0), + (a[e] = r.g || 0), + (u[e] = r.b || 0)); + return ( + (o = t(o)), + (a = t(a)), + (u = t(u)), + (r.opacity = 1), + function (t) { + return ((r.r = o(t)), (r.g = a(t)), (r.b = u(t)), r + ""); + } + ); + }; + } + var Fr = Rr(Er), + qr = Rr(Nr); + function Ur(t, n) { + n || (n = []); + var e, + r = t ? Math.min(n.length, t.length) : 0, + i = n.slice(); + return function (o) { + for (e = 0; e < r; ++e) i[e] = t[e] * (1 - o) + n[e] * o; + return i; + }; + } + function Ir(t) { + return ArrayBuffer.isView(t) && !(t instanceof DataView); + } + function Or(t, n) { + var e, + r = n ? n.length : 0, + i = t ? Math.min(r, t.length) : 0, + o = new Array(i), + a = new Array(r); + for (e = 0; e < i; ++e) o[e] = Gr(t[e], n[e]); + for (; e < r; ++e) a[e] = n[e]; + return function (t) { + for (e = 0; e < i; ++e) a[e] = o[e](t); + return a; + }; + } + function Br(t, n) { + var e = new Date(); + return ( + (t = +t), + (n = +n), + function (r) { + return (e.setTime(t * (1 - r) + n * r), e); + } + ); + } + function Yr(t, n) { + return ( + (t = +t), + (n = +n), + function (e) { + return t * (1 - e) + n * e; + } + ); + } + function Lr(t, n) { + var e, + r = {}, + i = {}; + for (e in ((null !== t && "object" == typeof t) || (t = {}), + (null !== n && "object" == typeof n) || (n = {}), + n)) + e in t ? (r[e] = Gr(t[e], n[e])) : (i[e] = n[e]); + return function (t) { + for (e in r) i[e] = r[e](t); + return i; + }; + } + var jr = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, + Hr = new RegExp(jr.source, "g"); + function Xr(t, n) { + var e, + r, + i, + o = (jr.lastIndex = Hr.lastIndex = 0), + a = -1, + u = [], + c = []; + for (t += "", n += ""; (e = jr.exec(t)) && (r = Hr.exec(n)); ) + ((i = r.index) > o && + ((i = n.slice(o, i)), u[a] ? (u[a] += i) : (u[++a] = i)), + (e = e[0]) === (r = r[0]) + ? u[a] + ? (u[a] += r) + : (u[++a] = r) + : ((u[++a] = null), c.push({ i: a, x: Yr(e, r) })), + (o = Hr.lastIndex)); + return ( + o < n.length && ((i = n.slice(o)), u[a] ? (u[a] += i) : (u[++a] = i)), + u.length < 2 + ? c[0] + ? (function (t) { + return function (n) { + return t(n) + ""; + }; + })(c[0].x) + : (function (t) { + return function () { + return t; + }; + })(n) + : ((n = c.length), + function (t) { + for (var e, r = 0; r < n; ++r) u[(e = c[r]).i] = e.x(t); + return u.join(""); + }) + ); + } + function Gr(t, n) { + var e, + r = typeof n; + return null == n || "boolean" === r + ? kr(n) + : ("number" === r + ? Yr + : "string" === r + ? (e = ze(n)) + ? ((n = e), Dr) + : Xr + : n instanceof ze + ? Dr + : n instanceof Date + ? Br + : Ir(n) + ? Ur + : Array.isArray(n) + ? Or + : ("function" != typeof n.valueOf && + "function" != typeof n.toString) || + isNaN(n) + ? Lr + : Yr)(t, n); + } + function Vr(t, n) { + return ( + (t = +t), + (n = +n), + function (e) { + return Math.round(t * (1 - e) + n * e); + } + ); + } + var Wr, + Zr = 180 / Math.PI, + Kr = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1, + }; + function Qr(t, n, e, r, i, o) { + var a, u, c; + return ( + (a = Math.sqrt(t * t + n * n)) && ((t /= a), (n /= a)), + (c = t * e + n * r) && ((e -= t * c), (r -= n * c)), + (u = Math.sqrt(e * e + r * r)) && ((e /= u), (r /= u), (c /= u)), + t * r < n * e && ((t = -t), (n = -n), (c = -c), (a = -a)), + { + translateX: i, + translateY: o, + rotate: Math.atan2(n, t) * Zr, + skewX: Math.atan(c) * Zr, + scaleX: a, + scaleY: u, + } + ); + } + function Jr(t, n, e, r) { + function i(t) { + return t.length ? t.pop() + " " : ""; + } + return function (o, a) { + var u = [], + c = []; + return ( + (o = t(o)), + (a = t(a)), + (function (t, r, i, o, a, u) { + if (t !== i || r !== o) { + var c = a.push("translate(", null, n, null, e); + u.push({ i: c - 4, x: Yr(t, i) }, { i: c - 2, x: Yr(r, o) }); + } else (i || o) && a.push("translate(" + i + n + o + e); + })(o.translateX, o.translateY, a.translateX, a.translateY, u, c), + (function (t, n, e, o) { + t !== n + ? (t - n > 180 ? (n += 360) : n - t > 180 && (t += 360), + o.push({ i: e.push(i(e) + "rotate(", null, r) - 2, x: Yr(t, n) })) + : n && e.push(i(e) + "rotate(" + n + r); + })(o.rotate, a.rotate, u, c), + (function (t, n, e, o) { + t !== n + ? o.push({ i: e.push(i(e) + "skewX(", null, r) - 2, x: Yr(t, n) }) + : n && e.push(i(e) + "skewX(" + n + r); + })(o.skewX, a.skewX, u, c), + (function (t, n, e, r, o, a) { + if (t !== e || n !== r) { + var u = o.push(i(o) + "scale(", null, ",", null, ")"); + a.push({ i: u - 4, x: Yr(t, e) }, { i: u - 2, x: Yr(n, r) }); + } else + (1 === e && 1 === r) || o.push(i(o) + "scale(" + e + "," + r + ")"); + })(o.scaleX, o.scaleY, a.scaleX, a.scaleY, u, c), + (o = a = null), + function (t) { + for (var n, e = -1, r = c.length; ++e < r; ) u[(n = c[e]).i] = n.x(t); + return u.join(""); + } + ); + }; + } + var ti = Jr( + function (t) { + const n = new ( + "function" == typeof DOMMatrix ? DOMMatrix : WebKitCSSMatrix + )(t + ""); + return n.isIdentity ? Kr : Qr(n.a, n.b, n.c, n.d, n.e, n.f); + }, + "px, ", + "px)", + "deg)", + ), + ni = Jr( + function (t) { + return null == t + ? Kr + : (Wr || + (Wr = document.createElementNS( + "http://www.w3.org/2000/svg", + "g", + )), + Wr.setAttribute("transform", t), + (t = Wr.transform.baseVal.consolidate()) + ? Qr((t = t.matrix).a, t.b, t.c, t.d, t.e, t.f) + : Kr); + }, + ", ", + ")", + ")", + ); + function ei(t) { + return ((t = Math.exp(t)) + 1 / t) / 2; + } + var ri = (function t(n, e, r) { + function i(t, i) { + var o, + a, + u = t[0], + c = t[1], + f = t[2], + s = i[0], + l = i[1], + h = i[2], + d = s - u, + p = l - c, + g = d * d + p * p; + if (g < 1e-12) + ((a = Math.log(h / f) / n), + (o = function (t) { + return [u + t * d, c + t * p, f * Math.exp(n * t * a)]; + })); + else { + var y = Math.sqrt(g), + v = (h * h - f * f + r * g) / (2 * f * e * y), + _ = (h * h - f * f - r * g) / (2 * h * e * y), + b = Math.log(Math.sqrt(v * v + 1) - v), + m = Math.log(Math.sqrt(_ * _ + 1) - _); + ((a = (m - b) / n), + (o = function (t) { + var r = t * a, + i = ei(b), + o = + (f / (e * y)) * + (i * + (function (t) { + return ((t = Math.exp(2 * t)) - 1) / (t + 1); + })(n * r + b) - + (function (t) { + return ((t = Math.exp(t)) - 1 / t) / 2; + })(b)); + return [u + o * d, c + o * p, (f * i) / ei(n * r + b)]; + })); + } + return ((o.duration = (1e3 * a * n) / Math.SQRT2), o); + } + return ( + (i.rho = function (n) { + var e = Math.max(0.001, +n), + r = e * e; + return t(e, r, r * r); + }), + i + ); + })(Math.SQRT2, 2, 4); + function ii(t) { + return function (n, e) { + var r = t((n = He(n)).h, (e = He(e)).h), + i = $r(n.s, e.s), + o = $r(n.l, e.l), + a = $r(n.opacity, e.opacity); + return function (t) { + return ( + (n.h = r(t)), + (n.s = i(t)), + (n.l = o(t)), + (n.opacity = a(t)), + n + "" + ); + }; + }; + } + var oi = ii(Pr), + ai = ii($r); + function ui(t) { + return function (n, e) { + var r = t((n = dr(n)).h, (e = dr(e)).h), + i = $r(n.c, e.c), + o = $r(n.l, e.l), + a = $r(n.opacity, e.opacity); + return function (t) { + return ( + (n.h = r(t)), + (n.c = i(t)), + (n.l = o(t)), + (n.opacity = a(t)), + n + "" + ); + }; + }; + } + var ci = ui(Pr), + fi = ui($r); + function si(t) { + return (function n(e) { + function r(n, r) { + var i = t((n = Tr(n)).h, (r = Tr(r)).h), + o = $r(n.s, r.s), + a = $r(n.l, r.l), + u = $r(n.opacity, r.opacity); + return function (t) { + return ( + (n.h = i(t)), + (n.s = o(t)), + (n.l = a(Math.pow(t, e))), + (n.opacity = u(t)), + n + "" + ); + }; + } + return ((e = +e), (r.gamma = n), r); + })(1); + } + var li = si(Pr), + hi = si($r); + function di(t, n) { + void 0 === n && ((n = t), (t = Gr)); + for ( + var e = 0, r = n.length - 1, i = n[0], o = new Array(r < 0 ? 0 : r); + e < r; + + ) + o[e] = t(i, (i = n[++e])); + return function (t) { + var n = Math.max(0, Math.min(r - 1, Math.floor((t *= r)))); + return o[n](t - n); + }; + } + var pi, + gi, + yi = 0, + vi = 0, + _i = 0, + bi = 1e3, + mi = 0, + xi = 0, + wi = 0, + Mi = "object" == typeof performance && performance.now ? performance : Date, + Ti = + "object" == typeof window && window.requestAnimationFrame + ? window.requestAnimationFrame.bind(window) + : function (t) { + setTimeout(t, 17); + }; + function Ai() { + return xi || (Ti(Si), (xi = Mi.now() + wi)); + } + function Si() { + xi = 0; + } + function Ei() { + this._call = this._time = this._next = null; + } + function Ni(t, n, e) { + var r = new Ei(); + return (r.restart(t, n, e), r); + } + function ki() { + (Ai(), ++yi); + for (var t, n = pi; n; ) + ((t = xi - n._time) >= 0 && n._call.call(void 0, t), (n = n._next)); + --yi; + } + function Ci() { + ((xi = (mi = Mi.now()) + wi), (yi = vi = 0)); + try { + ki(); + } finally { + ((yi = 0), + (function () { + var t, + n, + e = pi, + r = 1 / 0; + for (; e; ) + e._call + ? (r > e._time && (r = e._time), (t = e), (e = e._next)) + : ((n = e._next), + (e._next = null), + (e = t ? (t._next = n) : (pi = n))); + ((gi = t), zi(r)); + })(), + (xi = 0)); + } + } + function Pi() { + var t = Mi.now(), + n = t - mi; + n > bi && ((wi -= n), (mi = t)); + } + function zi(t) { + yi || + (vi && (vi = clearTimeout(vi)), + t - xi > 24 + ? (t < 1 / 0 && (vi = setTimeout(Ci, t - Mi.now() - wi)), + _i && (_i = clearInterval(_i))) + : (_i || ((mi = Mi.now()), (_i = setInterval(Pi, bi))), + (yi = 1), + Ti(Ci))); + } + function $i(t, n, e) { + var r = new Ei(); + return ( + (n = null == n ? 0 : +n), + r.restart( + (e) => { + (r.stop(), t(e + n)); + }, + n, + e, + ), + r + ); + } + Ei.prototype = Ni.prototype = { + constructor: Ei, + restart: function (t, n, e) { + if ("function" != typeof t) + throw new TypeError("callback is not a function"); + ((e = (null == e ? Ai() : +e) + (null == n ? 0 : +n)), + this._next || + gi === this || + (gi ? (gi._next = this) : (pi = this), (gi = this)), + (this._call = t), + (this._time = e), + zi()); + }, + stop: function () { + this._call && ((this._call = null), (this._time = 1 / 0), zi()); + }, + }; + var Di = $t("start", "end", "cancel", "interrupt"), + Ri = [], + Fi = 0, + qi = 1, + Ui = 2, + Ii = 3, + Oi = 4, + Bi = 5, + Yi = 6; + function Li(t, n, e, r, i, o) { + var a = t.__transition; + if (a) { + if (e in a) return; + } else t.__transition = {}; + !(function (t, n, e) { + var r, + i = t.__transition; + function o(t) { + ((e.state = qi), + e.timer.restart(a, e.delay, e.time), + e.delay <= t && a(t - e.delay)); + } + function a(o) { + var f, s, l, h; + if (e.state !== qi) return c(); + for (f in i) + if ((h = i[f]).name === e.name) { + if (h.state === Ii) return $i(a); + h.state === Oi + ? ((h.state = Yi), + h.timer.stop(), + h.on.call("interrupt", t, t.__data__, h.index, h.group), + delete i[f]) + : +f < n && + ((h.state = Yi), + h.timer.stop(), + h.on.call("cancel", t, t.__data__, h.index, h.group), + delete i[f]); + } + if ( + ($i(function () { + e.state === Ii && + ((e.state = Oi), e.timer.restart(u, e.delay, e.time), u(o)); + }), + (e.state = Ui), + e.on.call("start", t, t.__data__, e.index, e.group), + e.state === Ui) + ) { + for ( + e.state = Ii, r = new Array((l = e.tween.length)), f = 0, s = -1; + f < l; + ++f + ) + (h = e.tween[f].value.call(t, t.__data__, e.index, e.group)) && + (r[++s] = h); + r.length = s + 1; + } + } + function u(n) { + for ( + var i = + n < e.duration + ? e.ease.call(null, n / e.duration) + : (e.timer.restart(c), (e.state = Bi), 1), + o = -1, + a = r.length; + ++o < a; + + ) + r[o].call(t, i); + e.state === Bi && + (e.on.call("end", t, t.__data__, e.index, e.group), c()); + } + function c() { + for (var r in ((e.state = Yi), e.timer.stop(), delete i[n], i)) return; + delete t.__transition; + } + ((i[n] = e), (e.timer = Ni(o, 0, e.time))); + })(t, e, { + name: n, + index: r, + group: i, + on: Di, + tween: Ri, + time: o.time, + delay: o.delay, + duration: o.duration, + ease: o.ease, + timer: null, + state: Fi, + }); + } + function ji(t, n) { + var e = Xi(t, n); + if (e.state > Fi) throw new Error("too late; already scheduled"); + return e; + } + function Hi(t, n) { + var e = Xi(t, n); + if (e.state > Ii) throw new Error("too late; already running"); + return e; + } + function Xi(t, n) { + var e = t.__transition; + if (!e || !(e = e[n])) throw new Error("transition not found"); + return e; + } + function Gi(t, n) { + var e, + r, + i, + o = t.__transition, + a = !0; + if (o) { + for (i in ((n = null == n ? null : n + ""), o)) + (e = o[i]).name === n + ? ((r = e.state > Ui && e.state < Bi), + (e.state = Yi), + e.timer.stop(), + e.on.call( + r ? "interrupt" : "cancel", + t, + t.__data__, + e.index, + e.group, + ), + delete o[i]) + : (a = !1); + a && delete t.__transition; + } + } + function Vi(t, n) { + var e, r; + return function () { + var i = Hi(this, t), + o = i.tween; + if (o !== e) + for (var a = 0, u = (r = e = o).length; a < u; ++a) + if (r[a].name === n) { + (r = r.slice()).splice(a, 1); + break; + } + i.tween = r; + }; + } + function Wi(t, n, e) { + var r, i; + if ("function" != typeof e) throw new Error(); + return function () { + var o = Hi(this, t), + a = o.tween; + if (a !== r) { + i = (r = a).slice(); + for (var u = { name: n, value: e }, c = 0, f = i.length; c < f; ++c) + if (i[c].name === n) { + i[c] = u; + break; + } + c === f && i.push(u); + } + o.tween = i; + }; + } + function Zi(t, n, e) { + var r = t._id; + return ( + t.each(function () { + var t = Hi(this, r); + (t.value || (t.value = {}))[n] = e.apply(this, arguments); + }), + function (t) { + return Xi(t, r).value[n]; + } + ); + } + function Ki(t, n) { + var e; + return ( + "number" == typeof n + ? Yr + : n instanceof ze + ? Dr + : (e = ze(n)) + ? ((n = e), Dr) + : Xr + )(t, n); + } + function Qi(t) { + return function () { + this.removeAttribute(t); + }; + } + function Ji(t) { + return function () { + this.removeAttributeNS(t.space, t.local); + }; + } + function to(t, n, e) { + var r, + i, + o = e + ""; + return function () { + var a = this.getAttribute(t); + return a === o ? null : a === r ? i : (i = n((r = a), e)); + }; + } + function no(t, n, e) { + var r, + i, + o = e + ""; + return function () { + var a = this.getAttributeNS(t.space, t.local); + return a === o ? null : a === r ? i : (i = n((r = a), e)); + }; + } + function eo(t, n, e) { + var r, i, o; + return function () { + var a, + u, + c = e(this); + if (null != c) + return (a = this.getAttribute(t)) === (u = c + "") + ? null + : a === r && u === i + ? o + : ((i = u), (o = n((r = a), c))); + this.removeAttribute(t); + }; + } + function ro(t, n, e) { + var r, i, o; + return function () { + var a, + u, + c = e(this); + if (null != c) + return (a = this.getAttributeNS(t.space, t.local)) === (u = c + "") + ? null + : a === r && u === i + ? o + : ((i = u), (o = n((r = a), c))); + this.removeAttributeNS(t.space, t.local); + }; + } + function io(t, n) { + var e, r; + function i() { + var i = n.apply(this, arguments); + return ( + i !== r && + (e = + (r = i) && + (function (t, n) { + return function (e) { + this.setAttributeNS(t.space, t.local, n.call(this, e)); + }; + })(t, i)), + e + ); + } + return ((i._value = n), i); + } + function oo(t, n) { + var e, r; + function i() { + var i = n.apply(this, arguments); + return ( + i !== r && + (e = + (r = i) && + (function (t, n) { + return function (e) { + this.setAttribute(t, n.call(this, e)); + }; + })(t, i)), + e + ); + } + return ((i._value = n), i); + } + function ao(t, n) { + return function () { + ji(this, t).delay = +n.apply(this, arguments); + }; + } + function uo(t, n) { + return ( + (n = +n), + function () { + ji(this, t).delay = n; + } + ); + } + function co(t, n) { + return function () { + Hi(this, t).duration = +n.apply(this, arguments); + }; + } + function fo(t, n) { + return ( + (n = +n), + function () { + Hi(this, t).duration = n; + } + ); + } + var so = Wn.prototype.constructor; + function lo(t) { + return function () { + this.style.removeProperty(t); + }; + } + var ho = 0; + function po(t, n, e, r) { + ((this._groups = t), (this._parents = n), (this._name = e), (this._id = r)); + } + function go(t) { + return Wn().transition(t); + } + function yo() { + return ++ho; + } + var vo = Wn.prototype; + po.prototype = go.prototype = { + constructor: po, + select: function (t) { + var n = this._name, + e = this._id; + "function" != typeof t && (t = jt(t)); + for ( + var r = this._groups, i = r.length, o = new Array(i), a = 0; + a < i; + ++a + ) + for ( + var u, c, f = r[a], s = f.length, l = (o[a] = new Array(s)), h = 0; + h < s; + ++h + ) + (u = f[h]) && + (c = t.call(u, u.__data__, h, f)) && + ("__data__" in u && (c.__data__ = u.__data__), + (l[h] = c), + Li(l[h], n, e, h, l, Xi(u, e))); + return new po(o, this._parents, n, e); + }, + selectAll: function (t) { + var n = this._name, + e = this._id; + "function" != typeof t && (t = Gt(t)); + for ( + var r = this._groups, i = r.length, o = [], a = [], u = 0; + u < i; + ++u + ) + for (var c, f = r[u], s = f.length, l = 0; l < s; ++l) + if ((c = f[l])) { + for ( + var h, + d = t.call(c, c.__data__, l, f), + p = Xi(c, e), + g = 0, + y = d.length; + g < y; + ++g + ) + (h = d[g]) && Li(h, n, e, g, d, p); + (o.push(d), a.push(c)); + } + return new po(o, a, n, e); + }, + selectChild: vo.selectChild, + selectChildren: vo.selectChildren, + filter: function (t) { + "function" != typeof t && (t = Vt(t)); + for ( + var n = this._groups, e = n.length, r = new Array(e), i = 0; + i < e; + ++i + ) + for (var o, a = n[i], u = a.length, c = (r[i] = []), f = 0; f < u; ++f) + (o = a[f]) && t.call(o, o.__data__, f, a) && c.push(o); + return new po(r, this._parents, this._name, this._id); + }, + merge: function (t) { + if (t._id !== this._id) throw new Error(); + for ( + var n = this._groups, + e = t._groups, + r = n.length, + i = e.length, + o = Math.min(r, i), + a = new Array(r), + u = 0; + u < o; + ++u + ) + for ( + var c, + f = n[u], + s = e[u], + l = f.length, + h = (a[u] = new Array(l)), + d = 0; + d < l; + ++d + ) + (c = f[d] || s[d]) && (h[d] = c); + for (; u < r; ++u) a[u] = n[u]; + return new po(a, this._parents, this._name, this._id); + }, + selection: function () { + return new so(this._groups, this._parents); + }, + transition: function () { + for ( + var t = this._name, + n = this._id, + e = yo(), + r = this._groups, + i = r.length, + o = 0; + o < i; + ++o + ) + for (var a, u = r[o], c = u.length, f = 0; f < c; ++f) + if ((a = u[f])) { + var s = Xi(a, n); + Li(a, t, e, f, u, { + time: s.time + s.delay + s.duration, + delay: 0, + duration: s.duration, + ease: s.ease, + }); + } + return new po(r, this._parents, t, e); + }, + call: vo.call, + nodes: vo.nodes, + node: vo.node, + size: vo.size, + empty: vo.empty, + each: vo.each, + on: function (t, n) { + var e = this._id; + return arguments.length < 2 + ? Xi(this.node(), e).on.on(t) + : this.each( + (function (t, n, e) { + var r, + i, + o = (function (t) { + return (t + "") + .trim() + .split(/^|\s+/) + .every(function (t) { + var n = t.indexOf("."); + return ( + n >= 0 && (t = t.slice(0, n)), + !t || "start" === t + ); + }); + })(n) + ? ji + : Hi; + return function () { + var a = o(this, t), + u = a.on; + (u !== r && (i = (r = u).copy()).on(n, e), (a.on = i)); + }; + })(e, t, n), + ); + }, + attr: function (t, n) { + var e = It(t), + r = "transform" === e ? ni : Ki; + return this.attrTween( + t, + "function" == typeof n + ? (e.local ? ro : eo)(e, r, Zi(this, "attr." + t, n)) + : null == n + ? (e.local ? Ji : Qi)(e) + : (e.local ? no : to)(e, r, n), + ); + }, + attrTween: function (t, n) { + var e = "attr." + t; + if (arguments.length < 2) return (e = this.tween(e)) && e._value; + if (null == n) return this.tween(e, null); + if ("function" != typeof n) throw new Error(); + var r = It(t); + return this.tween(e, (r.local ? io : oo)(r, n)); + }, + style: function (t, n, e) { + var r = "transform" == (t += "") ? ti : Ki; + return null == n + ? this.styleTween( + t, + (function (t, n) { + var e, r, i; + return function () { + var o = _n(this, t), + a = (this.style.removeProperty(t), _n(this, t)); + return o === a + ? null + : o === e && a === r + ? i + : (i = n((e = o), (r = a))); + }; + })(t, r), + ).on("end.style." + t, lo(t)) + : "function" == typeof n + ? this.styleTween( + t, + (function (t, n, e) { + var r, i, o; + return function () { + var a = _n(this, t), + u = e(this), + c = u + ""; + return ( + null == u && + (this.style.removeProperty(t), (c = u = _n(this, t))), + a === c + ? null + : a === r && c === i + ? o + : ((i = c), (o = n((r = a), u))) + ); + }; + })(t, r, Zi(this, "style." + t, n)), + ).each( + (function (t, n) { + var e, + r, + i, + o, + a = "style." + n, + u = "end." + a; + return function () { + var c = Hi(this, t), + f = c.on, + s = null == c.value[a] ? o || (o = lo(n)) : void 0; + ((f === e && i === s) || (r = (e = f).copy()).on(u, (i = s)), + (c.on = r)); + }; + })(this._id, t), + ) + : this.styleTween( + t, + (function (t, n, e) { + var r, + i, + o = e + ""; + return function () { + var a = _n(this, t); + return a === o ? null : a === r ? i : (i = n((r = a), e)); + }; + })(t, r, n), + e, + ).on("end.style." + t, null); + }, + styleTween: function (t, n, e) { + var r = "style." + (t += ""); + if (arguments.length < 2) return (r = this.tween(r)) && r._value; + if (null == n) return this.tween(r, null); + if ("function" != typeof n) throw new Error(); + return this.tween( + r, + (function (t, n, e) { + var r, i; + function o() { + var o = n.apply(this, arguments); + return ( + o !== i && + (r = + (i = o) && + (function (t, n, e) { + return function (r) { + this.style.setProperty(t, n.call(this, r), e); + }; + })(t, o, e)), + r + ); + } + return ((o._value = n), o); + })(t, n, null == e ? "" : e), + ); + }, + text: function (t) { + return this.tween( + "text", + "function" == typeof t + ? (function (t) { + return function () { + var n = t(this); + this.textContent = null == n ? "" : n; + }; + })(Zi(this, "text", t)) + : (function (t) { + return function () { + this.textContent = t; + }; + })(null == t ? "" : t + ""), + ); + }, + textTween: function (t) { + var n = "text"; + if (arguments.length < 1) return (n = this.tween(n)) && n._value; + if (null == t) return this.tween(n, null); + if ("function" != typeof t) throw new Error(); + return this.tween( + n, + (function (t) { + var n, e; + function r() { + var r = t.apply(this, arguments); + return ( + r !== e && + (n = + (e = r) && + (function (t) { + return function (n) { + this.textContent = t.call(this, n); + }; + })(r)), + n + ); + } + return ((r._value = t), r); + })(t), + ); + }, + remove: function () { + return this.on( + "end.remove", + (function (t) { + return function () { + var n = this.parentNode; + for (var e in this.__transition) if (+e !== t) return; + n && n.removeChild(this); + }; + })(this._id), + ); + }, + tween: function (t, n) { + var e = this._id; + if (((t += ""), arguments.length < 2)) { + for ( + var r, i = Xi(this.node(), e).tween, o = 0, a = i.length; + o < a; + ++o + ) + if ((r = i[o]).name === t) return r.value; + return null; + } + return this.each((null == n ? Vi : Wi)(e, t, n)); + }, + delay: function (t) { + var n = this._id; + return arguments.length + ? this.each(("function" == typeof t ? ao : uo)(n, t)) + : Xi(this.node(), n).delay; + }, + duration: function (t) { + var n = this._id; + return arguments.length + ? this.each(("function" == typeof t ? co : fo)(n, t)) + : Xi(this.node(), n).duration; + }, + ease: function (t) { + var n = this._id; + return arguments.length + ? this.each( + (function (t, n) { + if ("function" != typeof n) throw new Error(); + return function () { + Hi(this, t).ease = n; + }; + })(n, t), + ) + : Xi(this.node(), n).ease; + }, + easeVarying: function (t) { + if ("function" != typeof t) throw new Error(); + return this.each( + (function (t, n) { + return function () { + var e = n.apply(this, arguments); + if ("function" != typeof e) throw new Error(); + Hi(this, t).ease = e; + }; + })(this._id, t), + ); + }, + end: function () { + var t, + n, + e = this, + r = e._id, + i = e.size(); + return new Promise(function (o, a) { + var u = { value: a }, + c = { + value: function () { + 0 == --i && o(); + }, + }; + (e.each(function () { + var e = Hi(this, r), + i = e.on; + (i !== t && + ((n = (t = i).copy())._.cancel.push(u), + n._.interrupt.push(u), + n._.end.push(c)), + (e.on = n)); + }), + 0 === i && o()); + }); + }, + [Symbol.iterator]: vo[Symbol.iterator], + }; + function _o(t) { + return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; + } + function bo(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; + } + var mo = (function t(n) { + function e(t) { + return Math.pow(t, n); + } + return ((n = +n), (e.exponent = t), e); + })(3), + xo = (function t(n) { + function e(t) { + return 1 - Math.pow(1 - t, n); + } + return ((n = +n), (e.exponent = t), e); + })(3), + wo = (function t(n) { + function e(t) { + return ((t *= 2) <= 1 ? Math.pow(t, n) : 2 - Math.pow(2 - t, n)) / 2; + } + return ((n = +n), (e.exponent = t), e); + })(3), + Mo = Math.PI, + To = Mo / 2; + function Ao(t) { + return (1 - Math.cos(Mo * t)) / 2; + } + function So(t) { + return 1.0009775171065494 * (Math.pow(2, -10 * t) - 0.0009765625); + } + function Eo(t) { + return ((t *= 2) <= 1 ? So(1 - t) : 2 - So(t - 1)) / 2; + } + function No(t) { + return ( + ((t *= 2) <= 1 + ? 1 - Math.sqrt(1 - t * t) + : Math.sqrt(1 - (t -= 2) * t) + 1) / 2 + ); + } + var ko = 4 / 11, + Co = 6 / 11, + Po = 8 / 11, + zo = 3 / 4, + $o = 9 / 11, + Do = 10 / 11, + Ro = 15 / 16, + Fo = 21 / 22, + qo = 63 / 64, + Uo = 1 / ko / ko; + function Io(t) { + return (t = +t) < ko + ? Uo * t * t + : t < Po + ? Uo * (t -= Co) * t + zo + : t < Do + ? Uo * (t -= $o) * t + Ro + : Uo * (t -= Fo) * t + qo; + } + var Oo = 1.70158, + Bo = (function t(n) { + function e(t) { + return (t = +t) * t * (n * (t - 1) + t); + } + return ((n = +n), (e.overshoot = t), e); + })(Oo), + Yo = (function t(n) { + function e(t) { + return --t * t * ((t + 1) * n + t) + 1; + } + return ((n = +n), (e.overshoot = t), e); + })(Oo), + Lo = (function t(n) { + function e(t) { + return ( + ((t *= 2) < 1 + ? t * t * ((n + 1) * t - n) + : (t -= 2) * t * ((n + 1) * t + n) + 2) / 2 + ); + } + return ((n = +n), (e.overshoot = t), e); + })(Oo), + jo = 2 * Math.PI, + Ho = (function t(n, e) { + var r = Math.asin(1 / (n = Math.max(1, n))) * (e /= jo); + function i(t) { + return n * So(-(--t)) * Math.sin((r - t) / e); + } + return ( + (i.amplitude = function (n) { + return t(n, e * jo); + }), + (i.period = function (e) { + return t(n, e); + }), + i + ); + })(1, 0.3), + Xo = (function t(n, e) { + var r = Math.asin(1 / (n = Math.max(1, n))) * (e /= jo); + function i(t) { + return 1 - n * So((t = +t)) * Math.sin((t + r) / e); + } + return ( + (i.amplitude = function (n) { + return t(n, e * jo); + }), + (i.period = function (e) { + return t(n, e); + }), + i + ); + })(1, 0.3), + Go = (function t(n, e) { + var r = Math.asin(1 / (n = Math.max(1, n))) * (e /= jo); + function i(t) { + return ( + ((t = 2 * t - 1) < 0 + ? n * So(-t) * Math.sin((r - t) / e) + : 2 - n * So(t) * Math.sin((r + t) / e)) / 2 + ); + } + return ( + (i.amplitude = function (n) { + return t(n, e * jo); + }), + (i.period = function (e) { + return t(n, e); + }), + i + ); + })(1, 0.3), + Vo = { time: null, delay: 0, duration: 250, ease: bo }; + function Wo(t, n) { + for (var e; !(e = t.__transition) || !(e = e[n]); ) + if (!(t = t.parentNode)) throw new Error(`transition ${n} not found`); + return e; + } + ((Wn.prototype.interrupt = function (t) { + return this.each(function () { + Gi(this, t); + }); + }), + (Wn.prototype.transition = function (t) { + var n, e; + t instanceof po + ? ((n = t._id), (t = t._name)) + : ((n = yo()), ((e = Vo).time = Ai()), (t = null == t ? null : t + "")); + for (var r = this._groups, i = r.length, o = 0; o < i; ++o) + for (var a, u = r[o], c = u.length, f = 0; f < c; ++f) + (a = u[f]) && Li(a, t, n, f, u, e || Wo(a, n)); + return new po(r, this._parents, t, n); + })); + var Zo = [null]; + var Ko = (t) => () => t; + function Qo( + t, + { sourceEvent: n, target: e, selection: r, mode: i, dispatch: o }, + ) { + Object.defineProperties(this, { + type: { value: t, enumerable: !0, configurable: !0 }, + sourceEvent: { value: n, enumerable: !0, configurable: !0 }, + target: { value: e, enumerable: !0, configurable: !0 }, + selection: { value: r, enumerable: !0, configurable: !0 }, + mode: { value: i, enumerable: !0, configurable: !0 }, + _: { value: o }, + }); + } + function Jo(t) { + (t.preventDefault(), t.stopImmediatePropagation()); + } + var ta = { name: "drag" }, + na = { name: "space" }, + ea = { name: "handle" }, + ra = { name: "center" }; + const { abs: ia, max: oa, min: aa } = Math; + function ua(t) { + return [+t[0], +t[1]]; + } + function ca(t) { + return [ua(t[0]), ua(t[1])]; + } + var fa = { + name: "x", + handles: ["w", "e"].map(va), + input: function (t, n) { + return null == t + ? null + : [ + [+t[0], n[0][1]], + [+t[1], n[1][1]], + ]; + }, + output: function (t) { + return t && [t[0][0], t[1][0]]; + }, + }, + sa = { + name: "y", + handles: ["n", "s"].map(va), + input: function (t, n) { + return null == t + ? null + : [ + [n[0][0], +t[0]], + [n[1][0], +t[1]], + ]; + }, + output: function (t) { + return t && [t[0][1], t[1][1]]; + }, + }, + la = { + name: "xy", + handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(va), + input: function (t) { + return null == t ? null : ca(t); + }, + output: function (t) { + return t; + }, + }, + ha = { + overlay: "crosshair", + selection: "move", + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize", + }, + da = { e: "w", w: "e", nw: "ne", ne: "nw", se: "sw", sw: "se" }, + pa = { n: "s", s: "n", nw: "sw", ne: "se", se: "ne", sw: "nw" }, + ga = { + overlay: 1, + selection: 1, + n: null, + e: 1, + s: null, + w: -1, + nw: -1, + ne: 1, + se: 1, + sw: -1, + }, + ya = { + overlay: 1, + selection: 1, + n: -1, + e: null, + s: 1, + w: null, + nw: -1, + ne: -1, + se: 1, + sw: 1, + }; + function va(t) { + return { type: t }; + } + function _a(t) { + return !t.ctrlKey && !t.button; + } + function ba() { + var t = this.ownerSVGElement || this; + return t.hasAttribute("viewBox") + ? [ + [(t = t.viewBox.baseVal).x, t.y], + [t.x + t.width, t.y + t.height], + ] + : [ + [0, 0], + [t.width.baseVal.value, t.height.baseVal.value], + ]; + } + function ma() { + return navigator.maxTouchPoints || "ontouchstart" in this; + } + function xa(t) { + for (; !t.__brush; ) if (!(t = t.parentNode)) return; + return t.__brush; + } + function wa(t) { + var n, + e = ba, + r = _a, + i = ma, + o = !0, + a = $t("start", "brush", "end"), + u = 6; + function c(n) { + var e = n + .property("__brush", g) + .selectAll(".overlay") + .data([va("overlay")]); + (e + .enter() + .append("rect") + .attr("class", "overlay") + .attr("pointer-events", "all") + .attr("cursor", ha.overlay) + .merge(e) + .each(function () { + var t = xa(this).extent; + Zn(this) + .attr("x", t[0][0]) + .attr("y", t[0][1]) + .attr("width", t[1][0] - t[0][0]) + .attr("height", t[1][1] - t[0][1]); + }), + n + .selectAll(".selection") + .data([va("selection")]) + .enter() + .append("rect") + .attr("class", "selection") + .attr("cursor", ha.selection) + .attr("fill", "#777") + .attr("fill-opacity", 0.3) + .attr("stroke", "#fff") + .attr("shape-rendering", "crispEdges")); + var r = n.selectAll(".handle").data(t.handles, function (t) { + return t.type; + }); + (r.exit().remove(), + r + .enter() + .append("rect") + .attr("class", function (t) { + return "handle handle--" + t.type; + }) + .attr("cursor", function (t) { + return ha[t.type]; + }), + n + .each(f) + .attr("fill", "none") + .attr("pointer-events", "all") + .on("mousedown.brush", h) + .filter(i) + .on("touchstart.brush", h) + .on("touchmove.brush", d) + .on("touchend.brush touchcancel.brush", p) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")); + } + function f() { + var t = Zn(this), + n = xa(this).selection; + n + ? (t + .selectAll(".selection") + .style("display", null) + .attr("x", n[0][0]) + .attr("y", n[0][1]) + .attr("width", n[1][0] - n[0][0]) + .attr("height", n[1][1] - n[0][1]), + t + .selectAll(".handle") + .style("display", null) + .attr("x", function (t) { + return "e" === t.type[t.type.length - 1] + ? n[1][0] - u / 2 + : n[0][0] - u / 2; + }) + .attr("y", function (t) { + return "s" === t.type[0] ? n[1][1] - u / 2 : n[0][1] - u / 2; + }) + .attr("width", function (t) { + return "n" === t.type || "s" === t.type + ? n[1][0] - n[0][0] + u + : u; + }) + .attr("height", function (t) { + return "e" === t.type || "w" === t.type + ? n[1][1] - n[0][1] + u + : u; + })) + : t + .selectAll(".selection,.handle") + .style("display", "none") + .attr("x", null) + .attr("y", null) + .attr("width", null) + .attr("height", null); + } + function s(t, n, e) { + var r = t.__brush.emitter; + return !r || (e && r.clean) ? new l(t, n, e) : r; + } + function l(t, n, e) { + ((this.that = t), + (this.args = n), + (this.state = t.__brush), + (this.active = 0), + (this.clean = e)); + } + function h(e) { + if ((!n || e.touches) && r.apply(this, arguments)) { + var i, + a, + u, + c, + l, + h, + d, + p, + g, + y, + v, + _ = this, + b = e.target.__data__.type, + m = + "selection" === (o && e.metaKey ? (b = "overlay") : b) + ? ta + : o && e.altKey + ? ra + : ea, + x = t === sa ? null : ga[b], + w = t === fa ? null : ya[b], + M = xa(_), + T = M.extent, + A = M.selection, + S = T[0][0], + E = T[0][1], + N = T[1][0], + k = T[1][1], + C = 0, + P = 0, + z = x && w && o && e.shiftKey, + $ = Array.from(e.touches || [e], (t) => { + const n = t.identifier; + return (((t = ne(t, _)).point0 = t.slice()), (t.identifier = n), t); + }); + Gi(_); + var D = s(_, arguments, !0).beforestart(); + if ("overlay" === b) { + A && (g = !0); + const n = [$[0], $[1] || $[0]]; + ((M.selection = A = + [ + [ + (i = t === sa ? S : aa(n[0][0], n[1][0])), + (u = t === fa ? E : aa(n[0][1], n[1][1])), + ], + [ + (l = t === sa ? N : oa(n[0][0], n[1][0])), + (d = t === fa ? k : oa(n[0][1], n[1][1])), + ], + ]), + $.length > 1 && I(e)); + } else ((i = A[0][0]), (u = A[0][1]), (l = A[1][0]), (d = A[1][1])); + ((a = i), (c = u), (h = l), (p = d)); + var R = Zn(_).attr("pointer-events", "none"), + F = R.selectAll(".overlay").attr("cursor", ha[b]); + if (e.touches) ((D.moved = U), (D.ended = O)); + else { + var q = Zn(e.view) + .on("mousemove.brush", U, !0) + .on("mouseup.brush", O, !0); + (o && + q + .on( + "keydown.brush", + function (t) { + switch (t.keyCode) { + case 16: + z = x && w; + break; + case 18: + m === ea && + (x && ((l = h - C * x), (i = a + C * x)), + w && ((d = p - P * w), (u = c + P * w)), + (m = ra), + I(t)); + break; + case 32: + (m !== ea && m !== ra) || + (x < 0 ? (l = h - C) : x > 0 && (i = a - C), + w < 0 ? (d = p - P) : w > 0 && (u = c - P), + (m = na), + F.attr("cursor", ha.selection), + I(t)); + break; + default: + return; + } + Jo(t); + }, + !0, + ) + .on( + "keyup.brush", + function (t) { + switch (t.keyCode) { + case 16: + z && ((y = v = z = !1), I(t)); + break; + case 18: + m === ra && + (x < 0 ? (l = h) : x > 0 && (i = a), + w < 0 ? (d = p) : w > 0 && (u = c), + (m = ea), + I(t)); + break; + case 32: + m === na && + (t.altKey + ? (x && ((l = h - C * x), (i = a + C * x)), + w && ((d = p - P * w), (u = c + P * w)), + (m = ra)) + : (x < 0 ? (l = h) : x > 0 && (i = a), + w < 0 ? (d = p) : w > 0 && (u = c), + (m = ea)), + F.attr("cursor", ha[b]), + I(t)); + break; + default: + return; + } + Jo(t); + }, + !0, + ), + ae(e.view)); + } + (f.call(_), D.start(e, m.name)); + } + function U(t) { + for (const n of t.changedTouches || [t]) + for (const t of $) + t.identifier === n.identifier && (t.cur = ne(n, _)); + if (z && !y && !v && 1 === $.length) { + const t = $[0]; + ia(t.cur[0] - t[0]) > ia(t.cur[1] - t[1]) ? (v = !0) : (y = !0); + } + for (const t of $) t.cur && ((t[0] = t.cur[0]), (t[1] = t.cur[1])); + ((g = !0), Jo(t), I(t)); + } + function I(t) { + const n = $[0], + e = n.point0; + var r; + switch (((C = n[0] - e[0]), (P = n[1] - e[1]), m)) { + case na: + case ta: + (x && ((C = oa(S - i, aa(N - l, C))), (a = i + C), (h = l + C)), + w && ((P = oa(E - u, aa(k - d, P))), (c = u + P), (p = d + P))); + break; + case ea: + $[1] + ? (x && + ((a = oa(S, aa(N, $[0][0]))), + (h = oa(S, aa(N, $[1][0]))), + (x = 1)), + w && + ((c = oa(E, aa(k, $[0][1]))), + (p = oa(E, aa(k, $[1][1]))), + (w = 1))) + : (x < 0 + ? ((C = oa(S - i, aa(N - i, C))), (a = i + C), (h = l)) + : x > 0 && + ((C = oa(S - l, aa(N - l, C))), (a = i), (h = l + C)), + w < 0 + ? ((P = oa(E - u, aa(k - u, P))), (c = u + P), (p = d)) + : w > 0 && + ((P = oa(E - d, aa(k - d, P))), (c = u), (p = d + P))); + break; + case ra: + (x && + ((a = oa(S, aa(N, i - C * x))), (h = oa(S, aa(N, l + C * x)))), + w && + ((c = oa(E, aa(k, u - P * w))), (p = oa(E, aa(k, d + P * w))))); + } + (h < a && + ((x *= -1), + (r = i), + (i = l), + (l = r), + (r = a), + (a = h), + (h = r), + b in da && F.attr("cursor", ha[(b = da[b])])), + p < c && + ((w *= -1), + (r = u), + (u = d), + (d = r), + (r = c), + (c = p), + (p = r), + b in pa && F.attr("cursor", ha[(b = pa[b])])), + M.selection && (A = M.selection), + y && ((a = A[0][0]), (h = A[1][0])), + v && ((c = A[0][1]), (p = A[1][1])), + (A[0][0] === a && A[0][1] === c && A[1][0] === h && A[1][1] === p) || + ((M.selection = [ + [a, c], + [h, p], + ]), + f.call(_), + D.brush(t, m.name))); + } + function O(t) { + if ( + ((function (t) { + t.stopImmediatePropagation(); + })(t), + t.touches) + ) { + if (t.touches.length) return; + (n && clearTimeout(n), + (n = setTimeout(function () { + n = null; + }, 500))); + } else + (ue(t.view, g), + q.on( + "keydown.brush keyup.brush mousemove.brush mouseup.brush", + null, + )); + (R.attr("pointer-events", "all"), + F.attr("cursor", ha.overlay), + M.selection && (A = M.selection), + (function (t) { + return t[0][0] === t[1][0] || t[0][1] === t[1][1]; + })(A) && ((M.selection = null), f.call(_)), + D.end(t, m.name)); + } + } + function d(t) { + s(this, arguments).moved(t); + } + function p(t) { + s(this, arguments).ended(t); + } + function g() { + var n = this.__brush || { selection: null }; + return ((n.extent = ca(e.apply(this, arguments))), (n.dim = t), n); + } + return ( + (c.move = function (n, e, r) { + n.tween + ? n + .on("start.brush", function (t) { + s(this, arguments).beforestart().start(t); + }) + .on("interrupt.brush end.brush", function (t) { + s(this, arguments).end(t); + }) + .tween("brush", function () { + var n = this, + r = n.__brush, + i = s(n, arguments), + o = r.selection, + a = t.input( + "function" == typeof e ? e.apply(this, arguments) : e, + r.extent, + ), + u = Gr(o, a); + function c(t) { + ((r.selection = 1 === t && null === a ? null : u(t)), + f.call(n), + i.brush()); + } + return null !== o && null !== a ? c : c(1); + }) + : n.each(function () { + var n = this, + i = arguments, + o = n.__brush, + a = t.input( + "function" == typeof e ? e.apply(n, i) : e, + o.extent, + ), + u = s(n, i).beforestart(); + (Gi(n), + (o.selection = null === a ? null : a), + f.call(n), + u.start(r).brush(r).end(r)); + }); + }), + (c.clear = function (t, n) { + c.move(t, null, n); + }), + (l.prototype = { + beforestart: function () { + return ( + 1 == ++this.active && + ((this.state.emitter = this), (this.starting = !0)), + this + ); + }, + start: function (t, n) { + return ( + this.starting + ? ((this.starting = !1), this.emit("start", t, n)) + : this.emit("brush", t), + this + ); + }, + brush: function (t, n) { + return (this.emit("brush", t, n), this); + }, + end: function (t, n) { + return ( + 0 == --this.active && + (delete this.state.emitter, this.emit("end", t, n)), + this + ); + }, + emit: function (n, e, r) { + var i = Zn(this.that).datum(); + a.call( + n, + this.that, + new Qo(n, { + sourceEvent: e, + target: c, + selection: t.output(this.state.selection), + mode: r, + dispatch: a, + }), + i, + ); + }, + }), + (c.extent = function (t) { + return arguments.length + ? ((e = "function" == typeof t ? t : Ko(ca(t))), c) + : e; + }), + (c.filter = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : Ko(!!t)), c) + : r; + }), + (c.touchable = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : Ko(!!t)), c) + : i; + }), + (c.handleSize = function (t) { + return arguments.length ? ((u = +t), c) : u; + }), + (c.keyModifiers = function (t) { + return arguments.length ? ((o = !!t), c) : o; + }), + (c.on = function () { + var t = a.on.apply(a, arguments); + return t === a ? c : t; + }), + c + ); + } + var Ma = Math.abs, + Ta = Math.cos, + Aa = Math.sin, + Sa = Math.PI, + Ea = Sa / 2, + Na = 2 * Sa, + ka = Math.max, + Ca = 1e-12; + function Pa(t, n) { + return Array.from({ length: n - t }, (n, e) => t + e); + } + function za(t, n) { + var e = 0, + r = null, + i = null, + o = null; + function a(a) { + var u, + c = a.length, + f = new Array(c), + s = Pa(0, c), + l = new Array(c * c), + h = new Array(c), + d = 0; + a = Float64Array.from( + { length: c * c }, + n ? (t, n) => a[n % c][(n / c) | 0] : (t, n) => a[(n / c) | 0][n % c], + ); + for (let n = 0; n < c; ++n) { + let e = 0; + for (let r = 0; r < c; ++r) e += a[n * c + r] + t * a[r * c + n]; + d += f[n] = e; + } + u = (d = ka(0, Na - e * c) / d) ? e : Na / c; + { + let n = 0; + r && s.sort((t, n) => r(f[t], f[n])); + for (const e of s) { + const r = n; + if (t) { + const t = Pa(1 + ~c, c).filter((t) => + t < 0 ? a[~t * c + e] : a[e * c + t], + ); + i && + t.sort((t, n) => + i( + t < 0 ? -a[~t * c + e] : a[e * c + t], + n < 0 ? -a[~n * c + e] : a[e * c + n], + ), + ); + for (const r of t) + if (r < 0) { + ( + l[~r * c + e] || + (l[~r * c + e] = { source: null, target: null }) + ).target = { + index: e, + startAngle: n, + endAngle: (n += a[~r * c + e] * d), + value: a[~r * c + e], + }; + } else { + ( + l[e * c + r] || + (l[e * c + r] = { source: null, target: null }) + ).source = { + index: e, + startAngle: n, + endAngle: (n += a[e * c + r] * d), + value: a[e * c + r], + }; + } + h[e] = { index: e, startAngle: r, endAngle: n, value: f[e] }; + } else { + const t = Pa(0, c).filter((t) => a[e * c + t] || a[t * c + e]); + i && t.sort((t, n) => i(a[e * c + t], a[e * c + n])); + for (const r of t) { + let t; + if ( + (e < r + ? ((t = + l[e * c + r] || + (l[e * c + r] = { source: null, target: null })), + (t.source = { + index: e, + startAngle: n, + endAngle: (n += a[e * c + r] * d), + value: a[e * c + r], + })) + : ((t = + l[r * c + e] || + (l[r * c + e] = { source: null, target: null })), + (t.target = { + index: e, + startAngle: n, + endAngle: (n += a[e * c + r] * d), + value: a[e * c + r], + }), + e === r && (t.source = t.target)), + t.source && t.target && t.source.value < t.target.value) + ) { + const n = t.source; + ((t.source = t.target), (t.target = n)); + } + } + h[e] = { index: e, startAngle: r, endAngle: n, value: f[e] }; + } + n += u; + } + } + return (((l = Object.values(l)).groups = h), o ? l.sort(o) : l); + } + return ( + (a.padAngle = function (t) { + return arguments.length ? ((e = ka(0, t)), a) : e; + }), + (a.sortGroups = function (t) { + return arguments.length ? ((r = t), a) : r; + }), + (a.sortSubgroups = function (t) { + return arguments.length ? ((i = t), a) : i; + }), + (a.sortChords = function (t) { + return arguments.length + ? (null == t + ? (o = null) + : (((n = t), + (o = function (t, e) { + return n( + t.source.value + t.target.value, + e.source.value + e.target.value, + ); + }))._ = t), + a) + : o && o._; + var n; + }), + a + ); + } + const $a = Math.PI, + Da = 2 * $a, + Ra = 1e-6, + Fa = Da - Ra; + function qa(t) { + this._ += t[0]; + for (let n = 1, e = t.length; n < e; ++n) this._ += arguments[n] + t[n]; + } + let Ua = class { + constructor(t) { + ((this._x0 = this._y0 = this._x1 = this._y1 = null), + (this._ = ""), + (this._append = + null == t + ? qa + : (function (t) { + let n = Math.floor(t); + if (!(n >= 0)) throw new Error(`invalid digits: ${t}`); + if (n > 15) return qa; + const e = 10 ** n; + return function (t) { + this._ += t[0]; + for (let n = 1, r = t.length; n < r; ++n) + this._ += Math.round(arguments[n] * e) / e + t[n]; + }; + })(t))); + } + moveTo(t, n) { + this + ._append`M${(this._x0 = this._x1 = +t)},${(this._y0 = this._y1 = +n)}`; + } + closePath() { + null !== this._x1 && + ((this._x1 = this._x0), (this._y1 = this._y0), this._append`Z`); + } + lineTo(t, n) { + this._append`L${(this._x1 = +t)},${(this._y1 = +n)}`; + } + quadraticCurveTo(t, n, e, r) { + this._append`Q${+t},${+n},${(this._x1 = +e)},${(this._y1 = +r)}`; + } + bezierCurveTo(t, n, e, r, i, o) { + this + ._append`C${+t},${+n},${+e},${+r},${(this._x1 = +i)},${(this._y1 = +o)}`; + } + arcTo(t, n, e, r, i) { + if (((t = +t), (n = +n), (e = +e), (r = +r), (i = +i) < 0)) + throw new Error(`negative radius: ${i}`); + let o = this._x1, + a = this._y1, + u = e - t, + c = r - n, + f = o - t, + s = a - n, + l = f * f + s * s; + if (null === this._x1) this._append`M${(this._x1 = t)},${(this._y1 = n)}`; + else if (l > Ra) + if (Math.abs(s * u - c * f) > Ra && i) { + let h = e - o, + d = r - a, + p = u * u + c * c, + g = h * h + d * d, + y = Math.sqrt(p), + v = Math.sqrt(l), + _ = i * Math.tan(($a - Math.acos((p + l - g) / (2 * y * v))) / 2), + b = _ / v, + m = _ / y; + (Math.abs(b - 1) > Ra && this._append`L${t + b * f},${n + b * s}`, + this + ._append`A${i},${i},0,0,${+(s * h > f * d)},${(this._x1 = t + m * u)},${(this._y1 = n + m * c)}`); + } else this._append`L${(this._x1 = t)},${(this._y1 = n)}`; + else; + } + arc(t, n, e, r, i, o) { + if (((t = +t), (n = +n), (o = !!o), (e = +e) < 0)) + throw new Error(`negative radius: ${e}`); + let a = e * Math.cos(r), + u = e * Math.sin(r), + c = t + a, + f = n + u, + s = 1 ^ o, + l = o ? r - i : i - r; + (null === this._x1 + ? this._append`M${c},${f}` + : (Math.abs(this._x1 - c) > Ra || Math.abs(this._y1 - f) > Ra) && + this._append`L${c},${f}`, + e && + (l < 0 && (l = (l % Da) + Da), + l > Fa + ? this + ._append`A${e},${e},0,1,${s},${t - a},${n - u}A${e},${e},0,1,${s},${(this._x1 = c)},${(this._y1 = f)}` + : l > Ra && + this + ._append`A${e},${e},0,${+(l >= $a)},${s},${(this._x1 = t + e * Math.cos(i))},${(this._y1 = n + e * Math.sin(i))}`)); + } + rect(t, n, e, r) { + this + ._append`M${(this._x0 = this._x1 = +t)},${(this._y0 = this._y1 = +n)}h${(e = +e)}v${+r}h${-e}Z`; + } + toString() { + return this._; + } + }; + function Ia() { + return new Ua(); + } + Ia.prototype = Ua.prototype; + var Oa = Array.prototype.slice; + function Ba(t) { + return function () { + return t; + }; + } + function Ya(t) { + return t.source; + } + function La(t) { + return t.target; + } + function ja(t) { + return t.radius; + } + function Ha(t) { + return t.startAngle; + } + function Xa(t) { + return t.endAngle; + } + function Ga() { + return 0; + } + function Va() { + return 10; + } + function Wa(t) { + var n = Ya, + e = La, + r = ja, + i = ja, + o = Ha, + a = Xa, + u = Ga, + c = null; + function f() { + var f, + s = n.apply(this, arguments), + l = e.apply(this, arguments), + h = u.apply(this, arguments) / 2, + d = Oa.call(arguments), + p = +r.apply(this, ((d[0] = s), d)), + g = o.apply(this, d) - Ea, + y = a.apply(this, d) - Ea, + v = +i.apply(this, ((d[0] = l), d)), + _ = o.apply(this, d) - Ea, + b = a.apply(this, d) - Ea; + if ( + (c || (c = f = Ia()), + h > Ca && + (Ma(y - g) > 2 * h + Ca + ? y > g + ? ((g += h), (y -= h)) + : ((g -= h), (y += h)) + : (g = y = (g + y) / 2), + Ma(b - _) > 2 * h + Ca + ? b > _ + ? ((_ += h), (b -= h)) + : ((_ -= h), (b += h)) + : (_ = b = (_ + b) / 2)), + c.moveTo(p * Ta(g), p * Aa(g)), + c.arc(0, 0, p, g, y), + g !== _ || y !== b) + ) + if (t) { + var m = v - +t.apply(this, arguments), + x = (_ + b) / 2; + (c.quadraticCurveTo(0, 0, m * Ta(_), m * Aa(_)), + c.lineTo(v * Ta(x), v * Aa(x)), + c.lineTo(m * Ta(b), m * Aa(b))); + } else + (c.quadraticCurveTo(0, 0, v * Ta(_), v * Aa(_)), + c.arc(0, 0, v, _, b)); + if ((c.quadraticCurveTo(0, 0, p * Ta(g), p * Aa(g)), c.closePath(), f)) + return ((c = null), f + "" || null); + } + return ( + t && + (f.headRadius = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : Ba(+n)), f) + : t; + }), + (f.radius = function (t) { + return arguments.length + ? ((r = i = "function" == typeof t ? t : Ba(+t)), f) + : r; + }), + (f.sourceRadius = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : Ba(+t)), f) + : r; + }), + (f.targetRadius = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : Ba(+t)), f) + : i; + }), + (f.startAngle = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : Ba(+t)), f) + : o; + }), + (f.endAngle = function (t) { + return arguments.length + ? ((a = "function" == typeof t ? t : Ba(+t)), f) + : a; + }), + (f.padAngle = function (t) { + return arguments.length + ? ((u = "function" == typeof t ? t : Ba(+t)), f) + : u; + }), + (f.source = function (t) { + return arguments.length ? ((n = t), f) : n; + }), + (f.target = function (t) { + return arguments.length ? ((e = t), f) : e; + }), + (f.context = function (t) { + return arguments.length ? ((c = null == t ? null : t), f) : c; + }), + f + ); + } + var Za = Array.prototype.slice; + function Ka(t, n) { + return t - n; + } + var Qa = (t) => () => t; + function Ja(t, n) { + for (var e, r = -1, i = n.length; ++r < i; ) + if ((e = tu(t, n[r]))) return e; + return 0; + } + function tu(t, n) { + for ( + var e = n[0], r = n[1], i = -1, o = 0, a = t.length, u = a - 1; + o < a; + u = o++ + ) { + var c = t[o], + f = c[0], + s = c[1], + l = t[u], + h = l[0], + d = l[1]; + if (nu(c, l, n)) return 0; + s > r != d > r && e < ((h - f) * (r - s)) / (d - s) + f && (i = -i); + } + return i; + } + function nu(t, n, e) { + var r, i, o, a; + return ( + (function (t, n, e) { + return (n[0] - t[0]) * (e[1] - t[1]) == (e[0] - t[0]) * (n[1] - t[1]); + })(t, n, e) && + ((i = t[(r = +(t[0] === n[0]))]), + (o = e[r]), + (a = n[r]), + (i <= o && o <= a) || (a <= o && o <= i)) + ); + } + function eu() {} + var ru = [ + [], + [ + [ + [1, 1.5], + [0.5, 1], + ], + ], + [ + [ + [1.5, 1], + [1, 1.5], + ], + ], + [ + [ + [1.5, 1], + [0.5, 1], + ], + ], + [ + [ + [1, 0.5], + [1.5, 1], + ], + ], + [ + [ + [1, 1.5], + [0.5, 1], + ], + [ + [1, 0.5], + [1.5, 1], + ], + ], + [ + [ + [1, 0.5], + [1, 1.5], + ], + ], + [ + [ + [1, 0.5], + [0.5, 1], + ], + ], + [ + [ + [0.5, 1], + [1, 0.5], + ], + ], + [ + [ + [1, 1.5], + [1, 0.5], + ], + ], + [ + [ + [0.5, 1], + [1, 0.5], + ], + [ + [1.5, 1], + [1, 1.5], + ], + ], + [ + [ + [1.5, 1], + [1, 0.5], + ], + ], + [ + [ + [0.5, 1], + [1.5, 1], + ], + ], + [ + [ + [1, 1.5], + [1.5, 1], + ], + ], + [ + [ + [0.5, 1], + [1, 1.5], + ], + ], + [], + ]; + function iu() { + var t = 1, + n = 1, + e = K, + r = u; + function i(t) { + var n = e(t); + if (Array.isArray(n)) n = n.slice().sort(Ka); + else { + const e = M(t, ou); + for (n = G(...Z(e[0], e[1], n), n); n[n.length - 1] >= e[1]; ) n.pop(); + for (; n[1] < e[0]; ) n.shift(); + } + return n.map((n) => o(t, n)); + } + function o(e, i) { + const o = null == i ? NaN : +i; + if (isNaN(o)) throw new Error(`invalid value: ${i}`); + var u = [], + c = []; + return ( + (function (e, r, i) { + var o, + u, + c, + f, + s, + l, + h = new Array(), + d = new Array(); + ((o = u = -1), (f = au(e[0], r)), ru[f << 1].forEach(p)); + for (; ++o < t - 1; ) + ((c = f), (f = au(e[o + 1], r)), ru[c | (f << 1)].forEach(p)); + ru[f | 0].forEach(p); + for (; ++u < n - 1; ) { + for ( + o = -1, + f = au(e[u * t + t], r), + s = au(e[u * t], r), + ru[(f << 1) | (s << 2)].forEach(p); + ++o < t - 1; + + ) + ((c = f), + (f = au(e[u * t + t + o + 1], r)), + (l = s), + (s = au(e[u * t + o + 1], r)), + ru[c | (f << 1) | (s << 2) | (l << 3)].forEach(p)); + ru[f | (s << 3)].forEach(p); + } + ((o = -1), (s = e[u * t] >= r), ru[s << 2].forEach(p)); + for (; ++o < t - 1; ) + ((l = s), + (s = au(e[u * t + o + 1], r)), + ru[(s << 2) | (l << 3)].forEach(p)); + function p(t) { + var n, + e, + r = [t[0][0] + o, t[0][1] + u], + c = [t[1][0] + o, t[1][1] + u], + f = a(r), + s = a(c); + (n = d[f]) + ? (e = h[s]) + ? (delete d[n.end], + delete h[e.start], + n === e + ? (n.ring.push(c), i(n.ring)) + : (h[n.start] = d[e.end] = + { + start: n.start, + end: e.end, + ring: n.ring.concat(e.ring), + })) + : (delete d[n.end], n.ring.push(c), (d[(n.end = s)] = n)) + : (n = h[s]) + ? (e = d[f]) + ? (delete h[n.start], + delete d[e.end], + n === e + ? (n.ring.push(c), i(n.ring)) + : (h[e.start] = d[n.end] = + { + start: e.start, + end: n.end, + ring: e.ring.concat(n.ring), + })) + : (delete h[n.start], + n.ring.unshift(r), + (h[(n.start = f)] = n)) + : (h[f] = d[s] = { start: f, end: s, ring: [r, c] }); + } + ru[s << 3].forEach(p); + })(e, o, function (t) { + (r(t, e, o), + (function (t) { + for ( + var n = 0, + e = t.length, + r = t[e - 1][1] * t[0][0] - t[e - 1][0] * t[0][1]; + ++n < e; + + ) + r += t[n - 1][1] * t[n][0] - t[n - 1][0] * t[n][1]; + return r; + })(t) > 0 + ? u.push([t]) + : c.push(t)); + }), + c.forEach(function (t) { + for (var n, e = 0, r = u.length; e < r; ++e) + if (-1 !== Ja((n = u[e])[0], t)) return void n.push(t); + }), + { type: "MultiPolygon", value: i, coordinates: u } + ); + } + function a(n) { + return 2 * n[0] + n[1] * (t + 1) * 4; + } + function u(e, r, i) { + e.forEach(function (e) { + var o = e[0], + a = e[1], + u = 0 | o, + c = 0 | a, + f = uu(r[c * t + u]); + (o > 0 && + o < t && + u === o && + (e[0] = cu(o, uu(r[c * t + u - 1]), f, i)), + a > 0 && + a < n && + c === a && + (e[1] = cu(a, uu(r[(c - 1) * t + u]), f, i))); + }); + } + return ( + (i.contour = o), + (i.size = function (e) { + if (!arguments.length) return [t, n]; + var r = Math.floor(e[0]), + o = Math.floor(e[1]); + if (!(r >= 0 && o >= 0)) throw new Error("invalid size"); + return ((t = r), (n = o), i); + }), + (i.thresholds = function (t) { + return arguments.length + ? ((e = + "function" == typeof t + ? t + : Array.isArray(t) + ? Qa(Za.call(t)) + : Qa(t)), + i) + : e; + }), + (i.smooth = function (t) { + return arguments.length ? ((r = t ? u : eu), i) : r === u; + }), + i + ); + } + function ou(t) { + return isFinite(t) ? t : NaN; + } + function au(t, n) { + return null != t && +t >= n; + } + function uu(t) { + return null == t || isNaN((t = +t)) ? -1 / 0 : t; + } + function cu(t, n, e, r) { + const i = r - n, + o = e - n, + a = isFinite(i) || isFinite(o) ? i / o : Math.sign(i) / Math.sign(o); + return isNaN(a) ? t : t + a - 0.5; + } + function fu(t) { + return t[0]; + } + function su(t) { + return t[1]; + } + function lu() { + return 1; + } + const hu = 134217729, + du = 33306690738754706e-32; + function pu(t, n, e, r, i) { + let o, + a, + u, + c, + f = n[0], + s = r[0], + l = 0, + h = 0; + s > f == s > -f ? ((o = f), (f = n[++l])) : ((o = s), (s = r[++h])); + let d = 0; + if (l < t && h < e) + for ( + s > f == s > -f + ? ((a = f + o), (u = o - (a - f)), (f = n[++l])) + : ((a = s + o), (u = o - (a - s)), (s = r[++h])), + o = a, + 0 !== u && (i[d++] = u); + l < t && h < e; + + ) + (s > f == s > -f + ? ((a = o + f), + (c = a - o), + (u = o - (a - c) + (f - c)), + (f = n[++l])) + : ((a = o + s), + (c = a - o), + (u = o - (a - c) + (s - c)), + (s = r[++h])), + (o = a), + 0 !== u && (i[d++] = u)); + for (; l < t; ) + ((a = o + f), + (c = a - o), + (u = o - (a - c) + (f - c)), + (f = n[++l]), + (o = a), + 0 !== u && (i[d++] = u)); + for (; h < e; ) + ((a = o + s), + (c = a - o), + (u = o - (a - c) + (s - c)), + (s = r[++h]), + (o = a), + 0 !== u && (i[d++] = u)); + return ((0 === o && 0 !== d) || (i[d++] = o), d); + } + function gu(t) { + return new Float64Array(t); + } + const yu = 22204460492503146e-32, + vu = 11093356479670487e-47, + _u = gu(4), + bu = gu(8), + mu = gu(12), + xu = gu(16), + wu = gu(4); + function Mu(t, n, e, r, i, o) { + const a = (n - o) * (e - i), + u = (t - i) * (r - o), + c = a - u, + f = Math.abs(a + u); + return Math.abs(c) >= 33306690738754716e-32 * f + ? c + : -(function (t, n, e, r, i, o, a) { + let u, c, f, s, l, h, d, p, g, y, v, _, b, m, x, w, M, T; + const A = t - i, + S = e - i, + E = n - o, + N = r - o; + ((m = A * N), + (h = hu * A), + (d = h - (h - A)), + (p = A - d), + (h = hu * N), + (g = h - (h - N)), + (y = N - g), + (x = p * y - (m - d * g - p * g - d * y)), + (w = E * S), + (h = hu * E), + (d = h - (h - E)), + (p = E - d), + (h = hu * S), + (g = h - (h - S)), + (y = S - g), + (M = p * y - (w - d * g - p * g - d * y)), + (v = x - M), + (l = x - v), + (_u[0] = x - (v + l) + (l - M)), + (_ = m + v), + (l = _ - m), + (b = m - (_ - l) + (v - l)), + (v = b - w), + (l = b - v), + (_u[1] = b - (v + l) + (l - w)), + (T = _ + v), + (l = T - _), + (_u[2] = _ - (T - l) + (v - l)), + (_u[3] = T)); + let k = (function (t, n) { + let e = n[0]; + for (let r = 1; r < t; r++) e += n[r]; + return e; + })(4, _u), + C = yu * a; + if (k >= C || -k >= C) return k; + if ( + ((l = t - A), + (u = t - (A + l) + (l - i)), + (l = e - S), + (f = e - (S + l) + (l - i)), + (l = n - E), + (c = n - (E + l) + (l - o)), + (l = r - N), + (s = r - (N + l) + (l - o)), + 0 === u && 0 === c && 0 === f && 0 === s) + ) + return k; + if ( + ((C = vu * a + du * Math.abs(k)), + (k += A * s + N * u - (E * f + S * c)), + k >= C || -k >= C) + ) + return k; + ((m = u * N), + (h = hu * u), + (d = h - (h - u)), + (p = u - d), + (h = hu * N), + (g = h - (h - N)), + (y = N - g), + (x = p * y - (m - d * g - p * g - d * y)), + (w = c * S), + (h = hu * c), + (d = h - (h - c)), + (p = c - d), + (h = hu * S), + (g = h - (h - S)), + (y = S - g), + (M = p * y - (w - d * g - p * g - d * y)), + (v = x - M), + (l = x - v), + (wu[0] = x - (v + l) + (l - M)), + (_ = m + v), + (l = _ - m), + (b = m - (_ - l) + (v - l)), + (v = b - w), + (l = b - v), + (wu[1] = b - (v + l) + (l - w)), + (T = _ + v), + (l = T - _), + (wu[2] = _ - (T - l) + (v - l)), + (wu[3] = T)); + const P = pu(4, _u, 4, wu, bu); + ((m = A * s), + (h = hu * A), + (d = h - (h - A)), + (p = A - d), + (h = hu * s), + (g = h - (h - s)), + (y = s - g), + (x = p * y - (m - d * g - p * g - d * y)), + (w = E * f), + (h = hu * E), + (d = h - (h - E)), + (p = E - d), + (h = hu * f), + (g = h - (h - f)), + (y = f - g), + (M = p * y - (w - d * g - p * g - d * y)), + (v = x - M), + (l = x - v), + (wu[0] = x - (v + l) + (l - M)), + (_ = m + v), + (l = _ - m), + (b = m - (_ - l) + (v - l)), + (v = b - w), + (l = b - v), + (wu[1] = b - (v + l) + (l - w)), + (T = _ + v), + (l = T - _), + (wu[2] = _ - (T - l) + (v - l)), + (wu[3] = T)); + const z = pu(P, bu, 4, wu, mu); + ((m = u * s), + (h = hu * u), + (d = h - (h - u)), + (p = u - d), + (h = hu * s), + (g = h - (h - s)), + (y = s - g), + (x = p * y - (m - d * g - p * g - d * y)), + (w = c * f), + (h = hu * c), + (d = h - (h - c)), + (p = c - d), + (h = hu * f), + (g = h - (h - f)), + (y = f - g), + (M = p * y - (w - d * g - p * g - d * y)), + (v = x - M), + (l = x - v), + (wu[0] = x - (v + l) + (l - M)), + (_ = m + v), + (l = _ - m), + (b = m - (_ - l) + (v - l)), + (v = b - w), + (l = b - v), + (wu[1] = b - (v + l) + (l - w)), + (T = _ + v), + (l = T - _), + (wu[2] = _ - (T - l) + (v - l)), + (wu[3] = T)); + const $ = pu(z, mu, 4, wu, xu); + return xu[$ - 1]; + })(t, n, e, r, i, o, f); + } + const Tu = Math.pow(2, -52), + Au = new Uint32Array(512); + class Su { + static from(t, n = zu, e = $u) { + const r = t.length, + i = new Float64Array(2 * r); + for (let o = 0; o < r; o++) { + const r = t[o]; + ((i[2 * o] = n(r)), (i[2 * o + 1] = e(r))); + } + return new Su(i); + } + constructor(t) { + const n = t.length >> 1; + if (n > 0 && "number" != typeof t[0]) + throw new Error("Expected coords to contain numbers."); + this.coords = t; + const e = Math.max(2 * n - 5, 0); + ((this._triangles = new Uint32Array(3 * e)), + (this._halfedges = new Int32Array(3 * e)), + (this._hashSize = Math.ceil(Math.sqrt(n))), + (this._hullPrev = new Uint32Array(n)), + (this._hullNext = new Uint32Array(n)), + (this._hullTri = new Uint32Array(n)), + (this._hullHash = new Int32Array(this._hashSize)), + (this._ids = new Uint32Array(n)), + (this._dists = new Float64Array(n)), + this.update()); + } + update() { + const { + coords: t, + _hullPrev: n, + _hullNext: e, + _hullTri: r, + _hullHash: i, + } = this, + o = t.length >> 1; + let a = 1 / 0, + u = 1 / 0, + c = -1 / 0, + f = -1 / 0; + for (let n = 0; n < o; n++) { + const e = t[2 * n], + r = t[2 * n + 1]; + (e < a && (a = e), + r < u && (u = r), + e > c && (c = e), + r > f && (f = r), + (this._ids[n] = n)); + } + const s = (a + c) / 2, + l = (u + f) / 2; + let h, d, p; + for (let n = 0, e = 1 / 0; n < o; n++) { + const r = Eu(s, l, t[2 * n], t[2 * n + 1]); + r < e && ((h = n), (e = r)); + } + const g = t[2 * h], + y = t[2 * h + 1]; + for (let n = 0, e = 1 / 0; n < o; n++) { + if (n === h) continue; + const r = Eu(g, y, t[2 * n], t[2 * n + 1]); + r < e && r > 0 && ((d = n), (e = r)); + } + let v = t[2 * d], + _ = t[2 * d + 1], + b = 1 / 0; + for (let n = 0; n < o; n++) { + if (n === h || n === d) continue; + const e = ku(g, y, v, _, t[2 * n], t[2 * n + 1]); + e < b && ((p = n), (b = e)); + } + let m = t[2 * p], + x = t[2 * p + 1]; + if (b === 1 / 0) { + for (let n = 0; n < o; n++) + this._dists[n] = t[2 * n] - t[0] || t[2 * n + 1] - t[1]; + Cu(this._ids, this._dists, 0, o - 1); + const n = new Uint32Array(o); + let e = 0; + for (let t = 0, r = -1 / 0; t < o; t++) { + const i = this._ids[t], + o = this._dists[i]; + o > r && ((n[e++] = i), (r = o)); + } + return ( + (this.hull = n.subarray(0, e)), + (this.triangles = new Uint32Array(0)), + void (this.halfedges = new Uint32Array(0)) + ); + } + if (Mu(g, y, v, _, m, x) < 0) { + const t = d, + n = v, + e = _; + ((d = p), (v = m), (_ = x), (p = t), (m = n), (x = e)); + } + const w = (function (t, n, e, r, i, o) { + const a = e - t, + u = r - n, + c = i - t, + f = o - n, + s = a * a + u * u, + l = c * c + f * f, + h = 0.5 / (a * f - u * c), + d = t + (f * s - u * l) * h, + p = n + (a * l - c * s) * h; + return { x: d, y: p }; + })(g, y, v, _, m, x); + ((this._cx = w.x), (this._cy = w.y)); + for (let n = 0; n < o; n++) + this._dists[n] = Eu(t[2 * n], t[2 * n + 1], w.x, w.y); + (Cu(this._ids, this._dists, 0, o - 1), (this._hullStart = h)); + let M = 3; + ((e[h] = n[p] = d), + (e[d] = n[h] = p), + (e[p] = n[d] = h), + (r[h] = 0), + (r[d] = 1), + (r[p] = 2), + i.fill(-1), + (i[this._hashKey(g, y)] = h), + (i[this._hashKey(v, _)] = d), + (i[this._hashKey(m, x)] = p), + (this.trianglesLen = 0), + this._addTriangle(h, d, p, -1, -1, -1)); + for (let o, a, u = 0; u < this._ids.length; u++) { + const c = this._ids[u], + f = t[2 * c], + s = t[2 * c + 1]; + if (u > 0 && Math.abs(f - o) <= Tu && Math.abs(s - a) <= Tu) continue; + if (((o = f), (a = s), c === h || c === d || c === p)) continue; + let l = 0; + for ( + let t = 0, n = this._hashKey(f, s); + t < this._hashSize && + ((l = i[(n + t) % this._hashSize]), -1 === l || l === e[l]); + t++ + ); + l = n[l]; + let g, + y = l; + for ( + ; + (g = e[y]), + Mu(f, s, t[2 * y], t[2 * y + 1], t[2 * g], t[2 * g + 1]) >= 0; + + ) + if (((y = g), y === l)) { + y = -1; + break; + } + if (-1 === y) continue; + let v = this._addTriangle(y, c, e[y], -1, -1, r[y]); + ((r[c] = this._legalize(v + 2)), (r[y] = v), M++); + let _ = e[y]; + for ( + ; + (g = e[_]), + Mu(f, s, t[2 * _], t[2 * _ + 1], t[2 * g], t[2 * g + 1]) < 0; + + ) + ((v = this._addTriangle(_, c, g, r[c], -1, r[_])), + (r[c] = this._legalize(v + 2)), + (e[_] = _), + M--, + (_ = g)); + if (y === l) + for ( + ; + (g = n[y]), + Mu(f, s, t[2 * g], t[2 * g + 1], t[2 * y], t[2 * y + 1]) < 0; + + ) + ((v = this._addTriangle(g, c, y, -1, r[y], r[g])), + this._legalize(v + 2), + (r[g] = v), + (e[y] = y), + M--, + (y = g)); + ((this._hullStart = n[c] = y), + (e[y] = n[_] = c), + (e[c] = _), + (i[this._hashKey(f, s)] = c), + (i[this._hashKey(t[2 * y], t[2 * y + 1])] = y)); + } + this.hull = new Uint32Array(M); + for (let t = 0, n = this._hullStart; t < M; t++) + ((this.hull[t] = n), (n = e[n])); + ((this.triangles = this._triangles.subarray(0, this.trianglesLen)), + (this.halfedges = this._halfedges.subarray(0, this.trianglesLen))); + } + _hashKey(t, n) { + return ( + Math.floor( + (function (t, n) { + const e = t / (Math.abs(t) + Math.abs(n)); + return (n > 0 ? 3 - e : 1 + e) / 4; + })(t - this._cx, n - this._cy) * this._hashSize, + ) % this._hashSize + ); + } + _legalize(t) { + const { _triangles: n, _halfedges: e, coords: r } = this; + let i = 0, + o = 0; + for (;;) { + const a = e[t], + u = t - (t % 3); + if (((o = u + ((t + 2) % 3)), -1 === a)) { + if (0 === i) break; + t = Au[--i]; + continue; + } + const c = a - (a % 3), + f = u + ((t + 1) % 3), + s = c + ((a + 2) % 3), + l = n[o], + h = n[t], + d = n[f], + p = n[s]; + if ( + Nu( + r[2 * l], + r[2 * l + 1], + r[2 * h], + r[2 * h + 1], + r[2 * d], + r[2 * d + 1], + r[2 * p], + r[2 * p + 1], + ) + ) { + ((n[t] = p), (n[a] = l)); + const r = e[s]; + if (-1 === r) { + let n = this._hullStart; + do { + if (this._hullTri[n] === s) { + this._hullTri[n] = t; + break; + } + n = this._hullPrev[n]; + } while (n !== this._hullStart); + } + (this._link(t, r), this._link(a, e[o]), this._link(o, s)); + const u = c + ((a + 1) % 3); + i < Au.length && (Au[i++] = u); + } else { + if (0 === i) break; + t = Au[--i]; + } + } + return o; + } + _link(t, n) { + ((this._halfedges[t] = n), -1 !== n && (this._halfedges[n] = t)); + } + _addTriangle(t, n, e, r, i, o) { + const a = this.trianglesLen; + return ( + (this._triangles[a] = t), + (this._triangles[a + 1] = n), + (this._triangles[a + 2] = e), + this._link(a, r), + this._link(a + 1, i), + this._link(a + 2, o), + (this.trianglesLen += 3), + a + ); + } + } + function Eu(t, n, e, r) { + const i = t - e, + o = n - r; + return i * i + o * o; + } + function Nu(t, n, e, r, i, o, a, u) { + const c = t - a, + f = n - u, + s = e - a, + l = r - u, + h = i - a, + d = o - u, + p = s * s + l * l, + g = h * h + d * d; + return ( + c * (l * g - p * d) - + f * (s * g - p * h) + + (c * c + f * f) * (s * d - l * h) < + 0 + ); + } + function ku(t, n, e, r, i, o) { + const a = e - t, + u = r - n, + c = i - t, + f = o - n, + s = a * a + u * u, + l = c * c + f * f, + h = 0.5 / (a * f - u * c), + d = (f * s - u * l) * h, + p = (a * l - c * s) * h; + return d * d + p * p; + } + function Cu(t, n, e, r) { + if (r - e <= 20) + for (let i = e + 1; i <= r; i++) { + const r = t[i], + o = n[r]; + let a = i - 1; + for (; a >= e && n[t[a]] > o; ) t[a + 1] = t[a--]; + t[a + 1] = r; + } + else { + let i = e + 1, + o = r; + (Pu(t, (e + r) >> 1, i), + n[t[e]] > n[t[r]] && Pu(t, e, r), + n[t[i]] > n[t[r]] && Pu(t, i, r), + n[t[e]] > n[t[i]] && Pu(t, e, i)); + const a = t[i], + u = n[a]; + for (;;) { + do { + i++; + } while (n[t[i]] < u); + do { + o--; + } while (n[t[o]] > u); + if (o < i) break; + Pu(t, i, o); + } + ((t[e + 1] = t[o]), + (t[o] = a), + r - i + 1 >= o - e + ? (Cu(t, n, i, r), Cu(t, n, e, o - 1)) + : (Cu(t, n, e, o - 1), Cu(t, n, i, r))); + } + } + function Pu(t, n, e) { + const r = t[n]; + ((t[n] = t[e]), (t[e] = r)); + } + function zu(t) { + return t[0]; + } + function $u(t) { + return t[1]; + } + const Du = 1e-6; + class Ru { + constructor() { + ((this._x0 = this._y0 = this._x1 = this._y1 = null), (this._ = "")); + } + moveTo(t, n) { + this._ += `M${(this._x0 = this._x1 = +t)},${(this._y0 = this._y1 = +n)}`; + } + closePath() { + null !== this._x1 && + ((this._x1 = this._x0), (this._y1 = this._y0), (this._ += "Z")); + } + lineTo(t, n) { + this._ += `L${(this._x1 = +t)},${(this._y1 = +n)}`; + } + arc(t, n, e) { + const r = (t = +t) + (e = +e), + i = (n = +n); + if (e < 0) throw new Error("negative radius"); + (null === this._x1 + ? (this._ += `M${r},${i}`) + : (Math.abs(this._x1 - r) > Du || Math.abs(this._y1 - i) > Du) && + (this._ += "L" + r + "," + i), + e && + (this._ += `A${e},${e},0,1,1,${t - e},${n}A${e},${e},0,1,1,${(this._x1 = r)},${(this._y1 = i)}`)); + } + rect(t, n, e, r) { + this._ += `M${(this._x0 = this._x1 = +t)},${(this._y0 = this._y1 = +n)}h${+e}v${+r}h${-e}Z`; + } + value() { + return this._ || null; + } + } + class Fu { + constructor() { + this._ = []; + } + moveTo(t, n) { + this._.push([t, n]); + } + closePath() { + this._.push(this._[0].slice()); + } + lineTo(t, n) { + this._.push([t, n]); + } + value() { + return this._.length ? this._ : null; + } + } + class qu { + constructor(t, [n, e, r, i] = [0, 0, 960, 500]) { + if (!((r = +r) >= (n = +n) && (i = +i) >= (e = +e))) + throw new Error("invalid bounds"); + ((this.delaunay = t), + (this._circumcenters = new Float64Array(2 * t.points.length)), + (this.vectors = new Float64Array(2 * t.points.length)), + (this.xmax = r), + (this.xmin = n), + (this.ymax = i), + (this.ymin = e), + this._init()); + } + update() { + return (this.delaunay.update(), this._init(), this); + } + _init() { + const { + delaunay: { points: t, hull: n, triangles: e }, + vectors: r, + } = this; + let i, o; + const a = (this.circumcenters = this._circumcenters.subarray( + 0, + (e.length / 3) * 2, + )); + for (let r, u, c = 0, f = 0, s = e.length; c < s; c += 3, f += 2) { + const s = 2 * e[c], + l = 2 * e[c + 1], + h = 2 * e[c + 2], + d = t[s], + p = t[s + 1], + g = t[l], + y = t[l + 1], + v = t[h], + _ = t[h + 1], + b = g - d, + m = y - p, + x = v - d, + w = _ - p, + M = 2 * (b * w - m * x); + if (Math.abs(M) < 1e-9) { + if (void 0 === i) { + i = o = 0; + for (const e of n) ((i += t[2 * e]), (o += t[2 * e + 1])); + ((i /= n.length), (o /= n.length)); + } + const e = 1e9 * Math.sign((i - d) * w - (o - p) * x); + ((r = (d + v) / 2 - e * w), (u = (p + _) / 2 + e * x)); + } else { + const t = 1 / M, + n = b * b + m * m, + e = x * x + w * w; + ((r = d + (w * n - m * e) * t), (u = p + (b * e - x * n) * t)); + } + ((a[f] = r), (a[f + 1] = u)); + } + let u, + c, + f, + s = n[n.length - 1], + l = 4 * s, + h = t[2 * s], + d = t[2 * s + 1]; + r.fill(0); + for (let e = 0; e < n.length; ++e) + ((s = n[e]), + (u = l), + (c = h), + (f = d), + (l = 4 * s), + (h = t[2 * s]), + (d = t[2 * s + 1]), + (r[u + 2] = r[l] = f - d), + (r[u + 3] = r[l + 1] = h - c)); + } + render(t) { + const n = null == t ? (t = new Ru()) : void 0, + { + delaunay: { halfedges: e, inedges: r, hull: i }, + circumcenters: o, + vectors: a, + } = this; + if (i.length <= 1) return null; + for (let n = 0, r = e.length; n < r; ++n) { + const r = e[n]; + if (r < n) continue; + const i = 2 * Math.floor(n / 3), + a = 2 * Math.floor(r / 3), + u = o[i], + c = o[i + 1], + f = o[a], + s = o[a + 1]; + this._renderSegment(u, c, f, s, t); + } + let u, + c = i[i.length - 1]; + for (let n = 0; n < i.length; ++n) { + ((u = c), (c = i[n])); + const e = 2 * Math.floor(r[c] / 3), + f = o[e], + s = o[e + 1], + l = 4 * u, + h = this._project(f, s, a[l + 2], a[l + 3]); + h && this._renderSegment(f, s, h[0], h[1], t); + } + return n && n.value(); + } + renderBounds(t) { + const n = null == t ? (t = new Ru()) : void 0; + return ( + t.rect( + this.xmin, + this.ymin, + this.xmax - this.xmin, + this.ymax - this.ymin, + ), + n && n.value() + ); + } + renderCell(t, n) { + const e = null == n ? (n = new Ru()) : void 0, + r = this._clip(t); + if (null === r || !r.length) return; + n.moveTo(r[0], r[1]); + let i = r.length; + for (; r[0] === r[i - 2] && r[1] === r[i - 1] && i > 1; ) i -= 2; + for (let t = 2; t < i; t += 2) + (r[t] === r[t - 2] && r[t + 1] === r[t - 1]) || + n.lineTo(r[t], r[t + 1]); + return (n.closePath(), e && e.value()); + } + *cellPolygons() { + const { + delaunay: { points: t }, + } = this; + for (let n = 0, e = t.length / 2; n < e; ++n) { + const t = this.cellPolygon(n); + t && ((t.index = n), yield t); + } + } + cellPolygon(t) { + const n = new Fu(); + return (this.renderCell(t, n), n.value()); + } + _renderSegment(t, n, e, r, i) { + let o; + const a = this._regioncode(t, n), + u = this._regioncode(e, r); + 0 === a && 0 === u + ? (i.moveTo(t, n), i.lineTo(e, r)) + : (o = this._clipSegment(t, n, e, r, a, u)) && + (i.moveTo(o[0], o[1]), i.lineTo(o[2], o[3])); + } + contains(t, n, e) { + return ( + (n = +n) == n && (e = +e) == e && this.delaunay._step(t, n, e) === t + ); + } + *neighbors(t) { + const n = this._clip(t); + if (n) + for (const e of this.delaunay.neighbors(t)) { + const t = this._clip(e); + if (t) + t: for (let r = 0, i = n.length; r < i; r += 2) + for (let o = 0, a = t.length; o < a; o += 2) + if ( + n[r] === t[o] && + n[r + 1] === t[o + 1] && + n[(r + 2) % i] === t[(o + a - 2) % a] && + n[(r + 3) % i] === t[(o + a - 1) % a] + ) { + yield e; + break t; + } + } + } + _cell(t) { + const { + circumcenters: n, + delaunay: { inedges: e, halfedges: r, triangles: i }, + } = this, + o = e[t]; + if (-1 === o) return null; + const a = []; + let u = o; + do { + const e = Math.floor(u / 3); + if ( + (a.push(n[2 * e], n[2 * e + 1]), + (u = u % 3 == 2 ? u - 2 : u + 1), + i[u] !== t) + ) + break; + u = r[u]; + } while (u !== o && -1 !== u); + return a; + } + _clip(t) { + if (0 === t && 1 === this.delaunay.hull.length) + return [ + this.xmax, + this.ymin, + this.xmax, + this.ymax, + this.xmin, + this.ymax, + this.xmin, + this.ymin, + ]; + const n = this._cell(t); + if (null === n) return null; + const { vectors: e } = this, + r = 4 * t; + return this._simplify( + e[r] || e[r + 1] + ? this._clipInfinite(t, n, e[r], e[r + 1], e[r + 2], e[r + 3]) + : this._clipFinite(t, n), + ); + } + _clipFinite(t, n) { + const e = n.length; + let r, + i, + o, + a, + u = null, + c = n[e - 2], + f = n[e - 1], + s = this._regioncode(c, f), + l = 0; + for (let h = 0; h < e; h += 2) + if ( + ((r = c), + (i = f), + (c = n[h]), + (f = n[h + 1]), + (o = s), + (s = this._regioncode(c, f)), + 0 === o && 0 === s) + ) + ((a = l), (l = 0), u ? u.push(c, f) : (u = [c, f])); + else { + let n, e, h, d, p; + if (0 === o) { + if (null === (n = this._clipSegment(r, i, c, f, o, s))) continue; + [e, h, d, p] = n; + } else { + if (null === (n = this._clipSegment(c, f, r, i, s, o))) continue; + (([d, p, e, h] = n), + (a = l), + (l = this._edgecode(e, h)), + a && l && this._edge(t, a, l, u, u.length), + u ? u.push(e, h) : (u = [e, h])); + } + ((a = l), + (l = this._edgecode(d, p)), + a && l && this._edge(t, a, l, u, u.length), + u ? u.push(d, p) : (u = [d, p])); + } + if (u) + ((a = l), + (l = this._edgecode(u[0], u[1])), + a && l && this._edge(t, a, l, u, u.length)); + else if ( + this.contains( + t, + (this.xmin + this.xmax) / 2, + (this.ymin + this.ymax) / 2, + ) + ) + return [ + this.xmax, + this.ymin, + this.xmax, + this.ymax, + this.xmin, + this.ymax, + this.xmin, + this.ymin, + ]; + return u; + } + _clipSegment(t, n, e, r, i, o) { + const a = i < o; + for (a && ([t, n, e, r, i, o] = [e, r, t, n, o, i]); ; ) { + if (0 === i && 0 === o) return a ? [e, r, t, n] : [t, n, e, r]; + if (i & o) return null; + let u, + c, + f = i || o; + (8 & f + ? ((u = t + ((e - t) * (this.ymax - n)) / (r - n)), (c = this.ymax)) + : 4 & f + ? ((u = t + ((e - t) * (this.ymin - n)) / (r - n)), (c = this.ymin)) + : 2 & f + ? ((c = n + ((r - n) * (this.xmax - t)) / (e - t)), + (u = this.xmax)) + : ((c = n + ((r - n) * (this.xmin - t)) / (e - t)), + (u = this.xmin)), + i + ? ((t = u), (n = c), (i = this._regioncode(t, n))) + : ((e = u), (r = c), (o = this._regioncode(e, r)))); + } + } + _clipInfinite(t, n, e, r, i, o) { + let a, + u = Array.from(n); + if ( + ((a = this._project(u[0], u[1], e, r)) && u.unshift(a[0], a[1]), + (a = this._project(u[u.length - 2], u[u.length - 1], i, o)) && + u.push(a[0], a[1]), + (u = this._clipFinite(t, u))) + ) + for ( + let n, e = 0, r = u.length, i = this._edgecode(u[r - 2], u[r - 1]); + e < r; + e += 2 + ) + ((n = i), + (i = this._edgecode(u[e], u[e + 1])), + n && i && ((e = this._edge(t, n, i, u, e)), (r = u.length))); + else + this.contains( + t, + (this.xmin + this.xmax) / 2, + (this.ymin + this.ymax) / 2, + ) && + (u = [ + this.xmin, + this.ymin, + this.xmax, + this.ymin, + this.xmax, + this.ymax, + this.xmin, + this.ymax, + ]); + return u; + } + _edge(t, n, e, r, i) { + for (; n !== e; ) { + let e, o; + switch (n) { + case 5: + n = 4; + continue; + case 4: + ((n = 6), (e = this.xmax), (o = this.ymin)); + break; + case 6: + n = 2; + continue; + case 2: + ((n = 10), (e = this.xmax), (o = this.ymax)); + break; + case 10: + n = 8; + continue; + case 8: + ((n = 9), (e = this.xmin), (o = this.ymax)); + break; + case 9: + n = 1; + continue; + case 1: + ((n = 5), (e = this.xmin), (o = this.ymin)); + } + (r[i] === e && r[i + 1] === o) || + !this.contains(t, e, o) || + (r.splice(i, 0, e, o), (i += 2)); + } + return i; + } + _project(t, n, e, r) { + let i, + o, + a, + u = 1 / 0; + if (r < 0) { + if (n <= this.ymin) return null; + (i = (this.ymin - n) / r) < u && + ((a = this.ymin), (o = t + (u = i) * e)); + } else if (r > 0) { + if (n >= this.ymax) return null; + (i = (this.ymax - n) / r) < u && + ((a = this.ymax), (o = t + (u = i) * e)); + } + if (e > 0) { + if (t >= this.xmax) return null; + (i = (this.xmax - t) / e) < u && + ((o = this.xmax), (a = n + (u = i) * r)); + } else if (e < 0) { + if (t <= this.xmin) return null; + (i = (this.xmin - t) / e) < u && + ((o = this.xmin), (a = n + (u = i) * r)); + } + return [o, a]; + } + _edgecode(t, n) { + return ( + (t === this.xmin ? 1 : t === this.xmax ? 2 : 0) | + (n === this.ymin ? 4 : n === this.ymax ? 8 : 0) + ); + } + _regioncode(t, n) { + return ( + (t < this.xmin ? 1 : t > this.xmax ? 2 : 0) | + (n < this.ymin ? 4 : n > this.ymax ? 8 : 0) + ); + } + _simplify(t) { + if (t && t.length > 4) { + for (let n = 0; n < t.length; n += 2) { + const e = (n + 2) % t.length, + r = (n + 4) % t.length; + ((t[n] === t[e] && t[e] === t[r]) || + (t[n + 1] === t[e + 1] && t[e + 1] === t[r + 1])) && + (t.splice(e, 2), (n -= 2)); + } + t.length || (t = null); + } + return t; + } + } + const Uu = 2 * Math.PI, + Iu = Math.pow; + function Ou(t) { + return t[0]; + } + function Bu(t) { + return t[1]; + } + function Yu(t, n, e) { + return [t + Math.sin(t + n) * e, n + Math.cos(t - n) * e]; + } + class Lu { + static from(t, n = Ou, e = Bu, r) { + return new Lu( + "length" in t + ? (function (t, n, e, r) { + const i = t.length, + o = new Float64Array(2 * i); + for (let a = 0; a < i; ++a) { + const i = t[a]; + ((o[2 * a] = n.call(r, i, a, t)), + (o[2 * a + 1] = e.call(r, i, a, t))); + } + return o; + })(t, n, e, r) + : Float64Array.from( + (function* (t, n, e, r) { + let i = 0; + for (const o of t) + (yield n.call(r, o, i, t), yield e.call(r, o, i, t), ++i); + })(t, n, e, r), + ), + ); + } + constructor(t) { + ((this._delaunator = new Su(t)), + (this.inedges = new Int32Array(t.length / 2)), + (this._hullIndex = new Int32Array(t.length / 2)), + (this.points = this._delaunator.coords), + this._init()); + } + update() { + return (this._delaunator.update(), this._init(), this); + } + _init() { + const t = this._delaunator, + n = this.points; + if ( + t.hull && + t.hull.length > 2 && + (function (t) { + const { triangles: n, coords: e } = t; + for (let t = 0; t < n.length; t += 3) { + const r = 2 * n[t], + i = 2 * n[t + 1], + o = 2 * n[t + 2]; + if ( + (e[o] - e[r]) * (e[i + 1] - e[r + 1]) - + (e[i] - e[r]) * (e[o + 1] - e[r + 1]) > + 1e-10 + ) + return !1; + } + return !0; + })(t) + ) { + this.collinear = Int32Array.from( + { length: n.length / 2 }, + (t, n) => n, + ).sort((t, e) => n[2 * t] - n[2 * e] || n[2 * t + 1] - n[2 * e + 1]); + const t = this.collinear[0], + e = this.collinear[this.collinear.length - 1], + r = [n[2 * t], n[2 * t + 1], n[2 * e], n[2 * e + 1]], + i = 1e-8 * Math.hypot(r[3] - r[1], r[2] - r[0]); + for (let t = 0, e = n.length / 2; t < e; ++t) { + const e = Yu(n[2 * t], n[2 * t + 1], i); + ((n[2 * t] = e[0]), (n[2 * t + 1] = e[1])); + } + this._delaunator = new Su(n); + } else delete this.collinear; + const e = (this.halfedges = this._delaunator.halfedges), + r = (this.hull = this._delaunator.hull), + i = (this.triangles = this._delaunator.triangles), + o = this.inedges.fill(-1), + a = this._hullIndex.fill(-1); + for (let t = 0, n = e.length; t < n; ++t) { + const n = i[t % 3 == 2 ? t - 2 : t + 1]; + (-1 !== e[t] && -1 !== o[n]) || (o[n] = t); + } + for (let t = 0, n = r.length; t < n; ++t) a[r[t]] = t; + r.length <= 2 && + r.length > 0 && + ((this.triangles = new Int32Array(3).fill(-1)), + (this.halfedges = new Int32Array(3).fill(-1)), + (this.triangles[0] = r[0]), + (o[r[0]] = 1), + 2 === r.length && + ((o[r[1]] = 0), + (this.triangles[1] = r[1]), + (this.triangles[2] = r[1]))); + } + voronoi(t) { + return new qu(this, t); + } + *neighbors(t) { + const { + inedges: n, + hull: e, + _hullIndex: r, + halfedges: i, + triangles: o, + collinear: a, + } = this; + if (a) { + const n = a.indexOf(t); + return ( + n > 0 && (yield a[n - 1]), + void (n < a.length - 1 && (yield a[n + 1])) + ); + } + const u = n[t]; + if (-1 === u) return; + let c = u, + f = -1; + do { + if ((yield (f = o[c]), (c = c % 3 == 2 ? c - 2 : c + 1), o[c] !== t)) + return; + if (((c = i[c]), -1 === c)) { + const n = e[(r[t] + 1) % e.length]; + return void (n !== f && (yield n)); + } + } while (c !== u); + } + find(t, n, e = 0) { + if ((t = +t) != t || (n = +n) != n) return -1; + const r = e; + let i; + for (; (i = this._step(e, t, n)) >= 0 && i !== e && i !== r; ) e = i; + return i; + } + _step(t, n, e) { + const { + inedges: r, + hull: i, + _hullIndex: o, + halfedges: a, + triangles: u, + points: c, + } = this; + if (-1 === r[t] || !c.length) return (t + 1) % (c.length >> 1); + let f = t, + s = Iu(n - c[2 * t], 2) + Iu(e - c[2 * t + 1], 2); + const l = r[t]; + let h = l; + do { + let r = u[h]; + const l = Iu(n - c[2 * r], 2) + Iu(e - c[2 * r + 1], 2); + if ( + (l < s && ((s = l), (f = r)), + (h = h % 3 == 2 ? h - 2 : h + 1), + u[h] !== t) + ) + break; + if (((h = a[h]), -1 === h)) { + if ( + ((h = i[(o[t] + 1) % i.length]), + h !== r && Iu(n - c[2 * h], 2) + Iu(e - c[2 * h + 1], 2) < s) + ) + return h; + break; + } + } while (h !== l); + return f; + } + render(t) { + const n = null == t ? (t = new Ru()) : void 0, + { points: e, halfedges: r, triangles: i } = this; + for (let n = 0, o = r.length; n < o; ++n) { + const o = r[n]; + if (o < n) continue; + const a = 2 * i[n], + u = 2 * i[o]; + (t.moveTo(e[a], e[a + 1]), t.lineTo(e[u], e[u + 1])); + } + return (this.renderHull(t), n && n.value()); + } + renderPoints(t, n) { + (void 0 !== n || + (t && "function" == typeof t.moveTo) || + ((n = t), (t = null)), + (n = null == n ? 2 : +n)); + const e = null == t ? (t = new Ru()) : void 0, + { points: r } = this; + for (let e = 0, i = r.length; e < i; e += 2) { + const i = r[e], + o = r[e + 1]; + (t.moveTo(i + n, o), t.arc(i, o, n, 0, Uu)); + } + return e && e.value(); + } + renderHull(t) { + const n = null == t ? (t = new Ru()) : void 0, + { hull: e, points: r } = this, + i = 2 * e[0], + o = e.length; + t.moveTo(r[i], r[i + 1]); + for (let n = 1; n < o; ++n) { + const i = 2 * e[n]; + t.lineTo(r[i], r[i + 1]); + } + return (t.closePath(), n && n.value()); + } + hullPolygon() { + const t = new Fu(); + return (this.renderHull(t), t.value()); + } + renderTriangle(t, n) { + const e = null == n ? (n = new Ru()) : void 0, + { points: r, triangles: i } = this, + o = 2 * i[(t *= 3)], + a = 2 * i[t + 1], + u = 2 * i[t + 2]; + return ( + n.moveTo(r[o], r[o + 1]), + n.lineTo(r[a], r[a + 1]), + n.lineTo(r[u], r[u + 1]), + n.closePath(), + e && e.value() + ); + } + *trianglePolygons() { + const { triangles: t } = this; + for (let n = 0, e = t.length / 3; n < e; ++n) + yield this.trianglePolygon(n); + } + trianglePolygon(t) { + const n = new Fu(); + return (this.renderTriangle(t, n), n.value()); + } + } + var ju = {}, + Hu = {}, + Xu = 34, + Gu = 10, + Vu = 13; + function Wu(t) { + return new Function( + "d", + "return {" + + t + .map(function (t, n) { + return JSON.stringify(t) + ": d[" + n + '] || ""'; + }) + .join(",") + + "}", + ); + } + function Zu(t) { + var n = Object.create(null), + e = []; + return ( + t.forEach(function (t) { + for (var r in t) r in n || e.push((n[r] = r)); + }), + e + ); + } + function Ku(t, n) { + var e = t + "", + r = e.length; + return r < n ? new Array(n - r + 1).join(0) + e : e; + } + function Qu(t) { + var n, + e = t.getUTCHours(), + r = t.getUTCMinutes(), + i = t.getUTCSeconds(), + o = t.getUTCMilliseconds(); + return isNaN(t) + ? "Invalid Date" + : ((n = t.getUTCFullYear()) < 0 + ? "-" + Ku(-n, 6) + : n > 9999 + ? "+" + Ku(n, 6) + : Ku(n, 4)) + + "-" + + Ku(t.getUTCMonth() + 1, 2) + + "-" + + Ku(t.getUTCDate(), 2) + + (o + ? "T" + + Ku(e, 2) + + ":" + + Ku(r, 2) + + ":" + + Ku(i, 2) + + "." + + Ku(o, 3) + + "Z" + : i + ? "T" + Ku(e, 2) + ":" + Ku(r, 2) + ":" + Ku(i, 2) + "Z" + : r || e + ? "T" + Ku(e, 2) + ":" + Ku(r, 2) + "Z" + : ""); + } + function Ju(t) { + var n = new RegExp('["' + t + "\n\r]"), + e = t.charCodeAt(0); + function r(t, n) { + var r, + i = [], + o = t.length, + a = 0, + u = 0, + c = o <= 0, + f = !1; + function s() { + if (c) return Hu; + if (f) return ((f = !1), ju); + var n, + r, + i = a; + if (t.charCodeAt(i) === Xu) { + for ( + ; + (a++ < o && t.charCodeAt(a) !== Xu) || t.charCodeAt(++a) === Xu; + + ); + return ( + (n = a) >= o + ? (c = !0) + : (r = t.charCodeAt(a++)) === Gu + ? (f = !0) + : r === Vu && ((f = !0), t.charCodeAt(a) === Gu && ++a), + t.slice(i + 1, n - 1).replace(/""/g, '"') + ); + } + for (; a < o; ) { + if ((r = t.charCodeAt((n = a++))) === Gu) f = !0; + else if (r === Vu) ((f = !0), t.charCodeAt(a) === Gu && ++a); + else if (r !== e) continue; + return t.slice(i, n); + } + return ((c = !0), t.slice(i, o)); + } + for ( + t.charCodeAt(o - 1) === Gu && --o, t.charCodeAt(o - 1) === Vu && --o; + (r = s()) !== Hu; + + ) { + for (var l = []; r !== ju && r !== Hu; ) (l.push(r), (r = s())); + (n && null == (l = n(l, u++))) || i.push(l); + } + return i; + } + function i(n, e) { + return n.map(function (n) { + return e + .map(function (t) { + return a(n[t]); + }) + .join(t); + }); + } + function o(n) { + return n.map(a).join(t); + } + function a(t) { + return null == t + ? "" + : t instanceof Date + ? Qu(t) + : n.test((t += "")) + ? '"' + t.replace(/"/g, '""') + '"' + : t; + } + return { + parse: function (t, n) { + var e, + i, + o = r(t, function (t, r) { + if (e) return e(t, r - 1); + ((i = t), + (e = n + ? (function (t, n) { + var e = Wu(t); + return function (r, i) { + return n(e(r), i, t); + }; + })(t, n) + : Wu(t))); + }); + return ((o.columns = i || []), o); + }, + parseRows: r, + format: function (n, e) { + return ( + null == e && (e = Zu(n)), + [e.map(a).join(t)].concat(i(n, e)).join("\n") + ); + }, + formatBody: function (t, n) { + return (null == n && (n = Zu(t)), i(t, n).join("\n")); + }, + formatRows: function (t) { + return t.map(o).join("\n"); + }, + formatRow: o, + formatValue: a, + }; + } + var tc = Ju(","), + nc = tc.parse, + ec = tc.parseRows, + rc = tc.format, + ic = tc.formatBody, + oc = tc.formatRows, + ac = tc.formatRow, + uc = tc.formatValue, + cc = Ju("\t"), + fc = cc.parse, + sc = cc.parseRows, + lc = cc.format, + hc = cc.formatBody, + dc = cc.formatRows, + pc = cc.formatRow, + gc = cc.formatValue; + const yc = + new Date("2019-01-01T00:00").getHours() || + new Date("2019-07-01T00:00").getHours(); + function vc(t) { + if (!t.ok) throw new Error(t.status + " " + t.statusText); + return t.blob(); + } + function _c(t) { + if (!t.ok) throw new Error(t.status + " " + t.statusText); + return t.arrayBuffer(); + } + function bc(t) { + if (!t.ok) throw new Error(t.status + " " + t.statusText); + return t.text(); + } + function mc(t, n) { + return fetch(t, n).then(bc); + } + function xc(t) { + return function (n, e, r) { + return ( + 2 === arguments.length && + "function" == typeof e && + ((r = e), (e = void 0)), + mc(n, e).then(function (n) { + return t(n, r); + }) + ); + }; + } + var wc = xc(nc), + Mc = xc(fc); + function Tc(t) { + if (!t.ok) throw new Error(t.status + " " + t.statusText); + if (204 !== t.status && 205 !== t.status) return t.json(); + } + function Ac(t) { + return (n, e) => + mc(n, e).then((n) => new DOMParser().parseFromString(n, t)); + } + var Sc = Ac("application/xml"), + Ec = Ac("text/html"), + Nc = Ac("image/svg+xml"); + function kc(t, n, e, r) { + if (isNaN(n) || isNaN(e)) return t; + var i, + o, + a, + u, + c, + f, + s, + l, + h, + d = t._root, + p = { data: r }, + g = t._x0, + y = t._y0, + v = t._x1, + _ = t._y1; + if (!d) return ((t._root = p), t); + for (; d.length; ) + if ( + ((f = n >= (o = (g + v) / 2)) ? (g = o) : (v = o), + (s = e >= (a = (y + _) / 2)) ? (y = a) : (_ = a), + (i = d), + !(d = d[(l = (s << 1) | f)])) + ) + return ((i[l] = p), t); + if ( + ((u = +t._x.call(null, d.data)), + (c = +t._y.call(null, d.data)), + n === u && e === c) + ) + return ((p.next = d), i ? (i[l] = p) : (t._root = p), t); + do { + ((i = i ? (i[l] = new Array(4)) : (t._root = new Array(4))), + (f = n >= (o = (g + v) / 2)) ? (g = o) : (v = o), + (s = e >= (a = (y + _) / 2)) ? (y = a) : (_ = a)); + } while ((l = (s << 1) | f) == (h = ((c >= a) << 1) | (u >= o))); + return ((i[h] = d), (i[l] = p), t); + } + function Cc(t, n, e, r, i) { + ((this.node = t), + (this.x0 = n), + (this.y0 = e), + (this.x1 = r), + (this.y1 = i)); + } + function Pc(t) { + return t[0]; + } + function zc(t) { + return t[1]; + } + function $c(t, n, e) { + var r = new Dc(null == n ? Pc : n, null == e ? zc : e, NaN, NaN, NaN, NaN); + return null == t ? r : r.addAll(t); + } + function Dc(t, n, e, r, i, o) { + ((this._x = t), + (this._y = n), + (this._x0 = e), + (this._y0 = r), + (this._x1 = i), + (this._y1 = o), + (this._root = void 0)); + } + function Rc(t) { + for (var n = { data: t.data }, e = n; (t = t.next); ) + e = e.next = { data: t.data }; + return n; + } + var Fc = ($c.prototype = Dc.prototype); + function qc(t) { + return function () { + return t; + }; + } + function Uc(t) { + return 1e-6 * (t() - 0.5); + } + function Ic(t) { + return t.x + t.vx; + } + function Oc(t) { + return t.y + t.vy; + } + function Bc(t) { + return t.index; + } + function Yc(t, n) { + var e = t.get(n); + if (!e) throw new Error("node not found: " + n); + return e; + } + ((Fc.copy = function () { + var t, + n, + e = new Dc(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + r = this._root; + if (!r) return e; + if (!r.length) return ((e._root = Rc(r)), e); + for (t = [{ source: r, target: (e._root = new Array(4)) }]; (r = t.pop()); ) + for (var i = 0; i < 4; ++i) + (n = r.source[i]) && + (n.length + ? t.push({ source: n, target: (r.target[i] = new Array(4)) }) + : (r.target[i] = Rc(n))); + return e; + }), + (Fc.add = function (t) { + const n = +this._x.call(null, t), + e = +this._y.call(null, t); + return kc(this.cover(n, e), n, e, t); + }), + (Fc.addAll = function (t) { + var n, + e, + r, + i, + o = t.length, + a = new Array(o), + u = new Array(o), + c = 1 / 0, + f = 1 / 0, + s = -1 / 0, + l = -1 / 0; + for (e = 0; e < o; ++e) + isNaN((r = +this._x.call(null, (n = t[e])))) || + isNaN((i = +this._y.call(null, n))) || + ((a[e] = r), + (u[e] = i), + r < c && (c = r), + r > s && (s = r), + i < f && (f = i), + i > l && (l = i)); + if (c > s || f > l) return this; + for (this.cover(c, f).cover(s, l), e = 0; e < o; ++e) + kc(this, a[e], u[e], t[e]); + return this; + }), + (Fc.cover = function (t, n) { + if (isNaN((t = +t)) || isNaN((n = +n))) return this; + var e = this._x0, + r = this._y0, + i = this._x1, + o = this._y1; + if (isNaN(e)) + ((i = (e = Math.floor(t)) + 1), (o = (r = Math.floor(n)) + 1)); + else { + for ( + var a, u, c = i - e || 1, f = this._root; + e > t || t >= i || r > n || n >= o; + + ) + switch ( + ((u = ((n < r) << 1) | (t < e)), + ((a = new Array(4))[u] = f), + (f = a), + (c *= 2), + u) + ) { + case 0: + ((i = e + c), (o = r + c)); + break; + case 1: + ((e = i - c), (o = r + c)); + break; + case 2: + ((i = e + c), (r = o - c)); + break; + case 3: + ((e = i - c), (r = o - c)); + } + this._root && this._root.length && (this._root = f); + } + return ( + (this._x0 = e), + (this._y0 = r), + (this._x1 = i), + (this._y1 = o), + this + ); + }), + (Fc.data = function () { + var t = []; + return ( + this.visit(function (n) { + if (!n.length) + do { + t.push(n.data); + } while ((n = n.next)); + }), + t + ); + }), + (Fc.extent = function (t) { + return arguments.length + ? this.cover(+t[0][0], +t[0][1]).cover(+t[1][0], +t[1][1]) + : isNaN(this._x0) + ? void 0 + : [ + [this._x0, this._y0], + [this._x1, this._y1], + ]; + }), + (Fc.find = function (t, n, e) { + var r, + i, + o, + a, + u, + c, + f, + s = this._x0, + l = this._y0, + h = this._x1, + d = this._y1, + p = [], + g = this._root; + for ( + g && p.push(new Cc(g, s, l, h, d)), + null == e + ? (e = 1 / 0) + : ((s = t - e), (l = n - e), (h = t + e), (d = n + e), (e *= e)); + (c = p.pop()); + + ) + if ( + !( + !(g = c.node) || + (i = c.x0) > h || + (o = c.y0) > d || + (a = c.x1) < s || + (u = c.y1) < l + ) + ) + if (g.length) { + var y = (i + a) / 2, + v = (o + u) / 2; + (p.push( + new Cc(g[3], y, v, a, u), + new Cc(g[2], i, v, y, u), + new Cc(g[1], y, o, a, v), + new Cc(g[0], i, o, y, v), + ), + (f = ((n >= v) << 1) | (t >= y)) && + ((c = p[p.length - 1]), + (p[p.length - 1] = p[p.length - 1 - f]), + (p[p.length - 1 - f] = c))); + } else { + var _ = t - +this._x.call(null, g.data), + b = n - +this._y.call(null, g.data), + m = _ * _ + b * b; + if (m < e) { + var x = Math.sqrt((e = m)); + ((s = t - x), + (l = n - x), + (h = t + x), + (d = n + x), + (r = g.data)); + } + } + return r; + }), + (Fc.remove = function (t) { + if ( + isNaN((o = +this._x.call(null, t))) || + isNaN((a = +this._y.call(null, t))) + ) + return this; + var n, + e, + r, + i, + o, + a, + u, + c, + f, + s, + l, + h, + d = this._root, + p = this._x0, + g = this._y0, + y = this._x1, + v = this._y1; + if (!d) return this; + if (d.length) + for (;;) { + if ( + ((f = o >= (u = (p + y) / 2)) ? (p = u) : (y = u), + (s = a >= (c = (g + v) / 2)) ? (g = c) : (v = c), + (n = d), + !(d = d[(l = (s << 1) | f)])) + ) + return this; + if (!d.length) break; + (n[(l + 1) & 3] || n[(l + 2) & 3] || n[(l + 3) & 3]) && + ((e = n), (h = l)); + } + for (; d.data !== t; ) if (((r = d), !(d = d.next))) return this; + return ( + (i = d.next) && delete d.next, + r + ? (i ? (r.next = i) : delete r.next, this) + : n + ? (i ? (n[l] = i) : delete n[l], + (d = n[0] || n[1] || n[2] || n[3]) && + d === (n[3] || n[2] || n[1] || n[0]) && + !d.length && + (e ? (e[h] = d) : (this._root = d)), + this) + : ((this._root = i), this) + ); + }), + (Fc.removeAll = function (t) { + for (var n = 0, e = t.length; n < e; ++n) this.remove(t[n]); + return this; + }), + (Fc.root = function () { + return this._root; + }), + (Fc.size = function () { + var t = 0; + return ( + this.visit(function (n) { + if (!n.length) + do { + ++t; + } while ((n = n.next)); + }), + t + ); + }), + (Fc.visit = function (t) { + var n, + e, + r, + i, + o, + a, + u = [], + c = this._root; + for ( + c && u.push(new Cc(c, this._x0, this._y0, this._x1, this._y1)); + (n = u.pop()); + + ) + if ( + !t((c = n.node), (r = n.x0), (i = n.y0), (o = n.x1), (a = n.y1)) && + c.length + ) { + var f = (r + o) / 2, + s = (i + a) / 2; + ((e = c[3]) && u.push(new Cc(e, f, s, o, a)), + (e = c[2]) && u.push(new Cc(e, r, s, f, a)), + (e = c[1]) && u.push(new Cc(e, f, i, o, s)), + (e = c[0]) && u.push(new Cc(e, r, i, f, s))); + } + return this; + }), + (Fc.visitAfter = function (t) { + var n, + e = [], + r = []; + for ( + this._root && + e.push(new Cc(this._root, this._x0, this._y0, this._x1, this._y1)); + (n = e.pop()); + + ) { + var i = n.node; + if (i.length) { + var o, + a = n.x0, + u = n.y0, + c = n.x1, + f = n.y1, + s = (a + c) / 2, + l = (u + f) / 2; + ((o = i[0]) && e.push(new Cc(o, a, u, s, l)), + (o = i[1]) && e.push(new Cc(o, s, u, c, l)), + (o = i[2]) && e.push(new Cc(o, a, l, s, f)), + (o = i[3]) && e.push(new Cc(o, s, l, c, f))); + } + r.push(n); + } + for (; (n = r.pop()); ) t(n.node, n.x0, n.y0, n.x1, n.y1); + return this; + }), + (Fc.x = function (t) { + return arguments.length ? ((this._x = t), this) : this._x; + }), + (Fc.y = function (t) { + return arguments.length ? ((this._y = t), this) : this._y; + })); + const Lc = 1664525, + jc = 1013904223, + Hc = 4294967296; + function Xc(t) { + return t.x; + } + function Gc(t) { + return t.y; + } + var Vc = Math.PI * (3 - Math.sqrt(5)); + function Wc(t, n) { + if ( + (e = (t = n ? t.toExponential(n - 1) : t.toExponential()).indexOf("e")) < + 0 + ) + return null; + var e, + r = t.slice(0, e); + return [r.length > 1 ? r[0] + r.slice(2) : r, +t.slice(e + 1)]; + } + function Zc(t) { + return (t = Wc(Math.abs(t))) ? t[1] : NaN; + } + var Kc, + Qc = + /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i; + function Jc(t) { + if (!(n = Qc.exec(t))) throw new Error("invalid format: " + t); + var n; + return new tf({ + fill: n[1], + align: n[2], + sign: n[3], + symbol: n[4], + zero: n[5], + width: n[6], + comma: n[7], + precision: n[8] && n[8].slice(1), + trim: n[9], + type: n[10], + }); + } + function tf(t) { + ((this.fill = void 0 === t.fill ? " " : t.fill + ""), + (this.align = void 0 === t.align ? ">" : t.align + ""), + (this.sign = void 0 === t.sign ? "-" : t.sign + ""), + (this.symbol = void 0 === t.symbol ? "" : t.symbol + ""), + (this.zero = !!t.zero), + (this.width = void 0 === t.width ? void 0 : +t.width), + (this.comma = !!t.comma), + (this.precision = void 0 === t.precision ? void 0 : +t.precision), + (this.trim = !!t.trim), + (this.type = void 0 === t.type ? "" : t.type + "")); + } + function nf(t, n) { + var e = Wc(t, n); + if (!e) return t + ""; + var r = e[0], + i = e[1]; + return i < 0 + ? "0." + new Array(-i).join("0") + r + : r.length > i + 1 + ? r.slice(0, i + 1) + "." + r.slice(i + 1) + : r + new Array(i - r.length + 2).join("0"); + } + ((Jc.prototype = tf.prototype), + (tf.prototype.toString = function () { + return ( + this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (void 0 === this.width ? "" : Math.max(1, 0 | this.width)) + + (this.comma ? "," : "") + + (void 0 === this.precision + ? "" + : "." + Math.max(0, 0 | this.precision)) + + (this.trim ? "~" : "") + + this.type + ); + })); + var ef = { + "%": (t, n) => (100 * t).toFixed(n), + b: (t) => Math.round(t).toString(2), + c: (t) => t + "", + d: function (t) { + return Math.abs((t = Math.round(t))) >= 1e21 + ? t.toLocaleString("en").replace(/,/g, "") + : t.toString(10); + }, + e: (t, n) => t.toExponential(n), + f: (t, n) => t.toFixed(n), + g: (t, n) => t.toPrecision(n), + o: (t) => Math.round(t).toString(8), + p: (t, n) => nf(100 * t, n), + r: nf, + s: function (t, n) { + var e = Wc(t, n); + if (!e) return t + ""; + var r = e[0], + i = e[1], + o = i - (Kc = 3 * Math.max(-8, Math.min(8, Math.floor(i / 3)))) + 1, + a = r.length; + return o === a + ? r + : o > a + ? r + new Array(o - a + 1).join("0") + : o > 0 + ? r.slice(0, o) + "." + r.slice(o) + : "0." + + new Array(1 - o).join("0") + + Wc(t, Math.max(0, n + o - 1))[0]; + }, + X: (t) => Math.round(t).toString(16).toUpperCase(), + x: (t) => Math.round(t).toString(16), + }; + function rf(t) { + return t; + } + var of, + af = Array.prototype.map, + uf = [ + "y", + "z", + "a", + "f", + "p", + "n", + "µ", + "m", + "", + "k", + "M", + "G", + "T", + "P", + "E", + "Z", + "Y", + ]; + function cf(t) { + var n, + e, + r = + void 0 === t.grouping || void 0 === t.thousands + ? rf + : ((n = af.call(t.grouping, Number)), + (e = t.thousands + ""), + function (t, r) { + for ( + var i = t.length, o = [], a = 0, u = n[0], c = 0; + i > 0 && + u > 0 && + (c + u + 1 > r && (u = Math.max(1, r - c)), + o.push(t.substring((i -= u), i + u)), + !((c += u + 1) > r)); + + ) + u = n[(a = (a + 1) % n.length)]; + return o.reverse().join(e); + }), + i = void 0 === t.currency ? "" : t.currency[0] + "", + o = void 0 === t.currency ? "" : t.currency[1] + "", + a = void 0 === t.decimal ? "." : t.decimal + "", + u = + void 0 === t.numerals + ? rf + : (function (t) { + return function (n) { + return n.replace(/[0-9]/g, function (n) { + return t[+n]; + }); + }; + })(af.call(t.numerals, String)), + c = void 0 === t.percent ? "%" : t.percent + "", + f = void 0 === t.minus ? "−" : t.minus + "", + s = void 0 === t.nan ? "NaN" : t.nan + ""; + function l(t) { + var n = (t = Jc(t)).fill, + e = t.align, + l = t.sign, + h = t.symbol, + d = t.zero, + p = t.width, + g = t.comma, + y = t.precision, + v = t.trim, + _ = t.type; + ("n" === _ + ? ((g = !0), (_ = "g")) + : ef[_] || (void 0 === y && (y = 12), (v = !0), (_ = "g")), + (d || ("0" === n && "=" === e)) && ((d = !0), (n = "0"), (e = "="))); + var b = + "$" === h + ? i + : "#" === h && /[boxX]/.test(_) + ? "0" + _.toLowerCase() + : "", + m = "$" === h ? o : /[%p]/.test(_) ? c : "", + x = ef[_], + w = /[defgprs%]/.test(_); + function M(t) { + var i, + o, + c, + h = b, + M = m; + if ("c" === _) ((M = x(t) + M), (t = "")); + else { + var T = (t = +t) < 0 || 1 / t < 0; + if ( + ((t = isNaN(t) ? s : x(Math.abs(t), y)), + v && + (t = (function (t) { + t: for (var n, e = t.length, r = 1, i = -1; r < e; ++r) + switch (t[r]) { + case ".": + i = n = r; + break; + case "0": + (0 === i && (i = r), (n = r)); + break; + default: + if (!+t[r]) break t; + i > 0 && (i = 0); + } + return i > 0 ? t.slice(0, i) + t.slice(n + 1) : t; + })(t)), + T && 0 == +t && "+" !== l && (T = !1), + (h = + (T ? ("(" === l ? l : f) : "-" === l || "(" === l ? "" : l) + h), + (M = + ("s" === _ ? uf[8 + Kc / 3] : "") + + M + + (T && "(" === l ? ")" : "")), + w) + ) + for (i = -1, o = t.length; ++i < o; ) + if (48 > (c = t.charCodeAt(i)) || c > 57) { + ((M = (46 === c ? a + t.slice(i + 1) : t.slice(i)) + M), + (t = t.slice(0, i))); + break; + } + } + g && !d && (t = r(t, 1 / 0)); + var A = h.length + t.length + M.length, + S = A < p ? new Array(p - A + 1).join(n) : ""; + switch ( + (g && + d && + ((t = r(S + t, S.length ? p - M.length : 1 / 0)), (S = "")), + e) + ) { + case "<": + t = h + t + M + S; + break; + case "=": + t = h + S + t + M; + break; + case "^": + t = S.slice(0, (A = S.length >> 1)) + h + t + M + S.slice(A); + break; + default: + t = S + h + t + M; + } + return u(t); + } + return ( + (y = + void 0 === y + ? 6 + : /[gprs]/.test(_) + ? Math.max(1, Math.min(21, y)) + : Math.max(0, Math.min(20, y))), + (M.toString = function () { + return t + ""; + }), + M + ); + } + return { + format: l, + formatPrefix: function (t, n) { + var e = l((((t = Jc(t)).type = "f"), t)), + r = 3 * Math.max(-8, Math.min(8, Math.floor(Zc(n) / 3))), + i = Math.pow(10, -r), + o = uf[8 + r / 3]; + return function (t) { + return e(i * t) + o; + }; + }, + }; + } + function ff(n) { + return ( + (of = cf(n)), + (t.format = of.format), + (t.formatPrefix = of.formatPrefix), + of + ); + } + function sf(t) { + return Math.max(0, -Zc(Math.abs(t))); + } + function lf(t, n) { + return Math.max( + 0, + 3 * Math.max(-8, Math.min(8, Math.floor(Zc(n) / 3))) - Zc(Math.abs(t)), + ); + } + function hf(t, n) { + return ( + (t = Math.abs(t)), + (n = Math.abs(n) - t), + Math.max(0, Zc(n) - Zc(t)) + 1 + ); + } + ((t.format = void 0), + (t.formatPrefix = void 0), + ff({ thousands: ",", grouping: [3], currency: ["$", ""] })); + var df = 1e-6, + pf = 1e-12, + gf = Math.PI, + yf = gf / 2, + vf = gf / 4, + _f = 2 * gf, + bf = 180 / gf, + mf = gf / 180, + xf = Math.abs, + wf = Math.atan, + Mf = Math.atan2, + Tf = Math.cos, + Af = Math.ceil, + Sf = Math.exp, + Ef = Math.hypot, + Nf = Math.log, + kf = Math.pow, + Cf = Math.sin, + Pf = + Math.sign || + function (t) { + return t > 0 ? 1 : t < 0 ? -1 : 0; + }, + zf = Math.sqrt, + $f = Math.tan; + function Df(t) { + return t > 1 ? 0 : t < -1 ? gf : Math.acos(t); + } + function Rf(t) { + return t > 1 ? yf : t < -1 ? -yf : Math.asin(t); + } + function Ff(t) { + return (t = Cf(t / 2)) * t; + } + function qf() {} + function Uf(t, n) { + t && Of.hasOwnProperty(t.type) && Of[t.type](t, n); + } + var If = { + Feature: function (t, n) { + Uf(t.geometry, n); + }, + FeatureCollection: function (t, n) { + for (var e = t.features, r = -1, i = e.length; ++r < i; ) + Uf(e[r].geometry, n); + }, + }, + Of = { + Sphere: function (t, n) { + n.sphere(); + }, + Point: function (t, n) { + ((t = t.coordinates), n.point(t[0], t[1], t[2])); + }, + MultiPoint: function (t, n) { + for (var e = t.coordinates, r = -1, i = e.length; ++r < i; ) + ((t = e[r]), n.point(t[0], t[1], t[2])); + }, + LineString: function (t, n) { + Bf(t.coordinates, n, 0); + }, + MultiLineString: function (t, n) { + for (var e = t.coordinates, r = -1, i = e.length; ++r < i; ) + Bf(e[r], n, 0); + }, + Polygon: function (t, n) { + Yf(t.coordinates, n); + }, + MultiPolygon: function (t, n) { + for (var e = t.coordinates, r = -1, i = e.length; ++r < i; ) + Yf(e[r], n); + }, + GeometryCollection: function (t, n) { + for (var e = t.geometries, r = -1, i = e.length; ++r < i; ) Uf(e[r], n); + }, + }; + function Bf(t, n, e) { + var r, + i = -1, + o = t.length - e; + for (n.lineStart(); ++i < o; ) ((r = t[i]), n.point(r[0], r[1], r[2])); + n.lineEnd(); + } + function Yf(t, n) { + var e = -1, + r = t.length; + for (n.polygonStart(); ++e < r; ) Bf(t[e], n, 1); + n.polygonEnd(); + } + function Lf(t, n) { + t && If.hasOwnProperty(t.type) ? If[t.type](t, n) : Uf(t, n); + } + var jf, + Hf, + Xf, + Gf, + Vf, + Wf, + Zf, + Kf, + Qf, + Jf, + ts, + ns, + es, + rs, + is, + os, + as = new T(), + us = new T(), + cs = { + point: qf, + lineStart: qf, + lineEnd: qf, + polygonStart: function () { + ((as = new T()), (cs.lineStart = fs), (cs.lineEnd = ss)); + }, + polygonEnd: function () { + var t = +as; + (us.add(t < 0 ? _f + t : t), + (this.lineStart = this.lineEnd = this.point = qf)); + }, + sphere: function () { + us.add(_f); + }, + }; + function fs() { + cs.point = ls; + } + function ss() { + hs(jf, Hf); + } + function ls(t, n) { + ((cs.point = hs), + (jf = t), + (Hf = n), + (Xf = t *= mf), + (Gf = Tf((n = (n *= mf) / 2 + vf))), + (Vf = Cf(n))); + } + function hs(t, n) { + var e = (t *= mf) - Xf, + r = e >= 0 ? 1 : -1, + i = r * e, + o = Tf((n = (n *= mf) / 2 + vf)), + a = Cf(n), + u = Vf * a, + c = Gf * o + u * Tf(i), + f = u * r * Cf(i); + (as.add(Mf(f, c)), (Xf = t), (Gf = o), (Vf = a)); + } + function ds(t) { + return [Mf(t[1], t[0]), Rf(t[2])]; + } + function ps(t) { + var n = t[0], + e = t[1], + r = Tf(e); + return [r * Tf(n), r * Cf(n), Cf(e)]; + } + function gs(t, n) { + return t[0] * n[0] + t[1] * n[1] + t[2] * n[2]; + } + function ys(t, n) { + return [ + t[1] * n[2] - t[2] * n[1], + t[2] * n[0] - t[0] * n[2], + t[0] * n[1] - t[1] * n[0], + ]; + } + function vs(t, n) { + ((t[0] += n[0]), (t[1] += n[1]), (t[2] += n[2])); + } + function _s(t, n) { + return [t[0] * n, t[1] * n, t[2] * n]; + } + function bs(t) { + var n = zf(t[0] * t[0] + t[1] * t[1] + t[2] * t[2]); + ((t[0] /= n), (t[1] /= n), (t[2] /= n)); + } + var ms, + xs, + ws, + Ms, + Ts, + As, + Ss, + Es, + Ns, + ks, + Cs, + Ps, + zs, + $s, + Ds, + Rs, + Fs = { + point: qs, + lineStart: Is, + lineEnd: Os, + polygonStart: function () { + ((Fs.point = Bs), + (Fs.lineStart = Ys), + (Fs.lineEnd = Ls), + (rs = new T()), + cs.polygonStart()); + }, + polygonEnd: function () { + (cs.polygonEnd(), + (Fs.point = qs), + (Fs.lineStart = Is), + (Fs.lineEnd = Os), + as < 0 + ? ((Wf = -(Kf = 180)), (Zf = -(Qf = 90))) + : rs > df + ? (Qf = 90) + : rs < -df && (Zf = -90), + (os[0] = Wf), + (os[1] = Kf)); + }, + sphere: function () { + ((Wf = -(Kf = 180)), (Zf = -(Qf = 90))); + }, + }; + function qs(t, n) { + (is.push((os = [(Wf = t), (Kf = t)])), + n < Zf && (Zf = n), + n > Qf && (Qf = n)); + } + function Us(t, n) { + var e = ps([t * mf, n * mf]); + if (es) { + var r = ys(es, e), + i = ys([r[1], -r[0], 0], r); + (bs(i), (i = ds(i))); + var o, + a = t - Jf, + u = a > 0 ? 1 : -1, + c = i[0] * bf * u, + f = xf(a) > 180; + (f ^ (u * Jf < c && c < u * t) + ? (o = i[1] * bf) > Qf && (Qf = o) + : f ^ (u * Jf < (c = ((c + 360) % 360) - 180) && c < u * t) + ? (o = -i[1] * bf) < Zf && (Zf = o) + : (n < Zf && (Zf = n), n > Qf && (Qf = n)), + f + ? t < Jf + ? js(Wf, t) > js(Wf, Kf) && (Kf = t) + : js(t, Kf) > js(Wf, Kf) && (Wf = t) + : Kf >= Wf + ? (t < Wf && (Wf = t), t > Kf && (Kf = t)) + : t > Jf + ? js(Wf, t) > js(Wf, Kf) && (Kf = t) + : js(t, Kf) > js(Wf, Kf) && (Wf = t)); + } else is.push((os = [(Wf = t), (Kf = t)])); + (n < Zf && (Zf = n), n > Qf && (Qf = n), (es = e), (Jf = t)); + } + function Is() { + Fs.point = Us; + } + function Os() { + ((os[0] = Wf), (os[1] = Kf), (Fs.point = qs), (es = null)); + } + function Bs(t, n) { + if (es) { + var e = t - Jf; + rs.add(xf(e) > 180 ? e + (e > 0 ? 360 : -360) : e); + } else ((ts = t), (ns = n)); + (cs.point(t, n), Us(t, n)); + } + function Ys() { + cs.lineStart(); + } + function Ls() { + (Bs(ts, ns), + cs.lineEnd(), + xf(rs) > df && (Wf = -(Kf = 180)), + (os[0] = Wf), + (os[1] = Kf), + (es = null)); + } + function js(t, n) { + return (n -= t) < 0 ? n + 360 : n; + } + function Hs(t, n) { + return t[0] - n[0]; + } + function Xs(t, n) { + return t[0] <= t[1] ? t[0] <= n && n <= t[1] : n < t[0] || t[1] < n; + } + var Gs = { + sphere: qf, + point: Vs, + lineStart: Zs, + lineEnd: Js, + polygonStart: function () { + ((Gs.lineStart = tl), (Gs.lineEnd = nl)); + }, + polygonEnd: function () { + ((Gs.lineStart = Zs), (Gs.lineEnd = Js)); + }, + }; + function Vs(t, n) { + t *= mf; + var e = Tf((n *= mf)); + Ws(e * Tf(t), e * Cf(t), Cf(n)); + } + function Ws(t, n, e) { + (++ms, (ws += (t - ws) / ms), (Ms += (n - Ms) / ms), (Ts += (e - Ts) / ms)); + } + function Zs() { + Gs.point = Ks; + } + function Ks(t, n) { + t *= mf; + var e = Tf((n *= mf)); + (($s = e * Tf(t)), + (Ds = e * Cf(t)), + (Rs = Cf(n)), + (Gs.point = Qs), + Ws($s, Ds, Rs)); + } + function Qs(t, n) { + t *= mf; + var e = Tf((n *= mf)), + r = e * Tf(t), + i = e * Cf(t), + o = Cf(n), + a = Mf( + zf( + (a = Ds * o - Rs * i) * a + + (a = Rs * r - $s * o) * a + + (a = $s * i - Ds * r) * a, + ), + $s * r + Ds * i + Rs * o, + ); + ((xs += a), + (As += a * ($s + ($s = r))), + (Ss += a * (Ds + (Ds = i))), + (Es += a * (Rs + (Rs = o))), + Ws($s, Ds, Rs)); + } + function Js() { + Gs.point = Vs; + } + function tl() { + Gs.point = el; + } + function nl() { + (rl(Ps, zs), (Gs.point = Vs)); + } + function el(t, n) { + ((Ps = t), (zs = n), (t *= mf), (n *= mf), (Gs.point = rl)); + var e = Tf(n); + (($s = e * Tf(t)), (Ds = e * Cf(t)), (Rs = Cf(n)), Ws($s, Ds, Rs)); + } + function rl(t, n) { + t *= mf; + var e = Tf((n *= mf)), + r = e * Tf(t), + i = e * Cf(t), + o = Cf(n), + a = Ds * o - Rs * i, + u = Rs * r - $s * o, + c = $s * i - Ds * r, + f = Ef(a, u, c), + s = Rf(f), + l = f && -s / f; + (Ns.add(l * a), + ks.add(l * u), + Cs.add(l * c), + (xs += s), + (As += s * ($s + ($s = r))), + (Ss += s * (Ds + (Ds = i))), + (Es += s * (Rs + (Rs = o))), + Ws($s, Ds, Rs)); + } + function il(t) { + return function () { + return t; + }; + } + function ol(t, n) { + function e(e, r) { + return ((e = t(e, r)), n(e[0], e[1])); + } + return ( + t.invert && + n.invert && + (e.invert = function (e, r) { + return (e = n.invert(e, r)) && t.invert(e[0], e[1]); + }), + e + ); + } + function al(t, n) { + return (xf(t) > gf && (t -= Math.round(t / _f) * _f), [t, n]); + } + function ul(t, n, e) { + return (t %= _f) + ? n || e + ? ol(fl(t), sl(n, e)) + : fl(t) + : n || e + ? sl(n, e) + : al; + } + function cl(t) { + return function (n, e) { + return (xf((n += t)) > gf && (n -= Math.round(n / _f) * _f), [n, e]); + }; + } + function fl(t) { + var n = cl(t); + return ((n.invert = cl(-t)), n); + } + function sl(t, n) { + var e = Tf(t), + r = Cf(t), + i = Tf(n), + o = Cf(n); + function a(t, n) { + var a = Tf(n), + u = Tf(t) * a, + c = Cf(t) * a, + f = Cf(n), + s = f * e + u * r; + return [Mf(c * i - s * o, u * e - f * r), Rf(s * i + c * o)]; + } + return ( + (a.invert = function (t, n) { + var a = Tf(n), + u = Tf(t) * a, + c = Cf(t) * a, + f = Cf(n), + s = f * i - c * o; + return [Mf(c * i + f * o, u * e + s * r), Rf(s * e - u * r)]; + }), + a + ); + } + function ll(t) { + function n(n) { + return (((n = t(n[0] * mf, n[1] * mf))[0] *= bf), (n[1] *= bf), n); + } + return ( + (t = ul(t[0] * mf, t[1] * mf, t.length > 2 ? t[2] * mf : 0)), + (n.invert = function (n) { + return ( + ((n = t.invert(n[0] * mf, n[1] * mf))[0] *= bf), + (n[1] *= bf), + n + ); + }), + n + ); + } + function hl(t, n, e, r, i, o) { + if (e) { + var a = Tf(n), + u = Cf(n), + c = r * e; + null == i + ? ((i = n + r * _f), (o = n - c / 2)) + : ((i = dl(a, i)), + (o = dl(a, o)), + (r > 0 ? i < o : i > o) && (i += r * _f)); + for (var f, s = i; r > 0 ? s > o : s < o; s -= c) + ((f = ds([a, -u * Tf(s), -u * Cf(s)])), t.point(f[0], f[1])); + } + } + function dl(t, n) { + (((n = ps(n))[0] -= t), bs(n)); + var e = Df(-n[1]); + return ((-n[2] < 0 ? -e : e) + _f - df) % _f; + } + function pl() { + var t, + n = []; + return { + point: function (n, e, r) { + t.push([n, e, r]); + }, + lineStart: function () { + n.push((t = [])); + }, + lineEnd: qf, + rejoin: function () { + n.length > 1 && n.push(n.pop().concat(n.shift())); + }, + result: function () { + var e = n; + return ((n = []), (t = null), e); + }, + }; + } + function gl(t, n) { + return xf(t[0] - n[0]) < df && xf(t[1] - n[1]) < df; + } + function yl(t, n, e, r) { + ((this.x = t), + (this.z = n), + (this.o = e), + (this.e = r), + (this.v = !1), + (this.n = this.p = null)); + } + function vl(t, n, e, r, i) { + var o, + a, + u = [], + c = []; + if ( + (t.forEach(function (t) { + if (!((n = t.length - 1) <= 0)) { + var n, + e, + r = t[0], + a = t[n]; + if (gl(r, a)) { + if (!r[2] && !a[2]) { + for (i.lineStart(), o = 0; o < n; ++o) + i.point((r = t[o])[0], r[1]); + return void i.lineEnd(); + } + a[0] += 2 * df; + } + (u.push((e = new yl(r, t, null, !0))), + c.push((e.o = new yl(r, null, e, !1))), + u.push((e = new yl(a, t, null, !1))), + c.push((e.o = new yl(a, null, e, !0)))); + } + }), + u.length) + ) { + for (c.sort(n), _l(u), _l(c), o = 0, a = c.length; o < a; ++o) + c[o].e = e = !e; + for (var f, s, l = u[0]; ; ) { + for (var h = l, d = !0; h.v; ) if ((h = h.n) === l) return; + ((f = h.z), i.lineStart()); + do { + if (((h.v = h.o.v = !0), h.e)) { + if (d) + for (o = 0, a = f.length; o < a; ++o) + i.point((s = f[o])[0], s[1]); + else r(h.x, h.n.x, 1, i); + h = h.n; + } else { + if (d) + for (f = h.p.z, o = f.length - 1; o >= 0; --o) + i.point((s = f[o])[0], s[1]); + else r(h.x, h.p.x, -1, i); + h = h.p; + } + ((f = (h = h.o).z), (d = !d)); + } while (!h.v); + i.lineEnd(); + } + } + } + function _l(t) { + if ((n = t.length)) { + for (var n, e, r = 0, i = t[0]; ++r < n; ) + ((i.n = e = t[r]), (e.p = i), (i = e)); + ((i.n = e = t[0]), (e.p = i)); + } + } + function bl(t) { + return xf(t[0]) <= gf ? t[0] : Pf(t[0]) * (((xf(t[0]) + gf) % _f) - gf); + } + function ml(t, n) { + var e = bl(n), + r = n[1], + i = Cf(r), + o = [Cf(e), -Tf(e), 0], + a = 0, + u = 0, + c = new T(); + 1 === i ? (r = yf + df) : -1 === i && (r = -yf - df); + for (var f = 0, s = t.length; f < s; ++f) + if ((h = (l = t[f]).length)) + for ( + var l, + h, + d = l[h - 1], + p = bl(d), + g = d[1] / 2 + vf, + y = Cf(g), + v = Tf(g), + _ = 0; + _ < h; + ++_, p = m, y = w, v = M, d = b + ) { + var b = l[_], + m = bl(b), + x = b[1] / 2 + vf, + w = Cf(x), + M = Tf(x), + A = m - p, + S = A >= 0 ? 1 : -1, + E = S * A, + N = E > gf, + k = y * w; + if ( + (c.add(Mf(k * S * Cf(E), v * M + k * Tf(E))), + (a += N ? A + S * _f : A), + N ^ (p >= e) ^ (m >= e)) + ) { + var C = ys(ps(d), ps(b)); + bs(C); + var P = ys(o, C); + bs(P); + var z = (N ^ (A >= 0) ? -1 : 1) * Rf(P[2]); + (r > z || (r === z && (C[0] || C[1]))) && + (u += N ^ (A >= 0) ? 1 : -1); + } + } + return (a < -df || (a < df && c < -pf)) ^ (1 & u); + } + function xl(t, n, e, r) { + return function (i) { + var o, + a, + u, + c = n(i), + f = pl(), + s = n(f), + l = !1, + h = { + point: d, + lineStart: g, + lineEnd: y, + polygonStart: function () { + ((h.point = v), + (h.lineStart = _), + (h.lineEnd = b), + (a = []), + (o = [])); + }, + polygonEnd: function () { + ((h.point = d), (h.lineStart = g), (h.lineEnd = y), (a = ft(a))); + var t = ml(o, r); + (a.length + ? (l || (i.polygonStart(), (l = !0)), vl(a, Ml, t, e, i)) + : t && + (l || (i.polygonStart(), (l = !0)), + i.lineStart(), + e(null, null, 1, i), + i.lineEnd()), + l && (i.polygonEnd(), (l = !1)), + (a = o = null)); + }, + sphere: function () { + (i.polygonStart(), + i.lineStart(), + e(null, null, 1, i), + i.lineEnd(), + i.polygonEnd()); + }, + }; + function d(n, e) { + t(n, e) && i.point(n, e); + } + function p(t, n) { + c.point(t, n); + } + function g() { + ((h.point = p), c.lineStart()); + } + function y() { + ((h.point = d), c.lineEnd()); + } + function v(t, n) { + (u.push([t, n]), s.point(t, n)); + } + function _() { + (s.lineStart(), (u = [])); + } + function b() { + (v(u[0][0], u[0][1]), s.lineEnd()); + var t, + n, + e, + r, + c = s.clean(), + h = f.result(), + d = h.length; + if ((u.pop(), o.push(u), (u = null), d)) + if (1 & c) { + if ((n = (e = h[0]).length - 1) > 0) { + for ( + l || (i.polygonStart(), (l = !0)), i.lineStart(), t = 0; + t < n; + ++t + ) + i.point((r = e[t])[0], r[1]); + i.lineEnd(); + } + } else + (d > 1 && 2 & c && h.push(h.pop().concat(h.shift())), + a.push(h.filter(wl))); + } + return h; + }; + } + function wl(t) { + return t.length > 1; + } + function Ml(t, n) { + return ( + ((t = t.x)[0] < 0 ? t[1] - yf - df : yf - t[1]) - + ((n = n.x)[0] < 0 ? n[1] - yf - df : yf - n[1]) + ); + } + al.invert = al; + var Tl = xl( + function () { + return !0; + }, + function (t) { + var n, + e = NaN, + r = NaN, + i = NaN; + return { + lineStart: function () { + (t.lineStart(), (n = 1)); + }, + point: function (o, a) { + var u = o > 0 ? gf : -gf, + c = xf(o - e); + (xf(c - gf) < df + ? (t.point(e, (r = (r + a) / 2 > 0 ? yf : -yf)), + t.point(i, r), + t.lineEnd(), + t.lineStart(), + t.point(u, r), + t.point(o, r), + (n = 0)) + : i !== u && + c >= gf && + (xf(e - i) < df && (e -= i * df), + xf(o - u) < df && (o -= u * df), + (r = (function (t, n, e, r) { + var i, + o, + a = Cf(t - e); + return xf(a) > df + ? wf( + (Cf(n) * (o = Tf(r)) * Cf(e) - + Cf(r) * (i = Tf(n)) * Cf(t)) / + (i * o * a), + ) + : (n + r) / 2; + })(e, r, o, a)), + t.point(i, r), + t.lineEnd(), + t.lineStart(), + t.point(u, r), + (n = 0)), + t.point((e = o), (r = a)), + (i = u)); + }, + lineEnd: function () { + (t.lineEnd(), (e = r = NaN)); + }, + clean: function () { + return 2 - n; + }, + }; + }, + function (t, n, e, r) { + var i; + if (null == t) + ((i = e * yf), + r.point(-gf, i), + r.point(0, i), + r.point(gf, i), + r.point(gf, 0), + r.point(gf, -i), + r.point(0, -i), + r.point(-gf, -i), + r.point(-gf, 0), + r.point(-gf, i)); + else if (xf(t[0] - n[0]) > df) { + var o = t[0] < n[0] ? gf : -gf; + ((i = (e * o) / 2), r.point(-o, i), r.point(0, i), r.point(o, i)); + } else r.point(n[0], n[1]); + }, + [-gf, -yf], + ); + function Al(t) { + var n = Tf(t), + e = 2 * mf, + r = n > 0, + i = xf(n) > df; + function o(t, e) { + return Tf(t) * Tf(e) > n; + } + function a(t, e, r) { + var i = [1, 0, 0], + o = ys(ps(t), ps(e)), + a = gs(o, o), + u = o[0], + c = a - u * u; + if (!c) return !r && t; + var f = (n * a) / c, + s = (-n * u) / c, + l = ys(i, o), + h = _s(i, f); + vs(h, _s(o, s)); + var d = l, + p = gs(h, d), + g = gs(d, d), + y = p * p - g * (gs(h, h) - 1); + if (!(y < 0)) { + var v = zf(y), + _ = _s(d, (-p - v) / g); + if ((vs(_, h), (_ = ds(_)), !r)) return _; + var b, + m = t[0], + x = e[0], + w = t[1], + M = e[1]; + x < m && ((b = m), (m = x), (x = b)); + var T = x - m, + A = xf(T - gf) < df; + if ( + (!A && M < w && ((b = w), (w = M), (M = b)), + A || T < df + ? A + ? (w + M > 0) ^ (_[1] < (xf(_[0] - m) < df ? w : M)) + : w <= _[1] && _[1] <= M + : (T > gf) ^ (m <= _[0] && _[0] <= x)) + ) { + var S = _s(d, (-p + v) / g); + return (vs(S, h), [_, ds(S)]); + } + } + } + function u(n, e) { + var i = r ? t : gf - t, + o = 0; + return ( + n < -i ? (o |= 1) : n > i && (o |= 2), + e < -i ? (o |= 4) : e > i && (o |= 8), + o + ); + } + return xl( + o, + function (t) { + var n, e, c, f, s; + return { + lineStart: function () { + ((f = c = !1), (s = 1)); + }, + point: function (l, h) { + var d, + p = [l, h], + g = o(l, h), + y = r ? (g ? 0 : u(l, h)) : g ? u(l + (l < 0 ? gf : -gf), h) : 0; + if ( + (!n && (f = c = g) && t.lineStart(), + g !== c && (!(d = a(n, p)) || gl(n, d) || gl(p, d)) && (p[2] = 1), + g !== c) + ) + ((s = 0), + g + ? (t.lineStart(), (d = a(p, n)), t.point(d[0], d[1])) + : ((d = a(n, p)), t.point(d[0], d[1], 2), t.lineEnd()), + (n = d)); + else if (i && n && r ^ g) { + var v; + y & e || + !(v = a(p, n, !0)) || + ((s = 0), + r + ? (t.lineStart(), + t.point(v[0][0], v[0][1]), + t.point(v[1][0], v[1][1]), + t.lineEnd()) + : (t.point(v[1][0], v[1][1]), + t.lineEnd(), + t.lineStart(), + t.point(v[0][0], v[0][1], 3))); + } + (!g || (n && gl(n, p)) || t.point(p[0], p[1]), + (n = p), + (c = g), + (e = y)); + }, + lineEnd: function () { + (c && t.lineEnd(), (n = null)); + }, + clean: function () { + return s | ((f && c) << 1); + }, + }; + }, + function (n, r, i, o) { + hl(o, t, e, i, n, r); + }, + r ? [0, -t] : [-gf, t - gf], + ); + } + var Sl, + El, + Nl, + kl, + Cl = 1e9, + Pl = -Cl; + function zl(t, n, e, r) { + function i(i, o) { + return t <= i && i <= e && n <= o && o <= r; + } + function o(i, o, u, f) { + var s = 0, + l = 0; + if ( + null == i || + (s = a(i, u)) !== (l = a(o, u)) || + (c(i, o) < 0) ^ (u > 0) + ) + do { + f.point(0 === s || 3 === s ? t : e, s > 1 ? r : n); + } while ((s = (s + u + 4) % 4) !== l); + else f.point(o[0], o[1]); + } + function a(r, i) { + return xf(r[0] - t) < df + ? i > 0 + ? 0 + : 3 + : xf(r[0] - e) < df + ? i > 0 + ? 2 + : 1 + : xf(r[1] - n) < df + ? i > 0 + ? 1 + : 0 + : i > 0 + ? 3 + : 2; + } + function u(t, n) { + return c(t.x, n.x); + } + function c(t, n) { + var e = a(t, 1), + r = a(n, 1); + return e !== r + ? e - r + : 0 === e + ? n[1] - t[1] + : 1 === e + ? t[0] - n[0] + : 2 === e + ? t[1] - n[1] + : n[0] - t[0]; + } + return function (a) { + var c, + f, + s, + l, + h, + d, + p, + g, + y, + v, + _, + b = a, + m = pl(), + x = { + point: w, + lineStart: function () { + ((x.point = M), f && f.push((s = []))); + ((v = !0), (y = !1), (p = g = NaN)); + }, + lineEnd: function () { + c && (M(l, h), d && y && m.rejoin(), c.push(m.result())); + ((x.point = w), y && b.lineEnd()); + }, + polygonStart: function () { + ((b = m), (c = []), (f = []), (_ = !0)); + }, + polygonEnd: function () { + var n = (function () { + for (var n = 0, e = 0, i = f.length; e < i; ++e) + for ( + var o, + a, + u = f[e], + c = 1, + s = u.length, + l = u[0], + h = l[0], + d = l[1]; + c < s; + ++c + ) + ((o = h), + (a = d), + (h = (l = u[c])[0]), + (d = l[1]), + a <= r + ? d > r && (h - o) * (r - a) > (d - a) * (t - o) && ++n + : d <= r && + (h - o) * (r - a) < (d - a) * (t - o) && + --n); + return n; + })(), + e = _ && n, + i = (c = ft(c)).length; + (e || i) && + (a.polygonStart(), + e && (a.lineStart(), o(null, null, 1, a), a.lineEnd()), + i && vl(c, u, n, o, a), + a.polygonEnd()); + ((b = a), (c = f = s = null)); + }, + }; + function w(t, n) { + i(t, n) && b.point(t, n); + } + function M(o, a) { + var u = i(o, a); + if ((f && s.push([o, a]), v)) + ((l = o), + (h = a), + (d = u), + (v = !1), + u && (b.lineStart(), b.point(o, a))); + else if (u && y) b.point(o, a); + else { + var c = [ + (p = Math.max(Pl, Math.min(Cl, p))), + (g = Math.max(Pl, Math.min(Cl, g))), + ], + m = [ + (o = Math.max(Pl, Math.min(Cl, o))), + (a = Math.max(Pl, Math.min(Cl, a))), + ]; + !(function (t, n, e, r, i, o) { + var a, + u = t[0], + c = t[1], + f = 0, + s = 1, + l = n[0] - u, + h = n[1] - c; + if (((a = e - u), l || !(a > 0))) { + if (((a /= l), l < 0)) { + if (a < f) return; + a < s && (s = a); + } else if (l > 0) { + if (a > s) return; + a > f && (f = a); + } + if (((a = i - u), l || !(a < 0))) { + if (((a /= l), l < 0)) { + if (a > s) return; + a > f && (f = a); + } else if (l > 0) { + if (a < f) return; + a < s && (s = a); + } + if (((a = r - c), h || !(a > 0))) { + if (((a /= h), h < 0)) { + if (a < f) return; + a < s && (s = a); + } else if (h > 0) { + if (a > s) return; + a > f && (f = a); + } + if (((a = o - c), h || !(a < 0))) { + if (((a /= h), h < 0)) { + if (a > s) return; + a > f && (f = a); + } else if (h > 0) { + if (a < f) return; + a < s && (s = a); + } + return ( + f > 0 && ((t[0] = u + f * l), (t[1] = c + f * h)), + s < 1 && ((n[0] = u + s * l), (n[1] = c + s * h)), + !0 + ); + } + } + } + } + })(c, m, t, n, e, r) + ? u && (b.lineStart(), b.point(o, a), (_ = !1)) + : (y || (b.lineStart(), b.point(c[0], c[1])), + b.point(m[0], m[1]), + u || b.lineEnd(), + (_ = !1)); + } + ((p = o), (g = a), (y = u)); + } + return x; + }; + } + var $l = { + sphere: qf, + point: qf, + lineStart: function () { + (($l.point = Rl), ($l.lineEnd = Dl)); + }, + lineEnd: qf, + polygonStart: qf, + polygonEnd: qf, + }; + function Dl() { + $l.point = $l.lineEnd = qf; + } + function Rl(t, n) { + ((El = t *= mf), (Nl = Cf((n *= mf))), (kl = Tf(n)), ($l.point = Fl)); + } + function Fl(t, n) { + t *= mf; + var e = Cf((n *= mf)), + r = Tf(n), + i = xf(t - El), + o = Tf(i), + a = r * Cf(i), + u = kl * e - Nl * r * o, + c = Nl * e + kl * r * o; + (Sl.add(Mf(zf(a * a + u * u), c)), (El = t), (Nl = e), (kl = r)); + } + function ql(t) { + return ((Sl = new T()), Lf(t, $l), +Sl); + } + var Ul = [null, null], + Il = { type: "LineString", coordinates: Ul }; + function Ol(t, n) { + return ((Ul[0] = t), (Ul[1] = n), ql(Il)); + } + var Bl = { + Feature: function (t, n) { + return Ll(t.geometry, n); + }, + FeatureCollection: function (t, n) { + for (var e = t.features, r = -1, i = e.length; ++r < i; ) + if (Ll(e[r].geometry, n)) return !0; + return !1; + }, + }, + Yl = { + Sphere: function () { + return !0; + }, + Point: function (t, n) { + return jl(t.coordinates, n); + }, + MultiPoint: function (t, n) { + for (var e = t.coordinates, r = -1, i = e.length; ++r < i; ) + if (jl(e[r], n)) return !0; + return !1; + }, + LineString: function (t, n) { + return Hl(t.coordinates, n); + }, + MultiLineString: function (t, n) { + for (var e = t.coordinates, r = -1, i = e.length; ++r < i; ) + if (Hl(e[r], n)) return !0; + return !1; + }, + Polygon: function (t, n) { + return Xl(t.coordinates, n); + }, + MultiPolygon: function (t, n) { + for (var e = t.coordinates, r = -1, i = e.length; ++r < i; ) + if (Xl(e[r], n)) return !0; + return !1; + }, + GeometryCollection: function (t, n) { + for (var e = t.geometries, r = -1, i = e.length; ++r < i; ) + if (Ll(e[r], n)) return !0; + return !1; + }, + }; + function Ll(t, n) { + return !(!t || !Yl.hasOwnProperty(t.type)) && Yl[t.type](t, n); + } + function jl(t, n) { + return 0 === Ol(t, n); + } + function Hl(t, n) { + for (var e, r, i, o = 0, a = t.length; o < a; o++) { + if (0 === (r = Ol(t[o], n))) return !0; + if ( + o > 0 && + (i = Ol(t[o], t[o - 1])) > 0 && + e <= i && + r <= i && + (e + r - i) * (1 - Math.pow((e - r) / i, 2)) < pf * i + ) + return !0; + e = r; + } + return !1; + } + function Xl(t, n) { + return !!ml(t.map(Gl), Vl(n)); + } + function Gl(t) { + return ((t = t.map(Vl)).pop(), t); + } + function Vl(t) { + return [t[0] * mf, t[1] * mf]; + } + function Wl(t, n, e) { + var r = lt(t, n - df, e).concat(n); + return function (t) { + return r.map(function (n) { + return [t, n]; + }); + }; + } + function Zl(t, n, e) { + var r = lt(t, n - df, e).concat(n); + return function (t) { + return r.map(function (n) { + return [n, t]; + }); + }; + } + function Kl() { + var t, + n, + e, + r, + i, + o, + a, + u, + c, + f, + s, + l, + h = 10, + d = h, + p = 90, + g = 360, + y = 2.5; + function v() { + return { type: "MultiLineString", coordinates: _() }; + } + function _() { + return lt(Af(r / p) * p, e, p) + .map(s) + .concat(lt(Af(u / g) * g, a, g).map(l)) + .concat( + lt(Af(n / h) * h, t, h) + .filter(function (t) { + return xf(t % p) > df; + }) + .map(c), + ) + .concat( + lt(Af(o / d) * d, i, d) + .filter(function (t) { + return xf(t % g) > df; + }) + .map(f), + ); + } + return ( + (v.lines = function () { + return _().map(function (t) { + return { type: "LineString", coordinates: t }; + }); + }), + (v.outline = function () { + return { + type: "Polygon", + coordinates: [ + s(r).concat( + l(a).slice(1), + s(e).reverse().slice(1), + l(u).reverse().slice(1), + ), + ], + }; + }), + (v.extent = function (t) { + return arguments.length + ? v.extentMajor(t).extentMinor(t) + : v.extentMinor(); + }), + (v.extentMajor = function (t) { + return arguments.length + ? ((r = +t[0][0]), + (e = +t[1][0]), + (u = +t[0][1]), + (a = +t[1][1]), + r > e && ((t = r), (r = e), (e = t)), + u > a && ((t = u), (u = a), (a = t)), + v.precision(y)) + : [ + [r, u], + [e, a], + ]; + }), + (v.extentMinor = function (e) { + return arguments.length + ? ((n = +e[0][0]), + (t = +e[1][0]), + (o = +e[0][1]), + (i = +e[1][1]), + n > t && ((e = n), (n = t), (t = e)), + o > i && ((e = o), (o = i), (i = e)), + v.precision(y)) + : [ + [n, o], + [t, i], + ]; + }), + (v.step = function (t) { + return arguments.length ? v.stepMajor(t).stepMinor(t) : v.stepMinor(); + }), + (v.stepMajor = function (t) { + return arguments.length ? ((p = +t[0]), (g = +t[1]), v) : [p, g]; + }), + (v.stepMinor = function (t) { + return arguments.length ? ((h = +t[0]), (d = +t[1]), v) : [h, d]; + }), + (v.precision = function (h) { + return arguments.length + ? ((y = +h), + (c = Wl(o, i, 90)), + (f = Zl(n, t, y)), + (s = Wl(u, a, 90)), + (l = Zl(r, e, y)), + v) + : y; + }), + v + .extentMajor([ + [-180, -90 + df], + [180, 90 - df], + ]) + .extentMinor([ + [-180, -80 - df], + [180, 80 + df], + ]) + ); + } + var Ql, + Jl, + th, + nh, + eh = (t) => t, + rh = new T(), + ih = new T(), + oh = { + point: qf, + lineStart: qf, + lineEnd: qf, + polygonStart: function () { + ((oh.lineStart = ah), (oh.lineEnd = fh)); + }, + polygonEnd: function () { + ((oh.lineStart = oh.lineEnd = oh.point = qf), + rh.add(xf(ih)), + (ih = new T())); + }, + result: function () { + var t = rh / 2; + return ((rh = new T()), t); + }, + }; + function ah() { + oh.point = uh; + } + function uh(t, n) { + ((oh.point = ch), (Ql = th = t), (Jl = nh = n)); + } + function ch(t, n) { + (ih.add(nh * t - th * n), (th = t), (nh = n)); + } + function fh() { + ch(Ql, Jl); + } + var sh = oh, + lh = 1 / 0, + hh = lh, + dh = -lh, + ph = dh, + gh = { + point: function (t, n) { + t < lh && (lh = t); + t > dh && (dh = t); + n < hh && (hh = n); + n > ph && (ph = n); + }, + lineStart: qf, + lineEnd: qf, + polygonStart: qf, + polygonEnd: qf, + result: function () { + var t = [ + [lh, hh], + [dh, ph], + ]; + return ((dh = ph = -(hh = lh = 1 / 0)), t); + }, + }; + var yh, + vh, + _h, + bh, + mh = gh, + xh = 0, + wh = 0, + Mh = 0, + Th = 0, + Ah = 0, + Sh = 0, + Eh = 0, + Nh = 0, + kh = 0, + Ch = { + point: Ph, + lineStart: zh, + lineEnd: Rh, + polygonStart: function () { + ((Ch.lineStart = Fh), (Ch.lineEnd = qh)); + }, + polygonEnd: function () { + ((Ch.point = Ph), (Ch.lineStart = zh), (Ch.lineEnd = Rh)); + }, + result: function () { + var t = kh + ? [Eh / kh, Nh / kh] + : Sh + ? [Th / Sh, Ah / Sh] + : Mh + ? [xh / Mh, wh / Mh] + : [NaN, NaN]; + return ((xh = wh = Mh = Th = Ah = Sh = Eh = Nh = kh = 0), t); + }, + }; + function Ph(t, n) { + ((xh += t), (wh += n), ++Mh); + } + function zh() { + Ch.point = $h; + } + function $h(t, n) { + ((Ch.point = Dh), Ph((_h = t), (bh = n))); + } + function Dh(t, n) { + var e = t - _h, + r = n - bh, + i = zf(e * e + r * r); + ((Th += (i * (_h + t)) / 2), + (Ah += (i * (bh + n)) / 2), + (Sh += i), + Ph((_h = t), (bh = n))); + } + function Rh() { + Ch.point = Ph; + } + function Fh() { + Ch.point = Uh; + } + function qh() { + Ih(yh, vh); + } + function Uh(t, n) { + ((Ch.point = Ih), Ph((yh = _h = t), (vh = bh = n))); + } + function Ih(t, n) { + var e = t - _h, + r = n - bh, + i = zf(e * e + r * r); + ((Th += (i * (_h + t)) / 2), + (Ah += (i * (bh + n)) / 2), + (Sh += i), + (Eh += (i = bh * t - _h * n) * (_h + t)), + (Nh += i * (bh + n)), + (kh += 3 * i), + Ph((_h = t), (bh = n))); + } + var Oh = Ch; + function Bh(t) { + this._context = t; + } + Bh.prototype = { + _radius: 4.5, + pointRadius: function (t) { + return ((this._radius = t), this); + }, + polygonStart: function () { + this._line = 0; + }, + polygonEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + (0 === this._line && this._context.closePath(), (this._point = NaN)); + }, + point: function (t, n) { + switch (this._point) { + case 0: + (this._context.moveTo(t, n), (this._point = 1)); + break; + case 1: + this._context.lineTo(t, n); + break; + default: + (this._context.moveTo(t + this._radius, n), + this._context.arc(t, n, this._radius, 0, _f)); + } + }, + result: qf, + }; + var Yh, + Lh, + jh, + Hh, + Xh, + Gh = new T(), + Vh = { + point: qf, + lineStart: function () { + Vh.point = Wh; + }, + lineEnd: function () { + (Yh && Zh(Lh, jh), (Vh.point = qf)); + }, + polygonStart: function () { + Yh = !0; + }, + polygonEnd: function () { + Yh = null; + }, + result: function () { + var t = +Gh; + return ((Gh = new T()), t); + }, + }; + function Wh(t, n) { + ((Vh.point = Zh), (Lh = Hh = t), (jh = Xh = n)); + } + function Zh(t, n) { + ((Hh -= t), (Xh -= n), Gh.add(zf(Hh * Hh + Xh * Xh)), (Hh = t), (Xh = n)); + } + var Kh = Vh; + let Qh, Jh, td, nd; + class ed { + constructor(t) { + ((this._append = + null == t + ? rd + : (function (t) { + const n = Math.floor(t); + if (!(n >= 0)) throw new RangeError(`invalid digits: ${t}`); + if (n > 15) return rd; + if (n !== Qh) { + const t = 10 ** n; + ((Qh = n), + (Jh = function (n) { + let e = 1; + this._ += n[0]; + for (const r = n.length; e < r; ++e) + this._ += Math.round(arguments[e] * t) / t + n[e]; + })); + } + return Jh; + })(t)), + (this._radius = 4.5), + (this._ = "")); + } + pointRadius(t) { + return ((this._radius = +t), this); + } + polygonStart() { + this._line = 0; + } + polygonEnd() { + this._line = NaN; + } + lineStart() { + this._point = 0; + } + lineEnd() { + (0 === this._line && (this._ += "Z"), (this._point = NaN)); + } + point(t, n) { + switch (this._point) { + case 0: + (this._append`M${t},${n}`, (this._point = 1)); + break; + case 1: + this._append`L${t},${n}`; + break; + default: + if ( + (this._append`M${t},${n}`, + this._radius !== td || this._append !== Jh) + ) { + const t = this._radius, + n = this._; + ((this._ = ""), + this + ._append`m0,${t}a${t},${t} 0 1,1 0,${-2 * t}a${t},${t} 0 1,1 0,${2 * t}z`, + (td = t), + (Jh = this._append), + (nd = this._), + (this._ = n)); + } + this._ += nd; + } + } + result() { + const t = this._; + return ((this._ = ""), t.length ? t : null); + } + } + function rd(t) { + let n = 1; + this._ += t[0]; + for (const e = t.length; n < e; ++n) this._ += arguments[n] + t[n]; + } + function id(t) { + return function (n) { + var e = new od(); + for (var r in t) e[r] = t[r]; + return ((e.stream = n), e); + }; + } + function od() {} + function ad(t, n, e) { + var r = t.clipExtent && t.clipExtent(); + return ( + t.scale(150).translate([0, 0]), + null != r && t.clipExtent(null), + Lf(e, t.stream(mh)), + n(mh.result()), + null != r && t.clipExtent(r), + t + ); + } + function ud(t, n, e) { + return ad( + t, + function (e) { + var r = n[1][0] - n[0][0], + i = n[1][1] - n[0][1], + o = Math.min(r / (e[1][0] - e[0][0]), i / (e[1][1] - e[0][1])), + a = +n[0][0] + (r - o * (e[1][0] + e[0][0])) / 2, + u = +n[0][1] + (i - o * (e[1][1] + e[0][1])) / 2; + t.scale(150 * o).translate([a, u]); + }, + e, + ); + } + function cd(t, n, e) { + return ud(t, [[0, 0], n], e); + } + function fd(t, n, e) { + return ad( + t, + function (e) { + var r = +n, + i = r / (e[1][0] - e[0][0]), + o = (r - i * (e[1][0] + e[0][0])) / 2, + a = -i * e[0][1]; + t.scale(150 * i).translate([o, a]); + }, + e, + ); + } + function sd(t, n, e) { + return ad( + t, + function (e) { + var r = +n, + i = r / (e[1][1] - e[0][1]), + o = -i * e[0][0], + a = (r - i * (e[1][1] + e[0][1])) / 2; + t.scale(150 * i).translate([o, a]); + }, + e, + ); + } + od.prototype = { + constructor: od, + point: function (t, n) { + this.stream.point(t, n); + }, + sphere: function () { + this.stream.sphere(); + }, + lineStart: function () { + this.stream.lineStart(); + }, + lineEnd: function () { + this.stream.lineEnd(); + }, + polygonStart: function () { + this.stream.polygonStart(); + }, + polygonEnd: function () { + this.stream.polygonEnd(); + }, + }; + var ld = 16, + hd = Tf(30 * mf); + function dd(t, n) { + return +n + ? (function (t, n) { + function e(r, i, o, a, u, c, f, s, l, h, d, p, g, y) { + var v = f - r, + _ = s - i, + b = v * v + _ * _; + if (b > 4 * n && g--) { + var m = a + h, + x = u + d, + w = c + p, + M = zf(m * m + x * x + w * w), + T = Rf((w /= M)), + A = + xf(xf(w) - 1) < df || xf(o - l) < df ? (o + l) / 2 : Mf(x, m), + S = t(A, T), + E = S[0], + N = S[1], + k = E - r, + C = N - i, + P = _ * k - v * C; + ((P * P) / b > n || + xf((v * k + _ * C) / b - 0.5) > 0.3 || + a * h + u * d + c * p < hd) && + (e(r, i, o, a, u, c, E, N, A, (m /= M), (x /= M), w, g, y), + y.point(E, N), + e(E, N, A, m, x, w, f, s, l, h, d, p, g, y)); + } + } + return function (n) { + var r, + i, + o, + a, + u, + c, + f, + s, + l, + h, + d, + p, + g = { + point: y, + lineStart: v, + lineEnd: b, + polygonStart: function () { + (n.polygonStart(), (g.lineStart = m)); + }, + polygonEnd: function () { + (n.polygonEnd(), (g.lineStart = v)); + }, + }; + function y(e, r) { + ((e = t(e, r)), n.point(e[0], e[1])); + } + function v() { + ((s = NaN), (g.point = _), n.lineStart()); + } + function _(r, i) { + var o = ps([r, i]), + a = t(r, i); + (e( + s, + l, + f, + h, + d, + p, + (s = a[0]), + (l = a[1]), + (f = r), + (h = o[0]), + (d = o[1]), + (p = o[2]), + ld, + n, + ), + n.point(s, l)); + } + function b() { + ((g.point = y), n.lineEnd()); + } + function m() { + (v(), (g.point = x), (g.lineEnd = w)); + } + function x(t, n) { + (_((r = t), n), + (i = s), + (o = l), + (a = h), + (u = d), + (c = p), + (g.point = _)); + } + function w() { + (e(s, l, f, h, d, p, i, o, r, a, u, c, ld, n), + (g.lineEnd = b), + b()); + } + return g; + }; + })(t, n) + : (function (t) { + return id({ + point: function (n, e) { + ((n = t(n, e)), this.stream.point(n[0], n[1])); + }, + }); + })(t); + } + var pd = id({ + point: function (t, n) { + this.stream.point(t * mf, n * mf); + }, + }); + function gd(t, n, e, r, i, o) { + if (!o) + return (function (t, n, e, r, i) { + function o(o, a) { + return [n + t * (o *= r), e - t * (a *= i)]; + } + return ( + (o.invert = function (o, a) { + return [((o - n) / t) * r, ((e - a) / t) * i]; + }), + o + ); + })(t, n, e, r, i); + var a = Tf(o), + u = Cf(o), + c = a * t, + f = u * t, + s = a / t, + l = u / t, + h = (u * e - a * n) / t, + d = (u * n + a * e) / t; + function p(t, o) { + return [c * (t *= r) - f * (o *= i) + n, e - f * t - c * o]; + } + return ( + (p.invert = function (t, n) { + return [r * (s * t - l * n + h), i * (d - l * t - s * n)]; + }), + p + ); + } + function yd(t) { + return vd(function () { + return t; + })(); + } + function vd(t) { + var n, + e, + r, + i, + o, + a, + u, + c, + f, + s, + l = 150, + h = 480, + d = 250, + p = 0, + g = 0, + y = 0, + v = 0, + _ = 0, + b = 0, + m = 1, + x = 1, + w = null, + M = Tl, + T = null, + A = eh, + S = 0.5; + function E(t) { + return c(t[0] * mf, t[1] * mf); + } + function N(t) { + return (t = c.invert(t[0], t[1])) && [t[0] * bf, t[1] * bf]; + } + function k() { + var t = gd(l, 0, 0, m, x, b).apply(null, n(p, g)), + r = gd(l, h - t[0], d - t[1], m, x, b); + return ( + (e = ul(y, v, _)), + (u = ol(n, r)), + (c = ol(e, u)), + (a = dd(u, S)), + C() + ); + } + function C() { + return ((f = s = null), E); + } + return ( + (E.stream = function (t) { + return f && s === t + ? f + : (f = pd( + (function (t) { + return id({ + point: function (n, e) { + var r = t(n, e); + return this.stream.point(r[0], r[1]); + }, + }); + })(e)(M(a(A((s = t))))), + )); + }), + (E.preclip = function (t) { + return arguments.length ? ((M = t), (w = void 0), C()) : M; + }), + (E.postclip = function (t) { + return arguments.length ? ((A = t), (T = r = i = o = null), C()) : A; + }), + (E.clipAngle = function (t) { + return arguments.length + ? ((M = +t ? Al((w = t * mf)) : ((w = null), Tl)), C()) + : w * bf; + }), + (E.clipExtent = function (t) { + return arguments.length + ? ((A = + null == t + ? ((T = r = i = o = null), eh) + : zl( + (T = +t[0][0]), + (r = +t[0][1]), + (i = +t[1][0]), + (o = +t[1][1]), + )), + C()) + : null == T + ? null + : [ + [T, r], + [i, o], + ]; + }), + (E.scale = function (t) { + return arguments.length ? ((l = +t), k()) : l; + }), + (E.translate = function (t) { + return arguments.length ? ((h = +t[0]), (d = +t[1]), k()) : [h, d]; + }), + (E.center = function (t) { + return arguments.length + ? ((p = (t[0] % 360) * mf), (g = (t[1] % 360) * mf), k()) + : [p * bf, g * bf]; + }), + (E.rotate = function (t) { + return arguments.length + ? ((y = (t[0] % 360) * mf), + (v = (t[1] % 360) * mf), + (_ = t.length > 2 ? (t[2] % 360) * mf : 0), + k()) + : [y * bf, v * bf, _ * bf]; + }), + (E.angle = function (t) { + return arguments.length ? ((b = (t % 360) * mf), k()) : b * bf; + }), + (E.reflectX = function (t) { + return arguments.length ? ((m = t ? -1 : 1), k()) : m < 0; + }), + (E.reflectY = function (t) { + return arguments.length ? ((x = t ? -1 : 1), k()) : x < 0; + }), + (E.precision = function (t) { + return arguments.length ? ((a = dd(u, (S = t * t))), C()) : zf(S); + }), + (E.fitExtent = function (t, n) { + return ud(E, t, n); + }), + (E.fitSize = function (t, n) { + return cd(E, t, n); + }), + (E.fitWidth = function (t, n) { + return fd(E, t, n); + }), + (E.fitHeight = function (t, n) { + return sd(E, t, n); + }), + function () { + return ( + (n = t.apply(this, arguments)), + (E.invert = n.invert && N), + k() + ); + } + ); + } + function _d(t) { + var n = 0, + e = gf / 3, + r = vd(t), + i = r(n, e); + return ( + (i.parallels = function (t) { + return arguments.length + ? r((n = t[0] * mf), (e = t[1] * mf)) + : [n * bf, e * bf]; + }), + i + ); + } + function bd(t, n) { + var e = Cf(t), + r = (e + Cf(n)) / 2; + if (xf(r) < df) + return (function (t) { + var n = Tf(t); + function e(t, e) { + return [t * n, Cf(e) / n]; + } + return ( + (e.invert = function (t, e) { + return [t / n, Rf(e * n)]; + }), + e + ); + })(t); + var i = 1 + e * (2 * r - e), + o = zf(i) / r; + function a(t, n) { + var e = zf(i - 2 * r * Cf(n)) / r; + return [e * Cf((t *= r)), o - e * Tf(t)]; + } + return ( + (a.invert = function (t, n) { + var e = o - n, + a = Mf(t, xf(e)) * Pf(e); + return ( + e * r < 0 && (a -= gf * Pf(t) * Pf(e)), + [a / r, Rf((i - (t * t + e * e) * r * r) / (2 * r))] + ); + }), + a + ); + } + function md() { + return _d(bd).scale(155.424).center([0, 33.6442]); + } + function xd() { + return md() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); + } + function wd(t) { + return function (n, e) { + var r = Tf(n), + i = Tf(e), + o = t(r * i); + return o === 1 / 0 ? [2, 0] : [o * i * Cf(n), o * Cf(e)]; + }; + } + function Md(t) { + return function (n, e) { + var r = zf(n * n + e * e), + i = t(r), + o = Cf(i), + a = Tf(i); + return [Mf(n * o, r * a), Rf(r && (e * o) / r)]; + }; + } + var Td = wd(function (t) { + return zf(2 / (1 + t)); + }); + Td.invert = Md(function (t) { + return 2 * Rf(t / 2); + }); + var Ad = wd(function (t) { + return (t = Df(t)) && t / Cf(t); + }); + function Sd(t, n) { + return [t, Nf($f((yf + n) / 2))]; + } + function Ed(t) { + var n, + e, + r, + i = yd(t), + o = i.center, + a = i.scale, + u = i.translate, + c = i.clipExtent, + f = null; + function s() { + var o = gf * a(), + u = i(ll(i.rotate()).invert([0, 0])); + return c( + null == f + ? [ + [u[0] - o, u[1] - o], + [u[0] + o, u[1] + o], + ] + : t === Sd + ? [ + [Math.max(u[0] - o, f), n], + [Math.min(u[0] + o, e), r], + ] + : [ + [f, Math.max(u[1] - o, n)], + [e, Math.min(u[1] + o, r)], + ], + ); + } + return ( + (i.scale = function (t) { + return arguments.length ? (a(t), s()) : a(); + }), + (i.translate = function (t) { + return arguments.length ? (u(t), s()) : u(); + }), + (i.center = function (t) { + return arguments.length ? (o(t), s()) : o(); + }), + (i.clipExtent = function (t) { + return arguments.length + ? (null == t + ? (f = n = e = r = null) + : ((f = +t[0][0]), + (n = +t[0][1]), + (e = +t[1][0]), + (r = +t[1][1])), + s()) + : null == f + ? null + : [ + [f, n], + [e, r], + ]; + }), + s() + ); + } + function Nd(t) { + return $f((yf + t) / 2); + } + function kd(t, n) { + var e = Tf(t), + r = t === n ? Cf(t) : Nf(e / Tf(n)) / Nf(Nd(n) / Nd(t)), + i = (e * kf(Nd(t), r)) / r; + if (!r) return Sd; + function o(t, n) { + i > 0 ? n < -yf + df && (n = -yf + df) : n > yf - df && (n = yf - df); + var e = i / kf(Nd(n), r); + return [e * Cf(r * t), i - e * Tf(r * t)]; + } + return ( + (o.invert = function (t, n) { + var e = i - n, + o = Pf(r) * zf(t * t + e * e), + a = Mf(t, xf(e)) * Pf(e); + return ( + e * r < 0 && (a -= gf * Pf(t) * Pf(e)), + [a / r, 2 * wf(kf(i / o, 1 / r)) - yf] + ); + }), + o + ); + } + function Cd(t, n) { + return [t, n]; + } + function Pd(t, n) { + var e = Tf(t), + r = t === n ? Cf(t) : (e - Tf(n)) / (n - t), + i = e / r + t; + if (xf(r) < df) return Cd; + function o(t, n) { + var e = i - n, + o = r * t; + return [e * Cf(o), i - e * Tf(o)]; + } + return ( + (o.invert = function (t, n) { + var e = i - n, + o = Mf(t, xf(e)) * Pf(e); + return ( + e * r < 0 && (o -= gf * Pf(t) * Pf(e)), + [o / r, i - Pf(r) * zf(t * t + e * e)] + ); + }), + o + ); + } + ((Ad.invert = Md(function (t) { + return t; + })), + (Sd.invert = function (t, n) { + return [t, 2 * wf(Sf(n)) - yf]; + }), + (Cd.invert = Cd)); + var zd = 1.340264, + $d = -0.081106, + Dd = 893e-6, + Rd = 0.003796, + Fd = zf(3) / 2; + function qd(t, n) { + var e = Rf(Fd * Cf(n)), + r = e * e, + i = r * r * r; + return [ + (t * Tf(e)) / (Fd * (zd + 3 * $d * r + i * (7 * Dd + 9 * Rd * r))), + e * (zd + $d * r + i * (Dd + Rd * r)), + ]; + } + function Ud(t, n) { + var e = Tf(n), + r = Tf(t) * e; + return [(e * Cf(t)) / r, Cf(n) / r]; + } + function Id(t, n) { + var e = n * n, + r = e * e; + return [ + t * + (0.8707 - + 0.131979 * e + + r * (r * (0.003971 * e - 0.001529 * r) - 0.013791)), + n * + (1.007226 + + e * (0.015085 + r * (0.028874 * e - 0.044475 - 0.005916 * r))), + ]; + } + function Od(t, n) { + return [Tf(n) * Cf(t), Cf(n)]; + } + function Bd(t, n) { + var e = Tf(n), + r = 1 + Tf(t) * e; + return [(e * Cf(t)) / r, Cf(n) / r]; + } + function Yd(t, n) { + return [Nf($f((yf + n) / 2)), -t]; + } + function Ld(t, n) { + return t.parent === n.parent ? 1 : 2; + } + function jd(t, n) { + return t + n.x; + } + function Hd(t, n) { + return Math.max(t, n.y); + } + function Xd(t) { + var n = 0, + e = t.children, + r = e && e.length; + if (r) for (; --r >= 0; ) n += e[r].value; + else n = 1; + t.value = n; + } + function Gd(t, n) { + t instanceof Map + ? ((t = [void 0, t]), void 0 === n && (n = Wd)) + : void 0 === n && (n = Vd); + for (var e, r, i, o, a, u = new Qd(t), c = [u]; (e = c.pop()); ) + if ((i = n(e.data)) && (a = (i = Array.from(i)).length)) + for (e.children = i, o = a - 1; o >= 0; --o) + (c.push((r = i[o] = new Qd(i[o]))), + (r.parent = e), + (r.depth = e.depth + 1)); + return u.eachBefore(Kd); + } + function Vd(t) { + return t.children; + } + function Wd(t) { + return Array.isArray(t) ? t[1] : null; + } + function Zd(t) { + (void 0 !== t.data.value && (t.value = t.data.value), + (t.data = t.data.data)); + } + function Kd(t) { + var n = 0; + do { + t.height = n; + } while ((t = t.parent) && t.height < ++n); + } + function Qd(t) { + ((this.data = t), (this.depth = this.height = 0), (this.parent = null)); + } + function Jd(t) { + return null == t ? null : tp(t); + } + function tp(t) { + if ("function" != typeof t) throw new Error(); + return t; + } + function np() { + return 0; + } + function ep(t) { + return function () { + return t; + }; + } + ((qd.invert = function (t, n) { + for ( + var e, r = n, i = r * r, o = i * i * i, a = 0; + a < 12 && + ((o = + (i = + (r -= e = + (r * (zd + $d * i + o * (Dd + Rd * i)) - n) / + (zd + 3 * $d * i + o * (7 * Dd + 9 * Rd * i))) * r) * + i * + i), + !(xf(e) < pf)); + ++a + ); + return [ + (Fd * t * (zd + 3 * $d * i + o * (7 * Dd + 9 * Rd * i))) / Tf(r), + Rf(Cf(r) / Fd), + ]; + }), + (Ud.invert = Md(wf)), + (Id.invert = function (t, n) { + var e, + r = n, + i = 25; + do { + var o = r * r, + a = o * o; + r -= e = + (r * + (1.007226 + + o * (0.015085 + a * (0.028874 * o - 0.044475 - 0.005916 * a))) - + n) / + (1.007226 + + o * (0.045255 + a * (0.259866 * o - 0.311325 - 0.005916 * 11 * a))); + } while (xf(e) > df && --i > 0); + return [ + t / + (0.8707 + + (o = r * r) * + (o * (o * o * o * (0.003971 - 0.001529 * o) - 0.013791) - + 0.131979)), + r, + ]; + }), + (Od.invert = Md(Rf)), + (Bd.invert = Md(function (t) { + return 2 * wf(t); + })), + (Yd.invert = function (t, n) { + return [-n, 2 * wf(Sf(t)) - yf]; + }), + (Qd.prototype = Gd.prototype = + { + constructor: Qd, + count: function () { + return this.eachAfter(Xd); + }, + each: function (t, n) { + let e = -1; + for (const r of this) t.call(n, r, ++e, this); + return this; + }, + eachAfter: function (t, n) { + for (var e, r, i, o = this, a = [o], u = [], c = -1; (o = a.pop()); ) + if ((u.push(o), (e = o.children))) + for (r = 0, i = e.length; r < i; ++r) a.push(e[r]); + for (; (o = u.pop()); ) t.call(n, o, ++c, this); + return this; + }, + eachBefore: function (t, n) { + for (var e, r, i = this, o = [i], a = -1; (i = o.pop()); ) + if ((t.call(n, i, ++a, this), (e = i.children))) + for (r = e.length - 1; r >= 0; --r) o.push(e[r]); + return this; + }, + find: function (t, n) { + let e = -1; + for (const r of this) if (t.call(n, r, ++e, this)) return r; + }, + sum: function (t) { + return this.eachAfter(function (n) { + for ( + var e = +t(n.data) || 0, r = n.children, i = r && r.length; + --i >= 0; + + ) + e += r[i].value; + n.value = e; + }); + }, + sort: function (t) { + return this.eachBefore(function (n) { + n.children && n.children.sort(t); + }); + }, + path: function (t) { + for ( + var n = this, + e = (function (t, n) { + if (t === n) return t; + var e = t.ancestors(), + r = n.ancestors(), + i = null; + ((t = e.pop()), (n = r.pop())); + for (; t === n; ) ((i = t), (t = e.pop()), (n = r.pop())); + return i; + })(n, t), + r = [n]; + n !== e; + + ) + ((n = n.parent), r.push(n)); + for (var i = r.length; t !== e; ) (r.splice(i, 0, t), (t = t.parent)); + return r; + }, + ancestors: function () { + for (var t = this, n = [t]; (t = t.parent); ) n.push(t); + return n; + }, + descendants: function () { + return Array.from(this); + }, + leaves: function () { + var t = []; + return ( + this.eachBefore(function (n) { + n.children || t.push(n); + }), + t + ); + }, + links: function () { + var t = this, + n = []; + return ( + t.each(function (e) { + e !== t && n.push({ source: e.parent, target: e }); + }), + n + ); + }, + copy: function () { + return Gd(this).eachBefore(Zd); + }, + [Symbol.iterator]: function* () { + var t, + n, + e, + r, + i = this, + o = [i]; + do { + for (t = o.reverse(), o = []; (i = t.pop()); ) + if ((yield i, (n = i.children))) + for (e = 0, r = n.length; e < r; ++e) o.push(n[e]); + } while (o.length); + }, + })); + const rp = 1664525, + ip = 1013904223, + op = 4294967296; + function ap() { + let t = 1; + return () => (t = (rp * t + ip) % op) / op; + } + function up(t, n) { + for ( + var e, + r, + i = 0, + o = (t = (function (t, n) { + let e, + r, + i = t.length; + for (; i; ) + ((r = (n() * i--) | 0), (e = t[i]), (t[i] = t[r]), (t[r] = e)); + return t; + })(Array.from(t), n)).length, + a = []; + i < o; + + ) + ((e = t[i]), r && sp(r, e) ? ++i : ((r = hp((a = cp(a, e)))), (i = 0))); + return r; + } + function cp(t, n) { + var e, r; + if (lp(n, t)) return [n]; + for (e = 0; e < t.length; ++e) + if (fp(n, t[e]) && lp(dp(t[e], n), t)) return [t[e], n]; + for (e = 0; e < t.length - 1; ++e) + for (r = e + 1; r < t.length; ++r) + if ( + fp(dp(t[e], t[r]), n) && + fp(dp(t[e], n), t[r]) && + fp(dp(t[r], n), t[e]) && + lp(pp(t[e], t[r], n), t) + ) + return [t[e], t[r], n]; + throw new Error(); + } + function fp(t, n) { + var e = t.r - n.r, + r = n.x - t.x, + i = n.y - t.y; + return e < 0 || e * e < r * r + i * i; + } + function sp(t, n) { + var e = t.r - n.r + 1e-9 * Math.max(t.r, n.r, 1), + r = n.x - t.x, + i = n.y - t.y; + return e > 0 && e * e > r * r + i * i; + } + function lp(t, n) { + for (var e = 0; e < n.length; ++e) if (!sp(t, n[e])) return !1; + return !0; + } + function hp(t) { + switch (t.length) { + case 1: + return (function (t) { + return { x: t.x, y: t.y, r: t.r }; + })(t[0]); + case 2: + return dp(t[0], t[1]); + case 3: + return pp(t[0], t[1], t[2]); + } + } + function dp(t, n) { + var e = t.x, + r = t.y, + i = t.r, + o = n.x, + a = n.y, + u = n.r, + c = o - e, + f = a - r, + s = u - i, + l = Math.sqrt(c * c + f * f); + return { + x: (e + o + (c / l) * s) / 2, + y: (r + a + (f / l) * s) / 2, + r: (l + i + u) / 2, + }; + } + function pp(t, n, e) { + var r = t.x, + i = t.y, + o = t.r, + a = n.x, + u = n.y, + c = n.r, + f = e.x, + s = e.y, + l = e.r, + h = r - a, + d = r - f, + p = i - u, + g = i - s, + y = c - o, + v = l - o, + _ = r * r + i * i - o * o, + b = _ - a * a - u * u + c * c, + m = _ - f * f - s * s + l * l, + x = d * p - h * g, + w = (p * m - g * b) / (2 * x) - r, + M = (g * y - p * v) / x, + T = (d * b - h * m) / (2 * x) - i, + A = (h * v - d * y) / x, + S = M * M + A * A - 1, + E = 2 * (o + w * M + T * A), + N = w * w + T * T - o * o, + k = -(Math.abs(S) > 1e-6 + ? (E + Math.sqrt(E * E - 4 * S * N)) / (2 * S) + : N / E); + return { x: r + w + M * k, y: i + T + A * k, r: k }; + } + function gp(t, n, e) { + var r, + i, + o, + a, + u = t.x - n.x, + c = t.y - n.y, + f = u * u + c * c; + f + ? ((i = n.r + e.r), + (i *= i), + (a = t.r + e.r), + i > (a *= a) + ? ((r = (f + a - i) / (2 * f)), + (o = Math.sqrt(Math.max(0, a / f - r * r))), + (e.x = t.x - r * u - o * c), + (e.y = t.y - r * c + o * u)) + : ((r = (f + i - a) / (2 * f)), + (o = Math.sqrt(Math.max(0, i / f - r * r))), + (e.x = n.x + r * u - o * c), + (e.y = n.y + r * c + o * u))) + : ((e.x = n.x + e.r), (e.y = n.y)); + } + function yp(t, n) { + var e = t.r + n.r - 1e-6, + r = n.x - t.x, + i = n.y - t.y; + return e > 0 && e * e > r * r + i * i; + } + function vp(t) { + var n = t._, + e = t.next._, + r = n.r + e.r, + i = (n.x * e.r + e.x * n.r) / r, + o = (n.y * e.r + e.y * n.r) / r; + return i * i + o * o; + } + function _p(t) { + ((this._ = t), (this.next = null), (this.previous = null)); + } + function bp(t, n) { + if ( + !(o = (t = (function (t) { + return "object" == typeof t && "length" in t ? t : Array.from(t); + })(t)).length) + ) + return 0; + var e, r, i, o, a, u, c, f, s, l, h; + if ((((e = t[0]).x = 0), (e.y = 0), !(o > 1))) return e.r; + if (((r = t[1]), (e.x = -r.r), (r.x = e.r), (r.y = 0), !(o > 2))) + return e.r + r.r; + (gp(r, e, (i = t[2])), + (e = new _p(e)), + (r = new _p(r)), + (i = new _p(i)), + (e.next = i.previous = r), + (r.next = e.previous = i), + (i.next = r.previous = e)); + t: for (c = 3; c < o; ++c) { + (gp(e._, r._, (i = t[c])), + (i = new _p(i)), + (f = r.next), + (s = e.previous), + (l = r._.r), + (h = e._.r)); + do { + if (l <= h) { + if (yp(f._, i._)) { + ((r = f), (e.next = r), (r.previous = e), --c); + continue t; + } + ((l += f._.r), (f = f.next)); + } else { + if (yp(s._, i._)) { + (((e = s).next = r), (r.previous = e), --c); + continue t; + } + ((h += s._.r), (s = s.previous)); + } + } while (f !== s.next); + for ( + i.previous = e, i.next = r, e.next = r.previous = r = i, a = vp(e); + (i = i.next) !== r; + + ) + (u = vp(i)) < a && ((e = i), (a = u)); + r = e.next; + } + for (e = [r._], i = r; (i = i.next) !== r; ) e.push(i._); + for (i = up(e, n), c = 0; c < o; ++c) (((e = t[c]).x -= i.x), (e.y -= i.y)); + return i.r; + } + function mp(t) { + return Math.sqrt(t.value); + } + function xp(t) { + return function (n) { + n.children || (n.r = Math.max(0, +t(n) || 0)); + }; + } + function wp(t, n, e) { + return function (r) { + if ((i = r.children)) { + var i, + o, + a, + u = i.length, + c = t(r) * n || 0; + if (c) for (o = 0; o < u; ++o) i[o].r += c; + if (((a = bp(i, e)), c)) for (o = 0; o < u; ++o) i[o].r -= c; + r.r = a + c; + } + }; + } + function Mp(t) { + return function (n) { + var e = n.parent; + ((n.r *= t), e && ((n.x = e.x + t * n.x), (n.y = e.y + t * n.y))); + }; + } + function Tp(t) { + ((t.x0 = Math.round(t.x0)), + (t.y0 = Math.round(t.y0)), + (t.x1 = Math.round(t.x1)), + (t.y1 = Math.round(t.y1))); + } + function Ap(t, n, e, r, i) { + for ( + var o, + a = t.children, + u = -1, + c = a.length, + f = t.value && (r - n) / t.value; + ++u < c; + + ) + (((o = a[u]).y0 = e), (o.y1 = i), (o.x0 = n), (o.x1 = n += o.value * f)); + } + var Sp = { depth: -1 }, + Ep = {}, + Np = {}; + function kp(t) { + return t.id; + } + function Cp(t) { + return t.parentId; + } + function Pp(t) { + let n = t.length; + if (n < 2) return ""; + for (; --n > 1 && !zp(t, n); ); + return t.slice(0, n); + } + function zp(t, n) { + if ("/" === t[n]) { + let e = 0; + for (; n > 0 && "\\" === t[--n]; ) ++e; + if (!(1 & e)) return !0; + } + return !1; + } + function $p(t, n) { + return t.parent === n.parent ? 1 : 2; + } + function Dp(t) { + var n = t.children; + return n ? n[0] : t.t; + } + function Rp(t) { + var n = t.children; + return n ? n[n.length - 1] : t.t; + } + function Fp(t, n, e) { + var r = e / (n.i - t.i); + ((n.c -= r), (n.s += e), (t.c += r), (n.z += e), (n.m += e)); + } + function qp(t, n, e) { + return t.a.parent === n.parent ? t.a : e; + } + function Up(t, n) { + ((this._ = t), + (this.parent = null), + (this.children = null), + (this.A = null), + (this.a = this), + (this.z = 0), + (this.m = 0), + (this.c = 0), + (this.s = 0), + (this.t = null), + (this.i = n)); + } + function Ip(t, n, e, r, i) { + for ( + var o, + a = t.children, + u = -1, + c = a.length, + f = t.value && (i - e) / t.value; + ++u < c; + + ) + (((o = a[u]).x0 = n), (o.x1 = r), (o.y0 = e), (o.y1 = e += o.value * f)); + } + Up.prototype = Object.create(Qd.prototype); + var Op = (1 + Math.sqrt(5)) / 2; + function Bp(t, n, e, r, i, o) { + for ( + var a, + u, + c, + f, + s, + l, + h, + d, + p, + g, + y, + v = [], + _ = n.children, + b = 0, + m = 0, + x = _.length, + w = n.value; + b < x; + + ) { + ((c = i - e), (f = o - r)); + do { + s = _[m++].value; + } while (!s && m < x); + for ( + l = h = s, + y = s * s * (g = Math.max(f / c, c / f) / (w * t)), + p = Math.max(h / y, y / l); + m < x; + ++m + ) { + if ( + ((s += u = _[m].value), + u < l && (l = u), + u > h && (h = u), + (y = s * s * g), + (d = Math.max(h / y, y / l)) > p) + ) { + s -= u; + break; + } + p = d; + } + (v.push((a = { value: s, dice: c < f, children: _.slice(b, m) })), + a.dice + ? Ap(a, e, r, i, w ? (r += (f * s) / w) : o) + : Ip(a, e, r, w ? (e += (c * s) / w) : i, o), + (w -= s), + (b = m)); + } + return v; + } + var Yp = (function t(n) { + function e(t, e, r, i, o) { + Bp(n, t, e, r, i, o); + } + return ( + (e.ratio = function (n) { + return t((n = +n) > 1 ? n : 1); + }), + e + ); + })(Op); + var Lp = (function t(n) { + function e(t, e, r, i, o) { + if ((a = t._squarify) && a.ratio === n) + for (var a, u, c, f, s, l = -1, h = a.length, d = t.value; ++l < h; ) { + for ( + c = (u = a[l]).children, f = u.value = 0, s = c.length; + f < s; + ++f + ) + u.value += c[f].value; + (u.dice + ? Ap(u, e, r, i, d ? (r += ((o - r) * u.value) / d) : o) + : Ip(u, e, r, d ? (e += ((i - e) * u.value) / d) : i, o), + (d -= u.value)); + } + else ((t._squarify = a = Bp(n, t, e, r, i, o)), (a.ratio = n)); + } + return ( + (e.ratio = function (n) { + return t((n = +n) > 1 ? n : 1); + }), + e + ); + })(Op); + function jp(t, n, e) { + return (n[0] - t[0]) * (e[1] - t[1]) - (n[1] - t[1]) * (e[0] - t[0]); + } + function Hp(t, n) { + return t[0] - n[0] || t[1] - n[1]; + } + function Xp(t) { + const n = t.length, + e = [0, 1]; + let r, + i = 2; + for (r = 2; r < n; ++r) { + for (; i > 1 && jp(t[e[i - 2]], t[e[i - 1]], t[r]) <= 0; ) --i; + e[i++] = r; + } + return e.slice(0, i); + } + var Gp = Math.random, + Vp = (function t(n) { + function e(t, e) { + return ( + (t = null == t ? 0 : +t), + (e = null == e ? 1 : +e), + 1 === arguments.length ? ((e = t), (t = 0)) : (e -= t), + function () { + return n() * e + t; + } + ); + } + return ((e.source = t), e); + })(Gp), + Wp = (function t(n) { + function e(t, e) { + return ( + arguments.length < 2 && ((e = t), (t = 0)), + (t = Math.floor(t)), + (e = Math.floor(e) - t), + function () { + return Math.floor(n() * e + t); + } + ); + } + return ((e.source = t), e); + })(Gp), + Zp = (function t(n) { + function e(t, e) { + var r, i; + return ( + (t = null == t ? 0 : +t), + (e = null == e ? 1 : +e), + function () { + var o; + if (null != r) ((o = r), (r = null)); + else + do { + ((r = 2 * n() - 1), (o = 2 * n() - 1), (i = r * r + o * o)); + } while (!i || i > 1); + return t + e * o * Math.sqrt((-2 * Math.log(i)) / i); + } + ); + } + return ((e.source = t), e); + })(Gp), + Kp = (function t(n) { + var e = Zp.source(n); + function r() { + var t = e.apply(this, arguments); + return function () { + return Math.exp(t()); + }; + } + return ((r.source = t), r); + })(Gp), + Qp = (function t(n) { + function e(t) { + return (t = +t) <= 0 + ? () => 0 + : function () { + for (var e = 0, r = t; r > 1; --r) e += n(); + return e + r * n(); + }; + } + return ((e.source = t), e); + })(Gp), + Jp = (function t(n) { + var e = Qp.source(n); + function r(t) { + if (0 == (t = +t)) return n; + var r = e(t); + return function () { + return r() / t; + }; + } + return ((r.source = t), r); + })(Gp), + tg = (function t(n) { + function e(t) { + return function () { + return -Math.log1p(-n()) / t; + }; + } + return ((e.source = t), e); + })(Gp), + ng = (function t(n) { + function e(t) { + if ((t = +t) < 0) throw new RangeError("invalid alpha"); + return ( + (t = 1 / -t), + function () { + return Math.pow(1 - n(), t); + } + ); + } + return ((e.source = t), e); + })(Gp), + eg = (function t(n) { + function e(t) { + if ((t = +t) < 0 || t > 1) throw new RangeError("invalid p"); + return function () { + return Math.floor(n() + t); + }; + } + return ((e.source = t), e); + })(Gp), + rg = (function t(n) { + function e(t) { + if ((t = +t) < 0 || t > 1) throw new RangeError("invalid p"); + return 0 === t + ? () => 1 / 0 + : 1 === t + ? () => 1 + : ((t = Math.log1p(-t)), + function () { + return 1 + Math.floor(Math.log1p(-n()) / t); + }); + } + return ((e.source = t), e); + })(Gp), + ig = (function t(n) { + var e = Zp.source(n)(); + function r(t, r) { + if ((t = +t) < 0) throw new RangeError("invalid k"); + if (0 === t) return () => 0; + if (((r = null == r ? 1 : +r), 1 === t)) + return () => -Math.log1p(-n()) * r; + var i = (t < 1 ? t + 1 : t) - 1 / 3, + o = 1 / (3 * Math.sqrt(i)), + a = t < 1 ? () => Math.pow(n(), 1 / t) : () => 1; + return function () { + do { + do { + var t = e(), + u = 1 + o * t; + } while (u <= 0); + u *= u * u; + var c = 1 - n(); + } while ( + c >= 1 - 0.0331 * t * t * t * t && + Math.log(c) >= 0.5 * t * t + i * (1 - u + Math.log(u)) + ); + return i * u * a() * r; + }; + } + return ((r.source = t), r); + })(Gp), + og = (function t(n) { + var e = ig.source(n); + function r(t, n) { + var r = e(t), + i = e(n); + return function () { + var t = r(); + return 0 === t ? 0 : t / (t + i()); + }; + } + return ((r.source = t), r); + })(Gp), + ag = (function t(n) { + var e = rg.source(n), + r = og.source(n); + function i(t, n) { + return ( + (t = +t), + (n = +n) >= 1 + ? () => t + : n <= 0 + ? () => 0 + : function () { + for ( + var i = 0, o = t, a = n; + o * a > 16 && o * (1 - a) > 16; + + ) { + var u = Math.floor((o + 1) * a), + c = r(u, o - u + 1)(); + c <= a + ? ((i += u), (o -= u), (a = (a - c) / (1 - c))) + : ((o = u - 1), (a /= c)); + } + for ( + var f = a < 0.5, s = e(f ? a : 1 - a), l = s(), h = 0; + l <= o; + ++h + ) + l += s(); + return i + (f ? h : o - h); + } + ); + } + return ((i.source = t), i); + })(Gp), + ug = (function t(n) { + function e(t, e, r) { + var i; + return ( + 0 == (t = +t) + ? (i = (t) => -Math.log(t)) + : ((t = 1 / t), (i = (n) => Math.pow(n, t))), + (e = null == e ? 0 : +e), + (r = null == r ? 1 : +r), + function () { + return e + r * i(-Math.log1p(-n())); + } + ); + } + return ((e.source = t), e); + })(Gp), + cg = (function t(n) { + function e(t, e) { + return ( + (t = null == t ? 0 : +t), + (e = null == e ? 1 : +e), + function () { + return t + e * Math.tan(Math.PI * n()); + } + ); + } + return ((e.source = t), e); + })(Gp), + fg = (function t(n) { + function e(t, e) { + return ( + (t = null == t ? 0 : +t), + (e = null == e ? 1 : +e), + function () { + var r = n(); + return t + e * Math.log(r / (1 - r)); + } + ); + } + return ((e.source = t), e); + })(Gp), + sg = (function t(n) { + var e = ig.source(n), + r = ag.source(n); + function i(t) { + return function () { + for (var i = 0, o = t; o > 16; ) { + var a = Math.floor(0.875 * o), + u = e(a)(); + if (u > o) return i + r(a - 1, o / u)(); + ((i += a), (o -= u)); + } + for (var c = -Math.log1p(-n()), f = 0; c <= o; ++f) + c -= Math.log1p(-n()); + return i + f; + }; + } + return ((i.source = t), i); + })(Gp); + const lg = 1 / 4294967296; + function hg(t, n) { + switch (arguments.length) { + case 0: + break; + case 1: + this.range(t); + break; + default: + this.range(n).domain(t); + } + return this; + } + function dg(t, n) { + switch (arguments.length) { + case 0: + break; + case 1: + "function" == typeof t ? this.interpolator(t) : this.range(t); + break; + default: + (this.domain(t), + "function" == typeof n ? this.interpolator(n) : this.range(n)); + } + return this; + } + const pg = Symbol("implicit"); + function gg() { + var t = new InternMap(), + n = [], + e = [], + r = pg; + function i(i) { + let o = t.get(i); + if (void 0 === o) { + if (r !== pg) return r; + t.set(i, (o = n.push(i) - 1)); + } + return e[o % e.length]; + } + return ( + (i.domain = function (e) { + if (!arguments.length) return n.slice(); + ((n = []), (t = new InternMap())); + for (const r of e) t.has(r) || t.set(r, n.push(r) - 1); + return i; + }), + (i.range = function (t) { + return arguments.length ? ((e = Array.from(t)), i) : e.slice(); + }), + (i.unknown = function (t) { + return arguments.length ? ((r = t), i) : r; + }), + (i.copy = function () { + return gg(n, e).unknown(r); + }), + hg.apply(i, arguments), + i + ); + } + function yg() { + var t, + n, + e = gg().unknown(void 0), + r = e.domain, + i = e.range, + o = 0, + a = 1, + u = !1, + c = 0, + f = 0, + s = 0.5; + function l() { + var e = r().length, + l = a < o, + h = l ? a : o, + d = l ? o : a; + ((t = (d - h) / Math.max(1, e - c + 2 * f)), + u && (t = Math.floor(t)), + (h += (d - h - t * (e - c)) * s), + (n = t * (1 - c)), + u && ((h = Math.round(h)), (n = Math.round(n)))); + var p = lt(e).map(function (n) { + return h + t * n; + }); + return i(l ? p.reverse() : p); + } + return ( + delete e.unknown, + (e.domain = function (t) { + return arguments.length ? (r(t), l()) : r(); + }), + (e.range = function (t) { + return arguments.length + ? (([o, a] = t), (o = +o), (a = +a), l()) + : [o, a]; + }), + (e.rangeRound = function (t) { + return (([o, a] = t), (o = +o), (a = +a), (u = !0), l()); + }), + (e.bandwidth = function () { + return n; + }), + (e.step = function () { + return t; + }), + (e.round = function (t) { + return arguments.length ? ((u = !!t), l()) : u; + }), + (e.padding = function (t) { + return arguments.length ? ((c = Math.min(1, (f = +t))), l()) : c; + }), + (e.paddingInner = function (t) { + return arguments.length ? ((c = Math.min(1, t)), l()) : c; + }), + (e.paddingOuter = function (t) { + return arguments.length ? ((f = +t), l()) : f; + }), + (e.align = function (t) { + return arguments.length ? ((s = Math.max(0, Math.min(1, t))), l()) : s; + }), + (e.copy = function () { + return yg(r(), [o, a]) + .round(u) + .paddingInner(c) + .paddingOuter(f) + .align(s); + }), + hg.apply(l(), arguments) + ); + } + function vg(t) { + var n = t.copy; + return ( + (t.padding = t.paddingOuter), + delete t.paddingInner, + delete t.paddingOuter, + (t.copy = function () { + return vg(n()); + }), + t + ); + } + function _g(t) { + return +t; + } + var bg = [0, 1]; + function mg(t) { + return t; + } + function xg(t, n) { + return (n -= t = +t) + ? function (e) { + return (e - t) / n; + } + : (function (t) { + return function () { + return t; + }; + })(isNaN(n) ? NaN : 0.5); + } + function wg(t, n, e) { + var r = t[0], + i = t[1], + o = n[0], + a = n[1]; + return ( + i < r ? ((r = xg(i, r)), (o = e(a, o))) : ((r = xg(r, i)), (o = e(o, a))), + function (t) { + return o(r(t)); + } + ); + } + function Mg(t, n, e) { + var r = Math.min(t.length, n.length) - 1, + i = new Array(r), + o = new Array(r), + a = -1; + for ( + t[r] < t[0] && ((t = t.slice().reverse()), (n = n.slice().reverse())); + ++a < r; + + ) + ((i[a] = xg(t[a], t[a + 1])), (o[a] = e(n[a], n[a + 1]))); + return function (n) { + var e = s(t, n, 1, r) - 1; + return o[e](i[e](n)); + }; + } + function Tg(t, n) { + return n + .domain(t.domain()) + .range(t.range()) + .interpolate(t.interpolate()) + .clamp(t.clamp()) + .unknown(t.unknown()); + } + function Ag() { + var t, + n, + e, + r, + i, + o, + a = bg, + u = bg, + c = Gr, + f = mg; + function s() { + var t = Math.min(a.length, u.length); + return ( + f !== mg && + (f = (function (t, n) { + var e; + return ( + t > n && ((e = t), (t = n), (n = e)), + function (e) { + return Math.max(t, Math.min(n, e)); + } + ); + })(a[0], a[t - 1])), + (r = t > 2 ? Mg : wg), + (i = o = null), + l + ); + } + function l(n) { + return null == n || isNaN((n = +n)) + ? e + : (i || (i = r(a.map(t), u, c)))(t(f(n))); + } + return ( + (l.invert = function (e) { + return f(n((o || (o = r(u, a.map(t), Yr)))(e))); + }), + (l.domain = function (t) { + return arguments.length ? ((a = Array.from(t, _g)), s()) : a.slice(); + }), + (l.range = function (t) { + return arguments.length ? ((u = Array.from(t)), s()) : u.slice(); + }), + (l.rangeRound = function (t) { + return ((u = Array.from(t)), (c = Vr), s()); + }), + (l.clamp = function (t) { + return arguments.length ? ((f = !!t || mg), s()) : f !== mg; + }), + (l.interpolate = function (t) { + return arguments.length ? ((c = t), s()) : c; + }), + (l.unknown = function (t) { + return arguments.length ? ((e = t), l) : e; + }), + function (e, r) { + return ((t = e), (n = r), s()); + } + ); + } + function Sg() { + return Ag()(mg, mg); + } + function Eg(n, e, r, i) { + var o, + a = W(n, e, r); + switch ((i = Jc(null == i ? ",f" : i)).type) { + case "s": + var u = Math.max(Math.abs(n), Math.abs(e)); + return ( + null != i.precision || isNaN((o = lf(a, u))) || (i.precision = o), + t.formatPrefix(i, u) + ); + case "": + case "e": + case "g": + case "p": + case "r": + null != i.precision || + isNaN((o = hf(a, Math.max(Math.abs(n), Math.abs(e))))) || + (i.precision = o - ("e" === i.type)); + break; + case "f": + case "%": + null != i.precision || + isNaN((o = sf(a))) || + (i.precision = o - 2 * ("%" === i.type)); + } + return t.format(i); + } + function Ng(t) { + var n = t.domain; + return ( + (t.ticks = function (t) { + var e = n(); + return G(e[0], e[e.length - 1], null == t ? 10 : t); + }), + (t.tickFormat = function (t, e) { + var r = n(); + return Eg(r[0], r[r.length - 1], null == t ? 10 : t, e); + }), + (t.nice = function (e) { + null == e && (e = 10); + var r, + i, + o = n(), + a = 0, + u = o.length - 1, + c = o[a], + f = o[u], + s = 10; + for ( + f < c && ((i = c), (c = f), (f = i), (i = a), (a = u), (u = i)); + s-- > 0; + + ) { + if ((i = V(c, f, e)) === r) return ((o[a] = c), (o[u] = f), n(o)); + if (i > 0) ((c = Math.floor(c / i) * i), (f = Math.ceil(f / i) * i)); + else { + if (!(i < 0)) break; + ((c = Math.ceil(c * i) / i), (f = Math.floor(f * i) / i)); + } + r = i; + } + return t; + }), + t + ); + } + function kg(t, n) { + var e, + r = 0, + i = (t = t.slice()).length - 1, + o = t[r], + a = t[i]; + return ( + a < o && ((e = r), (r = i), (i = e), (e = o), (o = a), (a = e)), + (t[r] = n.floor(o)), + (t[i] = n.ceil(a)), + t + ); + } + function Cg(t) { + return Math.log(t); + } + function Pg(t) { + return Math.exp(t); + } + function zg(t) { + return -Math.log(-t); + } + function $g(t) { + return -Math.exp(-t); + } + function Dg(t) { + return isFinite(t) ? +("1e" + t) : t < 0 ? 0 : t; + } + function Rg(t) { + return (n, e) => -t(-n, e); + } + function Fg(n) { + const e = n(Cg, Pg), + r = e.domain; + let i, + o, + a = 10; + function u() { + return ( + (i = (function (t) { + return t === Math.E + ? Math.log + : (10 === t && Math.log10) || + (2 === t && Math.log2) || + ((t = Math.log(t)), (n) => Math.log(n) / t); + })(a)), + (o = (function (t) { + return 10 === t + ? Dg + : t === Math.E + ? Math.exp + : (n) => Math.pow(t, n); + })(a)), + r()[0] < 0 ? ((i = Rg(i)), (o = Rg(o)), n(zg, $g)) : n(Cg, Pg), + e + ); + } + return ( + (e.base = function (t) { + return arguments.length ? ((a = +t), u()) : a; + }), + (e.domain = function (t) { + return arguments.length ? (r(t), u()) : r(); + }), + (e.ticks = (t) => { + const n = r(); + let e = n[0], + u = n[n.length - 1]; + const c = u < e; + c && ([e, u] = [u, e]); + let f, + s, + l = i(e), + h = i(u); + const d = null == t ? 10 : +t; + let p = []; + if (!(a % 1) && h - l < d) { + if (((l = Math.floor(l)), (h = Math.ceil(h)), e > 0)) { + for (; l <= h; ++l) + for (f = 1; f < a; ++f) + if (((s = l < 0 ? f / o(-l) : f * o(l)), !(s < e))) { + if (s > u) break; + p.push(s); + } + } else + for (; l <= h; ++l) + for (f = a - 1; f >= 1; --f) + if (((s = l > 0 ? f / o(-l) : f * o(l)), !(s < e))) { + if (s > u) break; + p.push(s); + } + 2 * p.length < d && (p = G(e, u, d)); + } else p = G(l, h, Math.min(h - l, d)).map(o); + return c ? p.reverse() : p; + }), + (e.tickFormat = (n, r) => { + if ( + (null == n && (n = 10), + null == r && (r = 10 === a ? "s" : ","), + "function" != typeof r && + (a % 1 || null != (r = Jc(r)).precision || (r.trim = !0), + (r = t.format(r))), + n === 1 / 0) + ) + return r; + const u = Math.max(1, (a * n) / e.ticks().length); + return (t) => { + let n = t / o(Math.round(i(t))); + return (n * a < a - 0.5 && (n *= a), n <= u ? r(t) : ""); + }; + }), + (e.nice = () => + r( + kg(r(), { + floor: (t) => o(Math.floor(i(t))), + ceil: (t) => o(Math.ceil(i(t))), + }), + )), + e + ); + } + function qg(t) { + return function (n) { + return Math.sign(n) * Math.log1p(Math.abs(n / t)); + }; + } + function Ug(t) { + return function (n) { + return Math.sign(n) * Math.expm1(Math.abs(n)) * t; + }; + } + function Ig(t) { + var n = 1, + e = t(qg(n), Ug(n)); + return ( + (e.constant = function (e) { + return arguments.length ? t(qg((n = +e)), Ug(n)) : n; + }), + Ng(e) + ); + } + function Og(t) { + return function (n) { + return n < 0 ? -Math.pow(-n, t) : Math.pow(n, t); + }; + } + function Bg(t) { + return t < 0 ? -Math.sqrt(-t) : Math.sqrt(t); + } + function Yg(t) { + return t < 0 ? -t * t : t * t; + } + function Lg(t) { + var n = t(mg, mg), + e = 1; + return ( + (n.exponent = function (n) { + return arguments.length + ? 1 === (e = +n) + ? t(mg, mg) + : 0.5 === e + ? t(Bg, Yg) + : t(Og(e), Og(1 / e)) + : e; + }), + Ng(n) + ); + } + function jg() { + var t = Lg(Ag()); + return ( + (t.copy = function () { + return Tg(t, jg()).exponent(t.exponent()); + }), + hg.apply(t, arguments), + t + ); + } + function Hg(t) { + return Math.sign(t) * t * t; + } + const Xg = new Date(), + Gg = new Date(); + function Vg(t, n, e, r) { + function i(n) { + return (t((n = 0 === arguments.length ? new Date() : new Date(+n))), n); + } + return ( + (i.floor = (n) => (t((n = new Date(+n))), n)), + (i.ceil = (e) => (t((e = new Date(e - 1))), n(e, 1), t(e), e)), + (i.round = (t) => { + const n = i(t), + e = i.ceil(t); + return t - n < e - t ? n : e; + }), + (i.offset = (t, e) => ( + n((t = new Date(+t)), null == e ? 1 : Math.floor(e)), + t + )), + (i.range = (e, r, o) => { + const a = []; + if ( + ((e = i.ceil(e)), + (o = null == o ? 1 : Math.floor(o)), + !(e < r && o > 0)) + ) + return a; + let u; + do { + (a.push((u = new Date(+e))), n(e, o), t(e)); + } while (u < e && e < r); + return a; + }), + (i.filter = (e) => + Vg( + (n) => { + if (n >= n) for (; t(n), !e(n); ) n.setTime(n - 1); + }, + (t, r) => { + if (t >= t) + if (r < 0) for (; ++r <= 0; ) for (; n(t, -1), !e(t); ); + else for (; --r >= 0; ) for (; n(t, 1), !e(t); ); + }, + )), + e && + ((i.count = (n, r) => ( + Xg.setTime(+n), + Gg.setTime(+r), + t(Xg), + t(Gg), + Math.floor(e(Xg, Gg)) + )), + (i.every = (t) => ( + (t = Math.floor(t)), + isFinite(t) && t > 0 + ? t > 1 + ? i.filter( + r ? (n) => r(n) % t == 0 : (n) => i.count(0, n) % t == 0, + ) + : i + : null + ))), + i + ); + } + const Wg = Vg( + () => {}, + (t, n) => { + t.setTime(+t + n); + }, + (t, n) => n - t, + ); + Wg.every = (t) => ( + (t = Math.floor(t)), + isFinite(t) && t > 0 + ? t > 1 + ? Vg( + (n) => { + n.setTime(Math.floor(n / t) * t); + }, + (n, e) => { + n.setTime(+n + e * t); + }, + (n, e) => (e - n) / t, + ) + : Wg + : null + ); + const Zg = Wg.range, + Kg = 1e3, + Qg = 6e4, + Jg = 36e5, + ty = 864e5, + ny = 6048e5, + ey = 2592e6, + ry = 31536e6, + iy = Vg( + (t) => { + t.setTime(t - t.getMilliseconds()); + }, + (t, n) => { + t.setTime(+t + n * Kg); + }, + (t, n) => (n - t) / Kg, + (t) => t.getUTCSeconds(), + ), + oy = iy.range, + ay = Vg( + (t) => { + t.setTime(t - t.getMilliseconds() - t.getSeconds() * Kg); + }, + (t, n) => { + t.setTime(+t + n * Qg); + }, + (t, n) => (n - t) / Qg, + (t) => t.getMinutes(), + ), + uy = ay.range, + cy = Vg( + (t) => { + t.setUTCSeconds(0, 0); + }, + (t, n) => { + t.setTime(+t + n * Qg); + }, + (t, n) => (n - t) / Qg, + (t) => t.getUTCMinutes(), + ), + fy = cy.range, + sy = Vg( + (t) => { + t.setTime( + t - t.getMilliseconds() - t.getSeconds() * Kg - t.getMinutes() * Qg, + ); + }, + (t, n) => { + t.setTime(+t + n * Jg); + }, + (t, n) => (n - t) / Jg, + (t) => t.getHours(), + ), + ly = sy.range, + hy = Vg( + (t) => { + t.setUTCMinutes(0, 0, 0); + }, + (t, n) => { + t.setTime(+t + n * Jg); + }, + (t, n) => (n - t) / Jg, + (t) => t.getUTCHours(), + ), + dy = hy.range, + py = Vg( + (t) => t.setHours(0, 0, 0, 0), + (t, n) => t.setDate(t.getDate() + n), + (t, n) => + (n - t - (n.getTimezoneOffset() - t.getTimezoneOffset()) * Qg) / ty, + (t) => t.getDate() - 1, + ), + gy = py.range, + yy = Vg( + (t) => { + t.setUTCHours(0, 0, 0, 0); + }, + (t, n) => { + t.setUTCDate(t.getUTCDate() + n); + }, + (t, n) => (n - t) / ty, + (t) => t.getUTCDate() - 1, + ), + vy = yy.range, + _y = Vg( + (t) => { + t.setUTCHours(0, 0, 0, 0); + }, + (t, n) => { + t.setUTCDate(t.getUTCDate() + n); + }, + (t, n) => (n - t) / ty, + (t) => Math.floor(t / ty), + ), + by = _y.range; + function my(t) { + return Vg( + (n) => { + (n.setDate(n.getDate() - ((n.getDay() + 7 - t) % 7)), + n.setHours(0, 0, 0, 0)); + }, + (t, n) => { + t.setDate(t.getDate() + 7 * n); + }, + (t, n) => + (n - t - (n.getTimezoneOffset() - t.getTimezoneOffset()) * Qg) / ny, + ); + } + const xy = my(0), + wy = my(1), + My = my(2), + Ty = my(3), + Ay = my(4), + Sy = my(5), + Ey = my(6), + Ny = xy.range, + ky = wy.range, + Cy = My.range, + Py = Ty.range, + zy = Ay.range, + $y = Sy.range, + Dy = Ey.range; + function Ry(t) { + return Vg( + (n) => { + (n.setUTCDate(n.getUTCDate() - ((n.getUTCDay() + 7 - t) % 7)), + n.setUTCHours(0, 0, 0, 0)); + }, + (t, n) => { + t.setUTCDate(t.getUTCDate() + 7 * n); + }, + (t, n) => (n - t) / ny, + ); + } + const Fy = Ry(0), + qy = Ry(1), + Uy = Ry(2), + Iy = Ry(3), + Oy = Ry(4), + By = Ry(5), + Yy = Ry(6), + Ly = Fy.range, + jy = qy.range, + Hy = Uy.range, + Xy = Iy.range, + Gy = Oy.range, + Vy = By.range, + Wy = Yy.range, + Zy = Vg( + (t) => { + (t.setDate(1), t.setHours(0, 0, 0, 0)); + }, + (t, n) => { + t.setMonth(t.getMonth() + n); + }, + (t, n) => + n.getMonth() - t.getMonth() + 12 * (n.getFullYear() - t.getFullYear()), + (t) => t.getMonth(), + ), + Ky = Zy.range, + Qy = Vg( + (t) => { + (t.setUTCDate(1), t.setUTCHours(0, 0, 0, 0)); + }, + (t, n) => { + t.setUTCMonth(t.getUTCMonth() + n); + }, + (t, n) => + n.getUTCMonth() - + t.getUTCMonth() + + 12 * (n.getUTCFullYear() - t.getUTCFullYear()), + (t) => t.getUTCMonth(), + ), + Jy = Qy.range, + tv = Vg( + (t) => { + (t.setMonth(0, 1), t.setHours(0, 0, 0, 0)); + }, + (t, n) => { + t.setFullYear(t.getFullYear() + n); + }, + (t, n) => n.getFullYear() - t.getFullYear(), + (t) => t.getFullYear(), + ); + tv.every = (t) => + isFinite((t = Math.floor(t))) && t > 0 + ? Vg( + (n) => { + (n.setFullYear(Math.floor(n.getFullYear() / t) * t), + n.setMonth(0, 1), + n.setHours(0, 0, 0, 0)); + }, + (n, e) => { + n.setFullYear(n.getFullYear() + e * t); + }, + ) + : null; + const nv = tv.range, + ev = Vg( + (t) => { + (t.setUTCMonth(0, 1), t.setUTCHours(0, 0, 0, 0)); + }, + (t, n) => { + t.setUTCFullYear(t.getUTCFullYear() + n); + }, + (t, n) => n.getUTCFullYear() - t.getUTCFullYear(), + (t) => t.getUTCFullYear(), + ); + ev.every = (t) => + isFinite((t = Math.floor(t))) && t > 0 + ? Vg( + (n) => { + (n.setUTCFullYear(Math.floor(n.getUTCFullYear() / t) * t), + n.setUTCMonth(0, 1), + n.setUTCHours(0, 0, 0, 0)); + }, + (n, e) => { + n.setUTCFullYear(n.getUTCFullYear() + e * t); + }, + ) + : null; + const rv = ev.range; + function iv(t, n, e, i, o, a) { + const u = [ + [iy, 1, Kg], + [iy, 5, 5e3], + [iy, 15, 15e3], + [iy, 30, 3e4], + [a, 1, Qg], + [a, 5, 3e5], + [a, 15, 9e5], + [a, 30, 18e5], + [o, 1, Jg], + [o, 3, 108e5], + [o, 6, 216e5], + [o, 12, 432e5], + [i, 1, ty], + [i, 2, 1728e5], + [e, 1, ny], + [n, 1, ey], + [n, 3, 7776e6], + [t, 1, ry], + ]; + function c(n, e, i) { + const o = Math.abs(e - n) / i, + a = r(([, , t]) => t).right(u, o); + if (a === u.length) return t.every(W(n / ry, e / ry, i)); + if (0 === a) return Wg.every(Math.max(W(n, e, i), 1)); + const [c, f] = u[o / u[a - 1][2] < u[a][2] / o ? a - 1 : a]; + return c.every(f); + } + return [ + function (t, n, e) { + const r = n < t; + r && ([t, n] = [n, t]); + const i = e && "function" == typeof e.range ? e : c(t, n, e), + o = i ? i.range(t, +n + 1) : []; + return r ? o.reverse() : o; + }, + c, + ]; + } + const [ov, av] = iv(ev, Qy, Fy, _y, hy, cy), + [uv, cv] = iv(tv, Zy, xy, py, sy, ay); + function fv(t) { + if (0 <= t.y && t.y < 100) { + var n = new Date(-1, t.m, t.d, t.H, t.M, t.S, t.L); + return (n.setFullYear(t.y), n); + } + return new Date(t.y, t.m, t.d, t.H, t.M, t.S, t.L); + } + function sv(t) { + if (0 <= t.y && t.y < 100) { + var n = new Date(Date.UTC(-1, t.m, t.d, t.H, t.M, t.S, t.L)); + return (n.setUTCFullYear(t.y), n); + } + return new Date(Date.UTC(t.y, t.m, t.d, t.H, t.M, t.S, t.L)); + } + function lv(t, n, e) { + return { y: t, m: n, d: e, H: 0, M: 0, S: 0, L: 0 }; + } + function hv(t) { + var n = t.dateTime, + e = t.date, + r = t.time, + i = t.periods, + o = t.days, + a = t.shortDays, + u = t.months, + c = t.shortMonths, + f = mv(i), + s = xv(i), + l = mv(o), + h = xv(o), + d = mv(a), + p = xv(a), + g = mv(u), + y = xv(u), + v = mv(c), + _ = xv(c), + b = { + a: function (t) { + return a[t.getDay()]; + }, + A: function (t) { + return o[t.getDay()]; + }, + b: function (t) { + return c[t.getMonth()]; + }, + B: function (t) { + return u[t.getMonth()]; + }, + c: null, + d: Yv, + e: Yv, + f: Gv, + g: i_, + G: a_, + H: Lv, + I: jv, + j: Hv, + L: Xv, + m: Vv, + M: Wv, + p: function (t) { + return i[+(t.getHours() >= 12)]; + }, + q: function (t) { + return 1 + ~~(t.getMonth() / 3); + }, + Q: k_, + s: C_, + S: Zv, + u: Kv, + U: Qv, + V: t_, + w: n_, + W: e_, + x: null, + X: null, + y: r_, + Y: o_, + Z: u_, + "%": N_, + }, + m = { + a: function (t) { + return a[t.getUTCDay()]; + }, + A: function (t) { + return o[t.getUTCDay()]; + }, + b: function (t) { + return c[t.getUTCMonth()]; + }, + B: function (t) { + return u[t.getUTCMonth()]; + }, + c: null, + d: c_, + e: c_, + f: d_, + g: T_, + G: S_, + H: f_, + I: s_, + j: l_, + L: h_, + m: p_, + M: g_, + p: function (t) { + return i[+(t.getUTCHours() >= 12)]; + }, + q: function (t) { + return 1 + ~~(t.getUTCMonth() / 3); + }, + Q: k_, + s: C_, + S: y_, + u: v_, + U: __, + V: m_, + w: x_, + W: w_, + x: null, + X: null, + y: M_, + Y: A_, + Z: E_, + "%": N_, + }, + x = { + a: function (t, n, e) { + var r = d.exec(n.slice(e)); + return r ? ((t.w = p.get(r[0].toLowerCase())), e + r[0].length) : -1; + }, + A: function (t, n, e) { + var r = l.exec(n.slice(e)); + return r ? ((t.w = h.get(r[0].toLowerCase())), e + r[0].length) : -1; + }, + b: function (t, n, e) { + var r = v.exec(n.slice(e)); + return r ? ((t.m = _.get(r[0].toLowerCase())), e + r[0].length) : -1; + }, + B: function (t, n, e) { + var r = g.exec(n.slice(e)); + return r ? ((t.m = y.get(r[0].toLowerCase())), e + r[0].length) : -1; + }, + c: function (t, e, r) { + return T(t, n, e, r); + }, + d: zv, + e: zv, + f: Uv, + g: Nv, + G: Ev, + H: Dv, + I: Dv, + j: $v, + L: qv, + m: Pv, + M: Rv, + p: function (t, n, e) { + var r = f.exec(n.slice(e)); + return r ? ((t.p = s.get(r[0].toLowerCase())), e + r[0].length) : -1; + }, + q: Cv, + Q: Ov, + s: Bv, + S: Fv, + u: Mv, + U: Tv, + V: Av, + w: wv, + W: Sv, + x: function (t, n, r) { + return T(t, e, n, r); + }, + X: function (t, n, e) { + return T(t, r, n, e); + }, + y: Nv, + Y: Ev, + Z: kv, + "%": Iv, + }; + function w(t, n) { + return function (e) { + var r, + i, + o, + a = [], + u = -1, + c = 0, + f = t.length; + for (e instanceof Date || (e = new Date(+e)); ++u < f; ) + 37 === t.charCodeAt(u) && + (a.push(t.slice(c, u)), + null != (i = pv[(r = t.charAt(++u))]) + ? (r = t.charAt(++u)) + : (i = "e" === r ? " " : "0"), + (o = n[r]) && (r = o(e, i)), + a.push(r), + (c = u + 1)); + return (a.push(t.slice(c, u)), a.join("")); + }; + } + function M(t, n) { + return function (e) { + var r, + i, + o = lv(1900, void 0, 1); + if (T(o, t, (e += ""), 0) != e.length) return null; + if ("Q" in o) return new Date(o.Q); + if ("s" in o) return new Date(1e3 * o.s + ("L" in o ? o.L : 0)); + if ( + (n && !("Z" in o) && (o.Z = 0), + "p" in o && (o.H = (o.H % 12) + 12 * o.p), + void 0 === o.m && (o.m = "q" in o ? o.q : 0), + "V" in o) + ) { + if (o.V < 1 || o.V > 53) return null; + ("w" in o || (o.w = 1), + "Z" in o + ? ((i = (r = sv(lv(o.y, 0, 1))).getUTCDay()), + (r = i > 4 || 0 === i ? qy.ceil(r) : qy(r)), + (r = yy.offset(r, 7 * (o.V - 1))), + (o.y = r.getUTCFullYear()), + (o.m = r.getUTCMonth()), + (o.d = r.getUTCDate() + ((o.w + 6) % 7))) + : ((i = (r = fv(lv(o.y, 0, 1))).getDay()), + (r = i > 4 || 0 === i ? wy.ceil(r) : wy(r)), + (r = py.offset(r, 7 * (o.V - 1))), + (o.y = r.getFullYear()), + (o.m = r.getMonth()), + (o.d = r.getDate() + ((o.w + 6) % 7)))); + } else + ("W" in o || "U" in o) && + ("w" in o || (o.w = "u" in o ? o.u % 7 : "W" in o ? 1 : 0), + (i = + "Z" in o + ? sv(lv(o.y, 0, 1)).getUTCDay() + : fv(lv(o.y, 0, 1)).getDay()), + (o.m = 0), + (o.d = + "W" in o + ? ((o.w + 6) % 7) + 7 * o.W - ((i + 5) % 7) + : o.w + 7 * o.U - ((i + 6) % 7))); + return "Z" in o + ? ((o.H += (o.Z / 100) | 0), (o.M += o.Z % 100), sv(o)) + : fv(o); + }; + } + function T(t, n, e, r) { + for (var i, o, a = 0, u = n.length, c = e.length; a < u; ) { + if (r >= c) return -1; + if (37 === (i = n.charCodeAt(a++))) { + if ( + ((i = n.charAt(a++)), + !(o = x[i in pv ? n.charAt(a++) : i]) || (r = o(t, e, r)) < 0) + ) + return -1; + } else if (i != e.charCodeAt(r++)) return -1; + } + return r; + } + return ( + (b.x = w(e, b)), + (b.X = w(r, b)), + (b.c = w(n, b)), + (m.x = w(e, m)), + (m.X = w(r, m)), + (m.c = w(n, m)), + { + format: function (t) { + var n = w((t += ""), b); + return ( + (n.toString = function () { + return t; + }), + n + ); + }, + parse: function (t) { + var n = M((t += ""), !1); + return ( + (n.toString = function () { + return t; + }), + n + ); + }, + utcFormat: function (t) { + var n = w((t += ""), m); + return ( + (n.toString = function () { + return t; + }), + n + ); + }, + utcParse: function (t) { + var n = M((t += ""), !0); + return ( + (n.toString = function () { + return t; + }), + n + ); + }, + } + ); + } + var dv, + pv = { "-": "", _: " ", 0: "0" }, + gv = /^\s*\d+/, + yv = /^%/, + vv = /[\\^$*+?|[\]().{}]/g; + function _v(t, n, e) { + var r = t < 0 ? "-" : "", + i = (r ? -t : t) + "", + o = i.length; + return r + (o < e ? new Array(e - o + 1).join(n) + i : i); + } + function bv(t) { + return t.replace(vv, "\\$&"); + } + function mv(t) { + return new RegExp("^(?:" + t.map(bv).join("|") + ")", "i"); + } + function xv(t) { + return new Map(t.map((t, n) => [t.toLowerCase(), n])); + } + function wv(t, n, e) { + var r = gv.exec(n.slice(e, e + 1)); + return r ? ((t.w = +r[0]), e + r[0].length) : -1; + } + function Mv(t, n, e) { + var r = gv.exec(n.slice(e, e + 1)); + return r ? ((t.u = +r[0]), e + r[0].length) : -1; + } + function Tv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.U = +r[0]), e + r[0].length) : -1; + } + function Av(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.V = +r[0]), e + r[0].length) : -1; + } + function Sv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.W = +r[0]), e + r[0].length) : -1; + } + function Ev(t, n, e) { + var r = gv.exec(n.slice(e, e + 4)); + return r ? ((t.y = +r[0]), e + r[0].length) : -1; + } + function Nv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r + ? ((t.y = +r[0] + (+r[0] > 68 ? 1900 : 2e3)), e + r[0].length) + : -1; + } + function kv(t, n, e) { + var r = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(n.slice(e, e + 6)); + return r + ? ((t.Z = r[1] ? 0 : -(r[2] + (r[3] || "00"))), e + r[0].length) + : -1; + } + function Cv(t, n, e) { + var r = gv.exec(n.slice(e, e + 1)); + return r ? ((t.q = 3 * r[0] - 3), e + r[0].length) : -1; + } + function Pv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.m = r[0] - 1), e + r[0].length) : -1; + } + function zv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.d = +r[0]), e + r[0].length) : -1; + } + function $v(t, n, e) { + var r = gv.exec(n.slice(e, e + 3)); + return r ? ((t.m = 0), (t.d = +r[0]), e + r[0].length) : -1; + } + function Dv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.H = +r[0]), e + r[0].length) : -1; + } + function Rv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.M = +r[0]), e + r[0].length) : -1; + } + function Fv(t, n, e) { + var r = gv.exec(n.slice(e, e + 2)); + return r ? ((t.S = +r[0]), e + r[0].length) : -1; + } + function qv(t, n, e) { + var r = gv.exec(n.slice(e, e + 3)); + return r ? ((t.L = +r[0]), e + r[0].length) : -1; + } + function Uv(t, n, e) { + var r = gv.exec(n.slice(e, e + 6)); + return r ? ((t.L = Math.floor(r[0] / 1e3)), e + r[0].length) : -1; + } + function Iv(t, n, e) { + var r = yv.exec(n.slice(e, e + 1)); + return r ? e + r[0].length : -1; + } + function Ov(t, n, e) { + var r = gv.exec(n.slice(e)); + return r ? ((t.Q = +r[0]), e + r[0].length) : -1; + } + function Bv(t, n, e) { + var r = gv.exec(n.slice(e)); + return r ? ((t.s = +r[0]), e + r[0].length) : -1; + } + function Yv(t, n) { + return _v(t.getDate(), n, 2); + } + function Lv(t, n) { + return _v(t.getHours(), n, 2); + } + function jv(t, n) { + return _v(t.getHours() % 12 || 12, n, 2); + } + function Hv(t, n) { + return _v(1 + py.count(tv(t), t), n, 3); + } + function Xv(t, n) { + return _v(t.getMilliseconds(), n, 3); + } + function Gv(t, n) { + return Xv(t, n) + "000"; + } + function Vv(t, n) { + return _v(t.getMonth() + 1, n, 2); + } + function Wv(t, n) { + return _v(t.getMinutes(), n, 2); + } + function Zv(t, n) { + return _v(t.getSeconds(), n, 2); + } + function Kv(t) { + var n = t.getDay(); + return 0 === n ? 7 : n; + } + function Qv(t, n) { + return _v(xy.count(tv(t) - 1, t), n, 2); + } + function Jv(t) { + var n = t.getDay(); + return n >= 4 || 0 === n ? Ay(t) : Ay.ceil(t); + } + function t_(t, n) { + return ((t = Jv(t)), _v(Ay.count(tv(t), t) + (4 === tv(t).getDay()), n, 2)); + } + function n_(t) { + return t.getDay(); + } + function e_(t, n) { + return _v(wy.count(tv(t) - 1, t), n, 2); + } + function r_(t, n) { + return _v(t.getFullYear() % 100, n, 2); + } + function i_(t, n) { + return _v((t = Jv(t)).getFullYear() % 100, n, 2); + } + function o_(t, n) { + return _v(t.getFullYear() % 1e4, n, 4); + } + function a_(t, n) { + var e = t.getDay(); + return _v( + (t = e >= 4 || 0 === e ? Ay(t) : Ay.ceil(t)).getFullYear() % 1e4, + n, + 4, + ); + } + function u_(t) { + var n = t.getTimezoneOffset(); + return ( + (n > 0 ? "-" : ((n *= -1), "+")) + + _v((n / 60) | 0, "0", 2) + + _v(n % 60, "0", 2) + ); + } + function c_(t, n) { + return _v(t.getUTCDate(), n, 2); + } + function f_(t, n) { + return _v(t.getUTCHours(), n, 2); + } + function s_(t, n) { + return _v(t.getUTCHours() % 12 || 12, n, 2); + } + function l_(t, n) { + return _v(1 + yy.count(ev(t), t), n, 3); + } + function h_(t, n) { + return _v(t.getUTCMilliseconds(), n, 3); + } + function d_(t, n) { + return h_(t, n) + "000"; + } + function p_(t, n) { + return _v(t.getUTCMonth() + 1, n, 2); + } + function g_(t, n) { + return _v(t.getUTCMinutes(), n, 2); + } + function y_(t, n) { + return _v(t.getUTCSeconds(), n, 2); + } + function v_(t) { + var n = t.getUTCDay(); + return 0 === n ? 7 : n; + } + function __(t, n) { + return _v(Fy.count(ev(t) - 1, t), n, 2); + } + function b_(t) { + var n = t.getUTCDay(); + return n >= 4 || 0 === n ? Oy(t) : Oy.ceil(t); + } + function m_(t, n) { + return ( + (t = b_(t)), + _v(Oy.count(ev(t), t) + (4 === ev(t).getUTCDay()), n, 2) + ); + } + function x_(t) { + return t.getUTCDay(); + } + function w_(t, n) { + return _v(qy.count(ev(t) - 1, t), n, 2); + } + function M_(t, n) { + return _v(t.getUTCFullYear() % 100, n, 2); + } + function T_(t, n) { + return _v((t = b_(t)).getUTCFullYear() % 100, n, 2); + } + function A_(t, n) { + return _v(t.getUTCFullYear() % 1e4, n, 4); + } + function S_(t, n) { + var e = t.getUTCDay(); + return _v( + (t = e >= 4 || 0 === e ? Oy(t) : Oy.ceil(t)).getUTCFullYear() % 1e4, + n, + 4, + ); + } + function E_() { + return "+0000"; + } + function N_() { + return "%"; + } + function k_(t) { + return +t; + } + function C_(t) { + return Math.floor(+t / 1e3); + } + function P_(n) { + return ( + (dv = hv(n)), + (t.timeFormat = dv.format), + (t.timeParse = dv.parse), + (t.utcFormat = dv.utcFormat), + (t.utcParse = dv.utcParse), + dv + ); + } + ((t.timeFormat = void 0), + (t.timeParse = void 0), + (t.utcFormat = void 0), + (t.utcParse = void 0), + P_({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + periods: ["AM", "PM"], + days: [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ], + shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + months: [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ], + shortMonths: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], + })); + var z_ = "%Y-%m-%dT%H:%M:%S.%LZ"; + var $_ = Date.prototype.toISOString + ? function (t) { + return t.toISOString(); + } + : t.utcFormat(z_), + D_ = $_; + var R_ = +new Date("2000-01-01T00:00:00.000Z") + ? function (t) { + var n = new Date(t); + return isNaN(n) ? null : n; + } + : t.utcParse(z_), + F_ = R_; + function q_(t) { + return new Date(t); + } + function U_(t) { + return t instanceof Date ? +t : +new Date(+t); + } + function I_(t, n, e, r, i, o, a, u, c, f) { + var s = Sg(), + l = s.invert, + h = s.domain, + d = f(".%L"), + p = f(":%S"), + g = f("%I:%M"), + y = f("%I %p"), + v = f("%a %d"), + _ = f("%b %d"), + b = f("%B"), + m = f("%Y"); + function x(t) { + return ( + c(t) < t + ? d + : u(t) < t + ? p + : a(t) < t + ? g + : o(t) < t + ? y + : r(t) < t + ? i(t) < t + ? v + : _ + : e(t) < t + ? b + : m + )(t); + } + return ( + (s.invert = function (t) { + return new Date(l(t)); + }), + (s.domain = function (t) { + return arguments.length ? h(Array.from(t, U_)) : h().map(q_); + }), + (s.ticks = function (n) { + var e = h(); + return t(e[0], e[e.length - 1], null == n ? 10 : n); + }), + (s.tickFormat = function (t, n) { + return null == n ? x : f(n); + }), + (s.nice = function (t) { + var e = h(); + return ( + (t && "function" == typeof t.range) || + (t = n(e[0], e[e.length - 1], null == t ? 10 : t)), + t ? h(kg(e, t)) : s + ); + }), + (s.copy = function () { + return Tg(s, I_(t, n, e, r, i, o, a, u, c, f)); + }), + s + ); + } + function O_() { + var t, + n, + e, + r, + i, + o = 0, + a = 1, + u = mg, + c = !1; + function f(n) { + return null == n || isNaN((n = +n)) + ? i + : u( + 0 === e + ? 0.5 + : ((n = (r(n) - t) * e), c ? Math.max(0, Math.min(1, n)) : n), + ); + } + function s(t) { + return function (n) { + var e, r; + return arguments.length + ? (([e, r] = n), (u = t(e, r)), f) + : [u(0), u(1)]; + }; + } + return ( + (f.domain = function (i) { + return arguments.length + ? (([o, a] = i), + (t = r((o = +o))), + (n = r((a = +a))), + (e = t === n ? 0 : 1 / (n - t)), + f) + : [o, a]; + }), + (f.clamp = function (t) { + return arguments.length ? ((c = !!t), f) : c; + }), + (f.interpolator = function (t) { + return arguments.length ? ((u = t), f) : u; + }), + (f.range = s(Gr)), + (f.rangeRound = s(Vr)), + (f.unknown = function (t) { + return arguments.length ? ((i = t), f) : i; + }), + function (i) { + return ( + (r = i), + (t = i(o)), + (n = i(a)), + (e = t === n ? 0 : 1 / (n - t)), + f + ); + } + ); + } + function B_(t, n) { + return n + .domain(t.domain()) + .interpolator(t.interpolator()) + .clamp(t.clamp()) + .unknown(t.unknown()); + } + function Y_() { + var t = Lg(O_()); + return ( + (t.copy = function () { + return B_(t, Y_()).exponent(t.exponent()); + }), + dg.apply(t, arguments) + ); + } + function L_() { + var t, + n, + e, + r, + i, + o, + a, + u = 0, + c = 0.5, + f = 1, + s = 1, + l = mg, + h = !1; + function d(t) { + return isNaN((t = +t)) + ? a + : ((t = 0.5 + ((t = +o(t)) - n) * (s * t < s * n ? r : i)), + l(h ? Math.max(0, Math.min(1, t)) : t)); + } + function p(t) { + return function (n) { + var e, r, i; + return arguments.length + ? (([e, r, i] = n), (l = di(t, [e, r, i])), d) + : [l(0), l(0.5), l(1)]; + }; + } + return ( + (d.domain = function (a) { + return arguments.length + ? (([u, c, f] = a), + (t = o((u = +u))), + (n = o((c = +c))), + (e = o((f = +f))), + (r = t === n ? 0 : 0.5 / (n - t)), + (i = n === e ? 0 : 0.5 / (e - n)), + (s = n < t ? -1 : 1), + d) + : [u, c, f]; + }), + (d.clamp = function (t) { + return arguments.length ? ((h = !!t), d) : h; + }), + (d.interpolator = function (t) { + return arguments.length ? ((l = t), d) : l; + }), + (d.range = p(Gr)), + (d.rangeRound = p(Vr)), + (d.unknown = function (t) { + return arguments.length ? ((a = t), d) : a; + }), + function (a) { + return ( + (o = a), + (t = a(u)), + (n = a(c)), + (e = a(f)), + (r = t === n ? 0 : 0.5 / (n - t)), + (i = n === e ? 0 : 0.5 / (e - n)), + (s = n < t ? -1 : 1), + d + ); + } + ); + } + function j_() { + var t = Lg(L_()); + return ( + (t.copy = function () { + return B_(t, j_()).exponent(t.exponent()); + }), + dg.apply(t, arguments) + ); + } + function H_(t) { + for (var n = (t.length / 6) | 0, e = new Array(n), r = 0; r < n; ) + e[r] = "#" + t.slice(6 * r, 6 * ++r); + return e; + } + var X_ = H_("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"), + G_ = H_("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"), + V_ = H_("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"), + W_ = H_("4269d0efb118ff725c6cc5b03ca951ff8ab7a463f297bbf59c6b4e9498a0"), + Z_ = H_( + "a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928", + ), + K_ = H_("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"), + Q_ = H_("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"), + J_ = H_("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"), + tb = H_("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"), + nb = H_( + "8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f", + ), + eb = H_("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab"), + rb = (t) => Fr(t[t.length - 1]), + ib = new Array(3) + .concat( + "d8b365f5f5f55ab4ac", + "a6611adfc27d80cdc1018571", + "a6611adfc27df5f5f580cdc1018571", + "8c510ad8b365f6e8c3c7eae55ab4ac01665e", + "8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e", + "8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e", + "8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e", + "5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30", + "5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30", + ) + .map(H_), + ob = rb(ib), + ab = new Array(3) + .concat( + "af8dc3f7f7f77fbf7b", + "7b3294c2a5cfa6dba0008837", + "7b3294c2a5cff7f7f7a6dba0008837", + "762a83af8dc3e7d4e8d9f0d37fbf7b1b7837", + "762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837", + "762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837", + "762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837", + "40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b", + "40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b", + ) + .map(H_), + ub = rb(ab), + cb = new Array(3) + .concat( + "e9a3c9f7f7f7a1d76a", + "d01c8bf1b6dab8e1864dac26", + "d01c8bf1b6daf7f7f7b8e1864dac26", + "c51b7de9a3c9fde0efe6f5d0a1d76a4d9221", + "c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221", + "c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221", + "c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221", + "8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419", + "8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419", + ) + .map(H_), + fb = rb(cb), + sb = new Array(3) + .concat( + "998ec3f7f7f7f1a340", + "5e3c99b2abd2fdb863e66101", + "5e3c99b2abd2f7f7f7fdb863e66101", + "542788998ec3d8daebfee0b6f1a340b35806", + "542788998ec3d8daebf7f7f7fee0b6f1a340b35806", + "5427888073acb2abd2d8daebfee0b6fdb863e08214b35806", + "5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806", + "2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08", + "2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08", + ) + .map(H_), + lb = rb(sb), + hb = new Array(3) + .concat( + "ef8a62f7f7f767a9cf", + "ca0020f4a58292c5de0571b0", + "ca0020f4a582f7f7f792c5de0571b0", + "b2182bef8a62fddbc7d1e5f067a9cf2166ac", + "b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac", + "b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac", + "b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac", + "67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061", + "67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061", + ) + .map(H_), + db = rb(hb), + pb = new Array(3) + .concat( + "ef8a62ffffff999999", + "ca0020f4a582bababa404040", + "ca0020f4a582ffffffbababa404040", + "b2182bef8a62fddbc7e0e0e09999994d4d4d", + "b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d", + "b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d", + "b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d", + "67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a", + "67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a", + ) + .map(H_), + gb = rb(pb), + yb = new Array(3) + .concat( + "fc8d59ffffbf91bfdb", + "d7191cfdae61abd9e92c7bb6", + "d7191cfdae61ffffbfabd9e92c7bb6", + "d73027fc8d59fee090e0f3f891bfdb4575b4", + "d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4", + "d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4", + "d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4", + "a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695", + "a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695", + ) + .map(H_), + vb = rb(yb), + _b = new Array(3) + .concat( + "fc8d59ffffbf91cf60", + "d7191cfdae61a6d96a1a9641", + "d7191cfdae61ffffbfa6d96a1a9641", + "d73027fc8d59fee08bd9ef8b91cf601a9850", + "d73027fc8d59fee08bffffbfd9ef8b91cf601a9850", + "d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850", + "d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850", + "a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837", + "a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837", + ) + .map(H_), + bb = rb(_b), + mb = new Array(3) + .concat( + "fc8d59ffffbf99d594", + "d7191cfdae61abdda42b83ba", + "d7191cfdae61ffffbfabdda42b83ba", + "d53e4ffc8d59fee08be6f59899d5943288bd", + "d53e4ffc8d59fee08bffffbfe6f59899d5943288bd", + "d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd", + "d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd", + "9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2", + "9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2", + ) + .map(H_), + xb = rb(mb), + wb = new Array(3) + .concat( + "e5f5f999d8c92ca25f", + "edf8fbb2e2e266c2a4238b45", + "edf8fbb2e2e266c2a42ca25f006d2c", + "edf8fbccece699d8c966c2a42ca25f006d2c", + "edf8fbccece699d8c966c2a441ae76238b45005824", + "f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824", + "f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b", + ) + .map(H_), + Mb = rb(wb), + Tb = new Array(3) + .concat( + "e0ecf49ebcda8856a7", + "edf8fbb3cde38c96c688419d", + "edf8fbb3cde38c96c68856a7810f7c", + "edf8fbbfd3e69ebcda8c96c68856a7810f7c", + "edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b", + "f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b", + "f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b", + ) + .map(H_), + Ab = rb(Tb), + Sb = new Array(3) + .concat( + "e0f3dba8ddb543a2ca", + "f0f9e8bae4bc7bccc42b8cbe", + "f0f9e8bae4bc7bccc443a2ca0868ac", + "f0f9e8ccebc5a8ddb57bccc443a2ca0868ac", + "f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e", + "f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e", + "f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081", + ) + .map(H_), + Eb = rb(Sb), + Nb = new Array(3) + .concat( + "fee8c8fdbb84e34a33", + "fef0d9fdcc8afc8d59d7301f", + "fef0d9fdcc8afc8d59e34a33b30000", + "fef0d9fdd49efdbb84fc8d59e34a33b30000", + "fef0d9fdd49efdbb84fc8d59ef6548d7301f990000", + "fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000", + "fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000", + ) + .map(H_), + kb = rb(Nb), + Cb = new Array(3) + .concat( + "ece2f0a6bddb1c9099", + "f6eff7bdc9e167a9cf02818a", + "f6eff7bdc9e167a9cf1c9099016c59", + "f6eff7d0d1e6a6bddb67a9cf1c9099016c59", + "f6eff7d0d1e6a6bddb67a9cf3690c002818a016450", + "fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450", + "fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636", + ) + .map(H_), + Pb = rb(Cb), + zb = new Array(3) + .concat( + "ece7f2a6bddb2b8cbe", + "f1eef6bdc9e174a9cf0570b0", + "f1eef6bdc9e174a9cf2b8cbe045a8d", + "f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d", + "f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b", + "fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b", + "fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858", + ) + .map(H_), + $b = rb(zb), + Db = new Array(3) + .concat( + "e7e1efc994c7dd1c77", + "f1eef6d7b5d8df65b0ce1256", + "f1eef6d7b5d8df65b0dd1c77980043", + "f1eef6d4b9dac994c7df65b0dd1c77980043", + "f1eef6d4b9dac994c7df65b0e7298ace125691003f", + "f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f", + "f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f", + ) + .map(H_), + Rb = rb(Db), + Fb = new Array(3) + .concat( + "fde0ddfa9fb5c51b8a", + "feebe2fbb4b9f768a1ae017e", + "feebe2fbb4b9f768a1c51b8a7a0177", + "feebe2fcc5c0fa9fb5f768a1c51b8a7a0177", + "feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177", + "fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177", + "fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a", + ) + .map(H_), + qb = rb(Fb), + Ub = new Array(3) + .concat( + "edf8b17fcdbb2c7fb8", + "ffffcca1dab441b6c4225ea8", + "ffffcca1dab441b6c42c7fb8253494", + "ffffccc7e9b47fcdbb41b6c42c7fb8253494", + "ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84", + "ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84", + "ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58", + ) + .map(H_), + Ib = rb(Ub), + Ob = new Array(3) + .concat( + "f7fcb9addd8e31a354", + "ffffccc2e69978c679238443", + "ffffccc2e69978c67931a354006837", + "ffffccd9f0a3addd8e78c67931a354006837", + "ffffccd9f0a3addd8e78c67941ab5d238443005a32", + "ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32", + "ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529", + ) + .map(H_), + Bb = rb(Ob), + Yb = new Array(3) + .concat( + "fff7bcfec44fd95f0e", + "ffffd4fed98efe9929cc4c02", + "ffffd4fed98efe9929d95f0e993404", + "ffffd4fee391fec44ffe9929d95f0e993404", + "ffffd4fee391fec44ffe9929ec7014cc4c028c2d04", + "ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04", + "ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506", + ) + .map(H_), + Lb = rb(Yb), + jb = new Array(3) + .concat( + "ffeda0feb24cf03b20", + "ffffb2fecc5cfd8d3ce31a1c", + "ffffb2fecc5cfd8d3cf03b20bd0026", + "ffffb2fed976feb24cfd8d3cf03b20bd0026", + "ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026", + "ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026", + "ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026", + ) + .map(H_), + Hb = rb(jb), + Xb = new Array(3) + .concat( + "deebf79ecae13182bd", + "eff3ffbdd7e76baed62171b5", + "eff3ffbdd7e76baed63182bd08519c", + "eff3ffc6dbef9ecae16baed63182bd08519c", + "eff3ffc6dbef9ecae16baed64292c62171b5084594", + "f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594", + "f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b", + ) + .map(H_), + Gb = rb(Xb), + Vb = new Array(3) + .concat( + "e5f5e0a1d99b31a354", + "edf8e9bae4b374c476238b45", + "edf8e9bae4b374c47631a354006d2c", + "edf8e9c7e9c0a1d99b74c47631a354006d2c", + "edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32", + "f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32", + "f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b", + ) + .map(H_), + Wb = rb(Vb), + Zb = new Array(3) + .concat( + "f0f0f0bdbdbd636363", + "f7f7f7cccccc969696525252", + "f7f7f7cccccc969696636363252525", + "f7f7f7d9d9d9bdbdbd969696636363252525", + "f7f7f7d9d9d9bdbdbd969696737373525252252525", + "fffffff0f0f0d9d9d9bdbdbd969696737373525252252525", + "fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000", + ) + .map(H_), + Kb = rb(Zb), + Qb = new Array(3) + .concat( + "efedf5bcbddc756bb1", + "f2f0f7cbc9e29e9ac86a51a3", + "f2f0f7cbc9e29e9ac8756bb154278f", + "f2f0f7dadaebbcbddc9e9ac8756bb154278f", + "f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486", + "fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486", + "fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d", + ) + .map(H_), + Jb = rb(Qb), + tm = new Array(3) + .concat( + "fee0d2fc9272de2d26", + "fee5d9fcae91fb6a4acb181d", + "fee5d9fcae91fb6a4ade2d26a50f15", + "fee5d9fcbba1fc9272fb6a4ade2d26a50f15", + "fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d", + "fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d", + "fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d", + ) + .map(H_), + nm = rb(tm), + em = new Array(3) + .concat( + "fee6cefdae6be6550d", + "feeddefdbe85fd8d3cd94701", + "feeddefdbe85fd8d3ce6550da63603", + "feeddefdd0a2fdae6bfd8d3ce6550da63603", + "feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04", + "fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04", + "fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704", + ) + .map(H_), + rm = rb(em); + var im = hi(Tr(300, 0.5, 0), Tr(-240, 0.5, 1)), + om = hi(Tr(-100, 0.75, 0.35), Tr(80, 1.5, 0.8)), + am = hi(Tr(260, 0.75, 0.35), Tr(80, 1.5, 0.8)), + um = Tr(); + var cm = Fe(), + fm = Math.PI / 3, + sm = (2 * Math.PI) / 3; + function lm(t) { + var n = t.length; + return function (e) { + return t[Math.max(0, Math.min(n - 1, Math.floor(e * n)))]; + }; + } + var hm = lm( + H_( + "44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725", + ), + ), + dm = lm( + H_( + "00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf", + ), + ), + pm = lm( + H_( + "00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4", + ), + ), + gm = lm( + H_( + "0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921", + ), + ); + function ym(t) { + return function () { + return t; + }; + } + const vm = Math.abs, + _m = Math.atan2, + bm = Math.cos, + mm = Math.max, + xm = Math.min, + wm = Math.sin, + Mm = Math.sqrt, + Tm = 1e-12, + Am = Math.PI, + Sm = Am / 2, + Em = 2 * Am; + function Nm(t) { + return t >= 1 ? Sm : t <= -1 ? -Sm : Math.asin(t); + } + function km(t) { + let n = 3; + return ( + (t.digits = function (e) { + if (!arguments.length) return n; + if (null == e) n = null; + else { + const t = Math.floor(e); + if (!(t >= 0)) throw new RangeError(`invalid digits: ${e}`); + n = t; + } + return t; + }), + () => new Ua(n) + ); + } + function Cm(t) { + return t.innerRadius; + } + function Pm(t) { + return t.outerRadius; + } + function zm(t) { + return t.startAngle; + } + function $m(t) { + return t.endAngle; + } + function Dm(t) { + return t && t.padAngle; + } + function Rm(t, n, e, r, i, o, a) { + var u = t - e, + c = n - r, + f = (a ? o : -o) / Mm(u * u + c * c), + s = f * c, + l = -f * u, + h = t + s, + d = n + l, + p = e + s, + g = r + l, + y = (h + p) / 2, + v = (d + g) / 2, + _ = p - h, + b = g - d, + m = _ * _ + b * b, + x = i - o, + w = h * g - p * d, + M = (b < 0 ? -1 : 1) * Mm(mm(0, x * x * m - w * w)), + T = (w * b - _ * M) / m, + A = (-w * _ - b * M) / m, + S = (w * b + _ * M) / m, + E = (-w * _ + b * M) / m, + N = T - y, + k = A - v, + C = S - y, + P = E - v; + return ( + N * N + k * k > C * C + P * P && ((T = S), (A = E)), + { + cx: T, + cy: A, + x01: -s, + y01: -l, + x11: T * (i / x - 1), + y11: A * (i / x - 1), + } + ); + } + var Fm = Array.prototype.slice; + function qm(t) { + return "object" == typeof t && "length" in t ? t : Array.from(t); + } + function Um(t) { + this._context = t; + } + function Im(t) { + return new Um(t); + } + function Om(t) { + return t[0]; + } + function Bm(t) { + return t[1]; + } + function Ym(t, n) { + var e = ym(!0), + r = null, + i = Im, + o = null, + a = km(u); + function u(u) { + var c, + f, + s, + l = (u = qm(u)).length, + h = !1; + for (null == r && (o = i((s = a()))), c = 0; c <= l; ++c) + (!(c < l && e((f = u[c]), c, u)) === h && + ((h = !h) ? o.lineStart() : o.lineEnd()), + h && o.point(+t(f, c, u), +n(f, c, u))); + if (s) return ((o = null), s + "" || null); + } + return ( + (t = "function" == typeof t ? t : void 0 === t ? Om : ym(t)), + (n = "function" == typeof n ? n : void 0 === n ? Bm : ym(n)), + (u.x = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(+n)), u) + : t; + }), + (u.y = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : ym(+t)), u) + : n; + }), + (u.defined = function (t) { + return arguments.length + ? ((e = "function" == typeof t ? t : ym(!!t)), u) + : e; + }), + (u.curve = function (t) { + return arguments.length ? ((i = t), null != r && (o = i(r)), u) : i; + }), + (u.context = function (t) { + return arguments.length + ? (null == t ? (r = o = null) : (o = i((r = t))), u) + : r; + }), + u + ); + } + function Lm(t, n, e) { + var r = null, + i = ym(!0), + o = null, + a = Im, + u = null, + c = km(f); + function f(f) { + var s, + l, + h, + d, + p, + g = (f = qm(f)).length, + y = !1, + v = new Array(g), + _ = new Array(g); + for (null == o && (u = a((p = c()))), s = 0; s <= g; ++s) { + if (!(s < g && i((d = f[s]), s, f)) === y) + if ((y = !y)) ((l = s), u.areaStart(), u.lineStart()); + else { + for (u.lineEnd(), u.lineStart(), h = s - 1; h >= l; --h) + u.point(v[h], _[h]); + (u.lineEnd(), u.areaEnd()); + } + y && + ((v[s] = +t(d, s, f)), + (_[s] = +n(d, s, f)), + u.point(r ? +r(d, s, f) : v[s], e ? +e(d, s, f) : _[s])); + } + if (p) return ((u = null), p + "" || null); + } + function s() { + return Ym().defined(i).curve(a).context(o); + } + return ( + (t = "function" == typeof t ? t : void 0 === t ? Om : ym(+t)), + (n = "function" == typeof n ? n : ym(void 0 === n ? 0 : +n)), + (e = "function" == typeof e ? e : void 0 === e ? Bm : ym(+e)), + (f.x = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(+n)), (r = null), f) + : t; + }), + (f.x0 = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(+n)), f) + : t; + }), + (f.x1 = function (t) { + return arguments.length + ? ((r = null == t ? null : "function" == typeof t ? t : ym(+t)), f) + : r; + }), + (f.y = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : ym(+t)), (e = null), f) + : n; + }), + (f.y0 = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : ym(+t)), f) + : n; + }), + (f.y1 = function (t) { + return arguments.length + ? ((e = null == t ? null : "function" == typeof t ? t : ym(+t)), f) + : e; + }), + (f.lineX0 = f.lineY0 = + function () { + return s().x(t).y(n); + }), + (f.lineY1 = function () { + return s().x(t).y(e); + }), + (f.lineX1 = function () { + return s().x(r).y(n); + }), + (f.defined = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : ym(!!t)), f) + : i; + }), + (f.curve = function (t) { + return arguments.length ? ((a = t), null != o && (u = a(o)), f) : a; + }), + (f.context = function (t) { + return arguments.length + ? (null == t ? (o = u = null) : (u = a((o = t))), f) + : o; + }), + f + ); + } + function jm(t, n) { + return n < t ? -1 : n > t ? 1 : n >= t ? 0 : NaN; + } + function Hm(t) { + return t; + } + Um.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + ((this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + this._point = 2; + default: + this._context.lineTo(t, n); + } + }, + }; + var Xm = Vm(Im); + function Gm(t) { + this._curve = t; + } + function Vm(t) { + function n(n) { + return new Gm(t(n)); + } + return ((n._curve = t), n); + } + function Wm(t) { + var n = t.curve; + return ( + (t.angle = t.x), + delete t.x, + (t.radius = t.y), + delete t.y, + (t.curve = function (t) { + return arguments.length ? n(Vm(t)) : n()._curve; + }), + t + ); + } + function Zm() { + return Wm(Ym().curve(Xm)); + } + function Km() { + var t = Lm().curve(Xm), + n = t.curve, + e = t.lineX0, + r = t.lineX1, + i = t.lineY0, + o = t.lineY1; + return ( + (t.angle = t.x), + delete t.x, + (t.startAngle = t.x0), + delete t.x0, + (t.endAngle = t.x1), + delete t.x1, + (t.radius = t.y), + delete t.y, + (t.innerRadius = t.y0), + delete t.y0, + (t.outerRadius = t.y1), + delete t.y1, + (t.lineStartAngle = function () { + return Wm(e()); + }), + delete t.lineX0, + (t.lineEndAngle = function () { + return Wm(r()); + }), + delete t.lineX1, + (t.lineInnerRadius = function () { + return Wm(i()); + }), + delete t.lineY0, + (t.lineOuterRadius = function () { + return Wm(o()); + }), + delete t.lineY1, + (t.curve = function (t) { + return arguments.length ? n(Vm(t)) : n()._curve; + }), + t + ); + } + function Qm(t, n) { + return [(n = +n) * Math.cos((t -= Math.PI / 2)), n * Math.sin(t)]; + } + Gm.prototype = { + areaStart: function () { + this._curve.areaStart(); + }, + areaEnd: function () { + this._curve.areaEnd(); + }, + lineStart: function () { + this._curve.lineStart(); + }, + lineEnd: function () { + this._curve.lineEnd(); + }, + point: function (t, n) { + this._curve.point(n * Math.sin(t), n * -Math.cos(t)); + }, + }; + class Jm { + constructor(t, n) { + ((this._context = t), (this._x = n)); + } + areaStart() { + this._line = 0; + } + areaEnd() { + this._line = NaN; + } + lineStart() { + this._point = 0; + } + lineEnd() { + ((this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + } + point(t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + this._point = 2; + default: + this._x + ? this._context.bezierCurveTo( + (this._x0 = (this._x0 + t) / 2), + this._y0, + this._x0, + n, + t, + n, + ) + : this._context.bezierCurveTo( + this._x0, + (this._y0 = (this._y0 + n) / 2), + t, + this._y0, + t, + n, + ); + } + ((this._x0 = t), (this._y0 = n)); + } + } + class tx { + constructor(t) { + this._context = t; + } + lineStart() { + this._point = 0; + } + lineEnd() {} + point(t, n) { + if (((t = +t), (n = +n), 0 === this._point)) this._point = 1; + else { + const e = Qm(this._x0, this._y0), + r = Qm(this._x0, (this._y0 = (this._y0 + n) / 2)), + i = Qm(t, this._y0), + o = Qm(t, n); + (this._context.moveTo(...e), + this._context.bezierCurveTo(...r, ...i, ...o)); + } + ((this._x0 = t), (this._y0 = n)); + } + } + function nx(t) { + return new Jm(t, !0); + } + function ex(t) { + return new Jm(t, !1); + } + function rx(t) { + return new tx(t); + } + function ix(t) { + return t.source; + } + function ox(t) { + return t.target; + } + function ax(t) { + let n = ix, + e = ox, + r = Om, + i = Bm, + o = null, + a = null, + u = km(c); + function c() { + let c; + const f = Fm.call(arguments), + s = n.apply(this, f), + l = e.apply(this, f); + if ( + (null == o && (a = t((c = u()))), + a.lineStart(), + (f[0] = s), + a.point(+r.apply(this, f), +i.apply(this, f)), + (f[0] = l), + a.point(+r.apply(this, f), +i.apply(this, f)), + a.lineEnd(), + c) + ) + return ((a = null), c + "" || null); + } + return ( + (c.source = function (t) { + return arguments.length ? ((n = t), c) : n; + }), + (c.target = function (t) { + return arguments.length ? ((e = t), c) : e; + }), + (c.x = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : ym(+t)), c) + : r; + }), + (c.y = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : ym(+t)), c) + : i; + }), + (c.context = function (n) { + return arguments.length + ? (null == n ? (o = a = null) : (a = t((o = n))), c) + : o; + }), + c + ); + } + const ux = Mm(3); + var cx = { + draw(t, n) { + const e = 0.59436 * Mm(n + xm(n / 28, 0.75)), + r = e / 2, + i = r * ux; + (t.moveTo(0, e), + t.lineTo(0, -e), + t.moveTo(-i, -r), + t.lineTo(i, r), + t.moveTo(-i, r), + t.lineTo(i, -r)); + }, + }, + fx = { + draw(t, n) { + const e = Mm(n / Am); + (t.moveTo(e, 0), t.arc(0, 0, e, 0, Em)); + }, + }, + sx = { + draw(t, n) { + const e = Mm(n / 5) / 2; + (t.moveTo(-3 * e, -e), + t.lineTo(-e, -e), + t.lineTo(-e, -3 * e), + t.lineTo(e, -3 * e), + t.lineTo(e, -e), + t.lineTo(3 * e, -e), + t.lineTo(3 * e, e), + t.lineTo(e, e), + t.lineTo(e, 3 * e), + t.lineTo(-e, 3 * e), + t.lineTo(-e, e), + t.lineTo(-3 * e, e), + t.closePath()); + }, + }; + const lx = Mm(1 / 3), + hx = 2 * lx; + var dx = { + draw(t, n) { + const e = Mm(n / hx), + r = e * lx; + (t.moveTo(0, -e), + t.lineTo(r, 0), + t.lineTo(0, e), + t.lineTo(-r, 0), + t.closePath()); + }, + }, + px = { + draw(t, n) { + const e = 0.62625 * Mm(n); + (t.moveTo(0, -e), + t.lineTo(e, 0), + t.lineTo(0, e), + t.lineTo(-e, 0), + t.closePath()); + }, + }, + gx = { + draw(t, n) { + const e = 0.87559 * Mm(n - xm(n / 7, 2)); + (t.moveTo(-e, 0), t.lineTo(e, 0), t.moveTo(0, e), t.lineTo(0, -e)); + }, + }, + yx = { + draw(t, n) { + const e = Mm(n), + r = -e / 2; + t.rect(r, r, e, e); + }, + }, + vx = { + draw(t, n) { + const e = 0.4431 * Mm(n); + (t.moveTo(e, e), + t.lineTo(e, -e), + t.lineTo(-e, -e), + t.lineTo(-e, e), + t.closePath()); + }, + }; + const _x = wm(Am / 10) / wm((7 * Am) / 10), + bx = wm(Em / 10) * _x, + mx = -bm(Em / 10) * _x; + var xx = { + draw(t, n) { + const e = Mm(0.8908130915292852 * n), + r = bx * e, + i = mx * e; + (t.moveTo(0, -e), t.lineTo(r, i)); + for (let n = 1; n < 5; ++n) { + const o = (Em * n) / 5, + a = bm(o), + u = wm(o); + (t.lineTo(u * e, -a * e), t.lineTo(a * r - u * i, u * r + a * i)); + } + t.closePath(); + }, + }; + const wx = Mm(3); + var Mx = { + draw(t, n) { + const e = -Mm(n / (3 * wx)); + (t.moveTo(0, 2 * e), + t.lineTo(-wx * e, -e), + t.lineTo(wx * e, -e), + t.closePath()); + }, + }; + const Tx = Mm(3); + var Ax = { + draw(t, n) { + const e = 0.6824 * Mm(n), + r = e / 2, + i = (e * Tx) / 2; + (t.moveTo(0, -e), t.lineTo(i, r), t.lineTo(-i, r), t.closePath()); + }, + }; + const Sx = -0.5, + Ex = Mm(3) / 2, + Nx = 1 / Mm(12), + kx = 3 * (Nx / 2 + 1); + var Cx = { + draw(t, n) { + const e = Mm(n / kx), + r = e / 2, + i = e * Nx, + o = r, + a = e * Nx + e, + u = -o, + c = a; + (t.moveTo(r, i), + t.lineTo(o, a), + t.lineTo(u, c), + t.lineTo(Sx * r - Ex * i, Ex * r + Sx * i), + t.lineTo(Sx * o - Ex * a, Ex * o + Sx * a), + t.lineTo(Sx * u - Ex * c, Ex * u + Sx * c), + t.lineTo(Sx * r + Ex * i, Sx * i - Ex * r), + t.lineTo(Sx * o + Ex * a, Sx * a - Ex * o), + t.lineTo(Sx * u + Ex * c, Sx * c - Ex * u), + t.closePath()); + }, + }, + Px = { + draw(t, n) { + const e = 0.6189 * Mm(n - xm(n / 6, 1.7)); + (t.moveTo(-e, -e), t.lineTo(e, e), t.moveTo(-e, e), t.lineTo(e, -e)); + }, + }; + const zx = [fx, sx, dx, yx, xx, Mx, Cx], + $x = [fx, gx, Px, Ax, cx, vx, px]; + function Dx() {} + function Rx(t, n, e) { + t._context.bezierCurveTo( + (2 * t._x0 + t._x1) / 3, + (2 * t._y0 + t._y1) / 3, + (t._x0 + 2 * t._x1) / 3, + (t._y0 + 2 * t._y1) / 3, + (t._x0 + 4 * t._x1 + n) / 6, + (t._y0 + 4 * t._y1 + e) / 6, + ); + } + function Fx(t) { + this._context = t; + } + function qx(t) { + this._context = t; + } + function Ux(t) { + this._context = t; + } + function Ix(t, n) { + ((this._basis = new Fx(t)), (this._beta = n)); + } + ((Fx.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._y0 = this._y1 = NaN), (this._point = 0)); + }, + lineEnd: function () { + switch (this._point) { + case 3: + Rx(this, this._x1, this._y1); + case 2: + this._context.lineTo(this._x1, this._y1); + } + ((this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + this._point = 2; + break; + case 2: + ((this._point = 3), + this._context.lineTo( + (5 * this._x0 + this._x1) / 6, + (5 * this._y0 + this._y1) / 6, + )); + default: + Rx(this, t, n); + } + ((this._x0 = this._x1), + (this._x1 = t), + (this._y0 = this._y1), + (this._y1 = n)); + }, + }), + (qx.prototype = { + areaStart: Dx, + areaEnd: Dx, + lineStart: function () { + ((this._x0 = + this._x1 = + this._x2 = + this._x3 = + this._x4 = + this._y0 = + this._y1 = + this._y2 = + this._y3 = + this._y4 = + NaN), + (this._point = 0)); + }, + lineEnd: function () { + switch (this._point) { + case 1: + (this._context.moveTo(this._x2, this._y2), + this._context.closePath()); + break; + case 2: + (this._context.moveTo( + (this._x2 + 2 * this._x3) / 3, + (this._y2 + 2 * this._y3) / 3, + ), + this._context.lineTo( + (this._x3 + 2 * this._x2) / 3, + (this._y3 + 2 * this._y2) / 3, + ), + this._context.closePath()); + break; + case 3: + (this.point(this._x2, this._y2), + this.point(this._x3, this._y3), + this.point(this._x4, this._y4)); + } + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), (this._x2 = t), (this._y2 = n)); + break; + case 1: + ((this._point = 2), (this._x3 = t), (this._y3 = n)); + break; + case 2: + ((this._point = 3), + (this._x4 = t), + (this._y4 = n), + this._context.moveTo( + (this._x0 + 4 * this._x1 + t) / 6, + (this._y0 + 4 * this._y1 + n) / 6, + )); + break; + default: + Rx(this, t, n); + } + ((this._x0 = this._x1), + (this._x1 = t), + (this._y0 = this._y1), + (this._y1 = n)); + }, + }), + (Ux.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._y0 = this._y1 = NaN), (this._point = 0)); + }, + lineEnd: function () { + ((this._line || (0 !== this._line && 3 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + this._point = 1; + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + var e = (this._x0 + 4 * this._x1 + t) / 6, + r = (this._y0 + 4 * this._y1 + n) / 6; + this._line + ? this._context.lineTo(e, r) + : this._context.moveTo(e, r); + break; + case 3: + this._point = 4; + default: + Rx(this, t, n); + } + ((this._x0 = this._x1), + (this._x1 = t), + (this._y0 = this._y1), + (this._y1 = n)); + }, + }), + (Ix.prototype = { + lineStart: function () { + ((this._x = []), (this._y = []), this._basis.lineStart()); + }, + lineEnd: function () { + var t = this._x, + n = this._y, + e = t.length - 1; + if (e > 0) + for ( + var r, i = t[0], o = n[0], a = t[e] - i, u = n[e] - o, c = -1; + ++c <= e; + + ) + ((r = c / e), + this._basis.point( + this._beta * t[c] + (1 - this._beta) * (i + r * a), + this._beta * n[c] + (1 - this._beta) * (o + r * u), + )); + ((this._x = this._y = null), this._basis.lineEnd()); + }, + point: function (t, n) { + (this._x.push(+t), this._y.push(+n)); + }, + })); + var Ox = (function t(n) { + function e(t) { + return 1 === n ? new Fx(t) : new Ix(t, n); + } + return ( + (e.beta = function (n) { + return t(+n); + }), + e + ); + })(0.85); + function Bx(t, n, e) { + t._context.bezierCurveTo( + t._x1 + t._k * (t._x2 - t._x0), + t._y1 + t._k * (t._y2 - t._y0), + t._x2 + t._k * (t._x1 - n), + t._y2 + t._k * (t._y1 - e), + t._x2, + t._y2, + ); + } + function Yx(t, n) { + ((this._context = t), (this._k = (1 - n) / 6)); + } + Yx.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN), + (this._point = 0)); + }, + lineEnd: function () { + switch (this._point) { + case 2: + this._context.lineTo(this._x2, this._y2); + break; + case 3: + Bx(this, this._x1, this._y1); + } + ((this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + ((this._point = 2), (this._x1 = t), (this._y1 = n)); + break; + case 2: + this._point = 3; + default: + Bx(this, t, n); + } + ((this._x0 = this._x1), + (this._x1 = this._x2), + (this._x2 = t), + (this._y0 = this._y1), + (this._y1 = this._y2), + (this._y2 = n)); + }, + }; + var Lx = (function t(n) { + function e(t) { + return new Yx(t, n); + } + return ( + (e.tension = function (n) { + return t(+n); + }), + e + ); + })(0); + function jx(t, n) { + ((this._context = t), (this._k = (1 - n) / 6)); + } + jx.prototype = { + areaStart: Dx, + areaEnd: Dx, + lineStart: function () { + ((this._x0 = + this._x1 = + this._x2 = + this._x3 = + this._x4 = + this._x5 = + this._y0 = + this._y1 = + this._y2 = + this._y3 = + this._y4 = + this._y5 = + NaN), + (this._point = 0)); + }, + lineEnd: function () { + switch (this._point) { + case 1: + (this._context.moveTo(this._x3, this._y3), this._context.closePath()); + break; + case 2: + (this._context.lineTo(this._x3, this._y3), this._context.closePath()); + break; + case 3: + (this.point(this._x3, this._y3), + this.point(this._x4, this._y4), + this.point(this._x5, this._y5)); + } + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), (this._x3 = t), (this._y3 = n)); + break; + case 1: + ((this._point = 2), + this._context.moveTo((this._x4 = t), (this._y4 = n))); + break; + case 2: + ((this._point = 3), (this._x5 = t), (this._y5 = n)); + break; + default: + Bx(this, t, n); + } + ((this._x0 = this._x1), + (this._x1 = this._x2), + (this._x2 = t), + (this._y0 = this._y1), + (this._y1 = this._y2), + (this._y2 = n)); + }, + }; + var Hx = (function t(n) { + function e(t) { + return new jx(t, n); + } + return ( + (e.tension = function (n) { + return t(+n); + }), + e + ); + })(0); + function Xx(t, n) { + ((this._context = t), (this._k = (1 - n) / 6)); + } + Xx.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN), + (this._point = 0)); + }, + lineEnd: function () { + ((this._line || (0 !== this._line && 3 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + this._point = 1; + break; + case 1: + this._point = 2; + break; + case 2: + ((this._point = 3), + this._line + ? this._context.lineTo(this._x2, this._y2) + : this._context.moveTo(this._x2, this._y2)); + break; + case 3: + this._point = 4; + default: + Bx(this, t, n); + } + ((this._x0 = this._x1), + (this._x1 = this._x2), + (this._x2 = t), + (this._y0 = this._y1), + (this._y1 = this._y2), + (this._y2 = n)); + }, + }; + var Gx = (function t(n) { + function e(t) { + return new Xx(t, n); + } + return ( + (e.tension = function (n) { + return t(+n); + }), + e + ); + })(0); + function Vx(t, n, e) { + var r = t._x1, + i = t._y1, + o = t._x2, + a = t._y2; + if (t._l01_a > Tm) { + var u = 2 * t._l01_2a + 3 * t._l01_a * t._l12_a + t._l12_2a, + c = 3 * t._l01_a * (t._l01_a + t._l12_a); + ((r = (r * u - t._x0 * t._l12_2a + t._x2 * t._l01_2a) / c), + (i = (i * u - t._y0 * t._l12_2a + t._y2 * t._l01_2a) / c)); + } + if (t._l23_a > Tm) { + var f = 2 * t._l23_2a + 3 * t._l23_a * t._l12_a + t._l12_2a, + s = 3 * t._l23_a * (t._l23_a + t._l12_a); + ((o = (o * f + t._x1 * t._l23_2a - n * t._l12_2a) / s), + (a = (a * f + t._y1 * t._l23_2a - e * t._l12_2a) / s)); + } + t._context.bezierCurveTo(r, i, o, a, t._x2, t._y2); + } + function Wx(t, n) { + ((this._context = t), (this._alpha = n)); + } + Wx.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN), + (this._l01_a = + this._l12_a = + this._l23_a = + this._l01_2a = + this._l12_2a = + this._l23_2a = + this._point = + 0)); + }, + lineEnd: function () { + switch (this._point) { + case 2: + this._context.lineTo(this._x2, this._y2); + break; + case 3: + this.point(this._x2, this._y2); + } + ((this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + if (((t = +t), (n = +n), this._point)) { + var e = this._x2 - t, + r = this._y2 - n; + this._l23_a = Math.sqrt( + (this._l23_2a = Math.pow(e * e + r * r, this._alpha)), + ); + } + switch (this._point) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + default: + Vx(this, t, n); + } + ((this._l01_a = this._l12_a), + (this._l12_a = this._l23_a), + (this._l01_2a = this._l12_2a), + (this._l12_2a = this._l23_2a), + (this._x0 = this._x1), + (this._x1 = this._x2), + (this._x2 = t), + (this._y0 = this._y1), + (this._y1 = this._y2), + (this._y2 = n)); + }, + }; + var Zx = (function t(n) { + function e(t) { + return n ? new Wx(t, n) : new Yx(t, 0); + } + return ( + (e.alpha = function (n) { + return t(+n); + }), + e + ); + })(0.5); + function Kx(t, n) { + ((this._context = t), (this._alpha = n)); + } + Kx.prototype = { + areaStart: Dx, + areaEnd: Dx, + lineStart: function () { + ((this._x0 = + this._x1 = + this._x2 = + this._x3 = + this._x4 = + this._x5 = + this._y0 = + this._y1 = + this._y2 = + this._y3 = + this._y4 = + this._y5 = + NaN), + (this._l01_a = + this._l12_a = + this._l23_a = + this._l01_2a = + this._l12_2a = + this._l23_2a = + this._point = + 0)); + }, + lineEnd: function () { + switch (this._point) { + case 1: + (this._context.moveTo(this._x3, this._y3), this._context.closePath()); + break; + case 2: + (this._context.lineTo(this._x3, this._y3), this._context.closePath()); + break; + case 3: + (this.point(this._x3, this._y3), + this.point(this._x4, this._y4), + this.point(this._x5, this._y5)); + } + }, + point: function (t, n) { + if (((t = +t), (n = +n), this._point)) { + var e = this._x2 - t, + r = this._y2 - n; + this._l23_a = Math.sqrt( + (this._l23_2a = Math.pow(e * e + r * r, this._alpha)), + ); + } + switch (this._point) { + case 0: + ((this._point = 1), (this._x3 = t), (this._y3 = n)); + break; + case 1: + ((this._point = 2), + this._context.moveTo((this._x4 = t), (this._y4 = n))); + break; + case 2: + ((this._point = 3), (this._x5 = t), (this._y5 = n)); + break; + default: + Vx(this, t, n); + } + ((this._l01_a = this._l12_a), + (this._l12_a = this._l23_a), + (this._l01_2a = this._l12_2a), + (this._l12_2a = this._l23_2a), + (this._x0 = this._x1), + (this._x1 = this._x2), + (this._x2 = t), + (this._y0 = this._y1), + (this._y1 = this._y2), + (this._y2 = n)); + }, + }; + var Qx = (function t(n) { + function e(t) { + return n ? new Kx(t, n) : new jx(t, 0); + } + return ( + (e.alpha = function (n) { + return t(+n); + }), + e + ); + })(0.5); + function Jx(t, n) { + ((this._context = t), (this._alpha = n)); + } + Jx.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN), + (this._l01_a = + this._l12_a = + this._l23_a = + this._l01_2a = + this._l12_2a = + this._l23_2a = + this._point = + 0)); + }, + lineEnd: function () { + ((this._line || (0 !== this._line && 3 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + if (((t = +t), (n = +n), this._point)) { + var e = this._x2 - t, + r = this._y2 - n; + this._l23_a = Math.sqrt( + (this._l23_2a = Math.pow(e * e + r * r, this._alpha)), + ); + } + switch (this._point) { + case 0: + this._point = 1; + break; + case 1: + this._point = 2; + break; + case 2: + ((this._point = 3), + this._line + ? this._context.lineTo(this._x2, this._y2) + : this._context.moveTo(this._x2, this._y2)); + break; + case 3: + this._point = 4; + default: + Vx(this, t, n); + } + ((this._l01_a = this._l12_a), + (this._l12_a = this._l23_a), + (this._l01_2a = this._l12_2a), + (this._l12_2a = this._l23_2a), + (this._x0 = this._x1), + (this._x1 = this._x2), + (this._x2 = t), + (this._y0 = this._y1), + (this._y1 = this._y2), + (this._y2 = n)); + }, + }; + var tw = (function t(n) { + function e(t) { + return n ? new Jx(t, n) : new Xx(t, 0); + } + return ( + (e.alpha = function (n) { + return t(+n); + }), + e + ); + })(0.5); + function nw(t) { + this._context = t; + } + function ew(t) { + return t < 0 ? -1 : 1; + } + function rw(t, n, e) { + var r = t._x1 - t._x0, + i = n - t._x1, + o = (t._y1 - t._y0) / (r || (i < 0 && -0)), + a = (e - t._y1) / (i || (r < 0 && -0)), + u = (o * i + a * r) / (r + i); + return ( + (ew(o) + ew(a)) * Math.min(Math.abs(o), Math.abs(a), 0.5 * Math.abs(u)) || + 0 + ); + } + function iw(t, n) { + var e = t._x1 - t._x0; + return e ? ((3 * (t._y1 - t._y0)) / e - n) / 2 : n; + } + function ow(t, n, e) { + var r = t._x0, + i = t._y0, + o = t._x1, + a = t._y1, + u = (o - r) / 3; + t._context.bezierCurveTo(r + u, i + u * n, o - u, a - u * e, o, a); + } + function aw(t) { + this._context = t; + } + function uw(t) { + this._context = new cw(t); + } + function cw(t) { + this._context = t; + } + function fw(t) { + this._context = t; + } + function sw(t) { + var n, + e, + r = t.length - 1, + i = new Array(r), + o = new Array(r), + a = new Array(r); + for (i[0] = 0, o[0] = 2, a[0] = t[0] + 2 * t[1], n = 1; n < r - 1; ++n) + ((i[n] = 1), (o[n] = 4), (a[n] = 4 * t[n] + 2 * t[n + 1])); + for ( + i[r - 1] = 2, o[r - 1] = 7, a[r - 1] = 8 * t[r - 1] + t[r], n = 1; + n < r; + ++n + ) + ((e = i[n] / o[n - 1]), (o[n] -= e), (a[n] -= e * a[n - 1])); + for (i[r - 1] = a[r - 1] / o[r - 1], n = r - 2; n >= 0; --n) + i[n] = (a[n] - i[n + 1]) / o[n]; + for (o[r - 1] = (t[r] + i[r - 1]) / 2, n = 0; n < r - 1; ++n) + o[n] = 2 * t[n + 1] - i[n + 1]; + return [i, o]; + } + function lw(t, n) { + ((this._context = t), (this._t = n)); + } + function hw(t, n) { + if ((i = t.length) > 1) + for (var e, r, i, o = 1, a = t[n[0]], u = a.length; o < i; ++o) + for (r = a, a = t[n[o]], e = 0; e < u; ++e) + a[e][1] += a[e][0] = isNaN(r[e][1]) ? r[e][0] : r[e][1]; + } + function dw(t) { + for (var n = t.length, e = new Array(n); --n >= 0; ) e[n] = n; + return e; + } + function pw(t, n) { + return t[n]; + } + function gw(t) { + const n = []; + return ((n.key = t), n); + } + function yw(t) { + var n = t.map(vw); + return dw(t).sort(function (t, e) { + return n[t] - n[e]; + }); + } + function vw(t) { + for (var n, e = -1, r = 0, i = t.length, o = -1 / 0; ++e < i; ) + (n = +t[e][1]) > o && ((o = n), (r = e)); + return r; + } + function _w(t) { + var n = t.map(bw); + return dw(t).sort(function (t, e) { + return n[t] - n[e]; + }); + } + function bw(t) { + for (var n, e = 0, r = -1, i = t.length; ++r < i; ) + (n = +t[r][1]) && (e += n); + return e; + } + ((nw.prototype = { + areaStart: Dx, + areaEnd: Dx, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + this._point && this._context.closePath(); + }, + point: function (t, n) { + ((t = +t), + (n = +n), + this._point + ? this._context.lineTo(t, n) + : ((this._point = 1), this._context.moveTo(t, n))); + }, + }), + (aw.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN), + (this._point = 0)); + }, + lineEnd: function () { + switch (this._point) { + case 2: + this._context.lineTo(this._x1, this._y1); + break; + case 3: + ow(this, this._t0, iw(this, this._t0)); + } + ((this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + (this._line = 1 - this._line)); + }, + point: function (t, n) { + var e = NaN; + if (((n = +n), (t = +t) !== this._x1 || n !== this._y1)) { + switch (this._point) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + this._point = 2; + break; + case 2: + ((this._point = 3), ow(this, iw(this, (e = rw(this, t, n))), e)); + break; + default: + ow(this, this._t0, (e = rw(this, t, n))); + } + ((this._x0 = this._x1), + (this._x1 = t), + (this._y0 = this._y1), + (this._y1 = n), + (this._t0 = e)); + } + }, + }), + ((uw.prototype = Object.create(aw.prototype)).point = function (t, n) { + aw.prototype.point.call(this, n, t); + }), + (cw.prototype = { + moveTo: function (t, n) { + this._context.moveTo(n, t); + }, + closePath: function () { + this._context.closePath(); + }, + lineTo: function (t, n) { + this._context.lineTo(n, t); + }, + bezierCurveTo: function (t, n, e, r, i, o) { + this._context.bezierCurveTo(n, t, r, e, o, i); + }, + }), + (fw.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x = []), (this._y = [])); + }, + lineEnd: function () { + var t = this._x, + n = this._y, + e = t.length; + if (e) + if ( + (this._line + ? this._context.lineTo(t[0], n[0]) + : this._context.moveTo(t[0], n[0]), + 2 === e) + ) + this._context.lineTo(t[1], n[1]); + else + for (var r = sw(t), i = sw(n), o = 0, a = 1; a < e; ++o, ++a) + this._context.bezierCurveTo( + r[0][o], + i[0][o], + r[1][o], + i[1][o], + t[a], + n[a], + ); + ((this._line || (0 !== this._line && 1 === e)) && + this._context.closePath(), + (this._line = 1 - this._line), + (this._x = this._y = null)); + }, + point: function (t, n) { + (this._x.push(+t), this._y.push(+n)); + }, + }), + (lw.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + ((this._x = this._y = NaN), (this._point = 0)); + }, + lineEnd: function () { + (0 < this._t && + this._t < 1 && + 2 === this._point && + this._context.lineTo(this._x, this._y), + (this._line || (0 !== this._line && 1 === this._point)) && + this._context.closePath(), + this._line >= 0 && + ((this._t = 1 - this._t), (this._line = 1 - this._line))); + }, + point: function (t, n) { + switch (((t = +t), (n = +n), this._point)) { + case 0: + ((this._point = 1), + this._line + ? this._context.lineTo(t, n) + : this._context.moveTo(t, n)); + break; + case 1: + this._point = 2; + default: + if (this._t <= 0) + (this._context.lineTo(this._x, n), this._context.lineTo(t, n)); + else { + var e = this._x * (1 - this._t) + t * this._t; + (this._context.lineTo(e, this._y), this._context.lineTo(e, n)); + } + } + ((this._x = t), (this._y = n)); + }, + })); + var mw = (t) => () => t; + function xw(t, { sourceEvent: n, target: e, transform: r, dispatch: i }) { + Object.defineProperties(this, { + type: { value: t, enumerable: !0, configurable: !0 }, + sourceEvent: { value: n, enumerable: !0, configurable: !0 }, + target: { value: e, enumerable: !0, configurable: !0 }, + transform: { value: r, enumerable: !0, configurable: !0 }, + _: { value: i }, + }); + } + function ww(t, n, e) { + ((this.k = t), (this.x = n), (this.y = e)); + } + ww.prototype = { + constructor: ww, + scale: function (t) { + return 1 === t ? this : new ww(this.k * t, this.x, this.y); + }, + translate: function (t, n) { + return (0 === t) & (0 === n) + ? this + : new ww(this.k, this.x + this.k * t, this.y + this.k * n); + }, + apply: function (t) { + return [t[0] * this.k + this.x, t[1] * this.k + this.y]; + }, + applyX: function (t) { + return t * this.k + this.x; + }, + applyY: function (t) { + return t * this.k + this.y; + }, + invert: function (t) { + return [(t[0] - this.x) / this.k, (t[1] - this.y) / this.k]; + }, + invertX: function (t) { + return (t - this.x) / this.k; + }, + invertY: function (t) { + return (t - this.y) / this.k; + }, + rescaleX: function (t) { + return t + .copy() + .domain(t.range().map(this.invertX, this).map(t.invert, t)); + }, + rescaleY: function (t) { + return t + .copy() + .domain(t.range().map(this.invertY, this).map(t.invert, t)); + }, + toString: function () { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + }, + }; + var Mw = new ww(1, 0, 0); + function Tw(t) { + for (; !t.__zoom; ) if (!(t = t.parentNode)) return Mw; + return t.__zoom; + } + function Aw(t) { + t.stopImmediatePropagation(); + } + function Sw(t) { + (t.preventDefault(), t.stopImmediatePropagation()); + } + function Ew(t) { + return !((t.ctrlKey && "wheel" !== t.type) || t.button); + } + function Nw() { + var t = this; + return t instanceof SVGElement + ? (t = t.ownerSVGElement || t).hasAttribute("viewBox") + ? [ + [(t = t.viewBox.baseVal).x, t.y], + [t.x + t.width, t.y + t.height], + ] + : [ + [0, 0], + [t.width.baseVal.value, t.height.baseVal.value], + ] + : [ + [0, 0], + [t.clientWidth, t.clientHeight], + ]; + } + function kw() { + return this.__zoom || Mw; + } + function Cw(t) { + return ( + -t.deltaY * + (1 === t.deltaMode ? 0.05 : t.deltaMode ? 1 : 0.002) * + (t.ctrlKey ? 10 : 1) + ); + } + function Pw() { + return navigator.maxTouchPoints || "ontouchstart" in this; + } + function zw(t, n, e) { + var r = t.invertX(n[0][0]) - e[0][0], + i = t.invertX(n[1][0]) - e[1][0], + o = t.invertY(n[0][1]) - e[0][1], + a = t.invertY(n[1][1]) - e[1][1]; + return t.translate( + i > r ? (r + i) / 2 : Math.min(0, r) || Math.max(0, i), + a > o ? (o + a) / 2 : Math.min(0, o) || Math.max(0, a), + ); + } + ((Tw.prototype = ww.prototype), + (t.Adder = T), + (t.Delaunay = Lu), + (t.FormatSpecifier = tf), + (t.InternMap = InternMap), + (t.InternSet = InternSet), + (t.Node = Qd), + (t.Path = Ua), + (t.Voronoi = qu), + (t.ZoomTransform = ww), + (t.active = function (t, n) { + var e, + r, + i = t.__transition; + if (i) + for (r in ((n = null == n ? null : n + ""), i)) + if ((e = i[r]).state > qi && e.name === n) + return new po([[t]], Zo, n, +r); + return null; + }), + (t.arc = function () { + var t = Cm, + n = Pm, + e = ym(0), + r = null, + i = zm, + o = $m, + a = Dm, + u = null, + c = km(f); + function f() { + var f, + s, + l = +t.apply(this, arguments), + h = +n.apply(this, arguments), + d = i.apply(this, arguments) - Sm, + p = o.apply(this, arguments) - Sm, + g = vm(p - d), + y = p > d; + if ((u || (u = f = c()), h < l && ((s = h), (h = l), (l = s)), h > Tm)) + if (g > Em - Tm) + (u.moveTo(h * bm(d), h * wm(d)), + u.arc(0, 0, h, d, p, !y), + l > Tm && + (u.moveTo(l * bm(p), l * wm(p)), u.arc(0, 0, l, p, d, y))); + else { + var v, + _, + b = d, + m = p, + x = d, + w = p, + M = g, + T = g, + A = a.apply(this, arguments) / 2, + S = A > Tm && (r ? +r.apply(this, arguments) : Mm(l * l + h * h)), + E = xm(vm(h - l) / 2, +e.apply(this, arguments)), + N = E, + k = E; + if (S > Tm) { + var C = Nm((S / l) * wm(A)), + P = Nm((S / h) * wm(A)); + ((M -= 2 * C) > Tm + ? ((x += C *= y ? 1 : -1), (w -= C)) + : ((M = 0), (x = w = (d + p) / 2)), + (T -= 2 * P) > Tm + ? ((b += P *= y ? 1 : -1), (m -= P)) + : ((T = 0), (b = m = (d + p) / 2))); + } + var z = h * bm(b), + $ = h * wm(b), + D = l * bm(w), + R = l * wm(w); + if (E > Tm) { + var F, + q = h * bm(m), + U = h * wm(m), + I = l * bm(x), + O = l * wm(x); + if (g < Am) + if ( + (F = (function (t, n, e, r, i, o, a, u) { + var c = e - t, + f = r - n, + s = a - i, + l = u - o, + h = l * c - s * f; + if (!(h * h < Tm)) + return [ + t + (h = (s * (n - o) - l * (t - i)) / h) * c, + n + h * f, + ]; + })(z, $, I, O, q, U, D, R)) + ) { + var B = z - F[0], + Y = $ - F[1], + L = q - F[0], + j = U - F[1], + H = + 1 / + wm( + (function (t) { + return t > 1 ? 0 : t < -1 ? Am : Math.acos(t); + })( + (B * L + Y * j) / + (Mm(B * B + Y * Y) * Mm(L * L + j * j)), + ) / 2, + ), + X = Mm(F[0] * F[0] + F[1] * F[1]); + ((N = xm(E, (l - X) / (H - 1))), + (k = xm(E, (h - X) / (H + 1)))); + } else N = k = 0; + } + (T > Tm + ? k > Tm + ? ((v = Rm(I, O, z, $, h, k, y)), + (_ = Rm(q, U, D, R, h, k, y)), + u.moveTo(v.cx + v.x01, v.cy + v.y01), + k < E + ? u.arc( + v.cx, + v.cy, + k, + _m(v.y01, v.x01), + _m(_.y01, _.x01), + !y, + ) + : (u.arc( + v.cx, + v.cy, + k, + _m(v.y01, v.x01), + _m(v.y11, v.x11), + !y, + ), + u.arc( + 0, + 0, + h, + _m(v.cy + v.y11, v.cx + v.x11), + _m(_.cy + _.y11, _.cx + _.x11), + !y, + ), + u.arc( + _.cx, + _.cy, + k, + _m(_.y11, _.x11), + _m(_.y01, _.x01), + !y, + ))) + : (u.moveTo(z, $), u.arc(0, 0, h, b, m, !y)) + : u.moveTo(z, $), + l > Tm && M > Tm + ? N > Tm + ? ((v = Rm(D, R, q, U, l, -N, y)), + (_ = Rm(z, $, I, O, l, -N, y)), + u.lineTo(v.cx + v.x01, v.cy + v.y01), + N < E + ? u.arc( + v.cx, + v.cy, + N, + _m(v.y01, v.x01), + _m(_.y01, _.x01), + !y, + ) + : (u.arc( + v.cx, + v.cy, + N, + _m(v.y01, v.x01), + _m(v.y11, v.x11), + !y, + ), + u.arc( + 0, + 0, + l, + _m(v.cy + v.y11, v.cx + v.x11), + _m(_.cy + _.y11, _.cx + _.x11), + y, + ), + u.arc( + _.cx, + _.cy, + N, + _m(_.y11, _.x11), + _m(_.y01, _.x01), + !y, + ))) + : u.arc(0, 0, l, w, x, y) + : u.lineTo(D, R)); + } + else u.moveTo(0, 0); + if ((u.closePath(), f)) return ((u = null), f + "" || null); + } + return ( + (f.centroid = function () { + var e = (+t.apply(this, arguments) + +n.apply(this, arguments)) / 2, + r = + (+i.apply(this, arguments) + +o.apply(this, arguments)) / 2 - + Am / 2; + return [bm(r) * e, wm(r) * e]; + }), + (f.innerRadius = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(+n)), f) + : t; + }), + (f.outerRadius = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : ym(+t)), f) + : n; + }), + (f.cornerRadius = function (t) { + return arguments.length + ? ((e = "function" == typeof t ? t : ym(+t)), f) + : e; + }), + (f.padRadius = function (t) { + return arguments.length + ? ((r = null == t ? null : "function" == typeof t ? t : ym(+t)), f) + : r; + }), + (f.startAngle = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : ym(+t)), f) + : i; + }), + (f.endAngle = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : ym(+t)), f) + : o; + }), + (f.padAngle = function (t) { + return arguments.length + ? ((a = "function" == typeof t ? t : ym(+t)), f) + : a; + }), + (f.context = function (t) { + return arguments.length ? ((u = null == t ? null : t), f) : u; + }), + f + ); + }), + (t.area = Lm), + (t.areaRadial = Km), + (t.ascending = n), + (t.autoType = function (t) { + for (var n in t) { + var e, + r, + i = t[n].trim(); + if (i) + if ("true" === i) i = !0; + else if ("false" === i) i = !1; + else if ("NaN" === i) i = NaN; + else if (isNaN((e = +i))) { + if ( + !(r = i.match( + /^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/, + )) + ) + continue; + (yc && + r[4] && + !r[7] && + (i = i.replace(/-/g, "/").replace(/T/, " ")), + (i = new Date(i))); + } else i = e; + else i = null; + t[n] = i; + } + return t; + }), + (t.axisBottom = function (t) { + return Pt(Mt, t); + }), + (t.axisLeft = function (t) { + return Pt(Tt, t); + }), + (t.axisRight = function (t) { + return Pt(wt, t); + }), + (t.axisTop = function (t) { + return Pt(xt, t); + }), + (t.bin = Q), + (t.bisect = s), + (t.bisectCenter = f), + (t.bisectLeft = c), + (t.bisectRight = u), + (t.bisector = r), + (t.blob = function (t, n) { + return fetch(t, n).then(vc); + }), + (t.blur = function (t, n) { + if (!((n = +n) >= 0)) throw new RangeError("invalid r"); + let e = t.length; + if (!((e = Math.floor(e)) >= 0)) throw new RangeError("invalid length"); + if (!e || !n) return t; + const r = y(n), + i = t.slice(); + return (r(t, i, 0, e, 1), r(i, t, 0, e, 1), r(t, i, 0, e, 1), t); + }), + (t.blur2 = l), + (t.blurImage = h), + (t.brush = function () { + return wa(la); + }), + (t.brushSelection = function (t) { + var n = t.__brush; + return n ? n.dim.output(n.selection) : null; + }), + (t.brushX = function () { + return wa(fa); + }), + (t.brushY = function () { + return wa(sa); + }), + (t.buffer = function (t, n) { + return fetch(t, n).then(_c); + }), + (t.chord = function () { + return za(!1, !1); + }), + (t.chordDirected = function () { + return za(!0, !1); + }), + (t.chordTranspose = function () { + return za(!1, !0); + }), + (t.cluster = function () { + var t = Ld, + n = 1, + e = 1, + r = !1; + function i(i) { + var o, + a = 0; + i.eachAfter(function (n) { + var e = n.children; + e + ? ((n.x = (function (t) { + return t.reduce(jd, 0) / t.length; + })(e)), + (n.y = (function (t) { + return 1 + t.reduce(Hd, 0); + })(e))) + : ((n.x = o ? (a += t(n, o)) : 0), (n.y = 0), (o = n)); + }); + var u = (function (t) { + for (var n; (n = t.children); ) t = n[0]; + return t; + })(i), + c = (function (t) { + for (var n; (n = t.children); ) t = n[n.length - 1]; + return t; + })(i), + f = u.x - t(u, c) / 2, + s = c.x + t(c, u) / 2; + return i.eachAfter( + r + ? function (t) { + ((t.x = (t.x - i.x) * n), (t.y = (i.y - t.y) * e)); + } + : function (t) { + ((t.x = ((t.x - f) / (s - f)) * n), + (t.y = (1 - (i.y ? t.y / i.y : 1)) * e)); + }, + ); + } + return ( + (i.separation = function (n) { + return arguments.length ? ((t = n), i) : t; + }), + (i.size = function (t) { + return arguments.length + ? ((r = !1), (n = +t[0]), (e = +t[1]), i) + : r + ? null + : [n, e]; + }), + (i.nodeSize = function (t) { + return arguments.length + ? ((r = !0), (n = +t[0]), (e = +t[1]), i) + : r + ? [n, e] + : null; + }), + i + ); + }), + (t.color = ze), + (t.contourDensity = function () { + var t = fu, + n = su, + e = lu, + r = 960, + i = 500, + o = 20, + a = 2, + u = 3 * o, + c = (r + 2 * u) >> a, + f = (i + 2 * u) >> a, + s = Qa(20); + function h(r) { + var i = new Float32Array(c * f), + s = Math.pow(2, -a), + h = -1; + for (const o of r) { + var d = (t(o, ++h, r) + u) * s, + p = (n(o, h, r) + u) * s, + g = +e(o, h, r); + if (g && d >= 0 && d < c && p >= 0 && p < f) { + var y = Math.floor(d), + v = Math.floor(p), + _ = d - y - 0.5, + b = p - v - 0.5; + ((i[y + v * c] += (1 - _) * (1 - b) * g), + (i[y + 1 + v * c] += _ * (1 - b) * g), + (i[y + 1 + (v + 1) * c] += _ * b * g), + (i[y + (v + 1) * c] += (1 - _) * b * g)); + } + } + return (l({ data: i, width: c, height: f }, o * s), i); + } + function d(t) { + var n = h(t), + e = s(n), + r = Math.pow(2, 2 * a); + return ( + Array.isArray(e) || (e = G(Number.MIN_VALUE, J(n) / r, e)), + iu() + .size([c, f]) + .thresholds(e.map((t) => t * r))(n) + .map((t, n) => ((t.value = +e[n]), p(t))) + ); + } + function p(t) { + return (t.coordinates.forEach(g), t); + } + function g(t) { + t.forEach(y); + } + function y(t) { + t.forEach(v); + } + function v(t) { + ((t[0] = t[0] * Math.pow(2, a) - u), + (t[1] = t[1] * Math.pow(2, a) - u)); + } + function _() { + return ((c = (r + 2 * (u = 3 * o)) >> a), (f = (i + 2 * u) >> a), d); + } + return ( + (d.contours = function (t) { + var n = h(t), + e = iu().size([c, f]), + r = Math.pow(2, 2 * a), + i = (t) => { + t = +t; + var i = p(e.contour(n, t * r)); + return ((i.value = t), i); + }; + return (Object.defineProperty(i, "max", { get: () => J(n) / r }), i); + }), + (d.x = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : Qa(+n)), d) + : t; + }), + (d.y = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : Qa(+t)), d) + : n; + }), + (d.weight = function (t) { + return arguments.length + ? ((e = "function" == typeof t ? t : Qa(+t)), d) + : e; + }), + (d.size = function (t) { + if (!arguments.length) return [r, i]; + var n = +t[0], + e = +t[1]; + if (!(n >= 0 && e >= 0)) throw new Error("invalid size"); + return ((r = n), (i = e), _()); + }), + (d.cellSize = function (t) { + if (!arguments.length) return 1 << a; + if (!((t = +t) >= 1)) throw new Error("invalid cell size"); + return ((a = Math.floor(Math.log(t) / Math.LN2)), _()); + }), + (d.thresholds = function (t) { + return arguments.length + ? ((s = + "function" == typeof t + ? t + : Array.isArray(t) + ? Qa(Za.call(t)) + : Qa(t)), + d) + : s; + }), + (d.bandwidth = function (t) { + if (!arguments.length) return Math.sqrt(o * (o + 1)); + if (!((t = +t) >= 0)) throw new Error("invalid bandwidth"); + return ((o = (Math.sqrt(4 * t * t + 1) - 1) / 2), _()); + }), + d + ); + }), + (t.contours = iu), + (t.count = v), + (t.create = function (t) { + return Zn(Yt(t).call(document.documentElement)); + }), + (t.creator = Yt), + (t.cross = function (...t) { + const n = + "function" == typeof t[t.length - 1] && + (function (t) { + return (n) => t(...n); + })(t.pop()), + e = (t = t.map(m)).map(_), + r = t.length - 1, + i = new Array(r + 1).fill(0), + o = []; + if (r < 0 || e.some(b)) return o; + for (;;) { + o.push(i.map((n, e) => t[e][n])); + let a = r; + for (; ++i[a] === e[a]; ) { + if (0 === a) return n ? o.map(n) : o; + i[a--] = 0; + } + } + }), + (t.csv = wc), + (t.csvFormat = rc), + (t.csvFormatBody = ic), + (t.csvFormatRow = ac), + (t.csvFormatRows = oc), + (t.csvFormatValue = uc), + (t.csvParse = nc), + (t.csvParseRows = ec), + (t.cubehelix = Tr), + (t.cumsum = function (t, n) { + var e = 0, + r = 0; + return Float64Array.from( + t, + void 0 === n ? (t) => (e += +t || 0) : (i) => (e += +n(i, r++, t) || 0), + ); + }), + (t.curveBasis = function (t) { + return new Fx(t); + }), + (t.curveBasisClosed = function (t) { + return new qx(t); + }), + (t.curveBasisOpen = function (t) { + return new Ux(t); + }), + (t.curveBumpX = nx), + (t.curveBumpY = ex), + (t.curveBundle = Ox), + (t.curveCardinal = Lx), + (t.curveCardinalClosed = Hx), + (t.curveCardinalOpen = Gx), + (t.curveCatmullRom = Zx), + (t.curveCatmullRomClosed = Qx), + (t.curveCatmullRomOpen = tw), + (t.curveLinear = Im), + (t.curveLinearClosed = function (t) { + return new nw(t); + }), + (t.curveMonotoneX = function (t) { + return new aw(t); + }), + (t.curveMonotoneY = function (t) { + return new uw(t); + }), + (t.curveNatural = function (t) { + return new fw(t); + }), + (t.curveStep = function (t) { + return new lw(t, 0.5); + }), + (t.curveStepAfter = function (t) { + return new lw(t, 1); + }), + (t.curveStepBefore = function (t) { + return new lw(t, 0); + }), + (t.descending = e), + (t.deviation = w), + (t.difference = function (t, ...n) { + t = new InternSet(t); + for (const e of n) for (const n of e) t.delete(n); + return t; + }), + (t.disjoint = function (t, n) { + const e = n[Symbol.iterator](), + r = new InternSet(); + for (const n of t) { + if (r.has(n)) return !1; + let t, i; + for (; ({ value: t, done: i } = e.next()) && !i; ) { + if (Object.is(n, t)) return !1; + r.add(t); + } + } + return !0; + }), + (t.dispatch = $t), + (t.drag = function () { + var t, + n, + e, + r, + i = se, + o = le, + a = he, + u = de, + c = {}, + f = $t("start", "drag", "end"), + s = 0, + l = 0; + function h(t) { + t.on("mousedown.drag", d) + .filter(u) + .on("touchstart.drag", y) + .on("touchmove.drag", v, ee) + .on("touchend.drag touchcancel.drag", _) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + function d(a, u) { + if (!r && i.call(this, a, u)) { + var c = b(this, o.call(this, a, u), a, u, "mouse"); + c && + (Zn(a.view).on("mousemove.drag", p, re).on("mouseup.drag", g, re), + ae(a.view), + ie(a), + (e = !1), + (t = a.clientX), + (n = a.clientY), + c("start", a)); + } + } + function p(r) { + if ((oe(r), !e)) { + var i = r.clientX - t, + o = r.clientY - n; + e = i * i + o * o > l; + } + c.mouse("drag", r); + } + function g(t) { + (Zn(t.view).on("mousemove.drag mouseup.drag", null), + ue(t.view, e), + oe(t), + c.mouse("end", t)); + } + function y(t, n) { + if (i.call(this, t, n)) { + var e, + r, + a = t.changedTouches, + u = o.call(this, t, n), + c = a.length; + for (e = 0; e < c; ++e) + (r = b(this, u, t, n, a[e].identifier, a[e])) && + (ie(t), r("start", t, a[e])); + } + } + function v(t) { + var n, + e, + r = t.changedTouches, + i = r.length; + for (n = 0; n < i; ++n) + (e = c[r[n].identifier]) && (oe(t), e("drag", t, r[n])); + } + function _(t) { + var n, + e, + i = t.changedTouches, + o = i.length; + for ( + r && clearTimeout(r), + r = setTimeout(function () { + r = null; + }, 500), + n = 0; + n < o; + ++n + ) + (e = c[i[n].identifier]) && (ie(t), e("end", t, i[n])); + } + function b(t, n, e, r, i, o) { + var u, + l, + d, + p = f.copy(), + g = ne(o || e, n); + if ( + null != + (d = a.call( + t, + new fe("beforestart", { + sourceEvent: e, + target: h, + identifier: i, + active: s, + x: g[0], + y: g[1], + dx: 0, + dy: 0, + dispatch: p, + }), + r, + )) + ) + return ( + (u = d.x - g[0] || 0), + (l = d.y - g[1] || 0), + function e(o, a, f) { + var y, + v = g; + switch (o) { + case "start": + ((c[i] = e), (y = s++)); + break; + case "end": + (delete c[i], --s); + case "drag": + ((g = ne(f || a, n)), (y = s)); + } + p.call( + o, + t, + new fe(o, { + sourceEvent: a, + subject: d, + target: h, + identifier: i, + active: y, + x: g[0] + u, + y: g[1] + l, + dx: g[0] - v[0], + dy: g[1] - v[1], + dispatch: p, + }), + r, + ); + } + ); + } + return ( + (h.filter = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : ce(!!t)), h) + : i; + }), + (h.container = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : ce(t)), h) + : o; + }), + (h.subject = function (t) { + return arguments.length + ? ((a = "function" == typeof t ? t : ce(t)), h) + : a; + }), + (h.touchable = function (t) { + return arguments.length + ? ((u = "function" == typeof t ? t : ce(!!t)), h) + : u; + }), + (h.on = function () { + var t = f.on.apply(f, arguments); + return t === f ? h : t; + }), + (h.clickDistance = function (t) { + return arguments.length ? ((l = (t = +t) * t), h) : Math.sqrt(l); + }), + h + ); + }), + (t.dragDisable = ae), + (t.dragEnable = ue), + (t.dsv = function (t, n, e, r) { + 3 === arguments.length && + "function" == typeof e && + ((r = e), (e = void 0)); + var i = Ju(t); + return mc(n, e).then(function (t) { + return i.parse(t, r); + }); + }), + (t.dsvFormat = Ju), + (t.easeBack = Lo), + (t.easeBackIn = Bo), + (t.easeBackInOut = Lo), + (t.easeBackOut = Yo), + (t.easeBounce = Io), + (t.easeBounceIn = function (t) { + return 1 - Io(1 - t); + }), + (t.easeBounceInOut = function (t) { + return ((t *= 2) <= 1 ? 1 - Io(1 - t) : Io(t - 1) + 1) / 2; + }), + (t.easeBounceOut = Io), + (t.easeCircle = No), + (t.easeCircleIn = function (t) { + return 1 - Math.sqrt(1 - t * t); + }), + (t.easeCircleInOut = No), + (t.easeCircleOut = function (t) { + return Math.sqrt(1 - --t * t); + }), + (t.easeCubic = bo), + (t.easeCubicIn = function (t) { + return t * t * t; + }), + (t.easeCubicInOut = bo), + (t.easeCubicOut = function (t) { + return --t * t * t + 1; + }), + (t.easeElastic = Xo), + (t.easeElasticIn = Ho), + (t.easeElasticInOut = Go), + (t.easeElasticOut = Xo), + (t.easeExp = Eo), + (t.easeExpIn = function (t) { + return So(1 - +t); + }), + (t.easeExpInOut = Eo), + (t.easeExpOut = function (t) { + return 1 - So(t); + }), + (t.easeLinear = (t) => +t), + (t.easePoly = wo), + (t.easePolyIn = mo), + (t.easePolyInOut = wo), + (t.easePolyOut = xo), + (t.easeQuad = _o), + (t.easeQuadIn = function (t) { + return t * t; + }), + (t.easeQuadInOut = _o), + (t.easeQuadOut = function (t) { + return t * (2 - t); + }), + (t.easeSin = Ao), + (t.easeSinIn = function (t) { + return 1 == +t ? 1 : 1 - Math.cos(t * To); + }), + (t.easeSinInOut = Ao), + (t.easeSinOut = function (t) { + return Math.sin(t * To); + }), + (t.every = function (t, n) { + if ("function" != typeof n) throw new TypeError("test is not a function"); + let e = -1; + for (const r of t) if (!n(r, ++e, t)) return !1; + return !0; + }), + (t.extent = M), + (t.fcumsum = function (t, n) { + const e = new T(); + let r = -1; + return Float64Array.from( + t, + void 0 === n ? (t) => e.add(+t || 0) : (i) => e.add(+n(i, ++r, t) || 0), + ); + }), + (t.filter = function (t, n) { + if ("function" != typeof n) throw new TypeError("test is not a function"); + const e = []; + let r = -1; + for (const i of t) n(i, ++r, t) && e.push(i); + return e; + }), + (t.flatGroup = function (t, ...n) { + return z(P(t, ...n), n); + }), + (t.flatRollup = function (t, n, ...e) { + return z(D(t, n, ...e), e); + }), + (t.forceCenter = function (t, n) { + var e, + r = 1; + function i() { + var i, + o, + a = e.length, + u = 0, + c = 0; + for (i = 0; i < a; ++i) ((u += (o = e[i]).x), (c += o.y)); + for (u = (u / a - t) * r, c = (c / a - n) * r, i = 0; i < a; ++i) + (((o = e[i]).x -= u), (o.y -= c)); + } + return ( + null == t && (t = 0), + null == n && (n = 0), + (i.initialize = function (t) { + e = t; + }), + (i.x = function (n) { + return arguments.length ? ((t = +n), i) : t; + }), + (i.y = function (t) { + return arguments.length ? ((n = +t), i) : n; + }), + (i.strength = function (t) { + return arguments.length ? ((r = +t), i) : r; + }), + i + ); + }), + (t.forceCollide = function (t) { + var n, + e, + r, + i = 1, + o = 1; + function a() { + for (var t, a, c, f, s, l, h, d = n.length, p = 0; p < o; ++p) + for (a = $c(n, Ic, Oc).visitAfter(u), t = 0; t < d; ++t) + ((c = n[t]), + (l = e[c.index]), + (h = l * l), + (f = c.x + c.vx), + (s = c.y + c.vy), + a.visit(g)); + function g(t, n, e, o, a) { + var u = t.data, + d = t.r, + p = l + d; + if (!u) return n > f + p || o < f - p || e > s + p || a < s - p; + if (u.index > c.index) { + var g = f - u.x - u.vx, + y = s - u.y - u.vy, + v = g * g + y * y; + v < p * p && + (0 === g && (v += (g = Uc(r)) * g), + 0 === y && (v += (y = Uc(r)) * y), + (v = ((p - (v = Math.sqrt(v))) / v) * i), + (c.vx += (g *= v) * (p = (d *= d) / (h + d))), + (c.vy += (y *= v) * p), + (u.vx -= g * (p = 1 - p)), + (u.vy -= y * p)); + } + } + } + function u(t) { + if (t.data) return (t.r = e[t.data.index]); + for (var n = (t.r = 0); n < 4; ++n) + t[n] && t[n].r > t.r && (t.r = t[n].r); + } + function c() { + if (n) { + var r, + i, + o = n.length; + for (e = new Array(o), r = 0; r < o; ++r) + ((i = n[r]), (e[i.index] = +t(i, r, n))); + } + } + return ( + "function" != typeof t && (t = qc(null == t ? 1 : +t)), + (a.initialize = function (t, e) { + ((n = t), (r = e), c()); + }), + (a.iterations = function (t) { + return arguments.length ? ((o = +t), a) : o; + }), + (a.strength = function (t) { + return arguments.length ? ((i = +t), a) : i; + }), + (a.radius = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : qc(+n)), c(), a) + : t; + }), + a + ); + }), + (t.forceLink = function (t) { + var n, + e, + r, + i, + o, + a, + u = Bc, + c = function (t) { + return 1 / Math.min(i[t.source.index], i[t.target.index]); + }, + f = qc(30), + s = 1; + function l(r) { + for (var i = 0, u = t.length; i < s; ++i) + for (var c, f, l, h, d, p, g, y = 0; y < u; ++y) + ((f = (c = t[y]).source), + (h = (l = c.target).x + l.vx - f.x - f.vx || Uc(a)), + (d = l.y + l.vy - f.y - f.vy || Uc(a)), + (h *= p = + (((p = Math.sqrt(h * h + d * d)) - e[y]) / p) * r * n[y]), + (d *= p), + (l.vx -= h * (g = o[y])), + (l.vy -= d * g), + (f.vx += h * (g = 1 - g)), + (f.vy += d * g)); + } + function h() { + if (r) { + var a, + c, + f = r.length, + s = t.length, + l = new Map(r.map((t, n) => [u(t, n, r), t])); + for (a = 0, i = new Array(f); a < s; ++a) + (((c = t[a]).index = a), + "object" != typeof c.source && (c.source = Yc(l, c.source)), + "object" != typeof c.target && (c.target = Yc(l, c.target)), + (i[c.source.index] = (i[c.source.index] || 0) + 1), + (i[c.target.index] = (i[c.target.index] || 0) + 1)); + for (a = 0, o = new Array(s); a < s; ++a) + ((c = t[a]), + (o[a] = + i[c.source.index] / (i[c.source.index] + i[c.target.index]))); + ((n = new Array(s)), d(), (e = new Array(s)), p()); + } + } + function d() { + if (r) for (var e = 0, i = t.length; e < i; ++e) n[e] = +c(t[e], e, t); + } + function p() { + if (r) for (var n = 0, i = t.length; n < i; ++n) e[n] = +f(t[n], n, t); + } + return ( + null == t && (t = []), + (l.initialize = function (t, n) { + ((r = t), (a = n), h()); + }), + (l.links = function (n) { + return arguments.length ? ((t = n), h(), l) : t; + }), + (l.id = function (t) { + return arguments.length ? ((u = t), l) : u; + }), + (l.iterations = function (t) { + return arguments.length ? ((s = +t), l) : s; + }), + (l.strength = function (t) { + return arguments.length + ? ((c = "function" == typeof t ? t : qc(+t)), d(), l) + : c; + }), + (l.distance = function (t) { + return arguments.length + ? ((f = "function" == typeof t ? t : qc(+t)), p(), l) + : f; + }), + l + ); + }), + (t.forceManyBody = function () { + var t, + n, + e, + r, + i, + o = qc(-30), + a = 1, + u = 1 / 0, + c = 0.81; + function f(e) { + var i, + o = t.length, + a = $c(t, Xc, Gc).visitAfter(l); + for (r = e, i = 0; i < o; ++i) ((n = t[i]), a.visit(h)); + } + function s() { + if (t) { + var n, + e, + r = t.length; + for (i = new Array(r), n = 0; n < r; ++n) + ((e = t[n]), (i[e.index] = +o(e, n, t))); + } + } + function l(t) { + var n, + e, + r, + o, + a, + u = 0, + c = 0; + if (t.length) { + for (r = o = a = 0; a < 4; ++a) + (n = t[a]) && + (e = Math.abs(n.value)) && + ((u += n.value), (c += e), (r += e * n.x), (o += e * n.y)); + ((t.x = r / c), (t.y = o / c)); + } else { + (((n = t).x = n.data.x), (n.y = n.data.y)); + do { + u += i[n.data.index]; + } while ((n = n.next)); + } + t.value = u; + } + function h(t, o, f, s) { + if (!t.value) return !0; + var l = t.x - n.x, + h = t.y - n.y, + d = s - o, + p = l * l + h * h; + if ((d * d) / c < p) + return ( + p < u && + (0 === l && (p += (l = Uc(e)) * l), + 0 === h && (p += (h = Uc(e)) * h), + p < a && (p = Math.sqrt(a * p)), + (n.vx += (l * t.value * r) / p), + (n.vy += (h * t.value * r) / p)), + !0 + ); + if (!(t.length || p >= u)) { + (t.data !== n || t.next) && + (0 === l && (p += (l = Uc(e)) * l), + 0 === h && (p += (h = Uc(e)) * h), + p < a && (p = Math.sqrt(a * p))); + do { + t.data !== n && + ((d = (i[t.data.index] * r) / p), + (n.vx += l * d), + (n.vy += h * d)); + } while ((t = t.next)); + } + } + return ( + (f.initialize = function (n, r) { + ((t = n), (e = r), s()); + }), + (f.strength = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : qc(+t)), s(), f) + : o; + }), + (f.distanceMin = function (t) { + return arguments.length ? ((a = t * t), f) : Math.sqrt(a); + }), + (f.distanceMax = function (t) { + return arguments.length ? ((u = t * t), f) : Math.sqrt(u); + }), + (f.theta = function (t) { + return arguments.length ? ((c = t * t), f) : Math.sqrt(c); + }), + f + ); + }), + (t.forceRadial = function (t, n, e) { + var r, + i, + o, + a = qc(0.1); + function u(t) { + for (var a = 0, u = r.length; a < u; ++a) { + var c = r[a], + f = c.x - n || 1e-6, + s = c.y - e || 1e-6, + l = Math.sqrt(f * f + s * s), + h = ((o[a] - l) * i[a] * t) / l; + ((c.vx += f * h), (c.vy += s * h)); + } + } + function c() { + if (r) { + var n, + e = r.length; + for (i = new Array(e), o = new Array(e), n = 0; n < e; ++n) + ((o[n] = +t(r[n], n, r)), + (i[n] = isNaN(o[n]) ? 0 : +a(r[n], n, r))); + } + } + return ( + "function" != typeof t && (t = qc(+t)), + null == n && (n = 0), + null == e && (e = 0), + (u.initialize = function (t) { + ((r = t), c()); + }), + (u.strength = function (t) { + return arguments.length + ? ((a = "function" == typeof t ? t : qc(+t)), c(), u) + : a; + }), + (u.radius = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : qc(+n)), c(), u) + : t; + }), + (u.x = function (t) { + return arguments.length ? ((n = +t), u) : n; + }), + (u.y = function (t) { + return arguments.length ? ((e = +t), u) : e; + }), + u + ); + }), + (t.forceSimulation = function (t) { + var n, + e = 1, + r = 0.001, + i = 1 - Math.pow(r, 1 / 300), + o = 0, + a = 0.6, + u = new Map(), + c = Ni(l), + f = $t("tick", "end"), + s = (function () { + let t = 1; + return () => (t = (Lc * t + jc) % Hc) / Hc; + })(); + function l() { + (h(), f.call("tick", n), e < r && (c.stop(), f.call("end", n))); + } + function h(r) { + var c, + f, + s = t.length; + void 0 === r && (r = 1); + for (var l = 0; l < r; ++l) + for ( + e += (o - e) * i, + u.forEach(function (t) { + t(e); + }), + c = 0; + c < s; + ++c + ) + (null == (f = t[c]).fx + ? (f.x += f.vx *= a) + : ((f.x = f.fx), (f.vx = 0)), + null == f.fy ? (f.y += f.vy *= a) : ((f.y = f.fy), (f.vy = 0))); + return n; + } + function d() { + for (var n, e = 0, r = t.length; e < r; ++e) { + if ( + (((n = t[e]).index = e), + null != n.fx && (n.x = n.fx), + null != n.fy && (n.y = n.fy), + isNaN(n.x) || isNaN(n.y)) + ) { + var i = 10 * Math.sqrt(0.5 + e), + o = e * Vc; + ((n.x = i * Math.cos(o)), (n.y = i * Math.sin(o))); + } + (isNaN(n.vx) || isNaN(n.vy)) && (n.vx = n.vy = 0); + } + } + function p(n) { + return (n.initialize && n.initialize(t, s), n); + } + return ( + null == t && (t = []), + d(), + (n = { + tick: h, + restart: function () { + return (c.restart(l), n); + }, + stop: function () { + return (c.stop(), n); + }, + nodes: function (e) { + return arguments.length ? ((t = e), d(), u.forEach(p), n) : t; + }, + alpha: function (t) { + return arguments.length ? ((e = +t), n) : e; + }, + alphaMin: function (t) { + return arguments.length ? ((r = +t), n) : r; + }, + alphaDecay: function (t) { + return arguments.length ? ((i = +t), n) : +i; + }, + alphaTarget: function (t) { + return arguments.length ? ((o = +t), n) : o; + }, + velocityDecay: function (t) { + return arguments.length ? ((a = 1 - t), n) : 1 - a; + }, + randomSource: function (t) { + return arguments.length ? ((s = t), u.forEach(p), n) : s; + }, + force: function (t, e) { + return arguments.length > 1 + ? (null == e ? u.delete(t) : u.set(t, p(e)), n) + : u.get(t); + }, + find: function (n, e, r) { + var i, + o, + a, + u, + c, + f = 0, + s = t.length; + for (null == r ? (r = 1 / 0) : (r *= r), f = 0; f < s; ++f) + (a = (i = n - (u = t[f]).x) * i + (o = e - u.y) * o) < r && + ((c = u), (r = a)); + return c; + }, + on: function (t, e) { + return arguments.length > 1 ? (f.on(t, e), n) : f.on(t); + }, + }) + ); + }), + (t.forceX = function (t) { + var n, + e, + r, + i = qc(0.1); + function o(t) { + for (var i, o = 0, a = n.length; o < a; ++o) + (i = n[o]).vx += (r[o] - i.x) * e[o] * t; + } + function a() { + if (n) { + var o, + a = n.length; + for (e = new Array(a), r = new Array(a), o = 0; o < a; ++o) + e[o] = isNaN((r[o] = +t(n[o], o, n))) ? 0 : +i(n[o], o, n); + } + } + return ( + "function" != typeof t && (t = qc(null == t ? 0 : +t)), + (o.initialize = function (t) { + ((n = t), a()); + }), + (o.strength = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : qc(+t)), a(), o) + : i; + }), + (o.x = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : qc(+n)), a(), o) + : t; + }), + o + ); + }), + (t.forceY = function (t) { + var n, + e, + r, + i = qc(0.1); + function o(t) { + for (var i, o = 0, a = n.length; o < a; ++o) + (i = n[o]).vy += (r[o] - i.y) * e[o] * t; + } + function a() { + if (n) { + var o, + a = n.length; + for (e = new Array(a), r = new Array(a), o = 0; o < a; ++o) + e[o] = isNaN((r[o] = +t(n[o], o, n))) ? 0 : +i(n[o], o, n); + } + } + return ( + "function" != typeof t && (t = qc(null == t ? 0 : +t)), + (o.initialize = function (t) { + ((n = t), a()); + }), + (o.strength = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : qc(+t)), a(), o) + : i; + }), + (o.y = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : qc(+n)), a(), o) + : t; + }), + o + ); + }), + (t.formatDefaultLocale = ff), + (t.formatLocale = cf), + (t.formatSpecifier = Jc), + (t.fsum = function (t, n) { + const e = new T(); + if (void 0 === n) for (let n of t) (n = +n) && e.add(n); + else { + let r = -1; + for (let i of t) (i = +n(i, ++r, t)) && e.add(i); + } + return +e; + }), + (t.geoAlbers = xd), + (t.geoAlbersUsa = function () { + var t, + n, + e, + r, + i, + o, + a = xd(), + u = md().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), + c = md().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), + f = { + point: function (t, n) { + o = [t, n]; + }, + }; + function s(t) { + var n = t[0], + a = t[1]; + return ( + (o = null), + e.point(n, a), + o || (r.point(n, a), o) || (i.point(n, a), o) + ); + } + function l() { + return ((t = n = null), s); + } + return ( + (s.invert = function (t) { + var n = a.scale(), + e = a.translate(), + r = (t[0] - e[0]) / n, + i = (t[1] - e[1]) / n; + return ( + i >= 0.12 && i < 0.234 && r >= -0.425 && r < -0.214 + ? u + : i >= 0.166 && i < 0.234 && r >= -0.214 && r < -0.115 + ? c + : a + ).invert(t); + }), + (s.stream = function (e) { + return t && n === e + ? t + : ((r = [a.stream((n = e)), u.stream(e), c.stream(e)]), + (i = r.length), + (t = { + point: function (t, n) { + for (var e = -1; ++e < i; ) r[e].point(t, n); + }, + sphere: function () { + for (var t = -1; ++t < i; ) r[t].sphere(); + }, + lineStart: function () { + for (var t = -1; ++t < i; ) r[t].lineStart(); + }, + lineEnd: function () { + for (var t = -1; ++t < i; ) r[t].lineEnd(); + }, + polygonStart: function () { + for (var t = -1; ++t < i; ) r[t].polygonStart(); + }, + polygonEnd: function () { + for (var t = -1; ++t < i; ) r[t].polygonEnd(); + }, + })); + var r, i; + }), + (s.precision = function (t) { + return arguments.length + ? (a.precision(t), u.precision(t), c.precision(t), l()) + : a.precision(); + }), + (s.scale = function (t) { + return arguments.length + ? (a.scale(t), + u.scale(0.35 * t), + c.scale(t), + s.translate(a.translate())) + : a.scale(); + }), + (s.translate = function (t) { + if (!arguments.length) return a.translate(); + var n = a.scale(), + o = +t[0], + s = +t[1]; + return ( + (e = a + .translate(t) + .clipExtent([ + [o - 0.455 * n, s - 0.238 * n], + [o + 0.455 * n, s + 0.238 * n], + ]) + .stream(f)), + (r = u + .translate([o - 0.307 * n, s + 0.201 * n]) + .clipExtent([ + [o - 0.425 * n + df, s + 0.12 * n + df], + [o - 0.214 * n - df, s + 0.234 * n - df], + ]) + .stream(f)), + (i = c + .translate([o - 0.205 * n, s + 0.212 * n]) + .clipExtent([ + [o - 0.214 * n + df, s + 0.166 * n + df], + [o - 0.115 * n - df, s + 0.234 * n - df], + ]) + .stream(f)), + l() + ); + }), + (s.fitExtent = function (t, n) { + return ud(s, t, n); + }), + (s.fitSize = function (t, n) { + return cd(s, t, n); + }), + (s.fitWidth = function (t, n) { + return fd(s, t, n); + }), + (s.fitHeight = function (t, n) { + return sd(s, t, n); + }), + s.scale(1070) + ); + }), + (t.geoArea = function (t) { + return ((us = new T()), Lf(t, cs), 2 * us); + }), + (t.geoAzimuthalEqualArea = function () { + return yd(Td).scale(124.75).clipAngle(179.999); + }), + (t.geoAzimuthalEqualAreaRaw = Td), + (t.geoAzimuthalEquidistant = function () { + return yd(Ad).scale(79.4188).clipAngle(179.999); + }), + (t.geoAzimuthalEquidistantRaw = Ad), + (t.geoBounds = function (t) { + var n, e, r, i, o, a, u; + if ( + ((Qf = Kf = -(Wf = Zf = 1 / 0)), (is = []), Lf(t, Fs), (e = is.length)) + ) { + for (is.sort(Hs), n = 1, o = [(r = is[0])]; n < e; ++n) + Xs(r, (i = is[n])[0]) || Xs(r, i[1]) + ? (js(r[0], i[1]) > js(r[0], r[1]) && (r[1] = i[1]), + js(i[0], r[1]) > js(r[0], r[1]) && (r[0] = i[0])) + : o.push((r = i)); + for (a = -1 / 0, n = 0, r = o[(e = o.length - 1)]; n <= e; r = i, ++n) + ((i = o[n]), + (u = js(r[1], i[0])) > a && ((a = u), (Wf = i[0]), (Kf = r[1]))); + } + return ( + (is = os = null), + Wf === 1 / 0 || Zf === 1 / 0 + ? [ + [NaN, NaN], + [NaN, NaN], + ] + : [ + [Wf, Zf], + [Kf, Qf], + ] + ); + }), + (t.geoCentroid = function (t) { + ((ms = xs = ws = Ms = Ts = As = Ss = Es = 0), + (Ns = new T()), + (ks = new T()), + (Cs = new T()), + Lf(t, Gs)); + var n = +Ns, + e = +ks, + r = +Cs, + i = Ef(n, e, r); + return i < pf && + ((n = As), + (e = Ss), + (r = Es), + xs < df && ((n = ws), (e = Ms), (r = Ts)), + (i = Ef(n, e, r)) < pf) + ? [NaN, NaN] + : [Mf(e, n) * bf, Rf(r / i) * bf]; + }), + (t.geoCircle = function () { + var t, + n, + e = il([0, 0]), + r = il(90), + i = il(2), + o = { + point: function (e, r) { + (t.push((e = n(e, r))), (e[0] *= bf), (e[1] *= bf)); + }, + }; + function a() { + var a = e.apply(this, arguments), + u = r.apply(this, arguments) * mf, + c = i.apply(this, arguments) * mf; + return ( + (t = []), + (n = ul(-a[0] * mf, -a[1] * mf, 0).invert), + hl(o, u, c, 1), + (a = { type: "Polygon", coordinates: [t] }), + (t = n = null), + a + ); + } + return ( + (a.center = function (t) { + return arguments.length + ? ((e = "function" == typeof t ? t : il([+t[0], +t[1]])), a) + : e; + }), + (a.radius = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : il(+t)), a) + : r; + }), + (a.precision = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : il(+t)), a) + : i; + }), + a + ); + }), + (t.geoClipAntimeridian = Tl), + (t.geoClipCircle = Al), + (t.geoClipExtent = function () { + var t, + n, + e, + r = 0, + i = 0, + o = 960, + a = 500; + return (e = { + stream: function (e) { + return t && n === e ? t : (t = zl(r, i, o, a)((n = e))); + }, + extent: function (u) { + return arguments.length + ? ((r = +u[0][0]), + (i = +u[0][1]), + (o = +u[1][0]), + (a = +u[1][1]), + (t = n = null), + e) + : [ + [r, i], + [o, a], + ]; + }, + }); + }), + (t.geoClipRectangle = zl), + (t.geoConicConformal = function () { + return _d(kd).scale(109.5).parallels([30, 30]); + }), + (t.geoConicConformalRaw = kd), + (t.geoConicEqualArea = md), + (t.geoConicEqualAreaRaw = bd), + (t.geoConicEquidistant = function () { + return _d(Pd).scale(131.154).center([0, 13.9389]); + }), + (t.geoConicEquidistantRaw = Pd), + (t.geoContains = function (t, n) { + return (t && Bl.hasOwnProperty(t.type) ? Bl[t.type] : Ll)(t, n); + }), + (t.geoDistance = Ol), + (t.geoEqualEarth = function () { + return yd(qd).scale(177.158); + }), + (t.geoEqualEarthRaw = qd), + (t.geoEquirectangular = function () { + return yd(Cd).scale(152.63); + }), + (t.geoEquirectangularRaw = Cd), + (t.geoGnomonic = function () { + return yd(Ud).scale(144.049).clipAngle(60); + }), + (t.geoGnomonicRaw = Ud), + (t.geoGraticule = Kl), + (t.geoGraticule10 = function () { + return Kl()(); + }), + (t.geoIdentity = function () { + var t, + n, + e, + r, + i, + o, + a, + u = 1, + c = 0, + f = 0, + s = 1, + l = 1, + h = 0, + d = null, + p = 1, + g = 1, + y = id({ + point: function (t, n) { + var e = b([t, n]); + this.stream.point(e[0], e[1]); + }, + }), + v = eh; + function _() { + return ((p = u * s), (g = u * l), (o = a = null), b); + } + function b(e) { + var r = e[0] * p, + i = e[1] * g; + if (h) { + var o = i * t - r * n; + ((r = r * t + i * n), (i = o)); + } + return [r + c, i + f]; + } + return ( + (b.invert = function (e) { + var r = e[0] - c, + i = e[1] - f; + if (h) { + var o = i * t + r * n; + ((r = r * t - i * n), (i = o)); + } + return [r / p, i / g]; + }), + (b.stream = function (t) { + return o && a === t ? o : (o = y(v((a = t)))); + }), + (b.postclip = function (t) { + return arguments.length ? ((v = t), (d = e = r = i = null), _()) : v; + }), + (b.clipExtent = function (t) { + return arguments.length + ? ((v = + null == t + ? ((d = e = r = i = null), eh) + : zl( + (d = +t[0][0]), + (e = +t[0][1]), + (r = +t[1][0]), + (i = +t[1][1]), + )), + _()) + : null == d + ? null + : [ + [d, e], + [r, i], + ]; + }), + (b.scale = function (t) { + return arguments.length ? ((u = +t), _()) : u; + }), + (b.translate = function (t) { + return arguments.length ? ((c = +t[0]), (f = +t[1]), _()) : [c, f]; + }), + (b.angle = function (e) { + return arguments.length + ? ((n = Cf((h = (e % 360) * mf))), (t = Tf(h)), _()) + : h * bf; + }), + (b.reflectX = function (t) { + return arguments.length ? ((s = t ? -1 : 1), _()) : s < 0; + }), + (b.reflectY = function (t) { + return arguments.length ? ((l = t ? -1 : 1), _()) : l < 0; + }), + (b.fitExtent = function (t, n) { + return ud(b, t, n); + }), + (b.fitSize = function (t, n) { + return cd(b, t, n); + }), + (b.fitWidth = function (t, n) { + return fd(b, t, n); + }), + (b.fitHeight = function (t, n) { + return sd(b, t, n); + }), + b + ); + }), + (t.geoInterpolate = function (t, n) { + var e = t[0] * mf, + r = t[1] * mf, + i = n[0] * mf, + o = n[1] * mf, + a = Tf(r), + u = Cf(r), + c = Tf(o), + f = Cf(o), + s = a * Tf(e), + l = a * Cf(e), + h = c * Tf(i), + d = c * Cf(i), + p = 2 * Rf(zf(Ff(o - r) + a * c * Ff(i - e))), + g = Cf(p), + y = p + ? function (t) { + var n = Cf((t *= p)) / g, + e = Cf(p - t) / g, + r = e * s + n * h, + i = e * l + n * d, + o = e * u + n * f; + return [Mf(i, r) * bf, Mf(o, zf(r * r + i * i)) * bf]; + } + : function () { + return [e * bf, r * bf]; + }; + return ((y.distance = p), y); + }), + (t.geoLength = ql), + (t.geoMercator = function () { + return Ed(Sd).scale(961 / _f); + }), + (t.geoMercatorRaw = Sd), + (t.geoNaturalEarth1 = function () { + return yd(Id).scale(175.295); + }), + (t.geoNaturalEarth1Raw = Id), + (t.geoOrthographic = function () { + return yd(Od) + .scale(249.5) + .clipAngle(90 + df); + }), + (t.geoOrthographicRaw = Od), + (t.geoPath = function (t, n) { + let e, + r, + i = 3, + o = 4.5; + function a(t) { + return ( + t && + ("function" == typeof o && r.pointRadius(+o.apply(this, arguments)), + Lf(t, e(r))), + r.result() + ); + } + return ( + (a.area = function (t) { + return (Lf(t, e(sh)), sh.result()); + }), + (a.measure = function (t) { + return (Lf(t, e(Kh)), Kh.result()); + }), + (a.bounds = function (t) { + return (Lf(t, e(mh)), mh.result()); + }), + (a.centroid = function (t) { + return (Lf(t, e(Oh)), Oh.result()); + }), + (a.projection = function (n) { + return arguments.length + ? ((e = null == n ? ((t = null), eh) : (t = n).stream), a) + : t; + }), + (a.context = function (t) { + return arguments.length + ? ((r = null == t ? ((n = null), new ed(i)) : new Bh((n = t))), + "function" != typeof o && r.pointRadius(o), + a) + : n; + }), + (a.pointRadius = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : (r.pointRadius(+t), +t)), a) + : o; + }), + (a.digits = function (t) { + if (!arguments.length) return i; + if (null == t) i = null; + else { + const n = Math.floor(t); + if (!(n >= 0)) throw new RangeError(`invalid digits: ${t}`); + i = n; + } + return (null === n && (r = new ed(i)), a); + }), + a.projection(t).digits(i).context(n) + ); + }), + (t.geoProjection = yd), + (t.geoProjectionMutator = vd), + (t.geoRotation = ll), + (t.geoStereographic = function () { + return yd(Bd).scale(250).clipAngle(142); + }), + (t.geoStereographicRaw = Bd), + (t.geoStream = Lf), + (t.geoTransform = function (t) { + return { stream: id(t) }; + }), + (t.geoTransverseMercator = function () { + var t = Ed(Yd), + n = t.center, + e = t.rotate; + return ( + (t.center = function (t) { + return arguments.length ? n([-t[1], t[0]]) : [(t = n())[1], -t[0]]; + }), + (t.rotate = function (t) { + return arguments.length + ? e([t[0], t[1], t.length > 2 ? t[2] + 90 : 90]) + : [(t = e())[0], t[1], t[2] - 90]; + }), + e([0, 0, 90]).scale(159.155) + ); + }), + (t.geoTransverseMercatorRaw = Yd), + (t.gray = function (t, n) { + return new ur(t, 0, 0, null == n ? 1 : n); + }), + (t.greatest = ot), + (t.greatestIndex = function (t, e = n) { + if (1 === e.length) return tt(t, e); + let r, + i = -1, + o = -1; + for (const n of t) + (++o, (i < 0 ? 0 === e(n, n) : e(n, r) > 0) && ((r = n), (i = o))); + return i; + }), + (t.group = C), + (t.groupSort = function (t, e, r) { + return ( + 2 !== e.length + ? U($(t, e, r), ([t, e], [r, i]) => n(e, i) || n(t, r)) + : U(C(t, r), ([t, r], [i, o]) => e(r, o) || n(t, i)) + ).map(([t]) => t); + }), + (t.groups = P), + (t.hcl = dr), + (t.hierarchy = Gd), + (t.histogram = Q), + (t.hsl = He), + (t.html = Ec), + (t.image = function (t, n) { + return new Promise(function (e, r) { + var i = new Image(); + for (var o in n) i[o] = n[o]; + ((i.onerror = r), + (i.onload = function () { + e(i); + }), + (i.src = t)); + }); + }), + (t.index = function (t, ...n) { + return F(t, k, R, n); + }), + (t.indexes = function (t, ...n) { + return F(t, Array.from, R, n); + }), + (t.interpolate = Gr), + (t.interpolateArray = function (t, n) { + return (Ir(n) ? Ur : Or)(t, n); + }), + (t.interpolateBasis = Er), + (t.interpolateBasisClosed = Nr), + (t.interpolateBlues = Gb), + (t.interpolateBrBG = ob), + (t.interpolateBuGn = Mb), + (t.interpolateBuPu = Ab), + (t.interpolateCividis = function (t) { + return ( + (t = Math.max(0, Math.min(1, t))), + "rgb(" + + Math.max( + 0, + Math.min( + 255, + Math.round( + -4.54 - + t * + (35.34 - + t * + (2381.73 - t * (6402.7 - t * (7024.72 - 2710.57 * t)))), + ), + ), + ) + + ", " + + Math.max( + 0, + Math.min( + 255, + Math.round( + 32.49 + + t * + (170.73 + + t * (52.82 - t * (131.46 - t * (176.58 - 67.37 * t)))), + ), + ), + ) + + ", " + + Math.max( + 0, + Math.min( + 255, + Math.round( + 81.24 + + t * + (442.36 - + t * + (2482.43 - + t * (6167.24 - t * (6614.94 - 2475.67 * t)))), + ), + ), + ) + + ")" + ); + }), + (t.interpolateCool = am), + (t.interpolateCubehelix = li), + (t.interpolateCubehelixDefault = im), + (t.interpolateCubehelixLong = hi), + (t.interpolateDate = Br), + (t.interpolateDiscrete = function (t) { + var n = t.length; + return function (e) { + return t[Math.max(0, Math.min(n - 1, Math.floor(e * n)))]; + }; + }), + (t.interpolateGnBu = Eb), + (t.interpolateGreens = Wb), + (t.interpolateGreys = Kb), + (t.interpolateHcl = ci), + (t.interpolateHclLong = fi), + (t.interpolateHsl = oi), + (t.interpolateHslLong = ai), + (t.interpolateHue = function (t, n) { + var e = Pr(+t, +n); + return function (t) { + var n = e(t); + return n - 360 * Math.floor(n / 360); + }; + }), + (t.interpolateInferno = pm), + (t.interpolateLab = function (t, n) { + var e = $r((t = ar(t)).l, (n = ar(n)).l), + r = $r(t.a, n.a), + i = $r(t.b, n.b), + o = $r(t.opacity, n.opacity); + return function (n) { + return ( + (t.l = e(n)), + (t.a = r(n)), + (t.b = i(n)), + (t.opacity = o(n)), + t + "" + ); + }; + }), + (t.interpolateMagma = dm), + (t.interpolateNumber = Yr), + (t.interpolateNumberArray = Ur), + (t.interpolateObject = Lr), + (t.interpolateOrRd = kb), + (t.interpolateOranges = rm), + (t.interpolatePRGn = ub), + (t.interpolatePiYG = fb), + (t.interpolatePlasma = gm), + (t.interpolatePuBu = $b), + (t.interpolatePuBuGn = Pb), + (t.interpolatePuOr = lb), + (t.interpolatePuRd = Rb), + (t.interpolatePurples = Jb), + (t.interpolateRainbow = function (t) { + (t < 0 || t > 1) && (t -= Math.floor(t)); + var n = Math.abs(t - 0.5); + return ( + (um.h = 360 * t - 100), + (um.s = 1.5 - 1.5 * n), + (um.l = 0.8 - 0.9 * n), + um + "" + ); + }), + (t.interpolateRdBu = db), + (t.interpolateRdGy = gb), + (t.interpolateRdPu = qb), + (t.interpolateRdYlBu = vb), + (t.interpolateRdYlGn = bb), + (t.interpolateReds = nm), + (t.interpolateRgb = Dr), + (t.interpolateRgbBasis = Fr), + (t.interpolateRgbBasisClosed = qr), + (t.interpolateRound = Vr), + (t.interpolateSinebow = function (t) { + var n; + return ( + (t = (0.5 - t) * Math.PI), + (cm.r = 255 * (n = Math.sin(t)) * n), + (cm.g = 255 * (n = Math.sin(t + fm)) * n), + (cm.b = 255 * (n = Math.sin(t + sm)) * n), + cm + "" + ); + }), + (t.interpolateSpectral = xb), + (t.interpolateString = Xr), + (t.interpolateTransformCss = ti), + (t.interpolateTransformSvg = ni), + (t.interpolateTurbo = function (t) { + return ( + (t = Math.max(0, Math.min(1, t))), + "rgb(" + + Math.max( + 0, + Math.min( + 255, + Math.round( + 34.61 + + t * + (1172.33 - + t * + (10793.56 - + t * (33300.12 - t * (38394.49 - 14825.05 * t)))), + ), + ), + ) + + ", " + + Math.max( + 0, + Math.min( + 255, + Math.round( + 23.31 + + t * + (557.33 + + t * + (1225.33 - t * (3574.96 - t * (1073.77 + 707.56 * t)))), + ), + ), + ) + + ", " + + Math.max( + 0, + Math.min( + 255, + Math.round( + 27.2 + + t * + (3211.1 - + t * + (15327.97 - + t * (27814 - t * (22569.18 - 6838.66 * t)))), + ), + ), + ) + + ")" + ); + }), + (t.interpolateViridis = hm), + (t.interpolateWarm = om), + (t.interpolateYlGn = Bb), + (t.interpolateYlGnBu = Ib), + (t.interpolateYlOrBr = Lb), + (t.interpolateYlOrRd = Hb), + (t.interpolateZoom = ri), + (t.interrupt = Gi), + (t.intersection = function (t, ...n) { + ((t = new InternSet(t)), (n = n.map(vt))); + t: for (const e of t) + for (const r of n) + if (!r.has(e)) { + t.delete(e); + continue t; + } + return t; + }), + (t.interval = function (t, n, e) { + var r = new Ei(), + i = n; + return null == n + ? (r.restart(t, n, e), r) + : ((r._restart = r.restart), + (r.restart = function (t, n, e) { + ((n = +n), + (e = null == e ? Ai() : +e), + r._restart( + function o(a) { + ((a += i), r._restart(o, (i += n), e), t(a)); + }, + n, + e, + )); + }), + r.restart(t, n, e), + r); + }), + (t.isoFormat = D_), + (t.isoParse = F_), + (t.json = function (t, n) { + return fetch(t, n).then(Tc); + }), + (t.lab = ar), + (t.lch = function (t, n, e, r) { + return 1 === arguments.length + ? hr(t) + : new pr(e, n, t, null == r ? 1 : r); + }), + (t.least = function (t, e = n) { + let r, + i = !1; + if (1 === e.length) { + let o; + for (const a of t) { + const t = e(a); + (i ? n(t, o) < 0 : 0 === n(t, t)) && ((r = a), (o = t), (i = !0)); + } + } else + for (const n of t) + (i ? e(n, r) < 0 : 0 === e(n, n)) && ((r = n), (i = !0)); + return r; + }), + (t.leastIndex = ht), + (t.line = Ym), + (t.lineRadial = Zm), + (t.link = ax), + (t.linkHorizontal = function () { + return ax(nx); + }), + (t.linkRadial = function () { + const t = ax(rx); + return ((t.angle = t.x), delete t.x, (t.radius = t.y), delete t.y, t); + }), + (t.linkVertical = function () { + return ax(ex); + }), + (t.local = Qn), + (t.map = function (t, n) { + if ("function" != typeof t[Symbol.iterator]) + throw new TypeError("values is not iterable"); + if ("function" != typeof n) + throw new TypeError("mapper is not a function"); + return Array.from(t, (e, r) => n(e, r, t)); + }), + (t.matcher = Vt), + (t.max = J), + (t.maxIndex = tt), + (t.mean = function (t, n) { + let e = 0, + r = 0; + if (void 0 === n) + for (let n of t) null != n && (n = +n) >= n && (++e, (r += n)); + else { + let i = -1; + for (let o of t) + null != (o = n(o, ++i, t)) && (o = +o) >= o && (++e, (r += o)); + } + if (e) return r / e; + }), + (t.median = function (t, n) { + return at(t, 0.5, n); + }), + (t.medianIndex = function (t, n) { + return ct(t, 0.5, n); + }), + (t.merge = ft), + (t.min = nt), + (t.minIndex = et), + (t.mode = function (t, n) { + const e = new InternMap(); + if (void 0 === n) + for (let n of t) null != n && n >= n && e.set(n, (e.get(n) || 0) + 1); + else { + let r = -1; + for (let i of t) + null != (i = n(i, ++r, t)) && i >= i && e.set(i, (e.get(i) || 0) + 1); + } + let r, + i = 0; + for (const [t, n] of e) n > i && ((i = n), (r = t)); + return r; + }), + (t.namespace = It), + (t.namespaces = Ut), + (t.nice = Z), + (t.now = Ai), + (t.pack = function () { + var t = null, + n = 1, + e = 1, + r = np; + function i(i) { + const o = ap(); + return ( + (i.x = n / 2), + (i.y = e / 2), + t + ? i + .eachBefore(xp(t)) + .eachAfter(wp(r, 0.5, o)) + .eachBefore(Mp(1)) + : i + .eachBefore(xp(mp)) + .eachAfter(wp(np, 1, o)) + .eachAfter(wp(r, i.r / Math.min(n, e), o)) + .eachBefore(Mp(Math.min(n, e) / (2 * i.r))), + i + ); + } + return ( + (i.radius = function (n) { + return arguments.length ? ((t = Jd(n)), i) : t; + }), + (i.size = function (t) { + return arguments.length ? ((n = +t[0]), (e = +t[1]), i) : [n, e]; + }), + (i.padding = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : ep(+t)), i) + : r; + }), + i + ); + }), + (t.packEnclose = function (t) { + return up(t, ap()); + }), + (t.packSiblings = function (t) { + return (bp(t, ap()), t); + }), + (t.pairs = function (t, n = st) { + const e = []; + let r, + i = !1; + for (const o of t) (i && e.push(n(r, o)), (r = o), (i = !0)); + return e; + }), + (t.partition = function () { + var t = 1, + n = 1, + e = 0, + r = !1; + function i(i) { + var o = i.height + 1; + return ( + (i.x0 = i.y0 = e), + (i.x1 = t), + (i.y1 = n / o), + i.eachBefore( + (function (t, n) { + return function (r) { + r.children && + Ap( + r, + r.x0, + (t * (r.depth + 1)) / n, + r.x1, + (t * (r.depth + 2)) / n, + ); + var i = r.x0, + o = r.y0, + a = r.x1 - e, + u = r.y1 - e; + (a < i && (i = a = (i + a) / 2), + u < o && (o = u = (o + u) / 2), + (r.x0 = i), + (r.y0 = o), + (r.x1 = a), + (r.y1 = u)); + }; + })(n, o), + ), + r && i.eachBefore(Tp), + i + ); + } + return ( + (i.round = function (t) { + return arguments.length ? ((r = !!t), i) : r; + }), + (i.size = function (e) { + return arguments.length ? ((t = +e[0]), (n = +e[1]), i) : [t, n]; + }), + (i.padding = function (t) { + return arguments.length ? ((e = +t), i) : e; + }), + i + ); + }), + (t.path = Ia), + (t.pathRound = function (t = 3) { + return new Ua(+t); + }), + (t.permute = q), + (t.pie = function () { + var t = Hm, + n = jm, + e = null, + r = ym(0), + i = ym(Em), + o = ym(0); + function a(a) { + var u, + c, + f, + s, + l, + h = (a = qm(a)).length, + d = 0, + p = new Array(h), + g = new Array(h), + y = +r.apply(this, arguments), + v = Math.min(Em, Math.max(-Em, i.apply(this, arguments) - y)), + _ = Math.min(Math.abs(v) / h, o.apply(this, arguments)), + b = _ * (v < 0 ? -1 : 1); + for (u = 0; u < h; ++u) + (l = g[(p[u] = u)] = +t(a[u], u, a)) > 0 && (d += l); + for ( + null != n + ? p.sort(function (t, e) { + return n(g[t], g[e]); + }) + : null != e && + p.sort(function (t, n) { + return e(a[t], a[n]); + }), + u = 0, + f = d ? (v - h * b) / d : 0; + u < h; + ++u, y = s + ) + ((c = p[u]), + (s = y + ((l = g[c]) > 0 ? l * f : 0) + b), + (g[c] = { + data: a[c], + index: u, + value: l, + startAngle: y, + endAngle: s, + padAngle: _, + })); + return g; + } + return ( + (a.value = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(+n)), a) + : t; + }), + (a.sortValues = function (t) { + return arguments.length ? ((n = t), (e = null), a) : n; + }), + (a.sort = function (t) { + return arguments.length ? ((e = t), (n = null), a) : e; + }), + (a.startAngle = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : ym(+t)), a) + : r; + }), + (a.endAngle = function (t) { + return arguments.length + ? ((i = "function" == typeof t ? t : ym(+t)), a) + : i; + }), + (a.padAngle = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : ym(+t)), a) + : o; + }), + a + ); + }), + (t.piecewise = di), + (t.pointRadial = Qm), + (t.pointer = ne), + (t.pointers = function (t, n) { + return ( + t.target && + ((t = te(t)), + void 0 === n && (n = t.currentTarget), + (t = t.touches || [t])), + Array.from(t, (t) => ne(t, n)) + ); + }), + (t.polygonArea = function (t) { + for (var n, e = -1, r = t.length, i = t[r - 1], o = 0; ++e < r; ) + ((n = i), (i = t[e]), (o += n[1] * i[0] - n[0] * i[1])); + return o / 2; + }), + (t.polygonCentroid = function (t) { + for ( + var n, e, r = -1, i = t.length, o = 0, a = 0, u = t[i - 1], c = 0; + ++r < i; + + ) + ((n = u), + (u = t[r]), + (c += e = n[0] * u[1] - u[0] * n[1]), + (o += (n[0] + u[0]) * e), + (a += (n[1] + u[1]) * e)); + return [o / (c *= 3), a / c]; + }), + (t.polygonContains = function (t, n) { + for ( + var e, + r, + i = t.length, + o = t[i - 1], + a = n[0], + u = n[1], + c = o[0], + f = o[1], + s = !1, + l = 0; + l < i; + ++l + ) + ((e = (o = t[l])[0]), + (r = o[1]) > u != f > u && + a < ((c - e) * (u - r)) / (f - r) + e && + (s = !s), + (c = e), + (f = r)); + return s; + }), + (t.polygonHull = function (t) { + if ((e = t.length) < 3) return null; + var n, + e, + r = new Array(e), + i = new Array(e); + for (n = 0; n < e; ++n) r[n] = [+t[n][0], +t[n][1], n]; + for (r.sort(Hp), n = 0; n < e; ++n) i[n] = [r[n][0], -r[n][1]]; + var o = Xp(r), + a = Xp(i), + u = a[0] === o[0], + c = a[a.length - 1] === o[o.length - 1], + f = []; + for (n = o.length - 1; n >= 0; --n) f.push(t[r[o[n]][2]]); + for (n = +u; n < a.length - c; ++n) f.push(t[r[a[n]][2]]); + return f; + }), + (t.polygonLength = function (t) { + for ( + var n, e, r = -1, i = t.length, o = t[i - 1], a = o[0], u = o[1], c = 0; + ++r < i; + + ) + ((n = a), + (e = u), + (n -= a = (o = t[r])[0]), + (e -= u = o[1]), + (c += Math.hypot(n, e))); + return c; + }), + (t.precisionFixed = sf), + (t.precisionPrefix = lf), + (t.precisionRound = hf), + (t.quadtree = $c), + (t.quantile = at), + (t.quantileIndex = ct), + (t.quantileSorted = ut), + (t.quantize = function (t, n) { + for (var e = new Array(n), r = 0; r < n; ++r) e[r] = t(r / (n - 1)); + return e; + }), + (t.quickselect = rt), + (t.radialArea = Km), + (t.radialLine = Zm), + (t.randomBates = Jp), + (t.randomBernoulli = eg), + (t.randomBeta = og), + (t.randomBinomial = ag), + (t.randomCauchy = cg), + (t.randomExponential = tg), + (t.randomGamma = ig), + (t.randomGeometric = rg), + (t.randomInt = Wp), + (t.randomIrwinHall = Qp), + (t.randomLcg = function (t = Math.random()) { + let n = 0 | (0 <= t && t < 1 ? t / lg : Math.abs(t)); + return () => ((n = (1664525 * n + 1013904223) | 0), lg * (n >>> 0)); + }), + (t.randomLogNormal = Kp), + (t.randomLogistic = fg), + (t.randomNormal = Zp), + (t.randomPareto = ng), + (t.randomPoisson = sg), + (t.randomUniform = Vp), + (t.randomWeibull = ug), + (t.range = lt), + (t.rank = function (t, e = n) { + if ("function" != typeof t[Symbol.iterator]) + throw new TypeError("values is not iterable"); + let r = Array.from(t); + const i = new Float64Array(r.length); + 2 !== e.length && ((r = r.map(e)), (e = n)); + const o = (t, n) => e(r[t], r[n]); + let a, u; + return ( + (t = Uint32Array.from(r, (t, n) => n)).sort( + e === n ? (t, n) => O(r[t], r[n]) : I(o), + ), + t.forEach((t, n) => { + const e = o(t, void 0 === a ? t : a); + e >= 0 + ? ((void 0 === a || e > 0) && ((a = t), (u = n)), (i[t] = u)) + : (i[t] = NaN); + }), + i + ); + }), + (t.reduce = function (t, n, e) { + if ("function" != typeof n) + throw new TypeError("reducer is not a function"); + const r = t[Symbol.iterator](); + let i, + o, + a = -1; + if (arguments.length < 3) { + if ((({ done: i, value: e } = r.next()), i)) return; + ++a; + } + for (; ({ done: i, value: o } = r.next()), !i; ) e = n(e, o, ++a, t); + return e; + }), + (t.reverse = function (t) { + if ("function" != typeof t[Symbol.iterator]) + throw new TypeError("values is not iterable"); + return Array.from(t).reverse(); + }), + (t.rgb = Fe), + (t.ribbon = function () { + return Wa(); + }), + (t.ribbonArrow = function () { + return Wa(Va); + }), + (t.rollup = $), + (t.rollups = D), + (t.scaleBand = yg), + (t.scaleDiverging = function t() { + var n = Ng(L_()(mg)); + return ( + (n.copy = function () { + return B_(n, t()); + }), + dg.apply(n, arguments) + ); + }), + (t.scaleDivergingLog = function t() { + var n = Fg(L_()).domain([0.1, 1, 10]); + return ( + (n.copy = function () { + return B_(n, t()).base(n.base()); + }), + dg.apply(n, arguments) + ); + }), + (t.scaleDivergingPow = j_), + (t.scaleDivergingSqrt = function () { + return j_.apply(null, arguments).exponent(0.5); + }), + (t.scaleDivergingSymlog = function t() { + var n = Ig(L_()); + return ( + (n.copy = function () { + return B_(n, t()).constant(n.constant()); + }), + dg.apply(n, arguments) + ); + }), + (t.scaleIdentity = function t(n) { + var e; + function r(t) { + return null == t || isNaN((t = +t)) ? e : t; + } + return ( + (r.invert = r), + (r.domain = r.range = + function (t) { + return arguments.length ? ((n = Array.from(t, _g)), r) : n.slice(); + }), + (r.unknown = function (t) { + return arguments.length ? ((e = t), r) : e; + }), + (r.copy = function () { + return t(n).unknown(e); + }), + (n = arguments.length ? Array.from(n, _g) : [0, 1]), + Ng(r) + ); + }), + (t.scaleImplicit = pg), + (t.scaleLinear = function t() { + var n = Sg(); + return ( + (n.copy = function () { + return Tg(n, t()); + }), + hg.apply(n, arguments), + Ng(n) + ); + }), + (t.scaleLog = function t() { + const n = Fg(Ag()).domain([1, 10]); + return ( + (n.copy = () => Tg(n, t()).base(n.base())), + hg.apply(n, arguments), + n + ); + }), + (t.scaleOrdinal = gg), + (t.scalePoint = function () { + return vg(yg.apply(null, arguments).paddingInner(1)); + }), + (t.scalePow = jg), + (t.scaleQuantile = function t() { + var e, + r = [], + i = [], + o = []; + function a() { + var t = 0, + n = Math.max(1, i.length); + for (o = new Array(n - 1); ++t < n; ) o[t - 1] = ut(r, t / n); + return u; + } + function u(t) { + return null == t || isNaN((t = +t)) ? e : i[s(o, t)]; + } + return ( + (u.invertExtent = function (t) { + var n = i.indexOf(t); + return n < 0 + ? [NaN, NaN] + : [n > 0 ? o[n - 1] : r[0], n < o.length ? o[n] : r[r.length - 1]]; + }), + (u.domain = function (t) { + if (!arguments.length) return r.slice(); + r = []; + for (let n of t) null == n || isNaN((n = +n)) || r.push(n); + return (r.sort(n), a()); + }), + (u.range = function (t) { + return arguments.length ? ((i = Array.from(t)), a()) : i.slice(); + }), + (u.unknown = function (t) { + return arguments.length ? ((e = t), u) : e; + }), + (u.quantiles = function () { + return o.slice(); + }), + (u.copy = function () { + return t().domain(r).range(i).unknown(e); + }), + hg.apply(u, arguments) + ); + }), + (t.scaleQuantize = function t() { + var n, + e = 0, + r = 1, + i = 1, + o = [0.5], + a = [0, 1]; + function u(t) { + return null != t && t <= t ? a[s(o, t, 0, i)] : n; + } + function c() { + var t = -1; + for (o = new Array(i); ++t < i; ) + o[t] = ((t + 1) * r - (t - i) * e) / (i + 1); + return u; + } + return ( + (u.domain = function (t) { + return arguments.length + ? (([e, r] = t), (e = +e), (r = +r), c()) + : [e, r]; + }), + (u.range = function (t) { + return arguments.length + ? ((i = (a = Array.from(t)).length - 1), c()) + : a.slice(); + }), + (u.invertExtent = function (t) { + var n = a.indexOf(t); + return n < 0 + ? [NaN, NaN] + : n < 1 + ? [e, o[0]] + : n >= i + ? [o[i - 1], r] + : [o[n - 1], o[n]]; + }), + (u.unknown = function (t) { + return arguments.length ? ((n = t), u) : u; + }), + (u.thresholds = function () { + return o.slice(); + }), + (u.copy = function () { + return t().domain([e, r]).range(a).unknown(n); + }), + hg.apply(Ng(u), arguments) + ); + }), + (t.scaleRadial = function t() { + var n, + e = Sg(), + r = [0, 1], + i = !1; + function o(t) { + var r = (function (t) { + return Math.sign(t) * Math.sqrt(Math.abs(t)); + })(e(t)); + return isNaN(r) ? n : i ? Math.round(r) : r; + } + return ( + (o.invert = function (t) { + return e.invert(Hg(t)); + }), + (o.domain = function (t) { + return arguments.length ? (e.domain(t), o) : e.domain(); + }), + (o.range = function (t) { + return arguments.length + ? (e.range((r = Array.from(t, _g)).map(Hg)), o) + : r.slice(); + }), + (o.rangeRound = function (t) { + return o.range(t).round(!0); + }), + (o.round = function (t) { + return arguments.length ? ((i = !!t), o) : i; + }), + (o.clamp = function (t) { + return arguments.length ? (e.clamp(t), o) : e.clamp(); + }), + (o.unknown = function (t) { + return arguments.length ? ((n = t), o) : n; + }), + (o.copy = function () { + return t(e.domain(), r).round(i).clamp(e.clamp()).unknown(n); + }), + hg.apply(o, arguments), + Ng(o) + ); + }), + (t.scaleSequential = function t() { + var n = Ng(O_()(mg)); + return ( + (n.copy = function () { + return B_(n, t()); + }), + dg.apply(n, arguments) + ); + }), + (t.scaleSequentialLog = function t() { + var n = Fg(O_()).domain([1, 10]); + return ( + (n.copy = function () { + return B_(n, t()).base(n.base()); + }), + dg.apply(n, arguments) + ); + }), + (t.scaleSequentialPow = Y_), + (t.scaleSequentialQuantile = function t() { + var e = [], + r = mg; + function i(t) { + if (null != t && !isNaN((t = +t))) + return r((s(e, t, 1) - 1) / (e.length - 1)); + } + return ( + (i.domain = function (t) { + if (!arguments.length) return e.slice(); + e = []; + for (let n of t) null == n || isNaN((n = +n)) || e.push(n); + return (e.sort(n), i); + }), + (i.interpolator = function (t) { + return arguments.length ? ((r = t), i) : r; + }), + (i.range = function () { + return e.map((t, n) => r(n / (e.length - 1))); + }), + (i.quantiles = function (t) { + return Array.from({ length: t + 1 }, (n, r) => at(e, r / t)); + }), + (i.copy = function () { + return t(r).domain(e); + }), + dg.apply(i, arguments) + ); + }), + (t.scaleSequentialSqrt = function () { + return Y_.apply(null, arguments).exponent(0.5); + }), + (t.scaleSequentialSymlog = function t() { + var n = Ig(O_()); + return ( + (n.copy = function () { + return B_(n, t()).constant(n.constant()); + }), + dg.apply(n, arguments) + ); + }), + (t.scaleSqrt = function () { + return jg.apply(null, arguments).exponent(0.5); + }), + (t.scaleSymlog = function t() { + var n = Ig(Ag()); + return ( + (n.copy = function () { + return Tg(n, t()).constant(n.constant()); + }), + hg.apply(n, arguments) + ); + }), + (t.scaleThreshold = function t() { + var n, + e = [0.5], + r = [0, 1], + i = 1; + function o(t) { + return null != t && t <= t ? r[s(e, t, 0, i)] : n; + } + return ( + (o.domain = function (t) { + return arguments.length + ? ((e = Array.from(t)), (i = Math.min(e.length, r.length - 1)), o) + : e.slice(); + }), + (o.range = function (t) { + return arguments.length + ? ((r = Array.from(t)), (i = Math.min(e.length, r.length - 1)), o) + : r.slice(); + }), + (o.invertExtent = function (t) { + var n = r.indexOf(t); + return [e[n - 1], e[n]]; + }), + (o.unknown = function (t) { + return arguments.length ? ((n = t), o) : n; + }), + (o.copy = function () { + return t().domain(e).range(r).unknown(n); + }), + hg.apply(o, arguments) + ); + }), + (t.scaleTime = function () { + return hg.apply( + I_(uv, cv, tv, Zy, xy, py, sy, ay, iy, t.timeFormat).domain([ + new Date(2e3, 0, 1), + new Date(2e3, 0, 2), + ]), + arguments, + ); + }), + (t.scaleUtc = function () { + return hg.apply( + I_(ov, av, ev, Qy, Fy, yy, hy, cy, iy, t.utcFormat).domain([ + Date.UTC(2e3, 0, 1), + Date.UTC(2e3, 0, 2), + ]), + arguments, + ); + }), + (t.scan = function (t, n) { + const e = ht(t, n); + return e < 0 ? void 0 : e; + }), + (t.schemeAccent = G_), + (t.schemeBlues = Xb), + (t.schemeBrBG = ib), + (t.schemeBuGn = wb), + (t.schemeBuPu = Tb), + (t.schemeCategory10 = X_), + (t.schemeDark2 = V_), + (t.schemeGnBu = Sb), + (t.schemeGreens = Vb), + (t.schemeGreys = Zb), + (t.schemeObservable10 = W_), + (t.schemeOrRd = Nb), + (t.schemeOranges = em), + (t.schemePRGn = ab), + (t.schemePaired = Z_), + (t.schemePastel1 = K_), + (t.schemePastel2 = Q_), + (t.schemePiYG = cb), + (t.schemePuBu = zb), + (t.schemePuBuGn = Cb), + (t.schemePuOr = sb), + (t.schemePuRd = Db), + (t.schemePurples = Qb), + (t.schemeRdBu = hb), + (t.schemeRdGy = pb), + (t.schemeRdPu = Fb), + (t.schemeRdYlBu = yb), + (t.schemeRdYlGn = _b), + (t.schemeReds = tm), + (t.schemeSet1 = J_), + (t.schemeSet2 = tb), + (t.schemeSet3 = nb), + (t.schemeSpectral = mb), + (t.schemeTableau10 = eb), + (t.schemeYlGn = Ob), + (t.schemeYlGnBu = Ub), + (t.schemeYlOrBr = Yb), + (t.schemeYlOrRd = jb), + (t.select = Zn), + (t.selectAll = function (t) { + return "string" == typeof t + ? new Vn([document.querySelectorAll(t)], [document.documentElement]) + : new Vn([Ht(t)], Gn); + }), + (t.selection = Wn), + (t.selector = jt), + (t.selectorAll = Gt), + (t.shuffle = dt), + (t.shuffler = pt), + (t.some = function (t, n) { + if ("function" != typeof n) throw new TypeError("test is not a function"); + let e = -1; + for (const r of t) if (n(r, ++e, t)) return !0; + return !1; + }), + (t.sort = U), + (t.stack = function () { + var t = ym([]), + n = dw, + e = hw, + r = pw; + function i(i) { + var o, + a, + u = Array.from(t.apply(this, arguments), gw), + c = u.length, + f = -1; + for (const t of i) + for (o = 0, ++f; o < c; ++o) + (u[o][f] = [0, +r(t, u[o].key, f, i)]).data = t; + for (o = 0, a = qm(n(u)); o < c; ++o) u[a[o]].index = o; + return (e(u, a), u); + } + return ( + (i.keys = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(Array.from(n))), i) + : t; + }), + (i.value = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : ym(+t)), i) + : r; + }), + (i.order = function (t) { + return arguments.length + ? ((n = + null == t + ? dw + : "function" == typeof t + ? t + : ym(Array.from(t))), + i) + : n; + }), + (i.offset = function (t) { + return arguments.length ? ((e = null == t ? hw : t), i) : e; + }), + i + ); + }), + (t.stackOffsetDiverging = function (t, n) { + if ((u = t.length) > 0) + for (var e, r, i, o, a, u, c = 0, f = t[n[0]].length; c < f; ++c) + for (o = a = 0, e = 0; e < u; ++e) + (i = (r = t[n[e]][c])[1] - r[0]) > 0 + ? ((r[0] = o), (r[1] = o += i)) + : i < 0 + ? ((r[1] = a), (r[0] = a += i)) + : ((r[0] = 0), (r[1] = i)); + }), + (t.stackOffsetExpand = function (t, n) { + if ((r = t.length) > 0) { + for (var e, r, i, o = 0, a = t[0].length; o < a; ++o) { + for (i = e = 0; e < r; ++e) i += t[e][o][1] || 0; + if (i) for (e = 0; e < r; ++e) t[e][o][1] /= i; + } + hw(t, n); + } + }), + (t.stackOffsetNone = hw), + (t.stackOffsetSilhouette = function (t, n) { + if ((e = t.length) > 0) { + for (var e, r = 0, i = t[n[0]], o = i.length; r < o; ++r) { + for (var a = 0, u = 0; a < e; ++a) u += t[a][r][1] || 0; + i[r][1] += i[r][0] = -u / 2; + } + hw(t, n); + } + }), + (t.stackOffsetWiggle = function (t, n) { + if ((i = t.length) > 0 && (r = (e = t[n[0]]).length) > 0) { + for (var e, r, i, o = 0, a = 1; a < r; ++a) { + for (var u = 0, c = 0, f = 0; u < i; ++u) { + for ( + var s = t[n[u]], + l = s[a][1] || 0, + h = (l - (s[a - 1][1] || 0)) / 2, + d = 0; + d < u; + ++d + ) { + var p = t[n[d]]; + h += (p[a][1] || 0) - (p[a - 1][1] || 0); + } + ((c += l), (f += h * l)); + } + ((e[a - 1][1] += e[a - 1][0] = o), c && (o -= f / c)); + } + ((e[a - 1][1] += e[a - 1][0] = o), hw(t, n)); + } + }), + (t.stackOrderAppearance = yw), + (t.stackOrderAscending = _w), + (t.stackOrderDescending = function (t) { + return _w(t).reverse(); + }), + (t.stackOrderInsideOut = function (t) { + var n, + e, + r = t.length, + i = t.map(bw), + o = yw(t), + a = 0, + u = 0, + c = [], + f = []; + for (n = 0; n < r; ++n) + ((e = o[n]), + a < u ? ((a += i[e]), c.push(e)) : ((u += i[e]), f.push(e))); + return f.reverse().concat(c); + }), + (t.stackOrderNone = dw), + (t.stackOrderReverse = function (t) { + return dw(t).reverse(); + }), + (t.stratify = function () { + var t, + n = kp, + e = Cp; + function r(r) { + var i, + o, + a, + u, + c, + f, + s, + l, + h = Array.from(r), + d = n, + p = e, + g = new Map(); + if (null != t) { + const n = h.map((n, e) => + (function (t) { + t = `${t}`; + let n = t.length; + zp(t, n - 1) && !zp(t, n - 2) && (t = t.slice(0, -1)); + return "/" === t[0] ? t : `/${t}`; + })(t(n, e, r)), + ), + e = n.map(Pp), + i = new Set(n).add(""); + for (const t of e) + i.has(t) || (i.add(t), n.push(t), e.push(Pp(t)), h.push(Np)); + ((d = (t, e) => n[e]), (p = (t, n) => e[n])); + } + for (a = 0, i = h.length; a < i; ++a) + ((o = h[a]), + (f = h[a] = new Qd(o)), + null != (s = d(o, a, r)) && + (s += "") && + ((l = f.id = s), g.set(l, g.has(l) ? Ep : f)), + null != (s = p(o, a, r)) && (s += "") && (f.parent = s)); + for (a = 0; a < i; ++a) + if ((s = (f = h[a]).parent)) { + if (!(c = g.get(s))) throw new Error("missing: " + s); + if (c === Ep) throw new Error("ambiguous: " + s); + (c.children ? c.children.push(f) : (c.children = [f]), + (f.parent = c)); + } else { + if (u) throw new Error("multiple roots"); + u = f; + } + if (!u) throw new Error("no root"); + if (null != t) { + for (; u.data === Np && 1 === u.children.length; ) + ((u = u.children[0]), --i); + for (let t = h.length - 1; t >= 0 && (f = h[t]).data === Np; --t) + f.data = null; + } + if ( + ((u.parent = Sp), + u + .eachBefore(function (t) { + ((t.depth = t.parent.depth + 1), --i); + }) + .eachBefore(Kd), + (u.parent = null), + i > 0) + ) + throw new Error("cycle"); + return u; + } + return ( + (r.id = function (t) { + return arguments.length ? ((n = Jd(t)), r) : n; + }), + (r.parentId = function (t) { + return arguments.length ? ((e = Jd(t)), r) : e; + }), + (r.path = function (n) { + return arguments.length ? ((t = Jd(n)), r) : t; + }), + r + ); + }), + (t.style = _n), + (t.subset = function (t, n) { + return _t(n, t); + }), + (t.sum = function (t, n) { + let e = 0; + if (void 0 === n) for (let n of t) (n = +n) && (e += n); + else { + let r = -1; + for (let i of t) (i = +n(i, ++r, t)) && (e += i); + } + return e; + }), + (t.superset = _t), + (t.svg = Nc), + (t.symbol = function (t, n) { + let e = null, + r = km(i); + function i() { + let i; + if ( + (e || (e = i = r()), + t.apply(this, arguments).draw(e, +n.apply(this, arguments)), + i) + ) + return ((e = null), i + "" || null); + } + return ( + (t = "function" == typeof t ? t : ym(t || fx)), + (n = "function" == typeof n ? n : ym(void 0 === n ? 64 : +n)), + (i.type = function (n) { + return arguments.length + ? ((t = "function" == typeof n ? n : ym(n)), i) + : t; + }), + (i.size = function (t) { + return arguments.length + ? ((n = "function" == typeof t ? t : ym(+t)), i) + : n; + }), + (i.context = function (t) { + return arguments.length ? ((e = null == t ? null : t), i) : e; + }), + i + ); + }), + (t.symbolAsterisk = cx), + (t.symbolCircle = fx), + (t.symbolCross = sx), + (t.symbolDiamond = dx), + (t.symbolDiamond2 = px), + (t.symbolPlus = gx), + (t.symbolSquare = yx), + (t.symbolSquare2 = vx), + (t.symbolStar = xx), + (t.symbolTimes = Px), + (t.symbolTriangle = Mx), + (t.symbolTriangle2 = Ax), + (t.symbolWye = Cx), + (t.symbolX = Px), + (t.symbols = zx), + (t.symbolsFill = zx), + (t.symbolsStroke = $x), + (t.text = mc), + (t.thresholdFreedmanDiaconis = function (t, n, e) { + const r = v(t), + i = at(t, 0.75) - at(t, 0.25); + return r && i ? Math.ceil((e - n) / (2 * i * Math.pow(r, -1 / 3))) : 1; + }), + (t.thresholdScott = function (t, n, e) { + const r = v(t), + i = w(t); + return r && i ? Math.ceil(((e - n) * Math.cbrt(r)) / (3.49 * i)) : 1; + }), + (t.thresholdSturges = K), + (t.tickFormat = Eg), + (t.tickIncrement = V), + (t.tickStep = W), + (t.ticks = G), + (t.timeDay = py), + (t.timeDays = gy), + (t.timeFormatDefaultLocale = P_), + (t.timeFormatLocale = hv), + (t.timeFriday = Sy), + (t.timeFridays = $y), + (t.timeHour = sy), + (t.timeHours = ly), + (t.timeInterval = Vg), + (t.timeMillisecond = Wg), + (t.timeMilliseconds = Zg), + (t.timeMinute = ay), + (t.timeMinutes = uy), + (t.timeMonday = wy), + (t.timeMondays = ky), + (t.timeMonth = Zy), + (t.timeMonths = Ky), + (t.timeSaturday = Ey), + (t.timeSaturdays = Dy), + (t.timeSecond = iy), + (t.timeSeconds = oy), + (t.timeSunday = xy), + (t.timeSundays = Ny), + (t.timeThursday = Ay), + (t.timeThursdays = zy), + (t.timeTickInterval = cv), + (t.timeTicks = uv), + (t.timeTuesday = My), + (t.timeTuesdays = Cy), + (t.timeWednesday = Ty), + (t.timeWednesdays = Py), + (t.timeWeek = xy), + (t.timeWeeks = Ny), + (t.timeYear = tv), + (t.timeYears = nv), + (t.timeout = $i), + (t.timer = Ni), + (t.timerFlush = ki), + (t.transition = go), + (t.transpose = gt), + (t.tree = function () { + var t = $p, + n = 1, + e = 1, + r = null; + function i(i) { + var c = (function (t) { + for (var n, e, r, i, o, a = new Up(t, 0), u = [a]; (n = u.pop()); ) + if ((r = n._.children)) + for ( + n.children = new Array((o = r.length)), i = o - 1; + i >= 0; + --i + ) + (u.push((e = n.children[i] = new Up(r[i], i))), (e.parent = n)); + return (((a.parent = new Up(null, 0)).children = [a]), a); + })(i); + if ((c.eachAfter(o), (c.parent.m = -c.z), c.eachBefore(a), r)) + i.eachBefore(u); + else { + var f = i, + s = i, + l = i; + i.eachBefore(function (t) { + (t.x < f.x && (f = t), + t.x > s.x && (s = t), + t.depth > l.depth && (l = t)); + }); + var h = f === s ? 1 : t(f, s) / 2, + d = h - f.x, + p = n / (s.x + h + d), + g = e / (l.depth || 1); + i.eachBefore(function (t) { + ((t.x = (t.x + d) * p), (t.y = t.depth * g)); + }); + } + return i; + } + function o(n) { + var e = n.children, + r = n.parent.children, + i = n.i ? r[n.i - 1] : null; + if (e) { + !(function (t) { + for (var n, e = 0, r = 0, i = t.children, o = i.length; --o >= 0; ) + (((n = i[o]).z += e), (n.m += e), (e += n.s + (r += n.c))); + })(n); + var o = (e[0].z + e[e.length - 1].z) / 2; + i ? ((n.z = i.z + t(n._, i._)), (n.m = n.z - o)) : (n.z = o); + } else i && (n.z = i.z + t(n._, i._)); + n.parent.A = (function (n, e, r) { + if (e) { + for ( + var i, + o = n, + a = n, + u = e, + c = o.parent.children[0], + f = o.m, + s = a.m, + l = u.m, + h = c.m; + (u = Rp(u)), (o = Dp(o)), u && o; + + ) + ((c = Dp(c)), + ((a = Rp(a)).a = n), + (i = u.z + l - o.z - f + t(u._, o._)) > 0 && + (Fp(qp(u, n, r), n, i), (f += i), (s += i)), + (l += u.m), + (f += o.m), + (h += c.m), + (s += a.m)); + (u && !Rp(a) && ((a.t = u), (a.m += l - s)), + o && !Dp(c) && ((c.t = o), (c.m += f - h), (r = n))); + } + return r; + })(n, i, n.parent.A || r[0]); + } + function a(t) { + ((t._.x = t.z + t.parent.m), (t.m += t.parent.m)); + } + function u(t) { + ((t.x *= n), (t.y = t.depth * e)); + } + return ( + (i.separation = function (n) { + return arguments.length ? ((t = n), i) : t; + }), + (i.size = function (t) { + return arguments.length + ? ((r = !1), (n = +t[0]), (e = +t[1]), i) + : r + ? null + : [n, e]; + }), + (i.nodeSize = function (t) { + return arguments.length + ? ((r = !0), (n = +t[0]), (e = +t[1]), i) + : r + ? [n, e] + : null; + }), + i + ); + }), + (t.treemap = function () { + var t = Yp, + n = !1, + e = 1, + r = 1, + i = [0], + o = np, + a = np, + u = np, + c = np, + f = np; + function s(t) { + return ( + (t.x0 = t.y0 = 0), + (t.x1 = e), + (t.y1 = r), + t.eachBefore(l), + (i = [0]), + n && t.eachBefore(Tp), + t + ); + } + function l(n) { + var e = i[n.depth], + r = n.x0 + e, + s = n.y0 + e, + l = n.x1 - e, + h = n.y1 - e; + (l < r && (r = l = (r + l) / 2), + h < s && (s = h = (s + h) / 2), + (n.x0 = r), + (n.y0 = s), + (n.x1 = l), + (n.y1 = h), + n.children && + ((e = i[n.depth + 1] = o(n) / 2), + (r += f(n) - e), + (s += a(n) - e), + (l -= u(n) - e) < r && (r = l = (r + l) / 2), + (h -= c(n) - e) < s && (s = h = (s + h) / 2), + t(n, r, s, l, h))); + } + return ( + (s.round = function (t) { + return arguments.length ? ((n = !!t), s) : n; + }), + (s.size = function (t) { + return arguments.length ? ((e = +t[0]), (r = +t[1]), s) : [e, r]; + }), + (s.tile = function (n) { + return arguments.length ? ((t = tp(n)), s) : t; + }), + (s.padding = function (t) { + return arguments.length + ? s.paddingInner(t).paddingOuter(t) + : s.paddingInner(); + }), + (s.paddingInner = function (t) { + return arguments.length + ? ((o = "function" == typeof t ? t : ep(+t)), s) + : o; + }), + (s.paddingOuter = function (t) { + return arguments.length + ? s.paddingTop(t).paddingRight(t).paddingBottom(t).paddingLeft(t) + : s.paddingTop(); + }), + (s.paddingTop = function (t) { + return arguments.length + ? ((a = "function" == typeof t ? t : ep(+t)), s) + : a; + }), + (s.paddingRight = function (t) { + return arguments.length + ? ((u = "function" == typeof t ? t : ep(+t)), s) + : u; + }), + (s.paddingBottom = function (t) { + return arguments.length + ? ((c = "function" == typeof t ? t : ep(+t)), s) + : c; + }), + (s.paddingLeft = function (t) { + return arguments.length + ? ((f = "function" == typeof t ? t : ep(+t)), s) + : f; + }), + s + ); + }), + (t.treemapBinary = function (t, n, e, r, i) { + var o, + a, + u = t.children, + c = u.length, + f = new Array(c + 1); + for (f[0] = a = o = 0; o < c; ++o) f[o + 1] = a += u[o].value; + !(function t(n, e, r, i, o, a, c) { + if (n >= e - 1) { + var s = u[n]; + return ((s.x0 = i), (s.y0 = o), (s.x1 = a), void (s.y1 = c)); + } + var l = f[n], + h = r / 2 + l, + d = n + 1, + p = e - 1; + for (; d < p; ) { + var g = (d + p) >>> 1; + f[g] < h ? (d = g + 1) : (p = g); + } + h - f[d - 1] < f[d] - h && n + 1 < d && --d; + var y = f[d] - l, + v = r - y; + if (a - i > c - o) { + var _ = r ? (i * v + a * y) / r : a; + (t(n, d, y, i, o, _, c), t(d, e, v, _, o, a, c)); + } else { + var b = r ? (o * v + c * y) / r : c; + (t(n, d, y, i, o, a, b), t(d, e, v, i, b, a, c)); + } + })(0, c, t.value, n, e, r, i); + }), + (t.treemapDice = Ap), + (t.treemapResquarify = Lp), + (t.treemapSlice = Ip), + (t.treemapSliceDice = function (t, n, e, r, i) { + (1 & t.depth ? Ip : Ap)(t, n, e, r, i); + }), + (t.treemapSquarify = Yp), + (t.tsv = Mc), + (t.tsvFormat = lc), + (t.tsvFormatBody = hc), + (t.tsvFormatRow = pc), + (t.tsvFormatRows = dc), + (t.tsvFormatValue = gc), + (t.tsvParse = fc), + (t.tsvParseRows = sc), + (t.union = function (...t) { + const n = new InternSet(); + for (const e of t) for (const t of e) n.add(t); + return n; + }), + (t.unixDay = _y), + (t.unixDays = by), + (t.utcDay = yy), + (t.utcDays = vy), + (t.utcFriday = By), + (t.utcFridays = Vy), + (t.utcHour = hy), + (t.utcHours = dy), + (t.utcMillisecond = Wg), + (t.utcMilliseconds = Zg), + (t.utcMinute = cy), + (t.utcMinutes = fy), + (t.utcMonday = qy), + (t.utcMondays = jy), + (t.utcMonth = Qy), + (t.utcMonths = Jy), + (t.utcSaturday = Yy), + (t.utcSaturdays = Wy), + (t.utcSecond = iy), + (t.utcSeconds = oy), + (t.utcSunday = Fy), + (t.utcSundays = Ly), + (t.utcThursday = Oy), + (t.utcThursdays = Gy), + (t.utcTickInterval = av), + (t.utcTicks = ov), + (t.utcTuesday = Uy), + (t.utcTuesdays = Hy), + (t.utcWednesday = Iy), + (t.utcWednesdays = Xy), + (t.utcWeek = Fy), + (t.utcWeeks = Ly), + (t.utcYear = ev), + (t.utcYears = rv), + (t.variance = x), + (t.version = "7.9.0"), + (t.window = pn), + (t.xml = Sc), + (t.zip = function () { + return gt(arguments); + }), + (t.zoom = function () { + var t, + n, + e, + r = Ew, + i = Nw, + o = zw, + a = Cw, + u = Pw, + c = [0, 1 / 0], + f = [ + [-1 / 0, -1 / 0], + [1 / 0, 1 / 0], + ], + s = 250, + l = ri, + h = $t("start", "zoom", "end"), + d = 500, + p = 150, + g = 0, + y = 10; + function v(t) { + t.property("__zoom", kw) + .on("wheel.zoom", T, { passive: !1 }) + .on("mousedown.zoom", A) + .on("dblclick.zoom", S) + .filter(u) + .on("touchstart.zoom", E) + .on("touchmove.zoom", N) + .on("touchend.zoom touchcancel.zoom", k) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + function _(t, n) { + return (n = Math.max(c[0], Math.min(c[1], n))) === t.k + ? t + : new ww(n, t.x, t.y); + } + function b(t, n, e) { + var r = n[0] - e[0] * t.k, + i = n[1] - e[1] * t.k; + return r === t.x && i === t.y ? t : new ww(t.k, r, i); + } + function m(t) { + return [(+t[0][0] + +t[1][0]) / 2, (+t[0][1] + +t[1][1]) / 2]; + } + function x(t, n, e, r) { + t.on("start.zoom", function () { + w(this, arguments).event(r).start(); + }) + .on("interrupt.zoom end.zoom", function () { + w(this, arguments).event(r).end(); + }) + .tween("zoom", function () { + var t = this, + o = arguments, + a = w(t, o).event(r), + u = i.apply(t, o), + c = null == e ? m(u) : "function" == typeof e ? e.apply(t, o) : e, + f = Math.max(u[1][0] - u[0][0], u[1][1] - u[0][1]), + s = t.__zoom, + h = "function" == typeof n ? n.apply(t, o) : n, + d = l(s.invert(c).concat(f / s.k), h.invert(c).concat(f / h.k)); + return function (t) { + if (1 === t) t = h; + else { + var n = d(t), + e = f / n[2]; + t = new ww(e, c[0] - n[0] * e, c[1] - n[1] * e); + } + a.zoom(null, t); + }; + }); + } + function w(t, n, e) { + return (!e && t.__zooming) || new M(t, n); + } + function M(t, n) { + ((this.that = t), + (this.args = n), + (this.active = 0), + (this.sourceEvent = null), + (this.extent = i.apply(t, n)), + (this.taps = 0)); + } + function T(t, ...n) { + if (r.apply(this, arguments)) { + var e = w(this, n).event(t), + i = this.__zoom, + u = Math.max( + c[0], + Math.min(c[1], i.k * Math.pow(2, a.apply(this, arguments))), + ), + s = ne(t); + if (e.wheel) + ((e.mouse[0][0] === s[0] && e.mouse[0][1] === s[1]) || + (e.mouse[1] = i.invert((e.mouse[0] = s))), + clearTimeout(e.wheel)); + else { + if (i.k === u) return; + ((e.mouse = [s, i.invert(s)]), Gi(this), e.start()); + } + (Sw(t), + (e.wheel = setTimeout(function () { + ((e.wheel = null), e.end()); + }, p)), + e.zoom( + "mouse", + o(b(_(i, u), e.mouse[0], e.mouse[1]), e.extent, f), + )); + } + } + function A(t, ...n) { + if (!e && r.apply(this, arguments)) { + var i = t.currentTarget, + a = w(this, n, !0).event(t), + u = Zn(t.view) + .on( + "mousemove.zoom", + function (t) { + if ((Sw(t), !a.moved)) { + var n = t.clientX - s, + e = t.clientY - l; + a.moved = n * n + e * e > g; + } + a.event(t).zoom( + "mouse", + o( + b(a.that.__zoom, (a.mouse[0] = ne(t, i)), a.mouse[1]), + a.extent, + f, + ), + ); + }, + !0, + ) + .on( + "mouseup.zoom", + function (t) { + (u.on("mousemove.zoom mouseup.zoom", null), + ue(t.view, a.moved), + Sw(t), + a.event(t).end()); + }, + !0, + ), + c = ne(t, i), + s = t.clientX, + l = t.clientY; + (ae(t.view), + Aw(t), + (a.mouse = [c, this.__zoom.invert(c)]), + Gi(this), + a.start()); + } + } + function S(t, ...n) { + if (r.apply(this, arguments)) { + var e = this.__zoom, + a = ne(t.changedTouches ? t.changedTouches[0] : t, this), + u = e.invert(a), + c = e.k * (t.shiftKey ? 0.5 : 2), + l = o(b(_(e, c), a, u), i.apply(this, n), f); + (Sw(t), + s > 0 + ? Zn(this).transition().duration(s).call(x, l, a, t) + : Zn(this).call(v.transform, l, a, t)); + } + } + function E(e, ...i) { + if (r.apply(this, arguments)) { + var o, + a, + u, + c, + f = e.touches, + s = f.length, + l = w(this, i, e.changedTouches.length === s).event(e); + for (Aw(e), a = 0; a < s; ++a) + ((c = [ + (c = ne((u = f[a]), this)), + this.__zoom.invert(c), + u.identifier, + ]), + l.touch0 + ? l.touch1 || + l.touch0[2] === c[2] || + ((l.touch1 = c), (l.taps = 0)) + : ((l.touch0 = c), (o = !0), (l.taps = 1 + !!t))); + (t && (t = clearTimeout(t)), + o && + (l.taps < 2 && + ((n = c[0]), + (t = setTimeout(function () { + t = null; + }, d))), + Gi(this), + l.start())); + } + } + function N(t, ...n) { + if (this.__zooming) { + var e, + r, + i, + a, + u = w(this, n).event(t), + c = t.changedTouches, + s = c.length; + for (Sw(t), e = 0; e < s; ++e) + ((i = ne((r = c[e]), this)), + u.touch0 && u.touch0[2] === r.identifier + ? (u.touch0[0] = i) + : u.touch1 && + u.touch1[2] === r.identifier && + (u.touch1[0] = i)); + if (((r = u.that.__zoom), u.touch1)) { + var l = u.touch0[0], + h = u.touch0[1], + d = u.touch1[0], + p = u.touch1[1], + g = (g = d[0] - l[0]) * g + (g = d[1] - l[1]) * g, + y = (y = p[0] - h[0]) * y + (y = p[1] - h[1]) * y; + ((r = _(r, Math.sqrt(g / y))), + (i = [(l[0] + d[0]) / 2, (l[1] + d[1]) / 2]), + (a = [(h[0] + p[0]) / 2, (h[1] + p[1]) / 2])); + } else { + if (!u.touch0) return; + ((i = u.touch0[0]), (a = u.touch0[1])); + } + u.zoom("touch", o(b(r, i, a), u.extent, f)); + } + } + function k(t, ...r) { + if (this.__zooming) { + var i, + o, + a = w(this, r).event(t), + u = t.changedTouches, + c = u.length; + for ( + Aw(t), + e && clearTimeout(e), + e = setTimeout(function () { + e = null; + }, d), + i = 0; + i < c; + ++i + ) + ((o = u[i]), + a.touch0 && a.touch0[2] === o.identifier + ? delete a.touch0 + : a.touch1 && a.touch1[2] === o.identifier && delete a.touch1); + if ( + (a.touch1 && !a.touch0 && ((a.touch0 = a.touch1), delete a.touch1), + a.touch0) + ) + a.touch0[1] = this.__zoom.invert(a.touch0[0]); + else if ( + (a.end(), + 2 === a.taps && + ((o = ne(o, this)), Math.hypot(n[0] - o[0], n[1] - o[1]) < y)) + ) { + var f = Zn(this).on("dblclick.zoom"); + f && f.apply(this, arguments); + } + } + } + return ( + (v.transform = function (t, n, e, r) { + var i = t.selection ? t.selection() : t; + (i.property("__zoom", kw), + t !== i + ? x(t, n, e, r) + : i.interrupt().each(function () { + w(this, arguments) + .event(r) + .start() + .zoom( + null, + "function" == typeof n ? n.apply(this, arguments) : n, + ) + .end(); + })); + }), + (v.scaleBy = function (t, n, e, r) { + v.scaleTo( + t, + function () { + return ( + this.__zoom.k * + ("function" == typeof n ? n.apply(this, arguments) : n) + ); + }, + e, + r, + ); + }), + (v.scaleTo = function (t, n, e, r) { + v.transform( + t, + function () { + var t = i.apply(this, arguments), + r = this.__zoom, + a = + null == e + ? m(t) + : "function" == typeof e + ? e.apply(this, arguments) + : e, + u = r.invert(a), + c = "function" == typeof n ? n.apply(this, arguments) : n; + return o(b(_(r, c), a, u), t, f); + }, + e, + r, + ); + }), + (v.translateBy = function (t, n, e, r) { + v.transform( + t, + function () { + return o( + this.__zoom.translate( + "function" == typeof n ? n.apply(this, arguments) : n, + "function" == typeof e ? e.apply(this, arguments) : e, + ), + i.apply(this, arguments), + f, + ); + }, + null, + r, + ); + }), + (v.translateTo = function (t, n, e, r, a) { + v.transform( + t, + function () { + var t = i.apply(this, arguments), + a = this.__zoom, + u = + null == r + ? m(t) + : "function" == typeof r + ? r.apply(this, arguments) + : r; + return o( + Mw.translate(u[0], u[1]) + .scale(a.k) + .translate( + "function" == typeof n ? -n.apply(this, arguments) : -n, + "function" == typeof e ? -e.apply(this, arguments) : -e, + ), + t, + f, + ); + }, + r, + a, + ); + }), + (M.prototype = { + event: function (t) { + return (t && (this.sourceEvent = t), this); + }, + start: function () { + return ( + 1 == ++this.active && + ((this.that.__zooming = this), this.emit("start")), + this + ); + }, + zoom: function (t, n) { + return ( + this.mouse && + "mouse" !== t && + (this.mouse[1] = n.invert(this.mouse[0])), + this.touch0 && + "touch" !== t && + (this.touch0[1] = n.invert(this.touch0[0])), + this.touch1 && + "touch" !== t && + (this.touch1[1] = n.invert(this.touch1[0])), + (this.that.__zoom = n), + this.emit("zoom"), + this + ); + }, + end: function () { + return ( + 0 == --this.active && + (delete this.that.__zooming, this.emit("end")), + this + ); + }, + emit: function (t) { + var n = Zn(this.that).datum(); + h.call( + t, + this.that, + new xw(t, { + sourceEvent: this.sourceEvent, + target: v, + type: t, + transform: this.that.__zoom, + dispatch: h, + }), + n, + ); + }, + }), + (v.wheelDelta = function (t) { + return arguments.length + ? ((a = "function" == typeof t ? t : mw(+t)), v) + : a; + }), + (v.filter = function (t) { + return arguments.length + ? ((r = "function" == typeof t ? t : mw(!!t)), v) + : r; + }), + (v.touchable = function (t) { + return arguments.length + ? ((u = "function" == typeof t ? t : mw(!!t)), v) + : u; + }), + (v.extent = function (t) { + return arguments.length + ? ((i = + "function" == typeof t + ? t + : mw([ + [+t[0][0], +t[0][1]], + [+t[1][0], +t[1][1]], + ])), + v) + : i; + }), + (v.scaleExtent = function (t) { + return arguments.length + ? ((c[0] = +t[0]), (c[1] = +t[1]), v) + : [c[0], c[1]]; + }), + (v.translateExtent = function (t) { + return arguments.length + ? ((f[0][0] = +t[0][0]), + (f[1][0] = +t[1][0]), + (f[0][1] = +t[0][1]), + (f[1][1] = +t[1][1]), + v) + : [ + [f[0][0], f[0][1]], + [f[1][0], f[1][1]], + ]; + }), + (v.constrain = function (t) { + return arguments.length ? ((o = t), v) : o; + }), + (v.duration = function (t) { + return arguments.length ? ((s = +t), v) : s; + }), + (v.interpolate = function (t) { + return arguments.length ? ((l = t), v) : l; + }), + (v.on = function () { + var t = h.on.apply(h, arguments); + return t === h ? v : t; + }), + (v.clickDistance = function (t) { + return arguments.length ? ((g = (t = +t) * t), v) : Math.sqrt(g); + }), + (v.tapDistance = function (t) { + return arguments.length ? ((y = +t), v) : y; + }), + v + ); + }), + (t.zoomIdentity = Mw), + (t.zoomTransform = Tw)); +}); diff --git a/static/nighttrains/map.css b/static/nighttrains/map.css new file mode 100644 index 000000000..762a34f53 --- /dev/null +++ b/static/nighttrains/map.css @@ -0,0 +1,192 @@ +@font-face { + font-family: 'Montserrat'; + src: url(https://back-on-track.eu/wp-content/fonts/montserrat/JTUSjIg1_i6t8kCHKm459WRhyzbi.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +#bot-map { + margin: 0; +} + +#bot-map text { + font-family: 'Montserrat', 'Arial', 'sans-serif'; +} + +#NIGHTTRAINS { + cursor: pointer; +} + +.zoomed #BORDERS, +.zoomed #CONTINENT, +.zoomed #GRID { + display: none; +} + +.zoomed #Rectangle-Background { + fill: #20456d; +} + +.traininfo-overlay { + position: fixed; + bottom: 0; + right: 0; + width: 100%; + margin: 0 !important; + + flex-flow: row nowrap; + align-items: center; + justify-content: center; + z-index: 1000; + + display: none; +} + +.traininfo-overlay.active { + display: flex; +} + +.traininfo-overlay .text-content { + width: 100%; + min-height: calc(100vh - 100vw * 1.44); + padding: 10px 10px 0 10px; + background: #fff; + z-index: 200; + overflow: scroll; + font-size: 12px; + line-height: 1.5; +} + +.traininfo-overlay h6 { + margin: 0; + font-size: 1.4em; +} + +.traininfo-overlay .buttons { + margin: 10px 0; +} + +.traininfo-overlay .buttons .button { + padding-top: 12px; + padding-bottom: 8px; + font-size: 12px; + line-height: 1; +} + +.traininfo-overlay .close { + position: absolute; + top: 6px; + right: 6px; + z-index: 2; + display: flex; + justify-content: space-between; + flex-direction: row-reverse; + gap: 10px; + margin: 0; +} + +.traininfo-overlay .details { + margin: 10px 0; +} + +.traininfo-overlay .details .button { + margin: 10px 0; +} + +.traininfo-overlay p { + margin: 0; +} + +.traininfo-overlay .row { + margin: 0; + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +.traininfo-overlay .column { + margin: 6px 0; + width: 100%; +} + +.traininfo-overlay .title { + font-size: 1.4em +} + +.traininfo-overlay .title .agency, +.traininfo-overlay .shortname { + font-weight: bold; + color: #2271b3; +} +.traininfo-overlay .itinerary { + padding-top: 1.5em; +} +.traininfo-overlay .note:not(:empty) { + margin-top: 10px; + color: #ee0000; +} + +.traininfo-overlay .trainlist p { + margin-bottom: 4px; +} + +.traininfo-overlay .trainlist a { + display: inline; +} + +.traininfo-overlay .miniline { + display: inline-block; + width: 24px; + height: 6px; + margin: 0 6px 1px 0; +} + +/* landscape format (e.g. desktop or rotated mobile) */ +@media (min-aspect-ratio: 1) { + .traininfo-overlay { + width: calc(min(33%, max(25%, 400px))); + height: 100%; + } + .traininfo-overlay .text-content { + height: 100%; + } + .traininfo-overlay h6 { + margin: 1.2em 0 0.6em 0; + } + .traininfo-overlay .close { + position: relative; + text-align: right; + margin: 0 -10px 0 0; + } + .traininfo-overlay .details { + width: 100%; + text-align: center; + } +} + +/* larger screen landscape format (e.g. desktop) */ +@media (min-aspect-ratio: 1) and (min-height: 600px) { + .traininfo-overlay .text-content { + padding: 20px; + font-size: 15px; + } + .traininfo-overlay .buttons .button { + font-size: 15px; + padding-top: 16px; + padding-bottom: 13px; + } + .traininfo-overlay .close { + margin: 0 -15px 0 0; + } + .traininfo-overlay .details { + margin: 2em 0 10px 0; + } + .traininfo-overlay p { + margin: 0.6em 0; + } + .traininfo-overlay .trainlist a { + display: block; + } + .traininfo-overlay .miniline { + margin-bottom: 2px; + } +} diff --git a/static/nighttrains/map.js b/static/nighttrains/map.js new file mode 100644 index 000000000..9223715f7 --- /dev/null +++ b/static/nighttrains/map.js @@ -0,0 +1,380 @@ +/* + * Javascript for the interactive features of the night train map + */ + +// This script assumes the existence of a variable map_i18n containing +// relevant translations. The variable is currently defined in a code +// snippet in the wordpress to allow adjusting translations from there. +// We define a fallback here to make it work standalone. +if (typeof map_i18n !== "object") { + var map_i18n = { + back: "Back", + close: "Close", + runs: "Runs", + details: "More Details", + selectline: "Select a line", + }; +} + +var map_div = document.querySelector("#bot-map"); +var map_svg = document.querySelector("#bot-map svg"); +var map_viewbox = map_svg.viewBox.baseVal; + +function handleZoom(e) { + d3.select("#bot-map > svg > g").attr("transform", e.transform); + if (e.transform.k > 2) { + map_svg.classList.add("zoomed"); + } else { + map_svg.classList.remove("zoomed"); + } +} + +let zoom = d3 + .zoom() + .scaleExtent([1, 16]) + .translateExtent([ + [0, 0], + [map_viewbox.width, map_viewbox.height], + ]) + .on("zoom", handleZoom); + +d3.select("#bot-map > svg") + .call(zoom) + .on("wheel.zoom", null) + .on("dblclick.zoom", null); + +function addOverlay(title_html, body_html, x_position = null) { + var html = '
'; + html += `${map_i18n.close}`; + if (last_clicked) { + html += `${map_i18n.back} `; + } + html += "
"; + html += "
" + title_html + "
"; + html += body_html; + + document.querySelector(".traininfo-overlay .text-content").innerHTML = html; + document.querySelector(".traininfo-overlay").classList.add("active"); + + // On wide screens, the overlay should be displayed on the right edge, + // unless the supplied x_position is too far right + // (on portrait format screens, the overlay is at the bottom anyways). + if (x_position) { + if (x_position < screen.width * 0.67) { + document.querySelector(".traininfo-overlay").style.right = "0"; + } else { + document.querySelector(".traininfo-overlay").style.right = "unset"; + } + } +} + +function removeOverlay() { + document.querySelector(".traininfo-overlay").classList.remove("active"); + removeHighlight(); +} + +function lastOverlay() { + removeHighlight(); + if (last_clicked) { + last_clicked_copy = last_clicked; + last_clicked = null; + if (last_clicked_copy.tagName) { + // it was a singe train! + onClickGenerator(last_clicked_copy.id); + } else if ("___" == last_clicked_copy.substr(0, 3)) { + // it was a list of trains! + showTrainListOverlay(last_clicked_copy.substr(3).split(",")); + } else { + console.log( + "Unknown value " + last_clicked_copy + " of variable last_clicked.", + ); + } + } else { + removeOverlay(); + } +} + +function getStrokeColor(id) { + el = document.getElementById(`#${id}#`); + stroke = el.getAttribute("stroke"); + if (!stroke || stroke == "none") { + if (el.children.length > 0) stroke = el.children[0].getAttribute("stroke"); + } + if (!stroke || stroke == "none") { + stroke = "#a0a0a0"; + } + return stroke; +} + +function showSingleTrainOverlay(id, x_position = null) { + removeHighlight(); + el = document.getElementById(`#${id}#`); + el.style.stroke = "white"; + el.style.strokeWidth = "2px"; + highlighted.push(el); + if (el.children.length > 0) { + var childs = el.children; + for (var i = 0; i < childs.length; i++) { + childs[i].style.stroke = "white"; + childs[i].style.strokeWidth = "2px"; + highlighted.push(childs[i]); + } + } + + const title = + `` + + `${view_ontd_map[id].agency_id} ` + + `${view_ontd_map[id].route_long_name}`; + const stroke = getStrokeColor(id); + + const text = ` +
+ +
+

+ +${view_ontd_map[id].trip_short_name_0} +

+

+${view_ontd_map[id].origin_trip_0} (${view_ontd_map[id].origin_departure_time_0}) - ${view_ontd_map[id].via_0} - ${view_ontd_map[id].destination_trip_0} (${view_ontd_map[id].destination_arrival_time_0}) +

+

${map_i18n.runs}: ${view_ontd_map[id].service_id_0}

+

${view_ontd_map[id].irregularities_0}

+
+ +
+

+ +${view_ontd_map[id].trip_short_name_1} +

+

+${view_ontd_map[id].origin_trip_1} (${view_ontd_map[id].origin_departure_time_1}) - ${view_ontd_map[id].via_1} - ${view_ontd_map[id].destination_trip_1} (${view_ontd_map[id].destination_arrival_time_1}) +

+

${map_i18n.runs}: ${view_ontd_map[id].service_id_1}

+

${view_ontd_map[id].irregularities_1}

+
+ +
+ +
+ +
+ `; + + if (!x_position) { + x_position = el.getBoundingClientRect().right; + } + addOverlay(title, text, x_position); +} + +function showTrainListOverlay(ids, x_position = null) { + removeHighlight(); + ids = [...new Set(ids)]; // make unique + last_clicked_string = "___" + ids.join(","); + + const title = `${map_i18n.selectline}`; + + // we want to sort by strings of the form ORIGIN – DESTINATION + var header_sort = ids.map(function (id) { + const start_end = [ + view_ontd_map[id].origin_trip_0, + view_ontd_map[id].destination_trip_0, + ].sort(); + return { id, text: `${start_end[0]} – ${start_end[1]}` }; + }); + header_sort.sort((a, b) => (a.text > b.text ? 1 : -1)); + var text = '
'; + for (const h_s of header_sort) { + id = h_s.id; + const stroke = getStrokeColor(id); + text += '

'; + text += ``; + text += ``; + text += `${h_s.text}`; + text += + ` ${view_ontd_map[id].agency_id} ` + + `${view_ontd_map[id].trip_short_name_0} + ` + + `${view_ontd_map[id].trip_short_name_1}`; + if (view_ontd_map[id].route_long_name) + text += ` "${view_ontd_map[id].route_long_name}"`; + text += "

"; + } + text += "
"; + + addOverlay(title, text, x_position); +} + +function removeHighlight() { + for (const hl of highlighted) { + hl.style.filter = "unset"; + hl.style.removeProperty("stroke"); + hl.style.removeProperty("stroke-width"); + } + highlighted = []; +} + +function get_view_ontd_map() { + //getting routes sheet from the bot-backend + var xmlhttp = new XMLHttpRequest(); + xmlhttp.onreadystatechange = function () { + if (this.readyState == 4 && this.status == 200) { + view_ontd_map = JSON.parse(this.responseText); + const ids = Object.keys(view_ontd_map); + for (const id of ids) { + //add route prefix-suffix so it doesn't get muddled up with other element ids + routeId = `#${id}#`; + const el = document.getElementById(routeId); + if (el) { + el.addEventListener("mouseenter", onMouseEnterGenerator(id)); + el.addEventListener("mouseleave", onMouseLeaveGenerator(id)); + el.addEventListener("click", onClickGenerator(id)); + } + //else{console.log(`couldn't find id ${id}`);} + } + } + }; + //use this to get data directly from the spreadsheet - not recommended... + //const url = "https://script.google.com/macros/s/AKfycbwY9zNQFq0urCHsTstWRKxLe0SstWrwyY04tSuDIVb_yRCtTs_HDlRARS-5fqltgEZr/exec?table=view_ontd_map" + //... from github - possible, but not what we want... + //const url = "https://back-on-track-eu.github.io/night-train-data/data/latest/view_ontd_map.json"; + // from the webspace (synchronised by our custom wordpress plugin) + const url = "/nighttrains/view_ontd_map.json"; + // from somewhere local + //const url = "../view_ontd_map.json"; + xmlhttp.open("GET", url, true); + xmlhttp.send(); +} + +var view_ontd_map = get_view_ontd_map(); + +var last_clicked = null; +var highlighted = []; + +const urlParams = new URLSearchParams(window.location.search); +var preset_route_id = urlParams.get("route_id"); +if (preset_route_id) { + preset_route_id = preset_route_id.replace(/[^0-9]/g, ""); + setTimeout(function () { + // We scroll to the path. In the future, we could also zoom on mobile. + preset_route_path = document.getElementById("#" + preset_route_id + "#"); + preset_route_box = preset_route_path.getBoundingClientRect(); + scroll_to_y = + preset_route_box.top + + preset_route_box.height / 2 - + map_div.getBoundingClientRect().top - + window.innerHeight / 2; + window.scrollTo(0, scroll_to_y); + onClickGenerator(preset_route_id)(new Event("click")); + }, 1500); +} + +map_svg.addEventListener("click", (event) => { + event.preventDefault(); + // To debug the touch action on a desktop, you may want to uncomment the + // following, and comment out the .on("wheel.zoom", null) further above. + if (event.pointerType === "mouse") { + removeOverlay(); + return; + } + var map_divrect = map_div.getBoundingClientRect(); + // get the transformation of the current zoom and pan state + var transform = d3.zoomTransform(d3.select("#bot-map svg").node()); + var pointer_x = event.clientX; + var pointer_y = event.clientY; + if (pointer_x === undefined || pointer_y === undefined) { + pointer_x = event.pageX - window.scrollX; + pointer_y = event.pageY - window.scrollY; + } + x_before = + ((pointer_x - map_divrect.left) / map_divrect.width) * map_viewbox.width; + y_before = + ((pointer_y - map_divrect.top) / map_divrect.height) * map_viewbox.height; + [x_touch, y_touch] = transform.invert([x_before, y_before]); + paths = document.querySelectorAll("#NIGHTTRAINS path"); + var path_ids = []; + for (const path of paths) { + // get the coord transformation matrix for the path's coords + var ctm = path.getScreenCTM().inverse().multiply(map_svg.getScreenCTM()); + var l = 0; + // traverse each path and compare distances to the touch point + while (l < path.getTotalLength()) { + // we need to apply two coordinate transformations, + // one for the path, and one for the current d3 zoom and pan state + var point = path.getPointAtLength(l).matrixTransform(ctm.inverse()); + var [x_point, y_point] = transform.invert([point.x, point.y]); + if ( + Math.abs(x_point - x_touch) < 12 && + Math.abs(y_point - y_touch) < 12 + ) { + // this path is nearby the touch location! + path_ids.push(path.id); + break; + } + l += 10; + } + } + console.log(x_touch + " " + y_touch + " - nearby: " + path_ids.join(", ")); + if (path_ids.length > 0) { + // get route_ids from path_ids + var valid_ids = new Set(Object.keys(view_ontd_map)); + path_ids = path_ids.map((x) => { + x_nohash = x.replaceAll("#", ""); + el = document.getElementById(x); + while (!valid_ids.has(x_nohash)) { + if (el === null || x === "NIGHTTRAINS" || el.tagName === "svg") { + console.log( + '"' + + x + + '" does not give rise to a valid route id, nor does any of its parents.', + ); + return null; // give up + } + el = el.parentElement; + x_nohash = el.id.replaceAll("#", ""); + } + return x_nohash; + }); + route_ids = path_ids.filter(Number); // remove NULLs + + if (route_ids.length == 1) { + showSingleTrainOverlay(route_ids[0]); + } + if (route_ids.length > 1) { + showTrainListOverlay(route_ids, event.pageX); + } + } else { + removeOverlay(); + } +}); + +function onMouseEnterGenerator(id) { + return function onMouseEnter(event) { + const { currentTarget: el } = event; + el.style.filter = "drop-shadow(0 0 1.4px white)"; + }; +} + +function onMouseLeaveGenerator(id) { + return function onMouseLeave(event) { + const { currentTarget: el } = event; + if (el !== last_clicked) { + el.style.filter = "unset"; + } + }; +} + +function onClickGenerator(id, last = null) { + return function onClick(event) { + event.preventDefault(); + + if (last) { + last_clicked = last; + } + showSingleTrainOverlay(id); + + // prevent the immediate closing of the tooltip by the click action of the map_svg + if (event.stopPropagation) event.stopPropagation(); + }; +} diff --git a/static/nighttrains/map.svg b/static/nighttrains/map.svg new file mode 100644 index 000000000..d630c9499 --- /dev/null +++ b/static/nighttrains/map.svg @@ -0,0 +1,1820 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + zssk.sk + + + vy.no + + + vr.fi + + + uz.gov.ua + + + urlaubs- + express.de + + + nachtexpress.de + + + trenitalia.com + + + ebilet.tcddtasimacilik.gov.tr + + + sncf-connect.com + + + rodalies.gencat.cat + + + elron.ee + + + ltglink.lt + + + vivi.lv + + + snalltaget.se + + + sleeper.scot + + + sj.no + + + sj.se + + + zcg-prevoz.me + + + regiojet.com + + + intercity.pl + + + optimatours.de + + + nightjet.com + + + nightjet.com + + + jegy.mav.hu + + + hzpp.hr + + + gwr.com + + + go-aheadnordic.no + + + europeansleeper.eu + + + cfrcalatori.ro + + + cd.cz + + + bdz.bg + + + astratranscarpatic.ro + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + London + + + Inverness + Inbhir Nis + + + Glasgow + + + Fort William + An Gearasdan + + + Penzance + + + Edinburgh + + + Birmingham + + + Aberdeen + + + Запоріжжя + + Zaporizhzhia + + + + + Ясіня + + Yasynya + + + + + + Ужгород + + Uzhhorod + + + + + + Трускавець + + Truskavets + + + + Суми + + Sumy + + + + + + Солотвино + Solotvyno + + + + + + Рахів + + Rakhiv + + + + Полтава + + Poltava + + + Одеса + + Odesa + + + + Миколаїв + + Mykolaiv + + + + + + + Львів + + Lviv + + + + + Київ + + Kyiv + + + + Кривий Ріг + Kryvyi Rih + + + + Ковель + + Kovel + + + + + Харків + + Kharkiv + + + + + + Кам'янець-Подільський + + Kamianets-Podilskyi + + + + Лозова + + Lozova + + + + + Івано-Франківськ + Ivano-Frankivsk + + + + Дніпро + + Dnipro + + + Чернігів + + Chernihiv + + + + Чернівці + + Chernivtsi + + + + + Черкаси + + Cherkasy + + + + Чоп + + Chop + + + Konya + + + İzmir + + + İstanbul + + + Edirne + + + Ankara + + + Humenné + + + Košice + + + + + Bratislava + + + + + Koper + + + + Malmö + + + Stockholm + + + Duved + + + Storlien + + + Umeå + + + Luleå + + + Санкт + - + Петербург + Sankt-Peterburg + + + + Москва + Moskva + + + + Београд + + Beograd + + + Vatra Dornei + + + Timișoara + + + Suceava + + + + + Satu Mare + + + + Oradea + + + Mangalia + + + Iași + + + + + Curtici + + + + Constanța + + + + + Cluj-Napoca + + + + București + + + Brașov + + + Bistrița + + + Arad + + + Zakopane + + + Warszawa + + + + Świnoujście + + + Szczecin + + + + + Szklarska Poręba + + + + Jelenia Góra + + + Przemyśl + + + Łeba + + + + + Kraków + + + + Kołobrzeg + + + Hel + + + Gdynia + + + Chelm + + + + + + Bielsko- + Biała + + + + + Trondheim + + + Stavanger + + + Oslo + + + Bodø + + + Bergen + + + Amsterdam + + + Bar + + + Chișinău + + + طرابلس + + + Ṭarābulus + + + + + + Milano + + + + Roma + + + Salerno + + + Palermo + + + Siracusa + + + Reggio di Calabria + + + Lecce + + + + + Torino + + + + + + Trieste + + + + Venezia + + + + + Innichen + San Candido + + + + Bolzano + Bozen + + + + Zagreb + + + Osijek + + + Vukovar + + + Split + + + + + Rijeka + + + + + + Budapest + + + + Toulouse + + + Tarbes + + + Rodez + + + Paris + + + Nice + + + Lyon + + + Latour-de-Carol + La Tor de Querol + + + Cerbère + Cervera de la Marenda + + + Albi + + + Briançon + + + Aurillac + + + Turku + Åbo + + + Kolari + + + Rovaniemi + + + Kemijärvi + + + Helsinki + Helsingfors + + + Αθήνα + + Athína + + + الإسكندرية + + + Al-Iskandarīyah + + + + Barcelona + + + Madrid + + + الجزائر + Al-Jazāʾir + + + + وهران + Wahrān + + + + Rīga + + + + + Stuttgart + + + + + + München + + + + Hamburg + + + Düsseldorf + + + Berlin + + + Praha + + + Zürich + + + Мінск + Minsk + + + + София + + Sofia + + + Варна + + Varna + + + + + Силистра + + Silistra + + + + Добрич + + Dobrich + + + Бургас + + Burgas + + + Bruxelles + Brussel + + + Wien + + + Bregenz + + + Lörrach + + + Villach + + + Innsbruck + + + + + Graz + + + + + + + + + Plymouth + + + + Crewe + + + + + Preston + + + + Carlisle + + + + Dundee + + + + Eskişehir + + + + Balıkesir + + + + + + Ljubljana + + + + + Sundsvall + + + + Östersund + + + + Helsingborg + + + + + Hässleholm + + + + Göteborg + + + + Gävle + + + + Ploiești + + + + + + Deva + + + Sighișoara + + + Sibiu + + + + + + Craiova + + + + + Baia Mare + + + + + Wrocław + + + + Poznań + + + + + + Katowice + + + + + Gdańsk + + + + Taranto + + + + Brindisi + + + + Bari + + + + Napoli + + + + Livorno + + + + Genova + + + + + + Firenze + + + + + Bologna + + + + Podgorica + + + + + København + + + + Rotterdam + + + Tampere + + + + Oulu + + + + + Toulon + + + Pau + + + + Montpellier + + + + + + Perpignan + Perpinyà + + + + + Marseille + + + + Bayonne + Baiona + + + + + Nürnberg + + + + Leipzig + + + + + + + Karlsruhe + + + + + Hannover + + + + + + Frankfurt + am Main + + + + + Dresden + + + + Köln + + + + Bremen + + + + Ostrava + + + + Brno + + + + Basel + + + + Русе + + Ruse + + + + Antwerpen + + + + + Salzburg + + + + + + Linz + + + + + + + + Interrail/Eurail + + + + + + important seat-only connections + + + + important ferry connections + + + + seasonal, non-daily + + + + seasonal only + + + + closing this year + + + + (re)opening this year (hopefully) + + + + 1-2 days a week + + + + 3-5 days a week + + + + 6-7 days a week + + + + + + + + diff --git a/static/nighttrains/view_ontd_map.json b/static/nighttrains/view_ontd_map.json new file mode 100644 index 000000000..b3503a233 --- /dev/null +++ b/static/nighttrains/view_ontd_map.json @@ -0,0 +1,4512 @@ +{ + "1": { + "route_id": 1, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 468", + "service_id_0": "2026: Mon, Wed, Fri", + "trip_short_name_1": "NJ 469", + "service_id_1": "2026: Tue, Thu, Sun", + "route_long_name": "", + "origin_trip_0": "Wien Hbf", + "origin_departure_time_0": "18:08", + "via_0": "Wien Meidling - St. Pölten Hbf - Linz Hbf - Salzburg Hbf - Rosenheim - München Ost - Koblenz Hbf - Bonn Hbf - Köln Ehrenfeld - Aachen Hbf - Liège Guillemins \/ Luik Guillemins - Bruxelles Noord \/ Brussel Nord - Bruxelles Noord \/ Brussel Nord", + "destination_trip_0": "Bruxelles Midi \/ Brussel Zuid", + "destination_arrival_time_0": "09:56", + "origin_trip_1": "Bruxelles Midi \/ Brussel Zuid", + "origin_departure_time_1": "19:06", + "via_1": "Bruxelles Noord \/ Brussel Nord - Liège Guillemins \/ Luik Guillemins - Aachen Hbf - Köln Hbf - Bonn-Beuel - Koblenz Hbf - München Ost - Rosenheim - Salzburg Hbf - Linz Hbf - St. Pölten Hbf - Wien Meidling", + "destination_trip_1": "Wien Hbf", + "destination_arrival_time_1": "10:13", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "2": { + "route_id": 2, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 408", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 409", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Berlin Hbf", + "origin_departure_time_0": "20:48", + "via_0": "Berlin Südkreuz - Lutherstadt Wittenberg Hbf - Bitterfeld - Halle (Saale) Hbf - Leipzig Hbf - Mannheim Hbf - Karlsruhe Hbf - Baden-Baden - Offenburg - Freiburg (Breisgau) Hbf - Basel Bad Bf - Basel SBB", + "destination_trip_0": "Zürich HB", + "destination_arrival_time_0": "09:05", + "origin_trip_1": "Zürich HB", + "origin_departure_time_1": "19:59", + "via_1": "Basel SBB - Basel Bad Bf - Freiburg (Breisgau) Hbf - Offenburg - Karlsruhe Hbf - Mannheim Hbf - Leipzig Hbf - Berlin Südkreuz", + "destination_trip_1": "Berlin Hbf", + "destination_arrival_time_1": "07:22", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "3": { + "route_id": 3, + "agency_id": "HŽPP", + "trip_short_name_0": "1820", + "service_id_0": "2026\/06\/22-08\/30: Daily", + "trip_short_name_1": "1821", + "service_id_1": "2026\/06\/22-08\/30: Daily", + "route_long_name": "", + "origin_trip_0": "Split", + "origin_departure_time_0": "21:03", + "via_0": "Knin - Gospić - Karlovac", + "destination_trip_0": "Zagreb Gl. K.", + "destination_arrival_time_0": "05:47", + "origin_trip_1": "Zagreb Gl. K.", + "origin_departure_time_1": "22:06", + "via_1": "Karlovac - Gospić - Knin", + "destination_trip_1": "Split", + "destination_arrival_time_1": "06:53", + "picture": "", + "irregularities_0": "Runs Sundays outside the summer window 2026\/06\/22-08\/30", + "irregularities_1": "Runs Fridays outside the summer window 2026\/06\/22-08\/30" + }, + "5": { + "route_id": 5, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 470", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 471", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Zürich HB", + "origin_departure_time_0": "20:59", + "via_0": "Basel SBB - Basel Bad Bf - Freiburg (Breisgau) Hbf - Offenburg - Baden-Baden - Karlsruhe Hbf - Bruchsal - Heidelberg Hbf - Darmstadt Hbf - Frankfurt (Main) Süd - Hanau Hbf - Göttingen - Hannover Hbf - Bremen Hbf - Hamburg Harburg", + "destination_trip_0": "Hamburg Hbf", + "destination_arrival_time_0": "08:00", + "origin_trip_1": "Hamburg Hbf", + "origin_departure_time_1": "21:44", + "via_1": "non-stop - Hamburg Harburg - Bremen Hbf - Hannover Hbf - Göttingen - Hanau Hbf - Frankfurt (Main) Süd - Karlsruhe Hbf - Offenburg - Freiburg (Breisgau) Hbf - Basel Bad Bf - Basel SBB", + "destination_trip_1": "Zürich HB", + "destination_arrival_time_1": "10:05", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "6": { + "route_id": 6, + "agency_id": "ČD", + "trip_short_name_0": "EN 442", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 443", + "service_id_1": "2026: Daily", + "route_long_name": "Slovakia", + "origin_trip_0": "Humenné", + "origin_departure_time_0": "19:31", + "via_0": "Strážske - Michalovce - Bánovce nad Ondavou - Trebišov - Košice - Kysak - Margecany - Spišská Nová Ves - Poprad Tatry - Liptovský Mikuláš - Ružomberok - Ružomberok - Olomouc hl.n. - Česká Třebová - Pardubice hl.n.", + "destination_trip_0": "Praha hl.n.", + "destination_arrival_time_0": "07:46", + "origin_trip_1": "Praha hl.n.", + "origin_departure_time_1": "22:16", + "via_1": "Kolín - Pardubice hl.n. - Česká Třebová - Olomouc hl.n. - Kraľovany - Ružomberok - Liptovský Mikuláš - Štrba - Poprad Tatry - Spišská Nová Ves - Margecany - Kysak - Kysak - Trebišov - Bánovce nad Ondavou - Michalovce - Strážske", + "destination_trip_1": "Humenné", + "destination_arrival_time_1": "10:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "7": { + "route_id": 7, + "agency_id": "RJ", + "trip_short_name_0": "1020", + "service_id_0": "2026: Daily", + "trip_short_name_1": "1021", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Chop", + "origin_departure_time_0": "17:35", + "via_0": "Košice - Poprad Tatry - Pardubice hl.n.", + "destination_trip_0": "Praha hl.n.", + "destination_arrival_time_0": "05:46", + "origin_trip_1": "Praha hl.n.", + "origin_departure_time_1": "21:52", + "via_1": "Pardubice hl.n. - Ostrava hl.n. - Poprad Tatry - Košice", + "destination_trip_1": "Chop", + "destination_arrival_time_1": "10:38", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "8": { + "route_id": 8, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "EN 50443", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 417\/EN 442", + "service_id_1": "2026: Daily", + "route_long_name": "Carpathia", + "origin_trip_0": "Praha hl.n.", + "origin_departure_time_0": "22:16", + "via_0": "Pardubice hl.n. - Olomouc hl.n. - Ostrava hl.n. - Gliwice - Zabrze - Katowice - Mysłowice - Jaworzno Szczakowa - Trzebinia - Krzeszowice - Kraków Gł. - Tarnow - Tarnow - Rzeszow Gł. - Przeworsk - Jarosław", + "destination_trip_0": "Przemyśl Gł.", + "destination_arrival_time_0": "10:11", + "origin_trip_1": "Przemyśl Gł.", + "origin_departure_time_1": "17:51", + "via_1": "Jarosław - Przeworsk - Rzeszow Gł. - Dębica - Tarnow - Kraków Gł. - Krzeszowice - Trzebinia - Jaworzno Szczakowa - Katowice - Zabrze - Gliwice - Gliwice - Olomouc hl.n. - Pardubice hl.n.", + "destination_trip_1": "Praha hl.n.", + "destination_arrival_time_1": "07:26", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "9": { + "route_id": 9, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "EN 443 \/ IC 406", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 407 \/ EN 442", + "service_id_1": "2026: Daily", + "route_long_name": "Slovakia \/ Chopin", + "origin_trip_0": "Praha hl.n.", + "origin_departure_time_0": "22:16", + "via_0": "Pardubice hl.n. - Olomouc hl.n. - Katowice - Zawiercie - Opoczno Południe - Warszawa Centralna", + "destination_trip_0": "Warszawa Wschodnia", + "destination_arrival_time_0": "08:15", + "origin_trip_1": "Warszawa Wschodnia", + "origin_departure_time_1": "19:05", + "via_1": "Warszawa Centralna - Opoczno Południe - Zawiercie - Katowice - Rybnik - Olomouc hl.n. - Pardubice hl.n.", + "destination_trip_1": "Praha hl.n.", + "destination_arrival_time_1": "07:26", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "10": { + "route_id": 10, + "agency_id": "PKP", + "trip_short_name_0": "TLK 35190\/50191", + "service_id_0": "2026\/06\/26-08\/30: Daily", + "trip_short_name_1": "TLK 55190\/53190", + "service_id_1": "2026\/06\/27-08\/31: Daily", + "route_long_name": "Korsarz", + "origin_trip_0": "Kraków Gł.", + "origin_departure_time_0": "20:14", + "via_0": "Trzebinia - Gdańsk Gł. - Gdynia Gł.", + "destination_trip_0": "Hel", + "destination_arrival_time_0": "08:02", + "origin_trip_1": "Hel", + "origin_departure_time_1": "21:12", + "via_1": "Gdynia Gł. - Gdańsk Gł. - Trzebinia", + "destination_trip_1": "Kraków Gł.", + "destination_arrival_time_1": "08:51", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "11": { + "route_id": 11, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1837", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1838", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Iași", + "origin_departure_time_0": "21:40", + "via_0": "Suceava - Dej Călători", + "destination_trip_0": "Cluj-Napoca", + "destination_arrival_time_0": "06:24", + "origin_trip_1": "Cluj-Napoca", + "origin_departure_time_1": "21:18", + "via_1": "Dej Călători - Suceava", + "destination_trip_1": "Iași", + "destination_arrival_time_1": "05:55", + "picture": "", + "irregularities_0": "currently suspended due to construction works", + "irregularities_1": "currently suspended due to construction works" + }, + "12": { + "route_id": 12, + "agency_id": "CFR", + "trip_short_name_0": "IC 472", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 473", + "service_id_1": "2026: Daily", + "route_long_name": "Ister", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "18:24", + "via_0": "Ploiești Vest - Brașov - Sibiu - Arad - Curtici - Szolnok", + "destination_trip_0": "Budapest Keleti", + "destination_arrival_time_0": "08:50", + "origin_trip_1": "Budapest Keleti", + "origin_departure_time_1": "19:10", + "via_1": "Szolnok - Mezőtúr - Gyoma - Csárdaszállás - Mezőberény - Murony - Békéscsaba - Kétegyháza - Lőkösháza - Curtici - Arad - Sebeș Alba - Sibiu - Făgăraș - Codlea - Brașov - Predeal - Azuga - Bușteni - Sinaia - Câmpina - Ploiești Vest", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "10:37", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "13": { + "route_id": 13, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1952", + "service_id_0": "2024\/06\/14-2024\/09\/07: Daily", + "trip_short_name_1": "IRN 1954\/R 8824", + "service_id_1": "2026\/06\/13-2026\/09\/06: Daily", + "route_long_name": "", + "origin_trip_0": "Suceava Nord", + "origin_departure_time_0": "20:15", + "via_0": "Suceava - Bacău - Buzău - Constanța", + "destination_trip_0": "Mangalia", + "destination_arrival_time_0": "05:25", + "origin_trip_1": "Mangalia", + "origin_departure_time_1": "21:50", + "via_1": "Constanța - Fetești - Buzău - Bacău - Suceava", + "destination_trip_1": "Suceava Nord", + "destination_arrival_time_1": "07:07", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "14": { + "route_id": 14, + "agency_id": "CFR", + "trip_short_name_0": "IRN 472\/IRN 1743", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1744\/IRN 79", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "18:24", + "via_0": "Brașov - Sibiu - Arad", + "destination_trip_0": "Oradea", + "destination_arrival_time_0": "07:56", + "origin_trip_1": "Oradea", + "origin_departure_time_1": "17:25", + "via_1": "Arad - Timişoara Nord - Craiova", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "08:23", + "picture": "", + "irregularities_0": "runs through Sibiu", + "irregularities_1": "runs through Craiova" + }, + "15": { + "route_id": 15, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1763", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1765", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Iași", + "origin_departure_time_0": "15:35", + "via_0": "Suceava - Câmpulung Moldovenesc - Vatra Dornei - Beclean pe Somes - Dej - Cluj-Napoca - Deva - Arad", + "destination_trip_0": "Timişoara Nord", + "destination_arrival_time_0": "09:08", + "origin_trip_1": "Timişoara Nord", + "origin_departure_time_1": "14:51", + "via_1": "Arad - Deva - Alba Iulia - Cluj-Napoca - Dej - Beclean pe Somes - Câmpulung Moldovenesc - Suceava", + "destination_trip_1": "Iași", + "destination_arrival_time_1": "07:46", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "16": { + "route_id": 16, + "agency_id": "CFR\/MÁV", + "trip_short_name_0": "IRN \/ IC 78", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN \/ IC 79", + "service_id_1": "2026: Daily", + "route_long_name": "Muntenia", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "21:19", + "via_0": "Craiova - Timişoara Nord - Arad - Curtici - Lőkösháza - Szolnok", + "destination_trip_0": "Budapest Keleti", + "destination_arrival_time_0": "12:50", + "origin_trip_1": "Budapest Keleti", + "origin_departure_time_1": "15:10", + "via_1": "Szolnok - Lőkösháza - Curtici - Arad - Timişoara Nord - Craiova", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "08:23", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "17": { + "route_id": 17, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 498", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 499", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Wien Hbf", + "origin_departure_time_0": "19:36", + "via_0": "Wien Meidling - St. Pölten Hbf - Linz Hbf - Passau Hbf - Regensburg Hbf - Nürnberg Hbf - Würzburg Hbf - Kassel-Wilhelmshöhe - Göttingen - Hannover Hbf - Hamburg Harburg", + "destination_trip_0": "Hamburg Hbf", + "destination_arrival_time_0": "09:08", + "origin_trip_1": "Hamburg Hbf", + "origin_departure_time_1": "19:19", + "via_1": "Hamburg Harburg - Hannover Hbf - Göttingen - Kassel-Wilhelmshöhe - Würzburg Hbf - Nürnberg Hbf - Regensburg Hbf - Passau Hbf - Wels Hbf - Linz Hbf - St. Pölten Hbf - Wien Meidling", + "destination_trip_1": "Wien Hbf", + "destination_arrival_time_1": "09:48", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "18": { + "route_id": 18, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 40420", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 40491", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Innsbruck Hbf", + "origin_departure_time_0": "20:46", + "via_0": "Jenbach - Wörgl Hbf - Kufstein - Rosenheim - München Ost - Ingolstadt Hbf - Nürnberg Hbf - Würzburg Hbf - Kassel-Wilhelmshöhe - Göttingen - Hannover Hbf - Hamburg Harburg", + "destination_trip_0": "Hamburg Hbf", + "destination_arrival_time_0": "09:08", + "origin_trip_1": "Hamburg Hbf", + "origin_departure_time_1": "19:19", + "via_1": "Hamburg Harburg - Hannover Hbf - Göttingen - Kassel-Wilhelmshöhe - Würzburg Hbf - Nürnberg Hbf - Ingolstadt Hbf - München Ost - Rosenheim - Kufstein - Wörgl Hbf - Jenbach", + "destination_trip_1": "Innsbruck Hbf", + "destination_arrival_time_1": "08:49", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "19": { + "route_id": 19, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1659", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1658", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "22:20", + "via_0": "Ploiești Sud - Suceava - Câmpulung Moldovenesc - Vatra Dornei", + "destination_trip_0": "Vatra Dornei Băi", + "destination_arrival_time_0": "07:30", + "origin_trip_1": "Vatra Dornei Băi", + "origin_departure_time_1": "20:10", + "via_1": "Vatra Dornei - Câmpulung Moldovenesc - Suceava - Ploiești Sud", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "05:35", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "20": { + "route_id": 20, + "agency_id": "CFR", + "trip_short_name_0": "IRN 12641", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 12642", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "21:20", + "via_0": "Ploiești Vest - Câmpina - Brașov - Miercurea Ciuc - Beclean pe Somes - Baia Mare", + "destination_trip_0": "Satu Mare", + "destination_arrival_time_0": "11:09", + "origin_trip_1": "Satu Mare", + "origin_departure_time_1": "16:30", + "via_1": "Baia Mare - Beclean pe Somes - Miercurea Ciuc - Brașov - Câmpina - Ploiești Vest", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "06:22", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "21": { + "route_id": 21, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1821", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1822", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "23:30", + "via_0": "Craiova - Petroșani - Deva", + "destination_trip_0": "Arad", + "destination_arrival_time_0": "11:06", + "origin_trip_1": "Arad", + "origin_departure_time_1": "17:30", + "via_1": "Deva - Petroșani - Craiova", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "05:11", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "22": { + "route_id": 22, + "agency_id": "CFM\/CFR", + "trip_short_name_0": "401", + "service_id_0": "2026: Daily", + "trip_short_name_1": "402", + "service_id_1": "2026: Daily", + "route_long_name": "Prietenia", + "origin_trip_0": "Chişinău", + "origin_departure_time_0": "16:50", + "via_0": "Ungheni - Ungheni-Prut - Nicolina - Iași - Târgu Frumos - Roman - Buzău - Mizil - Ploiești Sud", + "destination_trip_0": "București Nord", + "destination_arrival_time_0": "06:38", + "origin_trip_1": "București Nord", + "origin_departure_time_1": "19:06", + "via_1": "Ploiești Sud - Mizil - Buzău - Râmnicu Sărat - Focșani - Mărășești - Adjud - Bacău - Roman - Târgu Frumos - Ungheni-Prut - Ungheni", + "destination_trip_1": "Chişinău", + "destination_arrival_time_1": "08:44", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "23": { + "route_id": 23, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1669", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1668", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "22:55", + "via_0": "Ploiești Sud - Buzău", + "destination_trip_0": "Iași", + "destination_arrival_time_0": "05:35", + "origin_trip_1": "Iași", + "origin_departure_time_1": "22:45", + "via_1": "Vaslui - Bârlad", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "05:18", + "picture": "", + "irregularities_0": "Mid-June until early September from Constanța (dep 22:17)", + "irregularities_1": "Mid-June until early September to Constanța (arr 07:13)" + }, + "24": { + "route_id": 24, + "agency_id": "ATC", + "trip_short_name_0": "IR 11501", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IR 11500", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "19:28", + "via_0": "Videle - Roșiori Nord - Caracal - Craiova - Caransebeș - Lugoj - Timişoara Nord", + "destination_trip_0": "Arad", + "destination_arrival_time_0": "08:15", + "origin_trip_1": "Arad", + "origin_departure_time_1": "19:05", + "via_1": "Timişoara Nord - Lugoj - Caransebeș - Craiova - Caracal - Roșiori Nord - Videle", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "07:29", + "picture": "", + "irregularities_0": "Extends to Constanta from 2026\/06\/11 to 09\/06 as IRN 11504, arrives in Constanta at 10:06", + "irregularities_1": "Extends to Constanta from 2026\/06\/11 to 09\/07 as IRN 11502, leaves Constanta at 16:49" + }, + "25": { + "route_id": 25, + "agency_id": "CFR", + "trip_short_name_0": "IRN 12941", + "service_id_0": "2024\/06\/14-2024\/09\/07: Daily", + "trip_short_name_1": "IRN 12942\/R 8810", + "service_id_1": "2026\/06\/13-2026\/09\/06: Daily", + "route_long_name": "", + "origin_trip_0": "Satu Mare", + "origin_departure_time_0": "13:20", + "via_0": "Baia Mare - Dej - Beclean pe Somes - Deda - Gheorgheni - Siculeni - Buzău - Constanța", + "destination_trip_0": "Mangalia", + "destination_arrival_time_0": "09:28", + "origin_trip_1": "Mangalia", + "origin_departure_time_1": "15:18", + "via_1": "Constanța - Buzău - Mărășești - Brașov - Siculeni - Deda - Dej - Baia Mare", + "destination_trip_1": "Satu Mare", + "destination_arrival_time_1": "10:45", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "26": { + "route_id": 26, + "agency_id": "CFR", + "trip_short_name_0": "IRN 1920", + "service_id_0": "2026\/06\/11-09\/06: Daily", + "trip_short_name_1": "IRN 1922", + "service_id_1": "2026\/06\/11-09\/06: Daily", + "route_long_name": "", + "origin_trip_0": "Constanța", + "origin_departure_time_0": "18:43", + "via_0": "Medgidia - Fetești - București Nord - Videle - Roșiori Nord - Caracal - Craiova - Petroșani - Subcetate - Simeria - Deva - Ilia - Arad - Chișineu-Criș", + "destination_trip_0": "Oradea", + "destination_arrival_time_0": "12:40", + "origin_trip_1": "Oradea", + "origin_departure_time_1": "14:20", + "via_1": "Chișineu-Criș - Arad - Ilia - Deva - Simeria - Subcetate - Petroșani - Târgu Jiu - Craiova - Caracal - Roșiori Nord - Videle - București Nord - Fetești - Medgidia", + "destination_trip_1": "Constanța", + "destination_arrival_time_1": "08:31", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "27": { + "route_id": 27, + "agency_id": "TCDD\/BDŽ", + "trip_short_name_0": "12503\/492", + "service_id_0": "2026: Daily", + "trip_short_name_1": "493\/12504", + "service_id_1": "2026: Daily", + "route_long_name": "Balkan Express", + "origin_trip_0": "İstanbul Halkalı", + "origin_departure_time_0": "20:00", + "via_0": "Edirne - Kapıkule - Svilengrad - Dimitrovgrad - Plovdiv", + "destination_trip_0": "Sofia", + "destination_arrival_time_0": "11:48", + "origin_trip_1": "Sofia", + "origin_departure_time_1": "18:50", + "via_1": "Plovdiv - Dimitrovgrad - Svilengrad - Kapıkule - Edirne", + "destination_trip_1": "İstanbul Halkalı", + "destination_arrival_time_1": "09:56", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "28": { + "route_id": 28, + "agency_id": "TCDD\/BDŽ\/CFR", + "trip_short_name_0": "12503\/460", + "service_id_0": "2026\/06\/11-10\/09: Daily", + "trip_short_name_1": "461\/12504", + "service_id_1": "2026\/06\/13-10\/12: Daily", + "route_long_name": "Bosphor Express", + "origin_trip_0": "İstanbul Halkalı", + "origin_departure_time_0": "20:00", + "via_0": "Edirne - Kapıkule - Svilengrad - Dimitrovgrad - Stara Zagora - Veliko Tarnovo - Gorna Oryahovitsa - Ruse - Giurgiu Nord", + "destination_trip_0": "București Nord", + "destination_arrival_time_0": "16:56", + "origin_trip_1": "București Nord", + "origin_departure_time_1": "10:46", + "via_1": "Giurgiu Nord - Ruse - Gorna Oryahovitsa - Veliko Tarnovo - Stara Zagora - Dimitrovgrad - Svilengrad - Kapıkule - Edirne", + "destination_trip_1": "İstanbul Halkalı", + "destination_arrival_time_1": "09:56", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "30": { + "route_id": 30, + "agency_id": "TCDD", + "trip_short_name_0": "22006", + "service_id_0": "2026: Daily", + "trip_short_name_1": "32005", + "service_id_1": "2026: Daily", + "route_long_name": "Izmir Mavi", + "origin_trip_0": "Ankara", + "origin_departure_time_0": "20:00", + "via_0": "Eskişehir - Balıkesir - Manisa - İzmir Çiğli", + "destination_trip_0": "İzmir Basmane", + "destination_arrival_time_0": "10:01", + "origin_trip_1": "İzmir Basmane", + "origin_departure_time_1": "19:05", + "via_1": "İzmir Çiğli - Manisa - Balıkesir - Eskişehir", + "destination_trip_1": "Ankara", + "destination_arrival_time_1": "09:07", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "31": { + "route_id": 31, + "agency_id": "TCDD", + "trip_short_name_0": "22001", + "service_id_0": "2026: Daily", + "trip_short_name_1": "12002", + "service_id_1": "2026: Daily", + "route_long_name": "Ankara Ekspresi", + "origin_trip_0": "Ankara", + "origin_departure_time_0": "22:00", + "via_0": "Eskişehir - İstanbul Pendik - İstanbul Sögütlücesme", + "destination_trip_0": "İstanbul Halkalı", + "destination_arrival_time_0": "07:27", + "origin_trip_1": "İstanbul Halkalı", + "origin_departure_time_1": "22:00", + "via_1": "İstanbul Sögütlücesme - İstanbul Pendik - İzmit", + "destination_trip_1": "Ankara", + "destination_arrival_time_1": "06:37", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "37": { + "route_id": 37, + "agency_id": "CS", + "trip_short_name_0": "1003 (G)", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "1004 (G)", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "Lowlander", + "origin_trip_0": "London Euston", + "origin_departure_time_0": "23:45", + "via_0": "Watford Junction - Carlisle - Motherwell", + "destination_trip_0": "Glasgow Central", + "destination_arrival_time_0": "07:30", + "origin_trip_1": "Glasgow Central", + "origin_departure_time_1": "23:40", + "via_1": "Motherwell - Carlisle - Watford Junction", + "destination_trip_1": "London Euston", + "destination_arrival_time_1": "07:15", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_CS_Lowland.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "38": { + "route_id": 38, + "agency_id": "CS", + "trip_short_name_0": "1003 (E)", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "1004 (E)", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "Lowlander", + "origin_trip_0": "London Euston", + "origin_departure_time_0": "23:45", + "via_0": "Watford Junction - Carlisle", + "destination_trip_0": "Edinburgh Waverley", + "destination_arrival_time_0": "07:30", + "origin_trip_1": "Edinburgh Waverley", + "origin_departure_time_1": "23:40", + "via_1": "Carlisle - Watford Junction", + "destination_trip_1": "London Euston", + "destination_arrival_time_1": "07:15", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_CS_Lowland.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "39": { + "route_id": 39, + "agency_id": "CS", + "trip_short_name_0": "1001 (A)", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "1002 (A)", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "Highlander", + "origin_trip_0": "London Euston", + "origin_departure_time_0": "21:15", + "via_0": "Birmingham International - Crewe - Preston - Dundee", + "destination_trip_0": "Aberdeen", + "destination_arrival_time_0": "07:40", + "origin_trip_1": "Aberdeen", + "origin_departure_time_1": "21:43", + "via_1": "Dundee - Preston - Crewe - Birmingham International ", + "destination_trip_1": "London Euston", + "destination_arrival_time_1": "08:00", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_CS_Highlands.jpeg", + "irregularities_0": "Stops in Birminham Intl from 2026-01-15", + "irregularities_1": "Stops in Birminham Intl from 2026-01-15" + }, + "40": { + "route_id": 40, + "agency_id": "CS", + "trip_short_name_0": "1001 (FW)", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "1002 (FW)", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "Highlander", + "origin_trip_0": "London Euston", + "origin_departure_time_0": "21:15", + "via_0": "Birmingham International - Crewe - Preston - Crianlarich", + "destination_trip_0": "Fort William \/ An Gearasdan", + "destination_arrival_time_0": "10:00", + "origin_trip_1": "Fort William \/ An Gearasdan", + "origin_departure_time_1": "19:50", + "via_1": "Crianlarich - Preston - Crewe - Birmingham International ", + "destination_trip_1": "London Euston", + "destination_arrival_time_1": "08:00", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_CS_Highlands.jpeg", + "irregularities_0": "Stops in Birminham Intl from 2026-01-15", + "irregularities_1": "Stops in Birminham Intl from 2026-01-15" + }, + "41": { + "route_id": 41, + "agency_id": "CS", + "trip_short_name_0": "1001 (I)", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "1002 (I)", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "Highlander", + "origin_trip_0": "London Euston", + "origin_departure_time_0": "21:15", + "via_0": "Birmingham International - Crewe - Preston - Stirling - Perth \/ Peairt - Aviemore", + "destination_trip_0": "Inverness \/ Inbhir Nis", + "destination_arrival_time_0": "08:45", + "origin_trip_1": "Inverness \/ Inbhir Nis", + "origin_departure_time_1": "20:45", + "via_1": "Aviemore - Perth \/ Peairt - Stirling - Preston - Crewe - Birmingham International ", + "destination_trip_1": "London Euston", + "destination_arrival_time_1": "08:00", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_CS_Highlands.jpeg", + "irregularities_0": "Stops in Birminham Intl from 2026-01-15", + "irregularities_1": "Stops in Birminham Intl from 2026-01-15" + }, + "42": { + "route_id": 42, + "agency_id": "GWR", + "trip_short_name_0": "Sleeper (Penzance)", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "Sleeper (London)", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "Night Riviera", + "origin_trip_0": "London Paddington", + "origin_departure_time_0": "23:45", + "via_0": "Reading - Plymouth", + "destination_trip_0": "Penzance", + "destination_arrival_time_0": "07:50", + "origin_trip_1": "Penzance", + "origin_departure_time_1": "21:45", + "via_1": "Plymouth - Reading", + "destination_trip_1": "London Paddington", + "destination_arrival_time_1": "05:08", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_GWR.jpeg", + "irregularities_0": "", + "irregularities_1": "Departs 30 minutes earlier on Sundays" + }, + "44": { + "route_id": 44, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 402", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 403", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Zürich HB", + "origin_departure_time_0": "21:59", + "via_0": "Basel SBB - Basel Bad Bf - Freiburg (Breisgau) Hbf - Offenburg - Bonn Hbf - Köln Hbf - Düsseldorf Hbf - Duisburg Hbf - Oberhausen Hbf - Arnhem Centraal - Utrecht Centraal", + "destination_trip_0": "Amsterdam Centraal", + "destination_arrival_time_0": "08:59", + "origin_trip_1": "Amsterdam Centraal", + "origin_departure_time_1": "21:01", + "via_1": "Utrecht Centraal - Arnhem Centraal - Oberhausen Hbf - Duisburg Hbf - Düsseldorf Hbf - Köln Hbf - Bonn Hbf - Offenburg - Freiburg (Breisgau) Hbf - Basel Bad Bf - Basel SBB", + "destination_trip_1": "Zürich HB", + "destination_arrival_time_1": "08:05", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "Times may vary", + "irregularities_1": "Times may vary" + }, + "45": { + "route_id": 45, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 420", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 421", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Innsbruck Hbf", + "origin_departure_time_0": "20:46", + "via_0": "Jenbach - Wörgl Hbf - Kufstein - Rosenheim - München Ost - Ingolstadt Hbf - Nürnberg Hbf - Würzburg Hbf - Kassel-Wilhelmshöhe - Essen Hbf - Oberhausen Hbf - Arnhem Centraal - Utrecht Centraal", + "destination_trip_0": "Amsterdam Centraal", + "destination_arrival_time_0": "09:59", + "origin_trip_1": "Amsterdam Centraal", + "origin_departure_time_1": "18:59", + "via_1": "Amersfoort Centraal - Deventer - Münster (Westf) Hbf - Hamm (Westf) Hbf - Kassel-Wilhelmshöhe - Würzburg Hbf - Nürnberg Hbf - Ingolstadt Hbf - München Ost - Rosenheim - Kufstein - Wörgl Hbf - Jenbach", + "destination_trip_1": "Innsbruck Hbf", + "destination_arrival_time_1": "08:49", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "46": { + "route_id": 46, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 40421", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 40490", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Amsterdam Centraal", + "origin_departure_time_0": "18:01", + "via_0": "Utrecht Centraal - Arnhem Centraal - Oberhausen Hbf - Essen Hbf - Kassel-Wilhelmshöhe - Würzburg Hbf - Nürnberg Hbf - München Ost - Salzburg Hbf - Linz Hbf - St. Pölten Hbf - Wien Meidling", + "destination_trip_0": "Wien Hbf", + "destination_arrival_time_0": "09:48", + "origin_trip_1": "Wien Hbf", + "origin_departure_time_1": "18:36", + "via_1": "Wien Meidling - St. Pölten Hbf - Linz Hbf - Salzburg Hbf - München Ost - Nürnberg Hbf - Würzburg Hbf - Oberhausen Hbf - Arnhem Centraal - Utrecht Centraal", + "destination_trip_1": "Amsterdam Centraal", + "destination_arrival_time_1": "09:59", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "48": { + "route_id": 48, + "agency_id": "HŽPP", + "trip_short_name_0": "1880", + "service_id_0": "2026\/06\/22-08\/30: Daily", + "trip_short_name_1": "1881", + "service_id_1": "2026\/06\/22-08\/30: Daily", + "route_long_name": "Dalmacija", + "origin_trip_0": "Osijek", + "origin_departure_time_0": "18:44", + "via_0": "Bjelovar - Zagreb Gl. K. - Karlovac - Knin", + "destination_trip_0": "Split", + "destination_arrival_time_0": "08:49", + "origin_trip_1": "Split", + "origin_departure_time_1": "21:37", + "via_1": "Knin - Karlovac - Zagreb Gl. K. - Bjelovar", + "destination_trip_1": "Osijek", + "destination_arrival_time_1": "12:15", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "49": { + "route_id": 49, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 294", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 295", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Roma Tiburtina", + "origin_departure_time_0": "18:10", + "via_0": "Firenze Campo di Marte - Bologna Centrale - Tarvisio Boscoverde - Villach Hbf - Schwarzach-St.Veit - Salzburg Hbf - Rosenheim", + "destination_trip_0": "München Hbf", + "destination_arrival_time_0": "09:33", + "origin_trip_1": "München Hbf", + "origin_departure_time_1": "20:10", + "via_1": "Rosenheim - Salzburg Hbf - Villach Hbf - Bologna Centrale - Firenze S. M. N. - Tarvisio Boscoverde - Bologna Centrale - Firenze Campo di Marte", + "destination_trip_1": "Roma Tiburtina", + "destination_arrival_time_1": "09:10", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "50": { + "route_id": 50, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 456", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 457", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Graz Hbf", + "origin_departure_time_0": "19:21", + "via_0": "Bruck an der Mur - Mürzzuschlag - Wiener Neustadt Hbf - Wien Meidling - Wien Hbf - Břeclav - Brno hl.n. - Pardubice hl.n. - Praha hl.n. - Praha-Holešovice - Ústí nad Labem hl.n. - Děčín hl.n. - Bad Schandau - Dresden Hbf - Dresden Neustadt - Berlin Südkreuz", + "destination_trip_0": "Berlin Hbf", + "destination_arrival_time_0": "07:46", + "origin_trip_1": "Berlin Hbf", + "origin_departure_time_1": "18:06", + "via_1": "Berlin Südkreuz - Dresden Neustadt - Dresden Hbf - Bad Schandau - Děčín hl.n. - Ústí nad Labem hl.n. - Praha-Holešovice - Praha hl.n. - Pardubice hl.n. - Brno hl.n. - Břeclav - Wien Hbf - Wien Meidling - Bruck an der Mur", + "destination_trip_1": "Graz Hbf", + "destination_arrival_time_1": "09:19", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "53": { + "route_id": 53, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 236", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 237", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Venezia Santa Lucia", + "origin_departure_time_0": "21:05", + "via_0": "Venezia Mestre - Treviso Centrale - Conegliano - Pordenone - Udine - Tarvisio Boscoverde - Villach Hbf - Salzburg Hbf - Rosenheim - München Ost - Augsburg Hbf - Ulm Hbf - Göppingen", + "destination_trip_0": "Stuttgart Hbf", + "destination_arrival_time_0": "08:38", + "origin_trip_1": "Stuttgart Hbf", + "origin_departure_time_1": "20:29", + "via_1": "Göppingen - Ulm Hbf - Augsburg Hbf - München Ost - Rosenheim - Salzburg Hbf - Villach Hbf - Tarvisio Boscoverde - Udine - Pordenone - Conegliano - Treviso Centrale - Venezia Mestre", + "destination_trip_1": "Venezia Santa Lucia", + "destination_arrival_time_1": "08:34", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "54": { + "route_id": 54, + "agency_id": "MÁV\/ÖBB", + "trip_short_name_0": "EN 50237", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 50462", + "service_id_1": "2026: Daily", + "route_long_name": "Kálman Imre", + "origin_trip_0": "Budapest Keleti", + "origin_departure_time_0": "20:30", + "via_0": "Budapest Kelenföld - Győr - Wien Hbf - Wien Meidling - St. Pölten Hbf - Linz Hbf - Rosenheim - München Ost - Augsburg Hbf - Ulm Hbf", + "destination_trip_0": "Stuttgart Hbf", + "destination_arrival_time_0": "08:38", + "origin_trip_1": "Stuttgart Hbf", + "origin_departure_time_1": "20:29", + "via_1": "Ulm Hbf - Augsburg Hbf - München Ost - Salzburg Hbf - Linz Hbf - St. Pölten Hbf - Wien Meidling - Wien Hbf - Győr - Budapest Kelenföld", + "destination_trip_1": "Budapest Keleti", + "destination_arrival_time_1": "09:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "57": { + "route_id": 57, + "agency_id": "HŽPP\/ÖBB", + "trip_short_name_0": "EN 414", + "service_id_0": "Daily", + "trip_short_name_1": "EN 40237", + "service_id_1": "Daily", + "route_long_name": "", + "origin_trip_0": "Zagreb Gl. K.", + "origin_departure_time_0": "19:39", + "via_0": "Ljubljana - Villach Hbf - Rosenheim - München Ost - Augsburg Hbf - Ulm Hbf", + "destination_trip_0": "Stuttgart Hbf", + "destination_arrival_time_0": "08:43", + "origin_trip_1": "Stuttgart Hbf", + "origin_departure_time_1": "20:29", + "via_1": "Ulm Hbf - Augsburg Hbf - München Ost - Rosenheim - Villach Hbf - Ljubljana", + "destination_trip_1": "Zagreb Gl. K.", + "destination_arrival_time_1": "10:30", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_hzpp_en.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "58": { + "route_id": 58, + "agency_id": "MÁV", + "trip_short_name_0": "EN 40457", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 40476", + "service_id_1": "2026: Daily", + "route_long_name": "Metropol", + "origin_trip_0": "Berlin Hbf", + "origin_departure_time_0": "20:11", + "via_0": "Berlin Südkreuz - Dresden Neustadt - Dresden Hbf - Ústí nad Labem hl.n. - Praha hl.n. - Brno hl.n. - Bratislava hl.st. - Vac", + "destination_trip_0": "Budapest Nyugati", + "destination_arrival_time_0": "08:29", + "origin_trip_1": "Budapest Nyugati", + "origin_departure_time_1": "19:30", + "via_1": "Vac - Bratislava hl.st. - Brno hl.n. - Praha hl.n. - Dresden Hbf - Dresden Neustadt - Berlin Südkreuz", + "destination_trip_1": "Berlin Hbf", + "destination_arrival_time_1": "07:41", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "59": { + "route_id": 59, + "agency_id": "CFR\/MÁV\/ÖBB", + "trip_short_name_0": "D 346", + "service_id_0": "2026: Daily", + "trip_short_name_1": "D 347", + "service_id_1": "2026: Daily", + "route_long_name": "Dacia", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "16:00", + "via_0": "Ploiești Vest - Brașov - Sighișoara - Mediaș - Kőbánya-Kispest - Budapest Kelenföld - Győr", + "destination_trip_0": "Wien Hbf", + "destination_arrival_time_0": "08:53", + "origin_trip_1": "Wien Hbf", + "origin_departure_time_1": "19:08", + "via_1": "Győr - Budapest Kelenföld - Kőbánya-Kispest - Arad - Alba Iulia - Sighișoara - Brașov - Ploiești Vest", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "13:38", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "60": { + "route_id": 60, + "agency_id": "UZ\/ÖBB", + "trip_short_name_0": "40149", + "service_id_0": "2026: Daily", + "trip_short_name_1": "40749", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Wien Westbf", + "origin_departure_time_0": "18:30", + "via_0": "Wien Meidling - Wien Hbf - Hegyeshalom - Győr - Budapest Kelenföld - Cegléd - Szolnok - Debrecen - Nyíregyháza - Chop - Mukacheve - Stryj - Lviv", + "destination_trip_0": "Kyiv Pasazhyrskyi", + "destination_arrival_time_0": "17:44", + "origin_trip_1": "Kyiv Pasazhyrskyi", + "origin_departure_time_1": "12:33", + "via_1": "Lviv - Stryj - Mukacheve - Chop - Záhony - Nyíregyháza - Debrecen - Szolnok - Cegléd - Budapest Kelenföld - Győr - Hegyeshalom - Hegyeshalom", + "destination_trip_1": "Wien Westbf", + "destination_arrival_time_1": "08:53", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "62": { + "route_id": 62, + "agency_id": "SJ", + "trip_short_name_0": "1", + "service_id_0": "2026: Daily", + "trip_short_name_1": "2", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Stockholm C", + "origin_departure_time_0": "23:17", + "via_0": "Norrköping C - Hässleholm C - Helsingborg C - Lund C", + "destination_trip_0": "Malmö C", + "destination_arrival_time_0": "06:59", + "origin_trip_1": "Malmö C", + "origin_departure_time_1": "22:17", + "via_1": "Lund C - Helsingborg C - Hässleholm C", + "destination_trip_1": "Stockholm C", + "destination_arrival_time_1": "06:00", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_SJ.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "63": { + "route_id": 63, + "agency_id": "SJ", + "trip_short_name_0": "70", + "service_id_0": "2026: Daily", + "trip_short_name_1": "71", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Stockholm C", + "origin_departure_time_0": "22:40", + "via_0": "Arlanda - Uppsala C - Gävle C - Bräcke - Östersund C - Järpen - Åre", + "destination_trip_0": "Duved", + "destination_arrival_time_0": "08:17", + "origin_trip_1": "Duved", + "origin_departure_time_1": "19:30", + "via_1": "Åre - Järpen - Östersund C - Bräcke - Bollnäs - Uppsala C - Arlanda", + "destination_trip_1": "Stockholm C", + "destination_arrival_time_1": "05:05", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_SJ.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "65": { + "route_id": 65, + "agency_id": "GA", + "trip_short_name_0": "F5 725", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "F5 726", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "F5", + "origin_trip_0": "Oslo S", + "origin_departure_time_0": "22:25", + "via_0": "Drammen - Kongsberg - Sandnes", + "destination_trip_0": "Stavanger", + "destination_arrival_time_0": "07:21", + "origin_trip_1": "Stavanger", + "origin_departure_time_1": "22:15", + "via_1": "Sandnes - Kongsberg - Drammen", + "destination_trip_1": "Oslo S", + "destination_arrival_time_1": "07:25", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "67": { + "route_id": 67, + "agency_id": "CFR\/MÁV", + "trip_short_name_0": "IC 406", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 407", + "service_id_1": "2026: Daily", + "route_long_name": "Corona", + "origin_trip_0": "Brașov", + "origin_departure_time_0": "18:59", + "via_0": "Miercurea Ciuc - Gheorgheni - Deda - Beclean pe Somes - Debrecen - Szolnok", + "destination_trip_0": "Budapest Keleti", + "destination_arrival_time_0": "09:20", + "origin_trip_1": "Budapest Keleti", + "origin_departure_time_1": "17:40", + "via_1": "Debrecen - Carei - Deda - Gheorgheni - Miercurea Ciuc", + "destination_trip_1": "Brașov", + "destination_arrival_time_1": "09:15", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "68": { + "route_id": 68, + "agency_id": "VR", + "trip_short_name_0": "IC 264", + "service_id_0": "2026: Sat", + "trip_short_name_1": "IC 267", + "service_id_1": "2026: Fri", + "route_long_name": "", + "origin_trip_0": "Rovaniemi", + "origin_departure_time_0": "16:46", + "via_0": "Kemi - Oulu \/ Uleåborg - Ylivieska - Kokkola \/ Karleby - Tampere - Toijala - Riihimäki", + "destination_trip_0": "Helsinki \/ Helsingfors", + "destination_arrival_time_0": "07:08", + "origin_trip_1": "Helsinki \/ Helsingfors", + "origin_departure_time_1": "21:19", + "via_1": "Riihimäki - Toijala - Tampere - Kokkola \/ Karleby - Ylivieska - Oulu \/ Uleåborg - Kemi", + "destination_trip_1": "Rovaniemi", + "destination_arrival_time_1": "09:58", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "69": { + "route_id": 69, + "agency_id": "VY", + "trip_short_name_0": "605", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "606", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "F4", + "origin_trip_0": "Oslo S", + "origin_departure_time_0": "23:03", + "via_0": "Sandvika - Asker - Drammen - Hokksund - Myrdal - Dale", + "destination_trip_0": "Bergen", + "destination_arrival_time_0": "06:23", + "origin_trip_1": "Bergen", + "origin_departure_time_1": "23:01", + "via_1": "Dale - Myrdal - Hokksund - Drammen - Asker - Sandvika", + "destination_trip_1": "Oslo S", + "destination_arrival_time_1": "06:27", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "70": { + "route_id": 70, + "agency_id": "SJN", + "trip_short_name_0": "405", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "406", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "F6", + "origin_trip_0": "Oslo S", + "origin_departure_time_0": "22:49", + "via_0": "Hamar - Lillehammer", + "destination_trip_0": "Trondheim S", + "destination_arrival_time_0": "06:40", + "origin_trip_1": "Trondheim S", + "origin_departure_time_1": "23:17", + "via_1": "Lillehammer - Hamar", + "destination_trip_1": "Oslo S", + "destination_arrival_time_1": "06:58", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "71": { + "route_id": 71, + "agency_id": "SJN", + "trip_short_name_0": "475", + "service_id_0": "2026: Daily, except Sat", + "trip_short_name_1": "476", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "F7", + "origin_trip_0": "Trondheim S", + "origin_departure_time_0": "23:05", + "via_0": "Levanger - Steinkjer - Mo i Rana", + "destination_trip_0": "Bodø", + "destination_arrival_time_0": "09:05", + "origin_trip_1": "Bodø", + "origin_departure_time_1": "21:09", + "via_1": "Mo i Rana - Steinkjer - Levanger", + "destination_trip_1": "Trondheim S", + "destination_arrival_time_1": "07:15", + "picture": "", + "irregularities_0": "Suspended until June 2026 (accident)", + "irregularities_1": "Suspended until June 2026 (accident)" + }, + "72": { + "route_id": 72, + "agency_id": "VR", + "trip_short_name_0": "IC 265", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 274", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Helsinki \/ Helsingfors", + "origin_departure_time_0": "19:29", + "via_0": "Riihimäki - Tampere - Seinäjoki - Oulu \/ Uleåborg - Kemi - Rovaniemi", + "destination_trip_0": "Kemijärvi", + "destination_arrival_time_0": "08:50", + "origin_trip_1": "Kemijärvi", + "origin_departure_time_1": "19:00", + "via_1": "Rovaniemi - Kemi - Oulu \/ Uleåborg - Seinäjoki - Tampere - Riihimäki - Riihimäki", + "destination_trip_1": "Helsinki \/ Helsingfors", + "destination_arrival_time_1": "09:15", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_VR_New.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "73": { + "route_id": 73, + "agency_id": "ST", + "trip_short_name_0": "304", + "service_id_0": "2026\/07\/04-08\/01: Sat", + "trip_short_name_1": "305", + "service_id_1": "2026\/07\/03-07\/31: Fri", + "route_long_name": "", + "origin_trip_0": "Innsbruck Hbf", + "origin_departure_time_0": "18:00", + "via_0": "Jenbach - Kitzbühel - Zell am See - Salzburg Hbf - München Ost - Hamburg Hbf - Kolding - Odense - København Syd", + "destination_trip_0": "Malmö C", + "destination_arrival_time_0": "14:30", + "origin_trip_1": "Malmö C", + "origin_departure_time_1": "15:50", + "via_1": "København Syd - Odense - Kolding - Hamburg Hbf - München Ost - Salzburg Hbf - Zell am See - Kitzbühel - Jenbach", + "destination_trip_1": "Innsbruck Hbf", + "destination_arrival_time_1": "13:02", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_ST.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "74": { + "route_id": 74, + "agency_id": "MÁV\/ÖBB", + "trip_short_name_0": "EN 40462", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 40467", + "service_id_1": "2026: Daily", + "route_long_name": "Kálmán Imre", + "origin_trip_0": "Budapest Keleti", + "origin_departure_time_0": "20:30", + "via_0": "Budapest Kelenföld - Győr - Wien Hbf - Wien Meidling - St. Pölten Hbf - Linz Hbf - Bludenz - Feldkirch - Buchs (SG)", + "destination_trip_0": "Zürich HB", + "destination_arrival_time_0": "08:20", + "origin_trip_1": "Zürich HB", + "origin_departure_time_1": "21:40", + "via_1": "Buchs (SG) - Feldkirch - Bludenz - Linz Hbf - St. Pölten Hbf - Wien Meidling - Wien Hbf - Győr - Budapest Kelenföld", + "destination_trip_1": "Budapest Keleti", + "destination_arrival_time_1": "09:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "76": { + "route_id": 76, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 758", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 765", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Lecce", + "origin_departure_time_0": "19:41", + "via_0": "Brindisi - Taranto - Bari Centrale - Foggia - Bologna Centrale", + "destination_trip_0": "Milano Centrale", + "destination_arrival_time_0": "07:05", + "origin_trip_1": "Milano Centrale", + "origin_departure_time_1": "21:15", + "via_1": "Bologna Centrale - Foggia", + "destination_trip_1": "Lecce", + "destination_arrival_time_1": "07:00", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "77": { + "route_id": 77, + "agency_id": "ST", + "trip_short_name_0": "300", + "service_id_0": "2026\/03\/27-11\/01: Daily, except Saturday", + "trip_short_name_1": "301", + "service_id_1": "2026\/03\/27-11\/01: Daily, except Saturday", + "route_long_name": "Berlinaren", + "origin_trip_0": "Stockholm C", + "origin_departure_time_0": "16:20", + "via_0": "Södertälje syd övre - Linköping C - Nässjö C - Alvesta - Hässleholm C - Lund C - Malmö C - København Syd - Hamburg Hbf", + "destination_trip_0": "Berlin Hbf", + "destination_arrival_time_0": "08:35", + "origin_trip_1": "Berlin Hbf", + "origin_departure_time_1": "21:09", + "via_1": "Hamburg Hbf - København Syd - Malmö C - Lund C - Hässleholm C - Alvesta - Nässjö C - Linköping C - Norrköping C - Södertälje syd övre", + "destination_trip_1": "Stockholm C", + "destination_arrival_time_1": "13:17", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_ST.jpeg", + "irregularities_0": "continues to Dresden on some Fridays, arriving 11:00", + "irregularities_1": "continues from Dresden on some Sundays, depating 18:40" + }, + "78": { + "route_id": 78, + "agency_id": "RDC\/SJ", + "trip_short_name_0": "EN 345", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 346", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Stockholm C", + "origin_departure_time_0": "17:28", + "via_0": "Norrköping C - Linköping C - Nässjö C - Alvesta - Hässleholm C - Lund C - Malmö C - Kastrup Lufthavn - Padborg - Hamburg Hbf", + "destination_trip_0": "Berlin Hbf", + "destination_arrival_time_0": "10:28", + "origin_trip_1": "Berlin Hbf", + "origin_departure_time_1": "17:30", + "via_1": "Hamburg Hbf - Padborg - Kastrup Lufthavn - Malmö C - Lund C - Hässleholm C - Alvesta - Nässjö C - Linköping C - Norrköping C", + "destination_trip_1": "Stockholm C", + "destination_arrival_time_1": "09:56", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_SJ-RDC.jpeg", + "irregularities_0": "Tue, Thu, Sat from September 2026", + "irregularities_1": "Mon, Wed, Fri from September 2026" + }, + "79": { + "route_id": 79, + "agency_id": "ST", + "trip_short_name_0": "3920", + "service_id_0": "2026\/06\/25-09\/27: Wed, Sat", + "trip_short_name_1": "3921", + "service_id_1": "2026\/06\/26-09\/28: Thu, Sun", + "route_long_name": "", + "origin_trip_0": "Malmö C", + "origin_departure_time_0": "16:35", + "via_0": "Lund C - Hässleholm C - Alvesta - Nässjö C - Linköping C - Norrköping C - Stockholm C - Uppsala C - Östersund C - Åre - Duved", + "destination_trip_0": "Storlien", + "destination_arrival_time_0": "08:55", + "origin_trip_1": "Storlien", + "origin_departure_time_1": "15:25", + "via_1": "Duved - Åre - Östersund C - Uppsala C - Stockholm C - Norrköping C - Alvesta - Hässleholm C - Lund C", + "destination_trip_1": "Malmö C", + "destination_arrival_time_1": "07:15", + "picture": "", + "irregularities_0": "Runs via Helsingborg C, Halmstad C, Göteborg C and Skövde C to Stockholm C from 2025-07-16 to 2026-08-16, starting 1,5h earlier in Malmö and Lund. On Wednesdays, the train departs at 18:35 from Alvesta and 19:25 from Nässjö.", + "irregularities_1": "Runs via Stockholm C, Skövde C, Göteborg C, Halmstad C and Helsingborg C from 2025-07-17 to 2026-08-17, arriving 1,5h later in Lund and Malmö. On Wednesdays, the train departs later from the following stations: 15:50 from Malmö C, 16:10 from Lund C, 16:42 from Helsingborg C, 17:20 from Halmstad C, 19:20 from Göteborg C, 20:36 from Skövde C, 23:15 from Stockholm C, and 23:55 from Uppsala C." + }, + "80": { + "route_id": 80, + "agency_id": "ST", + "trip_short_name_0": "3904", + "service_id_0": "2026\/03\/04-05\/02: Wed, Sat", + "trip_short_name_1": "3905", + "service_id_1": "2026\/03\/05-05\/03: Thu, Sun", + "route_long_name": "", + "origin_trip_0": "Malmö C", + "origin_departure_time_0": "15:50", + "via_0": "Lund C - Helsingborg C - Halmstads central - Mölndals nedre - Östersund C - Åre", + "destination_trip_0": "Duved", + "destination_arrival_time_0": "07:40", + "origin_trip_1": "Duved", + "origin_departure_time_1": "17:25", + "via_1": "Åre - Östersund C - Mölndals nedre - Halmstads central - Helsingborg C - Lund C", + "destination_trip_1": "Malmö C", + "destination_arrival_time_1": "08:40", + "picture": "", + "irregularities_0": "Runs via Stockholm until 2 May", + "irregularities_1": "Runs via Stockholm until 3 May" + }, + "81": { + "route_id": 81, + "agency_id": "SJ", + "trip_short_name_0": "91", + "service_id_0": "2026: Daily", + "trip_short_name_1": "92", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Luleå C", + "origin_departure_time_0": "21:10", + "via_0": "Boden C - Umeå C - Sundsvall C - Gävle C - Uppsala C", + "destination_trip_0": "Stockholm C", + "destination_arrival_time_0": "10:09", + "origin_trip_1": "Stockholm C", + "origin_departure_time_1": "21:55", + "via_1": "Uppsala C - Gävle C - Örnsköldsvik C - Umeå C - Boden C", + "destination_trip_1": "Luleå C", + "destination_arrival_time_1": "11:53", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_SJ.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "83": { + "route_id": 83, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 797", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 798", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Torino Porta Susa", + "origin_departure_time_0": "20:40", + "via_0": "Milano Porta Garibaldi - Roma Tiburtina - Napoli Centrale", + "destination_trip_0": "Salerno", + "destination_arrival_time_0": "09:46", + "origin_trip_1": "Salerno", + "origin_departure_time_1": "20:38", + "via_1": "Napoli Centrale - Roma Tiburtina - Orvieto - Milano Porta Garibaldi", + "destination_trip_1": "Torino Porta Susa", + "destination_arrival_time_1": "09:05", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "84": { + "route_id": 84, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 1964", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1967", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Palermo Centrale", + "origin_departure_time_0": "12:58", + "via_0": "Termini Imerese - Barcellona Castroreale - Messina Centrale - Lamezia Terme Centrale - Salerno - Firenze S. M. N. - Bologna Centrale", + "destination_trip_0": "Milano Centrale", + "destination_arrival_time_0": "10:10", + "origin_trip_1": "Milano Centrale", + "origin_departure_time_1": "20:10", + "via_1": "Bologna Centrale - Firenze S. M. N. - Salerno - Lamezia Terme Centrale - Messina Centrale - Barcellona Castroreale - Termini Imerese", + "destination_trip_1": "Palermo Centrale", + "destination_arrival_time_1": "16:55", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte_1964-1967.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "85": { + "route_id": 85, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 1962", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1963", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Siracusa", + "origin_departure_time_0": "13:35", + "via_0": "Catania Centrale - Taormina Giardini - Messina Centrale - Lamezia Terme Centrale - Salerno - Firenze S. M. N. - Bologna Centrale", + "destination_trip_0": "Milano Centrale", + "destination_arrival_time_0": "10:10", + "origin_trip_1": "Milano Centrale", + "origin_departure_time_1": "20:10", + "via_1": "Bologna Centrale - Firenze S. M. N. - Salerno - Lamezia Terme Centrale - Messina Centrale - Taormina Giardini - Catania Centrale", + "destination_trip_1": "Siracusa", + "destination_arrival_time_1": "15:48", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte_1964-1967.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "86": { + "route_id": 86, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 752", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 755", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Lecce", + "origin_departure_time_0": "19:50", + "via_0": "Brindisi - Bari Centrale - Foggia - Bologna Centrale", + "destination_trip_0": "Milano Centrale", + "destination_arrival_time_0": "07:12", + "origin_trip_1": "Milano Centrale", + "origin_departure_time_1": "21:50", + "via_1": "Bologna Centrale - Foggia - Bari Centrale - Brindisi", + "destination_trip_1": "Lecce", + "destination_arrival_time_1": "09:30", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "90": { + "route_id": 90, + "agency_id": "VR", + "trip_short_name_0": "IC 266 (T)", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 933", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Rovaniemi", + "origin_departure_time_0": "17:52", + "via_0": "Kemi - Oulu \/ Uleåborg - Ylivieska - Kokkola \/ Karleby - Tampere - Turku \/ Åbo", + "destination_trip_0": "Turku satama \/ Åbo hamn", + "destination_arrival_time_0": "07:52", + "origin_trip_1": "Turku satama \/ Åbo hamn", + "origin_departure_time_1": "20:20", + "via_1": "Turku \/ Åbo - Toijala - Tampere - Kokkola \/ Karleby - Ylivieska - Oulu \/ Uleåborg - Kemi", + "destination_trip_1": "Rovaniemi", + "destination_arrival_time_1": "10:59", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_VR_New.jpeg", + "irregularities_0": "Not every Sat", + "irregularities_1": "" + }, + "91": { + "route_id": 91, + "agency_id": "VR", + "trip_short_name_0": "IC 266 (H)", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 273", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Rovaniemi", + "origin_departure_time_0": "17:52", + "via_0": "Kemi - Oulu \/ Uleåborg - Ylivieska - Kokkola \/ Karleby - Tampere - Toijala - Riihimäki", + "destination_trip_0": "Helsinki \/ Helsingfors", + "destination_arrival_time_0": "06:27", + "origin_trip_1": "Helsinki \/ Helsingfors", + "origin_departure_time_1": "23:13", + "via_1": "Riihimäki - Seinäjoki - Kokkola \/ Karleby - Ylivieska - Oulu \/ Uleåborg - Kemi", + "destination_trip_1": "Rovaniemi", + "destination_arrival_time_1": "11:03", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_VR_New.jpeg", + "irregularities_0": "Not every Sat", + "irregularities_1": "" + }, + "96": { + "route_id": 96, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 788", + "service_id_0": "2026: Sun", + "trip_short_name_1": "IC Notte 789", + "service_id_1": "2026: Fri", + "route_long_name": "", + "origin_trip_0": "Lecce", + "origin_departure_time_0": "22:15", + "via_0": "Brindisi - Bari Centrale", + "destination_trip_0": "Roma Termini", + "destination_arrival_time_0": "06:10", + "origin_trip_1": "Roma Termini", + "origin_departure_time_1": "23:58", + "via_1": "Bari Centrale - Brindisi", + "destination_trip_1": "Lecce", + "destination_arrival_time_1": "08:10", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "97": { + "route_id": 97, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 754", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 757", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Lecce", + "origin_departure_time_0": "20:25", + "via_0": "Brindisi - Bari Centrale - Foggia - Bologna Centrale", + "destination_trip_0": "Torino Lingotto", + "destination_arrival_time_0": "09:15", + "origin_trip_1": "Torino Lingotto", + "origin_departure_time_1": "20:58", + "via_1": "Bologna Centrale - Foggia - Bari Centrale - Brindisi", + "destination_trip_1": "Lecce", + "destination_arrival_time_1": "10:10", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "98": { + "route_id": 98, + "agency_id": "VR", + "trip_short_name_0": "P 269", + "service_id_0": "2026: Daily", + "trip_short_name_1": "P 276", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Helsinki \/ Helsingfors", + "origin_departure_time_0": "20:24", + "via_0": "Riihimäki - Tampere - Oulu \/ Uleåborg - Tornio-Itäinen", + "destination_trip_0": "Kolari", + "destination_arrival_time_0": "10:55", + "origin_trip_1": "Kolari", + "origin_departure_time_1": "19:42", + "via_1": "Tornio-Itäinen - Oulu \/ Uleåborg - Tampere - Riihimäki", + "destination_trip_1": "Helsinki \/ Helsingfors", + "destination_arrival_time_1": "10:34", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_VR_New.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "99": { + "route_id": 99, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 796", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1515", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Salerno", + "origin_departure_time_0": "20:52", + "via_0": "Napoli Centrale - Roma Tiburtina - Pisa Centrale - La Spezia Centrale - Genova Piazza Principe", + "destination_trip_0": "Torino Lingotto", + "destination_arrival_time_0": "10:32", + "origin_trip_1": "Torino Lingotto", + "origin_departure_time_1": "20:23", + "via_1": "Genova Piazza Principe - La Spezia Centrale - Pisa Centrale - Civitavecchia - Roma Ostiense - Napoli Centrale", + "destination_trip_1": "Salerno", + "destination_arrival_time_1": "09:11", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "100": { + "route_id": 100, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 794", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 795", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Reggio Calabria Centrale", + "origin_departure_time_0": "22:00", + "via_0": "Tropea - Lamezia Terme Centrale - Roma Ostiense - Civitavecchia - Grosseto - Livorno Centrale - Pisa Centrale - La Spezia Centrale - Genova Piazza Principe", + "destination_trip_0": "Torino Porta Nuova", + "destination_arrival_time_0": "14:40", + "origin_trip_1": "Torino Porta Nuova", + "origin_departure_time_1": "15:20", + "via_1": "Genova Piazza Principe - La Spezia Centrale - Pisa Centrale - Livorno Centrale - Grosseto - Civitavecchia - Roma Ostiense - Lamezia Terme Centrale - Tropea", + "destination_trip_1": "Reggio Calabria Centrale", + "destination_arrival_time_1": "09:45", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "101": { + "route_id": 101, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 1954", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1955 (P)", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Palermo Centrale", + "origin_departure_time_0": "18:48", + "via_0": "Termini Imerese - Barcellona Castroreale - Messina Centrale - Lamezia Terme Centrale", + "destination_trip_0": "Roma Termini", + "destination_arrival_time_0": "07:18", + "origin_trip_1": "Roma Termini", + "origin_departure_time_1": "20:16", + "via_1": "Napoli Centrale - Salerno - Messina Centrale - Barcellona Castroreale - Termini Imerese", + "destination_trip_1": "Palermo Centrale", + "destination_arrival_time_1": "09:24", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte_1964-1967.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "102": { + "route_id": 102, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 1958", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1959 (P)", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Palermo Centrale", + "origin_departure_time_0": "20:25", + "via_0": "Termini Imerese - Barcellona Castroreale - Messina Centrale - Salerno - Napoli Centrale", + "destination_trip_0": "Roma Termini", + "destination_arrival_time_0": "10:35", + "origin_trip_1": "Roma Termini", + "origin_departure_time_1": "23:00", + "via_1": "Lamezia Terme Centrale - Messina Centrale - Barcellona Castroreale - Termini Imerese", + "destination_trip_1": "Palermo Centrale", + "destination_arrival_time_1": "11:57", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte_1964-1967.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "103": { + "route_id": 103, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 1955 (S)", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1956", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Roma Termini", + "origin_departure_time_0": "20:16", + "via_0": "Napoli Centrale - Salerno - Messina Centrale - Taormina Giardini - Catania Centrale", + "destination_trip_0": "Siracusa", + "destination_arrival_time_0": "09:01", + "origin_trip_1": "Siracusa", + "origin_departure_time_1": "19:10", + "via_1": "Catania Centrale - Taormina Giardini - Messina Centrale - Lamezia Terme Centrale", + "destination_trip_1": "Roma Termini", + "destination_arrival_time_1": "07:18", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte_1964-1967.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "104": { + "route_id": 104, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 1959 (S)", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 1960", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Roma Termini", + "origin_departure_time_0": "23:00", + "via_0": "Lamezia Terme Centrale - Messina Centrale - Taormina Giardini - Catania Centrale", + "destination_trip_0": "Siracusa", + "destination_arrival_time_0": "11:29", + "origin_trip_1": "Siracusa", + "origin_departure_time_1": "21:45", + "via_1": "Catania Centrale - Taormina Giardini - Messina Centrale - Salerno - Napoli Centrale", + "destination_trip_1": "Roma Termini", + "destination_arrival_time_1": "09:51", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte_1964-1967.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "105": { + "route_id": 105, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 770", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Notte 774", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Trieste Centrale", + "origin_departure_time_0": "18:47", + "via_0": "Udine - Venezia Santa Lucia - Bologna Centrale", + "destination_trip_0": "Roma Termini", + "destination_arrival_time_0": "06:35", + "origin_trip_1": "Roma Termini", + "origin_departure_time_1": "22:35", + "via_1": "Venezia Santa Lucia - Udine", + "destination_trip_1": "Trieste Centrale", + "destination_arrival_time_1": "09:55", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "106": { + "route_id": 106, + "agency_id": "FS", + "trip_short_name_0": "IC Notte 763", + "service_id_0": "2026: Sat, Sun", + "trip_short_name_1": "IC Notte 764", + "service_id_1": "2026: Fri, Sat", + "route_long_name": "", + "origin_trip_0": "Bolzano \/ Bozen", + "origin_departure_time_0": "21:30", + "via_0": "Verona Porta Nuova - Orvieto", + "destination_trip_0": "Roma Termini", + "destination_arrival_time_0": "06:06", + "origin_trip_1": "Roma Termini", + "origin_departure_time_1": "23:00", + "via_1": "Orvieto - Verona Porta Nuova", + "destination_trip_1": "Bolzano \/ Bozen", + "destination_arrival_time_1": "08:08", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_Trenitalia_IC_Notte.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "107": { + "route_id": 107, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 5789", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Nuit 5790", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Paris Austerlitz", + "origin_departure_time_0": "20:51", + "via_0": "Crest - Gap", + "destination_trip_0": "Briançon", + "destination_arrival_time_0": "08:21", + "origin_trip_1": "Briançon", + "origin_departure_time_1": "19:58", + "via_1": "Gap - Crest", + "destination_trip_1": "Paris Austerlitz", + "destination_arrival_time_1": "08:08", + "picture": "", + "irregularities_0": "Times may vary", + "irregularities_1": "Times may vary" + }, + "108": { + "route_id": 108, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 5781", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Nuit 5772", + "service_id_1": "2026: Daily", + "route_long_name": "Le Train Bleu", + "origin_trip_0": "Paris Austerlitz", + "origin_departure_time_0": "21:25", + "via_0": "Marseille Saint-Charles - Toulon - Cannes", + "destination_trip_0": "Nice Ville", + "destination_arrival_time_0": "09:09", + "origin_trip_1": "Nice Ville", + "origin_departure_time_1": "19:00", + "via_1": "Cannes - Toulon - Marseille Saint-Charles", + "destination_trip_1": "Paris Austerlitz", + "destination_arrival_time_1": "06:55", + "picture": "", + "irregularities_0": "Leaves later before Feb 7th and from Feb 21st, 2024 ", + "irregularities_1": "" + }, + "109": { + "route_id": 109, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 3754 (Sun)", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Nuit 3755 (Sun)", + "service_id_1": "2026: Fri", + "route_long_name": "L'Occitan", + "origin_trip_0": "Albi Ville", + "origin_departure_time_0": "20:50", + "via_0": "Rodez - Figeac - St-Denis-lès-Martel", + "destination_trip_0": "Paris Austerlitz", + "destination_arrival_time_0": "08:31", + "origin_trip_1": "Paris Austerlitz", + "origin_departure_time_1": "18:51", + "via_1": "St-Denis-lès-Martel - Figeac - Rodez", + "destination_trip_1": "Albi Ville", + "destination_arrival_time_1": "09:02", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "110": { + "route_id": 110, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 5737", + "service_id_0": "2026: Fri", + "trip_short_name_1": "IC Nuit 5738", + "service_id_1": "2026: Sun", + "route_long_name": "", + "origin_trip_0": "Paris Austerlitz", + "origin_departure_time_0": "21:25", + "via_0": "Nîmes - Montpellier Saint-Roch - Béziers - Narbonne - Perpignan", + "destination_trip_0": "Cerbère", + "destination_arrival_time_0": "09:16", + "origin_trip_1": "Cerbère", + "origin_departure_time_1": "18:53", + "via_1": "Perpignan - Narbonne - Béziers - Montpellier Saint-Roch - Nîmes", + "destination_trip_1": "Paris Austerlitz", + "destination_arrival_time_1": "08:50", + "picture": "", + "irregularities_0": "Times may vary", + "irregularities_1": "Times may vary" + }, + "111": { + "route_id": 111, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 3740", + "service_id_0": "2026: Mon, Tue, Wed, Thu, Fri", + "trip_short_name_1": "IC Nuit 3731", + "service_id_1": "2026: Mon, Tue, Wed, Thu, Fri", + "route_long_name": "Le Pyrénéen", + "origin_trip_0": "Tarbes", + "origin_departure_time_0": "19:00", + "via_0": "Lourdes - Pau - Bayonne - Dax", + "destination_trip_0": "Paris Austerlitz", + "destination_arrival_time_0": "07:23", + "origin_trip_1": "Paris Austerlitz", + "origin_departure_time_1": "22:11", + "via_1": "Dax - Bayonne - Pau - Lourdes", + "destination_trip_1": "Tarbes", + "destination_arrival_time_1": "09:34", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "112": { + "route_id": 112, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 3970", + "service_id_0": "2026: Sat, Sun", + "trip_short_name_1": "IC Nuit 3971", + "service_id_1": "2026: Fri, Sat", + "route_long_name": "Le Pyrénéen", + "origin_trip_0": "Latour-de-Carol \/ La Tor de Querol", + "origin_departure_time_0": "18:48", + "via_0": "Pamiers - Fleury-les-Aubrais (Orléans)", + "destination_trip_0": "Paris Austerlitz", + "destination_arrival_time_0": "07:03", + "origin_trip_1": "Paris Austerlitz", + "origin_departure_time_1": "22:14", + "via_1": "Fleury-les-Aubrais (Orléans) - Pamiers", + "destination_trip_1": "Latour-de-Carol \/ La Tor de Querol", + "destination_arrival_time_1": "10:10", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "113": { + "route_id": 113, + "agency_id": "PKP", + "trip_short_name_0": "EN 1276", + "service_id_0": "2026\/06\/26-08\/28: Daily, except Sunday", + "trip_short_name_1": "EN 1277", + "service_id_1": "2026\/06\/28-08\/30: Daily, except Saturday", + "route_long_name": "Adriatic Express", + "origin_trip_0": "Rijeka", + "origin_departure_time_0": "19:06", + "via_0": "Břeclav - Staré Město u Uherského Hradiště - Přerov - Hranice na Moravě - Ostrava hl.n. - Bohumín - Tychy - Katowice - Zawiercie - Opoczno Południe - Warszawa Zachodnia - Warszawa Centralna", + "destination_trip_0": "Warszawa Wschodnia", + "destination_arrival_time_0": "14:15", + "origin_trip_1": "Warszawa Wschodnia", + "origin_departure_time_1": "13:41", + "via_1": "Warszawa Centralna - Warszawa Zachodnia - Opoczno Południe - Zawiercie - Katowice - Tychy - Bohumín - Ostrava hl.n. - Hranice na Moravě - Přerov - Staré Město u Uherského Hradiště - Břeclav - Ljubljana", + "destination_trip_1": "Rijeka", + "destination_arrival_time_1": "10:04", + "picture": "", + "irregularities_0": "Does not run on 06\/12,17,24 and 08\/02", + "irregularities_1": "Additional run on 06\/28, and 08\/16" + }, + "114": { + "route_id": 114, + "agency_id": "OTE", + "trip_short_name_0": "141", + "service_id_0": "2026: Sat", + "trip_short_name_1": "154", + "service_id_1": "2026: Tue", + "route_long_name": "", + "origin_trip_0": "Villach Hbf", + "origin_departure_time_0": "21:59", + "via_0": "non-stop", + "destination_trip_0": "Edirne", + "destination_arrival_time_0": "11:34", + "origin_trip_1": "Edirne", + "origin_departure_time_1": "17:45", + "via_1": "non-stop", + "destination_trip_1": "Villach Hbf", + "destination_arrival_time_1": "08:19", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "115": { + "route_id": 115, + "agency_id": "ÖBB", + "trip_short_name_0": "EN 1272", + "service_id_0": "2026\/05\/30-09\/26: Mon, Thu, Sat", + "trip_short_name_1": "EN 1273", + "service_id_1": "2026\/05\/29-09\/25: Wed, Fri, Sun", + "route_long_name": "", + "origin_trip_0": "Split", + "origin_departure_time_0": "17:20", + "via_0": "Knin - Zagreb Zapadni Kolodvor - Maribor - Graz Hbf - Bruck an der Mur - Wiener Neustadt Hbf - Wien Meidling - Wien Hbf", + "destination_trip_0": "Wien Hbf (Autoreisezuganlage)", + "destination_arrival_time_0": "09:29", + "origin_trip_1": "Wien Hbf (Autoreisezuganlage)", + "origin_departure_time_1": "18:57", + "via_1": "Wien Hbf - Wien Meidling - Wiener Neustadt Hbf - Bruck an der Mur - Graz Hbf - Maribor - Zagreb Zapadni Kolodvor - Knin", + "destination_trip_1": "Split", + "destination_arrival_time_1": "10:04", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "116": { + "route_id": 116, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "EN 40406", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 40407", + "service_id_1": "2026: Daily", + "route_long_name": "Chopin", + "origin_trip_0": "München Hbf", + "origin_departure_time_0": "18:35", + "via_0": "München Ost - Rosenheim - Salzburg Hbf - Attnang-Puchheim - Linz Hbf - St. Pölten Hbf - Wien Meidling - Wien Hbf - Břeclav - Katowice - Sosnowiec Główny - Zawiercie - Włoszczowa Północ - Warszawa Zachodnia - Warszawa Centralna", + "destination_trip_0": "Warszawa Wschodnia", + "destination_arrival_time_0": "08:15", + "origin_trip_1": "Warszawa Wschodnia", + "origin_departure_time_1": "19:41", + "via_1": "Warszawa Centralna - Warszawa Zachodnia - Włoszczowa Północ - Zawiercie - Sosnowiec Główny - Katowice - Břeclav - Wien Hbf - Wien Meidling - St. Pölten Hbf - Linz Hbf - Attnang-Puchheim - Salzburg Hbf - Rosenheim - München Ost", + "destination_trip_1": "München Hbf", + "destination_arrival_time_1": "10:24", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "117": { + "route_id": 117, + "agency_id": "HŽPP\/ÖBB", + "trip_short_name_0": "EN 40414", + "service_id_0": "Daily", + "trip_short_name_1": "EN 40465", + "service_id_1": "Daily", + "route_long_name": "", + "origin_trip_0": "Zagreb Gl. K.", + "origin_departure_time_0": "19:39", + "via_0": "Ljubljana - Villach Hbf - Innsbruck Hbf - St. Anton am Arlberg - Feldkirch - Buchs (SG)", + "destination_trip_0": "Zürich HB", + "destination_arrival_time_0": "09:20", + "origin_trip_1": "Zürich HB", + "origin_departure_time_1": "20:40", + "via_1": "Buchs (SG) - Feldkirch - Bludenz - St. Anton am Arlberg - Innsbruck Hbf - Villach Hbf - Ljubljana", + "destination_trip_1": "Zagreb Gl. K.", + "destination_arrival_time_1": "10:30", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_hzpp_en.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "118": { + "route_id": 118, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "EN 40416", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 40417", + "service_id_1": "2026: Daily", + "route_long_name": "Carpathia", + "origin_trip_0": "München Hbf", + "origin_departure_time_0": "18:35", + "via_0": "München Ost - Rosenheim - Salzburg Hbf - Attnang-Puchheim - Linz Hbf - St. Pölten Hbf - Wien Meidling - Wien Hbf - Břeclav - Gliwice - Zabrze - Katowice - Mysłowice - Jaworzno Szczakowa - Trzebinia - Krzeszowice - Kraków Gł. - Tarnow - Dębica - Rzeszow Gł. - Przeworsk - Jarosław", + "destination_trip_0": "Przemyśl Gł.", + "destination_arrival_time_0": "10:11", + "origin_trip_1": "Przemyśl Gł.", + "origin_departure_time_1": "17:51", + "via_1": "non-stop - Przeworsk - Rzeszow Gł. - Dębica - Tarnow - Kraków Gł. - Krzeszowice - Trzebinia - Jaworzno Szczakowa - Mysłowice - Katowice - Zabrze - Gliwice - Břeclav - Wien Hbf - Wien Meidling - St. Pölten Hbf - Linz Hbf - Attnang-Puchheim - Salzburg Hbf - Rosenheim - München Ost", + "destination_trip_1": "München Hbf", + "destination_arrival_time_1": "10:24", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "119": { + "route_id": 119, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 3754", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Nuit 3755", + "service_id_1": "2026: Daily, except Sat", + "route_long_name": "L'Occitan", + "origin_trip_0": "Rodez", + "origin_departure_time_0": "22:18", + "via_0": "Figeac - St-Denis-lès-Martel", + "destination_trip_0": "Paris Austerlitz", + "destination_arrival_time_0": "09:33", + "origin_trip_1": "Paris Austerlitz", + "origin_departure_time_1": "19:28", + "via_1": "St-Denis-lès-Martel - Figeac", + "destination_trip_1": "Rodez", + "destination_arrival_time_1": "07:09", + "picture": "", + "irregularities_0": "Departs 22:36 on Sun", + "irregularities_1": "Arrives earlier Fri\/Sat 06:57" + }, + "120": { + "route_id": 120, + "agency_id": "ČD", + "trip_short_name_0": "EN 40458", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 40459", + "service_id_1": "2026: Daily", + "route_long_name": "Canopus", + "origin_trip_0": "Praha hl.n.", + "origin_departure_time_0": "17:25", + "via_0": "Praha-Holešovice - Ústí nad Labem hl.n. - Děčín hl.n. - Bad Schandau - Dresden Hbf - Dresden Neustadt - Riesa - Leipzig Hbf - Karlsruhe Hbf - Baden-Baden - Offenburg - Freiburg (Breisgau) Hbf - Basel Bad Bf - Basel SBB", + "destination_trip_0": "Zürich HB", + "destination_arrival_time_0": "09:05", + "origin_trip_1": "Zürich HB", + "origin_departure_time_1": "19:59", + "via_1": "Basel SBB - Basel Bad Bf - Freiburg (Breisgau) Hbf - Offenburg - Karlsruhe Hbf - Mannheim Hbf - Frankfurt (Main) Süd - Leipzig Hbf - Riesa - Dresden Neustadt - Dresden Hbf - Bad Schandau - Děčín hl.n. - Ústí nad Labem hl.n. - Praha-Holešovice", + "destination_trip_1": "Praha hl.n.", + "destination_arrival_time_1": "09:25", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "121": { + "route_id": 121, + "agency_id": "PKP", + "trip_short_name_0": "IC 16170", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 61170", + "service_id_1": "2026: Daily", + "route_long_name": "Karkonosze", + "origin_trip_0": "Warszawa Wschodnia", + "origin_departure_time_0": "23:36", + "via_0": "Warszawa Centralna - Warszawa Zachodnia - Wrocław Gł. - Jelenia Góra", + "destination_trip_0": "Szklarska Poręba Górna", + "destination_arrival_time_0": "07:34", + "origin_trip_1": "Szklarska Poręba Górna", + "origin_departure_time_1": "20:18", + "via_1": "Jelenia Góra - Wrocław Gł. - Warszawa Zachodnia - Warszawa Centralna", + "destination_trip_1": "Warszawa Wschodnia", + "destination_arrival_time_1": "06:23", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "122": { + "route_id": 122, + "agency_id": "PKP", + "trip_short_name_0": "IC 38172", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 83172", + "service_id_1": "2026: Daily", + "route_long_name": "Podhalanin ", + "origin_trip_0": "Zakopane", + "origin_departure_time_0": "20:00", + "via_0": "Kraków Gł. - Poznań Gł. - Szczecin Gł.", + "destination_trip_0": "Świnoujście", + "destination_arrival_time_0": "09:15", + "origin_trip_1": "Świnoujście", + "origin_departure_time_1": "18:47", + "via_1": "Szczecin Gł. - Poznań Gł. - Kraków Gł.", + "destination_trip_1": "Zakopane", + "destination_arrival_time_1": "08:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "123": { + "route_id": 123, + "agency_id": "ZSSK", + "trip_short_name_0": "R 680", + "service_id_0": "2026: Daily", + "trip_short_name_1": "R 681", + "service_id_1": "2026: Daily", + "route_long_name": "Zemplín", + "origin_trip_0": "Humenné", + "origin_departure_time_0": "21:51", + "via_0": "Strážske - Michalovce - Bánovce nad Ondavou - Trebišov - Košice - Kysak - Margecany - Spišská Nová Ves - Poprad Tatry - Trnava - Bratislava-Vinohrady", + "destination_trip_0": "Bratislava hl.st.", + "destination_arrival_time_0": "05:33", + "origin_trip_1": "Bratislava hl.st.", + "origin_departure_time_1": "22:55", + "via_1": "Bratislava-Vinohrady - Trnava - Leopoldov - Piešťany - Nové Mesto nad Váhom - Trenčín - Trenčianska Teplá - Púchov - Košice - Trebišov - Bánovce nad Ondavou - Michalovce - Michalovce", + "destination_trip_1": "Humenné", + "destination_arrival_time_1": "07:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "124": { + "route_id": 124, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "EC 460", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EC 461", + "service_id_1": "2026: Daily", + "route_long_name": "Baltic Express", + "origin_trip_0": "Praha hl.n.", + "origin_departure_time_0": "18:49", + "via_0": "Jarosław - Lichkov - Międzylesie - Kłodzko Miasto - Wrocław Gł. - Poznań Gł. - Gdańsk Gł.", + "destination_trip_0": "Gdynia Gł.", + "destination_arrival_time_0": "05:58", + "origin_trip_1": "Gdynia Gł.", + "origin_departure_time_1": "21:59", + "via_1": "Gdańsk Gł. - Bydgoszcz Gł. - Wrocław Gł. - Kłodzko Miasto - Międzylesie - Lichkov - Pardubice hl.n.", + "destination_trip_1": "Praha hl.n.", + "destination_arrival_time_1": "09:14", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/04\/PKP_sleeper_type_308A_CC-BY_2-0_Adam-Kilian_wikimedia_commons.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "125": { + "route_id": 125, + "agency_id": "PKP", + "trip_short_name_0": "TLK 35190", + "service_id_0": "2026\/06\/26-2026\/08\/30: Daily", + "trip_short_name_1": "TLK 53190", + "service_id_1": "2026\/06\/27-2026\/08\/31: Daily", + "route_long_name": "Korsarz", + "origin_trip_0": "Kraków Gł.", + "origin_departure_time_0": "20:14", + "via_0": "Częstochowa - Łódź Kaliska - Toruń Gł. - Gdynia Główna", + "destination_trip_0": "Łeba", + "destination_arrival_time_0": "08:13", + "origin_trip_1": "Łeba", + "origin_departure_time_1": "21:00", + "via_1": "Gdynia Gł. - Gdańsk Gł. - Tczew - Łódź Kaliska - Częstochowa", + "destination_trip_1": "Kraków Gł.", + "destination_arrival_time_1": "08:48", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "126": { + "route_id": 126, + "agency_id": "PKP", + "trip_short_name_0": "EN 430 \/ IC 28170", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 82170 \/ EC 431", + "service_id_1": "2026: Daily", + "route_long_name": "Ursa \/ Uznam", + "origin_trip_0": "Przemyśl Gł.", + "origin_departure_time_0": "18:54", + "via_0": "Rzeszow Gł. - Tarnow - Kraków Gł. - Katowice - Opole Gł. - Wrocław Gł. - Leszno - Poznań Gł. - Krzyz - Szczecin Gł.", + "destination_trip_0": "Świnoujście", + "destination_arrival_time_0": "06:34", + "origin_trip_1": "Świnoujście", + "origin_departure_time_1": "21:34", + "via_1": "Szczecin Gł. - Krzyz - Poznań Gł. - Leszno - Wrocław Gł. - Opole Gł. - Katowice - Kraków Gł. - Tarnow - Rzeszow Gł.", + "destination_trip_1": "Przemyśl Gł.", + "destination_arrival_time_1": "09:11", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "127": { + "route_id": 127, + "agency_id": "MÁV\/PKP", + "trip_short_name_0": "IC 407 \/ EN 477", + "service_id_0": "2026: Daily", + "trip_short_name_1": "EN 476 \/ IC 406", + "service_id_1": "2026: Daily", + "route_long_name": "Metropol", + "origin_trip_0": "Warszawa Wschodnia", + "origin_departure_time_0": "19:41", + "via_0": "Warszawa Centralna - Zawiercie - Sosnowiec Główny - Katowice - Rybnik - Bratislava hl.st. - Nové Zámky - Vac", + "destination_trip_0": "Budapest Nyugati", + "destination_arrival_time_0": "08:29", + "origin_trip_1": "Budapest Nyugati", + "origin_departure_time_1": "19:30", + "via_1": "Vac - Nové Zámky - Bratislava hl.st. - Břeclav - Katowice - Sosnowiec Główny - Zawiercie - Warszawa Centralna", + "destination_trip_1": "Warszawa Wschodnia", + "destination_arrival_time_1": "08:15", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "128": { + "route_id": 128, + "agency_id": "PKP", + "trip_short_name_0": "IC 28170", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC 82170", + "service_id_1": "2026: Daily", + "route_long_name": "Uznam", + "origin_trip_0": "Chelm", + "origin_departure_time_0": "18:29", + "via_0": "Lublin - Warszawa Centralna - Łódź Widzew - Szczecin Gł.", + "destination_trip_0": "Świnoujście", + "destination_arrival_time_0": "06:38", + "origin_trip_1": "Świnoujście", + "origin_departure_time_1": "21:26", + "via_1": "Szczecin Gł. - Łódź Widzew - Warszawa Centralna - Lublin", + "destination_trip_1": "Chelm", + "destination_arrival_time_1": "09:27", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "129": { + "route_id": 129, + "agency_id": "PKP", + "trip_short_name_0": "TLK 35170", + "service_id_0": "2026: Daily", + "trip_short_name_1": "TLK 53170", + "service_id_1": "2026: Daily", + "route_long_name": "Karpaty", + "origin_trip_0": "Zakopane", + "origin_departure_time_0": "21:53", + "via_0": "Kraków Gł. - Częstochowa - Warszawa Centralna - Ciechanow - Tczew - Gdańsk Gł.", + "destination_trip_0": "Gdynia Gł.", + "destination_arrival_time_0": "08:40", + "origin_trip_1": "Gdynia Gł.", + "origin_departure_time_1": "19:22", + "via_1": "Gdańsk Gł. - Tczew - Ciechanow - Warszawa Centralna - Kraków Gł.", + "destination_trip_1": "Zakopane", + "destination_arrival_time_1": "06:02", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "130": { + "route_id": 130, + "agency_id": "ŽS\/ŽPCG", + "trip_short_name_0": "433", + "service_id_0": "2026: Daily", + "trip_short_name_1": "1130 \/ 432", + "service_id_1": "2026: Daily", + "route_long_name": "Lovćen", + "origin_trip_0": "Zemun", + "origin_departure_time_0": "19:35", + "via_0": "Beograd Centar - Rakovica - Lazarevac - Lajkovac - Valjevo - Kosjerić - Požega - Užice - Priboj - Kolašin - Podgorica - Golubovci - Golubovci", + "destination_trip_0": "Bar", + "destination_arrival_time_0": "06:54", + "origin_trip_1": "Bar", + "origin_departure_time_1": "20:10", + "via_1": "Sutomore - Golubovci - Podgorica - Kolašin - Mojkovac - Bijelo Polje - Prijepolje Teretna - Prijepolje - Kosjerić - Lajkovac - Lazarevac - Rakovica - Rakovica - Beograd Centar", + "destination_trip_1": "Zemun", + "destination_arrival_time_1": "07:25", + "picture": "", + "irregularities_0": "Tickets only available 60 days ahead at ticket offices in Montenegro or Serbia", + "irregularities_1": "Tickets only available 60 days ahead at ticket offices in Montenegro or Serbia" + }, + "131": { + "route_id": 131, + "agency_id": "BDŽ", + "trip_short_name_0": "ICF 8656", + "service_id_0": "2026: Daily", + "trip_short_name_1": "ICF 8657", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Varna", + "origin_departure_time_0": "23:45", + "via_0": "Beloslav - Sindel - Dalgopol - Komunari - Dimitrovgrad - Yabalkovo - Parvomai - Popovitsa - Cheshnegirovo - Sadovo - Katunitsa - Krumovo - Plovdiv - Proslav - Todor Kableshkov - Kadievo - Stambolijski - Pazardzhik - Septemvri - Belovo - Kostenets - Ihtiman", + "destination_trip_0": "Sofia", + "destination_arrival_time_0": "09:00", + "origin_trip_1": "Sofia", + "origin_departure_time_1": "21:00", + "via_1": "Poduiane - Iskar - Kazichene - Vakarel - Ihtiman - Kostenets - Belovo - Septemvri - Pazardzhik - Stambolijski - Plovdiv - Krumovo - Parvomai - Dimitrovgrad - Komunari - Dalgopol - Sindel - Beloslav", + "destination_trip_1": "Varna", + "destination_arrival_time_1": "05:42", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "133": { + "route_id": 133, + "agency_id": "BDŽ", + "trip_short_name_0": "ICF 2626", + "service_id_0": "2026: Daily", + "trip_short_name_1": "ICF 2627", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Varna", + "origin_departure_time_0": "21:40", + "via_0": "Beloslav - Poveljanovo - Sindel - Dobrina - Provadiya - Kaspichan - Shumen - Targovishte - Popovo - Strazhitsa - Gorna Oryahovitsa - Zverino - Svoge - Kurilo - Sofia Sever", + "destination_trip_0": "Sofia", + "destination_arrival_time_0": "05:45", + "origin_trip_1": "Sofia", + "origin_departure_time_1": "23:00", + "via_1": "Sofia Sever - Rebrovo - Svoge - Cerovo - Bov - Lakatnik - Zverino - Mezdra - Roman - Cherven Bryag - Pleven - Targovishte - Shumen - Kaspichan - Provadiya - Dobrina - Sindel - Poveljanovo - Beloslav", + "destination_trip_1": "Varna", + "destination_arrival_time_1": "06:52", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "134": { + "route_id": 134, + "agency_id": "BDŽ", + "trip_short_name_0": "ICF 8626", + "service_id_0": "2026: Daily", + "trip_short_name_1": "ICF 8627", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Burgas", + "origin_departure_time_0": "23:00", + "via_0": "Vladimir Pavlov - Aytos - Karnobat - Straldzha - Zimnitsa - Jambol - Nova Zagora - Stara Zagora - Elin Pelin - Kazichene - Iskar - Poduiane Patnicheska", + "destination_trip_0": "Sofia", + "destination_arrival_time_0": "05:45", + "origin_trip_1": "Sofia", + "origin_departure_time_1": "22:50", + "via_1": "Poduiane Patnicheska - Iskar - Kazichene - Elin Pelin - Ihtiman - Kostenets - Belovo - Septemvri - Pazardzhik - Stambolijski - Plovdiv - Nova Zagora - Jambol - Straldzha - Karnobat - Aytos - Vladimir Pavlov", + "destination_trip_1": "Burgas", + "destination_arrival_time_1": "05:50", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "135": { + "route_id": 135, + "agency_id": "BDŽ", + "trip_short_name_0": "ICF 9646", + "service_id_0": "2026: Daily", + "trip_short_name_1": "ICF 9647", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Silistra", + "origin_departure_time_0": "18:20", + "via_0": "Alfatar - Dulovo - Todorovo - Isperih - Samuil - Razgrad - Senovo - Vetovo - Ruse Razpredelitel - Ruse Tovarna - Ruse - Ivanovo - Dve Mogili - Borovo - Byala - Polski Trambesh - Petko Karavelovo - Gorna Oryahovitsa - Zverino - Lakatnik - Svoge - Kurilo", + "destination_trip_0": "Sofia", + "destination_arrival_time_0": "05:45", + "origin_trip_1": "Sofia", + "origin_departure_time_1": "20:10", + "via_1": "Sofia Sever - Kurilo - Rebrovo - Svoge - Lakatnik - Zverino - Mezdra - Roman - Cherven Bryag - Telish - Dolni Dabnik - Pleven - Levski - Pavlikeni - Gorna Oryahovitsa - Petko Karavelovo - Polski Trambesh - Borovo - Samuil - Isperih - Todorovo - Dulovo", + "destination_trip_1": "Silistra", + "destination_arrival_time_1": "07:25", + "picture": "", + "irregularities_0": "Train runs only to Gorna Orjahovica but with 1 couchette through coach to Sofia, not indicated in the official timetable", + "irregularities_1": "" + }, + "136": { + "route_id": 136, + "agency_id": "PKP", + "trip_short_name_0": "TLK 48190", + "service_id_0": "2026\/06\/26-2026\/08\/30: Daily", + "trip_short_name_1": "TLK 84190", + "service_id_1": "2026\/06\/27-2026\/08\/31: Daily", + "route_long_name": "Pirat", + "origin_trip_0": "Bielsko-Biała Główna", + "origin_departure_time_0": "21:25", + "via_0": "Żory - Rybnik - Opole Główne", + "destination_trip_0": "Kołobrzeg", + "destination_arrival_time_0": "07:08", + "origin_trip_1": "Kołobrzeg", + "origin_departure_time_1": "21:01", + "via_1": "Poznań Gł. - Rybnik - Żory", + "destination_trip_1": "Bielsko-Biała Główna", + "destination_arrival_time_1": "06:48", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "137": { + "route_id": 137, + "agency_id": "PKP", + "trip_short_name_0": "TLK 48190\/38194", + "service_id_0": "2026\/06\/26-08\/30: Daily", + "trip_short_name_1": "TLK 83194\/84190", + "service_id_1": "2026\/06\/27-08\/31: Daily", + "route_long_name": "Wolin \/ Pirat", + "origin_trip_0": "Bielsko-Biała Gł.", + "origin_departure_time_0": "21:25", + "via_0": "Rybnik - Opole Gł. - Kostrzyn - Szczecin Gł.", + "destination_trip_0": "Świnoujście", + "destination_arrival_time_0": "07:27", + "origin_trip_1": "Świnoujście", + "origin_departure_time_1": "20:25", + "via_1": "Szczecin Gł. - Kostrzyn - Zielona Góra Gł. - Rybnik", + "destination_trip_1": "Bielsko-Biała Gł.", + "destination_arrival_time_1": "06:48", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "138": { + "route_id": 138, + "agency_id": "PKP", + "trip_short_name_0": "TLK 38170", + "service_id_0": "2026: Daily", + "trip_short_name_1": "TLK 83170", + "service_id_1": "2026: Daily", + "route_long_name": "Ustronie", + "origin_trip_0": "Kraków Gł.", + "origin_departure_time_0": "21:33", + "via_0": "Kielce - Radom - Gdańsk Gł. - Gdynia Gł. - Słupsk - Koszalin", + "destination_trip_0": "Kołobrzeg", + "destination_arrival_time_0": "10:56", + "origin_trip_1": "Kołobrzeg", + "origin_departure_time_1": "19:05", + "via_1": "Koszalin - Słupsk - Gdynia Gł. - Gdańsk Gł. - Radom - Kielce", + "destination_trip_1": "Kraków Gł.", + "destination_arrival_time_1": "07:49", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "140": { + "route_id": 140, + "agency_id": "UZ", + "trip_short_name_0": "051", + "service_id_0": "2026: Daily", + "trip_short_name_1": "052 K", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "20:05", + "via_0": "Lviv", + "destination_trip_0": "Przemyśl Gł.", + "destination_arrival_time_0": "05:00", + "origin_trip_1": "Przemyśl Gł.", + "origin_departure_time_1": "22:30", + "via_1": "Lviv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "09:18", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "141": { + "route_id": 141, + "agency_id": "UZ", + "trip_short_name_0": "101", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "102", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Lozova", + "origin_departure_time_0": "10:03", + "via_0": "Poltava - Myrhorod - Lubny - Kyiv Pasazhyrskyi - Im.Tarasa Shevchenka", + "destination_trip_0": "Mykolaiv", + "destination_arrival_time_0": "05:01", + "origin_trip_1": "Mykolaiv", + "origin_departure_time_1": "13:04", + "via_1": "Im.Tarasa Shevchenka - Kyiv Pasazhyrskyi - Lubny - Myrhorod - Poltava", + "destination_trip_1": "Lozova", + "destination_arrival_time_1": "09:03", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "142": { + "route_id": 142, + "agency_id": "BDŽ", + "trip_short_name_0": "ICF 2636", + "service_id_0": "2026: Daily", + "trip_short_name_1": "ICF 2637", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Dobrich", + "origin_departure_time_0": "20:35", + "via_0": "Donchevo - Botevo - Oborishte - General Kiselovo - Valchi Dol - Suvorovo - Chernevo - Kipra - Devnya - Poveljanovo - Zverino - Svoge - Kurilo - Sofia Sever", + "destination_trip_0": "Sofia", + "destination_arrival_time_0": "05:45", + "origin_trip_1": "Sofia", + "origin_departure_time_1": "23:00", + "via_1": "Sofia Sever - Rebrovo - Svoge - Cerovo - Bov - Lakatnik - Zverino - Mezdra - Roman - Cherven Bryag - Pleven - Poveljanovo - Devnya - Kipra - Chernevo - Suvorovo - Valchi Dol - General Kiselovo - Oborishte - Botevo - Donchevo", + "destination_trip_1": "Dobrich", + "destination_arrival_time_1": "08:05", + "picture": "", + "irregularities_0": "Train runs only to Poveljanovo but with 1 sleeper through coach to Sofia, not indicated in the official timetable", + "irregularities_1": "Train runs only to Poveljanovo but with 1 sleeper through coach to Dobrich, not indicated in the official timetable" + }, + "147": { + "route_id": 147, + "agency_id": "UZ", + "trip_short_name_0": "036 Š", + "service_id_0": "2026: Daily", + "trip_short_name_1": "036 L", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Odesa Holovna", + "origin_departure_time_0": "21:15", + "via_0": "Podilsk - Zhmerynka - Khmelnytskyi - Ternopil - Lviv Pidzamche - Lviv", + "destination_trip_0": "Przemyśl Gł.", + "destination_arrival_time_0": "11:20", + "origin_trip_1": "Przemyśl Gł.", + "origin_departure_time_1": "16:20", + "via_1": "Lviv - Lviv Pidzamche - Ternopil - Khmelnytskyi - Zhmerynka - Podilsk", + "destination_trip_1": "Odesa Holovna", + "destination_arrival_time_1": "07:59", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "149": { + "route_id": 149, + "agency_id": "UZ", + "trip_short_name_0": "041", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "042", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Dnipro Holovny", + "origin_departure_time_0": "16:46", + "via_0": "Oleksandriia - Vinnytsia - Khmelnytskyi - Ternopil - Lviv", + "destination_trip_0": "Truskavets", + "destination_arrival_time_0": "12:35", + "origin_trip_1": "Truskavets", + "origin_departure_time_1": "13:33", + "via_1": "Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Oleksandriia", + "destination_trip_1": "Dnipro Holovny", + "destination_arrival_time_1": "09:08", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "150": { + "route_id": 150, + "agency_id": "UZ", + "trip_short_name_0": "015", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "016", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "Les Kurbas", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "14:10", + "via_0": "Poltava - Myrhorod - Lubny - Kyiv Pasazhyrskyi - Lviv - Ivano-Frankivsk", + "destination_trip_0": "Vorokhta", + "destination_arrival_time_0": "09:47", + "origin_trip_1": "Vorokhta", + "origin_departure_time_1": "12:43", + "via_1": "Ivano-Frankivsk - Lviv - Kyiv Pasazhyrskyi - Lubny - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "07:15", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "151": { + "route_id": 151, + "agency_id": "UZ", + "trip_short_name_0": "123", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "124", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "18:34", + "via_0": "Poltava - Myrhorod - Lubny - Kyiv Pasazhyrskyi - Lviv - Ivano-Frankivsk", + "destination_trip_0": "Chernivtsi", + "destination_arrival_time_0": "14:03", + "origin_trip_1": "Chernivtsi", + "origin_departure_time_1": "14:55", + "via_1": "Ivano-Frankivsk - Lviv - Kyiv Pasazhyrskyi - Lubny - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "10:45", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "152": { + "route_id": 152, + "agency_id": "UZ", + "trip_short_name_0": "023", + "service_id_0": "2026: Daily", + "trip_short_name_1": "024", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "21:30", + "via_0": "Kovel", + "destination_trip_0": "Chelm", + "destination_arrival_time_0": "08:08", + "origin_trip_1": "Chelm", + "origin_departure_time_1": "20:14", + "via_1": "Kovel", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "08:16", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "153": { + "route_id": 153, + "agency_id": "UZ", + "trip_short_name_0": "019", + "service_id_0": "2026: Daily", + "trip_short_name_1": "020", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "19:06", + "via_0": "Kovel", + "destination_trip_0": "Chelm", + "destination_arrival_time_0": "05:00", + "origin_trip_1": "Chelm", + "origin_departure_time_1": "23:10", + "via_1": "Kovel", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "22:45", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "154": { + "route_id": 154, + "agency_id": "UZ", + "trip_short_name_0": "007 O\/059 O", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "008 Š\/060 Š", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "Transcarpathia", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "20:03", + "via_0": "Poltava - Kremenchuk - Kropyvnytskyi - Voznesens'k", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "06:42", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "22:30", + "via_1": "Voznesens'k - Kropyvnytskyi - Kremenchuk - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "09:18", + "picture": "", + "irregularities_0": "Runs as 059 O every other day, approx 4h slower", + "irregularities_1": "Runs as 060 Š every other day, approx 5h slower" + }, + "155": { + "route_id": 155, + "agency_id": "UZ", + "trip_short_name_0": "032 D", + "service_id_0": "2026: Daily", + "trip_short_name_1": "032 P", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Przemyśl Gł.", + "origin_departure_time_0": "19:16", + "via_0": "Lviv - Oleksandriia - Dnipro Holovny", + "destination_trip_0": "Zaporizhzhia 1", + "destination_arrival_time_0": "15:14", + "origin_trip_1": "Zaporizhzhia 1", + "origin_departure_time_1": "13:50", + "via_1": "Dnipro Holovny - Oleksandriia - Lviv", + "destination_trip_1": "Przemyśl Gł.", + "destination_arrival_time_1": "20:19", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "156": { + "route_id": 156, + "agency_id": "UZ", + "trip_short_name_0": "021", + "service_id_0": "2026: Daily", + "trip_short_name_1": "022", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "19:26", + "via_0": "Poltava - Myrhorod - Lubny - Kyiv Pasazhyrskyi - Kozyatyn - Vinnytsia - Khmelnytskyi - Ternopil", + "destination_trip_0": "Lviv", + "destination_arrival_time_0": "11:18", + "origin_trip_1": "Lviv", + "origin_departure_time_1": "15:49", + "via_1": "Ternopil - Khmelnytskyi - Vinnytsia - Kozyatyn - Kyiv Pasazhyrskyi - Lubny - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "07:46", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "158": { + "route_id": 158, + "agency_id": "UZ", + "trip_short_name_0": "103", + "service_id_0": "2026: Daily", + "trip_short_name_1": "104", + "service_id_1": "2026: Daily", + "route_long_name": "Nezlamnist", + "origin_trip_0": "Lozova", + "origin_departure_time_0": "15:17", + "via_0": "Poltava - Myrhorod - Kyiv Pasazhyrskyi - Kozyatyn - Vinnytsia - Khmelnytskyi - Ternopil", + "destination_trip_0": "Lviv", + "destination_arrival_time_0": "09:29", + "origin_trip_1": "Lviv", + "origin_departure_time_1": "20:10", + "via_1": "Ternopil - Khmelnytskyi - Vinnytsia - Kozyatyn - Kyiv Pasazhyrskyi - Myrhorod - Poltava", + "destination_trip_1": "Lozova", + "destination_arrival_time_1": "14:22", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "161": { + "route_id": 161, + "agency_id": "UZ", + "trip_short_name_0": "063", + "service_id_0": "2026: Daily", + "trip_short_name_1": "064", + "service_id_1": "2026: Daily", + "route_long_name": "Oberig", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "22:52", + "via_0": "Poltava - Myrhorod - Kyiv Pasazhyrskyi - Lviv", + "destination_trip_0": "Przemyśl Gł.", + "destination_arrival_time_0": "16:59", + "origin_trip_1": "Przemyśl Gł.", + "origin_departure_time_1": "10:41", + "via_1": "Lviv - Kyiv Pasazhyrskyi - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "05:56", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "162": { + "route_id": 162, + "agency_id": "UZ", + "trip_short_name_0": "017 O\/045 D", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "017 L\/045 L", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "Skovoroda express", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "14:10", + "via_0": "Poltava - Myrhorod - Lubny - Kyiv Pasazhyrskyi - Lviv - Stryj - Mukacheve", + "destination_trip_0": "Uzhhorod", + "destination_arrival_time_0": "10:34", + "origin_trip_1": "Uzhhorod", + "origin_departure_time_1": "13:50", + "via_1": "Mukacheve - Stryj - Lviv - Kyiv Pasazhyrskyi - Lubny - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "09:30", + "picture": "", + "irregularities_0": "Runs as 045 D every other day, approx 6h slower", + "irregularities_1": "Runs as 045 L every other day, approx 6h slower" + }, + "164": { + "route_id": 164, + "agency_id": "UZ", + "trip_short_name_0": "001 D", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "001 L", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "Yednist", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "18:34", + "via_0": "Poltava - Myrhorod - Lubny - Kyiv Pasazhyrskyi - Lviv", + "destination_trip_0": "Ivano-Frankivsk", + "destination_arrival_time_0": "11:27", + "origin_trip_1": "Ivano-Frankivsk", + "origin_departure_time_1": "17:29", + "via_1": "Lviv - Kyiv Pasazhyrskyi - Lubny - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "22:45", + "picture": "", + "irregularities_0": "Currently to Ivano-Frankivsk, but from 29\/03 to Vorokhta", + "irregularities_1": "Currently to Ivano-Frankivsk, but from 29\/03 to Vorokhta" + }, + "166": { + "route_id": 166, + "agency_id": "UZ", + "trip_short_name_0": "141", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "142", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Ivano-Frankivsk", + "origin_departure_time_0": "20:54", + "via_0": "Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Kozyatyn - Fastiv - Kyiv Pasazhyrskyi", + "destination_trip_0": "Chernihiv", + "destination_arrival_time_0": "12:38", + "origin_trip_1": "Chernihiv", + "origin_departure_time_1": "13:08", + "via_1": "Kyiv Pasazhyrskyi - Fastiv - Kozyatyn - Vinnytsia - Khmelnytskyi - Ternopil - Lviv", + "destination_trip_1": "Ivano-Frankivsk", + "destination_arrival_time_1": "04:03", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "167": { + "route_id": 167, + "agency_id": "UZ", + "trip_short_name_0": "261", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "262", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Dnipro Holovny", + "origin_departure_time_0": "14:26", + "via_0": "Oleksandriia - Im.Tarasa Shevchenka - Bila Tserkva - Lviv - Ivano-Frankivsk", + "destination_trip_0": "Chernivtsi", + "destination_arrival_time_0": "21:46", + "origin_trip_1": "Chernivtsi", + "origin_departure_time_1": "17:11", + "via_1": "Ivano-Frankivsk - Lviv - Bila Tserkva - Im.Tarasa Shevchenka - Oleksandriia", + "destination_trip_1": "Dnipro Holovny", + "destination_arrival_time_1": "12:07", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "168": { + "route_id": 168, + "agency_id": "UZ", + "trip_short_name_0": "007 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "008 L", + "service_id_1": "2026: Daily", + "route_long_name": "Bukovyna", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "22:00", + "via_0": "Lviv - Ivano-Frankivsk", + "destination_trip_0": "Chernivtsi", + "destination_arrival_time_0": "09:23", + "origin_trip_1": "Chernivtsi", + "origin_departure_time_1": "19:37", + "via_1": "Ivano-Frankivsk - Lviv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "08:28", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "170": { + "route_id": 170, + "agency_id": "UZ", + "trip_short_name_0": "079", + "service_id_0": "2026: Daily", + "trip_short_name_1": "080", + "service_id_1": "2026: Daily", + "route_long_name": "Sicheslav", + "origin_trip_0": "Dnipro Holovny", + "origin_departure_time_0": "22:15", + "via_0": "Oleksandriia - Kyiv Pasazhyrskyi", + "destination_trip_0": "Lviv", + "destination_arrival_time_0": "13:49", + "origin_trip_1": "Lviv", + "origin_departure_time_1": "15:14", + "via_1": "Kyiv Pasazhyrskyi - Oleksandriia", + "destination_trip_1": "Dnipro Holovny", + "destination_arrival_time_1": "06:06", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "172": { + "route_id": 172, + "agency_id": "UZ", + "trip_short_name_0": "076 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "076 P", + "service_id_1": "2026: Daily", + "route_long_name": "Kryvorizhzhia", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "21:57", + "via_0": "Im.Tarasa Shevchenka", + "destination_trip_0": "Kryvyi Rih", + "destination_arrival_time_0": "05:05", + "origin_trip_1": "Kryvyi Rih", + "origin_departure_time_1": "23:31", + "via_1": "Im.Tarasa Shevchenka", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "06:30", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "173": { + "route_id": 173, + "agency_id": "UZ", + "trip_short_name_0": "105", + "service_id_0": "2026: Daily", + "trip_short_name_1": "106", + "service_id_1": "2026: Daily", + "route_long_name": "Chornomorets", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "22:08", + "via_0": "Kozyatyn - Vinnytsia - Zhmerynka - Podilsk - Rozdil'na", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "06:53", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "22:05", + "via_1": "Rozdil'na - Podilsk - Zhmerynka - Vinnytsia - Kozyatyn", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "07:50", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "174": { + "route_id": 174, + "agency_id": "UZ", + "trip_short_name_0": "099", + "service_id_0": "2026: Daily", + "trip_short_name_1": "100", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "06:25", + "via_0": "Vinnytsia - Zhmerynka - Nicolina - Iași - Mizil - Ploiești Sud", + "destination_trip_0": "București Nord", + "destination_arrival_time_0": "06:38", + "origin_trip_1": "București Nord", + "origin_departure_time_1": "19:06", + "via_1": "Ploiești Sud - Mizil - Buzău - Focșani - Adjud - Bacău - Roman - Zhmerynka - Vinnytsia", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "20:08", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "175": { + "route_id": 175, + "agency_id": "UZ", + "trip_short_name_0": "177 L", + "service_id_0": "2026: Daily", + "trip_short_name_1": "207 O", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Ivano-Frankivsk", + "origin_departure_time_0": "07:53", + "via_0": "Lviv", + "destination_trip_0": "Kyiv Pasazhyrskyi", + "destination_arrival_time_0": "17:44", + "origin_trip_1": "Kyiv Pasazhyrskyi", + "origin_departure_time_1": "22:00", + "via_1": "non-stop - Lviv", + "destination_trip_1": "Ivano-Frankivsk", + "destination_arrival_time_1": "07:08", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "177": { + "route_id": 177, + "agency_id": "UZ", + "trip_short_name_0": "143", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "144", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Sumy", + "origin_departure_time_0": "11:00", + "via_0": "Konotop - Kyiv Pasazhyrskyi - Vinnytsia - Khmelnytskyi - Ternopil - Lviv - Ivano-Frankivsk - Vorokhta - Yasinia", + "destination_trip_0": "Rakhiv", + "destination_arrival_time_0": "08:40", + "origin_trip_1": "Rakhiv", + "origin_departure_time_1": "13:26", + "via_1": "Yasinia - Vorokhta - Ivano-Frankivsk - Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Kyiv Pasazhyrskyi - Konotop", + "destination_trip_1": "Sumy", + "destination_arrival_time_1": "10:20", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "178": { + "route_id": 178, + "agency_id": "UZ", + "trip_short_name_0": "043 L", + "service_id_0": "2026: Daily", + "trip_short_name_1": "043 Š", + "service_id_1": "2026: Daily", + "route_long_name": "Stefania express", + "origin_trip_0": "Ivano-Frankivsk", + "origin_departure_time_0": "19:08", + "via_0": "Kalush - Stryj - Lviv - Kyiv Pasazhyrskyi", + "destination_trip_0": "Cherkasy", + "destination_arrival_time_0": "11:17", + "origin_trip_1": "Cherkasy", + "origin_departure_time_1": "15:17", + "via_1": "Kyiv Pasazhyrskyi - Lviv - Stryj - Kalush", + "destination_trip_1": "Ivano-Frankivsk", + "destination_arrival_time_1": "08:10", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "180": { + "route_id": 180, + "agency_id": "UZ", + "trip_short_name_0": "139", + "service_id_0": "2026: Tue, Fri, Sun", + "trip_short_name_1": "140", + "service_id_1": "2026: Mon, Wed, Sat", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "23:47", + "via_0": "Fastiv - Kozyatyn - Khmelnytskyi Hrechany", + "destination_trip_0": "Kamianets-Podilskyi", + "destination_arrival_time_0": "10:15", + "origin_trip_1": "Kamianets-Podilskyi", + "origin_departure_time_1": "18:55", + "via_1": "Khmelnytskyi Hrechany - Kozyatyn - Fastiv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "05:01", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "181": { + "route_id": 181, + "agency_id": "UZ", + "trip_short_name_0": "067", + "service_id_0": "2026: Daily", + "trip_short_name_1": "068", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "19:06", + "via_0": "Kovel - Chelm - Lublin - Warszawa Wschodnia - Warszawa Centralna", + "destination_trip_0": "Warszawa Zachodnia", + "destination_arrival_time_0": "09:53", + "origin_trip_1": "Warszawa Zachodnia", + "origin_departure_time_1": "18:15", + "via_1": "Warszawa Centralna - Warszawa Wschodnia - Lublin - Chelm - Kovel", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "10:45", + "picture": "", + "irregularities_0": "Quickly booked out", + "irregularities_1": "Quickly booked out" + }, + "182": { + "route_id": 182, + "agency_id": "UZ", + "trip_short_name_0": "097", + "service_id_0": "2026: Daily", + "trip_short_name_1": "098", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "23:08", + "via_0": "Rivne - Kivertsi - Lutsk", + "destination_trip_0": "Kovel", + "destination_arrival_time_0": "08:53", + "origin_trip_1": "Kovel", + "origin_departure_time_1": "19:15", + "via_1": "Lutsk - Kivertsi - Rivne", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "05:57", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "183": { + "route_id": 183, + "agency_id": "UZ", + "trip_short_name_0": "009", + "service_id_0": "2026: Daily", + "trip_short_name_1": "010", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "09:43", + "via_0": "Lviv - Mukacheve - Chop - Nyíregyháza - Szolnok", + "destination_trip_0": "Budapest Keleti", + "destination_arrival_time_0": "06:00", + "origin_trip_1": "Budapest Keleti", + "origin_departure_time_1": "22:40", + "via_1": "Szolnok - Debrecen - Chop - Mukacheve - Lviv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "19:54", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "184": { + "route_id": 184, + "agency_id": "UZ", + "trip_short_name_0": "113", + "service_id_0": "2026: 2-3 times per week", + "trip_short_name_1": "114", + "service_id_1": "2026: 2-3 times per week", + "route_long_name": "", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "23:01", + "via_0": "Poltava - Myrhorod - Kyiv Pasazhyrskyi - Fastiv - Zhytomyr - Rivne - Kivertsi - Lutsk - Kovel - Lviv - Stryj - Mukacheve - Chop", + "destination_trip_0": "Uzhhorod", + "destination_arrival_time_0": "07:02", + "origin_trip_1": "Uzhhorod", + "origin_departure_time_1": "22:43", + "via_1": "Chop - Mukacheve - Stryj - Lviv - Kovel - Kivertsi - Lutsk - Rivne - Zhytomyr - Fastiv - Kyiv Pasazhyrskyi - Myrhorod - Myrhorod", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "06:58", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "185": { + "route_id": 185, + "agency_id": "UZ", + "trip_short_name_0": "049", + "service_id_0": "2026: Daily", + "trip_short_name_1": "050", + "service_id_1": "2026: Daily", + "route_long_name": "Kobzar", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "21:47", + "via_0": "Lviv", + "destination_trip_0": "Truskavets", + "destination_arrival_time_0": "08:00", + "origin_trip_1": "Truskavets", + "origin_departure_time_1": "20:58", + "via_1": "Lviv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "06:51", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "186": { + "route_id": 186, + "agency_id": "UZ", + "trip_short_name_0": "029 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "029 L", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "20:20", + "via_0": "Lviv - Mukacheve", + "destination_trip_0": "Uzhhorod", + "destination_arrival_time_0": "08:27", + "origin_trip_1": "Uzhhorod", + "origin_departure_time_1": "19:07", + "via_1": "Mukacheve - Lviv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "08:28", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "189": { + "route_id": 189, + "agency_id": "UZ", + "trip_short_name_0": "038 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "038 P", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "22:13", + "via_0": "Im.Tarasa Shevchenka - Dnipro Holovny", + "destination_trip_0": "Zaporizhzhia 1", + "destination_arrival_time_0": "07:22", + "origin_trip_1": "Zaporizhzhia 1", + "origin_departure_time_1": "20:29", + "via_1": "Dnipro Holovny - Im.Tarasa Shevchenka", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "05:52", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "190": { + "route_id": 190, + "agency_id": "UZ", + "trip_short_name_0": "059 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "060 L", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "20:28", + "via_0": "Kozyatyn - Vinnytsia - Khmelnytskyi - Lviv - Uzhhorod", + "destination_trip_0": "Chop", + "destination_arrival_time_0": "12:48", + "origin_trip_1": "Chop", + "origin_departure_time_1": "14:58", + "via_1": "Uzhhorod - Sambir - Lviv - Vinnytsia - Kozyatyn", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "09:42", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "191": { + "route_id": 191, + "agency_id": "UZ", + "trip_short_name_0": "012 L", + "service_id_0": "2026: Daily", + "trip_short_name_1": "012 Š", + "service_id_1": "2026: Daily", + "route_long_name": "Zachidny express", + "origin_trip_0": "Lviv", + "origin_departure_time_0": "21:08", + "via_0": "Lviv Pidzamche - Ternopil - Khmelnytskyi - Zhmerynka - Kodyma - Podilsk - Rozdil'na", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "07:59", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "21:15", + "via_1": "Podilsk - Zhmerynka - Khmelnytskyi - Ternopil - Lviv Pidzamche", + "destination_trip_1": "Lviv", + "destination_arrival_time_1": "06:18", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "195": { + "route_id": 195, + "agency_id": "UZ\/CFM", + "trip_short_name_0": "351 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "351 L", + "service_id_1": "2026: Daily", + "route_long_name": "Bessarabia", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "18:06", + "via_0": "Vinnytsia - Zhmerynka - Vălcineț - Bălți Oras", + "destination_trip_0": "Chişinău", + "destination_arrival_time_0": "11:53", + "origin_trip_1": "Chişinău", + "origin_departure_time_1": "17:42", + "via_1": "Bălți Oras - Vălcineț - Zhmerynka - Vinnytsia", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "11:17", + "picture": "", + "irregularities_0": "Daily from 2026-06-28", + "irregularities_1": "Daily from 2026-06-28" + }, + "196": { + "route_id": 196, + "agency_id": "UZ", + "trip_short_name_0": "132 L", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "132 O", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Mukacheve", + "origin_departure_time_0": "17:04", + "via_0": "Stryj - Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Kyiv Pasazhyrskyi - Lubny", + "destination_trip_0": "Kremenchuk", + "destination_arrival_time_0": "12:23", + "origin_trip_1": "Kremenchuk", + "origin_departure_time_1": "17:37", + "via_1": "Lubny - Kyiv Pasazhyrskyi - Vinnytsia - Khmelnytskyi - Ternopil - Lviv - Stryj", + "destination_trip_1": "Mukacheve", + "destination_arrival_time_1": "11:20", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "197": { + "route_id": 197, + "agency_id": "UZ", + "trip_short_name_0": "091", + "service_id_0": "2026: Daily", + "trip_short_name_1": "092", + "service_id_1": "2026: Daily", + "route_long_name": "Leopolis", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "22:17", + "via_0": "Lviv Pidzamche", + "destination_trip_0": "Lviv", + "destination_arrival_time_0": "06:44", + "origin_trip_1": "Lviv", + "origin_departure_time_1": "23:08", + "via_1": "Lviv Pidzamche", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "06:58", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "198": { + "route_id": 198, + "agency_id": "UZ", + "trip_short_name_0": "055", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "056", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "16:29", + "via_0": "Fastiv - Kozyatyn - Vinnytsia - Khmelnytskyi - Ternopil - Lviv - Ivano-Frankivsk - Vorokhta - Yasinia", + "destination_trip_0": "Rakhiv", + "destination_arrival_time_0": "07:50", + "origin_trip_1": "Rakhiv", + "origin_departure_time_1": "17:13", + "via_1": "Yasinia - Vorokhta - Ivano-Frankivsk - Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Fastiv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "09:24", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "199": { + "route_id": 199, + "agency_id": "UZ", + "trip_short_name_0": "095", + "service_id_0": "2026: Daily", + "trip_short_name_1": "096", + "service_id_1": "2026: Daily", + "route_long_name": "Gutsulshchina", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "20:38", + "via_0": "Lviv - Ivano-Frankivsk - Vorokhta - Yasinia", + "destination_trip_0": "Rakhiv", + "destination_arrival_time_0": "09:27", + "origin_trip_1": "Rakhiv", + "origin_departure_time_1": "21:14", + "via_1": "Yasinia - Vorokhta - Ivano-Frankivsk - Lviv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "10:57", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "200": { + "route_id": 200, + "agency_id": "UZ", + "trip_short_name_0": "121", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "122", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Mykolaiv", + "origin_departure_time_0": "20:04", + "via_0": "Im.Tarasa Shevchenka", + "destination_trip_0": "Kyiv Pasazhyrskyi", + "destination_arrival_time_0": "05:27", + "origin_trip_1": "Kyiv Pasazhyrskyi", + "origin_departure_time_1": "20:29", + "via_1": "Im.Tarasa Shevchenka", + "destination_trip_1": "Mykolaiv", + "destination_arrival_time_1": "05:01", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "201": { + "route_id": 201, + "agency_id": "UZ", + "trip_short_name_0": "233", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "234", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Chernivtsi", + "origin_departure_time_0": "17:11", + "via_0": "Ivano-Frankivsk - Lviv - Bila Tserkva - Im.Tarasa Shevchenka", + "destination_trip_0": "Kryvyi Rih", + "destination_arrival_time_0": "11:08", + "origin_trip_1": "Kryvyi Rih", + "origin_departure_time_1": "15:06", + "via_1": "Im.Tarasa Shevchenka - Bila Tserkva - Lviv - Ivano-Frankivsk", + "destination_trip_1": "Chernivtsi", + "destination_arrival_time_1": "10:06", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "203": { + "route_id": 203, + "agency_id": "UZ", + "trip_short_name_0": "013 K", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "013 L", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "16:29", + "via_0": "Fastiv - Kozyatyn - Vinnytsia - Khmelnytskyi - Ternopil - Lviv - Stryj - Mukacheve", + "destination_trip_0": "Solotvyno", + "destination_arrival_time_0": "10:58", + "origin_trip_1": "Solotvyno", + "origin_departure_time_1": "14:56", + "via_1": "Mukacheve - Stryj - Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Kozyatyn - Fastiv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "09:24", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "207": { + "route_id": 207, + "agency_id": "UZ", + "trip_short_name_0": "052 P\/053", + "service_id_0": "2026: Daily", + "trip_short_name_1": "052 Š\/054", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Dnipro Holovny", + "origin_departure_time_0": "21:03", + "via_0": "Oleksandriia - Kropyvnytskyi - Voznesens'k", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "08:19", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "21:05", + "via_1": "Voznesens'k - Kropyvnytskyi - Oleksandriia", + "destination_trip_1": "Dnipro Holovny", + "destination_arrival_time_1": "08:56", + "picture": "", + "irregularities_0": "052 P departs from Zaporizhzhia", + "irregularities_1": "052 Š continues to Zaporizhzhia" + }, + "208": { + "route_id": 208, + "agency_id": "UZ", + "trip_short_name_0": "093", + "service_id_0": "2026: Daily", + "trip_short_name_1": "094", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Kharkiv", + "origin_departure_time_0": "16:50", + "via_0": "Poltava - Myrhorod - Kyiv Pasazhyrskyi - Rivne - Kivertsi - Kovel", + "destination_trip_0": "Chelm", + "destination_arrival_time_0": "10:47", + "origin_trip_1": "Chelm", + "origin_departure_time_1": "17:15", + "via_1": "Kovel - Kivertsi - Rivne - Kyiv Pasazhyrskyi - Myrhorod - Poltava", + "destination_trip_1": "Kharkiv", + "destination_arrival_time_1": "12:16", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "209": { + "route_id": 209, + "agency_id": "UZ", + "trip_short_name_0": "088 L", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "088 P", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Kovel", + "origin_departure_time_0": "17:48", + "via_0": "Kivertsi - Lutsk - Rivne - Kozyatyn - Bila Tserkva - Im.Tarasa Shevchenka - Oleksandriia", + "destination_trip_0": "Dnipro Holovny", + "destination_arrival_time_0": "11:38", + "origin_trip_1": "Dnipro Holovny", + "origin_departure_time_1": "17:42", + "via_1": "Oleksandriia - Im.Tarasa Shevchenka - Bila Tserkva - Kozyatyn - Rivne - Lutsk", + "destination_trip_1": "Kovel", + "destination_arrival_time_1": "13:40", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "210": { + "route_id": 210, + "agency_id": "UZ", + "trip_short_name_0": "148 K", + "service_id_0": "2026: Tue, Thu, Sun", + "trip_short_name_1": "148 Š", + "service_id_1": "2026: Mon, Wed, Fri", + "route_long_name": "", + "origin_trip_0": "Odesa Holovna", + "origin_departure_time_0": "19:34", + "via_0": "Voznesens'k - Im.Tarasa Shevchenka - Cherkasy", + "destination_trip_0": "Kyiv Pasazhyrskyi", + "destination_arrival_time_0": "09:07", + "origin_trip_1": "Kyiv Pasazhyrskyi", + "origin_departure_time_1": "19:32", + "via_1": "Cherkasy - Im.Tarasa Shevchenka - Voznesens'k", + "destination_trip_1": "Odesa Holovna", + "destination_arrival_time_1": "08:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "211": { + "route_id": 211, + "agency_id": "UZ", + "trip_short_name_0": "086 L", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "086 P", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Lviv", + "origin_departure_time_0": "13:46", + "via_0": "Ternopil - Khmelnytskyi - Vinnytsia - Oleksandriia - Dnipro Holovny", + "destination_trip_0": "Zaporizhzhia 1", + "destination_arrival_time_0": "10:40", + "origin_trip_1": "Zaporizhzhia 1", + "origin_departure_time_1": "18:52", + "via_1": "Dnipro Holovny - Oleksandriia - Vinnytsia - Khmelnytskyi - Ternopil", + "destination_trip_1": "Lviv", + "destination_arrival_time_1": "13:48", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "212": { + "route_id": 212, + "agency_id": "UZ", + "trip_short_name_0": "128 L", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "128 P", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Lviv", + "origin_departure_time_0": "15:00", + "via_0": "Lviv Pidzamche - Ternopil - Khmelnytskyi - Zhmerynka - Kodyma - Kropyvnytskyi - Oleksandriia - Kryvyi Rih - Dnipro Holovny", + "destination_trip_0": "Zaporizhzhia 1", + "destination_arrival_time_0": "15:46", + "origin_trip_1": "Zaporizhzhia 1", + "origin_departure_time_1": "12:04", + "via_1": "Dnipro Holovny - Kryvyi Rih - Oleksandriia - Kropyvnytskyi - Kodyma - Zhmerynka - Khmelnytskyi - Ternopil - Lviv Pidzamche", + "destination_trip_1": "Lviv", + "destination_arrival_time_1": "12:29", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "213": { + "route_id": 213, + "agency_id": "UZ", + "trip_short_name_0": "109", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "110", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Mykolaiv", + "origin_departure_time_0": "17:08", + "via_0": "Im.Tarasa Shevchenka - Vinnytsia - Khmelnytskyi - Ternopil", + "destination_trip_0": "Lviv", + "destination_arrival_time_0": "11:53", + "origin_trip_1": "Lviv", + "origin_departure_time_1": "16:01", + "via_1": "Ternopil - Khmelnytskyi - Vinnytsia - Im.Tarasa Shevchenka", + "destination_trip_1": "Mykolaiv", + "destination_arrival_time_1": "09:05", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "218": { + "route_id": 218, + "agency_id": "UZ", + "trip_short_name_0": "037", + "service_id_0": "2026: Daily", + "trip_short_name_1": "038 O\/Š", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Uzhhorod", + "origin_departure_time_0": "20:17", + "via_0": "Mukacheve - Stryj - Lviv - Ternopil - Khmelnytskyi - Zhmerynka - Podilsk - Rozdil'na", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "13:03", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "17:04", + "via_1": "Rozdil'na - Podilsk - Zhmerynka - Khmelnytskyi - Ternopil - Lviv - Stryj - Mukacheve", + "destination_trip_1": "Uzhhorod", + "destination_arrival_time_1": "10:56", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "219": { + "route_id": 219, + "agency_id": "UZ", + "trip_short_name_0": "136 L", + "service_id_0": "2026: Daily", + "trip_short_name_1": "136 Š", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Chernivtsi", + "origin_departure_time_0": "14:55", + "via_0": "Ivano-Frankivsk - Lviv - Ternopil - Khmelnytskyi - Zhmerynka - Podilsk", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "08:38", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "18:38", + "via_1": "Podilsk - Zhmerynka - Khmelnytskyi - Ternopil - Lviv - Ivano-Frankivsk", + "destination_trip_1": "Chernivtsi", + "destination_arrival_time_1": "11:23", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "220": { + "route_id": 220, + "agency_id": "UZ", + "trip_short_name_0": "003", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "004", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Uzhhorod", + "origin_departure_time_0": "16:40", + "via_0": "Mukacheve - Stryj - Lviv - Bila Tserkva - Im.Tarasa Shevchenka - Oleksandriia", + "destination_trip_0": "Dnipro Holovny", + "destination_arrival_time_0": "13:00", + "origin_trip_1": "Dnipro Holovny", + "origin_departure_time_1": "20:00", + "via_1": "Im.Tarasa Shevchenka - Bila Tserkva - Lviv - Stryj - Mukacheve", + "destination_trip_1": "Uzhhorod", + "destination_arrival_time_1": "14:54", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "221": { + "route_id": 221, + "agency_id": "UZ", + "trip_short_name_0": "006 L", + "service_id_0": "2026: Daily", + "trip_short_name_1": "006 P", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Yasinia", + "origin_departure_time_0": "13:05", + "via_0": "Vorokhta - Ivano-Frankivsk - Lviv - Bila Tserkva - Im.Tarasa Shevchenka - Dnipro Holovny", + "destination_trip_0": "Zaporizhzhia 1", + "destination_arrival_time_0": "10:40", + "origin_trip_1": "Zaporizhzhia 1", + "origin_departure_time_1": "13:50", + "via_1": "Dnipro Holovny - Oleksandriia - Im.Tarasa Shevchenka - Bila Tserkva - Lviv - Ivano-Frankivsk - Vorokhta", + "destination_trip_1": "Yasinia", + "destination_arrival_time_1": "12:11", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "222": { + "route_id": 222, + "agency_id": "UZ", + "trip_short_name_0": "078 L", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "078 Š", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Kovel", + "origin_departure_time_0": "17:48", + "via_0": "Kivertsi - Lutsk - Rivne - Kozyatyn - Vinnytsia - Podilsk - Rozdil'na", + "destination_trip_0": "Odesa Holovna", + "destination_arrival_time_0": "09:17", + "origin_trip_1": "Odesa Holovna", + "origin_departure_time_1": "19:46", + "via_1": "Rozdil'na - Podilsk - Vinnytsia - Kozyatyn - Rivne - Kivertsi - Lutsk", + "destination_trip_1": "Kovel", + "destination_arrival_time_1": "11:48", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "223": { + "route_id": 223, + "agency_id": "MÁV", + "trip_short_name_0": "1246 \/ 1605", + "service_id_0": "2026\/06\/26-08\/29: Daily", + "trip_short_name_1": "1604 \/ 1247", + "service_id_1": "2026\/06\/26-08\/29: Daily", + "route_long_name": "Istria", + "origin_trip_0": "Budapest Keleti", + "origin_departure_time_0": "21:30", + "via_0": "Budapest Kelenföld - Vesprem - Zalaegerszeg - Ljubljana", + "destination_trip_0": "Koper", + "destination_arrival_time_0": "08:59", + "origin_trip_1": "Koper", + "origin_departure_time_1": "18:50", + "via_1": "Ljubljana - Zalaegerszeg - Vesprem - Budapest Kelenföld", + "destination_trip_1": "Budapest Keleti", + "destination_arrival_time_1": "07:28", + "picture": "", + "irregularities_0": "seasonal", + "irregularities_1": "seasonal" + }, + "224": { + "route_id": 224, + "agency_id": "MÁV", + "trip_short_name_0": "1246 \/ 481", + "service_id_0": "2026\/06\/26-08\/29: Daily", + "trip_short_name_1": "480 \/ 1247", + "service_id_1": "2026\/06\/26-08\/29: Daily", + "route_long_name": "Istria", + "origin_trip_0": "Budapest Keleti", + "origin_departure_time_0": "21:30", + "via_0": "Budapest Kelenföld - Vesprem - Zalaegerszeg - Ljubljana - Opatija Matulji", + "destination_trip_0": "Rijeka", + "destination_arrival_time_0": "10:04", + "origin_trip_1": "Rijeka", + "origin_departure_time_1": "19:07", + "via_1": "Opatija Matulji - Ljubljana - Zalaegerszeg - Vesprem - Budapest Kelenföld", + "destination_trip_1": "Budapest Keleti", + "destination_arrival_time_1": "07:28", + "picture": "", + "irregularities_0": "seasonal", + "irregularities_1": "seasonal" + }, + "225": { + "route_id": 225, + "agency_id": "MÁV", + "trip_short_name_0": "IC 1204", + "service_id_0": "2026: summer only, to be announced", + "trip_short_name_1": "IC 1205", + "service_id_1": "2026: summer only, to be announced", + "route_long_name": "Adria", + "origin_trip_0": "Budapest Keleti", + "origin_departure_time_0": "00:00", + "via_0": "Budapest Kelenföld - Székesfehérvár - Siófok - Nagykanizsa - Zagreb Gl. K. - Karlovac - Knin", + "destination_trip_0": "Split", + "destination_arrival_time_0": "00:00", + "origin_trip_1": "Split", + "origin_departure_time_1": "00:00", + "via_1": "Knin - Karlovac - Zagreb Gl. K. - Nagykanizsa - Siófok - Székesfehérvár - Budapest Kelenföld", + "destination_trip_1": "Budapest Keleti", + "destination_arrival_time_1": "00:00", + "picture": "", + "irregularities_0": "seasonal", + "irregularities_1": "seasonal" + }, + "227": { + "route_id": 227, + "agency_id": "UZ", + "trip_short_name_0": "081 K", + "service_id_0": "2026: Daily", + "trip_short_name_1": "081 L", + "service_id_1": "2026: Daily", + "route_long_name": "Desna", + "origin_trip_0": "Kyiv Pasazhyrskyi", + "origin_departure_time_0": "17:41", + "via_0": "Fastiv - Kozyatyn - Vinnytsia - Khmelnytskyi - Ternopil - Lviv - Stryj - Mukacheve - Chop", + "destination_trip_0": "Uzhhorod", + "destination_arrival_time_0": "10:20", + "origin_trip_1": "Uzhhorod", + "origin_departure_time_1": "16:20", + "via_1": "Chop - Mukacheve - Stryj - Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Kozyatyn - Fastiv", + "destination_trip_1": "Kyiv Pasazhyrskyi", + "destination_arrival_time_1": "09:58", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "229": { + "route_id": 229, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 446", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 447", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Wien Hbf", + "origin_departure_time_0": "22:44", + "via_0": "Wien Meidling - St. Pölten Hbf - Amstetten (NÖ) - Linz Hbf - Wels Hbf - Attnang-Puchheim - Vöcklabruck - Salzburg Hbf - Innsbruck Hbf - Telfs-Pfaffenhofen - Ötztal - Imst-Pitztal - Landeck-Zams - St. Anton am Arlberg - Langen am Arlberg - Bludenz - Feldkirch - Rankweil - Götzis - Hohenems - Dornbirn", + "destination_trip_0": "Bregenz", + "destination_arrival_time_0": "08:57", + "origin_trip_1": "Bregenz", + "origin_departure_time_1": "21:40", + "via_1": "Dornbirn - Hohenems - Götzis - Rankweil - Feldkirch - Bludenz - Langen am Arlberg - St. Anton am Arlberg - Landeck-Zams - Imst-Pitztal - Ötztal - Innsbruck Hbf - Salzburg Hbf - Vöcklabruck - Attnang-Puchheim - Wels Hbf - Linz Hbf - St. Valentin - Amstetten (NÖ) - St. Pölten Hbf - Wien Meidling", + "destination_trip_1": "Wien Hbf", + "destination_arrival_time_1": "06:58", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "232": { + "route_id": 232, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 40233", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 40294", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Wien Hbf", + "origin_departure_time_0": "20:05", + "via_0": "Wien Meidling - Wiener Neustadt Hbf - Graz Hbf - Klagenfurt Hbf - Villach Hbf - Tarvisio Boscoverde - Bologna Centrale - Firenze Campo di Marte", + "destination_trip_0": "Roma Tiburtina", + "destination_arrival_time_0": "10:05", + "origin_trip_1": "Roma Tiburtina", + "origin_departure_time_1": "18:10", + "via_1": "Firenze Campo di Marte - Bologna Centrale - Tarvisio Boscoverde - Villach Hbf - Klagenfurt Hbf - Graz Hbf - Wiener Neustadt Hbf - Wien Meidling", + "destination_trip_1": "Wien Hbf", + "destination_arrival_time_1": "08:52", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "233": { + "route_id": 233, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 40236", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 40466", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Venezia Santa Lucia", + "origin_departure_time_0": "21:05", + "via_0": "Venezia Mestre - Treviso Centrale - Conegliano - Pordenone - Udine - Tarvisio Boscoverde - Villach Hbf - Salzburg Hbf - Attnang-Puchheim - Wels Hbf - Linz Hbf - Amstetten (NÖ) - St. Pölten Hbf - Wien Meidling", + "destination_trip_0": "Wien Hbf", + "destination_arrival_time_0": "08:17", + "origin_trip_1": "Wien Hbf", + "origin_departure_time_1": "21:39", + "via_1": "Wien Meidling - St. Pölten Hbf - Amstetten (NÖ) - Linz Hbf - Wels Hbf - Attnang-Puchheim - Salzburg Hbf - Villach Hbf - Tarvisio Boscoverde - Udine - Pordenone - Conegliano - Treviso Centrale - Venezia Mestre", + "destination_trip_1": "Venezia Santa Lucia", + "destination_arrival_time_1": "08:34", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "235": { + "route_id": 235, + "agency_id": "ÖBB", + "trip_short_name_0": "NJ 464", + "service_id_0": "2026: Daily", + "trip_short_name_1": "NJ 465", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Graz Hbf", + "origin_departure_time_0": "21:43", + "via_0": "non-stop - St. Paul im Lavanttal - Kühnsdorf Klopeiner See - Klagenfurt Hbf - Pörtschach am Wörthersee - Velden am Wörthersee - Villach Hbf - Spittal-Millstättersee - Mallnitz-Obervellach - Bad Gastein - Bad Hofgastein - Dorfgastein - Schwarzach-St.Veit - Innsbruck Hbf - Landeck-Zams - St. Anton am Arlberg - Langen am Arlberg - Bludenz - Feldkirch - Buchs (SG) - Sargans", + "destination_trip_0": "Zürich HB", + "destination_arrival_time_0": "09:20", + "origin_trip_1": "Zürich HB", + "origin_departure_time_1": "20:40", + "via_1": "Sargans - Buchs (SG) - Feldkirch - Bludenz - Langen am Arlberg - St. Anton am Arlberg - Landeck-Zams - Innsbruck Hbf - Wörgl Hbf - Schwarzach-St.Veit - Dorfgastein - Bad Hofgastein - Bad Gastein - Mallnitz-Obervellach - Spittal-Millstättersee - Villach Hbf - Velden am Wörthersee - Pörtschach am Wörthersee - Klagenfurt Hbf - Kühnsdorf Klopeiner See - St. Paul im Lavanttal", + "destination_trip_1": "Graz Hbf", + "destination_arrival_time_1": "08:28", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2023\/11\/NJnG-Thumb_SB8.jpg", + "irregularities_0": "", + "irregularities_1": "" + }, + "237": { + "route_id": 237, + "agency_id": "ES", + "trip_short_name_0": "452", + "service_id_0": "2026: Tue, Thu, Sun", + "trip_short_name_1": "453", + "service_id_1": "2026: Mon, Wed, Fri", + "route_long_name": "", + "origin_trip_0": "Praha hl.n.", + "origin_departure_time_0": "18:04", + "via_0": "Ústí nad Labem hl.n. - Děčín hl.n. - Bad Schandau - Dresden Hbf - Dresden Neustadt - Berlin Hbf - Deventer - Amersfoort Centraal - Amsterdam Centraal - Rotterdam Centraal - Antwerpen Centraal \/ Anvers Central", + "destination_trip_0": "Bruxelles Midi \/ Brussel Zuid", + "destination_arrival_time_0": "09:27", + "origin_trip_1": "Bruxelles Midi \/ Brussel Zuid", + "origin_departure_time_1": "19:22", + "via_1": "Antwerpen Centraal \/ Anvers Central - Rotterdam Centraal - Den Haag - Schipol Airport - Amsterdam Centraal - Amersfoort Centraal - Deventer - Berlin Hbf - Dresden Neustadt - Dresden Hbf - Bad Schandau - Děčín hl.n. - Ústí nad Labem hl.n.", + "destination_trip_1": "Praha hl.n.", + "destination_arrival_time_1": "10:45", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_ES.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "238": { + "route_id": 238, + "agency_id": "ES", + "trip_short_name_0": "474", + "service_id_0": "2026: Mon, Wed, Fri", + "trip_short_name_1": "475", + "service_id_1": "2026: Tue, Thu, Sun", + "route_long_name": "", + "origin_trip_0": "Berlin Hbf", + "origin_departure_time_0": "18:31", + "via_0": "Liège Guillemins \/ Luik Guillemins - Bruxelles Midi \/ Brussel Zuid - Mons \/ Bergen - Aulnoye-Aymeries", + "destination_trip_0": "Paris Gare du Nord", + "destination_arrival_time_0": "10:00", + "origin_trip_1": "Paris Gare du Nord", + "origin_departure_time_1": "17:45", + "via_1": "Aulnoye-Aymeries - Bruxelles Midi \/ Brussel Zuid - Liège Guillemins \/ Luik Guillemins", + "destination_trip_1": "Berlin Hbf", + "destination_arrival_time_1": "09:59", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_ES.jpeg", + "irregularities_0": "", + "irregularities_1": "" + }, + "239": { + "route_id": 239, + "agency_id": "ES", + "trip_short_name_0": "454", + "service_id_0": "", + "trip_short_name_1": "455", + "service_id_1": "", + "route_long_name": "", + "origin_trip_0": "Amsterdam Centraal", + "origin_departure_time_0": "00:00", + "via_0": "Utrecht Centraal - Arnhem Centraal - Duisburg Hbf - Düsseldorf Hbf - Köln Süd - Basel SBB - Bern - Brig - Stresa", + "destination_trip_0": "Milano Centrale", + "destination_arrival_time_0": "00:00", + "origin_trip_1": "Milano Centrale", + "origin_departure_time_1": "00:00", + "via_1": "Stresa - Brig - Bern - Basel SBB - Köln Süd - Düsseldorf Hbf - Duisburg Hbf - Arnhem Centraal - Utrecht Centraal", + "destination_trip_1": "Amsterdam Centraal", + "destination_arrival_time_1": "00:00", + "picture": "https:\/\/back-on-track.eu\/wp-content\/uploads\/2025\/03\/800_CC-BY_back-on-track_eu_ES.jpeg", + "irregularities_0": "Postponed to 2027", + "irregularities_1": "Postponed to 2027" + }, + "240": { + "route_id": 240, + "agency_id": "ES", + "trip_short_name_0": "456", + "service_id_0": "2026: Mon, Thu, Sat", + "trip_short_name_1": "457", + "service_id_1": "2026: Wed, Fri, Sun", + "route_long_name": "", + "origin_trip_0": "Bruxelles Midi \/ Brussel Zuid", + "origin_departure_time_0": "17:56", + "via_0": "Liège Guillemins \/ Luik Guillemins - Aachen Hbf - Köln Süd - Zürich HB - Arth-Goldau - Göschenen - Bellinzona - Lugano - Chiasso - Como San Giovanni", + "destination_trip_0": "Milano Porta Garibaldi", + "destination_arrival_time_0": "11:30", + "origin_trip_1": "Milano Porta Garibaldi", + "origin_departure_time_1": "17:30", + "via_1": "Como San Giovanni - Chiasso - Lugano - Bellinzona - Göschenen - Arth-Goldau - Zürich HB - Köln Süd - Aachen Hbf - Liège Guillemins \/ Luik Guillemins", + "destination_trip_1": "Bruxelles Midi \/ Brussel Zuid", + "destination_arrival_time_1": "11:10", + "picture": "", + "irregularities_0": "From 2026-09-09", + "irregularities_1": "From 2026-09-10" + }, + "243": { + "route_id": 243, + "agency_id": "TCDD", + "trip_short_name_0": "22012", + "service_id_0": "2026: Thu, Sun", + "trip_short_name_1": "52011", + "service_id_1": "2026: Tue, Thu", + "route_long_name": "Vangölü Ekspresi", + "origin_trip_0": "Ankara", + "origin_departure_time_0": "11:20", + "via_0": "Kırıkkale - Kayseri - Sivas - Malatya - Elazığ - Mûş", + "destination_trip_0": "Tatvan", + "destination_arrival_time_0": "13:57", + "origin_trip_1": "Tatvan", + "origin_departure_time_1": "10:25", + "via_1": "Mûş - Elazığ - Malatya - Sivas - Kayseri - Kırıkkale", + "destination_trip_1": "Ankara", + "destination_arrival_time_1": "12:45", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "245": { + "route_id": 245, + "agency_id": "TCDD", + "trip_short_name_0": "22014", + "service_id_0": "2026: Mon, Wed, Thu, Fri, Sat", + "trip_short_name_1": "52013", + "service_id_1": "2026: Mon, Wed, Fri, Sat, Son", + "route_long_name": "Güney Ekspresi", + "origin_trip_0": "Ankara", + "origin_departure_time_0": "11:20", + "via_0": "Kırıkkale - Kayseri - Sivas - Diyarbakır - Batman", + "destination_trip_0": "Kurtalan", + "destination_arrival_time_0": "14:10", + "origin_trip_1": "Kurtalan", + "origin_departure_time_1": "09:20", + "via_1": "Batman - Diyarbakır - Sivas - Kayseri - Kırıkkale", + "destination_trip_1": "Ankara", + "destination_arrival_time_1": "12:45", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "246": { + "route_id": 246, + "agency_id": "TCDD", + "trip_short_name_0": "22018", + "service_id_0": "2026: Thu, Sat", + "trip_short_name_1": "52019", + "service_id_1": "2026: Fri, Sun", + "route_long_name": "4 Eylül Mavi", + "origin_trip_0": "Ankara", + "origin_departure_time_0": "19:10", + "via_0": "Kırıkkale - Sivas", + "destination_trip_0": "Malatya", + "destination_arrival_time_0": "11:09", + "origin_trip_1": "Malatya", + "origin_departure_time_1": "15:30", + "via_1": "Sivas - Kayseri - Kırıkkale", + "destination_trip_1": "Ankara", + "destination_arrival_time_1": "07:24", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "247": { + "route_id": 247, + "agency_id": "TCDD", + "trip_short_name_0": "22010", + "service_id_0": "2026: Daily", + "trip_short_name_1": "42009", + "service_id_1": "2026: Daily", + "route_long_name": "Dogu Ekspresi", + "origin_trip_0": "Ankara", + "origin_departure_time_0": "18:00", + "via_0": "Kırıkkale - Kayseri - Sivas - Erzincan - Erzurum", + "destination_trip_0": "Kars", + "destination_arrival_time_0": "20:26", + "origin_trip_1": "Kars", + "origin_departure_time_1": "08:00", + "via_1": "Erzurum - Erzincan - Sivas - Kayseri - Kırıkkale", + "destination_trip_1": "Ankara", + "destination_arrival_time_1": "10:27", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "248": { + "route_id": 248, + "agency_id": "TCDD", + "trip_short_name_0": "32007", + "service_id_0": "2026: Daily", + "trip_short_name_1": "72008", + "service_id_1": "2026: Daily", + "route_long_name": "Konya Mavi", + "origin_trip_0": "İzmir Basmane", + "origin_departure_time_0": "20:05", + "via_0": "İzmir Çiğli - Manisa - Afyon A Çetinkaya", + "destination_trip_0": "Konya", + "destination_arrival_time_0": "09:11", + "origin_trip_1": "Konya", + "origin_departure_time_1": "19:00", + "via_1": "Afyon A Çetinkaya - Manisa - İzmir Çiğli", + "destination_trip_1": "İzmir Basmane", + "destination_arrival_time_1": "08:05", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "249": { + "route_id": 249, + "agency_id": "CFR", + "trip_short_name_0": "R-E 4007\/IRN 12642", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 12641\/R-E 4008", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Bistrița Nord", + "origin_departure_time_0": "21:10", + "via_0": "Sărățel - Gheorgheni - Brașov - Câmpina - Ploiești Vest", + "destination_trip_0": "București Nord", + "destination_arrival_time_0": "06:22", + "origin_trip_1": "București Nord", + "origin_departure_time_1": "21:20", + "via_1": "Ploiești Vest - Brașov - Gheorgheni - Sărățel", + "destination_trip_1": "Bistrița Nord", + "destination_arrival_time_1": "06:15", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "250": { + "route_id": 250, + "agency_id": "CFR", + "trip_short_name_0": "IRN 12641\/IRN 1643", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IRN 1644\/IRN 12642", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "București Nord", + "origin_departure_time_0": "21:20", + "via_0": "Ploiești Vest - Brașov - Sighișoara", + "destination_trip_0": "Cluj-Napoca", + "destination_arrival_time_0": "07:10", + "origin_trip_1": "Cluj-Napoca", + "origin_departure_time_1": "20:06", + "via_1": "Sighișoara - Brașov - Câmpina - Ploiești Vest", + "destination_trip_1": "București Nord", + "destination_arrival_time_1": "06:22", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "252": { + "route_id": 252, + "agency_id": "UEX", + "trip_short_name_0": "320\/324", + "service_id_0": "2026: 0-2 days\/week (May-Oct)", + "trip_short_name_1": "321\/325", + "service_id_1": "2026: 0-2 days\/week (May-Oct)", + "route_long_name": "", + "origin_trip_0": "Villach Hbf-Autoverladestelle", + "origin_departure_time_0": "19:05", + "via_0": "Villach Hbf - Salzburg Hbf - München Ost - Fulda - Hannover Hbf - Hamburg Hbf", + "destination_trip_0": "Hamburg Altona", + "destination_arrival_time_0": "09:15", + "origin_trip_1": "Hamburg Altona", + "origin_departure_time_1": "19:00", + "via_1": "Hamburg Hbf - Hannover Hbf - Göttingen - Fulda - München Ost - Salzburg Hbf - Villach Hbf", + "destination_trip_1": "Villach Hbf-Autoverladestelle", + "destination_arrival_time_1": "08:58", + "picture": "", + "irregularities_0": "check schedule on the operator's website", + "irregularities_1": "check schedule on the operator's website" + }, + "253": { + "route_id": 253, + "agency_id": "UEX", + "trip_short_name_0": "302\/322", + "service_id_0": "2026: 0-2 days\/week (May-Oct)", + "trip_short_name_1": "303\/323", + "service_id_1": "2026: 0-2 days\/week (May-Oct)", + "route_long_name": "", + "origin_trip_0": "Innsbruck Hbf", + "origin_departure_time_0": "21:00", + "via_0": "Wörgl Hbf - Kufstein - München Ost - Hannover Hbf - Hamburg Hbf", + "destination_trip_0": "Hamburg Altona", + "destination_arrival_time_0": "08:33", + "origin_trip_1": "Hamburg Altona", + "origin_departure_time_1": "20:00", + "via_1": "Hamburg Hbf - Hannover Hbf - München Ost - Kufstein - Wörgl Hbf", + "destination_trip_1": "Innsbruck Hbf", + "destination_arrival_time_1": "08:20", + "picture": "", + "irregularities_0": "check schedule on the operator's website", + "irregularities_1": "check schedule on the operator's website" + }, + "254": { + "route_id": 254, + "agency_id": "UEX", + "trip_short_name_0": "1856", + "service_id_0": "2026: 0-2 days\/week (May-Oct)", + "trip_short_name_1": "1857", + "service_id_1": "2026: 0-2 days\/week (May-Oct)", + "route_long_name": "", + "origin_trip_0": "München Süd", + "origin_departure_time_0": "21:15", + "via_0": "Augsburg Hbf - Hannover Hbf - Hamburg Hbf", + "destination_trip_0": "Hamburg Altona", + "destination_arrival_time_0": "08:18", + "origin_trip_1": "Hamburg Altona", + "origin_departure_time_1": "21:19", + "via_1": "Hamburg Hbf - Hannover Hbf - Augsburg Hbf", + "destination_trip_1": "München Süd", + "destination_arrival_time_1": "07:11", + "picture": "", + "irregularities_0": "check schedule on the operator's website", + "irregularities_1": "check schedule on the operator's website" + }, + "255": { + "route_id": 255, + "agency_id": "UEX", + "trip_short_name_0": "1858", + "service_id_0": "2026: 0-2 days\/week (May-Oct)", + "trip_short_name_1": "1859", + "service_id_1": "2026: 0-2 days\/week (May-Oct)", + "route_long_name": "", + "origin_trip_0": "Lörrach Autoreisezug Terminal", + "origin_departure_time_0": "20:25", + "via_0": "Lörrach Hbf - Freiburg (Breisgau) Hbf - Karlsruhe Hbf - Hannover Hbf - Lüneburg - Hamburg Hbf", + "destination_trip_0": "Hamburg Altona", + "destination_arrival_time_0": "07:33", + "origin_trip_1": "Hamburg Altona", + "origin_departure_time_1": "21:34", + "via_1": "Hamburg Hbf - Hannover Hbf - Karlsruhe Hbf - Freiburg (Breisgau) Hbf - Lörrach Hbf", + "destination_trip_1": "Lörrach Autoreisezug Terminal", + "destination_arrival_time_1": "08:15", + "picture": "", + "irregularities_0": "check schedule on the operator's website", + "irregularities_1": "check schedule on the operator's website" + }, + "256": { + "route_id": 256, + "agency_id": "UEX", + "trip_short_name_0": "332\/1372", + "service_id_0": "2026: 0-2 days\/week (May-Oct)", + "trip_short_name_1": "333\/1373", + "service_id_1": "2026: 0-2 days\/week (May-Oct)", + "route_long_name": "", + "origin_trip_0": "Innsbruck Hbf", + "origin_departure_time_0": "21:00", + "via_0": "Wörgl Hbf - München Ost - Darmstadt Hbf - Koblenz - Köln Hbf", + "destination_trip_0": "Düsseldorf Hbf", + "destination_arrival_time_0": "07:25", + "origin_trip_1": "Düsseldorf Hbf", + "origin_departure_time_1": "20:45", + "via_1": "Köln Hbf - Koblenz - Mainz Hbf - München Ost - Wörgl Hbf", + "destination_trip_1": "Innsbruck Hbf", + "destination_arrival_time_1": "08:20", + "picture": "", + "irregularities_0": "check schedule on the operator's website", + "irregularities_1": "check schedule on the operator's website" + }, + "257": { + "route_id": 257, + "agency_id": "UEX", + "trip_short_name_0": "334\/1374", + "service_id_0": "2026: 0-2 days\/week (May-Oct)", + "trip_short_name_1": "335\/1375", + "service_id_1": "2026: 0-2 days\/week (May-Oct)", + "route_long_name": "", + "origin_trip_0": "Villach Hbf-Autoverladestelle", + "origin_departure_time_0": "19:05", + "via_0": "Villach Hbf - Salzburg Hbf - München Ost - Darmstadt Hbf - Koblenz - Köln Hbf", + "destination_trip_0": "Düsseldorf Hbf", + "destination_arrival_time_0": "08:33", + "origin_trip_1": "Düsseldorf Hbf", + "origin_departure_time_1": "19:51", + "via_1": "Köln Hbf - Koblenz - Aschaffenburg Hbf - München Ost - Salzburg Hbf", + "destination_trip_1": "Villach Hbf-Autoverladestelle", + "destination_arrival_time_1": "08:50", + "picture": "", + "irregularities_0": "check schedule on the operator's website", + "irregularities_1": "check schedule on the operator's website" + }, + "258": { + "route_id": 258, + "agency_id": "UZ", + "trip_short_name_0": "069", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "070", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Przemyśl Gł.", + "origin_departure_time_0": "16:20", + "via_0": "Lviv - Ternopil - Khmelnytskyi - Vinnytsia - Kyiv Pasazhyrskyi - Lubny", + "destination_trip_0": "Kremenchuk", + "destination_arrival_time_0": "12:23", + "origin_trip_1": "Kremenchuk", + "origin_departure_time_1": "17:37", + "via_1": "Lubny - Kyiv Pasazhyrskyi - Vinnytsia - Khmelnytskyi - Ternopil - Lviv", + "destination_trip_1": "Przemyśl Gł.", + "destination_arrival_time_1": "11:20", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "259": { + "route_id": 259, + "agency_id": "UZ", + "trip_short_name_0": "033 P", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "033 L", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Kryvyi Rih", + "origin_departure_time_0": "15:06", + "via_0": "Im.Tarasa Shevchenka - Bila Tserkva - Lviv", + "destination_trip_0": "Ivano-Frankivsk", + "destination_arrival_time_0": "06:59", + "origin_trip_1": "Ivano-Frankivsk", + "origin_departure_time_1": "19:35", + "via_1": "Lviv - Bila Tserkva - Im.Tarasa Shevchenka", + "destination_trip_1": "Kryvyi Rih", + "destination_arrival_time_1": "11:08", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "261": { + "route_id": 261, + "agency_id": "RJ", + "trip_short_name_0": "1022", + "service_id_0": "Daily", + "trip_short_name_1": "1023", + "service_id_1": "Daily", + "route_long_name": "", + "origin_trip_0": "Przemyśl Gł.", + "origin_departure_time_0": "21:33", + "via_0": "Kraków Gł. - Ostrava hl.n. - Olomouc hl.n. - Pardubice hl.n.", + "destination_trip_0": "Praha hl.n.", + "destination_arrival_time_0": "06:58", + "origin_trip_1": "Praha hl.n.", + "origin_departure_time_1": "21:48", + "via_1": "Pardubice hl.n. - Olomouc hl.n. - Ostrava hl.n. - Kraków Gł. - Rzeszow Gł.", + "destination_trip_1": "Przemyśl Gł.", + "destination_arrival_time_1": "06:25", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "262": { + "route_id": 262, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 3789", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Nuit 3790", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Paris Austerlitz", + "origin_departure_time_0": "19:28", + "via_0": "St-Denis-lès-Martel - Bretenoux Biars - Laroquebrou \/ Laròcabrau", + "destination_trip_0": "Aurillac", + "destination_arrival_time_0": "07:30", + "origin_trip_1": "Aurillac", + "origin_departure_time_1": "22:41", + "via_1": "Laroquebrou \/ Laròcabrau - Bretenoux Biars - St-Denis-lès-Martel", + "destination_trip_1": "Paris Austerlitz", + "destination_arrival_time_1": "08:31", + "picture": "", + "irregularities_0": "", + "irregularities_1": " arrives earlier Sun (8:32)" + }, + "263": { + "route_id": 263, + "agency_id": "UZ", + "trip_short_name_0": "039 L", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "040 P", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Solotvyno", + "origin_departure_time_0": "08:53", + "via_0": "Mukacheve - Stryj - Lviv - Bila Tserkva - Oleksandriia - Dnipro Holovny", + "destination_trip_0": "Zaporizhzhia 1", + "destination_arrival_time_0": "11:10", + "origin_trip_1": "Zaporizhzhia 1", + "origin_departure_time_1": "16:27", + "via_1": "Dnipro Holovny - Oleksandriia - Bila Tserkva - Lviv - Stryj - Mukacheve", + "destination_trip_1": "Solotvyno", + "destination_arrival_time_1": "18:26", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "264": { + "route_id": 264, + "agency_id": "SNCF", + "trip_short_name_0": "IC Nuit 3750", + "service_id_0": "2026: Daily", + "trip_short_name_1": "IC Nuit 3751", + "service_id_1": "2026: Daily", + "route_long_name": "", + "origin_trip_0": "Toulouse Matabiau", + "origin_departure_time_0": "19:44", + "via_0": "Montauban Ville Bourbon - Fleury-les-Aubrais (Orléans)", + "destination_trip_0": "Paris Austerlitz", + "destination_arrival_time_0": "07:03", + "origin_trip_1": "Paris Austerlitz", + "origin_departure_time_1": "22:13", + "via_1": "Fleury-les-Aubrais (Orléans) - Montauban Ville Bourbon", + "destination_trip_1": "Toulouse Matabiau", + "destination_arrival_time_1": "07:44", + "picture": "", + "irregularities_0": "Departs 22:16 on Sat\/Sun and 22:25 on Fri", + "irregularities_1": "Arrives earlier Fri-Sun (07:00)" + }, + "265": { + "route_id": 265, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "TLK 403\/50171", + "service_id_0": "2026\/06\/26-08\/30: Daily", + "trip_short_name_1": "TLK 55170\/402", + "service_id_1": "2026\/06\/27-08\/31: Daily", + "route_long_name": "Wydmy", + "origin_trip_0": "Bohumín", + "origin_departure_time_0": "19:27", + "via_0": "Katovice - Gdynia Główna", + "destination_trip_0": "Hel", + "destination_arrival_time_0": "07:09", + "origin_trip_1": "Hel", + "origin_departure_time_1": "19:23", + "via_1": "Gdynia Główna - Katovice", + "destination_trip_1": "Bohumín", + "destination_arrival_time_1": "06:54", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "266": { + "route_id": 266, + "agency_id": "PKP\/ČD", + "trip_short_name_0": "TLK 403", + "service_id_0": "2026\/06\/26-08\/30: Daily", + "trip_short_name_1": "TLK 402", + "service_id_1": "2026\/06\/27-08\/31: Daily", + "route_long_name": "Wydmy", + "origin_trip_0": "Bohumín", + "origin_departure_time_0": "19:27", + "via_0": "Katovice - Gdynia Główna", + "destination_trip_0": "Łeba", + "destination_arrival_time_0": "07:13", + "origin_trip_1": "Łeba", + "origin_departure_time_1": "19:11", + "via_1": "Gdynia Główna - Katovice", + "destination_trip_1": "Bohumín", + "destination_arrival_time_1": "06:54", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "267": { + "route_id": 267, + "agency_id": "PKP", + "trip_short_name_0": "TLK 38194", + "service_id_0": "2026\/06\/26-08\/30: Daily", + "trip_short_name_1": "TLK 83194", + "service_id_1": "2026\/06\/27-08\/31: Daily", + "route_long_name": "Wolin", + "origin_trip_0": "Kraków Gł.", + "origin_departure_time_0": "21:03", + "via_0": "Katowice - Szczecin Gł.", + "destination_trip_0": "Świnoujście", + "destination_arrival_time_0": "07:27", + "origin_trip_1": "Świnoujście", + "origin_departure_time_1": "20:25", + "via_1": "Szczecin Gł. - Kostrzyn", + "destination_trip_1": "Kraków Gł.", + "destination_arrival_time_1": "07:12", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "268": { + "route_id": 268, + "agency_id": "PKP", + "trip_short_name_0": "TLK 38190", + "service_id_0": "2026\/06\/26-08\/30: Daily", + "trip_short_name_1": "TLK 83190", + "service_id_1": "2026\/06\/27-08\/31: Daily", + "route_long_name": "Bursztyn", + "origin_trip_0": "Kraków Gł.", + "origin_departure_time_0": "21:33", + "via_0": "Trzebinia - Częstochowa", + "destination_trip_0": "Kołobrzeg", + "destination_arrival_time_0": "07:44", + "origin_trip_1": "Kołobrzeg", + "origin_departure_time_1": "20:32", + "via_1": "Częstochowa - Trzebinia", + "destination_trip_1": "Kraków Gł.", + "destination_arrival_time_1": "06:46", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "269": { + "route_id": 269, + "agency_id": "UZ", + "trip_short_name_0": "083 P", + "service_id_0": "2026: Every 2nd day", + "trip_short_name_1": "083 L", + "service_id_1": "2026: Every 2nd day", + "route_long_name": "", + "origin_trip_0": "Dnipro Holovny", + "origin_departure_time_0": "20:00", + "via_0": "Im.Tarasa Shevchenka - Lviv - Stryj - Mukacheve", + "destination_trip_0": "Uzhhorod", + "destination_arrival_time_0": "14:54", + "origin_trip_1": "Uzhhorod", + "origin_departure_time_1": "16:40", + "via_1": "Mukacheve - Stryj - Lviv - Im.Tarasa Shevchenka - Oleksandriia", + "destination_trip_1": "Dnipro Holovny", + "destination_arrival_time_1": "12:45", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + }, + "": { + "route_id": "", + "agency_id": "", + "trip_short_name_0": "", + "service_id_0": "", + "trip_short_name_1": "", + "service_id_1": "", + "route_long_name": "", + "origin_trip_0": "", + "origin_departure_time_0": "", + "via_0": "", + "destination_trip_0": "", + "destination_arrival_time_0": "", + "origin_trip_1": "", + "origin_departure_time_1": "", + "via_1": "", + "destination_trip_1": "", + "destination_arrival_time_1": "", + "picture": "", + "irregularities_0": "", + "irregularities_1": "" + } +} From f1dced443d9dd90c675b5d6a2b651b09c169ff45 Mon Sep 17 00:00:00 2001 From: lennartrommeiss <61516567+lenderom@users.noreply.github.com> Date: Mon, 13 Jul 2026 18:43:46 +0200 Subject: [PATCH 2/3] fix: add basic functions --- content/nighttrains/index.de.md | 2 + content/nighttrains/index.en.md | 2 + content/nighttrains/index.fr.md | 2 + data/nighttrains/de/fip_details.json | 656 ++++++++++++++++++ data/nighttrains/en/fip_details.json | 656 ++++++++++++++++++ data/nighttrains/fr/fip_details.json | 656 ++++++++++++++++++ i18n/de.yaml | 12 + i18n/en.yaml | 12 + i18n/fr.yaml | 12 + .../_shortcodes/nighttrains-fip-details.html | 89 +++ layouts/_shortcodes/nighttrains-map.html | 10 + static/nighttrains/README.md | 25 + static/nighttrains/map.css | 102 +++ static/nighttrains/map.js | 26 + 14 files changed, 2262 insertions(+) create mode 100644 data/nighttrains/de/fip_details.json create mode 100644 data/nighttrains/en/fip_details.json create mode 100644 data/nighttrains/fr/fip_details.json create mode 100644 layouts/_shortcodes/nighttrains-fip-details.html diff --git a/content/nighttrains/index.de.md b/content/nighttrains/index.de.md index 81d24636b..e52ba4752 100644 --- a/content/nighttrains/index.de.md +++ b/content/nighttrains/index.de.md @@ -7,4 +7,6 @@ Hier findest du die Nachtzugkarte von Back-on-Track als lokale Kopie in unserem {{< nighttrains-map >}} +{{< nighttrains-fip-details >}} + Quelle: [Back-on-Track Nachtzugkarte](https://back-on-track.eu/de/nachtzugkarte/) diff --git a/content/nighttrains/index.en.md b/content/nighttrains/index.en.md index 62d6c4f86..086a7081c 100644 --- a/content/nighttrains/index.en.md +++ b/content/nighttrains/index.en.md @@ -7,4 +7,6 @@ Here you can find the Back-on-Track night train map as a local copy in our proje {{< nighttrains-map >}} +{{< nighttrains-fip-details >}} + Source: [Back-on-Track Night Train Map](https://back-on-track.eu/night-train-map/) diff --git a/content/nighttrains/index.fr.md b/content/nighttrains/index.fr.md index 8675e455d..1cc10d865 100644 --- a/content/nighttrains/index.fr.md +++ b/content/nighttrains/index.fr.md @@ -7,4 +7,6 @@ Vous trouverez ici la carte des trains de nuit de Back-on-Track comme copie loca {{< nighttrains-map >}} +{{< nighttrains-fip-details >}} + Source : [Carte des trains de nuit Back-on-Track](https://back-on-track.eu/night-train-map/) diff --git a/data/nighttrains/de/fip_details.json b/data/nighttrains/de/fip_details.json new file mode 100644 index 000000000..5bc49d297 --- /dev/null +++ b/data/nighttrains/de/fip_details.json @@ -0,0 +1,656 @@ +[ + { + "id": "oebb-nightjet", + "source_route_ids": [ + "1", + "2", + "5", + "17", + "18", + "44", + "45", + "46", + "49", + "50", + "53", + "115" + ], + "title": "Nightjet (OEBB)", + "description": "Nachtzugverbindungen von OEBB im Nightjet-Netz inklusive ausgewaehlter grenzueberschreitender Linien.", + "fip_global_fare": true, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "oebb-website", + "oebb-phone", + "oebb-ticket-office" + ] + }, + { + "id": "sncf-intercites-nuit", + "source_route_ids": [ + "107", + "108", + "109", + "110", + "111", + "112", + "119", + "262", + "264" + ], + "title": "Intercites de Nuit (SNCF)", + "description": "Nachtzuege der SNCF innerhalb Frankreichs mit saisonalen und ganzjaehrigen Linien.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "sncf-ticket-office", + "sncf-phone" + ] + }, + { + "id": "fs-intercity-notte", + "source_route_ids": [ + "76", + "83", + "84", + "85", + "86", + "96", + "97", + "99", + "100", + "101", + "102", + "103", + "104", + "126", + "128" + ], + "title": "Intercity Notte (FS)", + "description": "Nachtverbindungen von Trenitalia in Italien inklusive Linien mit Kurswagen fuer Sizilien.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "fs-website", + "fs-ticket-office" + ] + }, + { + "id": "sj-night-trains", + "source_route_ids": [ + "62", + "63", + "81" + ], + "title": "Nachtzuege Schweden (SJ)", + "description": "Fernverbindungen mit Schlafwagen in Schweden zwischen Stockholm, Duved, Malmoe und Lulea.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [] + }, + { + "id": "vr-night-trains", + "source_route_ids": [ + "68", + "72", + "90", + "91", + "98" + ], + "title": "Nachtzuege Finnland (VR)", + "description": "Nachtzuege in Finnland zwischen Helsinki, Turku und Lappland, teilweise mit Kurswagenkonzept.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [] + }, + { + "id": "placeholder-uz", + "source_route_ids": [ + "140", + "141", + "147", + "149", + "150", + "151", + "152", + "153", + "154", + "155", + "156", + "158", + "161", + "162", + "164", + "166", + "167", + "168", + "170", + "172", + "173", + "174", + "175", + "177", + "178", + "180", + "181", + "182", + "183", + "184", + "185", + "186", + "189", + "190", + "191", + "196", + "197", + "198", + "199", + "200", + "201", + "203", + "207", + "208", + "209", + "210", + "211", + "212", + "213", + "218", + "219", + "220", + "221", + "222", + "227", + "258", + "259", + "263", + "269" + ], + "title": "Nachtzuege UZ", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr", + "source_route_ids": [ + "11", + "12", + "13", + "14", + "15", + "19", + "20", + "21", + "23", + "25", + "26", + "249", + "250" + ], + "title": "Nachtzuege CFR", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-pkp", + "source_route_ids": [ + "10", + "113", + "121", + "122", + "125", + "129", + "136", + "137", + "138", + "267", + "268" + ], + "title": "Nachtzuege PKP", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-pkp-cd", + "source_route_ids": [ + "8", + "9", + "116", + "118", + "124", + "265", + "266" + ], + "title": "Nachtzuege PKP/CD", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd", + "source_route_ids": [ + "30", + "31", + "243", + "245", + "246", + "247", + "248" + ], + "title": "Nachtzuege TCDD", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uex", + "source_route_ids": [ + "252", + "253", + "254", + "255", + "256", + "257" + ], + "title": "Nachtzuege UEX", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-bdz", + "source_route_ids": [ + "131", + "133", + "134", + "135", + "142" + ], + "title": "Nachtzuege BDZ", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cs", + "source_route_ids": [ + "37", + "38", + "39", + "40", + "41" + ], + "title": "Nachtzuege CS", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-es", + "source_route_ids": [ + "237", + "238", + "239", + "240" + ], + "title": "Nachtzuege ES", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav", + "source_route_ids": [ + "58", + "223", + "224", + "225" + ], + "title": "Nachtzuege MAV", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-st", + "source_route_ids": [ + "73", + "77", + "79", + "80" + ], + "title": "Nachtzuege ST", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-oebb", + "source_route_ids": [ + "229", + "232", + "233", + "235" + ], + "title": "Nachtzuege OEBB", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr-mav", + "source_route_ids": [ + "16", + "67" + ], + "title": "Nachtzuege CFR/MAV", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-fs", + "source_route_ids": [ + "105", + "106" + ], + "title": "Nachtzuege FS", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-hzpp", + "source_route_ids": [ + "3", + "48" + ], + "title": "Nachtzuege HZPP", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-hzpp-oebb", + "source_route_ids": [ + "57", + "117" + ], + "title": "Nachtzuege HZPP/OEBB", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav-oebb", + "source_route_ids": [ + "54", + "74" + ], + "title": "Nachtzuege MAV/OEBB", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-rj", + "source_route_ids": [ + "7", + "261" + ], + "title": "Nachtzuege RJ", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-sjn", + "source_route_ids": [ + "70", + "71" + ], + "title": "Nachtzuege SJN", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cd", + "source_route_ids": [ + "6", + "120" + ], + "title": "Nachtzuege CD", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-atc", + "source_route_ids": [ + "24" + ], + "title": "Nachtzuege ATC", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfm-cfr", + "source_route_ids": [ + "22" + ], + "title": "Nachtzuege CFM/CFR", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr-mav-oebb", + "source_route_ids": [ + "59" + ], + "title": "Nachtzuege CFR/MAV/OEBB", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-ga", + "source_route_ids": [ + "65" + ], + "title": "Nachtzuege GA", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-gwr", + "source_route_ids": [ + "42" + ], + "title": "Nachtzuege GWR", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav-pkp", + "source_route_ids": [ + "127" + ], + "title": "Nachtzuege MAV/PKP", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-ote", + "source_route_ids": [ + "114" + ], + "title": "Nachtzuege OTE", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-rdc-sj", + "source_route_ids": [ + "78" + ], + "title": "Nachtzuege RDC/SJ", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd-bdz", + "source_route_ids": [ + "27" + ], + "title": "Nachtzuege TCDD/BDZ", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd-bdz-cfr", + "source_route_ids": [ + "28" + ], + "title": "Nachtzuege TCDD/BDZ/CFR", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uz-cfm", + "source_route_ids": [ + "195" + ], + "title": "Nachtzuege UZ/CFM", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uz-oebb", + "source_route_ids": [ + "60" + ], + "title": "Nachtzuege UZ/OEBB", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-vy", + "source_route_ids": [ + "69" + ], + "title": "Nachtzuege VY", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-zssk", + "source_route_ids": [ + "123" + ], + "title": "Nachtzuege ZSSK", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-zs-zpcg", + "source_route_ids": [ + "130" + ], + "title": "Nachtzuege ZS/ZPCG", + "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + } +] diff --git a/data/nighttrains/en/fip_details.json b/data/nighttrains/en/fip_details.json new file mode 100644 index 000000000..2a085659f --- /dev/null +++ b/data/nighttrains/en/fip_details.json @@ -0,0 +1,656 @@ +[ + { + "id": "oebb-nightjet", + "source_route_ids": [ + "1", + "2", + "5", + "17", + "18", + "44", + "45", + "46", + "49", + "50", + "53", + "115" + ], + "title": "Nightjet (OEBB)", + "description": "Night train services operated by OEBB in the Nightjet network, including selected cross-border routes.", + "fip_global_fare": true, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "oebb-website", + "oebb-phone", + "oebb-ticket-office" + ] + }, + { + "id": "sncf-intercites-nuit", + "source_route_ids": [ + "107", + "108", + "109", + "110", + "111", + "112", + "119", + "262", + "264" + ], + "title": "Intercites de Nuit (SNCF)", + "description": "SNCF night train services within France with seasonal and year-round routes.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "sncf-ticket-office", + "sncf-phone" + ] + }, + { + "id": "fs-intercity-notte", + "source_route_ids": [ + "76", + "83", + "84", + "85", + "86", + "96", + "97", + "99", + "100", + "101", + "102", + "103", + "104", + "126", + "128" + ], + "title": "Intercity Notte (FS)", + "description": "Trenitalia night services in Italy, including routes with through coaches to Sicily.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "fs-website", + "fs-ticket-office" + ] + }, + { + "id": "sj-night-trains", + "source_route_ids": [ + "62", + "63", + "81" + ], + "title": "Night Trains Sweden (SJ)", + "description": "Long-distance night trains in Sweden between Stockholm, Duved, Malmo and Lulea.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [] + }, + { + "id": "vr-night-trains", + "source_route_ids": [ + "68", + "72", + "90", + "91", + "98" + ], + "title": "Night Trains Finland (VR)", + "description": "Night train services in Finland between Helsinki, Turku and Lapland, partly using through coach concepts.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [] + }, + { + "id": "placeholder-uz", + "source_route_ids": [ + "140", + "141", + "147", + "149", + "150", + "151", + "152", + "153", + "154", + "155", + "156", + "158", + "161", + "162", + "164", + "166", + "167", + "168", + "170", + "172", + "173", + "174", + "175", + "177", + "178", + "180", + "181", + "182", + "183", + "184", + "185", + "186", + "189", + "190", + "191", + "196", + "197", + "198", + "199", + "200", + "201", + "203", + "207", + "208", + "209", + "210", + "211", + "212", + "213", + "218", + "219", + "220", + "221", + "222", + "227", + "258", + "259", + "263", + "269" + ], + "title": "Night trains UZ", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr", + "source_route_ids": [ + "11", + "12", + "13", + "14", + "15", + "19", + "20", + "21", + "23", + "25", + "26", + "249", + "250" + ], + "title": "Night trains CFR", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-pkp", + "source_route_ids": [ + "10", + "113", + "121", + "122", + "125", + "129", + "136", + "137", + "138", + "267", + "268" + ], + "title": "Night trains PKP", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-pkp-cd", + "source_route_ids": [ + "8", + "9", + "116", + "118", + "124", + "265", + "266" + ], + "title": "Night trains PKP/CD", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd", + "source_route_ids": [ + "30", + "31", + "243", + "245", + "246", + "247", + "248" + ], + "title": "Night trains TCDD", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uex", + "source_route_ids": [ + "252", + "253", + "254", + "255", + "256", + "257" + ], + "title": "Night trains UEX", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-bdz", + "source_route_ids": [ + "131", + "133", + "134", + "135", + "142" + ], + "title": "Night trains BDZ", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cs", + "source_route_ids": [ + "37", + "38", + "39", + "40", + "41" + ], + "title": "Night trains CS", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-es", + "source_route_ids": [ + "237", + "238", + "239", + "240" + ], + "title": "Night trains ES", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav", + "source_route_ids": [ + "58", + "223", + "224", + "225" + ], + "title": "Night trains MAV", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-st", + "source_route_ids": [ + "73", + "77", + "79", + "80" + ], + "title": "Night trains ST", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-oebb", + "source_route_ids": [ + "229", + "232", + "233", + "235" + ], + "title": "Night trains OEBB", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr-mav", + "source_route_ids": [ + "16", + "67" + ], + "title": "Night trains CFR/MAV", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-fs", + "source_route_ids": [ + "105", + "106" + ], + "title": "Night trains FS", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-hzpp", + "source_route_ids": [ + "3", + "48" + ], + "title": "Night trains HZPP", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-hzpp-oebb", + "source_route_ids": [ + "57", + "117" + ], + "title": "Night trains HZPP/OEBB", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav-oebb", + "source_route_ids": [ + "54", + "74" + ], + "title": "Night trains MAV/OEBB", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-rj", + "source_route_ids": [ + "7", + "261" + ], + "title": "Night trains RJ", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-sjn", + "source_route_ids": [ + "70", + "71" + ], + "title": "Night trains SJN", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cd", + "source_route_ids": [ + "6", + "120" + ], + "title": "Night trains CD", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-atc", + "source_route_ids": [ + "24" + ], + "title": "Night trains ATC", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfm-cfr", + "source_route_ids": [ + "22" + ], + "title": "Night trains CFM/CFR", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr-mav-oebb", + "source_route_ids": [ + "59" + ], + "title": "Night trains CFR/MAV/OEBB", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-ga", + "source_route_ids": [ + "65" + ], + "title": "Night trains GA", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-gwr", + "source_route_ids": [ + "42" + ], + "title": "Night trains GWR", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav-pkp", + "source_route_ids": [ + "127" + ], + "title": "Night trains MAV/PKP", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-ote", + "source_route_ids": [ + "114" + ], + "title": "Night trains OTE", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-rdc-sj", + "source_route_ids": [ + "78" + ], + "title": "Night trains RDC/SJ", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd-bdz", + "source_route_ids": [ + "27" + ], + "title": "Night trains TCDD/BDZ", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd-bdz-cfr", + "source_route_ids": [ + "28" + ], + "title": "Night trains TCDD/BDZ/CFR", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uz-cfm", + "source_route_ids": [ + "195" + ], + "title": "Night trains UZ/CFM", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uz-oebb", + "source_route_ids": [ + "60" + ], + "title": "Night trains UZ/OEBB", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-vy", + "source_route_ids": [ + "69" + ], + "title": "Night trains VY", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-zssk", + "source_route_ids": [ + "123" + ], + "title": "Night trains ZSSK", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-zs-zpcg", + "source_route_ids": [ + "130" + ], + "title": "Night trains ZS/ZPCG", + "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + } +] diff --git a/data/nighttrains/fr/fip_details.json b/data/nighttrains/fr/fip_details.json new file mode 100644 index 000000000..082e6e3ff --- /dev/null +++ b/data/nighttrains/fr/fip_details.json @@ -0,0 +1,656 @@ +[ + { + "id": "oebb-nightjet", + "source_route_ids": [ + "1", + "2", + "5", + "17", + "18", + "44", + "45", + "46", + "49", + "50", + "53", + "115" + ], + "title": "Nightjet (OEBB)", + "description": "Relations de nuit exploitees par OEBB dans le reseau Nightjet, y compris certaines liaisons transfrontalieres.", + "fip_global_fare": true, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "oebb-website", + "oebb-phone", + "oebb-ticket-office" + ] + }, + { + "id": "sncf-intercites-nuit", + "source_route_ids": [ + "107", + "108", + "109", + "110", + "111", + "112", + "119", + "262", + "264" + ], + "title": "Intercites de Nuit (SNCF)", + "description": "Services de nuit SNCF en France avec des liaisons saisonnieres et annuelles.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "sncf-ticket-office", + "sncf-phone" + ] + }, + { + "id": "fs-intercity-notte", + "source_route_ids": [ + "76", + "83", + "84", + "85", + "86", + "96", + "97", + "99", + "100", + "101", + "102", + "103", + "104", + "126", + "128" + ], + "title": "Intercity Notte (FS)", + "description": "Services de nuit de Trenitalia en Italie, y compris des relations avec voitures directes vers la Sicile.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [ + "fs-website", + "fs-ticket-office" + ] + }, + { + "id": "sj-night-trains", + "source_route_ids": [ + "62", + "63", + "81" + ], + "title": "Trains de nuit Suede (SJ)", + "description": "Trains de nuit longue distance en Suede entre Stockholm, Duved, Malmo et Lulea.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [] + }, + { + "id": "vr-night-trains", + "source_route_ids": [ + "68", + "72", + "90", + "91", + "98" + ], + "title": "Trains de nuit Finlande (VR)", + "description": "Relations de nuit en Finlande entre Helsinki, Turku et la Laponie, partiellement avec concept de voitures directes.", + "fip_global_fare": false, + "fip_coupon": true, + "fip_50": true, + "booking_options": [] + }, + { + "id": "placeholder-uz", + "source_route_ids": [ + "140", + "141", + "147", + "149", + "150", + "151", + "152", + "153", + "154", + "155", + "156", + "158", + "161", + "162", + "164", + "166", + "167", + "168", + "170", + "172", + "173", + "174", + "175", + "177", + "178", + "180", + "181", + "182", + "183", + "184", + "185", + "186", + "189", + "190", + "191", + "196", + "197", + "198", + "199", + "200", + "201", + "203", + "207", + "208", + "209", + "210", + "211", + "212", + "213", + "218", + "219", + "220", + "221", + "222", + "227", + "258", + "259", + "263", + "269" + ], + "title": "Trains de nuit UZ", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr", + "source_route_ids": [ + "11", + "12", + "13", + "14", + "15", + "19", + "20", + "21", + "23", + "25", + "26", + "249", + "250" + ], + "title": "Trains de nuit CFR", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-pkp", + "source_route_ids": [ + "10", + "113", + "121", + "122", + "125", + "129", + "136", + "137", + "138", + "267", + "268" + ], + "title": "Trains de nuit PKP", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-pkp-cd", + "source_route_ids": [ + "8", + "9", + "116", + "118", + "124", + "265", + "266" + ], + "title": "Trains de nuit PKP/CD", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd", + "source_route_ids": [ + "30", + "31", + "243", + "245", + "246", + "247", + "248" + ], + "title": "Trains de nuit TCDD", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uex", + "source_route_ids": [ + "252", + "253", + "254", + "255", + "256", + "257" + ], + "title": "Trains de nuit UEX", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-bdz", + "source_route_ids": [ + "131", + "133", + "134", + "135", + "142" + ], + "title": "Trains de nuit BDZ", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cs", + "source_route_ids": [ + "37", + "38", + "39", + "40", + "41" + ], + "title": "Trains de nuit CS", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-es", + "source_route_ids": [ + "237", + "238", + "239", + "240" + ], + "title": "Trains de nuit ES", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav", + "source_route_ids": [ + "58", + "223", + "224", + "225" + ], + "title": "Trains de nuit MAV", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-st", + "source_route_ids": [ + "73", + "77", + "79", + "80" + ], + "title": "Trains de nuit ST", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-oebb", + "source_route_ids": [ + "229", + "232", + "233", + "235" + ], + "title": "Trains de nuit OEBB", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr-mav", + "source_route_ids": [ + "16", + "67" + ], + "title": "Trains de nuit CFR/MAV", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-fs", + "source_route_ids": [ + "105", + "106" + ], + "title": "Trains de nuit FS", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-hzpp", + "source_route_ids": [ + "3", + "48" + ], + "title": "Trains de nuit HZPP", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-hzpp-oebb", + "source_route_ids": [ + "57", + "117" + ], + "title": "Trains de nuit HZPP/OEBB", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav-oebb", + "source_route_ids": [ + "54", + "74" + ], + "title": "Trains de nuit MAV/OEBB", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-rj", + "source_route_ids": [ + "7", + "261" + ], + "title": "Trains de nuit RJ", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-sjn", + "source_route_ids": [ + "70", + "71" + ], + "title": "Trains de nuit SJN", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cd", + "source_route_ids": [ + "6", + "120" + ], + "title": "Trains de nuit CD", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-atc", + "source_route_ids": [ + "24" + ], + "title": "Trains de nuit ATC", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfm-cfr", + "source_route_ids": [ + "22" + ], + "title": "Trains de nuit CFM/CFR", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-cfr-mav-oebb", + "source_route_ids": [ + "59" + ], + "title": "Trains de nuit CFR/MAV/OEBB", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-ga", + "source_route_ids": [ + "65" + ], + "title": "Trains de nuit GA", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-gwr", + "source_route_ids": [ + "42" + ], + "title": "Trains de nuit GWR", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-mav-pkp", + "source_route_ids": [ + "127" + ], + "title": "Trains de nuit MAV/PKP", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-ote", + "source_route_ids": [ + "114" + ], + "title": "Trains de nuit OTE", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-rdc-sj", + "source_route_ids": [ + "78" + ], + "title": "Trains de nuit RDC/SJ", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd-bdz", + "source_route_ids": [ + "27" + ], + "title": "Trains de nuit TCDD/BDZ", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-tcdd-bdz-cfr", + "source_route_ids": [ + "28" + ], + "title": "Trains de nuit TCDD/BDZ/CFR", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uz-cfm", + "source_route_ids": [ + "195" + ], + "title": "Trains de nuit UZ/CFM", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-uz-oebb", + "source_route_ids": [ + "60" + ], + "title": "Trains de nuit UZ/OEBB", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-vy", + "source_route_ids": [ + "69" + ], + "title": "Trains de nuit VY", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-zssk", + "source_route_ids": [ + "123" + ], + "title": "Trains de nuit ZSSK", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + }, + { + "id": "placeholder-zs-zpcg", + "source_route_ids": [ + "130" + ], + "title": "Trains de nuit ZS/ZPCG", + "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", + "fip_global_fare": false, + "fip_coupon": false, + "fip_50": false, + "booking_options": [] + } +] diff --git a/i18n/de.yaml b/i18n/de.yaml index 4d34eba30..b2245c27d 100644 --- a/i18n/de.yaml +++ b/i18n/de.yaml @@ -208,6 +208,18 @@ news: all: Alle News further: Weitere News headline: Was gibt's Neues? +nightTrains: + back: Zurueck + bookingOptions: Buchungswege + detailsHeading: Detailinformationen zu Nachtzuegen + fipInformationButton: FIP Informationen + missingBooking: Fehlender Buchungsweg + moreDetails: Mehr Details + 'no': Nein + runs: Faehrt + selectLine: Linie auswaehlen + sourceRouteIds: Zugeordnete Strecken-IDs + 'yes': Ja operators: descriptionTemplate: >- Informationen über die FIP-Bedingungen bei %s: Gültigkeit, Ticket- und diff --git a/i18n/en.yaml b/i18n/en.yaml index 976af2d84..98d5b4af7 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -204,6 +204,18 @@ news: all: All News further: Other News headline: What's new? +nightTrains: + back: Back + bookingOptions: Booking options + detailsHeading: Night train details + fipInformationButton: FIP Informations + missingBooking: Missing booking option + moreDetails: More Details + 'no': 'No' + runs: Runs + selectLine: Select a line + sourceRouteIds: Mapped route IDs + 'yes': 'Yes' operators: descriptionTemplate: >- Information about FIP conditions at %s: validity, ticket and reservation diff --git a/i18n/fr.yaml b/i18n/fr.yaml index 2139514c5..2c6030fa3 100644 --- a/i18n/fr.yaml +++ b/i18n/fr.yaml @@ -213,6 +213,18 @@ news: all: Toutes les actualités further: Autres actualités headline: Quoi de neuf ? +nightTrains: + back: Retour + bookingOptions: Canaux de reservation + detailsHeading: Informations detaillees sur les trains de nuit + fipInformationButton: Informations FIP + missingBooking: Canal de reservation manquant + moreDetails: Plus de details + 'no': Non + runs: Circule + selectLine: Selectionner une ligne + sourceRouteIds: IDs de lignes associees + 'yes': Oui operators: descriptionTemplate: >- Informations sur les conditions FIP chez %s : Validité, Achat de billets et diff --git a/layouts/_shortcodes/nighttrains-fip-details.html b/layouts/_shortcodes/nighttrains-fip-details.html new file mode 100644 index 000000000..d710a96f0 --- /dev/null +++ b/layouts/_shortcodes/nighttrains-fip-details.html @@ -0,0 +1,89 @@ +{{- $lang := .Page.Language.Lang -}} +{{- $langData := index hugo.Data.nighttrains $lang -}} +{{- $fallbackData := index hugo.Data.nighttrains "en" -}} +{{- $items := cond (and $langData $langData.fip_details) $langData.fip_details $fallbackData.fip_details -}} + +{{- if $items -}} + {{- $fipMap := dict -}} + {{- range $item := $items -}} + {{- range $routeId := $item.source_route_ids -}} + {{- $fipMap = merge $fipMap (dict (printf "%v" $routeId) $item.id) -}} + {{- end -}} + {{- end -}} + + + +

{{ T "nightTrains.detailsHeading" }}

+ + {{- range $item := $items -}} +
+ +
+ {{- partial "icon" "hotel" -}} + {{ $item.title }} +
+ {{ partial "icon" "keyboard_arrow_down" }} +
+ + + +
+

{{ $item.description }}

+ +
+ {{- partial "tag" (dict + "Icon" (cond $item.fip_global_fare "check_circle" "cancel") + "Type" (cond $item.fip_global_fare "success" "error") + "RawText" (print (T "fipValidity.fip-global-fare") ": " (T (cond $item.fip_global_fare "nightTrains.yes" "nightTrains.no"))) + ) + -}} + {{- partial "tag" (dict + "Icon" (cond $item.fip_coupon "check_circle" "cancel") + "Type" (cond $item.fip_coupon "success" "error") + "RawText" (print (T "fipValidity.fip-coupon") ": " (T (cond $item.fip_coupon "nightTrains.yes" "nightTrains.no"))) + ) + -}} + {{- partial "tag" (dict + "Icon" (cond $item.fip_50 "check_circle" "cancel") + "Type" (cond $item.fip_50 "success" "error") + "RawText" (print "FIP 50: " (T (cond $item.fip_50 "nightTrains.yes" "nightTrains.no"))) + ) + -}} +
+ + {{- if gt (len $item.booking_options) 0 -}} +

{{ T "nightTrains.bookingOptions" }}

+
+ {{- range $bookingId := $item.booking_options -}} + {{- $bookingPage := site.GetPage (print "booking/" $bookingId) -}} + {{- if $bookingPage -}} + {{- partial "button" (dict + "Destination" $bookingPage.RelPermalink + "Text" $bookingPage.Title + ) + -}} + {{- else -}} +

+ {{ T "nightTrains.missingBooking" }}: + {{ $bookingId }} +

+ {{- end -}} + {{- end -}} +
+ {{- end -}} + + +

+ {{ T "nightTrains.sourceRouteIds" }}: + {{ delimit $item.source_route_ids ", " }} +

+
+
+ {{- end -}} +{{- end -}} diff --git a/layouts/_shortcodes/nighttrains-map.html b/layouts/_shortcodes/nighttrains-map.html index 7d8bee1db..c96cb9756 100644 --- a/layouts/_shortcodes/nighttrains-map.html +++ b/layouts/_shortcodes/nighttrains-map.html @@ -9,4 +9,14 @@ + diff --git a/static/nighttrains/README.md b/static/nighttrains/README.md index 123770ef5..0e1e428c6 100644 --- a/static/nighttrains/README.md +++ b/static/nighttrains/README.md @@ -30,6 +30,29 @@ In `map.js`, coordinate conversion for mobile/touch selection was adjusted: Reason: In this Hugo site, the map is rendered inside the regular content container and is not positioned like the original full-width page. Without offset correction, touch points were shifted, so nearby routes were often not detected correctly. This especially affected the mobile behavior where the train list overlay (`.row.trainlist`) should appear when tapping near multiple lines. +### 3) Added local FIP link button in map overlay + +In `map.js`, the single-train overlay now renders an additional button next to "More Details": + +- label: `map_i18n.fipInformation` (configured as "FIP Informations") +- behavior: scroll to the matching local FIP expander and open it + +Technical details: + +- added `getFipDetailsTarget(route_id)` that resolves route IDs against `window.nighttrainsFipByRouteId` +- added `scrollToFipDetails(route_id)` that opens `
` and runs `scrollIntoView` +- added conditional overlay button in `showSingleTrainOverlay(id)` only if a mapping exists + +The route-to-expander mapping is generated in Hugo (not hardcoded in JS): + +- `layouts/_shortcodes/nighttrains-fip-details.html` builds a dictionary from each entry's `source_route_ids` to its local expander `id` +- this dictionary is exposed as `window.nighttrainsFipByRouteId` + +Translations for map overlay labels are injected before loading `map.js`: + +- `layouts/_shortcodes/nighttrains-map.html` sets `window.map_i18n` using i18n keys +- keys currently used: `nightTrains.back`, `dialog.close`, `nightTrains.runs`, `nightTrains.moreDetails`, `nightTrains.fipInformationButton`, `nightTrains.selectLine` + ## Reproduction steps 1. Refresh assets from source if needed: @@ -48,3 +71,5 @@ Reason: In this Hugo site, the map is rendered inside the regular content contai - Single route tap opens route detail overlay. - Mobile taps near route clusters can open train list overlay (`.row.trainlist`). - Overlay detail button and route metadata are loaded from local JSON. +- Overlay shows "FIP Informations" when route ID is mapped. +- Clicking "FIP Informations" scrolls to the correct expander and opens it. diff --git a/static/nighttrains/map.css b/static/nighttrains/map.css index 762a34f53..57a1a5301 100644 --- a/static/nighttrains/map.css +++ b/static/nighttrains/map.css @@ -190,3 +190,105 @@ margin-bottom: 2px; } } + +svg { + #\#7\#, + #\#24\#, + #\#30\#, + #\#31\#, + #\#62\#, + #\#63\#, + #\#68\#, + #\#72\#, + #\#73\#, + #\#77\#, + #\#78\#, + #\#79\#, + #\#80\#, + #\#81\#, + #\#88\#, + #\#90\#, + #\#91\#, + #\#98\#, + #\#114\#, + #\#140\#, + #\#141\#, + #\#147\#, + #\#149\#, + #\#150\#, + #\#151\#, + #\#152\#, + #\#153\#, + #\#154\#, + #\#155\#, + #\#156\#, + #\#158\#, + #\#161\#, + #\#162\#, + #\#164\#, + #\#166\#, + #\#167\#, + #\#168\#, + #\#170\#, + #\#172\#, + #\#173\#, + #\#174\#, + #\#175\#, + #\#177\#, + #\#178\#, + #\#180\#, + #\#181\#, + #\#182\#, + #\#183\#, + #\#184\#, + #\#185\#, + #\#186\#, + #\#189\#, + #\#190\#, + #\#191\#, + #\#195\#, + #\#196\#, + #\#197\#, + #\#198\#, + #\#199\#, + #\#200\#, + #\#201\#, + #\#203\#, + #\#207\#, + #\#208\#, + #\#209\#, + #\#210\#, + #\#211\#, + #\#212\#, + #\#213\#, + #\#218\#, + #\#219\#, + #\#220\#, + #\#221\#, + #\#222\#, + #\#227\#, + #\#237\#, + #\#238\#, + #\#239\#, + #\#240\#, + #\#243\#, + #\#245\#, + #\#246\#, + #\#247\#, + #\#248\#, + #\#252\#, + #\#253\#, + #\#254\#, + #\#255\#, + #\#256\#, + #\#257\#, + #\#258\#, + #\#259\#, + #\#261\#, + #\#263\#, + #\#269\#{ + stroke: #b2afaf; + stroke-width: 0.8; + opacity: 50%; + } +} diff --git a/static/nighttrains/map.js b/static/nighttrains/map.js index 9223715f7..c6c5a7e46 100644 --- a/static/nighttrains/map.js +++ b/static/nighttrains/map.js @@ -12,6 +12,7 @@ if (typeof map_i18n !== "object") { close: "Close", runs: "Runs", details: "More Details", + fipInformation: "FIP Informations", selectline: "Select a line", }; } @@ -20,6 +21,26 @@ var map_div = document.querySelector("#bot-map"); var map_svg = document.querySelector("#bot-map svg"); var map_viewbox = map_svg.viewBox.baseVal; +function getFipDetailsTarget(route_id) { + if (!window.nighttrainsFipByRouteId) { + return null; + } + return window.nighttrainsFipByRouteId[String(route_id)] || null; +} + +function scrollToFipDetails(route_id) { + var target_id = getFipDetailsTarget(route_id); + if (!target_id) { + return; + } + var target = document.getElementById(target_id); + if (!target) { + return; + } + target.open = true; + target.scrollIntoView({ behavior: "smooth", block: "start" }); +} + function handleZoom(e) { d3.select("#bot-map > svg > g").attr("transform", e.transform); if (e.transform.k > 2) { @@ -126,6 +147,10 @@ function showSingleTrainOverlay(id, x_position = null) { `${view_ontd_map[id].agency_id} ` + `${view_ontd_map[id].route_long_name}`; const stroke = getStrokeColor(id); + var fip_button = ""; + if (getFipDetailsTarget(id)) { + fip_button = `${map_i18n.fipInformation}`; + } const text = `
@@ -157,6 +182,7 @@ ${view_ontd_map[id].trip_short_name_1}
${map_i18n.details} +${fip_button}
From 4c1dfdd9bd2e2c3640fe66c84e7e87dbd2ace03b Mon Sep 17 00:00:00 2001 From: lennartrommeiss <61516567+lenderom@users.noreply.github.com> Date: Sat, 15 Aug 2026 12:22:18 +0200 Subject: [PATCH 3/3] fix: change structure --- content/nighttrain-details/_index.de.md | 9 + content/nighttrain-details/_index.en.md | 9 + content/nighttrain-details/_index.fr.md | 9 + .../atc-nighttrain/index.de.md | 12 + .../atc-nighttrain/index.en.md | 12 + .../atc-nighttrain/index.fr.md | 12 + .../nighttrain-details/bdz-icf/index.de.md | 22 + .../nighttrain-details/bdz-icf/index.en.md | 16 + .../nighttrain-details/bdz-icf/index.fr.md | 16 + .../fs-intercity-notte/index.de.md | 32 + .../fs-intercity-notte/index.en.md | 28 + .../fs-intercity-notte/index.fr.md | 28 + .../oebb-nightjet/index.de.md | 42 ++ .../oebb-nightjet/index.en.md | 26 + .../oebb-nightjet/index.fr.md | 26 + .../placeholder-cd/index.de.md | 13 + .../placeholder-cd/index.en.md | 13 + .../placeholder-cd/index.fr.md | 13 + .../placeholder-cfm-cfr/index.de.md | 12 + .../placeholder-cfm-cfr/index.en.md | 12 + .../placeholder-cfm-cfr/index.fr.md | 12 + .../placeholder-cfr-mav-oebb/index.de.md | 12 + .../placeholder-cfr-mav-oebb/index.en.md | 12 + .../placeholder-cfr-mav-oebb/index.fr.md | 12 + .../placeholder-cfr-mav/index.de.md | 13 + .../placeholder-cfr-mav/index.en.md | 13 + .../placeholder-cfr-mav/index.fr.md | 13 + .../placeholder-cfr/index.de.md | 24 + .../placeholder-cfr/index.en.md | 24 + .../placeholder-cfr/index.fr.md | 24 + .../placeholder-cs/index.de.md | 16 + .../placeholder-cs/index.en.md | 16 + .../placeholder-cs/index.fr.md | 16 + .../placeholder-es/index.de.md | 15 + .../placeholder-es/index.en.md | 15 + .../placeholder-es/index.fr.md | 15 + .../placeholder-fs/index.de.md | 13 + .../placeholder-fs/index.en.md | 13 + .../placeholder-fs/index.fr.md | 13 + .../placeholder-ga/index.de.md | 12 + .../placeholder-ga/index.en.md | 12 + .../placeholder-ga/index.fr.md | 12 + .../placeholder-gwr/index.de.md | 12 + .../placeholder-gwr/index.en.md | 12 + .../placeholder-gwr/index.fr.md | 12 + .../placeholder-hzpp-oebb/index.de.md | 13 + .../placeholder-hzpp-oebb/index.en.md | 13 + .../placeholder-hzpp-oebb/index.fr.md | 13 + .../placeholder-hzpp/index.de.md | 13 + .../placeholder-hzpp/index.en.md | 13 + .../placeholder-hzpp/index.fr.md | 13 + .../placeholder-mav-oebb/index.de.md | 13 + .../placeholder-mav-oebb/index.en.md | 13 + .../placeholder-mav-oebb/index.fr.md | 13 + .../placeholder-mav-pkp/index.de.md | 12 + .../placeholder-mav-pkp/index.en.md | 12 + .../placeholder-mav-pkp/index.fr.md | 12 + .../placeholder-mav/index.de.md | 15 + .../placeholder-mav/index.en.md | 15 + .../placeholder-mav/index.fr.md | 15 + .../placeholder-oebb/index.de.md | 15 + .../placeholder-oebb/index.en.md | 15 + .../placeholder-oebb/index.fr.md | 15 + .../placeholder-ote/index.de.md | 12 + .../placeholder-ote/index.en.md | 12 + .../placeholder-ote/index.fr.md | 12 + .../placeholder-pkp-cd/index.de.md | 18 + .../placeholder-pkp-cd/index.en.md | 18 + .../placeholder-pkp-cd/index.fr.md | 18 + .../placeholder-pkp/index.de.md | 22 + .../placeholder-pkp/index.en.md | 22 + .../placeholder-pkp/index.fr.md | 22 + .../placeholder-rdc-sj/index.de.md | 12 + .../placeholder-rdc-sj/index.en.md | 12 + .../placeholder-rdc-sj/index.fr.md | 12 + .../placeholder-rj/index.de.md | 13 + .../placeholder-rj/index.en.md | 13 + .../placeholder-rj/index.fr.md | 13 + .../placeholder-sjn/index.de.md | 13 + .../placeholder-sjn/index.en.md | 13 + .../placeholder-sjn/index.fr.md | 13 + .../placeholder-st/index.de.md | 15 + .../placeholder-st/index.en.md | 15 + .../placeholder-st/index.fr.md | 15 + .../placeholder-tcdd-bdz-cfr/index.de.md | 12 + .../placeholder-tcdd-bdz-cfr/index.en.md | 12 + .../placeholder-tcdd-bdz-cfr/index.fr.md | 12 + .../placeholder-tcdd-bdz/index.de.md | 12 + .../placeholder-tcdd-bdz/index.en.md | 12 + .../placeholder-tcdd-bdz/index.fr.md | 12 + .../placeholder-tcdd/index.de.md | 18 + .../placeholder-tcdd/index.en.md | 18 + .../placeholder-tcdd/index.fr.md | 18 + .../placeholder-uex/index.de.md | 17 + .../placeholder-uex/index.en.md | 17 + .../placeholder-uex/index.fr.md | 17 + .../placeholder-uz-cfm/index.de.md | 12 + .../placeholder-uz-cfm/index.en.md | 12 + .../placeholder-uz-cfm/index.fr.md | 12 + .../placeholder-uz-oebb/index.de.md | 12 + .../placeholder-uz-oebb/index.en.md | 12 + .../placeholder-uz-oebb/index.fr.md | 12 + .../placeholder-uz/index.de.md | 70 ++ .../placeholder-uz/index.en.md | 70 ++ .../placeholder-uz/index.fr.md | 70 ++ .../placeholder-vy/index.de.md | 12 + .../placeholder-vy/index.en.md | 12 + .../placeholder-vy/index.fr.md | 12 + .../placeholder-zs-zpcg/index.de.md | 12 + .../placeholder-zs-zpcg/index.en.md | 12 + .../placeholder-zs-zpcg/index.fr.md | 12 + .../placeholder-zssk/index.de.md | 12 + .../placeholder-zssk/index.en.md | 12 + .../placeholder-zssk/index.fr.md | 12 + .../sj-night-trains/index.de.md | 14 + .../sj-night-trains/index.en.md | 14 + .../sj-night-trains/index.fr.md | 14 + .../sncf-intercites-nuit/index.de.md | 22 + .../sncf-intercites-nuit/index.en.md | 22 + .../sncf-intercites-nuit/index.fr.md | 22 + .../vr-night-trains/index.de.md | 16 + .../vr-night-trains/index.en.md | 16 + .../vr-night-trains/index.fr.md | 16 + data/nighttrains/de/fip_details.json | 656 ------------------ data/nighttrains/en/fip_details.json | 656 ------------------ data/nighttrains/fr/fip_details.json | 656 ------------------ .../_shortcodes/nighttrains-fip-details.html | 61 +- static/nighttrains/README.md | 37 +- 128 files changed, 2083 insertions(+), 1989 deletions(-) create mode 100644 content/nighttrain-details/_index.de.md create mode 100644 content/nighttrain-details/_index.en.md create mode 100644 content/nighttrain-details/_index.fr.md create mode 100644 content/nighttrain-details/atc-nighttrain/index.de.md create mode 100644 content/nighttrain-details/atc-nighttrain/index.en.md create mode 100644 content/nighttrain-details/atc-nighttrain/index.fr.md create mode 100644 content/nighttrain-details/bdz-icf/index.de.md create mode 100644 content/nighttrain-details/bdz-icf/index.en.md create mode 100644 content/nighttrain-details/bdz-icf/index.fr.md create mode 100644 content/nighttrain-details/fs-intercity-notte/index.de.md create mode 100644 content/nighttrain-details/fs-intercity-notte/index.en.md create mode 100644 content/nighttrain-details/fs-intercity-notte/index.fr.md create mode 100644 content/nighttrain-details/oebb-nightjet/index.de.md create mode 100644 content/nighttrain-details/oebb-nightjet/index.en.md create mode 100644 content/nighttrain-details/oebb-nightjet/index.fr.md create mode 100644 content/nighttrain-details/placeholder-cd/index.de.md create mode 100644 content/nighttrain-details/placeholder-cd/index.en.md create mode 100644 content/nighttrain-details/placeholder-cd/index.fr.md create mode 100644 content/nighttrain-details/placeholder-cfm-cfr/index.de.md create mode 100644 content/nighttrain-details/placeholder-cfm-cfr/index.en.md create mode 100644 content/nighttrain-details/placeholder-cfm-cfr/index.fr.md create mode 100644 content/nighttrain-details/placeholder-cfr-mav-oebb/index.de.md create mode 100644 content/nighttrain-details/placeholder-cfr-mav-oebb/index.en.md create mode 100644 content/nighttrain-details/placeholder-cfr-mav-oebb/index.fr.md create mode 100644 content/nighttrain-details/placeholder-cfr-mav/index.de.md create mode 100644 content/nighttrain-details/placeholder-cfr-mav/index.en.md create mode 100644 content/nighttrain-details/placeholder-cfr-mav/index.fr.md create mode 100644 content/nighttrain-details/placeholder-cfr/index.de.md create mode 100644 content/nighttrain-details/placeholder-cfr/index.en.md create mode 100644 content/nighttrain-details/placeholder-cfr/index.fr.md create mode 100644 content/nighttrain-details/placeholder-cs/index.de.md create mode 100644 content/nighttrain-details/placeholder-cs/index.en.md create mode 100644 content/nighttrain-details/placeholder-cs/index.fr.md create mode 100644 content/nighttrain-details/placeholder-es/index.de.md create mode 100644 content/nighttrain-details/placeholder-es/index.en.md create mode 100644 content/nighttrain-details/placeholder-es/index.fr.md create mode 100644 content/nighttrain-details/placeholder-fs/index.de.md create mode 100644 content/nighttrain-details/placeholder-fs/index.en.md create mode 100644 content/nighttrain-details/placeholder-fs/index.fr.md create mode 100644 content/nighttrain-details/placeholder-ga/index.de.md create mode 100644 content/nighttrain-details/placeholder-ga/index.en.md create mode 100644 content/nighttrain-details/placeholder-ga/index.fr.md create mode 100644 content/nighttrain-details/placeholder-gwr/index.de.md create mode 100644 content/nighttrain-details/placeholder-gwr/index.en.md create mode 100644 content/nighttrain-details/placeholder-gwr/index.fr.md create mode 100644 content/nighttrain-details/placeholder-hzpp-oebb/index.de.md create mode 100644 content/nighttrain-details/placeholder-hzpp-oebb/index.en.md create mode 100644 content/nighttrain-details/placeholder-hzpp-oebb/index.fr.md create mode 100644 content/nighttrain-details/placeholder-hzpp/index.de.md create mode 100644 content/nighttrain-details/placeholder-hzpp/index.en.md create mode 100644 content/nighttrain-details/placeholder-hzpp/index.fr.md create mode 100644 content/nighttrain-details/placeholder-mav-oebb/index.de.md create mode 100644 content/nighttrain-details/placeholder-mav-oebb/index.en.md create mode 100644 content/nighttrain-details/placeholder-mav-oebb/index.fr.md create mode 100644 content/nighttrain-details/placeholder-mav-pkp/index.de.md create mode 100644 content/nighttrain-details/placeholder-mav-pkp/index.en.md create mode 100644 content/nighttrain-details/placeholder-mav-pkp/index.fr.md create mode 100644 content/nighttrain-details/placeholder-mav/index.de.md create mode 100644 content/nighttrain-details/placeholder-mav/index.en.md create mode 100644 content/nighttrain-details/placeholder-mav/index.fr.md create mode 100644 content/nighttrain-details/placeholder-oebb/index.de.md create mode 100644 content/nighttrain-details/placeholder-oebb/index.en.md create mode 100644 content/nighttrain-details/placeholder-oebb/index.fr.md create mode 100644 content/nighttrain-details/placeholder-ote/index.de.md create mode 100644 content/nighttrain-details/placeholder-ote/index.en.md create mode 100644 content/nighttrain-details/placeholder-ote/index.fr.md create mode 100644 content/nighttrain-details/placeholder-pkp-cd/index.de.md create mode 100644 content/nighttrain-details/placeholder-pkp-cd/index.en.md create mode 100644 content/nighttrain-details/placeholder-pkp-cd/index.fr.md create mode 100644 content/nighttrain-details/placeholder-pkp/index.de.md create mode 100644 content/nighttrain-details/placeholder-pkp/index.en.md create mode 100644 content/nighttrain-details/placeholder-pkp/index.fr.md create mode 100644 content/nighttrain-details/placeholder-rdc-sj/index.de.md create mode 100644 content/nighttrain-details/placeholder-rdc-sj/index.en.md create mode 100644 content/nighttrain-details/placeholder-rdc-sj/index.fr.md create mode 100644 content/nighttrain-details/placeholder-rj/index.de.md create mode 100644 content/nighttrain-details/placeholder-rj/index.en.md create mode 100644 content/nighttrain-details/placeholder-rj/index.fr.md create mode 100644 content/nighttrain-details/placeholder-sjn/index.de.md create mode 100644 content/nighttrain-details/placeholder-sjn/index.en.md create mode 100644 content/nighttrain-details/placeholder-sjn/index.fr.md create mode 100644 content/nighttrain-details/placeholder-st/index.de.md create mode 100644 content/nighttrain-details/placeholder-st/index.en.md create mode 100644 content/nighttrain-details/placeholder-st/index.fr.md create mode 100644 content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.de.md create mode 100644 content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.en.md create mode 100644 content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.fr.md create mode 100644 content/nighttrain-details/placeholder-tcdd-bdz/index.de.md create mode 100644 content/nighttrain-details/placeholder-tcdd-bdz/index.en.md create mode 100644 content/nighttrain-details/placeholder-tcdd-bdz/index.fr.md create mode 100644 content/nighttrain-details/placeholder-tcdd/index.de.md create mode 100644 content/nighttrain-details/placeholder-tcdd/index.en.md create mode 100644 content/nighttrain-details/placeholder-tcdd/index.fr.md create mode 100644 content/nighttrain-details/placeholder-uex/index.de.md create mode 100644 content/nighttrain-details/placeholder-uex/index.en.md create mode 100644 content/nighttrain-details/placeholder-uex/index.fr.md create mode 100644 content/nighttrain-details/placeholder-uz-cfm/index.de.md create mode 100644 content/nighttrain-details/placeholder-uz-cfm/index.en.md create mode 100644 content/nighttrain-details/placeholder-uz-cfm/index.fr.md create mode 100644 content/nighttrain-details/placeholder-uz-oebb/index.de.md create mode 100644 content/nighttrain-details/placeholder-uz-oebb/index.en.md create mode 100644 content/nighttrain-details/placeholder-uz-oebb/index.fr.md create mode 100644 content/nighttrain-details/placeholder-uz/index.de.md create mode 100644 content/nighttrain-details/placeholder-uz/index.en.md create mode 100644 content/nighttrain-details/placeholder-uz/index.fr.md create mode 100644 content/nighttrain-details/placeholder-vy/index.de.md create mode 100644 content/nighttrain-details/placeholder-vy/index.en.md create mode 100644 content/nighttrain-details/placeholder-vy/index.fr.md create mode 100644 content/nighttrain-details/placeholder-zs-zpcg/index.de.md create mode 100644 content/nighttrain-details/placeholder-zs-zpcg/index.en.md create mode 100644 content/nighttrain-details/placeholder-zs-zpcg/index.fr.md create mode 100644 content/nighttrain-details/placeholder-zssk/index.de.md create mode 100644 content/nighttrain-details/placeholder-zssk/index.en.md create mode 100644 content/nighttrain-details/placeholder-zssk/index.fr.md create mode 100644 content/nighttrain-details/sj-night-trains/index.de.md create mode 100644 content/nighttrain-details/sj-night-trains/index.en.md create mode 100644 content/nighttrain-details/sj-night-trains/index.fr.md create mode 100644 content/nighttrain-details/sncf-intercites-nuit/index.de.md create mode 100644 content/nighttrain-details/sncf-intercites-nuit/index.en.md create mode 100644 content/nighttrain-details/sncf-intercites-nuit/index.fr.md create mode 100644 content/nighttrain-details/vr-night-trains/index.de.md create mode 100644 content/nighttrain-details/vr-night-trains/index.en.md create mode 100644 content/nighttrain-details/vr-night-trains/index.fr.md delete mode 100644 data/nighttrains/de/fip_details.json delete mode 100644 data/nighttrains/en/fip_details.json delete mode 100644 data/nighttrains/fr/fip_details.json diff --git a/content/nighttrain-details/_index.de.md b/content/nighttrain-details/_index.de.md new file mode 100644 index 000000000..a23067b66 --- /dev/null +++ b/content/nighttrain-details/_index.de.md @@ -0,0 +1,9 @@ +--- +title: "Nachtzugdetails" + +cascade: + - build: + list: false + publishResources: false + render: never +--- diff --git a/content/nighttrain-details/_index.en.md b/content/nighttrain-details/_index.en.md new file mode 100644 index 000000000..747696a60 --- /dev/null +++ b/content/nighttrain-details/_index.en.md @@ -0,0 +1,9 @@ +--- +title: "Night train details" + +cascade: + - build: + list: false + publishResources: false + render: never +--- diff --git a/content/nighttrain-details/_index.fr.md b/content/nighttrain-details/_index.fr.md new file mode 100644 index 000000000..248ff377e --- /dev/null +++ b/content/nighttrain-details/_index.fr.md @@ -0,0 +1,9 @@ +--- +title: "Informations trains de nuit" + +cascade: + - build: + list: false + publishResources: false + render: never +--- diff --git a/content/nighttrain-details/atc-nighttrain/index.de.md b/content/nighttrain-details/atc-nighttrain/index.de.md new file mode 100644 index 000000000..eec13bc2f --- /dev/null +++ b/content/nighttrain-details/atc-nighttrain/index.de.md @@ -0,0 +1,12 @@ +--- +id: "atc-nighttrain" +title: "Astra Trains Carpatic (ATC) Nachtzug" +source_route_ids: + - "24" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Nachtzug innerhalb Rumäniens von Astra Trains Carpatic (ATC) mit Schlaf- und Liegewagen zwischen Bukarest und Arad. diff --git a/content/nighttrain-details/atc-nighttrain/index.en.md b/content/nighttrain-details/atc-nighttrain/index.en.md new file mode 100644 index 000000000..68ceda187 --- /dev/null +++ b/content/nighttrain-details/atc-nighttrain/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-atc" +title: "Night trains ATC" +source_route_ids: + - "24" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/atc-nighttrain/index.fr.md b/content/nighttrain-details/atc-nighttrain/index.fr.md new file mode 100644 index 000000000..e51ab17ac --- /dev/null +++ b/content/nighttrain-details/atc-nighttrain/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-atc" +title: "Trains de nuit ATC" +source_route_ids: + - "24" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/bdz-icf/index.de.md b/content/nighttrain-details/bdz-icf/index.de.md new file mode 100644 index 000000000..623a89644 --- /dev/null +++ b/content/nighttrain-details/bdz-icf/index.de.md @@ -0,0 +1,22 @@ +--- +id: "bdz-icf" +title: "BDŽ Intercity Fast Train (ICF)" +source_route_ids: + - "131" + - "133" + - "134" + - "135" + - "142" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [bdz-ticket-office] +--- + +Nachtzüge der [BDŽ](/operator/bdz) von Sofia nach Varna, Dobrich, Silistra und Burgas. Die Züge verkehren als normale Intercity Fast Trains (ICF) mit Sitzwagen, die zusätzliche Schlaf- und Liegewagen mitführen. + +#### Reservierungen + +Reservierungen sind nur für Schlaf- und Liegewagen möglich. Für Sitzwagen ist keine Reservierung erforderlich, außer der Zug ist mit _R_ im Fahrplan gekennzeichnet. In diesem Fall ist eine Reservierung auch für Sitzwagen erforderlich. + +**Kosten:** abhängig von Strecke und Auslastung sowie Wagenkategorie. diff --git a/content/nighttrain-details/bdz-icf/index.en.md b/content/nighttrain-details/bdz-icf/index.en.md new file mode 100644 index 000000000..2355a468f --- /dev/null +++ b/content/nighttrain-details/bdz-icf/index.en.md @@ -0,0 +1,16 @@ +--- +id: "placeholder-bdz" +title: "Night trains BDZ" +source_route_ids: + - "131" + - "133" + - "134" + - "135" + - "142" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/bdz-icf/index.fr.md b/content/nighttrain-details/bdz-icf/index.fr.md new file mode 100644 index 000000000..e5751030a --- /dev/null +++ b/content/nighttrain-details/bdz-icf/index.fr.md @@ -0,0 +1,16 @@ +--- +id: "placeholder-bdz" +title: "Trains de nuit BDZ" +source_route_ids: + - "131" + - "133" + - "134" + - "135" + - "142" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/fs-intercity-notte/index.de.md b/content/nighttrain-details/fs-intercity-notte/index.de.md new file mode 100644 index 000000000..1a3a681d6 --- /dev/null +++ b/content/nighttrain-details/fs-intercity-notte/index.de.md @@ -0,0 +1,32 @@ +--- +id: "fs-intercity-notte" +title: "Trenitalia (FS) Intercity Notte (ICN)" +source_route_ids: + - "76" + - "83" + - "84" + - "85" + - "86" + - "96" + - "97" + - "99" + - "100" + - "101" + - "102" + - "103" + - "104" + - "126" + - "128" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: + - "fs-ticket-office" +--- + +Nationaler Nachtzug der [Trenitalia](/operator/fs) mit Schlaf-, Liege- und Sitzwagen. + +#### Reservierungen + +**Kosten**: 25 € (1./2. Klasse) im Sitzwagen +Der Reservierungspreis enthält immer einen Aufschlag bei Nutzung mit FIP Freifahrtschein. Für Liege- oder Schlafwagen kommt noch ein Aufschlag für die jeweilige Kategorie dazu. diff --git a/content/nighttrain-details/fs-intercity-notte/index.en.md b/content/nighttrain-details/fs-intercity-notte/index.en.md new file mode 100644 index 000000000..5fd3986d5 --- /dev/null +++ b/content/nighttrain-details/fs-intercity-notte/index.en.md @@ -0,0 +1,28 @@ +--- +id: "fs-intercity-notte" +title: "Intercity Notte (FS)" +source_route_ids: + - "76" + - "83" + - "84" + - "85" + - "86" + - "96" + - "97" + - "99" + - "100" + - "101" + - "102" + - "103" + - "104" + - "126" + - "128" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: + - "fs-website" + - "fs-ticket-office" +--- + +Trenitalia night services in Italy, including routes with through coaches to Sicily. diff --git a/content/nighttrain-details/fs-intercity-notte/index.fr.md b/content/nighttrain-details/fs-intercity-notte/index.fr.md new file mode 100644 index 000000000..1b8b71925 --- /dev/null +++ b/content/nighttrain-details/fs-intercity-notte/index.fr.md @@ -0,0 +1,28 @@ +--- +id: "fs-intercity-notte" +title: "Intercity Notte (FS)" +source_route_ids: + - "76" + - "83" + - "84" + - "85" + - "86" + - "96" + - "97" + - "99" + - "100" + - "101" + - "102" + - "103" + - "104" + - "126" + - "128" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: + - "fs-website" + - "fs-ticket-office" +--- + +Services de nuit de Trenitalia en Italie, y compris des relations avec voitures directes vers la Sicile. diff --git a/content/nighttrain-details/oebb-nightjet/index.de.md b/content/nighttrain-details/oebb-nightjet/index.de.md new file mode 100644 index 000000000..e454cc8c6 --- /dev/null +++ b/content/nighttrain-details/oebb-nightjet/index.de.md @@ -0,0 +1,42 @@ +--- +id: "oebb-nightjet" +title: "ÖBB Nightjet" +source_route_ids: + - "1" + - "2" + - "5" + - "17" + - "18" + - "44" + - "45" + - "46" + - "49" + - "50" + - "53" + - "115" +fip_global_fare: true +fip_coupon: true +fip_50: true +booking_options: + - "oebb-phone" + - "oebb-ticket-office" + - "db-ticket-office" +--- + +Nachtzüge der ÖBB in verschiedene europäische Länder. Die Züge bieten Schlaf- und Liegewagen sowie Sitzwagen an und werden im Ausland in Kooperation mit anderen Bahngesellschaften betrieben. + +Innerhalb Österreichs können die Nightjet-Züge mit einem ÖBB-Freifahrtschein genutzt werden. In den anderen Ländern ist am dem [Grenzpunkt](/general/generalinformation/#grenzpunkte) ein Ticket/Freifahrtschein der jeweiligen Bahngesellschaft erforderlich (z.B. der DB oder SBB). + +{{% highlight important %}} +Nationale Freifahrten für Mitarbeitende der Deutschen Bahn werden in Deutschland nicht anerkannt. Liegt ein Teil der Nightjet Fahrt also in Deutschland (Start, Ende oder Durchreise) müssen Mitarbeiter der Deutschen Bahn für die gesamte Strecke ein Ticket zum FIP Globalpreis erwerben. Für Fahrten außerhalb Deutschlands mit FIP Freifahrtschein ist eine Reservierung/Aufpreis erforderlich. +{{% /highlight %}} + +{{% highlight tip %}} +Für Fahrten von Deutschland nach Italien, die nationalen Freifahrten bis Salzburg nutzen und dort in den Nightjet steigen, um den FIP Globalpreis zu vermeiden. +{{% /highlight %}} + +#### Reservierungen + +Für Nightjet Züge können Reservierungen/Aufpreise für Schlaf- und Liegewagen gebucht werden. Dafür ist ein FIP Freifahrtschein für die Länder/Bahngesellschaften erforderlich, die auf der Reise durchfahren werden. Wenn kein FIP Freifahrtschein genutzt wird, kann ein Ticket zum FIP Globalpreis für die gesamte Strecke erworben werden. + +**Kosten:** abhängig von Strecke und Auslastung sowie Wagenkategorie. diff --git a/content/nighttrain-details/oebb-nightjet/index.en.md b/content/nighttrain-details/oebb-nightjet/index.en.md new file mode 100644 index 000000000..328963b9a --- /dev/null +++ b/content/nighttrain-details/oebb-nightjet/index.en.md @@ -0,0 +1,26 @@ +--- +id: "oebb-nightjet" +title: "Nightjet (OEBB)" +source_route_ids: + - "1" + - "2" + - "5" + - "17" + - "18" + - "44" + - "45" + - "46" + - "49" + - "50" + - "53" + - "115" +fip_global_fare: true +fip_coupon: true +fip_50: true +booking_options: + - "oebb-website" + - "oebb-phone" + - "oebb-ticket-office" +--- + +Night train services operated by OEBB in the Nightjet network, including selected cross-border routes. diff --git a/content/nighttrain-details/oebb-nightjet/index.fr.md b/content/nighttrain-details/oebb-nightjet/index.fr.md new file mode 100644 index 000000000..c00bf91a0 --- /dev/null +++ b/content/nighttrain-details/oebb-nightjet/index.fr.md @@ -0,0 +1,26 @@ +--- +id: "oebb-nightjet" +title: "Nightjet (OEBB)" +source_route_ids: + - "1" + - "2" + - "5" + - "17" + - "18" + - "44" + - "45" + - "46" + - "49" + - "50" + - "53" + - "115" +fip_global_fare: true +fip_coupon: true +fip_50: true +booking_options: + - "oebb-website" + - "oebb-phone" + - "oebb-ticket-office" +--- + +Relations de nuit exploitees par OEBB dans le reseau Nightjet, y compris certaines liaisons transfrontalieres. diff --git a/content/nighttrain-details/placeholder-cd/index.de.md b/content/nighttrain-details/placeholder-cd/index.de.md new file mode 100644 index 000000000..7ce7204e3 --- /dev/null +++ b/content/nighttrain-details/placeholder-cd/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-cd" +title: "Nachtzuege CD" +source_route_ids: + - "6" + - "120" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-cd/index.en.md b/content/nighttrain-details/placeholder-cd/index.en.md new file mode 100644 index 000000000..276fd3bac --- /dev/null +++ b/content/nighttrain-details/placeholder-cd/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-cd" +title: "Night trains CD" +source_route_ids: + - "6" + - "120" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-cd/index.fr.md b/content/nighttrain-details/placeholder-cd/index.fr.md new file mode 100644 index 000000000..529bdcf99 --- /dev/null +++ b/content/nighttrain-details/placeholder-cd/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-cd" +title: "Trains de nuit CD" +source_route_ids: + - "6" + - "120" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-cfm-cfr/index.de.md b/content/nighttrain-details/placeholder-cfm-cfr/index.de.md new file mode 100644 index 000000000..7cd8c72ea --- /dev/null +++ b/content/nighttrain-details/placeholder-cfm-cfr/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-cfm-cfr" +title: "Nachtzuege CFM/CFR" +source_route_ids: + - "22" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-cfm-cfr/index.en.md b/content/nighttrain-details/placeholder-cfm-cfr/index.en.md new file mode 100644 index 000000000..f8101869f --- /dev/null +++ b/content/nighttrain-details/placeholder-cfm-cfr/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-cfm-cfr" +title: "Night trains CFM/CFR" +source_route_ids: + - "22" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-cfm-cfr/index.fr.md b/content/nighttrain-details/placeholder-cfm-cfr/index.fr.md new file mode 100644 index 000000000..5e24a3dea --- /dev/null +++ b/content/nighttrain-details/placeholder-cfm-cfr/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-cfm-cfr" +title: "Trains de nuit CFM/CFR" +source_route_ids: + - "22" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-cfr-mav-oebb/index.de.md b/content/nighttrain-details/placeholder-cfr-mav-oebb/index.de.md new file mode 100644 index 000000000..6f8de2012 --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr-mav-oebb/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-cfr-mav-oebb" +title: "Nachtzuege CFR/MAV/OEBB" +source_route_ids: + - "59" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-cfr-mav-oebb/index.en.md b/content/nighttrain-details/placeholder-cfr-mav-oebb/index.en.md new file mode 100644 index 000000000..78b92fed8 --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr-mav-oebb/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-cfr-mav-oebb" +title: "Night trains CFR/MAV/OEBB" +source_route_ids: + - "59" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-cfr-mav-oebb/index.fr.md b/content/nighttrain-details/placeholder-cfr-mav-oebb/index.fr.md new file mode 100644 index 000000000..3be420e28 --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr-mav-oebb/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-cfr-mav-oebb" +title: "Trains de nuit CFR/MAV/OEBB" +source_route_ids: + - "59" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-cfr-mav/index.de.md b/content/nighttrain-details/placeholder-cfr-mav/index.de.md new file mode 100644 index 000000000..044ea731b --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr-mav/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-cfr-mav" +title: "Nachtzuege CFR/MAV" +source_route_ids: + - "16" + - "67" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-cfr-mav/index.en.md b/content/nighttrain-details/placeholder-cfr-mav/index.en.md new file mode 100644 index 000000000..495d793d8 --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr-mav/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-cfr-mav" +title: "Night trains CFR/MAV" +source_route_ids: + - "16" + - "67" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-cfr-mav/index.fr.md b/content/nighttrain-details/placeholder-cfr-mav/index.fr.md new file mode 100644 index 000000000..0edbfadd8 --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr-mav/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-cfr-mav" +title: "Trains de nuit CFR/MAV" +source_route_ids: + - "16" + - "67" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-cfr/index.de.md b/content/nighttrain-details/placeholder-cfr/index.de.md new file mode 100644 index 000000000..7cb7cf7ae --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr/index.de.md @@ -0,0 +1,24 @@ +--- +id: "placeholder-cfr" +title: "Nachtzuege CFR" +source_route_ids: + - "11" + - "12" + - "13" + - "14" + - "15" + - "19" + - "20" + - "21" + - "23" + - "25" + - "26" + - "249" + - "250" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-cfr/index.en.md b/content/nighttrain-details/placeholder-cfr/index.en.md new file mode 100644 index 000000000..07d6ff8eb --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr/index.en.md @@ -0,0 +1,24 @@ +--- +id: "placeholder-cfr" +title: "Night trains CFR" +source_route_ids: + - "11" + - "12" + - "13" + - "14" + - "15" + - "19" + - "20" + - "21" + - "23" + - "25" + - "26" + - "249" + - "250" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-cfr/index.fr.md b/content/nighttrain-details/placeholder-cfr/index.fr.md new file mode 100644 index 000000000..b085ec48f --- /dev/null +++ b/content/nighttrain-details/placeholder-cfr/index.fr.md @@ -0,0 +1,24 @@ +--- +id: "placeholder-cfr" +title: "Trains de nuit CFR" +source_route_ids: + - "11" + - "12" + - "13" + - "14" + - "15" + - "19" + - "20" + - "21" + - "23" + - "25" + - "26" + - "249" + - "250" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-cs/index.de.md b/content/nighttrain-details/placeholder-cs/index.de.md new file mode 100644 index 000000000..966175dc7 --- /dev/null +++ b/content/nighttrain-details/placeholder-cs/index.de.md @@ -0,0 +1,16 @@ +--- +id: "placeholder-cs" +title: "Nachtzuege CS" +source_route_ids: + - "37" + - "38" + - "39" + - "40" + - "41" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-cs/index.en.md b/content/nighttrain-details/placeholder-cs/index.en.md new file mode 100644 index 000000000..edaf46d93 --- /dev/null +++ b/content/nighttrain-details/placeholder-cs/index.en.md @@ -0,0 +1,16 @@ +--- +id: "placeholder-cs" +title: "Night trains CS" +source_route_ids: + - "37" + - "38" + - "39" + - "40" + - "41" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-cs/index.fr.md b/content/nighttrain-details/placeholder-cs/index.fr.md new file mode 100644 index 000000000..c0806bc18 --- /dev/null +++ b/content/nighttrain-details/placeholder-cs/index.fr.md @@ -0,0 +1,16 @@ +--- +id: "placeholder-cs" +title: "Trains de nuit CS" +source_route_ids: + - "37" + - "38" + - "39" + - "40" + - "41" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-es/index.de.md b/content/nighttrain-details/placeholder-es/index.de.md new file mode 100644 index 000000000..af8001fee --- /dev/null +++ b/content/nighttrain-details/placeholder-es/index.de.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-es" +title: "Nachtzuege ES" +source_route_ids: + - "237" + - "238" + - "239" + - "240" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-es/index.en.md b/content/nighttrain-details/placeholder-es/index.en.md new file mode 100644 index 000000000..1b6b24b2d --- /dev/null +++ b/content/nighttrain-details/placeholder-es/index.en.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-es" +title: "Night trains ES" +source_route_ids: + - "237" + - "238" + - "239" + - "240" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-es/index.fr.md b/content/nighttrain-details/placeholder-es/index.fr.md new file mode 100644 index 000000000..048eef2d9 --- /dev/null +++ b/content/nighttrain-details/placeholder-es/index.fr.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-es" +title: "Trains de nuit ES" +source_route_ids: + - "237" + - "238" + - "239" + - "240" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-fs/index.de.md b/content/nighttrain-details/placeholder-fs/index.de.md new file mode 100644 index 000000000..5e7b2b7b7 --- /dev/null +++ b/content/nighttrain-details/placeholder-fs/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-fs" +title: "Nachtzuege FS" +source_route_ids: + - "105" + - "106" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-fs/index.en.md b/content/nighttrain-details/placeholder-fs/index.en.md new file mode 100644 index 000000000..ef8004fb4 --- /dev/null +++ b/content/nighttrain-details/placeholder-fs/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-fs" +title: "Night trains FS" +source_route_ids: + - "105" + - "106" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-fs/index.fr.md b/content/nighttrain-details/placeholder-fs/index.fr.md new file mode 100644 index 000000000..767627760 --- /dev/null +++ b/content/nighttrain-details/placeholder-fs/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-fs" +title: "Trains de nuit FS" +source_route_ids: + - "105" + - "106" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-ga/index.de.md b/content/nighttrain-details/placeholder-ga/index.de.md new file mode 100644 index 000000000..87d60c29b --- /dev/null +++ b/content/nighttrain-details/placeholder-ga/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-ga" +title: "Nachtzuege GA" +source_route_ids: + - "65" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-ga/index.en.md b/content/nighttrain-details/placeholder-ga/index.en.md new file mode 100644 index 000000000..234e82798 --- /dev/null +++ b/content/nighttrain-details/placeholder-ga/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-ga" +title: "Night trains GA" +source_route_ids: + - "65" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-ga/index.fr.md b/content/nighttrain-details/placeholder-ga/index.fr.md new file mode 100644 index 000000000..784de231f --- /dev/null +++ b/content/nighttrain-details/placeholder-ga/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-ga" +title: "Trains de nuit GA" +source_route_ids: + - "65" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-gwr/index.de.md b/content/nighttrain-details/placeholder-gwr/index.de.md new file mode 100644 index 000000000..42cec7438 --- /dev/null +++ b/content/nighttrain-details/placeholder-gwr/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-gwr" +title: "Nachtzuege GWR" +source_route_ids: + - "42" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-gwr/index.en.md b/content/nighttrain-details/placeholder-gwr/index.en.md new file mode 100644 index 000000000..d878c092d --- /dev/null +++ b/content/nighttrain-details/placeholder-gwr/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-gwr" +title: "Night trains GWR" +source_route_ids: + - "42" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-gwr/index.fr.md b/content/nighttrain-details/placeholder-gwr/index.fr.md new file mode 100644 index 000000000..b45f5a09d --- /dev/null +++ b/content/nighttrain-details/placeholder-gwr/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-gwr" +title: "Trains de nuit GWR" +source_route_ids: + - "42" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-hzpp-oebb/index.de.md b/content/nighttrain-details/placeholder-hzpp-oebb/index.de.md new file mode 100644 index 000000000..71bc2323f --- /dev/null +++ b/content/nighttrain-details/placeholder-hzpp-oebb/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-hzpp-oebb" +title: "Nachtzuege HZPP/OEBB" +source_route_ids: + - "57" + - "117" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-hzpp-oebb/index.en.md b/content/nighttrain-details/placeholder-hzpp-oebb/index.en.md new file mode 100644 index 000000000..e591f5aed --- /dev/null +++ b/content/nighttrain-details/placeholder-hzpp-oebb/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-hzpp-oebb" +title: "Night trains HZPP/OEBB" +source_route_ids: + - "57" + - "117" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-hzpp-oebb/index.fr.md b/content/nighttrain-details/placeholder-hzpp-oebb/index.fr.md new file mode 100644 index 000000000..015992455 --- /dev/null +++ b/content/nighttrain-details/placeholder-hzpp-oebb/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-hzpp-oebb" +title: "Trains de nuit HZPP/OEBB" +source_route_ids: + - "57" + - "117" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-hzpp/index.de.md b/content/nighttrain-details/placeholder-hzpp/index.de.md new file mode 100644 index 000000000..19591c216 --- /dev/null +++ b/content/nighttrain-details/placeholder-hzpp/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-hzpp" +title: "Nachtzuege HZPP" +source_route_ids: + - "3" + - "48" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-hzpp/index.en.md b/content/nighttrain-details/placeholder-hzpp/index.en.md new file mode 100644 index 000000000..0ab9b0c92 --- /dev/null +++ b/content/nighttrain-details/placeholder-hzpp/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-hzpp" +title: "Night trains HZPP" +source_route_ids: + - "3" + - "48" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-hzpp/index.fr.md b/content/nighttrain-details/placeholder-hzpp/index.fr.md new file mode 100644 index 000000000..53ef37622 --- /dev/null +++ b/content/nighttrain-details/placeholder-hzpp/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-hzpp" +title: "Trains de nuit HZPP" +source_route_ids: + - "3" + - "48" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-mav-oebb/index.de.md b/content/nighttrain-details/placeholder-mav-oebb/index.de.md new file mode 100644 index 000000000..85ebefdec --- /dev/null +++ b/content/nighttrain-details/placeholder-mav-oebb/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-mav-oebb" +title: "Nachtzuege MAV/OEBB" +source_route_ids: + - "54" + - "74" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-mav-oebb/index.en.md b/content/nighttrain-details/placeholder-mav-oebb/index.en.md new file mode 100644 index 000000000..60b4686e2 --- /dev/null +++ b/content/nighttrain-details/placeholder-mav-oebb/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-mav-oebb" +title: "Night trains MAV/OEBB" +source_route_ids: + - "54" + - "74" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-mav-oebb/index.fr.md b/content/nighttrain-details/placeholder-mav-oebb/index.fr.md new file mode 100644 index 000000000..9dfb72bcd --- /dev/null +++ b/content/nighttrain-details/placeholder-mav-oebb/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-mav-oebb" +title: "Trains de nuit MAV/OEBB" +source_route_ids: + - "54" + - "74" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-mav-pkp/index.de.md b/content/nighttrain-details/placeholder-mav-pkp/index.de.md new file mode 100644 index 000000000..bf9d599b2 --- /dev/null +++ b/content/nighttrain-details/placeholder-mav-pkp/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-mav-pkp" +title: "Nachtzuege MAV/PKP" +source_route_ids: + - "127" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-mav-pkp/index.en.md b/content/nighttrain-details/placeholder-mav-pkp/index.en.md new file mode 100644 index 000000000..91d03da8b --- /dev/null +++ b/content/nighttrain-details/placeholder-mav-pkp/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-mav-pkp" +title: "Night trains MAV/PKP" +source_route_ids: + - "127" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-mav-pkp/index.fr.md b/content/nighttrain-details/placeholder-mav-pkp/index.fr.md new file mode 100644 index 000000000..d5b285e9b --- /dev/null +++ b/content/nighttrain-details/placeholder-mav-pkp/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-mav-pkp" +title: "Trains de nuit MAV/PKP" +source_route_ids: + - "127" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-mav/index.de.md b/content/nighttrain-details/placeholder-mav/index.de.md new file mode 100644 index 000000000..91b26e2c1 --- /dev/null +++ b/content/nighttrain-details/placeholder-mav/index.de.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-mav" +title: "Nachtzuege MAV" +source_route_ids: + - "58" + - "223" + - "224" + - "225" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-mav/index.en.md b/content/nighttrain-details/placeholder-mav/index.en.md new file mode 100644 index 000000000..763532d13 --- /dev/null +++ b/content/nighttrain-details/placeholder-mav/index.en.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-mav" +title: "Night trains MAV" +source_route_ids: + - "58" + - "223" + - "224" + - "225" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-mav/index.fr.md b/content/nighttrain-details/placeholder-mav/index.fr.md new file mode 100644 index 000000000..432aee2ff --- /dev/null +++ b/content/nighttrain-details/placeholder-mav/index.fr.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-mav" +title: "Trains de nuit MAV" +source_route_ids: + - "58" + - "223" + - "224" + - "225" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-oebb/index.de.md b/content/nighttrain-details/placeholder-oebb/index.de.md new file mode 100644 index 000000000..0a8027261 --- /dev/null +++ b/content/nighttrain-details/placeholder-oebb/index.de.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-oebb" +title: "Nachtzuege OEBB" +source_route_ids: + - "229" + - "232" + - "233" + - "235" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-oebb/index.en.md b/content/nighttrain-details/placeholder-oebb/index.en.md new file mode 100644 index 000000000..357a78346 --- /dev/null +++ b/content/nighttrain-details/placeholder-oebb/index.en.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-oebb" +title: "Night trains OEBB" +source_route_ids: + - "229" + - "232" + - "233" + - "235" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-oebb/index.fr.md b/content/nighttrain-details/placeholder-oebb/index.fr.md new file mode 100644 index 000000000..2c7799d64 --- /dev/null +++ b/content/nighttrain-details/placeholder-oebb/index.fr.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-oebb" +title: "Trains de nuit OEBB" +source_route_ids: + - "229" + - "232" + - "233" + - "235" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-ote/index.de.md b/content/nighttrain-details/placeholder-ote/index.de.md new file mode 100644 index 000000000..76016c3ac --- /dev/null +++ b/content/nighttrain-details/placeholder-ote/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-ote" +title: "Nachtzuege OTE" +source_route_ids: + - "114" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-ote/index.en.md b/content/nighttrain-details/placeholder-ote/index.en.md new file mode 100644 index 000000000..f17931b2a --- /dev/null +++ b/content/nighttrain-details/placeholder-ote/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-ote" +title: "Night trains OTE" +source_route_ids: + - "114" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-ote/index.fr.md b/content/nighttrain-details/placeholder-ote/index.fr.md new file mode 100644 index 000000000..cbef11f6d --- /dev/null +++ b/content/nighttrain-details/placeholder-ote/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-ote" +title: "Trains de nuit OTE" +source_route_ids: + - "114" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-pkp-cd/index.de.md b/content/nighttrain-details/placeholder-pkp-cd/index.de.md new file mode 100644 index 000000000..c2b27ef88 --- /dev/null +++ b/content/nighttrain-details/placeholder-pkp-cd/index.de.md @@ -0,0 +1,18 @@ +--- +id: "placeholder-pkp-cd" +title: "Nachtzuege PKP/CD" +source_route_ids: + - "8" + - "9" + - "116" + - "118" + - "124" + - "265" + - "266" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-pkp-cd/index.en.md b/content/nighttrain-details/placeholder-pkp-cd/index.en.md new file mode 100644 index 000000000..e8cf4478d --- /dev/null +++ b/content/nighttrain-details/placeholder-pkp-cd/index.en.md @@ -0,0 +1,18 @@ +--- +id: "placeholder-pkp-cd" +title: "Night trains PKP/CD" +source_route_ids: + - "8" + - "9" + - "116" + - "118" + - "124" + - "265" + - "266" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-pkp-cd/index.fr.md b/content/nighttrain-details/placeholder-pkp-cd/index.fr.md new file mode 100644 index 000000000..701513110 --- /dev/null +++ b/content/nighttrain-details/placeholder-pkp-cd/index.fr.md @@ -0,0 +1,18 @@ +--- +id: "placeholder-pkp-cd" +title: "Trains de nuit PKP/CD" +source_route_ids: + - "8" + - "9" + - "116" + - "118" + - "124" + - "265" + - "266" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-pkp/index.de.md b/content/nighttrain-details/placeholder-pkp/index.de.md new file mode 100644 index 000000000..8f2447bbf --- /dev/null +++ b/content/nighttrain-details/placeholder-pkp/index.de.md @@ -0,0 +1,22 @@ +--- +id: "placeholder-pkp" +title: "Nachtzuege PKP" +source_route_ids: + - "10" + - "113" + - "121" + - "122" + - "125" + - "129" + - "136" + - "137" + - "138" + - "267" + - "268" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-pkp/index.en.md b/content/nighttrain-details/placeholder-pkp/index.en.md new file mode 100644 index 000000000..f4e00dc30 --- /dev/null +++ b/content/nighttrain-details/placeholder-pkp/index.en.md @@ -0,0 +1,22 @@ +--- +id: "placeholder-pkp" +title: "Night trains PKP" +source_route_ids: + - "10" + - "113" + - "121" + - "122" + - "125" + - "129" + - "136" + - "137" + - "138" + - "267" + - "268" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-pkp/index.fr.md b/content/nighttrain-details/placeholder-pkp/index.fr.md new file mode 100644 index 000000000..47bf9d426 --- /dev/null +++ b/content/nighttrain-details/placeholder-pkp/index.fr.md @@ -0,0 +1,22 @@ +--- +id: "placeholder-pkp" +title: "Trains de nuit PKP" +source_route_ids: + - "10" + - "113" + - "121" + - "122" + - "125" + - "129" + - "136" + - "137" + - "138" + - "267" + - "268" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-rdc-sj/index.de.md b/content/nighttrain-details/placeholder-rdc-sj/index.de.md new file mode 100644 index 000000000..026c96f21 --- /dev/null +++ b/content/nighttrain-details/placeholder-rdc-sj/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-rdc-sj" +title: "Nachtzuege RDC/SJ" +source_route_ids: + - "78" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-rdc-sj/index.en.md b/content/nighttrain-details/placeholder-rdc-sj/index.en.md new file mode 100644 index 000000000..6d955932c --- /dev/null +++ b/content/nighttrain-details/placeholder-rdc-sj/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-rdc-sj" +title: "Night trains RDC/SJ" +source_route_ids: + - "78" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-rdc-sj/index.fr.md b/content/nighttrain-details/placeholder-rdc-sj/index.fr.md new file mode 100644 index 000000000..9d3d41ef6 --- /dev/null +++ b/content/nighttrain-details/placeholder-rdc-sj/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-rdc-sj" +title: "Trains de nuit RDC/SJ" +source_route_ids: + - "78" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-rj/index.de.md b/content/nighttrain-details/placeholder-rj/index.de.md new file mode 100644 index 000000000..7e63ec603 --- /dev/null +++ b/content/nighttrain-details/placeholder-rj/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-rj" +title: "Nachtzuege RJ" +source_route_ids: + - "7" + - "261" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-rj/index.en.md b/content/nighttrain-details/placeholder-rj/index.en.md new file mode 100644 index 000000000..ef6ad9acf --- /dev/null +++ b/content/nighttrain-details/placeholder-rj/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-rj" +title: "Night trains RJ" +source_route_ids: + - "7" + - "261" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-rj/index.fr.md b/content/nighttrain-details/placeholder-rj/index.fr.md new file mode 100644 index 000000000..a275f7f5c --- /dev/null +++ b/content/nighttrain-details/placeholder-rj/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-rj" +title: "Trains de nuit RJ" +source_route_ids: + - "7" + - "261" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-sjn/index.de.md b/content/nighttrain-details/placeholder-sjn/index.de.md new file mode 100644 index 000000000..fbe35372a --- /dev/null +++ b/content/nighttrain-details/placeholder-sjn/index.de.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-sjn" +title: "Nachtzuege SJN" +source_route_ids: + - "70" + - "71" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-sjn/index.en.md b/content/nighttrain-details/placeholder-sjn/index.en.md new file mode 100644 index 000000000..1cb7de4d1 --- /dev/null +++ b/content/nighttrain-details/placeholder-sjn/index.en.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-sjn" +title: "Night trains SJN" +source_route_ids: + - "70" + - "71" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-sjn/index.fr.md b/content/nighttrain-details/placeholder-sjn/index.fr.md new file mode 100644 index 000000000..e0acc216e --- /dev/null +++ b/content/nighttrain-details/placeholder-sjn/index.fr.md @@ -0,0 +1,13 @@ +--- +id: "placeholder-sjn" +title: "Trains de nuit SJN" +source_route_ids: + - "70" + - "71" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-st/index.de.md b/content/nighttrain-details/placeholder-st/index.de.md new file mode 100644 index 000000000..29aa1c708 --- /dev/null +++ b/content/nighttrain-details/placeholder-st/index.de.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-st" +title: "Nachtzuege ST" +source_route_ids: + - "73" + - "77" + - "79" + - "80" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-st/index.en.md b/content/nighttrain-details/placeholder-st/index.en.md new file mode 100644 index 000000000..63c2c75c2 --- /dev/null +++ b/content/nighttrain-details/placeholder-st/index.en.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-st" +title: "Night trains ST" +source_route_ids: + - "73" + - "77" + - "79" + - "80" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-st/index.fr.md b/content/nighttrain-details/placeholder-st/index.fr.md new file mode 100644 index 000000000..8518a40fd --- /dev/null +++ b/content/nighttrain-details/placeholder-st/index.fr.md @@ -0,0 +1,15 @@ +--- +id: "placeholder-st" +title: "Trains de nuit ST" +source_route_ids: + - "73" + - "77" + - "79" + - "80" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.de.md b/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.de.md new file mode 100644 index 000000000..285eee007 --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-tcdd-bdz-cfr" +title: "Nachtzuege TCDD/BDZ/CFR" +source_route_ids: + - "28" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.en.md b/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.en.md new file mode 100644 index 000000000..5ba842667 --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-tcdd-bdz-cfr" +title: "Night trains TCDD/BDZ/CFR" +source_route_ids: + - "28" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.fr.md b/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.fr.md new file mode 100644 index 000000000..c4a7d827e --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd-bdz-cfr/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-tcdd-bdz-cfr" +title: "Trains de nuit TCDD/BDZ/CFR" +source_route_ids: + - "28" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-tcdd-bdz/index.de.md b/content/nighttrain-details/placeholder-tcdd-bdz/index.de.md new file mode 100644 index 000000000..301e29302 --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd-bdz/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-tcdd-bdz" +title: "Nachtzuege TCDD/BDZ" +source_route_ids: + - "27" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-tcdd-bdz/index.en.md b/content/nighttrain-details/placeholder-tcdd-bdz/index.en.md new file mode 100644 index 000000000..52ee1611c --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd-bdz/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-tcdd-bdz" +title: "Night trains TCDD/BDZ" +source_route_ids: + - "27" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-tcdd-bdz/index.fr.md b/content/nighttrain-details/placeholder-tcdd-bdz/index.fr.md new file mode 100644 index 000000000..38079818c --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd-bdz/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-tcdd-bdz" +title: "Trains de nuit TCDD/BDZ" +source_route_ids: + - "27" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-tcdd/index.de.md b/content/nighttrain-details/placeholder-tcdd/index.de.md new file mode 100644 index 000000000..749b8f7e1 --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd/index.de.md @@ -0,0 +1,18 @@ +--- +id: "placeholder-tcdd" +title: "Nachtzuege TCDD" +source_route_ids: + - "30" + - "31" + - "243" + - "245" + - "246" + - "247" + - "248" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-tcdd/index.en.md b/content/nighttrain-details/placeholder-tcdd/index.en.md new file mode 100644 index 000000000..e22d04bb9 --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd/index.en.md @@ -0,0 +1,18 @@ +--- +id: "placeholder-tcdd" +title: "Night trains TCDD" +source_route_ids: + - "30" + - "31" + - "243" + - "245" + - "246" + - "247" + - "248" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-tcdd/index.fr.md b/content/nighttrain-details/placeholder-tcdd/index.fr.md new file mode 100644 index 000000000..7401da2b0 --- /dev/null +++ b/content/nighttrain-details/placeholder-tcdd/index.fr.md @@ -0,0 +1,18 @@ +--- +id: "placeholder-tcdd" +title: "Trains de nuit TCDD" +source_route_ids: + - "30" + - "31" + - "243" + - "245" + - "246" + - "247" + - "248" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-uex/index.de.md b/content/nighttrain-details/placeholder-uex/index.de.md new file mode 100644 index 000000000..448356e60 --- /dev/null +++ b/content/nighttrain-details/placeholder-uex/index.de.md @@ -0,0 +1,17 @@ +--- +id: "placeholder-uex" +title: "Nachtzuege UEX" +source_route_ids: + - "252" + - "253" + - "254" + - "255" + - "256" + - "257" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-uex/index.en.md b/content/nighttrain-details/placeholder-uex/index.en.md new file mode 100644 index 000000000..779c97f39 --- /dev/null +++ b/content/nighttrain-details/placeholder-uex/index.en.md @@ -0,0 +1,17 @@ +--- +id: "placeholder-uex" +title: "Night trains UEX" +source_route_ids: + - "252" + - "253" + - "254" + - "255" + - "256" + - "257" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-uex/index.fr.md b/content/nighttrain-details/placeholder-uex/index.fr.md new file mode 100644 index 000000000..f3717acb8 --- /dev/null +++ b/content/nighttrain-details/placeholder-uex/index.fr.md @@ -0,0 +1,17 @@ +--- +id: "placeholder-uex" +title: "Trains de nuit UEX" +source_route_ids: + - "252" + - "253" + - "254" + - "255" + - "256" + - "257" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-uz-cfm/index.de.md b/content/nighttrain-details/placeholder-uz-cfm/index.de.md new file mode 100644 index 000000000..e814089eb --- /dev/null +++ b/content/nighttrain-details/placeholder-uz-cfm/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-uz-cfm" +title: "Nachtzuege UZ/CFM" +source_route_ids: + - "195" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-uz-cfm/index.en.md b/content/nighttrain-details/placeholder-uz-cfm/index.en.md new file mode 100644 index 000000000..98d0fc6e2 --- /dev/null +++ b/content/nighttrain-details/placeholder-uz-cfm/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-uz-cfm" +title: "Night trains UZ/CFM" +source_route_ids: + - "195" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-uz-cfm/index.fr.md b/content/nighttrain-details/placeholder-uz-cfm/index.fr.md new file mode 100644 index 000000000..4b75df70d --- /dev/null +++ b/content/nighttrain-details/placeholder-uz-cfm/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-uz-cfm" +title: "Trains de nuit UZ/CFM" +source_route_ids: + - "195" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-uz-oebb/index.de.md b/content/nighttrain-details/placeholder-uz-oebb/index.de.md new file mode 100644 index 000000000..424c993de --- /dev/null +++ b/content/nighttrain-details/placeholder-uz-oebb/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-uz-oebb" +title: "Nachtzuege UZ/OEBB" +source_route_ids: + - "60" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-uz-oebb/index.en.md b/content/nighttrain-details/placeholder-uz-oebb/index.en.md new file mode 100644 index 000000000..990ee5e8e --- /dev/null +++ b/content/nighttrain-details/placeholder-uz-oebb/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-uz-oebb" +title: "Night trains UZ/OEBB" +source_route_ids: + - "60" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-uz-oebb/index.fr.md b/content/nighttrain-details/placeholder-uz-oebb/index.fr.md new file mode 100644 index 000000000..f4519a49a --- /dev/null +++ b/content/nighttrain-details/placeholder-uz-oebb/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-uz-oebb" +title: "Trains de nuit UZ/OEBB" +source_route_ids: + - "60" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-uz/index.de.md b/content/nighttrain-details/placeholder-uz/index.de.md new file mode 100644 index 000000000..fb01e3a34 --- /dev/null +++ b/content/nighttrain-details/placeholder-uz/index.de.md @@ -0,0 +1,70 @@ +--- +id: "placeholder-uz" +title: "Nachtzuege UZ" +source_route_ids: + - "140" + - "141" + - "147" + - "149" + - "150" + - "151" + - "152" + - "153" + - "154" + - "155" + - "156" + - "158" + - "161" + - "162" + - "164" + - "166" + - "167" + - "168" + - "170" + - "172" + - "173" + - "174" + - "175" + - "177" + - "178" + - "180" + - "181" + - "182" + - "183" + - "184" + - "185" + - "186" + - "189" + - "190" + - "191" + - "196" + - "197" + - "198" + - "199" + - "200" + - "201" + - "203" + - "207" + - "208" + - "209" + - "210" + - "211" + - "212" + - "213" + - "218" + - "219" + - "220" + - "221" + - "222" + - "227" + - "258" + - "259" + - "263" + - "269" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-uz/index.en.md b/content/nighttrain-details/placeholder-uz/index.en.md new file mode 100644 index 000000000..211e08624 --- /dev/null +++ b/content/nighttrain-details/placeholder-uz/index.en.md @@ -0,0 +1,70 @@ +--- +id: "placeholder-uz" +title: "Night trains UZ" +source_route_ids: + - "140" + - "141" + - "147" + - "149" + - "150" + - "151" + - "152" + - "153" + - "154" + - "155" + - "156" + - "158" + - "161" + - "162" + - "164" + - "166" + - "167" + - "168" + - "170" + - "172" + - "173" + - "174" + - "175" + - "177" + - "178" + - "180" + - "181" + - "182" + - "183" + - "184" + - "185" + - "186" + - "189" + - "190" + - "191" + - "196" + - "197" + - "198" + - "199" + - "200" + - "201" + - "203" + - "207" + - "208" + - "209" + - "210" + - "211" + - "212" + - "213" + - "218" + - "219" + - "220" + - "221" + - "222" + - "227" + - "258" + - "259" + - "263" + - "269" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-uz/index.fr.md b/content/nighttrain-details/placeholder-uz/index.fr.md new file mode 100644 index 000000000..fc1cf01de --- /dev/null +++ b/content/nighttrain-details/placeholder-uz/index.fr.md @@ -0,0 +1,70 @@ +--- +id: "placeholder-uz" +title: "Trains de nuit UZ" +source_route_ids: + - "140" + - "141" + - "147" + - "149" + - "150" + - "151" + - "152" + - "153" + - "154" + - "155" + - "156" + - "158" + - "161" + - "162" + - "164" + - "166" + - "167" + - "168" + - "170" + - "172" + - "173" + - "174" + - "175" + - "177" + - "178" + - "180" + - "181" + - "182" + - "183" + - "184" + - "185" + - "186" + - "189" + - "190" + - "191" + - "196" + - "197" + - "198" + - "199" + - "200" + - "201" + - "203" + - "207" + - "208" + - "209" + - "210" + - "211" + - "212" + - "213" + - "218" + - "219" + - "220" + - "221" + - "222" + - "227" + - "258" + - "259" + - "263" + - "269" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-vy/index.de.md b/content/nighttrain-details/placeholder-vy/index.de.md new file mode 100644 index 000000000..c9e6c98c8 --- /dev/null +++ b/content/nighttrain-details/placeholder-vy/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-vy" +title: "Nachtzuege VY" +source_route_ids: + - "69" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-vy/index.en.md b/content/nighttrain-details/placeholder-vy/index.en.md new file mode 100644 index 000000000..ad8be4595 --- /dev/null +++ b/content/nighttrain-details/placeholder-vy/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-vy" +title: "Night trains VY" +source_route_ids: + - "69" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-vy/index.fr.md b/content/nighttrain-details/placeholder-vy/index.fr.md new file mode 100644 index 000000000..91855ec13 --- /dev/null +++ b/content/nighttrain-details/placeholder-vy/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-vy" +title: "Trains de nuit VY" +source_route_ids: + - "69" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-zs-zpcg/index.de.md b/content/nighttrain-details/placeholder-zs-zpcg/index.de.md new file mode 100644 index 000000000..f6dd0952c --- /dev/null +++ b/content/nighttrain-details/placeholder-zs-zpcg/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-zs-zpcg" +title: "Nachtzuege ZS/ZPCG" +source_route_ids: + - "130" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-zs-zpcg/index.en.md b/content/nighttrain-details/placeholder-zs-zpcg/index.en.md new file mode 100644 index 000000000..5a17a0fde --- /dev/null +++ b/content/nighttrain-details/placeholder-zs-zpcg/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-zs-zpcg" +title: "Night trains ZS/ZPCG" +source_route_ids: + - "130" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-zs-zpcg/index.fr.md b/content/nighttrain-details/placeholder-zs-zpcg/index.fr.md new file mode 100644 index 000000000..7e357ddb8 --- /dev/null +++ b/content/nighttrain-details/placeholder-zs-zpcg/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-zs-zpcg" +title: "Trains de nuit ZS/ZPCG" +source_route_ids: + - "130" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/placeholder-zssk/index.de.md b/content/nighttrain-details/placeholder-zssk/index.de.md new file mode 100644 index 000000000..9522efeed --- /dev/null +++ b/content/nighttrain-details/placeholder-zssk/index.de.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-zssk" +title: "Nachtzuege ZSSK" +source_route_ids: + - "123" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite. diff --git a/content/nighttrain-details/placeholder-zssk/index.en.md b/content/nighttrain-details/placeholder-zssk/index.en.md new file mode 100644 index 000000000..c80cc7ef0 --- /dev/null +++ b/content/nighttrain-details/placeholder-zssk/index.en.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-zssk" +title: "Night trains ZSSK" +source_route_ids: + - "123" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +FIP information for this night train group is not maintained yet. Please also check the operator page. diff --git a/content/nighttrain-details/placeholder-zssk/index.fr.md b/content/nighttrain-details/placeholder-zssk/index.fr.md new file mode 100644 index 000000000..c2655c12a --- /dev/null +++ b/content/nighttrain-details/placeholder-zssk/index.fr.md @@ -0,0 +1,12 @@ +--- +id: "placeholder-zssk" +title: "Trains de nuit ZSSK" +source_route_ids: + - "123" +fip_global_fare: false +fip_coupon: false +fip_50: false +booking_options: [] +--- + +Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur. diff --git a/content/nighttrain-details/sj-night-trains/index.de.md b/content/nighttrain-details/sj-night-trains/index.de.md new file mode 100644 index 000000000..ec906a9b2 --- /dev/null +++ b/content/nighttrain-details/sj-night-trains/index.de.md @@ -0,0 +1,14 @@ +--- +id: "sj-night-trains" +title: "Nachtzuege Schweden (SJ)" +source_route_ids: + - "62" + - "63" + - "81" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [] +--- + +Fernverbindungen mit Schlafwagen in Schweden zwischen Stockholm, Duved, Malmoe und Lulea. diff --git a/content/nighttrain-details/sj-night-trains/index.en.md b/content/nighttrain-details/sj-night-trains/index.en.md new file mode 100644 index 000000000..90a9ff2e8 --- /dev/null +++ b/content/nighttrain-details/sj-night-trains/index.en.md @@ -0,0 +1,14 @@ +--- +id: "sj-night-trains" +title: "Night Trains Sweden (SJ)" +source_route_ids: + - "62" + - "63" + - "81" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [] +--- + +Long-distance night trains in Sweden between Stockholm, Duved, Malmo and Lulea. diff --git a/content/nighttrain-details/sj-night-trains/index.fr.md b/content/nighttrain-details/sj-night-trains/index.fr.md new file mode 100644 index 000000000..a46bfcdf6 --- /dev/null +++ b/content/nighttrain-details/sj-night-trains/index.fr.md @@ -0,0 +1,14 @@ +--- +id: "sj-night-trains" +title: "Trains de nuit Suede (SJ)" +source_route_ids: + - "62" + - "63" + - "81" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [] +--- + +Trains de nuit longue distance en Suede entre Stockholm, Duved, Malmo et Lulea. diff --git a/content/nighttrain-details/sncf-intercites-nuit/index.de.md b/content/nighttrain-details/sncf-intercites-nuit/index.de.md new file mode 100644 index 000000000..5121dfc12 --- /dev/null +++ b/content/nighttrain-details/sncf-intercites-nuit/index.de.md @@ -0,0 +1,22 @@ +--- +id: "sncf-intercites-nuit" +title: "Intercites de Nuit (SNCF)" +source_route_ids: + - "107" + - "108" + - "109" + - "110" + - "111" + - "112" + - "119" + - "262" + - "264" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: + - "sncf-ticket-office" + - "sncf-phone" +--- + +Nachtzuege der SNCF innerhalb Frankreichs mit saisonalen und ganzjaehrigen Linien. diff --git a/content/nighttrain-details/sncf-intercites-nuit/index.en.md b/content/nighttrain-details/sncf-intercites-nuit/index.en.md new file mode 100644 index 000000000..d14fabf46 --- /dev/null +++ b/content/nighttrain-details/sncf-intercites-nuit/index.en.md @@ -0,0 +1,22 @@ +--- +id: "sncf-intercites-nuit" +title: "Intercites de Nuit (SNCF)" +source_route_ids: + - "107" + - "108" + - "109" + - "110" + - "111" + - "112" + - "119" + - "262" + - "264" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: + - "sncf-ticket-office" + - "sncf-phone" +--- + +SNCF night train services within France with seasonal and year-round routes. diff --git a/content/nighttrain-details/sncf-intercites-nuit/index.fr.md b/content/nighttrain-details/sncf-intercites-nuit/index.fr.md new file mode 100644 index 000000000..f88332e6e --- /dev/null +++ b/content/nighttrain-details/sncf-intercites-nuit/index.fr.md @@ -0,0 +1,22 @@ +--- +id: "sncf-intercites-nuit" +title: "Intercites de Nuit (SNCF)" +source_route_ids: + - "107" + - "108" + - "109" + - "110" + - "111" + - "112" + - "119" + - "262" + - "264" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: + - "sncf-ticket-office" + - "sncf-phone" +--- + +Services de nuit SNCF en France avec des liaisons saisonnieres et annuelles. diff --git a/content/nighttrain-details/vr-night-trains/index.de.md b/content/nighttrain-details/vr-night-trains/index.de.md new file mode 100644 index 000000000..e8bb0a0e9 --- /dev/null +++ b/content/nighttrain-details/vr-night-trains/index.de.md @@ -0,0 +1,16 @@ +--- +id: "vr-night-trains" +title: "Nachtzuege Finnland (VR)" +source_route_ids: + - "68" + - "72" + - "90" + - "91" + - "98" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [] +--- + +Nachtzuege in Finnland zwischen Helsinki, Turku und Lappland, teilweise mit Kurswagenkonzept. diff --git a/content/nighttrain-details/vr-night-trains/index.en.md b/content/nighttrain-details/vr-night-trains/index.en.md new file mode 100644 index 000000000..6cbb95339 --- /dev/null +++ b/content/nighttrain-details/vr-night-trains/index.en.md @@ -0,0 +1,16 @@ +--- +id: "vr-night-trains" +title: "Night Trains Finland (VR)" +source_route_ids: + - "68" + - "72" + - "90" + - "91" + - "98" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [] +--- + +Night train services in Finland between Helsinki, Turku and Lapland, partly using through coach concepts. diff --git a/content/nighttrain-details/vr-night-trains/index.fr.md b/content/nighttrain-details/vr-night-trains/index.fr.md new file mode 100644 index 000000000..347cbaf19 --- /dev/null +++ b/content/nighttrain-details/vr-night-trains/index.fr.md @@ -0,0 +1,16 @@ +--- +id: "vr-night-trains" +title: "Trains de nuit Finlande (VR)" +source_route_ids: + - "68" + - "72" + - "90" + - "91" + - "98" +fip_global_fare: false +fip_coupon: true +fip_50: true +booking_options: [] +--- + +Relations de nuit en Finlande entre Helsinki, Turku et la Laponie, partiellement avec concept de voitures directes. diff --git a/data/nighttrains/de/fip_details.json b/data/nighttrains/de/fip_details.json deleted file mode 100644 index 5bc49d297..000000000 --- a/data/nighttrains/de/fip_details.json +++ /dev/null @@ -1,656 +0,0 @@ -[ - { - "id": "oebb-nightjet", - "source_route_ids": [ - "1", - "2", - "5", - "17", - "18", - "44", - "45", - "46", - "49", - "50", - "53", - "115" - ], - "title": "Nightjet (OEBB)", - "description": "Nachtzugverbindungen von OEBB im Nightjet-Netz inklusive ausgewaehlter grenzueberschreitender Linien.", - "fip_global_fare": true, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "oebb-website", - "oebb-phone", - "oebb-ticket-office" - ] - }, - { - "id": "sncf-intercites-nuit", - "source_route_ids": [ - "107", - "108", - "109", - "110", - "111", - "112", - "119", - "262", - "264" - ], - "title": "Intercites de Nuit (SNCF)", - "description": "Nachtzuege der SNCF innerhalb Frankreichs mit saisonalen und ganzjaehrigen Linien.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "sncf-ticket-office", - "sncf-phone" - ] - }, - { - "id": "fs-intercity-notte", - "source_route_ids": [ - "76", - "83", - "84", - "85", - "86", - "96", - "97", - "99", - "100", - "101", - "102", - "103", - "104", - "126", - "128" - ], - "title": "Intercity Notte (FS)", - "description": "Nachtverbindungen von Trenitalia in Italien inklusive Linien mit Kurswagen fuer Sizilien.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "fs-website", - "fs-ticket-office" - ] - }, - { - "id": "sj-night-trains", - "source_route_ids": [ - "62", - "63", - "81" - ], - "title": "Nachtzuege Schweden (SJ)", - "description": "Fernverbindungen mit Schlafwagen in Schweden zwischen Stockholm, Duved, Malmoe und Lulea.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [] - }, - { - "id": "vr-night-trains", - "source_route_ids": [ - "68", - "72", - "90", - "91", - "98" - ], - "title": "Nachtzuege Finnland (VR)", - "description": "Nachtzuege in Finnland zwischen Helsinki, Turku und Lappland, teilweise mit Kurswagenkonzept.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [] - }, - { - "id": "placeholder-uz", - "source_route_ids": [ - "140", - "141", - "147", - "149", - "150", - "151", - "152", - "153", - "154", - "155", - "156", - "158", - "161", - "162", - "164", - "166", - "167", - "168", - "170", - "172", - "173", - "174", - "175", - "177", - "178", - "180", - "181", - "182", - "183", - "184", - "185", - "186", - "189", - "190", - "191", - "196", - "197", - "198", - "199", - "200", - "201", - "203", - "207", - "208", - "209", - "210", - "211", - "212", - "213", - "218", - "219", - "220", - "221", - "222", - "227", - "258", - "259", - "263", - "269" - ], - "title": "Nachtzuege UZ", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr", - "source_route_ids": [ - "11", - "12", - "13", - "14", - "15", - "19", - "20", - "21", - "23", - "25", - "26", - "249", - "250" - ], - "title": "Nachtzuege CFR", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-pkp", - "source_route_ids": [ - "10", - "113", - "121", - "122", - "125", - "129", - "136", - "137", - "138", - "267", - "268" - ], - "title": "Nachtzuege PKP", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-pkp-cd", - "source_route_ids": [ - "8", - "9", - "116", - "118", - "124", - "265", - "266" - ], - "title": "Nachtzuege PKP/CD", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd", - "source_route_ids": [ - "30", - "31", - "243", - "245", - "246", - "247", - "248" - ], - "title": "Nachtzuege TCDD", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uex", - "source_route_ids": [ - "252", - "253", - "254", - "255", - "256", - "257" - ], - "title": "Nachtzuege UEX", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-bdz", - "source_route_ids": [ - "131", - "133", - "134", - "135", - "142" - ], - "title": "Nachtzuege BDZ", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cs", - "source_route_ids": [ - "37", - "38", - "39", - "40", - "41" - ], - "title": "Nachtzuege CS", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-es", - "source_route_ids": [ - "237", - "238", - "239", - "240" - ], - "title": "Nachtzuege ES", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav", - "source_route_ids": [ - "58", - "223", - "224", - "225" - ], - "title": "Nachtzuege MAV", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-st", - "source_route_ids": [ - "73", - "77", - "79", - "80" - ], - "title": "Nachtzuege ST", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-oebb", - "source_route_ids": [ - "229", - "232", - "233", - "235" - ], - "title": "Nachtzuege OEBB", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr-mav", - "source_route_ids": [ - "16", - "67" - ], - "title": "Nachtzuege CFR/MAV", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-fs", - "source_route_ids": [ - "105", - "106" - ], - "title": "Nachtzuege FS", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-hzpp", - "source_route_ids": [ - "3", - "48" - ], - "title": "Nachtzuege HZPP", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-hzpp-oebb", - "source_route_ids": [ - "57", - "117" - ], - "title": "Nachtzuege HZPP/OEBB", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav-oebb", - "source_route_ids": [ - "54", - "74" - ], - "title": "Nachtzuege MAV/OEBB", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-rj", - "source_route_ids": [ - "7", - "261" - ], - "title": "Nachtzuege RJ", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-sjn", - "source_route_ids": [ - "70", - "71" - ], - "title": "Nachtzuege SJN", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cd", - "source_route_ids": [ - "6", - "120" - ], - "title": "Nachtzuege CD", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-atc", - "source_route_ids": [ - "24" - ], - "title": "Nachtzuege ATC", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfm-cfr", - "source_route_ids": [ - "22" - ], - "title": "Nachtzuege CFM/CFR", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr-mav-oebb", - "source_route_ids": [ - "59" - ], - "title": "Nachtzuege CFR/MAV/OEBB", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-ga", - "source_route_ids": [ - "65" - ], - "title": "Nachtzuege GA", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-gwr", - "source_route_ids": [ - "42" - ], - "title": "Nachtzuege GWR", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav-pkp", - "source_route_ids": [ - "127" - ], - "title": "Nachtzuege MAV/PKP", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-ote", - "source_route_ids": [ - "114" - ], - "title": "Nachtzuege OTE", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-rdc-sj", - "source_route_ids": [ - "78" - ], - "title": "Nachtzuege RDC/SJ", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd-bdz", - "source_route_ids": [ - "27" - ], - "title": "Nachtzuege TCDD/BDZ", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd-bdz-cfr", - "source_route_ids": [ - "28" - ], - "title": "Nachtzuege TCDD/BDZ/CFR", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uz-cfm", - "source_route_ids": [ - "195" - ], - "title": "Nachtzuege UZ/CFM", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uz-oebb", - "source_route_ids": [ - "60" - ], - "title": "Nachtzuege UZ/OEBB", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-vy", - "source_route_ids": [ - "69" - ], - "title": "Nachtzuege VY", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-zssk", - "source_route_ids": [ - "123" - ], - "title": "Nachtzuege ZSSK", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-zs-zpcg", - "source_route_ids": [ - "130" - ], - "title": "Nachtzuege ZS/ZPCG", - "description": "FIP Informationen fuer diese Nachtzuggruppe sind noch nicht gepflegt. Bitte pruefe zusaetzlich die Betreiberseite.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - } -] diff --git a/data/nighttrains/en/fip_details.json b/data/nighttrains/en/fip_details.json deleted file mode 100644 index 2a085659f..000000000 --- a/data/nighttrains/en/fip_details.json +++ /dev/null @@ -1,656 +0,0 @@ -[ - { - "id": "oebb-nightjet", - "source_route_ids": [ - "1", - "2", - "5", - "17", - "18", - "44", - "45", - "46", - "49", - "50", - "53", - "115" - ], - "title": "Nightjet (OEBB)", - "description": "Night train services operated by OEBB in the Nightjet network, including selected cross-border routes.", - "fip_global_fare": true, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "oebb-website", - "oebb-phone", - "oebb-ticket-office" - ] - }, - { - "id": "sncf-intercites-nuit", - "source_route_ids": [ - "107", - "108", - "109", - "110", - "111", - "112", - "119", - "262", - "264" - ], - "title": "Intercites de Nuit (SNCF)", - "description": "SNCF night train services within France with seasonal and year-round routes.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "sncf-ticket-office", - "sncf-phone" - ] - }, - { - "id": "fs-intercity-notte", - "source_route_ids": [ - "76", - "83", - "84", - "85", - "86", - "96", - "97", - "99", - "100", - "101", - "102", - "103", - "104", - "126", - "128" - ], - "title": "Intercity Notte (FS)", - "description": "Trenitalia night services in Italy, including routes with through coaches to Sicily.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "fs-website", - "fs-ticket-office" - ] - }, - { - "id": "sj-night-trains", - "source_route_ids": [ - "62", - "63", - "81" - ], - "title": "Night Trains Sweden (SJ)", - "description": "Long-distance night trains in Sweden between Stockholm, Duved, Malmo and Lulea.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [] - }, - { - "id": "vr-night-trains", - "source_route_ids": [ - "68", - "72", - "90", - "91", - "98" - ], - "title": "Night Trains Finland (VR)", - "description": "Night train services in Finland between Helsinki, Turku and Lapland, partly using through coach concepts.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [] - }, - { - "id": "placeholder-uz", - "source_route_ids": [ - "140", - "141", - "147", - "149", - "150", - "151", - "152", - "153", - "154", - "155", - "156", - "158", - "161", - "162", - "164", - "166", - "167", - "168", - "170", - "172", - "173", - "174", - "175", - "177", - "178", - "180", - "181", - "182", - "183", - "184", - "185", - "186", - "189", - "190", - "191", - "196", - "197", - "198", - "199", - "200", - "201", - "203", - "207", - "208", - "209", - "210", - "211", - "212", - "213", - "218", - "219", - "220", - "221", - "222", - "227", - "258", - "259", - "263", - "269" - ], - "title": "Night trains UZ", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr", - "source_route_ids": [ - "11", - "12", - "13", - "14", - "15", - "19", - "20", - "21", - "23", - "25", - "26", - "249", - "250" - ], - "title": "Night trains CFR", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-pkp", - "source_route_ids": [ - "10", - "113", - "121", - "122", - "125", - "129", - "136", - "137", - "138", - "267", - "268" - ], - "title": "Night trains PKP", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-pkp-cd", - "source_route_ids": [ - "8", - "9", - "116", - "118", - "124", - "265", - "266" - ], - "title": "Night trains PKP/CD", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd", - "source_route_ids": [ - "30", - "31", - "243", - "245", - "246", - "247", - "248" - ], - "title": "Night trains TCDD", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uex", - "source_route_ids": [ - "252", - "253", - "254", - "255", - "256", - "257" - ], - "title": "Night trains UEX", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-bdz", - "source_route_ids": [ - "131", - "133", - "134", - "135", - "142" - ], - "title": "Night trains BDZ", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cs", - "source_route_ids": [ - "37", - "38", - "39", - "40", - "41" - ], - "title": "Night trains CS", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-es", - "source_route_ids": [ - "237", - "238", - "239", - "240" - ], - "title": "Night trains ES", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav", - "source_route_ids": [ - "58", - "223", - "224", - "225" - ], - "title": "Night trains MAV", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-st", - "source_route_ids": [ - "73", - "77", - "79", - "80" - ], - "title": "Night trains ST", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-oebb", - "source_route_ids": [ - "229", - "232", - "233", - "235" - ], - "title": "Night trains OEBB", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr-mav", - "source_route_ids": [ - "16", - "67" - ], - "title": "Night trains CFR/MAV", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-fs", - "source_route_ids": [ - "105", - "106" - ], - "title": "Night trains FS", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-hzpp", - "source_route_ids": [ - "3", - "48" - ], - "title": "Night trains HZPP", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-hzpp-oebb", - "source_route_ids": [ - "57", - "117" - ], - "title": "Night trains HZPP/OEBB", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav-oebb", - "source_route_ids": [ - "54", - "74" - ], - "title": "Night trains MAV/OEBB", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-rj", - "source_route_ids": [ - "7", - "261" - ], - "title": "Night trains RJ", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-sjn", - "source_route_ids": [ - "70", - "71" - ], - "title": "Night trains SJN", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cd", - "source_route_ids": [ - "6", - "120" - ], - "title": "Night trains CD", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-atc", - "source_route_ids": [ - "24" - ], - "title": "Night trains ATC", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfm-cfr", - "source_route_ids": [ - "22" - ], - "title": "Night trains CFM/CFR", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr-mav-oebb", - "source_route_ids": [ - "59" - ], - "title": "Night trains CFR/MAV/OEBB", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-ga", - "source_route_ids": [ - "65" - ], - "title": "Night trains GA", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-gwr", - "source_route_ids": [ - "42" - ], - "title": "Night trains GWR", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav-pkp", - "source_route_ids": [ - "127" - ], - "title": "Night trains MAV/PKP", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-ote", - "source_route_ids": [ - "114" - ], - "title": "Night trains OTE", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-rdc-sj", - "source_route_ids": [ - "78" - ], - "title": "Night trains RDC/SJ", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd-bdz", - "source_route_ids": [ - "27" - ], - "title": "Night trains TCDD/BDZ", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd-bdz-cfr", - "source_route_ids": [ - "28" - ], - "title": "Night trains TCDD/BDZ/CFR", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uz-cfm", - "source_route_ids": [ - "195" - ], - "title": "Night trains UZ/CFM", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uz-oebb", - "source_route_ids": [ - "60" - ], - "title": "Night trains UZ/OEBB", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-vy", - "source_route_ids": [ - "69" - ], - "title": "Night trains VY", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-zssk", - "source_route_ids": [ - "123" - ], - "title": "Night trains ZSSK", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-zs-zpcg", - "source_route_ids": [ - "130" - ], - "title": "Night trains ZS/ZPCG", - "description": "FIP information for this night train group is not maintained yet. Please also check the operator page.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - } -] diff --git a/data/nighttrains/fr/fip_details.json b/data/nighttrains/fr/fip_details.json deleted file mode 100644 index 082e6e3ff..000000000 --- a/data/nighttrains/fr/fip_details.json +++ /dev/null @@ -1,656 +0,0 @@ -[ - { - "id": "oebb-nightjet", - "source_route_ids": [ - "1", - "2", - "5", - "17", - "18", - "44", - "45", - "46", - "49", - "50", - "53", - "115" - ], - "title": "Nightjet (OEBB)", - "description": "Relations de nuit exploitees par OEBB dans le reseau Nightjet, y compris certaines liaisons transfrontalieres.", - "fip_global_fare": true, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "oebb-website", - "oebb-phone", - "oebb-ticket-office" - ] - }, - { - "id": "sncf-intercites-nuit", - "source_route_ids": [ - "107", - "108", - "109", - "110", - "111", - "112", - "119", - "262", - "264" - ], - "title": "Intercites de Nuit (SNCF)", - "description": "Services de nuit SNCF en France avec des liaisons saisonnieres et annuelles.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "sncf-ticket-office", - "sncf-phone" - ] - }, - { - "id": "fs-intercity-notte", - "source_route_ids": [ - "76", - "83", - "84", - "85", - "86", - "96", - "97", - "99", - "100", - "101", - "102", - "103", - "104", - "126", - "128" - ], - "title": "Intercity Notte (FS)", - "description": "Services de nuit de Trenitalia en Italie, y compris des relations avec voitures directes vers la Sicile.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [ - "fs-website", - "fs-ticket-office" - ] - }, - { - "id": "sj-night-trains", - "source_route_ids": [ - "62", - "63", - "81" - ], - "title": "Trains de nuit Suede (SJ)", - "description": "Trains de nuit longue distance en Suede entre Stockholm, Duved, Malmo et Lulea.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [] - }, - { - "id": "vr-night-trains", - "source_route_ids": [ - "68", - "72", - "90", - "91", - "98" - ], - "title": "Trains de nuit Finlande (VR)", - "description": "Relations de nuit en Finlande entre Helsinki, Turku et la Laponie, partiellement avec concept de voitures directes.", - "fip_global_fare": false, - "fip_coupon": true, - "fip_50": true, - "booking_options": [] - }, - { - "id": "placeholder-uz", - "source_route_ids": [ - "140", - "141", - "147", - "149", - "150", - "151", - "152", - "153", - "154", - "155", - "156", - "158", - "161", - "162", - "164", - "166", - "167", - "168", - "170", - "172", - "173", - "174", - "175", - "177", - "178", - "180", - "181", - "182", - "183", - "184", - "185", - "186", - "189", - "190", - "191", - "196", - "197", - "198", - "199", - "200", - "201", - "203", - "207", - "208", - "209", - "210", - "211", - "212", - "213", - "218", - "219", - "220", - "221", - "222", - "227", - "258", - "259", - "263", - "269" - ], - "title": "Trains de nuit UZ", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr", - "source_route_ids": [ - "11", - "12", - "13", - "14", - "15", - "19", - "20", - "21", - "23", - "25", - "26", - "249", - "250" - ], - "title": "Trains de nuit CFR", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-pkp", - "source_route_ids": [ - "10", - "113", - "121", - "122", - "125", - "129", - "136", - "137", - "138", - "267", - "268" - ], - "title": "Trains de nuit PKP", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-pkp-cd", - "source_route_ids": [ - "8", - "9", - "116", - "118", - "124", - "265", - "266" - ], - "title": "Trains de nuit PKP/CD", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd", - "source_route_ids": [ - "30", - "31", - "243", - "245", - "246", - "247", - "248" - ], - "title": "Trains de nuit TCDD", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uex", - "source_route_ids": [ - "252", - "253", - "254", - "255", - "256", - "257" - ], - "title": "Trains de nuit UEX", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-bdz", - "source_route_ids": [ - "131", - "133", - "134", - "135", - "142" - ], - "title": "Trains de nuit BDZ", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cs", - "source_route_ids": [ - "37", - "38", - "39", - "40", - "41" - ], - "title": "Trains de nuit CS", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-es", - "source_route_ids": [ - "237", - "238", - "239", - "240" - ], - "title": "Trains de nuit ES", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav", - "source_route_ids": [ - "58", - "223", - "224", - "225" - ], - "title": "Trains de nuit MAV", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-st", - "source_route_ids": [ - "73", - "77", - "79", - "80" - ], - "title": "Trains de nuit ST", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-oebb", - "source_route_ids": [ - "229", - "232", - "233", - "235" - ], - "title": "Trains de nuit OEBB", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr-mav", - "source_route_ids": [ - "16", - "67" - ], - "title": "Trains de nuit CFR/MAV", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-fs", - "source_route_ids": [ - "105", - "106" - ], - "title": "Trains de nuit FS", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-hzpp", - "source_route_ids": [ - "3", - "48" - ], - "title": "Trains de nuit HZPP", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-hzpp-oebb", - "source_route_ids": [ - "57", - "117" - ], - "title": "Trains de nuit HZPP/OEBB", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav-oebb", - "source_route_ids": [ - "54", - "74" - ], - "title": "Trains de nuit MAV/OEBB", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-rj", - "source_route_ids": [ - "7", - "261" - ], - "title": "Trains de nuit RJ", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-sjn", - "source_route_ids": [ - "70", - "71" - ], - "title": "Trains de nuit SJN", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cd", - "source_route_ids": [ - "6", - "120" - ], - "title": "Trains de nuit CD", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-atc", - "source_route_ids": [ - "24" - ], - "title": "Trains de nuit ATC", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfm-cfr", - "source_route_ids": [ - "22" - ], - "title": "Trains de nuit CFM/CFR", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-cfr-mav-oebb", - "source_route_ids": [ - "59" - ], - "title": "Trains de nuit CFR/MAV/OEBB", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-ga", - "source_route_ids": [ - "65" - ], - "title": "Trains de nuit GA", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-gwr", - "source_route_ids": [ - "42" - ], - "title": "Trains de nuit GWR", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-mav-pkp", - "source_route_ids": [ - "127" - ], - "title": "Trains de nuit MAV/PKP", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-ote", - "source_route_ids": [ - "114" - ], - "title": "Trains de nuit OTE", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-rdc-sj", - "source_route_ids": [ - "78" - ], - "title": "Trains de nuit RDC/SJ", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd-bdz", - "source_route_ids": [ - "27" - ], - "title": "Trains de nuit TCDD/BDZ", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-tcdd-bdz-cfr", - "source_route_ids": [ - "28" - ], - "title": "Trains de nuit TCDD/BDZ/CFR", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uz-cfm", - "source_route_ids": [ - "195" - ], - "title": "Trains de nuit UZ/CFM", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-uz-oebb", - "source_route_ids": [ - "60" - ], - "title": "Trains de nuit UZ/OEBB", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-vy", - "source_route_ids": [ - "69" - ], - "title": "Trains de nuit VY", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-zssk", - "source_route_ids": [ - "123" - ], - "title": "Trains de nuit ZSSK", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - }, - { - "id": "placeholder-zs-zpcg", - "source_route_ids": [ - "130" - ], - "title": "Trains de nuit ZS/ZPCG", - "description": "Les informations FIP pour ce groupe de trains de nuit ne sont pas encore maintenues. Veuillez verifier aussi la page de l operateur.", - "fip_global_fare": false, - "fip_coupon": false, - "fip_50": false, - "booking_options": [] - } -] diff --git a/layouts/_shortcodes/nighttrains-fip-details.html b/layouts/_shortcodes/nighttrains-fip-details.html index d710a96f0..fb6a51682 100644 --- a/layouts/_shortcodes/nighttrains-fip-details.html +++ b/layouts/_shortcodes/nighttrains-fip-details.html @@ -1,13 +1,32 @@ {{- $lang := .Page.Language.Lang -}} -{{- $langData := index hugo.Data.nighttrains $lang -}} -{{- $fallbackData := index hugo.Data.nighttrains "en" -}} -{{- $items := cond (and $langData $langData.fip_details) $langData.fip_details $fallbackData.fip_details -}} +{{- $items := slice -}} +{{- $detailDirs := readDir "content/nighttrain-details" -}} +{{- range $entry := $detailDirs -}} + {{- if $entry.IsDir -}} + {{- $page := site.GetPage (print "nighttrain-details/" $entry.Name) -}} + {{- if $page -}} + {{- $items = $items | append $page -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- $items = where $items "Lang" $lang -}} +{{- if eq (len $items) 0 -}} + {{- range $entry := $detailDirs -}} + {{- if $entry.IsDir -}} + {{- $page := site.GetPage (print "en/nighttrain-details/" $entry.Name) -}} + {{- if $page -}} + {{- $items = $items | append $page -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- $items = $items.ByTitle -}} {{- if $items -}} {{- $fipMap := dict -}} {{- range $item := $items -}} - {{- range $routeId := $item.source_route_ids -}} - {{- $fipMap = merge $fipMap (dict (printf "%v" $routeId) $item.id) -}} + {{- range $routeId := $item.Params.source_route_ids -}} + {{- $fipMap = merge $fipMap (dict (printf "%v" $routeId) $item.Params.id) -}} {{- end -}} {{- end -}} @@ -21,12 +40,12 @@

{{ T "nightTrains.detailsHeading" }}

{{- partial "icon" "hotel" -}} - {{ $item.title }} + {{ $item.Title }}
{{ partial "icon" "keyboard_arrow_down" }}
@@ -34,33 +53,35 @@

{{ T "nightTrains.detailsHeading" }}

-

{{ $item.description }}

+ {{- $content := partial "increase-headings" (dict "content" $item.Content "offset" 1) -}} + {{- $content | safeHTML -}} +
{{- partial "tag" (dict - "Icon" (cond $item.fip_global_fare "check_circle" "cancel") - "Type" (cond $item.fip_global_fare "success" "error") - "RawText" (print (T "fipValidity.fip-global-fare") ": " (T (cond $item.fip_global_fare "nightTrains.yes" "nightTrains.no"))) + "Icon" (cond $item.Params.fip_global_fare "check_circle" "cancel") + "Type" (cond $item.Params.fip_global_fare "success" "error") + "RawText" (print (T "fipValidity.fip-global-fare") ": " (T (cond $item.Params.fip_global_fare "nightTrains.yes" "nightTrains.no"))) ) -}} {{- partial "tag" (dict - "Icon" (cond $item.fip_coupon "check_circle" "cancel") - "Type" (cond $item.fip_coupon "success" "error") - "RawText" (print (T "fipValidity.fip-coupon") ": " (T (cond $item.fip_coupon "nightTrains.yes" "nightTrains.no"))) + "Icon" (cond $item.Params.fip_coupon "check_circle" "cancel") + "Type" (cond $item.Params.fip_coupon "success" "error") + "RawText" (print (T "fipValidity.fip-coupon") ": " (T (cond $item.Params.fip_coupon "nightTrains.yes" "nightTrains.no"))) ) -}} {{- partial "tag" (dict - "Icon" (cond $item.fip_50 "check_circle" "cancel") - "Type" (cond $item.fip_50 "success" "error") - "RawText" (print "FIP 50: " (T (cond $item.fip_50 "nightTrains.yes" "nightTrains.no"))) + "Icon" (cond $item.Params.fip_50 "check_circle" "cancel") + "Type" (cond $item.Params.fip_50 "success" "error") + "RawText" (print "FIP 50: " (T (cond $item.Params.fip_50 "nightTrains.yes" "nightTrains.no"))) ) -}}
- {{- if gt (len $item.booking_options) 0 -}} + {{- if gt (len $item.Params.booking_options) 0 -}}

{{ T "nightTrains.bookingOptions" }}

- {{- range $bookingId := $item.booking_options -}} + {{- range $bookingId := $item.Params.booking_options -}} {{- $bookingPage := site.GetPage (print "booking/" $bookingId) -}} {{- if $bookingPage -}} {{- partial "button" (dict @@ -81,7 +102,7 @@

{{ T "nightTrains.bookingOptions" }}

{{ T "nightTrains.sourceRouteIds" }}: - {{ delimit $item.source_route_ids ", " }} + {{ delimit $item.Params.source_route_ids ", " }}

diff --git a/static/nighttrains/README.md b/static/nighttrains/README.md index 0e1e428c6..6f6679deb 100644 --- a/static/nighttrains/README.md +++ b/static/nighttrains/README.md @@ -53,6 +53,40 @@ Translations for map overlay labels are injected before loading `map.js`: - `layouts/_shortcodes/nighttrains-map.html` sets `window.map_i18n` using i18n keys - keys currently used: `nightTrains.back`, `dialog.close`, `nightTrains.runs`, `nightTrains.moreDetails`, `nightTrains.fipInformationButton`, `nightTrains.selectLine` +### 4) FIP details moved from JSON to hidden Markdown content + +FIP detail data is no longer stored in `data/nighttrains/*/fip_details.json`. + +It now lives in hidden content pages under: + +- `content/nighttrain-details//index.de.md` +- `content/nighttrain-details//index.en.md` +- `content/nighttrain-details//index.fr.md` + +Each file uses frontmatter fields: + +- `id` +- `title` +- `source_route_ids` +- `fip_global_fare` +- `fip_coupon` +- `fip_50` +- `booking_options` + +The Markdown body is the description text rendered inside the expander. + +The section is explicitly hidden from output like booking pages: + +- `content/nighttrain-details/_index.de.md` +- `content/nighttrain-details/_index.en.md` +- `content/nighttrain-details/_index.fr.md` + +with cascade build settings: + +- `list: false` +- `publishResources: false` +- `render: never` + ## Reproduction steps 1. Refresh assets from source if needed: @@ -70,6 +104,7 @@ Translations for map overlay labels are injected before loading `map.js`: - Map renders and zoom/pan works. - Single route tap opens route detail overlay. - Mobile taps near route clusters can open train list overlay (`.row.trainlist`). -- Overlay detail button and route metadata are loaded from local JSON. +- Overlay detail button and route metadata are loaded from local files. - Overlay shows "FIP Informations" when route ID is mapped. - Clicking "FIP Informations" scrolls to the correct expander and opens it. +- FIP expanders are rendered from hidden markdown pages in `content/nighttrain-details/`.