@mailwoman/corpus 4.16.2 → 5.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/out/src/adapter.d.ts +23 -26
- package/out/src/adapter.d.ts.map +1 -1
- package/out/src/adapter.js +25 -28
- package/out/src/adapter.js.map +1 -1
- package/out/src/adapters/ban/adapter.d.ts.map +1 -1
- package/out/src/adapters/ban/adapter.js +10 -10
- package/out/src/adapters/ban/adapter.js.map +1 -1
- package/out/src/adapters/ban/street-decompose.d.ts +2 -2
- package/out/src/adapters/ban/street-decompose.d.ts.map +1 -1
- package/out/src/adapters/ban/street-decompose.js +2 -2
- package/out/src/adapters/ban/street-decompose.js.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.d.ts +2 -2
- package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.js +9 -9
- package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
- package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames/adapter.js +5 -5
- package/out/src/adapters/geonames/adapter.js.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.js +3 -3
- package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts +3 -3
- package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
- package/out/src/adapters/gnaf/adapter.js +11 -10
- package/out/src/adapters/gnaf/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/assemble.d.ts +4 -5
- package/out/src/adapters/gnaf/assemble.d.ts.map +1 -1
- package/out/src/adapters/gnaf/assemble.js +1 -1
- package/out/src/adapters/gnaf/assemble.js.map +1 -1
- package/out/src/adapters/index.d.ts +9 -10
- package/out/src/adapters/index.d.ts.map +1 -1
- package/out/src/adapters/index.js +13 -14
- package/out/src/adapters/index.js.map +1 -1
- package/out/src/adapters/openaddresses/adapter.d.ts +8 -10
- package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
- package/out/src/adapters/openaddresses/adapter.js +8 -8
- package/out/src/adapters/openaddresses/adapter.js.map +1 -1
- package/out/src/adapters/overture/adapter.d.ts.map +1 -1
- package/out/src/adapters/overture/adapter.js +2 -2
- package/out/src/adapters/overture/adapter.js.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.js +6 -6
- package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.js +6 -6
- package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.js +6 -6
- package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.js +7 -7
- package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.d.ts +9 -9
- package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.js +6 -6
- package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
- package/out/src/adapters/tiger/adapter.d.ts.map +1 -1
- package/out/src/adapters/tiger/adapter.js +2 -2
- package/out/src/adapters/tiger/adapter.js.map +1 -1
- package/out/src/adapters/tiger/street-decompose.d.ts +2 -2
- package/out/src/adapters/tiger/street-decompose.d.ts.map +1 -1
- package/out/src/adapters/tiger/street-decompose.js +2 -2
- package/out/src/adapters/tiger/street-decompose.js.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +15 -17
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.js +6 -6
- package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.js +5 -5
- package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts +2 -2
- package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.js +6 -6
- package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts +3 -3
- package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.js +7 -7
- package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +12 -12
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.d.ts +3 -3
- package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.js +6 -6
- package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
- package/out/src/adapters/wof-admin-json/adapter.d.ts +17 -19
- package/out/src/adapters/wof-admin-json/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-json/adapter.js +25 -28
- package/out/src/adapters/wof-admin-json/adapter.js.map +1 -1
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts +8 -8
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-postalcode-json/adapter.js +11 -11
- package/out/src/adapters/wof-postalcode-json/adapter.js.map +1 -1
- package/out/src/align.d.ts +14 -16
- package/out/src/align.d.ts.map +1 -1
- package/out/src/align.js +15 -16
- package/out/src/align.js.map +1 -1
- package/out/src/build.d.ts +13 -15
- package/out/src/build.d.ts.map +1 -1
- package/out/src/build.js +4 -5
- package/out/src/build.js.map +1 -1
- package/out/src/codex/us-fips-state.d.ts +6 -8
- package/out/src/codex/us-fips-state.d.ts.map +1 -1
- package/out/src/codex/us-fips-state.js +6 -8
- package/out/src/codex/us-fips-state.js.map +1 -1
- package/out/src/golden.d.ts.map +1 -1
- package/out/src/golden.js +1 -1
- package/out/src/golden.js.map +1 -1
- package/out/src/index.d.ts +1 -0
- package/out/src/index.d.ts.map +1 -1
- package/out/src/index.js +1 -0
- package/out/src/index.js.map +1 -1
- package/out/src/license.d.ts +5 -6
- package/out/src/license.d.ts.map +1 -1
- package/out/src/license.js +5 -6
- package/out/src/license.js.map +1 -1
- package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
- package/out/src/parquet-wrapper/reader.js.map +1 -1
- package/out/src/parquet-wrapper/writer.d.ts.map +1 -1
- package/out/src/parquet-wrapper/writer.js +2 -2
- package/out/src/parquet-wrapper/writer.js.map +1 -1
- package/out/src/parquet.d.ts +16 -18
- package/out/src/parquet.d.ts.map +1 -1
- package/out/src/parquet.js +22 -23
- package/out/src/parquet.js.map +1 -1
- package/out/src/runner.d.ts +10 -10
- package/out/src/runner.d.ts.map +1 -1
- package/out/src/runner.js +8 -8
- package/out/src/runner.js.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.d.ts +16 -0
- package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -0
- package/out/src/shard-recipes/anchor-absorption.js +73 -0
- package/out/src/shard-recipes/anchor-absorption.js.map +1 -0
- package/out/src/shard-recipes/boundary-stress.d.ts +16 -0
- package/out/src/shard-recipes/boundary-stress.d.ts.map +1 -0
- package/out/src/shard-recipes/boundary-stress.js +77 -0
- package/out/src/shard-recipes/boundary-stress.js.map +1 -0
- package/out/src/shard-recipes/country-balanced.d.ts +28 -0
- package/out/src/shard-recipes/country-balanced.d.ts.map +1 -0
- package/out/src/shard-recipes/country-balanced.js +370 -0
- package/out/src/shard-recipes/country-balanced.js.map +1 -0
- package/out/src/shard-recipes/fr-admin-split.d.ts +34 -0
- package/out/src/shard-recipes/fr-admin-split.d.ts.map +1 -0
- package/out/src/shard-recipes/fr-admin-split.js +175 -0
- package/out/src/shard-recipes/fr-admin-split.js.map +1 -0
- package/out/src/shard-recipes/fr-bare-street.d.ts +24 -0
- package/out/src/shard-recipes/fr-bare-street.d.ts.map +1 -0
- package/out/src/shard-recipes/fr-bare-street.js +76 -0
- package/out/src/shard-recipes/fr-bare-street.js.map +1 -0
- package/out/src/shard-recipes/fr-order.d.ts +34 -0
- package/out/src/shard-recipes/fr-order.d.ts.map +1 -0
- package/out/src/shard-recipes/fr-order.js +238 -0
- package/out/src/shard-recipes/fr-order.js.map +1 -0
- package/out/src/shard-recipes/german.d.ts +19 -0
- package/out/src/shard-recipes/german.d.ts.map +1 -0
- package/out/src/shard-recipes/german.js +170 -0
- package/out/src/shard-recipes/german.js.map +1 -0
- package/out/src/shard-recipes/house-venue.d.ts +14 -0
- package/out/src/shard-recipes/house-venue.d.ts.map +1 -0
- package/out/src/shard-recipes/house-venue.js +66 -0
- package/out/src/shard-recipes/house-venue.js.map +1 -0
- package/out/src/shard-recipes/index.d.ts +18 -0
- package/out/src/shard-recipes/index.d.ts.map +1 -0
- package/out/src/shard-recipes/index.js +58 -0
- package/out/src/shard-recipes/index.js.map +1 -0
- package/out/src/shard-recipes/intersection.d.ts +38 -0
- package/out/src/shard-recipes/intersection.d.ts.map +1 -0
- package/out/src/shard-recipes/intersection.js +473 -0
- package/out/src/shard-recipes/intersection.js.map +1 -0
- package/out/src/shard-recipes/locale.d.ts +19 -0
- package/out/src/shard-recipes/locale.d.ts.map +1 -0
- package/out/src/shard-recipes/locale.js +257 -0
- package/out/src/shard-recipes/locale.js.map +1 -0
- package/out/src/shard-recipes/no-street.d.ts +14 -0
- package/out/src/shard-recipes/no-street.d.ts.map +1 -0
- package/out/src/shard-recipes/no-street.js +66 -0
- package/out/src/shard-recipes/no-street.js.map +1 -0
- package/out/src/shard-recipes/po-box-cedex.d.ts +34 -0
- package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -0
- package/out/src/shard-recipes/po-box-cedex.js +686 -0
- package/out/src/shard-recipes/po-box-cedex.js.map +1 -0
- package/out/src/shard-recipes/po-box.d.ts +13 -0
- package/out/src/shard-recipes/po-box.d.ts.map +1 -0
- package/out/src/shard-recipes/po-box.js +93 -0
- package/out/src/shard-recipes/po-box.js.map +1 -0
- package/out/src/shard-recipes/scaffold.d.ts +104 -0
- package/out/src/shard-recipes/scaffold.d.ts.map +1 -0
- package/out/src/shard-recipes/scaffold.js +76 -0
- package/out/src/shard-recipes/scaffold.js.map +1 -0
- package/out/src/shard-recipes/street-affix.d.ts +31 -0
- package/out/src/shard-recipes/street-affix.d.ts.map +1 -0
- package/out/src/shard-recipes/street-affix.js +408 -0
- package/out/src/shard-recipes/street-affix.js.map +1 -0
- package/out/src/shard-recipes/street-bare.d.ts +21 -0
- package/out/src/shard-recipes/street-bare.d.ts.map +1 -0
- package/out/src/shard-recipes/street-bare.js +82 -0
- package/out/src/shard-recipes/street-bare.js.map +1 -0
- package/out/src/shard-recipes/street.d.ts +11 -0
- package/out/src/shard-recipes/street.d.ts.map +1 -0
- package/out/src/shard-recipes/street.js +63 -0
- package/out/src/shard-recipes/street.js.map +1 -0
- package/out/src/shard-recipes/unit.d.ts +25 -0
- package/out/src/shard-recipes/unit.d.ts.map +1 -0
- package/out/src/shard-recipes/unit.js +255 -0
- package/out/src/shard-recipes/unit.js.map +1 -0
- package/out/src/split.d.ts +23 -29
- package/out/src/split.d.ts.map +1 -1
- package/out/src/split.js +22 -29
- package/out/src/split.js.map +1 -1
- package/out/src/synthesize-anchor-absorption.d.ts +2 -3
- package/out/src/synthesize-anchor-absorption.d.ts.map +1 -1
- package/out/src/synthesize-anchor-absorption.js +2 -2
- package/out/src/synthesize-anchor-absorption.js.map +1 -1
- package/out/src/synthesize-boundary-stress.d.ts +3 -4
- package/out/src/synthesize-boundary-stress.d.ts.map +1 -1
- package/out/src/synthesize-boundary-stress.js +3 -4
- package/out/src/synthesize-boundary-stress.js.map +1 -1
- package/out/src/synthesize-german.d.ts +15 -19
- package/out/src/synthesize-german.d.ts.map +1 -1
- package/out/src/synthesize-german.js +14 -17
- package/out/src/synthesize-german.js.map +1 -1
- package/out/src/synthesize-house-venue.d.ts +2 -3
- package/out/src/synthesize-house-venue.d.ts.map +1 -1
- package/out/src/synthesize-house-venue.js +2 -3
- package/out/src/synthesize-house-venue.js.map +1 -1
- package/out/src/synthesize-intersection.d.ts +2 -2
- package/out/src/synthesize-intersection.d.ts.map +1 -1
- package/out/src/synthesize-intersection.js +4 -4
- package/out/src/synthesize-intersection.js.map +1 -1
- package/out/src/synthesize-no-street.d.ts +5 -5
- package/out/src/synthesize-no-street.d.ts.map +1 -1
- package/out/src/synthesize-no-street.js +27 -23
- package/out/src/synthesize-no-street.js.map +1 -1
- package/out/src/synthesize-po-box.d.ts +15 -17
- package/out/src/synthesize-po-box.d.ts.map +1 -1
- package/out/src/synthesize-po-box.js +27 -27
- package/out/src/synthesize-po-box.js.map +1 -1
- package/out/src/synthesize-street.d.ts +8 -9
- package/out/src/synthesize-street.d.ts.map +1 -1
- package/out/src/synthesize-street.js +3 -3
- package/out/src/synthesize-street.js.map +1 -1
- package/out/src/synthesize.d.ts +57 -66
- package/out/src/synthesize.d.ts.map +1 -1
- package/out/src/synthesize.js +56 -65
- package/out/src/synthesize.js.map +1 -1
- package/out/src/tokenize.d.ts +5 -6
- package/out/src/tokenize.d.ts.map +1 -1
- package/out/src/tokenize.js +5 -6
- package/out/src/tokenize.js.map +1 -1
- package/out/src/types.d.ts +49 -51
- package/out/src/types.d.ts.map +1 -1
- package/out/src/wof-json.d.ts +32 -34
- package/out/src/wof-json.d.ts.map +1 -1
- package/out/src/wof-json.js +23 -25
- package/out/src/wof-json.js.map +1 -1
- package/package.json +14 -14
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `country-balanced` shard recipe — the BALANCED, MODEL-FIRST country-coverage shard (#464). The
|
|
7
|
+
* shipped model is STARVED on `country` (P=R=F1=0 on the homograph eval), so this fills the void
|
|
8
|
+
* the way the `unit` shard did, but built to AVOID over-firing "trailing token ⇒ country". Three
|
|
9
|
+
* ingredients, ported faithfully from scripts/build-country-shard-balanced.mjs:
|
|
10
|
+
*
|
|
11
|
+
* 1. Breadth/recall — real OA skeletons (US/DE/FR/IT/NL) with a country token in a varied surface form
|
|
12
|
+
* from `@mailwoman/codex/country` (canonical / endonym / ISO code), + ~30% country-ABSENT
|
|
13
|
+
* negatives (teach O-emission, the precision floor).
|
|
14
|
+
* 2. Homograph CONTRAST pairs — each true country-name homograph (Georgia, Jordan, Lebanon, Mexico,
|
|
15
|
+
* Peru, Turkey) rendered BOTH ways: as `country` (foreign-city context) AND as the US
|
|
16
|
+
* `region`/`locality` (US-ZIP context). Teaches that the label is CONTEXTUAL, not
|
|
17
|
+
* positional.
|
|
18
|
+
* 3. Code-as-region negatives — 2-letter codes that are both a US state abbrev and an ISO country code
|
|
19
|
+
* (CA/GA/IN/MA/PA/AL) in US-ZIP context → must read as `region`, never `country`.
|
|
20
|
+
*
|
|
21
|
+
* `--golden` emits a held-out synthetic val over the VT (US) + Berlin (DE) holdouts. This is a
|
|
22
|
+
* `generate`-mode recipe that still reads REAL tuples off disk — `--count` bounds the OUTPUT, not
|
|
23
|
+
* the input. The passed `random` (the framework LCG) is consumed in the exact call order the
|
|
24
|
+
* legacy script used.
|
|
25
|
+
*/
|
|
26
|
+
import { type ShardRecipe } from "./scaffold.js";
|
|
27
|
+
export declare const countryBalancedRecipe: ShardRecipe;
|
|
28
|
+
//# sourceMappingURL=country-balanced.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"country-balanced.d.ts","sourceRoot":"","sources":["../../../src/shard-recipes/country-balanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAUH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AA+UhE,eAAO,MAAM,qBAAqB,EAAE,WAwFnC,CAAA"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `country-balanced` shard recipe — the BALANCED, MODEL-FIRST country-coverage shard (#464). The
|
|
7
|
+
* shipped model is STARVED on `country` (P=R=F1=0 on the homograph eval), so this fills the void
|
|
8
|
+
* the way the `unit` shard did, but built to AVOID over-firing "trailing token ⇒ country". Three
|
|
9
|
+
* ingredients, ported faithfully from scripts/build-country-shard-balanced.mjs:
|
|
10
|
+
*
|
|
11
|
+
* 1. Breadth/recall — real OA skeletons (US/DE/FR/IT/NL) with a country token in a varied surface form
|
|
12
|
+
* from `@mailwoman/codex/country` (canonical / endonym / ISO code), + ~30% country-ABSENT
|
|
13
|
+
* negatives (teach O-emission, the precision floor).
|
|
14
|
+
* 2. Homograph CONTRAST pairs — each true country-name homograph (Georgia, Jordan, Lebanon, Mexico,
|
|
15
|
+
* Peru, Turkey) rendered BOTH ways: as `country` (foreign-city context) AND as the US
|
|
16
|
+
* `region`/`locality` (US-ZIP context). Teaches that the label is CONTEXTUAL, not
|
|
17
|
+
* positional.
|
|
18
|
+
* 3. Code-as-region negatives — 2-letter codes that are both a US state abbrev and an ISO country code
|
|
19
|
+
* (CA/GA/IN/MA/PA/AL) in US-ZIP context → must read as `region`, never `country`.
|
|
20
|
+
*
|
|
21
|
+
* `--golden` emits a held-out synthetic val over the VT (US) + Berlin (DE) holdouts. This is a
|
|
22
|
+
* `generate`-mode recipe that still reads REAL tuples off disk — `--count` bounds the OUTPUT, not
|
|
23
|
+
* the input. The passed `random` (the framework LCG) is consumed in the exact call order the
|
|
24
|
+
* legacy script used.
|
|
25
|
+
*/
|
|
26
|
+
import { spawnSync } from "node:child_process";
|
|
27
|
+
import { COUNTRY_SURFACE_FORMS, CountryNames } from "@mailwoman/codex/country";
|
|
28
|
+
import { stableSourceID } from "../adapter.js";
|
|
29
|
+
import { alignRow } from "../align.js";
|
|
30
|
+
import { makeMulberry32 } from "./scaffold.js";
|
|
31
|
+
// v2: the country TOKEN is decoupled from the skeleton's locale and drawn from a BROAD pool — every
|
|
32
|
+
// ISO canonical name + every curated surface form (endonyms/abbrevs). Surface forms are over-weighted
|
|
33
|
+
// so endonyms/abbrevs ("Deutschland","USA","NL") get strong signal.
|
|
34
|
+
const COUNTRY_FORM_POOL = (() => {
|
|
35
|
+
const surface = Object.values(COUNTRY_SURFACE_FORMS).flat(); // endonyms + abbrevs + canonical (curated)
|
|
36
|
+
const names = [...CountryNames];
|
|
37
|
+
// all ~249 ISO canonical English names (breadth)
|
|
38
|
+
return { surface, names };
|
|
39
|
+
})();
|
|
40
|
+
const COUNTRY_ABSENT_PROB = 0.3; // negatives: rows with NO country token → teach golden precision
|
|
41
|
+
// Multi-locale OA sources. region = implied admin where the extract is single-region (US states, DE
|
|
42
|
+
// Saxony); countrywide extracts (FR/IT/NL) read region from the CSV when present.
|
|
43
|
+
const SOURCES = [
|
|
44
|
+
{ zip: "/tmp/oa-cache/us__ia__statewide.zip", csv: "us/ia/statewide.csv", iso2: "US", region: "IA", order: "us" },
|
|
45
|
+
{ zip: "/tmp/oa-cache/us__il__cook.zip", csv: "us/il/cook.csv", iso2: "US", region: "IL", order: "us" },
|
|
46
|
+
{ zip: "/tmp/oa-cache/us__mt__statewide.zip", csv: "us/mt/statewide.csv", iso2: "US", region: "MT", order: "us" },
|
|
47
|
+
{ zip: "/tmp/oa-cache/us__sd__statewide.zip", csv: "us/sd/statewide.csv", iso2: "US", region: "SD", order: "us" },
|
|
48
|
+
{ zip: "/tmp/oa-cache/de__sn__statewide.zip", csv: "de/sn/statewide.csv", iso2: "DE", region: "", order: "eu" },
|
|
49
|
+
{ zip: "/tmp/oa-cache/fr__countrywide.zip", csv: "fr/countrywide.csv", iso2: "FR", region: "", order: "fr" },
|
|
50
|
+
// ES uses the Spanish IGN schema, not the OA standard columns — skipped here (codex still recognizes
|
|
51
|
+
// "España"/"Spain"). A dedicated IGN adapter is a follow-up.
|
|
52
|
+
{ zip: "/tmp/oa-cache/it__countrywide.zip", csv: "it/countrywide.csv", iso2: "IT", region: "", order: "eu" },
|
|
53
|
+
{ zip: "/tmp/oa-cache/nl__countrywide.zip", csv: "nl/countrywide.csv", iso2: "NL", region: "", order: "eu" },
|
|
54
|
+
];
|
|
55
|
+
// Held-out for --golden: Vermont (US holdout) + Berlin (DE holdout) — geographic split, never trained.
|
|
56
|
+
const EVAL_SOURCES = [
|
|
57
|
+
{ zip: "/tmp/oa-cache/us__vt__statewide.zip", csv: "us/vt/statewide.csv", iso2: "US", region: "VT", order: "us" },
|
|
58
|
+
{ zip: "/tmp/oa-cache/de__berlin.zip", csv: "de/berlin.csv", iso2: "DE", region: "", order: "eu" },
|
|
59
|
+
];
|
|
60
|
+
function splitCSV(line) {
|
|
61
|
+
const out = [];
|
|
62
|
+
let cur = "", inQ = false;
|
|
63
|
+
for (let i = 0; i < line.length; i++) {
|
|
64
|
+
const c = line[i];
|
|
65
|
+
if (inQ) {
|
|
66
|
+
if (c === '"') {
|
|
67
|
+
if (line[i + 1] === '"') {
|
|
68
|
+
cur += '"';
|
|
69
|
+
i++;
|
|
70
|
+
}
|
|
71
|
+
else
|
|
72
|
+
inQ = false;
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
cur += c;
|
|
76
|
+
}
|
|
77
|
+
else if (c === '"')
|
|
78
|
+
inQ = true;
|
|
79
|
+
else if (c === ",") {
|
|
80
|
+
out.push(cur);
|
|
81
|
+
cur = "";
|
|
82
|
+
}
|
|
83
|
+
else
|
|
84
|
+
cur += c;
|
|
85
|
+
}
|
|
86
|
+
out.push(cur);
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
function readTuples(source, limit) {
|
|
90
|
+
// countrywide extracts (FR/IT/NL) are GB-scale — cap the bytes with `head` (read ~8 lines per wanted
|
|
91
|
+
// tuple to survive dedup/skips) so the toString stays under V8's string limit.
|
|
92
|
+
const maxLines = Math.max(limit * 8, 20000) + 1;
|
|
93
|
+
const r = spawnSync("bash", ["-c", `unzip -p "${source.zip}" "${source.csv}" | head -n ${maxLines}`], {
|
|
94
|
+
maxBuffer: 1024 * 1024 * 1024,
|
|
95
|
+
encoding: "buffer",
|
|
96
|
+
});
|
|
97
|
+
if (r.status !== 0) {
|
|
98
|
+
console.error(` WARN: unzip failed for ${source.zip} (status ${r.status})`);
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const lines = r.stdout.toString("utf8").split(/\r?\n/);
|
|
102
|
+
if (lines.length < 2)
|
|
103
|
+
return [];
|
|
104
|
+
const header = splitCSV(lines[0]).map((h) => h.trim().toLowerCase());
|
|
105
|
+
const idx = (n) => header.indexOf(n);
|
|
106
|
+
const iNum = idx("number"), iStreet = idx("street"), iCity = idx("city"), iRegion = idx("region"), iPost = idx("postcode");
|
|
107
|
+
const get = (cells, i) => (i >= 0 && i < cells.length ? (cells[i] ?? "").trim() : "");
|
|
108
|
+
const tuples = [];
|
|
109
|
+
const seen = new Set();
|
|
110
|
+
for (let li = 1; li < lines.length && tuples.length < limit; li++) {
|
|
111
|
+
if (!lines[li])
|
|
112
|
+
continue;
|
|
113
|
+
const cells = splitCSV(lines[li]);
|
|
114
|
+
const street = get(cells, iStreet), locality = get(cells, iCity), house_number = get(cells, iNum);
|
|
115
|
+
if (!street || !locality || !house_number)
|
|
116
|
+
continue;
|
|
117
|
+
const key = `${house_number}|${street}|${locality}`.toLowerCase();
|
|
118
|
+
if (seen.has(key))
|
|
119
|
+
continue;
|
|
120
|
+
seen.add(key);
|
|
121
|
+
tuples.push({
|
|
122
|
+
house_number,
|
|
123
|
+
street,
|
|
124
|
+
locality,
|
|
125
|
+
region: get(cells, iRegion) || source.region,
|
|
126
|
+
postcode: get(cells, iPost),
|
|
127
|
+
iso2: source.iso2,
|
|
128
|
+
order: source.order,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return tuples;
|
|
132
|
+
}
|
|
133
|
+
/** Pick a country token from the BROAD pool, or null (a country-absent negative). v2. */
|
|
134
|
+
function pickCountry(random) {
|
|
135
|
+
if (random() < COUNTRY_ABSENT_PROB)
|
|
136
|
+
return null; // negative — teaches "trailing token != always country"
|
|
137
|
+
// 60% curated surface forms (endonym/abbrev variety), 40% broad ISO canonical names (coverage).
|
|
138
|
+
const pool = random() < 0.6 ? COUNTRY_FORM_POOL.surface : COUNTRY_FORM_POOL.names;
|
|
139
|
+
return pool[Math.floor(random() * pool.length)];
|
|
140
|
+
}
|
|
141
|
+
/** Render the address body in native-ish order. `country` null → a country-ABSENT negative row. */
|
|
142
|
+
function renderCountry(random, t, country) {
|
|
143
|
+
const { house_number: hn, street, locality: loc, region: reg, postcode: pc, order } = t;
|
|
144
|
+
const components = { house_number: hn, street, locality: loc };
|
|
145
|
+
if (reg)
|
|
146
|
+
components.region = reg;
|
|
147
|
+
if (pc)
|
|
148
|
+
components.postcode = pc;
|
|
149
|
+
let body;
|
|
150
|
+
if (order === "us") {
|
|
151
|
+
const regPc = [reg, pc].filter(Boolean).join(" ");
|
|
152
|
+
body = `${hn} ${street}, ${loc}${regPc ? ", " + regPc : ""}`;
|
|
153
|
+
}
|
|
154
|
+
else if (order === "fr") {
|
|
155
|
+
// French is NUMBER-street, postcode-city: "84 Route de la Fontaine, 75008 Paris".
|
|
156
|
+
body = `${hn} ${street}, ${[pc, loc].filter(Boolean).join(" ")}`;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// DE/IT/NL: street-number, postcode-city: "Pariser Platz 1, 10117 Berlin".
|
|
160
|
+
const pcCity = [pc, loc].filter(Boolean).join(" ");
|
|
161
|
+
body = `${street} ${hn}, ${pcCity}`;
|
|
162
|
+
}
|
|
163
|
+
if (!country) {
|
|
164
|
+
// Negative: a normal address, NO country token/component. Teaches that a trailing region/city/
|
|
165
|
+
// postcode is NOT a country (counters the v1 golden over-firing).
|
|
166
|
+
return { fmt: "negative", raw: body, components };
|
|
167
|
+
}
|
|
168
|
+
const withC = { ...components, country };
|
|
169
|
+
const r = random();
|
|
170
|
+
if (r < 0.8)
|
|
171
|
+
return { fmt: "full", raw: `${body}, ${country}`, components: withC };
|
|
172
|
+
if (r < 0.92)
|
|
173
|
+
return { fmt: "full-nl", raw: `${body}\n${country}`, components: withC };
|
|
174
|
+
const bareBody = order === "us" || order === "fr" ? `${hn} ${street}, ${loc}` : `${street} ${hn}, ${loc}`;
|
|
175
|
+
return {
|
|
176
|
+
fmt: "bare",
|
|
177
|
+
raw: `${bareBody}, ${country}`,
|
|
178
|
+
components: { house_number: hn, street, locality: loc, country },
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const HOMOGRAPHS = [
|
|
182
|
+
{
|
|
183
|
+
surface: "Georgia",
|
|
184
|
+
iso2: "GE",
|
|
185
|
+
cities: ["Tbilisi", "Batumi", "Kutaisi", "Rustavi"],
|
|
186
|
+
us: { role: "region", locality: "Atlanta", region: "Georgia", postcodes: ["30309", "31401", "30601", "31201"] },
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
surface: "Jordan",
|
|
190
|
+
iso2: "JO",
|
|
191
|
+
cities: ["Amman", "Irbid", "Zarqa", "Aqaba"],
|
|
192
|
+
us: { role: "locality", locality: "Jordan", region: "MN", postcodes: ["55352"] },
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
surface: "Lebanon",
|
|
196
|
+
iso2: "LB",
|
|
197
|
+
cities: ["Beirut", "Tripoli", "Sidon", "Byblos"],
|
|
198
|
+
us: { role: "locality", locality: "Lebanon", region: "TN", postcodes: ["37087", "03766", "17042", "45036"] },
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
surface: "Mexico",
|
|
202
|
+
iso2: "MX",
|
|
203
|
+
cities: ["Guadalajara", "Monterrey", "Puebla", "Oaxaca"],
|
|
204
|
+
us: { role: "locality", locality: "Mexico", region: "MO", postcodes: ["65265"] },
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
surface: "Peru",
|
|
208
|
+
iso2: "PE",
|
|
209
|
+
cities: ["Cusco", "Arequipa", "Trujillo", "Iquitos"],
|
|
210
|
+
us: { role: "locality", locality: "Peru", region: "IL", postcodes: ["61354", "46970"] },
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
surface: "Turkey",
|
|
214
|
+
iso2: "TR",
|
|
215
|
+
cities: ["Ankara", "Izmir", "Bursa", "Antalya"],
|
|
216
|
+
us: { role: "locality", locality: "Turkey", region: "TX", postcodes: ["79261", "28393"] },
|
|
217
|
+
},
|
|
218
|
+
];
|
|
219
|
+
const ABBREV_REGIONS = [
|
|
220
|
+
{ code: "CA", localities: ["Los Angeles", "Sacramento", "San Diego"], postcodes: ["90012", "95814", "92101"] }, // California / Canada
|
|
221
|
+
{ code: "GA", localities: ["Atlanta", "Savannah", "Macon"], postcodes: ["30309", "31401", "31201"] }, // Georgia(US) / Georgia
|
|
222
|
+
{ code: "IN", localities: ["Indianapolis", "Fort Wayne"], postcodes: ["46204", "46802"] }, // Indiana / India
|
|
223
|
+
{ code: "MA", localities: ["Boston", "Worcester"], postcodes: ["02108", "01608"] }, // Massachusetts / Morocco
|
|
224
|
+
{ code: "PA", localities: ["Philadelphia", "Pittsburgh"], postcodes: ["19103", "15222"] }, // Pennsylvania / Panama
|
|
225
|
+
{ code: "AL", localities: ["Birmingham", "Montgomery"], postcodes: ["35203", "36104"] }, // Alabama / Albania
|
|
226
|
+
];
|
|
227
|
+
const STREET_POOL = [
|
|
228
|
+
"Main Street",
|
|
229
|
+
"Oak Avenue",
|
|
230
|
+
"Park Road",
|
|
231
|
+
"Elm Street",
|
|
232
|
+
"Hill Road",
|
|
233
|
+
"Market Street",
|
|
234
|
+
"Church Street",
|
|
235
|
+
"King Street",
|
|
236
|
+
"2nd Avenue",
|
|
237
|
+
"Maple Drive",
|
|
238
|
+
];
|
|
239
|
+
const pick = (random, arr) => arr[Math.floor(random() * arr.length)];
|
|
240
|
+
const houseNo = (random) => String(1 + Math.floor(random() * 998));
|
|
241
|
+
/**
|
|
242
|
+
* A homograph CONTRAST row: ~half render the surface as `country` (foreign city), half as the US `region`/`locality`
|
|
243
|
+
* (US ZIP, NO country). Returns iso2 for provenance.
|
|
244
|
+
*/
|
|
245
|
+
function renderHomograph(random) {
|
|
246
|
+
const h = pick(random, HOMOGRAPHS);
|
|
247
|
+
const hn = houseNo(random), street = pick(random, STREET_POOL);
|
|
248
|
+
if (random() < 0.5) {
|
|
249
|
+
const city = pick(random, h.cities);
|
|
250
|
+
const withStreet = random() < 0.6;
|
|
251
|
+
const raw = withStreet ? `${hn} ${street}, ${city}, ${h.surface}` : `${city}, ${h.surface}`;
|
|
252
|
+
const components = withStreet
|
|
253
|
+
? { house_number: hn, street, locality: city, country: h.surface }
|
|
254
|
+
: { locality: city, country: h.surface };
|
|
255
|
+
return { fmt: "homograph-country", raw, components, iso2: h.iso2 };
|
|
256
|
+
}
|
|
257
|
+
const pc = pick(random, h.us.postcodes);
|
|
258
|
+
if (h.us.role === "region") {
|
|
259
|
+
// surface is the US STATE: "123 Oak Ave, Atlanta, Georgia 30309" → region, no country
|
|
260
|
+
return {
|
|
261
|
+
fmt: "homograph-us-region",
|
|
262
|
+
raw: `${hn} ${street}, ${h.us.locality}, ${h.surface} ${pc}`,
|
|
263
|
+
components: { house_number: hn, street, locality: h.us.locality, region: h.surface, postcode: pc },
|
|
264
|
+
iso2: "US",
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
// surface is the US CITY: "123 Oak Ave, Lebanon, TN 37087" → locality, no country
|
|
268
|
+
return {
|
|
269
|
+
fmt: "homograph-us-locality",
|
|
270
|
+
raw: `${hn} ${street}, ${h.surface}, ${h.us.region} ${pc}`,
|
|
271
|
+
components: { house_number: hn, street, locality: h.surface, region: h.us.region, postcode: pc },
|
|
272
|
+
iso2: "US",
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/** An abbrev-as-region negative: "123 Main St, Los Angeles, CA 90012" → region CA, NO country. */
|
|
276
|
+
function renderAbbrevRegion(random) {
|
|
277
|
+
const a = pick(random, ABBREV_REGIONS);
|
|
278
|
+
const hn = houseNo(random), street = pick(random, STREET_POOL), locality = pick(random, a.localities), postcode = pick(random, a.postcodes);
|
|
279
|
+
return {
|
|
280
|
+
fmt: "abbrev-region",
|
|
281
|
+
raw: `${hn} ${street}, ${locality}, ${a.code} ${postcode}`,
|
|
282
|
+
components: { house_number: hn, street, locality, region: a.code, postcode },
|
|
283
|
+
iso2: "US",
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const HOMOGRAPH_FRAC = 0.22; // share of rows that are homograph contrast pairs
|
|
287
|
+
const ABBREV_FRAC = 0.08; // share that are code-as-region negatives (cumulative with HOMOGRAPH_FRAC)
|
|
288
|
+
export const countryBalancedRecipe = {
|
|
289
|
+
name: "country-balanced",
|
|
290
|
+
description: "Balanced model-first country rows (#464): OA skeletons + ISO surface forms + homograph contrast pairs",
|
|
291
|
+
mode: "generate",
|
|
292
|
+
options: [{ flag: "--golden", description: "Emit the held-out VT+Berlin eval slice" }],
|
|
293
|
+
async run(opts, write) {
|
|
294
|
+
if (opts.count == null)
|
|
295
|
+
throw new Error("country-balanced recipe requires --count <N>");
|
|
296
|
+
const count = opts.count;
|
|
297
|
+
// Legacy build-country-shard-balanced.mjs seeded mulberry32 with the raw seed: `const random = mulberry32(opts.seed)`.
|
|
298
|
+
const random = makeMulberry32(opts.seed);
|
|
299
|
+
const source = opts.sourceName ?? "synth-country";
|
|
300
|
+
const sources = opts.golden ? EVAL_SOURCES : SOURCES;
|
|
301
|
+
const perSource = Math.ceil((count * 3) / sources.length); // over-read; balance locales
|
|
302
|
+
const pool = [];
|
|
303
|
+
for (const s of sources) {
|
|
304
|
+
const t = readTuples(s, perSource);
|
|
305
|
+
console.error(` ${s.csv} (${s.iso2}): ${t.length} tuples`);
|
|
306
|
+
for (const x of t)
|
|
307
|
+
pool.push(x);
|
|
308
|
+
}
|
|
309
|
+
if (pool.length === 0) {
|
|
310
|
+
throw new Error("No tuples — are the cached OA zips present in /tmp/oa-cache?");
|
|
311
|
+
}
|
|
312
|
+
let emitted = 0;
|
|
313
|
+
let skipped = 0;
|
|
314
|
+
let guard = 0;
|
|
315
|
+
const N = pool.length;
|
|
316
|
+
while (emitted < count && guard++ < count * 8) {
|
|
317
|
+
// Mix three row types: homograph contrast (the distinction), code-as-region negatives, and the
|
|
318
|
+
// breadth/recall main path (random ISO form on an OA skeleton, ~30% country-absent).
|
|
319
|
+
const roll = random();
|
|
320
|
+
let rendered;
|
|
321
|
+
let rowISO2;
|
|
322
|
+
if (roll < HOMOGRAPH_FRAC) {
|
|
323
|
+
const h = renderHomograph(random);
|
|
324
|
+
rendered = h;
|
|
325
|
+
rowISO2 = h.iso2;
|
|
326
|
+
}
|
|
327
|
+
else if (roll < HOMOGRAPH_FRAC + ABBREV_FRAC) {
|
|
328
|
+
const a = renderAbbrevRegion(random);
|
|
329
|
+
rendered = a;
|
|
330
|
+
rowISO2 = a.iso2;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
const t = pool[Math.floor(random() * N)];
|
|
334
|
+
const country = pickCountry(random); // may be null → a country-absent negative row
|
|
335
|
+
rendered = renderCountry(random, t, country);
|
|
336
|
+
rowISO2 = t.iso2;
|
|
337
|
+
if (country && !rendered.raw.includes(country)) {
|
|
338
|
+
skipped++;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const { raw, components } = rendered;
|
|
343
|
+
const localeTag = rowISO2 === "US" ? "en-US" : `${rowISO2.toLowerCase()}-${rowISO2}`;
|
|
344
|
+
if (opts.golden) {
|
|
345
|
+
write(JSON.stringify({ raw, components, country: rowISO2 }) + "\n");
|
|
346
|
+
emitted++;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const canonical = {
|
|
350
|
+
raw,
|
|
351
|
+
components,
|
|
352
|
+
country: rowISO2,
|
|
353
|
+
locale: localeTag,
|
|
354
|
+
source,
|
|
355
|
+
source_id: stableSourceID(source, components),
|
|
356
|
+
corpus_version: "0.4.0",
|
|
357
|
+
license: "OpenAddresses multi-locale skeletons + injected ISO-3166 country surface forms (codex)",
|
|
358
|
+
};
|
|
359
|
+
const aligned = alignRow(canonical);
|
|
360
|
+
if (aligned.kind !== "labeled" || !aligned.row) {
|
|
361
|
+
skipped++;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
write(JSON.stringify({ ...aligned.row, synth_method: "country", synth_base_id: null }) + "\n");
|
|
365
|
+
emitted++;
|
|
366
|
+
}
|
|
367
|
+
return { emitted, skipped };
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
//# sourceMappingURL=country-balanced.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"country-balanced.js","sourceRoot":"","sources":["../../../src/shard-recipes/country-balanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAG9E,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,OAAO,EAAE,cAAc,EAAoB,MAAM,eAAe,CAAA;AAEhE,oGAAoG;AACpG,sGAAsG;AACtG,oEAAoE;AACpE,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,CAAA,CAAC,2CAA2C;IACvG,MAAM,KAAK,GAAG,CAAC,GAAG,YAAY,CAAC,CAAA;IAE/B,iDAAiD;IACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AAC1B,CAAC,CAAC,EAAE,CAAA;AACJ,MAAM,mBAAmB,GAAG,GAAG,CAAA,CAAC,iEAAiE;AAWjG,oGAAoG;AACpG,kFAAkF;AAClF,MAAM,OAAO,GAA6B;IACzC,EAAE,GAAG,EAAE,qCAAqC,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACjH,EAAE,GAAG,EAAE,gCAAgC,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACvG,EAAE,GAAG,EAAE,qCAAqC,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACjH,EAAE,GAAG,EAAE,qCAAqC,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACjH,EAAE,GAAG,EAAE,qCAAqC,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;IAC/G,EAAE,GAAG,EAAE,mCAAmC,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;IAC5G,qGAAqG;IACrG,6DAA6D;IAC7D,EAAE,GAAG,EAAE,mCAAmC,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;IAC5G,EAAE,GAAG,EAAE,mCAAmC,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;CAC5G,CAAA;AACD,uGAAuG;AACvG,MAAM,YAAY,GAA6B;IAC9C,EAAE,GAAG,EAAE,qCAAqC,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACjH,EAAE,GAAG,EAAE,8BAA8B,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;CAClG,CAAA;AAaD,SAAS,QAAQ,CAAC,IAAY;IAC7B,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,IAAI,GAAG,GAAG,EAAE,EACX,GAAG,GAAG,KAAK,CAAA;IAEZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QAEjB,IAAI,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;gBACf,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACzB,GAAG,IAAI,GAAG,CAAA;oBACV,CAAC,EAAE,CAAA;gBACJ,CAAC;;oBAAM,GAAG,GAAG,KAAK,CAAA;YACnB,CAAC;;gBAAM,GAAG,IAAI,CAAC,CAAA;QAChB,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG;YAAE,GAAG,GAAG,IAAI,CAAA;aAC3B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACb,GAAG,GAAG,EAAE,CAAA;QACT,CAAC;;YAAM,GAAG,IAAI,CAAC,CAAA;IAChB,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAEb,OAAO,GAAG,CAAA;AACX,CAAC;AAED,SAAS,UAAU,CAAC,MAAqB,EAAE,KAAa;IACvD,qGAAqG;IACrG,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;IAC/C,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,eAAe,QAAQ,EAAE,CAAC,EAAE;QACrG,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;QAC7B,QAAQ,EAAE,QAAQ;KAClB,CAAC,CAAA;IAEF,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,4BAA4B,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;QAE5E,OAAO,EAAE,CAAA;IACV,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEtD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAA;IAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;IACrE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACpD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,EACzB,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,EACvB,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,EACnB,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,EACvB,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,CAAA;IACxB,MAAM,GAAG,GAAG,CAAC,KAAe,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC/G,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAE9B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;QACnE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,SAAQ;QACxB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAE,CAAC,CAAA;QAClC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,EACjC,QAAQ,GAAG,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAC5B,YAAY,GAAG,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAEhC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY;YAAE,SAAQ;QACnD,MAAM,GAAG,GAAG,GAAG,YAAY,IAAI,MAAM,IAAI,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAA;QAEjE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAQ;QAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACb,MAAM,CAAC,IAAI,CAAC;YACX,YAAY;YACZ,MAAM;YACN,QAAQ;YACR,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,MAAM;YAC5C,QAAQ,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;YAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,MAAM,CAAC,KAAK;SACnB,CAAC,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACd,CAAC;AAED,yFAAyF;AACzF,SAAS,WAAW,CAAC,MAAoB;IACxC,IAAI,MAAM,EAAE,GAAG,mBAAmB;QAAE,OAAO,IAAI,CAAA,CAAC,wDAAwD;IACxG,gGAAgG;IAChG,MAAM,IAAI,GAAG,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAA;IAEjF,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAE,CAAA;AACjD,CAAC;AAED,mGAAmG;AACnG,SAAS,aAAa,CACrB,MAAoB,EACpB,CAAe,EACf,OAAsB;IAEtB,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;IACvF,MAAM,UAAU,GAA0C,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAA;IAErG,IAAI,GAAG;QAAE,UAAU,CAAC,MAAM,GAAG,GAAG,CAAA;IAEhC,IAAI,EAAE;QAAE,UAAU,CAAC,QAAQ,GAAG,EAAE,CAAA;IAChC,IAAI,IAAY,CAAA;IAEhB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjD,IAAI,GAAG,GAAG,EAAE,IAAI,MAAM,KAAK,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IAC7D,CAAC;SAAM,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC3B,kFAAkF;QAClF,IAAI,GAAG,GAAG,EAAE,IAAI,MAAM,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;IACjE,CAAC;SAAM,CAAC;QACP,2EAA2E;QAC3E,MAAM,MAAM,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAClD,IAAI,GAAG,GAAG,MAAM,IAAI,EAAE,KAAK,MAAM,EAAE,CAAA;IACpC,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,+FAA+F;QAC/F,kEAAkE;QAClE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;IAClD,CAAC;IACD,MAAM,KAAK,GAA0C,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,CAAA;IAC/E,MAAM,CAAC,GAAG,MAAM,EAAE,CAAA;IAElB,IAAI,CAAC,GAAG,GAAG;QAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,KAAK,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;IAElF,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,KAAK,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;IACtF,MAAM,QAAQ,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAA;IAEzG,OAAO;QACN,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,GAAG,QAAQ,KAAK,OAAO,EAAE;QAC9B,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE;KAChE,CAAA;AACF,CAAC;AAYD,MAAM,UAAU,GAAyB;IACxC;QACC,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;QACnD,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;KAC/G;IACD;QACC,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;QAC5C,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;KAChF;IACD;QACC,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC;QAChD,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;KAC5G;IACD;QACC,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACxD,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;KAChF;IACD;QACC,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC;QACpD,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;KACvF;IACD;QACC,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC;QAC/C,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;KACzF;CACD,CAAA;AAOD,MAAM,cAAc,GAA4B;IAC/C,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,sBAAsB;IACtI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,wBAAwB;IAC9H,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,kBAAkB;IAC7G,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,0BAA0B;IAC9G,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,wBAAwB;IACnH,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,oBAAoB;CAC7G,CAAA;AACD,MAAM,WAAW,GAAsB;IACtC,aAAa;IACb,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,WAAW;IACX,eAAe;IACf,eAAe;IACf,aAAa;IACb,YAAY;IACZ,aAAa;CACb,CAAA;AACD,MAAM,IAAI,GAAG,CAAI,MAAoB,EAAE,GAAiB,EAAK,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAE,CAAA;AACvG,MAAM,OAAO,GAAG,CAAC,MAAoB,EAAU,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAA;AAExF;;;GAGG;AACH,SAAS,eAAe,CAAC,MAAoB;IAM5C,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAClC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,EACzB,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAEnC,IAAI,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;QACnC,MAAM,UAAU,GAAG,MAAM,EAAE,GAAG,GAAG,CAAA;QACjC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAA;QAC3F,MAAM,UAAU,GAA0C,UAAU;YACnE,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;YAClE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA;QAEzC,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACnE,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAA;IAEvC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,sFAAsF;QACtF,OAAO;YACN,GAAG,EAAE,qBAAqB;YAC1B,GAAG,EAAE,GAAG,EAAE,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE;YAC5D,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;YAClG,IAAI,EAAE,IAAI;SACV,CAAA;IACF,CAAC;IAED,kFAAkF;IAClF,OAAO;QACN,GAAG,EAAE,uBAAuB;QAC5B,GAAG,EAAE,GAAG,EAAE,IAAI,MAAM,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,EAAE;QAC1D,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAChG,IAAI,EAAE,IAAI;KACV,CAAA;AACF,CAAC;AAED,kGAAkG;AAClG,SAAS,kBAAkB,CAAC,MAAoB;IAM/C,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACtC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,EACzB,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAClC,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,EACrC,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;IAErC,OAAO;QACN,GAAG,EAAE,eAAe;QACpB,GAAG,EAAE,GAAG,EAAE,IAAI,MAAM,KAAK,QAAQ,KAAK,CAAC,CAAC,IAAI,IAAI,QAAQ,EAAE;QAC1D,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE;QAC5E,IAAI,EAAE,IAAI;KACV,CAAA;AACF,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,CAAA,CAAC,kDAAkD;AAC9E,MAAM,WAAW,GAAG,IAAI,CAAA,CAAC,2EAA2E;AAEpG,MAAM,CAAC,MAAM,qBAAqB,GAAgB;IACjD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,uGAAuG;IACpH,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;IACtF,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK;QACpB,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;QACvF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,uHAAuH;QACvH,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,IAAI,eAAe,CAAA;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAA;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA,CAAC,6BAA6B;QAEvF,MAAM,IAAI,GAAmB,EAAE,CAAA;QAE/B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;YAClC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,MAAM,SAAS,CAAC,CAAA;YAE3D,KAAK,MAAM,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;QAChF,CAAC;QAED,IAAI,OAAO,GAAG,CAAC,CAAA;QACf,IAAI,OAAO,GAAG,CAAC,CAAA;QACf,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;QAErB,OAAO,OAAO,GAAG,KAAK,IAAI,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;YAC/C,+FAA+F;YAC/F,qFAAqF;YACrF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAA;YACrB,IAAI,QAAyF,CAAA;YAC7F,IAAI,OAAe,CAAA;YAEnB,IAAI,IAAI,GAAG,cAAc,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;gBACjC,QAAQ,GAAG,CAAC,CAAA;gBACZ,OAAO,GAAG,CAAC,CAAC,IAAI,CAAA;YACjB,CAAC;iBAAM,IAAI,IAAI,GAAG,cAAc,GAAG,WAAW,EAAE,CAAC;gBAChD,MAAM,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;gBACpC,QAAQ,GAAG,CAAC,CAAA;gBACZ,OAAO,GAAG,CAAC,CAAC,IAAI,CAAA;YACjB,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAE,CAAA;gBACzC,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA,CAAC,8CAA8C;gBAClF,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;gBAC5C,OAAO,GAAG,CAAC,CAAC,IAAI,CAAA;gBAEhB,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAChD,OAAO,EAAE,CAAA;oBACT,SAAQ;gBACT,CAAC;YACF,CAAC;YACD,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAA;YACpC,MAAM,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,OAAO,EAAE,CAAA;YAEpF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;gBACnE,OAAO,EAAE,CAAA;gBACT,SAAQ;YACT,CAAC;YACD,MAAM,SAAS,GAAiB;gBAC/B,GAAG;gBACH,UAAU;gBACV,OAAO,EAAE,OAAO;gBAChB,MAAM,EAAE,SAAS;gBACjB,MAAM;gBACN,SAAS,EAAE,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC;gBAC7C,cAAc,EAAE,OAAO;gBACvB,OAAO,EAAE,wFAAwF;aACjG,CAAA;YACD,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;YAEnC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;gBAChD,OAAO,EAAE,CAAA;gBACT,SAAQ;YACT,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;YAC9F,OAAO,EAAE,CAAA;QACV,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA;IAC5B,CAAC;CACD,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `fr-admin-split` shard recipe — the FR admin-split coverage shard (night 2026-06-19,
|
|
7
|
+
* surpass-v1.5.0). Teaches the model to SPLIT the département out of the locality on
|
|
8
|
+
* bare/space/comma-delimited French place rows — the admin-deciding failure class the pre-GPU
|
|
9
|
+
* self-validation proved moves the resolved coordinate (collision communes −61%; see
|
|
10
|
+
* docs/articles/evals/2026-06-19-fr-admin-split-prevalidation.md). Ported from
|
|
11
|
+
* scripts/build-fr-admin-split-shard.mjs.
|
|
12
|
+
*
|
|
13
|
+
* Failure shapes (the model currently mis-handles all of these):
|
|
14
|
+
*
|
|
15
|
+
* - `Thauron, Creuse` → région dropped to null (the comma+full-name miss)
|
|
16
|
+
* - `Montredon, Lozère` → région = "ère" (the diacritic subword split, #727)
|
|
17
|
+
* - (AU analog) `CANBERRA ACT` → the space-delimited admin fuse
|
|
18
|
+
*
|
|
19
|
+
* The département is the essential admin unit for FR postal geography and maps to the `region`
|
|
20
|
+
* component tag in our schema. We derive it DETERMINISTICALLY from the real postcode via codex
|
|
21
|
+
* `departementForCodePostal` (first two digits = département) — salvage-first, no re-derived
|
|
22
|
+
* table.
|
|
23
|
+
*
|
|
24
|
+
* Data (`--communes`, opts.communes): REAL BAN (Base Adresse Nationale) commune+postcode+coord
|
|
25
|
+
* tuples, one per line, TAB-separated `commune <TAB> postcode <TAB> lon <TAB> lat`. Build the
|
|
26
|
+
* input TSV once from the BAN staging CSV (see the legacy script header). Anchor-ON by
|
|
27
|
+
* construction: rows carry a REAL postcode token in `raw` + a `postcode` component, so the
|
|
28
|
+
* training loader paints the anchor feature onto that span automatically. The trailing-postcode
|
|
29
|
+
* anchor REINFORCES the FR split (FR postcode is trailing, unlike German PLZ-leading — the v0.9.2
|
|
30
|
+
* scar is positional, not universal).
|
|
31
|
+
*/
|
|
32
|
+
import { type ShardRecipe } from "./scaffold.js";
|
|
33
|
+
export declare const frAdminSplitRecipe: ShardRecipe;
|
|
34
|
+
//# sourceMappingURL=fr-admin-split.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fr-admin-split.d.ts","sourceRoot":"","sources":["../../../src/shard-recipes/fr-admin-split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAWH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AA0FhE,eAAO,MAAM,kBAAkB,EAAE,WAgFhC,CAAA"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `fr-admin-split` shard recipe — the FR admin-split coverage shard (night 2026-06-19,
|
|
7
|
+
* surpass-v1.5.0). Teaches the model to SPLIT the département out of the locality on
|
|
8
|
+
* bare/space/comma-delimited French place rows — the admin-deciding failure class the pre-GPU
|
|
9
|
+
* self-validation proved moves the resolved coordinate (collision communes −61%; see
|
|
10
|
+
* docs/articles/evals/2026-06-19-fr-admin-split-prevalidation.md). Ported from
|
|
11
|
+
* scripts/build-fr-admin-split-shard.mjs.
|
|
12
|
+
*
|
|
13
|
+
* Failure shapes (the model currently mis-handles all of these):
|
|
14
|
+
*
|
|
15
|
+
* - `Thauron, Creuse` → région dropped to null (the comma+full-name miss)
|
|
16
|
+
* - `Montredon, Lozère` → région = "ère" (the diacritic subword split, #727)
|
|
17
|
+
* - (AU analog) `CANBERRA ACT` → the space-delimited admin fuse
|
|
18
|
+
*
|
|
19
|
+
* The département is the essential admin unit for FR postal geography and maps to the `region`
|
|
20
|
+
* component tag in our schema. We derive it DETERMINISTICALLY from the real postcode via codex
|
|
21
|
+
* `departementForCodePostal` (first two digits = département) — salvage-first, no re-derived
|
|
22
|
+
* table.
|
|
23
|
+
*
|
|
24
|
+
* Data (`--communes`, opts.communes): REAL BAN (Base Adresse Nationale) commune+postcode+coord
|
|
25
|
+
* tuples, one per line, TAB-separated `commune <TAB> postcode <TAB> lon <TAB> lat`. Build the
|
|
26
|
+
* input TSV once from the BAN staging CSV (see the legacy script header). Anchor-ON by
|
|
27
|
+
* construction: rows carry a REAL postcode token in `raw` + a `postcode` component, so the
|
|
28
|
+
* training loader paints the anchor feature onto that span automatically. The trailing-postcode
|
|
29
|
+
* anchor REINFORCES the FR split (FR postcode is trailing, unlike German PLZ-leading — the v0.9.2
|
|
30
|
+
* scar is positional, not universal).
|
|
31
|
+
*/
|
|
32
|
+
import { createReadStream } from "node:fs";
|
|
33
|
+
import { createInterface } from "node:readline";
|
|
34
|
+
import { departementForCodePostal } from "@mailwoman/codex/fr";
|
|
35
|
+
import { stableSourceID } from "../adapter.js";
|
|
36
|
+
import { alignRow } from "../align.js";
|
|
37
|
+
import { makeMulberry32 } from "./scaffold.js";
|
|
38
|
+
const DEFAULT_COMMUNES = "/tmp/reg/fr-communes.tsv";
|
|
39
|
+
const LICENSE = "BAN (Base Adresse Nationale) commune+postcode tuples, rendered admin-split — see ingest SOURCE";
|
|
40
|
+
/** Read the distinct commune TSV (commune, postcode, lon, lat); derive the département name. */
|
|
41
|
+
async function readCommunes(path) {
|
|
42
|
+
const rows = [];
|
|
43
|
+
const rl = createInterface({ input: createReadStream(path, { encoding: "utf8" }), crlfDelay: Infinity });
|
|
44
|
+
for await (const line of rl) {
|
|
45
|
+
if (!line)
|
|
46
|
+
continue;
|
|
47
|
+
const [commune, postcode, lon, lat] = line.split("\t");
|
|
48
|
+
if (!commune || !postcode)
|
|
49
|
+
continue;
|
|
50
|
+
const dep = departementForCodePostal(postcode);
|
|
51
|
+
if (!dep)
|
|
52
|
+
continue; // bad/unmappable postcode — skip (CEDEX, etc.)
|
|
53
|
+
// Substring invariant: a département whose name isn't a clean token (none are) or a commune
|
|
54
|
+
// containing the département name would confuse alignment — both are vanishingly rare here.
|
|
55
|
+
rows.push({ commune, postcode, departement: dep.name, lon, lat });
|
|
56
|
+
}
|
|
57
|
+
return rows;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Render one admin-split variant. The CORE teaching signal: the département, even as a full word after a comma or a
|
|
61
|
+
* space, is `region` — never folded into `locality`. Variants 1-3 are the failure class; 4-5 are canonical-FR
|
|
62
|
+
* preservation so the model doesn't over-fire region on every trailing token (and the bare commune still resolves).
|
|
63
|
+
*/
|
|
64
|
+
function render(random, c) {
|
|
65
|
+
const r = random();
|
|
66
|
+
const loc = random() < 0.1 ? c.commune.toUpperCase() : c.commune;
|
|
67
|
+
const dep = c.departement;
|
|
68
|
+
const pc = c.postcode;
|
|
69
|
+
let out;
|
|
70
|
+
if (r < 0.25) {
|
|
71
|
+
// 1. bare comma, NO postcode — the Thauron/#727 shape (anchor off)
|
|
72
|
+
out = { raw: `${loc}, ${dep}`, components: { locality: loc, region: dep }, order: "bare-comma" };
|
|
73
|
+
}
|
|
74
|
+
else if (r < 0.5) {
|
|
75
|
+
// 2. bare comma + postcode — anchor ON
|
|
76
|
+
out = {
|
|
77
|
+
raw: `${loc}, ${dep} ${pc}`,
|
|
78
|
+
components: { locality: loc, region: dep, postcode: pc },
|
|
79
|
+
order: "bare-comma-pc",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
else if (r < 0.7) {
|
|
83
|
+
// 3. space-delimited admin (the AU `CANBERRA ACT` fuse applied to FR) — anchor ON
|
|
84
|
+
out = { raw: `${loc} ${dep} ${pc}`, components: { locality: loc, region: dep, postcode: pc }, order: "space-pc" };
|
|
85
|
+
}
|
|
86
|
+
else if (r < 0.85) {
|
|
87
|
+
// 4. canonical FR postcode-first (NO département) — preservation, anchor ON
|
|
88
|
+
out = { raw: `${pc} ${loc}`, components: { postcode: pc, locality: loc }, order: "canonical-pc-first" };
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// 5. commune + postcode (NO département) — preservation, anchor ON
|
|
92
|
+
out = { raw: `${loc} ${pc}`, components: { locality: loc, postcode: pc }, order: "commune-pc" };
|
|
93
|
+
}
|
|
94
|
+
// fr.country preservation (the v1.8.0 #728 finding): the v1.8.0 shard's bare rows carried NO country
|
|
95
|
+
// token, so the model under-emitted country on FR (fr.country −3.5pp). ~20% of rows now append an
|
|
96
|
+
// explicit "France" + a `country` component — the model relearns to emit country WHEN the token is
|
|
97
|
+
// present without over-firing it on the (still-majority) country-less rows. Substring invariant holds.
|
|
98
|
+
if (random() < 0.2) {
|
|
99
|
+
out = {
|
|
100
|
+
raw: `${out.raw}, France`,
|
|
101
|
+
components: { ...out.components, country: "France" },
|
|
102
|
+
order: `${out.order}+fr`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
export const frAdminSplitRecipe = {
|
|
108
|
+
name: "fr-admin-split",
|
|
109
|
+
description: "FR admin-split rows: BAN communes → split département into `region` (+ canonical-FR preservation)",
|
|
110
|
+
mode: "generate",
|
|
111
|
+
options: [
|
|
112
|
+
{ flag: "--communes <tsv>", description: "BAN commune+postcode+coord TSV. Default /tmp/reg/fr-communes.tsv" },
|
|
113
|
+
],
|
|
114
|
+
async run(opts, write) {
|
|
115
|
+
// Legacy build-fr-admin-split-shard.mjs seeded `mulberry32(opts.seed)`.
|
|
116
|
+
const random = makeMulberry32(opts.seed);
|
|
117
|
+
const count = opts.count ?? 60000;
|
|
118
|
+
const source = opts.sourceName ?? "synth-fr-admin-split";
|
|
119
|
+
const communesPath = opts.communes ?? DEFAULT_COMMUNES;
|
|
120
|
+
const pool = await readCommunes(communesPath);
|
|
121
|
+
console.error(` ${communesPath}: ${pool.length} communes with derived département`);
|
|
122
|
+
if (pool.length === 0) {
|
|
123
|
+
throw new Error("No communes — build the TSV from BAN first (see the recipe header).");
|
|
124
|
+
}
|
|
125
|
+
let emitted = 0;
|
|
126
|
+
let skipped = 0;
|
|
127
|
+
let guard = 0;
|
|
128
|
+
const orderCounts = {};
|
|
129
|
+
const N = pool.length;
|
|
130
|
+
while (emitted < count && guard++ < count * 12) {
|
|
131
|
+
const base = pool[Math.floor(random() * N)];
|
|
132
|
+
const { raw, components, order } = render(random, base);
|
|
133
|
+
// Alignment precondition: every component surface appears verbatim in raw.
|
|
134
|
+
const values = Object.values(components).filter((v) => Boolean(v));
|
|
135
|
+
if (!values.every((v) => raw.includes(v))) {
|
|
136
|
+
skipped++;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (opts.golden) {
|
|
140
|
+
// Held-out eval slice for the centroid gate — carries the truth coordinate.
|
|
141
|
+
write(JSON.stringify({ raw, components, country: "FR", lat: Number(base.lat), lon: Number(base.lon) }) + "\n");
|
|
142
|
+
emitted++;
|
|
143
|
+
orderCounts[order] = (orderCounts[order] ?? 0) + 1;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const sourceID = stableSourceID(source, {
|
|
147
|
+
locality: components.locality,
|
|
148
|
+
region: components.region,
|
|
149
|
+
postcode: components.postcode,
|
|
150
|
+
});
|
|
151
|
+
const canonical = {
|
|
152
|
+
raw,
|
|
153
|
+
components,
|
|
154
|
+
country: "FR",
|
|
155
|
+
locale: "fr-FR",
|
|
156
|
+
source,
|
|
157
|
+
source_id: sourceID,
|
|
158
|
+
corpus_version: "0.5.0",
|
|
159
|
+
license: LICENSE,
|
|
160
|
+
};
|
|
161
|
+
const aligned = alignRow(canonical);
|
|
162
|
+
if (aligned.kind !== "labeled" || !aligned.row) {
|
|
163
|
+
skipped++;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
write(JSON.stringify({ ...aligned.row, synth_method: "fr-admin-split", synth_order: order, synth_base_id: null }) +
|
|
167
|
+
"\n");
|
|
168
|
+
emitted++;
|
|
169
|
+
orderCounts[order] = (orderCounts[order] ?? 0) + 1;
|
|
170
|
+
}
|
|
171
|
+
console.error(` emitted=${emitted} skipped=${skipped} order-mix=${JSON.stringify(orderCounts)}`);
|
|
172
|
+
return { emitted, skipped };
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
//# sourceMappingURL=fr-admin-split.js.map
|