Sort by timestamp not seq, filter teleportation glitches
Track 22 May showed 31km instead of 12.6km because 4 points had wrong seq order — native service and WebView GPS interleaved. Sorting by seq placed them wrong, creating 2km+ teleport jumps. Fixes: - All sort calls now use timestamp only (seq was unreliable) - computeStats skips segments > 180 km/h (GPS teleportation) - After recalculate: 22 May track should show ~12.6 km
This commit is contained in:
parent
9b5c9a204c
commit
0dd4a67e7b
2 changed files with 8 additions and 12 deletions
|
|
@ -40,11 +40,8 @@ GPS.distance = function(lat1, lon1, lat2, lon2) {
|
|||
GPS.computeStats = function(points, weightKg, opts) {
|
||||
if (points.length < 2) return { distance: 0, elevGain: 0, elevLoss: 0, avgSpeed: 0, maxSpeed: 0, kcal: 0, duration: 0, avgCadence: null };
|
||||
|
||||
// Sort by seq (if present) or timestamp to fix out-of-order points from native service
|
||||
const sorted = points.slice().sort((a, b) => {
|
||||
if (a.seq != null && b.seq != null) return a.seq - b.seq;
|
||||
return new Date(a.ts) - new Date(b.ts);
|
||||
});
|
||||
// Always sort by timestamp — seq can be wrong if points arrived out of order during recording
|
||||
const sorted = points.slice().sort((a, b) => new Date(a.ts) - new Date(b.ts));
|
||||
|
||||
let distance = 0, elevGain = 0, elevLoss = 0;
|
||||
const speeds = []; // m/s per segment
|
||||
|
|
@ -84,9 +81,13 @@ GPS.computeStats = function(points, weightKg, opts) {
|
|||
for (let i = 1; i < sorted.length; i++) {
|
||||
const p = sorted[i], prev = sorted[i - 1];
|
||||
const d = GPS.distance(prev.lat, prev.lon, p.lat, p.lon);
|
||||
distance += d;
|
||||
|
||||
const dt = (new Date(p.ts) - new Date(prev.ts)) / 1000;
|
||||
// Skip teleportation glitches (> 180 km/h = GPS jump)
|
||||
if (dt > 0 && d / dt > 50) continue;
|
||||
|
||||
distance += d;
|
||||
|
||||
const v = dt > 0 ? d / dt : 0; // m/s
|
||||
speeds.push(v);
|
||||
|
||||
|
|
|
|||
|
|
@ -1870,7 +1870,6 @@ function renderRecordingInline(container) {
|
|||
// Restore trail if already recording — sort by seq/ts to avoid jumps
|
||||
if (GPS.recording.points.length > 0) {
|
||||
const sorted = GPS.recording.points.slice().sort((a, b) => {
|
||||
if (a.seq != null && b.seq != null) return a.seq - b.seq;
|
||||
return new Date(a.ts) - new Date(b.ts);
|
||||
});
|
||||
const coords = sorted.map(p => [p.lat, p.lon]);
|
||||
|
|
@ -1883,7 +1882,6 @@ function renderRecordingInline(container) {
|
|||
// Rebuilds polyline from all sorted points instead of adding one-by-one.
|
||||
GPS.recording.onBatchUpdate = () => {
|
||||
const sorted = GPS.recording.points.slice().sort((a, b) => {
|
||||
if (a.seq != null && b.seq != null) return a.seq - b.seq;
|
||||
return new Date(a.ts) - new Date(b.ts);
|
||||
});
|
||||
const coords = sorted.map(p => [p.lat, p.lon]);
|
||||
|
|
@ -1923,10 +1921,7 @@ function setupLiveUpdates(container) {
|
|||
|
||||
GPS.recording.onBatchUpdate = () => {
|
||||
if (!gpsTrailLine || !gpsMap) return;
|
||||
const sorted = GPS.recording.points.slice().sort((a, b) => {
|
||||
if (a.seq != null && b.seq != null) return a.seq - b.seq;
|
||||
return new Date(a.ts) - new Date(b.ts);
|
||||
});
|
||||
const sorted = GPS.recording.points.slice().sort((a, b) => new Date(a.ts) - new Date(b.ts));
|
||||
const coords = sorted.map(p => [p.lat, p.lon]);
|
||||
gpsTrailLine.setLatLngs(coords);
|
||||
if (coords.length) gpsMap.panTo(coords[coords.length - 1]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue