@mailwoman/resolver-wof-sqlite 9.4.0 → 10.1.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/README.md +8 -8
- package/lib/address/{point-interpolation.ts → point/interpolation.ts} +40 -38
- package/lib/address/point/schema.ts +132 -0
- package/lib/address/point.ts +68 -81
- package/lib/{address/index.ts → address.ts} +2 -2
- package/lib/ancestry/backfill.ts +24 -88
- package/lib/{ancestry/index.ts → ancestry.ts} +19 -15
- package/lib/build/candidate.ts +608 -0
- package/lib/build/population-corrections.ts +64 -0
- package/lib/build/slim.ts +338 -0
- package/lib/candidate/alias-bags.ts +74 -14
- package/lib/candidate/ancestors/schema.ts +211 -0
- package/lib/candidate/{ancestors-sidecar.ts → ancestors/sidecar.ts} +17 -24
- package/lib/candidate/country-display-names.ts +6 -20
- package/lib/candidate/extract-fold.ts +12 -57
- package/lib/candidate/fts.ts +28 -0
- package/lib/candidate/importance.ts +221 -0
- package/lib/candidate/lookup.ts +669 -0
- package/lib/candidate/name-roles.ts +16 -34
- package/lib/candidate/own-name.ts +34 -31
- package/lib/candidate/place-attrs.ts +20 -13
- package/lib/candidate/schema.ts +211 -0
- package/lib/candidate/scoring.ts +222 -0
- package/lib/capital-schema.ts +21 -17
- package/lib/capitals.ts +26 -24
- package/lib/coincident-roles.ts +74 -55
- package/lib/convention/schema.ts +13 -7
- package/lib/convention.ts +144 -0
- package/lib/coverage-manifest-schema.ts +34 -39
- package/lib/currency-backfill.ts +24 -69
- package/lib/env.ts +1 -1
- package/lib/exact-match.ts +31 -20
- package/lib/extracts.ts +96 -73
- package/lib/fst/autocomplete.ts +52 -35
- package/lib/fst/builder.ts +30 -36
- package/lib/fst/deserialize-web.ts +8 -9
- package/lib/fst/format.ts +41 -23
- package/lib/fst/freshness.ts +17 -95
- package/lib/fst/matcher.ts +2 -2
- package/lib/fst/serialize.ts +45 -60
- package/lib/fst/types.ts +71 -59
- package/lib/fts/query.ts +5 -36
- package/lib/fts.ts +280 -0
- package/lib/geonames/aliases.ts +72 -149
- package/lib/geonames/postal.ts +162 -77
- package/lib/index.ts +20 -27
- package/lib/interpolation.ts +43 -96
- package/lib/lookup.ts +137 -257
- package/lib/name-score.ts +9 -7
- package/lib/nsul/lookup.ts +36 -53
- package/lib/nsul/schema.ts +16 -43
- package/lib/paths.ts +159 -0
- package/lib/place-importance-schema.ts +57 -164
- package/lib/poi/lookup.ts +100 -109
- package/lib/poi/schema.ts +42 -26
- package/lib/polygon-schema.ts +10 -6
- package/lib/postal/city/alias/lookup.ts +79 -0
- package/lib/postal/{city-alias-schema.ts → city/alias/schema.ts} +14 -10
- package/lib/postal/{city-candidate-schema.ts → city/candidate-schema.ts} +26 -20
- package/lib/postal.ts +9 -0
- package/lib/postcode-point-lookup.ts +9 -19
- package/lib/primary-preference.ts +45 -125
- package/lib/proximity-rerank.ts +43 -32
- package/lib/ranking-weights.ts +98 -76
- package/lib/region-keys.ts +68 -40
- package/lib/reverse.ts +108 -72
- package/lib/schema.ts +74 -42
- package/lib/search-fetch.ts +90 -68
- package/lib/sqlite/convention-source.ts +57 -0
- package/lib/sqlite/utils.ts +79 -0
- package/lib/street/centroid/schema.ts +149 -0
- package/lib/street/centroid.ts +16 -25
- package/lib/street/{morphology-fst-builder.ts → morphology/fst/builder.ts} +56 -41
- package/lib/street/{morphology-fst-loader.ts → morphology/fst/loader.ts} +36 -29
- package/lib/street/name-lookup.ts +43 -35
- package/lib/street/normalize.ts +85 -216
- package/lib/street/segment-schema.ts +116 -43
- package/lib/{street/index.ts → street.ts} +3 -3
- package/lib/types.ts +94 -140
- package/lib/unified-schema.ts +29 -29
- package/lib/uprn/existence.ts +30 -19
- package/lib/uprn/lookup.ts +28 -67
- package/lib/uprn/schema.ts +18 -40
- package/lib/weights-overlay-linker.ts +204 -232
- package/out/address/point/interpolation.d.ts +45 -0
- package/out/address/point/interpolation.d.ts.map +1 -0
- package/out/address/{point-interpolation.js → point/interpolation.js} +38 -38
- package/out/address/point/interpolation.js.map +1 -0
- package/out/address/point/schema.d.ts +74 -0
- package/out/address/point/schema.d.ts.map +1 -0
- package/out/address/{point-schema.js → point/schema.js} +4 -20
- package/out/address/point/schema.js.map +1 -0
- package/out/address/point.d.ts +24 -21
- package/out/address/point.d.ts.map +1 -1
- package/out/address/point.js +60 -77
- package/out/address/point.js.map +1 -1
- package/out/{address/index.js → address.d.ts} +3 -3
- package/out/address.d.ts.map +1 -0
- package/out/{address/index.d.ts → address.js} +3 -3
- package/out/address.js.map +1 -0
- package/out/ancestry/backfill.d.ts +11 -64
- package/out/ancestry/backfill.d.ts.map +1 -1
- package/out/ancestry/backfill.js +18 -76
- package/out/ancestry/backfill.js.map +1 -1
- package/out/ancestry.d.ts +49 -0
- package/out/ancestry.d.ts.map +1 -0
- package/out/ancestry.js +59 -0
- package/out/ancestry.js.map +1 -0
- package/out/build/candidate.d.ts +170 -0
- package/out/build/candidate.d.ts.map +1 -0
- package/out/{build-candidate.js → build/candidate.js} +33 -102
- package/out/build/candidate.js.map +1 -0
- package/out/build/population-corrections.d.ts +52 -0
- package/out/build/population-corrections.d.ts.map +1 -0
- package/out/build/population-corrections.js +40 -0
- package/out/build/population-corrections.js.map +1 -0
- package/out/build/slim.d.ts +44 -0
- package/out/build/slim.d.ts.map +1 -0
- package/out/{build-slim.js → build/slim.js} +33 -94
- package/out/build/slim.js.map +1 -0
- package/out/candidate/alias-bags.d.ts +13 -5
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +55 -12
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/ancestors/schema.d.ts +166 -0
- package/out/candidate/ancestors/schema.d.ts.map +1 -0
- package/out/candidate/ancestors/schema.js +131 -0
- package/out/candidate/ancestors/schema.js.map +1 -0
- package/out/candidate/ancestors/sidecar.d.ts +27 -0
- package/out/candidate/ancestors/sidecar.d.ts.map +1 -0
- package/out/candidate/{ancestors-sidecar.js → ancestors/sidecar.js} +17 -24
- package/out/candidate/ancestors/sidecar.js.map +1 -0
- package/out/candidate/country-display-names.d.ts +5 -15
- package/out/candidate/country-display-names.d.ts.map +1 -1
- package/out/candidate/country-display-names.js +6 -20
- package/out/candidate/country-display-names.js.map +1 -1
- package/out/candidate/extract-fold.d.ts +8 -16
- package/out/candidate/extract-fold.d.ts.map +1 -1
- package/out/candidate/extract-fold.js +6 -48
- package/out/candidate/extract-fold.js.map +1 -1
- package/out/candidate/fts.d.ts +19 -0
- package/out/candidate/fts.d.ts.map +1 -0
- package/out/candidate/fts.js +22 -0
- package/out/candidate/fts.js.map +1 -0
- package/out/candidate/importance.d.ts +127 -0
- package/out/candidate/importance.d.ts.map +1 -0
- package/out/candidate/importance.js +162 -0
- package/out/candidate/importance.js.map +1 -0
- package/out/candidate/lookup.d.ts +36 -0
- package/out/candidate/lookup.d.ts.map +1 -0
- package/out/candidate/lookup.js +456 -0
- package/out/candidate/lookup.js.map +1 -0
- package/out/candidate/name-roles.d.ts +10 -22
- package/out/candidate/name-roles.d.ts.map +1 -1
- package/out/candidate/name-roles.js +15 -33
- package/out/candidate/name-roles.js.map +1 -1
- package/out/candidate/own-name.d.ts +23 -25
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +34 -31
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/place-attrs.d.ts +20 -13
- package/out/candidate/place-attrs.d.ts.map +1 -1
- package/out/candidate/place-attrs.js +4 -5
- package/out/candidate/place-attrs.js.map +1 -1
- package/out/candidate/schema.d.ts +120 -0
- package/out/candidate/schema.d.ts.map +1 -0
- package/out/{candidate-schema.js → candidate/schema.js} +11 -23
- package/out/candidate/schema.js.map +1 -0
- package/out/{candidate-scoring.d.ts → candidate/scoring.d.ts} +8 -9
- package/out/candidate/scoring.d.ts.map +1 -0
- package/out/candidate/scoring.js +157 -0
- package/out/candidate/scoring.js.map +1 -0
- package/out/capital-schema.d.ts +21 -17
- package/out/capital-schema.d.ts.map +1 -1
- package/out/capital-schema.js +17 -15
- package/out/capital-schema.js.map +1 -1
- package/out/capitals.d.ts +26 -24
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js +23 -21
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +60 -43
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +61 -50
- package/out/coincident-roles.js.map +1 -1
- package/out/convention/schema.d.ts +12 -6
- package/out/convention/schema.d.ts.map +1 -1
- package/out/convention/schema.js +6 -4
- package/out/convention/schema.js.map +1 -1
- package/out/convention.d.ts +97 -0
- package/out/convention.d.ts.map +1 -0
- package/out/convention.js +81 -0
- package/out/convention.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +33 -38
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +20 -29
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +13 -35
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +12 -39
- package/out/currency-backfill.js.map +1 -1
- package/out/env.d.ts +2 -2
- package/out/env.js +1 -1
- package/out/exact-match.d.ts +19 -10
- package/out/exact-match.d.ts.map +1 -1
- package/out/exact-match.js +31 -20
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +65 -54
- package/out/extracts.d.ts.map +1 -1
- package/out/extracts.js +63 -55
- package/out/extracts.js.map +1 -1
- package/out/fst/autocomplete.d.ts +28 -20
- package/out/fst/autocomplete.d.ts.map +1 -1
- package/out/fst/autocomplete.js +38 -27
- package/out/fst/autocomplete.js.map +1 -1
- package/out/fst/builder.d.ts.map +1 -1
- package/out/fst/builder.js +30 -36
- package/out/fst/builder.js.map +1 -1
- package/out/fst/deserialize-web.d.ts +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -1
- package/out/fst/deserialize-web.js +8 -9
- package/out/fst/deserialize-web.js.map +1 -1
- package/out/fst/format.d.ts +41 -23
- package/out/fst/format.d.ts.map +1 -1
- package/out/fst/format.js +41 -23
- package/out/fst/format.js.map +1 -1
- package/out/fst/freshness.d.ts +11 -73
- package/out/fst/freshness.d.ts.map +1 -1
- package/out/fst/freshness.js +12 -76
- package/out/fst/freshness.js.map +1 -1
- package/out/fst/matcher.d.ts +1 -1
- package/out/fst/matcher.d.ts.map +1 -1
- package/out/fst/matcher.js +2 -2
- package/out/fst/matcher.js.map +1 -1
- package/out/fst/serialize.d.ts +30 -26
- package/out/fst/serialize.d.ts.map +1 -1
- package/out/fst/serialize.js +44 -58
- package/out/fst/serialize.js.map +1 -1
- package/out/fst/types.d.ts +71 -59
- package/out/fst/types.d.ts.map +1 -1
- package/out/fst/types.js +1 -4
- package/out/fst/types.js.map +1 -1
- package/out/{fst/index.js → fst.d.ts} +1 -1
- package/out/fst.d.ts.map +1 -0
- package/out/{fst/index.d.ts → fst.js} +1 -1
- package/out/fst.js.map +1 -0
- package/out/fts/query.d.ts +2 -27
- package/out/fts/query.d.ts.map +1 -1
- package/out/fts/query.js +5 -36
- package/out/fts/query.js.map +1 -1
- package/out/fts.d.ts +126 -0
- package/out/fts.d.ts.map +1 -0
- package/out/fts.js +188 -0
- package/out/fts.js.map +1 -0
- package/out/geonames/aliases.d.ts +26 -67
- package/out/geonames/aliases.d.ts.map +1 -1
- package/out/geonames/aliases.js +44 -121
- package/out/geonames/aliases.js.map +1 -1
- package/out/geonames/postal.d.ts +84 -50
- package/out/geonames/postal.d.ts.map +1 -1
- package/out/geonames/postal.js +115 -78
- package/out/geonames/postal.js.map +1 -1
- package/out/{geonames/index.js → geonames.d.ts} +1 -1
- package/out/geonames.d.ts.map +1 -0
- package/out/{geonames/index.d.ts → geonames.js} +1 -1
- package/out/geonames.js.map +1 -0
- package/out/index.d.ts +20 -21
- package/out/index.d.ts.map +1 -1
- package/out/index.js +14 -15
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +15 -52
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +25 -68
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +24 -53
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +117 -223
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts +2 -2
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js +9 -7
- package/out/name-score.js.map +1 -1
- package/out/nsul/lookup.d.ts +33 -34
- package/out/nsul/lookup.d.ts.map +1 -1
- package/out/nsul/lookup.js +26 -40
- package/out/nsul/lookup.js.map +1 -1
- package/out/nsul/schema.d.ts +16 -43
- package/out/nsul/schema.d.ts.map +1 -1
- package/out/nsul/schema.js +9 -35
- package/out/nsul/schema.js.map +1 -1
- package/out/{nsul/index.d.ts → nsul.d.ts} +1 -1
- package/out/nsul.d.ts.map +1 -0
- package/out/{nsul/index.js → nsul.js} +1 -1
- package/out/nsul.js.map +1 -0
- package/out/paths.d.ts +124 -0
- package/out/paths.d.ts.map +1 -0
- package/out/paths.js +104 -0
- package/out/paths.js.map +1 -0
- package/out/place-importance-schema.d.ts +49 -141
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +25 -140
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/lookup.d.ts +38 -42
- package/out/poi/lookup.d.ts.map +1 -1
- package/out/poi/lookup.js +67 -90
- package/out/poi/lookup.js.map +1 -1
- package/out/poi/schema.d.ts +41 -25
- package/out/poi/schema.d.ts.map +1 -1
- package/out/poi/schema.js +25 -17
- package/out/poi/schema.js.map +1 -1
- package/out/{poi/index.js → poi.d.ts} +1 -1
- package/out/poi.d.ts.map +1 -0
- package/out/{poi/index.d.ts → poi.js} +1 -1
- package/out/poi.js.map +1 -0
- package/out/polygon-schema.d.ts +10 -6
- package/out/polygon-schema.d.ts.map +1 -1
- package/out/polygon-schema.js +2 -2
- package/out/polygon-schema.js.map +1 -1
- package/out/postal/{city-alias-lookup.d.ts → city/alias/lookup.d.ts} +22 -25
- package/out/postal/city/alias/lookup.d.ts.map +1 -0
- package/out/postal/city/alias/lookup.js +49 -0
- package/out/postal/city/alias/lookup.js.map +1 -0
- package/out/postal/{city-alias-schema.d.ts → city/alias/schema.d.ts} +15 -11
- package/out/postal/city/alias/schema.d.ts.map +1 -0
- package/out/postal/{city-alias-schema.js → city/alias/schema.js} +11 -9
- package/out/postal/city/alias/schema.js.map +1 -0
- package/out/postal/city/candidate-schema.d.ts +72 -0
- package/out/postal/city/candidate-schema.d.ts.map +1 -0
- package/out/postal/city/candidate-schema.js +60 -0
- package/out/postal/city/candidate-schema.js.map +1 -0
- package/out/postal.d.ts +9 -0
- package/out/postal.d.ts.map +1 -0
- package/out/postal.js +9 -0
- package/out/postal.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +9 -19
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +5 -17
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +39 -93
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +13 -97
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +40 -29
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/proximity-rerank.js +38 -29
- package/out/proximity-rerank.js.map +1 -1
- package/out/ranking-weights.d.ts +91 -62
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +26 -25
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +48 -29
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js +68 -40
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +75 -50
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +61 -49
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +74 -42
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js +4 -5
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +16 -12
- package/out/search-fetch.d.ts.map +1 -1
- package/out/search-fetch.js +83 -63
- package/out/search-fetch.js.map +1 -1
- package/out/sqlite/convention-source.d.ts +25 -0
- package/out/sqlite/convention-source.d.ts.map +1 -0
- package/out/sqlite/convention-source.js +48 -0
- package/out/sqlite/convention-source.js.map +1 -0
- package/out/sqlite/utils.d.ts +45 -0
- package/out/sqlite/utils.d.ts.map +1 -0
- package/out/sqlite/utils.js +56 -0
- package/out/sqlite/utils.js.map +1 -0
- package/out/street/centroid/schema.d.ts +100 -0
- package/out/street/centroid/schema.d.ts.map +1 -0
- package/out/street/centroid/schema.js +66 -0
- package/out/street/centroid/schema.js.map +1 -0
- package/out/street/centroid.d.ts +9 -19
- package/out/street/centroid.d.ts.map +1 -1
- package/out/street/centroid.js +11 -22
- package/out/street/centroid.js.map +1 -1
- package/out/street/{morphology-fst-builder.d.ts → morphology/fst/builder.d.ts} +21 -11
- package/out/street/morphology/fst/builder.d.ts.map +1 -0
- package/out/street/{morphology-fst-builder.js → morphology/fst/builder.js} +40 -34
- package/out/street/morphology/fst/builder.js.map +1 -0
- package/out/street/morphology/fst/loader.d.ts +74 -0
- package/out/street/morphology/fst/loader.d.ts.map +1 -0
- package/out/street/{morphology-fst-loader.js → morphology/fst/loader.js} +21 -21
- package/out/street/morphology/fst/loader.js.map +1 -0
- package/out/street/name-lookup.d.ts +24 -18
- package/out/street/name-lookup.d.ts.map +1 -1
- package/out/street/name-lookup.js +32 -31
- package/out/street/name-lookup.js.map +1 -1
- package/out/street/normalize.d.ts +35 -136
- package/out/street/normalize.d.ts.map +1 -1
- package/out/street/normalize.js +74 -191
- package/out/street/normalize.js.map +1 -1
- package/out/street/segment-schema.d.ts +79 -39
- package/out/street/segment-schema.d.ts.map +1 -1
- package/out/street/segment-schema.js +71 -21
- package/out/street/segment-schema.js.map +1 -1
- package/out/{street/index.d.ts → street.d.ts} +4 -4
- package/out/street.d.ts.map +1 -0
- package/out/{street/index.js → street.js} +4 -4
- package/out/street.js.map +1 -0
- package/out/types.d.ts +69 -138
- package/out/types.d.ts.map +1 -1
- package/out/types.js +0 -6
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +8 -12
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +29 -29
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +28 -17
- package/out/uprn/existence.d.ts.map +1 -1
- package/out/uprn/existence.js +26 -16
- package/out/uprn/existence.js.map +1 -1
- package/out/uprn/lookup.d.ts +14 -44
- package/out/uprn/lookup.d.ts.map +1 -1
- package/out/uprn/lookup.js +20 -56
- package/out/uprn/lookup.js.map +1 -1
- package/out/uprn/schema.d.ts +18 -40
- package/out/uprn/schema.d.ts.map +1 -1
- package/out/uprn/schema.js +10 -32
- package/out/uprn/schema.js.map +1 -1
- package/out/{uprn/index.d.ts → uprn.d.ts} +1 -1
- package/out/uprn.d.ts.map +1 -0
- package/out/{uprn/index.js → uprn.js} +1 -1
- package/out/uprn.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +132 -141
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +86 -154
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +94 -599
- package/lib/address/point-schema.ts +0 -155
- package/lib/build-candidate.ts +0 -632
- package/lib/build-slim.ts +0 -408
- package/lib/candidate-ancestors-schema.ts +0 -195
- package/lib/candidate-fts.ts +0 -46
- package/lib/candidate-importance.ts +0 -224
- package/lib/candidate-lookup.ts +0 -977
- package/lib/candidate-schema.ts +0 -247
- package/lib/candidate-scoring.ts +0 -261
- package/lib/convention/index.ts +0 -154
- package/lib/fts/index.ts +0 -361
- package/lib/postal/city-alias-lookup.ts +0 -97
- package/lib/postal/index.ts +0 -9
- package/lib/sqlite-convention-source.ts +0 -65
- package/lib/sqlite-utils.ts +0 -82
- package/lib/street/centroid-schema.ts +0 -154
- package/out/address/index.d.ts.map +0 -1
- package/out/address/index.js.map +0 -1
- package/out/address/point-interpolation.d.ts +0 -49
- package/out/address/point-interpolation.d.ts.map +0 -1
- package/out/address/point-interpolation.js.map +0 -1
- package/out/address/point-schema.d.ts +0 -97
- package/out/address/point-schema.d.ts.map +0 -1
- package/out/address/point-schema.js.map +0 -1
- package/out/ancestry/index.d.ts +0 -45
- package/out/ancestry/index.d.ts.map +0 -1
- package/out/ancestry/index.js +0 -55
- package/out/ancestry/index.js.map +0 -1
- package/out/build-candidate.d.ts +0 -184
- package/out/build-candidate.d.ts.map +0 -1
- package/out/build-candidate.js.map +0 -1
- package/out/build-slim.d.ts +0 -80
- package/out/build-slim.d.ts.map +0 -1
- package/out/build-slim.js.map +0 -1
- package/out/candidate/ancestors-sidecar.d.ts +0 -32
- package/out/candidate/ancestors-sidecar.d.ts.map +0 -1
- package/out/candidate/ancestors-sidecar.js.map +0 -1
- package/out/candidate-ancestors-schema.d.ts +0 -150
- package/out/candidate-ancestors-schema.d.ts.map +0 -1
- package/out/candidate-ancestors-schema.js +0 -123
- package/out/candidate-ancestors-schema.js.map +0 -1
- package/out/candidate-fts.d.ts +0 -37
- package/out/candidate-fts.d.ts.map +0 -1
- package/out/candidate-fts.js +0 -40
- package/out/candidate-fts.js.map +0 -1
- package/out/candidate-importance.d.ts +0 -132
- package/out/candidate-importance.d.ts.map +0 -1
- package/out/candidate-importance.js +0 -169
- package/out/candidate-importance.js.map +0 -1
- package/out/candidate-lookup.d.ts +0 -76
- package/out/candidate-lookup.d.ts.map +0 -1
- package/out/candidate-lookup.js +0 -768
- package/out/candidate-lookup.js.map +0 -1
- package/out/candidate-schema.d.ts +0 -155
- package/out/candidate-schema.d.ts.map +0 -1
- package/out/candidate-schema.js.map +0 -1
- package/out/candidate-scoring.d.ts.map +0 -1
- package/out/candidate-scoring.js +0 -196
- package/out/candidate-scoring.js.map +0 -1
- package/out/convention/index.d.ts +0 -106
- package/out/convention/index.d.ts.map +0 -1
- package/out/convention/index.js +0 -93
- package/out/convention/index.js.map +0 -1
- package/out/fst/index.d.ts.map +0 -1
- package/out/fst/index.js.map +0 -1
- package/out/fts/index.d.ts +0 -184
- package/out/fts/index.d.ts.map +0 -1
- package/out/fts/index.js +0 -277
- package/out/fts/index.js.map +0 -1
- package/out/geonames/index.d.ts.map +0 -1
- package/out/geonames/index.js.map +0 -1
- package/out/nsul/index.d.ts.map +0 -1
- package/out/nsul/index.js.map +0 -1
- package/out/poi/index.d.ts.map +0 -1
- package/out/poi/index.js.map +0 -1
- package/out/postal/city-alias-lookup.d.ts.map +0 -1
- package/out/postal/city-alias-lookup.js +0 -62
- package/out/postal/city-alias-lookup.js.map +0 -1
- package/out/postal/city-alias-schema.d.ts.map +0 -1
- package/out/postal/city-alias-schema.js.map +0 -1
- package/out/postal/city-candidate-schema.d.ts +0 -66
- package/out/postal/city-candidate-schema.d.ts.map +0 -1
- package/out/postal/city-candidate-schema.js +0 -56
- package/out/postal/city-candidate-schema.js.map +0 -1
- package/out/postal/index.d.ts +0 -9
- package/out/postal/index.d.ts.map +0 -1
- package/out/postal/index.js +0 -9
- package/out/postal/index.js.map +0 -1
- package/out/sqlite-convention-source.d.ts +0 -29
- package/out/sqlite-convention-source.d.ts.map +0 -1
- package/out/sqlite-convention-source.js +0 -57
- package/out/sqlite-convention-source.js.map +0 -1
- package/out/sqlite-utils.d.ts +0 -45
- package/out/sqlite-utils.d.ts.map +0 -1
- package/out/sqlite-utils.js +0 -57
- package/out/sqlite-utils.js.map +0 -1
- package/out/street/centroid-schema.d.ts +0 -105
- package/out/street/centroid-schema.d.ts.map +0 -1
- package/out/street/centroid-schema.js +0 -78
- package/out/street/centroid-schema.js.map +0 -1
- package/out/street/index.d.ts.map +0 -1
- package/out/street/index.js.map +0 -1
- package/out/street/morphology-fst-builder.d.ts.map +0 -1
- package/out/street/morphology-fst-builder.js.map +0 -1
- package/out/street/morphology-fst-loader.d.ts +0 -67
- package/out/street/morphology-fst-loader.d.ts.map +0 -1
- package/out/street/morphology-fst-loader.js.map +0 -1
- package/out/uprn/index.d.ts.map +0 -1
- package/out/uprn/index.js.map +0 -1
- /package/lib/{fst/index.ts → fst.ts} +0 -0
- /package/lib/{geonames/index.ts → geonames.ts} +0 -0
- /package/lib/{nsul/index.ts → nsul.ts} +0 -0
- /package/lib/{poi/index.ts → poi.ts} +0 -0
- /package/lib/{uprn/index.ts → uprn.ts} +0 -0
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { COUNTRY_POPULATION } from "@mailwoman/codex/country"
|
|
8
|
+
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
9
|
+
import { removePath } from "@mailwoman/core/fs/writers"
|
|
10
|
+
import { stringifyJSON } from "@mailwoman/core/json"
|
|
11
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
12
|
+
import type { PathBuilderLike } from "path-ts"
|
|
13
|
+
|
|
14
|
+
import { POPULATION_CORRECTIONS } from "#build/population-corrections"
|
|
15
|
+
import { explodeAliasBags } from "#candidate/alias-bags"
|
|
16
|
+
import { buildAncestorsSidecar } from "#candidate/ancestors/sidecar"
|
|
17
|
+
import { stageCountryDisplayNames } from "#candidate/country-display-names"
|
|
18
|
+
import { foldExtract } from "#candidate/extract-fold"
|
|
19
|
+
import { createCandidateFTS } from "#candidate/fts"
|
|
20
|
+
import { IMPORTANCE_JOIN_RADIUS_KM, loadImportanceIndex } from "#candidate/importance"
|
|
21
|
+
import { GLOSS_KEY_THRESHOLD, stampNameRoles } from "#candidate/name-roles"
|
|
22
|
+
import type { PlaceAttrs } from "#candidate/place-attrs"
|
|
23
|
+
import {
|
|
24
|
+
CANDIDATE_COLUMNS,
|
|
25
|
+
createCandidateStagingTables,
|
|
26
|
+
createCandidateTable,
|
|
27
|
+
type CandidateDatabase,
|
|
28
|
+
} from "#candidate/schema"
|
|
29
|
+
import { createCapitalTable } from "#capital-schema"
|
|
30
|
+
import type { CapitalPoint } from "#capitals"
|
|
31
|
+
import { resurrectCurrencyHoles } from "#currency-backfill"
|
|
32
|
+
import type { WOFDatabase } from "#schema"
|
|
33
|
+
import { normalizeLocalityForKey } from "#street/normalize"
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Re-exports the country display-name staging pass from the candidate build's public module.
|
|
37
|
+
*/
|
|
38
|
+
export { stageCountryDisplayNames } from "#candidate/country-display-names"
|
|
39
|
+
/**
|
|
40
|
+
* Re-exports the gloss detector's excluded placetypes and default key-count threshold.
|
|
41
|
+
*/
|
|
42
|
+
export { GLOSS_EXCLUDED_PLACETYPES, GLOSS_KEY_THRESHOLD } from "#candidate/name-roles"
|
|
43
|
+
/**
|
|
44
|
+
* Re-exports the per-place record that every candidate staging pass writes its rows from.
|
|
45
|
+
*/
|
|
46
|
+
export type { PlaceAttrs } from "#candidate/place-attrs"
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Options for {@link buildCandidateTable}.
|
|
50
|
+
*/
|
|
51
|
+
export interface BuildCandidateOptions {
|
|
52
|
+
/**
|
|
53
|
+
* The source WOF admin database.
|
|
54
|
+
*
|
|
55
|
+
* It must have the `spr`, `place_population`, `place_search`, `place_abbr` and `ancestors` tables.
|
|
56
|
+
*/
|
|
57
|
+
input: PathBuilderLike
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The candidate database to write, replacing any existing file.
|
|
61
|
+
*/
|
|
62
|
+
output: PathBuilderLike
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The capital reference entries to store in the artifact's `capital` table.
|
|
66
|
+
*
|
|
67
|
+
* The caller supplies these entries because this published module cannot read repository paths.
|
|
68
|
+
* The builder creates no `capital` table when the caller omits them.
|
|
69
|
+
*
|
|
70
|
+
* The capital loader then falls back to the repository's `capitals-v1.json`.
|
|
71
|
+
*/
|
|
72
|
+
capitals?: readonly CapitalPoint[]
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Postcode extract databases whose located `spr` rows become `postalcode` candidate rows.
|
|
76
|
+
*
|
|
77
|
+
* Each extract's `names` table becomes aliases, such as the delivery city "Brooklyn" for 11201.
|
|
78
|
+
*/
|
|
79
|
+
postcodes?: readonly PathBuilderLike[]
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Locality extract databases whose located `spr` rows become `locality`
|
|
83
|
+
* candidate rows with zero population.
|
|
84
|
+
*
|
|
85
|
+
* Their `names` tables become non-primary aliases.
|
|
86
|
+
* When an extract's `ancestors` table gives a row's region, the row gets
|
|
87
|
+
* that region's scope and closure rows.
|
|
88
|
+
* Other rows stay unscoped.
|
|
89
|
+
*/
|
|
90
|
+
localities?: readonly PathBuilderLike[]
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A WOF admin database with a `place_importance` table supplies the `importance` column.
|
|
94
|
+
*
|
|
95
|
+
* Rows join on name key, country and placetype, then on the nearest centroid.
|
|
96
|
+
* Without this option every row's `importance` is NULL.
|
|
97
|
+
* Consumers treat NULL as unmeasured.
|
|
98
|
+
*/
|
|
99
|
+
importance?: PathBuilderLike
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Settings for restoring deprecated WOF places that have no successor and have a GeoNames attestation.
|
|
103
|
+
*
|
|
104
|
+
* A deprecated place is restored only when no live row of the same name lies within 10 km and
|
|
105
|
+
* a GeoNames populated place with the same folded name and at least 1,000 people lies within 10 km.
|
|
106
|
+
* Countries without `<cc>.txt` under `geonamesDir` are skipped and reported.
|
|
107
|
+
*/
|
|
108
|
+
currencyBackfill?: {
|
|
109
|
+
geonamesDir: PathBuilderLike
|
|
110
|
+
countries: readonly string[]
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The deprecated placetypes eligible for restoration.
|
|
114
|
+
* The default is `locality`.
|
|
115
|
+
*/
|
|
116
|
+
deadPlacetypes?: readonly string[]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Receives a phase name and a message as each build step runs.
|
|
121
|
+
*/
|
|
122
|
+
onProgress?: (phase: string, message: string) => void
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The key-count threshold for the gloss anomaly detector.
|
|
126
|
+
* The default is {@link GLOSS_KEY_THRESHOLD}.
|
|
127
|
+
*
|
|
128
|
+
* Tests override it with a value sized for fixtures.
|
|
129
|
+
*/
|
|
130
|
+
glossKeyThreshold?: number
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Row and place counts from each stage of {@link buildCandidateTable}.
|
|
135
|
+
*/
|
|
136
|
+
export interface BuildCandidateResult {
|
|
137
|
+
rows: number
|
|
138
|
+
places: number
|
|
139
|
+
primaries: number
|
|
140
|
+
aliases: number
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The count of region aliases dropped because another region in the same
|
|
144
|
+
* country uses the name as its official name.
|
|
145
|
+
*
|
|
146
|
+
* The count is always zero for a source without a `names` table.
|
|
147
|
+
*/
|
|
148
|
+
regionOfficialRefused: number
|
|
149
|
+
abbrevs: number
|
|
150
|
+
postcodes: number
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The count of aliases added to postcode rows from the extracts' `names` tables.
|
|
154
|
+
*
|
|
155
|
+
* An extract without a `names` table is reported through `onProgress`.
|
|
156
|
+
*/
|
|
157
|
+
postcodeAliases: number
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The count of closure rows written to the `candidate_ancestor` sidecar,
|
|
161
|
+
* including rows from locality extracts.
|
|
162
|
+
*/
|
|
163
|
+
ancestorRows: number
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The count of places with at least one closure row.
|
|
167
|
+
*/
|
|
168
|
+
ancestorPlaces: number
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The count of places that received a pre/post interval label.
|
|
172
|
+
* It equals the node count of the canonical-parent forest.
|
|
173
|
+
*
|
|
174
|
+
* Containment against a place outside the forest is unknown.
|
|
175
|
+
*/
|
|
176
|
+
intervalPlaces: number
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The count of places that received an `importance` score.
|
|
180
|
+
*
|
|
181
|
+
* It is `undefined` when no score source was given.
|
|
182
|
+
*/
|
|
183
|
+
importanceScored?: number
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The count of places that matched a scored group by name key, country and placetype
|
|
187
|
+
* but whose nearest scored centroid lay beyond {@link IMPORTANCE_JOIN_RADIUS_KM}.
|
|
188
|
+
*
|
|
189
|
+
* A large change between rebuilds means the score source and the admin source have diverged.
|
|
190
|
+
*/
|
|
191
|
+
importanceFiltered?: number
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The count of alias rows the gloss anomaly detector stamped `name_role = 'gloss'`.
|
|
195
|
+
*/
|
|
196
|
+
roleGloss: number
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The count of alias rows stamped `name_role = 'abbr'`, which marks a variant in the official language.
|
|
200
|
+
*/
|
|
201
|
+
roleAbbr: number
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* The count of admin places whose staged key count reached the gloss key threshold.
|
|
205
|
+
* It is the denominator for `keyTailWithRole`.
|
|
206
|
+
*/
|
|
207
|
+
keyTailPlaces: number
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The count of places in `keyTailPlaces` with at least one stamped role row.
|
|
211
|
+
*/
|
|
212
|
+
keyTailWithRole: number
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Builds the candidate lookup database from a WOF admin database and replaces any existing output.
|
|
217
|
+
* The builder adds an FTS5 trigram index for fuzzy lookup.
|
|
218
|
+
*/
|
|
219
|
+
export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<BuildCandidateResult> {
|
|
220
|
+
const progress = opts.onProgress ?? (() => {})
|
|
221
|
+
|
|
222
|
+
if (await pathExists(opts.output)) {
|
|
223
|
+
await removePath(opts.output)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
using src = new DatabaseClient<WOFDatabase>(opts.input, { readOnly: true })
|
|
227
|
+
using kdb = new DatabaseClient<CandidateDatabase>(opts.output)
|
|
228
|
+
|
|
229
|
+
kdb.exec("PRAGMA page_size=8192; PRAGMA journal_mode=OFF; PRAGMA synchronous=OFF; PRAGMA cache_size=-2000000;")
|
|
230
|
+
|
|
231
|
+
await createCandidateStagingTables(kdb)
|
|
232
|
+
|
|
233
|
+
const ccodes = new Map<string, number>()
|
|
234
|
+
const ptcodes = new Map<string, number>()
|
|
235
|
+
|
|
236
|
+
const ccID = (code: string | null): number => {
|
|
237
|
+
const c = (code || "??").toUpperCase()
|
|
238
|
+
let id = ccodes.get(c)
|
|
239
|
+
|
|
240
|
+
if (id === undefined) {
|
|
241
|
+
id = ccodes.size
|
|
242
|
+
ccodes.set(c, id)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return id
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const ptID = (pt: string | null): number => {
|
|
249
|
+
const p = pt || ""
|
|
250
|
+
let id = ptcodes.get(p)
|
|
251
|
+
|
|
252
|
+
if (id === undefined) {
|
|
253
|
+
id = ptcodes.size
|
|
254
|
+
ptcodes.set(p, id)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return id
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
let importance: ReturnType<typeof loadImportanceIndex> | undefined
|
|
261
|
+
|
|
262
|
+
if (opts.importance) {
|
|
263
|
+
progress("importance", `loading place_importance from ${opts.importance}`)
|
|
264
|
+
importance = loadImportanceIndex(opts.importance)
|
|
265
|
+
|
|
266
|
+
progress(
|
|
267
|
+
"importance",
|
|
268
|
+
`${importance.stats.places.toLocaleString()} scored places in ${importance.stats.keys.toLocaleString()} (name, country, placetype) groups` +
|
|
269
|
+
(importance.stats.unkeyable ? `; ${importance.stats.unkeyable.toLocaleString()} unkeyable names skipped` : "")
|
|
270
|
+
)
|
|
271
|
+
} else {
|
|
272
|
+
progress("importance", "no score source given — `importance` will be NULL on every row")
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
progress("region", "loading region ancestry")
|
|
276
|
+
const regionOf = new Map<number, number>()
|
|
277
|
+
let multiRegion = 0
|
|
278
|
+
|
|
279
|
+
for (const r of src
|
|
280
|
+
.prepare(
|
|
281
|
+
"SELECT id, MIN(ancestor_id) AS ancestor_id, COUNT(DISTINCT ancestor_id) AS n" +
|
|
282
|
+
" FROM ancestors WHERE ancestor_placetype='region' GROUP BY id"
|
|
283
|
+
)
|
|
284
|
+
.iterate()) {
|
|
285
|
+
regionOf.set(Number(r.id), Number(r.ancestor_id))
|
|
286
|
+
|
|
287
|
+
if (Number(r.n) > 1) {
|
|
288
|
+
multiRegion++
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
progress(
|
|
293
|
+
"region",
|
|
294
|
+
`${regionOf.size.toLocaleString()} places carry a region` +
|
|
295
|
+
(multiRegion ? ` (${multiRegion.toLocaleString()} carry more than one; stamped with the lowest id)` : "")
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
const insStage = kdb.prepare(`INSERT INTO cand_stage VALUES (${CANDIDATE_COLUMNS.map(() => "?").join(", ")})`)
|
|
299
|
+
|
|
300
|
+
progress("primaries", "indexing place names")
|
|
301
|
+
const attrs = new Map<number, PlaceAttrs>()
|
|
302
|
+
let nPrim = 0
|
|
303
|
+
kdb.exec("BEGIN")
|
|
304
|
+
|
|
305
|
+
for (const r of src
|
|
306
|
+
.prepare(
|
|
307
|
+
`SELECT s.id AS id, s.name AS name, s.placetype AS placetype, s.country AS country,
|
|
308
|
+
s.latitude AS lat, s.longitude AS lon,
|
|
309
|
+
s.min_latitude AS mnlat, s.min_longitude AS mnlon, s.max_latitude AS mxlat, s.max_longitude AS mxlon,
|
|
310
|
+
pp.population AS pop
|
|
311
|
+
FROM spr s LEFT JOIN place_population pp ON pp.id = s.id
|
|
312
|
+
WHERE s.is_current != 0 AND s.is_deprecated = 0`
|
|
313
|
+
)
|
|
314
|
+
.iterate()) {
|
|
315
|
+
const sid = Number(r.id)
|
|
316
|
+
const cid = ccID(r.country as string | null)
|
|
317
|
+
const ptid = ptID(r.placetype as string | null)
|
|
318
|
+
const rid = regionOf.get(sid) ?? 0
|
|
319
|
+
|
|
320
|
+
const wofPop = r.pop === null || r.pop === undefined ? null : Number(r.pop)
|
|
321
|
+
|
|
322
|
+
const pop =
|
|
323
|
+
POPULATION_CORRECTIONS[sid]?.population ??
|
|
324
|
+
(wofPop === null && r.placetype === "country" ? (COUNTRY_POPULATION[String(r.country ?? "")] ?? null) : wofPop)
|
|
325
|
+
|
|
326
|
+
const neg = -Math.log10((pop ?? 0) + 1)
|
|
327
|
+
const name = String(r.name ?? "")
|
|
328
|
+
const pkey = normalizeLocalityForKey(name)
|
|
329
|
+
const lat = r.lat as number
|
|
330
|
+
const lon = r.lon as number
|
|
331
|
+
|
|
332
|
+
const a: PlaceAttrs = {
|
|
333
|
+
cid,
|
|
334
|
+
rid,
|
|
335
|
+
ptid,
|
|
336
|
+
name,
|
|
337
|
+
lat,
|
|
338
|
+
lon,
|
|
339
|
+
mnLat: r.mnlat as number,
|
|
340
|
+
mnLon: r.mnlon as number,
|
|
341
|
+
mxLat: r.mxlat as number,
|
|
342
|
+
mxLon: r.mxlon as number,
|
|
343
|
+
pop,
|
|
344
|
+
neg,
|
|
345
|
+
pkey,
|
|
346
|
+
imp: importance?.find(name, r.country as string | null, r.placetype as string | null, lat, lon) ?? null,
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
attrs.set(sid, a)
|
|
350
|
+
|
|
351
|
+
if (pkey) {
|
|
352
|
+
insStage.run(
|
|
353
|
+
pkey,
|
|
354
|
+
cid,
|
|
355
|
+
rid,
|
|
356
|
+
ptid,
|
|
357
|
+
neg,
|
|
358
|
+
sid,
|
|
359
|
+
name,
|
|
360
|
+
a.lat,
|
|
361
|
+
a.lon,
|
|
362
|
+
a.mnLat,
|
|
363
|
+
a.mnLon,
|
|
364
|
+
a.mxLat,
|
|
365
|
+
a.mxLon,
|
|
366
|
+
pop,
|
|
367
|
+
1,
|
|
368
|
+
a.imp,
|
|
369
|
+
null
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
nPrim++
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
kdb.exec("COMMIT")
|
|
377
|
+
progress("primaries", `${nPrim.toLocaleString()} primaries; ${attrs.size.toLocaleString()} places`)
|
|
378
|
+
|
|
379
|
+
if (importance) {
|
|
380
|
+
progress(
|
|
381
|
+
"importance",
|
|
382
|
+
`${importance.matched.toLocaleString()} places scored; ` +
|
|
383
|
+
`${importance.refused.toLocaleString()} refused (nearest same-name place > ${IMPORTANCE_JOIN_RADIUS_KM} km away)`
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const stageRow = (k: string, a: PlaceAttrs, sid: number, isPrimary: number): void => {
|
|
388
|
+
insStage.run(
|
|
389
|
+
k,
|
|
390
|
+
a.cid,
|
|
391
|
+
a.rid,
|
|
392
|
+
a.ptid,
|
|
393
|
+
a.neg,
|
|
394
|
+
sid,
|
|
395
|
+
a.name,
|
|
396
|
+
a.lat,
|
|
397
|
+
a.lon,
|
|
398
|
+
a.mnLat,
|
|
399
|
+
a.mnLon,
|
|
400
|
+
a.mxLat,
|
|
401
|
+
a.mxLon,
|
|
402
|
+
a.pop,
|
|
403
|
+
isPrimary,
|
|
404
|
+
a.imp,
|
|
405
|
+
null
|
|
406
|
+
)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
progress(
|
|
410
|
+
"country-display-names",
|
|
411
|
+
`${stageCountryDisplayNames({
|
|
412
|
+
attrs,
|
|
413
|
+
iso2ByID: new Map([...ccodes].map(([code, id]) => [id, code])),
|
|
414
|
+
countryPtID: ptID("country"),
|
|
415
|
+
stageRow,
|
|
416
|
+
tx: kdb,
|
|
417
|
+
}).toLocaleString()} country surfaces`
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
if (opts.currencyBackfill) {
|
|
421
|
+
const nBackfill = await resurrectCurrencyHoles({
|
|
422
|
+
src,
|
|
423
|
+
tx: kdb,
|
|
424
|
+
geonamesDir: opts.currencyBackfill.geonamesDir,
|
|
425
|
+
countries: opts.currencyBackfill.countries,
|
|
426
|
+
...(opts.currencyBackfill.deadPlacetypes ? { deadPlacetypes: opts.currencyBackfill.deadPlacetypes } : {}),
|
|
427
|
+
attrs,
|
|
428
|
+
ccID,
|
|
429
|
+
ptID,
|
|
430
|
+
regionOf,
|
|
431
|
+
importance,
|
|
432
|
+
stageRow,
|
|
433
|
+
progress,
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
progress("currency-backfill", `${nBackfill.toLocaleString()} resurrections staged`)
|
|
437
|
+
} else {
|
|
438
|
+
progress("currency-backfill", "not configured — deprecated-no-successor holes stay dead (#1737)")
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
progress("aliases", "exploding alias bags")
|
|
442
|
+
|
|
443
|
+
const { nAlias, keyCounts, regionOfficialRefused } = explodeAliasBags(src, kdb, attrs, stageRow, {
|
|
444
|
+
regionPlacetypeID: ptID("region"),
|
|
445
|
+
ccID,
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
progress(
|
|
449
|
+
"aliases",
|
|
450
|
+
`${nAlias.toLocaleString()} aliases` +
|
|
451
|
+
(regionOfficialRefused
|
|
452
|
+
? `; ${regionOfficialRefused.toLocaleString()} region aliases refused as another region's official name`
|
|
453
|
+
: "")
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
let nAbbr = 0
|
|
457
|
+
kdb.exec("BEGIN")
|
|
458
|
+
|
|
459
|
+
for (const r of src.prepare("SELECT id, abbr FROM place_abbr").iterate()) {
|
|
460
|
+
const a = attrs.get(Number(r.id))
|
|
461
|
+
|
|
462
|
+
if (!a) continue
|
|
463
|
+
const k = normalizeLocalityForKey(String(r.abbr ?? ""))
|
|
464
|
+
|
|
465
|
+
if (!k) continue
|
|
466
|
+
stageRow(k, a, Number(r.id), 1)
|
|
467
|
+
|
|
468
|
+
nAbbr++
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
kdb.exec("COMMIT")
|
|
472
|
+
progress("abbrevs", `${nAbbr.toLocaleString()} abbrevs`)
|
|
473
|
+
|
|
474
|
+
const roles = stampNameRoles({
|
|
475
|
+
src,
|
|
476
|
+
out: kdb,
|
|
477
|
+
attrs,
|
|
478
|
+
keyCounts,
|
|
479
|
+
glossThreshold: opts.glossKeyThreshold ?? GLOSS_KEY_THRESHOLD,
|
|
480
|
+
ptcodes,
|
|
481
|
+
ccodes,
|
|
482
|
+
progress,
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
const sidecar = await buildAncestorsSidecar({ src, out: kdb, attrs, ptID, progress })
|
|
486
|
+
|
|
487
|
+
let nPostcode = 0
|
|
488
|
+
let nPostcodeAlias = 0
|
|
489
|
+
|
|
490
|
+
for (const pcDB of opts.postcodes ?? []) {
|
|
491
|
+
const folded = foldExtract({
|
|
492
|
+
out: kdb,
|
|
493
|
+
extractPath: pcDB,
|
|
494
|
+
extractPlacetype: "postalcode",
|
|
495
|
+
ccID,
|
|
496
|
+
ptID,
|
|
497
|
+
stageRow,
|
|
498
|
+
progress,
|
|
499
|
+
})
|
|
500
|
+
|
|
501
|
+
nPostcode += folded.primaries
|
|
502
|
+
nPostcodeAlias += folded.aliases
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (nPostcode > 0) {
|
|
506
|
+
progress("postcodes", `${nPostcode.toLocaleString()} postcodes; ${nPostcodeAlias.toLocaleString()} aliases`)
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
let nLocality = 0
|
|
510
|
+
let nLocalityScoped = 0
|
|
511
|
+
let nLocalityAncestor = 0
|
|
512
|
+
|
|
513
|
+
for (const locDB of opts.localities ?? []) {
|
|
514
|
+
const folded = foldExtract({
|
|
515
|
+
out: kdb,
|
|
516
|
+
extractPath: locDB,
|
|
517
|
+
extractPlacetype: "locality",
|
|
518
|
+
ccID,
|
|
519
|
+
ptID,
|
|
520
|
+
stageRow,
|
|
521
|
+
attrs,
|
|
522
|
+
progress,
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
nLocality += folded.primaries
|
|
526
|
+
nLocalityScoped += folded.scoped
|
|
527
|
+
nLocalityAncestor += folded.ancestorRows
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (nLocality > 0) {
|
|
531
|
+
progress(
|
|
532
|
+
"localities",
|
|
533
|
+
`${nLocality.toLocaleString()} extract localities folded` +
|
|
534
|
+
(nLocalityScoped
|
|
535
|
+
? `; ${nLocalityScoped.toLocaleString()} carry a region scope (${nLocalityAncestor.toLocaleString()} closure rows)`
|
|
536
|
+
: "")
|
|
537
|
+
)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (ccodes.size) {
|
|
541
|
+
await kdb
|
|
542
|
+
.insertInto("country_codes")
|
|
543
|
+
.values([...ccodes].map(([code, id]) => ({ id, code })))
|
|
544
|
+
.execute()
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (ptcodes.size) {
|
|
548
|
+
await kdb
|
|
549
|
+
.insertInto("placetype_codes")
|
|
550
|
+
.values([...ptcodes].map(([placetype, id]) => ({ id, placetype })))
|
|
551
|
+
.execute()
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (opts.capitals?.length) {
|
|
555
|
+
await createCapitalTable<CandidateDatabase>(kdb)
|
|
556
|
+
|
|
557
|
+
await kdb
|
|
558
|
+
.insertInto("capital")
|
|
559
|
+
.values(
|
|
560
|
+
opts.capitals.map((entry) => ({
|
|
561
|
+
country: entry.country,
|
|
562
|
+
latitude: entry.latitude,
|
|
563
|
+
longitude: entry.longitude,
|
|
564
|
+
level: entry.level,
|
|
565
|
+
keys: stringifyJSON(entry.k),
|
|
566
|
+
}))
|
|
567
|
+
)
|
|
568
|
+
.execute()
|
|
569
|
+
|
|
570
|
+
progress("capitals", `${opts.capitals.length.toLocaleString()} capital-reference rows carried in-artifact`)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
progress("cluster", "building clustered candidate table + VACUUM")
|
|
574
|
+
|
|
575
|
+
const cols = CANDIDATE_COLUMNS.join(", ")
|
|
576
|
+
const keyOrder = CANDIDATE_COLUMNS.slice(0, 6).join(", ")
|
|
577
|
+
await createCandidateTable(kdb)
|
|
578
|
+
|
|
579
|
+
kdb.exec(`INSERT OR IGNORE INTO candidate (${cols}) SELECT ${cols} FROM cand_stage ORDER BY ${keyOrder};`)
|
|
580
|
+
await kdb.schema.dropTable("cand_stage").execute()
|
|
581
|
+
|
|
582
|
+
progress("fts", "building FTS5-trigram fuzzy index")
|
|
583
|
+
createCandidateFTS(kdb)
|
|
584
|
+
|
|
585
|
+
kdb.exec("PRAGMA page_size=8192")
|
|
586
|
+
kdb.exec("VACUUM")
|
|
587
|
+
|
|
588
|
+
const { n: rows } = await kdb
|
|
589
|
+
.selectFrom("candidate")
|
|
590
|
+
.select((eb) => eb.fn.countAll<number>().as("n"))
|
|
591
|
+
.executeTakeFirstOrThrow()
|
|
592
|
+
|
|
593
|
+
return {
|
|
594
|
+
rows,
|
|
595
|
+
places: attrs.size,
|
|
596
|
+
primaries: nPrim,
|
|
597
|
+
aliases: nAlias,
|
|
598
|
+
regionOfficialRefused,
|
|
599
|
+
abbrevs: nAbbr,
|
|
600
|
+
postcodes: nPostcode,
|
|
601
|
+
postcodeAliases: nPostcodeAlias,
|
|
602
|
+
ancestorRows: sidecar.ancestorRows + nLocalityAncestor,
|
|
603
|
+
ancestorPlaces: sidecar.ancestorPlaces + nLocalityScoped,
|
|
604
|
+
intervalPlaces: sidecar.intervalPlaces,
|
|
605
|
+
...roles,
|
|
606
|
+
...(importance ? { importanceScored: importance.matched, importanceFiltered: importance.refused } : {}),
|
|
607
|
+
}
|
|
608
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file Populations the gazetteer records at a fraction of their size, corrected against the record's own concordance.
|
|
6
|
+
*
|
|
7
|
+
* This file records corrections for review. The build must not rewrite populations from a
|
|
8
|
+
* same-name-parent ratio. The detector cannot distinguish a district's mis-recorded namesake
|
|
9
|
+
* city from a small village with the district name. Both places are real.
|
|
10
|
+
*
|
|
11
|
+
* Each entry identifies one row that a reviewer checked against a second source.
|
|
12
|
+
* The row's own `gn:id` must agree with the coordinates. The GeoNames record must identify the same place.
|
|
13
|
+
*
|
|
14
|
+
* The correction applies to the candidate artifact rather than the admin gazetteer.
|
|
15
|
+
* `place_population` in `admin-global-priority.db` still stores the WOF figure, so a reader going
|
|
16
|
+
* there sees WOF's value and a reader going to `candidate.db` sees the corroborated number. The
|
|
17
|
+
* admin database is a transcription of its source, so correcting it there would make the
|
|
18
|
+
* transcription disagree with what it transcribes.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* One corrected population, with what corroborates it.
|
|
23
|
+
*/
|
|
24
|
+
export interface PopulationCorrection {
|
|
25
|
+
/**
|
|
26
|
+
* The GeoNames id from the WOF record's own `concordances` row makes this a
|
|
27
|
+
* correction rather than a substitution.
|
|
28
|
+
*
|
|
29
|
+
* The two sources describe the same place according to WOF.
|
|
30
|
+
*/
|
|
31
|
+
geonamesID: string
|
|
32
|
+
population: number
|
|
33
|
+
/**
|
|
34
|
+
* What the gazetteer recorded, kept so a reader can see the size of the
|
|
35
|
+
* disagreement without opening the artifact.
|
|
36
|
+
*/
|
|
37
|
+
recorded: number
|
|
38
|
+
/**
|
|
39
|
+
* The place and the reviewer's reading.
|
|
40
|
+
*/
|
|
41
|
+
note: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* WOF id → the corrected population.
|
|
46
|
+
*
|
|
47
|
+
* One entry, because one row has been followed.
|
|
48
|
+
* A second correction requires the same review.
|
|
49
|
+
*
|
|
50
|
+
* Read the row's `gn:id` and confirm the coordinates agree.
|
|
51
|
+
* Then record the second source's value.
|
|
52
|
+
*/
|
|
53
|
+
export const POPULATION_CORRECTIONS: Readonly<Record<number, PopulationCorrection>> = {
|
|
54
|
+
102_030_887: {
|
|
55
|
+
geonamesID: "1278149",
|
|
56
|
+
population: 1_175_116,
|
|
57
|
+
recorded: 19_172,
|
|
58
|
+
note:
|
|
59
|
+
"Aurangabad (Chhatrapati Sambhaji Nagar), Maharashtra. The WOF record sits at 19.870 / 75.349 and GeoNames " +
|
|
60
|
+
"1278149 — the id that record's own concordance names — sits at 19.878 / 75.342, about 1 km apart, classed " +
|
|
61
|
+
"`PPLA2`. WOF's 19,172 against its parent district's 3,701,282 is the 193x ratio that surfaced it; the " +
|
|
62
|
+
"corroborated figure makes the city 32% of its district rather than 0.5% of it.",
|
|
63
|
+
},
|
|
64
|
+
}
|