fix: deterministic multi-GPX trackpoint ordering and catch-path completion
Pre-allocate fileResults[idx] slots so GPX files always concatenate in URL order regardless of fetch arrival order (Bug 1). Both .then and .catch now call computeDistance() after decrementing pending so a failed last fetch no longer leaves the distance element permanently blank (Bug 2). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
This commit is contained in:
@@ -144,33 +144,46 @@ function haversine(lat1, lng1, lat2, lng2) {
|
||||
var distEl = document.getElementById('stat-distance');
|
||||
|
||||
if (GPX_URLS.length > 0) {
|
||||
// Mode A: sum haversine between all GPX trackpoints
|
||||
// Mode A: sum haversine between all GPX trackpoints (deterministic order)
|
||||
var pending = GPX_URLS.length;
|
||||
var masterPts = [];
|
||||
GPX_URLS.forEach(function(url) {
|
||||
var fileResults = new Array(GPX_URLS.length);
|
||||
GPX_URLS.forEach(function(url, idx) {
|
||||
fetch(url)
|
||||
.then(function(r) { return r.text(); })
|
||||
.then(function(text) {
|
||||
var xml = new DOMParser().parseFromString(text, 'text/xml');
|
||||
var trkpts = xml.querySelectorAll('trkpt');
|
||||
var pts = [];
|
||||
trkpts.forEach(function(pt) {
|
||||
masterPts.push({
|
||||
pts.push({
|
||||
lat: parseFloat(pt.getAttribute('lat')),
|
||||
lon: parseFloat(pt.getAttribute('lon'))
|
||||
});
|
||||
});
|
||||
fileResults[idx] = pts;
|
||||
pending--;
|
||||
if (pending === 0) {
|
||||
var total = 0;
|
||||
for (var i = 1; i < masterPts.length; i++) {
|
||||
total += haversine(masterPts[i-1].lat, masterPts[i-1].lon,
|
||||
masterPts[i].lat, masterPts[i].lon);
|
||||
}
|
||||
distEl.textContent = masterPts.length < 2 ? '—' : Math.round(total).toLocaleString();
|
||||
}
|
||||
if (pending === 0) { computeDistance(); }
|
||||
})
|
||||
.catch(function(err) { console.warn('GPX load failed:', url, err); pending--; });
|
||||
.catch(function(err) {
|
||||
console.warn('GPX load failed:', url, err);
|
||||
fileResults[idx] = [];
|
||||
pending--;
|
||||
if (pending === 0) { computeDistance(); }
|
||||
});
|
||||
});
|
||||
|
||||
function computeDistance() {
|
||||
var masterPts = [];
|
||||
fileResults.forEach(function(pts) {
|
||||
if (pts) { pts.forEach(function(p) { masterPts.push(p); }); }
|
||||
});
|
||||
var total = 0;
|
||||
for (var i = 1; i < masterPts.length; i++) {
|
||||
total += haversine(masterPts[i-1].lat, masterPts[i-1].lon,
|
||||
masterPts[i].lat, masterPts[i].lon);
|
||||
}
|
||||
distEl.textContent = masterPts.length < 2 ? '—' : Math.round(total).toLocaleString();
|
||||
}
|
||||
} else {
|
||||
// Mode B: sum haversine between consecutive entry lat/lng points
|
||||
var total = 0;
|
||||
|
||||
Reference in New Issue
Block a user