@mailwoman/resolver-wof-sqlite 10.7.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/address/point/interpolation.ts +4 -4
- package/lib/address/point/spine-schema.ts +59 -0
- package/lib/address/point.ts +44 -1
- package/lib/ancestry/backfill.ts +3 -25
- package/lib/build/candidate.ts +22 -5
- package/lib/build/slim.ts +0 -19
- package/lib/candidate/alias-bags.ts +32 -14
- package/lib/candidate/bare-admin-names.ts +54 -0
- package/lib/candidate/importance.ts +2 -2
- package/lib/candidate/lookup.ts +63 -30
- package/lib/candidate/own-name.ts +1 -5
- package/lib/candidate/scoring.ts +4 -4
- package/lib/capitals.ts +2 -2
- package/lib/currency-backfill.ts +4 -4
- package/lib/fst/autocomplete.ts +1 -1
- package/lib/fst/binary-matcher.ts +379 -0
- package/lib/fst/builder.ts +1 -1
- package/lib/fst/deserialize-web.ts +14 -143
- package/lib/fst/matcher.ts +3 -3
- package/lib/fst/serialize.ts +1 -1
- package/lib/fst.ts +1 -0
- package/lib/geonames/aliases.ts +2 -2
- package/lib/index.ts +0 -1
- package/lib/interpolation.ts +3 -2
- package/lib/landmark/rows.ts +91 -0
- package/lib/landmark.ts +94 -0
- package/lib/lookup.ts +7 -27
- package/lib/nsul/lookup.ts +2 -1
- package/lib/nsul/schema.ts +2 -8
- package/lib/place-importance-schema.ts +1 -1
- package/lib/poi/lookup.ts +14 -14
- package/lib/primary-preference.ts +13 -20
- package/lib/proximity-rerank.ts +2 -2
- package/lib/reverse.ts +8 -5
- package/lib/schema.ts +0 -18
- package/lib/search-fetch.ts +3 -3
- package/lib/sqlite/convention-source.ts +1 -1
- package/lib/street/centroid.ts +2 -2
- package/lib/street/morphology/fst/builder.ts +3 -3
- package/lib/street/morphology/fst/loader.ts +3 -3
- package/lib/street/normalize.ts +150 -1
- package/lib/types.ts +15 -2
- package/lib/uprn/existence.ts +0 -1
- package/lib/uprn/lookup.ts +5 -5
- package/lib/uprn/schema.ts +3 -4
- package/lib/weights-overlay-linker.ts +4 -4
- package/out/address/point/interpolation.js +4 -4
- package/out/address/point/interpolation.js.map +1 -1
- package/out/address/point/spine-schema.d.ts +40 -0
- package/out/address/point/spine-schema.d.ts.map +1 -0
- package/out/address/point/spine-schema.js +40 -0
- package/out/address/point/spine-schema.js.map +1 -0
- package/out/address/point.d.ts.map +1 -1
- package/out/address/point.js +36 -1
- package/out/address/point.js.map +1 -1
- package/out/ancestry/backfill.d.ts.map +1 -1
- package/out/ancestry/backfill.js +3 -22
- package/out/ancestry/backfill.js.map +1 -1
- package/out/build/candidate.d.ts.map +1 -1
- package/out/build/candidate.js +17 -5
- package/out/build/candidate.js.map +1 -1
- package/out/build/slim.d.ts +1 -1
- package/out/build/slim.d.ts.map +1 -1
- package/out/build/slim.js +0 -12
- package/out/build/slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +8 -0
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +20 -11
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/bare-admin-names.d.ts +26 -0
- package/out/candidate/bare-admin-names.d.ts.map +1 -0
- package/out/candidate/bare-admin-names.js +38 -0
- package/out/candidate/bare-admin-names.js.map +1 -0
- package/out/candidate/importance.js +2 -2
- package/out/candidate/importance.js.map +1 -1
- package/out/candidate/lookup.d.ts.map +1 -1
- package/out/candidate/lookup.js +43 -23
- package/out/candidate/lookup.js.map +1 -1
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +1 -5
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/scoring.js +4 -4
- package/out/candidate/scoring.js.map +1 -1
- package/out/capitals.js +2 -2
- package/out/capitals.js.map +1 -1
- package/out/currency-backfill.js +4 -4
- package/out/currency-backfill.js.map +1 -1
- package/out/env.d.ts +3 -0
- package/out/env.d.ts.map +1 -1
- package/out/fst/autocomplete.js +1 -1
- package/out/fst/autocomplete.js.map +1 -1
- package/out/fst/binary-matcher.d.ts +34 -0
- package/out/fst/binary-matcher.d.ts.map +1 -0
- package/out/fst/binary-matcher.js +294 -0
- package/out/fst/binary-matcher.js.map +1 -0
- package/out/fst/builder.js +1 -1
- package/out/fst/builder.js.map +1 -1
- package/out/fst/deserialize-web.d.ts +11 -6
- package/out/fst/deserialize-web.d.ts.map +1 -1
- package/out/fst/deserialize-web.js +12 -94
- package/out/fst/deserialize-web.js.map +1 -1
- package/out/fst/matcher.js +3 -3
- package/out/fst/matcher.js.map +1 -1
- package/out/fst/serialize.js +1 -1
- package/out/fst/serialize.js.map +1 -1
- package/out/fst.d.ts +1 -0
- package/out/fst.d.ts.map +1 -1
- package/out/fst.js +1 -0
- package/out/fst.js.map +1 -1
- package/out/geonames/aliases.js +2 -2
- package/out/geonames/aliases.js.map +1 -1
- package/out/index.d.ts +1 -1
- package/out/index.d.ts.map +1 -1
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +3 -2
- package/out/interpolation.js.map +1 -1
- package/out/landmark/rows.d.ts +63 -0
- package/out/landmark/rows.d.ts.map +1 -0
- package/out/landmark/rows.js +48 -0
- package/out/landmark/rows.js.map +1 -0
- package/out/landmark.d.ts +40 -0
- package/out/landmark.d.ts.map +1 -0
- package/out/landmark.js +78 -0
- package/out/landmark.js.map +1 -0
- package/out/lookup.d.ts +3 -7
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +4 -21
- package/out/lookup.js.map +1 -1
- package/out/nsul/lookup.d.ts +1 -1
- package/out/nsul/lookup.d.ts.map +1 -1
- package/out/nsul/lookup.js +1 -1
- package/out/nsul/lookup.js.map +1 -1
- package/out/nsul/schema.d.ts +2 -5
- package/out/nsul/schema.d.ts.map +1 -1
- package/out/nsul/schema.js +2 -7
- package/out/nsul/schema.js.map +1 -1
- package/out/place-importance-schema.js +1 -1
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/lookup.d.ts +3 -3
- package/out/poi/lookup.d.ts.map +1 -1
- package/out/poi/lookup.js +9 -9
- package/out/poi/lookup.js.map +1 -1
- package/out/primary-preference.d.ts +10 -10
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +8 -9
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.js +2 -2
- package/out/proximity-rerank.js.map +1 -1
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +7 -5
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +0 -17
- package/out/schema.d.ts.map +1 -1
- package/out/search-fetch.js +3 -3
- package/out/search-fetch.js.map +1 -1
- package/out/sqlite/convention-source.js +1 -1
- package/out/sqlite/convention-source.js.map +1 -1
- package/out/street/centroid.js +2 -2
- package/out/street/centroid.js.map +1 -1
- package/out/street/morphology/fst/builder.d.ts +2 -2
- package/out/street/morphology/fst/builder.js +2 -2
- package/out/street/morphology/fst/builder.js.map +1 -1
- package/out/street/morphology/fst/loader.d.ts +2 -2
- package/out/street/morphology/fst/loader.js +2 -2
- package/out/street/morphology/fst/loader.js.map +1 -1
- package/out/street/normalize.d.ts +23 -0
- package/out/street/normalize.d.ts.map +1 -1
- package/out/street/normalize.js +126 -1
- package/out/street/normalize.js.map +1 -1
- package/out/types.d.ts +13 -2
- package/out/types.d.ts.map +1 -1
- package/out/uprn/existence.d.ts.map +1 -1
- package/out/uprn/existence.js.map +1 -1
- package/out/uprn/lookup.d.ts.map +1 -1
- package/out/uprn/lookup.js +3 -3
- package/out/uprn/lookup.js.map +1 -1
- package/out/uprn/schema.d.ts +1 -1
- package/out/uprn/schema.d.ts.map +1 -1
- package/out/uprn/schema.js +1 -1
- package/out/uprn/schema.js.map +1 -1
- package/out/weights-overlay-linker.js +4 -4
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +16 -13
- package/lib/coincident-roles.ts +0 -347
- package/out/coincident-roles.d.ts +0 -121
- package/out/coincident-roles.d.ts.map +0 -1
- package/out/coincident-roles.js +0 -222
- package/out/coincident-roles.js.map +0 -1
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Design rationale + the four-layer street-supplement architecture lives in
|
|
18
18
|
* `docs/articles/concepts/street-supplement-architecture.md`.
|
|
19
19
|
*
|
|
20
|
-
* Source: `
|
|
20
|
+
* Source: `dictionaries/data/libpostal/dictionaries/{locale}/street_types.txt`. Each line is pipe-delimited
|
|
21
21
|
* surface forms with the canonical form first: avenue|av|ave|aven|avenu|avn|avnu|avnue
|
|
22
22
|
*
|
|
23
23
|
* Output: an `FSTMatcher` ready to serialize via `serializeFST` to e.g.
|
|
@@ -61,7 +61,7 @@ export const REGION_ABBREVIATION_VARIANTS: ReadonlySet<string> = new Set(
|
|
|
61
61
|
|
|
62
62
|
export interface BuildStreetMorphologyFSTOpts {
|
|
63
63
|
/**
|
|
64
|
-
* Path to the `
|
|
64
|
+
* Path to the `dictionaries/data/libpostal/dictionaries` directory containing per-locale subfolders.
|
|
65
65
|
*/
|
|
66
66
|
dictionariesDir: PathBuilderLike
|
|
67
67
|
/**
|
|
@@ -213,7 +213,7 @@ export async function buildStreetMorphologyFST(
|
|
|
213
213
|
const node = nodes[stateID]!
|
|
214
214
|
let next = node.edges.get(t)
|
|
215
215
|
|
|
216
|
-
if (next
|
|
216
|
+
if (!next) {
|
|
217
217
|
next = nodes.length
|
|
218
218
|
nodes.push({ edges: new Map(), places: [] })
|
|
219
219
|
node.edges.set(t, next)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* 1. An explicit `artifactPath`, e.g. the weights-package sibling surfaced by
|
|
11
11
|
* `NeuralAddressClassifier.streetMorphologyPath`. When given, it is the only artifact probed.
|
|
12
12
|
* 2. Otherwise the staged sealed artifact at `$MAILWOMAN_DATA_ROOT/db/wof/fst-street-morphology.bin`.
|
|
13
|
-
* 3. A build-from-dictionaries fallback: `buildStreetMorphologyFST` over
|
|
13
|
+
* 3. A build-from-dictionaries fallback: `buildStreetMorphologyFST` over `@mailwoman/dictionaries`' libpostal
|
|
14
14
|
* `street_types.txt` files, kept so a missing artifact degrades to a per-process build instead
|
|
15
15
|
* of a crash.
|
|
16
16
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import { readLocalBuffer } from "@mailwoman/core/fs/readers"
|
|
23
23
|
import { pathExists } from "@mailwoman/core/fs/readers/stat"
|
|
24
|
-
import { resourceDictionaryPath } from "@mailwoman/
|
|
24
|
+
import { resourceDictionaryPath } from "@mailwoman/dictionaries/paths"
|
|
25
25
|
import type { PathBuilder, PathBuilderLike } from "path-ts"
|
|
26
26
|
|
|
27
27
|
import type { FSTMatcher } from "#fst/matcher"
|
|
@@ -54,7 +54,7 @@ export interface LoadStreetMorphologyFSTOpts {
|
|
|
54
54
|
/**
|
|
55
55
|
* Dictionaries dir for the build fallback.
|
|
56
56
|
*
|
|
57
|
-
* @defaultValue
|
|
57
|
+
* @defaultValue the libpostal dictionaries `@mailwoman/dictionaries` ships.
|
|
58
58
|
*/
|
|
59
59
|
dictionariesDir?: PathBuilderLike
|
|
60
60
|
/**
|
package/lib/street/normalize.ts
CHANGED
|
@@ -68,6 +68,16 @@ function fold(input: string): string {
|
|
|
68
68
|
.trim()
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* The name and version of the street-key normalization {@link normalizeStreetForKeyLocale} applies.
|
|
73
|
+
*
|
|
74
|
+
* An artifact manifest of a street-keyed role records this pair with its locale,
|
|
75
|
+
* and a reader refuses an artifact keyed by another version.
|
|
76
|
+
* Version `1` is the normalization in this module when versions began to be recorded, on 2026-10-29.
|
|
77
|
+
* A change to any key it produces is a new version.
|
|
78
|
+
*/
|
|
79
|
+
export const STREET_KEY_NORMALIZATION = { algorithm: "street-key", version: "1" } as const
|
|
80
|
+
|
|
71
81
|
/**
|
|
72
82
|
* Normalizes a US or English street name into an address-point key, folding directionals,
|
|
73
83
|
* spelled ordinals and the USPS street-type suffix.
|
|
@@ -90,7 +100,7 @@ export function normalizeStreetForKey(street: string): StreetKey {
|
|
|
90
100
|
AbbreviationToDirectional.get(raw.toUpperCase())?.toLowerCase().replace(" ", "")
|
|
91
101
|
|
|
92
102
|
const mergePair = (a?: string, b?: string) =>
|
|
93
|
-
a && b && /^(north|south)$/.test(a) && /^(east|west)$/.test(b) ? a + b :
|
|
103
|
+
a && b && /^(north|south)$/.test(a) && /^(east|west)$/.test(b) ? a + b : null
|
|
94
104
|
|
|
95
105
|
const leadPair = mergePair(tokens[0], tokens[1])
|
|
96
106
|
|
|
@@ -138,6 +148,23 @@ export function normalizeStreetForKey(street: string): StreetKey {
|
|
|
138
148
|
*/
|
|
139
149
|
export type StreetLocale = "us" | "en" | "es" | "fr" | "de" | "it" | "nl" | "pl" | "vn" | "id" | "zh"
|
|
140
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Every locale {@link normalizeStreetForKeyLocale} keys streets under.
|
|
153
|
+
*/
|
|
154
|
+
export const STREET_LOCALES = [
|
|
155
|
+
"us",
|
|
156
|
+
"en",
|
|
157
|
+
"es",
|
|
158
|
+
"fr",
|
|
159
|
+
"de",
|
|
160
|
+
"it",
|
|
161
|
+
"nl",
|
|
162
|
+
"pl",
|
|
163
|
+
"vn",
|
|
164
|
+
"id",
|
|
165
|
+
"zh",
|
|
166
|
+
] as const satisfies readonly StreetLocale[]
|
|
167
|
+
|
|
141
168
|
function foldHan(input: string): string {
|
|
142
169
|
return input.normalize("NFKC").replaceAll("臺", "台").replaceAll(/\s+/g, "").toLowerCase()
|
|
143
170
|
}
|
|
@@ -434,6 +461,14 @@ const CANONICAL_TYPE_WORDS: ReadonlySet<string> = new Set(
|
|
|
434
461
|
[...US_STREET_SUFFIX_LOOKUP.values()].map((v) => v.toLowerCase())
|
|
435
462
|
)
|
|
436
463
|
|
|
464
|
+
const ENGLISH_ORDINAL_RULES = new Intl.PluralRules("en-US", { type: "ordinal" })
|
|
465
|
+
|
|
466
|
+
const ENGLISH_ORDINAL_SUFFIX: Record<string, string> = { one: "st", two: "nd", few: "rd", other: "th" }
|
|
467
|
+
|
|
468
|
+
function ordinalOf(n: number): string {
|
|
469
|
+
return `${n}${ENGLISH_ORDINAL_SUFFIX[ENGLISH_ORDINAL_RULES.select(n)] ?? "th"}`
|
|
470
|
+
}
|
|
471
|
+
|
|
437
472
|
/**
|
|
438
473
|
* Lists the lookup keys to probe for a street span, most literal first, adding doubled-type
|
|
439
474
|
* and Saint/St-swap recovery forms for `us` and `en`.
|
|
@@ -463,6 +498,29 @@ export function streetKeyVariants(street: string, locale: StreetLocale = "us"):
|
|
|
463
498
|
}
|
|
464
499
|
}
|
|
465
500
|
|
|
501
|
+
// NAD writes a numbered street with its ordinal suffix ("48th St")
|
|
502
|
+
// and NYC Open Data writes the bare number ("48 ST").
|
|
503
|
+
// The build keys each row as written, so the reader probes both forms.
|
|
504
|
+
for (const variant of variants.slice()) {
|
|
505
|
+
const parts = variant.split(" ")
|
|
506
|
+
|
|
507
|
+
const toggled = parts
|
|
508
|
+
.map((token, i) => {
|
|
509
|
+
// Only a number followed by a street type is an ordinal ("48 street"), not "us route 9".
|
|
510
|
+
if (!CANONICAL_TYPE_WORDS.has(parts[i + 1] ?? "")) return token
|
|
511
|
+
const bare = /^(\d+)(?:st|nd|rd|th)$/.exec(token)?.[1]
|
|
512
|
+
|
|
513
|
+
if (bare) return bare
|
|
514
|
+
|
|
515
|
+
return /^\d+$/.test(token) ? ordinalOf(Number(token)) : token
|
|
516
|
+
})
|
|
517
|
+
.join(" ") as StreetKey
|
|
518
|
+
|
|
519
|
+
if (toggled !== variant && !variants.includes(toggled)) {
|
|
520
|
+
variants.push(toggled)
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
466
524
|
const preSwap = variants.slice()
|
|
467
525
|
|
|
468
526
|
for (const variant of preSwap) {
|
|
@@ -478,5 +536,96 @@ export function streetKeyVariants(street: string, locale: StreetLocale = "us"):
|
|
|
478
536
|
}
|
|
479
537
|
}
|
|
480
538
|
|
|
539
|
+
for (const candidate of routeKeyVariants(primary)) {
|
|
540
|
+
if (!variants.includes(candidate)) {
|
|
541
|
+
variants.push(candidate)
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
481
545
|
return variants
|
|
482
546
|
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* The route designators a numbered road is written with, by the system the query's prefix selects.
|
|
550
|
+
*
|
|
551
|
+
* The forms are the ones US address sources store, measured over the state extracts:
|
|
552
|
+
* `state road 10`, `state highway 42`, `highway 79`, `united states highway 31`, `interstate 35`.
|
|
553
|
+
*/
|
|
554
|
+
const ROUTE_DESIGNATORS: Readonly<Record<"us" | "state" | "interstate", readonly string[]>> = {
|
|
555
|
+
us: ["united states highway", "us highway", "us route", "highway", "route"],
|
|
556
|
+
state: ["state road", "state highway", "state route", "highway", "route"],
|
|
557
|
+
interstate: ["interstate"],
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* The spellings of a county road, as US address sources store them.
|
|
562
|
+
*
|
|
563
|
+
* Wisconsin leads with `cth`, Texas with `county road`, and Florida with `cr`,
|
|
564
|
+
* and a county road may take letters, as `cth cw` does.
|
|
565
|
+
*/
|
|
566
|
+
const COUNTY_ROAD_DESIGNATORS: readonly string[] = ["county road", "county highway", "county", "cth", "co road", "cr"]
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Reads a county road's designator from a query, such as `county rd cw`,
|
|
570
|
+
* `cty hwy 5`, `co rd 12`, `cr 40` or `cth a`.
|
|
571
|
+
*
|
|
572
|
+
* A bare `co 5` stays a Colorado state route.
|
|
573
|
+
*/
|
|
574
|
+
const COUNTY_ROAD_QUERY =
|
|
575
|
+
/^(?:(?:county|cty|co) (?:road|rd|highway|hwy|trunk|trunk highway) (\d+[a-z]?|[a-z]{1,3})|(?:county|cty|cth|cr) (\d+[a-z]?|[a-z]{1,2}))$/
|
|
576
|
+
|
|
577
|
+
const COMPASS_WORDS: readonly string[] = ["north", "south", "east", "west"]
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* A query's route number and system: `in 245` and `state route 245` read as state routes,
|
|
581
|
+
* `us 93` as a US route, and `i 68` as an interstate.
|
|
582
|
+
*
|
|
583
|
+
* A two-letter prefix is any state's code, because the shape is the same in every state.
|
|
584
|
+
*/
|
|
585
|
+
function parseRouteQuery(key: string): { system: keyof typeof ROUTE_DESIGNATORS; route: string } | null {
|
|
586
|
+
const match =
|
|
587
|
+
/^(us|i|interstate|[a-z]{2}|state|sr)(?: (?:road|rd|route|rte|rt|highway|hwy))? (\d+[a-z]?)$/.exec(key) ??
|
|
588
|
+
/^(highway|hwy|route|rte)() ?(\d+[a-z]?)$/.exec(key)
|
|
589
|
+
|
|
590
|
+
if (!match) return null
|
|
591
|
+
|
|
592
|
+
const route = match.at(-1)!
|
|
593
|
+
const prefix = match[1]!
|
|
594
|
+
|
|
595
|
+
if (prefix === "us") return { system: "us", route }
|
|
596
|
+
|
|
597
|
+
if (prefix === "i" || prefix === "interstate") return { system: "interstate", route }
|
|
598
|
+
|
|
599
|
+
return { system: "state", route }
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Lists the stored spellings of a numbered route, with and without the compass word a source may add.
|
|
604
|
+
*
|
|
605
|
+
* `IN-245` is stored as `north state road 245` in Indiana, so a query gives no hint of the spelling.
|
|
606
|
+
* The caller's postcode, locality or box still scopes each probe.
|
|
607
|
+
*/
|
|
608
|
+
export function routeKeyVariants(key: StreetKey): StreetKey[] {
|
|
609
|
+
const written = key.replaceAll("-", " ")
|
|
610
|
+
const countyRoad = COUNTY_ROAD_QUERY.exec(written)
|
|
611
|
+
|
|
612
|
+
if (countyRoad) {
|
|
613
|
+
const route = countyRoad[1] ?? countyRoad[2]!
|
|
614
|
+
|
|
615
|
+
return COUNTY_ROAD_DESIGNATORS.map((designator) => `${designator} ${route}` as StreetKey)
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
const parsed = parseRouteQuery(written)
|
|
619
|
+
|
|
620
|
+
if (!parsed) return []
|
|
621
|
+
|
|
622
|
+
return ROUTE_DESIGNATORS[parsed.system].flatMap((designator) => {
|
|
623
|
+
const base = `${designator} ${parsed.route}`
|
|
624
|
+
|
|
625
|
+
return [
|
|
626
|
+
base,
|
|
627
|
+
...COMPASS_WORDS.map((compass) => `${compass} ${base}`),
|
|
628
|
+
...COMPASS_WORDS.map((compass) => `${base} ${compass}`),
|
|
629
|
+
] as StreetKey[]
|
|
630
|
+
})
|
|
631
|
+
}
|
package/lib/types.ts
CHANGED
|
@@ -109,10 +109,15 @@ export interface PlaceCandidate {
|
|
|
109
109
|
regionScopeMiss: boolean | null
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
* Set when the variant exemption spared the candidate from the
|
|
113
|
-
*
|
|
112
|
+
* Set when the variant exemption spared the candidate from the alias penalty,
|
|
113
|
+
* by the candidate-table backend only.
|
|
114
114
|
*/
|
|
115
115
|
variantAliasExempted: true | null
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Set when the input matched an alias of this place, by the candidate-table backend only.
|
|
119
|
+
*/
|
|
120
|
+
matchedAlias?: true | null
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
/**
|
|
@@ -155,6 +160,14 @@ export interface FindPlaceQuery {
|
|
|
155
160
|
*/
|
|
156
161
|
parentID?: number
|
|
157
162
|
|
|
163
|
+
/**
|
|
164
|
+
* A resolved parent place whose containment orders the rows and admits contained sub-locality
|
|
165
|
+
* rows the placetype filter excludes, read through the ancestors sidecar (#2804).
|
|
166
|
+
*
|
|
167
|
+
* It ranks rather than filters, so a query sets this or `parentID`.
|
|
168
|
+
*/
|
|
169
|
+
parentQualifierID?: number
|
|
170
|
+
|
|
158
171
|
/**
|
|
159
172
|
* The sibling postcode for a `locality` query.
|
|
160
173
|
*
|
package/lib/uprn/existence.ts
CHANGED
|
@@ -18,7 +18,6 @@ import { shortCellToParentInt } from "@mailwoman/spatial"
|
|
|
18
18
|
|
|
19
19
|
import type { UPRNLookup } from "#uprn/lookup"
|
|
20
20
|
import { UPRN_COVERAGE_H3_RESOLUTION, UPRN_H3_RESOLUTION, uprnH3Cell } from "#uprn/schema"
|
|
21
|
-
|
|
22
21
|
/**
|
|
23
22
|
* The identity fold, on purpose: this probe keys on a coordinate rather than a name,
|
|
24
23
|
* so there is no string folding for the builder and the probe to disagree about.
|
package/lib/uprn/lookup.ts
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { allRows } from "@mailwoman/core/utils"
|
|
10
|
-
import {
|
|
10
|
+
import { haversine, shortCellToInt, type GeoCoordinate } from "@mailwoman/spatial"
|
|
11
11
|
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
12
|
-
import { gridDisk } from "h3
|
|
12
|
+
import { gridDisk } from "@sister.software/h3"
|
|
13
13
|
import type { PathBuilderLike } from "path-ts"
|
|
14
14
|
|
|
15
15
|
import type { UPRNDatabase } from "#uprn/schema"
|
|
@@ -128,13 +128,13 @@ export class UPRNLookup implements Disposable {
|
|
|
128
128
|
|
|
129
129
|
if (closestPossibleM > Math.min(radiusM, best?.distanceM ?? radiusM)) break
|
|
130
130
|
|
|
131
|
-
const diskCells = gridDisk(origin, ring)
|
|
131
|
+
const diskCells = gridDisk(origin, ring)
|
|
132
132
|
const newCells: number[] = []
|
|
133
133
|
|
|
134
134
|
for (const cell of diskCells) {
|
|
135
135
|
if (!seenCells.has(cell)) {
|
|
136
136
|
seenCells.add(cell)
|
|
137
|
-
newCells.push(shortCellToInt(cell
|
|
137
|
+
newCells.push(shortCellToInt(cell))
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -148,7 +148,7 @@ export class UPRNLookup implements Disposable {
|
|
|
148
148
|
)
|
|
149
149
|
|
|
150
150
|
for (const row of rows) {
|
|
151
|
-
const distanceM =
|
|
151
|
+
const distanceM = haversine(latitude, longitude, row.lat, row.lon) * 1000
|
|
152
152
|
|
|
153
153
|
if (distanceM <= radiusM && (!best || distanceM < best.distanceM)) {
|
|
154
154
|
best = { uprn: row.uprn, latitude: row.lat, longitude: row.lon, distanceM }
|
package/lib/uprn/schema.ts
CHANGED
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { layerschemadatabase } from "@mailwoman/core/layers"
|
|
10
|
-
import { shortCellToInt
|
|
11
|
-
import { latLngToCell } from "h3
|
|
10
|
+
import { shortCellToInt } from "@mailwoman/spatial"
|
|
11
|
+
import { latLngToCell, type H3Cell } from "@sister.software/h3"
|
|
12
12
|
import type { Kysely } from "kysely"
|
|
13
|
-
|
|
14
13
|
/**
|
|
15
14
|
* Resolution the `uprn` table's `h3_cell` column is keyed at, shared with the other layer spines.
|
|
16
15
|
*/
|
|
@@ -65,7 +64,7 @@ export interface UPRNDatabase extends layerschemadatabase {
|
|
|
65
64
|
* This is the one derivation the builder and its consumers share so their cells cannot disagree.
|
|
66
65
|
*/
|
|
67
66
|
export function uprnFullCell(latitude: number, longitude: number): H3Cell {
|
|
68
|
-
return latLngToCell(latitude, longitude, UPRN_H3_RESOLUTION)
|
|
67
|
+
return latLngToCell(latitude, longitude, UPRN_H3_RESOLUTION)
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
/**
|
|
@@ -385,7 +385,7 @@ async function pairIndexIsFresh(
|
|
|
385
385
|
return false
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
-
if (minimumPlausibleBytes
|
|
388
|
+
if (minimumPlausibleBytes && (await statPath(dest)).size < minimumPlausibleBytes) {
|
|
389
389
|
console.log(
|
|
390
390
|
`rebuilding ${artifact} — ${(await statPath(dest)).size.toLocaleString()} bytes is implausibly small ` +
|
|
391
391
|
`for this recipe (wrong-source clobber)`
|
|
@@ -508,8 +508,8 @@ export async function buildPairIndexOverlay(overlay: PairIndexOverlay): Promise<
|
|
|
508
508
|
country,
|
|
509
509
|
"--delta",
|
|
510
510
|
String(delta),
|
|
511
|
-
...(transitionBeta
|
|
512
|
-
...(parentDelta
|
|
511
|
+
...(!transitionBeta ? [] : ["--transition-beta", String(transitionBeta)]),
|
|
512
|
+
...(!parentDelta ? [] : ["--parent-delta", String(parentDelta)]),
|
|
513
513
|
...extraArgs,
|
|
514
514
|
],
|
|
515
515
|
{ stdio: "inherit" }
|
|
@@ -727,7 +727,7 @@ async function linkBaseModelPair(destDir: PathBuilder, digestCard: string | null
|
|
|
727
727
|
const recipe = await readReleaseConfig()
|
|
728
728
|
|
|
729
729
|
const dataRoot = dataRootPath()
|
|
730
|
-
const digests = digestCard ? (await readWeightsCard(digestCard))?.files_md5 :
|
|
730
|
+
const digests = digestCard ? (await readWeightsCard(digestCard))?.files_md5 : null
|
|
731
731
|
|
|
732
732
|
const pair = [
|
|
733
733
|
{ label: "model", name: "model.onnx", override: $public.MAILWOMAN_DEV_MODEL, recipe: recipe.weights.model },
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
*
|
|
29
29
|
* Standalone like the segment tier, wired through the ordered `spatialTiers` list.
|
|
30
30
|
*/
|
|
31
|
-
import {
|
|
31
|
+
import { haversine } from "@mailwoman/spatial/geometries/point/distance";
|
|
32
32
|
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
33
33
|
import { hasTable, prepareAll } from "#sqlite-utils";
|
|
34
34
|
import { canonicalizeRouteKey, streetKeyVariants } from "#street/normalize";
|
|
@@ -137,7 +137,7 @@ function interpolateFromNeighbors(rows, n) {
|
|
|
137
137
|
}
|
|
138
138
|
if (below && above) {
|
|
139
139
|
const t = (n - below.n) / (above.n - below.n);
|
|
140
|
-
const spanM =
|
|
140
|
+
const spanM = haversine(below.lat, below.lon, above.lat, above.lon) * 1000;
|
|
141
141
|
return {
|
|
142
142
|
lat: below.lat + (above.lat - below.lat) * t,
|
|
143
143
|
lon: below.lon + (above.lon - below.lon) * t,
|
|
@@ -161,8 +161,8 @@ function interpolateFromNeighbors(rows, n) {
|
|
|
161
161
|
return null;
|
|
162
162
|
const lat = far.lat + (near.lat - far.lat) * t;
|
|
163
163
|
const lon = far.lon + (near.lon - far.lon) * t;
|
|
164
|
-
const pairM =
|
|
165
|
-
const overshootM =
|
|
164
|
+
const pairM = haversine(near.lat, near.lon, far.lat, far.lon) * 1000;
|
|
165
|
+
const overshootM = haversine(lat, lon, near.lat, near.lon) * 1000;
|
|
166
166
|
return {
|
|
167
167
|
lat,
|
|
168
168
|
lon,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interpolation.js","sourceRoot":"","sources":["../../../lib/address/point/interpolation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"interpolation.js","sourceRoot":"","sources":["../../../lib/address/point/interpolation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAA;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAIzD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAoB,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAiB,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1F;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAA;AAqB7B,MAAM,OAAO,wBAAwB;IAG3B,GAAG,CAAoB;IAChC;;;;;OAKG;IACM,UAAU,CAAiB;IAC3B,SAAS,CAAgC;IACzC,WAAW,CAAyF;IAE7G,YAAY,IAAuF;QAClG,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAA;QAEvC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAA;QACzB,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,cAAc,CAAK,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAClF,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;QACnF,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAA;QAE9B,qEAAqE;QACrE,+FAA+F;QAC/F,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,UAAU,CAC5B,IAAI,CAAC,GAAG,EACR;;;;sCAIkC,CAClC,CAAA;QACF,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,CAAA;IACnC,CAAC;IAEQ,iBAAiB,GAAG,IAAI,CAAA;IAEjC,IAAI,CAAC,KAAyB;QAC7B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;QAErC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAA;QACzC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;QAE3B,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAA;QAEpF,gGAAgG;QAChG,IAAI,IAAI,GAAe,EAAE,CAAA;QAEzB,KAAK,MAAM,OAAO,IAAI,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAA;YAE/C,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YAE5D,IAAI,IAAI,CAAC,MAAM;gBAAE,MAAK;QACvB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAEvE,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAA;IAClD,CAAC;IAED,CAAC,MAAM,CAAC,OAAO,CAAC;QACf,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;IAClC,CAAC;CACD;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAyB;IACjD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAsB,CAAA;IAEzC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAE5B,IAAI,KAAK,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChB,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;QACtB,CAAC;IACF,CAAC;IAED,OAAO,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACrB,CAAC;QACD,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM;QAC5D,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM;QAC5D,MAAM,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,MAAM;QACxB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,OAAO;KAC1B,CAAC,CAAC;SACF,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAChC,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAyB,EAAE,CAAS;IACrE,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;IAErC,kDAAkD;IAClD,mCAAmC;IACnC,IAAI,KAAK,GAAwB,IAAI,CAAA;IACrC,IAAI,KAAK,GAAwB,IAAI,CAAA;IAErC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,KAAK,GAAG,MAAM,CAAA;QACf,CAAC;aAAM,CAAC;YACP,KAAK,GAAG,MAAM,CAAA;YAEd,MAAK;QACN,CAAC;IACF,CAAC;IAED,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;QAE1E,OAAO;YACN,GAAG,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAC5C,GAAG,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAC5C,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,eAAe;YACvB,aAAa,EAAE,IAAI;YACnB,OAAO,EAAE,MAAM;YACf,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;YACnC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO,EAAE,KAAK,CAAC,OAAO;SACtB,CAAA;IACF,CAAC;IAED,uFAAuF;IACvF,2DAA2D;IAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAE5D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAChC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAA;IACvE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;IAExC,IAAI,CAAC,GAAG,mBAAmB;QAAE,OAAO,IAAI,CAAA;IAExC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IACpE,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IAEjE,OAAO;QACN,GAAG;QACH,GAAG;QACH,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,eAAe;QACvB,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,QAAQ;QACjB,wFAAwF;QACxF,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC;QAC5C,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,IAAI,CAAC,OAAO;KACrB,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file The shared rooftop schema with an H3 spine column and the layer-interface tables.
|
|
6
|
+
*
|
|
7
|
+
* The OpenStreetMap and G-NAF rooftop builders write this shape. Readers of existing address points
|
|
8
|
+
* project only the columns of `address_point` in `#address/point/schema`, so the H3 spine and the
|
|
9
|
+
* layer-interface tables leave their query path unchanged.
|
|
10
|
+
*/
|
|
11
|
+
import { type layerschemadatabase } from "@mailwoman/core/layers";
|
|
12
|
+
import type { Kysely } from "kysely";
|
|
13
|
+
import { type AddressPointTable } from "#address/point/schema";
|
|
14
|
+
/**
|
|
15
|
+
* Jitter-stable address/POI join cell.
|
|
16
|
+
* Matches @mailwoman/address-id.
|
|
17
|
+
*/
|
|
18
|
+
export declare const ADDRESS_POINT_H3_RESOLUTION = 9;
|
|
19
|
+
export interface SpineAddressPointTable extends AddressPointTable {
|
|
20
|
+
/**
|
|
21
|
+
* 48-bit shortened H3 cell stored as a safe SQLite integer.
|
|
22
|
+
*/
|
|
23
|
+
h3_cell: number;
|
|
24
|
+
}
|
|
25
|
+
export interface SpineAddressPointDatabase extends layerschemadatabase {
|
|
26
|
+
address_point: SpineAddressPointTable;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Positional insert order: the shared address-point fields followed by the H3 spine.
|
|
30
|
+
*/
|
|
31
|
+
export declare const SPINE_ADDRESS_POINT_COLUMNS: readonly ["street_norm", "street_key", "number", "unit", "postcode", "locality_norm", "street_raw", "lat", "lon", "source", "release", "admin_code", "certified", "h3_cell"];
|
|
32
|
+
/**
|
|
33
|
+
* Create the legacy-compatible domain table plus the H3 spine and the layer-interface tables.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createSpineAddressPointTables(db: Kysely<SpineAddressPointDatabase>): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Build after the bulk load so the spine index is not updated on every streaming insert.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createSpineAddressPointIndexes(db: Kysely<SpineAddressPointDatabase>): Promise<void>;
|
|
40
|
+
//# sourceMappingURL=spine-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spine-schema.d.ts","sourceRoot":"","sources":["../../../lib/address/point/spine-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAsD,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACrH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEpC,OAAO,EAAyB,KAAK,iBAAiB,EAA2B,MAAM,uBAAuB,CAAA;AAE9G;;;GAGG;AACH,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAChE;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACrE,aAAa,EAAE,sBAAsB,CAAA;CACrC;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,8KAAiD,CAAA;AAEzF;;GAEG;AACH,wBAAsB,6BAA6B,CAAC,EAAE,EAAE,MAAM,CAAC,yBAAyB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAUxG;AAED;;GAEG;AACH,wBAAsB,8BAA8B,CAAC,EAAE,EAAE,MAAM,CAAC,yBAAyB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file The shared rooftop schema with an H3 spine column and the layer-interface tables.
|
|
6
|
+
*
|
|
7
|
+
* The OpenStreetMap and G-NAF rooftop builders write this shape. Readers of existing address points
|
|
8
|
+
* project only the columns of `address_point` in `#address/point/schema`, so the H3 spine and the
|
|
9
|
+
* layer-interface tables leave their query path unchanged.
|
|
10
|
+
*/
|
|
11
|
+
import { createLayerCoverageTable, createLayerManifestTable } from "@mailwoman/core/layers";
|
|
12
|
+
import { ADDRESS_POINT_COLUMNS, createAddressPointTable } from "#address/point/schema";
|
|
13
|
+
/**
|
|
14
|
+
* Jitter-stable address/POI join cell.
|
|
15
|
+
* Matches @mailwoman/address-id.
|
|
16
|
+
*/
|
|
17
|
+
export const ADDRESS_POINT_H3_RESOLUTION = 9;
|
|
18
|
+
/**
|
|
19
|
+
* Positional insert order: the shared address-point fields followed by the H3 spine.
|
|
20
|
+
*/
|
|
21
|
+
export const SPINE_ADDRESS_POINT_COLUMNS = [...ADDRESS_POINT_COLUMNS, "h3_cell"];
|
|
22
|
+
/**
|
|
23
|
+
* Create the legacy-compatible domain table plus the H3 spine and the layer-interface tables.
|
|
24
|
+
*/
|
|
25
|
+
export async function createSpineAddressPointTables(db) {
|
|
26
|
+
await createAddressPointTable(db);
|
|
27
|
+
await db.schema
|
|
28
|
+
.alterTable("address_point")
|
|
29
|
+
.addColumn("h3_cell", "integer", (column) => column.notNull())
|
|
30
|
+
.execute();
|
|
31
|
+
await createLayerManifestTable(db);
|
|
32
|
+
await createLayerCoverageTable(db);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build after the bulk load so the spine index is not updated on every streaming insert.
|
|
36
|
+
*/
|
|
37
|
+
export async function createSpineAddressPointIndexes(db) {
|
|
38
|
+
await db.schema.createIndex("idx_ap_h3").on("address_point").column("h3_cell").execute();
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=spine-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spine-schema.js","sourceRoot":"","sources":["../../../lib/address/point/spine-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAA4B,MAAM,wBAAwB,CAAA;AAGrH,OAAO,EAAE,qBAAqB,EAA0B,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAE9G;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAA;AAa5C;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,GAAG,qBAAqB,EAAE,SAAS,CAAU,CAAA;AAEzF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,EAAqC;IACxF,MAAM,uBAAuB,CAAC,EAAE,CAAC,CAAA;IAEjC,MAAM,EAAE,CAAC,MAAM;SACb,UAAU,CAAC,eAAe,CAAC;SAC3B,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;SAC7D,OAAO,EAAE,CAAA;IAEX,MAAM,wBAAwB,CAAC,EAAE,CAAC,CAAA;IAClC,MAAM,wBAAwB,CAAC,EAAE,CAAC,CAAA;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,EAAqC;IACzF,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAA;AACzF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../lib/address/point.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../lib/address/point.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAGnF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,KAAK,EAAE,oBAAoB,EAAqB,MAAM,uBAAuB,CAAA;AAEpF,OAAO,EASN,KAAK,YAAY,EACjB,MAAM,mBAAmB,CAAA;AAmC1B;;;;;;;;;;GAUG;AACH,qBAAa,wBAAwB,CAAC,EAAE,SAAS,oBAAoB,GAAG,oBAAoB,CAC3F,YAAW,kBAAkB,EAAE,UAAU;;IAkCzC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YACC,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE;QACL,YAAY,CAAC,EAAE,YAAY,CAAA;QAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,CAAA;QACrC,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;KAC7B,EA+CN;IAED,IAAI,CAAC,KAAK,EAAE;QACX,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAC/E,GAAG,eAAe,GAAG,IAAI,CAsCzB;IA8MD,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAEvB;CACD"}
|
package/out/address/point.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @file SQLite implementation of core's `AddressPointLookup`.
|
|
6
6
|
*/
|
|
7
7
|
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
8
|
+
import { indexExists } from "@mailwoman/sqlite/introspection";
|
|
8
9
|
import { hasTable, prepareGet } from "#sqlite-utils";
|
|
9
10
|
import { normalizeHouseNumberForKey, normalizeLocalityForKey, normalizeLocalityForKeyLocale, streetKeyVariants, streetLocaleForSurface, stripArrondissement, } from "#street/normalize";
|
|
10
11
|
/**
|
|
@@ -12,6 +13,23 @@ import { normalizeHouseNumberForKey, normalizeLocalityForKey, normalizeLocalityF
|
|
|
12
13
|
* It must match the fields of `AddressPointRow`.
|
|
13
14
|
*/
|
|
14
15
|
const SELECT_COLS = "lat, lon, source, release, locality_norm, postcode";
|
|
16
|
+
/**
|
|
17
|
+
* The widest span of numbers a written range covers on one building or block.
|
|
18
|
+
*/
|
|
19
|
+
const WIDEST_HOUSE_NUMBER_RANGE = 200;
|
|
20
|
+
/**
|
|
21
|
+
* Returns whether two hyphenated numbers read as one number rather than a range of houses.
|
|
22
|
+
*
|
|
23
|
+
* `8-9 Upper St` is a range, and joining it would answer the different house at number 89.
|
|
24
|
+
* `19-4074` and Queens's `123-45` cannot be ranges, because a range climbs by a short step.
|
|
25
|
+
*/
|
|
26
|
+
function isJoinedHyphenNumber(number) {
|
|
27
|
+
const parts = /^(\d+)-(\d+)$/.exec(number);
|
|
28
|
+
if (!parts)
|
|
29
|
+
return false;
|
|
30
|
+
const span = Number(parts[2]) - Number(parts[1]);
|
|
31
|
+
return span < 0 || span > WIDEST_HOUSE_NUMBER_RANGE;
|
|
32
|
+
}
|
|
15
33
|
/**
|
|
16
34
|
* Finds an address point by exact normalized `(street, number)` within a postcode,
|
|
17
35
|
* a locality, or a bounding box.
|
|
@@ -42,6 +60,7 @@ export class AddressPointSqliteLookup {
|
|
|
42
60
|
* The (street, number) index narrows the rows first, so the `LIKE` scans only rows that share the pair.
|
|
43
61
|
*/
|
|
44
62
|
#byLocalityTail;
|
|
63
|
+
#hasStreetIndex = false;
|
|
45
64
|
#byBbox;
|
|
46
65
|
/**
|
|
47
66
|
* @param dbPath Extract path.
|
|
@@ -79,6 +98,7 @@ export class AddressPointSqliteLookup {
|
|
|
79
98
|
WHERE postcode = ? AND street_norm = ? AND number = ?`);
|
|
80
99
|
this.#byLocality = prepareGet(this.#db, `SELECT ${SELECT_COLS} FROM address_point
|
|
81
100
|
WHERE locality_norm = ? AND street_norm = ? AND number = ? LIMIT 1`);
|
|
101
|
+
this.#hasStreetIndex = indexExists(this.#db, "idx_ap_street");
|
|
82
102
|
this.#byBbox = prepareGet(this.#db, `SELECT ${SELECT_COLS} FROM address_point
|
|
83
103
|
WHERE street_norm = ? AND number = ? AND lat BETWEEN ? AND ? AND lon BETWEEN ? AND ? LIMIT 1`);
|
|
84
104
|
this.#byLocalityTail = prepareGet(this.#db, `SELECT ${SELECT_COLS} FROM address_point
|
|
@@ -126,6 +146,20 @@ export class AddressPointSqliteLookup {
|
|
|
126
146
|
*/
|
|
127
147
|
#findForKey(streetNorm, number, query) {
|
|
128
148
|
let row = this.#probe(streetNorm, number, query);
|
|
149
|
+
// A hyphenated number can be one number written two ways: Hawaii's `19-4074`
|
|
150
|
+
// is stored as `194074` by some sources.
|
|
151
|
+
// This runs ahead of the range fallback, because that fallback reads it as house number 19.
|
|
152
|
+
if (!row && isJoinedHyphenNumber(number)) {
|
|
153
|
+
row = this.#probe(streetNorm, number.replace("-", ""), query);
|
|
154
|
+
}
|
|
155
|
+
// A grid number leads with a compass letter.
|
|
156
|
+
// One writer's `N3971` is another source's `n 3971`.
|
|
157
|
+
if (!row) {
|
|
158
|
+
const grid = /^([nesw])(?:\s+)?(\d+)$/.exec(number);
|
|
159
|
+
if (grid) {
|
|
160
|
+
row = this.#probe(streetNorm, number.includes(" ") ? `${grid[1]}${grid[2]}` : `${grid[1]} ${grid[2]}`, query);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
129
163
|
// The registers store one number per point, so a range such as "385-387" falls back to its low end.
|
|
130
164
|
if (!row) {
|
|
131
165
|
const low = /^(\d+[a-z]?)-\d+[a-z]?$/.exec(number)?.[1];
|
|
@@ -192,7 +226,8 @@ export class AddressPointSqliteLookup {
|
|
|
192
226
|
row = heldBack;
|
|
193
227
|
}
|
|
194
228
|
// The bounding box serves extracts whose points have no postcode or locality, such as OSM.
|
|
195
|
-
|
|
229
|
+
// A database without the street index skips this search, because each miss would scan the whole table.
|
|
230
|
+
if (!row && query.bbox && this.#hasStreetIndex) {
|
|
196
231
|
const b = query.bbox;
|
|
197
232
|
const candidate = this.#byBbox(streetNorm, number, b.minLat, b.maxLat, b.minLon, b.maxLon);
|
|
198
233
|
// A row with its own scope that the scoped probes missed is a different address in the same box.
|
package/out/address/point.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point.js","sourceRoot":"","sources":["../../lib/address/point.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"point.js","sourceRoot":"","sources":["../../lib/address/point.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAA;AAI7D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAoB,MAAM,eAAe,CAAA;AACtE,OAAO,EACN,0BAA0B,EAC1B,uBAAuB,EACvB,6BAA6B,EAG7B,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,GAEnB,MAAM,mBAAmB,CAAA;AAQ1B;;;GAGG;AACH,MAAM,WAAW,GAAG,oDAAoD,CAAA;AAExE;;GAEG;AACH,MAAM,yBAAyB,GAAG,GAAG,CAAA;AAErC;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,MAAc;IAC3C,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE1C,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAExB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAEhD,OAAO,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,yBAAyB,CAAA;AACpD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,wBAAwB;IAG3B,GAAG,CAAoB;IACvB,OAAO,CAAc;IACrB,aAAa,CAAwB;IACrC,cAAc,CAAoB;IAClC,WAAW,CAAiG;IAC5G,mBAAmB,CAEhB;IACZ;;;OAGG;IACM,kBAAkB,CAEf;IACH,WAAW,CAAkG;IACtH;;;;OAIG;IACM,eAAe,CAEZ;IACH,eAAe,GAAY,KAAK,CAAA;IAChC,OAAO,CAKJ;IAEZ;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YACC,MAAuB,EACvB,IAAI,GAIA,EAAE;QAEN,IAAI,CAAC,GAAG,GAAG,IAAI,cAAc,CAAK,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAA;QACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAC1F,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,IAAI,OAAO,CAAA;QAEnD,sGAAsG;QACtG,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,UAAU,CAC5B,IAAI,CAAC,GAAG,EACR,UAAU,WAAW;mEAC0C,CAC/D,CAAA;YAED,IAAI,CAAC,mBAAmB,GAAG,UAAU,CACpC,IAAI,CAAC,GAAG,EACR,UAAU,WAAW;yFACgE,CACrF,CAAA;YAED,IAAI,CAAC,kBAAkB,GAAG,UAAU,CACnC,IAAI,CAAC,GAAG,EACR;2DACuD,CACvD,CAAA;YAED,IAAI,CAAC,WAAW,GAAG,UAAU,CAC5B,IAAI,CAAC,GAAG,EACR,UAAU,WAAW;wEAC+C,CACpE,CAAA;YAED,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;YAE7D,IAAI,CAAC,OAAO,GAAG,UAAU,CACxB,IAAI,CAAC,GAAG,EACR,UAAU,WAAW;kGACyE,CAC9F,CAAA;YAED,IAAI,CAAC,eAAe,GAAG,UAAU,CAChC,IAAI,CAAC,GAAG,EACR,UAAU,WAAW;2EACkD,CACvE,CAAA;QACF,CAAC;IACF,CAAC;IAED,IAAI,CAAC,KAQJ;QACA,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAA;QACxE,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAErE,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAExB,6CAA6C;QAC7C,0DAA0D;QAC1D,iFAAiF;QACjF,mEAAmE;QACnE,MAAM,MAAM,GACX,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS;YAC1D,CAAC,CAAC,KAAK,CAAC,MAAM;gBACb,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE;gBAC7D,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,6BAA6B,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE;YACnF,CAAC,CAAC,KAAK,CAAA;QAET,oDAAoD;QACpD,uDAAuD;QACvD,uCAAuC;QACvC,IAAI,GAAG,GAA2B,IAAI,CAAA;QAEtC,KAAK,MAAM,UAAU,IAAI,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,sBAAsB,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YAC9G,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;YAElD,IAAI,GAAG;gBAAE,MAAK;QACf,CAAC;QAED,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QAErB,OAAO;YACN,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,YAAY,EAAE,GAAG,CAAC,aAAa,IAAI,IAAI;YACvC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;SAC9B,CAAA;IACF,CAAC;IAED;;;OAGG;IACH,WAAW,CACV,UAAqB,EACrB,MAAc,EACd,KAOC;QAED,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;QAEhD,6EAA6E;QAC7E,yCAAyC;QACzC,4FAA4F;QAC5F,IAAI,CAAC,GAAG,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1C,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;QAC9D,CAAC;QAED,6CAA6C;QAC7C,qDAAqD;QACrD,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAEnD,IAAI,IAAI,EAAE,CAAC;gBACV,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;YAC9G,CAAC;QACF,CAAC;QAED,oGAAoG;QACpG,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAEvD,IAAI,GAAG,EAAE,CAAC;gBACT,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;YAC1C,CAAC;QACF,CAAC;QAED,mFAAmF;QACnF,+EAA+E;QAC/E,4BAA4B;QAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC/C,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAE5C,IAAI,MAAM,EAAE,CAAC;gBACZ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAE,EAAE,KAAK,CAAC,CAAA;YAC/G,CAAC;iBAAM,IAAI,MAAM,EAAE,CAAC;gBACnB,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAE,EAAE,KAAK,CAAC,CAAA;YAChH,CAAC;QACF,CAAC;QAED,8EAA8E;QAC9E,gCAAgC;QAChC,mFAAmF;QACnF,8BAA8B;QAC9B,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAErD,IAAI,IAAI,EAAE,CAAC;gBACV,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;YAC3C,CAAC;QACF,CAAC;QAED,OAAO,GAAG,CAAA;IACX,CAAC;IAED;;;OAGG;IACH,MAAM,CACL,UAAqB,EACrB,MAAc,EACd,KAKC;QAED,IAAI,GAAG,GAA2B,IAAI,CAAA;QACtC,8GAA8G;QAC9G,IAAI,QAAQ,GAA2B,IAAI,CAAA;QAE3C,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;YACtC,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAE7E,yEAAyE;YACzE,gEAAgE;YAChE,wEAAwE;YACxE,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAoB,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAC1G,MAAM,SAAS,GAAG,QAAQ,IAAI,IAAI,CAAC,WAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAA;YAE7E,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;gBAC5D,GAAG,GAAG,SAAS,CAAA;YAChB,CAAC;iBAAM,IAAI,SAAS,IAAI,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrG,QAAQ,GAAG,SAAS,CAAA;YACrB,CAAC;QACF,CAAC;QAED,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC5B,GAAG,GAAG,IAAI,CAAC,WAAY,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAA;QAC/E,CAAC;QAED,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxD,6EAA6E;YAC7E,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC,CAAA;QACzE,CAAC;QAED,IAAI,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAC;YACtB,GAAG,GAAG,QAAQ,CAAA;QACf,CAAC;QAED,2FAA2F;QAC3F,uGAAuG;QACvG,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAChD,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAA;YACpB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;YAE3F,iGAAiG;YACjG,GAAG,GAAG,SAAS,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;QAChF,CAAC;QAED,OAAO,GAAG,CAAA;IACX,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,QAAgB;QAC5B,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO,mBAAmB,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAA;QAExF,OAAO,6BAA6B,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC7D,CAAC;IAED;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,GAAoB,EAAE,KAA+C;QACtF,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE;YAAE,OAAO,IAAI,CAAA;QAEhG,IAAI,IAAI,CAAC,aAAa,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;YAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAElD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GACtB,GAAG,CAAC,aAAa,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;YAE5G,OAAO,OAAO,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,CAAC,CAAA;QAC/D,CAAC;QAED,OAAO,KAAK,CAAA;IACb,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAChB,GAAoB,EACpB,QAAgB,EAChB,UAAqB,EACrB,MAAc,EACd,IAA+E;QAE/E,IAAI,IAAI,CAAC,cAAc,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QAElD,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QAElE,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QAE9F,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QAEtB,OAAO,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,CAAA;IAC5G,CAAC;IAED,CAAC,MAAM,CAAC,OAAO,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;IAC3B,CAAC;CACD"}
|