Geo_test.res.mjs
1// Generated by ReScript, PLEASE EDIT WITH CARE
2
3import * as Geo from "../src/lib/Geo.res.mjs";
4import * as Vitest from "vitest";
5import * as Core__Option from "@rescript/core/lib/es6/src/Core__Option.res.mjs";
6import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
7
8function makeRoute(id, d, t, param) {
9 return {
10 id: id,
11 d: d,
12 t: t,
13 bbox: undefined
14 };
15}
16
17function makeWaypoint(id, pointOpt, fromOpt, labelOpt, gidOpt, countryOpt, consOpt, nonroutableOpt, errorOpt, param) {
18 let point = pointOpt !== undefined ? pointOpt : [
19 0.0,
20 0.0
21 ];
22 let from = fromOpt !== undefined ? Primitive_option.valFromOption(fromOpt) : undefined;
23 let label = labelOpt !== undefined ? labelOpt : "";
24 let gid = gidOpt !== undefined ? gidOpt : "";
25 let country = countryOpt !== undefined ? countryOpt : "";
26 let cons = consOpt !== undefined ? consOpt : [];
27 let nonroutable = nonroutableOpt !== undefined ? nonroutableOpt : false;
28 let error = errorOpt !== undefined ? Primitive_option.valFromOption(errorOpt) : undefined;
29 return {
30 id: id,
31 point: point,
32 from: from,
33 label: label,
34 gid: gid,
35 country: country,
36 cons: cons,
37 nonroutable: nonroutable,
38 error: error
39 };
40}
41
42function makeLineGeoJSON(coords) {
43 return Object.fromEntries([
44 [
45 "type",
46 "Feature"
47 ],
48 [
49 "geometry",
50 Object.fromEntries([
51 [
52 "type",
53 "LineString"
54 ],
55 [
56 "coordinates",
57 coords.map(param => [
58 param[0],
59 param[1]
60 ])
61 ]
62 ])
63 ],
64 [
65 "properties",
66 {}
67 ]
68 ]);
69}
70
71function makeLineGeoJSONWithProps(coords, distance, time) {
72 return Object.fromEntries([
73 [
74 "type",
75 "Feature"
76 ],
77 [
78 "geometry",
79 Object.fromEntries([
80 [
81 "type",
82 "LineString"
83 ],
84 [
85 "coordinates",
86 coords.map(param => [
87 param[0],
88 param[1]
89 ])
90 ]
91 ])
92 ],
93 [
94 "properties",
95 Object.fromEntries([
96 [
97 "distance",
98 distance
99 ],
100 [
101 "time",
102 time
103 ]
104 ])
105 ]
106 ]);
107}
108
109let mapEntries = ((map) => Array.from(map.entries()));
110
111function stringArraysEqual(a, b) {
112 if (a.length !== b.length) {
113 return false;
114 }
115 let _idx = 0;
116 while (true) {
117 let idx = _idx;
118 if (idx >= a.length) {
119 return true;
120 }
121 if (a[idx] !== b[idx]) {
122 return false;
123 }
124 _idx = idx + 1 | 0;
125 continue;
126 };
127}
128
129Vitest.describe("Geo.getDistance", () => {
130 Vitest.test("linear path: calculates fromPreviousWaypoint and single fromStart path", ctx => {
131 let waypoints = [
132 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
133 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
134 "A",
135 {
136 id: "route-ab",
137 d: 100.0,
138 t: undefined,
139 bbox: undefined
140 }
141 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
142 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
143 "B",
144 {
145 id: "route-bc",
146 d: 50.0,
147 t: undefined,
148 bbox: undefined
149 }
150 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
151 ];
152 let geojson = makeLineGeoJSONWithProps([
153 [
154 0.0,
155 0.0
156 ],
157 [
158 1.0,
159 0.0
160 ]
161 ], 111.19, 0.0);
162 let result = Geo.getDistance([
163 0.5,
164 0.0
165 ], "route-bc", waypoints, geojson);
166 ctx.expect(result.fromPreviousWaypoint).toBeGreaterThan(0.0);
167 let entries = mapEntries(result.fromStart);
168 ctx.expect(entries.length).toBe(1);
169 let match = entries[0];
170 if (match !== undefined) {
171 ctx.expect(stringArraysEqual(match[0], [
172 "A",
173 "B"
174 ])).toBe(true);
175 ctx.expect(match[1]).toBe(100.0 + result.fromPreviousWaypoint);
176 } else {
177 ctx.expect("should have one entry").toBe("");
178 }
179 ctx.expect(result.toNextWaypoint).toBeGreaterThan(0.0);
180 ctx.expect(result.toNextWaypoint).toBeLessThan(111.2);
181 let total = result.fromPreviousWaypoint + result.toNextWaypoint;
182 ctx.expect(total).toBeGreaterThan(111.0);
183 ctx.expect(total).toBeLessThan(111.3);
184 });
185 Vitest.test("toNextWaypoint calculates remaining distance correctly", ctx => {
186 let waypoints = [
187 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
188 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
189 "A",
190 {
191 id: "route-ab",
192 d: 100.0,
193 t: undefined,
194 bbox: undefined
195 }
196 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
197 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
198 "B",
199 {
200 id: "route-bc",
201 d: 50.0,
202 t: undefined,
203 bbox: undefined
204 }
205 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
206 ];
207 let geojson = makeLineGeoJSONWithProps([
208 [
209 0.0,
210 0.0
211 ],
212 [
213 1.0,
214 0.0
215 ]
216 ], 111.19, 0.0);
217 let result = Geo.getDistance([
218 0.5,
219 0.0
220 ], "route-bc", waypoints, geojson);
221 let diff = Math.abs(result.fromPreviousWaypoint - result.toNextWaypoint);
222 ctx.expect(diff).toBeLessThan(1.0);
223 let total = result.fromPreviousWaypoint + result.toNextWaypoint;
224 ctx.expect(total).toBeGreaterThan(111.0);
225 ctx.expect(total).toBeLessThan(111.3);
226 });
227 Vitest.test("merge path: two routes to source waypoint", ctx => {
228 let waypoints = [
229 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
230 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
231 "A",
232 {
233 id: "route-ab",
234 d: 100.0,
235 t: undefined,
236 bbox: undefined
237 }
238 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
239 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
240 "B",
241 {
242 id: "route-bc",
243 d: 30.0,
244 t: undefined,
245 bbox: undefined
246 }
247 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
248 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([
249 [
250 "B",
251 {
252 id: "route-bd",
253 d: 60.0,
254 t: undefined,
255 bbox: undefined
256 }
257 ],
258 [
259 "C",
260 {
261 id: "route-cd",
262 d: 20.0,
263 t: undefined,
264 bbox: undefined
265 }
266 ]
267 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
268 makeWaypoint("E", undefined, Primitive_option.some(Object.fromEntries([[
269 "D",
270 {
271 id: "route-de",
272 d: 40.0,
273 t: undefined,
274 bbox: undefined
275 }
276 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
277 ];
278 let geojson = makeLineGeoJSON([
279 [
280 0.0,
281 0.0
282 ],
283 [
284 0.5,
285 0.0
286 ]
287 ]);
288 let result = Geo.getDistance([
289 0.25,
290 0.0
291 ], "route-de", waypoints, geojson);
292 let entries = mapEntries(result.fromStart);
293 ctx.expect(entries.length).toBe(2);
294 let findEntry = (expectedPath, expectedDist) => entries.find(param => {
295 if (stringArraysEqual(param[0], expectedPath)) {
296 return Math.abs(param[1] - expectedDist) < 0.0001;
297 } else {
298 return false;
299 }
300 });
301 ctx.expect(Core__Option.isSome(findEntry([
302 "A",
303 "B",
304 "D"
305 ], 160.0 + result.fromPreviousWaypoint))).toBe(true);
306 ctx.expect(Core__Option.isSome(findEntry([
307 "A",
308 "B",
309 "C",
310 "D"
311 ], 150.0 + result.fromPreviousWaypoint))).toBe(true);
312 });
313 Vitest.test("cycle detection: skips cyclic paths", ctx => {
314 let waypoints = [
315 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
316 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([
317 [
318 "A",
319 {
320 id: "route-ab",
321 d: 100.0,
322 t: undefined,
323 bbox: undefined
324 }
325 ],
326 [
327 "C",
328 {
329 id: "route-cb",
330 d: 50.0,
331 t: undefined,
332 bbox: undefined
333 }
334 ]
335 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
336 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
337 "B",
338 {
339 id: "route-bc",
340 d: 30.0,
341 t: undefined,
342 bbox: undefined
343 }
344 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
345 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([[
346 "B",
347 {
348 id: "route-bd",
349 d: 20.0,
350 t: undefined,
351 bbox: undefined
352 }
353 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
354 ];
355 let geojson = makeLineGeoJSON([
356 [
357 0.0,
358 0.0
359 ],
360 [
361 0.5,
362 0.0
363 ]
364 ]);
365 let result = Geo.getDistance([
366 0.25,
367 0.0
368 ], "route-bd", waypoints, geojson);
369 let entries = mapEntries(result.fromStart);
370 ctx.expect(entries.length).toBe(1);
371 let match = entries.find(param => stringArraysEqual(param[0], [
372 "A",
373 "B"
374 ]));
375 let hasValidPath = match !== undefined;
376 ctx.expect(hasValidPath).toBe(true);
377 });
378 Vitest.test("missing route hash: returns zero/empty result", ctx => {
379 let waypoints = [
380 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
381 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
382 "A",
383 {
384 id: "route-ab",
385 d: 100.0,
386 t: undefined,
387 bbox: undefined
388 }
389 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
390 ];
391 let geojson = makeLineGeoJSON([
392 [
393 0.0,
394 0.0
395 ],
396 [
397 1.0,
398 0.0
399 ]
400 ]);
401 let result = Geo.getDistance([
402 0.5,
403 0.0
404 ], "nonexistent-route", waypoints, geojson);
405 ctx.expect(result.fromPreviousWaypoint).toBe(0.0);
406 ctx.expect(result.fromStart.size).toBe(0);
407 });
408 Vitest.test("origin only: hover on first segment", ctx => {
409 let waypoints = [makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)];
410 let geojson = makeLineGeoJSON([
411 [
412 0.0,
413 0.0
414 ],
415 [
416 1.0,
417 0.0
418 ]
419 ]);
420 let result = Geo.getDistance([
421 0.5,
422 0.0
423 ], "any-route", waypoints, geojson);
424 ctx.expect(result.fromPreviousWaypoint).toBe(0.0);
425 ctx.expect(result.fromStart.size).toBe(0);
426 });
427 Vitest.test("route keys with :saa suffix (auto-added routes)", ctx => {
428 let waypoints = [
429 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
430 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
431 "A:saa",
432 {
433 id: "route-ab",
434 d: 100.0,
435 t: undefined,
436 bbox: undefined
437 }
438 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
439 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
440 "B:saa",
441 {
442 id: "route-bc",
443 d: 50.0,
444 t: undefined,
445 bbox: undefined
446 }
447 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
448 ];
449 let geojson = makeLineGeoJSON([
450 [
451 0.0,
452 0.0
453 ],
454 [
455 1.0,
456 0.0
457 ]
458 ]);
459 let result = Geo.getDistance([
460 0.5,
461 0.0
462 ], "route-bc", waypoints, geojson);
463 ctx.expect(result.fromPreviousWaypoint).toBeGreaterThan(0.0);
464 let entries = mapEntries(result.fromStart);
465 ctx.expect(entries.length).toBe(1);
466 let match = entries[0];
467 if (match !== undefined) {
468 ctx.expect(stringArraysEqual(match[0], [
469 "A",
470 "B"
471 ])).toBe(true);
472 ctx.expect(match[1]).toBe(100.0 + result.fromPreviousWaypoint);
473 } else {
474 ctx.expect("should have one entry").toBe("");
475 }
476 });
477 Vitest.test("route keys with adventure constraint suffix", ctx => {
478 let waypoints = [
479 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
480 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
481 "A:adv(80)",
482 {
483 id: "route-ab",
484 d: 120.0,
485 t: undefined,
486 bbox: undefined
487 }
488 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
489 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
490 "B:adv(80)",
491 {
492 id: "route-bc",
493 d: 60.0,
494 t: undefined,
495 bbox: undefined
496 }
497 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
498 ];
499 let geojson = makeLineGeoJSON([
500 [
501 0.0,
502 0.0
503 ],
504 [
505 1.0,
506 0.0
507 ]
508 ]);
509 let result = Geo.getDistance([
510 0.5,
511 0.0
512 ], "route-bc", waypoints, geojson);
513 let entries = mapEntries(result.fromStart);
514 ctx.expect(entries.length).toBe(1);
515 let match = entries[0];
516 if (match !== undefined) {
517 ctx.expect(stringArraysEqual(match[0], [
518 "A",
519 "B"
520 ])).toBe(true);
521 ctx.expect(match[1]).toBe(120.0 + result.fromPreviousWaypoint);
522 } else {
523 ctx.expect("should have one entry").toBe("");
524 }
525 });
526 Vitest.test("route keys with multiple constraints", ctx => {
527 let waypoints = [
528 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
529 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
530 "A:adv(80):max(100):saa",
531 {
532 id: "route-ab",
533 d: 110.0,
534 t: undefined,
535 bbox: undefined
536 }
537 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
538 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
539 "B:adv(80):max(100):saa",
540 {
541 id: "route-bc",
542 d: 55.0,
543 t: undefined,
544 bbox: undefined
545 }
546 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
547 ];
548 let geojson = makeLineGeoJSON([
549 [
550 0.0,
551 0.0
552 ],
553 [
554 1.0,
555 0.0
556 ]
557 ]);
558 let result = Geo.getDistance([
559 0.5,
560 0.0
561 ], "route-bc", waypoints, geojson);
562 let entries = mapEntries(result.fromStart);
563 ctx.expect(entries.length).toBe(1);
564 let match = entries[0];
565 if (match !== undefined) {
566 ctx.expect(stringArraysEqual(match[0], [
567 "A",
568 "B"
569 ])).toBe(true);
570 ctx.expect(match[1]).toBe(110.0 + result.fromPreviousWaypoint);
571 } else {
572 ctx.expect("should have one entry").toBe("");
573 }
574 });
575 Vitest.test("mixed route keys with and without constraints", ctx => {
576 let waypoints = [
577 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
578 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
579 "A",
580 {
581 id: "route-ab",
582 d: 100.0,
583 t: undefined,
584 bbox: undefined
585 }
586 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
587 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
588 "B:saa",
589 {
590 id: "route-bc",
591 d: 50.0,
592 t: undefined,
593 bbox: undefined
594 }
595 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
596 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([[
597 "C:adv(60):saa",
598 {
599 id: "route-cd",
600 d: 30.0,
601 t: undefined,
602 bbox: undefined
603 }
604 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
605 ];
606 let geojson = makeLineGeoJSON([
607 [
608 0.0,
609 0.0
610 ],
611 [
612 1.0,
613 0.0
614 ]
615 ]);
616 let result = Geo.getDistance([
617 0.5,
618 0.0
619 ], "route-cd", waypoints, geojson);
620 let entries = mapEntries(result.fromStart);
621 ctx.expect(entries.length).toBe(1);
622 let match = entries[0];
623 if (match !== undefined) {
624 ctx.expect(stringArraysEqual(match[0], [
625 "A",
626 "B",
627 "C"
628 ])).toBe(true);
629 ctx.expect(match[1]).toBe(150.0 + result.fromPreviousWaypoint);
630 } else {
631 ctx.expect("should have one entry").toBe("");
632 }
633 });
634 Vitest.test("returns correct previousID and nextID", ctx => {
635 let waypoints = [
636 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
637 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
638 "A",
639 {
640 id: "route-ab",
641 d: 100.0,
642 t: undefined,
643 bbox: undefined
644 }
645 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
646 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
647 "B",
648 {
649 id: "route-bc",
650 d: 50.0,
651 t: undefined,
652 bbox: undefined
653 }
654 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
655 ];
656 let geojson = makeLineGeoJSON([
657 [
658 0.0,
659 0.0
660 ],
661 [
662 1.0,
663 0.0
664 ]
665 ]);
666 let result = Geo.getDistance([
667 0.5,
668 0.0
669 ], "route-bc", waypoints, geojson);
670 ctx.expect(result.previousID).toEqual("B");
671 ctx.expect(result.nextID).toEqual("C");
672 });
673 Vitest.test("returns None for previousID and nextID when route not found", ctx => {
674 let waypoints = [
675 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
676 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
677 "A",
678 {
679 id: "route-ab",
680 d: 100.0,
681 t: undefined,
682 bbox: undefined
683 }
684 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
685 ];
686 let geojson = makeLineGeoJSON([
687 [
688 0.0,
689 0.0
690 ],
691 [
692 1.0,
693 0.0
694 ]
695 ]);
696 let result = Geo.getDistance([
697 0.5,
698 0.0
699 ], "nonexistent-route", waypoints, geojson);
700 ctx.expect(result.previousID).toEqual(undefined);
701 ctx.expect(result.nextID).toEqual(undefined);
702 });
703});
704
705Vitest.describe("Geo.getTime", () => {
706 Vitest.test("linear path: calculates fromPreviousWaypoint and single fromStart path", ctx => {
707 let waypoints = [
708 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
709 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
710 "A",
711 {
712 id: "route-ab",
713 d: 100.0,
714 t: 3600.0,
715 bbox: undefined
716 }
717 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
718 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
719 "B",
720 {
721 id: "route-bc",
722 d: 50.0,
723 t: 1800.0,
724 bbox: undefined
725 }
726 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
727 ];
728 let geojson = makeLineGeoJSONWithProps([
729 [
730 0.0,
731 0.0
732 ],
733 [
734 1.0,
735 0.0
736 ]
737 ], 111.19, 1800.0);
738 let result = Geo.getTime([
739 0.5,
740 0.0
741 ], "route-bc", waypoints, geojson);
742 ctx.expect(result.fromPreviousWaypoint).toBeGreaterThan(0.0);
743 ctx.expect(result.fromPreviousWaypoint).toBeLessThan(1800.0);
744 let entries = mapEntries(result.fromStart);
745 ctx.expect(entries.length).toBe(1);
746 let match = entries[0];
747 if (match !== undefined) {
748 ctx.expect(stringArraysEqual(match[0], [
749 "A",
750 "B"
751 ])).toBe(true);
752 ctx.expect(match[1]).toBe(3600.0 + result.fromPreviousWaypoint);
753 } else {
754 ctx.expect("should have one entry").toBe("");
755 }
756 ctx.expect(result.toNextWaypoint).toBeGreaterThan(0.0);
757 ctx.expect(result.toNextWaypoint).toBeLessThan(1800.0);
758 let totalTime = result.fromPreviousWaypoint + result.toNextWaypoint;
759 ctx.expect(Math.abs(totalTime - 1800.0)).toBeLessThan(0.1);
760 });
761 Vitest.test("toNextWaypoint calculates remaining time correctly", ctx => {
762 let waypoints = [
763 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
764 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
765 "A",
766 {
767 id: "route-ab",
768 d: 100.0,
769 t: 3600.0,
770 bbox: undefined
771 }
772 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
773 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
774 "B",
775 {
776 id: "route-bc",
777 d: 50.0,
778 t: 1800.0,
779 bbox: undefined
780 }
781 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
782 ];
783 let geojson = makeLineGeoJSONWithProps([
784 [
785 0.0,
786 0.0
787 ],
788 [
789 1.0,
790 0.0
791 ]
792 ], 111.19, 1800.0);
793 let result = Geo.getTime([
794 0.5,
795 0.0
796 ], "route-bc", waypoints, geojson);
797 let diff = Math.abs(result.fromPreviousWaypoint - result.toNextWaypoint);
798 ctx.expect(diff).toBeLessThan(10.0);
799 let total = result.fromPreviousWaypoint + result.toNextWaypoint;
800 ctx.expect(Math.abs(total - 1800.0)).toBeLessThan(0.1);
801 });
802 Vitest.test("merge path: two routes to source waypoint with different times", ctx => {
803 let waypoints = [
804 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
805 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
806 "A",
807 {
808 id: "route-ab",
809 d: 100.0,
810 t: 3600.0,
811 bbox: undefined
812 }
813 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
814 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
815 "B",
816 {
817 id: "route-bc",
818 d: 30.0,
819 t: 1200.0,
820 bbox: undefined
821 }
822 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
823 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([
824 [
825 "B",
826 {
827 id: "route-bd",
828 d: 60.0,
829 t: 2400.0,
830 bbox: undefined
831 }
832 ],
833 [
834 "C",
835 {
836 id: "route-cd",
837 d: 20.0,
838 t: 800.0,
839 bbox: undefined
840 }
841 ]
842 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
843 makeWaypoint("E", undefined, Primitive_option.some(Object.fromEntries([[
844 "D",
845 {
846 id: "route-de",
847 d: 40.0,
848 t: 1600.0,
849 bbox: undefined
850 }
851 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
852 ];
853 let geojson = makeLineGeoJSONWithProps([
854 [
855 0.0,
856 0.0
857 ],
858 [
859 0.5,
860 0.0
861 ]
862 ], 55.6, 1600.0);
863 let result = Geo.getTime([
864 0.25,
865 0.0
866 ], "route-de", waypoints, geojson);
867 let entries = mapEntries(result.fromStart);
868 ctx.expect(entries.length).toBe(2);
869 let findEntry = (expectedPath, expectedTime) => entries.find(param => {
870 if (stringArraysEqual(param[0], expectedPath)) {
871 return Math.abs(param[1] - expectedTime) < 0.0001;
872 } else {
873 return false;
874 }
875 });
876 ctx.expect(Core__Option.isSome(findEntry([
877 "A",
878 "B",
879 "D"
880 ], 6000.0 + result.fromPreviousWaypoint))).toBe(true);
881 ctx.expect(Core__Option.isSome(findEntry([
882 "A",
883 "B",
884 "C",
885 "D"
886 ], 5600.0 + result.fromPreviousWaypoint))).toBe(true);
887 });
888 Vitest.test("returns correct previousID and nextID", ctx => {
889 let waypoints = [
890 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
891 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
892 "A",
893 {
894 id: "route-ab",
895 d: 100.0,
896 t: 3600.0,
897 bbox: undefined
898 }
899 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
900 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
901 "B",
902 {
903 id: "route-bc",
904 d: 50.0,
905 t: 1800.0,
906 bbox: undefined
907 }
908 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
909 ];
910 let geojson = makeLineGeoJSONWithProps([
911 [
912 0.0,
913 0.0
914 ],
915 [
916 1.0,
917 0.0
918 ]
919 ], 111.19, 1800.0);
920 let result = Geo.getTime([
921 0.5,
922 0.0
923 ], "route-bc", waypoints, geojson);
924 ctx.expect(result.previousID).toEqual("B");
925 ctx.expect(result.nextID).toEqual("C");
926 });
927 Vitest.test("zero total distance: returns zero time for current segment", ctx => {
928 let waypoints = [
929 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
930 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
931 "A",
932 {
933 id: "route-ab",
934 d: 100.0,
935 t: 3600.0,
936 bbox: undefined
937 }
938 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
939 ];
940 let geojson = makeLineGeoJSONWithProps([
941 [
942 0.0,
943 0.0
944 ],
945 [
946 1.0,
947 0.0
948 ]
949 ], 0.0, 1800.0);
950 let result = Geo.getTime([
951 0.5,
952 0.0
953 ], "route-ab", waypoints, geojson);
954 ctx.expect(result.fromPreviousWaypoint).toBe(0.0);
955 });
956 Vitest.test("missing route hash: returns zero/empty result", ctx => {
957 let waypoints = [
958 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
959 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
960 "A",
961 {
962 id: "route-ab",
963 d: 100.0,
964 t: 3600.0,
965 bbox: undefined
966 }
967 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
968 ];
969 let geojson = makeLineGeoJSONWithProps([
970 [
971 0.0,
972 0.0
973 ],
974 [
975 1.0,
976 0.0
977 ]
978 ], 100.0, 3600.0);
979 let result = Geo.getTime([
980 0.5,
981 0.0
982 ], "nonexistent-route", waypoints, geojson);
983 ctx.expect(result.fromPreviousWaypoint).toBe(0.0);
984 ctx.expect(result.fromStart.size).toBe(0);
985 });
986 Vitest.test("route with time of None: uses 0 as default", ctx => {
987 let waypoints = [
988 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
989 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
990 "A",
991 {
992 id: "route-ab",
993 d: 100.0,
994 t: 3600.0,
995 bbox: undefined
996 }
997 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
998 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
999 "B",
1000 {
1001 id: "route-bc",
1002 d: 50.0,
1003 t: undefined,
1004 bbox: undefined
1005 }
1006 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1007 ];
1008 let geojson = makeLineGeoJSONWithProps([
1009 [
1010 0.0,
1011 0.0
1012 ],
1013 [
1014 1.0,
1015 0.0
1016 ]
1017 ], 111.19, 1800.0);
1018 let result = Geo.getTime([
1019 0.5,
1020 0.0
1021 ], "route-bc", waypoints, geojson);
1022 let entries = mapEntries(result.fromStart);
1023 let match = entries[0];
1024 if (match !== undefined) {
1025 ctx.expect(stringArraysEqual(match[0], [
1026 "A",
1027 "B"
1028 ])).toBe(true);
1029 ctx.expect(match[1]).toBe(3600.0 + result.fromPreviousWaypoint);
1030 } else {
1031 ctx.expect("should have one entry").toBe("");
1032 }
1033 });
1034 Vitest.test("route keys with constraint suffixes work correctly", ctx => {
1035 let waypoints = [
1036 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1037 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1038 "A:saa",
1039 {
1040 id: "route-ab",
1041 d: 100.0,
1042 t: 3600.0,
1043 bbox: undefined
1044 }
1045 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1046 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1047 "B:saa",
1048 {
1049 id: "route-bc",
1050 d: 50.0,
1051 t: 1800.0,
1052 bbox: undefined
1053 }
1054 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1055 ];
1056 let geojson = makeLineGeoJSONWithProps([
1057 [
1058 0.0,
1059 0.0
1060 ],
1061 [
1062 1.0,
1063 0.0
1064 ]
1065 ], 111.19, 1800.0);
1066 let result = Geo.getTime([
1067 0.5,
1068 0.0
1069 ], "route-bc", waypoints, geojson);
1070 let entries = mapEntries(result.fromStart);
1071 ctx.expect(entries.length).toBe(1);
1072 let match = entries[0];
1073 if (match !== undefined) {
1074 ctx.expect(stringArraysEqual(match[0], [
1075 "A",
1076 "B"
1077 ])).toBe(true);
1078 ctx.expect(match[1]).toBe(3600.0 + result.fromPreviousWaypoint);
1079 } else {
1080 ctx.expect("should have one entry").toBe("");
1081 }
1082 });
1083});
1084
1085Vitest.describe("Geo.getDistanceMatrix", () => {
1086 Vitest.test("linear path A -> B -> C: builds correct distance matrix", ctx => {
1087 let waypoints = [
1088 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1089 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1090 "A",
1091 {
1092 id: "route-ab",
1093 d: 100.0,
1094 t: undefined,
1095 bbox: undefined
1096 }
1097 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1098 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1099 "B",
1100 {
1101 id: "route-bc",
1102 d: 50.0,
1103 t: undefined,
1104 bbox: undefined
1105 }
1106 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1107 ];
1108 let matrix = Geo.getDistanceMatrix(waypoints);
1109 let entries = mapEntries(matrix);
1110 ctx.expect(entries.length).toBe(2);
1111 let pathAB = entries.find(param => stringArraysEqual(param[0], [
1112 "A",
1113 "B"
1114 ]));
1115 if (pathAB !== undefined) {
1116 ctx.expect(pathAB[1]).toBe(100.0);
1117 } else {
1118 ctx.expect("should have path [A,B]").toBe("");
1119 }
1120 let pathABC = entries.find(param => stringArraysEqual(param[0], [
1121 "A",
1122 "B",
1123 "C"
1124 ]));
1125 if (pathABC !== undefined) {
1126 ctx.expect(pathABC[1]).toBe(150.0);
1127 } else {
1128 ctx.expect("should have path [A,B,C]").toBe("");
1129 }
1130 });
1131 Vitest.test("multiple paths to same destination: includes all routes", ctx => {
1132 let waypoints = [
1133 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1134 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1135 "A",
1136 {
1137 id: "route-ab",
1138 d: 100.0,
1139 t: undefined,
1140 bbox: undefined
1141 }
1142 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1143 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([[
1144 "A",
1145 {
1146 id: "route-ad",
1147 d: 80.0,
1148 t: undefined,
1149 bbox: undefined
1150 }
1151 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1152 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([
1153 [
1154 "B",
1155 {
1156 id: "route-bc",
1157 d: 50.0,
1158 t: undefined,
1159 bbox: undefined
1160 }
1161 ],
1162 [
1163 "D",
1164 {
1165 id: "route-dc",
1166 d: 30.0,
1167 t: undefined,
1168 bbox: undefined
1169 }
1170 ]
1171 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1172 ];
1173 let matrix = Geo.getDistanceMatrix(waypoints);
1174 let entries = mapEntries(matrix);
1175 ctx.expect(entries.length).toBe(4);
1176 let pathAB = entries.find(param => stringArraysEqual(param[0], [
1177 "A",
1178 "B"
1179 ]));
1180 if (pathAB !== undefined) {
1181 ctx.expect(pathAB[1]).toBe(100.0);
1182 } else {
1183 ctx.expect("should have path [A,B]").toBe("");
1184 }
1185 let pathAD = entries.find(param => stringArraysEqual(param[0], [
1186 "A",
1187 "D"
1188 ]));
1189 if (pathAD !== undefined) {
1190 ctx.expect(pathAD[1]).toBe(80.0);
1191 } else {
1192 ctx.expect("should have path [A,D]").toBe("");
1193 }
1194 let pathABC = entries.find(param => stringArraysEqual(param[0], [
1195 "A",
1196 "B",
1197 "C"
1198 ]));
1199 if (pathABC !== undefined) {
1200 ctx.expect(pathABC[1]).toBe(150.0);
1201 } else {
1202 ctx.expect("should have path [A,B,C]").toBe("");
1203 }
1204 let pathADC = entries.find(param => stringArraysEqual(param[0], [
1205 "A",
1206 "D",
1207 "C"
1208 ]));
1209 if (pathADC !== undefined) {
1210 ctx.expect(pathADC[1]).toBe(110.0);
1211 } else {
1212 ctx.expect("should have path [A,D,C]").toBe("");
1213 }
1214 });
1215 Vitest.test("non-routable waypoint: excluded from matrix", ctx => {
1216 let waypoints = [
1217 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1218 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1219 "A",
1220 {
1221 id: "route-ab",
1222 d: 100.0,
1223 t: undefined,
1224 bbox: undefined
1225 }
1226 ]])), undefined, undefined, undefined, undefined, true, undefined, undefined),
1227 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1228 "B",
1229 {
1230 id: "route-bc",
1231 d: 50.0,
1232 t: undefined,
1233 bbox: undefined
1234 }
1235 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1236 ];
1237 let matrix = Geo.getDistanceMatrix(waypoints);
1238 let entries = mapEntries(matrix);
1239 ctx.expect(entries.length).toBe(0);
1240 });
1241 Vitest.test("cycle detection: avoids infinite loops", ctx => {
1242 let waypoints = [
1243 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1244 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([
1245 [
1246 "A",
1247 {
1248 id: "route-ab",
1249 d: 100.0,
1250 t: undefined,
1251 bbox: undefined
1252 }
1253 ],
1254 [
1255 "C",
1256 {
1257 id: "route-cb",
1258 d: 50.0,
1259 t: undefined,
1260 bbox: undefined
1261 }
1262 ]
1263 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1264 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1265 "B",
1266 {
1267 id: "route-bc",
1268 d: 30.0,
1269 t: undefined,
1270 bbox: undefined
1271 }
1272 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1273 ];
1274 let matrix = Geo.getDistanceMatrix(waypoints);
1275 let entries = mapEntries(matrix);
1276 ctx.expect(entries.length).toBe(2);
1277 let hasAB = entries.some(param => stringArraysEqual(param[0], [
1278 "A",
1279 "B"
1280 ]));
1281 ctx.expect(hasAB).toBe(true);
1282 let hasABC = entries.some(param => stringArraysEqual(param[0], [
1283 "A",
1284 "B",
1285 "C"
1286 ]));
1287 ctx.expect(hasABC).toBe(true);
1288 let hasLongPath = entries.some(param => param[0].length > 3);
1289 ctx.expect(hasLongPath).toBe(false);
1290 });
1291 Vitest.test("no origin: returns empty matrix", ctx => {
1292 let waypoints = [
1293 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([[
1294 "X",
1295 {
1296 id: "route-xa",
1297 d: 100.0,
1298 t: undefined,
1299 bbox: undefined
1300 }
1301 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1302 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1303 "A",
1304 {
1305 id: "route-ab",
1306 d: 50.0,
1307 t: undefined,
1308 bbox: undefined
1309 }
1310 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1311 ];
1312 let matrix = Geo.getDistanceMatrix(waypoints);
1313 let entries = mapEntries(matrix);
1314 ctx.expect(entries.length).toBe(0);
1315 });
1316 Vitest.test("route keys with suffixes: parses correctly", ctx => {
1317 let waypoints = [
1318 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1319 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1320 "A:saa",
1321 {
1322 id: "route-ab",
1323 d: 100.0,
1324 t: undefined,
1325 bbox: undefined
1326 }
1327 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1328 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1329 "B:saa",
1330 {
1331 id: "route-bc",
1332 d: 50.0,
1333 t: undefined,
1334 bbox: undefined
1335 }
1336 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1337 ];
1338 let matrix = Geo.getDistanceMatrix(waypoints);
1339 let entries = mapEntries(matrix);
1340 ctx.expect(entries.length).toBe(2);
1341 let hasAB = entries.some(param => stringArraysEqual(param[0], [
1342 "A",
1343 "B"
1344 ]));
1345 ctx.expect(hasAB).toBe(true);
1346 let hasABC = entries.some(param => stringArraysEqual(param[0], [
1347 "A",
1348 "B",
1349 "C"
1350 ]));
1351 ctx.expect(hasABC).toBe(true);
1352 });
1353});
1354
1355Vitest.describe("Geo.relativeDistances", () => {
1356 Vitest.test("linear path: calculates correct relative distances", ctx => {
1357 let waypoints = [
1358 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1359 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1360 "A",
1361 {
1362 id: undefined,
1363 d: 100.0,
1364 t: undefined,
1365 bbox: undefined
1366 }
1367 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1368 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1369 "B",
1370 {
1371 id: undefined,
1372 d: 50.0,
1373 t: undefined,
1374 bbox: undefined
1375 }
1376 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1377 ];
1378 let matrix = Geo.getDistanceMatrix(waypoints);
1379 let relative = Geo.relativeDistances("B", matrix);
1380 ctx.expect(relative.get("A")).toEqual(-100.0);
1381 ctx.expect(relative.get("B")).toEqual(0.0);
1382 ctx.expect(relative.get("C")).toEqual(50.0);
1383 });
1384 Vitest.test("reference at origin: all distances positive", ctx => {
1385 let waypoints = [
1386 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1387 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1388 "A",
1389 {
1390 id: undefined,
1391 d: 100.0,
1392 t: undefined,
1393 bbox: undefined
1394 }
1395 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1396 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1397 "B",
1398 {
1399 id: undefined,
1400 d: 50.0,
1401 t: undefined,
1402 bbox: undefined
1403 }
1404 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1405 ];
1406 let matrix = Geo.getDistanceMatrix(waypoints);
1407 let relative = Geo.relativeDistances("A", matrix);
1408 ctx.expect(relative.get("A")).toEqual(0.0);
1409 ctx.expect(relative.get("B")).toEqual(100.0);
1410 ctx.expect(relative.get("C")).toEqual(150.0);
1411 });
1412 Vitest.test("reference at destination: all distances negative", ctx => {
1413 let waypoints = [
1414 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1415 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1416 "A",
1417 {
1418 id: undefined,
1419 d: 100.0,
1420 t: undefined,
1421 bbox: undefined
1422 }
1423 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1424 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1425 "B",
1426 {
1427 id: undefined,
1428 d: 50.0,
1429 t: undefined,
1430 bbox: undefined
1431 }
1432 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1433 ];
1434 let matrix = Geo.getDistanceMatrix(waypoints);
1435 let relative = Geo.relativeDistances("C", matrix);
1436 ctx.expect(relative.get("A")).toEqual(-150.0);
1437 ctx.expect(relative.get("B")).toEqual(-50.0);
1438 ctx.expect(relative.get("C")).toEqual(0.0);
1439 });
1440 Vitest.test("multiple paths: chooses shortest absolute distance", ctx => {
1441 let waypoints = [
1442 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1443 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1444 "A",
1445 {
1446 id: undefined,
1447 d: 100.0,
1448 t: undefined,
1449 bbox: undefined
1450 }
1451 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1452 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([[
1453 "A",
1454 {
1455 id: undefined,
1456 d: 80.0,
1457 t: undefined,
1458 bbox: undefined
1459 }
1460 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1461 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([
1462 [
1463 "B",
1464 {
1465 id: undefined,
1466 d: 50.0,
1467 t: undefined,
1468 bbox: undefined
1469 }
1470 ],
1471 [
1472 "D",
1473 {
1474 id: undefined,
1475 d: 30.0,
1476 t: undefined,
1477 bbox: undefined
1478 }
1479 ]
1480 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1481 ];
1482 let matrix = Geo.getDistanceMatrix(waypoints);
1483 let relativeToC = Geo.relativeDistances("C", matrix);
1484 ctx.expect(relativeToC.get("A")).toEqual(-110.0);
1485 ctx.expect(relativeToC.get("B")).toEqual(-50.0);
1486 ctx.expect(relativeToC.get("D")).toEqual(-30.0);
1487 ctx.expect(relativeToC.get("C")).toEqual(0.0);
1488 let relativeToB = Geo.relativeDistances("B", matrix);
1489 ctx.expect(relativeToB.get("A")).toEqual(-100.0);
1490 ctx.expect(relativeToB.get("B")).toEqual(0.0);
1491 ctx.expect(relativeToB.get("C")).toEqual(50.0);
1492 ctx.expect(relativeToB.get("D")).toEqual(undefined);
1493 });
1494 Vitest.test("reference not in matrix: returns empty map", ctx => {
1495 let waypoints = [
1496 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1497 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1498 "A",
1499 {
1500 id: undefined,
1501 d: 100.0,
1502 t: undefined,
1503 bbox: undefined
1504 }
1505 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1506 ];
1507 let matrix = Geo.getDistanceMatrix(waypoints);
1508 let relative = Geo.relativeDistances("Z", matrix);
1509 ctx.expect(relative.size).toBe(0);
1510 });
1511 Vitest.test("complex branching: correct relative distances", ctx => {
1512 let waypoints = [
1513 makeWaypoint("A", undefined, Primitive_option.some(Object.fromEntries([])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1514 makeWaypoint("B", undefined, Primitive_option.some(Object.fromEntries([[
1515 "A",
1516 {
1517 id: undefined,
1518 d: 10.0,
1519 t: undefined,
1520 bbox: undefined
1521 }
1522 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1523 makeWaypoint("C", undefined, Primitive_option.some(Object.fromEntries([[
1524 "B",
1525 {
1526 id: undefined,
1527 d: 20.0,
1528 t: undefined,
1529 bbox: undefined
1530 }
1531 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1532 makeWaypoint("D", undefined, Primitive_option.some(Object.fromEntries([[
1533 "B",
1534 {
1535 id: undefined,
1536 d: 5.0,
1537 t: undefined,
1538 bbox: undefined
1539 }
1540 ]])), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
1541 makeWaypoint("E", undefined, Primitive_option.some(Object.fromEntries([
1542 [
1543 "C",
1544 {
1545 id: undefined,
1546 d: 30.0,
1547 t: undefined,
1548 bbox: undefined
1549 }
1550 ],
1551 [
1552 "D",
1553 {
1554 id: undefined,
1555 d: 30.0,
1556 t: undefined,
1557 bbox: undefined
1558 }
1559 ]
1560 ])), undefined, undefined, undefined, undefined, undefined, undefined, undefined)
1561 ];
1562 let matrix = Geo.getDistanceMatrix(waypoints);
1563 let relativeToE = Geo.relativeDistances("E", matrix);
1564 ctx.expect(relativeToE.get("A")).toEqual(-45.0);
1565 ctx.expect(relativeToE.get("B")).toEqual(-35.0);
1566 ctx.expect(relativeToE.get("C")).toEqual(-30.0);
1567 ctx.expect(relativeToE.get("D")).toEqual(-30.0);
1568 ctx.expect(relativeToE.get("E")).toEqual(0.0);
1569 let relativeToC = Geo.relativeDistances("C", matrix);
1570 ctx.expect(relativeToC.get("A")).toEqual(-30.0);
1571 ctx.expect(relativeToC.get("B")).toEqual(-20.0);
1572 ctx.expect(relativeToC.get("C")).toEqual(0.0);
1573 ctx.expect(relativeToC.get("D")).toEqual(undefined);
1574 ctx.expect(relativeToC.get("E")).toEqual(30.0);
1575 });
1576});
1577
1578export {
1579 makeRoute,
1580 makeWaypoint,
1581 makeLineGeoJSON,
1582 makeLineGeoJSONWithProps,
1583 mapEntries,
1584 stringArraysEqual,
1585}
1586/* Not a pure module */