Add script to generate formatted report.
This commit is contained in:
parent
3f2d0afcac
commit
e5b4a14dfd
@ -12,6 +12,9 @@ const errorReason = require('../lib/utils').errorReason;
|
|||||||
|
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
|
|
||||||
|
const osmtogeojson = require('osmtogeojson');
|
||||||
|
const osmxmltojson = require('osmtogeojson/parse_osmxml');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.setGridSize = (meters) => {
|
this.setGridSize = (meters) => {
|
||||||
// the constant is calculated (with BigDecimal as: 1.0/(DEG_TO_RAD*EARTH_RADIUS_IN_METERS
|
// the constant is calculated (with BigDecimal as: 1.0/(DEG_TO_RAD*EARTH_RADIUS_IN_METERS
|
||||||
@ -170,13 +173,18 @@ module.exports = function () {
|
|||||||
if (exists) callback();
|
if (exists) callback();
|
||||||
else {
|
else {
|
||||||
this.OSMDB.toXML((xml) => {
|
this.OSMDB.toXML((xml) => {
|
||||||
fs.writeFile(this.scenarioCacheFile, xml, (err) => {
|
var q = d3.queue(1);
|
||||||
if (err) callback(err);
|
|
||||||
var params = ['cat',this.scenarioCacheFile,'-O','-o',this.scenarioCacheFilePBF, '--no-progress'];
|
q.defer(fs.writeFile, this.scenarioCacheFile, xml);
|
||||||
let child = child_process.execFile('/usr/local/bin/osmium', params, {maxBuffer: 1024 * 1024 * 1000, env: {}}, (err,stdout,stderr) => {
|
q.defer((cb) => {
|
||||||
callback(err);
|
var json = osmxmltojson.parseFromString(xml);
|
||||||
});
|
var geojson = osmtogeojson(json);
|
||||||
|
fs.writeFile(`${this.scenarioCacheFile}.geojson`,JSON.stringify(geojson),cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var params = ['cat',this.scenarioCacheFile,'-O','-o',this.scenarioCacheFilePBF, '--no-progress'];
|
||||||
|
q.defer(child_process.execFile,'/usr/local/bin/osmium', params, {maxBuffer: 1024 * 1024 * 1000, env: {}});
|
||||||
|
q.awaitAll(callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -25,10 +25,12 @@ module.exports = function () {
|
|||||||
this.profile = this.OSRM_PROFILE || this.DEFAULT_PROFILE;
|
this.profile = this.OSRM_PROFILE || this.DEFAULT_PROFILE;
|
||||||
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
|
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
|
||||||
this.setupFeatureCache(feature);
|
this.setupFeatureCache(feature);
|
||||||
|
this.feature = feature;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Before((scenario, callback) => {
|
this.Before((scenario, callback) => {
|
||||||
|
this.scenario = scenario;
|
||||||
this.osrmLoader.setLoadMethod(this.DEFAULT_LOAD_METHOD);
|
this.osrmLoader.setLoadMethod(this.DEFAULT_LOAD_METHOD);
|
||||||
this.setGridSize(this.DEFAULT_GRID_SIZE);
|
this.setGridSize(this.DEFAULT_GRID_SIZE);
|
||||||
this.setOrigin(this.DEFAULT_ORIGIN);
|
this.setOrigin(this.DEFAULT_ORIGIN);
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var polyline = require('polyline');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.ShouldGetAResponse = () => {
|
this.ShouldGetAResponse = () => {
|
||||||
@ -28,10 +30,11 @@ module.exports = function () {
|
|||||||
if (e) return callback(e);
|
if (e) return callback(e);
|
||||||
var headers = new Set(table.raw()[0]);
|
var headers = new Set(table.raw()[0]);
|
||||||
|
|
||||||
var requestRow = (row, ri, cb) => {
|
var requestRow = (row, rowIndex, cb) => {
|
||||||
var got;
|
var got;
|
||||||
|
|
||||||
var afterRequest = (err, res, body) => {
|
var afterRequest = (err, res, body) => {
|
||||||
|
console.log(waypoints);
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (body && body.length) {
|
if (body && body.length) {
|
||||||
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
|
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
|
||||||
@ -76,6 +79,67 @@ module.exports = function () {
|
|||||||
weight_name = this.weightName(route);
|
weight_name = this.weightName(route);
|
||||||
weights = this.weightList(route);
|
weights = this.weightList(route);
|
||||||
approaches = this.approachList(route);
|
approaches = this.approachList(route);
|
||||||
|
|
||||||
|
|
||||||
|
var resultdata = {
|
||||||
|
feature: this.feature.getName(),
|
||||||
|
scenario: this.scenario.getName(),
|
||||||
|
row: rowIndex,
|
||||||
|
expected: {
|
||||||
|
route: table.hashes()[rowIndex]["route"],
|
||||||
|
turns: table.hashes()[rowIndex]["turns"],
|
||||||
|
},
|
||||||
|
got: {
|
||||||
|
route: instructions,
|
||||||
|
turns: turns
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.writeFileSync(`${this.scenarioCacheFile}_${rowIndex}_results.json`,JSON.stringify(resultdata));
|
||||||
|
|
||||||
|
var geojson = {
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: { type: 'startpoint' },
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: [parseFloat(waypoints[0].lon),parseFloat(waypoints[0].lat)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: { type: 'endpoint' },
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: [parseFloat(waypoints[1].lon), parseFloat(waypoints[1].lat)]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'LineString',
|
||||||
|
coordinates: []
|
||||||
|
},
|
||||||
|
properties: {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract Valhalla route geometry
|
||||||
|
if (this.osrmLoader.method === 'valhalla') {
|
||||||
|
geojson.features[2].geometry.coordinates = polyline.decode(route.legs[0].shape,6).map(c => c.reverse());
|
||||||
|
} else {
|
||||||
|
// OSRM route geometry
|
||||||
|
// TODO: Assume polyline5 for now
|
||||||
|
if (typeof route.geometry === 'string') {
|
||||||
|
geojson.features[2].geometry.coordinates = polyline.decode(route.geometry).map(c => c.reverse());
|
||||||
|
} else {
|
||||||
|
geojson.features[2].geometry = route.geometry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.writeFileSync(`${this.scenarioCacheFile}_${rowIndex}_shape.geojson`,JSON.stringify(geojson));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('status')) {
|
if (headers.has('status')) {
|
||||||
|
|||||||
6483
package-lock.json
generated
6483
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,13 @@
|
|||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"carto": "^0.18.2",
|
||||||
|
"mapnik": "^3.6.2",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"nan": "^2.6.2",
|
"nan": "^2.6.2",
|
||||||
"node-cmake": "^2.3.2",
|
"node-cmake": "^2.3.2",
|
||||||
"node-pre-gyp": "^0.6.36",
|
"node-pre-gyp": "^0.6.36",
|
||||||
|
"osmtogeojson": "^3.0.0-beta.3"
|
||||||
"rimraf": "^2.5.4"
|
"rimraf": "^2.5.4"
|
||||||
},
|
},
|
||||||
"browserify": {
|
"browserify": {
|
||||||
|
|||||||
193
scripts/tests2doc.js
Normal file
193
scripts/tests2doc.js
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
"use strict"
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const d3 = require('d3-queue');
|
||||||
|
|
||||||
|
|
||||||
|
var mapnik = require('mapnik');
|
||||||
|
|
||||||
|
mapnik.register_default_input_plugins();
|
||||||
|
mapnik.register_system_fonts()
|
||||||
|
|
||||||
|
//console.log(mapnik.fonts());
|
||||||
|
|
||||||
|
const find = (dir) =>
|
||||||
|
fs.readdirSync(dir)
|
||||||
|
.reduce((files, file) =>
|
||||||
|
fs.statSync(path.join(dir, file)).isDirectory() ?
|
||||||
|
files.concat(find(path.join(dir, file))) :
|
||||||
|
files.concat(path.join(dir, file)),
|
||||||
|
[]);
|
||||||
|
|
||||||
|
function makemappng(basefile, routefile, callback) {
|
||||||
|
|
||||||
|
var stylesheet = `
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE Map[]>
|
||||||
|
<Map srs="+init=epsg:3857" buffer-size="8">
|
||||||
|
|
||||||
|
<Style name="testmap" filter-mode="all">
|
||||||
|
<Rule>
|
||||||
|
<Filter>[highway] = 'motorway'</Filter>
|
||||||
|
<LineSymbolizer stroke-width="12" stroke-linejoin="round" stroke-linecap="round" stroke="#bbbbbb" />
|
||||||
|
<LineSymbolizer stroke-width="10" stroke-linejoin="round" stroke-linecap="round" stroke="#aacc77" />
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='-10'>'name=' + [name]</TextSymbolizer>
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='10'>'highway=' + [highway]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
<Rule>
|
||||||
|
<Filter>[highway] = 'motorway_link'</Filter>
|
||||||
|
<LineSymbolizer stroke-width="12" stroke-linejoin="round" stroke-linecap="round" stroke="#bbbbbb" />
|
||||||
|
<LineSymbolizer stroke-width="10" stroke-linejoin="round" stroke-linecap="round" stroke="#77aacc" />
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='-10'>'name=' + [name]</TextSymbolizer>
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='10'>'highway=' + [highway]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
|
||||||
|
<Rule>
|
||||||
|
<Filter>[highway] = 'trunk'</Filter>
|
||||||
|
<LineSymbolizer stroke-width="12" stroke-linejoin="round" stroke-linecap="round" stroke="#bbbbbb" />
|
||||||
|
<LineSymbolizer stroke-width="10" stroke-linejoin="round" stroke-linecap="round" stroke="#ccaa77" />
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='-10'>'name=' + [name]</TextSymbolizer>
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='10'>'highway=' + [highway]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
<Rule>
|
||||||
|
<Filter>[highway] = 'trunk_link'</Filter>
|
||||||
|
<LineSymbolizer stroke-width="12" stroke-linejoin="round" stroke-linecap="round" stroke="#bbbbbb" />
|
||||||
|
<LineSymbolizer stroke-width="10" stroke-linejoin="round" stroke-linecap="round" stroke="#aa77cc" />
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='-10'>'name=' + [name]</TextSymbolizer>
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='10'>'highway=' + [highway]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
|
||||||
|
<Rule>
|
||||||
|
<Filter>[highway] = 'primary'</Filter>
|
||||||
|
<LineSymbolizer stroke-width="10" stroke-linejoin="round" stroke-linecap="round" stroke="#bbbbbb" />
|
||||||
|
<LineSymbolizer stroke-width="8" stroke-linejoin="round" stroke-linecap="round" stroke="#77ccaa" />
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='-8'>'name=' + [name]</TextSymbolizer>
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='8'>'highway=' + [highway]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
<Rule>
|
||||||
|
<Filter>[highway] = 'primary_link'</Filter>
|
||||||
|
<LineSymbolizer stroke-width="10" stroke-linejoin="round" stroke-linecap="round" stroke="#bbbbbb" />
|
||||||
|
<LineSymbolizer stroke-width="8" stroke-linejoin="round" stroke-linecap="round" stroke="#aa77cc" />
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='-8'>'name=' + [name]</TextSymbolizer>
|
||||||
|
<TextSymbolizer face-name="Arial Regular" size="10" fill="black" placement="line" allow-overlap="false" dy='8'>'highway=' + [highway]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Layer name="testmap" srs="+init=epsg:4326">
|
||||||
|
<StyleName>testmap</StyleName>
|
||||||
|
<Datasource>
|
||||||
|
<Parameter name="type">geojson</Parameter>
|
||||||
|
<Parameter name="file">${basefile}</Parameter>
|
||||||
|
</Datasource>
|
||||||
|
</Layer>
|
||||||
|
|
||||||
|
<Style name="testroute-line" filter-mode="all">
|
||||||
|
<Rule>
|
||||||
|
<LineSymbolizer stroke-width="5" stroke-linejoin="round" stroke-linecap="round" stroke="#000077" offset="6"/>
|
||||||
|
<LineSymbolizer stroke-width="3" stroke-linejoin="round" stroke-linecap="round" stroke="#0000ff" offset="6"/>
|
||||||
|
</Rule>
|
||||||
|
</Style>
|
||||||
|
<Style name="testroute-markers" filter-mode="all">
|
||||||
|
<Rule>
|
||||||
|
<Filter>[type] = 'startpoint'</Filter>
|
||||||
|
<MarkersSymbolizer fill="green" width="20" height="20" stroke="green"/>
|
||||||
|
</Rule>
|
||||||
|
<Rule>
|
||||||
|
<Filter>[type] = 'endpoint'</Filter>
|
||||||
|
<MarkersSymbolizer fill="red" width="20" height="20" stroke="red"/>
|
||||||
|
</Rule>
|
||||||
|
</Style>
|
||||||
|
<Layer name="testroute" srs="+init=epsg:4326">
|
||||||
|
<StyleName>testroute-line</StyleName>
|
||||||
|
<StyleName>testroute-markers</StyleName>
|
||||||
|
<Datasource>
|
||||||
|
<Parameter name="type">geojson</Parameter>
|
||||||
|
<Parameter name="file">${routefile}</Parameter>
|
||||||
|
</Datasource>
|
||||||
|
</Layer>
|
||||||
|
</Map>`;
|
||||||
|
|
||||||
|
var map = new mapnik.Map(300, 200);
|
||||||
|
map.fromStringSync(stylesheet,{strict:true});
|
||||||
|
map.zoomAll();
|
||||||
|
|
||||||
|
var extent = map.extent;
|
||||||
|
extent[0] = extent[0] - Math.abs(extent[0]) * 0.00001;
|
||||||
|
extent[1] = extent[1] - Math.abs(extent[1]) * 0.00001;
|
||||||
|
|
||||||
|
extent[2] = extent[2] + Math.abs(extent[2]) * 0.00001;
|
||||||
|
extent[3] = extent[3] + Math.abs(extent[3]) * 0.00001;
|
||||||
|
map.zoomToBox(extent);
|
||||||
|
|
||||||
|
var buffer = new mapnik.Image(300,200)
|
||||||
|
map.render(buffer, {}, (err,image) => {
|
||||||
|
callback(image.encodeSync('png'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var report = "";
|
||||||
|
|
||||||
|
var toc = [];
|
||||||
|
|
||||||
|
find('test/cache').filter((f) => f.match(/[0-9]+_results.json$/)).forEach((f) => {
|
||||||
|
var files = f.match(/(.*?)_([0-9]+)_results.json$/,f);
|
||||||
|
|
||||||
|
var results = JSON.parse(fs.readFileSync(f));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Generate map image
|
||||||
|
|
||||||
|
var imagefile = `${files[1]}_${files[2]}`.replace(/\//g,'_');
|
||||||
|
|
||||||
|
var png = makemappng(`${files[1]}.geojson`, `${files[1]}_${files[2]}_shape.geojson`, (png) => {
|
||||||
|
fs.writeFileSync(`report/${imagefile}`,png);
|
||||||
|
});
|
||||||
|
|
||||||
|
toc.push({ title: `${results.feature} - ${results.scenario}`, link: imagefile });
|
||||||
|
|
||||||
|
report += `<div class='scenario ${results.got.turns == results.expected.turns ? 'ok' : 'error'}'>
|
||||||
|
<h2><a name="${imagefile}">${results.feature} - ${results.scenario}</a></h2>
|
||||||
|
<table class="row">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<img src="${imagefile}"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<table class="results">
|
||||||
|
<tr><th/><th style='text-align: left'>Route</th><th style='text-align: left'>Turns</th></tr>
|
||||||
|
<tr><th style='text-align: right'>Expected</th><td>${results.expected.route}</td><td>${results.expected.turns}</td></tr>
|
||||||
|
<tr><th style='text-align: right'>Got</th><td>${results.got.route}</td><td class='${results.got.turns == results.expected.turns ? 'ok' : 'error'}'>${results.got.turns}</td></tr>
|
||||||
|
</table>
|
||||||
|
</td></tr></table>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Generate HTML table
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`
|
||||||
|
<!DOCYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body { font-family: sans-serif; }
|
||||||
|
.results td { padding-left: 1em; font-family: monospace; }
|
||||||
|
.results th { padding-left: 1em; }
|
||||||
|
.scenario.error { background: #fbb; }
|
||||||
|
.error { color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
`);
|
||||||
|
toc.forEach(r => {
|
||||||
|
console.log(`<a href='#${r.link}'>${r.title}</a><br/>`);
|
||||||
|
});
|
||||||
|
console.log(report);
|
||||||
|
console.log(`
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
Loading…
Reference in New Issue
Block a user