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:
parent
663dc479c2
commit
ea4980a5d7
6407 changed files with 1072847 additions and 18 deletions
10
node_modules/ajv/lib/vocabularies/core/id.ts
generated
vendored
Normal file
10
node_modules/ajv/lib/vocabularies/core/id.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type {CodeKeywordDefinition} from "../../types"
|
||||
|
||||
const def: CodeKeywordDefinition = {
|
||||
keyword: "id",
|
||||
code() {
|
||||
throw new Error('NOT SUPPORTED: keyword "id", use "$id" for schema ID')
|
||||
},
|
||||
}
|
||||
|
||||
export default def
|
||||
16
node_modules/ajv/lib/vocabularies/core/index.ts
generated
vendored
Normal file
16
node_modules/ajv/lib/vocabularies/core/index.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import type {Vocabulary} from "../../types"
|
||||
import idKeyword from "./id"
|
||||
import refKeyword from "./ref"
|
||||
|
||||
const core: Vocabulary = [
|
||||
"$schema",
|
||||
"$id",
|
||||
"$defs",
|
||||
"$vocabulary",
|
||||
{keyword: "$comment"},
|
||||
"definitions",
|
||||
idKeyword,
|
||||
refKeyword,
|
||||
]
|
||||
|
||||
export default core
|
||||
129
node_modules/ajv/lib/vocabularies/core/ref.ts
generated
vendored
Normal file
129
node_modules/ajv/lib/vocabularies/core/ref.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import type {CodeKeywordDefinition, AnySchema} from "../../types"
|
||||
import type {KeywordCxt} from "../../compile/validate"
|
||||
import MissingRefError from "../../compile/ref_error"
|
||||
import {callValidateCode} from "../code"
|
||||
import {_, nil, stringify, Code, Name} from "../../compile/codegen"
|
||||
import N from "../../compile/names"
|
||||
import {SchemaEnv, resolveRef} from "../../compile"
|
||||
import {mergeEvaluated} from "../../compile/util"
|
||||
|
||||
const def: CodeKeywordDefinition = {
|
||||
keyword: "$ref",
|
||||
schemaType: "string",
|
||||
code(cxt: KeywordCxt): void {
|
||||
const {gen, schema: $ref, it} = cxt
|
||||
const {baseId, schemaEnv: env, validateName, opts, self} = it
|
||||
const {root} = env
|
||||
if (($ref === "#" || $ref === "#/") && baseId === root.baseId) return callRootRef()
|
||||
const schOrEnv = resolveRef.call(self, root, baseId, $ref)
|
||||
if (schOrEnv === undefined) throw new MissingRefError(it.opts.uriResolver, baseId, $ref)
|
||||
if (schOrEnv instanceof SchemaEnv) return callValidate(schOrEnv)
|
||||
return inlineRefSchema(schOrEnv)
|
||||
|
||||
function callRootRef(): void {
|
||||
if (env === root) return callRef(cxt, validateName, env, env.$async)
|
||||
const rootName = gen.scopeValue("root", {ref: root})
|
||||
return callRef(cxt, _`${rootName}.validate`, root, root.$async)
|
||||
}
|
||||
|
||||
function callValidate(sch: SchemaEnv): void {
|
||||
const v = getValidate(cxt, sch)
|
||||
callRef(cxt, v, sch, sch.$async)
|
||||
}
|
||||
|
||||
function inlineRefSchema(sch: AnySchema): void {
|
||||
const schName = gen.scopeValue(
|
||||
"schema",
|
||||
opts.code.source === true ? {ref: sch, code: stringify(sch)} : {ref: sch}
|
||||
)
|
||||
const valid = gen.name("valid")
|
||||
const schCxt = cxt.subschema(
|
||||
{
|
||||
schema: sch,
|
||||
dataTypes: [],
|
||||
schemaPath: nil,
|
||||
topSchemaRef: schName,
|
||||
errSchemaPath: $ref,
|
||||
},
|
||||
valid
|
||||
)
|
||||
cxt.mergeEvaluated(schCxt)
|
||||
cxt.ok(valid)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export function getValidate(cxt: KeywordCxt, sch: SchemaEnv): Code {
|
||||
const {gen} = cxt
|
||||
return sch.validate
|
||||
? gen.scopeValue("validate", {ref: sch.validate})
|
||||
: _`${gen.scopeValue("wrapper", {ref: sch})}.validate`
|
||||
}
|
||||
|
||||
export function callRef(cxt: KeywordCxt, v: Code, sch?: SchemaEnv, $async?: boolean): void {
|
||||
const {gen, it} = cxt
|
||||
const {allErrors, schemaEnv: env, opts} = it
|
||||
const passCxt = opts.passContext ? N.this : nil
|
||||
if ($async) callAsyncRef()
|
||||
else callSyncRef()
|
||||
|
||||
function callAsyncRef(): void {
|
||||
if (!env.$async) throw new Error("async schema referenced by sync schema")
|
||||
const valid = gen.let("valid")
|
||||
gen.try(
|
||||
() => {
|
||||
gen.code(_`await ${callValidateCode(cxt, v, passCxt)}`)
|
||||
addEvaluatedFrom(v) // TODO will not work with async, it has to be returned with the result
|
||||
if (!allErrors) gen.assign(valid, true)
|
||||
},
|
||||
(e) => {
|
||||
gen.if(_`!(${e} instanceof ${it.ValidationError as Name})`, () => gen.throw(e))
|
||||
addErrorsFrom(e)
|
||||
if (!allErrors) gen.assign(valid, false)
|
||||
}
|
||||
)
|
||||
cxt.ok(valid)
|
||||
}
|
||||
|
||||
function callSyncRef(): void {
|
||||
cxt.result(
|
||||
callValidateCode(cxt, v, passCxt),
|
||||
() => addEvaluatedFrom(v),
|
||||
() => addErrorsFrom(v)
|
||||
)
|
||||
}
|
||||
|
||||
function addErrorsFrom(source: Code): void {
|
||||
const errs = _`${source}.errors`
|
||||
gen.assign(N.vErrors, _`${N.vErrors} === null ? ${errs} : ${N.vErrors}.concat(${errs})`) // TODO tagged
|
||||
gen.assign(N.errors, _`${N.vErrors}.length`)
|
||||
}
|
||||
|
||||
function addEvaluatedFrom(source: Code): void {
|
||||
if (!it.opts.unevaluated) return
|
||||
const schEvaluated = sch?.validate?.evaluated
|
||||
// TODO refactor
|
||||
if (it.props !== true) {
|
||||
if (schEvaluated && !schEvaluated.dynamicProps) {
|
||||
if (schEvaluated.props !== undefined) {
|
||||
it.props = mergeEvaluated.props(gen, schEvaluated.props, it.props)
|
||||
}
|
||||
} else {
|
||||
const props = gen.var("props", _`${source}.evaluated.props`)
|
||||
it.props = mergeEvaluated.props(gen, props, it.props, Name)
|
||||
}
|
||||
}
|
||||
if (it.items !== true) {
|
||||
if (schEvaluated && !schEvaluated.dynamicItems) {
|
||||
if (schEvaluated.items !== undefined) {
|
||||
it.items = mergeEvaluated.items(gen, schEvaluated.items, it.items)
|
||||
}
|
||||
} else {
|
||||
const items = gen.var("items", _`${source}.evaluated.items`)
|
||||
it.items = mergeEvaluated.items(gen, items, it.items, Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default def
|
||||
Loading…
Add table
Add a link
Reference in a new issue