var util = require('util'); var path = require('path'); var fs = require('fs'); var d3 = require('d3-queue'); var OSM = require('../support/build_osm'); module.exports = function () { this.Given(/^the profile "([^"]*)"$/, (profile, callback) => { this.setProfile(profile, callback); }); this.Given(/^the extract extra arguments "(.*?)"$/, (args, callback) => { this.setExtractArgs(args); callback(); }); this.Given(/^the contract extra arguments "(.*?)"$/, (args, callback) => { this.setContractArgs(args); callback(); }); this.Given(/^a grid size of (\d+) meters$/, (meters, callback) => { this.setGridSize(meters); callback(); }); this.Given(/^the origin ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)$/, (lat, lon, callback) => { this.setOrigin([parseFloat(lon), parseFloat(lat)]); callback(); }); this.Given(/^the shortcuts$/, (table, callback) => { var q = d3.queue(); var addShortcut = (row, cb) => { this.shortcutsHash[row.key] = row.value; cb(); }; table.hashes().forEach((row) => { q.defer(addShortcut, row); }); q.awaitAll(callback); }); this.Given(/^the node map$/, (table, callback) => { var q = d3.queue(); var addNode = (name, ri, ci, cb) => { if (name) { 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); 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); this.addLocation(name, lonLat[0], lonLat[1], null); } cb(); } else cb(); }; table.raw().forEach((row, ri) => { row.forEach((name, ci) => { q.defer(addNode, name, ri, ci); }); }); q.awaitAll(callback); }); this.Given(/^the node locations$/, (table, callback) => { var q = d3.queue(); var addNodeLocations = (row, cb) => { var 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); this.addOSMNode(name, row.lon, row.lat, id); } else { this.addLocation(name, row.lon, row.lat); } cb(); }; table.hashes().forEach((row) => q.defer(addNodeLocations, row)); q.awaitAll(callback); }); this.Given(/^the nodes$/, (table, callback) => { var q = d3.queue(); var addNode = (row, cb) => { var 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) { node.addTag(key, row[key]); } cb(); }; table.hashes().forEach((row) => q.defer(addNode, row)); q.awaitAll(callback); }); 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(); var addWay = (row, cb) => { var way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID); var nodes = row.nodes; if (this.nameWayHash.nodes) throw new Error(util.format('*** duplicate way %s', nodes)); for (var i=0; i q.defer(addWay, row)); q.awaitAll(callback); }); this.Given(/^the relations$/, (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(); var addRelation = (row, cb) => { var 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:(.*)/), 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); 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); if (!way) throw new Error(util.format('*** unknown relation way member "%s"'), wayName); relation.addMember('way', way.id, isWay[1]); }); } else if (isColonSeparated && isColonSeparated[1] !== 'restriction') { throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"'), isColonSeparated[1], isColonSeparated[2]); } else { relation.addTag(key, row[key]); } } relation.uid = this.OSM_UID; this.OSMDB.addRelation(relation); cb(); }; table.hashes().forEach((row) => q.defer(addRelation, row)); q.awaitAll(callback); }); this.Given(/^the input file ([^"]*)$/, (file, callback) => { if (path.extname(file) !== '.osm') throw new Error('*** Input file must be in .osm format'); fs.readFile(file, 'utf8', (err, data) => { if (!err) this.osm_str = data.toString(); callback(err); }); }); this.Given(/^the raster source$/, (data, callback) => { fs.writeFile(path.resolve(this.TEST_FOLDER, 'rastersource.asc'), data, callback); }); this.Given(/^the speed file$/, (data, callback) => { fs.writeFile(path.resolve(this.TEST_FOLDER, 'speeds.csv'), data, callback); }); this.Given(/^the data has been saved to disk$/, (callback) => { try { this.reprocess(callback); } catch(e) { this.processError = e; callback(e); } }); this.Given(/^the data has been extracted$/, (callback) => { this.writeAndExtract((err) => { if (err) this.processError = err; callback(); }); }); this.Given(/^the data has been contracted$/, (callback) => { this.reprocess((err) => { if (err) this.processError = err; callback(); }); }); this.Given(/^osrm\-routed is stopped$/, (callback) => { this.OSRMLoader.shutdown((err) => { if (err) this.processError = err; callback(); }); }); this.Given(/^data is loaded directly/, () => { this.loadMethod = 'directly'; }); this.Given(/^data is loaded with datastore$/, () => { this.loadMethod = 'datastore'; }); this.Given(/^the HTTP method "([^"]*)"$/, (method, callback) => { this.httpMethod = method; callback(); }); };