You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
14 KiB
297 lines
14 KiB
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
|
<meta charset="utf-8"> |
|
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"> |
|
<title>Testing BRouter profiles</title> |
|
|
|
<link rel="stylesheet" href="css/leaflet.css"> |
|
<style> |
|
body { |
|
max-width: 800px; |
|
margin: auto; |
|
font-family: sans-serif; |
|
font-size: 14px; |
|
text-align: justify; |
|
} |
|
|
|
h1 { |
|
text-align: center; |
|
margin-top: 20px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.summary { |
|
font-size: 0.8em; |
|
} |
|
|
|
.summary li { |
|
margin-bottom: 2px; |
|
} |
|
|
|
.testcase { |
|
margin-bottom: 30px; |
|
} |
|
|
|
.map { |
|
height: 300px; |
|
} |
|
|
|
.footer { |
|
font-size: 0.8em; |
|
display: flex; |
|
} |
|
|
|
.debug { |
|
flex: auto; |
|
text-align: left; |
|
} |
|
|
|
.back-top { |
|
flex: auto; |
|
text-align: right; |
|
} |
|
|
|
label { |
|
display: inline-block; |
|
text-align: left; |
|
} |
|
|
|
input[type="text"], textarea { |
|
width: 100%; |
|
display: inline-block; |
|
} |
|
|
|
textarea { |
|
min-height: 300px; |
|
} |
|
|
|
#step2 { |
|
display: none; |
|
} |
|
|
|
.center { |
|
text-align: center; |
|
} |
|
|
|
.error { |
|
font-weight: bold; |
|
color: red; |
|
} |
|
|
|
#status { |
|
font-weight: bold; |
|
color: blue; |
|
text-align: center; |
|
} |
|
|
|
#error { |
|
text-align: center; |
|
} |
|
|
|
.footnote { |
|
font-size: 0.8em; |
|
margin-top: -10px; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<h1 id="brouter-tester">BRouter profiles tester</h1> |
|
<p>Here are some test cases to check <a href="http://brouter.de/">BRouter</a> profiles and help with development of new profiles.</p> |
|
|
|
<p><strong>Important: beware that the map tiles used are the live map tiles (using up to date OSM data) contrary to the BRouter <code>segments4</code> test files which are using a fixed dump of OSM data. Then, the map background may come out of sync with the data used by BRouter and are only there as an eyeguide.</strong></p> |
|
|
|
<p>The map show the route computed with the selected profile (in blue), the route computed by the reference profile (in grey) as well as a route computed by a human (in green). Note that the human route is not necessarily the best one or the unique valid solution.</p> |
|
|
|
<p>The tests assume the BRouter instance uses <a href="https://pub.phyks.me/brouter-testing/segments4/">these <code>segments4</code> files</a> which are built from the <a href="https://download.geofabrik.de/">Geofabrik.de</a> extracts of metropolitan France, New York state (US) and Sachsen state (Germany) from the 10th of November, 2018. The <code>profiles2</code> folder used to build the <code>segments4</code> files is available <a href="https://pub.phyks.me/brouter-testing/profiles2/">here</a> (including the <code>lookups.dat</code> file). The SRTM data used to build the <code>segments4</code> are available <a href="https://pub.phyks.me/brouter-testing/srtm/">here</a>.</p> |
|
|
|
|
|
<h2>Settings</h2> |
|
<form id="settings"> |
|
<p> |
|
<label for="profile">Profile content: </label> |
|
<textarea name="profile" id="profile"></textarea> |
|
</p> |
|
<p> |
|
<label for="reference-profile">Reference profile: </label> |
|
<input type="text" name="reference_profile" id="reference-profile" value="trekking" /> |
|
</p> |
|
<p> |
|
<label for="brouter-url">BRouter URL: </label> |
|
<input type="text" name="brouter_url" id="brouter-url" value="http://brouter.de:7777" /> |
|
<p class="footnote">Your BRouter instance should provide <a href="https://developer.mozilla.org/fr/docs/Web/HTTP/CORS">CORS</a> headers. Otherwise, you can use an extension such as <a href="https://addons.mozilla.org/fr/firefox/addon/cors-everywhere/">CORS Everywhere</a>.</p> |
|
</p> |
|
<p> |
|
<label for="brouter-web-url">BRouter web URL (for debug): </label> |
|
<input type="text" name="brouter_web_url" id="brouter-web-url" value="http://brouter.de/brouter-web/" /> |
|
</p> |
|
<p> |
|
<label for="tile-url">Tile URL: </label> |
|
<input type="text" name="tile_url" id="tile-url" value="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/> |
|
</p> |
|
|
|
<p class="error" id="error"></p> |
|
<p id="status"></p> |
|
<p class="center"><input type="submit" value="Run tests"/></p> |
|
</form> |
|
|
|
<div id="step2"> |
|
<h2>Summary</h2> |
|
<div class="summary"></div> |
|
|
|
<template class="testcase-template"> |
|
<div class="testcase"> |
|
<p class="description"></p> |
|
<p class="error"></p> |
|
<div class="map"></div> |
|
<div class="footer"> |
|
<p class="debug"><a href="">Debug this test case</a></p> |
|
<p class="back-top"><a href="#brouter-tester">Back to top ↑</a></p> |
|
</div> |
|
</div> |
|
</template> |
|
</div> |
|
|
|
<script src="js/leaflet.js"></script> |
|
<script src="tests.js"></script> |
|
<script type="text/javascript"> |
|
document.querySelector('#settings').addEventListener('submit', (event) => { |
|
event.preventDefault(); |
|
document.querySelector('#settings input[type="submit"]').disabled = true; |
|
|
|
var profile = document.querySelector('#profile').value; |
|
var referenceProfile = document.querySelector('#reference-profile').value; |
|
var brouterUrl = document.querySelector('#brouter-url').value; |
|
var brouterWebUrl = document.querySelector('#brouter-web-url').value; |
|
var tileUrl = document.querySelector('#tile-url').value; |
|
|
|
if (!profile || !referenceProfile || !brouterUrl || !brouterWebUrl) { |
|
document.querySelector('#error').innerText = 'ERROR: Missing field.'; |
|
return; |
|
} |
|
|
|
fetch(brouterUrl + '/brouter/profile', { |
|
method : "POST", |
|
body: profile, |
|
}).then( |
|
response => response.json() |
|
).then((response) => { |
|
var profileId = response['profileid']; |
|
|
|
document.querySelector('#step2').style.display = 'block'; |
|
document.querySelector('#status').innerText = 'Running tests…'; |
|
|
|
var idx = 0; |
|
var promisesQueue = Promise.resolve(null); |
|
Object.keys(TESTS).forEach((testCategory) => { |
|
var testCategoryID = testCategory.replace(/[^a-zA-Z]/g, ""); |
|
|
|
// Create dedicated section |
|
var h2 = document.createElement('h2'); |
|
h2.innerText = testCategory; |
|
h2.id = testCategoryID; |
|
document.body.appendChild(h2); |
|
|
|
// Handle summary |
|
var summaryTitle = document.createElement('h3'); |
|
var summaryTitleLink = document.createElement('a'); |
|
summaryTitleLink.href = '#' + testCategoryID; |
|
summaryTitleLink.innerText = testCategory; |
|
summaryTitle.appendChild(summaryTitleLink); |
|
var summaryList = document.createElement('ul'); |
|
summaryList.id = testCategoryID + '-summary'; |
|
var summary = document.querySelector('.summary'); |
|
summary.appendChild(summaryTitle); |
|
summary.appendChild(summaryList); |
|
|
|
// Handle all test cases |
|
TESTS[testCategory].forEach((testCase) => { |
|
var startPoint = testCase.start_point; |
|
var endPoint = testCase.end_point; |
|
|
|
// Update summary |
|
var li = document.createElement('li'); |
|
var a = document.createElement('a'); |
|
a.href = '#testcase-' + idx; |
|
a.innerText = testCase.description; |
|
li.appendChild(a); |
|
document.querySelector('#' + testCategoryID + '-summary').append(li); |
|
|
|
// Create entry with map and description |
|
var template = document.querySelector(".testcase-template"); |
|
var clone = template.content.cloneNode(true); |
|
clone.querySelector('.map').id = 'map_' + idx; |
|
clone.querySelector('.error').id = 'error_' + idx; |
|
clone.querySelector('.description').id = 'testcase-' + idx; |
|
clone.querySelector('.description').innerText = '→ ' + testCase.description; |
|
clone.querySelector('.debug a').href = ( |
|
document.querySelector('#brouter-web-url').value + '/#' + |
|
'map=15/' + startPoint[1] + '/' + startPoint[0] + '/osm&' + |
|
'lonlats=' + startPoint.join(',') + '|' + endPoint.join(',') + '&' + |
|
'profile=' + document.querySelector('#reference-profile').value |
|
); |
|
document.body.appendChild(clone); |
|
|
|
var map = L.map('map_' + idx); |
|
L.tileLayer(tileUrl, { |
|
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors', |
|
minZoom: 0, |
|
maxZoom: 20, |
|
}).addTo(map); |
|
map.fitBounds(L.latLngBounds( |
|
L.latLng(Math.min(startPoint[1], endPoint[1]), Math.min(startPoint[0], endPoint[0])), |
|
L.latLng(Math.max(startPoint[1], endPoint[1]), Math.max(startPoint[0], endPoint[0])) |
|
)); |
|
if (testCase.human) { |
|
L.geoJSON(testCase.human, { style: { color: '#5CA423' } }).addTo(map); |
|
} |
|
|
|
function delayFetch(startPoint, endPoint, map, idx) { |
|
return function () { |
|
return new Promise(function (resolve, reject) { |
|
fetch( |
|
brouterUrl + '/brouter?' + |
|
'lonlats=' + startPoint.join(',') + '|' + endPoint.join(',') + '&' + |
|
'profile=' + profileId + '&' + |
|
'alternativeidx=0&format=geojson' |
|
).then(function (geojson) { |
|
return geojson.json(); |
|
}).then(function (geojson) { |
|
L.geoJSON(geojson).addTo(map); |
|
fetch( |
|
brouterUrl + '/brouter?' + |
|
'lonlats=' + startPoint.join(',') + '|' + endPoint.join(',') + '&' + |
|
'profile=' + referenceProfile + '&' + |
|
'alternativeidx=0&format=geojson' |
|
).then(function (geojson) { |
|
return geojson.json(); |
|
}).then(function (geojson) { |
|
L.geoJSON(geojson, { style: { color: '#666666' } }).addTo(map); |
|
resolve(null); |
|
}); |
|
}).catch(function (error) { |
|
document.querySelector('#error').innerText = 'ERROR, see test results below.'; |
|
document.querySelector('#status').innerText = ''; |
|
document.querySelector('#error_' + idx).innerText = 'ERROR: ' + error; |
|
}); |
|
}); |
|
}; |
|
} |
|
|
|
// Overlay route with current profile |
|
promisesQueue = promisesQueue.then(delayFetch(startPoint, endPoint, map, idx)); |
|
|
|
idx += 1; |
|
}); |
|
promisesQueue.then(() => { |
|
document.querySelector('#status').innerText = 'All tests done, see individual results below!'; |
|
}) |
|
}); |
|
}).catch((exc) => { |
|
document.querySelector('#error').innerText = 'ERROR:' + exc; |
|
}); |
|
}); |
|
</script> |
|
</body> |
|
</html>
|
|
|