route4me-nodejs-sdk
Version:
Access Route4Me's logistics-as-a-service API using our Node.js SDK
421 lines (398 loc) • 15.9 kB
JavaScript
"use strict"
const utils = require("../utils")
/**
* Optimizations facility
*
* @category Optimizations
*/
class Optimizations {
/**
* Constructor
*
* @see {@link https://route4me.io/docs/#optimizations}
* @since 0.1.3
* @private
*
* @param {RequestManager} requestManager - Request Manager
* @return {Optimizations} - Optimizations facility
*/
constructor(requestManager) {
this.r = requestManager
}
/**
* Create a new optimization
*
* @see {@link https://route4me.io/docs/#create-an-optimization}
*
* @param {jsonschema:Optimizations.CreateRequest} optimization - Parameters for new optimization
* @param {boolean} isRedirect
* @param {module:route4me-node~RequestCallback<jsonschema:
* Optimizations.Response>} [callback]
*/
create(optimization, isRedirect, callback) {
if (!isRedirect) {
const qs = {}
qs["redirect"] = 0
return this.r._makeRequest({
method: "POST",
path: "/api.v4/optimization_problem.php",
qs,
body: optimization,
validationContext: "Optimizations.Response",
}, callback)
}
return this.r._makeRequest({
method: "POST",
path: "/api.v4/optimization_problem.php",
body: optimization,
validationContext: "Optimizations.Response",
}, callback)
}
/* eslint-disable max-len */
/**
* Create a new optimization with Advanced constraints
*
* @see {@link https://route4me.io/docs/#create-an-optimization}
* @since 0.1.15
*
* @param {object} props - Optimization properties.
* Here are some required or useful properties, for full list of properties look at docs.
* @see {@link https://github.com/route4me/route4me-json-schemas/blob/master/Optimization_create.json}
*
* @param {object} props.parameters - Route Parameters.
* Here are some required and useful parameters, for full list of properties look at docs.
* @see {@link https://github.com/route4me/route4me-json-schemas/blob/master/RouteParameters.json}
*
* @param {number} props.parameters.algorithm_type - The optimization algorithm to be used.
* Possible values:
* 1 = TSP, 2 = VRP, 3 = CVRP_TW_SD, 4 = CVRP_TW_MD, 5 = TSP_TW, 6 = TSP_TW_CR, 7 = BBCVRP,
* 9 = ADVANCED_CVRP_TW,100 = ALG_NONE, 101 = ALG_LEGACY_DISTRIBUTED
*
* @param {string} props.parameters.device_type - The type of the device that is
* creating this route.
* Possible values: "web", "iphone", "ipad", "android_phone", "android_tablet".
*
* @param {string} props.parameters.distance_unit - The distance measurement unit for the route.
* Possible values: "mi", "km".
*
* @param {number} props.parameters.route_max_duration = 86400 - How many seconds a route can last at most.
* Default is 24 hours = 86400 seconds.
*
* @param {number} props.parameters.route_time = 25200 - Time when the route starts
* (relative to route_date) (Seconds). UTC timezone as well.
* Default is 07:00 UTC = 25200 seconds.
*
* @param {number} props.parameters.travel_mode - The mode of travel that the directions
* should be optimized for.
* Possible values: "Driving", "Walking", "Bicycling".
*
* @param {string} [props.parameters.optimize] - The driving directions will be generated
* biased for this selection. This has no impact on route sequencing.
* Possible values: "Distance", "Time", "timeWithTraffic".
*
* @param {number} [props.parameters.parts] - Legacy feature which permits a user to
* request an example number of optimized routes.
*
* @param {number} [props.parameters.route_date] - The route start date in UTC, unix timestamp
* seconds. Used to show users when the route will begin, also used for reporting and analytics.
*
* @param {string} [props.parameters.route_name] - The name of this route. this route name will
* be accessible in the search API, and also will be displayed on the mobile device of a user.
*
* @param {boolean} [props.parameters.rt] - The tour type of this route. rt is short
* for round trip, the optimization engine changes its behavior for round trip routes.
*
* @param {number} [props.parameters.vehicle_capacity] - How much cargo can the vehicle carry
* (units, e.g. cubic meters)
*
* @param {number} [props.parameters.vehicle_max_distance_mi] - Maximum distance for a single vehicle
* in this route (always in miles).
*
* @param {number} [props.parameters.advanced_constraints] - Advanced Constraints.
* @param {number} [props.parameters.advanced_constraints.max_cargo_weight] - Maximum cargo weight per route.
* @param {number} [props.parameters.advanced_constraints.max_cargo_volume] - Maximum cargo volume per route.
* @param {number} [props.parameters.advanced_constraints.max_capacity] - How much total cargo
* can be transported per route (units, e.g. cubic meters).
*
* @param {number} [props.parameters.advanced_constraints.members_count] - Legacy feature which
* permits a user to request an example number of optimized routes.
*
* @param {array[]} props.parameters.advanced_constraints.available_time_windows - An array of the
* available time windows, e.g. [[43200, 72000], [TimeStart, TimeEnd]]
* Time Window Start in seconds: 7:00 am EST = (7 + 5) * 3600 = 43200
* Time Window End in seconds: 15:00 am EST = (15 + 5) * 3600 = 72000
*
* @param {string[]} [props.parameters.advanced_constraints.tags] - The driver tags
* specified in a team member's custom data. (e.g. 'driver skills':
* ["Class A CDL", "Class B CDL", "Forklift", "Skid Steer Loader", "Independent Contractor"])
*
* @param {number[]} [props.parameters.advanced_constraints.route4me_members_id] - An array of the skilled driver IDs.
* @param {object} [props.parameters.advanced_constraints.depot_address] - A depot address.
* @param {number} props.parameters.advanced_constraints.depot_address.source_id - Source ID.
* @param {string} props.parameters.advanced_constraints.depot_address.source_type - Source type (e.g. input_addresses).
* @param {object[]} [props.parameters.advanced_constraints.location_sequence_pattern] - The parameter is used
* in advanced constraints to set the stops you plan to visit each route.
* Note: empty string "" means any stops,
* for example ["", AddresssObject1, AddresssObject2, "", AddresssObject3] means any stops
* before AddresssObject1 and between AddresssObject2 and AddresssObject3.
*
* @param {string} [props.parameters.advanced_constraints.location_sequence_pattern.alias] - Location alias
* @param {string} [props.parameters.advanced_constraints.location_sequence_pattern.address] - Location address
* @param {number} props.parameters.advanced_constraints.location_sequence_pattern.lat - Location latitude
* @param {number} props.parameters.advanced_constraints.location_sequence_pattern.lng - Location longitude
* @param {number} [props.parameters.advanced_constraints.location_sequence_pattern.time] - Location service time
* @param {string} [props.parameters.advanced_constraints.group] - Group name of the advanced constraints.
*
* @param {object[]} [props.depots] - A valid array of Address objects of Depots.
* @param {object[]} props.addresses - A valid array of Address objects.
* Here are some required and useful properties of the Address object,
* for full list of properties look at docs.
* @see {@link https://github.com/route4me/route4me-json-schemas/blob/master/Address.json}
*
* @param {number} props.addresses.lat - Latitude.
* @param {number} props.addresses.lng - Longitude.
* @param {string} [props.addresses.alias] - Address Alias.
* @param {string} [props.addresses.address] - The route Address Line 1.
* @param {boolean} [props.addresses.is_depot = false] - This address is a depot.
* @param {string} [props.addresses.group] - Address group.
* @param {number} [props.addresses.time] - Service time (seconds).
* @param {number} [props.addresses.time_window_start] - Time Window Start in seconds, relative to
* the route start date (midnight), UTC time zone. It is relative to start date because start time
* changes would shift time windows.
*
* @param {number} [props.addresses.time_window_end] - Time Window End in seconds, relative to the
* route start date (midnight), UTC time zone. It is relative to start date because start time
* changes would shift time windows.
*
* @param {string[]} [props.addresses.tags] - Array of address tags.
* @param {number} [props.addresses.contact_id] - Address book contact id (0 means not connected
* to the address book).
*
* @param {string} [props.optimized_callback_url] - A URL that gets called when the optimization is solved,
* or if there is an error. The callback is called with a POST request.
* The POST data sent is:
* timestamp (Seconds) - Server timestamp of request sent;
* optimization_problem_id (Hash String) - ID of the optimization;
* state (Small Int) - The state can be one of the values:
* 4 = OPTIMIZATION_STATE_OPTIMIZED, which means the optimization was successful;
* 5 = OPTIMIZATION_STATE_ERROR, which means there was an error solving the optimization.
* Query string (GET fields).
*
* @param {boolean} [isRedirect] - If set, it will be redirected. Use false for no redirection or not send.
*
* @param {RequestCallback} callback - The callback that handles the response.
* @see {@link https://github.com/route4me/route4me-json-schemas/blob/master/Optimization_response.json}
*/
createWithAdvancedConstraints(props, isRedirect, callback) {
let isRdr = isRedirect || false
let cb = callback
if (undefined === cb && "function" === typeof isRdr) {
cb = isRdr
isRdr = false
}
if (!isRdr) {
return this.r._makeRequest({
method: "POST",
path: "/api.v4/optimization_problem.php",
qs: { redirect: 0 },
body: props,
validationContext: "Optimizations.Response",
}, cb)
}
return this.r._makeRequest({
method: "POST",
path: "/api.v4/optimization_problem.php",
body: props,
validationContext: "Optimizations.Response",
}, cb)
}
/* eslint-enable max-len */
/**
* GET a single optimization by
* [optimization_problem_id]{@link Optimizations#get~id} parameter.
*
* @see {@link https://route4me.io/docs/#get-an-optimization}
*
* @param {string} id - Optimization Problem ID
* @param {module:route4me-node~RequestCallback<jsonschema:
* Optimizations.Optimization>} [callback]
*/
get(id, callback) {
return this.r._makeRequest({
method: "GET",
path: "/api.v4/optimization_problem.php",
qs: {
"optimization_problem_id": id,
},
validationContext: "Optimizations.Optimization",
}, callback)
}
/**
* GET all optimizations belonging to an user.
*
* @see {@link https://route4me.io/docs/#get-optimizations}
*
* @todo TODO: there is no JSON-schema for the response
* @todo TODO: convert options to optional parameter
*
* @param {(number|string|Array<string>|Array<number>)} states - List of states [1..6]
* @param {Object} options - List-parameters
* @param {number} [options.limit] - List limit
* @param {number} [options.offset] - List offset
* @param {module:route4me-node~RequestCallback<jsonschema:
* Optimizations.Optimizations>} [callback]
*/
list(states, options, callback) {
const validStates = utils.toOptimizationStatesSafe(states)
if (validStates instanceof Error) {
const err = validStates
return this.r._makeError(err, callback)
}
const qs = {}
if (validStates) { qs["states"] = validStates }
if ("offset" in options) {
qs["offset"] = options.offset
}
if ("limit" in options) {
qs["limit"] = options.limit
}
return this.r._makeRequest({
method: "GET",
path: "/api.v4/optimization_problem.php",
qs,
validationContext: "Optimizations.Optimizations",
}, callback)
}
/**
* Edit optimization
*
* Re-optimize existing optimizations by changing some parameters or addresses.
*
* @see {@link https://route4me.io/docs/#re-optimize-an-optimization}
* @since 0.1.7
*
* @param {string} id - Optimization Problem ID
* @param {jsonschema:Optimizations.CreateRequest} data - New values for `Optimization`
* @param {boolean} [reoptimize=false] - Determine, whether the `Optimization`
* should be reoptimized
*
* @param {module:route4me-node~RequestCallback<jsonschema:Optimizations.Response>} [callback]
*/
update(id, data, reoptimize, callback) {
let cb = callback
let reopt = reoptimize
if (undefined === cb
&& "function" === typeof (reopt)
) {
cb = reopt
reopt = false
}
return this.r._makeRequest({
method: "PUT",
path: "/api.v4/optimization_problem.php",
qs: {
"optimization_problem_id": id,
"reoptimize": reopt ? "1" : "0",
},
body: data,
validationContext: "Optimizations.Response",
}, cb)
}
/**
* Remove an existing optimization belonging to an user.
*
* @see {@link https://route4me.io/docs/#remove-an-optimization}
* @since 0.1.7
*
* @todo TODO: There is no schema for validation an output
*
* @example
* const response = {
* "status":true,
* "removed":1
* }
*
* @param {string} ids - Optimization Problem IDs
* @param {module:route4me-node~RequestCallback<jsonschema:
* Optimizations.RemoveResponse>} [callback]
*/
remove(ids, callback) {
return this.r._makeRequest({
method: "DELETE",
path: "/api.v4/optimization_problem.php",
qs: {
"optimization_problem_ids": ids,
},
validationContext: "Optimizations.RemoveResponse",
}, callback)
}
/**
* Insert an address into an optimization, resulting in the recalculation of optimal routes.
*
* @see {@link https://route4me.io/docs/#insert-an-address-into-an-optimization}
* @tag Optimizations
* @tag Addresses
* @since 0.1.7
*
* @param {string} id - Optimization Problem ID
* @param {Array<jsonschema:Addresses.Address>} addresses - Addresses array
* @param {boolean} [reoptimize=false] - Determine, whether the
* `Optimization` should be reoptimized
*
* @param {module:route4me-node~RequestCallback<jsonschema:Addresses.Addresses>} [callback]
*/
linkAddress(id, addresses, reoptimize, callback) {
let cb = callback
let reopt = reoptimize
if (undefined === cb
&& "function" === typeof (reopt)
) {
cb = reopt
reopt = false
}
return this.r._makeRequest({
method: "PUT",
path: "/api.v4/optimization_problem.php",
qs: {
"optimization_problem_id": id,
"reoptimize": reopt ? "1" : "0",
},
body: { "addresses": addresses },
validationContext: "Addresses.Addresses",
}, cb)
}
/**
* Remove a destination (an address) with specified route_destination_id
* from an optimization problem with specified optimization_problem_id.
*
* @see {@link https://route4me.io/docs/#remove-an-address-from-an-optimization}
* @tag Optimizations
* @tag Addresses
* @since 0.1.7
*
* @todo TODO: There is no schema for validation an output
*
* @example
* const response = {
* "deleted":true,
* "route_destination_id":1
* }
*
* @param {string} id - Optimization Problem ID
* @param {number} addressId - Address ID
* @param {module:route4me-node~RequestCallback<jsonschema:
* Optimizations.UnlinkAddressResponse>} [callback]
*/
unlinkAddress(id, addressId, callback) {
return this.r._makeRequest({
method: "DELETE",
path: "/api.v4/address.php",
qs: {
"optimization_problem_id": id,
"route_destination_id": addressId,
},
validationContext: "Optimizations.UnlinkAddressResponse",
}, callback)
}
}
module.exports = Optimizations