@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
169 lines (168 loc) • 9.03 kB
JavaScript
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 RouteResultShipmentEditor extends RouteResultEditorBase {
assignShipments(agentIndex, shipmentIndexes, newPriority) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
this.validateAgent(agentIndex);
this.validateShipments(shipmentIndexes, agentIndex);
for (const shipmentIndex of shipmentIndexes) {
this.setShipmentPriority(shipmentIndex, newPriority);
}
const inputDataCopy = Utils.cloneObject(this.result.getRawData().properties.params);
if ((_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_shipments) {
this.markShipmentsUnassigned(inputDataCopy.shipments, this.result.getRawData().properties.issues.unassigned_shipments);
}
this.markShipmentsForAgent(inputDataCopy.shipments, shipmentIndexes, agentIndex);
this.markRemainingShipmentsWithAgentRequirement(inputDataCopy.shipments, shipmentIndexes);
this.addAgentCapabilities(inputDataCopy.agents);
const planner = new RoutePlanner(this.result.getOptions(), inputDataCopy);
const newResult = yield planner.plan();
this.updateResult(newResult);
return true;
});
}
removeShipments(shipmentIndexes) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
this.validateShipments(shipmentIndexes);
const inputDataCopy = Utils.cloneObject(this.result.getRawData().properties.params);
this.markShipmentsUnassigned(inputDataCopy.shipments, shipmentIndexes);
if ((_a = this.result.getRawData().properties.issues) === null || _a === void 0 ? void 0 : _a.unassigned_shipments) {
this.markShipmentsUnassigned(inputDataCopy.shipments, this.result.getRawData().properties.issues.unassigned_shipments);
}
this.markRemainingShipmentsWithAgentRequirement(inputDataCopy.shipments, shipmentIndexes);
this.addAgentCapabilities(inputDataCopy.agents);
const planner = new RoutePlanner(this.result.getOptions(), inputDataCopy);
const newResult = yield planner.plan();
this.updateResult(newResult);
return true;
});
}
markShipmentsUnassigned(shipments, shipmentIndexes) {
shipmentIndexes.forEach(shipmentIndex => {
if (shipments[shipmentIndex]) {
if (!shipments[shipmentIndex].requirements) {
shipments[shipmentIndex].requirements = [];
}
if (!shipments[shipmentIndex].requirements.includes(this.unassignedReq)) {
shipments[shipmentIndex].requirements.push(this.unassignedReq);
}
}
});
}
markRemainingShipmentsWithAgentRequirement(shipments, shipmentIndexes) {
for (let i = 0; i < shipments.length; i++) {
if (!shipmentIndexes.includes(i)) {
// This is a remaining shipment, find which agent it belongs to
const shipmentInfo = this.result.getShipmentInfoByIndex(i);
if (shipmentInfo) {
const agentIndex = shipmentInfo.getAgent().getAgentIndex();
const assignAgentReq = `${this.assignAgentReqStart}${agentIndex}`;
if (!shipments[i].requirements) {
shipments[i].requirements = [];
}
if (!shipments[i].requirements.includes(assignAgentReq)) {
shipments[i].requirements.push(assignAgentReq);
}
}
}
}
}
addNewShipments(agentIndex, shipments) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let shipmentsRaw = shipments.map(shipment => shipment.getRaw());
this.validateAgent(agentIndex);
this.validateNewShipments(shipmentsRaw);
// Add new shipments to the original data (permanent change)
const initialShipmentsCount = this.result.getRawData().properties.params.shipments.length;
this.result.getRawData().properties.params.shipments.push(...shipmentsRaw);
// Get the indexes of the newly added shipments
const newShipmentIndexes = shipmentsRaw.map((_, index) => initialShipmentsCount + 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_shipments) {
this.markShipmentsUnassigned(inputDataCopy.shipments, this.result.getRawData().properties.issues.unassigned_shipments);
}
this.markShipmentsForAgent(inputDataCopy.shipments, newShipmentIndexes, agentIndex);
this.markRemainingShipmentsWithAgentRequirement(inputDataCopy.shipments, newShipmentIndexes);
this.addAgentCapabilities(inputDataCopy.agents);
const planner = new RoutePlanner(this.result.getOptions(), inputDataCopy);
const newResult = yield planner.plan();
this.updateResult(newResult);
return true;
});
}
validateShipments(shipmentIndexes, agentIndex) {
if (shipmentIndexes.length == 0) {
throw new Error("No shipments provided");
}
if (!this.checkIfArrayIsUnique(shipmentIndexes)) {
throw new Error("Shipments are not unique");
}
shipmentIndexes.forEach((shipmentIndex) => {
let shipmentInfo = this.result.getShipmentInfoByIndex(shipmentIndex);
if (shipmentInfo == undefined) {
this.validateShipmentExists(shipmentIndex);
}
if (agentIndex != undefined) {
if ((shipmentInfo === null || shipmentInfo === void 0 ? void 0 : shipmentInfo.getAgent().getAgentIndex()) == agentIndex) {
throw new Error(`Shipment with index ${shipmentIndex} already assigned to agent with index ${agentIndex}`);
}
}
});
}
validateShipmentExists(shipmentIndex) {
let shipmentFound = this.getShipmentByIndex(shipmentIndex);
if (!shipmentFound) {
throw new Error(`Shipment with index ${shipmentIndex} not found`);
}
else {
let isUnassignedShipment = this.result.getRawData().properties.issues.unassigned_shipments.includes(shipmentIndex);
if (!isUnassignedShipment) {
throw new Error(`Shipment with index ${shipmentIndex} is invalid`);
}
}
}
validateNewShipments(shipments) {
if (shipments.length == 0) {
throw new Error("No shipments provided");
}
if (!this.checkIfArrayIsUnique(shipments)) {
throw new Error("Shipments are not unique");
}
}
setShipmentPriority(jobIndex, newPriority) {
if (newPriority != undefined) {
this.result.getRawData().properties.params.shipments[jobIndex].priority = newPriority;
}
}
markShipmentsForAgent(shipments, shipmentIndexes, agentIndex) {
shipmentIndexes.forEach(shipmentIndex => {
if (shipments[shipmentIndex]) {
const assignAgentReq = `assign-agent-${agentIndex}`;
if (!shipments[shipmentIndex].requirements) {
shipments[shipmentIndex].requirements = [];
}
if (shipments[shipmentIndex].requirements.includes('unassigned')) {
shipments[shipmentIndex].requirements.splice(shipments[shipmentIndex].requirements.indexOf('unassigned'), 1);
}
if (!shipments[shipmentIndex].requirements.includes(assignAgentReq)) {
shipments[shipmentIndex].requirements.push(assignAgentReq);
}
}
});
}
}