Source: bemap-services-v2/routing/bemap-routing-request.js

/**
 * BeNomad BeMap JavaScript API - RoutingRequest
 *
 * Typed request for `bemap.RoutingV2.calculate(request)`.
 *
 * Wire shape mirrors the BeMap server contract (cross-checked against
 * `bemap-flutter-api/lib/service/routing/model/request/routing_request.dart`).
 * Endpoint: `POST service/routing/1.0`.
 *
 * Required wire fields: `destinations`, `routingCriterias`, `options`, `outputLanguage`.
 *
 * @since 1.5.0
 * @public
 * @constructor
 * @param {Object} [options]
 * @param {Array.<bemap.RoutingDestination|bemap.Coordinate|bemap.CoordinateSat|Object>} [options.destinations]
 *   Single flat list. First = origin, last = destination, anything between = via.
 *   Bare coordinates auto-promoted to `RoutingDestination` at serialisation time.
 * @param {Array.<String>} [options.routingCriterias]   Subset of `bemap.RoutingCriteria.*`. Defaults to ['FASTEST'].
 * @param {Array.<String>} [options.options]            Subset of `bemap.RoutingOptions.*`. Defaults to ['POLYLINE'].
 * @param {String} [options.outputLanguage='en']        ISO 639-1 language code for instructions.
 * @param {String} [options.routingMode]                One of `bemap.RoutingMode.*`. Server default is MODE_VIAS.
 * @param {bemap.RoutingVehicleProfile} [options.routingVehicleProfile]
 * @param {Array.<Object>} [options.preferredRoads]
 * @param {Array.<Object>} [options.routingRoadBlocks]
 * @param {Array.<String>} [options.avoidCountryCodes]  ISO-3166 Alpha-3 codes.
 * @param {Number} [options.xyRadius]                   Maximum snap radius around input points.
 * @param {Date|Number|String} [options.departureTime]  Epoch ms / Date / ISO local datetime.
 * @param {Date|Number|String} [options.arrivalTime]    Arrive-by time (epoch ms / Date / ISO). Alternative to departureTime.
 * @param {Number} [options.isoChroneLimit]             Required for MODE_ISOCHRONE.
 * @param {Number} [options.corridorRadius]
 * @param {Array.<Object>} [options.fenceShapes]
 * @param {Number} [options.maxAlternativeRoutes]       0 .. 2
 * @param {Object} [options.routingChargeFeature]
 * @param {Number} [options.matrixStartCount]
 * @param {Array.<Object>} [options.customData]
 * @param {String} [options.geoserver]                  Override Context geoserver.
 * @param {Number} [options.switchIndex]
 * @param {String} [options.requestId]                  Client-side id (used by .cancel()).
 */
bemap.RoutingRequest = function(options) {
    var opts = options || {};

    this.destinations = Array.isArray(opts.destinations) ? opts.destinations.slice() : [];
    this.routingCriterias = Array.isArray(opts.routingCriterias) ? opts.routingCriterias.slice() : null;
    this.options = Array.isArray(opts.options) ? opts.options.slice() : null;
    this.outputLanguage = opts.outputLanguage || null;
    this.routingMode = opts.routingMode || null;
    this.routingVehicleProfile = opts.routingVehicleProfile || null;
    this.preferredRoads = Array.isArray(opts.preferredRoads) ? opts.preferredRoads.slice() : null;
    this.routingRoadBlocks = Array.isArray(opts.routingRoadBlocks) ? opts.routingRoadBlocks.slice() : null;
    this.avoidCountryCodes = Array.isArray(opts.avoidCountryCodes) ? opts.avoidCountryCodes.slice() : null;
    this.xyRadius = (typeof opts.xyRadius === 'number') ? opts.xyRadius : null;
    this.departureTime = opts.departureTime || null;
    this.arrivalTime = opts.arrivalTime || null;
    this.isoChroneLimit = (typeof opts.isoChroneLimit === 'number') ? opts.isoChroneLimit : null;
    this.corridorRadius = (typeof opts.corridorRadius === 'number') ? opts.corridorRadius : null;
    this.fenceShapes = Array.isArray(opts.fenceShapes) ? opts.fenceShapes.slice() : null;
    this.maxAlternativeRoutes = (typeof opts.maxAlternativeRoutes === 'number') ? opts.maxAlternativeRoutes : null;
    this.routingChargeFeature = opts.routingChargeFeature || null;
    this.matrixStartCount = (typeof opts.matrixStartCount === 'number') ? opts.matrixStartCount : null;
    this.customData = Array.isArray(opts.customData) ? opts.customData.slice() : null;
    this.geoserver = opts.geoserver || null;
    this.switchIndex = (typeof opts.switchIndex === 'number') ? opts.switchIndex : null;
    this.requestId = opts.requestId || null;
};

