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

175 lines (174 loc) 8.66 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 { RouteResultEditorBase } from "./route-result-editor-base"; import { RoutePlanner } from "../../route-planner"; import { Utils } from "../utils"; export class RouteResultJobEditor extends RouteResultEditorBase { assignJobs(agentIndex, jobIndexes, newPriority) { var _a; return __awaiter(this, void 0, void 0, function* () { this.validateAgent(agentIndex); this.validateJobs(jobIndexes, agentIndex); // Set job priorities in the original data (permanent change) for (const jobIndex of jobIndexes) { this.setJobPriority(jobIndex, newPriority); } // Clone the input data for planning const inputDataCopy = Utils.cloneObject(this.result.getRawData().properties.params); // Apply temporary requirements and capabilities for planning if ((_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_jobs) { this.markJobsUnassigned(inputDataCopy.jobs, this.result.getRawData().properties.issues.unassigned_jobs); } this.markJobsForAgent(inputDataCopy.jobs, jobIndexes, agentIndex); this.markRemainingJobsWithAgentRequirement(inputDataCopy.jobs, jobIndexes); this.addAgentCapabilities(inputDataCopy.agents); const planner = new RoutePlanner(this.result.getOptions(), inputDataCopy); const newResult = yield planner.plan(); this.updateResult(newResult); return true; }); } removeJobs(jobIndexes) { var _a; return __awaiter(this, void 0, void 0, function* () { this.validateJobs(jobIndexes); const inputDataCopy = Utils.cloneObject(this.result.getRawData().properties.params); this.markJobsUnassigned(inputDataCopy.jobs, jobIndexes); if ((_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_jobs) { this.markJobsUnassigned(inputDataCopy.jobs, this.result.getRawData().properties.issues.unassigned_jobs); } this.markRemainingJobsWithAgentRequirement(inputDataCopy.jobs, jobIndexes); this.addAgentCapabilities(inputDataCopy.agents); const planner = new RoutePlanner(this.result.getOptions(), inputDataCopy); const newResult = yield planner.plan(); this.updateResult(newResult); return true; }); } addNewJobs(agentIndex, jobs) { var _a; return __awaiter(this, void 0, void 0, function* () { let jobsRaw = jobs.map(job => job.getRaw()); this.validateAgent(agentIndex); this.validateNewJobs(jobsRaw); // Add new jobs to the original data (permanent change) const initialJobsCount = this.result.getRawData().properties.params.jobs.length; this.result.getRawData().properties.params.jobs.push(...jobsRaw); // Get the indexes of the newly added jobs const newJobIndexes = jobsRaw.map((_, index) => initialJobsCount + index); // Clone the input data for planning const inputDataCopy = Utils.cloneObject(this.result.getRawData().properties.params); // Apply temporary requirements and capabilities for planning if ((_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_jobs) { this.markJobsUnassigned(inputDataCopy.jobs, this.result.getRawData().properties.issues.unassigned_jobs); } this.markJobsForAgent(inputDataCopy.jobs, newJobIndexes, agentIndex); this.markRemainingJobsWithAgentRequirement(inputDataCopy.jobs, newJobIndexes); this.addAgentCapabilities(inputDataCopy.agents); const planner = new RoutePlanner(this.result.getOptions(), inputDataCopy); const newResult = yield planner.plan(); this.updateResult(newResult); return true; }); } markJobsUnassigned(jobs, jobIndexes) { jobIndexes.forEach(jobIndex => { if (jobs[jobIndex]) { if (!jobs[jobIndex].requirements) { jobs[jobIndex].requirements = []; } if (!jobs[jobIndex].requirements.includes(this.unassignedReq)) { jobs[jobIndex].requirements.push(this.unassignedReq); } } }); } markRemainingJobsWithAgentRequirement(jobs, jobIndexes) { for (let i = 0; i < jobs.length; i++) { if (!jobIndexes.includes(i)) { // This is a remaining job, find which agent it belongs to const jobInfo = this.result.getJobInfoByIndex(i); if (jobInfo) { const agentIndex = jobInfo.getAgent().getAgentIndex(); const assignAgentReq = `${this.assignAgentReqStart}${agentIndex}`; if (!jobs[i].requirements) { jobs[i].requirements = []; } if (jobs[i].requirements.includes('unassigned')) { jobs[i].requirements.splice(jobs[i].requirements.indexOf('unassigned'), 1); } if (!jobs[i].requirements.includes(assignAgentReq)) { jobs[i].requirements.push(assignAgentReq); } } } } } markJobsForAgent(jobs, jobIndexes, agentIndex) { jobIndexes.forEach(jobIndex => { if (jobs[jobIndex]) { const assignAgentReq = `assign-agent-${agentIndex}`; if (!jobs[jobIndex].requirements) { jobs[jobIndex].requirements = []; } if (jobs[jobIndex].requirements.includes('unassigned')) { jobs[jobIndex].requirements.splice(jobs[jobIndex].requirements.indexOf('unassigned'), 1); } if (!jobs[jobIndex].requirements.includes(assignAgentReq)) { jobs[jobIndex].requirements.push(assignAgentReq); } } }); } validateJobs(jobIndexes, agentIndex) { if (jobIndexes.length == 0) { throw new Error("No jobs provided"); } if (!this.checkIfArrayIsUnique(jobIndexes)) { throw new Error("Jobs are not unique"); } jobIndexes.forEach((jobIndex) => { let jobInfo = this.result.getJobInfoByIndex(jobIndex); if (jobInfo == undefined) { this.validateJobExists(jobIndex); } if (agentIndex != undefined) { if ((jobInfo === null || jobInfo === void 0 ? void 0 : jobInfo.getAgent().getAgentIndex()) == agentIndex) { throw new Error(`Job with index ${jobIndex} already assigned to agent with index ${agentIndex}`); } } }); } validateJobExists(jobIndex) { let jobFound = this.getJobByIndex(jobIndex); if (!jobFound) { throw new Error(`Job with index ${jobIndex} not found`); } else { let isUnassignedJob = this.result.getRawData().properties.issues.unassigned_jobs.includes(jobIndex); if (!isUnassignedJob) { throw new Error(`Job with index ${jobIndex} is invalid`); } } } validateNewJobs(jobs) { if (jobs.length == 0) { throw new Error("No jobs provided"); } if (!this.checkIfArrayIsUnique(jobs)) { throw new Error("Jobs are not unique"); } } setJobPriority(jobIndex, newPriority) { if (newPriority != undefined) { this.result.getRawData().properties.params.jobs[jobIndex].priority = newPriority; } } }