@furkot/directions
Advanced tools
Comparing version 2.0.2 to 2.1.0
@@ -15,3 +15,3 @@ // path simplification constants | ||
walk: 2, | ||
other: 3, | ||
rv: 5, | ||
ferry: 6 | ||
@@ -18,0 +18,0 @@ }; |
@@ -1,3 +0,7 @@ | ||
const { pathType } = require("../../model"); | ||
// https://docs.graphhopper.com/#tag/Routing-API | ||
// https://github.com/boldtrn/kurviger-api-documentation | ||
const { pathType, travelMode } = require("../../model"); | ||
const status = require('../status'); | ||
const tagRoute = require('../tag-route'); | ||
const util = require('../util'); | ||
@@ -21,14 +25,26 @@ | ||
function prepareWaypoint(qs, p) { | ||
// waypoint format is lat,lon | ||
qs.push('point=' + encodeURIComponent(p[1] + ',' + p[0])); | ||
return qs; | ||
} | ||
const ferryTypes = { | ||
ferry: true | ||
}; | ||
const roughTypes = { | ||
compacted: true, | ||
dirt: true, | ||
fine_gravel: true, | ||
grass: true, | ||
gravel: true, | ||
ground: true, | ||
sand: true, | ||
unpaved: true | ||
}; | ||
const tollTypes = { | ||
all: true | ||
}; | ||
function extractSegment(result, { distance, interval, text, time }) { | ||
const { directions: { segments }, path } = result; | ||
const [from, to] = interval; | ||
segments.push({ | ||
duration: Math.round((time || 0) / 1000), | ||
distance: Math.round(distance || 0), | ||
path: path && path.slice(interval[0], interval[1]), | ||
path: path?.slice(from, to + 1), | ||
instructions: text | ||
@@ -39,3 +55,15 @@ }); | ||
function extractDirections(result, { distance, instructions, points, time }) { | ||
function setFerryMode(seg) { | ||
seg.mode = travelMode.ferry; | ||
} | ||
function setRough(seg) { | ||
seg.rough = true; | ||
} | ||
function setTolls(seg) { | ||
seg.tolls = true; | ||
} | ||
function extractDirections(result, { details, distance, instructions, points, time }) { | ||
const { directions: { routes, segments }, fullPath } = result; | ||
@@ -59,2 +87,26 @@ result.path = util.decode(points); | ||
} | ||
const ferry = tagRoute(details?.road_environment, { | ||
segments, | ||
types: ferryTypes, | ||
updateSegment: setFerryMode | ||
}); | ||
if (ferry?.foundType) { | ||
route.ferry = true; | ||
} | ||
const rough = tagRoute(details?.surface, { | ||
segments, | ||
types: roughTypes, | ||
updateSegment: setRough | ||
}); | ||
if (rough?.foundType) { | ||
route.rough = true; | ||
} | ||
const tolls = tagRoute(details?.toll, { | ||
segments, | ||
types: tollTypes, | ||
updateSegment: setTolls | ||
}); | ||
if (tolls?.foundType) { | ||
route.tolls = true; | ||
} | ||
} | ||
@@ -84,9 +136,44 @@ return result; | ||
function vehicleSize(query, options) { | ||
const { mode, vehicle } = query; | ||
if (!(vehicle && mode === travelMode.rv)) { | ||
return; | ||
} | ||
const { hazmat } = vehicle; | ||
if (hazmat) { | ||
options.push({ | ||
if: 'hazmat == NO', | ||
multiply_by: '0.0' | ||
}); | ||
} | ||
['height', 'width', 'length', 'weight', 'axle_load'].forEach(p => { | ||
if (vehicle[p]) { | ||
options.push({ | ||
if: `max_${p} < ${vehicle[p]}`, | ||
multiply_by: '0.0' | ||
}); | ||
} | ||
}); | ||
} | ||
function init(options) { | ||
function prepareUrl(url, { avoidHighways, avoidTolls, avoidUnpaved, curvy, mode, path, points, turnbyturn }) { | ||
function prepareUrl(url) { | ||
return `${url}?key=${options.graphhopper_key}`; | ||
} | ||
function prepareRequest(query) { | ||
const { avoidFerry, avoidHighways, avoidTolls, avoidUnpaved, curvy, mode, path, points, turnbyturn } = query; | ||
if (options.parameters.max_curvy_distance && curvy && mode === -1 && points.length === 2 && | ||
util.distance(points[0], points[1]) > options.parameters.max_curvy_distance) { | ||
return; | ||
} | ||
let req = { | ||
vehicle: vehicle[mode] || vehicle[0], | ||
key: options.graphhopper_key | ||
points, | ||
details: ['road_environment', 'toll'] | ||
}; | ||
if (!turnbyturn && path !== pathType.smooth && path !== pathType.coarse) { | ||
req.instructions = false; | ||
} | ||
if (curvy && mode === -1) { | ||
@@ -98,2 +185,11 @@ req.vehicle = 'motorcycle.kurviger.de'; | ||
} | ||
if (avoidHighways) { | ||
req.avoid_motorways = true; | ||
} | ||
if (avoidTolls) { | ||
req.avoid_toll_roads = true; | ||
} | ||
if (avoidFerry) { | ||
req.avoid_ferries = true; | ||
} | ||
if (avoidUnpaved) { | ||
@@ -103,29 +199,29 @@ req.avoid_unpaved_roads = true; | ||
} | ||
if (!turnbyturn && path !== pathType.smooth && path !== pathType.coarse) { | ||
req.instructions = false; | ||
} | ||
if (options.parameters.flexible) { | ||
if (avoidTolls) { | ||
req['ch.disable'] = true; | ||
req.avoid = ['toll']; | ||
else { | ||
req.details.push('surface'); | ||
req['ch.disable'] = true; | ||
req.custom_model = { | ||
priority: [{ | ||
if: 'road_class == MOTORWAY', | ||
multiply_by: avoidHighways ? '0.1' : '1.0' | ||
}, { | ||
if: 'toll == ALL', | ||
multiply_by: avoidTolls ? '0.1' : '1.0' | ||
}, { | ||
if: 'road_environment == FERRY', | ||
multiply_by: avoidFerry ? '0.1' : '1.0' | ||
}] | ||
}; | ||
if (avoidUnpaved) { | ||
req.custom_model.priority.push({ | ||
if: 'surface == UNPAVED', | ||
multiply_by: '0.0' | ||
}); | ||
} | ||
if (avoidHighways) { | ||
req['ch.disable'] = true; | ||
req.avoid = req.avoid || []; | ||
req.avoid.push('motorway'); | ||
} | ||
vehicleSize(query, req.custom_model.priority); | ||
} | ||
req = points.reduce(prepareWaypoint, Object.keys(req).map(function (name) { | ||
return name + '=' + encodeURIComponent(req[name]); | ||
})); | ||
return url + '?' + req.join('&'); | ||
return req; | ||
} | ||
function prepareRequest({ mode, points, curvy }) { | ||
return !(options.parameters.max_curvy_distance && curvy && mode === -1 && points.length === 2 && | ||
util.distance(points[0], points[1]) > options.parameters.max_curvy_distance); | ||
} | ||
function processResponse(response, query) { | ||
@@ -163,2 +259,3 @@ | ||
maxPoints: options.graphhopper_max_points || 5, // max 5 points for free and 30-150 for paid plan | ||
post: true, | ||
url: prepareUrl.bind(undefined, options.graphhopper_url), | ||
@@ -165,0 +262,0 @@ status: getStatus, |
@@ -6,2 +6,3 @@ // https://openrouteservice.org/dev/#/api-docs/directions | ||
const status = require('../status'); | ||
const tagRoute = require('../tag-route'); | ||
const util = require('../util'); | ||
@@ -23,51 +24,59 @@ | ||
}; | ||
const ferryType = 9; | ||
const avoidFeatures = { | ||
avoidHighways: 'highways', | ||
avoidTolls: 'tollways', | ||
avoidFerry: 'ferries' | ||
}; | ||
const ferryTypes = { | ||
'9': true | ||
}; | ||
const roughTypes = { | ||
'2': true, // Unpaved | ||
'8': true, // Compacted Gravel | ||
'9': true, // Fine Gravel | ||
'10': true, // Gravel | ||
'11': true, // Dirt | ||
'12': true, // Ground | ||
'15': true, // Sand | ||
'17': true, // Grass | ||
'18': true // Grass Paver | ||
}; | ||
const tollTypes = { | ||
'1': true | ||
}; | ||
const maxRoundabout = 12 * 60 * 60; // 12 hours maximum for route that is 10 times longer than direct distance | ||
function nextFerry(result, points = [-1, -1]) { | ||
let { waytypes } = result; | ||
if (!waytypes) { | ||
return; | ||
} | ||
for (; result.way < waytypes.length; result.way += 1) { | ||
const waytype = waytypes[result.way]; | ||
if (waytype[0] > points[1]) { | ||
return; | ||
} | ||
if (waytype[2] === ferryType && ( | ||
(waytype[0] <= points[0] && waytype[1] >= points[1]) || | ||
(waytype[0] > points[0] && waytype[1] < points[1]) || | ||
(waytype[0] >= points[0] && waytype[0] <= points[1]) || | ||
(waytype[1] >= points[0] && waytype[1] <= points[1]) | ||
)) { | ||
return waytype; | ||
} | ||
} | ||
} | ||
function extractStep(result, { distance, duration, instruction, way_points }) { | ||
const { directions: { segments, routes }, path } = result; | ||
const { directions: { segments }, path } = result; | ||
const seg = { | ||
duration: Math.round(duration || 0), | ||
distance: Math.round(distance || 0), | ||
path: path && path.slice(way_points[0], way_points[1]), | ||
path: path?.slice(way_points[0], way_points[1] + 1), | ||
instructions: instruction | ||
}; | ||
segments.push(seg); | ||
const ferrySeg = nextFerry(result, way_points); | ||
if (ferrySeg) { | ||
seg.mode = travelMode.ferry; | ||
util.last(routes).ferry = true; | ||
} | ||
return result; | ||
} | ||
function setFerryMode(seg) { | ||
seg.mode = travelMode.ferry; | ||
} | ||
function setRough(seg) { | ||
seg.rough = true; | ||
} | ||
function setTolls(seg) { | ||
seg.tolls = true; | ||
} | ||
function extractDirections(result, { distance, duration, steps }, i) { | ||
const { directions: { routes, segments }, path, waypoints } = result; | ||
const { directions: { routes, segments }, path, surface, waypoints, waytypes, tollways } = result; | ||
const route = { | ||
duration: Math.round(duration || 0), | ||
distance: Math.round(distance || 0), | ||
path: path && path.slice(waypoints[i], waypoints[i + 1] + 1) | ||
path: path?.slice(waypoints[i], waypoints[i + 1] + 1) | ||
}; | ||
if (!(route.duration || route.distance || (route.path && route.path.length > 1))) { | ||
if (!(route.duration || route.distance || (route.path?.length > 1))) { | ||
route.path = []; | ||
@@ -80,8 +89,6 @@ } | ||
if (segments && steps) { | ||
result.way = 0; | ||
nextFerry(result); | ||
steps.reduce(extractStep, result); | ||
if (segments.length === 1) { | ||
const seg = segments[0]; | ||
if (!(seg.duration || seg.distance || (seg.path && seg.path.length > 1))) { | ||
if (!(seg.duration || seg.distance || (seg.path?.length > 1))) { | ||
seg.path = []; | ||
@@ -93,2 +100,26 @@ } | ||
} | ||
const ferry = tagRoute(waytypes, { | ||
segments, | ||
types: ferryTypes, | ||
updateSegment: setFerryMode | ||
}); | ||
if (ferry?.foundType) { | ||
route.ferry = true; | ||
} | ||
const rough = tagRoute(surface, { | ||
segments, | ||
types: roughTypes, | ||
updateSegment: setRough | ||
}); | ||
if (rough?.foundType) { | ||
route.rough = true; | ||
} | ||
const tolls = tagRoute(tollways, { | ||
segments, | ||
types: tollTypes, | ||
updateSegment: setTolls | ||
}); | ||
if (tolls?.foundType) { | ||
route.tolls = true; | ||
} | ||
} | ||
@@ -115,3 +146,3 @@ return result; | ||
function getStatus(st, response) { | ||
if (!st && response && response.routes && response.routes.length) { | ||
if (!st && response?.routes?.length) { | ||
const { distance, duration } = response.routes.reduce((result, { summary}) => { | ||
@@ -134,3 +165,3 @@ result.distance += summary.distance; | ||
const { mode, vehicle } = query; | ||
if (!(vehicle && mode === 5)) { | ||
if (!(vehicle && mode === travelMode.rv)) { | ||
return restrictions; | ||
@@ -156,5 +187,16 @@ } | ||
function avoidFeature(result, flag) { | ||
const { query, req } = result; | ||
if (query[flag]) { | ||
req.options = req.options || {}; | ||
req.options.avoid_features = req.options.avoid_features || []; | ||
req.options.avoid_features.push(avoidFeatures[flag]); | ||
} | ||
return result; | ||
} | ||
function prepareRequest(query) { | ||
const req = { | ||
coordinates: query.points | ||
coordinates: query.points, | ||
extra_info: ['surface', 'tollways'] | ||
}; | ||
@@ -164,3 +206,3 @@ if (!query.turnbyturn && query.path !== pathType.smooth && query.path !== pathType.coarse) { | ||
} else { | ||
req.extra_info = ['waytype']; | ||
req.extra_info.push('waytype'); | ||
} | ||
@@ -175,14 +217,7 @@ const restrictions = vehicleSize(query, profileRestrictions[query.mode]); | ||
} | ||
const param = { query, req }; | ||
if ((profile[query.mode] || profile[0]) === 'driving-car') { | ||
if (query.avoidHighways) { | ||
req.options = req.options || { | ||
avoid_features: ['highways'] | ||
}; | ||
} | ||
if (query.avoidTolls) { | ||
req.options = req.options || {}; | ||
req.options.avoid_features = req.options.avoid_features || []; | ||
req.options.avoid_features.push('tollways'); | ||
} | ||
['avoidHighways', 'avoidTolls'].reduce(avoidFeature, param); | ||
} | ||
avoidFeature(param, 'avoidFerry'); | ||
@@ -194,3 +229,3 @@ return req; | ||
if (!(response && response.routes && response.routes.length)) { | ||
if (!response?.routes?.length) { | ||
// let it cascade to the next service | ||
@@ -216,4 +251,6 @@ return; | ||
path: util.decode(geometry), | ||
surface: extras?.surface?.values, | ||
tollways: extras?.tollways?.values, | ||
waypoints, | ||
waytypes: extras && extras.waytypes && extras.waytypes.values | ||
waytypes: extras?.waytypes?.values | ||
}); | ||
@@ -220,0 +257,0 @@ if (fullPath) { |
@@ -52,2 +52,3 @@ // https://github.com/valhalla/valhalla-docs | ||
rough, | ||
toll, | ||
travel_mode | ||
@@ -58,6 +59,12 @@ }) { | ||
let duration = time; | ||
// for some reason Valhalla calculates absurdly low speed on some dirt roads | ||
if (rough && duration && travel_mode === 'drive' && distance > turnDistance && distance / duration < minSpeed) { | ||
duration = Math.round(distance / minSpeed); | ||
if (rough) { | ||
util.last(routes).rough = true; | ||
// for some reason Valhalla calculates absurdly low speed on some dirt roads | ||
if (duration && travel_mode === 'drive' && distance > turnDistance && distance / duration < minSpeed) { | ||
duration = Math.round(distance / minSpeed); | ||
} | ||
} | ||
if (toll) { | ||
util.last(routes).tolls = true; | ||
} | ||
result.legDuration += duration; | ||
@@ -70,2 +77,8 @@ const seg = { | ||
}; | ||
if (rough) { | ||
seg.rough = true; | ||
} | ||
if (toll) { | ||
seg.tolls = true; | ||
} | ||
if (type === maneuver.ferryExit || result.ferry) { | ||
@@ -161,3 +174,3 @@ if (result.ferry) { | ||
const { mode, vehicle } = query; | ||
if (!(vehicle && mode === 5)) { | ||
if (!(vehicle && mode === travelMode.rv)) { | ||
return; | ||
@@ -191,2 +204,10 @@ } | ||
} | ||
if (query.avoidFerry) { | ||
req.costing_options[req.costing].use_ferry = 0; | ||
} else { | ||
req.costing_options[req.costing].use_ferry = 1; | ||
} | ||
if (query.avoidUnpaved) { | ||
req.costing_options[req.costing].exclude_unpaved = true; | ||
} | ||
vehicleSize(query, req.costing_options[req.costing]); | ||
@@ -193,0 +214,0 @@ |
{ | ||
"name": "@furkot/directions", | ||
"version": "2.0.2", | ||
"version": "2.1.0", | ||
"description": "Directions service for Furkot", | ||
@@ -5,0 +5,0 @@ "author": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
48493
16
1662