/* Fluent setters */
bemap.RoutingRequest.prototype.addDestination = function(d) { this.destinations.push(d); return this; };
bemap.RoutingRequest.prototype.setDestinations = function(arr) {
    this.destinations = Array.isArray(arr) ? arr.slice() : [];
    return this;
};
bemap.RoutingRequest.prototype.setRoutingCriterias = function(c) {
    this.routingCriterias = Array.isArray(c) ? c.slice() : null;
    return this;
};
bemap.RoutingRequest.prototype.setOptions = function(o) {
    this.options = Array.isArray(o) ? o.slice() : null;
    return this;
};
bemap.RoutingRequest.prototype.setOutputLanguage = function(l) { this.outputLanguage = l; return this; };
bemap.RoutingRequest.prototype.setRoutingMode = function(m) { this.routingMode = m; return this; };
bemap.RoutingRequest.prototype.setRoutingVehicleProfile = function(v) { this.routingVehicleProfile = v; return this; };
bemap.RoutingRequest.prototype.setMaxAlternativeRoutes = function(n) { this.maxAlternativeRoutes = n; return this; };
bemap.RoutingRequest.prototype.setDepartureTime = function(d) { this.departureTime = d; return this; };
bemap.RoutingRequest.prototype.setIsoChroneLimit = function(n) { this.isoChroneLimit = n; return this; };
bemap.RoutingRequest.prototype.setGeoserver = function(g) { this.geoserver = g; return this; };
bemap.RoutingRequest.prototype.setRequestId = function(id) { this.requestId = id; return this; };
bemap.RoutingRequest.prototype.setArrivalTime = function(d) { this.arrivalTime = d; return this; };
bemap.RoutingRequest.prototype.setPreferredRoads = function(a) { this.preferredRoads = Array.isArray(a) ? a.slice() : null; return this; };
bemap.RoutingRequest.prototype.setRoutingRoadBlocks = function(a) { this.routingRoadBlocks = Array.isArray(a) ? a.slice() : null; return this; };
bemap.RoutingRequest.prototype.setAvoidCountryCodes = function(a) { this.avoidCountryCodes = Array.isArray(a) ? a.slice() : null; return this; };
bemap.RoutingRequest.prototype.setXyRadius = function(n) { this.xyRadius = (typeof n === 'number') ? n : null; return this; };
bemap.RoutingRequest.prototype.setCorridorRadius = function(n) { this.corridorRadius = (typeof n === 'number') ? n : null; return this; };
bemap.RoutingRequest.prototype.setFenceShapes = function(a) { this.fenceShapes = Array.isArray(a) ? a.slice() : null; return this; };
bemap.RoutingRequest.prototype.setRoutingChargeFeature = function(o) { this.routingChargeFeature = o || null; return this; };
bemap.RoutingRequest.prototype.setMatrixStartCount = function(n) { this.matrixStartCount = (typeof n === 'number') ? n : null; return this; };
bemap.RoutingRequest.prototype.setCustomData = function(a) { this.customData = Array.isArray(a) ? a.slice() : null; return this; };
bemap.RoutingRequest.prototype.setSwitchIndex = function(n) { this.switchIndex = (typeof n === 'number') ? n : null; return this; };

/** @private */
bemap.RoutingRequest._asEpochOrIso = function(v) {
    if (v === null || v === undefined) return null;
    if (v instanceof Date) return v.getTime();
    if (typeof v === 'number') return v;
    return String(v);
};

/** @private */
bemap.RoutingRequest._serialiseDestinations = function(arr) {
    var out = [];
    for (var i = 0; i < arr.length; i++) {
        var d = arr[i];
        if (!d) continue;
        if (d instanceof bemap.RoutingDestination) {
            out.push(d.toJson());
        } else if (d instanceof bemap.CoordinateSat || d instanceof bemap.Coordinate) {
            out.push(new bemap.RoutingDestination({ coordinateSat: d }).toJson());
        } else if (typeof d === 'object') {
            // Plain {lon, lat, ...} object — coerce
            out.push(new bemap.RoutingDestination({ coordinateSat: d }).toJson());
        }
    }
    return out;
};

bemap.RoutingRequest.prototype.toJson = function() {
    var body = {};

    // Required wire fields
    body.destinations = bemap.RoutingRequest._serialiseDestinations(this.destinations);
    body.routingCriterias = (this.routingCriterias && this.routingCriterias.length)
        ? this.routingCriterias.slice()
        : [bemap.RoutingCriteria.FASTEST];
    body.options = (this.options && this.options.length)
        ? this.options.slice()
        : [bemap.RoutingOptions.POLYLINE];
    body.outputLanguage = this.outputLanguage || 'en';

    // Optional
    if (this.routingMode) body.routingMode = this.routingMode;
    if (this.routingVehicleProfile) {
        body.routingVehicleProfile = (typeof this.routingVehicleProfile.toJson === 'function')
            ? this.routingVehicleProfile.toJson() : this.routingVehicleProfile;
    }
    if (this.preferredRoads && this.preferredRoads.length) body.preferredRoads = this.preferredRoads.slice();
    if (this.routingRoadBlocks && this.routingRoadBlocks.length) body.routingRoadBlocks = this.routingRoadBlocks.slice();
    if (this.avoidCountryCodes && this.avoidCountryCodes.length) body.avoidCountryCodes = this.avoidCountryCodes.slice();
    if (this.xyRadius !== null) body.xyRadius = this.xyRadius;
    var dep = bemap.RoutingRequest._asEpochOrIso(this.departureTime);
    if (dep !== null) body.departureTime = dep;
    var arr = bemap.RoutingRequest._asEpochOrIso(this.arrivalTime);
    if (arr !== null) body.arrivalTime = arr;
    if (this.isoChroneLimit !== null) body.isoChroneLimit = this.isoChroneLimit;
    if (this.corridorRadius !== null) body.corridorRadius = this.corridorRadius;
    if (this.fenceShapes && this.fenceShapes.length) body.fenceShapes = this.fenceShapes.slice();
    if (this.maxAlternativeRoutes !== null) body.maxAlternativeRoutes = this.maxAlternativeRoutes;
    if (this.routingChargeFeature) body.routingChargeFeature = this.routingChargeFeature;
    if (this.matrixStartCount !== null) body.matrixStartCount = this.matrixStartCount;
    if (this.customData && this.customData.length) body.customData = this.customData.slice();
    if (this.geoserver) body.geoserver = this.geoserver;
    if (this.switchIndex !== null) body.switchIndex = this.switchIndex;

    return body;
};