Canvas rewrite
-Full rewrite to use Canvas instead of SVG -Restructured backend
This commit is contained in:
1 parent
856320c976
commit
45d9e8d577
13 files changed
+1612
-1056
No files matched your search
@@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import {Color} from './js/colorlib.js';
|
import {Color} from './js/colorlib.js';
|
||||||
|
import {SpriteBounds} from './js/spritelib.js';
|
||||||
|
|
||||||
export const gradeColors = {
|
export const gradeColors = {
|
||||||
grade_flat: '#fff',
|
grade_flat: '#fff',
|
||||||
@@ -39,4 +40,55 @@ export const sidingUsageMeanings = {
|
|||||||
LP:'Passenger Transfer',
|
LP:'Passenger Transfer',
|
||||||
SP:'Passenger Car Storage',
|
SP:'Passenger Car Storage',
|
||||||
D:'Service & Repair',
|
D:'Service & Repair',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const bezierGradeResolution = 80;
|
||||||
|
export const bezierLengthResolution = 80;
|
||||||
|
export const bezierCurvatureResolution = 80;
|
||||||
|
export const scrollZoomFactor = 1.25;
|
||||||
|
export const buttonZoomFactor = 1.5;
|
||||||
|
|
||||||
|
export const minZoomLevel = 0.01;
|
||||||
|
export const maxZoomLevel = 60;
|
||||||
|
export const defaultMapPadding = 500;
|
||||||
|
|
||||||
|
export const maxZoneLength = 700;
|
||||||
|
|
||||||
|
/** How many pixels around the view is still considered "visible", beyond this and items are culled. */
|
||||||
|
export const viewCullMargin = 60;
|
||||||
|
|
||||||
|
export const tooltipHitzone = {
|
||||||
|
default: {radius:12},
|
||||||
|
junction: {width:24, height:35},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const spriteBounds = {
|
||||||
|
unknown: new SpriteBounds(0,0,20,20),
|
||||||
|
junction: new SpriteBounds(0,20,20,20),
|
||||||
|
gradeArrow: new SpriteBounds(20,20,20,20),
|
||||||
|
gradeArrowDown: new SpriteBounds(40,20,20,20),
|
||||||
|
speed_1: new SpriteBounds(20,40,20,20),
|
||||||
|
speed_2: new SpriteBounds(40,40,20,20),
|
||||||
|
speed_3: new SpriteBounds(60,40,20,20),
|
||||||
|
speed_4: new SpriteBounds(20,60,20,20),
|
||||||
|
speed_5: new SpriteBounds(40,60,20,20),
|
||||||
|
speed_6: new SpriteBounds(60,60,20,20),
|
||||||
|
speed_7: new SpriteBounds(80,60,20,20),
|
||||||
|
speed_8: new SpriteBounds(100,60,20,20),
|
||||||
|
speed_9: new SpriteBounds(120,60,20,20),
|
||||||
|
speed_10: new SpriteBounds(140,60,20,20),
|
||||||
|
speed_12: new SpriteBounds(160,60,20,20),
|
||||||
|
office: new SpriteBounds(0,80,20,20),
|
||||||
|
office_military: new SpriteBounds(20,80,20,20),
|
||||||
|
office_museum: new SpriteBounds(40,80,20,20),
|
||||||
|
water: new SpriteBounds(0,100,20,20),
|
||||||
|
coal: new SpriteBounds(20,100,20,20),
|
||||||
|
landmark: new SpriteBounds(40,100,20,20),
|
||||||
|
shop: new SpriteBounds(60,100,20,20),
|
||||||
|
garage: new SpriteBounds(80,100,20,20),
|
||||||
|
demonstrator: new SpriteBounds(100,100,20,20),
|
||||||
|
service: new SpriteBounds(0,120,20,20),
|
||||||
|
service_repair: new SpriteBounds(20,120,20,20),
|
||||||
|
service_diesel: new SpriteBounds(40,120,20,20),
|
||||||
|
service_charger: new SpriteBounds(60,120,20,20),
|
||||||
}
|
}
|
||||||
+8
-210
@@ -12,218 +12,11 @@
|
|||||||
<meta property="og:description" content="Web-based map of Derail Valley">
|
<meta property="og:description" content="Web-based map of Derail Valley">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||||
<script type="module" src="index.js"></script>
|
<script type="module" src="index.js"></script>
|
||||||
<script type="module" src="legend.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="mapContainer">
|
<div id="mapContainer">
|
||||||
<div id="mapNavigator">
|
<canvas id="mapCanvas"></canvas>
|
||||||
<svg id="map" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 10000 10000">
|
<div id="tooltip" class="panel" style="display:none"></div>
|
||||||
<style>
|
|
||||||
.fixedScale{
|
|
||||||
transform: scale(var(--markerScale));
|
|
||||||
}
|
|
||||||
.sign, .rail, .signText, .poi{
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.signText{
|
|
||||||
fill:#000;
|
|
||||||
font: 60px Arial;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.signText.gradeSign{
|
|
||||||
font-size: 30px;
|
|
||||||
stroke:#fff;
|
|
||||||
stroke-width: 6px;
|
|
||||||
paint-order: stroke fill;
|
|
||||||
}
|
|
||||||
.yardSignage{
|
|
||||||
font: 200px "Noto Sans Mono";
|
|
||||||
text-anchor: middle;
|
|
||||||
}
|
|
||||||
.rail{
|
|
||||||
fill: none;
|
|
||||||
}
|
|
||||||
.rail.grade_flat{
|
|
||||||
stroke: var(--grade_flat);
|
|
||||||
}
|
|
||||||
.rail.grade_0{
|
|
||||||
stroke: var(--grade_0);
|
|
||||||
}
|
|
||||||
.rail.grade_1{
|
|
||||||
stroke: var(--grade_1);
|
|
||||||
}
|
|
||||||
.rail.grade_2{
|
|
||||||
stroke: var(--grade_2);
|
|
||||||
}
|
|
||||||
.rail.grade_3{
|
|
||||||
stroke: var(--grade_3);
|
|
||||||
}
|
|
||||||
.rail.grade_4{
|
|
||||||
stroke: var(--grade_4);
|
|
||||||
}
|
|
||||||
.rail.grade_5{
|
|
||||||
stroke: var(--grade_5);
|
|
||||||
}
|
|
||||||
.rail.grade_6{
|
|
||||||
stroke: var(--grade_6);
|
|
||||||
}
|
|
||||||
.rail.grade_7{
|
|
||||||
stroke: var(--grade_7);
|
|
||||||
}
|
|
||||||
.rail.grade_8{
|
|
||||||
stroke: var(--grade_8);
|
|
||||||
}
|
|
||||||
.rail.grade_9{
|
|
||||||
stroke: var(--grade_9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gradeSign.grade_flat{
|
|
||||||
fill: var(--grade_flat);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_0{
|
|
||||||
fill: var(--grade_0);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_1{
|
|
||||||
fill: var(--grade_1);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_2{
|
|
||||||
fill: var(--grade_2);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_3{
|
|
||||||
fill: var(--grade_3);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_4{
|
|
||||||
fill: var(--grade_4);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_5{
|
|
||||||
fill: var(--grade_5);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_6{
|
|
||||||
fill: var(--grade_6);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_7{
|
|
||||||
fill: var(--grade_7);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_8{
|
|
||||||
fill: var(--grade_8);
|
|
||||||
}
|
|
||||||
.gradeSign.grade_9{
|
|
||||||
fill: var(--grade_9);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style id="zoomStyle"></style>
|
|
||||||
<defs>
|
|
||||||
<g id="gradeArrow" transform="scale(30)" viewBox="0 0 10 10" >
|
|
||||||
<path d="M 0 -7 L 3.8 4 L -3.8 4 z" fill="black"/>
|
|
||||||
<path d="M 0 -5 L 3 4 L 0 5 L -3 4 z"/>
|
|
||||||
</g>
|
|
||||||
<g id="gradeArrowDownhill" transform="rotate(180) scale(30)" viewBox="0 0 10 10" >
|
|
||||||
<path d="M 0 -7 L 3.8 4 L -3.8 4 z" fill="black"/>
|
|
||||||
<path d="M 0 -5 L 3 4 L 0 5 L -3 4 z"/>
|
|
||||||
<path d="M 0 -1.9 1.91 3.83 H -1.9 z" fill="black"/>
|
|
||||||
<path d="M 0 -0.3 1.5 4.3 h -3 z"/>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign" transform="scale(15)" viewBox="0 0 10 10" style="fill:#fff; stroke:#e73819">
|
|
||||||
<circle cx="0" cy="0" r="3"/>
|
|
||||||
</g>
|
|
||||||
<g id="speedSignWarning" transform="scale(15)" viewBox="0 0 10 10" style="fill:#702012; stroke:#e73819">
|
|
||||||
<circle cx="0" cy="0" r="3"/>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_1" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSignWarning"></use>
|
|
||||||
<text class="signText" style="fill:#fff;transform:translate(-15px, 20px)">1</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_2" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSignWarning"></use>
|
|
||||||
<text class="signText" style="fill:#fff;transform:translate(-15px, 20px)">2</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_3" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSignWarning"></use>
|
|
||||||
<text class="signText" style="fill:#fff;transform:translate(-15px, 20px)">3</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_4" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-15px, 20px)">4</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_5" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-16px, 20px)">5</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_6" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-15px, 20px)">6</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_7" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-15px, 20px)">7</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_8" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-16px, 20px)">8</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_9" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-15px, 20px)">9</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_10" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-35px, 20px)">10</text>
|
|
||||||
</g>
|
|
||||||
<g id="speedSign_12" transform="scale(3)" viewBox="0 0 10 10">
|
|
||||||
<use href="#speedSign"></use>
|
|
||||||
<text class="signText" style="transform:translate(-35px, 20px)">12</text>
|
|
||||||
</g>
|
|
||||||
<g id="junctionSign" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<g transform="translate(-10 -10)">
|
|
||||||
<rect ry="1.347" y="0.539" x="5.003" height="18.922" width="9.994" style="stroke:#ebebeb;stroke-width:0.9"></rect>
|
|
||||||
<rect ry="0.989" transform="rotate(22.53)" y="-3.763" x="12.079" height="18.335" width="1.979" style="fill:#ebebeb"></rect>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_office" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="M10 3.8l5.56 6.03h-1.66v5.2h-2.51v-3.93h-2.78v3.93h-2.51v-5.2h-1.66z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_water" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="M10 2c-1.02 2.01-7.08 14.38 0 14.38 7.08 0 1.02-12.46 0-14.38z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_coal" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="M10.75 2.98 7.85 4.02 5.64 7.39 5.74 7.54 7.08 7.06 10.14 9.03 10.47 8.6 13.67 7.4 14.65 8.03 14.94 7.21 13.65 4.97ZM7.07 7.6 4.18 8.64 1.96 12.01 3.49 15.33h6.78l.99-3.5-1.3-2.25zm6.61.47-2.9 1.04-.27.4.17.13 1.22 2.21-.91 3.48h5.88l.99-3.02-1.3-2.25z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_landmark" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="m11.39 1.43c-.2-.09-.42 0-.51.2L4.22 16.88c-.09.2 0 .42.2.5.2.09.42 0 .51-.2L11.59 1.93c.09-.2 0-.42-.2-.51zm.53.93-2.39 5.48c.21 0 .42 0 .62.01.2.01.41.02.61.03.2.01.4.03.6.05.2.02.39.04.59.06.19.02.39.05.58.08.19.03.38.06.57.1.09.02.18.04.28.05l2.12-2.56c-.01-.01-.02-.03-.04-.05C15.31 5.46 15.18 5.3 15.05 5.14 14.91 4.99 14.78 4.83 14.64 4.68 14.5 4.53 14.36 4.39 14.22 4.24 14.08 4.1 13.93 3.96 13.79 3.82 13.64 3.68 13.49 3.55 13.34 3.42 13.27 3.35 13.19 3.29 13.12 3.23 13.04 3.16 12.96 3.1 12.88 3.04 12.81 2.98 12.73 2.92 12.65 2.86 12.57 2.8 12.49 2.74 12.41 2.69 12.33 2.63 12.25 2.57 12.16 2.52 12.08 2.47 12 2.41 11.92 2.36Zm3.37 4.06-2.12 2.56c.1.02.19.04.29.06.19.04.37.08.55.13.18.04.37.09.55.14.18.05.36.1.54.15.18.05.36.1.53.16.18.05.35.11.53.17.18.06.35.12.53.17.17.06.35.12.52.18.35.12.69.25 1.04.37C18 10.15 17.76 9.79 17.51 9.44 17.27 9.09 17.02 8.74 16.78 8.39 16.65 8.22 16.53 8.05 16.4 7.88 16.28 7.7 16.15 7.53 16.02 7.36 15.9 7.2 15.77 7.03 15.64 6.86 15.53 6.71 15.41 6.57 15.29 6.42Z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_shop" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="M9.25 17.9V16.35C8.29 16.26 7.75 15.91 7.12 15.31 6.49 14.71 6.14 13.86 6.06 12.75l2.2-.49c.03.65.21 1.14.54 1.49.33.35.75.52 1.24.52.47 0 .81-.13 1.03-.4.23-.27.34-.55.34-.85 0-.39-.11-.71-.34-.94-.23-.24-.52-.46-.88-.65L8.66 10.62C7.91 10.23 7.33 9.75 6.9 9.2 6.48 8.65 6.27 7.92 6.27 7.02 6.27 6.37 6.41 5.8 6.68 5.31 6.97 4.8 7.35 4.4 7.83 4.1 8.32 3.8 8.63 3.61 9.25 3.54V2.1h1.65v1.48c.91.12 1.41.49 1.94 1.1.53.6.82 1.39.88 2.36L11.65 7.47C11.62 6.87 11.45 6.41 11.15 6.08 10.86 5.75 10.5 5.58 10.07 5.58 9.66 5.58 9.33 5.7 9.08 5.94 8.84 6.17 8.72 6.48 8.72 6.88c0 .36.11.65.32.86.21.21.51.42.88.63l1.63.86c.83.45 1.43.95 1.82 1.51.39.55.58 1.23.58 2.02 0 .6-.13 1.16-.4 1.67-.25.51-.63.95-1.12 1.3-.48.33-.84.54-1.53.63v1.4z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_garage" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="M10 2.88 2.98 6.42 2.98 15.1 5.53 15.1 5.53 8.91 14.47 8.91 14.47 15.1 17.02 15.1 17.02 6.42 10 2.88z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_service" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="m8.92 1.99q3.29 0 4.68 1.13 1.39 1.1 1.39 2.74 0 2.06-1.78 3.36-.67.5-1.63.91l-.38.17q-.17.07-.34 1.01-.14.91-.14 1.32-.12.12-.7.29-.55.14-.94.14-.36 0-.55-.05-.26-.43-.26-1.87 0-1.44.12-1.85 3.79-.91 3.79-3.07 0-1.87-3.46-1.87-1.22 0-1.78.24-.14-.24-.14-1.01 0-.77.22-1.3.65-.29 1.9-.29zm-.7 15.5q-.46-.48-.46-1.15 0-.67.46-1.13.48-.48 1.15-.48.67 0 1.13.48.48.46.48 1.13 0 .67-.48 1.15-.46.46-1.13.46-.67 0-1.15-.46z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_service_repair" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="m12.88 2.82c-.1.01-.2.05-.28.13l-2.19 2.19c-.15.16-.17.39-.03.53l1.12 1.12c.29-.29.37.07.57.58l-1.61 1.6 1.77 1.72 1.7-1.7c.44.03.82-.06.99.11.22.22.19.59-.06.85l-.02.02c1.48 1.26 3.85-1.11 2.59-2.59l-.02.02c-.25.25-.63.28-.85.06-.3-.3.23-1.31-.61-2.15l-.1-.1c-.73-.74-2.07-.7-1.6-1.18l-1.12-1.12c-.06-.06-.16-.09-.25-.09zM5.63 3.68c-.28 0-.55.05-.83.14l2.02 2.02-1.85 1.86-2.02-2.02c-.72 2.23 1.45 4.34 3.67 3.55l7.27 7.27c.46.47 1.22.47 1.71-.02.49-.49.5-1.25.03-1.72L8.36 7.49c.69-1.94-.84-3.84-2.73-3.81zm2.41 7.72-3.36 3.35c-.47.47-.47 1.23.02 1.72.49.49 1.25.49 1.72.02l3.38-3.38z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_service_diesel" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="m12.67 2.93c-.5-.01-1 .09-1.46.31L9.86 3.88 9.76 3.66 7.64 4.67 7.18 4.02C7.09 3.89 6.92 3.86 6.79 3.95L5.55 4.8C5.43 4.89 5.4 5.07 5.48 5.2L5.87 5.75 5.51 6.22 2.7 10.29c-.2.3-.18.7.06.97-.4.74-.49 1.54-.3 2.26.22.86.77 1.6 1.5 2.16 1.46 1.12 3.68 1.56 5.63.5 1.07-.59 2.19-.79 2.99-.64.8.14 1.26.52 1.39 1.32.05.33.36.55.69.5.33-.05.55-.36.5-.69-.2-1.27-1.2-2.1-2.36-2.31-1.16-.21-2.51.08-3.78.77C7.53 15.95 5.8 15.6 4.69 14.74 4.14 14.32 3.76 13.77 3.62 13.23 3.52 12.83 3.53 12.42 3.73 11.99l1.39.96c.81.56 1.93.36 2.49-.46L10.41 8.46 9.88 5.6 10.53 5.29 10.42 5.05 11.76 4.42C12.2 4.21 12.7 4.17 13.17 4.32L16.71 5.44 17.1 4.2 13.56 3.08C13.27 2.99 12.97 2.94 12.67 2.93Zm4.24 3.31c-.39.63-2.7 4.48 0 4.48 2.7 0 .39-3.88 0-4.48zM6.91 7.47 8.22 7.92 7.2 8.58c-.04.03-.08.06-.11.11l-1.55 2.46c-.1.16-.05.38.11.48.16.1.38.05.48-.11L7.64 9.12 8.94 8.29c.24.29.25.71.02 1.03L7.44 11.52C6.92 12.27 5.93 12.48 5.22 11.99L4.36 11.4Z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
<g id="mrk_service_charger" transform="scale(20)" viewBox="0 0 20 20">
|
|
||||||
<circle r="10"></circle>
|
|
||||||
<path transform="translate(-10 -10)" d="m7.96 2.6h4.56l-1.97 5.8h3.02L8.61 18.36 9.6 10.25H7.26Z" fill="#fff"></path>
|
|
||||||
</g>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
<svg id="mapMarkers" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 10000 10000">
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="stats" class="orange">
|
<div id="stats" class="orange">
|
||||||
@@ -254,7 +47,8 @@
|
|||||||
<hr style="margin: 5px 0;">
|
<hr style="margin: 5px 0;">
|
||||||
Hover over tracks and objects for detailed information.
|
Hover over tracks and objects for detailed information.
|
||||||
<hr style="margin: 5px 0;">
|
<hr style="margin: 5px 0;">
|
||||||
Last Updated: <span id="lastUpdate"></span>
|
Last update <span id="lastUpdate"></span>:
|
||||||
|
<div id="changelog"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<h3>Key</h3>
|
<h3>Key</h3>
|
||||||
@@ -277,5 +71,9 @@
|
|||||||
<button id="legendButton" class="panel orange"><svg style="transform:rotate(180deg) translateY(0px)" viewBox="0 0 32 32"><path fill="currentColor" d="M31 16 20 31l-16 0L15 16 4 1l16 0Z"/></svg></button>
|
<button id="legendButton" class="panel orange"><svg style="transform:rotate(180deg) translateY(0px)" viewBox="0 0 32 32"><path fill="currentColor" d="M31 16 20 31l-16 0L15 16 4 1l16 0Z"/></svg></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="display:none">
|
||||||
|
<img id="mapSprites" src="mapSprites.svg">
|
||||||
|
<img id="mapTerrain" src="">
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import * as Vector from './vectorlib.js';
|
import * as Vector from './vectorlib.js';
|
||||||
|
import * as Utils from './utillib.js';
|
||||||
/** A 3D vector
|
/** A 3D vector
|
||||||
* @typedef {Object} Vector
|
* @typedef {Object} Vector
|
||||||
* @property {number} x
|
* @property {number} x
|
||||||
@@ -138,4 +139,53 @@ export function evaluateAcceleration(p1, h1, h2, p2, t){
|
|||||||
result[axis] = p1[axis]*p1v + h1[axis]*h1v + h2[axis]*h2v + p2[axis]*p2v;
|
result[axis] = p1[axis]*p1v + h1[axis]*h1v + h2[axis]*h2v + p2[axis]*p2v;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the min and max bounds of a bezier.
|
||||||
|
* @param {Vector} p1
|
||||||
|
* @param {Vector} h1
|
||||||
|
* @param {Vector} h2
|
||||||
|
* @param {Vector} p2
|
||||||
|
*/
|
||||||
|
export function getBounds(p1, h1, h2, p2){
|
||||||
|
// TODO: replace this with a not brute-forced version.
|
||||||
|
let pos;
|
||||||
|
let min = {x:Infinity, y:Infinity, z:Infinity};
|
||||||
|
let max = {x:-Infinity, y:-Infinity, z:-Infinity};
|
||||||
|
for(let i=0; i<=40; i++){
|
||||||
|
pos = evaluatePoint(p1, h1, h2, p2, i/40);
|
||||||
|
min.x = Math.min(pos.x, min.x);
|
||||||
|
max.x = Math.max(pos.x, max.x);
|
||||||
|
min.y = Math.min(pos.y, min.y);
|
||||||
|
max.y = Math.max(pos.y, max.y);
|
||||||
|
min.z = Math.min(pos.z, min.z);
|
||||||
|
max.z = Math.max(pos.z, max.z);
|
||||||
|
}
|
||||||
|
return {min:min, max:max};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the closest point on the curve to `testPoint` in 2D space, as well as the distance.
|
||||||
|
* (This means using the (x,z) coordinates of the bezier as (x,y))
|
||||||
|
* @param {Vector} p1
|
||||||
|
* @param {Vector} h1
|
||||||
|
* @param {Vector} h2
|
||||||
|
* @param {Vector} p2
|
||||||
|
* @param {*} testPoint
|
||||||
|
*/
|
||||||
|
export function getNearestPoint2D(p1, h1, h2, p2, testPoint, iterationCount = 200){
|
||||||
|
// TODO: replace this with a more accurate version
|
||||||
|
let minDistance = Infinity;
|
||||||
|
let bezEval;
|
||||||
|
let evalDist;
|
||||||
|
let closestPoint = {x:0, y:0};
|
||||||
|
for(let i=0; i<=iterationCount; i++){
|
||||||
|
bezEval = evaluatePoint(p1, h1, h2, p2, i/iterationCount);
|
||||||
|
evalDist = Math.pow(testPoint.x-bezEval.x, 2) + Math.pow(testPoint.y-bezEval.z, 2);
|
||||||
|
if(evalDist < minDistance){
|
||||||
|
minDistance = evalDist;
|
||||||
|
closestPoint.x = bezEval.x;
|
||||||
|
closestPoint.y = bezEval.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {point:closestPoint, distance:Math.sqrt(minDistance)};
|
||||||
}
|
}
|
||||||
+573
@@ -0,0 +1,573 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as Vector from './vectorlib.js';
|
||||||
|
import * as Bezier from './bezierlib.js';
|
||||||
|
import * as Utils from './utillib.js';
|
||||||
|
import {Color} from './colorlib.js';
|
||||||
|
import * as Config from './../config.js';
|
||||||
|
|
||||||
|
export let railTracks = [];
|
||||||
|
export let markers = [];
|
||||||
|
|
||||||
|
let visibleMarkers = [];
|
||||||
|
|
||||||
|
let uniqueTrackNames = {};
|
||||||
|
|
||||||
|
export let testPoint = {x:0,y:0};
|
||||||
|
|
||||||
|
export let matrix = {
|
||||||
|
initialize: () => {
|
||||||
|
matrix.minX = Infinity;
|
||||||
|
matrix.minY = Infinity;
|
||||||
|
matrix.minAlt = Infinity;
|
||||||
|
matrix.maxX = -Infinity;
|
||||||
|
matrix.maxY = -Infinity;
|
||||||
|
matrix.maxAlt = -Infinity;
|
||||||
|
|
||||||
|
for(const railTrack of railTracks){
|
||||||
|
for(const curve of railTrack.curves){
|
||||||
|
matrix.minX = Math.min(matrix.minX, curve.start.x, curve.h1.x, curve.h2.x, curve.end.x);
|
||||||
|
matrix.minY = Math.min(matrix.minY, curve.start.z, curve.h1.z, curve.h2.z, curve.end.z);
|
||||||
|
matrix.minAlt = Math.min(matrix.minAlt, curve.start.y, curve.h1.y, curve.h2.y, curve.end.y);
|
||||||
|
matrix.maxX = Math.max(matrix.maxX, curve.start.x, curve.h1.x, curve.h2.x, curve.end.x);
|
||||||
|
matrix.maxY = Math.max(matrix.maxY, curve.start.z, curve.h1.z, curve.h2.z, curve.end.z);
|
||||||
|
matrix.maxAlt = Math.max(matrix.maxAlt, curve.start.y, curve.h1.y, curve.h2.y, curve.end.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matrix.width = matrix.maxX-matrix.minX;
|
||||||
|
matrix.height = matrix.maxY-matrix.minY;
|
||||||
|
|
||||||
|
console.log(`(${matrix.minX}, ${matrix.minY}) to (${matrix.maxX}, ${matrix.maxY}). Altitude from ${matrix.minAlt} to ${matrix.maxAlt}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export let view = {
|
||||||
|
initialize: () => {
|
||||||
|
const mapContainer = document.getElementById('mapContainer');
|
||||||
|
let isLandscape = mapContainer.clientWidth > mapContainer.clientHeight;
|
||||||
|
view.scale = Math.min(mapContainer.clientWidth/(matrix.width + Config.defaultMapPadding*2), mapContainer.clientHeight/(matrix.height + Config.defaultMapPadding*2));
|
||||||
|
if(isLandscape){
|
||||||
|
view.x = mapContainer.clientWidth*0.6 - (matrix.width * 0.5 + matrix.minX)*view.scale;
|
||||||
|
view.y = (matrix.minY - Config.defaultMapPadding) * view.scale;
|
||||||
|
}else{
|
||||||
|
view.x = -(matrix.minX - Config.defaultMapPadding) * view.scale;
|
||||||
|
view.y = -(mapContainer.clientHeight*0.5 - (matrix.height * 0.5 + matrix.minY)*view.scale);
|
||||||
|
}
|
||||||
|
view.dirty = false;
|
||||||
|
|
||||||
|
view.convertX = x => {
|
||||||
|
return x * view.scale + view.x;
|
||||||
|
}
|
||||||
|
view.convertY = y => {
|
||||||
|
return (matrix.minY+matrix.maxY-y) * view.scale - view.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
view.unconvertX = x => {
|
||||||
|
return (x - view.x) / view.scale;
|
||||||
|
}
|
||||||
|
view.unconvertY = y => {
|
||||||
|
return -((y + view.y) / view.scale - (matrix.minY + matrix.maxY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let layers = {};
|
||||||
|
|
||||||
|
export function reset(){
|
||||||
|
railTracks = [];
|
||||||
|
markers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortTracks(){
|
||||||
|
railTracks.sort((a,b) => {
|
||||||
|
if(a.curves && b.curves)
|
||||||
|
return a.curves[0].start.y-b.curves[b.curves.length-1].end.y;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortMarkers(){
|
||||||
|
markers.sort((a,b) => {
|
||||||
|
if(a.type == b.type){
|
||||||
|
switch(a.type){
|
||||||
|
case 'speed':
|
||||||
|
return b.value-a.value;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(a.type == 'station') return 1;
|
||||||
|
if(b.type == 'station') return -1;
|
||||||
|
if(a.type == 'speed') return 1;
|
||||||
|
if(b.type == 'speed') return -1;
|
||||||
|
if(a.type == 'junction') return 1;
|
||||||
|
if(b.type == 'junction') return -1;
|
||||||
|
if(a.type == 'service') return 1;
|
||||||
|
if(b.type == 'service') return -1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function filterToTrack(trackName, trackNum = 0){
|
||||||
|
if(typeof(trackName) == 'string'){
|
||||||
|
for(let railTrack of railTracks){
|
||||||
|
if(railTrack.name == trackName && railTrack.number == trackNum){
|
||||||
|
railTracks = [railTrack];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(typeof(trackName) == 'object'){
|
||||||
|
let newRailTracks = [];
|
||||||
|
for(let railTrack of railTracks){
|
||||||
|
for(let filter of trackName){
|
||||||
|
if(railTrack.name == filter.name && railTrack.number == (filter.number ?? 0)){
|
||||||
|
newRailTracks.push(railTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
railTracks = newRailTracks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addTrack(trackData){
|
||||||
|
let newTrack = {
|
||||||
|
name: trackData.name,
|
||||||
|
curves: [],
|
||||||
|
bounds: {min:{x:Infinity,y:Infinity,z:Infinity},max:{x:-Infinity,y:-Infinity,z:-Infinity}},
|
||||||
|
};
|
||||||
|
if(uniqueTrackNames[trackData.name] == null){
|
||||||
|
uniqueTrackNames[trackData.name] = 0;
|
||||||
|
}else{
|
||||||
|
uniqueTrackNames[trackData.name]++;
|
||||||
|
}
|
||||||
|
newTrack.number = uniqueTrackNames[trackData.name];
|
||||||
|
|
||||||
|
let yardData = /\[(#)\]|\[(Y)\][_-]\[(.*?)\][_-]\[((.*?)[_-](.*?)[_-](.*?)|.*)\]/.exec(trackData.name);
|
||||||
|
if(yardData){
|
||||||
|
if(yardData[1]){ // track is [#], thus in yard limits, but not a specific designated yard.
|
||||||
|
newTrack.isYard = true;
|
||||||
|
}else if(yardData[2]){ // track is [Y], and is a specific yard.
|
||||||
|
newTrack.isYard = true;
|
||||||
|
newTrack.yardStation = yardData[3]; // Which station the track belongs to
|
||||||
|
newTrack.yardDesignation = yardData[4]; // Full yard designation, used on signs
|
||||||
|
newTrack.yardName = yardData[5]; // A yard, B yard, C yard, etc.
|
||||||
|
newTrack.yardSidingNumber = yardData[6]; // Which siding within the yard
|
||||||
|
newTrack.yardUsage = yardData[7]; // Outbound? Parking? Inbound? Loading? That's this.
|
||||||
|
}
|
||||||
|
}else if(/Turntable Track/.test(newTrack.name)){
|
||||||
|
newTrack.isTurntable = true;
|
||||||
|
}else if(/\[track (diverging|through)\]/.test(newTrack.name)){
|
||||||
|
newTrack.isJunction = true;
|
||||||
|
}
|
||||||
|
newTrack.randomColor = Color.random();
|
||||||
|
|
||||||
|
for(let i=0; i+1<trackData.points.length; i++){
|
||||||
|
const curveStart = trackData.points[i].position;
|
||||||
|
const curveHandle1 = trackData.points[i].h2;
|
||||||
|
const curveHandle2 = trackData.points[i+1].h1;
|
||||||
|
const curveEnd = trackData.points[i+1].position;
|
||||||
|
|
||||||
|
newTrack.curves[i] = {
|
||||||
|
start: curveStart,
|
||||||
|
h1: curveHandle1,
|
||||||
|
h2: curveHandle2,
|
||||||
|
end: curveEnd,
|
||||||
|
grade: Bezier.estimateGrade(curveStart, curveHandle1, curveHandle2, curveEnd, Config.bezierGradeResolution),
|
||||||
|
length: Bezier.estimateLength(curveStart, curveHandle1, curveHandle2, curveEnd, Config.bezierLengthResolution),
|
||||||
|
curvature: Bezier.estimateCurvature(curveStart, curveHandle1, curveHandle2, curveEnd, Config.bezierCurvatureResolution),
|
||||||
|
randomColor: Color.random(),
|
||||||
|
color: '#fff',
|
||||||
|
averageHeight: (curveStart.y+curveEnd.y) * 0.5,
|
||||||
|
bounds: Bezier.getBounds(curveStart, curveHandle1, curveHandle2, curveEnd),
|
||||||
|
}
|
||||||
|
newTrack.curves[i].gradeClass = Utils.gradeToClass(newTrack.curves[i].grade);
|
||||||
|
newTrack.curves[i].postedSpeed = Utils.radiusToSpeed(1/newTrack.curves[i].curvature);
|
||||||
|
if(newTrack.isYard || newTrack.isTurntable) newTrack.curves[i].postedSpeed = Math.min(newTrack.curves[i].postedSpeed, 50);
|
||||||
|
|
||||||
|
newTrack.curves[i].tooltip = [
|
||||||
|
`<h2>Rail</h2>"${trackData.name}"${uniqueTrackNames[trackData.name] > 0 ? ' #'+uniqueTrackNames[trackData.name] : ''} Sec${i}`,
|
||||||
|
`Max Grade: ${Math.round(newTrack.curves[i].grade*1000)/10}%`,
|
||||||
|
`Min Radius: ${Math.round(1/newTrack.curves[i].curvature)} meters`,
|
||||||
|
`Top Speed: ${Utils.radiusToSpeed(1/newTrack.curves[i].curvature)} km/h`,
|
||||||
|
`Length: ${Math.round(newTrack.curves[i].length*10)/10} meters`,
|
||||||
|
`Altitude (ASL): ${Math.round(newTrack.curves[i].averageHeight)-110} meters`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
newTrack.bounds.min.x = Math.min(newTrack.bounds.min.x, newTrack.curves[i].bounds.min.x);
|
||||||
|
newTrack.bounds.max.x = Math.max(newTrack.bounds.max.x, newTrack.curves[i].bounds.max.x);
|
||||||
|
newTrack.bounds.min.y = Math.min(newTrack.bounds.min.y, newTrack.curves[i].bounds.min.y);
|
||||||
|
newTrack.bounds.max.y = Math.max(newTrack.bounds.max.y, newTrack.curves[i].bounds.max.y);
|
||||||
|
newTrack.bounds.min.z = Math.min(newTrack.bounds.min.z, newTrack.curves[i].bounds.min.z);
|
||||||
|
newTrack.bounds.max.z = Math.max(newTrack.bounds.max.z, newTrack.curves[i].bounds.max.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
railTracks.push(newTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addJunction(junctionData){
|
||||||
|
if(junctionData.name.startsWith('S-') || junctionData.excludeFromJunctionMap)
|
||||||
|
junctionData.minZoom = 1;
|
||||||
|
else if(junctionData.name.startsWith('W-'))
|
||||||
|
junctionData.minZoom = 0.05;
|
||||||
|
junctionData.tooltip = `<h2>Junction</h2>"${junctionData.name}" - #${junctionData.index}\n${junctionData.excludeFromJunctionMap ? 'Inv' : 'V'}isible On Map\nLinked Junctions:\n- ${junctionData.linkedJunctions.join('\n- ')}`;
|
||||||
|
junctionData.tooltipHitzone = Config.tooltipHitzone.junction;
|
||||||
|
markers.push(junctionData);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addPoi(poiData, level = 0){
|
||||||
|
let newPoi = {
|
||||||
|
type: poiData.type,
|
||||||
|
name: poiData.name,
|
||||||
|
color: poiData.color,
|
||||||
|
position: poiData.position,
|
||||||
|
};
|
||||||
|
if(level > 0) newPoi.minZoom = 0.3;
|
||||||
|
|
||||||
|
switch(poiData.type){
|
||||||
|
case 'service':
|
||||||
|
newPoi.serviceTypes = [];
|
||||||
|
if(poiData.repair) newPoi.serviceTypes.push('Repair');
|
||||||
|
if(poiData.diesel) newPoi.serviceTypes.push('Diesel');
|
||||||
|
if(poiData.charger) newPoi.serviceTypes.push('Charger');
|
||||||
|
if(newPoi.serviceTypes.length == 0){
|
||||||
|
newPoi.tooltip = '<h1>Service</h1><hr>?';
|
||||||
|
}else{
|
||||||
|
newPoi.tooltip = '<h1>Service</h1><hr>- '+newPoi.serviceTypes.join('\n- ');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'station':
|
||||||
|
newPoi.maxZoom = 1;
|
||||||
|
newPoi.nickname = poiData.nickname;
|
||||||
|
newPoi.shorthand = poiData.shorthand;
|
||||||
|
newPoi.color = poiData.color;
|
||||||
|
newPoi.tooltip = `<h1>${poiData.name}</h1>`;
|
||||||
|
break;
|
||||||
|
case 'shop':
|
||||||
|
newPoi.tooltip = `<h1>Shop</h1>${poiData.stock ? '<hr>'+poiData.stock.sort().join('\n') : ''}`;
|
||||||
|
break;
|
||||||
|
case 'water':
|
||||||
|
newPoi.tooltip = '<h1>Water Tower</h1>';
|
||||||
|
break;
|
||||||
|
case 'coal':
|
||||||
|
newPoi.tooltip = '<h1>Coal Tower</h1>';
|
||||||
|
break;
|
||||||
|
case 'office':
|
||||||
|
if(poiData.museum) newPoi.tooltip = '<h1>Museum Office</h1>';
|
||||||
|
else if(poiData.military) newPoi.tooltip = '<h1>Military Office</h1>';
|
||||||
|
else newPoi.tooltip = '<h1>Office</h1>';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newPoi.tooltip = `<h1>${newPoi.name}</h1>${poiData.description ? '<hr>'+poiData.description : ''}`;
|
||||||
|
newPoi.minZoom = 0.07;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
markers.push(newPoi);
|
||||||
|
if(poiData.children){
|
||||||
|
for(let child of poiData.children){
|
||||||
|
addPoi(child, level+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateTrackSignage(){
|
||||||
|
let yardMarkers = {};
|
||||||
|
for(const railTrack of railTracks){
|
||||||
|
let trackZoneData = {};
|
||||||
|
let lastCurve = false;
|
||||||
|
|
||||||
|
let resetTzdGrade = (i=0) => {
|
||||||
|
trackZoneData.gradeClass = railTrack.curves[i].gradeClass;
|
||||||
|
trackZoneData.gradeDirection = Math.sign(railTrack.curves[i].grade);
|
||||||
|
trackZoneData.gradeZoneStart = i;
|
||||||
|
trackZoneData.gradeZoneLength = 0;
|
||||||
|
};
|
||||||
|
let resetTzdSpeed = (i=0) => {
|
||||||
|
trackZoneData.postedSpeed = railTrack.curves[i].postedSpeed;
|
||||||
|
trackZoneData.speedZoneStart = i;
|
||||||
|
trackZoneData.speedZoneLength = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
resetTzdGrade();
|
||||||
|
resetTzdSpeed();
|
||||||
|
|
||||||
|
for(let i=0; i<railTrack.curves.length; i++){
|
||||||
|
let nextIndex = i+1;
|
||||||
|
if(nextIndex == railTrack.curves.length){
|
||||||
|
lastCurve = true;
|
||||||
|
nextIndex = i;
|
||||||
|
}
|
||||||
|
//Grade Markers
|
||||||
|
trackZoneData.gradeZoneLength += railTrack.curves[i].length;
|
||||||
|
if(railTrack.curves[nextIndex].gradeClass != trackZoneData.gradeClass
|
||||||
|
|| Math.sign(railTrack.curves[nextIndex].grade) != trackZoneData.gradeDirection
|
||||||
|
|| trackZoneData.gradeZoneLength > Config.maxZoneLength
|
||||||
|
|| lastCurve){
|
||||||
|
if(railTrack.curves[i].gradeClass != 'flat'){
|
||||||
|
let markerIndex = Math.ceil((trackZoneData.gradeZoneStart + i)/2);
|
||||||
|
let markerOffset = (trackZoneData.gradeZoneStart + i) % 2 ? 0.1 : 0.6;
|
||||||
|
let b1 = railTrack.curves[markerIndex].start;
|
||||||
|
let b2 = railTrack.curves[markerIndex].h1;
|
||||||
|
let b3 = railTrack.curves[markerIndex].h2;
|
||||||
|
let b4 = railTrack.curves[markerIndex].end;
|
||||||
|
|
||||||
|
let newMarker = {
|
||||||
|
type: 'grade',
|
||||||
|
value: railTrack.curves[markerIndex].grade,
|
||||||
|
position: Bezier.evaluatePoint(b1, b2, b3, b4, markerOffset),
|
||||||
|
gradeClass: railTrack.curves[markerIndex].gradeClass,
|
||||||
|
minZoom: Math.max(0.02, Math.min(1.0, 20/trackZoneData.gradeZoneLength)),
|
||||||
|
zoneLength: trackZoneData.gradeZoneLength,
|
||||||
|
zoneCount: i - trackZoneData.gradeZoneStart + 1,
|
||||||
|
tooltipHitzone: {radius:16},
|
||||||
|
}
|
||||||
|
let tangent = newMarker.value > 0
|
||||||
|
? Bezier.evaluateVelocity(b1, b2, b3, b4, markerOffset)
|
||||||
|
: Bezier.evaluateVelocity(b4, b3, b2, b1, markerOffset);
|
||||||
|
let tangentLength = Math.sqrt(tangent.x * tangent.x + tangent.z * tangent.z) * Math.sign(tangent.y);
|
||||||
|
newMarker.rotation = Math.atan2(tangent.x/tangentLength, tangent.z/tangentLength);
|
||||||
|
newMarker.tooltip = `<h2>Grade</h2>${Math.round(newMarker.value*1000)/10}% Grade\nUphill bearing ${Utils.mod(newMarker.rotation/(Math.PI*2)*360, 360).toFixed(0)}, ${Utils.angleToCardinalDirection(newMarker.rotation)}\nSection Length: ${newMarker.zoneLength.toFixed(1)} meters\nCovers ${newMarker.zoneCount} track sections`;
|
||||||
|
markers.push(newMarker);
|
||||||
|
}
|
||||||
|
resetTzdGrade(nextIndex);
|
||||||
|
}
|
||||||
|
//Speed Markers
|
||||||
|
trackZoneData.speedZoneLength += railTrack.curves[i].length;
|
||||||
|
if(railTrack.curves[nextIndex].postedSpeed != trackZoneData.postedSpeed
|
||||||
|
|| trackZoneData.speedZoneLength > Config.maxZoneLength
|
||||||
|
|| lastCurve){
|
||||||
|
let markerIndex = Math.ceil((trackZoneData.speedZoneStart + i)/2);
|
||||||
|
let markerOffset = (trackZoneData.speedZoneStart + i) % 2 ? 0.2 : 0.7;
|
||||||
|
let b1 = railTrack.curves[markerIndex].start;
|
||||||
|
let b2 = railTrack.curves[markerIndex].h1;
|
||||||
|
let b3 = railTrack.curves[markerIndex].h2;
|
||||||
|
let b4 = railTrack.curves[markerIndex].end;
|
||||||
|
|
||||||
|
let newMarker = {
|
||||||
|
type: 'speed',
|
||||||
|
value: railTrack.curves[markerIndex].postedSpeed,
|
||||||
|
position: Bezier.evaluatePoint(b1, b2, b3, b4, markerOffset),
|
||||||
|
zoneLength: trackZoneData.speedZoneLength,
|
||||||
|
zoneCount: i - trackZoneData.speedZoneStart + 1,
|
||||||
|
minZoom: 0.05,
|
||||||
|
}
|
||||||
|
if((railTrack.isYard || railTrack.isJunction) && newMarker.value > 30){
|
||||||
|
if(newMarker.value > 40) newMarker.minZoom = 5;
|
||||||
|
else newMarker.minZoom = 0.5;
|
||||||
|
}
|
||||||
|
if(newMarker.value > 80) newMarker.minZoom *= 6.5;
|
||||||
|
else if(newMarker.value > 60) newMarker.minZoom *= 5;
|
||||||
|
else if(newMarker.value > 40) newMarker.minZoom *= 3;
|
||||||
|
|
||||||
|
if(newMarker.zoneLength > 500) newMarker.minZoom *= 0.15;
|
||||||
|
|
||||||
|
if(newMarker.zoneLength < 35 && newMarker.value > 40) newMarker.minZoom *= 6;
|
||||||
|
|
||||||
|
newMarker.tooltip = `<h2>Speed</h2>${Math.round(newMarker.value)} km/h\nSection Length: ${newMarker.zoneLength.toFixed(1)} meters\nCovers ${newMarker.zoneCount} track sections`;
|
||||||
|
markers.push(newMarker);
|
||||||
|
resetTzdSpeed(nextIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(railTrack.yardDesignation && railTrack.yardDesignation != '--'){
|
||||||
|
if(!yardMarkers[railTrack.yardStation]) yardMarkers[railTrack.yardStation] = {};
|
||||||
|
let centerIndex = Math.floor(railTrack.curves.length/2);
|
||||||
|
let yardSignPos = railTrack.curves[centerIndex].start;
|
||||||
|
if(railTrack.curves.length % 2 == 1){
|
||||||
|
let curve = railTrack.curves[centerIndex];
|
||||||
|
yardSignPos = Bezier.evaluatePoint(curve.start, curve.h1, curve.h2, curve.end, 0.5);
|
||||||
|
}
|
||||||
|
if(railTrack.yardName){
|
||||||
|
if(!yardMarkers[railTrack.yardStation][railTrack.yardName])
|
||||||
|
yardMarkers[railTrack.yardStation][railTrack.yardName] = {accCenter:{x:0,y:0,z:0},accCount:0};
|
||||||
|
yardMarkers[railTrack.yardStation][railTrack.yardName].accCenter.x += yardSignPos.x;
|
||||||
|
yardMarkers[railTrack.yardStation][railTrack.yardName].accCenter.y += yardSignPos.y;
|
||||||
|
yardMarkers[railTrack.yardStation][railTrack.yardName].accCenter.z += yardSignPos.z;
|
||||||
|
yardMarkers[railTrack.yardStation][railTrack.yardName].accCount++;
|
||||||
|
}
|
||||||
|
let newMarker = {
|
||||||
|
type: 'yardSiding',
|
||||||
|
name: railTrack.yardDesignation,
|
||||||
|
position: yardSignPos,
|
||||||
|
minZoom: 2.5,
|
||||||
|
};
|
||||||
|
if(railTrack.yardName && railTrack.yardSidingNumber && railTrack.yardUsage){
|
||||||
|
if(!Config.sidingUsageMeanings[railTrack.yardUsage]) console.log(`Unknown siding usage for ${railTrack.yardDesignation} at ${railTrack.yardStation}`);
|
||||||
|
newMarker.tooltip = `<h2>Siding</h2>${railTrack.yardDesignation}\n${Config.sidingUsageMeanings[railTrack.yardUsage]}`;
|
||||||
|
}else{
|
||||||
|
newMarker.tooltip = `<h2>Siding</h2>${railTrack.yardDesignation}`;
|
||||||
|
}
|
||||||
|
markers.push(newMarker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let station in yardMarkers){
|
||||||
|
for(let yard in yardMarkers[station]){
|
||||||
|
markers.push({
|
||||||
|
type: 'yard',
|
||||||
|
name: `${yard} Yard`,
|
||||||
|
position: {
|
||||||
|
x: yardMarkers[station][yard].accCenter.x/yardMarkers[station][yard].accCount,
|
||||||
|
y: yardMarkers[station][yard].accCenter.y/yardMarkers[station][yard].accCount,
|
||||||
|
z: yardMarkers[station][yard].accCenter.z/yardMarkers[station][yard].accCount,
|
||||||
|
},
|
||||||
|
tooltip: `<h1>${yard} Yard</h1>`,
|
||||||
|
maxZoom: 2.5,
|
||||||
|
minZoom: 0.25,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the relevant tooltip for where the cursor is (if possible)
|
||||||
|
* Returns "" if there is none.
|
||||||
|
* @param {Number} cursorX
|
||||||
|
* @param {Number} cursorY
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
export function testTooltip(cursorX, cursorY){
|
||||||
|
cursorX = view.unconvertX(cursorX);
|
||||||
|
cursorY = view.unconvertY(cursorY);
|
||||||
|
|
||||||
|
let finalTooltip = '';
|
||||||
|
let radius = 0;
|
||||||
|
let width = 0;
|
||||||
|
let height = 0;
|
||||||
|
for(const marker of markers){
|
||||||
|
if(!marker.visible) continue;
|
||||||
|
if(marker.boundsCheck != null){
|
||||||
|
if(marker.boundsCheck(cursorX, cursorY))
|
||||||
|
finalTooltip = marker.tooltip ?? finalTooltip;
|
||||||
|
}else if(marker.tooltipHitzone && marker.tooltipHitzone.width && marker.tooltipHitzone.height){
|
||||||
|
width = marker.tooltipHitzone.width * 0.5/view.scale;
|
||||||
|
height = marker.tooltipHitzone.height * 0.5/view.scale;
|
||||||
|
if( marker.position.x - cursorX + (marker.tooltipHitzone.offsetX ?? 0)/view.scale <= width
|
||||||
|
&& marker.position.x - cursorX + (marker.tooltipHitzone.offsetX ?? 0)/view.scale >= -width
|
||||||
|
&& marker.position.z - cursorY + (marker.tooltipHitzone.offsetY ?? 0)/view.scale <= height
|
||||||
|
&& marker.position.z - cursorY + (marker.tooltipHitzone.offsetY ?? 0)/view.scale >= -height){
|
||||||
|
finalTooltip = marker.tooltip ?? finalTooltip;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(marker.tooltipHitzone)
|
||||||
|
radius = (marker.tooltipHitzone.radius ?? Config.tooltipHitzone.default.radius) / view.scale;
|
||||||
|
else
|
||||||
|
radius = Config.tooltipHitzone.default.radius / view.scale;
|
||||||
|
if(Math.pow(marker.position.x - cursorX, 2) + Math.pow(marker.position.z - cursorY, 2) <= radius * radius){
|
||||||
|
finalTooltip = marker.tooltip ?? finalTooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(finalTooltip != '') return finalTooltip;
|
||||||
|
|
||||||
|
let bestDistance = Infinity;
|
||||||
|
let test = {};
|
||||||
|
let boundsPadding = 40/view.scale;
|
||||||
|
for(const railTrack of railTracks){
|
||||||
|
if(cursorX >= railTrack.bounds.min.x - boundsPadding && cursorX <= railTrack.bounds.max.x + boundsPadding && cursorY >= railTrack.bounds.min.z - boundsPadding && cursorY <= railTrack.bounds.max.z + boundsPadding){
|
||||||
|
for(const curve of railTrack.curves){
|
||||||
|
if(cursorX >= curve.bounds.min.x - boundsPadding && cursorX <= curve.bounds.max.x + boundsPadding && cursorY >= curve.bounds.min.z - boundsPadding && cursorY <= curve.bounds.max.z + boundsPadding){
|
||||||
|
test = Bezier.getNearestPoint2D(curve.start, curve.h1, curve.h2, curve.end, {x:cursorX, y:cursorY}, Math.floor(curve.length*2));
|
||||||
|
if(test.distance < bestDistance){
|
||||||
|
bestDistance = test.distance;
|
||||||
|
finalTooltip = curve.tooltip;
|
||||||
|
testPoint = test.point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestDistance <= Math.min(Math.max(0.9, 12/view.scale), 120) ? finalTooltip : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTrackColorMode(mode){
|
||||||
|
let modeFunction;
|
||||||
|
const keyElement = document.getElementById('legendKeyColors');
|
||||||
|
let gradientString = '';
|
||||||
|
keyElement.innerHTML = '';
|
||||||
|
switch(mode){
|
||||||
|
case 'Track Type':
|
||||||
|
modeFunction = (curve, railTrack) => {
|
||||||
|
let finalColor = '#aaa';
|
||||||
|
if(railTrack.isYard && railTrack.yardDesignation) finalColor = '#4bf';
|
||||||
|
else if(railTrack.isYard) finalColor = '#4fb';
|
||||||
|
else if(railTrack.isJunction) finalColor = '#fb4';
|
||||||
|
else if(railTrack.isTurntable) finalColor = '#b4f';
|
||||||
|
|
||||||
|
curve.color = finalColor;
|
||||||
|
};
|
||||||
|
keyElement.innerHTML = `
|
||||||
|
<span class="colorKey"><span style="background:#4bf"></span> Designated Yard</span>
|
||||||
|
<span class="colorKey"><span style="background:#4fb"></span> Other Yard</span>
|
||||||
|
<span class="colorKey"><span style="background:#fb4"></span> Point</span>
|
||||||
|
<span class="colorKey"><span style="background:#b4f"></span> Turntable</span>
|
||||||
|
<span class="colorKey"><span style="background:#aaa"></span> Other Tracks</span>`;
|
||||||
|
break;
|
||||||
|
case 'Grade':
|
||||||
|
modeFunction = curve => {
|
||||||
|
curve.color = Config.gradeColors['grade_'+curve.gradeClass];
|
||||||
|
};
|
||||||
|
for(let grade in Config.gradeColors){
|
||||||
|
keyElement.innerHTML += `<span class="colorKey" style="${grade.replace('grade_','') < 6 || grade == 'grade_flat' ? 'color:#000;' : ''}padding:0px 3px;background:${Config.gradeColors[grade]}">${(Utils.classToGrade(grade.replace('grade_',''))*100).toFixed(1)}%</span>`;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Altitude':
|
||||||
|
modeFunction = (curve, railTrack) => {
|
||||||
|
curve.color = Color.blendGradient(Config.altitudeGradient, (curve.averageHeight-matrix.minAlt)/(matrix.maxAlt-matrix.minAlt)).hex;
|
||||||
|
}
|
||||||
|
gradientString = 'linear-gradient(to right';
|
||||||
|
for(let col of Config.altitudeGradient) gradientString += ', '+col.hex;
|
||||||
|
gradientString += ')';
|
||||||
|
|
||||||
|
keyElement.innerHTML = `
|
||||||
|
<div style="display:flex">
|
||||||
|
<div>${Math.floor(matrix.minAlt)}m</div>
|
||||||
|
<div class="gradientKey" style="flex-grow:1;background:${gradientString}"></div>
|
||||||
|
<div>${Math.ceil(matrix.maxAlt)}m</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
break;
|
||||||
|
case 'Speed':
|
||||||
|
modeFunction = curve => {
|
||||||
|
curve.color = Color.blendGradient(Config.speedGradient, (curve.postedSpeed+10)/110).hex;
|
||||||
|
};
|
||||||
|
|
||||||
|
gradientString = 'linear-gradient(to right';
|
||||||
|
for(let col of Config.speedGradient) gradientString += ', '+col.hex;
|
||||||
|
gradientString += ')';
|
||||||
|
keyElement.innerHTML = `
|
||||||
|
<div style="display:flex">
|
||||||
|
<div>10 kmh</div>
|
||||||
|
<div class="gradientKey" style="flex-grow:1;background:${gradientString}"></div>
|
||||||
|
<div>120 kmh</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
break;
|
||||||
|
case 'Track Random':
|
||||||
|
modeFunction = (curve, railTrack) => {
|
||||||
|
curve.color = railTrack.randomColor.hex;
|
||||||
|
};
|
||||||
|
keyElement.innerHTML = 'Random per continuous track section';
|
||||||
|
break;
|
||||||
|
case 'Curve Random':
|
||||||
|
modeFunction = curve => {
|
||||||
|
curve.color = curve.randomColor.hex;
|
||||||
|
};
|
||||||
|
keyElement.innerHTML = 'Random per individual track bezier curve';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
modeFunction = curve => {
|
||||||
|
curve.color = '#fff';
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(modeFunction != null){
|
||||||
|
for(let railTrack of railTracks){
|
||||||
|
for(let curve of railTrack.curves){
|
||||||
|
modeFunction(curve, railTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.dirty = true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
export class SpriteBounds{
|
||||||
|
constructor(x, y, width, height){
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
+98
-1
@@ -1,5 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import * as Config from './../config.js';
|
||||||
|
import {SpriteBounds} from './spritelib.js';
|
||||||
|
|
||||||
export const gradeIncrements = [
|
export const gradeIncrements = [
|
||||||
0.0498,
|
0.0498,
|
||||||
0.04,
|
0.04,
|
||||||
@@ -11,7 +14,60 @@ export const gradeIncrements = [
|
|||||||
0.01,
|
0.01,
|
||||||
0.005,
|
0.005,
|
||||||
0.001
|
0.001
|
||||||
]
|
];
|
||||||
|
|
||||||
|
const gradeArrowDimensions = 64;
|
||||||
|
export const gradeArrows = new OffscreenCanvas(11*gradeArrowDimensions, 2*gradeArrowDimensions);
|
||||||
|
|
||||||
|
export function generateGradeArrows(){
|
||||||
|
const ctx = gradeArrows.getContext('2d');
|
||||||
|
const mapSprites = document.getElementById('mapSprites');
|
||||||
|
for(let i=0; i<11; i++){
|
||||||
|
ctx.drawImage(
|
||||||
|
mapSprites,
|
||||||
|
Config.spriteBounds.gradeArrow.x,
|
||||||
|
Config.spriteBounds.gradeArrow.y,
|
||||||
|
Config.spriteBounds.gradeArrow.width,
|
||||||
|
Config.spriteBounds.gradeArrow.height,
|
||||||
|
i*gradeArrowDimensions,
|
||||||
|
0,
|
||||||
|
gradeArrowDimensions,
|
||||||
|
gradeArrowDimensions
|
||||||
|
);
|
||||||
|
ctx.drawImage(
|
||||||
|
mapSprites,
|
||||||
|
Config.spriteBounds.gradeArrowDown.x,
|
||||||
|
Config.spriteBounds.gradeArrowDown.y,
|
||||||
|
Config.spriteBounds.gradeArrowDown.width,
|
||||||
|
Config.spriteBounds.gradeArrowDown.height,
|
||||||
|
i*gradeArrowDimensions,
|
||||||
|
gradeArrowDimensions,
|
||||||
|
gradeArrowDimensions,
|
||||||
|
gradeArrowDimensions
|
||||||
|
);
|
||||||
|
|
||||||
|
if(i == 0){
|
||||||
|
Config.spriteBounds['gradeArrow_flat'] = new SpriteBounds(0, 0, gradeArrowDimensions, gradeArrowDimensions);
|
||||||
|
Config.spriteBounds['gradeArrowDown_flat'] = new SpriteBounds(0, gradeArrowDimensions, gradeArrowDimensions, gradeArrowDimensions);
|
||||||
|
}else{
|
||||||
|
Config.spriteBounds['gradeArrow_'+(i-1)] = new SpriteBounds(i*gradeArrowDimensions, 0, gradeArrowDimensions, gradeArrowDimensions);
|
||||||
|
Config.spriteBounds['gradeArrowDown_'+(i-1)] = new SpriteBounds(i*gradeArrowDimensions, gradeArrowDimensions, gradeArrowDimensions, gradeArrowDimensions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let arrowLayer = gradeArrows.transferToImageBitmap();
|
||||||
|
for(let i=0; i<11; i++){
|
||||||
|
if(i == 0)
|
||||||
|
ctx.fillStyle = Config.gradeColors.grade_flat;
|
||||||
|
else
|
||||||
|
ctx.fillStyle = Config.gradeColors['grade_'+(i-1)];
|
||||||
|
ctx.fillRect(i*gradeArrowDimensions, 0, gradeArrowDimensions, gradeArrowDimensions * 2);
|
||||||
|
}
|
||||||
|
ctx.globalCompositeOperation = 'multiply';
|
||||||
|
ctx.drawImage(arrowLayer, 0, 0);
|
||||||
|
ctx.globalCompositeOperation = 'destination-in';
|
||||||
|
ctx.drawImage(arrowLayer, 0, 0);
|
||||||
|
arrowLayer.close();
|
||||||
|
}
|
||||||
|
|
||||||
export function randomRange(min=0.0, max=1.0){
|
export function randomRange(min=0.0, max=1.0){
|
||||||
return Math.random()*(max-min) + min;
|
return Math.random()*(max-min) + min;
|
||||||
@@ -74,4 +130,45 @@ export function radiusToSpeed(radius){
|
|||||||
|
|
||||||
export function clamp(v, min = 0, max = 1){
|
export function clamp(v, min = 0, max = 1){
|
||||||
return Math.max(Math.min(v, max), min);
|
return Math.max(Math.min(v, max), min);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function zoomToCullLevel(zoom){
|
||||||
|
if(zoom < 1) return 0;
|
||||||
|
if(zoom < 2) return 1;
|
||||||
|
if(zoom < 3) return 2;
|
||||||
|
if(zoom < 6) return 3;
|
||||||
|
if(zoom < 12) return 4;
|
||||||
|
if(zoom < 24) return 5;
|
||||||
|
if(zoom < 60) return 6;
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lerp(a, b, t){
|
||||||
|
return (a * (1-t)) + (b*t);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mod(a, b){
|
||||||
|
return (a % b + b) % b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function titleCase(text){
|
||||||
|
text = text.toString();
|
||||||
|
if(text){
|
||||||
|
return `${text[0].toUpperCase()}${text.substring(1)}`;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const cardinalDirections = [
|
||||||
|
'North',
|
||||||
|
'Northeast',
|
||||||
|
'East',
|
||||||
|
'Southeast',
|
||||||
|
'South',
|
||||||
|
'Southwest',
|
||||||
|
'West',
|
||||||
|
'Northwest',
|
||||||
|
]
|
||||||
|
export function angleToCardinalDirection(angle){
|
||||||
|
return cardinalDirections[Math.floor(mod(angle/(2*Math.PI) + (0.5/cardinalDirections.length), 1)*cardinalDirections.length)];
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
import * as Utils from './js/utillib.js';
|
import * as Utils from './js/utillib.js';
|
||||||
import * as Config from './config.js';
|
import * as Config from './config.js';
|
||||||
import { Color } from './js/colorlib.js';
|
import { Color } from './js/colorlib.js';
|
||||||
import { setTrackColorMode } from './index.js';
|
import * as MapData from './js/mapdata.js';
|
||||||
|
|
||||||
let settingEntries = [
|
let settingEntries = [
|
||||||
{
|
{
|
||||||
@@ -18,9 +18,9 @@ let settingEntries = [
|
|||||||
'Track Random',
|
'Track Random',
|
||||||
'Curve Random',
|
'Curve Random',
|
||||||
],
|
],
|
||||||
default: 'Grade',
|
state: 'Grade',
|
||||||
func: state =>{
|
func: state =>{
|
||||||
setTrackColorMode(state);
|
MapData.setTrackColorMode(state);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -28,15 +28,17 @@ let settingEntries = [
|
|||||||
id: 'toggle_signage',
|
id: 'toggle_signage',
|
||||||
state: true,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('signage_container').style.display = state ? 'unset' : 'none';
|
MapData.layers.signage = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
label: 'Speed Signs',
|
label: 'Speed Signage',
|
||||||
id: 'toggle_speedSigns',
|
id: 'toggle_speedSigns',
|
||||||
state: true,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('signage_speed').style.display = state ? 'unset' : 'none';
|
MapData.layers.speedSigns = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -44,7 +46,8 @@ let settingEntries = [
|
|||||||
id: 'toggle_gradeSigns',
|
id: 'toggle_gradeSigns',
|
||||||
state: true,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('signage_grade').style.display = state ? 'unset' : 'none';
|
MapData.layers.gradeArrows = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -52,15 +55,17 @@ let settingEntries = [
|
|||||||
id: 'toggle_yardSigns',
|
id: 'toggle_yardSigns',
|
||||||
state: true,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('signage_yard').style.display = state ? 'unset' : 'none';
|
MapData.layers.yardSigns = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Junctions',
|
label: 'Junctions',
|
||||||
id: 'toggle_junctions',
|
id: 'toggle_junctions',
|
||||||
state: false,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('signage_junction').style.display = state ? 'unset' : 'none';
|
MapData.layers.junctions = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -70,15 +75,26 @@ let settingEntries = [
|
|||||||
id: 'toggle_poi',
|
id: 'toggle_poi',
|
||||||
state: true,
|
state: true,
|
||||||
func: state => {
|
func: state => {
|
||||||
document.getElementById('poi_container').style.display = state ? 'unset' : 'none';
|
MapData.layers.poi = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
label: 'Stations',
|
||||||
|
id: 'toggle_stations',
|
||||||
|
state: true,
|
||||||
|
func: state =>{
|
||||||
|
MapData.layers.stations = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Services',
|
label: 'Services',
|
||||||
id: 'toggle_services',
|
id: 'toggle_services',
|
||||||
state: true,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('poi_service').style.display = state ? 'unset' : 'none';
|
MapData.layers.services = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -86,7 +102,8 @@ let settingEntries = [
|
|||||||
id: 'toggle_landmarks',
|
id: 'toggle_landmarks',
|
||||||
state: true,
|
state: true,
|
||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('poi_landmarks').style.display = state ? 'unset' : 'none';
|
MapData.layers.landmarks = state;
|
||||||
|
MapData.view.dirty = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -98,19 +115,44 @@ let settingEntries = [
|
|||||||
'Uphill',
|
'Uphill',
|
||||||
'Downhill',
|
'Downhill',
|
||||||
],
|
],
|
||||||
default: 'Uphill',
|
state: 'Uphill',
|
||||||
func: state =>{
|
func: state =>{
|
||||||
let newHref = state == 'Uphill' ? '#gradeArrow' : '#gradeArrowDownhill';
|
MapData.layers.gradeDirection = state == 'Downhill' ? 'Down' : '';
|
||||||
for(let arrow of document.getElementsByClassName('gradeArrow')){
|
MapData.view.dirty = true;
|
||||||
arrow.setAttribute('href', newHref);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Terrain',
|
||||||
|
id: 'dropdown_terrain',
|
||||||
|
options: [
|
||||||
|
'None',
|
||||||
|
'Simple',
|
||||||
|
'DVRT',
|
||||||
|
],
|
||||||
|
state: 'None',
|
||||||
|
func: state =>{
|
||||||
|
let mapTerrain = document.getElementById('mapTerrain');
|
||||||
|
if(state == 'None'){
|
||||||
|
MapData.layers.terrain = false;
|
||||||
|
MapData.view.dirty = true;
|
||||||
|
}else{
|
||||||
|
mapTerrain.onload = () => {
|
||||||
|
MapData.layers.terrain = true;
|
||||||
|
MapData.view.dirty = true;
|
||||||
|
}
|
||||||
|
if(state == 'Simple'){
|
||||||
|
document.getElementById('mapTerrain').src = 'terrains/simple.jpg';
|
||||||
|
}else if(state == 'DVRT'){
|
||||||
|
document.getElementById('mapTerrain').src = 'terrains/dvrt.jpg';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const legendKey = document.getElementById('legendKey');
|
const legendKey = document.getElementById('legendKey');
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
export function initialize(){
|
||||||
const settingsPanel = document.getElementById('settingsPanel');
|
const settingsPanel = document.getElementById('settingsPanel');
|
||||||
for(let thisSetting of settingEntries){
|
for(let thisSetting of settingEntries){
|
||||||
addSettingEntry(thisSetting, settingsPanel);
|
addSettingEntry(thisSetting, settingsPanel);
|
||||||
@@ -130,7 +172,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
if(document.body.clientWidth <= 700) legendButtonEvent();
|
if(document.body.clientWidth <= 700) legendButtonEvent();
|
||||||
populateKey();
|
populateKey();
|
||||||
setLastUpdateData();
|
setLastUpdateData();
|
||||||
});
|
};
|
||||||
|
|
||||||
function addSettingEntry(thisSetting, parent, indent=0){
|
function addSettingEntry(thisSetting, parent, indent=0){
|
||||||
thisSetting.divContainer = document.createElement('div');
|
thisSetting.divContainer = document.createElement('div');
|
||||||
@@ -166,7 +208,7 @@ function addSettingEntry(thisSetting, parent, indent=0){
|
|||||||
optionElement.value = inputEntry;
|
optionElement.value = inputEntry;
|
||||||
optionElement.innerHTML = inputEntry;
|
optionElement.innerHTML = inputEntry;
|
||||||
}
|
}
|
||||||
if(inputEntry == thisSetting.default) optionElement.selected = true;
|
if(inputEntry == thisSetting.state) optionElement.selected = true;
|
||||||
thisSetting.inputElement.appendChild(optionElement);
|
thisSetting.inputElement.appendChild(optionElement);
|
||||||
}
|
}
|
||||||
if(thisSetting.func){
|
if(thisSetting.func){
|
||||||
@@ -199,6 +241,10 @@ function addSettingEntry(thisSetting, parent, indent=0){
|
|||||||
thisSetting.inputElement.style.margin = `0 0.5em 0 ${indent}em`;
|
thisSetting.inputElement.style.margin = `0 0.5em 0 ${indent}em`;
|
||||||
thisSetting.divContainer.prepend(thisSetting.inputElement);
|
thisSetting.divContainer.prepend(thisSetting.inputElement);
|
||||||
|
|
||||||
|
if(thisSetting.func){
|
||||||
|
thisSetting.func(thisSetting.state);
|
||||||
|
}
|
||||||
|
|
||||||
if(thisSetting.children){
|
if(thisSetting.children){
|
||||||
for(let child of thisSetting.children){
|
for(let child of thisSetting.children){
|
||||||
addSettingEntry(child, parent, indent+1);
|
addSettingEntry(child, parent, indent+1);
|
||||||
@@ -208,11 +254,16 @@ function addSettingEntry(thisSetting, parent, indent=0){
|
|||||||
|
|
||||||
let pageLoadUpdateDate = null;
|
let pageLoadUpdateDate = null;
|
||||||
async function setLastUpdateData(){
|
async function setLastUpdateData(){
|
||||||
|
if(!window.location.host.includes('github')) return;
|
||||||
let commits = await (await fetch(new Request('https://api.github.com/repos/PyroNicampt/DV-Community-Map/commits'))).json();
|
let commits = await (await fetch(new Request('https://api.github.com/repos/PyroNicampt/DV-Community-Map/commits'))).json();
|
||||||
let lastUpdateElement = document.getElementById('lastUpdate');
|
let lastUpdateElement = document.getElementById('lastUpdate');
|
||||||
|
if(!commits){
|
||||||
|
lastUpdateElement.innerHTML = '<a href="https://github.com/PyroNicampt/DV-Community-Map/commits/main/" title="Could not fetch commit history">Fetch Error</a>';
|
||||||
|
return;
|
||||||
|
};
|
||||||
let updateDate = new Date(commits[0].commit.author.date);
|
let updateDate = new Date(commits[0].commit.author.date);
|
||||||
|
lastUpdateElement.innerHTML = `<a href="https://github.com/PyroNicampt/DV-Community-Map/commits/main/" title="${updateDate.toString()}">${Utils.formattedTimeBetweenDates(new Date(), updateDate)} ${new Date() >= updateDate ? 'ago' : 'from now'}</a>`;
|
||||||
lastUpdateElement.innerHTML = `<a href="https://github.com/PyroNicampt/DV-Community-Map/commits/main/" title="${updateDate.toString()}">${Utils.formattedTimeBetweenDates(new Date(), updateDate)} ago</a>`;
|
document.getElementById('changelog').innerHTML = commits[0].commit.message.replace('\n','<br>');
|
||||||
if(pageLoadUpdateDate == null){
|
if(pageLoadUpdateDate == null){
|
||||||
pageLoadUpdateDate = updateDate;
|
pageLoadUpdateDate = updateDate;
|
||||||
}else{
|
}else{
|
||||||
@@ -221,38 +272,24 @@ async function setLastUpdateData(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {setLastUpdateData()}, 900000);
|
setTimeout(() => {setLastUpdateData()}, 600000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateKey(){
|
function populateKey(){
|
||||||
const getGradeValue = gradeIndex => {return Math.round(Utils.gradeIncrements[Utils.gradeIncrements.length-gradeIndex-1]*10000)/100};
|
addKeyEntry('gradeArrow', 'Grade Indication')
|
||||||
for(let i=-1; i<Utils.gradeIncrements.length; i++){
|
addKeyEntry('speed_5', 'Speed Limit');
|
||||||
let gradeValue = `< ${getGradeValue(0)}`;
|
addKeyEntry('junction', 'Junction/Switch');
|
||||||
let gradeIndex = 'flat';
|
addKeyEntry('office', 'Station Office');
|
||||||
if(i>=0){
|
addKeyEntry('shop', 'Shop');
|
||||||
gradeValue = `${getGradeValue(i)}`;
|
addKeyEntry('service_repair', 'Repair Service');
|
||||||
gradeIndex = i;
|
addKeyEntry('service_diesel', 'Diesel Refuel');
|
||||||
}
|
addKeyEntry('service_charger', 'Electric Charger');
|
||||||
if(i == Utils.gradeIncrements.length-1){
|
addKeyEntry('coal', 'Coal Tower');
|
||||||
gradeValue = '> '+gradeValue+'%';
|
addKeyEntry('water', 'Water Tower');
|
||||||
}else if(i >= 0){
|
addKeyEntry('landmark', 'Landmark');
|
||||||
gradeValue += ` - ${getGradeValue(i+1)}%`;
|
addKeyEntry('garage', 'Garage');
|
||||||
}
|
|
||||||
addKeyEntry(`<use fill="${Config.gradeColors['grade_'+gradeIndex]}" href="#gradeArrow" transform="rotate(90)"/>`, ` ${gradeValue} Grade`);
|
|
||||||
}
|
|
||||||
addKeyEntry('<use href="#speedSign_5"/>', ' Speed Limit');
|
|
||||||
addKeyEntry('<use href="#junctionSign" fill="#de2121" transform="scale(0.75)"/>', ' Junction/Switch');
|
|
||||||
addKeyEntry('<use href="#mrk_office" fill="#c4693e" transform="scale(0.75)"/>', ' Station Office');
|
|
||||||
addKeyEntry('<use href="#mrk_shop" fill="#4f54e9" transform="scale(0.75)"/>', ' Shop');
|
|
||||||
addKeyEntry('<use href="#mrk_service_repair" fill="#239a96" transform="scale(0.75)"/>', ' Repair Service');
|
|
||||||
addKeyEntry('<use href="#mrk_service_diesel" fill="#239a96" transform="scale(0.75)"/>', ' Diesel Refuel');
|
|
||||||
addKeyEntry('<use href="#mrk_service_charger" fill="#239a96" transform="scale(0.75)"/>', ' Electric Charger');
|
|
||||||
addKeyEntry('<use href="#mrk_coal" fill="#202020" transform="scale(0.75)"/>', ' Coal Tower');
|
|
||||||
addKeyEntry('<use href="#mrk_water" fill="#3fa5ff" transform="scale(0.75)"/>', ' Water Tower');
|
|
||||||
addKeyEntry('<use href="#mrk_landmark" fill="#af5757" transform="scale(0.75)"/>', ' Landmark');
|
|
||||||
addKeyEntry('<use href="#mrk_garage" fill="#8b5dd7" transform="scale(0.75)"/>', ' Garage');
|
|
||||||
//Add empty entries to make entries align right in the columns.
|
//Add empty entries to make entries align right in the columns.
|
||||||
for(let i=0; i<2; i++){
|
for(let i=0; i<3; i++){
|
||||||
addKeyEntry();
|
addKeyEntry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,15 +299,17 @@ function populateKey(){
|
|||||||
* @param {string} keyImageHTML
|
* @param {string} keyImageHTML
|
||||||
* @param {string} keyLabel
|
* @param {string} keyLabel
|
||||||
*/
|
*/
|
||||||
function addKeyEntry(keyImageHTML, keyLabel){
|
function addKeyEntry(keySprite, keyLabel){
|
||||||
if(!keyLabel) keyLabel = ' ';
|
if(!keyLabel) keyLabel = ' ';
|
||||||
let keyDiv = document.createElement('div');
|
let keyDiv = document.createElement('div');
|
||||||
if(keyImageHTML){
|
if(keySprite && Config.spriteBounds[keySprite]){
|
||||||
let keyImage = document.createElement('svg');
|
let keyImage = document.createElement('span');
|
||||||
keyImage.innerHTML = keyImageHTML;
|
let spriteBounds = Config.spriteBounds[keySprite];
|
||||||
keyImage.classList.add('inlineSvg');
|
keyImage.classList.add('inlineSvg');
|
||||||
keyImage.setAttribute('viewBox', '-150 -150 300 300');
|
keyImage.style.background = `url('mapSprites.svg') -${spriteBounds.x/spriteBounds.width}em -${spriteBounds.y/spriteBounds.height}em`;
|
||||||
|
keyImage.style.backgroundSize = '1000%';
|
||||||
keyDiv.appendChild(keyImage);
|
keyDiv.appendChild(keyImage);
|
||||||
|
keyLabel = ' '+keyLabel;
|
||||||
}
|
}
|
||||||
keyDiv.innerHTML += keyLabel;
|
keyDiv.innerHTML += keyLabel;
|
||||||
legendKey.appendChild(keyDiv);
|
legendKey.appendChild(keyDiv);
|
||||||
|
|||||||
+282
@@ -0,0 +1,282 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
viewBox="0 0 200 200"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xml:space="preserve"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs1" /><g
|
||||||
|
id="g33"><rect
|
||||||
|
style="fill:#bb3f3f;stroke:#ebebeb;stroke-width:0.9"
|
||||||
|
id="rect32"
|
||||||
|
width="9.9940004"
|
||||||
|
height="18.922001"
|
||||||
|
x="5.0029998"
|
||||||
|
y="20.539"
|
||||||
|
ry="1.347"
|
||||||
|
rx="1.347" /><rect
|
||||||
|
style="fill:#ebebeb"
|
||||||
|
id="rect33"
|
||||||
|
width="1.979"
|
||||||
|
height="18.334999"
|
||||||
|
x="19.742342"
|
||||||
|
y="14.710581"
|
||||||
|
ry="0.98900002"
|
||||||
|
transform="rotate(22.53)"
|
||||||
|
rx="0.98900002" /></g><g
|
||||||
|
id="g34"><circle
|
||||||
|
style="opacity:1;fill:#702012;fill-opacity:1;stroke:#e73819;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path33"
|
||||||
|
cx="10"
|
||||||
|
cy="50"
|
||||||
|
r="8.5" /><circle
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#e73819;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="circle33"
|
||||||
|
cx="9.9997206"
|
||||||
|
cy="69.999718"
|
||||||
|
r="8.5" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path33"
|
||||||
|
id="use34"
|
||||||
|
transform="translate(20)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path33"
|
||||||
|
id="use35"
|
||||||
|
transform="translate(40)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path33"
|
||||||
|
id="use36"
|
||||||
|
transform="translate(60)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use37"
|
||||||
|
transform="translate(20.000279)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use38"
|
||||||
|
transform="translate(40.000279)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use39"
|
||||||
|
transform="translate(60.000279)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use40"
|
||||||
|
transform="translate(80.000279)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use41"
|
||||||
|
transform="translate(100.00028)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use42"
|
||||||
|
transform="translate(120.00028)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use43"
|
||||||
|
transform="translate(140.00028)" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#circle33"
|
||||||
|
id="use44"
|
||||||
|
transform="translate(160.00028)" /><path
|
||||||
|
d="m 29.496942,47.783503 q -0.249023,0.226384 -0.543322,0.354669 -0.2943,0.128284 -0.694245,0.128284 -0.226385,0 -0.422584,-0.08301 -0.188654,-0.09055 -0.324485,-0.233931 -0.13583,-0.150923 -0.218838,-0.339576 -0.07546,-0.188654 -0.07546,-0.399946 0,-0.211292 0.06791,-0.362214 0.06792,-0.158469 0.188654,-0.271662 0.120738,-0.113192 0.279207,-0.203745 0.158469,-0.09055 0.339576,-0.188654 0.377308,-0.249023 0.671607,-0.505592 0.301846,-0.256568 0.535776,-0.475407 0.233931,-0.226384 0.407492,-0.384853 0.173561,-0.158469 0.301846,-0.218838 0.07546,-0.03773 0.13583,-0.06037 0.06792,-0.03019 0.135831,-0.03773 0.06791,-0.01509 0.150923,-0.01509 0.08301,-0.0075 0.211292,-0.0075 0.392399,0 0.618783,0.158469 0.233931,0.158469 0.347123,0.415038 0.120738,0.249022 0.150923,0.56596 0.03018,0.316938 0.03018,0.641422 v 7.002821 q 0,0.33203 -0.03018,0.656514 -0.03018,0.316938 -0.150923,0.565961 -0.113192,0.249023 -0.347123,0.407492 -0.226384,0.150922 -0.618783,0.150922 -0.399946,0 -0.62633,-0.150922 -0.226384,-0.158469 -0.347123,-0.407492 -0.113192,-0.249023 -0.143376,-0.565961 -0.03018,-0.324484 -0.03018,-0.656514 z"
|
||||||
|
id="text44"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;fill:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="1" /><path
|
||||||
|
d="m 49.994806,44.512566 q 0.852716,0 1.49414,0.233931 0.64897,0.226385 1.079102,0.641424 0.430131,0.407493 0.64897,0.981001 0.218839,0.565963 0.218839,1.252664 0,0.45277 -0.128285,0.837624 -0.120739,0.384854 -0.324485,0.701793 -0.1962,0.316939 -0.45277,0.573509 -0.25657,0.256569 -0.520685,0.45277 -0.633878,0.467862 -1.426226,0.754616 -0.264115,0.105646 -0.528231,0.25657 -0.25657,0.143377 -0.460316,0.339577 -0.203747,0.188654 -0.332031,0.445224 -0.128285,0.249023 -0.128285,0.573508 v 0.467863 h 2.626065 q 0.316939,0 0.633878,0.03018 0.316939,0.03018 0.573508,0.135831 0.25657,0.105646 0.41504,0.316939 0.158469,0.203747 0.158469,0.558416 0,0.362216 -0.158469,0.573509 -0.15847,0.211292 -0.41504,0.324485 -0.256569,0.113192 -0.573508,0.143377 -0.316939,0.03019 -0.633878,0.03019 h -3.75799 q -0.377308,0 -0.626331,-0.120739 -0.241478,-0.128285 -0.384855,-0.316939 -0.143377,-0.1962 -0.203746,-0.430131 -0.05282,-0.241478 -0.05282,-0.475409 v -1.207386 q 0,-0.581055 0.188654,-1.086648 0.1962,-0.513139 0.543324,-0.928178 0.354669,-0.422585 0.837624,-0.754616 0.4905,-0.332032 1.086647,-0.565963 0.596147,-0.233931 0.950817,-0.445223 0.35467,-0.218839 0.543324,-0.422586 0.1962,-0.211292 0.25657,-0.422585 0.06037,-0.211292 0.06037,-0.430131 0,-0.392401 -0.135831,-0.618786 -0.128285,-0.226385 -0.324485,-0.332031 -0.188654,-0.113192 -0.399947,-0.135831 -0.203746,-0.03018 -0.347123,-0.03018 -0.377309,0 -0.603694,0.113193 -0.226384,0.105646 -0.347123,0.271662 -0.113193,0.166015 -0.150923,0.369762 -0.03018,0.1962 -0.03018,0.377308 0,0.2943 -0.113192,0.505593 -0.113193,0.203747 -0.286755,0.332031 -0.166015,0.128285 -0.369762,0.188654 -0.1962,0.06037 -0.362216,0.06037 -0.513139,0 -0.830078,-0.279208 -0.316939,-0.286755 -0.316939,-0.731978 0,-0.196201 0.04528,-0.505593 0.04528,-0.309393 0.173562,-0.656517 0.128285,-0.347123 0.362216,-0.694247 0.233931,-0.347123 0.611239,-0.626331 0.377308,-0.279209 0.920632,-0.45277 0.543324,-0.173562 1.297941,-0.173562 z"
|
||||||
|
id="text45"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;fill:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="2" /><path
|
||||||
|
d="M 70.623647,46.946934 V 46.841288 H 68.66165 q -0.256569,0 -0.535776,-0.03018 -0.271661,-0.03019 -0.498045,-0.135831 -0.226385,-0.105646 -0.377307,-0.316938 -0.143377,-0.211292 -0.143377,-0.573506 0,-0.354669 0.143377,-0.558415 0.150922,-0.211292 0.377307,-0.316938 0.226384,-0.105646 0.498045,-0.13583 0.279207,-0.03019 0.535776,-0.03019 h 3.36558 q 0.301846,0 0.535776,0.0981 0.241477,0.0981 0.399946,0.264115 0.166015,0.158469 0.249022,0.369761 0.08301,0.211292 0.08301,0.43013 0,0.128284 -0.02264,0.249023 -0.01509,0.120738 -0.08301,0.23393 l -1.358306,2.263843 q 0.347123,0.143377 0.679153,0.384853 0.33203,0.233931 0.588599,0.596145 0.264115,0.362215 0.415038,0.860261 0.158469,0.490499 0.158469,1.131921 0,0.72443 -0.158469,1.29039 -0.150923,0.558415 -0.415038,0.973453 -0.256569,0.415038 -0.611237,0.701791 -0.347123,0.279207 -0.747069,0.452769 -0.392399,0.173561 -0.814983,0.249022 -0.422584,0.07546 -0.830076,0.07546 -0.309392,0 -0.66406,-0.06037 -0.354669,-0.06037 -0.709338,-0.188654 -0.347122,-0.128284 -0.671606,-0.309392 -0.316938,-0.188653 -0.565961,-0.445222 -0.249023,-0.256569 -0.399946,-0.573507 -0.143376,-0.316938 -0.143376,-0.701791 0,-0.188654 0.05282,-0.354669 0.05282,-0.173561 0.158469,-0.301846 0.113192,-0.13583 0.279207,-0.211292 0.166015,-0.08301 0.399946,-0.08301 0.309391,0 0.573506,0.173561 0.271662,0.173561 0.452769,0.535776 0.04528,0.08301 0.135831,0.188654 0.0981,0.105646 0.249022,0.196199 0.158469,0.09055 0.377307,0.158469 0.218838,0.06037 0.505592,0.06037 0.437676,0 0.716883,-0.135831 0.286754,-0.143377 0.452769,-0.369761 0.166015,-0.226384 0.226384,-0.513138 0.06792,-0.286753 0.06792,-0.581053 0,-0.339576 -0.113193,-0.626329 -0.113192,-0.286754 -0.309391,-0.498046 -0.188654,-0.211292 -0.437677,-0.324484 -0.241476,-0.120738 -0.498045,-0.120738 -0.362215,0 -0.588599,-0.218838 -0.226384,-0.218839 -0.226384,-0.596146 0,-0.158469 0.06037,-0.347122 0.06037,-0.1962 0.196199,-0.437677 z"
|
||||||
|
id="text46"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;fill:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="3" /><path
|
||||||
|
d="m 31.77858,68.317547 q 0.369761,0 0.581053,0.105646 0.211292,0.0981 0.316938,0.271661 0.113192,0.173561 0.143376,0.407492 0.03019,0.226384 0.03019,0.482953 v 4.467316 q 0,0.264115 -0.03019,0.4905 -0.03018,0.226384 -0.13583,0.399945 -0.105646,0.166015 -0.316938,0.264115 -0.211292,0.0981 -0.573507,0.0981 -0.354669,0 -0.565961,-0.09055 -0.211292,-0.0981 -0.324484,-0.256569 -0.113192,-0.158469 -0.150923,-0.377307 -0.03018,-0.218838 -0.03018,-0.467861 v -1.343213 h -2.580781 q -0.467861,0 -0.769707,-0.07546 -0.301845,-0.07546 -0.482953,-0.1962 -0.173561,-0.128285 -0.249023,-0.2943 -0.06791,-0.166015 -0.06791,-0.339576 0,-0.09055 0.01509,-0.181108 0.02264,-0.09055 0.04528,-0.181107 l 1.524321,-5.297392 q 0.07546,-0.279207 0.143377,-0.543322 0.07546,-0.264115 0.1962,-0.467861 0.128284,-0.203746 0.347122,-0.324484 0.218838,-0.128285 0.596145,-0.128285 0.271662,0 0.445223,0.07546 0.181107,0.07546 0.286753,0.203745 0.105646,0.120739 0.143377,0.286754 0.04528,0.158469 0.04528,0.339576 0,0.181108 -0.03019,0.369761 -0.03018,0.181108 -0.07546,0.339577 -0.03773,0.158469 -0.08301,0.286753 -0.03773,0.120738 -0.05282,0.181108 0,0 -0.04528,0.166015 -0.04528,0.158469 -0.120738,0.422584 -0.07546,0.256569 -0.166015,0.596145 -0.09055,0.33203 -0.188654,0.679153 -0.23393,0.814983 -0.520683,1.848805 l 0.06037,0.06037 h 1.58469 v -1.026275 q 0,-0.256569 0.03018,-0.482954 0.03019,-0.226384 0.135831,-0.392399 0.105646,-0.173561 0.316938,-0.271661 0.211292,-0.105646 0.573507,-0.105646 z"
|
||||||
|
id="text47"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="4" /><path
|
||||||
|
d="m 48.981411,68.651633 q 0.309392,-0.113192 0.671606,-0.158469 0.369761,-0.05282 0.656515,-0.05282 0.271661,0 0.603691,0.06037 0.332031,0.06037 0.671607,0.211292 0.339576,0.143377 0.664061,0.384853 0.324484,0.241477 0.573506,0.603692 0.249023,0.354669 0.399946,0.845168 0.150923,0.490499 0.150923,1.124375 0,0.72443 -0.158469,1.29039 -0.150923,0.558415 -0.415038,0.973453 -0.256569,0.415038 -0.611238,0.701791 -0.347122,0.279207 -0.747068,0.452769 -0.392399,0.173561 -0.814983,0.249022 -0.422584,0.07546 -0.830076,0.07546 -0.445222,0 -0.943268,-0.113192 -0.490499,-0.120739 -0.935721,-0.354669 -0.437677,-0.241477 -0.777253,-0.596145 -0.33203,-0.362215 -0.452769,-0.852714 -0.04528,-0.181108 -0.04528,-0.362215 0,-0.188654 0.05282,-0.354669 0.05282,-0.173561 0.158469,-0.301846 0.113192,-0.13583 0.279207,-0.211292 0.166015,-0.08301 0.399945,-0.08301 0.309392,0 0.573507,0.173561 0.271661,0.173561 0.452769,0.535776 0.04528,0.08301 0.13583,0.188654 0.0981,0.105646 0.249023,0.196199 0.158469,0.09055 0.377307,0.158469 0.218838,0.06037 0.505592,0.06037 0.437676,0 0.716883,-0.135831 0.286754,-0.143377 0.452769,-0.369761 0.166015,-0.226384 0.226384,-0.513138 0.06791,-0.286753 0.06791,-0.581053 0,-0.369761 -0.128284,-0.633876 -0.128284,-0.271661 -0.347123,-0.445222 -0.211292,-0.181107 -0.482953,-0.264115 -0.271661,-0.09055 -0.550868,-0.09055 -0.241477,0 -0.482953,0.06792 -0.233931,0.06037 -0.475407,0.13583 -0.233931,0.07546 -0.475407,0.143377 -0.241477,0.06037 -0.498046,0.06037 -0.173561,0 -0.347122,-0.03773 -0.173561,-0.03773 -0.309392,-0.13583 -0.135831,-0.105646 -0.226384,-0.271661 -0.08301,-0.166016 -0.08301,-0.430131 l 0.437676,-4.150378 q 0.01509,-0.166015 0.06037,-0.347123 0.05282,-0.188653 0.150922,-0.347122 0.105646,-0.158469 0.271662,-0.256569 0.173561,-0.105646 0.437676,-0.105646 h 3.018457 q 0.279207,0 0.565961,0.03018 0.294299,0.03018 0.520683,0.13583 0.233931,0.105646 0.377308,0.316938 0.150922,0.203746 0.150922,0.558415 0,0.362215 -0.150922,0.573507 -0.143377,0.211292 -0.377308,0.316938 -0.226384,0.105646 -0.520683,0.13583 -0.286754,0.03019 -0.565961,0.03019 h -1.811074 q -0.06037,0 -0.120739,0.0075 -0.05282,0 -0.0981,0.03018 -0.03773,0.03019 -0.06791,0.0981 -0.02264,0.06037 -0.03018,0.181108 z"
|
||||||
|
id="text48"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="5" /><path
|
||||||
|
d="m 67.13104,71.482665 q 0,-0.354669 0,-0.814983 0.0075,-0.467861 0.0075,-0.92063 0,-0.452768 0,-0.830075 0.0075,-0.377308 0.0075,-0.558415 0,-0.437676 0.09055,-0.882899 0.09055,-0.452768 0.256569,-0.867806 0.173562,-0.415038 0.415038,-0.777253 0.241477,-0.362215 0.535776,-0.633876 0.301846,-0.271661 0.641422,-0.422584 0.347123,-0.158469 0.731976,-0.158469 0.264115,0.01509 0.460315,0.105646 0.203746,0.08301 0.339576,0.218838 0.135831,0.128285 0.203746,0.2943 0.06792,0.166015 0.06792,0.347122 0,0.249023 -0.135831,0.498046 -0.135831,0.249023 -0.422584,0.467861 -0.226384,0.181107 -0.392399,0.324484 -0.166016,0.143377 -0.279208,0.286753 -0.105646,0.143377 -0.173561,0.309392 -0.06037,0.158469 -0.0981,0.369761 -0.03018,0.203746 -0.04528,0.482953 -0.0075,0.279208 -0.0075,0.656515 0.07546,-0.158469 0.218838,-0.264115 0.143377,-0.105646 0.309392,-0.166015 0.173561,-0.06037 0.362215,-0.08301 0.188654,-0.03019 0.362215,-0.03019 0.211292,0 0.498045,0.03773 0.2943,0.03773 0.603692,0.150923 0.309392,0.105646 0.611237,0.309392 0.301846,0.203746 0.535776,0.535776 0.233931,0.324484 0.377307,0.799891 0.150923,0.475407 0.150923,1.124375 v 0.694245 q 0,0.754615 -0.188653,1.282845 -0.181108,0.52823 -0.467861,0.882898 -0.286754,0.347123 -0.641422,0.543323 -0.354669,0.196199 -0.694245,0.301845 -0.339577,0.0981 -0.633876,0.120739 -0.286754,0.02264 -0.437677,0.02264 -0.203745,0 -0.520683,-0.02264 -0.309392,-0.02264 -0.664061,-0.120739 -0.354669,-0.105646 -0.709337,-0.301845 -0.347123,-0.1962 -0.633876,-0.543323 -0.286754,-0.354668 -0.467861,-0.882898 -0.173562,-0.52823 -0.173562,-1.282845 z m 2.203474,0.890445 q 0.01509,0.249023 0.113192,0.445222 0.08301,0.173562 0.264115,0.309392 0.181108,0.135831 0.513138,0.135831 0.33203,0 0.505592,-0.135831 0.173561,-0.13583 0.256568,-0.309392 0.09055,-0.196199 0.113193,-0.445222 v -1.101737 q -0.02264,-0.249023 -0.113193,-0.445222 -0.08301,-0.166015 -0.264115,-0.301846 -0.173561,-0.143377 -0.498045,-0.143377 -0.33203,0 -0.513138,0.143377 -0.181107,0.135831 -0.264115,0.301846 -0.0981,0.196199 -0.113192,0.445222 z"
|
||||||
|
id="text49"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="6" /><path
|
||||||
|
d="m 90.621152,67.038889 v -0.09055 h -2.369488 q -0.264115,0 -0.550869,-0.03019 -0.279207,-0.03018 -0.520684,-0.13583 -0.23393,-0.105646 -0.392399,-0.316938 -0.150923,-0.211292 -0.150923,-0.573507 0,-0.354669 0.150923,-0.558415 0.158469,-0.211292 0.392399,-0.316938 0.241477,-0.105646 0.520684,-0.13583 0.286754,-0.03018 0.550869,-0.03018 h 4.044732 q 0.301846,0 0.535776,0.0981 0.241477,0.0981 0.399946,0.264115 0.166015,0.158469 0.249023,0.369761 0.08301,0.211292 0.08301,0.43013 0,0.128284 -0.02264,0.249023 -0.02264,0.120738 -0.08301,0.23393 l -2.173289,3.969271 q -0.188654,0.339577 -0.301846,0.588599 -0.105646,0.241477 -0.166015,0.460315 -0.05282,0.218838 -0.07546,0.452769 -0.01509,0.23393 -0.01509,0.550868 v 1.131921 q 0,0.332031 -0.02264,0.648969 -0.01509,0.316938 -0.128284,0.56596 -0.113193,0.249023 -0.362215,0.399946 -0.241477,0.150923 -0.694245,0.150923 -0.445223,0 -0.686699,-0.150923 -0.233931,-0.150923 -0.347123,-0.399946 -0.105646,-0.249022 -0.128284,-0.56596 -0.01509,-0.316938 -0.01509,-0.648969 v -1.131921 q 0,-0.535776 0.02264,-0.875353 0.03018,-0.339576 0.105646,-0.596145 0.07546,-0.264115 0.203746,-0.513138 0.128284,-0.249022 0.33203,-0.611237 z"
|
||||||
|
id="text50"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="7" /><path
|
||||||
|
d="m 109.15229,72.552229 q 0.0151,0.23393 0.12073,0.415038 0.0906,0.158469 0.27921,0.286753 0.18865,0.128284 0.55087,0.128284 0.33958,0 0.52068,-0.128284 0.18866,-0.128284 0.27166,-0.286753 0.0981,-0.181108 0.1132,-0.415038 v -1.433767 q -0.0151,-0.256569 -0.1132,-0.452769 -0.083,-0.173561 -0.27166,-0.309392 -0.1811,-0.143377 -0.52068,-0.143377 -0.18111,0 -0.31694,0.03773 -0.12828,0.03773 -0.23393,0.105646 -0.0981,0.06037 -0.16601,0.143377 -0.0679,0.08301 -0.1132,0.166015 -0.10564,0.1962 -0.12073,0.452769 z m 0.95081,-8.029096 q 0.17356,0 0.46031,0.02264 0.2943,0.01509 0.62633,0.0981 0.33203,0.08301 0.66406,0.256569 0.33958,0.173561 0.61124,0.490499 0.27166,0.316938 0.43768,0.799891 0.17356,0.475407 0.17356,1.169653 v 0.196199 q 0,0.467861 -0.0604,0.799891 -0.0604,0.324485 -0.17356,0.550869 -0.11319,0.226384 -0.27166,0.377307 -0.15847,0.150923 -0.35467,0.264115 0.1962,0.113192 0.37731,0.264115 0.18865,0.150923 0.32448,0.377307 0.14338,0.226384 0.22638,0.558415 0.083,0.324484 0.083,0.792345 v 0.830075 q 0,0.694245 -0.18111,1.177199 -0.1811,0.475407 -0.4754,0.792345 -0.28676,0.316938 -0.64142,0.490499 -0.35467,0.173561 -0.7018,0.256569 -0.34712,0.08301 -0.64896,0.0981 -0.30185,0.02264 -0.47541,0.02264 -0.17356,0 -0.48295,-0.02264 -0.30185,-0.01509 -0.66406,-0.0981 -0.35467,-0.08301 -0.72443,-0.256569 -0.36222,-0.173561 -0.66406,-0.490499 -0.30185,-0.316938 -0.4905,-0.792345 -0.18866,-0.482954 -0.18866,-1.177199 v -0.830075 q 0,-0.467861 0.083,-0.792345 0.083,-0.332031 0.21884,-0.558415 0.14337,-0.226384 0.32448,-0.377307 0.18866,-0.150923 0.38486,-0.264115 -0.1962,-0.113192 -0.35467,-0.264115 -0.15847,-0.150923 -0.27166,-0.377307 -0.1132,-0.226384 -0.17357,-0.550869 -0.0604,-0.33203 -0.0604,-0.799891 v -0.196199 q 0,-0.694246 0.17356,-1.169653 0.1811,-0.482953 0.46031,-0.799891 0.28675,-0.316938 0.63388,-0.490499 0.35467,-0.173561 0.69424,-0.256569 0.33958,-0.08301 0.63388,-0.0981 0.2943,-0.02264 0.46786,-0.02264 z m -0.95081,3.441041 q 0.0151,0.23393 0.12073,0.415038 0.0906,0.158469 0.27921,0.286753 0.18865,0.128285 0.55087,0.128285 0.33958,0 0.52068,-0.128285 0.18866,-0.128284 0.27166,-0.286753 0.0981,-0.181108 0.1132,-0.415038 V 67.34539 q -0.0151,-0.256569 -0.1132,-0.452768 -0.083,-0.173562 -0.27166,-0.309392 -0.1811,-0.143377 -0.52068,-0.143377 -0.18111,0 -0.31694,0.03773 -0.12828,0.03773 -0.23393,0.105646 -0.0981,0.06037 -0.16601,0.143377 -0.0679,0.08301 -0.1132,0.166015 -0.10564,0.196199 -0.12073,0.452768 z"
|
||||||
|
id="text51"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="8" /><path
|
||||||
|
d="m 133.23948,68.343537 q 0,0.354669 -0.008,0.814983 0,0.460315 0,0.905538 0,0.445222 -0.008,0.822529 0,0.369761 0,0.550869 0,0.66406 -0.20374,1.335667 -0.1962,0.66406 -0.55087,1.207383 -0.34713,0.535776 -0.83008,0.875352 -0.48295,0.339577 -1.05646,0.339577 -0.27166,-0.01509 -0.47541,-0.0981 -0.20374,-0.09055 -0.33957,-0.218838 -0.13583,-0.135831 -0.20375,-0.301846 -0.0679,-0.166015 -0.0679,-0.347123 0,-0.249022 0.13583,-0.498045 0.13583,-0.249023 0.42258,-0.467861 0.23393,-0.173561 0.39995,-0.316938 0.16601,-0.150923 0.2792,-0.2943 0.1132,-0.143376 0.17357,-0.301845 0.0679,-0.166015 0.0981,-0.377307 0.0377,-0.211292 0.0453,-0.4905 0.0151,-0.279207 0.0151,-0.66406 -0.083,0.158469 -0.22638,0.264115 -0.13583,0.105646 -0.30939,0.166015 -0.16602,0.06037 -0.36222,0.09055 -0.18865,0.02264 -0.36976,0.02264 -0.21129,0 -0.50559,-0.03773 -0.28675,-0.03773 -0.59614,-0.143376 -0.3094,-0.113192 -0.61124,-0.309392 -0.30185,-0.203746 -0.53578,-0.52823 -0.23393,-0.33203 -0.38485,-0.792345 -0.14338,-0.467861 -0.14338,-1.116829 v -0.694245 q 0,-0.754615 0.18111,-1.282845 0.18865,-0.535776 0.47541,-0.882898 0.28675,-0.354669 0.64142,-0.550869 0.35467,-0.203746 0.69424,-0.301845 0.33958,-0.105646 0.62633,-0.128285 0.28676,-0.02264 0.44523,-0.02264 0.20374,0 0.52068,0.02264 0.31694,0.02264 0.66406,0.128285 0.35467,0.0981 0.70179,0.301845 0.35467,0.1962 0.63388,0.550869 0.2792,0.347122 0.45277,0.882898 0.1811,0.52823 0.1811,1.282845 z m -2.17329,-0.890445 q -0.0151,-0.249023 -0.11319,-0.445222 -0.083,-0.166015 -0.26411,-0.301846 -0.18111,-0.143377 -0.51314,-0.143377 -0.33203,0 -0.51314,0.143377 -0.18111,0.135831 -0.26411,0.301846 -0.0981,0.196199 -0.1132,0.445222 v 1.101737 q 0.0151,0.249023 0.1132,0.445222 0.083,0.173562 0.26411,0.309392 0.18111,0.135831 0.51314,0.135831 0.33203,0 0.51314,-0.135831 0.1811,-0.13583 0.26411,-0.309392 0.0981,-0.196199 0.11319,-0.445222 z"
|
||||||
|
id="text52"
|
||||||
|
style="font-size:15.4545px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-1px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="9" /><path
|
||||||
|
d="m 146.21384,68.364815 q -0.22559,0.205078 -0.49219,0.321289 -0.2666,0.116211 -0.62891,0.116211 -0.20508,0 -0.38281,-0.0752 -0.1709,-0.08203 -0.29394,-0.211914 -0.12305,-0.136718 -0.19825,-0.307617 -0.0684,-0.170898 -0.0684,-0.362304 0,-0.191407 0.0615,-0.328125 0.0615,-0.143555 0.1709,-0.246094 0.10937,-0.102539 0.25293,-0.184571 0.14355,-0.08203 0.30761,-0.170898 0.3418,-0.225586 0.6084,-0.458008 0.27344,-0.232422 0.48535,-0.430664 0.21192,-0.205078 0.36914,-0.348633 0.15723,-0.143554 0.27344,-0.198242 0.0684,-0.03418 0.12305,-0.05469 0.0615,-0.02734 0.12304,-0.03418 0.0615,-0.01367 0.13672,-0.01367 0.0752,-0.0068 0.19141,-0.0068 0.35547,0 0.56055,0.143555 0.21191,0.143555 0.31445,0.375976 0.10937,0.225586 0.13672,0.512696 0.0273,0.287109 0.0273,0.581054 v 6.34375 q 0,0.300782 -0.0273,0.594727 -0.0274,0.287109 -0.13672,0.512695 -0.10254,0.225586 -0.31445,0.369141 -0.20508,0.136719 -0.56055,0.136719 -0.36231,0 -0.56738,-0.136719 -0.20508,-0.143555 -0.31446,-0.369141 -0.10254,-0.225586 -0.12988,-0.512695 -0.0273,-0.293945 -0.0273,-0.594727 z m 3.00937,-0.259766 q 0,-0.663086 0.18457,-1.12793 0.19141,-0.471679 0.48535,-0.779296 0.29395,-0.307618 0.64942,-0.485352 0.35547,-0.177734 0.69043,-0.266602 0.34179,-0.08887 0.6084,-0.109375 0.27343,-0.02051 0.40332,-0.02051 h 0.23242 q 0.12988,0 0.40332,0.02051 0.27344,0.02051 0.60156,0.109375 0.33496,0.08887 0.68359,0.266602 0.35547,0.177734 0.64258,0.485352 0.29395,0.307617 0.47852,0.779296 0.18457,0.464844 0.18457,1.12793 v 4.033203 q 0,0.683594 -0.18457,1.16211 -0.18457,0.478515 -0.47852,0.799804 -0.28711,0.314453 -0.64258,0.492188 -0.34863,0.177734 -0.68359,0.273437 -0.32812,0.08887 -0.60156,0.109375 -0.27344,0.02051 -0.40332,0.02051 h -0.23242 q -0.12989,0 -0.40332,-0.02051 -0.26661,-0.02051 -0.6084,-0.109375 -0.33496,-0.0957 -0.69043,-0.273437 -0.35547,-0.177735 -0.64942,-0.492188 -0.29394,-0.321289 -0.48535,-0.799804 -0.18457,-0.478516 -0.18457,-1.16211 z m 2.24219,4.388672 q 0.0205,0.239258 0.12988,0.423828 0.0889,0.157227 0.2666,0.293945 0.18457,0.129883 0.50586,0.129883 0.31446,0 0.49219,-0.129883 0.17773,-0.136718 0.2666,-0.293945 0.10254,-0.18457 0.12988,-0.423828 v -4.621094 q -0.0273,-0.239258 -0.12988,-0.423828 -0.0889,-0.157226 -0.2666,-0.287109 -0.17773,-0.136719 -0.49219,-0.136719 -0.32129,0 -0.50586,0.136719 -0.17773,0.129883 -0.2666,0.287109 -0.10937,0.18457 -0.12988,0.423828 z"
|
||||||
|
id="text53"
|
||||||
|
style="font-size:14px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-0.6px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="10" /><path
|
||||||
|
d="m 165.96384,68.364815 q -0.22559,0.205078 -0.49219,0.321289 -0.2666,0.116211 -0.62891,0.116211 -0.20508,0 -0.38281,-0.0752 -0.1709,-0.08203 -0.29394,-0.211914 -0.12305,-0.136718 -0.19825,-0.307617 -0.0684,-0.170898 -0.0684,-0.362304 0,-0.191407 0.0615,-0.328125 0.0615,-0.143555 0.1709,-0.246094 0.10937,-0.102539 0.25293,-0.184571 0.14355,-0.08203 0.30761,-0.170898 0.3418,-0.225586 0.6084,-0.458008 0.27344,-0.232422 0.48535,-0.430664 0.21192,-0.205078 0.36914,-0.348633 0.15723,-0.143554 0.27344,-0.198242 0.0684,-0.03418 0.12305,-0.05469 0.0615,-0.02734 0.12304,-0.03418 0.0615,-0.01367 0.13672,-0.01367 0.0752,-0.0068 0.19141,-0.0068 0.35547,0 0.56055,0.143555 0.21191,0.143555 0.31445,0.375976 0.10937,0.225586 0.13672,0.512696 0.0273,0.287109 0.0273,0.581054 v 6.34375 q 0,0.300782 -0.0273,0.594727 -0.0274,0.287109 -0.13672,0.512695 -0.10254,0.225586 -0.31445,0.369141 -0.20508,0.136719 -0.56055,0.136719 -0.36231,0 -0.56738,-0.136719 -0.20508,-0.143555 -0.31446,-0.369141 -0.10254,-0.225586 -0.12988,-0.512695 -0.0273,-0.293945 -0.0273,-0.594727 z m 6.08554,-3.048828 q 0.77246,0 1.35352,0.211914 0.58789,0.205078 0.97754,0.581054 0.38965,0.369141 0.58789,0.888672 0.19824,0.512696 0.19824,1.134766 0,0.410156 -0.11621,0.758789 -0.10937,0.348633 -0.29395,0.635742 -0.17773,0.28711 -0.41015,0.519531 -0.23242,0.232422 -0.47168,0.410157 -0.57422,0.423828 -1.29199,0.683593 -0.23926,0.0957 -0.47852,0.232422 -0.23242,0.129883 -0.41699,0.307617 -0.18457,0.170899 -0.30078,0.403321 -0.11621,0.225586 -0.11621,0.519531 v 0.423828 h 2.3789 q 0.28711,0 0.57422,0.02734 0.28711,0.02734 0.51953,0.123047 0.23242,0.0957 0.37598,0.287109 0.14355,0.18457 0.14355,0.50586 0,0.328125 -0.14355,0.519531 -0.14356,0.191406 -0.37598,0.293945 -0.23242,0.102539 -0.51953,0.129883 -0.28711,0.02734 -0.57422,0.02734 h -3.40429 q -0.3418,0 -0.56739,-0.109375 -0.21875,-0.116211 -0.34863,-0.28711 -0.12988,-0.177734 -0.18457,-0.389648 -0.0479,-0.21875 -0.0479,-0.430664 v -1.09375 q 0,-0.526367 0.1709,-0.984375 0.17773,-0.464844 0.49218,-0.840821 0.32129,-0.382812 0.75879,-0.683593 0.44434,-0.300782 0.98438,-0.512696 0.54004,-0.211914 0.86133,-0.40332 0.32129,-0.198242 0.49218,-0.382812 0.17774,-0.191407 0.23243,-0.382813 0.0547,-0.191406 0.0547,-0.389648 0,-0.355469 -0.12304,-0.560547 -0.11621,-0.205078 -0.29395,-0.300781 -0.1709,-0.10254 -0.3623,-0.123047 -0.18457,-0.02734 -0.31446,-0.02734 -0.34179,0 -0.54687,0.102539 -0.20508,0.0957 -0.31445,0.246094 -0.10254,0.15039 -0.13672,0.334961 -0.0274,0.177734 -0.0274,0.341797 0,0.266601 -0.10254,0.458007 -0.10254,0.184571 -0.25976,0.300782 -0.15039,0.116211 -0.33496,0.170898 -0.17774,0.05469 -0.32813,0.05469 -0.46484,0 -0.75195,-0.25293 -0.28711,-0.259766 -0.28711,-0.663086 0,-0.177734 0.041,-0.458008 0.041,-0.280273 0.15722,-0.594726 0.11621,-0.314454 0.32813,-0.628907 0.21191,-0.314453 0.55371,-0.567383 0.34179,-0.252929 0.83398,-0.410156 0.49219,-0.157226 1.17578,-0.157226 z"
|
||||||
|
id="text1"
|
||||||
|
style="font-size:14px;line-height:1;font-family:'Concert One';-inkscape-font-specification:'Concert One, Normal';letter-spacing:-0.6px;word-spacing:5px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="12" /></g><g
|
||||||
|
id="layer2"
|
||||||
|
style="display:inline"><g
|
||||||
|
id="g57"
|
||||||
|
transform="matrix(1.6041667,0,0,1.6041667,30,31.604167)"
|
||||||
|
style="stroke-width:0.623377"><path
|
||||||
|
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.24675;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 0,-7 3.8,4 h -7.6 z"
|
||||||
|
id="path57" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.24675;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 0,-5 3,4 0,5 -3,4 Z"
|
||||||
|
id="path56" /></g><g
|
||||||
|
id="g59"
|
||||||
|
transform="matrix(1.6041667,0,0,-1.6041667,49.999833,28.395834)"
|
||||||
|
style="stroke-width:0.623377"><path
|
||||||
|
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.24675;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 0,-7 3.8,4 h -7.6 z"
|
||||||
|
id="path58" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.24675;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 0,-5 3,4 0,5 -3,4 Z"
|
||||||
|
id="path59" /><path
|
||||||
|
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.24675;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 0,-3.4155845 1.3234947,0.4155845 0,-0.44155834 -1.3234947,0.4155845 Z"
|
||||||
|
id="path60" /></g></g><g
|
||||||
|
id="layer1"><circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path54"
|
||||||
|
cx="10"
|
||||||
|
cy="10"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#fff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m8.92 1.99q3.29 0 4.68 1.13 1.39 1.1 1.39 2.74 0 2.06-1.78 3.36-.67.5-1.63.91l-.38.17q-.17.07-.34 1.01-.14.91-.14 1.32-.12.12-.7.29-.55.14-.94.14-.36 0-.55-.05-.26-.43-.26-1.87 0-1.44.12-1.85 3.79-.91 3.79-3.07 0-1.87-3.46-1.87-1.22 0-1.78.24-.14-.24-.14-1.01 0-.77.22-1.3.65-.29 1.9-.29zm-.7 15.5q-.46-.48-.46-1.15 0-.67.46-1.13.48-.48 1.15-.48.67 0 1.13.48.48.46.48 1.13 0 .67-.48 1.15-.46.46-1.13.46-.67 0-1.15-.46z"
|
||||||
|
id="path55" /><circle
|
||||||
|
style="opacity:1;fill:#c4693e;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle1"
|
||||||
|
cx="10"
|
||||||
|
cy="90"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 10,83.8 5.56,6.03 H 13.9 v 5.2 H 11.39 V 91.1 H 8.61 v 3.93 H 6.1 v -5.2 H 4.44 Z"
|
||||||
|
id="path1" /><circle
|
||||||
|
style="opacity:1;fill:#978e47;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle2"
|
||||||
|
cx="30"
|
||||||
|
cy="90"
|
||||||
|
r="10" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path1"
|
||||||
|
id="use2"
|
||||||
|
transform="translate(20)" /><circle
|
||||||
|
style="opacity:1;fill:#b44;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle3"
|
||||||
|
cx="50"
|
||||||
|
cy="90"
|
||||||
|
r="10" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path1"
|
||||||
|
id="use3"
|
||||||
|
transform="translate(40)" /><circle
|
||||||
|
style="opacity:1;fill:#3fa5ff;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle4"
|
||||||
|
cx="10"
|
||||||
|
cy="110"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 10,102 c -1.02,2.01 -7.08,14.38 0,14.38 7.08,0 1.02,-12.46 0,-14.38 z"
|
||||||
|
id="path4" /><circle
|
||||||
|
style="opacity:1;fill:#202020;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle5"
|
||||||
|
cx="30"
|
||||||
|
cy="110"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 30.75,102.98 -2.9,1.04 -2.21,3.37 0.1,0.15 1.34,-0.48 3.06,1.97 0.33,-0.43 3.2,-1.2 0.98,0.63 0.29,-0.82 -1.29,-2.24 z m -3.68,4.62 -2.89,1.04 -2.22,3.37 1.53,3.32 h 6.78 l 0.99,-3.5 -1.3,-2.25 z m 6.61,0.47 -2.9,1.04 -0.27,0.4 0.17,0.13 1.22,2.21 -0.91,3.48 h 5.88 l 0.99,-3.02 -1.3,-2.25 z"
|
||||||
|
id="path5" /><circle
|
||||||
|
style="opacity:1;fill:#c02c2c;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle6"
|
||||||
|
cx="50"
|
||||||
|
cy="110"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 51.389932,101.42993 c -0.2,-0.09 -0.42,0 -0.51,0.2 l -6.66,15.25 c -0.09,0.2 0,0.42 0.2,0.5 0.2,0.09 0.42,0 0.51,-0.2 l 6.66,-15.25 c 0.09,-0.2 0,-0.42 -0.2,-0.51 z m 0.53,0.93 -2.39,5.48 c 0.21,0 0.42,0 0.62,0.01 0.2,0.01 0.41,0.02 0.61,0.03 0.2,0.01 0.4,0.03 0.6,0.05 0.2,0.02 0.39,0.04 0.59,0.06 0.19,0.02 0.39,0.05 0.58,0.08 0.19,0.03 0.38,0.06 0.57,0.1 0.09,0.02 0.18,0.04 0.28,0.05 l 2.12,-2.56 c -0.01,-0.01 -0.02,-0.03 -0.04,-0.05 -0.15,-0.15 -0.28,-0.31 -0.41,-0.47 -0.14,-0.15 -0.27,-0.31 -0.41,-0.46 -0.14,-0.15 -0.28,-0.29 -0.42,-0.44 -0.14,-0.14 -0.29,-0.28 -0.43,-0.42 -0.15,-0.14 -0.3,-0.27 -0.45,-0.4 -0.07,-0.07 -0.15,-0.13 -0.22,-0.19 -0.08,-0.07 -0.16,-0.13 -0.24,-0.19 -0.07,-0.06 -0.15,-0.12 -0.23,-0.18 -0.08,-0.06 -0.16,-0.12 -0.24,-0.17 -0.08,-0.06 -0.16,-0.12 -0.25,-0.17 -0.08,-0.05 -0.16,-0.11 -0.24,-0.16 z m 3.37,4.06 -2.12,2.56 c 0.1,0.02 0.19,0.04 0.29,0.06 0.19,0.04 0.37,0.08 0.55,0.13 0.18,0.04 0.37,0.09 0.55,0.14 0.18,0.05 0.36,0.1 0.54,0.15 0.18,0.05 0.36,0.1 0.53,0.16 0.18,0.05 0.35,0.11 0.53,0.17 0.18,0.06 0.35,0.12 0.53,0.17 0.17,0.06 0.35,0.12 0.52,0.18 0.35,0.12 0.69,0.25 1.04,0.37 -0.25,-0.36 -0.49,-0.72 -0.74,-1.07 -0.24,-0.35 -0.49,-0.7 -0.73,-1.05 -0.13,-0.17 -0.25,-0.34 -0.38,-0.51 -0.12,-0.18 -0.25,-0.35 -0.38,-0.52 -0.12,-0.16 -0.25,-0.33 -0.38,-0.5 -0.11,-0.15 -0.23,-0.29 -0.35,-0.44 z"
|
||||||
|
id="path6" /><circle
|
||||||
|
style="opacity:1;fill:#4f54e9;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle7"
|
||||||
|
cx="70"
|
||||||
|
cy="110"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 69.25,117.9 v -1.55 c -0.96,-0.09 -1.5,-0.44 -2.13,-1.04 -0.63,-0.6 -0.98,-1.45 -1.06,-2.56 l 2.2,-0.49 c 0.03,0.65 0.21,1.14 0.54,1.49 0.33,0.35 0.75,0.52 1.24,0.52 0.47,0 0.81,-0.13 1.03,-0.4 0.23,-0.27 0.34,-0.55 0.34,-0.85 0,-0.39 -0.11,-0.71 -0.34,-0.94 -0.23,-0.24 -0.52,-0.46 -0.88,-0.65 l -1.53,-0.81 c -0.75,-0.39 -1.33,-0.87 -1.76,-1.42 -0.42,-0.55 -0.63,-1.28 -0.63,-2.18 0,-0.65 0.14,-1.22 0.41,-1.71 0.29,-0.51 0.67,-0.91 1.15,-1.21 0.49,-0.3 0.8,-0.49 1.42,-0.56 v -1.44 h 1.65 v 1.48 c 0.91,0.12 1.41,0.49 1.94,1.1 0.53,0.6 0.82,1.39 0.88,2.36 l -2.07,0.43 c -0.03,-0.6 -0.2,-1.06 -0.5,-1.39 -0.29,-0.33 -0.65,-0.5 -1.08,-0.5 -0.41,0 -0.74,0.12 -0.99,0.36 -0.24,0.23 -0.36,0.54 -0.36,0.94 0,0.36 0.11,0.65 0.32,0.86 0.21,0.21 0.51,0.42 0.88,0.63 l 1.63,0.86 c 0.83,0.45 1.43,0.95 1.82,1.51 0.39,0.55 0.58,1.23 0.58,2.02 0,0.6 -0.13,1.16 -0.4,1.67 -0.25,0.51 -0.63,0.95 -1.12,1.3 -0.48,0.33 -0.84,0.54 -1.53,0.63 v 1.4 z"
|
||||||
|
id="path7" /><circle
|
||||||
|
style="opacity:1;fill:#8b5dd7;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle8"
|
||||||
|
cx="90"
|
||||||
|
cy="110"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 90,102.88 -7.02,3.54 v 8.68 h 2.55 v -6.19 h 8.94 v 6.19 h 2.55 v -8.68 z"
|
||||||
|
id="path8" /><circle
|
||||||
|
style="opacity:1;fill:#239a96;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle9"
|
||||||
|
cx="10"
|
||||||
|
cy="130"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 8.92,121.99 q 3.29,0 4.68,1.13 1.39,1.1 1.39,2.74 0,2.06 -1.78,3.36 -0.67,0.5 -1.63,0.91 l -0.38,0.17 q -0.17,0.07 -0.34,1.01 -0.14,0.91 -0.14,1.32 -0.12,0.12 -0.7,0.29 -0.55,0.14 -0.94,0.14 -0.36,0 -0.55,-0.05 -0.26,-0.43 -0.26,-1.87 0,-1.44 0.12,-1.85 3.79,-0.91 3.79,-3.07 0,-1.87 -3.46,-1.87 -1.22,0 -1.78,0.24 -0.14,-0.24 -0.14,-1.01 0,-0.77 0.22,-1.3 0.65,-0.29 1.9,-0.29 z m -0.7,15.5 q -0.46,-0.48 -0.46,-1.15 0,-0.67 0.46,-1.13 0.48,-0.48 1.15,-0.48 0.67,0 1.13,0.48 0.48,0.46 0.48,1.13 0,0.67 -0.48,1.15 -0.46,0.46 -1.13,0.46 -0.67,0 -1.15,-0.46 z"
|
||||||
|
id="path9" /><circle
|
||||||
|
style="opacity:1;fill:#239a96;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle10"
|
||||||
|
cx="30"
|
||||||
|
cy="130"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 32.879599,122.82 c -0.1,0.01 -0.2,0.05 -0.28,0.13 l -2.19,2.19 c -0.15,0.16 -0.17,0.39 -0.03,0.53 l 1.12,1.12 c 0.29,-0.29 0.37,0.07 0.57,0.58 l -1.61,1.6 1.77,1.72 1.7,-1.7 c 0.44,0.03 0.82,-0.06 0.99,0.11 0.22,0.22 0.19,0.59 -0.06,0.85 l -0.02,0.02 c 1.48,1.26 3.85,-1.11 2.59,-2.59 l -0.02,0.02 c -0.25,0.25 -0.63,0.28 -0.85,0.06 -0.3,-0.3 0.23,-1.31 -0.61,-2.15 l -0.1,-0.1 c -0.73,-0.74 -2.07,-0.7 -1.6,-1.18 l -1.12,-1.12 c -0.06,-0.06 -0.16,-0.09 -0.25,-0.09 z m -7.25,0.86 c -0.28,0 -0.55,0.05 -0.83,0.14 l 2.02,2.02 -1.85,1.86 -2.02,-2.02 c -0.72,2.23 1.45,4.34 3.67,3.55 l 7.27,7.27 c 0.46,0.47 1.22,0.47 1.71,-0.02 0.49,-0.49 0.5,-1.25 0.03,-1.72 l -7.27,-7.27 c 0.69,-1.94 -0.84,-3.84 -2.73,-3.81 z m 2.41,7.72 -3.36,3.35 c -0.47,0.47 -0.47,1.23 0.02,1.72 0.49,0.49 1.25,0.49 1.72,0.02 l 3.38,-3.38 z"
|
||||||
|
id="path10" /><circle
|
||||||
|
style="opacity:1;fill:#239a96;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle11"
|
||||||
|
cx="50"
|
||||||
|
cy="130"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 52.669556,122.92968 c -0.5,-0.01 -1,0.09 -1.46,0.31 l -1.35,0.64 -0.1,-0.22 -2.12,1.01 -0.46,-0.65 c -0.09,-0.13 -0.26,-0.16 -0.39,-0.07 l -1.24,0.85 c -0.12,0.09 -0.15,0.27 -0.07,0.4 l 0.39,0.55 -0.36,0.47 -2.81,4.07 c -0.2,0.3 -0.18,0.7 0.06,0.97 -0.4,0.74 -0.49,1.54 -0.3,2.26 0.22,0.86 0.77,1.6 1.5,2.16 1.46,1.12 3.68,1.56 5.63,0.5 1.07,-0.59 2.19,-0.79 2.99,-0.64 0.8,0.14 1.26,0.52 1.39,1.32 0.05,0.33 0.36,0.55 0.69,0.5 0.33,-0.05 0.55,-0.36 0.5,-0.69 -0.2,-1.27 -1.2,-2.1 -2.36,-2.31 -1.16,-0.21 -2.51,0.08 -3.78,0.77 -1.49,0.82 -3.22,0.47 -4.33,-0.39 -0.55,-0.42 -0.93,-0.97 -1.07,-1.51 -0.1,-0.4 -0.09,-0.81 0.11,-1.24 l 1.39,0.96 c 0.81,0.56 1.93,0.36 2.49,-0.46 l 2.8,-4.03 -0.53,-2.86 0.65,-0.31 -0.11,-0.24 1.34,-0.63 c 0.44,-0.21 0.94,-0.25 1.41,-0.1 l 3.54,1.12 0.39,-1.24 -3.54,-1.12 c -0.29,-0.09 -0.59,-0.14 -0.89,-0.15 z m 4.24,3.31 c -0.39,0.63 -2.7,4.48 0,4.48 2.7,0 0.39,-3.88 0,-4.48 z m -10,1.23 1.31,0.45 -1.02,0.66 c -0.04,0.03 -0.08,0.06 -0.11,0.11 l -1.55,2.46 c -0.1,0.16 -0.05,0.38 0.11,0.48 0.16,0.1 0.38,0.05 0.48,-0.11 l 1.51,-2.4 1.3,-0.83 c 0.24,0.29 0.25,0.71 0.02,1.03 l -1.52,2.2 c -0.52,0.75 -1.51,0.96 -2.22,0.47 l -0.86,-0.59 z"
|
||||||
|
id="path11" /><circle
|
||||||
|
style="opacity:1;fill:#239a96;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle12"
|
||||||
|
cx="70"
|
||||||
|
cy="130"
|
||||||
|
r="10" /><path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 67.96,122.6 h 4.56 l -1.97,5.8 h 3.02 l -4.96,9.96 0.99,-8.11 h -2.34 z"
|
||||||
|
id="path12" /><circle
|
||||||
|
style="opacity:1;fill:#b13204;fill-opacity:1;stroke:none;stroke-width:1.99998;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle13"
|
||||||
|
cx="110"
|
||||||
|
cy="110"
|
||||||
|
r="10" /><path
|
||||||
|
id="path13"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="m 115.6875,105.5 -0.125,2.5625 -2.5625,0.0625 -0.875,1.1875 0.875,-0.0625 -2.07583,2.73928 0.45267,-2.13259 -1.08081,0.0183 0.37814,-1.37814 -3.61167,0.19064 L 107,106.5 l 0.4375,0.0625 0.125,-0.9375 -5.25,0.375 0.8125,6.5625 12.6875,-0.4375 -0.125,1.5625 h 2.125 L 117.25,111.5 l 0.4375,-3.5625 h -0.875 l 0.25,-2.25 z m -9.48828,1.14062 0.0879,2.1211 -2.29883,0.13281 -0.4414,-1.94531 z m 8.17578,5.98438 c -0.51777,0 -0.9375,0.4757 -0.9375,1.0625 0,0.5868 0.41973,1.0625 0.9375,1.0625 0.51777,0 0.9375,-0.4757 0.9375,-1.0625 0,-0.5868 -0.41973,-1.0625 -0.9375,-1.0625 z m -2.125,0.0625 c -0.5868,0 -1.0625,0.51767 -1.0625,1.15625 0,0.63858 0.4757,1.15625 1.0625,1.15625 0.5868,0 1.0625,-0.51767 1.0625,-1.15625 0,-0.63858 -0.4757,-1.15625 -1.0625,-1.15625 z m -2.65625,0.125 c -0.63858,0 -1.15625,0.51767 -1.15625,1.15625 0,0.63858 0.51767,1.15625 1.15625,1.15625 0.63858,0 1.15625,-0.51767 1.15625,-1.15625 0,-0.63858 -0.51767,-1.15625 -1.15625,-1.15625 z m -2.625,0.25 c -0.63858,0 -1.15625,0.48969 -1.15625,1.09375 0,0.60406 0.51767,1.09375 1.15625,1.09375 0.63858,0 1.15625,-0.48969 1.15625,-1.09375 0,-0.60406 -0.51767,-1.09375 -1.15625,-1.09375 z m 9.125,0.75 c -0.25888,0 -0.46875,0.22386 -0.46875,0.5 0,0.27614 0.20987,0.5 0.46875,0.5 0.25888,0 0.46875,-0.22386 0.46875,-0.5 0,-0.27614 -0.20987,-0.5 -0.46875,-0.5 z m -11.9375,0.5 c -0.25888,0 -0.46875,0.22386 -0.46875,0.5 0,0.27614 0.20987,0.5 0.46875,0.5 0.25888,0 0.46875,-0.22386 0.46875,-0.5 0,-0.27614 -0.20987,-0.5 -0.46875,-0.5 z" /></g></svg>
|
||||||
|
After Width: | Height: | Size: 41 KiB |
+106
@@ -107,6 +107,7 @@
|
|||||||
{
|
{
|
||||||
"name":"Olaf's Garage",
|
"name":"Olaf's Garage",
|
||||||
"type":"garage",
|
"type":"garage",
|
||||||
|
"description":"DM1U-150 Utility Rail Vehicle\nKey sold at Machine Factory's Shop",
|
||||||
"position":{"x":10448.56,"y":134.9,"z":1331.074}
|
"position":{"x":10448.56,"y":134.9,"z":1331.074}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -135,6 +136,39 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type":"shop",
|
"type":"shop",
|
||||||
|
"stock":[
|
||||||
|
"Boombox",
|
||||||
|
"Red Beacon",
|
||||||
|
"Plastic Crate",
|
||||||
|
"Cassette A7",
|
||||||
|
"Cassette P6",
|
||||||
|
"Cassette P9",
|
||||||
|
"Red Light Bar",
|
||||||
|
"File Box",
|
||||||
|
"Purple Flag Marker",
|
||||||
|
"Reginald's Garage Key",
|
||||||
|
"Cassette P10",
|
||||||
|
"Cassette P5",
|
||||||
|
"Cassette P7",
|
||||||
|
"Handheld Game Console",
|
||||||
|
"Wooden Crate",
|
||||||
|
"Cassette A1",
|
||||||
|
"Cassette P2",
|
||||||
|
"Yellow Flag Marker",
|
||||||
|
"Green Flag Marker",
|
||||||
|
"Orange Flag Marker",
|
||||||
|
"Cyan Flag Marker",
|
||||||
|
"Cassette P4",
|
||||||
|
"Green Light Bar",
|
||||||
|
"Cassette P1",
|
||||||
|
"Blue Flag Marker",
|
||||||
|
"Cassette P8",
|
||||||
|
"White Flag Marker",
|
||||||
|
"Red Flag Marker",
|
||||||
|
"Cassette A2",
|
||||||
|
"Blue Beacon",
|
||||||
|
"Cassette P3"
|
||||||
|
],
|
||||||
"position":{"x":1911.48,"y":122.26,"z":5788.65}
|
"position":{"x":1911.48,"y":122.26,"z":5788.65}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -164,6 +198,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type":"shop",
|
"type":"shop",
|
||||||
|
"stock":[
|
||||||
|
"Cassette A12",
|
||||||
|
"Cassette A15",
|
||||||
|
"Cassette A6",
|
||||||
|
"Cassette A3",
|
||||||
|
"Old Bob's Garage Key"
|
||||||
|
],
|
||||||
"position":{"x":9528.669,"y":119.3432,"z":13419.99}
|
"position":{"x":9528.669,"y":119.3432,"z":13419.99}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -248,6 +289,30 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type":"shop",
|
"type":"shop",
|
||||||
|
"stock":[
|
||||||
|
"Shelf",
|
||||||
|
"Rotary Controller",
|
||||||
|
"Analog Controller",
|
||||||
|
"Cassette A16",
|
||||||
|
"Crimping Tool",
|
||||||
|
"Blue Light Bar",
|
||||||
|
"Brake Cylinder LED Bar",
|
||||||
|
"Electric Hand Drill",
|
||||||
|
"Digital Speedometer",
|
||||||
|
"Golden Shovel",
|
||||||
|
"Infrared Thermometer",
|
||||||
|
"Button Controller",
|
||||||
|
"Filler Gun",
|
||||||
|
"Sun Visor",
|
||||||
|
"Cassette A10",
|
||||||
|
"Expert Shovel",
|
||||||
|
"Digital Clock",
|
||||||
|
"Alternating Controller",
|
||||||
|
"White Light Bar",
|
||||||
|
"Soldering Gun",
|
||||||
|
"Clinometer",
|
||||||
|
"Cassette A8"
|
||||||
|
],
|
||||||
"position":{"x":13035.07,"y":140.1661,"z":11158.79}
|
"position":{"x":13035.07,"y":140.1661,"z":11158.79}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -286,6 +351,20 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type":"shop",
|
"type":"shop",
|
||||||
|
"stock":[
|
||||||
|
"Plastic Crate",
|
||||||
|
"Steve's Garage Key",
|
||||||
|
"Wooden Crate",
|
||||||
|
"Red Beacon",
|
||||||
|
"Steam Locomotive Checklist",
|
||||||
|
"File Box",
|
||||||
|
"Cassette A11",
|
||||||
|
"Purple Light Bar",
|
||||||
|
"Cassette A4",
|
||||||
|
"Pocketwatch",
|
||||||
|
"Blue Beacon",
|
||||||
|
"Cyan Light Bar"
|
||||||
|
],
|
||||||
"position":{"x":13423.26,"y":113.1099,"z":3611.852}
|
"position":{"x":13423.26,"y":113.1099,"z":3611.852}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -396,6 +475,30 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type":"shop",
|
"type":"shop",
|
||||||
|
"stock":[
|
||||||
|
"Amber Beacon",
|
||||||
|
"Headlight",
|
||||||
|
"Button Controller",
|
||||||
|
"Automatic Train Stop",
|
||||||
|
"Analog Controller",
|
||||||
|
"Cassette A13",
|
||||||
|
"Rotary Controller",
|
||||||
|
"Locomotive Remote",
|
||||||
|
"Alternating Controller",
|
||||||
|
"Olaf's Garage Key",
|
||||||
|
"Demonstrator Paint Can",
|
||||||
|
"Yellow Light Bar",
|
||||||
|
"Wireless MU Controller",
|
||||||
|
"Anti-Wheelslip Computer",
|
||||||
|
"Overheat Protection",
|
||||||
|
"Cassette A14",
|
||||||
|
"Orange Light Bar",
|
||||||
|
"Cassette A9",
|
||||||
|
"Distance Tracker",
|
||||||
|
"Amp Limiter",
|
||||||
|
"Switch Setter",
|
||||||
|
"Cassette A5"
|
||||||
|
],
|
||||||
"position":{"x":2236.745,"y":159.266,"z":10834.23}
|
"position":{"x":2236.745,"y":159.266,"z":10834.23}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -525,16 +628,19 @@
|
|||||||
{
|
{
|
||||||
"name":"Old Bob's Garage",
|
"name":"Old Bob's Garage",
|
||||||
"type":"garage",
|
"type":"garage",
|
||||||
|
"description":"BE2 Microshunter\nKey sold at Food Factory's Shop",
|
||||||
"position":{"x":1590.981,"y":137.4275,"z":12227.22}
|
"position":{"x":1590.981,"y":137.4275,"z":12227.22}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"Reginald's Garage",
|
"name":"Reginald's Garage",
|
||||||
"type":"garage",
|
"type":"garage",
|
||||||
|
"description":"Caboose\nKey sold at City West's Shop",
|
||||||
"position":{"x":4387.325,"y":147.84,"z":2458.901}
|
"position":{"x":4387.325,"y":147.84,"z":2458.901}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"Steve's Garage",
|
"name":"Steve's Garage",
|
||||||
"type":"garage",
|
"type":"garage",
|
||||||
|
"description":"DE6 Slug\nKey sold at Harbor's Shop",
|
||||||
"position":{"x":14527.17,"y":163.7,"z":2365.416}
|
"position":{"x":14527.17,"y":163.7,"z":2365.416}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ a:visited{
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel hr {
|
||||||
|
border: 0px;
|
||||||
|
border-bottom: 2px solid #b3b3b396;
|
||||||
|
}
|
||||||
|
|
||||||
#topleft{
|
#topleft{
|
||||||
position:fixed;
|
position:fixed;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
@@ -182,4 +187,39 @@ button{
|
|||||||
width: var(--legendButtonSize);
|
width: var(--legendButtonSize);
|
||||||
height: var(--legendButtonSize);
|
height: var(--legendButtonSize);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.signText {
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelog {
|
||||||
|
width: fit-content;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tooltip{
|
||||||
|
position: fixed;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
pointer-events: none;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
#tooltip h1{
|
||||||
|
font-variation-settings: "wght" 600;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1em;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
padding: 0 4px 4px 4px;
|
||||||
|
}
|
||||||
|
#tooltip h2{
|
||||||
|
font-variation-settings: "wght" 600;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 1em;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
opacity: 0.7;
|
||||||
|
border-bottom: 2px solid #b3b3b396;
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 386 KiB |
Reference in new issue
Block a user