"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateWalkingRoute = calculateWalkingRoute; const spatial_1 = require("../../../utils/spatial"); const WALKING_SPEED_MPS = 5000 / 60; // 5 km/h in meters per minute const MINUTES_PER_DOOR = 2; /** * Nearest-neighbor walking route algorithm. * Starts from volunteer GPS position or cut polygon centroid. */ function calculateWalkingRoute(locations, startLat, startLng, cutGeojson) { if (locations.length === 0) { return { orderedLocations: [], totalDistanceMeters: 0, estimatedMinutes: 0 }; } // Determine starting point let currentLat; let currentLng; if (startLat !== undefined && startLng !== undefined) { currentLat = startLat; currentLng = startLng; } else if (cutGeojson) { const polygons = (0, spatial_1.parseGeoJsonPolygon)(cutGeojson); const centroid = (0, spatial_1.calculateCentroid)(polygons[0]); currentLat = centroid.lat; currentLng = centroid.lng; } else { // Use first location as starting point currentLat = locations[0].latitude; currentLng = locations[0].longitude; } const remaining = [...locations]; const ordered = []; let totalDistance = 0; while (remaining.length > 0) { let nearestIdx = 0; let nearestDist = Infinity; for (let i = 0; i < remaining.length; i++) { const loc = remaining[i]; const dist = (0, spatial_1.haversineDistance)(currentLat, currentLng, loc.latitude, loc.longitude); if (dist < nearestDist) { nearestDist = dist; nearestIdx = i; } } const nearest = remaining.splice(nearestIdx, 1)[0]; ordered.push(nearest); totalDistance += nearestDist; currentLat = nearest.latitude; currentLng = nearest.longitude; } const walkingMinutes = totalDistance / WALKING_SPEED_MPS; const doorMinutes = ordered.length * MINUTES_PER_DOOR; const estimatedMinutes = Math.round(walkingMinutes + doorMinutes); return { orderedLocations: ordered, totalDistanceMeters: Math.round(totalDistance), estimatedMinutes, }; } //# sourceMappingURL=canvass-route.service.js.map