fix: measure trip gap tolerance in real calendar days, not array-index distance
clusterTrips's gap check compared array-index adjacency between DaySignal entries. Since `days` only contains dates with >=1 photo (GROUP BY DATE(...) with no zero-photo rows), two trips separated by months with no photos in between were array-adjacent (gapLen=0) and got merged into one bogus trip. Compare actual elapsed calendar days between the last and next away day instead.
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
* Pure functions — no DB, no network. Easy to unit-test.
|
||||
*/
|
||||
|
||||
import { differenceInCalendarDays, parseISO } from "date-fns";
|
||||
|
||||
export interface DaySignal {
|
||||
/** YYYY-MM-DD */
|
||||
date: string;
|
||||
@@ -160,12 +162,16 @@ export function clusterTrips(days: DaySignal[], opts: ClusterOptions): Trip[] {
|
||||
k += 1;
|
||||
continue;
|
||||
}
|
||||
// Count consecutive non-away days
|
||||
const gapStart = k;
|
||||
// Skip consecutive non-away days, then compare actual elapsed calendar
|
||||
// days (not array-index distance) against the next away day — `days`
|
||||
// only contains dates with ≥1 photo, so a months-long photo-less gap
|
||||
// must not look "adjacent" just because no entries sit between them.
|
||||
while (k < sorted.length && !away[k]) k += 1;
|
||||
const gapLen = k - gapStart;
|
||||
if (gapLen > opts.gapTolerance) break; // close trip at endIdx
|
||||
// else tolerated; `k` now points at next away day (or end)
|
||||
if (k < sorted.length) {
|
||||
const gapDays = differenceInCalendarDays(parseISO(sorted[k].date), parseISO(sorted[endIdx].date));
|
||||
if (gapDays > opts.gapTolerance) break; // close trip at endIdx
|
||||
}
|
||||
// else tolerated (or no more away days left); `k` now points at next away day (or end)
|
||||
}
|
||||
|
||||
const slice = sorted.slice(i, endIdx + 1);
|
||||
|
||||
Reference in New Issue
Block a user