Fix European trip return heuristic for weekend location tracking

Adjust European short trip heuristic from >3 days to >1 day to correctly
detect when user has returned home from European trips. This fixes the
April 29-30, 2023 case where the location incorrectly showed "Sankt Georg, Hamburg"
instead of "Bristol" when the user was free (no events scheduled) after
the foss-north trip ended on April 27.

The previous logic required more than 3 days to pass before assuming
return home from European countries, but for short European trips by
rail/ferry, users typically return within 1-2 days.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2025-07-16 06:38:37 +02:00
parent 663dc479c2
commit ea4980a5d7
6407 changed files with 1072847 additions and 18 deletions

View file

@ -0,0 +1,95 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var traceMapping = require('@jridgewell/trace-mapping');
var genMapping = require('@jridgewell/gen-mapping');
class SourceMapConsumer {
constructor(map, mapUrl) {
const trace = (this._map = new traceMapping.AnyMap(map, mapUrl));
this.file = trace.file;
this.names = trace.names;
this.sourceRoot = trace.sourceRoot;
this.sources = trace.resolvedSources;
this.sourcesContent = trace.sourcesContent;
this.version = trace.version;
}
static fromSourceMap(map, mapUrl) {
// This is more performant if we receive
// a @jridgewell/source-map SourceMapGenerator
if (map.toDecodedMap) {
return new SourceMapConsumer(map.toDecodedMap(), mapUrl);
}
// This is a fallback for `source-map` and `source-map-js`
return new SourceMapConsumer(map.toJSON(), mapUrl);
}
get mappings() {
return traceMapping.encodedMappings(this._map);
}
originalPositionFor(needle) {
return traceMapping.originalPositionFor(this._map, needle);
}
generatedPositionFor(originalPosition) {
return traceMapping.generatedPositionFor(this._map, originalPosition);
}
allGeneratedPositionsFor(originalPosition) {
return traceMapping.allGeneratedPositionsFor(this._map, originalPosition);
}
hasContentsOfAllSources() {
if (!this.sourcesContent || this.sourcesContent.length !== this.sources.length) {
return false;
}
for (const content of this.sourcesContent) {
if (content == null) {
return false;
}
}
return true;
}
sourceContentFor(source, nullOnMissing) {
const sourceContent = traceMapping.sourceContentFor(this._map, source);
if (sourceContent != null) {
return sourceContent;
}
if (nullOnMissing) {
return null;
}
throw new Error(`"${source}" is not in the SourceMap.`);
}
eachMapping(callback, context /*, order?: number*/) {
// order is ignored as @jridgewell/trace-map doesn't implement it
traceMapping.eachMapping(this._map, context ? callback.bind(context) : callback);
}
destroy() {
// noop.
}
}
class SourceMapGenerator {
constructor(opts) {
// TODO :: should this be duck-typed ?
this._map = opts instanceof genMapping.GenMapping ? opts : new genMapping.GenMapping(opts);
}
static fromSourceMap(consumer) {
return new SourceMapGenerator(genMapping.fromMap(consumer));
}
addMapping(mapping) {
genMapping.maybeAddMapping(this._map, mapping);
}
setSourceContent(source, content) {
genMapping.setSourceContent(this._map, source, content);
}
toJSON() {
return genMapping.toEncodedMap(this._map);
}
toString() {
return JSON.stringify(this.toJSON());
}
toDecodedMap() {
return genMapping.toDecodedMap(this._map);
}
}
exports.SourceMapConsumer = SourceMapConsumer;
exports.SourceMapGenerator = SourceMapGenerator;
//# sourceMappingURL=source-map.cjs.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,90 @@
import { AnyMap, encodedMappings, originalPositionFor, generatedPositionFor, allGeneratedPositionsFor, sourceContentFor, eachMapping } from '@jridgewell/trace-mapping';
import { GenMapping, fromMap, maybeAddMapping, setSourceContent, toEncodedMap, toDecodedMap } from '@jridgewell/gen-mapping';
class SourceMapConsumer {
constructor(map, mapUrl) {
const trace = (this._map = new AnyMap(map, mapUrl));
this.file = trace.file;
this.names = trace.names;
this.sourceRoot = trace.sourceRoot;
this.sources = trace.resolvedSources;
this.sourcesContent = trace.sourcesContent;
this.version = trace.version;
}
static fromSourceMap(map, mapUrl) {
// This is more performant if we receive
// a @jridgewell/source-map SourceMapGenerator
if (map.toDecodedMap) {
return new SourceMapConsumer(map.toDecodedMap(), mapUrl);
}
// This is a fallback for `source-map` and `source-map-js`
return new SourceMapConsumer(map.toJSON(), mapUrl);
}
get mappings() {
return encodedMappings(this._map);
}
originalPositionFor(needle) {
return originalPositionFor(this._map, needle);
}
generatedPositionFor(originalPosition) {
return generatedPositionFor(this._map, originalPosition);
}
allGeneratedPositionsFor(originalPosition) {
return allGeneratedPositionsFor(this._map, originalPosition);
}
hasContentsOfAllSources() {
if (!this.sourcesContent || this.sourcesContent.length !== this.sources.length) {
return false;
}
for (const content of this.sourcesContent) {
if (content == null) {
return false;
}
}
return true;
}
sourceContentFor(source, nullOnMissing) {
const sourceContent = sourceContentFor(this._map, source);
if (sourceContent != null) {
return sourceContent;
}
if (nullOnMissing) {
return null;
}
throw new Error(`"${source}" is not in the SourceMap.`);
}
eachMapping(callback, context /*, order?: number*/) {
// order is ignored as @jridgewell/trace-map doesn't implement it
eachMapping(this._map, context ? callback.bind(context) : callback);
}
destroy() {
// noop.
}
}
class SourceMapGenerator {
constructor(opts) {
// TODO :: should this be duck-typed ?
this._map = opts instanceof GenMapping ? opts : new GenMapping(opts);
}
static fromSourceMap(consumer) {
return new SourceMapGenerator(fromMap(consumer));
}
addMapping(mapping) {
maybeAddMapping(this._map, mapping);
}
setSourceContent(source, content) {
setSourceContent(this._map, source, content);
}
toJSON() {
return toEncodedMap(this._map);
}
toString() {
return JSON.stringify(this.toJSON());
}
toDecodedMap() {
return toDecodedMap(this._map);
}
}
export { SourceMapConsumer, SourceMapGenerator };
//# sourceMappingURL=source-map.mjs.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,35 @@
import { AnyMap, originalPositionFor, generatedPositionFor, eachMapping } from '@jridgewell/trace-mapping';
import { GenMapping, maybeAddMapping, toDecodedMap, toEncodedMap, setSourceContent } from '@jridgewell/gen-mapping';
import type { TraceMap, SourceMapInput, SectionedSourceMapInput, DecodedSourceMap } from '@jridgewell/trace-mapping';
export type { TraceMap, SourceMapInput, SectionedSourceMapInput, DecodedSourceMap };
import type { Mapping, EncodedSourceMap } from '@jridgewell/gen-mapping';
export type { Mapping, EncodedSourceMap };
export declare class SourceMapConsumer {
private _map;
file: TraceMap['file'];
names: TraceMap['names'];
sourceRoot: TraceMap['sourceRoot'];
sources: TraceMap['sources'];
sourcesContent: TraceMap['sourcesContent'];
version: TraceMap['version'];
constructor(map: ConstructorParameters<typeof AnyMap>[0], mapUrl: Parameters<typeof AnyMap>[1]);
static fromSourceMap(map: SourceMapGenerator, mapUrl: Parameters<typeof AnyMap>[1]): SourceMapConsumer;
get mappings(): string;
originalPositionFor(needle: Parameters<typeof originalPositionFor>[1]): ReturnType<typeof originalPositionFor>;
generatedPositionFor(originalPosition: Parameters<typeof generatedPositionFor>[1]): ReturnType<typeof generatedPositionFor>;
allGeneratedPositionsFor(originalPosition: Parameters<typeof generatedPositionFor>[1]): ReturnType<typeof generatedPositionFor>[];
hasContentsOfAllSources(): boolean;
sourceContentFor(source: string, nullOnMissing?: boolean): string | null;
eachMapping(callback: Parameters<typeof eachMapping>[1], context?: any): void;
destroy(): void;
}
export declare class SourceMapGenerator {
private _map;
constructor(opts: ConstructorParameters<typeof GenMapping>[0] | GenMapping);
static fromSourceMap(consumer: SourceMapConsumer): SourceMapGenerator;
addMapping(mapping: Parameters<typeof maybeAddMapping>[1]): ReturnType<typeof maybeAddMapping>;
setSourceContent(source: Parameters<typeof setSourceContent>[1], content: Parameters<typeof setSourceContent>[2]): ReturnType<typeof setSourceContent>;
toJSON(): ReturnType<typeof toEncodedMap>;
toString(): string;
toDecodedMap(): ReturnType<typeof toDecodedMap>;
}