UNPKG

@geoapify/route-planner-sdk

Version:

TypeScript SDK for the Geoapify Route Planner API. Supports route optimization, delivery planning, and timeline visualization in browser and Node.js

296 lines (295 loc) 14.7 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Utils } from "../utils"; import { RoutePlanner } from "../../route-planner"; import { OptimizeAgentInput } from "./optimize-agent-input"; export class RouteResultEditorBase { constructor(result) { this.result = result; } optimizeRoute(optimizeAgentInput) { return __awaiter(this, void 0, void 0, function* () { let newRawData = Utils.cloneObject(this.result.getRawData().properties.params); let originalIndexes = { originalAgentIndex: optimizeAgentInput.agentIndex, originalJobsIndexes: {}, originalShipmentsIndexes: {}, }; this.generateOptimizedRoute(newRawData, optimizeAgentInput, originalIndexes); const planner = new RoutePlanner(this.result.getOptions(), newRawData); let result = yield planner.plan(); let newFeatureResponse = result.getRawData().features[0]; if (newFeatureResponse) { this.fixAgentIndex(optimizeAgentInput.agentIndex, newFeatureResponse); this.fixShipmentJobIndexes(newFeatureResponse, originalIndexes); this.fixWaypointIndexes(newFeatureResponse, originalIndexes); this.fixUnassignedItems(result.getRawData(), originalIndexes); } return result; }); } generateOptimizedRoute(newRawData, optimizeAgentInput, originalIndexes) { var _a, _b, _c; newRawData.agents = (_a = newRawData.agents) === null || _a === void 0 ? void 0 : _a.filter((nextAgent, index) => index == optimizeAgentInput.agentIndex); let newJobIndex = 0; let newJobs = []; (_b = newRawData.jobs) === null || _b === void 0 ? void 0 : _b.forEach(((nextJob, index) => { if (optimizeAgentInput.agentJobIndexes.has(index)) { newJobs[newJobIndex] = nextJob; originalIndexes.originalJobsIndexes[newJobIndex] = index; newJobIndex++; } })); newRawData.jobs = newJobs; let newShipmentIndex = 0; let newShipments = []; (_c = newRawData.shipments) === null || _c === void 0 ? void 0 : _c.forEach(((nextShipment, index) => { if (optimizeAgentInput.agentShipmentIndexes.has(index)) { newShipments[newShipmentIndex] = nextShipment; originalIndexes.originalShipmentsIndexes[newShipmentIndex] = index; newShipmentIndex++; } })); newRawData.shipments = newShipments; } removeAgent(agentIndex) { this.removeAgentWithIndex(agentIndex); this.addUnassignedAgentIfNeeded(agentIndex); // TODO: maybe we need to add shipments/locations in unassigned arrays } removeAgentWithIndex(agentIndex) { this.result.getRawData().features = this.result.getRawData().features.filter(agent => agent.properties.agent_index != agentIndex); } updateAgent(newResult, originalAgentIndex) { if (newResult.getUnassignedAgents().length > 0) { if (!this.result.getRawData().properties.issues.unassigned_agents.includes(originalAgentIndex)) { this.removeAgentWithIndex(originalAgentIndex); } else { this.updateResultWithUpdatedAgent(newResult, originalAgentIndex); } this.updateUnassignedItems(newResult); } else { let existingAgentSolution = this.result.getAgentSolutionByIndex(originalAgentIndex); if (existingAgentSolution) { this.removeAgentWithIndex(originalAgentIndex); } this.updateResultWithUpdatedAgent(newResult, originalAgentIndex); this.updateUnassignedItems(newResult); } } updateResultWithUpdatedAgent(newResult, originalAgentIndex) { let newFeatureResponse = newResult.getRawData().features[0]; this.result.getRawData().features.push(newFeatureResponse); } generateOptimizeAgentInput(agentIndex, existingAgent) { if (!existingAgent) { return new OptimizeAgentInput(agentIndex, [], []); } let agentJobs = existingAgent.getActions() .filter(action => action.getJobIndex() !== undefined) .map(action => action.getJobIndex()); let agentShipments = existingAgent.getActions() .filter(action => action.getShipmentIndex() !== undefined) .map(action => action.getShipmentIndex()); return new OptimizeAgentInput(existingAgent.getAgentIndex(), agentJobs, agentShipments); } checkIfArrayIsUnique(myArray) { return myArray.length === new Set(myArray).size; } getAgentByIndex(agentIndex) { return this.result.getRawData().properties.params.agents[agentIndex]; } getJobByIndex(jobIndex) { return this.result.getRawData().properties.params.jobs[jobIndex]; } getShipmentByIndex(shipmentIndex) { return this.result.getRawData().properties.params.shipments[shipmentIndex]; } validateAgent(agentIndex) { let agentFound = this.getAgentByIndex(agentIndex); if (!agentFound) { throw new Error(`Agent with index ${agentIndex} not found`); } } updateUnassignedItems(newResult) { this.updateUnassignedAgents(newResult); this.updateUnassignedJobs(newResult); this.updateUnassignedShipments(newResult); } updateUnassignedAgents(newResult) { if (newResult.getUnassignedAgents().length > 0) { this.addUnassignedAgentIfNeeded(newResult.getRawData().properties.issues.unassigned_agents[0]); } else { this.addIssuesPropertiesIfMissing(); if (!this.result.getRawData().properties.issues.unassigned_agents) { this.result.getRawData().properties.issues.unassigned_agents = []; } this.result.getRawData().properties.issues.unassigned_agents = this.result.getRawData().properties.issues.unassigned_agents.filter(unassignedAgentIndex => unassignedAgentIndex != newResult.getData().agents[0].agentIndex); } } updateUnassignedJobs(newResult) { let unassignedJobs = this.getUnassignedJobs(newResult); unassignedJobs.forEach(jobIndex => { var _a, _b; if (!((_b = (_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_jobs) === null || _b === void 0 ? void 0 : _b.includes(jobIndex))) { this.addIssuesPropertiesIfMissing(); this.generateEmptyUnassignedJobsIfNeeded(); this.result.getRawData().properties.issues.unassigned_jobs.push(jobIndex); } }); if (newResult.getRawData().features.length > 0) { let assignedJobs = newResult.getRawData().features[0].properties.actions.filter(action => action.job_index != undefined).map(action => action.job_index); assignedJobs.forEach(jobIndex => { var _a, _b; if ((_b = (_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_jobs) === null || _b === void 0 ? void 0 : _b.includes(jobIndex)) { this.addIssuesPropertiesIfMissing(); this.generateEmptyUnassignedJobsIfNeeded(); this.result.getRawData().properties.issues.unassigned_jobs = this.result.getRawData().properties.issues.unassigned_jobs.filter(unassignedJobIndex => unassignedJobIndex != jobIndex); } }); } } updateUnassignedShipments(newResult) { let unassignedShipments = this.getUnassignedShipments(newResult); unassignedShipments.forEach(shipmentIndex => { var _a, _b; if (!((_b = (_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_shipments) === null || _b === void 0 ? void 0 : _b.includes(shipmentIndex))) { this.addIssuesPropertiesIfMissing(); this.generateEmptyUnassignedShipmentsIfNeeded(); this.result.getRawData().properties.issues.unassigned_shipments.push(shipmentIndex); } }); if (newResult.getRawData().features.length > 0) { let assignedShipments = newResult.getRawData().features[0].properties.actions.filter(action => action.shipment_index != undefined).map(action => action.shipment_index); assignedShipments.forEach(shipmentIndex => { var _a, _b; if ((_b = (_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_shipments) === null || _b === void 0 ? void 0 : _b.includes(shipmentIndex)) { this.addIssuesPropertiesIfMissing(); this.generateEmptyUnassignedShipmentsIfNeeded(); this.result.getRawData().properties.issues.unassigned_shipments = this.result.getRawData().properties.issues.unassigned_shipments.filter(unassignedShipmentIndex => unassignedShipmentIndex != shipmentIndex); } }); } } getUnassignedJobs(newResult) { if (!newResult.getRawData().properties.issues || !newResult.getRawData().properties.issues.unassigned_jobs) { return []; } return newResult.getRawData().properties.issues.unassigned_jobs; } getUnassignedShipments(newResult) { if (!newResult.getRawData().properties.issues || !newResult.getRawData().properties.issues.unassigned_shipments) { return []; } return newResult.getRawData().properties.issues.unassigned_shipments; } addUnassignedAgentIfNeeded(agentIndex) { if (!this.result.getRawData().properties.issues.unassigned_agents.includes(agentIndex)) { if (!this.result.getRawData().properties.issues.unassigned_agents) { this.result.getRawData().properties.issues.unassigned_agents = []; } this.result.getRawData().properties.issues.unassigned_agents.push(agentIndex); } } addIssuesPropertiesIfMissing() { if (!this.result.getRawData().properties.issues) { this.result.getRawData().properties.issues = { unassigned_shipments: [], unassigned_jobs: [], unassigned_agents: [] }; } } fixAgentIndex(originalAgentIndex, agentData) { if (originalAgentIndex != -1) { agentData.properties.agent_index = originalAgentIndex; } else { console.log(`Agent with index ${originalAgentIndex} not found in the result`); } } fixShipmentJobIndexes(agentData, originalIndexes) { agentData.properties.actions.forEach(action => { if (action.shipment_index != undefined) { action.shipment_index = originalIndexes.originalShipmentsIndexes[action.shipment_index]; } if (action.job_index != undefined) { action.job_index = originalIndexes.originalJobsIndexes[action.job_index]; } }); } fixWaypointIndexes(agentData, originalIndexes) { agentData.properties.waypoints.forEach(waypoint => { waypoint.actions.forEach(action => { if (action.shipment_index != undefined) { action.shipment_index = originalIndexes.originalShipmentsIndexes[action.shipment_index]; } if (action.job_index != undefined) { action.job_index = originalIndexes.originalJobsIndexes[action.job_index]; } }); }); } generateEmptyUnassignedShipmentsIfNeeded() { if (!this.result.getRawData().properties.issues) { this.result.getRawData().properties.issues = { unassigned_jobs: [], unassigned_agents: [], unassigned_shipments: [] }; } else { if (!this.result.getRawData().properties.issues.unassigned_shipments) { this.result.getRawData().properties.issues.unassigned_shipments = []; } } } generateEmptyUnassignedJobsIfNeeded() { if (!this.result.getRawData().properties.issues) { this.result.getRawData().properties.issues = { unassigned_jobs: [], unassigned_agents: [], unassigned_shipments: [] }; } else { if (!this.result.getRawData().properties.issues.unassigned_jobs) { this.result.getRawData().properties.issues.unassigned_jobs = []; } } } fixUnassignedItems(rawData, originalIndexes) { var _a, _b, _c; if ((_a = rawData.properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_agents) { rawData.properties.issues.unassigned_agents = rawData.properties.issues.unassigned_agents.map((agentIndex) => { return originalIndexes.originalAgentIndex; }); } if ((_b = rawData.properties.issues) === null || _b === void 0 ? void 0 : _b.unassigned_jobs) { rawData.properties.issues.unassigned_jobs = rawData.properties.issues.unassigned_jobs.map((jobIndex) => { return originalIndexes.originalJobsIndexes[jobIndex]; }); } if ((_c = rawData.properties.issues) === null || _c === void 0 ? void 0 : _c.unassigned_shipments) { rawData.properties.issues.unassigned_shipments = rawData.properties.issues.unassigned_shipments.map((shipmentIndex) => { return originalIndexes.originalShipmentsIndexes[shipmentIndex]; }); } } }