Migration to new Rust-based engine (#401)

* wasm first steps

* parsing start

* parsing continued

* progress

* progress

* progress

* progress

* progress

* progress

* progress

* progress

* fixes

* reorganize

* change type

* fix

* progress

* refactoring

* progress

* progress

* progress

* keep style info

* progress

* progress

* remove (copy) in name

* progress

* merge methods into 1

* splice

* progress

* progress

* progress

* cleaning

* progress

* progress

* progress

* visibility

* progress

* progress

* progress

* progress

* progress

* fixes

* progress

* fix markers

* fix

* progress

* progress

* progress

* progress

* progress

* progress

* small fix

* use engine info

* fix popups

* small fix

* progress

* progress

* progress

* clean tool

* handle self closing elements

* reduce data exchanges across boundary

* copy on wasm side to avoid any data corruption

* speed fix

* routing

* refactoring

* reverse

* reverse

* crop

* split

* merge

* progress

* time tool

* fix bounds for waypoints

* reduce

* fix reactivity

* handle corrupt time data

* export

* progress

* remove gpx js package

* remove todo

* update readme

* cleaning

* progress

* fix link fields

* remove unused fields

* refactoring and tests

* import and export of routes, ref #192

* per-chunk categories storage

* cross-tab sync

* outdated state

* refactoring

* reorder methods

* refactoring

* fix

* improve flow

* renaming

* progress

* progress

* fix

* progress

* per file history

* keep original flag

* use history variant

* fix

* progress

* file explorer

* progress

* fix

* sticky folders

* improved sticky folders

* fix sortable

* fix sortable

* fix

* fix tab size

* no file delete on desktop

* fix routing on other file

* fix sorting

* remember language

* open links in browser

* commit missing changes

* avoid selecting on resize

* clarify filename

* explorer actions

* fix folder styling

* drop anywhere in folder

* cleaning

* fixes

* remove focus-ring

* full screen

* small fix

* consistent highlight color

* improved preview

* performance improvements

* sparser data transfers

* sparser data transfers

* show popup once data is loaded

* fix routing control size

* fix

* sparse desktop build

* remove custom ign styles

* use new endpoint for openhikingmap

* strip native menu

* reorder context menu items

* route full support

* route - track conversion

* create route file action

* route export, filter out anchors at high zoom level

* clarify name handling

* move hide & center to view

* routes continued

* update docs

* fix power format, closes #378

* lint fixes

* fix display of additional data with gaps, closes #361

* fix linting issues

* fix import modules

* fix multidrag

* change base to resolve

* fix type errors

* fix layer typings

* fix last type error

* each keys

* improve typings

* deploy to cloudflare

---------

Co-authored-by: vcoppe <vcoppe@hexaly.com>
This commit is contained in:
vcoppeandvcoppe authored and GitHub committed 2026-10-31 18:08:22 +01:00
1 parent 6a0d434371
commit 8fe7d8d64d
484 files changed
+53949 -41152

No files matched your search

+51
View File
@@ -0,0 +1,51 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
getHighwayColor,
getSlopeColor,
getSurfaceColor,
highwayColors,
surfaceColors,
} from '$lib/data/colors';
describe('colors of the OSM data', () => {
it('has the color of a surface, or the one of the missing ones', () => {
assert.equal(getSurfaceColor('asphalt'), surfaceColors.asphalt);
assert.equal(getSurfaceColor('grass'), '#61b55c');
assert.equal(getSurfaceColor('something new'), surfaceColors.missing);
assert.equal(getSurfaceColor(''), surfaceColors.missing);
});
it('has the color of a highway, or the one of the missing ones', () => {
assert.equal(getHighwayColor('motorway', undefined, undefined), highwayColors.motorway);
assert.equal(getHighwayColor('path', undefined, undefined), highwayColors.path);
assert.equal(getHighwayColor('something new', undefined, undefined), highwayColors.missing);
});
});
describe('slope colors', () => {
const hue = (color: string) => Number(/hsl\(([-\d.e]+),/.exec(color)![1]);
const lightness = (color: string) => Number(/,([\d.]+)%\)$/.exec(color)![1]);
it('is yellow on the flat, redder uphill and greener downhill, symmetrically', () => {
const flat = getSlopeColor(0);
assert.equal(hue(flat), 60);
assert.equal(lightness(flat), 90);
// steeper is further from the flat color, in both directions
assert.ok(hue(getSlopeColor(10)) < 60);
assert.ok(hue(getSlopeColor(-10)) > 60);
assert.ok(lightness(getSlopeColor(10)) < 90);
assert.ok(hue(getSlopeColor(20)) < hue(getSlopeColor(10)));
const up = getSlopeColor(7);
const down = getSlopeColor(-7);
assert.ok(Math.abs(hue(up) + hue(down) - 120) < 1e-9);
assert.ok(Math.abs(lightness(up) - lightness(down)) < 1e-9);
});
it('does not go further than 20 %', () => {
assert.equal(getSlopeColor(20), getSlopeColor(35));
assert.equal(getSlopeColor(1000), getSlopeColor(20));
assert.equal(getSlopeColor(-20), getSlopeColor(-55));
assert.notEqual(getSlopeColor(19), getSlopeColor(20));
});
});
+171
View File
@@ -0,0 +1,171 @@
export const surfaceColors: { [key: string]: string } = {
missing: '#d1d1d1',
paved: '#8c8c8c',
unpaved: '#6b443a',
asphalt: '#8c8c8c',
concrete: '#8c8c8c',
cobblestone: '#ffd991',
paving_stones: '#8c8c8c',
sett: '#ffd991',
metal: '#8c8c8c',
wood: '#6b443a',
compacted: '#ffffa8',
fine_gravel: '#ffffa8',
gravel: '#ffffa8',
pebblestone: '#ffffa8',
rock: '#ffd991',
dirt: '#ffffa8',
ground: '#6b443a',
earth: '#6b443a',
mud: '#6b443a',
sand: '#ffffc4',
grass: '#61b55c',
grass_paver: '#61b55c',
clay: '#6b443a',
stone: '#ffd991',
};
export function getSurfaceColor(surface: string): string {
return surfaceColors[surface] ? surfaceColors[surface] : surfaceColors.missing;
}
export const highwayColors: { [key: string]: string } = {
missing: '#d1d1d1',
motorway: '#ff4d33',
motorway_link: '#ff4d33',
trunk: '#ff5e4d',
trunk_link: '#ff947f',
primary: '#ff6e5c',
primary_link: '#ff6e5c',
secondary: '#ff8d7b',
secondary_link: '#ff8d7b',
tertiary: '#ffd75f',
tertiary_link: '#ffd75f',
unclassified: '#f1f2a5',
road: '#f1f2a5',
residential: '#73b2ff',
living_street: '#73b2ff',
service: '#9c9cd9',
track: '#a8e381',
footway: '#a8e381',
path: '#a8e381',
pedestrian: '#a8e381',
cycleway: '#9de2ff',
construction: '#e09a4a',
bridleway: '#946f43',
raceway: '#ff0000',
rest_area: '#9c9cd9',
services: '#9c9cd9',
corridor: '#474747',
elevator: '#474747',
steps: '#474747',
bus_stop: '#8545a3',
busway: '#8545a3',
via_ferrata: '#474747',
};
export const sacScaleColors: { [key: string]: string } = {
hiking: '#007700',
mountain_hiking: '#1843ad',
demanding_mountain_hiking: '#ffff00',
alpine_hiking: '#ff9233',
demanding_alpine_hiking: '#ff0000',
difficult_alpine_hiking: '#000000',
};
export const mtbScaleColors: { [key: string]: string } = {
'0-': '#007700',
'0': '#007700',
'0+': '#007700',
'1-': '#1843ad',
'1': '#1843ad',
'1+': '#1843ad',
'2-': '#ffff00',
'2': '#ffff00',
'2+': '#ffff00',
'3': '#ff0000',
'4': '#00ff00',
'5': '#000000',
'6': '#b105eb',
};
function createPattern(
backgroundColor: string,
sacScaleColor: string | undefined,
mtbScaleColor: string | undefined,
size: number = 16,
lineWidth: number = 4
) {
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, size, size);
ctx.lineWidth = lineWidth;
const halfSize = size / 2;
const halfLineWidth = lineWidth / 2;
if (sacScaleColor) {
ctx.strokeStyle = sacScaleColor;
ctx.beginPath();
ctx.moveTo(halfSize - halfLineWidth, -halfLineWidth);
ctx.lineTo(size + halfLineWidth, halfSize + halfLineWidth);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(-halfLineWidth, halfSize - halfLineWidth);
ctx.lineTo(halfSize + halfLineWidth, size + halfLineWidth);
ctx.stroke();
}
if (mtbScaleColor) {
ctx.strokeStyle = mtbScaleColor;
ctx.beginPath();
ctx.moveTo(halfSize - halfLineWidth, size + halfLineWidth);
ctx.lineTo(size + halfLineWidth, halfSize - halfLineWidth);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(-halfLineWidth, halfSize + halfLineWidth);
ctx.lineTo(halfSize + halfLineWidth, -halfLineWidth);
ctx.stroke();
}
}
return ctx?.createPattern(canvas, 'repeat') || backgroundColor;
}
const patterns: Record<string, string | CanvasPattern> = {};
export function getHighwayColor(
highway: string,
sacScale: string | undefined,
mtbScale: string | undefined
) {
const backgroundColor = highwayColors[highway] ? highwayColors[highway] : highwayColors.missing;
const sacScaleColor = sacScale ? sacScaleColors[sacScale] : undefined;
const mtbScaleColor = mtbScale ? mtbScaleColors[mtbScale] : undefined;
if (sacScale || mtbScale) {
const patternId = `${backgroundColor}-${[sacScale, mtbScale].filter((x) => x).join('-')}`;
if (!patterns[patternId]) {
patterns[patternId] = createPattern(backgroundColor, sacScaleColor, mtbScaleColor);
}
return patterns[patternId];
}
return backgroundColor;
}
const maxSlope = 20;
export function getSlopeColor(slope: number): string {
if (slope > maxSlope) {
slope = maxSlope;
} else if (slope < -maxSlope) {
slope = -maxSlope;
}
let v = slope / maxSlope;
v = 1 / (1 + Math.exp(-6 * v));
v = v - 0.5;
const hue = ((0.5 - v) * 120).toString(10);
const lightness = 90 - Math.abs(v) * 70;
return `hsl(${hue},70%,${lightness}%)`;
}
@@ -0,0 +1,863 @@
{
"_info": "Taken from https://github.com/mjaschen/gravel-overlay, with prior authorization from the author (https://github.com/gpxstudio/gpx.studio/issues/32#issuecomment-2320219804).",
"version": 8,
"name": "Gravel Overlay",
"metadata": {
"mapbox:autocomposite": false,
"mapbox:type": "template",
"maputnik:renderer": "mbgljs",
"openmaptiles:version": "3.x",
"openmaptiles:mapbox:owner": "openmaptiles",
"openmaptiles:mapbox:source:url": "mapbox://openmaptiles.4qljc88t"
},
"sources": {
"openmaptiles": {
"type": "vector",
"url": "https://tiles.bikerouter.de/services/gravel/"
}
},
"sprite": "https://demotiles.maplibre.org/styles/osm-bright-gl-style/sprite",
"layers": [
{
"id": "background",
"type": "background",
"layout": {
"visibility": "none"
},
"paint": {
"background-color": "rgba(145, 211, 164, 1)"
}
},
{
"id": "debug_rail",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"filter": ["all", ["==", "$type", "LineString"], ["in", "class", "rail"]],
"layout": {
"visibility": "none"
},
"paint": {
"line-color": "rgba(144, 144, 144, 1)"
}
},
{
"id": "debug_road",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"filter": [
"all",
["==", "$type", "LineString"],
[
"in",
"class",
"motorway",
"trunk",
"primary",
"secondary",
"tertiary",
"minor",
"residential",
"track",
"path"
]
],
"layout": {
"visibility": "none"
},
"paint": {
"line-color": "rgba(204, 204, 204, 1)",
"line-width": {
"stops": [
[10, 0.5],
[12, 1]
]
}
}
},
{
"id": "tr_X_g45-bg",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["match", ["get", "class"], ["track"], true, false],
[
"any",
["match", ["get", "tracktype"], ["grade5"], true, false],
[
"all",
["match", ["get", "tracktype"], ["grade4"], true, false],
["match", ["get", "surface"], ["dirt", "grass", "mud", "sand"], true, false]
]
]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 0, 0, 0.7)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.3],
[14, 1.7]
]
},
"line-dasharray": [1],
"line-offset": {
"stops": [
[12, 0],
[13, 1.8],
[15, 3],
[16, 4]
],
"base": 1.55
}
}
},
{
"id": "tr_X_g45",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["match", ["get", "class"], ["track"], true, false],
[
"any",
["match", ["get", "tracktype"], ["grade5"], true, false],
[
"all",
["match", ["get", "tracktype"], ["grade4"], true, false],
["match", ["get", "surface"], ["dirt", "grass", "mud", "sand"], true, false]
]
]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 0, 0.7)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.3],
[14, 1.7]
]
},
"line-dasharray": [2, 2],
"line-offset": {
"stops": [
[12, 0],
[13, 1.8],
[15, 3],
[16, 4]
],
"base": 1.55
}
}
},
{
"id": "tr_B_g3",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "track"],
["match", ["get", "tracktype"], ["grade3"], true, false],
[
"any",
["match", ["get", "smoothness"], ["bad", "good", "intermediate"], true, false],
[
"match",
["get", "surface"],
["compacted", "fine_gravel", "gravel"],
true,
false
]
]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(235, 6, 158, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.3],
[14, 1.7]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 2],
[15, 4],
[16, 5]
],
"base": 1.55
},
"line-dasharray": [3, 1.5]
}
},
{
"id": "tr_A_g2-plain-case",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "track"],
["match", ["get", "tracktype"], ["grade2"], true, false],
["!", ["has", "surface"]],
["!", ["has", "smoothness"]]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 255, 0.6)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.8],
[12, 3],
[14, 4]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 1.5],
[15, 3],
[16, 4]
],
"base": 1.55
}
}
},
{
"id": "tr_A_g2-plain",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "track"],
["match", ["get", "tracktype"], ["grade2"], true, false],
["!", ["has", "surface"]],
["!", ["has", "smoothness"]]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(235, 6, 158, 0.6)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.5],
[12, 1.5],
[14, 2]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 1.5],
[15, 3],
[16, 4]
],
"base": 1.55
},
"line-dasharray": [5, 1]
}
},
{
"id": "tr_A_g2-case",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "track"],
["match", ["get", "tracktype"], ["grade2"], true, false],
[
"any",
[
"match",
["get", "surface"],
["compacted", "fine_gravel", "gravel"],
true,
false
],
["match", ["get", "smoothness"], ["bad", "good", "intermediate"], true, false]
]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 255, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.8],
[12, 3],
[14, 4]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 2],
[15, 4],
[16, 5]
],
"base": 1.55
}
}
},
{
"id": "tr_A_g2",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "track"],
["match", ["get", "tracktype"], ["grade2"], true, false],
[
"any",
[
"match",
["get", "surface"],
["compacted", "fine_gravel", "gravel"],
true,
false
],
["match", ["get", "smoothness"], ["bad", "good", "intermediate"], true, false]
]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(235, 6, 158, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.5],
[12, 1.5],
[14, 2]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 2],
[15, 4],
[16, 5]
],
"base": 1.55
}
}
},
{
"id": "p_X-bg",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "path"],
["in", "smoothness", "very_bad", "horrible", "very_horrible", "impassable"],
["!in", "tracktype", "grade5", "grade4"]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 0, 0, 0.7)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.1],
[14, 1.5]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 1.8],
[15, 3],
[16, 4]
],
"base": 1.55
}
}
},
{
"id": "p_X",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "path"],
["in", "smoothness", "very_bad", "horrible", "very_horrible", "impassable"],
["!in", "tracktype", "grade5", "grade4"]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 0, 0.7)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.1],
[14, 1.5]
]
},
"line-dasharray": [2, 2],
"line-offset": {
"stops": [
[12, 0],
[13, 1.8],
[15, 3],
[16, 4]
],
"base": 1.55
}
}
},
{
"id": "p_B",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["==", "class", "path"],
["in", "smoothness", "good", "intermediate", "bad"],
[
"!in",
"surface",
"gravel",
"fine_gravel",
"compacted",
"cobblestone",
"sett",
"unhewn_cobblestone",
"paving_stones"
],
["!in", "bicycle", "no"],
["!in", "access", "no"]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(235, 6, 158, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.1],
[14, 1.5]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 2],
[15, 4],
[16, 5]
],
"base": 1.55
},
"line-dasharray": [1.5, 1]
}
},
{
"id": "p_A-case",
"type": "line",
"metadata": {
"maputnik:comment": "Gravel surface with ok-ish smoothness"
},
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "path"],
[
"any",
["match", ["get", "surface"], ["compacted", "fine_gravel"], true, false],
[
"all",
["match", ["get", "surface"], ["gravel"], true, false],
[
"match",
["get", "smoothness"],
["bad", "good", "intermediate"],
true,
false
]
]
],
["match", ["get", "bicycle"], ["no"], false, true],
["match", ["get", "access"], ["no"], false, true]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 255, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.7],
[12, 2.5],
[14, 3.2]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 2],
[15, 4],
[16, 5]
],
"base": 1.55
}
}
},
{
"id": "p_A",
"type": "line",
"metadata": {
"maputnik:comment": "Gravel surface with ok-ish smoothness"
},
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", ["geometry-type"], "LineString"],
["==", ["get", "class"], "path"],
[
"any",
["match", ["get", "surface"], ["compacted", "fine_gravel"], true, false],
[
"all",
["match", ["get", "surface"], ["gravel"], true, false],
[
"match",
["get", "smoothness"],
["bad", "good", "intermediate"],
true,
false
]
]
],
["match", ["get", "bicycle"], ["no"], false, true],
["match", ["get", "access"], ["no"], false, true]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(235, 6, 158, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.5],
[12, 1.5],
[14, 2]
]
},
"line-offset": {
"stops": [
[12, 0],
[13, 2],
[15, 4],
[16, 5]
],
"base": 1.55
}
}
},
{
"id": "r_X_cobbles-case",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "minor", "service", "track", "path", "residential"],
["in", "surface", "sett", "cobblestone", "unhewn_cobblestone"],
["!in", "service", "driveway"]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(0, 0, 0, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.5],
[12, 1.5],
[14, 2]
]
}
}
},
{
"id": "r_X_cobbles",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "minor", "service", "track", "path", "residential"],
["in", "surface", "sett", "cobblestone", "unhewn_cobblestone"],
["!in", "service", "driveway"]
],
"layout": {
"line-cap": "butt",
"line-join": "miter",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(245, 255, 0, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.5],
[12, 1.5],
[14, 2]
]
},
"line-dasharray": [1.5, 1]
}
},
{
"id": "r_X-bg",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "minor"],
["in", "smoothness", "very_bad", "horrible", "very_horrible", "impassable"],
["!in", "surface", "sett", "cobblestone", "unhewn_cobblestone"]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 0, 0, 0.7)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.1],
[14, 1.5]
]
}
}
},
{
"id": "r_X",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "minor"],
["in", "smoothness", "very_bad", "horrible", "very_horrible", "impassable"],
["!in", "surface", "sett", "cobblestone", "unhewn_cobblestone"]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 0, 0.7)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.4],
[12, 1.1],
[14, 1.5]
]
},
"line-dasharray": [2, 2]
}
},
{
"id": "r_A_case",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "minor", "residential", "service"],
["in", "surface", "gravel", "compacted", "fine_gravel"],
["!in", "service", "driveway", "parking_aisle", "drive-through", "emergency_access"]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(255, 255, 255, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.8],
[12, 3],
[14, 4]
]
}
}
},
{
"id": "r_A",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"minzoom": 10,
"filter": [
"all",
["==", "$type", "LineString"],
["in", "class", "minor", "residential", "service"],
["in", "surface", "gravel", "compacted", "fine_gravel"],
["!in", "service", "driveway", "parking_aisle", "drive-through", "emergency_access"]
],
"layout": {
"line-cap": "square",
"line-join": "bevel",
"visibility": "visible"
},
"paint": {
"line-color": "rgba(235, 6, 158, 1)",
"line-width": {
"base": 1.55,
"stops": [
[10, 0.5],
[12, 1.5],
[14, 2]
]
}
}
},
{
"id": "cemetery",
"type": "symbol",
"source": "openmaptiles",
"source-layer": "landuse",
"filter": ["all", ["==", "class", "cemetery"]],
"layout": {
"icon-image": "cemetery_11",
"icon-rotation-alignment": "map",
"icon-size": 1.5
}
},
{
"id": "drinking_water",
"type": "symbol",
"source": "openmaptiles",
"source-layer": "poi",
"minzoom": 9,
"maxzoom": 20,
"filter": [
"any",
["==", "class", "drinking_water"],
["==", "subclass", "drinking_water"]
],
"layout": {
"icon-image": "drinking_water_11",
"visibility": "visible",
"icon-rotation-alignment": "map",
"icon-size": 1.4
}
}
],
"id": "basic",
"owner": "Marcus Jaschen"
}
@@ -0,0 +1,290 @@
// Generated by src/lib/scripts/example-statistics.ts from example.gpx: do not edit.
export const exampleData = {
global: {
totalDistance: 35.97253714756412,
movingDistance: 35.97253714756412,
totalTime: 11033,
movingTime: 11033,
elevationGain: 860.2000000000002,
elevationLoss: 537.8000000000003,
startTime: 1672527600024,
endTime: 1672538633024,
totalSpeed: 11.737617486742575,
movingSpeed: 11.737617486742575,
bounds: { west: -66.660451, south: 48.745764, east: -66.510044, north: 48.92168 },
},
totalDistance: [
0, 0.04328068848542093, 0.11650720502525283, 0.3351587959345754, 1.0682436029275066,
1.5026156340883394, 1.7821196261503274, 2.106207216285154, 2.2410399811984894,
2.9453552435682093, 3.6025169832366335, 3.9844079748662025, 4.853369564407712,
5.245189634628891, 5.701904241715643, 5.8426474906816495, 6.569912055579026,
6.653689376713522, 6.7837648541758915, 6.977468888973151, 7.12513222708653,
7.250970625751078, 7.327345186465471, 7.523057936506123, 7.870270298566722,
8.331907238547238, 8.49966250663381, 8.712146310893873, 9.145642024727252,
9.591804416173956, 9.867268606811916, 10.354226519938479, 10.4995033343533,
10.768320772932757, 10.945182629048222, 11.179142591075422, 11.44408361293813,
11.958196546084086, 12.320595371530443, 12.674140395065313, 12.985892133977105,
13.620373921093831, 13.907784560535925, 14.347390028106815, 14.710337166798299,
15.20320527974895, 15.87459256056528, 18.06487313488486, 19.45780363453859,
19.576216563691453, 20.04629122790926, 20.11508563990313, 20.57906851024942,
20.967882401756427, 21.174446555588826, 21.44870285726096, 21.70815037486119,
21.853596645545945, 22.18038572464859, 22.673623863657042, 23.255471531923366,
23.804171560172605, 24.12646319419839, 24.583516514019728, 24.96563101163832,
25.28996993026779, 25.6464275900608, 25.83865311967249, 25.924206335752725,
26.46043835304079, 26.66269792060754, 26.868668538885316, 26.951359258371486,
27.47113438147256, 27.75981601401171, 27.946424773943168, 28.10186807045419,
28.737895463790068, 28.87567424451052, 29.35605997508892, 29.60491379421725,
29.786435932558835, 30.26638431743931, 30.60806722475413, 30.78584552536327,
30.913622065558272, 31.059459055705133, 31.303159892950628, 31.570611362268927,
31.794495167895366, 32.24998958790923, 32.37413113102769, 32.67948450835431,
32.985096351049044, 33.56292688668583, 33.93674728522087, 34.064219803714735,
34.54278128265628, 34.723139141379185, 35.335211178826825, 35.78464553975441,
35.97253714756412,
],
movingDistance: [
0, 0.04328068848542093, 0.11650720502525283, 0.3351587959345754, 1.0682436029275066,
1.5026156340883394, 1.7821196261503274, 2.106207216285154, 2.2410399811984894,
2.9453552435682093, 3.6025169832366335, 3.9844079748662025, 4.853369564407712,
5.245189634628891, 5.701904241715643, 5.8426474906816495, 6.569912055579026,
6.653689376713522, 6.7837648541758915, 6.977468888973151, 7.12513222708653,
7.250970625751078, 7.327345186465471, 7.523057936506123, 7.870270298566722,
8.331907238547238, 8.49966250663381, 8.712146310893873, 9.145642024727252,
9.591804416173956, 9.867268606811916, 10.354226519938479, 10.4995033343533,
10.768320772932757, 10.945182629048222, 11.179142591075422, 11.44408361293813,
11.958196546084086, 12.320595371530443, 12.674140395065313, 12.985892133977105,
13.620373921093831, 13.907784560535925, 14.347390028106815, 14.710337166798299,
15.20320527974895, 15.87459256056528, 18.06487313488486, 19.45780363453859,
19.576216563691453, 20.04629122790926, 20.11508563990313, 20.57906851024942,
20.967882401756427, 21.174446555588826, 21.44870285726096, 21.70815037486119,
21.853596645545945, 22.18038572464859, 22.673623863657042, 23.255471531923366,
23.804171560172605, 24.12646319419839, 24.583516514019728, 24.96563101163832,
25.28996993026779, 25.6464275900608, 25.83865311967249, 25.924206335752725,
26.46043835304079, 26.66269792060754, 26.868668538885316, 26.951359258371486,
27.47113438147256, 27.75981601401171, 27.946424773943168, 28.10186807045419,
28.737895463790068, 28.87567424451052, 29.35605997508892, 29.60491379421725,
29.786435932558835, 30.26638431743931, 30.60806722475413, 30.78584552536327,
30.913622065558272, 31.059459055705133, 31.303159892950628, 31.570611362268927,
31.794495167895366, 32.24998958790923, 32.37413113102769, 32.67948450835431,
32.985096351049044, 33.56292688668583, 33.93674728522087, 34.064219803714735,
34.54278128265628, 34.723139141379185, 35.335211178826825, 35.78464553975441,
35.97253714756412,
],
totalTime: [
0, 14000, 46000, 151000, 346000, 424000, 481000, 541000, 567000, 683000, 878000, 942000,
1181000, 1285000, 1384000, 1412000, 1565000, 1588000, 1618000, 1660000, 1693000, 1720000,
1734000, 1774000, 1841000, 1921000, 1952000, 1990000, 2063000, 2137000, 2183000, 2332000,
2375000, 2476000, 2537000, 2628000, 2733000, 2955000, 3078000, 3210000, 3330000, 3757000,
3916000, 4078000, 4146000, 4324000, 4571000, 5400000, 5824000, 6419000, 6578000, 6590000,
6726000, 6847000, 7063000, 7278000, 7578000, 7785000, 7865000, 7950000, 8263000, 8417000,
8482000, 8617000, 8682000, 8723000, 8788000, 8830000, 8853000, 8978000, 9012000, 9050000,
9063000, 9154000, 9211000, 9248000, 9278000, 9403000, 9435000, 9528000, 9571000, 9603000,
9685000, 9736000, 9780000, 9811000, 9843000, 9895000, 9940000, 9995000, 10126000, 10153000,
10216000, 10270000, 10389000, 10475000, 10511000, 10618000, 10653000, 10908000, 11003000,
11033000,
],
movingTime: [
0, 14000, 46000, 151000, 346000, 424000, 481000, 541000, 567000, 683000, 878000, 942000,
1181000, 1285000, 1384000, 1412000, 1565000, 1588000, 1618000, 1660000, 1693000, 1720000,
1734000, 1774000, 1841000, 1921000, 1952000, 1990000, 2063000, 2137000, 2183000, 2332000,
2375000, 2476000, 2537000, 2628000, 2733000, 2955000, 3078000, 3210000, 3330000, 3757000,
3916000, 4078000, 4146000, 4324000, 4571000, 5400000, 5824000, 6419000, 6578000, 6590000,
6726000, 6847000, 7063000, 7278000, 7578000, 7785000, 7865000, 7950000, 8263000, 8417000,
8482000, 8617000, 8682000, 8723000, 8788000, 8830000, 8853000, 8978000, 9012000, 9050000,
9063000, 9154000, 9211000, 9248000, 9278000, 9403000, 9435000, 9528000, 9571000, 9603000,
9685000, 9736000, 9780000, 9811000, 9843000, 9895000, 9940000, 9995000, 10126000, 10153000,
10216000, 10270000, 10389000, 10475000, 10511000, 10618000, 10653000, 10908000, 11003000,
11033000,
],
elevationGain: [
0, 5.2000000000000455, 19.000000000000057, 43.400000000000034, 75.60000000000002,
80.66666666666669, 84.2000000000001, 86.33333333333343, 86.60000000000008,
86.60000000000008, 120.40000000000009, 120.40000000000009, 143.40000000000015,
160.0000000000001, 160.4666666666668, 161.80000000000013, 163.6000000000002,
165.0666666666669, 165.26666666666682, 165.26666666666682, 165.26666666666682,
165.26666666666682, 165.26666666666682, 165.26666666666682, 165.26666666666682,
165.26666666666682, 165.26666666666682, 165.26666666666682, 165.26666666666682,
165.26666666666682, 165.26666666666682, 179.66666666666686, 194.4000000000002,
206.4000000000002, 221.9333333333335, 237.40000000000015, 263.73333333333346,
289.6000000000001, 318.0666666666668, 340.46666666666675, 372.6000000000001,
405.1333333333334, 438.86666666666684, 446.86666666666684, 448.86666666666684,
489.7333333333335, 552.4000000000001, 636.8666666666668, 667.7333333333335,
680.4000000000001, 680.4000000000001, 682.7333333333335, 692.2666666666668,
706.9333333333335, 725.2000000000002, 754.2000000000002, 782.6000000000003,
803.1333333333334, 803.1333333333334, 803.1333333333334, 843.5333333333334,
843.5333333333334, 843.5333333333334, 843.5333333333334, 843.5333333333334,
843.5333333333334, 843.5333333333334, 843.5333333333334, 845.2, 845.2, 845.2, 845.2, 845.2,
845.2, 845.2, 845.2, 845.2, 845.2, 845.2, 845.2, 845.2, 845.2, 845.2, 845.2,
846.9333333333333, 848.2666666666667, 848.4666666666666, 848.4666666666666,
848.4666666666666, 850.4, 854.1333333333332, 856.2666666666668, 856.2666666666668,
856.2666666666668, 856.2666666666668, 856.2666666666668, 858.4000000000001,
860.2000000000002, 860.2000000000002, 860.2000000000002, 860.2000000000002,
860.2000000000002,
],
elevationLoss: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20000000000004547, 0.20000000000004547, 20.40000000000009,
20.40000000000009, 20.40000000000009, 20.40000000000009, 20.40000000000009,
20.40000000000009, 20.40000000000009, 20.40000000000009, 20.866666666666788,
21.333333333333485, 21.800000000000182, 22.26666666666688, 23.133333333333496,
25.26666666666688, 27.933333333333508, 31.06666666666689, 34.46666666666681,
39.46666666666681, 45.400000000000205, 51.26666666666682, 51.26666666666682,
51.26666666666682, 51.26666666666682, 51.26666666666682, 51.26666666666682,
51.26666666666682, 51.26666666666682, 51.26666666666682, 51.26666666666682,
51.26666666666682, 51.26666666666682, 51.26666666666682, 51.26666666666682,
51.26666666666682, 51.26666666666682, 51.26666666666682, 51.26666666666682,
51.26666666666682, 51.26666666666682, 54.73333333333352, 54.73333333333352,
54.73333333333352, 54.73333333333352, 54.73333333333352, 54.73333333333352,
54.73333333333352, 54.73333333333352, 71.33333333333354, 90.93333333333345,
90.93333333333345, 103.26666666666671, 118.93333333333345, 137.93333333333345,
182.53333333333347, 231.86666666666684, 275.6666666666669, 313.5333333333335,
313.5333333333335, 314.5333333333335, 317.6666666666668, 323.80000000000024,
332.40000000000026, 340.1333333333335, 346.5333333333335, 349.00000000000006,
355.8666666666666, 361.7999999999999, 367.59999999999997, 371.13333333333327,
378.59999999999997, 389.06666666666666, 400.3999999999999, 412.2000000000001,
412.2000000000001, 412.2000000000001, 412.2000000000001, 414.0666666666668,
415.2666666666668, 415.2666666666668, 415.2666666666668, 415.2666666666668,
440.0666666666668, 462.2666666666668, 469.6000000000001, 472.2666666666667,
472.2666666666667, 472.2666666666667, 473.40000000000015, 497.93333333333356,
519.4000000000003, 537.8000000000003,
],
slope: [
5.54519829509753, 11.329771405243958, 13.361742112430905, 6.556437280063828,
3.3748571006965706, 1.4008034553191204, 0.8946446834706256, 0.34864437421436856,
0.023833697214010865, 2.4238382250011337, 1.3088844858730833, 0.7354983423695479,
3.1409086334150653, 1.2256423076302692, 0.20085098686760294, 0.437784077436669,
0.5425120546520237, 0.7481781910257762, -0.3088521546718895, -0.4101153511136872,
-0.1462513564675528, -0.4945281465002597, -0.5145407171378057, -0.2946999437560697,
-0.7417945450232967, -1.0804074014330973, -1.2097652068240252, -1.269390092150544,
-1.4096385772574478, -1.6906250826786617, 1.6526278471972953, 3.985861405936538,
6.327061969720709, 6.462045767621801, 6.718241042985547, 7.336125039207492,
7.855681831346254, 6.708409718819214, 6.0060576064991755, 7.635690246436876,
7.376614554438903, 7.961883391751326, 5.7495287376423185, 1.246024238407464,
4.2065153584168264, 7.094663287987479, 5.1718091508901205, 4.191770925552759,
3.162749054180518, -1.155504394077654, -2.486689363250133, 3.1532876038197415,
3.7758117104036595, 3.829499622714933, 9.10942941353019, 14.240107950438869,
12.941665571593896, -0.9317388039630531, -4.414487617055606, 1.6556817957741452,
2.4589851525664814, -2.8014045434450368, -4.413963268792533, -7.960267137482532,
-12.683072647006348, -15.24684513552079, -15.673890080960359, -9.647966381748613,
0.6754743880371754, -0.5145623969089836, -3.135485920405431, -3.879979247223856,
-3.352887180002204, -2.176987189136962, -0.9678293676606319, -1.2863539093324792,
-2.400594266311405, -1.938469929926933, -0.19412308181177693, -1.6181239765102629,
-4.647099739859, -3.3259229591723516, -2.84799279461206, -1.7710658389233644,
0.785456382783462, 0.4385748023866403, 0.25671447794793106, -1.4085821207384774,
-0.6105810335595012, 1.8251983257651685, 1.3111677817452918, -6.658984457921569,
-7.692745586787598, -3.282613638567991, -1.324014882722225, 0.2792778338655941,
1.5840695473562374, 0.1214109154598013, -4.214883885805801, -4.182735032776085,
-5.523076373263165, -10.644434966065772,
],
slopeSegmentStarts: [
0, 4, 9, 10, 11, 13, 30, 42, 44, 47, 53, 57, 59, 60, 63, 67, 83, 91, 93, 98,
],
slopeSegmentSlopes: [
7.077037465314024, 0.5753520337401837, 5.143330470981779, -5.289467529413177,
3.1409086334150653, -0.553863318953831, 6.771412441716311, 1.246024238407464,
5.604351892140715, 2.2941711127147597, 10.861290836693483, -4.414487617055606,
6.94339810974512, -3.539036752039, -13.990509017835178, -2.033792785924166,
0.45298474033593794, -7.692745586787598, -0.4142590757867528, -5.154482373206842,
],
slopeSegmentDistances: [
1.0682436029275066, 1.8771116406407027, 0.6571617396684242, 0.38189099162956897,
1.2607816597626882, 4.622078972183025, 4.040515953724009, 0.802552606262374,
3.3545359680865605, 2.9030092668715675, 0.8857142437895185, 0.8200272181110968,
0.5818476682663238, 1.3280449820963618, 1.255136605652762, 4.7694141050816405,
1.7660639062735584, 0.610965220021356, 1.738042790330141, 1.2493980061849328,
],
lng: [
-66.658624, -66.658127, -66.658472, -66.660451, -66.650629, -66.646183, -66.646388,
-66.642677, -66.640854, -66.633175, -66.635593, -66.630508, -66.633652, -66.633982,
-66.636621, -66.636833, -66.632505, -66.632642, -66.63365, -66.636288, -66.637602,
-66.639281, -66.640209, -66.641257, -66.645941, -66.648858, -66.647392, -66.647989,
-66.643139, -66.637565, -66.63382, -66.627346, -66.627095, -66.623563, -66.622373,
-66.619597, -66.617774, -66.61598, -66.612289, -66.612662, -66.611191, -66.610542,
-66.611253, -66.614945, -66.615775, -66.613768, -66.608474, -66.608964, -66.610557,
-66.609899, -66.604874, -66.605225, -66.610658, -66.609756, -66.610351, -66.609261,
-66.612153, -66.61214, -66.607951, -66.604558, -66.598406, -66.591258, -66.586899,
-66.580708, -66.575533, -66.571339, -66.567595, -66.564982, -66.56396, -66.558605,
-66.557755, -66.555736, -66.555848, -66.551324, -66.549922, -66.547886, -66.54855,
-66.545275, -66.543694, -66.53717, -66.533767, -66.531437, -66.524936, -66.520542,
-66.518785, -66.517736, -66.517472, -66.518888, -66.516545, -66.5175, -66.514672,
-66.515141, -66.517794, -66.51814, -66.515673, -66.512786, -66.513151, -66.5121, -66.513039,
-66.513625, -66.512188, -66.510044,
],
lat: [
48.745764, 48.745974, 48.746592, 48.748063, 48.749297, 48.751879, 48.754389, 48.755973,
48.756134, 48.759941, 48.765632, 48.764883, 48.772418, 48.775935, 48.779656, 48.780914,
48.7868, 48.787548, 48.788511, 48.788629, 48.789636, 48.789875, 48.789562, 48.787943,
48.787467, 48.791147, 48.792306, 48.794176, 48.79641, 48.798028, 48.798255, 48.797259,
48.798555, 48.799212, 48.800596, 48.801637, 48.803695, 48.808165, 48.810336, 48.813506,
48.816137, 48.821827, 48.824369, 48.827487, 48.830705, 48.834936, 48.839867, 48.859562,
48.872045, 48.873018, 48.875654, 48.876228, 48.878383, 48.881829, 48.883645, 48.886005,
48.887357, 48.888665, 48.88969, 48.893524, 48.896844, 48.89835, 48.897915, 48.89849,
48.898005, 48.898957, 48.901011, 48.900816, 48.901191, 48.897895, 48.896164, 48.894872,
48.894132, 48.890526, 48.888099, 48.887087, 48.885759, 48.88046, 48.879786, 48.87928,
48.879289, 48.879852, 48.879259, 48.880304, 48.879199, 48.880118, 48.881418, 48.883402,
48.885249, 48.887162, 48.890812, 48.891885, 48.894006, 48.896745, 48.901682, 48.904457,
48.905578, 48.909826, 48.911326, 48.916817, 48.920747, 48.92168,
],
ele: [
290.4, 292.8, 303.6, 331.8, 366, 371.2, 376, 376.6, 377.6, 376.8, 410.6, 390.4, 419.8, 430,
430.2, 431.2, 434, 435.6, 435.6, 434.6, 434.2, 434.2, 433.2, 432.8, 431.6, 426.8, 424.8,
422.2, 416.6, 409.8, 404.4, 422.4, 429.6, 448.6, 458.4, 476.2, 495, 537.4, 553.8, 580.4,
604.6, 650.2, 678, 692, 688, 728, 770.6, 876, 920.8, 923.8, 914, 910.4, 930.8, 942.6, 953.6,
986.4, 1029.6, 1038.8, 1025.2, 1002.6, 1043, 1030.4, 1018.6, 996, 951.8, 906.4, 848, 820.4,
821.2, 824.6, 817.4, 811.8, 806.2, 791.6, 788.6, 787, 784.2, 768, 769.2, 766.8, 757.4,
746.8, 735.4, 723.4, 726.2, 725.8, 727.4, 726.8, 720.2, 723.8, 732.6, 731.4, 704, 684.4,
675, 671.8, 676.4, 681.4, 677.2, 648, 632.8, 612.8,
],
timestamps: [
1672527600024, 1672527614024, 1672527646024, 1672527751024, 1672527946024, 1672528024024,
1672528081024, 1672528141024, 1672528167024, 1672528283024, 1672528478024, 1672528542024,
1672528781024, 1672528885024, 1672528984024, 1672529012024, 1672529165024, 1672529188024,
1672529218024, 1672529260024, 1672529293024, 1672529320024, 1672529334024, 1672529374024,
1672529441024, 1672529521024, 1672529552024, 1672529590024, 1672529663024, 1672529737024,
1672529783024, 1672529932024, 1672529975024, 1672530076024, 1672530137024, 1672530228024,
1672530333024, 1672530555024, 1672530678024, 1672530810024, 1672530930024, 1672531357024,
1672531516024, 1672531678024, 1672531746024, 1672531924024, 1672532171024, 1672533000024,
1672533424024, 1672534019024, 1672534178024, 1672534190024, 1672534326024, 1672534447024,
1672534663024, 1672534878024, 1672535178024, 1672535385024, 1672535465024, 1672535550024,
1672535863024, 1672536017024, 1672536082024, 1672536217024, 1672536282024, 1672536323024,
1672536388024, 1672536430024, 1672536453024, 1672536578024, 1672536612024, 1672536650024,
1672536663024, 1672536754024, 1672536811024, 1672536848024, 1672536878024, 1672537003024,
1672537035024, 1672537128024, 1672537171024, 1672537203024, 1672537285024, 1672537336024,
1672537380024, 1672537411024, 1672537443024, 1672537495024, 1672537540024, 1672537595024,
1672537726024, 1672537753024, 1672537816024, 1672537870024, 1672537989024, 1672538075024,
1672538111024, 1672538218024, 1672538253024, 1672538508024, 1672538603024, 1672538633024,
],
speed: [
11.129319896251097, 9.117955175889351, 7.6697896847953, 11.420836774827047,
15.395035228401284, 19.036693952608555, 18.572048682978913, 19.210619513643987,
21.274175339570412, 15.759862403013887, 14.442431786381372, 14.861614825794996,
13.232693805089438, 15.04790560743128, 16.935813242440407, 17.264243811647404,
16.589493123379203, 14.52585047073047, 16.18897561298147, 16.38563389971064,
16.410104206675626, 17.755284238150917, 18.13915405033632, 18.266639285649575,
19.80855433570078, 20.41272026163526, 19.83856029634617, 20.950687073300834,
21.54264747624692, 21.64879746253991, 14.075484992575811, 11.854401141400949,
10.35235632485696, 9.903984326553841, 9.729990429694698, 9.163487459202377,
8.576740789086204, 9.146209654876312, 10.107442573852628, 9.50423946352374,
6.2274966978110875, 5.663502961794799, 8.153451667435336, 12.561692967584985,
12.524125633787333, 9.861928041320306, 9.574353418670329, 10.294940036954442,
5.339387972231342, 2.8097550877114332, 11.34461213077211, 12.95944740827415,
11.945791216622078, 6.360121552587119, 4.016133735072683, 3.7307451444281803,
2.874985478946628, 5.923509614057983, 17.89150294060575, 9.724394236656252,
8.715142842518263, 14.317671160685329, 14.0282091692482, 15.10502071391872,
23.992757532953096, 23.121393229442734, 18.46036898931696, 15.384668992168189,
15.124505676526212, 16.720564185392, 20.41150929222635, 20.376094430396314,
20.854586858789187, 19.665164326383863, 18.202610775470102, 18.378916465566082,
18.382545054508643, 17.743326284094163, 17.803137925406997, 19.303399845178138,
20.658045958555817, 20.88854283859139, 22.239643999271156, 19.684845773960607,
14.666632358598804, 15.635058876677832, 16.694478316815264, 18.97060106834699,
17.688069898010582, 13.14925598013496, 13.206895362508604, 17.179796817802924,
18.798929846810953, 18.383772034644412, 16.711918843992997, 14.792250010689015,
15.256799935436915, 16.704997292901556, 9.837060780048157, 10.918351526145143,
18.354987899634057, 22.54699293716527,
],
atemp: [
18, 18, 18, 19, 22, 22, 22, 21, 20, 20, 23, 23, 19, 19, 18, 18, 17, 17, 18, 18, 18, 19, 19,
19, 19, 19, 18, 18, 17, 17, 16, 16, 16, 17, 18, 17, 17, 18, 18, 18, 19, 22, 23, 23, 23, 22,
19, 18, 20, 20, 18, 18, 17, 19, 20, 21, 22, 22, 21, 19, 18, 16, 16, 16, 16, 16, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 15, 15,
15, 15, 15, 15, 16, 16, 16, 18, 17, 17,
],
};
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><gpx creator="StravaGPX" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxpx="http://www.garmin.com/xmlschemas/PowerExtension/v1" xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2"><metadata><name>Example</name><author><name>gpx.studio</name><link href="https://gpx.studio"/></author><time>2023-08-20T12:42:07.000Z</time></metadata><trk><name>Example</name><type>cycling</type><trkseg><trkpt lat="48.745764" lon="-66.658624"><ele>290.4</ele><time>2022-12-31T23:00:00.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>18</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.745974" lon="-66.658127"><ele>292.8</ele><time>2022-12-31T23:00:14.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>18</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.746592" lon="-66.658472"><ele>303.6</ele><time>2022-12-31T23:00:46.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>18</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.748063" lon="-66.660451"><ele>331.8</ele><time>2022-12-31T23:02:31.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>19</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.749297" lon="-66.650629"><ele>366</ele><time>2022-12-31T23:05:46.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.751879" lon="-66.646183"><ele>371.2</ele><time>2022-12-31T23:07:04.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.754389" lon="-66.646388"><ele>376</ele><time>2022-12-31T23:08:01.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.755973" lon="-66.642677"><ele>376.6</ele><time>2022-12-31T23:09:01.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>21</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.756134" lon="-66.640854"><ele>377.6</ele><time>2022-12-31T23:09:27.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>20</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.759941" lon="-66.633175"><ele>376.8</ele><time>2022-12-31T23:11:23.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>20</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.765632" lon="-66.635593"><ele>410.6</ele><time>2022-12-31T23:14:38.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>23</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.764883" lon="-66.630508"><ele>390.4</ele><time>2022-12-31T23:15:42.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>23</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.772418" lon="-66.633652"><ele>419.8</ele><time>2022-12-31T23:19:41.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>19</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.775935" lon="-66.633982"><ele>430</ele><time>2022-12-31T23:21:25.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>19</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.779656" lon="-66.636621"><ele>430.2</ele><time>2022-12-31T23:23:04.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>18</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.780914" lon="-66.636833"><ele>431.2</ele><time>2022-12-31T23:23:32.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>18</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.7868" lon="-66.632505"><ele>434</ele><time>2022-12-31T23:26:05.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>17</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt><trkpt lat="48.787548" lon="-66.632642"><ele>435.6</ele><time>2022-12-31T23:26:28.024Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>17</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkLine truncated
@@ -0,0 +1,48 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { computeExampleData, engineIsBuilt } from '$lib/scripts/example-statistics';
import { exampleData } from '$lib/data/example/example-data';
import { exampleStatistics } from '$lib/data/example';
describe('exampleStatistics', () => {
it('has the statistics of the whole example for the whole range', async () => {
const whole = await exampleStatistics.slice(0, exampleStatistics.length - 1);
const global = exampleStatistics.global;
assert.ok(whole);
for (const key of [
'totalDistance',
'movingDistance',
'totalTime',
'movingTime',
'elevationGain',
'elevationLoss',
'startTime',
'endTime',
'totalSpeed',
'movingSpeed',
] as const) {
assert.ok(Math.abs((whole[key] as number) - (global[key] as number)) < 1e-6, key);
}
});
it('has no speed for a range that does not last', async () => {
const point = await exampleStatistics.slice(20, 20);
assert.equal(point?.totalTime, 0);
assert.equal(point?.totalSpeed, undefined);
assert.equal(point?.movingSpeed, undefined);
});
it('has nothing for ranges that are not in the example', async () => {
assert.equal(await exampleStatistics.slice(5, 500), undefined);
assert.equal(await exampleStatistics.slice(-1, 3), undefined);
assert.equal(await exampleStatistics.slice(10, 5), undefined);
});
it(
'is what the engine computes (npm run generate:example if not)',
{ skip: !engineIsBuilt() && 'the engine is not built' },
async () => {
assert.deepEqual(JSON.parse(JSON.stringify(await computeExampleData())), exampleData);
}
);
});
+81
View File
@@ -0,0 +1,81 @@
/**
* The statistics of an example file (a ride of 102 trackpoints with timestamps and temperatures),
* for the pages that show the elevation profile and the statistics without a file: the home page
* and the documentation. They are the ones that the engine computes for `example.gpx`, kept as
* they are (see `example-data.ts`) so that the example does not need the engine.
*/
import type { GlobalStatistics, SelectionPoint, SelectionStatistics } from '$lib/engine';
import { intervalAt } from '$lib/engine/trackpoint-categories';
import { exampleData as data } from '$lib/data/example/example-data';
const length = data.lng.length;
// the values that are cumulative over the selection: those of a range are the difference of its ends
const cumulative = {
totalDistance: data.totalDistance,
movingDistance: data.movingDistance,
totalTime: data.totalTime,
movingTime: data.movingTime,
elevationGain: data.elevationGain,
elevationLoss: data.elevationLoss,
};
/** The statistics of the trackpoints from `start` to `end` (both included), as the engine does. */
async function slice(start: number, end: number): Promise<GlobalStatistics | undefined> {
if (!(start >= 0 && start <= end && end < length)) {
return undefined;
}
const delta = (values: number[]) => values[end] - values[start];
// the times are in ms, in seconds in the statistics; a range cannot last a negative time
const totalTime = Math.max(0, delta(cumulative.totalTime));
const movingTime = Math.max(0, delta(cumulative.movingTime));
const totalDistance = delta(cumulative.totalDistance);
const movingDistance = delta(cumulative.movingDistance);
const hours = (ms: number) => ms / 3_600_000;
return {
...data.global,
totalDistance,
movingDistance,
totalTime: totalTime / 1000,
movingTime: movingTime / 1000,
elevationGain: delta(cumulative.elevationGain),
elevationLoss: delta(cumulative.elevationLoss),
startTime: data.timestamps[start],
endTime: data.timestamps[end],
totalSpeed: totalTime > 0 ? totalDistance / hours(totalTime) : undefined,
movingSpeed: movingTime > 0 ? movingDistance / hours(movingTime) : undefined,
};
}
const slopeSegmentStarts = Uint32Array.from(data.slopeSegmentStarts);
/** The data of the trackpoint at `index`, as the engine gives it (the example has no OSM data). */
async function point(index: number): Promise<SelectionPoint | undefined> {
if (!(index >= 0 && index < length)) {
return undefined;
}
const segment = intervalAt(slopeSegmentStarts, index);
return {
slope: data.slope[index],
time: data.timestamps[index],
slopeSegmentSlope: data.slopeSegmentSlopes[segment],
slopeSegmentDistance: data.slopeSegmentDistances[segment],
};
}
export const exampleStatistics: SelectionStatistics = {
global: data.global,
length,
totalDistance: Float64Array.from(data.totalDistance),
lng: Float64Array.from(data.lng),
lat: Float64Array.from(data.lat),
ele: Float64Array.from(data.ele),
speed: Float64Array.from(data.speed),
atemp: Float64Array.from(data.atemp),
slopeSegments: {
starts: slopeSegmentStarts,
slopes: Float64Array.from(data.slopeSegmentSlopes),
},
slice,
point,
};
+103
View File
@@ -0,0 +1,103 @@
// The layers are plain data, which the settings and the menus rely on being consistent.
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
basemaps,
basemapTree,
defaultBasemap,
defaultBasemapTree,
defaultOpacities,
defaultOverlays,
defaultOverlayTree,
defaultOverpassQueries,
defaultOverpassTree,
defaultTerrainSource,
overlays,
overlayTree,
overpassQueryData,
overpassTree,
terrainSources,
type LayerTreeType,
} from '$lib/data/layers';
import { getLayers } from '$lib/components/map/layer-control/utils';
const leaves = (tree: LayerTreeType) => Object.keys(getLayers(tree));
describe('layers', () => {
it('has a basemap and an overlay for every leaf of their trees', () => {
for (const id of leaves(basemapTree)) assert.ok(id in basemaps, `basemap ${id}`);
for (const id of leaves(overlayTree)) assert.ok(id in overlays, `overlay ${id}`);
for (const id of leaves(overpassTree)) assert.ok(id in overpassQueryData, `query ${id}`);
});
it('offers every layer and every query in its trees', () => {
const missingFrom = (ids: string[], tree: LayerTreeType) => {
const offered = new Set(leaves(tree));
return ids.filter((id) => !offered.has(id));
};
const basemapIds = Object.keys(basemaps);
assert.deepEqual(missingFrom(basemapIds, basemapTree), [], 'basemapTree');
assert.deepEqual(missingFrom(basemapIds, defaultBasemapTree), [], 'defaultBasemapTree');
const overlayIds = Object.keys(overlays);
assert.deepEqual(missingFrom(overlayIds, overlayTree), [], 'overlayTree');
assert.deepEqual(missingFrom(overlayIds, defaultOverlayTree), [], 'defaultOverlayTree');
const queryIds = Object.keys(overpassQueryData);
assert.deepEqual(missingFrom(queryIds, overpassTree), [], 'overpassTree');
assert.deepEqual(missingFrom(queryIds, defaultOverpassTree), [], 'defaultOverpassTree');
assert.deepEqual(
missingFrom(queryIds, defaultOverpassQueries),
[],
'defaultOverpassQueries'
);
});
it('only offers by default what exists', () => {
assert.ok(defaultBasemap in basemaps);
for (const id of leaves(defaultBasemapTree)) assert.ok(id in basemaps, `basemap ${id}`);
for (const id of leaves(defaultOverlayTree)) assert.ok(id in overlays, `overlay ${id}`);
for (const id of leaves(defaultOverpassTree)) assert.ok(id in overpassQueryData, `${id}`);
for (const id of leaves(defaultOverlays)) assert.ok(id in overlays, `overlay ${id}`);
for (const id of leaves(defaultOverpassQueries)) {
assert.ok(id in overpassQueryData, `query ${id}`);
}
assert.ok(defaultTerrainSource in terrainSources);
});
it('has the default selections inside the default trees', () => {
const inTree = (selection: LayerTreeType, tree: LayerTreeType) => {
const offered = new Set(leaves(tree));
for (const id of leaves(selection)) assert.ok(offered.has(id), `${id}`);
};
inTree(defaultOverlays, defaultOverlayTree);
inTree(defaultOverpassQueries, defaultOverpassTree);
});
it('has the default tree inside the whole tree', () => {
const all = new Set(leaves(basemapTree));
for (const id of leaves(defaultBasemapTree)) assert.ok(all.has(id), `${id}`);
});
it('has no id used by two leaves of a tree', () => {
for (const tree of [basemapTree, overlayTree, overpassTree, defaultBasemapTree]) {
const ids: string[] = [];
const walk = (node: LayerTreeType) =>
Object.entries(node).forEach(([id, value]) =>
typeof value === 'boolean' ? ids.push(id) : walk(value)
);
walk(tree);
assert.equal(new Set(ids).size, ids.length);
}
});
it('has opacities between 0 and 1, for overlays', () => {
for (const [id, opacity] of Object.entries(defaultOpacities)) {
assert.ok(opacity >= 0 && opacity <= 1, id);
}
});
it('has the queries it needs', () => {
for (const [id, data] of Object.entries(overpassQueryData)) {
assert.ok(Object.keys(data).length > 0, id);
}
});
});
File diff suppressed because it is too large. Load diff
+139
View File
@@ -0,0 +1,139 @@
import {
Landmark,
Shell,
Bike,
Building,
Tent,
Car,
Wrench,
ShoppingBasket,
Droplet,
DoorOpen,
Trees,
Fuel,
House,
Info,
TreeDeciduous,
CircleParking,
Cross,
Utensils,
Construction,
BrickWall,
ShowerHead,
Mountain,
Phone,
TrainFront,
Bed,
Binoculars,
TriangleAlert,
Anchor,
Toilet,
X,
type IconProps,
} from '@lucide/svelte';
import {
Landmark as LandmarkSvg,
Shell as ShellSvg,
Bike as BikeSvg,
Building as BuildingSvg,
Tent as TentSvg,
Car as CarSvg,
Wrench as WrenchSvg,
ShoppingBasket as ShoppingBasketSvg,
Droplet as DropletSvg,
DoorOpen as DoorOpenSvg,
Trees as TreesSvg,
Fuel as FuelSvg,
House as HouseSvg,
Info as InfoSvg,
TreeDeciduous as TreeDeciduousSvg,
CircleParking as CircleParkingSvg,
Cross as CrossSvg,
Utensils as UtensilsSvg,
Construction as ConstructionSvg,
BrickWall as BrickWallSvg,
ShowerHead as ShowerHeadSvg,
Mountain as MountainSvg,
Phone as PhoneSvg,
TrainFront as TrainFrontSvg,
Bed as BedSvg,
Binoculars as BinocularsSvg,
TriangleAlert as TriangleAlertSvg,
Anchor as AnchorSvg,
Toilet as ToiletSvg,
X as XSvg,
} from 'lucide-static';
import type { Component } from 'svelte';
export type Symbol = {
value: string;
icon?: Component<IconProps>;
iconSvg?: string;
};
export const symbols: { [key: string]: Symbol } = {
alert: { value: 'Alert', icon: TriangleAlert, iconSvg: TriangleAlertSvg },
anchor: { value: 'Anchor', icon: Anchor, iconSvg: AnchorSvg },
bank: { value: 'Bank', icon: Landmark, iconSvg: LandmarkSvg },
beach: { value: 'Beach', icon: Shell, iconSvg: ShellSvg },
bike_trail: { value: 'Bike Trail', icon: Bike, iconSvg: BikeSvg },
binoculars: { value: 'Binoculars', icon: Binoculars, iconSvg: BinocularsSvg },
bridge: { value: 'Bridge' },
building: { value: 'Building', icon: Building, iconSvg: BuildingSvg },
campground: { value: 'Campground', icon: Tent, iconSvg: TentSvg },
car: { value: 'Car', icon: Car, iconSvg: CarSvg },
car_repair: { value: 'Car Repair', icon: Wrench, iconSvg: WrenchSvg },
convenience_store: {
value: 'Convenience Store',
icon: ShoppingBasket,
iconSvg: ShoppingBasketSvg,
},
crossing: {
value: 'Crossing',
icon: X,
iconSvg: XSvg,
},
department_store: {
value: 'Department Store',
icon: ShoppingBasket,
iconSvg: ShoppingBasketSvg,
},
drinking_water: { value: 'Drinking Water', icon: Droplet, iconSvg: DropletSvg },
exit: { value: 'Exit', icon: DoorOpen, iconSvg: DoorOpenSvg },
lodge: { value: 'Lodge', icon: House, iconSvg: HouseSvg },
lodging: { value: 'Lodging', icon: Bed, iconSvg: BedSvg },
forest: { value: 'Forest', icon: Trees, iconSvg: TreesSvg },
gas_station: { value: 'Gas Station', icon: Fuel, iconSvg: FuelSvg },
ground_transportation: {
value: 'Ground Transportation',
icon: TrainFront,
iconSvg: TrainFrontSvg,
},
hotel: { value: 'Hotel', icon: Bed, iconSvg: BedSvg },
house: { value: 'House', icon: House, iconSvg: HouseSvg },
information: { value: 'Information', icon: Info, iconSvg: InfoSvg },
park: { value: 'Park', icon: TreeDeciduous, iconSvg: TreeDeciduousSvg },
parking_area: { value: 'Parking Area', icon: CircleParking, iconSvg: CircleParkingSvg },
pharmacy: { value: 'Pharmacy', icon: Cross, iconSvg: CrossSvg },
picnic_area: { value: 'Picnic Area', icon: Utensils, iconSvg: UtensilsSvg },
restaurant: { value: 'Restaurant', icon: Utensils, iconSvg: UtensilsSvg },
restricted_area: { value: 'Restricted Area', icon: Construction, iconSvg: ConstructionSvg },
restroom: { value: 'Restroom', icon: Toilet, iconSvg: ToiletSvg },
road: { value: 'Road', icon: BrickWall, iconSvg: BrickWallSvg },
scenic_area: { value: 'Scenic Area', icon: Binoculars, iconSvg: BinocularsSvg },
shelter: { value: 'Shelter', icon: Tent, iconSvg: TentSvg },
shopping_center: { value: 'Shopping Center', icon: ShoppingBasket },
shower: { value: 'Shower', icon: ShowerHead, iconSvg: ShowerHeadSvg },
summit: { value: 'Summit', icon: Mountain, iconSvg: MountainSvg },
telephone: { value: 'Telephone', icon: Phone, iconSvg: PhoneSvg },
tunnel: { value: 'Tunnel' },
water_source: { value: 'Water Source', icon: Droplet, iconSvg: DropletSvg },
};
export function getSymbolKey(value: string | undefined): string | undefined {
if (value === undefined) {
return undefined;
} else {
return Object.keys(symbols).find((key) => symbols[key].value === value);
}
}