fix: compute GPX stats per-file to avoid spurious inter-track segments
Both stats.html.twig and trip.html.twig previously flattened all GPX trackpoints into a single masterPts array before computing haversine distance, elevation, and moving time. This caused the junction between file N's last point and file N+1's first point to be treated as a real segment — e.g. Florence→coast (~79 km, ~42 h) for Italy's 3-file demo data, overstating distance and moving time significantly. Fix: compute all metrics within each file independently and sum the results. fileResults collection and callback consumption are unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
This commit is contained in:
@@ -437,50 +437,52 @@ function parseGpxFiles(urls, callback) {
|
||||
});
|
||||
|
||||
function computeAndCallback() {
|
||||
var masterPts = [];
|
||||
var totalDistance = 0, totalEleGain = 0, totalEleLoss = 0;
|
||||
var globalHighest = NaN, globalLowest = NaN, totalMovingTime = 0;
|
||||
|
||||
fileResults.forEach(function(pts) {
|
||||
if (pts) { pts.forEach(function(p) { masterPts.push(p); }); }
|
||||
});
|
||||
var n = masterPts.length;
|
||||
if (n < 2) { callback({ distance: 0 }); return; }
|
||||
var distance = 0, eleGain = 0, eleLoss = 0;
|
||||
var highest = NaN, lowest = NaN, movingTime = 0;
|
||||
for (var i = 1; i < n; i++) {
|
||||
var p0 = masterPts[i-1], p1 = masterPts[i];
|
||||
var d = haversineKm(p0.lat, p0.lon, p1.lat, p1.lon);
|
||||
distance += d;
|
||||
if (!isNaN(p0.ele) && !isNaN(p1.ele)) {
|
||||
var dEle = p1.ele - p0.ele;
|
||||
if (dEle > 1) eleGain += dEle - 1;
|
||||
else if (dEle < -1) eleLoss += (-dEle) - 1;
|
||||
if (isNaN(highest) || p1.ele > highest) highest = p1.ele;
|
||||
if (isNaN(lowest) || p1.ele < lowest) lowest = p1.ele;
|
||||
}
|
||||
if (p0.time && p1.time) {
|
||||
var dtHrs = (Date.parse(p1.time) - Date.parse(p0.time)) / 3600000;
|
||||
if (dtHrs > 0) {
|
||||
var speed = d / dtHrs;
|
||||
if (speed >= 1) movingTime += dtHrs;
|
||||
if (!pts || pts.length < 2) return;
|
||||
for (var i = 1; i < pts.length; i++) {
|
||||
var p0 = pts[i-1], p1 = pts[i];
|
||||
var d = haversineKm(p0.lat, p0.lon, p1.lat, p1.lon);
|
||||
totalDistance += d;
|
||||
|
||||
if (!isNaN(p0.ele) && !isNaN(p1.ele)) {
|
||||
var dEle = p1.ele - p0.ele;
|
||||
if (dEle > 1) totalEleGain += dEle - 1;
|
||||
if (dEle < -1) totalEleLoss += (-dEle) - 1;
|
||||
if (isNaN(globalHighest) || p1.ele > globalHighest) globalHighest = p1.ele;
|
||||
if (isNaN(globalLowest) || p1.ele < globalLowest) globalLowest = p1.ele;
|
||||
}
|
||||
|
||||
if (p0.time && p1.time) {
|
||||
var dtHrs = (Date.parse(p1.time) - Date.parse(p0.time)) / 3600000;
|
||||
if (dtHrs > 0) {
|
||||
var speed = d / dtHrs;
|
||||
if (speed >= 1) totalMovingTime += dtHrs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// include first point in elevation range
|
||||
if (!isNaN(masterPts[0].ele)) {
|
||||
if (isNaN(highest) || masterPts[0].ele > highest) highest = masterPts[0].ele;
|
||||
if (isNaN(lowest) || masterPts[0].ele < lowest) lowest = masterPts[0].ele;
|
||||
}
|
||||
var avgSpeed = movingTime > 0 ? distance / movingTime : 0;
|
||||
var movHours = Math.floor(movingTime);
|
||||
var movMins = Math.round((movingTime - movHours) * 60);
|
||||
// include first point of each file in elevation range
|
||||
if (pts.length > 0 && !isNaN(pts[0].ele)) {
|
||||
if (isNaN(globalHighest) || pts[0].ele > globalHighest) globalHighest = pts[0].ele;
|
||||
if (isNaN(globalLowest) || pts[0].ele < globalLowest) globalLowest = pts[0].ele;
|
||||
}
|
||||
});
|
||||
|
||||
var avgSpeed = totalMovingTime > 0 ? totalDistance / totalMovingTime : 0;
|
||||
var movHours = Math.floor(totalMovingTime);
|
||||
var movMins = Math.round((totalMovingTime - movHours) * 60);
|
||||
if (movMins === 60) { movHours++; movMins = 0; }
|
||||
|
||||
callback({
|
||||
distance: distance,
|
||||
eleGain: eleGain,
|
||||
eleLoss: eleLoss,
|
||||
highest: highest,
|
||||
lowest: lowest,
|
||||
movingTime: movHours + ':' + (movMins < 10 ? '0' : '') + movMins,
|
||||
avgSpeed: avgSpeed
|
||||
distance: totalDistance,
|
||||
eleGain: totalEleGain,
|
||||
eleLoss: totalEleLoss,
|
||||
highest: globalHighest,
|
||||
lowest: globalLowest,
|
||||
movingTime: movHours + ':' + (movMins < 10 ? '0' : '') + movMins,
|
||||
avgSpeed: avgSpeed
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user