diff --git a/src/routePlanner/hooks/useMarkersOnMap/getLayersForMarkers.ts b/src/routePlanner/hooks/useMarkersOnMap/getLayersForMarkers.ts index 6afb8b1..b274b23 100644 --- a/src/routePlanner/hooks/useMarkersOnMap/getLayersForMarkers.ts +++ b/src/routePlanner/hooks/useMarkersOnMap/getLayersForMarkers.ts @@ -1,4 +1,5 @@ import leaflet from 'leaflet'; +import { toPairs } from '../../../shared/collections'; import type { Marker } from '../../types'; export type MarkerLayersStyle = { @@ -10,19 +11,9 @@ export const getLayersForMarkers = ( markerLayersStyle: MarkerLayersStyle, ) => [ // lines - ...markers.flatMap((thisMarker, i) => { - const previousMarker = markers[i - 1]; - if (!previousMarker) { - return []; - } - - return [ - leaflet.polyline([ - previousMarker.coordinates, - thisMarker.coordinates, - ]), - ]; - }), + ...toPairs(markers).map(([a, b]) => + leaflet.polyline([a.coordinates, b.coordinates]), + ), // circles and labels ...markers.map((marker) => leaflet diff --git a/src/shared/collections.test.ts b/src/shared/collections.test.ts index 8ff22b8..97404e6 100644 --- a/src/shared/collections.test.ts +++ b/src/shared/collections.test.ts @@ -1,5 +1,5 @@ import t from 'tap'; -import { reorderElements } from './collections.js'; +import { reorderElements, toPairs } from './collections.js'; void t.test('reorderElements', (t) => { const checkReordering = ( @@ -40,3 +40,35 @@ void t.test('reorderElements', (t) => { checkReordering(4, 4, 'abcde'); t.end(); }); + +void t.test('toPairs', (t) => { + t.matchOnlyStrict(toPairs([]), []); + t.matchOnlyStrict(toPairs(['a']), []); + t.matchOnlyStrict(toPairs(['a', 'b']), [['a', 'b']]); + t.matchOnlyStrict(toPairs(['a', 'b', 'c']), [ + ['a', 'b'], + ['b', 'c'], + ]); + t.matchOnlyStrict(toPairs(['a', 'b', 'c', 'd']), [ + ['a', 'b'], + ['b', 'c'], + ['c', 'd'], + ]); + t.matchOnlyStrict(toPairs([undefined, 'b', 'c']), [ + [undefined, 'b'], + ['b', 'c'], + ]); + t.matchOnlyStrict(toPairs(['a', undefined, 'c']), [ + ['a', undefined], + [undefined, 'c'], + ]); + t.matchOnlyStrict(toPairs(['a', 'b', undefined]), [ + ['a', 'b'], + ['b', undefined], + ]); + t.matchOnlyStrict(toPairs([undefined, undefined, undefined]), [ + [undefined, undefined], + [undefined, undefined], + ]); + t.end(); +}); diff --git a/src/shared/collections.ts b/src/shared/collections.ts index edefd9d..b00e51c 100644 --- a/src/shared/collections.ts +++ b/src/shared/collections.ts @@ -22,3 +22,15 @@ export const reorderElements = ( return collection; }; + +export const toPairs = (collection: T[]): [T, T][] => + collection.flatMap((element, index, collection) => { + if (!index) { + return []; + } + + const previousElement = collection[index - 1]; + // We just checked that index of the previous element is inside array bounds + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return [[previousElement!, element]]; + }); diff --git a/src/shared/routes.ts b/src/shared/routes.ts index 359ffc8..b2384f5 100644 --- a/src/shared/routes.ts +++ b/src/shared/routes.ts @@ -1,19 +1,8 @@ import haversineDistance from 'haversine-distance'; +import { toPairs } from './collections'; import { Waypoint } from './types'; -export const getRouteLength = (points: Waypoint[]) => { - let result = 0; - for (let i = 0; i < points.length; i++) { - const currentPoint = points[i]; - const previousPoint = points[i - 1]; - if (!currentPoint || !previousPoint) { - continue; - } - result += haversineDistance( - previousPoint.coordinates, - currentPoint.coordinates, - ); - } - - return result; -}; +export const getRouteLength = (points: Waypoint[]) => + toPairs(points) + .map(([a, b]) => haversineDistance(a.coordinates, b.coordinates)) + .reduce((sum, value) => sum + value, 0);