diff --git a/features/guidance/anticipate-lanes.feature b/features/guidance/anticipate-lanes.feature index e235f2fba..049faf97c 100644 --- a/features/guidance/anticipate-lanes.feature +++ b/features/guidance/anticipate-lanes.feature @@ -530,7 +530,10 @@ Feature: Turn Lane Guidance @anticipate Scenario: No Lanes for Roundabouts, see #2626 - Given the profile "lhs" + Given the profile file "car" extended with + """ + properties.left_hand_driving = true + """ And the node map | | | a | | | | | | b | | | diff --git a/features/step_definitions/data.js b/features/step_definitions/data.js index dbb3882d1..85d7c5da2 100644 --- a/features/step_definitions/data.js +++ b/features/step_definitions/data.js @@ -1,3 +1,5 @@ +'use strict'; + var util = require('util'); var path = require('path'); var fs = require('fs'); @@ -32,9 +34,9 @@ module.exports = function () { }); this.Given(/^the shortcuts$/, (table, callback) => { - var q = d3.queue(); + let q = d3.queue(); - var addShortcut = (row, cb) => { + let addShortcut = (row, cb) => { this.shortcutsHash[row.key] = row.value; cb(); }; @@ -47,29 +49,28 @@ module.exports = function () { }); this.Given(/^the node map$/, (table, callback) => { - var q = d3.queue(); + let q = d3.queue(); - var addNode = (name, ri, ci, cb) => { + let addNode = (name, ri, ci, cb) => { if (name) { - var nodeWithID = name.match(/([a-z])\:([0-9]*)/); + let nodeWithID = name.match(/([a-z])\:([0-9]*)/); if (nodeWithID) { - var nodeName = nodeWithID[1], + let nodeName = nodeWithID[1], nodeID = nodeWithID[2]; if (this.nameNodeHash[nodeName]) throw new Error(util.format('*** duplicate node %s', name)); - lonLat = this.tableCoordToLonLat(ci, ri); + let lonLat = this.tableCoordToLonLat(ci, ri); this.addOSMNode(nodeName, lonLat[0], lonLat[1], nodeID); } else { if (name.length !== 1) throw new Error(util.format('*** node invalid name %s, must be single characters', name)); if (!name.match(/[a-z0-9]/)) throw new Error(util.format('*** invalid node name %s, must me alphanumeric', name)); - var lonLat; if (name.match(/[a-z]/)) { if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name)); - lonLat = this.tableCoordToLonLat(ci, ri); + let lonLat = this.tableCoordToLonLat(ci, ri); this.addOSMNode(name, lonLat[0], lonLat[1], null); } else { if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name); - lonLat = this.tableCoordToLonLat(ci, ri); + let lonLat = this.tableCoordToLonLat(ci, ri); this.addLocation(name, lonLat[0], lonLat[1], null); } } @@ -89,14 +90,14 @@ module.exports = function () { }); this.Given(/^the node locations$/, (table, callback) => { - var q = d3.queue(); + let q = d3.queue(); - var addNodeLocations = (row, cb) => { - var name = row.node; + let addNodeLocations = (row, cb) => { + let name = row.node; if (this.findNodeByName(name)) throw new Error(util.format('*** duplicate node %s'), name); if (name.match(/[a-z]/)) { - var id = row.id && parseInt(row.id); + let id = row.id && parseInt(row.id); this.addOSMNode(name, row.lon, row.lat, id); } else { this.addLocation(name, row.lon, row.lat); @@ -111,14 +112,14 @@ module.exports = function () { }); this.Given(/^the nodes$/, (table, callback) => { - var q = d3.queue(); + let q = d3.queue(); - var addNode = (row, cb) => { - var name = row.node, + let addNode = (row, cb) => { + let name = row.node, node = this.findNodeByName(name); delete row.node; if (!node) throw new Error(util.format('*** unknown node %s'), name); - for (var key in row) { + for (let key in row) { node.addTag(key, row[key]); } cb(); @@ -132,27 +133,27 @@ module.exports = function () { this.Given(/^the ways$/, (table, callback) => { if (this.osm_str) throw new Error('*** Map data already defined - did you pass an input file in this scenario?'); - var q = d3.queue(); + let q = d3.queue(); - var addWay = (row, cb) => { - var way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID); + let addWay = (row, cb) => { + let way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID); - var nodes = row.nodes; + let nodes = row.nodes; if (this.nameWayHash.nodes) throw new Error(util.format('*** duplicate way %s', nodes)); - for (var i=0; i { if (this.osm_str) throw new Error('*** Map data already defined - did you pass an input file in this scenario?'); - var q = d3.queue(); + let q = d3.queue(); - var addRelation = (row, cb) => { - var relation = new OSM.Relation(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID); + let addRelation = (row, cb) => { + let relation = new OSM.Relation(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID); - for (var key in row) { - var isNode = key.match(/^node:(.*)/), + for (let key in row) { + let isNode = key.match(/^node:(.*)/), isWay = key.match(/^way:(.*)/), isColonSeparated = key.match(/^(.*):(.*)/); if (isNode) { row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => { if (nodeName.length !== 1) throw new Error(util.format('*** invalid relation node member "%s"'), nodeName); - var node = this.findNodeByName(nodeName); + let node = this.findNodeByName(nodeName); if (!node) throw new Error(util.format('*** unknown relation node member "%s"'), nodeName); relation.addMember('node', node.id, isNode[1]); }); } else if (isWay) { row[key].split(',').map(function(v) { return v.trim(); }).forEach((wayName) => { - var way = this.findWayByName(wayName); + let way = this.findWayByName(wayName); if (!way) throw new Error(util.format('*** unknown relation way member "%s"'), wayName); relation.addMember('way', way.id, isWay[1]); }); @@ -248,6 +249,21 @@ module.exports = function () { fs.writeFile(this.penaltiesCacheFile, data, callback); }); + this.Given(/^the profile file(?: "([^"]*)" extended with)?$/, (profile, data, callback) => { + let text = 'package.path = "' + this.PROFILES_PATH + '/?.lua;" .. package.path\n'; + if (profile == null) { + text += data + '\n'; + } else { + text += 'local f = assert(io.open("' + this.PROFILES_PATH + '/' + profile + '.lua", "r"))\n'; + text += 'local m = assert(loadstring(f:read("*all") .. [[\n' + data + '\n]]))\n'; + text += 'f:close()\n'; + text += 'm()\n'; + } + this.profileFile = this.profileCacheFile; + // TODO: Don't overwrite if it exists + fs.writeFile(this.profileCacheFile, text, callback); + }); + this.Given(/^the data has been saved to disk$/, (callback) => { this.reprocess(callback); }); diff --git a/features/support/cache.js b/features/support/cache.js index e388f5976..130e87650 100644 --- a/features/support/cache.js +++ b/features/support/cache.js @@ -103,6 +103,7 @@ module.exports = function() { this.rasterCacheFile = this.getRasterCacheFile(this.featureProcessedCacheDirectory, scenarioID); this.speedsCacheFile = this.getSpeedsCacheFile(this.featureProcessedCacheDirectory, scenarioID); this.penaltiesCacheFile = this.getPenaltiesCacheFile(this.featureProcessedCacheDirectory, scenarioID); + this.profileCacheFile = this.getProfileCacheFile(this.featureProcessedCacheDirectory, scenarioID); }; // returns a hash of all OSRM code side dependencies @@ -159,6 +160,11 @@ module.exports = function() { return path.join(featureCacheDirectory, scenarioID) + '_penalties.csv'; }; + // test/cache/{feature_path}/{feature_hash}/{scenario}_profile.lua + this.getProfileCacheFile = (featureCacheDirectory, scenarioID) => { + return path.join(featureCacheDirectory, scenarioID) + '_profile.lua'; + }; + // test/cache/{feature_path}/{feature_hash}/{scenario}.osm this.getScenarioCacheFile = (featureCacheDirectory, scenarioID) => { return path.join(featureCacheDirectory, scenarioID) + '.osm'; diff --git a/features/testbot/side_bias.feature b/features/testbot/side_bias.feature index fe24117c5..1d6d629c7 100644 --- a/features/testbot/side_bias.feature +++ b/features/testbot/side_bias.feature @@ -1,9 +1,23 @@ @routing @testbot @sidebias Feature: Testbot - side bias + Background: + Given the profile file + """ + require 'testbot' + properties.left_hand_driving = true + """ + Scenario: Left hand bias - Given the profile "lhs" - And the node map + Given the profile file "testbot" extended with + """ + properties.left_hand_driving = true + function turn_function (angle) + local k = 10 * angle * angle * 50 / (90.0 * 90.0) + return (angle >= 0) and k * 1.2 or k / 1.2 + end + """ + Given the node map | a | | b | | c | | | | | | | | | | d | | | @@ -19,7 +33,14 @@ Feature: Testbot - side bias | d | c | bd,bc,bc | 100s +-1 | Scenario: Right hand bias - Given the profile "rhs" + Given the profile file "testbot" extended with + """ + properties.left_hand_driving = false + function turn_function (angle) + local k = 10 * angle * angle * 50 / (90.0 * 90.0) + return (angle >= 0) and k / 1.2 or k * 1.2 + end + """ And the node map | a | | b | | c | | | | | | | @@ -36,7 +57,6 @@ Feature: Testbot - side bias | d | c | bd,bc,bc | 82s +-1 | Scenario: Roundabout exit counting for left sided driving - Given the profile "lhs" And a grid size of 10 meters And the node map | | | a | | | @@ -44,7 +64,7 @@ Feature: Testbot - side bias | h | g | | c | d | | | | e | | | | | | f | | | - And the ways + And the ways | nodes | junction | | ab | | | cd | | @@ -52,14 +72,13 @@ Feature: Testbot - side bias | gh | | | bcegb | roundabout | - When I route I should get + When I route I should get | waypoints | route | turns | | a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive | | a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive | | a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive | - Scenario: Mixed Entry and Exit - Given the profile "lhs" + Scenario: Mixed Entry and Exit And a grid size of 10 meters And the node map | | c | | a | | diff --git a/profiles/lhs.lua b/profiles/lhs.lua deleted file mode 100644 index 84f192428..000000000 --- a/profiles/lhs.lua +++ /dev/null @@ -1,20 +0,0 @@ --- Testbot, with turn penalty --- Used for testing turn penalties - -require 'testbot' - -properties.left_hand_driving = true - -local turn_penalty = 50 -local turn_bias = properties.left_hand_driving and 1/1.2 or 1.2 - -function turn_function (angle) - ---- compute turn penalty as angle^2, with a left/right bias - -- multiplying by 10 converts to deci-seconds see issue #1318 - k = 10*turn_penalty/(90.0*90.0) - if angle>=0 then - return angle*angle*k/turn_bias - else - return angle*angle*k*turn_bias - end -end diff --git a/profiles/rhs.lua b/profiles/rhs.lua deleted file mode 100644 index 022a1443a..000000000 --- a/profiles/rhs.lua +++ /dev/null @@ -1,20 +0,0 @@ --- Testbot, with turn penalty --- Used for testing turn penalties - -require 'testbot' - -properties.left_hand_driving = false - -local turn_penalty = 50 -local turn_bias = properties.left_hand_driving and 1/1.2 or 1.2 - -function turn_function (angle) - ---- compute turn penalty as angle^2, with a left/right bias - -- multiplying by 10 converts to deci-seconds see issue #1318 - k = 10*turn_penalty/(90.0*90.0) - if angle>=0 then - return angle*angle*k/turn_bias - else - return angle*angle*k*turn_bias - end -end