diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd837c03..df57a396 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,9 @@ jobs: - name: Check generated Language data drift run: uv run python tools/regenerate_language_data.py --check + - name: Check generated UNSPSC codeset data drift + run: uv run python tools/regenerate_unspsc_data.py --check + - name: Verify no generated data drift (git diff) run: git diff --exit-code diff --git a/CHANGELOG.md b/CHANGELOG.md index 39bf9603..6faf273f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **UNSPSC — Product/service codes:** new capability with one grammar (`unspsc_recognition`: bare 8-digit, zero-padded parents, 6-digit class alias, `UNSPSC`-labelled, `UNSPSC000.` MDM IDs, 10-digit +BFI, ASCII-only, longest-first 10/8/6) and four rules backed by the UNGM UNSPSC Code Structure article (`Section 1-hierarchy-structure` — 6/8/10 lanes, PARSER; `Section 2-level-padding` — `00`-pair lattice, PARSER), the UNDP codeset (UNGM live export 2026-09-30, 13,482 live stems plus 8 synthesized family ancestors (ancestor-walk only); `Section 3-codeset-membership` — stem plus live ancestors, always-active LOOKUP_TABLE; partial — UNDP v26.0801 XLSX gated 403) and the UNECE Classification Guidelines v2.04 (`Section 4-business-function-suffix` — informative-only, PARSER gated by `include_business_function=True`, default on; gating drops the suffix candidate, not the verdict). Canonical form is the 8-digit zero-padded wire stem; offered output formats `labeled` and `native` (both re-enter as fixed points; pair-hyphenated `segmented` display deliberately unoffered — hyphens never re-enter by design). Space/dot/hyphen-grouped, truncated 2/4-digit, and 7/9/11-digit runs → `MISSING`; mid-zero padding, unissued stems, Wikidata-cited-but-unexported codes (e.g. `11101803`) → `INVALID` under the pinned snapshot; two distinct codes in one call → `MultipleMentionsError`. + - **Domain — Hostnames:** new capability with two grammars (`ascii_hostname`: LDH shapes, case-neutral, trailing-dot runs; `idn_hostname`: any script with reserved-ASCII excluded, ASCII overlap dedups by span) and five rules backed by RFC 1034 (`Section-3.1-name-syntax` — ≥2 labels, no empty label, PARSER), RFC 1035 (`Section-2.3.4-label-length` — 63 octets/label, 253 chars/name post-encode, PARSER), UTS #46 (`UTS46-statuses` — statuses with STD3 rules, D13 hyphen checks, ACE round trip, PARSER; shipped table 15.1.0), RFC 5893 (`Section-2-bidi-context` — §2 six conditions plus ContextJ join-control rejection, PARSER), and the IANA Root Zone Database v2026092300 (`root-zone-membership` — encoded-TLD membership ANDed with the other four, LOOKUP_TABLE; no corroboration → `INVALID`). Canonical form is the lowercase ASCII A-label dotted name with no trailing dot; offered output format `unicode` (per-label Punycode decode, re-enters as a fixed point). Single labels (`localhost`) and undelegated TLDs → `INVALID`; containers (`user@example.com`, URLs, `*.example.com`) → `MISSING` (boundary kills); two distinct hostnames in one call → `MultipleMentionsError`. - **Timezone — Wave-2 first-cut table expansion (#170):** two legacy Links (`Canada/Eastern` → `America/Toronto`, `US/PACIFIC` → `America/Los_Angeles`, both live in tzdb `backward`) and one fixed zone (`Etc/GMT-8`, live in `etcetera`, POSIX sign kept as authored). Previously `MISSING`, now `SUCCESS` under the default contract. Data tables + guide rows only — no grammar-logic, contract, engine, or canonical-form change; the subset contract (unlisted keys → `MISSING`) and the short-caps carve rule are unchanged. diff --git a/CONTEXT.md b/CONTEXT.md index 18535660..b741a58a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -60,6 +60,7 @@ Capability-defined intermediate representation that Grammars must produce: - **Timezone:** `TimezoneNotation(key, family, compact)` — `key` is the as-written mention, `family` discriminates `"name"` / `"abbreviation"`, `compact` is the lookup key (rules restore canonical case and resolve Links) - **UtcOffset:** `UtcOffsetNotation(compact)` — `compact` is the grammar-normalized extended `+HH:MM` form (`Z` → `+00:00`); rules own range validation (`-12:00..+14:00`, `-00:00` refused) - **UUID:** `UUIDNotation(compact, hyphenated, urn, version)` — `compact` is the 32-hex lowercase form, `hyphenated` the `8-4-4-4-12` canonical, `urn` the `urn:uuid:` carrier, `version` the version nibble (informative, never gates) +- **UNSPSC:** `UNSPSCNotation(digits, level, function, native_length)` — `digits` is the 8-digit zero-padded stem (6-digit class alias padded `+"00"` by the grammar; 10-digit input keeps its 8-digit stem), `level` is `"segment"` / `"family"` / `"class"` / `"commodity"` from trailing-`00` pairs (no authority lookup), `function` the 2-digit BFI suffix or `""`, `native_length` the spelled digit length (6/8/10, retained as the `native` format facet); grammar never validates membership — rules own it - **Phone / URL:** capability-defined shapes for address / number / URI components ### Notation Type Example @@ -78,7 +79,7 @@ class EmailNotation: ## The Capabilities -Paxman ships twenty-eight built-in capabilities (28 in `paxman/capabilities/__init__.py` and `paxman/api/bootstrap.py:_SHIPPED`, alphabetical by registry name), each wired to an authoritative specification: +Paxman ships twenty-nine built-in capabilities (29 in `paxman/capabilities/__init__.py` and `paxman/api/bootstrap.py:_SHIPPED`, alphabetical by registry name), each wired to an authoritative specification: | Capability | Domain | Authorities | |------------|--------|-------------| @@ -107,6 +108,7 @@ Paxman ships twenty-eight built-in capabilities (28 in `paxman/capabilities/__in | **Phone** | Phone numbers | ITU-T E.164, RFC 3966, NANP | | **SI Unit** | SI unit expressions | BIPM SI Brochure, ISO 80000-1 | | **Timezone** | Timezone identifiers | IANA Time Zone Database | +| **UNSPSC** | Product/service codes | UNDP UNSPSC Code Structure (UNGM), UNDP Codeset (UNGM live export 2026-09-30), UNECE BFI Guidelines v2.04 | | **URL** | URLs | WHATWG URL Standard | | **UtcOffset** | UTC offsets | ISO 8601, RFC 3339 | | **UUID** | UUIDs | IETF RFC 9562 | @@ -836,7 +838,7 @@ paxman/ ├── __main__.py # python -m paxman entry point ├── api/ │ ├── __init__.py -│ ├── bootstrap.py # _SHIPPED (28 capabilities, alphabetical; paxman/capabilities/__init__.py exports 28), register_all_shipped(), list_shipped_capabilities() +│ ├── bootstrap.py # _SHIPPED (29 capabilities, alphabetical; paxman/capabilities/__init__.py exports 29), register_all_shipped(), list_shipped_capabilities() │ └── canonicalize.py # Public canonicalize() function → run_capability() ├── shared_data/ │ └── currency_snapshot.json # CLDR v47 + ISO 4217 snapshot → Currency + Money data via tools/regenerate_currency_data.py @@ -1048,6 +1050,12 @@ paxman/ │ ├── grammar/data/ # grandfathered_tags, english_names, localized_names, script_names, region_names │ ├── rules/ # bcp47_rfc5646, iso_639_1/2/3/5, iana_language_subtag_registry, cldr_language_display_name │ └── rules/data/ # iana_language_subtags, iso_639 tables, english_display_names + ├── UNSPSC/ # grammar/ (1) + rules/ (3) + rules/data/ — UNGM structure, UNDP codeset (UNGM live export), UNECE BFI + │ ├── capability.py # UNSPSCCapability + │ ├── contract.py # UNSPSCContract (unspsc/labeled/native output formats; include_business_function) + │ ├── notation.py # UNSPSCNotation (digits, level, function, native_length) + │ ├── grammar/ # unspsc_recognition + │ └── rules/ # undp_unspsc_structure_ed2025, undp_unspsc_codeset_ed2026, unece_bfi_ed2005 (+ data/unspsc_codeset) └── LEI/ # grammar/ (1) + rules/ (2) — ISO 17442-1:2020, GLEIF LOU prefix list ├── capability.py # LEICapability ├── contract.py # LEIContract @@ -1089,7 +1097,7 @@ tests/ │ ├── test_capability_contract.py# CapabilityContract (output_format policy, defaults) │ ├── test_capability.py # Capability ABC │ ├── test_capability_surface.py # Surface homogeneity across capabilities -│ ├── test_capability_exports.py # __init__ export completeness (28 capabilities) +│ ├── test_capability_exports.py # __init__ export completeness (29 capabilities) │ ├── test_version_stamp.py # VersionStamp │ ├── test_discovery.py # Registry register/freeze/reset │ ├── test_errors.py # Exception hierarchy diff --git a/README.md b/README.md index 515c7980..7fc91bab 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ If multiple specifications disagree on the canonical value, the status is `AMBIG ## Capabilities -Paxman ships with twenty-eight built-in capabilities (28 in `paxman/capabilities/__init__.py` and `paxman/api/bootstrap.py:_SHIPPED`, alphabetical by registry name): +Paxman ships with twenty-nine built-in capabilities (29 in `paxman/capabilities/__init__.py` and `paxman/api/bootstrap.py:_SHIPPED`, alphabetical by registry name): | Capability | Domain | Grammars | Rules | Description | |---|---|---|---|---| @@ -95,6 +95,7 @@ Paxman ships with twenty-eight built-in capabilities (28 in `paxman/capabilities | **Phone** | Phone numbers | 4 (e164, tel_uri, international_00, national) | 5 | ITU-T E.164, RFC 3966, NANP | | **SI Unit** | SI unit expressions | 3 (symbol, name, compound) | 7 | BIPM SI Brochure, ISO 80000-1 | | **Timezone** | Timezone identifiers | 2 (timezone_name, timezone_abbreviation) | 4 | IANA Time Zone Database | +| **UNSPSC** | Product/service codes | 1 (unspsc) | 4 | UNDP UNSPSC (UNGM structure, UNGM live-export snapshot, UNECE BFI) | | **URL** | URLs | 1 (absolute_uri) | 1 | WHATWG URL Standard | | **UtcOffset** | UTC offsets | 1 (utc_offset) | 1 | ISO 8601-1:2019, RFC 3339 | | **UUID** | UUIDs | 1 (uuid) | 1 | IETF RFC 9562 | @@ -574,7 +575,7 @@ result = paxman.canonicalize("2026-01-15", contract) ## Community Extensions -Paxman ships with twenty-eight built-in capabilities, but a capability is closed for modification yet open for extension: you can add recognition and validation without touching the library. Register a `Grammar` subclass and the `Rule` subclass that validates it, then opt a contract into them by naming the grammar in `extra_grammars`: +Paxman ships with twenty-nine built-in capabilities, but a capability is closed for modification yet open for extension: you can add recognition and validation without touching the library. Register a `Grammar` subclass and the `Rule` subclass that validates it, then opt a contract into them by naming the grammar in `extra_grammars`: ```python import re diff --git a/benchmarks/baseline.json b/benchmarks/baseline.json index c5c17717..e4cf72ee 100644 --- a/benchmarks/baseline.json +++ b/benchmarks/baseline.json @@ -287,6 +287,15 @@ "p95_ms": 142.99965801183134, "min_ms": 58.47020004875958, "max_ms": 155.29442497063428 + }, + { + "capability": "unspsc", + "iterations": 100, + "mean_ms": 0.11675417306832969, + "p50_ms": 0.10525202378630638, + "p95_ms": 0.16783701721578836, + "min_ms": 0.10288890916854143, + "max_ms": 0.2312560100108385 } ], "iterations": 100 diff --git a/benchmarks/scenarios.py b/benchmarks/scenarios.py index 2325a6ce..24fdc844 100644 --- a/benchmarks/scenarios.py +++ b/benchmarks/scenarios.py @@ -296,6 +296,23 @@ def _isni_contract() -> object: return ISNI.create_contract() +def _unspsc_register() -> None: + from paxman.capabilities import UNSPSC + from paxman.core.discovery import get_capability, register_capability + from paxman.core.errors import CapabilityError + + try: + get_capability("unspsc") + except CapabilityError: + register_capability(UNSPSC()) + + +def _unspsc_contract() -> object: + from paxman.capabilities import UNSPSC + + return UNSPSC.create_contract() + + def _language_register() -> None: from paxman.capabilities import Language from paxman.core.discovery import get_capability, register_capability @@ -602,6 +619,12 @@ def _si_text(size: int) -> str: "register": _isni_register, "contract_factory": _isni_contract, }, + { + "capability": "unspsc", + "text": "UNSPSC 44103103", + "register": _unspsc_register, + "contract_factory": _unspsc_contract, + }, { "capability": "issn", "text": "0317-8471", diff --git a/docs/development/MILESTONE.md b/docs/development/MILESTONE.md index 8a91c96c..a905c6df 100644 --- a/docs/development/MILESTONE.md +++ b/docs/development/MILESTONE.md @@ -2,11 +2,11 @@ > **Purpose:** Roadmap guidance for capabilities to bring into Paxman, ordered by priority. > This table is a planning aid — details need not be exactly accurate in terms of implementation. -> 28 capabilities are shipped (BIC, ChemicalElement, Coordinates, Country, CreditCard, Currency, Date, DOI, Domain, Email, GTIN, IBAN, IP, ISBN, ISIN, ISNI, ISSN, Language, LEI, MacAddress, Money, ORCID, Phone, SIUnit, Timezone, URL, UtcOffset, UUID) and are listed in §1 only — they are excluded from the future roadmap in §2. +> 29 capabilities are shipped (BIC, ChemicalElement, Coordinates, Country, CreditCard, Currency, Date, DOI, Domain, Email, GTIN, IBAN, IP, ISBN, ISIN, ISNI, ISSN, Language, LEI, MacAddress, Money, ORCID, Phone, SIUnit, Timezone, UNSPSC, URL, UtcOffset, UUID) and are listed in §1 only — they are excluded from the future roadmap in §2. --- -## 1. Delivered Capabilities (28 shipped) +## 1. Delivered Capabilities (29 shipped) Verified against `paxman/capabilities/__init__.py` + `paxman/api/bootstrap.py:_SHIPPED` (alphabetical bootstrap order) and `paxman/capabilities//rules/` provenance constants. Examples were re-checked through `canonicalize()` on 2026-09-22. @@ -40,6 +40,7 @@ Verified against `paxman/capabilities/__init__.py` + `paxman/api/bootstrap.py:_S | 26 | **GTIN** | GS1 General Specifications 26.0 | "590 1234 12345 7" → "05901234123457" | `research/2026-09-22-gtin-canonicalization.md`, `plans/2026-09-22-gtin-capability.md` | | 27 | **LEI** | ISO 17442-1:2020, GLEIF LOU prefix list | "5493000IBP32UQZ0KL24" → "5493000IBP32UQZ0KL24" | `research/2026-09-22-lei-canonicalization.md`, `plans/2026-09-22-lei-capability.md` | | 28 | **ISNI** | ISO 27729:2024 (MOD 11-2) | "ISNI 0000 0001 2103 2683" → "0000 0001 2103 2683" | `research/2026-09-26-isni-canonicalization.md`, `plans/2026-09-26-isni-capability.md` | +| 29 | **UNSPSC** | UNDP UNSPSC (UNGM structure, UNGM live-export snapshot, UNECE BFI) | "UNSPSC 44103103" → "44103103" | `research/2026-09-30-unspsc-canonicalization.md`, `plans/2026-09-30-unspsc-capability.md` | Notes on §1: diff --git a/docs/development/plans/2026-09-30-unspsc-capability.md b/docs/development/plans/2026-09-30-unspsc-capability.md new file mode 100644 index 00000000..1ac63d58 --- /dev/null +++ b/docs/development/plans/2026-09-30-unspsc-capability.md @@ -0,0 +1,160 @@ +# UNSPSC Capability Implementation Plan + +> **For workers:** Execute task-by-task via `tdd` + `verification-before-completion`. Review gate: `paxman-momus-review` (plan), `paxman-oracle-review` (after impl). + +**Goal:** Ship a 29th capability, `UNSPSC`, that canonicalizes UNSPSC mentions (bare 8-digit, zero-padded parents, 6-digit class alias, `UNSPSC`-labelled, `UNSPSC000.` MDM IDs, 10-digit +BFI) to the 8-digit zero-padded wire stem with UNDP v26.0801 provenance. + +**Architecture:** Single `PipelineGrammar` (`unspsc_recognition`, `RegexStage`, longest-first 10/8/6 alternation, `single_value=True`) feeding four rules in three publication files (two always-active PARSERs for structure/padding, one always-active LOOKUP_TABLE for codeset membership at the pinned snapshot, one gated PARSER for the BFI suffix); contract offers `segmented` + `labeled` + `native` encodings via the `format_value()` seam only. No `paxman/core` or `paxman/engine` change. + +**Tech Stack:** Python 3.11+, uv, ruff, strict pyright, import-linter, pytest (markers: unit/capability/integration/property), `paxman/core/grammar` staged pipeline, `paxman/capabilities/UNSPSC`. + +**References:** `docs/development/research/2026-09-30-unspsc-canonicalization.md` (§2.1 inventory, §4.2 pattern, §5.2 rule map, §7 vectors, §13 decisions; review-corrected 2026-09-30), `paxman/capabilities/GTIN/` (notation facets `notation.py:20-22`, grammar `grammar/gtin_recognition.py:44-61,95`), `paxman/capabilities/ISBN/` (grammar `grammar/isbn13_recognition.py:15-40`, registry rule `rules/isbn_range_message_ed2026.py:13-33`, data `rules/data/range_message.py:14,30,2253`), `paxman/capabilities/ISIN/rules/anna_isin_guidelines_ed2025.py:30`, HOW_TO_ADD_NEW_CAPABILITY.md Steps 0–10, HOW_TO_ADD_NEW_GRAMMAR.md, ARCHITECTURE.md (Recognition Pipeline Contract, formatting seam), ADR-0010 (re-entry), ADR-0011 (offered-format classes), ADR-0012 (parser corroboration — N/A here: membership is LOOKUP_TABLE). + +**Branch:** `feature/unspsc-capability` (research committed as `4e8c0ac`; implementation continues on this branch per this plan). + +--- + +## File Structure + +- Create (scaffold via Task 0): `paxman/capabilities/UNSPSC/__init__.py`, `notation.py`, `contract.py`, `capability.py`, `grammar/__init__.py`, `grammar/unspsc_recognition.py`, `rules/__init__.py`, `rules/undp_unspsc_structure_ed2025.py` (Task 5), `rules/undp_unspsc_codeset_ed2023.py` (Task 6), `rules/unece_bfi_ed2005.py` (Task 7), `rules/data/__init__.py`, `rules/data/unspsc_codeset.py`, plus test stubs under `tests/capabilities/unspsc/` +- Create (data lifecycle): `paxman/shared_data/unspsc_snapshot.json`, `tools/regenerate_unspsc_data.py` (with `--check`) +- Modify: `paxman/capabilities/__init__.py` (lazy export `UNSPSC` + `__all__`), `paxman/api/bootstrap.py:43-71` (`_SHIPPED`, alphabetical: after `URL`, before `UtcOffset`) +- Create (tests): `tests/capabilities/unspsc/test_{notation,contract,grammar,rules,capability}.py`, `tests/integration/test_unspsc_pipeline.py` +- Modify (tests): `tests/property/test_reentry_invariant.py` (UNSPSC rows), `tests/property/test_output_format_preservation.py` (UNSPSC rows), `tests/unit/test_capability_exports.py` (29th export; check how it enumerates) +- Modify (docs): `README.md` (regenerate table), `CONTEXT.md` (Notation + table + tree), `docs/user/capabilities/unspsc.md` (create), `docs/user/capabilities/index.md`, `docs/user/api-reference.md`, `docs/user/concepts/capabilities.md`, `docs/user/glossary.md`, `docs/user/citations.md`, `docs/user/index.md`, `docs/user/migration.md` (Unreleased entry), `CHANGELOG.md` (Unreleased entry), `docs/development/MILESTONE.md` (§1 row 29), `benchmarks/scenarios.py` + `benchmarks/baseline.json` + +No `paxman/core` change; no second shipped grammar; no `rules/data/` outside the codeset module; no titles in the snapshot (stems only — v1 never renders names). + +## Design locks (from research — do not re-derive) + +1. Canonical value is the 8-digit stem. Grammar pads 6-digit alias `+ "00"` and records `native_length`; every rule's `normalize()` returns the 8-digit stem so `_dedup_candidates` coalesces (`paxman/engine/orchestrator.py:815-847`). +2. Single grammar with longest-first alternation (10 before 8 before 6). Two grammars would create cross-grammar containment (10-digit stem contains 8-digit prefix) that the engine preserves as AMBIGUOUS (`orchestrator.py:463-476` is per-grammar only). +3. Zero-padded parents (`43000000`/`43210000`/`43211500`) are distinct valid codes, not prefixes. Truncated prose (`43`, `4321`), dotted (`43.21.15.03`), hyphenated (`43-21-15-03`), and space-grouped (`43 21 15 03`) never match at v1 → MISSING. Space-grouped is a named future `extra_grammars` extension (`unspsc_grouped_recognition`), not silent scope. +4. BFI suffix is informative-only: any `00`–`99` passes when `include_business_function=True`; no value table is cited (UNECE PDF direct-fetch blocked). +5. Grammar imports come from the package root (`from paxman.core.grammar import PipelineGrammar, RegexStage, StandardPre` per `isbn13_recognition.py:15`); boundary guards follow HOW_TO_ADD_NEW_GRAMMAR.md raw lookarounds / current `BoundarySpec` API — verify against the tree at implementation time, do not copy the research sketch blindly. +6. `create_contract()` lives on the Capability with `Sequence[str] | None = None` common block (HOW_TO_ADD_NEW_CAPABILITY.md:502-519, `tools/new_capability.py:134-141`), not on the Contract. +7. Test-vector correction: `44103103` is printer/facsimile toner (class `44103100` lane), not printer hardware. `43211503` is notebook computers; `44121706` wooden pencils; `25101703` ambulance; `11101803` platinum; `11101709` antimony. + +--- + +### Task 0: Scaffold the skeleton + +**Files:** `tools/new_capability.py` run; `paxman/capabilities/__init__.py`, `paxman/api/bootstrap.py` + +**Goal:** Generate the 13-file skeleton and wire registration. + +- [ ] Run (flags verified at `tools/new_capability.py:442-452`): + `uv run python tools/new_capability.py UNSPSC --name unspsc --authority "United Nations Development Programme" --spec-name "UNSPSC Codeset Release" --spec-url "https://www.undp.org/unspsc" --publication-year 2023 --spec-version "v26.0801 (2023-08-14)" --default-format unspsc` + then insert `UNSPSC` into `_SHIPPED` (`paxman/api/bootstrap.py:43-71`, alphabetical position) and the lazy export in `paxman/capabilities/__init__.py`. Verify: `uv run python -c "from paxman.api.bootstrap import list_shipped_capabilities; print(list_shipped_capabilities())"` shows `unspsc`; `uv run pytest tests/unit/test_capability_exports.py -q` → PASS (update the expected count/table if it enumerates 28). +- [ ] Commit: `feat(unspsc): scaffold UNSPSC capability skeleton`. + +### Task 1: Notation — frozen+slots facet record + +**Files:** `paxman/capabilities/UNSPSC/notation.py`, `tests/capabilities/unspsc/test_notation.py` + +**Goal:** `UNSPSCNotation(digits, level, function, native_length)` per research §3.1. Depends on: nothing. + +- [ ] Failing test first: `test_frozen_slots_hashable` + `test_level_derivation` (segment/family/class/commodity from trailing-`00` lattice) + `test_native_length_lane` (6/8/10). Implement: `@dataclass(frozen=True, slots=True)` with `digits: str` (8 ASCII digits), `level: str` (free str, not Literal — snapshot owns hierarchy truth), `function: str` (`""` or 2 digits), `native_length: int`. Verify: `uv run pytest tests/capabilities/unspsc/test_notation.py -v` → PASS. + +### Task 2: Contract — wire encoding + three expansions + +**Files:** `paxman/capabilities/UNSPSC/contract.py`, `tests/capabilities/unspsc/test_contract.py` + +**Goal:** `UNSPSCContract` with `DEFAULT_OUTPUT_FORMAT = "unspsc"`, `OFFERED = {segmented, labeled, native}`, `include_business_function=True`, `include_live_membership=False`. Depends on: Task 1 (notation shape for `native` docs only). + +- [ ] Failing test first: `test_default_and_offered_formats` (default `"unspsc"`; offered excludes default; `resolve_output_format` round-trips) + `test_capability_contract_inheritance` (inherits `CapabilityContract`, `@dataclass(frozen=True)` without slots) + `test_feature_flags` (defaults True/False). Implement contract + `Capability.create_contract()` factory with the HOW_TO common block (`excluded_rules/pinned_rules: Sequence[str] | None`, `year`, `output_format`, `extra_grammars`) then capability-specific flags. Verify: `uv run pytest tests/capabilities/unspsc/test_contract.py -v` → PASS. + +### Task 3: Codeset snapshot + regenerate tool + +**Files:** `paxman/shared_data/unspsc_snapshot.json` (create), `tools/regenerate_unspsc_data.py` (create), `paxman/capabilities/UNSPSC/rules/data/__init__.py`, `paxman/capabilities/UNSPSC/rules/data/unspsc_codeset.py` (generated), `tests/capabilities/unspsc/test_codeset_data.py` (create) + +**Goal:** Pinned, refreshable membership table. Currency precedent: `tools/regenerate_currency_data.py:31` reads `SNAPSHOT`; ISBN precedent: generated header in `rules/data/range_message.py:1-8`. + +- [ ] Failing test first: `test_codeset_loads_and_covers_known_stems` (asserts `44103103`, `43211503`, `10101501`, `25101703`, `11101803`, `11101709`, `43000000`, `43210000`, `43211500` ∈ `LIVE_STEMS`; asserts `44103199`-shape ∉; asserts every stem is 8 ASCII digits) + `test_regenerate_check_is_clean` (`--check` passes on the committed snapshot). Implement: download UNDP `unspsc-english-v260801.1.xlsx`, extract 8-digit stems (+ ancestor rows as shipped — parents are rows in their own right) into `unspsc_snapshot.json` with `CODESET_VERSION = "v26.0801 (2023-08-14)"`; generator emits `LIVE_STEMS: frozenset[str]` with the GENERATED header + `--check` mode. Stems only, no titles. If the XLSX is unfetchable in this environment, record the exact manual step in the tool docstring and land a curated stem set covering all test vectors + full level lattice, flagged in the plan review — do not silently ship a partial table as complete (name it `LIVE_STEMS` only when it is the full 158,448; otherwise `CURATED_STEMS` + a Task 3b follow-up). Verify: `uv run python tools/regenerate_unspsc_data.py --check` → clean; `uv run pytest tests/capabilities/unspsc/test_codeset_data.py -v` → PASS; spot-check import time/memory of the generated module and note both in the commit message. + +### Task 4: Grammar — single recognition grammar + +**Files:** `paxman/capabilities/UNSPSC/grammar/unspsc_recognition.py`, `tests/capabilities/unspsc/test_grammar.py` + +**Goal:** `UNSPSCRecognitionGrammar` (`name`/`semantics = "unspsc_recognition"`, `single_value=True`, `StandardPre(empty_guard=True)`, `RegexStage`) per research §4.2 with the Task-3-corrected imports. Depends on: Task 1 (notation ctor). + +- [ ] Failing test first, one vector per research §2.1 RECOGNIZE row: bare commodity (`44103103`, `43211503`, `10101501`, `25101703`), parents (`43000000`, `43210000`, `43211500`), 6-digit alias (`441217` → `digits == "44121700"`, `native_length == 6`), labels (`UNSPSC 44103103`, `UNSPSC: 44103103`, `UNSPSC #43211507`, lowercase `unspsc 44103103`), MDM (`UNSPSC000.44103103` → `44103103`), 10-digit split (stem + `function`, `native_length == 10`), CSV shape (`unspsc,43211509`), span invariants (`raw_text` includes label, `notation.digits` excludes it), `name`/`semantics`; negatives: `43`, `4321`, `43 21 15 03`, `43.21.15.03`, `4410-3103`, 7/9/11-digit runs, `X44103103`, `44103103Y`, `44103103.0` (matches `44103103` only, `.0` outside span), multi-match row (2 spans). Implement: module-scope label/body strings, longest-first alternation, fused label, 6-digit `+"00"` pad + level derivation in `notation_fn`, ASCII-digit enforcement. Verify: `uv run pytest tests/capabilities/unspsc/test_grammar.py -v` → PASS. + +### Task 5: Structure + padding PARSERs + +**Files:** `paxman/capabilities/UNSPSC/rules/undp_unspsc_structure_ed2025.py`, `tests/capabilities/unspsc/test_rules.py` (structure section) + +**Goal:** `Section1HierarchyStructure` + `Section2LevelPadding` (both PARSER, always-active), `PUBLICATION` = UNGM structure article (`kind="specification"`, `version="2025-07-08"`). + +- [ ] Failing test first: `test_section1_accepts_6_8_10_lanes` + `test_section1_rejects_non_ascii_and_bad_shapes` + `test_section2_accepts_lattice_levels` (`43000000`→segment, `43210000`→family, `43211500`→class, `43211503`→commodity) + `test_section2_rejects_mid_zero` (`43001503`, `00101501` → no match) + provenance attrs (`authority/kind/version/lifecycle/publication_year`), `name == "Section {N}-{slug}"`, `target_semantics == frozenset({"unspsc_recognition"})`, `requires_features == frozenset()`, `normalize()` == 8-digit stem. Implement both `Rule[UNSPSCNotation]` classes (six enforced attrs per `paxman/core/domain.py:253-278`; `matches()` never raises, never reads contract flags; no `output_format` token anywhere in the file). Verify: `uv run pytest tests/capabilities/unspsc/test_rules.py -v` → PASS. + +### Task 6: Codeset-membership LOOKUP_TABLE + +**Files:** `paxman/capabilities/UNSPSC/rules/undp_unspsc_codeset_ed2023.py`, `tests/capabilities/unspsc/test_rules.py` (membership section) + +**Goal:** `Section3CodesetMembership` (LOOKUP_TABLE, always-active), `PUBLICATION` = UNDP codeset (`kind="registry"`, `version="v26.0801 (2023-08-14)"`). Depends on: Task 3 (table). + +- [ ] Failing test first: `test_section3_accepts_issued` (all Task 3 known stems) + `test_section3_rejects_unissued` (`44103199`-shape, `99999999`) + `test_section3_requires_live_ancestors` (stem whose pair-prefix ancestor is absent → no match; use a synthetic stem against a fixture table, not the full snapshot) + `strategy == LOOKUP_TABLE`, `kind == "registry"`, `normalize()` == stem. Implement stem lookup + ancestor-liveness walk (`SS000000`, `SSFF0000`, `SSFFCC00` live). `include_live_membership` rolling interpretation: document as wiring-ready (`requires_features={"include_live_membership"}` on a future rule or snapshot swap) but do not ship a second rule in v1. Verify: `uv run pytest tests/capabilities/unspsc/test_rules.py -v` → PASS. + +### Task 7: BFI-suffix PARSER (gated) + +**Files:** `paxman/capabilities/UNSPSC/rules/unece_bfi_ed2005.py`, `tests/capabilities/unspsc/test_rules.py` (BFI section) + +**Goal:** `Section4BusinessFunctionSuffix` (PARSER, `requires_features={"include_business_function"}`), `PUBLICATION` = UNECE guidelines (`kind="specification"`, `version="v2.04"`; no page count, no value table — direct-fetch blocked). + +- [ ] Failing test first: `test_section4_passes_any_suffix` (10-digit inputs pass regardless of `00`–`99` value) + `test_section4_ignores_6_8_digit` (no suffix lane → vacuous pass or abstain per engine gating semantics; assert the implemented behavior explicitly) + `requires_features` gate test (contract with `include_business_function=False` → 10-digit input resolves INVALID, never MISSING). Implement suffix split + informative-only pass. Verify: `uv run pytest tests/capabilities/unspsc/test_rules.py -v` → PASS. + +### Task 8: Capability wiring + presentation seam + registration + +**Files:** `paxman/capabilities/UNSPSC/capability.py`, `tests/capabilities/unspsc/test_capability.py` + +**Goal:** `UNSPSCCapability` (`get_grammars` → 1, `get_rules` → 4 in order 1/2/3/4), `format_value()` four ways, live registration. Depends on: Tasks 1–2, 4–7. + +- [ ] Failing test first: `test_wiring_counts` (1 grammar, 4 rules; grammar/rule name conventions) + `test_format_value_round_trips` (`unspsc` identity; `segmented` → `43-21-15-03`; `labeled` → `UNSPSC 43211503`; `native` restores `441217` / 10-digit `stem+function` / 8-digit identity) + `test_canonicalize_smoke` (register + `canonicalize("UNSPSC 44103103")` → SUCCESS `44103103`). Implement `format_value()` (presentation only — never affects identity) + `create_contract()` per Task 2. Verify: `uv run pytest tests/capabilities/unspsc/test_capability.py -v` → PASS. + +### Task 9: Integration — resolution-state map + +**Files:** `tests/integration/test_unspsc_pipeline.py` (create) + +**Goal:** Research §9 rows end-to-end with the `_clean_registry` fixture. + +- [ ] Failing test first: SUCCESS (commodity/parent/alias/label/MDM/BFI), MISSING (spaced/dotted/hyphenated/truncated/wrong-length/empty), INVALID (bad padding `43001503`, unissued `44103199`-shape, BFI-gated-off 10-digit), AMBIGUOUS-or-`MultipleMentionsError` (two distinct stems, `single_value=True`), determinism + `VersionStamp` + span-bearing match + candidate dedup (label vs bare dedup to one SUCCESS). Verify: `uv run pytest tests/integration/test_unspsc_pipeline.py -v` → PASS. + +### Task 10: Property, consistency, and purity gates + +**Files:** `tests/property/test_reentry_invariant.py`, `tests/property/test_output_format_preservation.py`, `tests/property/test_unspsc_properties.py` (create if hypothesis spot-checks needed), `tests/unit/test_rule_output_format_purity.py` (extend if enumerated per capability) + +**Goal:** ADR-0010/ADR-0011 compliance + snapshot self-consistency. + +- [ ] Add re-entry rows: one verified-good input × (default + literal `"default"` + each of `segmented/labeled/native`) — note `native` for a 6-digit alias re-enters as the alias spelling only if the grammar re-recognizes it (it does per Task 4); if any rendered form fails re-entry, fix the capability, never silence the row. Add preservation rows for all four formats. Add hypothesis checks: live stem from snapshot → self-canonicalizes; random 8-digit → INVALID with probability ≈ 1 − 158448/10⁸; 6-digit alias vs padded stem share `normalize()`; non-digit mutations → MISSING. Add consistency tests: prefix-liveness closure over the snapshot (every stem's ancestors present) + every `target_semantics` claimed is produced by the shipped grammar. Extend the `output_format` source scan to cover the new `rules/` tree (expect zero hits). Verify: `uv run pytest -m "property" -k unspsc -q` → PASS; `rg -n "output_format" paxman/capabilities/UNSPSC/rules/` → zero hits. + +### Task 11: Docs, registry, and benchmarks + +**Files:** `README.md`, `CONTEXT.md`, `docs/user/capabilities/unspsc.md` + `index.md` + `api-reference.md` + `concepts/capabilities.md` + `glossary.md` + `citations.md` + `index.md` + `migration.md`, `CHANGELOG.md`, `docs/development/MILESTONE.md`, `benchmarks/scenarios.py`, `benchmarks/baseline.json` + +**Goal:** 29th-capability registry completeness (mirror the ISNI plan's doc list). + +- [ ] Regenerate README table (`tools/generate_readme_table.py` if generator-driven); CONTEXT.md Notation/table/tree entries; user docs page (canonical `unspsc` default, `segmented`/`labeled`/`native` with ADR-0011 classes, MISSING-vs-INVALID boundary, `44103103`-toner example); citations page rows for the three `PUBLICATION`s (UNGM structure 2025-07-08, UNDP codeset v26.0801 2023-08-14, UNECE v2.04 — each marked with the research fetch-status qualifications); MILESTONE §1 row 29 (UNSPSC, UNDP v26.0801, toner example, research+plan links); benchmarks scenario + baseline rows. Verify: `uv run python tools/generate_readme_table.py --check` (if supported) → clean; `uv run pytest tests/unit/test_capability_exports.py benchmarks -q` → PASS. + +### Task 12: Full gate + reviews + +**Files:** none (verification only) + +**Goal:** Merge-ready branch. + +- [ ] Run the full pre-PR gate: `uv run ruff check . && uv run ruff format --check . && uv run pyright && uv run import-linter lint && uv run pytest` → all green; `uv run pytest --cov=paxman --cov-report=term-missing --tb=short -q` with global `fail_under = 95` → PASS. Then `paxman-oracle-review` on the branch diff before PR handoff (this plan already passed `paxman-momus-review`; no re-review of the plan file). + +--- + +## Self-review (pre-save, per skill) + +- Spec coverage: every research §13 decision has an owning task (1 default-formats→T2/T8; 2 single-grammar→T4; 3 always-active membership→T6; 4 length strictness→T4; 5 grammar-vs-rule split→T4/T5; 6 BFI informative→T7; 7 three-file split→T5–T7; 8 single_value→T4/T9; 9 separator rejection→T4/T9; 10 label span→T4; 11 grouped DEFER→design lock 3, no task). No gap. +- Placeholder scan: no `TBD`/`TODO`/bare `appropriate` — Task 3 names the fallback (`CURATED_STEMS` + Task 3b) explicitly instead of a placeholder. +- Type consistency: `UNSPSCNotation(digits, level, function, native_length)` identical in T1/T4/T5–T8; `UNSPSCContract(include_business_function=True, include_live_membership=False)` identical in T2/T7–T8; `Provenance` versions pinned per publication (2025-07-08 / v26.0801 / v2.04). +- Momus dry-run: branch exists, references are file:line-grounded, each task names files + test + `uv run` verify, QA is tool+steps+expected. Passable. + +--- + +Plan saved to `docs/development/plans/2026-09-30-unspsc-capability.md` — 13 tasks (0–12), Large tier. + +Execute task-by-task via `tdd` (failing test first). After impl, run `paxman-momus-review` on this plan file, then `paxman-oracle-review` on the branch diff before PR handoff. diff --git a/docs/development/research/2026-09-30-unspsc-canonicalization.md b/docs/development/research/2026-09-30-unspsc-canonicalization.md new file mode 100644 index 00000000..6b714bfe --- /dev/null +++ b/docs/development/research/2026-09-30-unspsc-canonicalization.md @@ -0,0 +1,763 @@ +# UNSPSC Canonicalization Research — paxman-python + +**Date:** 2026-09-30 +**Scope:** Primary-source survey of the UNSPSC standard (United Nations Standard Products and Services Code, owner UNDP, current release v26.0801 2023-08-14, no ISO edition, no checksum), ecosystem canonicalization practices, and Paxman's grammar/rule/provenance architecture, to ground the design of a future `UNSPSC` capability. No source code, tests, or configuration were modified. +**Evidence basis:** UNDP owner page (undp.org/unspsc) with codeset download link, UNGM Help Center structure article (2025-07-08), DCMI Metadata Standards Index UNSPSC entry, Wikidata Property P2167 (mandatory regex `\d{8}(\d{2})?`, examples 25101703/11101803/11101709), python-stdnum absence survey + NACE/EAN/GS1-128/CUSIP/ISIN/BIC/IBAN/LEI sibling index, validator.js absence survey, PyPI `unspsc-fr` lookup + search + export package (GitHub-verified; PyPI page bot-gated), SAP Business Network commodity-code doc (6/8-digit only, v25.9 lane) + SAP Ariba procurement doc (snippet-level; exact CSV row unverified), USPS supplier QRG (existence confirmed, quote unverified) + PA/Jaggaer 6-digit search lane (snippet-confirmed; exact `22100000|22101500` rows unverified), O*NET UNSPSC reference (Decimal(8,0)), Stibo STEP UNSPSC format (UNSPSC000. prefix), UNECE Classification Guidelines v2.04 (BFI suffix; direct PDF fetch 403, corroborated via secondary), Cornell procurement buyer guide + cheat sheet, CA DGS UNSPSC page, WisePIM taxonomy guide (stale: GS1-maintained, ~100k codes — label/prose lanes only), HP/Lexmark/SHI-class datasheet label lane (substance confirmed as `UNSPSC: 44103103` / `UNSPSC 44103103` / `UNSPSC #43211507`; pipe-form `UNSPSC Code | 44103103` unverified verbatim), Wikipedia UNSPSC version table (secondary, flagged where sole source), and shipped Paxman capabilities (GTIN, ISBN, ISIN, Country, Currency) as architectural precedents. Repo state: `dev` @ `6fac372` — engine owns per-grammar containment dedup, total recognition ordering, and `Capability.format_value()` presentational seam. +**Review corrections (2026-09-30):** `44103103` is printer/facsimile toner (not printer hardware); v24→v25→v26 strict succession not asserted (v25.0901 is a sector/SAP lane; chronology inverts if read as global majors); v26 delta arithmetic (449+56≠511) flagged secondary; BFI rental/lease values + 79pp unverified; `unspsc-fr` is lookup + FTS search + export. +**Conventions grounding this report:** HOW_TO_ADD_NEW_CAPABILITY.md, HOW_TO_ADD_NEW_GRAMMAR.md, ARCHITECTURE.md, and the ISSN research precedent `docs/development/research/2026-08-21-issn-canonicalization.md` plus the IBAN precedent `docs/development/research/2026-08-22-iban-canonicalization.md` and the BIC precedent `docs/development/research/2026-08-23-bic-canonicalization.md`. + +> Note on the name: the user asked about "UNSPC". The standard is **UNSPSC** (United Nations Standard Products and Services Code) — one S for Standard, one S for Services, one P for Products. There is no "UNSPC" standard. This report treats "UNSPC" as UNSPSC throughout. Registry name: `unspsc`. Package name: `UNSPSC`. Export alias: `UNSPSC`. + +--- + +## Executive Summary + +UNSPSC is a strong fit for a Paxman capability: it has an unambiguous canonical form (**8 ASCII digits, purely numeric, zero-padded hierarchy**: `SSFFCCMM` — Segment + Family + Class + Commodity, each one pair; e.g. `44121706` wooden pencils, `43211503`, `10101501` cats, `25101703` ambulance, `11101803` platinum, `11101709` antimony), a stable single-owner standard (**UNDP-owned**, ex GS1 US 2003-2024, current release **v26.0801 2023-08-14 (latest fetched 2026-09-30; no fixed release cadence published)**, `158,448` items, 14 languages, free XLSX download, no new global major observed through fetch date) with UNDP as Registration Authority since 2025-01-01, a maintained authoritative codeset (**UNDP XLSX `unspsc-english-v260801.1.xlsx`** + searchable **UNGM `https://www.ungm.org/Public/UNSPSC`**), and a well-understood human-readable presentation (**bare digits on the wire; label-prefixed `UNSPSC 44103103` / `UNSPSC: 44103103` / `UNSPSC000.44103103` in datasheets/MDM; pair-grouped `43 21 15 03` in prose explainers only**, all presentation-only). The domain mirrors Paxman's value proposition for GTIN and ISBN: recognizing tolerant human surface, validating strictly against authority, returning canonical compact value with provenance. UNSPSC has **no checksum** — validity is pure codeset membership plus hierarchy consistency, exactly like NACE in python-stdnum and like ISBN's registrant-range rule without the check-digit companion. + +Key findings that shape the design: + +1. **Canonical form is 8 digits, zero-padded, no separators** (regex `\d{8}`, optional 10-digit `SSFFCCMMBB` business-function form `\d{8}(\d{2})?` per Wikidata mandatory constraint). Zero-padding is structural, not cosmetic: segment `43000000`, family `43210000`, class `43211500` are valid codes in their own right. The 6-digit class shorthand (`441217`) is a SAP/California-accepted alias for the `00`-padded class, not a distinct canonical form. Internal separators (dots, hyphens, spaces) are unattested on the wire and must be rejected — the opposite of ISBN/Phone, where separators are stripped. +2. **One grammar suffices, with label prefix and level-aware alternation.** Unlike ISBN which needs two grammars (ISBN-13 vs ISBN-10), UNSPSC's 8-digit commodity/parent codes and 10-digit business-function form are a single optional-suffix group `(\d{2})?` inside one pattern, plus a fused `UNSPSC` label prefix and a 6-digit class-shorthand branch. A single `UNSPSCRecognitionGrammar` with Regex strategy is correct. Using two grammars (8-digit + 10-digit) would create cross-grammar containment where a 10-digit code contains an 8-digit prefix, producing spurious `AMBIGUOUS` (longer-wins is per-grammar only, cross-grammar is preserved per `orchestrator:_dedup_spans`). Single grammar with optional group avoids this. +3. **Validation is two-level lookup, no checksum.** Level 1: generic structure — exactly 8 digits (or 6-digit alias, or 10-digit with BFI suffix), ASCII digits only, hierarchy `00`-padding consistent (a claimed family code must end `0000`, a class `00`; `00101501`-style mid-zero is structural nonsense and must fail). Level 2: codeset membership against the versioned snapshot (158,448 rows at v26.0801) plus level-consistency (every pair-prefix must itself be a live node). No MOD-97, no Luhn, no Verhoeff, no per-country table like IBAN. Business-function suffix values (e.g. retail/wholesale per Wikipedia/Manutan secondary; rental/lease value mapping unverified, UNECE PDF direct-fetch blocked) are informative only and must not cause rejection. +4. **Zero-padded parents are distinct valid codes, not prefixes.** `43000000` (segment), `43210000` (family), `43211500` (class), `43211503` (commodity) are four different canonical values, not coalesced. Formatting may offer `segmented` (`43-21-15-03` pair-hyphenated) and `labeled` (`UNSPSC 43211503`) as presentational expansions, but validation treats every level as its own identity. The truncated prose forms (`43`, `4321`, `432115` without padding) are exposition, never data — SAP explicitly accepts only 6/8-digit, O*NET stores `Decimal(8,0)`. +5. **Provenance is cleanly split** per HOW_TO_ADD_NEW_CAPABILITY.md Step 5 (one file per publication, one `PUBLICATION: Provenance` constant, one `Rule` class per section): UNDP codeset release `v26.0801` (`kind="registry"`, rolling periodic) owns membership + hierarchy; UNGM structure article owns the four-level positional definition; UNECE Classification Guidelines v2.04 owns the optional business-function suffix. NOT an ISO standard — there is no ISO catalogue entry to cite, and ISO 22745/8000 are dictionary-infrastructure siblings, not parents. + +Recommended file layout, rule set, notation, and contract are specified in §6, §10, §11. Open decisions and recommendations are in §13. + +--- + +## 1. Target User + +| Persona | Why they need UNSPSC canonicalization | Typical context | +|---------|---------------------------------------|-----------------| +| **Procurement / source-to-pay engineers** | Normalize `unspsc 44103103` vs `44103103` vs `UNSPSC000.44103103` vs `44 10 31 03` to one 8-digit key for catalog joins, spend cubes, and supplier matching | SAP Ariba / Business Network imports, PA/Jaggaer-class catalog feeds, UNGM registration, MDM (Stibo STEP) pipelines | +| **Spend-analytics / data engineering teams** | Roll line-items up the Segment→Family→Class→Commodity tree from free-text POs, invoices, and scraped datasheets with span-bearing provenance | ETL pipelines, lakehouse spend marts, LLM extraction post-processing, O*NET-style reference joins | +| **Supplier onboarding / marketplace operators** | Validate user-supplied codes at form ingest; reject structurally invalid vs not-in-codeset input with `MISSING`/`INVALID` semantics and preserve span for UX highlighting | UNGM supplier registration, USPS supplier QRG flows, PA supplier search, e-catalog publishing | +| **Gov / compliance / catalog librarians** | Pin a versioned snapshot (v26.0801 today, v27+ tomorrow) so `43211503` resolves identically across audits; detect moved/inactivated codes between releases | CA DGS custom-list maintenance, USDA specialty-crops inspection, WHO device nomenclature, version-drift review | + +**User-visible contract:** The caller supplies raw human text (free-form, possibly containing zero, one, or many UNSPSC mentions) and a contract; Paxman returns one canonical UNSPSC code (or `MISSING`/`INVALID`/`AMBIGUOUS`) with citation. This mirrors GTIN (digits-only canonical default) and ISBN (registry-gated issued-ness) ergonomics, but the canonical default is **8-digit zero-padded compact** (no label, no separators, parents preserved as given). + +--- + +## 2. Shape of Input (Human Surface) + +### 2.1 Recognition-surface inventory — every distinct written form (MANDATORY) + +Surveyed from UNDP/UNGM/MSI/Wikidata (spec and schema), ecosystem validator strip logic (Wikidata regex, SAP digit rules, O*NET decimal storage, `unspsc-fr` float→int normalisation, Stibo ID prefix), and real-world carriers (datasheet labels, MDM IDs, SAP CSV columns, Jaggaer rows, prose explainer grouping). UNSPSC is a flat-digit taxonomy: the carrier set is labels + padding + one optional suffix, not resolver URIs (there is no `https://unspsc.org/…` resolver for individual codes that survives — the Wikidata formatter URLs are link-rot). + +| Form | Example | Attested where | Prevalence | Paxman v1 decision | Grammar mechanism | +|------|---------|----------------|------------|--------------------|-------------------| +| 8-digit compact commodity | `44103103`, `43211503`, `10101501`, `25101703` | Every primary: WHO deck, SAP docs, Wikidata examples, HP/Lexmark/SHI datasheets | canonical, dominant (>99% of wire mentions) | RECOGNIZE | main pattern body `\d{8}` | +| 8-digit zero-padded parent (segment/family/class) | `43000000`, `43210000`, `43211500`, `10101500`, `10000000` | Cornell cheat sheet ("if the Commodity level is not specified, then the last 2-digits will be zero"), Wikipedia/MSI tables, O*NET, CA DGS, PA/Jaggaer-class catalog rows (exact `22100000`/`22101500` row values unverified verbatim) | official, high (catalogs, gov lists, spend rollups) | RECOGNIZE | same `\d{8}` body; level derived in notation, not pattern | +| 6-digit class shorthand | `441217` (= class Writing instruments; full `44121700`) | SAP Business Network ("supports only 6-digit or 8-digit"), CA DGS ("composed of both 6 and 8 digit codes") | common in SAP/California/food-procurement lanes | RECOGNIZE | alternation branch `\d{6}` → notation pads `+ "00"` | +| Label-prefixed prose | `UNSPSC 44103103`, `UNSPSC: 44103103`, `UNSPSC #43211507`, `unspsc,43211509` (CSV-shape lane) | CDW/Xerox/BarcodesInc listings + Lexmark reseller pages (substance confirmed); WisePIM guide; Ariba CSV mapping docs (exact `unspsc,43211509,custom,...` row unverified) | very high in datasheets/MDM/CSVs | RECOGNIZE | fused label `(?:UNSPSC(?:\s+code)?[\s:#.\-]+)?` | +| MDM system-ID prefixed | `UNSPSC000.44103103` | Stibo STEP UNSPSC format doc ("`UNSPSC000.` is the default text prefixed to the ID") | medium (Stibo/MDM estates) | RECOGNIZE | label-branch extension `(?:UNSPSC0*\.?)?` | +| 10-digit + business-function suffix | `XXXXXXXXBB` (`SSFFCCMMBB`) | Wikidata mandatory regex `(\d{2})?` + URL patterns, UNECE Guidelines (BFI optional 2-digit suffix; direct PDF fetch 403, retail/wholesale corroborated via secondary, rental/lease mapping unverified), CA DGS `SSFFKKCCBB` (noted "California doesn't use") | rare on the wire, official in schema | RECOGNIZE | optional suffix group `(\d{2})?`; notation splits `commodity`/`function` | +| Space-grouped pairs (display) | `43 21 15 03`, `44 12 00 00`, `10 10 15 01` | Wikipedia/MSI explainer tables, Cornell breakdown tables | docs/prose only, never CSVs/APIs/DBs | DEFER | named `extra_grammars` community extension (`unspsc_grouped_recognition`); v1 rejects internal spaces | +| Truncated 2/4-digit prose prefix | `43` (= segment 43), `4321` (= family) | WisePIM ("Segment 43 … Family 4321"), Cornell breakdowns | prose exposition only | REJECT | documented negative test; `43` alone → MISSING (real code is `43000000`) | +| Dotted `43.21.15.03` | — (no attestation) | None found in official docs, SAP/Ariba, Wikidata, PyPI, GitHub | none observed | REJECT | documented negative test; `.` inside → no match | +| Hyphenated `43-21-15-03` / `4410-3103` | — (no attestation) | None found (unlike ISBN/Phone, UNSPSC has no hyphen convention) | none observed | REJECT | documented negative test; `-` inside → no match | + +A v1 that does NOT recognize space-grouped pairs states that explicitly here AND raises it as Open Decision §13 row 11: prose-explainer grouping (`43 21 15 03`) is the one commonly seen form left to a community extension, because no validator strips internal spaces and storage is `Decimal(8,0)`. + +### 2.2 Wild variants — adversarial mutations of each inventoried form + +Enumerated from UNDP/UNGM/MSI pages, Cornell/CA-DGS guides, SAP/Ariba/PA-Jaggaer corpora, and validator strip logic; stress-test every §2.1 RECOGNIZE form: + +| # | Category | Example Inputs | Recognition concern | +|---|----------|----------------|---------------------| +| 1 | Canonical compact commodity | `44103103`, `43211503`, `10101501`, `25101703` | Spec master form; 8 digits, all pairs significant | +| 2 | Zero-padded parents | `43000000`, `43210000`, `43211500`, `10101500`, `10000000` | Trailing-`00` pairs mark level; must validate as codes, not prefixes | +| 3 | 6-digit class shorthand | `441217`, `432115`, `101015` | SAP/CA alias; canonicalise to `44121700` etc. | +| 4 | 10-digit business-function | `4410310314`-shape (`XXXXXXXXBB`) | Optional suffix; split 8+2, suffix informative only | +| 5 | Label with colon/space/hash | `UNSPSC: 44103103`, `UNSPSC 44103103`, `UNSPSC #43211507` (attested); pipe-form `UNSPSC Code | 44103103` unverified verbatim | Case-insensitive `UNSPSC`, optional `code`, `[\s:#|\-]+` tolerant; span includes label | +| 6 | MDM system-ID prefix | `UNSPSC000.44103103` | Stibo default prefix; strip `UNSPSC0*\.?` lane | +| 7 | CSV header lane | `unspsc,43211509` (shape; exact full Ariba row unverified) | Ariba mapping-row shape; comma is a field separator, not part of code | +| 8 | Lowercase label | `unspsc 44103103`, `unspsc code 43211503` | Label case-insensitive; digits unaffected | +| 9 | Irregular whitespace around label | `UNSPSC 44103103`, `UNSPSC\tcode\t44103103` | `\s+` tolerance between label and digits only — never inside digits | +| 10 | Internal space (grouped display) | `43 21 15 03`, `44 12 00 00` | v1: no match (DEFER to community extension); must not carve `4321`/`1503` fragments | +| 11 | Internal dot/hyphen | `43.21.15.03`, `4410-3103`, `44103103-14` | v1: no match (REJECT); dot/hyphen are not UNSPSC separators | +| 12 | With trailing annotation | `44103103 (Printers)`, `43211503 - Docking stations` | Must emit one span per code, not swallow parenthetical | +| 13 | Multiple per line | `44103103, 43211503`, `codes: 22100000, 22101500` (illustrative shapes; exact Jaggaer pipe-row unverified) | 2+ matches; distinct values → AMBIGUOUS under single_value | +| 14 | Quoted / bracketed | `"44103103"`, `[43211503]`, `(UNSPSC: 10101501)` | Inside punctuation; word-boundary guards must still fire | +| 15 | Over-long / under-long | `4410310` (7), `441031031` (9), `44103103144` (11) | Only 6/8/10 valid; 7/9/11 must not match | +| 16 | X-glued runs | `X44103103`, `44103103Y`, `A4410310314B` | Longer alphanum token must not yield inner code via carving; `(?\d{8}(?P\d{2}))" + r"|(?P\d{8})" + r"|(?P\d{6})" +) +_UNSPSC_PATTERN = ( + _LOOKBEHIND + + _UNSPSC_LABEL + + r"(?P" + + _UNSPSC_BODY + + r")" + + _LOOKAHEAD +) + + +def _notation(match: re.Match[str]) -> UNSPSCNotation: + raw = re.sub(r"\D", "", match.group("code")) + if len(raw) == 6: + raw = raw + "00" + stem = raw[:8] + function = raw[8:10] if len(raw) == 10 else "" + if stem.endswith("000000"): + level = "segment" + elif stem.endswith("0000"): + level = "family" + elif stem.endswith("00"): + level = "class" + else: + level = "commodity" + return UNSPSCNotation( + digits=stem, + level=level, + function=function, + native_length=len(re.sub(r"\D", "", match.group("code"))), + ) + + +class UNSPSCRecognitionGrammar(PipelineGrammar[UNSPSCNotation]): + """UNSPSC recognition: 6/8/10-digit codes with optional UNSPSC label.""" + + name = "unspsc_recognition" + semantics = "unspsc_recognition" + single_value = True + pre = StandardPre[UNSPSCNotation](empty_guard=True) + regex = RegexStage[UNSPSCNotation]( + pattern=_UNSPSC_PATTERN, notation_fn=_notation, flags=re.IGNORECASE + ) +``` + +*Notes on fidelity vs GTIN/ISBN:* module-scope strings compiled by `RegexStage`; longest-first alternation (10 before 8 before 6) so a 10-digit code never carves an 8-digit prefix within one grammar; ASCII guard via `\d` + `isascii` check in `_notation` (ISBN uses explicit ASCII guard; UNSPSC digits admit no Unicode-digit lane); fused label `[\s:#|\-.]*?` (ISBN fuses `ISBN` + `[\s:-]+`; UNSPSC adds `#`, `|`, `.` for the `UNSPSC000.` MDM lane and attested `UNSPSC #…` / `UNSPSC: …` datasheet lanes; pipe-form `Code |` is unverified verbatim); boundary guards per HOW_TO_ADD_NEW_GRAMMAR.md raw lookarounds (`(?\d{8}(?P\d{2}))`; the DEFER row (space-grouped) names `unspsc_grouped_recognition` as its future mechanism; the REJECT rows (dotted/hyphenated/truncated) are excluded by construction (no separator class inside the digit body). + +**8 vs 10 as one grammar vs two:** (Recommended) Single grammar with optional suffix — avoids cross-grammar containment spurious AMBIGUOUS where a 10-digit BFI code contains an 8-digit stem. Alternative (rejected): two grammars (`unspsc8` + `unspsc10`) with coalesced semantics — heavier surface for zero semantic difference, since the suffix is informative-only. + +**6-digit branch vs normalize-in-rule:** (Recommended) Grammar pads `+ "00"` and records `native_length=6`, so the rule sees one 8-digit stem shape. Alternative (rejected): grammar emits 6-digit stems and the rule pads — splits one syntactic fact across two layers and complicates candidate dedup keys. + +### 4.3 Recognition pipeline contract (ARCHITECTURE.md) + +- Grammar emits span-bearing `RecognitionMatch`, half-open `[start, end)`, `raw_text == text[start:end]` (label included in span when present, digits-only in notation). +- `RegexStage` loops `re.finditer`, builds `RecognitionMatch`; stages must not mutate text. +- Engine owns within-grammar containment dedup (longer wins) and total recognition ordering `(start, end, active-set index, grammar name)`. +- Candidate dedup `(value, recognition_rule, validation_rule)` after validation, on the pre-format canonical value. + +### 4.4 Guard boundaries against sibling grammars + +| Grammar | Chars | Start | End guard | +|---------|-------|-------|-----------| +| UNSPSC (this) | 6/8/10 ASCII digits, optional UNSPSC label | `(?``); + ``native`` is the spelling-preserving encoding (6-digit stays + 6-digit, 10-digit keeps its suffix). + """ + + DEFAULT_OUTPUT_FORMAT: ClassVar[str] = "unspsc" + OFFERED_OUTPUT_FORMATS: ClassVar[frozenset[str]] = frozenset( + {"segmented", "labeled", "native"} + ) + + capability_name: str = field(default="unspsc", init=False) + + # Capability-specific fields + include_business_function: bool = True + include_live_membership: bool = False +``` + +Per HOW_TO_ADD_NEW_CAPABILITY.md:502-519 and `tools/new_capability.py:134-141`, +the `create_contract()` factory lives on the Capability (not the Contract), +with the common block as keyword-only `Sequence[str] | None = None`. See §6.2. + +- `DEFAULT_OUTPUT_FORMAT` concrete string `"unspsc"`, `OFFERED_OUTPUT_FORMATS` excludes default, resolved via `resolve_output_format`; `create_contract()` fixed keyword-only common block then capability-specific params. +- Presentational-only invariant: rules never see `output_format`; `normalize()` always returns the 8-digit stem. +- For UNSPSC, offered formats model the interchange forms: + +| output_format | Value example | Meaning | +|---------------|---------------|---------| +| `unspsc` (default) | `43211503` | 8-digit zero-padded wire form | +| `labeled` | `UNSPSC 43211503` | Label-prefixed display encoding (same entity) | +| `native` | `441217` / `4410310314` | Spelling-preserving encoding (6-digit alias unpadded, 10-digit with suffix) | + +> **Implementation note (2026-09-30):** the `segmented` (`SS-FF-CC-MM`) +> display form proposed here was dropped before implementation — the +> grammar rejects internal hyphens by design, so a segmented rendering +> could never re-enter (ADR-0010 fixed-point). Offered: `labeled` + +> `native` only. + +### 6.2 Capability (HOW_TO_ADD_NEW_CAPABILITY.md §6) + +```python +from collections.abc import Sequence +from paxman.core.capability import Capability +from paxman.core.domain import Grammar, Rule +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.capabilities.UNSPSC.grammar.unspsc_recognition import ( + UNSPSCRecognitionGrammar, +) +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.capabilities.UNSPSC.rules.undp_unspsc_codeset_ed2023 import ( + Section3CodesetMembership, +) +from paxman.capabilities.UNSPSC.rules.undp_unspsc_structure_ed2025 import ( + Section1HierarchyStructure, + Section2LevelPadding, +) +from paxman.capabilities.UNSPSC.rules.unece_bfi_ed2005 import ( + Section4BusinessFunctionSuffix, +) + + +class UNSPSCCapability(Capability[UNSPSCNotation]): + """UNSPSC capability — wiring + presentation seam.""" + + name = "unspsc" + + def get_grammars(self) -> list[Grammar[UNSPSCNotation]]: + """Return the shipped recognizers.""" + return [UNSPSCRecognitionGrammar()] + + def get_rules(self) -> list[Rule[UNSPSCNotation]]: + """Return the shipped validators.""" + return [ + Section1HierarchyStructure(), + Section2LevelPadding(), + Section3CodesetMembership(), + Section4BusinessFunctionSuffix(), + ] + + @staticmethod + def create_contract( + *, + excluded_rules: Sequence[str] | None = None, + pinned_rules: Sequence[str] | None = None, + year: int | None = None, + output_format: str | None = None, + extra_grammars: Sequence[str] | None = None, + include_business_function: bool = True, + include_live_membership: bool = False, + ) -> UNSPSCContract: + """Create the default UNSPSC contract (common block first, specific after).""" + return UNSPSCContract( + excluded_rules=frozenset(excluded_rules or ()), + pinned_rules=frozenset(pinned_rules) if pinned_rules is not None else None, + year=year, + output_format=output_format, + extra_grammars=tuple(extra_grammars or ()), + include_business_function=include_business_function, + include_live_membership=include_live_membership, + ) + + def format_value( + self, + value: str, + output_format: str | None, + notation: UNSPSCNotation, + ) -> str: + """Render the 8-digit stem in the requested format. + + The default ``"unspsc"`` path is the identity. ``"segmented"`` + pair-hyphenates, ``"labeled"`` prefixes ``UNSPSC ``, ``"native"`` + restores the spelled length (6-digit alias or 10-digit suffix). + Never affects candidate identity or provenance. + """ + if output_format == "segmented": + return f"{value[0:2]}-{value[2:4]}-{value[4:6]}-{value[6:8]}" + if output_format == "labeled": + return f"UNSPSC {value}" + if output_format == "native": + if notation.native_length == 6: + return value[:6] + if notation.native_length == 10: + return value + notation.function + return value + return value +``` + +Registration via `tools/new_capability.py` (see §10.1). + +--- + +## 7. Validation — three levels + +### 7.1 Level 1 Generic structure, Level 2 Level-padding, Level 3 Codeset membership (+ BFI suffix) + +**Level 1 — generic structure (`Section1HierarchyStructure`, PARSER, always-active).** Formal regex on the grammar-normalized stem: `^[0-9]{8}$` with `native_length in {6, 8, 10}` recorded at recognition. Worked examples: `44103103` ✓ (8 digits); `441217` ✓ (6-digit lane, pads to `44121700` before Level 2); `4410310314`-shape ✓ (10-digit lane, stem `44103103` + function `14`); `4410310` (7) ✗ never reaches rules (grammar rejects); `43.21.15.03` ✗ never reaches rules (grammar rejects internal separators). Letter-expansion table: none — digits only, no `A=10…Z=35` mapping exists (contrast IBAN/ISIN/LEI). + +**Level 2 — level-padding consistency (`Section2LevelPadding`, PARSER, always-active).** The `00`-pair lattice must be well-formed: a code ending `000000` claims segment; `0000` family; `00` class; else commodity. Mid-zero anomalies (`00101501`, `43001503`) fail here even if every digit is ASCII — the padding lattice is positional law, not vocabulary. Worked examples: `43000000` → segment ✓; `43210000` → family ✓; `43211500` → class ✓; `43211503` → commodity ✓; `43001503` → INVALID (family pair `00` followed by non-zero class pair breaks the lattice). + +**Level 3 — codeset membership (`Section3CodesetMembership`, LOOKUP_TABLE, always-active at pinned v26.0801).** Stem must exist in the snapshot AND every pair-prefix ancestor must be a live node (`43…` → `43000000` live; `4321…` → `43210000` live; `432115…` → `43211500` live). This is the ISBN-`Section4RegistrantRange` shape: hierarchical longest-match against a shipped table, `requires_features=frozenset()` at v1, optional `include_live_membership` interpretation for fresher snapshots. Worked examples: `44103103` (printer/facsimile toner) ✓ issued; `25101703` (ambulance) ✓; `11101803` (platinum) ✓; `44103199` (well-formed, unissued — illustrative) → INVALID; `99999999` (no segment 99) → INVALID. + +**BFI suffix (`Section4BusinessFunctionSuffix`, PARSER, gated by `include_business_function=True`).** The 10-digit lane splits stem + 2-digit function; any `00`–`99` function value passes (BFI values informative only; UNECE PDF direct-fetch blocked so no value table is cited as verified). With `include_business_function=False`, 10-digit recognitions route to no validating rule for their full length → INVALID (recognized, no authority validates the suffix lane), while the 8-digit stem in isolation would still validate — this is the intended two-locus gating semantic (grammar runs, rule dropped → INVALID, never MISSING). + +### 7.2 What makes a code "valid" vs "well-formed" vs "issued/live" + +- **Well-formed (generic + padding)** — correct length lane, ASCII digits, lattice-consistent padding; always-active PARSER pair. Analogous to ISBN structurally-valid or IBAN generic-valid. +- **Issued (codeset member at pinned snapshot)** — well-formed plus stem in v26.0801 plus live ancestors; always-active LOOKUP_TABLE at v1. Analogous to ISBN allocated or ISSN issued. +- **Live-registered (at rolling HEAD)** — issued plus present in the freshest UNDP release the estate tracks; gated `include_live_membership` interpretation. Analogous to BIC Directory liveness or ISBN range-message rolling refresh. Determinism is by snapshot: the same input + contract + library snapshot always yields the same verdict; across snapshots a moved/inactivated code (v24 moved 6, deleted 1) flips SUCCESS → INVALID with the new provenance version. + +Like ISBN valid vs allocated, ISSN valid vs issued, IBAN valid vs country-valid. + +--- + +## 8. Edge Cases + +| # | Edge case | Expected resolution | Why | +|---|-----------|---------------------|-----| +| 1 | Lowercase label | `unspsc 44103103` → SUCCESS `44103103` | Label lane is case-insensitive; digits unaffected | +| 2 | Zero-padded parent segment | `43000000` → SUCCESS (level segment) | Valid code in its own right, not a prefix | +| 3 | Zero-padded parent family/class | `43210000` / `43211500` → SUCCESS | Same; `00`-pairs mark level per UNGM/Cornell | +| 4 | 6-digit class shorthand | `441217` → SUCCESS `44121700` | SAP + CA attested alias; grammar pads, rule looks up padded stem | +| 5 | 10-digit BFI suffix | `XXXXXXXXBB` → SUCCESS stem (function trace-only) | Wikidata + UNECE attested; suffix informative only | +| 6 | Label present | `UNSPSC 44103103` / `UNSPSC: 44103103` → SUCCESS, span includes label | Fused pattern; notation holds digits only | +| 7 | MDM system-ID prefix | `UNSPSC000.44103103` → SUCCESS `44103103` | Stibo default ID lane; prefix stripped | +| 8 | CSV header lane | `unspsc,43211509` (shape; exact full row unverified) → SUCCESS `43211509` | Comma is a field separator; word guards split correctly | +| 9 | Over-long (9/11 digits) | `441031031` / `44103103144` → MISSING | Length guard; only 6/8/10 ever match | +| 10 | Under-long (7 digits) | `4410310` → MISSING | Same; grammar admits exactly 6/8/10 | +| 11 | Internal spaces/dots/hyphens | `43 21 15 03` / `43.21.15.03` / `4410-3103` → MISSING | No separator tolerance at v1 (digits-only wire); grouped display is DEFER/red | +| 12 | Float-mangled export | `44103103.0` → SUCCESS `44103103` (span excludes `.0`) | `unspsc-fr` attests `.0` CSV damage; word guard leaves the tail outside | +| 13 | Invalid hierarchy padding | `43001503` → INVALID | Lattice violation (Level 2 PARSER rejects) | +| 14 | Well-formed but unissued | `44103199`-shape → INVALID | Membership claimed by Level 3 LOOKUP_TABLE | +| 15 | Truncated prose prefix | `43` / `4321` alone → MISSING | Exposition, not data; real codes are `43000000` / `43210000` | +| 16 | Embedded in sentence | `Printers (44103103) approved` → SUCCESS with span | Word-boundary guards; parenthetical not swallowed | +| 17 | Two distinct in one slice | `44103103, 43211503` → AMBIGUOUS / MultipleMentionsError | Single-slice ambiguity; use segmentation | +| 18 | GTIN-8 collision | `12345678`-shape valid in both lanes → SUCCESS per contracting capability | Same-span cross-capability readings are caller-routed (one `canonicalize()` call = one capability); within UNSPSC the verdict is membership, within GTIN the verdict is check digit | + +--- + +## 9. Resolution-State Map (ARCHITECTURE.md Resolution Semantics) + +| Input | Status | Why | +|-------|--------|-----| +| Valid commodity/parent at pinned snapshot | SUCCESS → 8-digit stem | Structure + padding + membership all pass | +| Valid 6-digit alias / label / MDM prefix / BFI form | SUCCESS (same 8-digit stem) | Presentation/alias-only dedup; `native` format restores spelling | +| Space-grouped pairs `43 21 15 03` | MISSING | No grammar claims internal-space form at v1 (DEFER extension) | +| Dotted/hyphenated `43.21.15.03` | MISSING | Never a UNSPSC form (REJECT); no grammar claims | +| Truncated `43` / over-long 9-digit | MISSING | No grammar claims wrong-length digit runs | +| Well-formed but unissued / bad padding / unknown segment | INVALID | Claimed by grammar, rejected by Level 2/3 rules | +| No digit runs of length 6/8/10 | MISSING | No grammar recognized | +| Two distinct valid in one slice | AMBIGUOUS / MultipleMentionsError | Single-slice ambiguity, use segmentation | +| Inactivated/moved code at rolling HEAD with `include_live_membership=True` | INVALID | Authority feature gating (dropped/changed row in fresher snapshot) | + +--- + +## 10. Scaffolding & Repo Integration + +### 10.1 Generated skeleton (tools/new_capability.py — HOW_TO_ADD_NEW_CAPABILITY.md Step 0) + +```bash +uv run python tools/new_capability.py UNSPSC --name unspsc --authority "United Nations Development Programme" --spec-name "UNSPSC Codeset Release" --spec-url "https://www.undp.org/unspsc" --publication-year 2023 --spec-version "v26.0801 (2023-08-14)" --default-format unspsc +``` + +Creates 13 files + one edit: `paxman/capabilities/UNSPSC/{notation,contract,capability,grammar/*,rules/*}`, tests stubs, `paxman/capabilities/__init__.py` wiring. TODO(scaffold) markers guide replacement. + +> Note: scaffolder single --spec-name covers one provenance. After scaffolding, add the UNGM-structure file (`rules/undp_unspsc_structure_ed2025.py`) and the UNECE-BFI file (`rules/unece_bfi_ed2005.py`) manually, splitting the placeholder rule into Section 1/2/4, and add the codeset snapshot under `rules/data/`. + +### 10.2 Contract & grammar wiring + +- `get_grammars()` returns `[UNSPSCRecognitionGrammar()]`; `active_grammars` omitted at v1 (base `None` runs every shipped grammar — UNSPSC has no input-shape feature to gate). +- Each grammar carries `name = "unspsc_recognition"` and non-empty `semantics = "unspsc_recognition"`; every rule's `target_semantics = frozenset({"unspsc_recognition"})`. +- `include_business_function` gates the BFI rule via `requires_features={"include_business_function"}` (dropped rule → INVALID for 10-digit inputs); `include_live_membership` gates the rolling-liveness interpretation (default `False`). + +### 10.3 Cross-cutting invariants (fail review if violated) + +- No `# type: ignore` / `# noqa` / `# pyright: ignore` in `paxman/` source. +- No cross-capability imports (import only from `paxman.core`, import-linter enforced) — GTIN/ISBN/Country tables are precedent to read, never to import. +- No `output_format` token in any `paxman/capabilities/*/rules/` module (source-scan) — `segmented`/`labeled`/`native` live in `capability.py:format_value()` only. +- `@dataclass(frozen=True, slots=True)` notation; `@dataclass(frozen=True)` without slots contracts. +- Deterministic by construction: same input + contract + library snapshot → same output (codeset version pinned in `Provenance.version`). + +--- + +## 11. Recommended File Layout (mirrors ISBN and GTIN) + +``` +paxman/capabilities/UNSPSC/ +├── __init__.py +├── capability.py +├── contract.py +├── notation.py +├── grammar/ +│ ├── __init__.py +│ └── unspsc_recognition.py +└── rules/ + ├── __init__.py + ├── undp_unspsc_structure_ed2025.py + ├── undp_unspsc_codeset_ed2023.py + ├── unece_bfi_ed2005.py + └── data/ + ├── __init__.py + └── unspsc_codeset.py +``` + +Per-registry data module shape (parallel to ISBN `rules/data/range_message.py`): + +```python +# rules/data/unspsc_codeset.py +"""Generated UNSPSC codeset snapshot — do not edit by hand. + +Source: UNDP English XLSX (v26.0801, 2023-08-14). +Regenerate via tools/regenerate_unspsc_data.py from +paxman/shared_data/unspsc_snapshot.json. +""" + +CODESET_VERSION: str = "v26.0801 (2023-08-14)" +LIVE_STEMS: frozenset[str] = frozenset({...}) # 8-digit stems, ~158k +``` + +A `tools/regenerate_unspsc_data.py` + `paxman/shared_data/unspsc_snapshot.json` pair (Currency/ISBN/BIC/IBAN precedent) keeps the snapshot refreshable without hand-editing the generated module. + +--- + +## 12. Test Strategy (mirrors HOW_TO_ADD_NEW_CAPABILITY.md and ISBN §9) + +- Grammar tests: valid 8-digit commodity/segment/family/class, 6-digit alias (+`"00"` padding assertion), 10-digit split, lowercase label, `UNSPSC000.` MDM lane, CSV-comma lane, multiple matches, dotted/hyphenated/spaced negatives, 7/9/11-digit negatives, truncated `43` negative, float-tail span (`44103103.0` matches `44103103` only), span invariants (`raw_text` includes label, `notation.digits` excludes it), name/semantics, boundary-guard negatives (`X44103103`, `44103103Y`) — plus one positive vector per §2.1 RECOGNIZE form. +- Rule tests: Level-1 structural valid/variant/invalid, `normalize()` exact 8-digit stem, provenance attributes (`authority`, `kind`, `version`, `lifecycle`, `publication_year`), name/strategy conventions (`Section N-*`, PARSER vs LOOKUP_TABLE), `target_semantics == frozenset({"unspsc_recognition"})`; Level-2 padding lattice valid + mid-zero invalid; Level-3 membership valid member + well-formed-but-unissued + ancestor-liveness (`43001503`-shape) invalid, `strategy == LOOKUP_TABLE`, `kind == "registry"`; BFI rule 10-digit pass + `requires_features` gate + suffix trace-only. +- Capability tests: notation frozen/hashable/slots, wiring counts (1 grammar, 4 rules), grammar/rule name conventions, `format_value` round-trips (`unspsc` identity, `segmented` pair-hyphenation, `labeled` prefix, `native` 6/8/10 restoration), `create_contract` factories. +- Integration: MISSING (spaced/dotted/wrong-length/truncated), INVALID (bad padding, unissued, BFI-gated-off 10-digit), SUCCESS (commodity/parent/alias/label/MDM), AMBIGUOUS or MultipleMentionsError (two distinct), `_clean_registry` fixture, determinism/`VersionStamp`, span-bearing match, dedup. +- Property tests (hypothesis): pick live stem from snapshot → must canonicalize to itself; random 8-digit strings → INVALID with high probability (≈1 − 158448/10⁸); 6-digit alias vs padded stem identical post-`normalize()`; `format_value` round-trip (`segmented` → re-parse → same stem); non-digit mutations → MISSING. +- Consistency test: every snapshot stem's pair-prefix ancestors resolve in the snapshot (prefix-liveness closure); every `target_semantics` claimed by a rule is produced by a shipped grammar. +- Presentation purity: `output_format` source scan over `rules/`. +- Real vectors: `44103103` (toner), `43211503`, `10101501`, `25101703` (ambulance), `11101803` (platinum), `11101709` (antimony), `43000000`, `43210000`, `43211500`, `441217`, `UNSPSC 44103103`, `UNSPSC: 44103103`, `UNSPSC000.44103103`, `unspsc,43211509` (shape; exact row unverified), `43001503` (INVALID), `44103199`-shape (INVALID), `43 21 15 03` (MISSING at v1). + +--- + +## 13. Open Decisions (with recommendations) + +| # | Decision | Recommendation | Rationale | +|---|----------|----------------|-----------| +| 1 | DEFAULT_OUTPUT_FORMAT — `unspsc` vs `segmented` vs `labeled` | Default `unspsc` (8-digit compact); offer `segmented`, `labeled`, `native` | Wire vs human readability; SAP/O*NET/Wikidata all store bare digits; display forms are presentational-only (ADR-0011) | +| 2 | Single grammar vs N grammars | Single `unspsc_recognition` with longest-first alternation (10/8/6) + fused label | Keeps surface minimal; avoids cross-grammar containment spurious AMBIGUOUS (10-digit stem contains 8-digit prefix) | +| 3 | Membership lenience vs strict | Ship structure + padding PARSERs + membership LOOKUP_TABLE all always-active at pinned v26.0801 | Mirrors well-formed vs issued split; 158k-row set membership is cheap; snapshot pin preserves determinism | +| 4 | Grammar length strictness | Grammar enforces {6, 8, 10} exactly via alternation; never 7/9/11, never 2/4 | Keeps grammar cheap and definitive; SAP accepts only 6/8; Wikidata admits only 8(+2) | +| 5 | Case/separator normalization in grammar vs rule | Grammar folds label case and strips the label/MDM lane; rules validate digits only; internal separators never stripped | Syntax not semantics; digits-only wire is multiply attested, separator tolerance is unattested | +| 6 | Business-function suffix semantics | Informative only; any `00`–`99` passes when `include_business_function=True`; dropped rule → INVALID for 10-digit | UNECE defines values but no validity split; routing hint, not validity (BIC test/passive-flag precedent) | +| 7 | Single PUBLICATION vs split | Split three ways: UNGM-structure (spec) + UNDP-codeset (registry) + UNECE-BFI (spec) | One file per publication is the HOW_TO rule; fused would mix specification and registry lifecycles | +| 8 | `single_value` for batch | `True` initially; segmentation for multi-code rows; offer `extra_grammars` batch variant with `False` | Consistent with GTIN/ISBN/ISIN/Country precedent; catalog lines are multi-entity by authorial choice | +| 9 | Internal-separator tolerance | Contiguous digits only at v1; spaces/dots/hyphens → MISSING | No validator strips them; O*NET `Decimal(8,0)` proves storage has none; ISBN/Phone analogy explicitly rejected with evidence | +| 10 | Label span inclusion | Include label in `raw_text` span (fused regex); `notation.digits` label-free | Mirrors ISBN/ISSN/IBAN label handling; preserves UX highlighting without polluting identity | +| 11 | Which alternative written forms does v1 recognize (space-grouped pairs `43 21 15 03`)? | DEFER to `unspsc_grouped_recognition` community extension via `extra_grammars`, citing §2.1 | Prose-only attestation, zero wire validators; unhandled-at-v1 is a documented scope cut, not a blind spot — planners see it here | + +--- + +## 14. Ambiguity Analysis (Paxman-specific) + +- No inherent UNSPSC-vs-UNSPSC positional ambiguity — fixed 6/8/10 widths eliminate the reordering ambiguity Date exhibits; the longest-first alternation resolves the 10-contains-8 nesting inside one grammar, and two distinct codes in one slice are authorial choice (segmentation intended), not lexical ambiguity. +- UNSPSC vs GTIN-8 overlap is not lexical ambiguity — the same 8 digits may be a live UNSPSC stem and a check-valid GTIN-8 simultaneously (e.g. an illustrative `12345678`-shape). Each capability answers for its own authority in its own `canonicalize()` call (membership vs Mod-10); there is no cross-capability arbitration in the engine, so this is caller routing, not a coin flip. +- Parent vs commodity is not ambiguity — `43211500` (class) and `43211503` (commodity) share six digits but are distinct canonical values with distinct titles and levels; the padding lattice plus membership lookup keeps them apart exactly as ISBN prefix vs group vs registrant ranges stay apart. +- 6-digit alias vs 8-digit padded is not ambiguity — `441217` normalizes to `44121700` deterministically (right-pad `"00"`), and `native` format restores the spelling; same entity, two encodings (ADR-0011), one dedup key. +- Staleness is not ambiguity — a code moved/inactivated between UNDP releases (v24 moved 6, deleted 1) resolves against the pinned snapshot with its `Provenance.version`; determinism-by-snapshot plus `include_live_membership` gating turns version drift into a citable INVALID, not a competing reading. + +--- + +## 15. URL Reference (authoritative, fetched 2026-09-30) + +| Claim | URL | Kind | +|-------|-----|------| +| UNDP owns UNSPSC; open global standard; free codeset download `unspsc-english-v260801.1.xlsx`; contact `info.unspsc@undp.org` | https://www.undp.org/unspsc | primary | +| Four-level hierarchy, purely numeric; `XX000000`/`XXXX0000`/`XXXXXX00`/`XXXXXXXX`; replaced UNCCS 2012; search + Export to Excel | https://help.ungm.org/hc/en-us/articles/360012816160-What-are-UNSPSC-codes- | primary | +| UNSPSC search (live directory) | https://www.ungm.org/Public/UNSPSC | primary | +| DCMI MSI entry: MoU 1998, ECCMA→GS1 US→UNDP lineage, structure table, v26.0801 158,448 items, 14 languages, implementations, related standards | https://msi.dublincore.org/standards/unspsc | primary (index) | +| Wikidata P2167: mandatory `\d{8}(\d{2})?`, URL patterns, examples 25101703/11101803/11101709, link-rot on unspsc.org formatter, live source UNGM | https://www.wikidata.org/wiki/Property:P2167 | primary (constraint mirror) | +| Wikidata item Q1361569 (UNSPSC scheme identity) | https://www.wikidata.org/wiki/Q1361569 | secondary | +| SAP Business Network commodity codes: 8-digit lane, 6/8-digit only, v25.9 lane (snippet-level), `44121706` example | https://help.sap.com/docs/business-network-for-procurement/managing-network-catalog/commodity-codes | primary (snippet-level; direct HTML fetch empty) | +| Stibo STEP UNSPSC format: `UNSPSC000.` default ID prefix | https://doc.stibosystems.com/doc/version/2026.1/web/content/dataexc/datafmt/unspsc_format.html | primary | +| UNECE Classification Guidelines v2.04: BFI optional 2-digit suffix (direct PDF fetch 403; corroborated via secondary) | https://unece.org/fileadmin/DAM/trade/agr/meetings/ge.11/2005/2005_i04_UNSPSC.pdf | primary (citation; direct-quote verification blocked) | +| Cornell procurement buyer guide: `44121706` wooden pencils, eight-digits-four-classifications | https://finance.cornell.edu/procurement/buyers/unspsc | primary | +| CA DGS UNSPSC page: `SSFFKKCCBB`, `43211602` docking stations, 6+8-digit custom lists, BFI unused | https://www.dgs.ca.gov/PD/Resources/Page-Content/Procurement-Division-Resources-List-Folder/United-Nations-Standard-Products-and-Services-Code-UNSPSC | primary | +| O*NET UNSPSC reference: `Decimal(8,0)` storage | https://www.onetcenter.org/dictionary/27.2/mssql/unspsc_reference.html | primary | +| `unspsc-fr`: lookup + search + export, float→int normalisation, v26.0801, 149,849 commodities (GitHub-verified; PyPI bot-gated) | https://pypi.org/project/unspsc-fr | primary (index; body via repo) | +| `unspsc-fr` repo: `get`/`children`/`ancestors` + `search` API, SQLite/JSON/Parquet export | https://github.com/codebysaadbouh/unspsc-fr | primary | +| python-stdnum docs index: no UNSPSC; NACE/EAN/GS1-128/CUSIP/ISIN/BIC/IBAN/LEI siblings | https://arthurdejong.org/python-stdnum/doc/ | primary (negative) | +| validator.js repo: no `isUNSPSC` in README validator table (file-level `src/lib/` listing not enumerated; no counter-evidence) | https://github.com/validatorjs/validator.js | primary (negative) | +| Wikipedia UNSPSC: version table, lineage, segment-57, BFI level (sole source for pre-v26 counts — secondary) | https://en.wikipedia.org/wiki/UNSPSC | secondary | +| WisePIM taxonomy guide: label lanes, segment/family/class prose breakdowns (stale governance/counts — prose lanes only) | https://wisepim.com/guides/product-taxonomy/unspsc | secondary (stale) | +| BIC research precedent (template) | docs/development/research/2026-08-23-bic-canonicalization.md | primary (repo) | +| IBAN research precedent (checksum-depth complement) | docs/development/research/2026-08-22-iban-canonicalization.md | primary (repo) | +| ISSN research precedent (concise single-grammar) | docs/development/research/2026-08-21-issn-canonicalization.md | primary (repo) | +| Paxman scaffolder & conventions | HOW_TO_ADD_NEW_CAPABILITY.md, HOW_TO_ADD_NEW_GRAMMAR.md, ARCHITECTURE.md | primary (repo) | +| Paxman shipped precedent: GTIN grammar/rules/data + notation | paxman/capabilities/GTIN/grammar/gtin_recognition.py, paxman/capabilities/GTIN/rules/gs1_prefix_ed2026.py, paxman/capabilities/GTIN/rules/data/gs1_prefix.py, paxman/capabilities/GTIN/notation.py | primary (repo) | +| Paxman shipped precedent: ISBN range-message registry rule + data + grammar | paxman/capabilities/ISBN/rules/isbn_range_message_ed2026.py, paxman/capabilities/ISBN/rules/data/range_message.py, paxman/capabilities/ISBN/grammar/isbn13_recognition.py | primary (repo) | +| Paxman shipped precedent: ISIN prefix allowlist, Country/Currency tables, engine dedup | paxman/capabilities/ISIN/rules/anna_isin_guidelines_ed2025.py, paxman/capabilities/Country/rules/iso_3166_ed2024.py, paxman/engine/orchestrator.py, paxman/core/domain.py | primary (repo) | + +--- + +## 16. Evidence Completion — Resolved + +This report's UNSPSC-specific authoritative evidence has been fetched and cited (2026-09-30): + +- [x] Owner + RA pages: UNDP ownership (ex GS1 US 2003–2024, UNDP since 2025-01-01), `info.unspsc@undp.org`, free XLSX `unspsc-english-v260801.1.xlsx`, UNGM search + Export to Excel; lineage table back to 1998 MoU (ECCMA v6.0315 → GS1 US → UNDP, v08.1201 → v26.0801) +- [x] NOT-an-ISO-standard proved (no catalogue entry; ISO 22745/8000 are dictionary-infrastructure siblings) with related-scheme map (UNCCS/CPV/ECLASS/GPC/NAICS/HS) +- [x] Structure: 4-level `SSFFCCMM` positional pairs + optional `BB` business function, ASCII digits, zero-padding is structural, ≥6 worked examples across all levels +- [x] No checksum proved (UNGM "purely numeric" partition + Cornell 4×2 partition + CA DGS `SSFFKKCCBB` + Wikidata bare digit-count regex — four independent sources, zero check algorithms published) +- [x] Codeset size + versioning: v26.0801 158,448 (2023-08-14) + v24.0301 157,116 with deltas + new segment 57 + 14 languages + periodic cadence (pre-v26 counts flagged secondary) +- [x] Ecosystem regex consensus: Wikidata `\d{8}(\d{2})?` + SAP 6/8-digit + O*NET `Decimal(8,0)` + `unspsc-fr` float→int + Stibo `UNSPSC000.` lane (plus stdnum/validator.js confirmed absence) +- [x] Recognition-surface inventory complete (§2.1): 10 rows, every spec/schema/≥2-validator form listed with evidence and a RECOGNIZE/DEFER/REJECT disposition — no silently unhandled form +- [x] Wild input shapes validated (§2.2, 18 categories) against UNDP/UNGM/MSI + Cornell/CA-DGS + SAP/Ariba/PA-Jaggaer + Wikidata/PyPI/MDM +- [x] Label scope decision (fused `UNSPSC` + `code` + `:#|-.` + `UNSPSC000.` MDM lane, span includes label) +- [x] Parent/alias equivalence decision (parents distinct codes; 6-digit pads to `+00`; BFI splits 8+2 informative-only) +- [x] Separator decision (digits-only wire; spaces/dots/hyphens REJECT at v1 with evidence — ISBN/Phone analogy refused in writing) +- [x] Registry liveness scope decision (always-active pinned v26.0801 + `include_live_membership` rolling interpretation) +- [x] File layout / rule provenance in §5.2 / §11 / §12 frozen for implementation (pending scaffolder invocation per HOW_TO_ADD_NEW_CAPABILITY.md Step 0) + +--- + +## Appendix — What the Shipped GTIN, ISBN, ISIN, Country and Currency Capabilities Teach UNSPSC (verbatim precedent) + +> The following precedent is **verbatim-sourced from the codebase** (explored 2026-09-30, not speculative) and anchors the proposal to what Paxman already ships. + +GTIN (`paxman/capabilities/GTIN/notation.py:8-22`) teaches the notation facet pattern: `digits` plus `native_length` plus a trace-only marker (`has_ai`; UNSPSC analog: `function`). ISBN (`paxman/capabilities/ISBN/grammar/isbn13_recognition.py:30-40`) teaches the single-grammar staged pipeline (`PipelineGrammar` + `StandardPre(empty_guard=True)` + `RegexStage` with module-scope pattern, fused label, digit-continuation lookarounds). ISBN's `Section4RegistrantRange` (`paxman/capabilities/ISBN/rules/isbn_range_message_ed2026.py:13-33`, data in `rules/data/range_message.py` with `EAN_PREFIX_RULES`/`GROUP_RULES` longest-match via `find_registrant_length`) is the direct model for UNSPSC Level-3 membership: hierarchical table walk, `LOOKUP_TABLE`, `kind="registry"`, `requires_features={"include_range_validation"}` gating when rolling. ISIN (`paxman/capabilities/ISIN/rules/anna_isin_guidelines_ed2025.py`) teaches the small-allowlist alternative (`_VALID_PREFIXES`) — rejected for UNSPSC because 158k stems need a full snapshot, not a prefix set. Country/Currency (`rules/data/*.py` plain `frozenset` tables; Currency snapshot + `tools/regenerate_currency_data.py` from `paxman/shared_data/currency_snapshot.json`) teach the snapshot+regenerate lifecycle the UNSPSC codeset must follow. The engine (`paxman/engine/orchestrator.py`: `_enforce_single_value_invariant`, `_dedup_candidates` on `(value, recognition_rule, validation_rule)`, `_determine_status` MISSING-vs-INVALID split, `_format_candidates` after dedup) teaches that `output_format` never affects identity — the ADR-0011 guarantee the `segmented`/`labeled`/`native` formats rely on. The four architectural lessons for UNSPSC: + +1. **Grammar strips, rule validates, capability formats.** The label/MDM lane and 6-digit padding are syntax (grammar); padding-lattice and membership are semantics (rules); pair-hyphenation and labeling are display (`format_value`). No layer borrows another's job. +2. **One file per provenance, one class per section.** UNGM-structure (spec) + UNDP-codeset (registry) + UNECE-BFI (spec) stay in three files with three `PUBLICATION` constants; `Section N-*` naming throughout. +3. **No `output_format` in rules, ever.** `segmented`/`labeled`/`native` appear only in `capability.py`; `normalize()` always returns the 8-digit stem. +4. **Single grammar with optional group avoids spurious AMBIGUOUS; cross-grammar containment is preserved.** The 10-contains-8 nesting that would poison a two-grammar split is handled longest-first inside one pattern — the BIC-8-vs-11 lesson applied to digits. + +--- + +*Report saved to `docs/development/research/` (this directory) per MILESTONE guidance for UNSPSC. It mirrors the structure, depth, and provenance discipline of `docs/development/research/2026-08-22-iban-canonicalization.md` and `docs/development/research/2026-08-23-bic-canonicalization.md` and the deeper ISBN precedent. For implementation, start from `tools/new_capability.py` scaffolder per HOW_TO_ADD_NEW_CAPABILITY.md Step 0.* + +*Note: `docs/development/` is ephemeral per `docs/development/AGENTS.md` — not shipped, may drift, may be removed without notice, and must not be referenced by code or shipped docs.* diff --git a/docs/user/api-reference.md b/docs/user/api-reference.md index 6cfd0193..ac150f22 100644 --- a/docs/user/api-reference.md +++ b/docs/user/api-reference.md @@ -198,6 +198,7 @@ Current defaults and offered alternatives: | ISIN | `isin` | `grouped` | | ISNI | `isni` | `compact`, `urn` | | LEI | `lei` | `urn` | +| UNSPSC | `unspsc` | `labeled`, `native` | | GTIN | `gtin14` | `native` | | CreditCard | `pan` | `grouped` | | Language | `bcp47` | `alpha2`, `alpha3`, `alpha3-bib`, `name` | @@ -347,6 +348,7 @@ Statuses vs exceptions: statuses are domain answers returned inside `ExecutionRe | Serial identifiers | ISSN | `ISSN.create_contract(...)` | | Securities identification numbers | ISIN | `ISIN.create_contract(...)` | | Researcher/organization identifiers | ISNI | `ISNI.create_contract(...)` | +| Product/service codes | UNSPSC | `UNSPSC.create_contract(...)` | | Legal entity identifiers | LEI | `LEI.create_contract(...)` | | Trade item identifiers | GTIN | `GTIN.create_contract(...)` | | Payment card numbers (PANs) | CreditCard | `CreditCard.create_contract(...)` | diff --git a/docs/user/capabilities/index.md b/docs/user/capabilities/index.md index acc2f7a0..cd61d389 100644 --- a/docs/user/capabilities/index.md +++ b/docs/user/capabilities/index.md @@ -51,6 +51,7 @@ For the shared concepts behind these pages see [Contracts](../concepts/contracts | `6ba7b810-9dad-11d1-80b4-00c04fd430c8`, `{…}`, `urn:uuid:…` | [UUID](uuid/) | | `10.1038/nature12345`, `https://doi.org/10.1038/…`, `doi:10.1038/…` | [DOI](doi/) | | `example.com`, `münchen.de`, `XN--MNCHEN-3YA.de` | [Domain](domain/) | +| `UNSPSC 44103103`, `441217`, `UNSPSC000.44103103` | [UNSPSC](unspsc/) | > The set above reflects the **current release**. New capabilities are added in minor releases — check `paxman.capabilities` or the latest release notes if you don't see what you need. diff --git a/docs/user/capabilities/unspsc.md b/docs/user/capabilities/unspsc.md new file mode 100644 index 00000000..884523c5 --- /dev/null +++ b/docs/user/capabilities/unspsc.md @@ -0,0 +1,142 @@ +--- +title: "UNSPSC" +--- + +Canonicalizes **one UNSPSC mention** per call — a bare 8-digit code (`44103103`), a zero-padded parent (`43000000`, `43210000`, `43211500`), a 6-digit class alias (`441217`), a `UNSPSC`-labelled mention, a `UNSPSC000.` MDM system ID, or a 10-digit code with a business-function suffix — to the 8-digit wire stem. + +> **In plain language:** give it `UNSPSC 44103103`, `44103103`, `UNSPSC000.44103103`, or `441217` and it hands back `44103103` / `44121700` when the stem is a live row of the pinned UNGM-export snapshot. A well-formed but unissued stem is `INVALID`, never a guess; shapes outside the recognized spellings are `MISSING`. + +--- + +## What it recognizes — and what it does not + +| Recognizes | Does not recognize | +|------------|--------------------| +| Bare 8-digit commodity (`44103103` printer/facsimile toner, `43211503` notebook computers, `10101501` cats, `25101703` ambulances) | 7/9/11-digit runs (`4410310`, `441031031`) → `MISSING` (length guard) | +| Zero-padded parents (`43000000` segment, `43210000` family, `43211500` class — distinct codes, not prefixes) | Truncated prose prefixes (`43`, `4321`) → `MISSING` (real codes are `43000000`, `43210000`) | +| 6-digit class alias (`441217` → `44121700`, SAP/California lane) | Dotted/hyphenated grouping (`43.21.15.03`, `43-21-15-03`, `44103103-14`) → `MISSING` (digits-only wire) | +| `UNSPSC` label (`UNSPSC 44103103`, `UNSPSC: 44103103`, `UNSPSC #43211507`, lowercase, `Code` word) | Space-grouped pairs (`43 21 15 03`, prose display only) → `MISSING` | +| MDM system IDs (`UNSPSC000.44103103` — Stibo STEP lane) | Float tail as code (`44103103.0` matches `44103103`; `.0` stays outside the span) | +| 10-digit + business-function suffix (`4410310314` — suffix informative only) | Bare suffixes (`14`, `retail` without the 8-digit stem) → `MISSING` | +| CSV lanes (`unspsc,43211509` — comma is a field separator) | Glued surroundings (`X44103103`, `44103103Y`) → `MISSING` (word boundary) | +| Embedded mentions (`Printers (44103103) approved`) | Prose without an 8-digit shape → `MISSING` | + +--- + +## Canonical output + +Default `output_format` is `"unspsc"` (8-digit zero-padded wire stem). + +| `output_format` | Renders | Example | +|-----------------|---------|---------| +| *(default)* `unspsc` / `None` / `"default"` | 8-digit stem | `44103103` | +| `labeled` | `UNSPSC` prefix | `UNSPSC 44103103` | +| `native` | Spelling-preserving (6-digit stays 6-digit, 10-digit keeps its suffix) | `441217` / `4410310314` | + +Any other value raises `ContractError`. Every offered format re-enters under the default contract (ADR-0010 fixed point). The pair-hyphenated display (`43-21-15-03`) is deliberately unoffered — hyphens never re-enter by design. + +```python +from paxman.capabilities import UNSPSC +import paxman + +paxman.register_all_shipped() +print(paxman.canonicalize("UNSPSC 44103103", UNSPSC.create_contract()).canonicalized_value) +print(paxman.canonicalize("441217", UNSPSC.create_contract()).canonicalized_value) +print(paxman.canonicalize("UNSPSC000.44103103", UNSPSC.create_contract()).canonicalized_value) +print(paxman.canonicalize("44103103", UNSPSC.create_contract(output_format="labeled")).canonicalized_value) +``` + +--- + +## Contract + +```python +contract = UNSPSC.create_contract( + output_format=None, # "unspsc" (default); None/"default"/"unspsc" all resolve to it + include_business_function=True, # gate the BFI-suffix rule (dropped rule removes the suffix candidate, not the verdict) + # plus every common field: suppress_common_words / excluded_rules / pinned_rules / year / extra_grammars +) +``` + +- One grammar: `unspsc_recognition` (6/8/10 lanes + fused label, longest-first). +- Four rules: `Section 1-hierarchy-structure` + `Section 2-level-padding` (UNGM structure; both PARSER, always-active), `Section 3-codeset-membership` (UNDP codeset snapshot; LOOKUP_TABLE, always-active), `Section 4-business-function-suffix` (UNECE guidelines; PARSER, gated by `include_business_function`). +- Deterministic by snapshot: same input + contract + library snapshot → same output. The snapshot pins the UNGM live export of 2026-09-30 (13,482 live stems); a code moved or inactivated after that export resolves `INVALID` under the pinned snapshot, not silently `SUCCESS`. + +--- + +## Statuses + +| Input | Contract | Status | Value / why | +|-------|----------|--------|-------------| +| `44103103` / `UNSPSC 44103103` / `UNSPSC000.44103103` | defaults | `SUCCESS` | `"44103103"` (presentation-only dedup) | +| `441217` | defaults | `SUCCESS` | `"44121700"` (alias pads `+"00"`) | +| `4410310314` | defaults | `SUCCESS` | `"44103103"` (suffix trace-only) | +| `43000000` / `43210000` / `43211500` | defaults | `SUCCESS` | parents are codes in their own right | +| `43001503` / `00101501` | defaults | `INVALID` | mid-zero padding breaks the lattice | +| `44103199` / `99999999` | defaults | `INVALID` | well-formed but unissued | +| `11101803` (Wikidata-cited platinum) | defaults | `INVALID` | absent from the pinned snapshot by design — not a claim about the full UNDP codeset | +| `57110000` (synthesized ancestor) | defaults | `INVALID` | serves the ancestor walk only, never stem membership | +| `4410310314` | `include_business_function=False` | `SUCCESS` | `"44103103"` (suffix candidate dropped; stem still validates — ISBN range-validation precedent) | +| `43 21 15 03` / `43.21.15.03` / `43` | defaults | `MISSING` | no grammar claims these shapes | +| two distinct codes | defaults | raises `MultipleMentionsError` | un-segmented multi-entity input (`single_value=True`) | +| `44103103` | `output_format="segmented"` | raises `ContractError` | never offered | + +```mermaid +flowchart TB + A[Text] --> G[Grammar:
unspsc_recognition] + G --> R{Sections 1+2
shape + padding} + R -->|well-formed| M{Section 3
membership + ancestors} + M -->|live stem| OK[SUCCESS] + M -->|unissued| INV[INVALID] + R -->|mid-zero| INV + G -->|nothing claimed| MISS[MISSING] + + style OK fill:#e6ffed,stroke:#2d8a4e + style INV fill:#fff5f5,stroke:#cc3333 + style MISS fill:#fff5f5,stroke:#cc3333 +``` + +**Sibling note:** an 8-digit string may also match the GTIN-8 shape — each side resolves under its own contract (UNSPSC `SUCCESS` is codeset membership, GTIN `SUCCESS` is a Mod-10 check digit). There is no cross-capability arbitration; route by authority. + +--- + +## Notebook snippet — normalize a mixed column + +```python +import paxman +from paxman.capabilities import UNSPSC +from paxman.core.domain import Resolution + +paxman.register_all_shipped() +contract = UNSPSC.create_contract() + +rows = [ + "UNSPSC 44103103", + "44103103", + "UNSPSC000.44103103", + "441217", + "4410310314", + "43000000", + "43 21 15 03", + "44103199", + "not a code", +] + +for text in rows: + r = paxman.canonicalize(text, contract) + val = r.canonicalized_value if r.status == Resolution.SUCCESS else "—" + rule = r.candidates[0].validation_rule if r.candidates else "—" + print(f"{text!r:28} → {r.status.value:10} {val!r:14} ({rule})") +``` + +--- + +## Provenance + +- **United Nations Development Programme, UNSPSC Code Structure (UNGM Help Center)** (specification, 2025-07-08; four-level positional definition) — `Section 1-hierarchy-structure`, `Section 2-level-padding` +- **United Nations Development Programme, UNSPSC Codeset (UNGM live export 2026-09-30)** (registry, 13,482 live stems; partial — UNDP v26.0801 XLSX gated) — `Section 3-codeset-membership` +- **United Nations Economic Commission for Europe, Classification Guidelines (Business Function Identifiers)** (specification, v2.04; suffix informative-only, no value table cited) — `Section 4-business-function-suffix` + +Each candidate's `validation_rule` carries the section, and `candidate.provenance[0].publication_year` the year. + +See also: [GTIN](./gtin/), [ISBN](./isbn/), [Execution Result](../concepts/execution-result/), [Provenance](../concepts/provenance/). diff --git a/docs/user/citations.md b/docs/user/citations.md index 8016a498..035712d2 100644 --- a/docs/user/citations.md +++ b/docs/user/citations.md @@ -38,6 +38,8 @@ All entries below are derived from the `PUBLICATION` constants and `citation`/`n | **WHATWG** | URL Standard (Living Standard) | URL | 1 | | **IEEE** | IEEE Std 802-2024 | MacAddress | 1 | | **IUPAC** | IUPAC Periodic Table 04 May 2022, IUPAC Red Book 2005 Ch. IR-3 | ChemicalElement | 2 | +| **UNDP** | UNSPSC Code Structure (UNGM Help Center); UNSPSC Codeset (UNGM live export 2026-09-30) | UNSPSC | 3 | +| **UNECE** | Classification Guidelines (Business Function Identifiers) v2.04 | UNSPSC | 1 | | **Derived convention** | US locale — MM/DD/YYYY, European locale — DD/MM/YYYY | Date | 2 | > **Note on "Derived convention":** The two Date rules for `MM/DD/YYYY` and `DD/MM/YYYY` are locale conventions rather than an external standards publication. They are included here for completeness and carry `kind="convention"` with no `reference_url`. @@ -290,6 +292,30 @@ All IEEE entries are `kind="specification"`, `lifecycle="active"`. The registry entry is `kind="registry"`; the Red Book entry is `kind="specification"`; both are `lifecycle="active"`. +## UNDP — United Nations Development Programme + +Specification: **UNSPSC Code Structure (UNGM Help Center)** — `https://help.ungm.org/hc/en-us/articles/360012816160-What-are-UNSPSC-codes-` — `kind="specification"`, `version="2025-07-08"`, `lifecycle="active"`, `publication_year=2025`. + +**UNSPSC Codeset (UNGM live export)** — `https://www.ungm.org/Public/UNSPSC` — `kind="registry"`, `version="UNGM live export 2026-09-30 (13,482 stems)"`, `lifecycle="active"`, `publication_year=2026`. Partial: the UNDP v26.0801 XLSX (158,448 items) is access-gated; the table holds the live-directory subset. + +| Capability | Rule | Citation | +|------------|------|----------| +| UNSPSC | `Section 1-hierarchy-structure` | Four-level hierarchy, purely numeric codes | +| UNSPSC | `Section 2-level-padding` | Level padding (segment 000000, family 0000, class 00) | +| UNSPSC | `Section 3-codeset-membership` | Codeset membership (stem + SS000000/SSFF0000/SSFFCC00 live) | + +--- + +## UNECE — United Nations Economic Commission for Europe + +Specification: **Classification Guidelines (Business Function Identifiers)** — `https://unece.org/fileadmin/DAM/trade/agr/meetings/ge.11/2005/2005_i04_UNSPSC.pdf` — `kind="specification"`, `version="v2.04"`, `lifecycle="active"`, `publication_year=2005`. Direct fetch is access-gated; no value table is cited — the suffix is informative-only. + +| Capability | Rule | Citation | +|------------|------|----------| +| UNSPSC | `Section 4-business-function-suffix` | Business Function Identifiers (optional 2-digit suffix) | + +--- + ## Derived conventions — Date (non-authoritative) These two Date rules carry `authority="Derived convention"`, `kind="convention"` and no `reference_url`. They document widely-used locale conventions rather than an external specification. diff --git a/docs/user/concepts/capabilities.md b/docs/user/concepts/capabilities.md index 44bc723f..a3a10a10 100644 --- a/docs/user/concepts/capabilities.md +++ b/docs/user/concepts/capabilities.md @@ -95,6 +95,7 @@ The set below reflects the **current release** and is intentionally not presente | **GTIN** | Trade item identifiers (GS1) | compact 8/12/13/14 runs, zero-padded 14-digit fields, space/hyphen groupings, `GTIN`/`UPC`/`EAN` labels, `(01)`/`AI 01` markers | 14-digit zero-padded (`"00614141999996"`); `native` offers the spelled length | | **CreditCard** | Payment card numbers (ISO/IEC 7812-1) | compact 12–19-digit runs, space/hyphen groupings (4-4-4-4, 4-6-5, 14-digit), `PAN` labels | contiguous digits (`"4111111111111111"`); `grouped` offers groups-of-four | | **Domain** | Hostnames (RFC 1034/1035, UTS #46, RFC 5893, IANA Root Zone) | bare FQDNs any case, root dots, U-labels, ACE labels, fullwidth/dot variants, embedded mentions | lowercase A-label (`"xn--mnchen-3ya.de"`); `unicode` offers the U-label rendering | +| **UNSPSC** | Product/service codes (UNDP UNSPSC) | bare 8-digit, zero-padded parents, 6-digit aliases, `UNSPSC` labels, `UNSPSC000.` MDM IDs, 10-digit +BFI | 8-digit wire stem (`"44103103"`); `labeled`/`native` offered | > This table is an overview. Each capability's contract documents its specific flags (e.g. `include_localized` for Country, `default_country` for Phone). See [Contracts](contracts/) and the [README](https://github.com/nexusnv/paxman-python#readme) examples for per-capability details; each row is expanded into its own guide under [Capabilities](../capabilities/). diff --git a/docs/user/glossary.md b/docs/user/glossary.md index 385a09df..9130fbc7 100644 --- a/docs/user/glossary.md +++ b/docs/user/glossary.md @@ -122,6 +122,8 @@ Common terms used throughout Paxman — in the library API, the pipeline, the ca **ISNI** — International Standard Name Identifier (ISO 27729:2024). Paxman capability with spaced-quad canonical (`0000 0001 2103 2683`); `compact`, `urn` offered. See [Citations](citations/). +**UNSPSC** — United Nations Standard Products and Services Code (UNDP). Paxman capability with 8-digit wire-stem canonical (`44103103`); `labeled`, `native` offered. See [Citations](citations/). + **LEI** — Legal Entity Identifier (ISO 17442-1:2020, GLEIF LOU prefix list). Paxman capability. See [Citations](citations/). **IETF** — Internet Engineering Task Force. Authority for RFC 5322, RFC 6761, RFC 791, RFC 5952, RFC 3966, BCP 47 RFC 5646. See [Citations](citations/). diff --git a/docs/user/index.md b/docs/user/index.md index 90e16198..14300688 100644 --- a/docs/user/index.md +++ b/docs/user/index.md @@ -120,6 +120,7 @@ Paxman ships with capabilities that each cover one kind of identifier. The set i - **UUID** — 128-bit identifiers (IETF RFC 9562) - **DOI** — digital object identifiers (ISO 26324:2025) - **Domain** — hostnames (RFC 1034/1035, UTS #46, RFC 5893, IANA Root Zone Database) +- **UNSPSC** — product/service codes (UNDP UNSPSC, UNGM live-export snapshot, UNECE BFI) You only load what you use — importing `paxman.capabilities.Email` does not load the others. diff --git a/docs/user/migration.md b/docs/user/migration.md index e7c0df4e..68554542 100644 --- a/docs/user/migration.md +++ b/docs/user/migration.md @@ -367,6 +367,10 @@ check digit plus ANNA ISIN Guidelines V25 prefix allowlist) is registered by contracts are byte-identical. See the [ISIN guide](capabilities/isin/) and the [Citations](citations/) ISO/ANNA rows. +### Unreleased — New capability: UNSPSC (additive) + +`UNSPSC` (8-digit wire-stem canonical, `labeled` and `native` offered re-encodings, UNGM structure + UNDP codeset snapshot + UNECE BFI suffix) is registered by `register_all_shipped()` (now 29 shipped). No migration required — existing contracts are byte-identical. See the [UNSPSC guide](capabilities/unspsc/) and the [Citations](citations/) UNDP/UNECE rows. + ### Unreleased — New capability: ISNI (additive) `ISNI` (spaced display `XXXX XXXX XXXX XXXC` canonical, `compact` 16-char and `urn` `urn:isni:` offered re-encodings, ISO 27729:2024 structure + MOD 11-2 check digit) is registered by `register_all_shipped()` (now 28 shipped). No migration required — existing contracts are byte-identical. See the [ISNI guide](capabilities/isni/) and the [Citations](citations/) ISO row. diff --git a/paxman/api/bootstrap.py b/paxman/api/bootstrap.py index f521ebe2..5cc7a1d1 100644 --- a/paxman/api/bootstrap.py +++ b/paxman/api/bootstrap.py @@ -16,6 +16,7 @@ ISSN, LEI, ORCID, + UNSPSC, URL, UUID, ChemicalElement, @@ -66,6 +67,7 @@ Phone, SIUnit, Timezone, + UNSPSC, URL, UtcOffset, UUID, diff --git a/paxman/capabilities/UNSPSC/__init__.py b/paxman/capabilities/UNSPSC/__init__.py new file mode 100644 index 00000000..a2086b3d --- /dev/null +++ b/paxman/capabilities/UNSPSC/__init__.py @@ -0,0 +1,9 @@ +"""UNSPSC capability package.""" + +from __future__ import annotations + +from paxman.capabilities.UNSPSC.capability import UNSPSCCapability +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation + +__all__ = ["UNSPSCCapability", "UNSPSCContract", "UNSPSCNotation"] diff --git a/paxman/capabilities/UNSPSC/capability.py b/paxman/capabilities/UNSPSC/capability.py new file mode 100644 index 00000000..b72d2d6f --- /dev/null +++ b/paxman/capabilities/UNSPSC/capability.py @@ -0,0 +1,109 @@ +"""UNSPSC capability — wires grammars and rules together.""" + +from __future__ import annotations + +from collections.abc import Sequence + +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.capabilities.UNSPSC.grammar.unspsc_recognition import ( + UNSPSCRecognitionGrammar, +) +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.capabilities.UNSPSC.rules.undp_unspsc_codeset_ed2026 import ( + Section3CodesetMembership, +) +from paxman.capabilities.UNSPSC.rules.undp_unspsc_structure_ed2025 import ( + Section1HierarchyStructure, + Section2LevelPadding, +) +from paxman.capabilities.UNSPSC.rules.unece_bfi_ed2005 import ( + Section4BusinessFunctionSuffix, +) +from paxman.core.capability import Capability +from paxman.core.domain import Grammar, Rule + + +class UNSPSCCapability(Capability[UNSPSCNotation]): + """UNSPSC canonicalization capability. + + Recognizes 6/8/10-digit UNSPSC mentions (bare, labelled, MDM + ``UNSPSC000.`` IDs) and validates them against the UNGM structure + article, the UNDP codeset snapshot, and the UNECE BFI guidelines. + """ + + name = "unspsc" + + def get_grammars(self) -> list[Grammar[UNSPSCNotation]]: + """Return the default grammar instances.""" + return [UNSPSCRecognitionGrammar()] + + def get_rules(self) -> list[Rule[UNSPSCNotation]]: + """Return the default validation rule instances.""" + return [ + Section1HierarchyStructure(), + Section2LevelPadding(), + Section3CodesetMembership(), + Section4BusinessFunctionSuffix(), + ] + + @staticmethod + def create_contract( + *, + excluded_rules: Sequence[str] | None = None, + pinned_rules: Sequence[str] | None = None, + year: int | None = None, + output_format: str | None = None, + extra_grammars: Sequence[str] | None = None, + include_business_function: bool = True, + suppress_common_words: bool = False, + ) -> UNSPSCContract: + """Factory method for creating contracts with proper defaults. + + Args: + excluded_rules: Rule names to exclude. + pinned_rules: Pin to specific rules (takes precedence over + excluded_rules). + year: Year for temporal filtering. + output_format: Output format for canonical values. Optional; + None/"default"/"unspsc" resolve to "unspsc". + extra_grammars: Community grammar names (opt-in) to run + alongside the shipped grammars, in order (SEAM — the + surface guard's common block ends with this parameter). + include_business_function: Gate the BFI-suffix rule. + suppress_common_words: Suppress common-word boundary claims. + + Returns: + Configured UNSPSCContract instance. + """ + return UNSPSCContract( + excluded_rules=tuple(excluded_rules) if excluded_rules else (), + pinned_rules=tuple(pinned_rules) if pinned_rules is not None else None, + year=year, + output_format=output_format, + extra_grammars=tuple(extra_grammars) if extra_grammars else (), + include_business_function=include_business_function, + suppress_common_words=suppress_common_words, + ) + + def format_value( + self, + value: str, + output_format: str | None, + notation: UNSPSCNotation, + ) -> str: + """Render the 8-digit stem in the requested format. + + The default ``"unspsc"`` path is the identity. ``"labeled"`` + prefixes ``UNSPSC ``, ``"native"`` restores the spelled length + (6-digit alias or 10-digit suffix). Never affects candidate + identity or provenance. + """ + if output_format == "labeled": + return f"UNSPSC {value}" + if output_format == "native": + if notation.native_length == 6: + return value[:6] + if notation.native_length == 10: + return value + notation.function + return value + return value diff --git a/paxman/capabilities/UNSPSC/contract.py b/paxman/capabilities/UNSPSC/contract.py new file mode 100644 index 00000000..b240422e --- /dev/null +++ b/paxman/capabilities/UNSPSC/contract.py @@ -0,0 +1,50 @@ +"""UNSPSC contract — user-facing configuration.""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import ClassVar + +from paxman.core.capability_contract import CapabilityContract + + +@dataclass(frozen=True) +class UNSPSCContract(CapabilityContract): + """User-facing configuration for the UNSPSC capability. + + Formats (ADR-0011 classes): ``unspsc`` is the wire encoding + (8-digit compact, default); ``labeled`` is the label-carrier encoding + (``UNSPSC ``, 1:1 reversible); ``native`` is the + spelling-preserving encoding (6-digit stays 6-digit, 10-digit keeps + its suffix; injective across length lanes). + + ``segmented`` (pair-hyphenated display) is deliberately NOT offered: + the grammar rejects internal hyphens by design, so a segmented + rendering could never re-enter (ADR-0010 fixed-point). + + Attributes: + capability_name: Fixed to "unspsc" (not user-settable). + output_format: Canonical output format — "unspsc" is the default + 8-digit wire stem; "labeled" and "native" are offered as + presentation-only re-encodings. Optional — + None/"default"/"unspsc" all resolve to "unspsc". + excluded_rules: Tuple of rule names to exclude. + pinned_rules: Pin to specific rules (takes precedence over + excluded_rules). + year: Year for temporal filtering. + extra_grammars: Community grammar names (opt-in) to run alongside + the shipped grammars, in order (SEAM — inherited from base). + include_business_function: Gate for the 10-digit business-function + suffix rule (default True; dropped rule removes the suffix + candidate/provenance while the stem still validates via + Sections 1-3, so the verdict stays SUCCESS). + """ + + DEFAULT_OUTPUT_FORMAT: ClassVar[str] = "unspsc" + OFFERED_OUTPUT_FORMATS: ClassVar[frozenset[str]] = frozenset({"labeled", "native"}) + + capability_name: str = field(default="unspsc", init=False) + include_business_function: bool = True + + def __post_init__(self) -> None: + super().__post_init__() diff --git a/paxman/capabilities/UNSPSC/grammar/__init__.py b/paxman/capabilities/UNSPSC/grammar/__init__.py new file mode 100644 index 00000000..2112ee58 --- /dev/null +++ b/paxman/capabilities/UNSPSC/grammar/__init__.py @@ -0,0 +1 @@ +"""UNSPSC recognition grammars.""" diff --git a/paxman/capabilities/UNSPSC/grammar/unspsc_recognition.py b/paxman/capabilities/UNSPSC/grammar/unspsc_recognition.py new file mode 100644 index 00000000..7e40d3b2 --- /dev/null +++ b/paxman/capabilities/UNSPSC/grammar/unspsc_recognition.py @@ -0,0 +1,80 @@ +"""UNSPSC recognition grammar (staged pipeline). + +Recognizes 6/8/10-digit UNSPSC codes with an optional fused ``UNSPSC`` +label (case-insensitive, optional ``code`` word, ``:#|-.`` separators) +and the Stibo ``UNSPSC000.`` MDM lane. Longest-first alternation (10 +before 8 before 6) keeps a 10-digit business-function code from carving +an 8-digit prefix within this single grammar. Internal separators +(spaces, dots, hyphens) are never tolerated: the wire form is +digits-only per every primary (Wikidata ``\\d{8}(\\d{2})?``, SAP +"eight-digit numbers", O*NET ``Decimal(8,0)``). +""" + +from __future__ import annotations + +import re + +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.core.grammar import PipelineGrammar, RegexStage, StandardPre + +_LOOKBEHIND = r"(?\d{8}(?P\d{2}))" + r"|(?P\d{8})" + r"|(?P\d{6})" +) +_UNSPSC_PATTERN = ( + _LOOKBEHIND + + _UNSPSC_LABEL + + r"(?P" + + _UNSPSC_BODY + + r")" + + _LOOKAHEAD + + r"(?![-]\d)" +) +# Trailing (?![-]\d) mirrors the ISBN-13 fix: a hyphen+digit continuation +# (e.g. "44103103-14", an attempted hyphenated BFI suffix) means the digit +# run is not a standalone code — no carving. The symmetric (? UNSPSCNotation: + """Map a UNSPSC match to its stem + level/function facets.""" + spelled = re.sub(r"\D", "", match.group("code")) + raw = spelled + "00" if len(spelled) == 6 else spelled + stem = raw[:8] + function = raw[8:10] if len(raw) == 10 else "" + if stem.endswith("000000"): + level = "segment" + elif stem.endswith("0000"): + level = "family" + elif stem.endswith("00"): + level = "class" + else: + level = "commodity" + return UNSPSCNotation( + digits=stem, + level=level, + function=function, + native_length=len(spelled), + ) + + +class UNSPSCRecognitionGrammar(PipelineGrammar[UNSPSCNotation]): + """UNSPSC recognition: 6/8/10-digit codes with optional UNSPSC label.""" + + name = "unspsc_recognition" + semantics = "unspsc_recognition" + single_value = True + + pre = StandardPre[UNSPSCNotation](empty_guard=True) + regex = RegexStage[UNSPSCNotation]( + pattern=_UNSPSC_PATTERN, + notation_fn=_unspsc_notation, + flags=re.IGNORECASE | re.ASCII, + ) diff --git a/paxman/capabilities/UNSPSC/notation.py b/paxman/capabilities/UNSPSC/notation.py new file mode 100644 index 00000000..bcf61d76 --- /dev/null +++ b/paxman/capabilities/UNSPSC/notation.py @@ -0,0 +1,26 @@ +"""UNSPSC notation — grammar-normalized digit form.""" + +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass(frozen=True, slots=True) +class UNSPSCNotation: + """UNSPSC notation — grammar-normalized digit form. + + ``digits`` is the 8-digit zero-padded code (a 6-digit class shorthand + is padded +"00" by the grammar; a 10-digit input keeps its 8-digit + stem here). + ``level`` is one of "segment" | "family" | "class" | "commodity", + derived from trailing-00 pairs (no authority lookup). + ``function`` is the 2-digit business-function suffix, or "" when the + input was 6/8 digits (trace-only, never affects validity). + ``native_length`` is the spelled digit length (6, 8, or 10), + retained as a facet for the ``native`` offered format. + """ + + digits: str + level: str + function: str + native_length: int diff --git a/paxman/capabilities/UNSPSC/rules/__init__.py b/paxman/capabilities/UNSPSC/rules/__init__.py new file mode 100644 index 00000000..1e0b6d54 --- /dev/null +++ b/paxman/capabilities/UNSPSC/rules/__init__.py @@ -0,0 +1 @@ +"""UNSPSC validation rules.""" diff --git a/paxman/capabilities/UNSPSC/rules/data/unspsc_codeset.py b/paxman/capabilities/UNSPSC/rules/data/unspsc_codeset.py new file mode 100644 index 00000000..7becab34 --- /dev/null +++ b/paxman/capabilities/UNSPSC/rules/data/unspsc_codeset.py @@ -0,0 +1,13522 @@ +""" +GENERATED by tools/regenerate_unspsc_data.py — do not edit by hand. + +UNDP UNSPSC codeset snapshot (live-directory subset). +Source: UNGM Public/UNSPSC Excel export, fetched 2026-09-30. +Stems: 13482 live 8-digit codes. +Coverage: partial — the UNDP v26.0801 XLSX (158,448 items) is +access-gated; this table holds the live-directory subset until the +full codeset can be ingested. Do not cite stem absence as +codeset absence beyond this pinned snapshot. +SYNTHESIZED_ANCESTORS are family rows absent from the export but +implied by live classes beneath them (flagged in the snapshot). +They serve ancestor-liveness ONLY — never stem membership — so a +synthesized code alone resolves INVALID while classes beneath it +still pass the ancestor walk. + +Regenerate with: uv run python tools/regenerate_unspsc_data.py +""" + +from __future__ import annotations + +CODESET_VERSION: str = "UNGM live export 2026-09-30 (13,482 stems)" + +LIVE_STEMS: frozenset[str] = frozenset( + { + "10000000", + "10100000", + "10101500", + "10101501", + "10101502", + "10101506", + "10101507", + "10101508", + "10101509", + "10101511", + "10101512", + "10101513", + "10101516", + "10101517", + "10101518", + "10101600", + "10101601", + "10101602", + "10101603", + "10101604", + "10101605", + "10101607", + "10101700", + "10101701", + "10101800", + "10101801", + "10101900", + "10101903", + "10101904", + "10102000", + "10102100", + "10102101", + "10110000", + "10120000", + "10121500", + "10121501", + "10121600", + "10121601", + "10121700", + "10121701", + "10121800", + "10121801", + "10122100", + "10130000", + "10131500", + "10131506", + "10131600", + "10131601", + "10131602", + "10131605", + "10131700", + "10131701", + "10140000", + "10141500", + "10141501", + "10150000", + "10151500", + "10151503", + "10151504", + "10151505", + "10151506", + "10151507", + "10151508", + "10151509", + "10151510", + "10151511", + "10151512", + "10151513", + "10151514", + "10151515", + "10151517", + "10151518", + "10151520", + "10151521", + "10151522", + "10151523", + "10151524", + "10151525", + "10151526", + "10151529", + "10151531", + "10151532", + "10151533", + "10151534", + "10151535", + "10151536", + "10151537", + "10151538", + "10151539", + "10151540", + "10151541", + "10151600", + "10151601", + "10151602", + "10151603", + "10151604", + "10151605", + "10151606", + "10151607", + "10151608", + "10151609", + "10151610", + "10151611", + "10151612", + "10151613", + "10151614", + "10151616", + "10151700", + "10151800", + "10151900", + "10151904", + "10152000", + "10152001", + "10152003", + "10152008", + "10152048", + "10152055", + "10152056", + "10152057", + "10152100", + "10152200", + "10152201", + "10152300", + "10152301", + "10152302", + "10152400", + "10152401", + "10152402", + "10152403", + "10152404", + "10152405", + "10160000", + "10161500", + "10170000", + "10171500", + "10171501", + "10171502", + "10171504", + "10171506", + "10171507", + "10171600", + "10171601", + "10171602", + "10171603", + "10171604", + "10171605", + "10171611", + "10171612", + "10171613", + "10171614", + "10171615", + "10171616", + "10171700", + "10171702", + "10171703", + "10171800", + "10190000", + "10191500", + "10191506", + "10191507", + "10191508", + "10191509", + "10191510", + "10191511", + "10191512", + "10191513", + "10191514", + "10191515", + "10191516", + "10191517", + "10191518", + "10191519", + "10191520", + "10191700", + "10191701", + "10191703", + "10191704", + "10191705", + "10191706", + "10191707", + "10191708", + "10200000", + "10210000", + "10220000", + "11000000", + "11100000", + "11101500", + "11101501", + "11101506", + "11101600", + "11101700", + "11101800", + "11110000", + "11111500", + "11111501", + "11111600", + "11111601", + "11111602", + "11111603", + "11111604", + "11111605", + "11111606", + "11111607", + "11111608", + "11111609", + "11111610", + "11111611", + "11111612", + "11111613", + "11111700", + "11111701", + "11111800", + "11111801", + "11111802", + "11111803", + "11111804", + "11111805", + "11111806", + "11111807", + "11111808", + "11111809", + "11111810", + "11111811", + "11111812", + "11120000", + "11121500", + "11121502", + "11121600", + "11121603", + "11121604", + "11121605", + "11121606", + "11121607", + "11121608", + "11121610", + "11121614", + "11121616", + "11121621", + "11121622", + "11121623", + "11121624", + "11121625", + "11121700", + "11121800", + "11121900", + "11122000", + "11122001", + "11122002", + "11122003", + "11122004", + "11122005", + "11122006", + "11130000", + "11131500", + "11131501", + "11131600", + "11131602", + "11131607", + "11131609", + "11131610", + "11140000", + "11141600", + "11141700", + "11150000", + "11151500", + "11151600", + "11151700", + "11160000", + "11161500", + "11161600", + "11161700", + "11161800", + "11162000", + "11162100", + "11162101", + "11162102", + "11162104", + "11162105", + "11162107", + "11162108", + "11162109", + "11162110", + "11162111", + "11162112", + "11162113", + "11162114", + "11162115", + "11162116", + "11162117", + "11162118", + "11162119", + "11162120", + "11162121", + "11162122", + "11162123", + "11162124", + "11162125", + "11162126", + "11162127", + "11162128", + "11162129", + "11162130", + "11162131", + "11162132", + "11162133", + "11162200", + "11162300", + "11162400", + "11170000", + "11171500", + "11171501", + "11171600", + "11171601", + "11171602", + "11171603", + "11171700", + "11171701", + "11171702", + "11171800", + "11171801", + "11171900", + "11171901", + "11172000", + "11172001", + "11172100", + "11172101", + "11172200", + "11172300", + "11180000", + "11190000", + "12000000", + "12130000", + "12131500", + "12131501", + "12131502", + "12131503", + "12131504", + "12131505", + "12131506", + "12131507", + "12131508", + "12131509", + "12131600", + "12131700", + "12131702", + "12131703", + "12131704", + "12131705", + "12131706", + "12131707", + "12131708", + "12131709", + "12131800", + "12140000", + "12141500", + "12141600", + "12141700", + "12141800", + "12141900", + "12142000", + "12142100", + "12142200", + "12142201", + "12142202", + "12142203", + "12142204", + "12142205", + "12142206", + "12142207", + "12142208", + "12160000", + "12161500", + "12161700", + "12161800", + "12161804", + "12161900", + "12162000", + "12162100", + "12162200", + "12162300", + "12162700", + "12162800", + "12163100", + "12163200", + "12163600", + "12164100", + "12164300", + "12164400", + "12164500", + "12164900", + "12165100", + "12170000", + "12171500", + "12171600", + "12171700", + "12180000", + "12181500", + "12181600", + "12190000", + "12191500", + "12350000", + "12352000", + "12352100", + "12352200", + "12352300", + "12352324", + "12352400", + "12352500", + "13000000", + "13100000", + "13101500", + "13101600", + "13101700", + "13101900", + "13102000", + "13110000", + "13111000", + "13111100", + "13111200", + "13111201", + "13111202", + "13111203", + "13111204", + "13111205", + "13111206", + "13111207", + "13111208", + "13111209", + "13111210", + "13111211", + "13111212", + "13111213", + "13111214", + "13111215", + "13111216", + "13111217", + "13111218", + "13111219", + "13111220", + "13111300", + "14000000", + "14100000", + "14101500", + "14101501", + "14110000", + "14111500", + "14111501", + "14111502", + "14111503", + "14111504", + "14111505", + "14111506", + "14111507", + "14111508", + "14111509", + "14111510", + "14111511", + "14111512", + "14111513", + "14111514", + "14111515", + "14111516", + "14111518", + "14111519", + "14111520", + "14111523", + "14111524", + "14111525", + "14111526", + "14111527", + "14111528", + "14111529", + "14111530", + "14111531", + "14111532", + "14111533", + "14111534", + "14111535", + "14111536", + "14111537", + "14111538", + "14111539", + "14111540", + "14111541", + "14111542", + "14111543", + "14111544", + "14111545", + "14111546", + "14111600", + "14111601", + "14111604", + "14111605", + "14111606", + "14111607", + "14111608", + "14111609", + "14111610", + "14111611", + "14111613", + "14111614", + "14111615", + "14111616", + "14111617", + "14111618", + "14111700", + "14111701", + "14111702", + "14111703", + "14111704", + "14111705", + "14111706", + "14111800", + "14111801", + "14111802", + "14111803", + "14111804", + "14111805", + "14111806", + "14111807", + "14111808", + "14111809", + "14111810", + "14111811", + "14111812", + "14111813", + "14111814", + "14111815", + "14111816", + "14111817", + "14111818", + "14111819", + "14111820", + "14111821", + "14111822", + "14111823", + "14111824", + "14111825", + "14111826", + "14111827", + "14111828", + "14111829", + "14111830", + "14111831", + "14120000", + "14121500", + "14121501", + "14121502", + "14121503", + "14121504", + "14121505", + "14121506", + "14121507", + "14121508", + "14121509", + "14121510", + "14121600", + "14121601", + "14121602", + "14121603", + "14121604", + "14121605", + "14121700", + "14121701", + "14121702", + "14121703", + "14121800", + "14121801", + "14121802", + "14121803", + "14121804", + "14121805", + "14121806", + "14121807", + "14121808", + "14121809", + "14121810", + "14121811", + "14121812", + "14121813", + "14121900", + "14121901", + "14121902", + "14121903", + "14121904", + "14121905", + "14122100", + "14122101", + "14122102", + "14122103", + "14122104", + "14122105", + "14122106", + "14122107", + "14122108", + "14122200", + "14122201", + "14122202", + "14122203", + "14122204", + "15000000", + "15100000", + "15101500", + "15101502", + "15101503", + "15101504", + "15101505", + "15101506", + "15101507", + "15101508", + "15101509", + "15101510", + "15101513", + "15101600", + "15101605", + "15101609", + "15101615", + "15101700", + "15101800", + "15101801", + "15101802", + "15110000", + "15111500", + "15111501", + "15111502", + "15111503", + "15111504", + "15111505", + "15111506", + "15111507", + "15111508", + "15111509", + "15111510", + "15111511", + "15111700", + "15120000", + "15121500", + "15121501", + "15121504", + "15121508", + "15121800", + "15121807", + "15121900", + "15130000", + "15131500", + "15131502", + "15131503", + "15131504", + "15131505", + "15131506", + "15131600", + "15131601", + "20000000", + "20100000", + "20101500", + "20101501", + "20101502", + "20101600", + "20101700", + "20101709", + "20101800", + "20101900", + "20102000", + "20102100", + "20102200", + "20102300", + "20102301", + "20102302", + "20102303", + "20102304", + "20102305", + "20102306", + "20102307", + "20110000", + "20111500", + "20111504", + "20111505", + "20111600", + "20111700", + "20120000", + "20121400", + "20121449", + "20121600", + "20130000", + "20140000", + "21000000", + "21100000", + "21101500", + "21101501", + "21101502", + "21101503", + "21101504", + "21101505", + "21101506", + "21101507", + "21101508", + "21101509", + "21101517", + "21101600", + "21101601", + "21101700", + "21101701", + "21101703", + "21101705", + "21101708", + "21101709", + "21101800", + "21101801", + "21101802", + "21101803", + "21101804", + "21101805", + "21101806", + "21101807", + "21101808", + "21101810", + "21101900", + "21101901", + "21101903", + "21101905", + "21101906", + "21101916", + "21102000", + "21102001", + "21102002", + "21102009", + "21102100", + "21102200", + "21102300", + "21102305", + "21102400", + "21102401", + "21102500", + "21102501", + "21102502", + "21102503", + "21102600", + "21102601", + "21110000", + "21111500", + "21111501", + "21111504", + "21111600", + "22000000", + "22100000", + "22101500", + "22101501", + "22101502", + "22101504", + "22101505", + "22101507", + "22101508", + "22101509", + "22101511", + "22101513", + "22101514", + "22101516", + "22101518", + "22101519", + "22101520", + "22101521", + "22101522", + "22101523", + "22101524", + "22101525", + "22101526", + "22101527", + "22101528", + "22101529", + "22101530", + "22101531", + "22101532", + "22101533", + "22101534", + "22101535", + "22101536", + "22101537", + "22101538", + "22101539", + "22101600", + "22101632", + "22101633", + "22101700", + "22101701", + "22101702", + "22101703", + "22101704", + "22101705", + "22101709", + "22101710", + "22101711", + "22101712", + "22101713", + "22101714", + "22101715", + "22101716", + "22101717", + "22101718", + "22101719", + "22101720", + "22101721", + "22101722", + "22101723", + "22101724", + "22101800", + "22101801", + "22101802", + "22101803", + "22101804", + "22101900", + "22101901", + "22101902", + "22101904", + "22101905", + "22101906", + "22101907", + "22101908", + "22101909", + "22102000", + "22102001", + "23000000", + "23100000", + "23101500", + "23101501", + "23101502", + "23101505", + "23101506", + "23101507", + "23101508", + "23101509", + "23101510", + "23101511", + "23101512", + "23101513", + "23101514", + "23101537", + "23110000", + "23120000", + "23121500", + "23121501", + "23121506", + "23121507", + "23121600", + "23121614", + "23130000", + "23131500", + "23131501", + "23131503", + "23131600", + "23131700", + "23140000", + "23141600", + "23141601", + "23141700", + "23150000", + "23151500", + "23151600", + "23151700", + "23151800", + "23151816", + "23151817", + "23151900", + "23152000", + "23152100", + "23152200", + "23152900", + "23152901", + "23152912", + "23153000", + "23153100", + "23153145", + "23153200", + "23153400", + "23153500", + "23153600", + "23153605", + "23153700", + "23153800", + "23160000", + "23161500", + "23161501", + "23161600", + "23161700", + "23180000", + "23181500", + "23181501", + "23181502", + "23181507", + "23181514", + "23181519", + "23181522", + "23181523", + "23181600", + "23181601", + "23181700", + "23181800", + "23190000", + "23191000", + "23191001", + "23191100", + "23191101", + "23200000", + "23201000", + "23201200", + "23201201", + "23201202", + "23201203", + "23201204", + "23210000", + "23220000", + "23221000", + "23221001", + "23221100", + "23230000", + "23231000", + "23231001", + "23240000", + "23241400", + "23241401", + "23241500", + "23241600", + "23241615", + "23241700", + "23241800", + "23241900", + "23242100", + "23242200", + "23242300", + "23242400", + "23242500", + "23242600", + "23242612", + "23250000", + "23251500", + "23251501", + "23251600", + "23251700", + "23251800", + "23251900", + "23260000", + "23261500", + "23261501", + "23270000", + "23271400", + "23271401", + "23271423", + "23271500", + "23271600", + "23271603", + "23271700", + "23271712", + "23271800", + "23271812", + "23280000", + "23281500", + "23290000", + "23291500", + "23300000", + "23301500", + "24000000", + "24100000", + "24101500", + "24101501", + "24101502", + "24101503", + "24101504", + "24101505", + "24101506", + "24101507", + "24101508", + "24101509", + "24101510", + "24101511", + "24101512", + "24101513", + "24101514", + "24101515", + "24101516", + "24101517", + "24101600", + "24101601", + "24101602", + "24101603", + "24101604", + "24101605", + "24101606", + "24101608", + "24101609", + "24101610", + "24101611", + "24101612", + "24101613", + "24101615", + "24101625", + "24101626", + "24101629", + "24101630", + "24101633", + "24101643", + "24101644", + "24101655", + "24101656", + "24101658", + "24101659", + "24101661", + "24101663", + "24101675", + "24101700", + "24101706", + "24101751", + "24101800", + "24101900", + "24102000", + "24102006", + "24102100", + "24102101", + "24102102", + "24102103", + "24102104", + "24102105", + "24102106", + "24102107", + "24102108", + "24102109", + "24102200", + "24102300", + "24102400", + "24102401", + "24102402", + "24102403", + "24110000", + "24111500", + "24111501", + "24111502", + "24111503", + "24111507", + "24111508", + "24111509", + "24111510", + "24111511", + "24111512", + "24111513", + "24111514", + "24111515", + "24111800", + "24111801", + "24111802", + "24111803", + "24111804", + "24111805", + "24111806", + "24111807", + "24111808", + "24111809", + "24111810", + "24111811", + "24111812", + "24111813", + "24111814", + "24111815", + "24111816", + "24111817", + "24111825", + "24112000", + "24112003", + "24112004", + "24112005", + "24112006", + "24112007", + "24112100", + "24112101", + "24112113", + "24112200", + "24112204", + "24112209", + "24112400", + "24112401", + "24112402", + "24112412", + "24112500", + "24112501", + "24112600", + "24112603", + "24112700", + "24112701", + "24112702", + "24112800", + "24112801", + "24112802", + "24112803", + "24112805", + "24112806", + "24112807", + "24112900", + "24113000", + "24113003", + "24113100", + "24113101", + "24113102", + "24113103", + "24113104", + "24113105", + "24113106", + "24113107", + "24113108", + "24113109", + "24113110", + "24120000", + "24121500", + "24121502", + "24121511", + "24121512", + "24121513", + "24121514", + "24121800", + "24122000", + "24122002", + "24122003", + "24130000", + "24131500", + "24131501", + "24131502", + "24131503", + "24131504", + "24131505", + "24131506", + "24131513", + "24131515", + "24131516", + "24131600", + "24131601", + "24131602", + "24131603", + "24131604", + "24131605", + "24131606", + "24131607", + "24131900", + "24140000", + "24141500", + "24141501", + "24141504", + "24141506", + "24141510", + "24141521", + "24141600", + "24141700", + "25000000", + "25100000", + "25101500", + "25101501", + "25101502", + "25101503", + "25101504", + "25101505", + "25101506", + "25101507", + "25101508", + "25101509", + "25101510", + "25101600", + "25101601", + "25101602", + "25101604", + "25101609", + "25101610", + "25101611", + "25101612", + "25101613", + "25101614", + "25101615", + "25101700", + "25101702", + "25101703", + "25101704", + "25101705", + "25101706", + "25101707", + "25101708", + "25101709", + "25101710", + "25101711", + "25101712", + "25101713", + "25101714", + "25101715", + "25101716", + "25101717", + "25101718", + "25101719", + "25101800", + "25101801", + "25101802", + "25101803", + "25101804", + "25101900", + "25101901", + "25101902", + "25101903", + "25101904", + "25101905", + "25101906", + "25101907", + "25101908", + "25101909", + "25101910", + "25101911", + "25101912", + "25101913", + "25101914", + "25101915", + "25101916", + "25101917", + "25101918", + "25101919", + "25101920", + "25101921", + "25101922", + "25101923", + "25101924", + "25101925", + "25101926", + "25101927", + "25101928", + "25101929", + "25101930", + "25101931", + "25101932", + "25101933", + "25101934", + "25101935", + "25101936", + "25101937", + "25101938", + "25101939", + "25101940", + "25101941", + "25101942", + "25101943", + "25101944", + "25101945", + "25101946", + "25101947", + "25101948", + "25102000", + "25102001", + "25102002", + "25102003", + "25102100", + "25102101", + "25102102", + "25102103", + "25102104", + "25102105", + "25102106", + "25110000", + "25111500", + "25111501", + "25111502", + "25111503", + "25111504", + "25111505", + "25111506", + "25111507", + "25111508", + "25111509", + "25111510", + "25111511", + "25111512", + "25111513", + "25111514", + "25111515", + "25111516", + "25111517", + "25111518", + "25111520", + "25111524", + "25111527", + "25111528", + "25111529", + "25111532", + "25111533", + "25111600", + "25111601", + "25111602", + "25111603", + "25111700", + "25111722", + "25111724", + "25111725", + "25111726", + "25111800", + "25111801", + "25111802", + "25111803", + "25111804", + "25111805", + "25111806", + "25111807", + "25111808", + "25111809", + "25111900", + "25111901", + "25111902", + "25111903", + "25111904", + "25111905", + "25111906", + "25111907", + "25120000", + "25121500", + "25121501", + "25130000", + "25131400", + "25131401", + "25131402", + "25131403", + "25131500", + "25131504", + "25131505", + "25131506", + "25131507", + "25131508", + "25131509", + "25131510", + "25131511", + "25131512", + "25131513", + "25131600", + "25131601", + "25131602", + "25131604", + "25131700", + "25131705", + "25131707", + "25131709", + "25131800", + "25131900", + "25131902", + "25132100", + "25132101", + "25150000", + "25151700", + "25151701", + "25160000", + "25161500", + "25161505", + "25161506", + "25161507", + "25170000", + "25171500", + "25171507", + "25171600", + "25171700", + "25171702", + "25171713", + "25171900", + "25171901", + "25172000", + "25172100", + "25172200", + "25172300", + "25172400", + "25172406", + "25172500", + "25172502", + "25172503", + "25172504", + "25172505", + "25172506", + "25172509", + "25172511", + "25172512", + "25172514", + "25172600", + "25172607", + "25172614", + "25172700", + "25172709", + "25172710", + "25172711", + "25172800", + "25172804", + "25172805", + "25172900", + "25172908", + "25173000", + "25173100", + "25173107", + "25173108", + "25173110", + "25173111", + "25173112", + "25173113", + "25173114", + "25173115", + "25173116", + "25173117", + "25173118", + "25173119", + "25173120", + "25173121", + "25173122", + "25173123", + "25173124", + "25173125", + "25173126", + "25173127", + "25173128", + "25173129", + "25173130", + "25173131", + "25173132", + "25173133", + "25173134", + "25173135", + "25173300", + "25173700", + "25173800", + "25173900", + "25174000", + "25174100", + "25174200", + "25174213", + "25174400", + "25174414", + "25174600", + "25174700", + "25174800", + "25174900", + "25175000", + "25175100", + "25175101", + "25175102", + "25175103", + "25175106", + "25175200", + "25175201", + "25175202", + "25175203", + "25180000", + "25181600", + "25181601", + "25181604", + "25181605", + "25181606", + "25181610", + "25181612", + "25181614", + "25181700", + "25181701", + "25181703", + "25181708", + "25181719", + "25181720", + "25190000", + "25191500", + "25191501", + "25191502", + "25191503", + "25191504", + "25191505", + "25191506", + "25191507", + "25191508", + "25191509", + "25191510", + "25191511", + "25191512", + "25191513", + "25191514", + "25191515", + "25191516", + "25191517", + "25191518", + "25191519", + "25191520", + "25191521", + "25191522", + "25191523", + "25191524", + "25191525", + "25191526", + "25191527", + "25191528", + "25191529", + "25191530", + "25191531", + "25191532", + "25191533", + "25191534", + "25191535", + "25191536", + "25191537", + "25191538", + "25191539", + "25191540", + "25191541", + "25191542", + "25191543", + "25191544", + "25191545", + "25191546", + "25191547", + "25191548", + "25191549", + "25191550", + "25191551", + "25191552", + "25191553", + "25191554", + "25191600", + "25191700", + "25191800", + "25200000", + "25201700", + "25201701", + "25201702", + "25201800", + "25201801", + "25201900", + "25201901", + "25202100", + "25202300", + "25202301", + "25202800", + "25202801", + "25202802", + "25202803", + "25202900", + "25202901", + "25202902", + "25202903", + "25202904", + "25202905", + "25202906", + "25202907", + "25202908", + "25202909", + "25202910", + "25202911", + "26000000", + "26100000", + "26101100", + "26101200", + "26101300", + "26101400", + "26101412", + "26101500", + "26101501", + "26101502", + "26101503", + "26101504", + "26101505", + "26101506", + "26101507", + "26101508", + "26101509", + "26101511", + "26101513", + "26101515", + "26101700", + "26101720", + "26101732", + "26101736", + "26101740", + "26101764", + "26101900", + "26110000", + "26111500", + "26111600", + "26111601", + "26111602", + "26111603", + "26111604", + "26111605", + "26111606", + "26111607", + "26111608", + "26111609", + "26111610", + "26111611", + "26111612", + "26111613", + "26111614", + "26111700", + "26111701", + "26111702", + "26111703", + "26111704", + "26111705", + "26111706", + "26111707", + "26111708", + "26111709", + "26111710", + "26111711", + "26111712", + "26111713", + "26111714", + "26111715", + "26111716", + "26111717", + "26111718", + "26111719", + "26111720", + "26111721", + "26111722", + "26111723", + "26111724", + "26111725", + "26111726", + "26111727", + "26111728", + "26111729", + "26111800", + "26111801", + "26111900", + "26112000", + "26112001", + "26112003", + "26112004", + "26112100", + "26120000", + "26121500", + "26121536", + "26121600", + "26121609", + "26121613", + "26121629", + "26121630", + "26121635", + "26121636", + "26121700", + "26121800", + "26130000", + "26131500", + "26131501", + "26131502", + "26131503", + "26131504", + "26131505", + "26131506", + "26131507", + "26131508", + "26131509", + "26131510", + "26131511", + "26131600", + "26131700", + "26131800", + "26131900", + "26140000", + "26141600", + "26141700", + "26141800", + "26141900", + "26142000", + "26142100", + "26142200", + "26142300", + "26142302", + "26142400", + "26142407", + "27000000", + "27110000", + "27111500", + "27111504", + "27111509", + "27111600", + "27111700", + "27111701", + "27111704", + "27111800", + "27111801", + "27111900", + "27111913", + "27112000", + "27112004", + "27112035", + "27112100", + "27112200", + "27112300", + "27112400", + "27112500", + "27112600", + "27112700", + "27112712", + "27112800", + "27112841", + "27112900", + "27113000", + "27113100", + "27113200", + "27113201", + "27113203", + "27113204", + "27113205", + "27113300", + "27113400", + "27113401", + "27113402", + "27113403", + "27120000", + "27121500", + "27121504", + "27130000", + "27131500", + "27131501", + "27140000", + "27141000", + "30000000", + "30100000", + "30101500", + "30101700", + "30101800", + "30102000", + "30102200", + "30102300", + "30102306", + "30102400", + "30102800", + "30102900", + "30103100", + "30103200", + "30103500", + "30103600", + "30103619", + "30103700", + "30103800", + "30103900", + "30110000", + "30111500", + "30111501", + "30111502", + "30111503", + "30111504", + "30111505", + "30111506", + "30111507", + "30111508", + "30111509", + "30111600", + "30111601", + "30111602", + "30111603", + "30111604", + "30111605", + "30111607", + "30111700", + "30111701", + "30111800", + "30111900", + "30120000", + "30121500", + "30121504", + "30121600", + "30121601", + "30121602", + "30121603", + "30121604", + "30121605", + "30121700", + "30121701", + "30121702", + "30121703", + "30121704", + "30121705", + "30121706", + "30121707", + "30121708", + "30121709", + "30121710", + "30121711", + "30121712", + "30121713", + "30121714", + "30121715", + "30121716", + "30121717", + "30121718", + "30121719", + "30121720", + "30121721", + "30121800", + "30130000", + "30131500", + "30131502", + "30131503", + "30131504", + "30131505", + "30131506", + "30131507", + "30131508", + "30131509", + "30131510", + "30131511", + "30131512", + "30131513", + "30131514", + "30131515", + "30131516", + "30131517", + "30131518", + "30131600", + "30131602", + "30131603", + "30131604", + "30131605", + "30131606", + "30131607", + "30131608", + "30131609", + "30131610", + "30131611", + "30131700", + "30131703", + "30140000", + "30150000", + "30151500", + "30151501", + "30151502", + "30151503", + "30151505", + "30151507", + "30151508", + "30151509", + "30151510", + "30151511", + "30151512", + "30151513", + "30151514", + "30151515", + "30151600", + "30151700", + "30151800", + "30151900", + "30152000", + "30152100", + "30160000", + "30161500", + "30161600", + "30161700", + "30161702", + "30161800", + "30161803", + "30161900", + "30162000", + "30162100", + "30162200", + "30162300", + "30162400", + "30170000", + "30171500", + "30171501", + "30171502", + "30171503", + "30171504", + "30171505", + "30171506", + "30171507", + "30171508", + "30171509", + "30171510", + "30171511", + "30171512", + "30171513", + "30171514", + "30171515", + "30171516", + "30171517", + "30171518", + "30171519", + "30171520", + "30171521", + "30171522", + "30171523", + "30171524", + "30171525", + "30171526", + "30171527", + "30171600", + "30171700", + "30171701", + "30171703", + "30171704", + "30171705", + "30171706", + "30171707", + "30171708", + "30171709", + "30171710", + "30171711", + "30171712", + "30171800", + "30171900", + "30171901", + "30171902", + "30171903", + "30171904", + "30171905", + "30171906", + "30171907", + "30171908", + "30172000", + "30172100", + "30180000", + "30181500", + "30181501", + "30181502", + "30181503", + "30181504", + "30181505", + "30181506", + "30181507", + "30181508", + "30181511", + "30181514", + "30181515", + "30181518", + "30181519", + "30181600", + "30181601", + "30181602", + "30181603", + "30181604", + "30181605", + "30181606", + "30181607", + "30181608", + "30181609", + "30181610", + "30181611", + "30181612", + "30181613", + "30181614", + "30181700", + "30181701", + "30181702", + "30181800", + "30181801", + "30181802", + "30181803", + "30181804", + "30181805", + "30181806", + "30181807", + "30181808", + "30181809", + "30181810", + "30181811", + "30181812", + "30190000", + "30191500", + "30191600", + "30191700", + "30191800", + "30240000", + "30241500", + "30241501", + "30241502", + "30241503", + "30241504", + "30241505", + "30241506", + "30241507", + "30241508", + "30241509", + "30241510", + "30241511", + "30241512", + "30241513", + "30241514", + "30241515", + "30241600", + "30241601", + "30241602", + "30241603", + "30241604", + "30241700", + "30241701", + "30241702", + "30241705", + "30250000", + "30260000", + "30263900", + "30265000", + "30265001", + "30265002", + "30265003", + "30265004", + "30265005", + "30265006", + "30265007", + "30265008", + "30265009", + "30265010", + "30265011", + "30265012", + "30265400", + "30265401", + "30265402", + "30265403", + "30265404", + "30265800", + "30265802", + "31000000", + "31100000", + "31110000", + "31130000", + "31140000", + "31150000", + "31151500", + "31151600", + "31151700", + "31151800", + "31151900", + "31151902", + "31151904", + "31152000", + "31152100", + "31152200", + "31152300", + "31160000", + "31161500", + "31161600", + "31161700", + "31161800", + "31161900", + "31162000", + "31162100", + "31162200", + "31162300", + "31162400", + "31162500", + "31162600", + "31162700", + "31162800", + "31162900", + "31163000", + "31163100", + "31163200", + "31163300", + "31163400", + "31170000", + "31171500", + "31171504", + "31171600", + "31171700", + "31171800", + "31171900", + "31180000", + "31190000", + "31191500", + "31191506", + "31191600", + "31200000", + "31201500", + "31201505", + "31201600", + "31210000", + "31211500", + "31211507", + "31211523", + "31211600", + "31211700", + "31211800", + "31211900", + "31220000", + "31230000", + "31240000", + "31250000", + "31260000", + "31270000", + "31280000", + "31290000", + "31300000", + "31310000", + "31320000", + "31330000", + "31340000", + "31350000", + "31360000", + "31370000", + "31380000", + "31390000", + "31400000", + "31401500", + "31401503", + "31410000", + "31420000", + "32000000", + "32100000", + "32101500", + "32101600", + "32101601", + "32110000", + "32120000", + "32121700", + "32121701", + "32121702", + "32121703", + "32121704", + "32121705", + "32130000", + "32131000", + "32140000", + "32150000", + "39000000", + "39100000", + "39101600", + "39101601", + "39101602", + "39101603", + "39101605", + "39101608", + "39101612", + "39101613", + "39101616", + "39101800", + "39101900", + "39110000", + "39111500", + "39111510", + "39111527", + "39111530", + "39111531", + "39111542", + "39111600", + "39111608", + "39111610", + "39111612", + "39111613", + "39111616", + "39111617", + "39111621", + "39111622", + "39111623", + "39111624", + "39111625", + "39111626", + "39111627", + "39111628", + "39111629", + "39111630", + "39111700", + "39111800", + "39111810", + "39111900", + "39112000", + "39112001", + "39112100", + "39112200", + "39112300", + "39112400", + "39112500", + "39112600", + "39120000", + "39121000", + "39121001", + "39121004", + "39121006", + "39121011", + "39121017", + "39121036", + "39121040", + "39121100", + "39121101", + "39121300", + "39121400", + "39121402", + "39121406", + "39121500", + "39121534", + "39121600", + "39121621", + "39121635", + "39121700", + "39121701", + "39121721", + "39121800", + "39121801", + "39121803", + "39121900", + "39121901", + "39122000", + "39122001", + "39122100", + "39122200", + "39122216", + "39122300", + "39130000", + "39131500", + "39131600", + "39131700", + "40000000", + "40100000", + "40101500", + "40101503", + "40101512", + "40101600", + "40101601", + "40101602", + "40101604", + "40101609", + "40101700", + "40101701", + "40101702", + "40101703", + "40101704", + "40101707", + "40101709", + "40101710", + "40101711", + "40101712", + "40101713", + "40101714", + "40101716", + "40101717", + "40101719", + "40101720", + "40101721", + "40101722", + "40101723", + "40101800", + "40101801", + "40101802", + "40101805", + "40101806", + "40101807", + "40101808", + "40101900", + "40101901", + "40101902", + "40101903", + "40102000", + "40102100", + "40140000", + "40141600", + "40141700", + "40141900", + "40142000", + "40142200", + "40142500", + "40150000", + "40151500", + "40151503", + "40151506", + "40151507", + "40151510", + "40151583", + "40151585", + "40151600", + "40151601", + "40151607", + "40151700", + "40160000", + "40161500", + "40161504", + "40161505", + "40161600", + "40161602", + "40161608", + "40161609", + "40161700", + "40161800", + "40170000", + "40171600", + "40174700", + "40174712", + "40180000", + "40181800", + "40183000", + "40183001", + "41000000", + "41100000", + "41101500", + "41101502", + "41101503", + "41101504", + "41101515", + "41101516", + "41101518", + "41101519", + "41101700", + "41101701", + "41101703", + "41101705", + "41101706", + "41101707", + "41101708", + "41101709", + "41101800", + "41101801", + "41101802", + "41101803", + "41101804", + "41101805", + "41101806", + "41101807", + "41101808", + "41101809", + "41101810", + "41101811", + "41101812", + "41101813", + "41101900", + "41101901", + "41101902", + "41101903", + "41102400", + "41102401", + "41102402", + "41102403", + "41102404", + "41102405", + "41102406", + "41102407", + "41102410", + "41102412", + "41102421", + "41102422", + "41102423", + "41102424", + "41102425", + "41102426", + "41102427", + "41102428", + "41102429", + "41102430", + "41102500", + "41102501", + "41102502", + "41102503", + "41102504", + "41102505", + "41102506", + "41102507", + "41102508", + "41102509", + "41102510", + "41102511", + "41102512", + "41102513", + "41102600", + "41102601", + "41102602", + "41102603", + "41102604", + "41102605", + "41102606", + "41102608", + "41102610", + "41102611", + "41102612", + "41102613", + "41102614", + "41102700", + "41102701", + "41102702", + "41102703", + "41102704", + "41102705", + "41102900", + "41102901", + "41102905", + "41102909", + "41102910", + "41102911", + "41102912", + "41102913", + "41102914", + "41102915", + "41102916", + "41102917", + "41102918", + "41102919", + "41102920", + "41102921", + "41102922", + "41102923", + "41102928", + "41103000", + "41103001", + "41103003", + "41103004", + "41103005", + "41103006", + "41103007", + "41103008", + "41103010", + "41103011", + "41103012", + "41103013", + "41103014", + "41103015", + "41103017", + "41103019", + "41103020", + "41103021", + "41103022", + "41103023", + "41103024", + "41103025", + "41103026", + "41103027", + "41103028", + "41103029", + "41103030", + "41103031", + "41103032", + "41103033", + "41103034", + "41103035", + "41103036", + "41103037", + "41103200", + "41103201", + "41103202", + "41103203", + "41103205", + "41103206", + "41103207", + "41103208", + "41103209", + "41103210", + "41103211", + "41103212", + "41103213", + "41103300", + "41103301", + "41103302", + "41103303", + "41103305", + "41103306", + "41103307", + "41103308", + "41103309", + "41103310", + "41103311", + "41103312", + "41103313", + "41103314", + "41103315", + "41103316", + "41103317", + "41103318", + "41103319", + "41103320", + "41103321", + "41103322", + "41103323", + "41103324", + "41103325", + "41103326", + "41103327", + "41103328", + "41103400", + "41103401", + "41103403", + "41103406", + "41103407", + "41103408", + "41103409", + "41103410", + "41103411", + "41103412", + "41103413", + "41103414", + "41103415", + "41103416", + "41103417", + "41103418", + "41103419", + "41103420", + "41103421", + "41103500", + "41103501", + "41103502", + "41103504", + "41103506", + "41103507", + "41103508", + "41103509", + "41103510", + "41103511", + "41103512", + "41103513", + "41103514", + "41103515", + "41103516", + "41103517", + "41103700", + "41103701", + "41103702", + "41103703", + "41103704", + "41103705", + "41103706", + "41103707", + "41103708", + "41103709", + "41103710", + "41103711", + "41103712", + "41103713", + "41103714", + "41103715", + "41103716", + "41103717", + "41103718", + "41103800", + "41103801", + "41103802", + "41103803", + "41103804", + "41103805", + "41103806", + "41103807", + "41103808", + "41103809", + "41103810", + "41103811", + "41103812", + "41103813", + "41103814", + "41103815", + "41103816", + "41103817", + "41103818", + "41103819", + "41103900", + "41103901", + "41103902", + "41103903", + "41103904", + "41103905", + "41103906", + "41103907", + "41103908", + "41103909", + "41103910", + "41103911", + "41103912", + "41103913", + "41103914", + "41103915", + "41103916", + "41103917", + "41104000", + "41104001", + "41104002", + "41104003", + "41104004", + "41104005", + "41104006", + "41104007", + "41104008", + "41104009", + "41104010", + "41104011", + "41104012", + "41104013", + "41104014", + "41104015", + "41104017", + "41104018", + "41104020", + "41104021", + "41104022", + "41104023", + "41104100", + "41104101", + "41104102", + "41104103", + "41104104", + "41104105", + "41104106", + "41104107", + "41104108", + "41104109", + "41104110", + "41104111", + "41104112", + "41104114", + "41104115", + "41104116", + "41104117", + "41104118", + "41104119", + "41104120", + "41104121", + "41104122", + "41104123", + "41104124", + "41104125", + "41104126", + "41104127", + "41104128", + "41104129", + "41104130", + "41104131", + "41104132", + "41104133", + "41104134", + "41104135", + "41104136", + "41104137", + "41104138", + "41104200", + "41104201", + "41104202", + "41104203", + "41104204", + "41104205", + "41104206", + "41104207", + "41104208", + "41104209", + "41104210", + "41104211", + "41104212", + "41104213", + "41104214", + "41104300", + "41104301", + "41104302", + "41104303", + "41104304", + "41104305", + "41104306", + "41104307", + "41104308", + "41104309", + "41104400", + "41104401", + "41104402", + "41104403", + "41104404", + "41104405", + "41104406", + "41104413", + "41104414", + "41104415", + "41104416", + "41104417", + "41104418", + "41104419", + "41104420", + "41104423", + "41104424", + "41104425", + "41104426", + "41104427", + "41104500", + "41104501", + "41104502", + "41104503", + "41104504", + "41104505", + "41104506", + "41104507", + "41104508", + "41104509", + "41104510", + "41104511", + "41104512", + "41104513", + "41104600", + "41104601", + "41104602", + "41104603", + "41104604", + "41104605", + "41104609", + "41104610", + "41104611", + "41104612", + "41104613", + "41104700", + "41104701", + "41104702", + "41104703", + "41104704", + "41104800", + "41104801", + "41104802", + "41104803", + "41104804", + "41104805", + "41104806", + "41104810", + "41104811", + "41104812", + "41104813", + "41104814", + "41104815", + "41104816", + "41104817", + "41104818", + "41104819", + "41104820", + "41104821", + "41104900", + "41104901", + "41104902", + "41104903", + "41104904", + "41104905", + "41104907", + "41104908", + "41104909", + "41104910", + "41104911", + "41104912", + "41104913", + "41104914", + "41104915", + "41104916", + "41104917", + "41104918", + "41104919", + "41104920", + "41104921", + "41104922", + "41104923", + "41104924", + "41104925", + "41104927", + "41104928", + "41104929", + "41104930", + "41104931", + "41104932", + "41104933", + "41105000", + "41105001", + "41105002", + "41105003", + "41105100", + "41105101", + "41105102", + "41105103", + "41105104", + "41105105", + "41105106", + "41105107", + "41105108", + "41105109", + "41105200", + "41105201", + "41105202", + "41105203", + "41105204", + "41105205", + "41105206", + "41105207", + "41105208", + "41105209", + "41105300", + "41105301", + "41105302", + "41105303", + "41105304", + "41105305", + "41105307", + "41105308", + "41105309", + "41105310", + "41105311", + "41105312", + "41105313", + "41105314", + "41105315", + "41105316", + "41105317", + "41105319", + "41105320", + "41105321", + "41105322", + "41105323", + "41105325", + "41105326", + "41105327", + "41105328", + "41105329", + "41105330", + "41105331", + "41105332", + "41105333", + "41105334", + "41105335", + "41105336", + "41105337", + "41105338", + "41105339", + "41105340", + "41105341", + "41105342", + "41105343", + "41105344", + "41105345", + "41105500", + "41105501", + "41105502", + "41105504", + "41105506", + "41105508", + "41105509", + "41105510", + "41105511", + "41105512", + "41105513", + "41105514", + "41105515", + "41105516", + "41105517", + "41105518", + "41105519", + "41105520", + "41105521", + "41105600", + "41105601", + "41105700", + "41105800", + "41105803", + "41105804", + "41105900", + "41105902", + "41105903", + "41105906", + "41105907", + "41105908", + "41106000", + "41106004", + "41106005", + "41106100", + "41106101", + "41106102", + "41106103", + "41106104", + "41106200", + "41106203", + "41106204", + "41106210", + "41106211", + "41106212", + "41106213", + "41106214", + "41106215", + "41106216", + "41106217", + "41106218", + "41106219", + "41106220", + "41106221", + "41106222", + "41106223", + "41106224", + "41106232", + "41106300", + "41106302", + "41106303", + "41106306", + "41106307", + "41106308", + "41106309", + "41106311", + "41106313", + "41106314", + "41106315", + "41106400", + "41106401", + "41106402", + "41106403", + "41106500", + "41106501", + "41106502", + "41106505", + "41106506", + "41106507", + "41106508", + "41106509", + "41106510", + "41106511", + "41106512", + "41106513", + "41106514", + "41106515", + "41106516", + "41106600", + "41106601", + "41106604", + "41106605", + "41106606", + "41106607", + "41106608", + "41106609", + "41106610", + "41106611", + "41106612", + "41106615", + "41106616", + "41106617", + "41106619", + "41106620", + "41106621", + "41106622", + "41110000", + "41111500", + "41111501", + "41111502", + "41111503", + "41111504", + "41111505", + "41111506", + "41111507", + "41111508", + "41111509", + "41111510", + "41111511", + "41111512", + "41111513", + "41111515", + "41111516", + "41111517", + "41111518", + "41111519", + "41111520", + "41111521", + "41111522", + "41111523", + "41111524", + "41111525", + "41111526", + "41111528", + "41111529", + "41111530", + "41111531", + "41111600", + "41111601", + "41111602", + "41111603", + "41111604", + "41111605", + "41111606", + "41111607", + "41111613", + "41111614", + "41111615", + "41111616", + "41111617", + "41111618", + "41111619", + "41111620", + "41111621", + "41111622", + "41111623", + "41111624", + "41111625", + "41111626", + "41111627", + "41111628", + "41111629", + "41111630", + "41111631", + "41111632", + "41111633", + "41111634", + "41111635", + "41111636", + "41111637", + "41111638", + "41111639", + "41111640", + "41111641", + "41111642", + "41111643", + "41111644", + "41111645", + "41111646", + "41111647", + "41111648", + "41111649", + "41111650", + "41111651", + "41111652", + "41111700", + "41111701", + "41111702", + "41111703", + "41111704", + "41111705", + "41111706", + "41111707", + "41111708", + "41111709", + "41111710", + "41111711", + "41111712", + "41111713", + "41111714", + "41111715", + "41111716", + "41111717", + "41111718", + "41111719", + "41111720", + "41111721", + "41111722", + "41111723", + "41111724", + "41111725", + "41111726", + "41111727", + "41111728", + "41111729", + "41111730", + "41111731", + "41111733", + "41111734", + "41111735", + "41111736", + "41111737", + "41111738", + "41111739", + "41111740", + "41111741", + "41111742", + "41111743", + "41111744", + "41111745", + "41111746", + "41111747", + "41111748", + "41111749", + "41111750", + "41111751", + "41111752", + "41111753", + "41111754", + "41111755", + "41111756", + "41111757", + "41111758", + "41111759", + "41111760", + "41111761", + "41111762", + "41111763", + "41111764", + "41111765", + "41111766", + "41111767", + "41111768", + "41111769", + "41111770", + "41111771", + "41111772", + "41111800", + "41111808", + "41111809", + "41111810", + "41111811", + "41111812", + "41111815", + "41111816", + "41111817", + "41111818", + "41111819", + "41111820", + "41111900", + "41111901", + "41111902", + "41111903", + "41111904", + "41111905", + "41111906", + "41111907", + "41111908", + "41111909", + "41111910", + "41111911", + "41111912", + "41111913", + "41111914", + "41111915", + "41111916", + "41111917", + "41111918", + "41111919", + "41111920", + "41111921", + "41111922", + "41111923", + "41111924", + "41111926", + "41111927", + "41111928", + "41111929", + "41111930", + "41111931", + "41111932", + "41111933", + "41111934", + "41111935", + "41111936", + "41111937", + "41111938", + "41111939", + "41111940", + "41111941", + "41111942", + "41111943", + "41111944", + "41111945", + "41111946", + "41111947", + "41111948", + "41111949", + "41111950", + "41111951", + "41111952", + "41111953", + "41111954", + "41111955", + "41111956", + "41111957", + "41111958", + "41111959", + "41111960", + "41111961", + "41111962", + "41111963", + "41111964", + "41111965", + "41111966", + "41111967", + "41111968", + "41111969", + "41111970", + "41111971", + "41111972", + "41111973", + "41111974", + "41111975", + "41111976", + "41111977", + "41111978", + "41111979", + "41111980", + "41111981", + "41112100", + "41112101", + "41112103", + "41112104", + "41112105", + "41112106", + "41112107", + "41112108", + "41112109", + "41112110", + "41112111", + "41112112", + "41112113", + "41112114", + "41112200", + "41112201", + "41112202", + "41112203", + "41112204", + "41112205", + "41112206", + "41112207", + "41112209", + "41112210", + "41112211", + "41112212", + "41112213", + "41112214", + "41112215", + "41112216", + "41112217", + "41112219", + "41112220", + "41112221", + "41112222", + "41112223", + "41112224", + "41112225", + "41112226", + "41112227", + "41112228", + "41112229", + "41112230", + "41112231", + "41112232", + "41112233", + "41112234", + "41112235", + "41112236", + "41112237", + "41112238", + "41112239", + "41112240", + "41112241", + "41112242", + "41112243", + "41112244", + "41112300", + "41112301", + "41112302", + "41112303", + "41112304", + "41112305", + "41112306", + "41112307", + "41112400", + "41112401", + "41112402", + "41112403", + "41112404", + "41112405", + "41112406", + "41112407", + "41112408", + "41112409", + "41112410", + "41112411", + "41112412", + "41112413", + "41112414", + "41112415", + "41112416", + "41112417", + "41112418", + "41112419", + "41112420", + "41112421", + "41112422", + "41112423", + "41112500", + "41112501", + "41112502", + "41112503", + "41112504", + "41112505", + "41112506", + "41112508", + "41112509", + "41112510", + "41112511", + "41112512", + "41112513", + "41112514", + "41112516", + "41112517", + "41112518", + "41112519", + "41112520", + "41112521", + "41112522", + "41112523", + "41112600", + "41112601", + "41112602", + "41112700", + "41112701", + "41112702", + "41112704", + "41112800", + "41112801", + "41112802", + "41112803", + "41112900", + "41112901", + "41112902", + "41112903", + "41112904", + "41113000", + "41113001", + "41113002", + "41113003", + "41113004", + "41113005", + "41113006", + "41113007", + "41113008", + "41113009", + "41113010", + "41113023", + "41113024", + "41113025", + "41113026", + "41113027", + "41113029", + "41113030", + "41113031", + "41113033", + "41113034", + "41113035", + "41113036", + "41113037", + "41113038", + "41113039", + "41113040", + "41113041", + "41113042", + "41113043", + "41113044", + "41113045", + "41113046", + "41113047", + "41113048", + "41113049", + "41113050", + "41113051", + "41113052", + "41113053", + "41113054", + "41113055", + "41113056", + "41113057", + "41113100", + "41113107", + "41113108", + "41113109", + "41113110", + "41113115", + "41113116", + "41113117", + "41113118", + "41113119", + "41113124", + "41113300", + "41113301", + "41113309", + "41113310", + "41113311", + "41113312", + "41113313", + "41113318", + "41113319", + "41113320", + "41113322", + "41113323", + "41113325", + "41113327", + "41113328", + "41113331", + "41113332", + "41113333", + "41113400", + "41113600", + "41113601", + "41113602", + "41113603", + "41113604", + "41113605", + "41113606", + "41113607", + "41113608", + "41113611", + "41113612", + "41113613", + "41113614", + "41113615", + "41113616", + "41113617", + "41113618", + "41113619", + "41113620", + "41113621", + "41113622", + "41113623", + "41113624", + "41113625", + "41113626", + "41113627", + "41113628", + "41113629", + "41113630", + "41113631", + "41113632", + "41113633", + "41113634", + "41113635", + "41113636", + "41113637", + "41113638", + "41113639", + "41113640", + "41113641", + "41113642", + "41113643", + "41113644", + "41113645", + "41113646", + "41113647", + "41113649", + "41113650", + "41113651", + "41113652", + "41113653", + "41113654", + "41113655", + "41113656", + "41113657", + "41113658", + "41113659", + "41113660", + "41113661", + "41113662", + "41113663", + "41113664", + "41113665", + "41113666", + "41113667", + "41113668", + "41113669", + "41113670", + "41113671", + "41113672", + "41113673", + "41113674", + "41113675", + "41113676", + "41113677", + "41113678", + "41113679", + "41113680", + "41113681", + "41113682", + "41113683", + "41113684", + "41113685", + "41113686", + "41113687", + "41113688", + "41113689", + "41113700", + "41113701", + "41113702", + "41113703", + "41113704", + "41113705", + "41113706", + "41113708", + "41113709", + "41113710", + "41113711", + "41113712", + "41113713", + "41113714", + "41113716", + "41113717", + "41113726", + "41113727", + "41113728", + "41113800", + "41113801", + "41113802", + "41113803", + "41113804", + "41113805", + "41113806", + "41113807", + "41113808", + "41113809", + "41113810", + "41113811", + "41113812", + "41113813", + "41113814", + "41113815", + "41113816", + "41113817", + "41113818", + "41113819", + "41113820", + "41113821", + "41113822", + "41113823", + "41113824", + "41113825", + "41113826", + "41113827", + "41113828", + "41113829", + "41113830", + "41113831", + "41113900", + "41113901", + "41113902", + "41113903", + "41113904", + "41113905", + "41113906", + "41113907", + "41113908", + "41113909", + "41113910", + "41114000", + "41114001", + "41114100", + "41114102", + "41114103", + "41114104", + "41114105", + "41114106", + "41114107", + "41114108", + "41114200", + "41114201", + "41114202", + "41114203", + "41114207", + "41114300", + "41114301", + "41114302", + "41114303", + "41114400", + "41114401", + "41114402", + "41114403", + "41114404", + "41114405", + "41114406", + "41114407", + "41114408", + "41114409", + "41114410", + "41114411", + "41114412", + "41114413", + "41114414", + "41114415", + "41114416", + "41114417", + "41114418", + "41114419", + "41114420", + "41114421", + "41114422", + "41114423", + "41114424", + "41114425", + "41114426", + "41114427", + "41114428", + "41114429", + "41114430", + "41114431", + "41114500", + "41114501", + "41114502", + "41114503", + "41114504", + "41114505", + "41114506", + "41114507", + "41114508", + "41114509", + "41114510", + "41114511", + "41114512", + "41114513", + "41114514", + "41114515", + "41114516", + "41114517", + "41114518", + "41114519", + "41114520", + "41114521", + "41114522", + "41114523", + "41114524", + "41114525", + "41114526", + "41114527", + "41114528", + "41114529", + "41114530", + "41114600", + "41114601", + "41114602", + "41114603", + "41114604", + "41114605", + "41114606", + "41114607", + "41114608", + "41114609", + "41114610", + "41114611", + "41114612", + "41114613", + "41114614", + "41114615", + "41114616", + "41114617", + "41114618", + "41114619", + "41114620", + "41114621", + "41114622", + "41114623", + "41114624", + "41114625", + "41114626", + "41114627", + "41114628", + "41114629", + "41114630", + "41114631", + "41114632", + "41114633", + "41114634", + "41114635", + "41114636", + "41114637", + "41114638", + "41114639", + "41114640", + "41114641", + "41114642", + "41114643", + "41114644", + "41114645", + "41114646", + "41114647", + "41114648", + "41114649", + "41114650", + "41114700", + "41114800", + "41114802", + "41115100", + "41115102", + "41115200", + "41115300", + "41115301", + "41115302", + "41115303", + "41115304", + "41115307", + "41115308", + "41115310", + "41115311", + "41115312", + "41115314", + "41115315", + "41115316", + "41115317", + "41115318", + "41115319", + "41115320", + "41115321", + "41115322", + "41115323", + "41115324", + "41115325", + "41115326", + "41115327", + "41115330", + "41115335", + "41115340", + "41115400", + "41115401", + "41115402", + "41115403", + "41115404", + "41115405", + "41115406", + "41115407", + "41115408", + "41115409", + "41115411", + "41115412", + "41115413", + "41115414", + "41115415", + "41115416", + "41115417", + "41115418", + "41115500", + "41115505", + "41115600", + "41115601", + "41115602", + "41115603", + "41115609", + "41115700", + "41115703", + "41115704", + "41115705", + "41115707", + "41115708", + "41115709", + "41115800", + "41115801", + "41115802", + "41115803", + "41115804", + "41115805", + "41115806", + "41115807", + "41115808", + "41115809", + "41115810", + "41115811", + "41115812", + "41115813", + "41115814", + "41115815", + "41115816", + "41115817", + "41115818", + "41115819", + "41115820", + "41115821", + "41115822", + "41115823", + "41115824", + "41115825", + "41115826", + "41115827", + "41115828", + "41115829", + "41115830", + "41115831", + "41115832", + "41115833", + "41115834", + "41115835", + "41115836", + "41115837", + "41115838", + "41115839", + "41115840", + "41115841", + "41115842", + "41115843", + "41115844", + "41115845", + "41115846", + "41115847", + "41115848", + "41115849", + "41115850", + "41115851", + "41115852", + "41115853", + "41115854", + "41115855", + "41115856", + "41115857", + "41115858", + "41115859", + "41115860", + "41115861", + "41115862", + "41115863", + "41115864", + "41115865", + "41115866", + "41115867", + "41115868", + "41115872", + "41116000", + "41116001", + "41116002", + "41116003", + "41116004", + "41116005", + "41116006", + "41116007", + "41116008", + "41116009", + "41116010", + "41116011", + "41116012", + "41116013", + "41116014", + "41116015", + "41116016", + "41116017", + "41116018", + "41116019", + "41116020", + "41116021", + "41116022", + "41116023", + "41116024", + "41116025", + "41116026", + "41116027", + "41116029", + "41116100", + "41116101", + "41116102", + "41116103", + "41116104", + "41116105", + "41116106", + "41116107", + "41116108", + "41116109", + "41116110", + "41116111", + "41116112", + "41116113", + "41116116", + "41116117", + "41116118", + "41116119", + "41116120", + "41116121", + "41116122", + "41116123", + "41116124", + "41116125", + "41116126", + "41116127", + "41116128", + "41116129", + "41116130", + "41116131", + "41116132", + "41116133", + "41116134", + "41116135", + "41116136", + "41116137", + "41116138", + "41116139", + "41116140", + "41116141", + "41116142", + "41116143", + "41116144", + "41116145", + "41116146", + "41116147", + "41116148", + "41116149", + "41116150", + "41116151", + "41116152", + "41116153", + "41116154", + "41116155", + "41116156", + "41116157", + "41116158", + "41116159", + "41116160", + "41116161", + "41116162", + "41116163", + "41116164", + "41116165", + "41116166", + "41116167", + "41116200", + "41116201", + "41116202", + "41116203", + "41116205", + "41116206", + "41116207", + "41116208", + "41116209", + "41116210", + "41116211", + "41116212", + "41116213", + "41116214", + "41116215", + "41116216", + "41116217", + "41116218", + "41116219", + "41116220", + "41116221", + "41116222", + "41116223", + "41116224", + "41116225", + "41116300", + "41116301", + "41116302", + "41116303", + "41116304", + "41116400", + "41116500", + "41116501", + "41116502", + "41120000", + "41121500", + "41121501", + "41121502", + "41121503", + "41121504", + "41121505", + "41121506", + "41121507", + "41121508", + "41121509", + "41121510", + "41121511", + "41121513", + "41121514", + "41121515", + "41121516", + "41121517", + "41121518", + "41121519", + "41121520", + "41121521", + "41121522", + "41121523", + "41121600", + "41121601", + "41121602", + "41121603", + "41121604", + "41121605", + "41121606", + "41121607", + "41121608", + "41121609", + "41121610", + "41121700", + "41121701", + "41121702", + "41121703", + "41121704", + "41121705", + "41121706", + "41121707", + "41121708", + "41121709", + "41121710", + "41121711", + "41121712", + "41121713", + "41121714", + "41121715", + "41121800", + "41121801", + "41121802", + "41121803", + "41121804", + "41121805", + "41121806", + "41121807", + "41121808", + "41121809", + "41121810", + "41121811", + "41121812", + "41121813", + "41121814", + "41121815", + "41121816", + "41121817", + "41121818", + "41121819", + "41121820", + "41121821", + "41122000", + "41122001", + "41122002", + "41122003", + "41122004", + "41122100", + "41122101", + "41122102", + "41122103", + "41122104", + "41122105", + "41122106", + "41122107", + "41122108", + "41122109", + "41122110", + "41122111", + "41122112", + "41122113", + "41122114", + "41122200", + "41122201", + "41122202", + "41122203", + "41122300", + "41122301", + "41122400", + "41122401", + "41122402", + "41122403", + "41122404", + "41122405", + "41122406", + "41122407", + "41122408", + "41122409", + "41122410", + "41122411", + "41122412", + "41122413", + "41122414", + "41122415", + "41122416", + "41122417", + "41122418", + "41122419", + "41122420", + "41122421", + "41122500", + "41122501", + "41122502", + "41122503", + "41122600", + "41122601", + "41122602", + "41122603", + "41122604", + "41122605", + "41122606", + "41122607", + "41122608", + "41122700", + "41122701", + "41122702", + "41122703", + "41122704", + "41122800", + "41122801", + "41122802", + "41122803", + "41122804", + "41122805", + "41122806", + "41122807", + "41122808", + "41122809", + "41122810", + "41122811", + "41123000", + "41123001", + "41123002", + "41123003", + "41123004", + "41123005", + "41123006", + "41123100", + "41123101", + "41123102", + "41123103", + "41123104", + "41123105", + "41123106", + "41123200", + "41123201", + "41123202", + "41123203", + "41123204", + "41123300", + "41123302", + "41123303", + "41123304", + "41123305", + "41123306", + "41123307", + "41123308", + "41123309", + "41123310", + "41123311", + "41123312", + "41123313", + "41123314", + "41123400", + "41123401", + "41123402", + "41123403", + "41150000", + "41151500", + "41151600", + "41151629", + "41170000", + "41171600", + "42000000", + "42120000", + "42121500", + "42121501", + "42121506", + "42121507", + "42121518", + "42121600", + "42121700", + "42121800", + "42130000", + "42131500", + "42131501", + "42131502", + "42131503", + "42131504", + "42131505", + "42131506", + "42131507", + "42131508", + "42131509", + "42131510", + "42131511", + "42131512", + "42131513", + "42131514", + "42131600", + "42131601", + "42131602", + "42131603", + "42131604", + "42131607", + "42131608", + "42131609", + "42131610", + "42131611", + "42131612", + "42131613", + "42131615", + "42131700", + "42131701", + "42131702", + "42131704", + "42131706", + "42131707", + "42131708", + "42131709", + "42131710", + "42131711", + "42131713", + "42131716", + "42131717", + "42131719", + "42131721", + "42131722", + "42132100", + "42132101", + "42132102", + "42132103", + "42132104", + "42132105", + "42132106", + "42132107", + "42132108", + "42132109", + "42132110", + "42132111", + "42132112", + "42132113", + "42132114", + "42132115", + "42132116", + "42132200", + "42132201", + "42132202", + "42132203", + "42132204", + "42132205", + "42132300", + "42132301", + "42132302", + "42132303", + "42140000", + "42141500", + "42141501", + "42141502", + "42141503", + "42141504", + "42141507", + "42141600", + "42141601", + "42141602", + "42141603", + "42141605", + "42141606", + "42141607", + "42141608", + "42141700", + "42141701", + "42141800", + "42141801", + "42141802", + "42141803", + "42141804", + "42141805", + "42141806", + "42141807", + "42141808", + "42141809", + "42141810", + "42141811", + "42141812", + "42141813", + "42141814", + "42141815", + "42141816", + "42141817", + "42141819", + "42141822", + "42141900", + "42141903", + "42141904", + "42141905", + "42142100", + "42142101", + "42142102", + "42142103", + "42142104", + "42142105", + "42142106", + "42142107", + "42142108", + "42142109", + "42142110", + "42142111", + "42142112", + "42142113", + "42142114", + "42142119", + "42142120", + "42142121", + "42142130", + "42142200", + "42142201", + "42142300", + "42142301", + "42142302", + "42142303", + "42142500", + "42142501", + "42142502", + "42142503", + "42142504", + "42142506", + "42142509", + "42142510", + "42142511", + "42142512", + "42142513", + "42142514", + "42142516", + "42142518", + "42142519", + "42142520", + "42142521", + "42142523", + "42142525", + "42142527", + "42142528", + "42142529", + "42142530", + "42142531", + "42142532", + "42142533", + "42142534", + "42142535", + "42142536", + "42142537", + "42142538", + "42142600", + "42142601", + "42142602", + "42142603", + "42142604", + "42142605", + "42142606", + "42142607", + "42142608", + "42142609", + "42142610", + "42142611", + "42142612", + "42142613", + "42142614", + "42142615", + "42142616", + "42142617", + "42142618", + "42142619", + "42142620", + "42142627", + "42142628", + "42142629", + "42142630", + "42142700", + "42142701", + "42142702", + "42142703", + "42142704", + "42142705", + "42142706", + "42142707", + "42142708", + "42142709", + "42142710", + "42142712", + "42142713", + "42142714", + "42142715", + "42142716", + "42142717", + "42142718", + "42142719", + "42142720", + "42142721", + "42142733", + "42142734", + "42142736", + "42142800", + "42142801", + "42142802", + "42142900", + "42142901", + "42142902", + "42143100", + "42143101", + "42143102", + "42143103", + "42143104", + "42143105", + "42143106", + "42143107", + "42143108", + "42143109", + "42143110", + "42143111", + "42143112", + "42143113", + "42143114", + "42143115", + "42143116", + "42143117", + "42143118", + "42143119", + "42143120", + "42143121", + "42143122", + "42143123", + "42143124", + "42143125", + "42143126", + "42143127", + "42143128", + "42143129", + "42143130", + "42143131", + "42143132", + "42143133", + "42143134", + "42143135", + "42143136", + "42143200", + "42143201", + "42143203", + "42143204", + "42143300", + "42143301", + "42143302", + "42143303", + "42143304", + "42143307", + "42143400", + "42143500", + "42143515", + "42143516", + "42143523", + "42143600", + "42143601", + "42143602", + "42143603", + "42143604", + "42143605", + "42143606", + "42143607", + "42143608", + "42143609", + "42143700", + "42143701", + "42143702", + "42143703", + "42143704", + "42143705", + "42143706", + "42143707", + "42143708", + "42143709", + "42143713", + "42143800", + "42143801", + "42143802", + "42143803", + "42143900", + "42143901", + "42143902", + "42143903", + "42144000", + "42144100", + "42144101", + "42144102", + "42144103", + "42144200", + "42144400", + "42144401", + "42144406", + "42144500", + "42150000", + "42151500", + "42151501", + "42151502", + "42151503", + "42151504", + "42151600", + "42151614", + "42151636", + "42151686", + "42151700", + "42151705", + "42151800", + "42151900", + "42151901", + "42152000", + "42152008", + "42152016", + "42152017", + "42152100", + "42152200", + "42152234", + "42152300", + "42152400", + "42152423", + "42152424", + "42152425", + "42152434", + "42152446", + "42152465", + "42152500", + "42152501", + "42152502", + "42152503", + "42152504", + "42152505", + "42152506", + "42152507", + "42152508", + "42152509", + "42152511", + "42152512", + "42152513", + "42152600", + "42152700", + "42152800", + "42152900", + "42152902", + "42160000", + "42161500", + "42161501", + "42161502", + "42161503", + "42161504", + "42161505", + "42161506", + "42161507", + "42161508", + "42161509", + "42161510", + "42161600", + "42161601", + "42161602", + "42161603", + "42161604", + "42161605", + "42161606", + "42161607", + "42161608", + "42161609", + "42161610", + "42161611", + "42161612", + "42161613", + "42161614", + "42161615", + "42161616", + "42161617", + "42161618", + "42161619", + "42161620", + "42161621", + "42161622", + "42161623", + "42161624", + "42161625", + "42161627", + "42161628", + "42161629", + "42161630", + "42161631", + "42161632", + "42161633", + "42161634", + "42161635", + "42161659", + "42161700", + "42161701", + "42161702", + "42161703", + "42161704", + "42161800", + "42161803", + "42161900", + "42170000", + "42171500", + "42171501", + "42171502", + "42171503", + "42171600", + "42171601", + "42171602", + "42171603", + "42171604", + "42171605", + "42171606", + "42171607", + "42171608", + "42171609", + "42171610", + "42171611", + "42171612", + "42171613", + "42171614", + "42171700", + "42171701", + "42171702", + "42171703", + "42171704", + "42171800", + "42171801", + "42171805", + "42171810", + "42171900", + "42171922", + "42172000", + "42172001", + "42172002", + "42172003", + "42172004", + "42172005", + "42172006", + "42172008", + "42172009", + "42172010", + "42172011", + "42172014", + "42172015", + "42172016", + "42172017", + "42172100", + "42172101", + "42172103", + "42172104", + "42172105", + "42172106", + "42180000", + "42181500", + "42181501", + "42181502", + "42181503", + "42181506", + "42181514", + "42181516", + "42181540", + "42181541", + "42181542", + "42181547", + "42181600", + "42181601", + "42181602", + "42181603", + "42181604", + "42181605", + "42181606", + "42181607", + "42181608", + "42181609", + "42181610", + "42181611", + "42181700", + "42181701", + "42181713", + "42181720", + "42181721", + "42181725", + "42181800", + "42181801", + "42181802", + "42181803", + "42181804", + "42181805", + "42181900", + "42181902", + "42181903", + "42181904", + "42181905", + "42181907", + "42181908", + "42181918", + "42182000", + "42182001", + "42182003", + "42182004", + "42182005", + "42182006", + "42182013", + "42182015", + "42182017", + "42182100", + "42182101", + "42182102", + "42182103", + "42182107", + "42182200", + "42182201", + "42182202", + "42182203", + "42182204", + "42182205", + "42182206", + "42182207", + "42182208", + "42182209", + "42182210", + "42182211", + "42182300", + "42182301", + "42182302", + "42182303", + "42182304", + "42182306", + "42182307", + "42182308", + "42182311", + "42182313", + "42182314", + "42182315", + "42182316", + "42182327", + "42182400", + "42182401", + "42182416", + "42182500", + "42182600", + "42182601", + "42182602", + "42182603", + "42182604", + "42182700", + "42182701", + "42182702", + "42182703", + "42182704", + "42182705", + "42182706", + "42182707", + "42182708", + "42182800", + "42182801", + "42182802", + "42182803", + "42182804", + "42182805", + "42182806", + "42182807", + "42182808", + "42183000", + "42183002", + "42183010", + "42183013", + "42183015", + "42183018", + "42183021", + "42183029", + "42183031", + "42183037", + "42183050", + "42183076", + "42183078", + "42183080", + "42183200", + "42183201", + "42183400", + "42183403", + "42183500", + "42183503", + "42183509", + "42190000", + "42191500", + "42191501", + "42191502", + "42191600", + "42191601", + "42191602", + "42191603", + "42191605", + "42191607", + "42191611", + "42191612", + "42191614", + "42191700", + "42191701", + "42191705", + "42191707", + "42191710", + "42191711", + "42191713", + "42191800", + "42191801", + "42191802", + "42191803", + "42191804", + "42191805", + "42191806", + "42191807", + "42191808", + "42191810", + "42191811", + "42191812", + "42191813", + "42191814", + "42191819", + "42191900", + "42191901", + "42191902", + "42191903", + "42191905", + "42191906", + "42191907", + "42191908", + "42191911", + "42192000", + "42192001", + "42192002", + "42192003", + "42192005", + "42192006", + "42192100", + "42192101", + "42192102", + "42192103", + "42192104", + "42192107", + "42192108", + "42192110", + "42192200", + "42192201", + "42192202", + "42192203", + "42192204", + "42192205", + "42192206", + "42192207", + "42192208", + "42192209", + "42192210", + "42192211", + "42192212", + "42192214", + "42192215", + "42192217", + "42192220", + "42192300", + "42192301", + "42192302", + "42192303", + "42192304", + "42192305", + "42192400", + "42192401", + "42192402", + "42192403", + "42192404", + "42192405", + "42192406", + "42192407", + "42192409", + "42192410", + "42192412", + "42192413", + "42192414", + "42192415", + "42192416", + "42192417", + "42192418", + "42192419", + "42192420", + "42192421", + "42192422", + "42192423", + "42192424", + "42192425", + "42192426", + "42192427", + "42192428", + "42192429", + "42192431", + "42192433", + "42192434", + "42192435", + "42192500", + "42192501", + "42192502", + "42192600", + "42192601", + "42192602", + "42192603", + "42192604", + "42192606", + "42192617", + "42192700", + "42192701", + "42192702", + "42192706", + "42192707", + "42192800", + "42200000", + "42201500", + "42201501", + "42201502", + "42201508", + "42201509", + "42201511", + "42201600", + "42201601", + "42201602", + "42201607", + "42201608", + "42201609", + "42201611", + "42201700", + "42201704", + "42201705", + "42201706", + "42201707", + "42201708", + "42201709", + "42201710", + "42201711", + "42201712", + "42201713", + "42201718", + "42201723", + "42201728", + "42201800", + "42201803", + "42201804", + "42201805", + "42201806", + "42201807", + "42201808", + "42201809", + "42201810", + "42201811", + "42201812", + "42201813", + "42201814", + "42201815", + "42201816", + "42201817", + "42201818", + "42201819", + "42201820", + "42201821", + "42201822", + "42201823", + "42201824", + "42201825", + "42201826", + "42201827", + "42201828", + "42201829", + "42201830", + "42201831", + "42201832", + "42201833", + "42201834", + "42201835", + "42201836", + "42201837", + "42201838", + "42201839", + "42201840", + "42201841", + "42201843", + "42201844", + "42201845", + "42201846", + "42201847", + "42201848", + "42201849", + "42201850", + "42201851", + "42201852", + "42201853", + "42201855", + "42201858", + "42201860", + "42201861", + "42201863", + "42201900", + "42201901", + "42201902", + "42201903", + "42201904", + "42201905", + "42201906", + "42201907", + "42201908", + "42202000", + "42202100", + "42202101", + "42202102", + "42202103", + "42202104", + "42202105", + "42202106", + "42202200", + "42202300", + "42202301", + "42202302", + "42202303", + "42202400", + "42202401", + "42202500", + "42202600", + "42202700", + "42202702", + "42202900", + "42202901", + "42202902", + "42203000", + "42203200", + "42203201", + "42203400", + "42203402", + "42203403", + "42203404", + "42203405", + "42203406", + "42203407", + "42203408", + "42203409", + "42203410", + "42203413", + "42203414", + "42203415", + "42203416", + "42203417", + "42203418", + "42203420", + "42203421", + "42203422", + "42203423", + "42203424", + "42203425", + "42203426", + "42203427", + "42203428", + "42203429", + "42203430", + "42203436", + "42203447", + "42203500", + "42203501", + "42203502", + "42203503", + "42203504", + "42203505", + "42203506", + "42203600", + "42203601", + "42203602", + "42203603", + "42203605", + "42203606", + "42203608", + "42203613", + "42203700", + "42203701", + "42203702", + "42203703", + "42203704", + "42203705", + "42203706", + "42203707", + "42203708", + "42203709", + "42203710", + "42203711", + "42203712", + "42203800", + "42203801", + "42203802", + "42203803", + "42203804", + "42203900", + "42203901", + "42203902", + "42203903", + "42204000", + "42204001", + "42204002", + "42204003", + "42204004", + "42204005", + "42204006", + "42204007", + "42204008", + "42204009", + "42204100", + "42204101", + "42210000", + "42211500", + "42211501", + "42211502", + "42211503", + "42211504", + "42211505", + "42211506", + "42211508", + "42211600", + "42211700", + "42211701", + "42211702", + "42211703", + "42211704", + "42211705", + "42211706", + "42211707", + "42211708", + "42211709", + "42211710", + "42211711", + "42211712", + "42211800", + "42211900", + "42211901", + "42211902", + "42211903", + "42211904", + "42211905", + "42211906", + "42211907", + "42211908", + "42211909", + "42211910", + "42211911", + "42211912", + "42211913", + "42211914", + "42211915", + "42211916", + "42211917", + "42211918", + "42212000", + "42212001", + "42212002", + "42212003", + "42212004", + "42212005", + "42212006", + "42212007", + "42212100", + "42212200", + "42212300", + "42220000", + "42221500", + "42221501", + "42221502", + "42221503", + "42221504", + "42221506", + "42221507", + "42221508", + "42221509", + "42221512", + "42221514", + "42221515", + "42221516", + "42221600", + "42221601", + "42221602", + "42221603", + "42221604", + "42221605", + "42221606", + "42221607", + "42221608", + "42221609", + "42221610", + "42221611", + "42221612", + "42221613", + "42221614", + "42221615", + "42221616", + "42221617", + "42221618", + "42221619", + "42221700", + "42221701", + "42221703", + "42221704", + "42221705", + "42221706", + "42221707", + "42221800", + "42221801", + "42221802", + "42221803", + "42221900", + "42221901", + "42221902", + "42221903", + "42221904", + "42221905", + "42221906", + "42221907", + "42222000", + "42222001", + "42222002", + "42222003", + "42222004", + "42222005", + "42222006", + "42222007", + "42222008", + "42222009", + "42222011", + "42222100", + "42222101", + "42222102", + "42222103", + "42222104", + "42222200", + "42222201", + "42222202", + "42222300", + "42222301", + "42222302", + "42222303", + "42222304", + "42222305", + "42222307", + "42230000", + "42231500", + "42231501", + "42231504", + "42231505", + "42231510", + "42231600", + "42231601", + "42231613", + "42231700", + "42231703", + "42231800", + "42231801", + "42231802", + "42231806", + "42231810", + "42231812", + "42231813", + "42231814", + "42231815", + "42231816", + "42231817", + "42231818", + "42231900", + "42231901", + "42231902", + "42231903", + "42231904", + "42232000", + "42240000", + "42241500", + "42241502", + "42241503", + "42241504", + "42241505", + "42241506", + "42241507", + "42241509", + "42241510", + "42241511", + "42241512", + "42241513", + "42241514", + "42241516", + "42241517", + "42241600", + "42241602", + "42241603", + "42241604", + "42241606", + "42241700", + "42241701", + "42241702", + "42241703", + "42241705", + "42241706", + "42241707", + "42241708", + "42241709", + "42241800", + "42241801", + "42241802", + "42241803", + "42241804", + "42241805", + "42241806", + "42241807", + "42241808", + "42241809", + "42241811", + "42241900", + "42242000", + "42242100", + "42250000", + "42251500", + "42251501", + "42251502", + "42251503", + "42251504", + "42251505", + "42251506", + "42251600", + "42251608", + "42251613", + "42251623", + "42251624", + "42251700", + "42251701", + "42251702", + "42251703", + "42251704", + "42251705", + "42251706", + "42251800", + "42251805", + "42260000", + "42261500", + "42261501", + "42261502", + "42261503", + "42261504", + "42261505", + "42261506", + "42261507", + "42261508", + "42261509", + "42261510", + "42261511", + "42261512", + "42261513", + "42261514", + "42261516", + "42261600", + "42261601", + "42261602", + "42261604", + "42261605", + "42261606", + "42261607", + "42261608", + "42261609", + "42261610", + "42261611", + "42261612", + "42261613", + "42261700", + "42261703", + "42261800", + "42261801", + "42261802", + "42261803", + "42261804", + "42261805", + "42261806", + "42261807", + "42261808", + "42261809", + "42261810", + "42261900", + "42262000", + "42262100", + "42270000", + "42271500", + "42271502", + "42271503", + "42271504", + "42271505", + "42271517", + "42271600", + "42271602", + "42271604", + "42271609", + "42271610", + "42271651", + "42271700", + "42271701", + "42271702", + "42271703", + "42271704", + "42271705", + "42271706", + "42271707", + "42271708", + "42271709", + "42271710", + "42271711", + "42271712", + "42271713", + "42271714", + "42271715", + "42271716", + "42271717", + "42271718", + "42271719", + "42271720", + "42271721", + "42271722", + "42271728", + "42271729", + "42271730", + "42271800", + "42271801", + "42271802", + "42271803", + "42271807", + "42271900", + "42271902", + "42271903", + "42271904", + "42271905", + "42271910", + "42271919", + "42271931", + "42272000", + "42272001", + "42272003", + "42272004", + "42272005", + "42272006", + "42272007", + "42272008", + "42272009", + "42272017", + "42272020", + "42272100", + "42272200", + "42272202", + "42272203", + "42272204", + "42272205", + "42272207", + "42272215", + "42272216", + "42272217", + "42272218", + "42272219", + "42272220", + "42272222", + "42272223", + "42272224", + "42272225", + "42272230", + "42272300", + "42272301", + "42272306", + "42272500", + "42272501", + "42272502", + "42272503", + "42272505", + "42272506", + "42272507", + "42272509", + "42272510", + "42280000", + "42281500", + "42281501", + "42281502", + "42281508", + "42281509", + "42281519", + "42281521", + "42281530", + "42281531", + "42281532", + "42281600", + "42281604", + "42281700", + "42281701", + "42281703", + "42281704", + "42281714", + "42281800", + "42281801", + "42281802", + "42281803", + "42281804", + "42281805", + "42281806", + "42281807", + "42281808", + "42281809", + "42281810", + "42281811", + "42281900", + "42281901", + "42281902", + "42281903", + "42281904", + "42281905", + "42281906", + "42281907", + "42281908", + "42281909", + "42281912", + "42281913", + "42281914", + "42281915", + "42281916", + "42282000", + "42282001", + "42282010", + "42282017", + "42290000", + "42291500", + "42291600", + "42291614", + "42291632", + "42291700", + "42291701", + "42291800", + "42291801", + "42291900", + "42292000", + "42292001", + "42292100", + "42292300", + "42292400", + "42292403", + "42292500", + "42292600", + "42292700", + "42292800", + "42292801", + "42292802", + "42292803", + "42292900", + "42292901", + "42292903", + "42292904", + "42292907", + "42292908", + "42293000", + "42293001", + "42293002", + "42293003", + "42293004", + "42293005", + "42293006", + "42293100", + "42293106", + "42293300", + "42293400", + "42293500", + "42293511", + "42293514", + "42293515", + "42293518", + "42293519", + "42293521", + "42293522", + "42293523", + "42293524", + "42293525", + "42293528", + "42293529", + "42293600", + "42293605", + "42293700", + "42293800", + "42293900", + "42293901", + "42293902", + "42294000", + "42294100", + "42294200", + "42294201", + "42294202", + "42294203", + "42294204", + "42294205", + "42294206", + "42294207", + "42294212", + "42294214", + "42294218", + "42294219", + "42294222", + "42294300", + "42294400", + "42294401", + "42294402", + "42294500", + "42294600", + "42294601", + "42294602", + "42294603", + "42294604", + "42294605", + "42294606", + "42294607", + "42294611", + "42294700", + "42294701", + "42294702", + "42294713", + "42294900", + "42294902", + "42294903", + "42294904", + "42294905", + "42294906", + "42294907", + "42294908", + "42294909", + "42294910", + "42294913", + "42294914", + "42294915", + "42294917", + "42294919", + "42294920", + "42294921", + "42294922", + "42294923", + "42294924", + "42294925", + "42294926", + "42294927", + "42294928", + "42294929", + "42294930", + "42294931", + "42294933", + "42294934", + "42294936", + "42294937", + "42294938", + "42294939", + "42294941", + "42294942", + "42294943", + "42294944", + "42294946", + "42294948", + "42294949", + "42294950", + "42294951", + "42294952", + "42294953", + "42294954", + "42294955", + "42294956", + "42294957", + "42294958", + "42294959", + "42294972", + "42294978", + "42295000", + "42295001", + "42295002", + "42295003", + "42295004", + "42295005", + "42295006", + "42295013", + "42295014", + "42295015", + "42295016", + "42295100", + "42295101", + "42295104", + "42295106", + "42295108", + "42295112", + "42295114", + "42295119", + "42295120", + "42295121", + "42295122", + "42295123", + "42295124", + "42295137", + "42295148", + "42295150", + "42295157", + "42295159", + "42295167", + "42295200", + "42295201", + "42295202", + "42295203", + "42295204", + "42295300", + "42295313", + "42295400", + "42295401", + "42295402", + "42295406", + "42295408", + "42295409", + "42295410", + "42295411", + "42295413", + "42295414", + "42295415", + "42295417", + "42295418", + "42295419", + "42295421", + "42295422", + "42295423", + "42295424", + "42295426", + "42295427", + "42295435", + "42295440", + "42295446", + "42295448", + "42295451", + "42295452", + "42295453", + "42295454", + "42295456", + "42295458", + "42295459", + "42295460", + "42295461", + "42295462", + "42295464", + "42295465", + "42295470", + "42295471", + "42295472", + "42295480", + "42295484", + "42295500", + "42295502", + "42295513", + "42295600", + "42295800", + "42295900", + "42295910", + "42295911", + "42295912", + "42296000", + "42296100", + "42296200", + "42296201", + "42296202", + "42296203", + "42296204", + "42296205", + "42296206", + "42296207", + "42296208", + "42296209", + "42296210", + "42296211", + "42296212", + "42296300", + "42296304", + "42296305", + "42296308", + "42296311", + "42296313", + "42296314", + "42296317", + "42296318", + "42296323", + "42296324", + "42296326", + "42296334", + "42296335", + "42296400", + "42296401", + "42296402", + "42296404", + "42296406", + "42296407", + "42296408", + "42296409", + "42296411", + "42296412", + "42296413", + "42296414", + "42296500", + "42296502", + "42296507", + "42296600", + "42296700", + "42296701", + "42296702", + "42296703", + "42296704", + "42296705", + "42296800", + "42296812", + "42296818", + "42300000", + "42301500", + "42301501", + "42301502", + "42301503", + "42301504", + "42301505", + "42301506", + "42301507", + "42301508", + "42310000", + "42311500", + "42311501", + "42311502", + "42311503", + "42311506", + "42311510", + "42311512", + "42311513", + "42311515", + "42311517", + "42311518", + "42311519", + "42311520", + "42311523", + "42311524", + "42311527", + "42311528", + "42311531", + "42311537", + "42311539", + "42311540", + "42311541", + "42311543", + "42311546", + "42311548", + "42311551", + "42311552", + "42311555", + "42311600", + "42311606", + "42311607", + "42312000", + "42312010", + "42312014", + "42312100", + "42312101", + "42312102", + "42312103", + "42312104", + "42312105", + "42312106", + "42312107", + "42312108", + "42312109", + "42312110", + "42312111", + "42312112", + "42312113", + "42312115", + "42312200", + "42312201", + "42312202", + "42312203", + "42312204", + "42312206", + "42312207", + "42312208", + "42312209", + "42312300", + "42312301", + "42312302", + "42312303", + "42312304", + "42312305", + "42312306", + "42312307", + "42312309", + "42312310", + "42312311", + "42312312", + "42312313", + "42312400", + "42312401", + "42312402", + "42312403", + "42312500", + "42312501", + "42312502", + "42312503", + "42312504", + "42312600", + "42312603", + "42320000", + "43000000", + "43190000", + "43191500", + "43191501", + "43191502", + "43191503", + "43191504", + "43191505", + "43191507", + "43191508", + "43191509", + "43191510", + "43191511", + "43191512", + "43191513", + "43191514", + "43191515", + "43191516", + "43191517", + "43191518", + "43191519", + "43191520", + "43191521", + "43191600", + "43191601", + "43191602", + "43191603", + "43191604", + "43191605", + "43191606", + "43191607", + "43191608", + "43191609", + "43191610", + "43191611", + "43191612", + "43191614", + "43191615", + "43191616", + "43191618", + "43191619", + "43191621", + "43191622", + "43191623", + "43191624", + "43191625", + "43191626", + "43191627", + "43191628", + "43191629", + "43191630", + "43191631", + "43191632", + "43191633", + "43191634", + "43191635", + "43200000", + "43201400", + "43201401", + "43201402", + "43201403", + "43201404", + "43201405", + "43201406", + "43201407", + "43201409", + "43201410", + "43201411", + "43201412", + "43201413", + "43201414", + "43201415", + "43201416", + "43201417", + "43201500", + "43201501", + "43201502", + "43201503", + "43201507", + "43201508", + "43201509", + "43201513", + "43201522", + "43201531", + "43201533", + "43201534", + "43201535", + "43201537", + "43201538", + "43201539", + "43201540", + "43201541", + "43201542", + "43201543", + "43201544", + "43201545", + "43201546", + "43201547", + "43201549", + "43201550", + "43201552", + "43201553", + "43201554", + "43201555", + "43201556", + "43201557", + "43201558", + "43201559", + "43201560", + "43201600", + "43201601", + "43201602", + "43201603", + "43201604", + "43201605", + "43201608", + "43201609", + "43201610", + "43201611", + "43201612", + "43201614", + "43201615", + "43201616", + "43201617", + "43201618", + "43201619", + "43201800", + "43201801", + "43201802", + "43201803", + "43201806", + "43201807", + "43201808", + "43201809", + "43201810", + "43201811", + "43201812", + "43201813", + "43201814", + "43201815", + "43201816", + "43201817", + "43201818", + "43201819", + "43201820", + "43201821", + "43201822", + "43201823", + "43201825", + "43201826", + "43201827", + "43201828", + "43201829", + "43201830", + "43201831", + "43201832", + "43201833", + "43201834", + "43201835", + "43201900", + "43201902", + "43201903", + "43201904", + "43201905", + "43202000", + "43202001", + "43202002", + "43202003", + "43202004", + "43202005", + "43202006", + "43202007", + "43202008", + "43202009", + "43202010", + "43202100", + "43202101", + "43202102", + "43202103", + "43202104", + "43202105", + "43202106", + "43202107", + "43202108", + "43202200", + "43202201", + "43202202", + "43202204", + "43202205", + "43202206", + "43202207", + "43202208", + "43202209", + "43202210", + "43202211", + "43202212", + "43202213", + "43202214", + "43202215", + "43202216", + "43202217", + "43202218", + "43202219", + "43202220", + "43202221", + "43202222", + "43202223", + "43210000", + "43211500", + "43211501", + "43211502", + "43211503", + "43211504", + "43211505", + "43211506", + "43211507", + "43211508", + "43211509", + "43211510", + "43211511", + "43211512", + "43211513", + "43211514", + "43211515", + "43211516", + "43211517", + "43211518", + "43211519", + "43211520", + "43211521", + "43211522", + "43211600", + "43211601", + "43211602", + "43211603", + "43211604", + "43211605", + "43211606", + "43211607", + "43211608", + "43211609", + "43211610", + "43211611", + "43211612", + "43211613", + "43211614", + "43211615", + "43211616", + "43211617", + "43211618", + "43211619", + "43211700", + "43211701", + "43211702", + "43211704", + "43211705", + "43211706", + "43211707", + "43211708", + "43211709", + "43211710", + "43211711", + "43211712", + "43211713", + "43211714", + "43211715", + "43211717", + "43211718", + "43211719", + "43211720", + "43211721", + "43211722", + "43211723", + "43211724", + "43211725", + "43211726", + "43211727", + "43211728", + "43211729", + "43211730", + "43211731", + "43211732", + "43211733", + "43211734", + "43211800", + "43211801", + "43211802", + "43211803", + "43211804", + "43211805", + "43211806", + "43211807", + "43211900", + "43211901", + "43211902", + "43211903", + "43211904", + "43211905", + "43211906", + "43211907", + "43211908", + "43211909", + "43211910", + "43211911", + "43211912", + "43211913", + "43211914", + "43212000", + "43212001", + "43212002", + "43212003", + "43212100", + "43212101", + "43212102", + "43212103", + "43212104", + "43212105", + "43212106", + "43212107", + "43212108", + "43212109", + "43212110", + "43212111", + "43212112", + "43212113", + "43212114", + "43212115", + "43212116", + "43212117", + "43212118", + "43212200", + "43212201", + "43220000", + "43221500", + "43221501", + "43221502", + "43221503", + "43221504", + "43221505", + "43221506", + "43221507", + "43221508", + "43221509", + "43221510", + "43221513", + "43221514", + "43221515", + "43221516", + "43221517", + "43221518", + "43221519", + "43221520", + "43221521", + "43221522", + "43221523", + "43221524", + "43221525", + "43221526", + "43221527", + "43221528", + "43221529", + "43221530", + "43221531", + "43221532", + "43221533", + "43221534", + "43221537", + "43221600", + "43221601", + "43221602", + "43221603", + "43221604", + "43221700", + "43221701", + "43221702", + "43221703", + "43221704", + "43221705", + "43221706", + "43221707", + "43221708", + "43221709", + "43221710", + "43221711", + "43221712", + "43221713", + "43221714", + "43221715", + "43221716", + "43221717", + "43221718", + "43221719", + "43221720", + "43221721", + "43221722", + "43221723", + "43221724", + "43221725", + "43221726", + "43221727", + "43221728", + "43221729", + "43221730", + "43221731", + "43221732", + "43221733", + "43221734", + "43221735", + "43221736", + "43221737", + "43221738", + "43221739", + "43221740", + "43221741", + "43221742", + "43221743", + "43221744", + "43221745", + "43221746", + "43221747", + "43221748", + "43221749", + "43221750", + "43221800", + "43221801", + "43221802", + "43221803", + "43221804", + "43221805", + "43221806", + "43221807", + "43221808", + "43221809", + "43221810", + "43221811", + "43222500", + "43222501", + "43222502", + "43222503", + "43222504", + "43222600", + "43222602", + "43222604", + "43222605", + "43222606", + "43222607", + "43222608", + "43222609", + "43222610", + "43222611", + "43222612", + "43222615", + "43222619", + "43222620", + "43222621", + "43222622", + "43222623", + "43222624", + "43222625", + "43222626", + "43222627", + "43222628", + "43222629", + "43222630", + "43222631", + "43222632", + "43222633", + "43222634", + "43222635", + "43222636", + "43222637", + "43222638", + "43222639", + "43222640", + "43222641", + "43222642", + "43222643", + "43222644", + "43222700", + "43222701", + "43222702", + "43222703", + "43222704", + "43222800", + "43222801", + "43222802", + "43222803", + "43222805", + "43222806", + "43222811", + "43222813", + "43222814", + "43222815", + "43222816", + "43222817", + "43222818", + "43222819", + "43222820", + "43222822", + "43222823", + "43222824", + "43222825", + "43222826", + "43222827", + "43222900", + "43222901", + "43222902", + "43222903", + "43223000", + "43223001", + "43223100", + "43223101", + "43223102", + "43223103", + "43223104", + "43223105", + "43223106", + "43223107", + "43223108", + "43223109", + "43223110", + "43223111", + "43223112", + "43223113", + "43223200", + "43223201", + "43223202", + "43223203", + "43223204", + "43223205", + "43223206", + "43223207", + "43223208", + "43223209", + "43223210", + "43223211", + "43223212", + "43223300", + "43223301", + "43223302", + "43223303", + "43223305", + "43223306", + "43223307", + "43223308", + "43223309", + "43223310", + "43223311", + "43223312", + "43223313", + "43223314", + "43223315", + "43223316", + "43223317", + "43223318", + "43223319", + "43223320", + "43223321", + "43223322", + "43223323", + "43223324", + "43223325", + "43223326", + "43223327", + "43223328", + "43223329", + "43223330", + "43223331", + "43223332", + "43223333", + "43223334", + "43223335", + "43223336", + "43223337", + "43223338", + "43223339", + "43223340", + "43223341", + "43223342", + "43223343", + "43230000", + "43231500", + "43231501", + "43231503", + "43231505", + "43231506", + "43231507", + "43231508", + "43231509", + "43231510", + "43231511", + "43231512", + "43231513", + "43231514", + "43231515", + "43231516", + "43231517", + "43231600", + "43231601", + "43231602", + "43231603", + "43231604", + "43231605", + "43231606", + "43232000", + "43232001", + "43232002", + "43232003", + "43232004", + "43232005", + "43232100", + "43232101", + "43232102", + "43232103", + "43232104", + "43232105", + "43232106", + "43232107", + "43232108", + "43232110", + "43232111", + "43232112", + "43232200", + "43232201", + "43232202", + "43232203", + "43232204", + "43232205", + "43232300", + "43232301", + "43232302", + "43232303", + "43232304", + "43232305", + "43232306", + "43232307", + "43232309", + "43232310", + "43232311", + "43232312", + "43232313", + "43232314", + "43232400", + "43232401", + "43232402", + "43232403", + "43232404", + "43232405", + "43232406", + "43232407", + "43232408", + "43232409", + "43232500", + "43232501", + "43232502", + "43232503", + "43232504", + "43232505", + "43232506", + "43232507", + "43232508", + "43232509", + "43232510", + "43232600", + "43232601", + "43232602", + "43232603", + "43232604", + "43232605", + "43232606", + "43232607", + "43232608", + "43232609", + "43232610", + "43232611", + "43232612", + "43232613", + "43232614", + "43232615", + "43232616", + "43232617", + "43232618", + "43232619", + "43232620", + "43232700", + "43232701", + "43232702", + "43232703", + "43232704", + "43232705", + "43232800", + "43232801", + "43232802", + "43232803", + "43232804", + "43232805", + "43232900", + "43232901", + "43232902", + "43232903", + "43232904", + "43232905", + "43232906", + "43232907", + "43232908", + "43232909", + "43232910", + "43232911", + "43232912", + "43232913", + "43232914", + "43232915", + "43232916", + "43233000", + "43233001", + "43233002", + "43233004", + "43233005", + "43233006", + "43233200", + "43233201", + "43233203", + "43233204", + "43233205", + "43233400", + "43233401", + "43233402", + "43233403", + "43233404", + "43233405", + "43233406", + "43233407", + "43233410", + "43233411", + "43233413", + "43233414", + "43233415", + "43233416", + "43233417", + "43233418", + "43233419", + "43233420", + "43233421", + "43233500", + "43233501", + "43233502", + "43233503", + "43233504", + "43233505", + "43233506", + "43233507", + "43233508", + "43233509", + "43233510", + "43233511", + "43233512", + "43233513", + "43233600", + "43233601", + "43233602", + "43233603", + "43233700", + "43233701", + "44000000", + "44100000", + "44101500", + "44101501", + "44101503", + "44101504", + "44101505", + "44101506", + "44101507", + "44101508", + "44101509", + "44101510", + "44101511", + "44101600", + "44101601", + "44101602", + "44101603", + "44101604", + "44101605", + "44101606", + "44101607", + "44101608", + "44101700", + "44101701", + "44101702", + "44101703", + "44101704", + "44101705", + "44101706", + "44101707", + "44101708", + "44101709", + "44101710", + "44101711", + "44101712", + "44101713", + "44101714", + "44101715", + "44101716", + "44101718", + "44101719", + "44101720", + "44101721", + "44101722", + "44101723", + "44101724", + "44101725", + "44101726", + "44101727", + "44101728", + "44101729", + "44101730", + "44101800", + "44101802", + "44101803", + "44101804", + "44101805", + "44101806", + "44101807", + "44101808", + "44101809", + "44101810", + "44101900", + "44101901", + "44101902", + "44101903", + "44101904", + "44102000", + "44102001", + "44102002", + "44102003", + "44102004", + "44102100", + "44102101", + "44102102", + "44102103", + "44102104", + "44102105", + "44102106", + "44102107", + "44102108", + "44102109", + "44102200", + "44102201", + "44102202", + "44102203", + "44102300", + "44102301", + "44102302", + "44102303", + "44102304", + "44102305", + "44102306", + "44102307", + "44102400", + "44102402", + "44102403", + "44102404", + "44102405", + "44102406", + "44102407", + "44102408", + "44102409", + "44102411", + "44102412", + "44102413", + "44102414", + "44102500", + "44102501", + "44102502", + "44102503", + "44102504", + "44102600", + "44102602", + "44102603", + "44102604", + "44102605", + "44102606", + "44102607", + "44102608", + "44102609", + "44102610", + "44102800", + "44102801", + "44102802", + "44102803", + "44102804", + "44102805", + "44102806", + "44102900", + "44102901", + "44102902", + "44102903", + "44102904", + "44102905", + "44102906", + "44102907", + "44102908", + "44102909", + "44102910", + "44102911", + "44102912", + "44102913", + "44103000", + "44103001", + "44103002", + "44103003", + "44103004", + "44103005", + "44103100", + "44103101", + "44103103", + "44103104", + "44103105", + "44103106", + "44103107", + "44103108", + "44103109", + "44103110", + "44103111", + "44103112", + "44103113", + "44103114", + "44103116", + "44103117", + "44103118", + "44103119", + "44103120", + "44103121", + "44103122", + "44103123", + "44103124", + "44103125", + "44103126", + "44103127", + "44103200", + "44103201", + "44103202", + "44103203", + "44103204", + "44103205", + "44103206", + "44103207", + "44103500", + "44103502", + "44103503", + "44103504", + "44103505", + "44103506", + "44103507", + "44103508", + "44103600", + "44103601", + "44110000", + "44111500", + "44111501", + "44111502", + "44111503", + "44111506", + "44111507", + "44111509", + "44111510", + "44111511", + "44111512", + "44111513", + "44111514", + "44111515", + "44111516", + "44111517", + "44111518", + "44111519", + "44111520", + "44111521", + "44111522", + "44111523", + "44111600", + "44111601", + "44111603", + "44111604", + "44111605", + "44111607", + "44111608", + "44111609", + "44111610", + "44111611", + "44111612", + "44111613", + "44111614", + "44111615", + "44111616", + "44111617", + "44111618", + "44111800", + "44111801", + "44111802", + "44111803", + "44111804", + "44111805", + "44111806", + "44111807", + "44111808", + "44111809", + "44111810", + "44111812", + "44111813", + "44111814", + "44111815", + "44111816", + "44111817", + "44111818", + "44111900", + "44111901", + "44111902", + "44111903", + "44111904", + "44111905", + "44111906", + "44111907", + "44111908", + "44111909", + "44111910", + "44111911", + "44111912", + "44111913", + "44111914", + "44112000", + "44112001", + "44112002", + "44112004", + "44112005", + "44112006", + "44112007", + "44112008", + "44120000", + "44121500", + "44121501", + "44121503", + "44121504", + "44121505", + "44121506", + "44121507", + "44121508", + "44121509", + "44121510", + "44121511", + "44121512", + "44121513", + "44121600", + "44121604", + "44121605", + "44121611", + "44121612", + "44121613", + "44121614", + "44121615", + "44121617", + "44121618", + "44121619", + "44121620", + "44121621", + "44121622", + "44121623", + "44121624", + "44121625", + "44121626", + "44121627", + "44121628", + "44121630", + "44121631", + "44121632", + "44121633", + "44121634", + "44121635", + "44121636", + "44121700", + "44121701", + "44121702", + "44121703", + "44121704", + "44121705", + "44121706", + "44121707", + "44121708", + "44121709", + "44121710", + "44121711", + "44121712", + "44121713", + "44121714", + "44121715", + "44121716", + "44121717", + "44121718", + "44121719", + "44121720", + "44121721", + "44121800", + "44121801", + "44121802", + "44121804", + "44121805", + "44121806", + "44121807", + "44121808", + "44121809", + "44121900", + "44121902", + "44121904", + "44121905", + "44121906", + "44121907", + "44121908", + "44122000", + "44122001", + "44122002", + "44122003", + "44122005", + "44122008", + "44122009", + "44122010", + "44122011", + "44122012", + "44122013", + "44122014", + "44122015", + "44122016", + "44122017", + "44122018", + "44122019", + "44122020", + "44122021", + "44122022", + "44122023", + "44122024", + "44122025", + "44122026", + "44122027", + "44122028", + "44122029", + "44122030", + "44122031", + "44122032", + "44122033", + "44122034", + "44122035", + "44122036", + "44122037", + "44122100", + "44122101", + "44122103", + "44122104", + "44122105", + "44122106", + "44122107", + "44122109", + "44122110", + "44122111", + "44122112", + "44122113", + "44122114", + "44122115", + "44122116", + "44122117", + "44122118", + "44122119", + "44122120", + "44122121", + "44122122", + "45000000", + "45100000", + "45101500", + "45101501", + "45101502", + "45101503", + "45101504", + "45101505", + "45101506", + "45101507", + "45101508", + "45101509", + "45101510", + "45101511", + "45101512", + "45101513", + "45101514", + "45101515", + "45101516", + "45101517", + "45101518", + "45101520", + "45101600", + "45101602", + "45101603", + "45101604", + "45101606", + "45101607", + "45101608", + "45101609", + "45101610", + "45101611", + "45101612", + "45101613", + "45101614", + "45101615", + "45101616", + "45101700", + "45101701", + "45101702", + "45101703", + "45101704", + "45101705", + "45101706", + "45101707", + "45101708", + "45101709", + "45101710", + "45101711", + "45101800", + "45101801", + "45101802", + "45101803", + "45101804", + "45101805", + "45101806", + "45101807", + "45101808", + "45101900", + "45101901", + "45101902", + "45101903", + "45101904", + "45101905", + "45102000", + "45102001", + "45102002", + "45102003", + "45102004", + "45102005", + "45110000", + "45111400", + "45111401", + "45111402", + "45111500", + "45111501", + "45111502", + "45111503", + "45111504", + "45111600", + "45111601", + "45111602", + "45111603", + "45111604", + "45111605", + "45111606", + "45111607", + "45111608", + "45111609", + "45111610", + "45111612", + "45111613", + "45111614", + "45111615", + "45111616", + "45111617", + "45111618", + "45111619", + "45111620", + "45111700", + "45111701", + "45111702", + "45111703", + "45111704", + "45111705", + "45111706", + "45111707", + "45111708", + "45111709", + "45111710", + "45111711", + "45111712", + "45111713", + "45111714", + "45111715", + "45111716", + "45111717", + "45111718", + "45111719", + "45111720", + "45111721", + "45111722", + "45111723", + "45111724", + "45111725", + "45111800", + "45111801", + "45111802", + "45111803", + "45111804", + "45111805", + "45111806", + "45111807", + "45111808", + "45111809", + "45111810", + "45111811", + "45111812", + "45111813", + "45111814", + "45111815", + "45111816", + "45111817", + "45111818", + "45111819", + "45111820", + "45111821", + "45111822", + "45111823", + "45111824", + "45111825", + "45111826", + "45111827", + "45111828", + "45111829", + "45111900", + "45111901", + "45111902", + "45112000", + "45112001", + "45112002", + "45112003", + "45112004", + "45120000", + "45121500", + "45121501", + "45121502", + "45121503", + "45121504", + "45121505", + "45121506", + "45121510", + "45121511", + "45121512", + "45121513", + "45121514", + "45121515", + "45121516", + "45121517", + "45121518", + "45121519", + "45121520", + "45121521", + "45121522", + "45121523", + "45121600", + "45121601", + "45121602", + "45121603", + "45121604", + "45121605", + "45121606", + "45121607", + "45121608", + "45121609", + "45121610", + "45121611", + "45121612", + "45121613", + "45121614", + "45121615", + "45121616", + "45121617", + "45121618", + "45121619", + "45121620", + "45121621", + "45121622", + "45121623", + "45121624", + "45121625", + "45121626", + "45121627", + "45121628", + "45121629", + "45121630", + "45121631", + "45121632", + "45121700", + "45121701", + "45121702", + "45121703", + "45121704", + "45121705", + "45121706", + "45121707", + "45121708", + "45121709", + "45121710", + "45121711", + "45121712", + "45121713", + "45121714", + "45121715", + "45121716", + "45121717", + "45121718", + "45121719", + "45121720", + "45121721", + "45121800", + "45121801", + "45121802", + "45121803", + "45121804", + "45121805", + "45121806", + "45121807", + "45121808", + "45121809", + "45121810", + "45130000", + "45131500", + "45131501", + "45131502", + "45131503", + "45131505", + "45131506", + "45131507", + "45131508", + "45131509", + "45131510", + "45131600", + "45131601", + "45131604", + "45131700", + "45131701", + "45140000", + "45141500", + "45141501", + "45141502", + "45141503", + "45141504", + "45141600", + "45141601", + "45141602", + "45141603", + "45141604", + "45141605", + "45141606", + "45141607", + "45141608", + "45141609", + "45141610", + "45141611", + "45141612", + "46000000", + "46100000", + "46101500", + "46101504", + "46101505", + "46101600", + "46101700", + "46101800", + "46101802", + "46110000", + "46111500", + "46111504", + "46111505", + "46111506", + "46120000", + "46130000", + "46140000", + "46150000", + "46151500", + "46151501", + "46151502", + "46151503", + "46151504", + "46151505", + "46151506", + "46151507", + "46151508", + "46151509", + "46151600", + "46151601", + "46151602", + "46151604", + "46151605", + "46151606", + "46151607", + "46151608", + "46151609", + "46151610", + "46151700", + "46151702", + "46151703", + "46151704", + "46151705", + "46151706", + "46151707", + "46151708", + "46151709", + "46151710", + "46151711", + "46151712", + "46151713", + "46151714", + "46151715", + "46151716", + "46151717", + "46151800", + "46151801", + "46151802", + "46151900", + "46151901", + "46160000", + "46161500", + "46161501", + "46161502", + "46161503", + "46161504", + "46161506", + "46161516", + "46161528", + "46161534", + "46161535", + "46161536", + "46161537", + "46161538", + "46161600", + "46161601", + "46161602", + "46161603", + "46161604", + "46161605", + "46161700", + "46161701", + "46161702", + "46161703", + "46161704", + "46161705", + "46161706", + "46161707", + "46161708", + "46161710", + "46161711", + "46161712", + "46161713", + "46161714", + "46161715", + "46170000", + "46171500", + "46171525", + "46171600", + "46171602", + "46171603", + "46171604", + "46171605", + "46171606", + "46171607", + "46171608", + "46171609", + "46171610", + "46171611", + "46171612", + "46171613", + "46171615", + "46171616", + "46171617", + "46171618", + "46171619", + "46171620", + "46171621", + "46171622", + "46171623", + "46171624", + "46171625", + "46171626", + "46171627", + "46171628", + "46171629", + "46171630", + "46171631", + "46171632", + "46171633", + "46171634", + "46171635", + "46171636", + "46171637", + "46171638", + "46171639", + "46171640", + "46171641", + "46171642", + "46171643", + "46171644", + "46171645", + "46171646", + "46171648", + "46171649", + "46171650", + "46171700", + "46171701", + "46180000", + "46181500", + "46181501", + "46181502", + "46181503", + "46181504", + "46181506", + "46181507", + "46181508", + "46181509", + "46181512", + "46181532", + "46181540", + "46181541", + "46181543", + "46181552", + "46181555", + "46181566", + "46181600", + "46181601", + "46181602", + "46181603", + "46181604", + "46181605", + "46181606", + "46181612", + "46181700", + "46181701", + "46181702", + "46181704", + "46181705", + "46181800", + "46181801", + "46181802", + "46181804", + "46181810", + "46181812", + "46181900", + "46181902", + "46182000", + "46182001", + "46182002", + "46182003", + "46182004", + "46182005", + "46182006", + "46182007", + "46182008", + "46182010", + "46182100", + "46182101", + "46182103", + "46182104", + "46182105", + "46182107", + "46182200", + "46182300", + "46182301", + "46182302", + "46182306", + "46182307", + "46182309", + "46182314", + "46182400", + "46182401", + "46182402", + "46182407", + "46182500", + "46182504", + "46182505", + "46190000", + "46191500", + "46191501", + "46191502", + "46191503", + "46191504", + "46191505", + "46191506", + "46191507", + "46191508", + "46191509", + "46191510", + "46191511", + "46191600", + "46191601", + "46191602", + "46191603", + "46191604", + "46191605", + "46191606", + "46191607", + "46191608", + "46191609", + "46191610", + "46191611", + "46191612", + "46191613", + "46191614", + "46191615", + "46191616", + "46191617", + "46191618", + "46191619", + "46191620", + "46191621", + "46191623", + "46191624", + "46191625", + "46200000", + "46201000", + "46201001", + "46201002", + "46201100", + "46201101", + "46201102", + "46210000", + "46211500", + "46211501", + "46211502", + "46211503", + "46211504", + "46211600", + "46211601", + "46211602", + "46211603", + "46211604", + "46220000", + "46221500", + "46221501", + "46221502", + "46221503", + "46221504", + "46221505", + "46221506", + "46221507", + "46221508", + "46221509", + "46221510", + "46221511", + "46221512", + "46221513", + "47000000", + "47100000", + "47101500", + "47101501", + "47101502", + "47101503", + "47101504", + "47101506", + "47101507", + "47101508", + "47101510", + "47101512", + "47101513", + "47101514", + "47101517", + "47101521", + "47101522", + "47101523", + "47101524", + "47101525", + "47101528", + "47101529", + "47101530", + "47101531", + "47101532", + "47101534", + "47101535", + "47101536", + "47101537", + "47101538", + "47101576", + "47101600", + "47101601", + "47101605", + "47101606", + "47101609", + "47101611", + "47101614", + "47110000", + "47111500", + "47111501", + "47111502", + "47111503", + "47111507", + "47111509", + "47111510", + "47111600", + "47111700", + "47120000", + "47121500", + "47121501", + "47121502", + "47121600", + "47121602", + "47121605", + "47121606", + "47121608", + "47121700", + "47121701", + "47121702", + "47121703", + "47121704", + "47121705", + "47121706", + "47121707", + "47121708", + "47121709", + "47121710", + "47121800", + "47121801", + "47121802", + "47121803", + "47121804", + "47121805", + "47121806", + "47121807", + "47121808", + "47121809", + "47121810", + "47121811", + "47121812", + "47121813", + "47121814", + "47121815", + "47121816", + "47121900", + "47121901", + "47121902", + "47121903", + "47130000", + "47131500", + "47131501", + "47131502", + "47131600", + "47131601", + "47131602", + "47131603", + "47131604", + "47131605", + "47131608", + "47131611", + "47131617", + "47131618", + "47131700", + "47131701", + "47131702", + "47131703", + "47131704", + "47131800", + "47131801", + "47131803", + "47131804", + "47131805", + "47131807", + "47131808", + "47131810", + "47131811", + "47131824", + "47131829", + "47131900", + "47131901", + "47131902", + "47131903", + "47132100", + "47132101", + "47132102", + "48000000", + "48100000", + "48101500", + "48101501", + "48101502", + "48101503", + "48101504", + "48101505", + "48101506", + "48101507", + "48101508", + "48101509", + "48101510", + "48101511", + "48101512", + "48101513", + "48101514", + "48101515", + "48101516", + "48101517", + "48101518", + "48101519", + "48101520", + "48101521", + "48101522", + "48101523", + "48101524", + "48101525", + "48101526", + "48101527", + "48101528", + "48101529", + "48101530", + "48101531", + "48101532", + "48101533", + "48101534", + "48101535", + "48101536", + "48101537", + "48101538", + "48101539", + "48101540", + "48101541", + "48101542", + "48101543", + "48101544", + "48101545", + "48101546", + "48101600", + "48101601", + "48101602", + "48101603", + "48101604", + "48101605", + "48101606", + "48101607", + "48101608", + "48101609", + "48101610", + "48101611", + "48101612", + "48101613", + "48101614", + "48101615", + "48101616", + "48101617", + "48101618", + "48101619", + "48101700", + "48101701", + "48101702", + "48101703", + "48101704", + "48101705", + "48101706", + "48101707", + "48101708", + "48101709", + "48101710", + "48101711", + "48101712", + "48101713", + "48101714", + "48101715", + "48101716", + "48101800", + "48101801", + "48101802", + "48101803", + "48101804", + "48101805", + "48101806", + "48101807", + "48101808", + "48101809", + "48101810", + "48101811", + "48101812", + "48101813", + "48101814", + "48101815", + "48101816", + "48101817", + "48101818", + "48101819", + "48101820", + "48101821", + "48101900", + "48101901", + "48101902", + "48101903", + "48101904", + "48101905", + "48101906", + "48101907", + "48101908", + "48101909", + "48101910", + "48101911", + "48101912", + "48101913", + "48101914", + "48101915", + "48101916", + "48101917", + "48101918", + "48101919", + "48101920", + "48101921", + "48101926", + "48102000", + "48102001", + "48102002", + "48102003", + "48102004", + "48102005", + "48102006", + "48102007", + "48102008", + "48102009", + "48102010", + "48102100", + "48102101", + "48102102", + "48102103", + "48102104", + "48102105", + "48102106", + "48102107", + "48102108", + "48110000", + "48120000", + "48130000", + "48131500", + "48131502", + "49000000", + "49100000", + "49101600", + "49101602", + "49101700", + "49101701", + "49101702", + "49120000", + "49121500", + "49121502", + "49121503", + "49121504", + "49121505", + "49121506", + "49121507", + "49121508", + "49121509", + "49121510", + "49121600", + "49121601", + "49121602", + "49121603", + "49130000", + "49131500", + "49131501", + "49140000", + "49141500", + "49141501", + "49141502", + "49141503", + "49141504", + "49141505", + "49141506", + "49141507", + "49141508", + "49141509", + "49150000", + "49151500", + "49151501", + "49151502", + "49160000", + "49161500", + "49161501", + "49161503", + "49161504", + "49161505", + "49161506", + "49161509", + "49161600", + "49161601", + "49161602", + "49161603", + "49161604", + "49161607", + "49161608", + "49161700", + "49161702", + "49170000", + "49171500", + "49171501", + "49171503", + "49171600", + "49171601", + "49180000", + "49181500", + "49181501", + "49181507", + "49200000", + "49201500", + "49201501", + "49201503", + "49201504", + "49201512", + "49201518", + "49201600", + "49201601", + "49201603", + "49201612", + "49210000", + "49211600", + "49211800", + "49211802", + "49211803", + "49211804", + "49211805", + "49211806", + "49211807", + "49211808", + "49211809", + "49211811", + "49220000", + "49221500", + "49221501", + "49221502", + "49221505", + "49221506", + "49221511", + "49240000", + "49241500", + "49241501", + "49241503", + "49241700", + "49241701", + "49241704", + "50000000", + "50100000", + "50101700", + "50110000", + "50111500", + "50111513", + "50120000", + "50121500", + "50121537", + "50121538", + "50121539", + "50121541", + "50121542", + "50130000", + "50131600", + "50131700", + "50131701", + "50131704", + "50131800", + "50131801", + "50131802", + "50131803", + "50150000", + "50151500", + "50151513", + "50151514", + "50151517", + "50151518", + "50151519", + "50151520", + "50151521", + "50151600", + "50151604", + "50160000", + "50161500", + "50161509", + "50161800", + "50161816", + "50170000", + "50171500", + "50171548", + "50171550", + "50171551", + "50171552", + "50180000", + "50181700", + "50181708", + "50181709", + "50181710", + "50181900", + "50181901", + "50190000", + "50191500", + "50191505", + "50191506", + "50191507", + "50192100", + "50192300", + "50192400", + "50192500", + "50192600", + "50192700", + "50192800", + "50192900", + "50193000", + "50193100", + "50193200", + "50200000", + "50201700", + "50201706", + "50201709", + "50201710", + "50201711", + "50201713", + "50201714", + "50201715", + "50201717", + "50202200", + "50202300", + "50202301", + "50202306", + "50202312", + "50210000", + "50220000", + "50221000", + "50221002", + "50221100", + "50221102", + "50221108", + "50221111", + "50221112", + "50221113", + "50221114", + "50221115", + "50221300", + "50221301", + "50221303", + "50221304", + "50221305", + "50221306", + "50221307", + "50300000", + "50301500", + "50301501", + "50301502", + "50301503", + "50301504", + "50301505", + "50301506", + "50301507", + "50301508", + "50301509", + "50301510", + "50301511", + "50301512", + "50301513", + "50301514", + "50301515", + "50301516", + "50301517", + "50310000", + "50311500", + "50311501", + "50311502", + "50311503", + "50311504", + "50311505", + "50311506", + "50311507", + "50311508", + "50311509", + "50311510", + "50311511", + "50311512", + "50311513", + "50311514", + "50311515", + "50311516", + "50311517", + "50320000", + "50321500", + "50321501", + "50330000", + "50331500", + "50331501", + "50331502", + "50340000", + "50341500", + "50341501", + "50360000", + "50361500", + "50361501", + "50370000", + "50371500", + "50371501", + "50380000", + "50400000", + "50401500", + "50401501", + "50403400", + "50404500", + "50404509", + "50407000", + "50408000", + "50410000", + "50411500", + "50411501", + "50420000", + "50421500", + "50421501", + "50421800", + "50421834", + "50421853", + "50421854", + "50421855", + "50421856", + "50421857", + "50424000", + "50424006", + "50424007", + "50425400", + "50425407", + "50425408", + "50425409", + "50425410", + "50425600", + "50425610", + "50430000", + "50431500", + "50431501", + "50440000", + "50441500", + "50441501", + "50450000", + "50451500", + "50451501", + "50460000", + "50461500", + "50461501", + "50465300", + "50465307", + "50466800", + "50466818", + "50470000", + "50471500", + "50471501", + "50500000", + "50501500", + "50501501", + "50501502", + "50501503", + "50501504", + "50501505", + "50501506", + "50501507", + "50501508", + "50501509", + "50501510", + "50501511", + "50501512", + "50501513", + "50501600", + "50501700", + "50501708", + "50501709", + "50501710", + "50501711", + "50501712", + "50501713", + "50501714", + "50501715", + "50501716", + "50501717", + "50501718", + "50501719", + "50501720", + "50501721", + "50501722", + "50501723", + "50501724", + "50501725", + "50501726", + "50501727", + "50501800", + "50501804", + "50501900", + "50501901", + "50501902", + "50501903", + "50501904", + "51000000", + "51100000", + "51101600", + "51101602", + "51101604", + "51101607", + "51101612", + "51101613", + "51101614", + "51101616", + "51101618", + "51101620", + "51101629", + "51101630", + "51101636", + "51101680", + "51101693", + "51101900", + "51101902", + "51101903", + "51101904", + "51101905", + "51101906", + "51101907", + "51101908", + "51101911", + "51101912", + "51101913", + "51101914", + "51101915", + "51101923", + "51101928", + "51101929", + "51102800", + "51102811", + "51102818", + "51102821", + "51102822", + "51102823", + "51102832", + "51102842", + "51102844", + "51102852", + "51102856", + "51102858", + "51102862", + "51102863", + "51102864", + "51102871", + "51102872", + "51102878", + "51102900", + "51102901", + "51102904", + "51102905", + "51102907", + "51102909", + "51102910", + "51110000", + "51111600", + "51111602", + "51111606", + "51111610", + "51111617", + "51111625", + "51111629", + "51111642", + "51111650", + "51111659", + "51111700", + "51111704", + "51111716", + "51111717", + "51111728", + "51111731", + "51111733", + "51111736", + "51111739", + "51111740", + "51111742", + "51111746", + "51111758", + "51111761", + "51111765", + "51111766", + "51111767", + "51111772", + "51111778", + "51111779", + "51111780", + "51111781", + "51111782", + "51111783", + "51111784", + "51111785", + "51111786", + "51111800", + "51111802", + "51111803", + "51111805", + "51111807", + "51111815", + "51111820", + "51111824", + "51111828", + "51111830", + "51111833", + "51111838", + "51111842", + "51111855", + "51111856", + "51111862", + "51111863", + "51111873", + "51111874", + "51111875", + "51111876", + "51111877", + "51111878", + "51111900", + "51111901", + "51111904", + "51111906", + "51112000", + "51112001", + "51112002", + "51112004", + "51112005", + "51112006", + "51112008", + "51112010", + "51112012", + "51112014", + "51112015", + "51112016", + "51112017", + "51112020", + "51112021", + "51112022", + "51112023", + "51112026", + "51112027", + "51112028", + "51112029", + "51112030", + "51112031", + "51112032", + "51112033", + "51112034", + "51112035", + "51112037", + "51112088", + "51112300", + "51112301", + "51112400", + "51112402", + "51112500", + "51112503", + "51112505", + "51112507", + "51112508", + "51112510", + "51112513", + "51112600", + "51112601", + "51112700", + "51112701", + "51112702", + "51112705", + "51112800", + "51112804", + "51112900", + "51112901", + "51112902", + "51113000", + "51113500", + "51113501", + "51113502", + "51113503", + "51120000", + "51121500", + "51121583", + "51122600", + "51122601", + "51122603", + "51122606", + "51123500", + "51123501", + "51123600", + "51123601", + "51123900", + "51123906", + "51124100", + "51124101", + "51124400", + "51124404", + "51124500", + "51124503", + "51130000", + "51131500", + "51131506", + "51131507", + "51131520", + "51131524", + "51131525", + "51131526", + "51131600", + "51131602", + "51131604", + "51131607", + "51131615", + "51131621", + "51131624", + "51131629", + "51131631", + "51131641", + "51131642", + "51131649", + "51131650", + "51131665", + "51131700", + "51131701", + "51131703", + "51131705", + "51131711", + "51131740", + "51131800", + "51131801", + "51131808", + "51131811", + "51131812", + "51131817", + "51131819", + "51131820", + "51131821", + "51131823", + "51131827", + "51131828", + "51131829", + "51131830", + "51131831", + "51131832", + "51131833", + "51131834", + "51131900", + "51131901", + "51131908", + "51131909", + "51131911", + "51132000", + "51132001", + "51132100", + "51132102", + "51132200", + "51132225", + "51132300", + "51132308", + "51140000", + "51141500", + "51141501", + "51141504", + "51141507", + "51141509", + "51141513", + "51141518", + "51141522", + "51141526", + "51141528", + "51141531", + "51141535", + "51141538", + "51141563", + "51141566", + "51141590", + "51141596", + "51142300", + "51142302", + "51142315", + "51142400", + "51142411", + "51142413", + "51142423", + "51142433", + "51142435", + "51142500", + "51142501", + "51142517", + "51142538", + "51142565", + "51142568", + "51143000", + "51143100", + "51143103", + "51143104", + "51143112", + "51143200", + "51143202", + "51143203", + "51143222", + "51143400", + "51143406", + "51143409", + "51143500", + "51143501", + "51143502", + "51143900", + "51143908", + "51144000", + "51144014", + "51144015", + "51144600", + "51144601", + "51150000", + "51151500", + "51151512", + "51151514", + "51151527", + "51151529", + "51151541", + "51151544", + "51151548", + "51151549", + "51151600", + "51151604", + "51151606", + "51151616", + "51151617", + "51151625", + "51151657", + "51151666", + "51151674", + "51151675", + "51151900", + "51151904", + "51152000", + "51152004", + "51152005", + "51152006", + "51152017", + "51152046", + "51152051", + "51152064", + "51152067", + "51152070", + "51152072", + "51152075", + "51160000", + "51161500", + "51161524", + "51161563", + "51161569", + "51161574", + "51161700", + "51161702", + "51161705", + "51161708", + "51161709", + "51161800", + "51162000", + "51162002", + "51162012", + "51162030", + "51162038", + "51162039", + "51162040", + "51162041", + "51162042", + "51162043", + "51162100", + "51162101", + "51162103", + "51162104", + "51162106", + "51162107", + "51162300", + "51162357", + "51162600", + "51162603", + "51162626", + "51162700", + "51162701", + "51162702", + "51162704", + "51162713", + "51162728", + "51162732", + "51162747", + "51170000", + "51171500", + "51171505", + "51171510", + "51171511", + "51171600", + "51171605", + "51171607", + "51171610", + "51171614", + "51171628", + "51171630", + "51171641", + "51171700", + "51171714", + "51171724", + "51171800", + "51171806", + "51171807", + "51171808", + "51171816", + "51171820", + "51171822", + "51171823", + "51171838", + "51171839", + "51171840", + "51171858", + "51171900", + "51171901", + "51171905", + "51171906", + "51171909", + "51171910", + "51171911", + "51171915", + "51171916", + "51171917", + "51171926", + "51171932", + "51171935", + "51171962", + "51171973", + "51171974", + "51171980", + "51171984", + "51172100", + "51172148", + "51172200", + "51172201", + "51172300", + "51172305", + "51172308", + "51172309", + "51172310", + "51172311", + "51172319", + "51172320", + "51172321", + "51172324", + "51172327", + "51172328", + "51172332", + "51172333", + "51172338", + "51172340", + "51172400", + "51172410", + "51172413", + "51172481", + "51172483", + "51172484", + "51172485", + "51172486", + "51172487", + "51172490", + "51172800", + "51172833", + "51180000", + "51181500", + "51181578", + "51181579", + "51181600", + "51181604", + "51181605", + "51181606", + "51181608", + "51181613", + "51181614", + "51181625", + "51181629", + "51181900", + "51181901", + "51181912", + "51181927", + "51181931", + "51181932", + "51182000", + "51182002", + "51182014", + "51182024", + "51182027", + "51182035", + "51182047", + "51182071", + "51182100", + "51182101", + "51182102", + "51182106", + "51182108", + "51182200", + "51182201", + "51182202", + "51182203", + "51182204", + "51182206", + "51182207", + "51182214", + "51182222", + "51182300", + "51182302", + "51182400", + "51182406", + "51182415", + "51182416", + "51182417", + "51182426", + "51182428", + "51182435", + "51182441", + "51182500", + "51182501", + "51182700", + "51182709", + "51182710", + "51182711", + "51183300", + "51183301", + "51183303", + "51183306", + "51183500", + "51183505", + "51183510", + "51183600", + "51183601", + "51183603", + "51183607", + "51183608", + "51183610", + "51183611", + "51183613", + "51183614", + "51183615", + "51183622", + "51183623", + "51183700", + "51183706", + "51183800", + "51183801", + "51184000", + "51184004", + "51184007", + "51190000", + "51191500", + "51191502", + "51191504", + "51191507", + "51191509", + "51191515", + "51191517", + "51191549", + "51191554", + "51191555", + "51191572", + "51191600", + "51191602", + "51191604", + "51191605", + "51191607", + "51191609", + "51191800", + "51191802", + "51191806", + "51191900", + "51191909", + "51191915", + "51191917", + "51191918", + "51191919", + "51191923", + "51191967", + "51191968", + "51191970", + "51192000", + "51192001", + "51192002", + "51192300", + "51192317", + "51192318", + "51192400", + "51192429", + "51192443", + "51192445", + "51192458", + "51192459", + "51200000", + "51201500", + "51201569", + "51201571", + "51201573", + "51201574", + "51201575", + "51201576", + "51201580", + "51201600", + "51201604", + "51201606", + "51201607", + "51201608", + "51201609", + "51201610", + "51201615", + "51201616", + "51201617", + "51201618", + "51201620", + "51201621", + "51201623", + "51201624", + "51201625", + "51201626", + "51201627", + "51201628", + "51201629", + "51201631", + "51201632", + "51201633", + "51201634", + "51201646", + "51201647", + "51201648", + "51201652", + "51201653", + "51201654", + "51201655", + "51201656", + "51201657", + "51201658", + "51201659", + "51201660", + "51201700", + "51201702", + "51201703", + "51201704", + "51201705", + "51201800", + "51201802", + "51201803", + "51201805", + "51201806", + "51201810", + "51201811", + "51201812", + "51201831", + "51201900", + "51201901", + "51202000", + "51202002", + "51202200", + "51202203", + "51202204", + "51202206", + "51202207", + "51202300", + "51202306", + "51202400", + "51202401", + "51202402", + "51202403", + "51202405", + "51202406", + "51202409", + "51202411", + "51202412", + "51202413", + "51202414", + "51202416", + "51202417", + "51202500", + "51202501", + "51202600", + "51202603", + "51202700", + "51202701", + "51202800", + "51202801", + "51202803", + "51202804", + "51202805", + "51203100", + "51203101", + "51203200", + "51203201", + "51203202", + "51203203", + "51203300", + "51203301", + "51203302", + "51203303", + "51203400", + "51203401", + "51203402", + "51203403", + "51203600", + "51203605", + "51203800", + "51203801", + "51204000", + "51204001", + "51204200", + "51204201", + "51204202", + "51204203", + "51204204", + "51204205", + "51240000", + "51241100", + "51241103", + "51241110", + "51241128", + "51241131", + "51241133", + "51241143", + "51241144", + "51241200", + "51241205", + "51241209", + "51241215", + "51241227", + "51241232", + "51241235", + "51241237", + "51241243", + "51241246", + "51241262", + "51241263", + "51241500", + "51241513", + "51241522", + "51241544", + "51241555", + "51241560", + "51241565", + "51241600", + "51241603", + "51241605", + "51241660", + "51241800", + "51241886", + "51242200", + "51242209", + "51242300", + "51242302", + "51260000", + "51261700", + "51261701", + "51261702", + "51261703", + "51261704", + "51261705", + "51261706", + "51262000", + "51262002", + "51262400", + "51262404", + "51262410", + "51262414", + "51262900", + "51262907", + "51262914", + "51263000", + "51263002", + "51263009", + "51263100", + "51263101", + "51263105", + "51263122", + "51263139", + "51263151", + "51263162", + "51263169", + "51263175", + "51263400", + "51263406", + "51270000", + "51271600", + "51271613", + "51271622", + "51271623", + "51271629", + "51271636", + "51272000", + "51272006", + "51272100", + "51272111", + "51272200", + "51272207", + "51272300", + "51272302", + "51272400", + "51272401", + "51272406", + "51272408", + "51272900", + "51272901", + "51273000", + "51273009", + "51273900", + "51273921", + "51273937", + "51273950", + "51280000", + "51281500", + "51281501", + "51281502", + "51281503", + "51281504", + "51281507", + "51281509", + "51281513", + "51281518", + "51281519", + "51281520", + "51281521", + "51281600", + "51281607", + "51281614", + "51281616", + "51281618", + "51281624", + "51281626", + "51281627", + "51281632", + "51281651", + "51281659", + "51281675", + "51281700", + "51281702", + "51281703", + "51281710", + "51281711", + "51281712", + "51281713", + "51281714", + "51281716", + "51281717", + "51281800", + "51281801", + "51281803", + "51281805", + "51281806", + "51281818", + "51281819", + "51281821", + "51281823", + "51281900", + "51281902", + "51282000", + "51282001", + "51282003", + "51282004", + "51282005", + "51282100", + "51282101", + "51282109", + "51282200", + "51282201", + "51282202", + "51282208", + "51282300", + "51282301", + "51282302", + "51282303", + "51282304", + "51282308", + "51282309", + "51282310", + "51282317", + "51282327", + "51282400", + "51282404", + "51282407", + "51282409", + "51282411", + "51282500", + "51282502", + "51282506", + "51282511", + "51282514", + "51282517", + "51282523", + "51282600", + "51282602", + "51282610", + "51282700", + "51282701", + "51282702", + "51282703", + "51282800", + "51282801", + "51282804", + "51282808", + "51282900", + "51282901", + "51282902", + "51282909", + "51282916", + "51282921", + "51282926", + "51282931", + "51282932", + "51282944", + "51282951", + "51282953", + "51282956", + "51283000", + "51283002", + "51283003", + "51283006", + "51283100", + "51283101", + "51283106", + "51283107", + "51283108", + "51283110", + "51283112", + "51283200", + "51283210", + "51283300", + "51283301", + "51283303", + "51283400", + "51283401", + "51283402", + "51283403", + "51283404", + "51283405", + "51283406", + "51283407", + "51283408", + "51283409", + "51283410", + "51283411", + "51283412", + "51283413", + "51283414", + "51283415", + "51283416", + "51283417", + "51283418", + "51283419", + "51283420", + "51283421", + "51283422", + "51283423", + "51283424", + "51283500", + "51283501", + "51283502", + "51283505", + "51283507", + "51283509", + "51283600", + "51283601", + "51283602", + "51283603", + "51283604", + "51283700", + "51283701", + "51283702", + "51283705", + "51283706", + "51283709", + "51283711", + "51283712", + "51283717", + "51283718", + "51283719", + "51283724", + "51283725", + "51283726", + "51283800", + "51283801", + "51283804", + "51283900", + "51283901", + "51283904", + "51283908", + "51283941", + "51284000", + "51284002", + "51284004", + "51284006", + "51284012", + "51284014", + "51284017", + "51284027", + "51284035", + "51284043", + "51284100", + "51284103", + "51284104", + "51284106", + "51284108", + "51284109", + "51284115", + "51284119", + "51284121", + "51284135", + "51284136", + "51284141", + "51284150", + "51284300", + "51284303", + "51284500", + "51284502", + "51284600", + "51284603", + "51284605", + "51284610", + "51284613", + "51284900", + "51284903", + "51284911", + "51285000", + "51285003", + "51285004", + "51285005", + "51285006", + "51285100", + "51285101", + "51285300", + "51285302", + "51285307", + "51285500", + "51285502", + "51285600", + "51285900", + "51285907", + "51286200", + "51286201", + "51286206", + "51286500", + "51286501", + "51286800", + "51286801", + "51287000", + "51287004", + "51290000", + "51291700", + "51291712", + "51292000", + "51292011", + "51292012", + "51292019", + "51292023", + "51292027", + "51292900", + "51292908", + "51292921", + "51293000", + "51293002", + "51293012", + "51293400", + "51293402", + "51294000", + "51294001", + "51294400", + "51294403", + "51294500", + "51294513", + "51300000", + "51301800", + "51301802", + "51301900", + "51301904", + "51302000", + "51302004", + "51302300", + "51302308", + "51302309", + "51302318", + "51302320", + "51302325", + "51302336", + "51302337", + "51302400", + "51302401", + "51302403", + "51302404", + "51302500", + "51302503", + "51302700", + "51302701", + "51302900", + "51302901", + "51303000", + "51303001", + "51303002", + "51303100", + "51303104", + "51303400", + "51303402", + "51303403", + "51303407", + "51303600", + "51303611", + "51310000", + "51311900", + "51311901", + "51312100", + "51312105", + "51312200", + "51312204", + "51312300", + "51312304", + "51312309", + "51312400", + "51312401", + "51312405", + "51313000", + "51313100", + "51313101", + "51313111", + "51313112", + "51313120", + "51313200", + "51313205", + "51313218", + "51313300", + "51313301", + "51313305", + "51313400", + "51313401", + "51313415", + "51313421", + "51313422", + "51313424", + "51313700", + "51313702", + "51313709", + "51313800", + "51313801", + "51313802", + "51320000", + "51321500", + "51321501", + "51321505", + "51321600", + "51321604", + "51321700", + "51321701", + "51321708", + "51321800", + "51321804", + "51321808", + "51321900", + "51321901", + "51321904", + "51322200", + "51322201", + "51322205", + "51322300", + "51322301", + "51322700", + "51322704", + "51330000", + "51331900", + "51331901", + "51332000", + "51332003", + "51332006", + "51332500", + "51332501", + "51332700", + "51332703", + "51332800", + "51332807", + "51332812", + "51332814", + "51332822", + "51332831", + "51332840", + "51332855", + "51332880", + "51333200", + "51333202", + "51333400", + "51333410", + "51333413", + "51333500", + "51333502", + "51333600", + "51333601", + "51334200", + "51334204", + "51334207", + "51334300", + "51334303", + "51334306", + "51340000", + "51341500", + "51341501", + "51341600", + "51341604", + "51341800", + "51341801", + "51341802", + "51341803", + "51341805", + "51341806", + "51341807", + "51341900", + "51341901", + "51341903", + "51341904", + "51342300", + "51342301", + "51342304", + "51342305", + "51342307", + "51342308", + "51342309", + "51342310", + "51342311", + "51342313", + "51342316", + "51342400", + "51342402", + "51342500", + "51342501", + "51342503", + "51342506", + "51342700", + "51342701", + "51342702", + "51342709", + "51342710", + "51342715", + "51342900", + "51342901", + "51342902", + "51342904", + "51343000", + "51343002", + "51343004", + "51343005", + "51343100", + "51343101", + "51343110", + "51343115", + "51343116", + "51343200", + "51343201", + "51343203", + "51343204", + "51343500", + "51343502", + "51343504", + "51343509", + "51343511", + "51343700", + "51343702", + "51343704", + "51343800", + "51343801", + "51343803", + "51343804", + "51343806", + "51343808", + "51343809", + "51343810", + "51343811", + "51343812", + "51343813", + "51343814", + "51343816", + "51343820", + "51343821", + "51343822", + "51343826", + "51343827", + "51343828", + "51350000", + "51351500", + "51351509", + "51351510", + "51351511", + "51351514", + "51351600", + "51351605", + "51351606", + "51351608", + "51351609", + "51351612", + "51351613", + "51351627", + "51351635", + "51351636", + "51351637", + "51351800", + "51351804", + "51351900", + "51351912", + "51352000", + "51352005", + "51352006", + "51352008", + "51352400", + "51352404", + "51352413", + "51352414", + "51352422", + "51352426", + "51352435", + "51352436", + "51360000", + "51361500", + "51361501", + "51361800", + "51361809", + "51361900", + "51361918", + "51362600", + "51362601", + "51362604", + "51370000", + "51371600", + "51371601", + "51371604", + "51371800", + "51371803", + "51371900", + "51371910", + "51372000", + "51372003", + "51372015", + "51372022", + "51372031", + "51372036", + "51372040", + "51372100", + "51372107", + "51372108", + "51372125", + "51372127", + "51372300", + "51372305", + "51372321", + "51373200", + "51373204", + "51373300", + "51373341", + "51380000", + "51381500", + "51381502", + "51381504", + "51381505", + "51381700", + "51381701", + "51382700", + "51382702", + "51383300", + "51383304", + "51383315", + "51383400", + "51383401", + "51383500", + "51383507", + "51383510", + "51383900", + "51383905", + "51384500", + "51384509", + "51384511", + "51384514", + "51384522", + "51384600", + "51384607", + "51384627", + "51384800", + "51384802", + "51384803", + "51385600", + "51385608", + "51385800", + "51385804", + "51385805", + "51386600", + "51386609", + "51386615", + "51390000", + "51391600", + "51391602", + "51391616", + "51391700", + "51391703", + "51391717", + "51391722", + "51391726", + "51391734", + "51391739", + "51391743", + "51391746", + "51392400", + "51392403", + "51392408", + "51392412", + "51393400", + "51393405", + "51393600", + "51393604", + "51393606", + "51400000", + "51401500", + "51401501", + "51401505", + "51401516", + "51401518", + "51401525", + "51401533", + "51401538", + "51401550", + "51401569", + "51401570", + "51401700", + "51401705", + "51402200", + "51402206", + "51410000", + "51411600", + "51411605", + "51412000", + "51412004", + "51412600", + "51412601", + "51412700", + "51412702", + "51413200", + "51413204", + "51413207", + "51413212", + "51413300", + "51413301", + "51413500", + "51413504", + "51420000", + "51421500", + "51421501", + "51421504", + "51421505", + "51421800", + "51421802", + "51422100", + "51422101", + "51422122", + "51422200", + "51422202", + "51422205", + "51422206", + "51422300", + "51422302", + "51422303", + "51422306", + "51422315", + "51422327", + "51422331", + "51422340", + "51422342", + "51422354", + "51422356", + "51422364", + "51422400", + "51422408", + "51422415", + "51422417", + "51422421", + "51422425", + "51422434", + "51430000", + "51431500", + "51431507", + "51431600", + "51431602", + "51431609", + "51431614", + "51431700", + "51431708", + "51431800", + "51431801", + "51431803", + "51431900", + "51431902", + "51432300", + "51432305", + "51432313", + "51432315", + "51432400", + "51432401", + "51432500", + "51432503", + "51432600", + "51432606", + "51432700", + "51432705", + "51432800", + "51432803", + "51432805", + "51432806", + "51433300", + "51433303", + "51433305", + "51433700", + "51433707", + "51433708", + "51433800", + "51433804", + "51433900", + "51433902", + "51433903", + "51433915", + "51433924", + "51433925", + "51434500", + "51434502", + "51434900", + "51434907", + "51434908", + "51434909", + "51434931", + "51434938", + "51434945", + "51434949", + "51434958", + "51434959", + "51434960", + "51434961", + "51434962", + "51434963", + "51434964", + "51440000", + "51441600", + "51441619", + "51442000", + "51442001", + "51442004", + "51442007", + "51450000", + "51451600", + "51451604", + "51451800", + "51451801", + "51451900", + "51451907", + "51452100", + "51452101", + "51452200", + "51452201", + "51452202", + "51452300", + "51452301", + "51452302", + "51452305", + "51452307", + "51452400", + "51452401", + "51452402", + "51452500", + "51452501", + "51452502", + "51452600", + "51452601", + "51452700", + "51452701", + "51452800", + "51452801", + "51452900", + "51452901", + "51453000", + "51453001", + "51453200", + "51453201", + "51453400", + "51453401", + "51453404", + "51453500", + "51453501", + "51453502", + "51453600", + "51453601", + "51460000", + "51461600", + "51461606", + "51461607", + "51470000", + "51471500", + "51471502", + "51471505", + "51472000", + "51472002", + "51472300", + "51472302", + "51472600", + "51472601", + "51472800", + "51472802", + "51472803", + "51472805", + "51472900", + "51472901", + "51472902", + "51473000", + "51473001", + "51473003", + "51473013", + "51473016", + "51473020", + "51473100", + "51473104", + "51473200", + "51473203", + "51473300", + "51473302", + "51473307", + "51473500", + "51473502", + "51473503", + "51473504", + "51473600", + "51473602", + "51473700", + "51473704", + "51474000", + "51474001", + "52000000", + "52100000", + "52101500", + "52101517", + "52120000", + "52121500", + "52121501", + "52121505", + "52121508", + "52121600", + "52121700", + "52130000", + "52131500", + "52131600", + "52131700", + "52140000", + "52141500", + "52141501", + "52141502", + "52141509", + "52141600", + "52141700", + "52141800", + "52141804", + "52150000", + "52151500", + "52151501", + "52151504", + "52151600", + "52151700", + "52151800", + "52151900", + "52152000", + "52152100", + "52152101", + "52152200", + "52152300", + "52160000", + "52161500", + "52161502", + "52161505", + "52161511", + "52161512", + "52161514", + "52161515", + "52161516", + "52161518", + "52161520", + "52161523", + "52161524", + "52161526", + "52161535", + "52161542", + "52161543", + "52161553", + "52161600", + "52170000", + "53000000", + "53100000", + "53101500", + "53101600", + "53101606", + "53101700", + "53101800", + "53101806", + "53101807", + "53101900", + "53102000", + "53102100", + "53102200", + "53102300", + "53102305", + "53102400", + "53102402", + "53102500", + "53102501", + "53102504", + "53102505", + "53102511", + "53102516", + "53102600", + "53102700", + "53102701", + "53102702", + "53102703", + "53102704", + "53102705", + "53102706", + "53102707", + "53102708", + "53102709", + "53102710", + "53102712", + "53102715", + "53102716", + "53102717", + "53102718", + "53102719", + "53102800", + "53102900", + "53103000", + "53103005", + "53103100", + "53103101", + "53103200", + "53103201", + "53103300", + "53110000", + "53111500", + "53111501", + "53111502", + "53111503", + "53111504", + "53111505", + "53111600", + "53111700", + "53111800", + "53111900", + "53112000", + "53112100", + "53120000", + "53121500", + "53121501", + "53121502", + "53121503", + "53121600", + "53121601", + "53121602", + "53121603", + "53121700", + "53121701", + "53121705", + "53121706", + "53121800", + "53121801", + "53121802", + "53130000", + "53131500", + "53131501", + "53131502", + "53131503", + "53131504", + "53131505", + "53131506", + "53131507", + "53131508", + "53131509", + "53131510", + "53131600", + "53131601", + "53131602", + "53131603", + "53131604", + "53131605", + "53131606", + "53131607", + "53131608", + "53131609", + "53131610", + "53131611", + "53131612", + "53131613", + "53131614", + "53131615", + "53131616", + "53131617", + "53131618", + "53131621", + "53131622", + "53131624", + "53131625", + "53131626", + "53131627", + "53131628", + "53131629", + "53131630", + "53131634", + "53131635", + "53131637", + "53131639", + "53131641", + "53131643", + "53131647", + "53131648", + "53131649", + "53131651", + "53131652", + "53131662", + "53131663", + "53131664", + "53131665", + "53131666", + "53131667", + "53131700", + "53131702", + "53140000", + "53141600", + "53141602", + "54000000", + "54100000", + "54110000", + "54111500", + "54111501", + "54111600", + "54111601", + "54111603", + "54111700", + "54111701", + "54111709", + "54111710", + "54120000", + "55000000", + "55100000", + "55101500", + "55101501", + "55101502", + "55101503", + "55101504", + "55101505", + "55101506", + "55101507", + "55101509", + "55101510", + "55101513", + "55101514", + "55101515", + "55101516", + "55101517", + "55101518", + "55101519", + "55101520", + "55101521", + "55101522", + "55101523", + "55101524", + "55101525", + "55101526", + "55101527", + "55101528", + "55101529", + "55101530", + "55101531", + "55101532", + "55110000", + "55111500", + "55111501", + "55120000", + "55121500", + "55121501", + "55121502", + "55121503", + "55121600", + "55121601", + "55121602", + "55121604", + "55121605", + "55121606", + "55121607", + "55121608", + "55121609", + "55121700", + "55121701", + "55121702", + "55121703", + "55121704", + "55121705", + "55121706", + "55121707", + "55121708", + "55121710", + "55121715", + "55121800", + "55121801", + "55121802", + "55121803", + "55121804", + "55121806", + "55121807", + "55121808", + "55121900", + "55121901", + "55121902", + "55121903", + "55121904", + "55121905", + "55121906", + "55121907", + "55121908", + "56000000", + "56100000", + "56101500", + "56101502", + "56101503", + "56101504", + "56101507", + "56101508", + "56101509", + "56101510", + "56101513", + "56101514", + "56101515", + "56101516", + "56101518", + "56101519", + "56101520", + "56101529", + "56101530", + "56101531", + "56101532", + "56101535", + "56101539", + "56101542", + "56101543", + "56101547", + "56101600", + "56101700", + "56101701", + "56101702", + "56101703", + "56101704", + "56101705", + "56101706", + "56101707", + "56101708", + "56101710", + "56101711", + "56101712", + "56101715", + "56101716", + "56101718", + "56101719", + "56101722", + "56101800", + "56101900", + "56110000", + "56111500", + "56111501", + "56111507", + "56111509", + "56111511", + "56111513", + "56111514", + "56111600", + "56111601", + "56111602", + "56111603", + "56111604", + "56111605", + "56111606", + "56111700", + "56111701", + "56111800", + "56111802", + "56111806", + "56111900", + "56111906", + "56112000", + "56112100", + "56112106", + "56112108", + "56112109", + "56112200", + "56112300", + "56120000", + "56121000", + "56121400", + "56121500", + "56121501", + "56121502", + "56121503", + "56121504", + "56121505", + "56121506", + "56121507", + "56121508", + "56121509", + "56121510", + "56121700", + "56121900", + "56122000", + "56122001", + "56130000", + "56140000", + "57000000", + "57010000", + "57010100", + "57010101", + "57010102", + "57010103", + "57020000", + "57020100", + "57020101", + "57020102", + "57030000", + "57030100", + "57030101", + "57030102", + "57030103", + "57030104", + "57030105", + "57030106", + "57030107", + "57030108", + "57030109", + "57030110", + "57030111", + "57030112", + "57030200", + "57030300", + "57030301", + "57030302", + "57030303", + "57030304", + "57030305", + "57030400", + "57030401", + "57040000", + "57040100", + "57040101", + "57040102", + "57040103", + "57040104", + "57040105", + "57040200", + "57040201", + "57040300", + "57040301", + "57050000", + "57050100", + "57050101", + "57050102", + "57050103", + "57050104", + "57050105", + "57050200", + "57050201", + "57050202", + "57050203", + "57050204", + "57050205", + "57050300", + "57050301", + "57060000", + "57060100", + "57060101", + "57060102", + "57060200", + "57060201", + "57060202", + "57060203", + "57060204", + "57060205", + "57060206", + "57060208", + "57060300", + "57060301", + "57060302", + "57060303", + "57060400", + "57060401", + "57070000", + "57070100", + "57070101", + "57070102", + "57070103", + "57070104", + "57070105", + "57080000", + "57080100", + "57080101", + "57080102", + "57080103", + "57080104", + "57111100", + "57222100", + "57333100", + "57333200", + "57333300", + "57333400", + "57444100", + "57444200", + "57444300", + "57555100", + "57555200", + "57555300", + "57666100", + "57666200", + "57666300", + "57666400", + "57777100", + "57888100", + "60000000", + "60100000", + "60101700", + "60101734", + "60103700", + "60103701", + "60103702", + "60103704", + "60103900", + "60103905", + "60103915", + "60104100", + "60104200", + "60104201", + "60104202", + "60104203", + "60104204", + "60104400", + "60104700", + "60104701", + "60104702", + "60105300", + "60105301", + "60105302", + "60105303", + "60105304", + "60105305", + "60105306", + "60105307", + "60105308", + "60105309", + "60105600", + "60105613", + "60105627", + "60105900", + "60105901", + "60105902", + "60105903", + "60105904", + "60105905", + "60105906", + "60105907", + "60105908", + "60105915", + "60106100", + "60106101", + "60106102", + "60106104", + "60106108", + "60106200", + "60106201", + "60106202", + "60106203", + "60106204", + "60106205", + "60106206", + "60106208", + "60106209", + "60106300", + "60106301", + "60106302", + "60110000", + "60120000", + "60121300", + "60121301", + "60121600", + "60121606", + "60130000", + "60131000", + "60131001", + "60131003", + "60131006", + "60131100", + "60131101", + "60131102", + "60131104", + "60131105", + "60131200", + "60131201", + "60131202", + "60131203", + "60131204", + "60131207", + "60131300", + "60131301", + "60131302", + "60131303", + "60131304", + "60131305", + "60131306", + "60131307", + "60131308", + "60131400", + "60131401", + "60131402", + "60131403", + "60131404", + "60131405", + "60131406", + "60131500", + "60131501", + "60131503", + "60131504", + "60131505", + "60131506", + "60131507", + "60131508", + "60131509", + "60131512", + "60131520", + "60131600", + "60131601", + "60131700", + "60131701", + "60131702", + "60131703", + "60131800", + "60131801", + "60131802", + "60131803", + "60140000", + "60141000", + "60141100", + "60141102", + "64000000", + "64100000", + "64101700", + "64101701", + "64101702", + "64101703", + "64110000", + "64111700", + "64111705", + "64120000", + "64121500", + "64140000", + "64141700", + "64141701", + "70000000", + "70100000", + "70101500", + "70101501", + "70101502", + "70101503", + "70101504", + "70101507", + "70101510", + "70101600", + "70101601", + "70101602", + "70101603", + "70101607", + "70101700", + "70101701", + "70101702", + "70101703", + "70101704", + "70101800", + "70101801", + "70101802", + "70101803", + "70101804", + "70101805", + "70101806", + "70101900", + "70101901", + "70101902", + "70101903", + "70101904", + "70101905", + "70110000", + "70111500", + "70111501", + "70111502", + "70111503", + "70111504", + "70111505", + "70111506", + "70111507", + "70111508", + "70111600", + "70111700", + "70111701", + "70111702", + "70111703", + "70111704", + "70111706", + "70111707", + "70111708", + "70111709", + "70111710", + "70111711", + "70111712", + "70111713", + "70120000", + "70121500", + "70121501", + "70121502", + "70121503", + "70121504", + "70121505", + "70121600", + "70121601", + "70121602", + "70121603", + "70121604", + "70121605", + "70121606", + "70121607", + "70121608", + "70121610", + "70121700", + "70121701", + "70121703", + "70121704", + "70121705", + "70121706", + "70121800", + "70121801", + "70121802", + "70121803", + "70121900", + "70121901", + "70121902", + "70121903", + "70122000", + "70122001", + "70122002", + "70122003", + "70122004", + "70122005", + "70122006", + "70122007", + "70122008", + "70122009", + "70122010", + "70130000", + "70131500", + "70131501", + "70131502", + "70131503", + "70131506", + "70131600", + "70131601", + "70131603", + "70131604", + "70131605", + "70131700", + "70131701", + "70131702", + "70131703", + "70131704", + "70131705", + "70131706", + "70140000", + "70141500", + "70141501", + "70141503", + "70141507", + "70141508", + "70141512", + "70141515", + "70141516", + "70141520", + "70141600", + "70141601", + "70141602", + "70141604", + "70141605", + "70141700", + "70141701", + "70141702", + "70141800", + "70141801", + "70141802", + "70141803", + "70141804", + "70141900", + "70141901", + "70141902", + "70141903", + "70141904", + "70142000", + "70142001", + "70142002", + "70142003", + "70142004", + "70142005", + "70142006", + "70142007", + "70142008", + "70142009", + "70142010", + "70142011", + "70150000", + "70151500", + "70151501", + "70151505", + "70151506", + "70151507", + "70151510", + "70151600", + "70151601", + "70151602", + "70151603", + "70151604", + "70151605", + "70151606", + "70151700", + "70151701", + "70151703", + "70151706", + "70151800", + "70151801", + "70151802", + "70151803", + "70151804", + "70151805", + "70151806", + "70151807", + "70151900", + "70151901", + "70151902", + "70151903", + "70160000", + "70161500", + "70161501", + "70161600", + "70161601", + "70161700", + "70161701", + "70161702", + "70161703", + "70161704", + "70161705", + "70161706", + "70161710", + "70161711", + "70170000", + "70171500", + "70171501", + "70171502", + "70171503", + "70171504", + "70171505", + "70171506", + "70171507", + "70171600", + "70171601", + "70171602", + "70171603", + "70171604", + "70171605", + "70171606", + "70171607", + "70171700", + "70171701", + "70171702", + "70171703", + "70171704", + "70171705", + "70171706", + "70171707", + "70171708", + "70171709", + "70171710", + "70171800", + "70171801", + "70171802", + "70171803", + "70190000", + "70190100", + "71000000", + "71100000", + "71101700", + "71110000", + "71112300", + "71120000", + "71130000", + "71140000", + "71141100", + "71141103", + "71150000", + "71151100", + "71160000", + "71161000", + "71161600", + "71161605", + "72000000", + "72100000", + "72101500", + "72101501", + "72101504", + "72101505", + "72101506", + "72101507", + "72101508", + "72101509", + "72101510", + "72101511", + "72101512", + "72101513", + "72101514", + "72101515", + "72101516", + "72101517", + "72101518", + "72101519", + "72101520", + "72101521", + "72102100", + "72102101", + "72102102", + "72102103", + "72102104", + "72102105", + "72102106", + "72102900", + "72102902", + "72102903", + "72102905", + "72102906", + "72103100", + "72103101", + "72103102", + "72103103", + "72103104", + "72103300", + "72103301", + "72103302", + "72103304", + "72103305", + "72110000", + "72111000", + "72111001", + "72111002", + "72111003", + "72111004", + "72111005", + "72111006", + "72111007", + "72111008", + "72111100", + "72111101", + "72111102", + "72111103", + "72111104", + "72111105", + "72111106", + "72111107", + "72111108", + "72111109", + "72111110", + "72111111", + "72120000", + "72121000", + "72121001", + "72121002", + "72121003", + "72121004", + "72121005", + "72121006", + "72121007", + "72121008", + "72121100", + "72121101", + "72121102", + "72121103", + "72121104", + "72121105", + "72121200", + "72121201", + "72121202", + "72121203", + "72121300", + "72121301", + "72121302", + "72121400", + "72121401", + "72121402", + "72121403", + "72121404", + "72121405", + "72121406", + "72121407", + "72121408", + "72121409", + "72121410", + "72121500", + "72121501", + "72121502", + "72121503", + "72121504", + "72121505", + "72121506", + "72121507", + "72121508", + "72121509", + "72121510", + "72121511", + "72121512", + "72121513", + "72121514", + "72121515", + "72121516", + "72121517", + "72140000", + "72141000", + "72141001", + "72141002", + "72141003", + "72141004", + "72141100", + "72141101", + "72141102", + "72141103", + "72141104", + "72141105", + "72141106", + "72141107", + "72141108", + "72141109", + "72141110", + "72141111", + "72141112", + "72141113", + "72141114", + "72141115", + "72141116", + "72141117", + "72141118", + "72141119", + "72141120", + "72141121", + "72141122", + "72141123", + "72141124", + "72141125", + "72141126", + "72141127", + "72141128", + "72141129", + "72141130", + "72141200", + "72141201", + "72141202", + "72141203", + "72141204", + "72141205", + "72141206", + "72141207", + "72141209", + "72141210", + "72141211", + "72141212", + "72141213", + "72141214", + "72141215", + "72141216", + "72141400", + "72141401", + "72141402", + "72141500", + "72141502", + "72141503", + "72141504", + "72141505", + "72141507", + "72141508", + "72141509", + "72141510", + "72141511", + "72141600", + "72141601", + "72141602", + "72141603", + "72141604", + "72141605", + "72141700", + "72141701", + "72141702", + "72150000", + "72151000", + "72151001", + "72151002", + "72151003", + "72151004", + "72151005", + "72151006", + "72151100", + "72151101", + "72151102", + "72151103", + "72151200", + "72151201", + "72151202", + "72151203", + "72151204", + "72151205", + "72151206", + "72151207", + "72151300", + "72151301", + "72151302", + "72151303", + "72151304", + "72151305", + "72151306", + "72151307", + "72151308", + "72151400", + "72151401", + "72151402", + "72151500", + "72151501", + "72151502", + "72151503", + "72151504", + "72151505", + "72151506", + "72151507", + "72151508", + "72151509", + "72151510", + "72151511", + "72151514", + "72151515", + "72151600", + "72151601", + "72151602", + "72151603", + "72151604", + "72151605", + "72151606", + "72151607", + "72151608", + "72151609", + "72151700", + "72151701", + "72151702", + "72151703", + "72151704", + "72151800", + "72151801", + "72151802", + "72151803", + "72151900", + "72151901", + "72151903", + "72151904", + "72151905", + "72151906", + "72151907", + "72151908", + "72151909", + "72151910", + "72151911", + "72152000", + "72152001", + "72152002", + "72152003", + "72152004", + "72152005", + "72152100", + "72152101", + "72152102", + "72152103", + "72152104", + "72152200", + "72152201", + "72152202", + "72152203", + "72152204", + "72152300", + "72152301", + "72152302", + "72152303", + "72152400", + "72152401", + "72152402", + "72152403", + "72152404", + "72152405", + "72152500", + "72152501", + "72152502", + "72152503", + "72152504", + "72152505", + "72152506", + "72152507", + "72152508", + "72152509", + "72152600", + "72152601", + "72152602", + "72152603", + "72152604", + "72152605", + "72152606", + "72152607", + "72152700", + "72152701", + "72152702", + "72152703", + "72152704", + "72152705", + "72152706", + "72152707", + "72152708", + "72152709", + "72152710", + "72152711", + "72152800", + "72152801", + "72152802", + "72152900", + "72152901", + "72152902", + "72152903", + "72152904", + "72152905", + "72152906", + "72152907", + "72152908", + "72152909", + "72153000", + "72153001", + "72153002", + "72153100", + "72153101", + "72153102", + "72153103", + "72153104", + "72153105", + "72153106", + "72153107", + "72153108", + "72153200", + "72153201", + "72153202", + "72153203", + "72153204", + "72153205", + "72153206", + "72153207", + "72153208", + "72153209", + "72153300", + "72153301", + "72153302", + "72153303", + "72153400", + "72153401", + "72153402", + "72153500", + "72153501", + "72153502", + "72153503", + "72153504", + "72153505", + "72153506", + "72153507", + "72153600", + "72153601", + "72153602", + "72153603", + "72153604", + "72153605", + "72153606", + "72153607", + "72153608", + "72153609", + "72153610", + "72153611", + "72153612", + "72153613", + "72153700", + "72153701", + "72153702", + "72153900", + "72153901", + "72153902", + "72154000", + "72154001", + "72154002", + "72154003", + "72154004", + "72154005", + "72154006", + "72154007", + "72154008", + "72154009", + "72154010", + "72154011", + "72154012", + "72154013", + "72154014", + "72154015", + "72154016", + "72154017", + "72154018", + "72154019", + "72154020", + "72154021", + "72154022", + "72154023", + "72154024", + "72154025", + "72154026", + "72154027", + "72154028", + "72154029", + "72154030", + "72154031", + "72154032", + "72154033", + "72154034", + "72154035", + "72154036", + "72154037", + "72154038", + "72154039", + "72154040", + "72154041", + "72154042", + "72154043", + "72154044", + "72154045", + "72154046", + "72154047", + "72154048", + "72154049", + "72154050", + "72154051", + "72154052", + "72154053", + "72154054", + "72154055", + "72154056", + "72154057", + "72154058", + "72154059", + "72154060", + "72154061", + "72154062", + "72154063", + "72154064", + "72154065", + "72154066", + "72154067", + "72154068", + "72154069", + "72154100", + "72154101", + "72154102", + "72154103", + "72154104", + "72154105", + "72154106", + "72154107", + "72154108", + "72154109", + "72154110", + "72154200", + "72154201", + "72154300", + "72154301", + "72154302", + "72154303", + "72154400", + "72154401", + "72154402", + "72154500", + "72154501", + "72154502", + "72154503", + "72154600", + "72154601", + "72154602", + "72154603", + "72154604", + "72154605", + "73000000", + "73100000", + "73101600", + "73110000", + "73111500", + "73120000", + "73130000", + "73131500", + "73131600", + "73131700", + "73131800", + "73131900", + "73140000", + "73141500", + "73141600", + "73141700", + "73141715", + "73150000", + "73151500", + "73151501", + "73151502", + "73151600", + "73151700", + "73151800", + "73151900", + "73152000", + "73152100", + "73152101", + "73152102", + "73152103", + "73152104", + "73152105", + "73152106", + "73152107", + "73152108", + "73152109", + "73152112", + "73160000", + "73161500", + "73161600", + "73170000", + "73171500", + "73171501", + "73171502", + "73171503", + "73171504", + "73171506", + "73171507", + "73171510", + "73171511", + "73171512", + "73171600", + "73171602", + "73171605", + "73180000", + "73181100", + "73181103", + "76000000", + "76100000", + "76101500", + "76101600", + "76101601", + "76101602", + "76110000", + "76111500", + "76111501", + "76111503", + "76111504", + "76111505", + "76111506", + "76111507", + "76111600", + "76111601", + "76111602", + "76111603", + "76111604", + "76111605", + "76111800", + "76111801", + "76120000", + "76121500", + "76121501", + "76121502", + "76121503", + "76121504", + "76121505", + "76121506", + "76121507", + "76121600", + "76121601", + "76121602", + "76121603", + "76121604", + "76121700", + "76121701", + "76121702", + "76121800", + "76121900", + "76121901", + "76121902", + "76121903", + "76121904", + "76121905", + "76122000", + "76122001", + "76122002", + "76122003", + "76122004", + "76122100", + "76122200", + "76122300", + "76122400", + "76122407", + "76130000", + "76131500", + "76131600", + "76131700", + "77000000", + "77100000", + "77101500", + "77101501", + "77101502", + "77101503", + "77101504", + "77101505", + "77101506", + "77101600", + "77101601", + "77101602", + "77101603", + "77101604", + "77101605", + "77101700", + "77101701", + "77101702", + "77101703", + "77101704", + "77101705", + "77101706", + "77101707", + "77101800", + "77101801", + "77101802", + "77101803", + "77101804", + "77101805", + "77101806", + "77101900", + "77101901", + "77101902", + "77101903", + "77101904", + "77101905", + "77101906", + "77101907", + "77101908", + "77101909", + "77101910", + "77102000", + "77102002", + "77102004", + "77110000", + "77111500", + "77111501", + "77111502", + "77111503", + "77111504", + "77111505", + "77111506", + "77111507", + "77111508", + "77111600", + "77111601", + "77111602", + "77111603", + "77120000", + "77121500", + "77121501", + "77121503", + "77121504", + "77121600", + "77121601", + "77121602", + "77121603", + "77121604", + "77121605", + "77121606", + "77121607", + "77121608", + "77121609", + "77121610", + "77121700", + "77121701", + "77121702", + "77121703", + "77121704", + "77121705", + "77121706", + "77121707", + "77121708", + "77121709", + "77130000", + "77131500", + "77131501", + "77131502", + "77131503", + "77131600", + "77131601", + "77131602", + "77131603", + "77131604", + "77131700", + "77140000", + "78000000", + "78100000", + "78101500", + "78101501", + "78101502", + "78101503", + "78101504", + "78101505", + "78101600", + "78101601", + "78101602", + "78101603", + "78101604", + "78101608", + "78101609", + "78101610", + "78101700", + "78101701", + "78101702", + "78101703", + "78101704", + "78101708", + "78101709", + "78101710", + "78101800", + "78101801", + "78101802", + "78101803", + "78101804", + "78101808", + "78101809", + "78101810", + "78101900", + "78101901", + "78101902", + "78101903", + "78101904", + "78101905", + "78102000", + "78102100", + "78102101", + "78102102", + "78102103", + "78102200", + "78102201", + "78102202", + "78102203", + "78102204", + "78102205", + "78102206", + "78110000", + "78111500", + "78111501", + "78111502", + "78111503", + "78111504", + "78111505", + "78111506", + "78111600", + "78111601", + "78111602", + "78111603", + "78111700", + "78111701", + "78111702", + "78111704", + "78111705", + "78111706", + "78111707", + "78111800", + "78111802", + "78111803", + "78111804", + "78111807", + "78111808", + "78111809", + "78111810", + "78111811", + "78111812", + "78111813", + "78111814", + "78111815", + "78111900", + "78120000", + "78121500", + "78121501", + "78121600", + "78121601", + "78121603", + "78130000", + "78131500", + "78131501", + "78131502", + "78131600", + "78131601", + "78131602", + "78131603", + "78131700", + "78131701", + "78131702", + "78131800", + "78131801", + "78131802", + "78131803", + "78131804", + "78131806", + "78131807", + "78140000", + "78141500", + "78141501", + "78141502", + "78141503", + "78141504", + "78141505", + "78141510", + "78141600", + "78141601", + "78141602", + "78141603", + "78141700", + "78141701", + "78141702", + "78141703", + "78141704", + "78141800", + "78141801", + "78141802", + "78141803", + "78141804", + "78141805", + "78141806", + "78141807", + "78141900", + "78142000", + "78142001", + "78142002", + "78142003", + "78180000", + "78181500", + "78181501", + "78181505", + "78181506", + "78181507", + "78181508", + "78181509", + "78181600", + "78181700", + "78181701", + "78181702", + "78181703", + "78181704", + "78181800", + "78181818", + "78181842", + "78200000", + "78201000", + "78202000", + "78203000", + "78204000", + "78204001", + "78204002", + "78204003", + "78204004", + "78204005", + "78204006", + "78204007", + "78204008", + "78204009", + "78204010", + "78204011", + "78204012", + "78204013", + "78204014", + "78204015", + "78204016", + "78204017", + "78204018", + "78204019", + "80000000", + "80100000", + "80101500", + "80101501", + "80101502", + "80101503", + "80101504", + "80101505", + "80101506", + "80101507", + "80101508", + "80101509", + "80101510", + "80101511", + "80101512", + "80101513", + "80101600", + "80101601", + "80101602", + "80101603", + "80101604", + "80101605", + "80101606", + "80101607", + "80101700", + "80101702", + "80101703", + "80101704", + "80101706", + "80110000", + "80111500", + "80111501", + "80111502", + "80111503", + "80111504", + "80111505", + "80111506", + "80111507", + "80111508", + "80111509", + "80111510", + "80111511", + "80111600", + "80111601", + "80111602", + "80111603", + "80111604", + "80111605", + "80111606", + "80111607", + "80111608", + "80111609", + "80111610", + "80111611", + "80111612", + "80111613", + "80111614", + "80111615", + "80111616", + "80111617", + "80111618", + "80111619", + "80111620", + "80111621", + "80111622", + "80111623", + "80111624", + "80111625", + "80111700", + "80111701", + "80111702", + "80111703", + "80111704", + "80111705", + "80111706", + "80111707", + "80111708", + "80111709", + "80111710", + "80111711", + "80111712", + "80111713", + "80111714", + "80111715", + "80111716", + "80111717", + "80111718", + "80111719", + "80120000", + "80121500", + "80121501", + "80121502", + "80121503", + "80121600", + "80121601", + "80121602", + "80121603", + "80121604", + "80121605", + "80121606", + "80121607", + "80121608", + "80121609", + "80121611", + "80121700", + "80121701", + "80121703", + "80121704", + "80121706", + "80121707", + "80121708", + "80121800", + "80121801", + "80121802", + "80121803", + "80121804", + "80121900", + "80121901", + "80121902", + "80121903", + "80121904", + "80122000", + "80130000", + "80131500", + "80131501", + "80131502", + "80131503", + "80131504", + "80131505", + "80131506", + "80131600", + "80131601", + "80131602", + "80131603", + "80131604", + "80131605", + "80131700", + "80131701", + "80131702", + "80131703", + "80131800", + "80131801", + "80131802", + "80131803", + "80140000", + "80141400", + "80141401", + "80141402", + "80141403", + "80141404", + "80141405", + "80141406", + "80141407", + "80141408", + "80141409", + "80141410", + "80141411", + "80141412", + "80141500", + "80141501", + "80141502", + "80141503", + "80141504", + "80141505", + "80141506", + "80141507", + "80141508", + "80141509", + "80141510", + "80141511", + "80141512", + "80141513", + "80141514", + "80141600", + "80141601", + "80141603", + "80141604", + "80141605", + "80141606", + "80141607", + "80141609", + "80141612", + "80141613", + "80141618", + "80141619", + "80141624", + "80141625", + "80141626", + "80141630", + "80141633", + "80141635", + "80141700", + "80141701", + "80141702", + "80141703", + "80141704", + "80141705", + "80141706", + "80141800", + "80141801", + "80141802", + "80141803", + "80141900", + "80141901", + "80141902", + "80150000", + "80151500", + "80151501", + "80151502", + "80151503", + "80151504", + "80151505", + "80151600", + "80151601", + "80151602", + "80151603", + "80151604", + "80151605", + "80160000", + "80161500", + "80161501", + "80161502", + "80161503", + "80161504", + "80161505", + "80161506", + "80161507", + "80161508", + "80161600", + "80161601", + "80161602", + "80161603", + "80161700", + "80161701", + "80161702", + "80161703", + "80161800", + "80161801", + "80170000", + "80171500", + "80171501", + "80171502", + "80171503", + "80171504", + "80171505", + "80171600", + "80171602", + "80171800", + "80171801", + "80171802", + "80171803", + "80171900", + "80171902", + "80171903", + "80171904", + "80171905", + "80171906", + "80171907", + "80171908", + "80171909", + "80172000", + "80172001", + "80172002", + "80172003", + "80172100", + "80172101", + "80172102", + "80172103", + "80172104", + "81000000", + "81100000", + "81101500", + "81101501", + "81101502", + "81101503", + "81101505", + "81101506", + "81101507", + "81101508", + "81101509", + "81101510", + "81101511", + "81101512", + "81101513", + "81101514", + "81101515", + "81101516", + "81101517", + "81101518", + "81101519", + "81101520", + "81101521", + "81101522", + "81101523", + "81101524", + "81101525", + "81101526", + "81101527", + "81101528", + "81101529", + "81101530", + "81101600", + "81101700", + "81101701", + "81101702", + "81101703", + "81101706", + "81101707", + "81101710", + "81101711", + "81101713", + "81101800", + "81101900", + "81101902", + "81102000", + "81102001", + "81102100", + "81102101", + "81102200", + "81102201", + "81102202", + "81102203", + "81102300", + "81102301", + "81102302", + "81102400", + "81102401", + "81102402", + "81102500", + "81102501", + "81102502", + "81102503", + "81102600", + "81102601", + "81102800", + "81102801", + "81102802", + "81102803", + "81102804", + "81102805", + "81102806", + "81102807", + "81102808", + "81102809", + "81102810", + "81102811", + "81102815", + "81110000", + "81111500", + "81111501", + "81111502", + "81111503", + "81111504", + "81111505", + "81111506", + "81111507", + "81111508", + "81111509", + "81111510", + "81111511", + "81111512", + "81111600", + "81111601", + "81111602", + "81111603", + "81111604", + "81111605", + "81111606", + "81111607", + "81111608", + "81111609", + "81111610", + "81111611", + "81111612", + "81111613", + "81111700", + "81111701", + "81111702", + "81111703", + "81111704", + "81111705", + "81111706", + "81111707", + "81111708", + "81111709", + "81111800", + "81111801", + "81111802", + "81111803", + "81111804", + "81111805", + "81111806", + "81111808", + "81111809", + "81111810", + "81111811", + "81111812", + "81111814", + "81111818", + "81111819", + "81111820", + "81111900", + "81111901", + "81111902", + "81112000", + "81112001", + "81112002", + "81112003", + "81112004", + "81112005", + "81112006", + "81112007", + "81112008", + "81112009", + "81112010", + "81112100", + "81112101", + "81112102", + "81112103", + "81112104", + "81112105", + "81112106", + "81112107", + "81112200", + "81112201", + "81112202", + "81112203", + "81112204", + "81112205", + "81112206", + "81112207", + "81112208", + "81112209", + "81112210", + "81112211", + "81112212", + "81112213", + "81112214", + "81112215", + "81112216", + "81112217", + "81112218", + "81112219", + "81112220", + "81112221", + "81112222", + "81112223", + "81112224", + "81112300", + "81112301", + "81112302", + "81112303", + "81112304", + "81112305", + "81112306", + "81112307", + "81112308", + "81112309", + "81112310", + "81112400", + "81112401", + "81112500", + "81112501", + "81112502", + "81120000", + "81121500", + "81121501", + "81121502", + "81121503", + "81121504", + "81121505", + "81121600", + "81121601", + "81121602", + "81121603", + "81121604", + "81121605", + "81121606", + "81121607", + "81130000", + "81131500", + "81131501", + "81131502", + "81131503", + "81131504", + "81131505", + "81140000", + "81141500", + "81141501", + "81141502", + "81141503", + "81141504", + "81141505", + "81141506", + "81141600", + "81141601", + "81141602", + "81141603", + "81141604", + "81141605", + "81141606", + "81141700", + "81141701", + "81141702", + "81141703", + "81141704", + "81141800", + "81141801", + "81141802", + "81141803", + "81141804", + "81141805", + "81141806", + "81141807", + "81141900", + "81141901", + "81141902", + "81150000", + "81151500", + "81151501", + "81151502", + "81151503", + "81151600", + "81151601", + "81151602", + "81151603", + "81151604", + "81151700", + "81151701", + "81151702", + "81151703", + "81151704", + "81151705", + "81151800", + "81151801", + "81151802", + "81151803", + "81151804", + "81151805", + "81151806", + "81151900", + "81151901", + "81151902", + "81151903", + "81151904", + "81160000", + "81161500", + "81161501", + "81161502", + "81161503", + "81161600", + "81161601", + "81161700", + "81161701", + "81161702", + "81161703", + "81161704", + "81161705", + "81161706", + "81161707", + "81161708", + "81161709", + "81161710", + "81161711", + "81161712", + "81161713", + "81161714", + "81161800", + "81161801", + "81162000", + "81162100", + "81162200", + "81162202", + "81170000", + "81171500", + "81171501", + "81171600", + "81171601", + "81171700", + "81171701", + "81171702", + "81171800", + "81171801", + "81171900", + "81171901", + "82000000", + "82100000", + "82101500", + "82101600", + "82101603", + "82101700", + "82101701", + "82101702", + "82101800", + "82101900", + "82101901", + "82101902", + "82101903", + "82101904", + "82101905", + "82110000", + "82111400", + "82111401", + "82111402", + "82111403", + "82111404", + "82111405", + "82111406", + "82111500", + "82111501", + "82111502", + "82111503", + "82111600", + "82111601", + "82111602", + "82111603", + "82111604", + "82111700", + "82111701", + "82111702", + "82111703", + "82111704", + "82111705", + "82111800", + "82111801", + "82111802", + "82111803", + "82111804", + "82111900", + "82111901", + "82111902", + "82111903", + "82111904", + "82112000", + "82112001", + "82112002", + "82112003", + "82112004", + "82112005", + "82112006", + "82112007", + "82112008", + "82112009", + "82112010", + "82112011", + "82112012", + "82112013", + "82112014", + "82112015", + "82112016", + "82112017", + "82112018", + "82112019", + "82112020", + "82112021", + "82112022", + "82112023", + "82112024", + "82112025", + "82112026", + "82112027", + "82112028", + "82112029", + "82112030", + "82112031", + "82112032", + "82112033", + "82112034", + "82112035", + "82112036", + "82112037", + "82112038", + "82112039", + "82112040", + "82112041", + "82112042", + "82112043", + "82112044", + "82112045", + "82112046", + "82112047", + "82112048", + "82112049", + "82112050", + "82112051", + "82112052", + "82112053", + "82112054", + "82112055", + "82112056", + "82112057", + "82112058", + "82112059", + "82112060", + "82112061", + "82112062", + "82112063", + "82112064", + "82112065", + "82112066", + "82112067", + "82120000", + "82121500", + "82121501", + "82121502", + "82121503", + "82121504", + "82121505", + "82121506", + "82121507", + "82121508", + "82121509", + "82121510", + "82121511", + "82121512", + "82121513", + "82121600", + "82121601", + "82121602", + "82121603", + "82121700", + "82121701", + "82121702", + "82121800", + "82121801", + "82121802", + "82121900", + "82121901", + "82121902", + "82121903", + "82121904", + "82121905", + "82121906", + "82121907", + "82121908", + "82130000", + "82131500", + "82131501", + "82131502", + "82131503", + "82131504", + "82131505", + "82131600", + "82131601", + "82131602", + "82131603", + "82131604", + "82140000", + "82141500", + "82141501", + "82141502", + "82141503", + "82141504", + "82141505", + "82141506", + "82141507", + "82141600", + "82141601", + "82141602", + "82150000", + "82151500", + "82151501", + "82151502", + "82151503", + "82151504", + "82151505", + "82151506", + "82151507", + "82151508", + "82151509", + "82151510", + "82151511", + "82151512", + "82151700", + "82151701", + "82151702", + "82151703", + "82151704", + "82151705", + "82151706", + "82160000", + "83000000", + "83100000", + "83101500", + "83101501", + "83101502", + "83101503", + "83101504", + "83101505", + "83101506", + "83101507", + "83101508", + "83101509", + "83101510", + "83101600", + "83101601", + "83101602", + "83101603", + "83101604", + "83101605", + "83101606", + "83101800", + "83101801", + "83101802", + "83101803", + "83101804", + "83101805", + "83101806", + "83101807", + "83101808", + "83101900", + "83101901", + "83101902", + "83101903", + "83110000", + "83111500", + "83111501", + "83111502", + "83111503", + "83111504", + "83111505", + "83111506", + "83111507", + "83111508", + "83111510", + "83111511", + "83111600", + "83111601", + "83111602", + "83111603", + "83111604", + "83111605", + "83111606", + "83111700", + "83111701", + "83111702", + "83111703", + "83111800", + "83111801", + "83111802", + "83111803", + "83111804", + "83111900", + "83111901", + "83111902", + "83111903", + "83111904", + "83111905", + "83112200", + "83112201", + "83112202", + "83112203", + "83112204", + "83112205", + "83112206", + "83112300", + "83112301", + "83112302", + "83112303", + "83112304", + "83112400", + "83112401", + "83112402", + "83112403", + "83112404", + "83112405", + "83112406", + "83112500", + "83112501", + "83112502", + "83112503", + "83112504", + "83112505", + "83112506", + "83112600", + "83112601", + "83112602", + "83112603", + "83112604", + "83112605", + "83112606", + "83120000", + "83121500", + "83121501", + "83121502", + "83121503", + "83121504", + "83121600", + "83121601", + "83121602", + "83121603", + "83121604", + "83121605", + "83121606", + "83121700", + "83121701", + "83121702", + "83121703", + "83121704", + "84000000", + "84100000", + "84101500", + "84101501", + "84101502", + "84101503", + "84101600", + "84101601", + "84101602", + "84101603", + "84101604", + "84101700", + "84101701", + "84101702", + "84101703", + "84101704", + "84101705", + "84110000", + "84111500", + "84111501", + "84111502", + "84111503", + "84111504", + "84111505", + "84111506", + "84111507", + "84111508", + "84111600", + "84111601", + "84111602", + "84111603", + "84111700", + "84111701", + "84111702", + "84111703", + "84111800", + "84111801", + "84111802", + "84120000", + "84121500", + "84121501", + "84121502", + "84121503", + "84121504", + "84121600", + "84121601", + "84121602", + "84121603", + "84121604", + "84121605", + "84121606", + "84121607", + "84121608", + "84121700", + "84121701", + "84121702", + "84121703", + "84121704", + "84121705", + "84121706", + "84121800", + "84121801", + "84121802", + "84121803", + "84121804", + "84121805", + "84121806", + "84121900", + "84121901", + "84121902", + "84121903", + "84122000", + "84122001", + "84130000", + "84131500", + "84131501", + "84131502", + "84131503", + "84131504", + "84131505", + "84131506", + "84131507", + "84131508", + "84131509", + "84131510", + "84131511", + "84131512", + "84131513", + "84131514", + "84131515", + "84131516", + "84131517", + "84131518", + "84131519", + "84131600", + "84131601", + "84131602", + "84131603", + "84131604", + "84131605", + "84131606", + "84131607", + "84131608", + "84131609", + "84131610", + "84131611", + "84131613", + "84131700", + "84131701", + "84131702", + "84131800", + "84131801", + "84131802", + "84140000", + "84141500", + "84141501", + "84141502", + "84141503", + "84141600", + "84141601", + "84141602", + "84141700", + "84141701", + "84141702", + "85000000", + "85100000", + "85101500", + "85101501", + "85101502", + "85101503", + "85101504", + "85101505", + "85101506", + "85101508", + "85101509", + "85101600", + "85101700", + "85101701", + "85101702", + "85101703", + "85101705", + "85101707", + "85110000", + "85111500", + "85111501", + "85111502", + "85111503", + "85111504", + "85111505", + "85111506", + "85111507", + "85111508", + "85111509", + "85111510", + "85111511", + "85111512", + "85111513", + "85111514", + "85111600", + "85111601", + "85111602", + "85111603", + "85111604", + "85111605", + "85111606", + "85111607", + "85111608", + "85111609", + "85111610", + "85111611", + "85111612", + "85111613", + "85111614", + "85111615", + "85111616", + "85111617", + "85111700", + "85111701", + "85111702", + "85111703", + "85111704", + "85120000", + "85121500", + "85121501", + "85121502", + "85121503", + "85121504", + "85121600", + "85121608", + "85121613", + "85121700", + "85121800", + "85121801", + "85121802", + "85121803", + "85121804", + "85121805", + "85121806", + "85121807", + "85121808", + "85121809", + "85121810", + "85121811", + "85121900", + "85121901", + "85121902", + "85122000", + "85122001", + "85122002", + "85122003", + "85122004", + "85122005", + "85122100", + "85122101", + "85122102", + "85122103", + "85122109", + "85122200", + "85122201", + "85130000", + "85131500", + "85131600", + "85131700", + "85140000", + "85141500", + "85141600", + "85141601", + "85141602", + "85141700", + "85150000", + "85151500", + "85151501", + "85151502", + "85151503", + "85151600", + "85151601", + "85151604", + "85151606", + "85151700", + "85151701", + "85151702", + "85151703", + "85151704", + "85151705", + "85160000", + "85161500", + "85161501", + "85161502", + "85161503", + "85161504", + "85161505", + "85170000", + "85171500", + "85171501", + "85171600", + "85171601", + "85210000", + "85217100", + "85260000", + "85261600", + "85270000", + "85380000", + "85383300", + "85400000", + "85470000", + "85472000", + "85472700", + "85472742", + "85700000", + "85760000", + "85765500", + "85765508", + "86000000", + "86100000", + "86101400", + "86101401", + "86101402", + "86101403", + "86101404", + "86101405", + "86101406", + "86101407", + "86101408", + "86101409", + "86101410", + "86101411", + "86101412", + "86101413", + "86101414", + "86101415", + "86101416", + "86101417", + "86101418", + "86101419", + "86101420", + "86101500", + "86101501", + "86101502", + "86101503", + "86101504", + "86101505", + "86101506", + "86101507", + "86101508", + "86101509", + "86101600", + "86101601", + "86101602", + "86101603", + "86101604", + "86101605", + "86101606", + "86101607", + "86101608", + "86101609", + "86101610", + "86101700", + "86101701", + "86101702", + "86101703", + "86101704", + "86101705", + "86101706", + "86101708", + "86101709", + "86101710", + "86101711", + "86101712", + "86101713", + "86101714", + "86101715", + "86101716", + "86101718", + "86101719", + "86101800", + "86101802", + "86101803", + "86101806", + "86101810", + "86110000", + "86111500", + "86111501", + "86111502", + "86111503", + "86111504", + "86111505", + "86111600", + "86111601", + "86111602", + "86111603", + "86111604", + "86111700", + "86111701", + "86111702", + "86111800", + "86111801", + "86111802", + "86120000", + "86121500", + "86121600", + "86121601", + "86121602", + "86121700", + "86121701", + "86121702", + "86121800", + "86121802", + "86121803", + "86121804", + "86130000", + "86131500", + "86131501", + "86131502", + "86131503", + "86131504", + "86131600", + "86131601", + "86131602", + "86131603", + "86131700", + "86131701", + "86131800", + "86131803", + "86131900", + "86132000", + "86132001", + "86132100", + "86132101", + "86132102", + "86132200", + "86132201", + "86140000", + "86141500", + "86141501", + "86141600", + "86141700", + "86141702", + "86141703", + "86141704", + "90000000", + "90100000", + "90101500", + "90101501", + "90101502", + "90101503", + "90101504", + "90101600", + "90101601", + "90101602", + "90101603", + "90101604", + "90101605", + "90101700", + "90101701", + "90101800", + "90101801", + "90101802", + "90101900", + "90101901", + "90101902", + "90110000", + "90111500", + "90111501", + "90111502", + "90111503", + "90111504", + "90111600", + "90111601", + "90111602", + "90111603", + "90111604", + "90111700", + "90111701", + "90111702", + "90111703", + "90111800", + "90111801", + "90111802", + "90111803", + "90111900", + "90111901", + "90111902", + "90120000", + "90121500", + "90121502", + "90121600", + "90121601", + "90121602", + "90121603", + "90121700", + "90121800", + "90121801", + "90130000", + "90140000", + "90150000", + "91000000", + "91100000", + "91101500", + "91101501", + "91110000", + "91111500", + "91111502", + "91111600", + "91111700", + "91111800", + "91111900", + "92000000", + "92100000", + "92101500", + "92101501", + "92101502", + "92101503", + "92101504", + "92101505", + "92101600", + "92101601", + "92101602", + "92101603", + "92101604", + "92101700", + "92101701", + "92101702", + "92101703", + "92101704", + "92101800", + "92101900", + "92101901", + "92101902", + "92101903", + "92101904", + "92110000", + "92111500", + "92111501", + "92111502", + "92111503", + "92111504", + "92111505", + "92111506", + "92111507", + "92111600", + "92111601", + "92111602", + "92111603", + "92111604", + "92111605", + "92111606", + "92111607", + "92111608", + "92111609", + "92111610", + "92111611", + "92111612", + "92111613", + "92111614", + "92111615", + "92111616", + "92111700", + "92111800", + "92111900", + "92112000", + "92112100", + "92112200", + "92112300", + "92112400", + "92120000", + "92121500", + "92121502", + "92121503", + "92121504", + "92121600", + "92121601", + "92121602", + "92121603", + "92121604", + "92121700", + "92121701", + "92121702", + "92121703", + "92121708", + "92121709", + "92121710", + "92121800", + "92121802", + "93000000", + "93100000", + "93101500", + "93101504", + "93101600", + "93101601", + "93101602", + "93101603", + "93101604", + "93101605", + "93101607", + "93101608", + "93101700", + "93101701", + "93101702", + "93101703", + "93101704", + "93101705", + "93101706", + "93101707", + "93110000", + "93111500", + "93111501", + "93111502", + "93111503", + "93111504", + "93111505", + "93111506", + "93111507", + "93111600", + "93111601", + "93111602", + "93111603", + "93111604", + "93111605", + "93111606", + "93111607", + "93111608", + "93120000", + "93121500", + "93121501", + "93121502", + "93121503", + "93121504", + "93121505", + "93121506", + "93121507", + "93121508", + "93121509", + "93121600", + "93121601", + "93121604", + "93121605", + "93121606", + "93121607", + "93121608", + "93121609", + "93121610", + "93121612", + "93121613", + "93121614", + "93121615", + "93121700", + "93121701", + "93121703", + "93121704", + "93121706", + "93121707", + "93121708", + "93121709", + "93121710", + "93130000", + "93131500", + "93131501", + "93131502", + "93131503", + "93131504", + "93131505", + "93131506", + "93131507", + "93131600", + "93131601", + "93131602", + "93131603", + "93131609", + "93131610", + "93131611", + "93131700", + "93131702", + "93131703", + "93131704", + "93131705", + "93131800", + "93131801", + "93131802", + "93131803", + "93140000", + "93141500", + "93141501", + "93141502", + "93141503", + "93141506", + "93141507", + "93141508", + "93141509", + "93141510", + "93141511", + "93141513", + "93141600", + "93141601", + "93141602", + "93141603", + "93141604", + "93141605", + "93141608", + "93141609", + "93141610", + "93141612", + "93141700", + "93141701", + "93141702", + "93141706", + "93141707", + "93141709", + "93141710", + "93141711", + "93141712", + "93141713", + "93141715", + "93141800", + "93141801", + "93141802", + "93141803", + "93141804", + "93141805", + "93141806", + "93141807", + "93141808", + "93141810", + "93141811", + "93141812", + "93141813", + "93141814", + "93141900", + "93141902", + "93141905", + "93141906", + "93141907", + "93141908", + "93141909", + "93142000", + "93142001", + "93142002", + "93142003", + "93142004", + "93142005", + "93142006", + "93142007", + "93142008", + "93142009", + "93142100", + "93142101", + "93142102", + "93142103", + "93142104", + "93150000", + "93151500", + "93151501", + "93151502", + "93151503", + "93151504", + "93151505", + "93151506", + "93151507", + "93151508", + "93151509", + "93151510", + "93151511", + "93151512", + "93151513", + "93151514", + "93151515", + "93151516", + "93151517", + "93151518", + "93151519", + "93151600", + "93151601", + "93151602", + "93151603", + "93151605", + "93151606", + "93151607", + "93151608", + "93151610", + "93151611", + "93151700", + "93160000", + "93161500", + "93161501", + "93161502", + "93161503", + "93161504", + "93161600", + "93161601", + "93161602", + "93161603", + "93161604", + "93161605", + "93161606", + "93161607", + "93161608", + "93161609", + "93161700", + "93161701", + "93161702", + "93161703", + "93161704", + "93161800", + "93161801", + "93161802", + "93161804", + "93161805", + "93161808", + "93170000", + "93171500", + "93171501", + "93171502", + "93171503", + "93171504", + "93171600", + "93171601", + "93171602", + "93171603", + "93171604", + "93171700", + "93171800", + "93171801", + "93171802", + "93171803", + "94000000", + "94100000", + "94110000", + "94120000", + "94130000", + "94131500", + "94131501", + "94131600", + "94131601", + "94131602", + "94131603", + "94131604", + "94131605", + "94131700", + "94131701", + "94131702", + "94131703", + "94131704", + "94131800", + "94131801", + "94131802", + "94131803", + "94131804", + "94131805", + "94131900", + "94131901", + "94131902", + "94131903", + "94132000", + "94132001", + "94132004", + "95000000", + "95100000", + "95101500", + "95101600", + "95101700", + "95101707", + "95101800", + "95101900", + "95110000", + "95111500", + "95111503", + "95111504", + "95111600", + "95111609", + "95111610", + "95111611", + "95111612", + "95111615", + "95120000", + "95121500", + "95121600", + "95121601", + "95121602", + "95121603", + "95121604", + "95121605", + "95121606", + "95121607", + "95121608", + "95121611", + "95121612", + "95121613", + "95121614", + "95121620", + "95121621", + "95121624", + "95121625", + "95121626", + "95121627", + "95121628", + "95121629", + "95121630", + "95121631", + "95121632", + "95121634", + "95121635", + "95121636", + "95121639", + "95121640", + "95121641", + "95121642", + "95121643", + "95121644", + "95121645", + "95121647", + "95121700", + "95121701", + "95121702", + "95121703", + "95121704", + "95121705", + "95121706", + "95121707", + "95121708", + "95121709", + "95121710", + "95121711", + "95121712", + "95121713", + "95121714", + "95121715", + "95121800", + "95121801", + "95121802", + "95121803", + "95121804", + "95121805", + "95121806", + "95121807", + "95121808", + "95121809", + "95121810", + "95121811", + "95121812", + "95121900", + "95121901", + "95121902", + "95121903", + "95121904", + "95121905", + "95121906", + "95121907", + "95121908", + "95121909", + "95121910", + "95121911", + "95121913", + "95122000", + "95122001", + "95122002", + "95122003", + "95122004", + "95122005", + "95122006", + "95122007", + "95122008", + "95122100", + "95122101", + "95122102", + "95122103", + "95122104", + "95122105", + "95122106", + "95122300", + "95122400", + "95122500", + "95122600", + "95122700", + "95130000", + "95131500", + "95131600", + "95131601", + "95131602", + "95131603", + "95131604", + "95131605", + "95131606", + "95131700", + "95140000", + "95141500", + "95141501", + "95141502", + "95141600", + "95141601", + "95141602", + "95141603", + "95141604", + "95141605", + "95141606", + "95141700", + "95141701", + "95141702", + "95141703", + "95141704", + "95141705", + "95141706", + "95141707", + "95141708", + "95141709", + "95141710", + "95141711", + "95141713", + "95141714", + "95141715", + "95141800", + "95141801", + "95141802", + "95141803", + "95141804", + "95141900", + "95141901", + "95141902", + "95141903", + "95141904", + } +) + +SYNTHESIZED_ANCESTORS: frozenset[str] = frozenset( + { + "57110000", + "57220000", + "57330000", + "57440000", + "57550000", + "57660000", + "57770000", + "57880000", + } +) diff --git a/paxman/capabilities/UNSPSC/rules/undp_unspsc_codeset_ed2026.py b/paxman/capabilities/UNSPSC/rules/undp_unspsc_codeset_ed2026.py new file mode 100644 index 00000000..742bb82e --- /dev/null +++ b/paxman/capabilities/UNSPSC/rules/undp_unspsc_codeset_ed2026.py @@ -0,0 +1,70 @@ +"""UNDP UNSPSC codeset rule: stem membership plus ancestor liveness. + +The stem must exist in the pinned snapshot AND every pair-prefix +ancestor (``SS000000``, ``SSFF0000``, ``SSFFCC00``) must resolve against +the live rows plus the flagged synthesized ancestors. Hierarchy truth +lives in the snapshot, not the type: ``43001503``-style mid-zero +anomalies fail here even when padding-consistent, and a synthesized +ancestor alone (e.g. ``57110000``) is INVALID — synthesis serves the +ancestor walk only, never stem membership. +""" + +from __future__ import annotations + +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.capabilities.UNSPSC.rules.data.unspsc_codeset import ( + CODESET_VERSION, + LIVE_STEMS, + SYNTHESIZED_ANCESTORS, +) +from paxman.core.contract import Contract +from paxman.core.domain import Provenance, Rule, RuleStrategy + +PUBLICATION = Provenance( + authority="United Nations Development Programme", + specification_name="UNSPSC Codeset (UNGM live export)", + kind="registry", + reference_url="https://www.ungm.org/Public/UNSPSC", + version=CODESET_VERSION, + lifecycle="active", + publication_year=2026, +) + + +def _ancestors(stem: str) -> tuple[str, str, str]: + """Pair-prefix ancestors: segment, family, class rows.""" + return (stem[:2] + "000000", stem[:4] + "0000", stem[:6] + "00") + + +def _is_member(notation: UNSPSCNotation) -> bool: + """Stem is a live row and all pair-prefix ancestors resolve. + + Synthesized ancestors serve the ancestor walk ONLY: a synthesized + code alone is not a live row and resolves INVALID. + """ + stem = notation.digits + if len(stem) != 8 or not stem.isascii() or not stem.isdigit(): + return False + if stem not in LIVE_STEMS: + return False + live = LIVE_STEMS | SYNTHESIZED_ANCESTORS + return all(ancestor in live for ancestor in _ancestors(stem)) + + +class Section3CodesetMembership(Rule[UNSPSCNotation]): + """UNDP codeset Section 3 — stem membership with live ancestors.""" + + name = "Section 3-codeset-membership" + strategy = RuleStrategy.LOOKUP_TABLE + provenance = PUBLICATION + citation = "Codeset membership (stem + SS000000/SSFF0000/SSFFCC00 live)" + target_semantics = frozenset({"unspsc_recognition"}) + requires_features = frozenset() + + def matches(self, notation: UNSPSCNotation, contract: Contract) -> bool: + """Check whether the stem and its ancestors are live rows.""" + return _is_member(notation) + + def normalize(self, notation: UNSPSCNotation, contract: Contract) -> str: + """Normalize to the 8-digit compact stem.""" + return notation.digits diff --git a/paxman/capabilities/UNSPSC/rules/undp_unspsc_structure_ed2025.py b/paxman/capabilities/UNSPSC/rules/undp_unspsc_structure_ed2025.py new file mode 100644 index 00000000..3b8de89c --- /dev/null +++ b/paxman/capabilities/UNSPSC/rules/undp_unspsc_structure_ed2025.py @@ -0,0 +1,97 @@ +"""UNGM UNSPSC code-structure rules: hierarchy lanes and level padding. + +Both rule classes validate the positional shape only — no authority table +is consulted. Codeset membership (including ancestor liveness) is owned by +``undp_unspsc_codeset_ed2026.Section3CodesetMembership``. +""" + +from __future__ import annotations + +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.core.contract import Contract +from paxman.core.domain import Provenance, Rule, RuleStrategy + +PUBLICATION = Provenance( + authority="United Nations Development Programme", + specification_name="UNSPSC Code Structure (UNGM Help Center)", + kind="specification", + reference_url="https://help.ungm.org/hc/en-us/articles/360012816160-What-are-UNSPSC-codes-", + version="2025-07-08", + lifecycle="active", + publication_year=2025, +) + + +def _is_hierarchy_shape(notation: UNSPSCNotation) -> bool: + """8-digit ASCII stem on a 6/8/10 spelled lane with a coherent suffix.""" + if len(notation.digits) != 8: + return False + if not notation.digits.isascii() or not notation.digits.isdigit(): + return False + if notation.native_length not in (6, 8, 10): + return False + if notation.native_length == 10: + return ( + len(notation.function) == 2 + and notation.function.isascii() + and notation.function.isdigit() + ) + return notation.function == "" + + +def _is_padding_consistent(notation: UNSPSCNotation) -> bool: + """Trailing-00 pairs form a well-formed lattice (no mid-zero breaks). + + Once a ``00`` pair appears, every following pair must also be ``00``: + ``43000000``/``43210000``/``43211500`` are well-formed, ``43001503`` + and ``00101501`` are not. (Unissued but well-formed stems such as + ``43111503`` pass here and fail codeset membership instead.) + """ + pairs = [notation.digits[i : i + 2] for i in (0, 2, 4, 6)] + seen_zero = False + for pair in pairs: + if pair == "00": + seen_zero = True + elif seen_zero: + return False + return True + + +class Section1HierarchyStructure(Rule[UNSPSCNotation]): + """UNGM structure Section 1 — hierarchy lanes (6/8/10, ASCII digits).""" + + name = "Section 1-hierarchy-structure" + strategy = RuleStrategy.PARSER + provenance = PUBLICATION + citation = "Four-level hierarchy, purely numeric codes" + target_semantics = frozenset({"unspsc_recognition"}) + requires_features = frozenset() + + def matches(self, notation: UNSPSCNotation, contract: Contract) -> bool: + """Check whether the notation is on a valid hierarchy lane.""" + return _is_hierarchy_shape(notation) + + def normalize(self, notation: UNSPSCNotation, contract: Contract) -> str: + """Normalize to the 8-digit compact stem.""" + return notation.digits + + +class Section2LevelPadding(Rule[UNSPSCNotation]): + """UNGM structure Section 2 — 00-pair lattice consistency.""" + + name = "Section 2-level-padding" + strategy = RuleStrategy.PARSER + provenance = PUBLICATION + citation = "Level padding (segment 000000, family 0000, class 00)" + target_semantics = frozenset({"unspsc_recognition"}) + requires_features = frozenset() + + def matches(self, notation: UNSPSCNotation, contract: Contract) -> bool: + """Check whether the padding lattice is well-formed.""" + if not _is_hierarchy_shape(notation): + return False + return _is_padding_consistent(notation) + + def normalize(self, notation: UNSPSCNotation, contract: Contract) -> str: + """Normalize to the 8-digit compact stem.""" + return notation.digits diff --git a/paxman/capabilities/UNSPSC/rules/unece_bfi_ed2005.py b/paxman/capabilities/UNSPSC/rules/unece_bfi_ed2005.py new file mode 100644 index 00000000..e329b207 --- /dev/null +++ b/paxman/capabilities/UNSPSC/rules/unece_bfi_ed2005.py @@ -0,0 +1,58 @@ +"""UNECE business-function rule: the 10-digit suffix lane, informative only. + +The rule speaks ONLY to the 10-digit lane: any ``00``–``99`` suffix value +passes, and shorter lanes abstain (False) so no UNECE provenance attaches +to suffix-less inputs and a pinned-Section-4 contract cannot validate +garbage (GTIN/ISNI full-conjunction precedent). Gating is engine-side via +``requires_features``: with ``include_business_function=False`` the rule +drops and the stem still validates via Sections 1–3, so the verdict stays +SUCCESS with the suffix candidate removed (ISBN corroborating-rule +precedent). Residual: ``year`` filtering that drops the 2025/2026 rules +leaves this 2005 PARSER standing alone on 10-digit shape (ADR-0012 +vacuity) — disclosed, not closed. +""" + +from __future__ import annotations + +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.core.contract import Contract +from paxman.core.domain import Provenance, Rule, RuleStrategy + +PUBLICATION = Provenance( + authority="United Nations Economic Commission for Europe", + specification_name="Classification Guidelines (Business Function Identifiers)", + kind="specification", + reference_url=( + "https://unece.org/fileadmin/DAM/trade/agr/meetings/ge.11/2005/2005_i04_UNSPSC.pdf" + ), + version="v2.04", + lifecycle="active", + publication_year=2005, +) + + +def _is_suffix_coherent(notation: UNSPSCNotation) -> bool: + """10-digit lane carries a well-formed 2-digit suffix; other lanes abstain.""" + if notation.native_length != 10: + return False + function = notation.function + return len(function) == 2 and function.isascii() and function.isdigit() + + +class Section4BusinessFunctionSuffix(Rule[UNSPSCNotation]): + """UNECE guidelines Section 4 — business-function suffix (gated).""" + + name = "Section 4-business-function-suffix" + strategy = RuleStrategy.PARSER + provenance = PUBLICATION + citation = "Business Function Identifiers (optional 2-digit suffix)" + target_semantics = frozenset({"unspsc_recognition"}) + requires_features = frozenset({"include_business_function"}) + + def matches(self, notation: UNSPSCNotation, contract: Contract) -> bool: + """Check whether the suffix lane is coherent (any value passes).""" + return _is_suffix_coherent(notation) + + def normalize(self, notation: UNSPSCNotation, contract: Contract) -> str: + """Normalize to the 8-digit compact stem.""" + return notation.digits diff --git a/paxman/capabilities/__init__.py b/paxman/capabilities/__init__.py index 6ac2ca0f..09d55390 100644 --- a/paxman/capabilities/__init__.py +++ b/paxman/capabilities/__init__.py @@ -38,6 +38,7 @@ "Phone", "SIUnit", "Timezone", + "UNSPSC", "URL", "UUID", "UtcOffset", @@ -75,6 +76,7 @@ "Phone": ("paxman.capabilities.Phone.capability", "PhoneCapability"), "SIUnit": ("paxman.capabilities.SIUnit.capability", "SIUnitCapability"), "Timezone": ("paxman.capabilities.Timezone.capability", "TimezoneCapability"), + "UNSPSC": ("paxman.capabilities.UNSPSC.capability", "UNSPSCCapability"), "URL": ("paxman.capabilities.URL.capability", "URLCapability"), "UUID": ("paxman.capabilities.UUID.capability", "UUIDCapability"), "UtcOffset": ("paxman.capabilities.UtcOffset.capability", "UtcOffsetCapability"), @@ -114,6 +116,7 @@ from paxman.capabilities.Phone.capability import PhoneCapability as Phone from paxman.capabilities.SIUnit.capability import SIUnitCapability as SIUnit from paxman.capabilities.Timezone.capability import TimezoneCapability as Timezone + from paxman.capabilities.UNSPSC.capability import UNSPSCCapability as UNSPSC from paxman.capabilities.URL.capability import URLCapability as URL from paxman.capabilities.UtcOffset.capability import ( UtcOffsetCapability as UtcOffset, diff --git a/paxman/cli.py b/paxman/cli.py index 7c6e7544..cf3f6800 100644 --- a/paxman/cli.py +++ b/paxman/cli.py @@ -238,6 +238,10 @@ def _create_contract( from paxman.capabilities import Timezone return Timezone.create_contract(suppress_common_words=suppress_common_words) + if normalized == "unspsc": + from paxman.capabilities import UNSPSC + + return UNSPSC.create_contract(suppress_common_words=suppress_common_words) if normalized == "url": from paxman.capabilities import URL diff --git a/paxman/shared_data/unspsc_snapshot.json b/paxman/shared_data/unspsc_snapshot.json new file mode 100644 index 00000000..e57a0480 --- /dev/null +++ b/paxman/shared_data/unspsc_snapshot.json @@ -0,0 +1,13502 @@ +{ + "source": "UNGM Public/UNSPSC Excel export (https://www.ungm.org/Public/UNSPSC/Excel)", + "fetched": "2026-09-30", + "codeset_version": "UNGM live export 2026-09-30 (13,482 stems)", + "full_codeset_note": "UNDP v26.0801 (2023-08-14, 158,448 items) remains the reference release; this snapshot holds the live-directory subset until the full XLSX can be ingested.", + "stem_count": 13482, + "stems": [ + "10000000", + "10100000", + "10101500", + "10101501", + "10101502", + "10101506", + "10101507", + "10101508", + "10101509", + "10101511", + "10101512", + "10101513", + "10101516", + "10101517", + "10101518", + "10101600", + "10101601", + "10101602", + "10101603", + "10101604", + "10101605", + "10101607", + "10101700", + "10101701", + "10101800", + "10101801", + "10101900", + "10101903", + "10101904", + "10102000", + "10102100", + "10102101", + "10110000", + "10120000", + "10121500", + "10121501", + "10121600", + "10121601", + "10121700", + "10121701", + "10121800", + "10121801", + "10122100", + "10130000", + "10131500", + "10131506", + "10131600", + "10131601", + "10131602", + "10131605", + "10131700", + "10131701", + "10140000", + "10141500", + "10141501", + "10150000", + "10151500", + "10151503", + "10151504", + "10151505", + "10151506", + "10151507", + "10151508", + "10151509", + "10151510", + "10151511", + "10151512", + "10151513", + "10151514", + "10151515", + "10151517", + "10151518", + "10151520", + "10151521", + "10151522", + "10151523", + "10151524", + "10151525", + "10151526", + "10151529", + "10151531", + "10151532", + "10151533", + "10151534", + "10151535", + "10151536", + "10151537", + "10151538", + "10151539", + "10151540", + "10151541", + "10151600", + "10151601", + "10151602", + "10151603", + "10151604", + "10151605", + "10151606", + "10151607", + "10151608", + "10151609", + "10151610", + "10151611", + "10151612", + "10151613", + "10151614", + "10151616", + "10151700", + "10151800", + "10151900", + "10151904", + "10152000", + "10152001", + "10152003", + "10152008", + "10152048", + "10152055", + "10152056", + "10152057", + "10152100", + "10152200", + "10152201", + "10152300", + "10152301", + "10152302", + "10152400", + "10152401", + "10152402", + "10152403", + "10152404", + "10152405", + "10160000", + "10161500", + "10170000", + "10171500", + "10171501", + "10171502", + "10171504", + "10171506", + "10171507", + "10171600", + "10171601", + "10171602", + "10171603", + "10171604", + "10171605", + "10171611", + "10171612", + "10171613", + "10171614", + "10171615", + "10171616", + "10171700", + "10171702", + "10171703", + "10171800", + "10190000", + "10191500", + "10191506", + "10191507", + "10191508", + "10191509", + "10191510", + "10191511", + "10191512", + "10191513", + "10191514", + "10191515", + "10191516", + "10191517", + "10191518", + "10191519", + "10191520", + "10191700", + "10191701", + "10191703", + "10191704", + "10191705", + "10191706", + "10191707", + "10191708", + "10200000", + "10210000", + "10220000", + "11000000", + "11100000", + "11101500", + "11101501", + "11101506", + "11101600", + "11101700", + "11101800", + "11110000", + "11111500", + "11111501", + "11111600", + "11111601", + "11111602", + "11111603", + "11111604", + "11111605", + "11111606", + "11111607", + "11111608", + "11111609", + "11111610", + "11111611", + "11111612", + "11111613", + "11111700", + "11111701", + "11111800", + "11111801", + "11111802", + "11111803", + "11111804", + "11111805", + "11111806", + "11111807", + "11111808", + "11111809", + "11111810", + "11111811", + "11111812", + "11120000", + "11121500", + "11121502", + "11121600", + "11121603", + "11121604", + "11121605", + "11121606", + "11121607", + "11121608", + "11121610", + "11121614", + "11121616", + "11121621", + "11121622", + "11121623", + "11121624", + "11121625", + "11121700", + "11121800", + "11121900", + "11122000", + "11122001", + "11122002", + "11122003", + "11122004", + "11122005", + "11122006", + "11130000", + "11131500", + "11131501", + "11131600", + "11131602", + "11131607", + "11131609", + "11131610", + "11140000", + "11141600", + "11141700", + "11150000", + "11151500", + "11151600", + "11151700", + "11160000", + "11161500", + "11161600", + "11161700", + "11161800", + "11162000", + "11162100", + "11162101", + "11162102", + "11162104", + "11162105", + "11162107", + "11162108", + "11162109", + "11162110", + "11162111", + "11162112", + "11162113", + "11162114", + "11162115", + "11162116", + "11162117", + "11162118", + "11162119", + "11162120", + "11162121", + "11162122", + "11162123", + "11162124", + "11162125", + "11162126", + "11162127", + "11162128", + "11162129", + "11162130", + "11162131", + "11162132", + "11162133", + "11162200", + "11162300", + "11162400", + "11170000", + "11171500", + "11171501", + "11171600", + "11171601", + "11171602", + "11171603", + "11171700", + "11171701", + "11171702", + "11171800", + "11171801", + "11171900", + "11171901", + "11172000", + "11172001", + "11172100", + "11172101", + "11172200", + "11172300", + "11180000", + "11190000", + "12000000", + "12130000", + "12131500", + "12131501", + "12131502", + "12131503", + "12131504", + "12131505", + "12131506", + "12131507", + "12131508", + "12131509", + "12131600", + "12131700", + "12131702", + "12131703", + "12131704", + "12131705", + "12131706", + "12131707", + "12131708", + "12131709", + "12131800", + "12140000", + "12141500", + "12141600", + "12141700", + "12141800", + "12141900", + "12142000", + "12142100", + "12142200", + "12142201", + "12142202", + "12142203", + "12142204", + "12142205", + "12142206", + "12142207", + "12142208", + "12160000", + "12161500", + "12161700", + "12161800", + "12161804", + "12161900", + "12162000", + "12162100", + "12162200", + "12162300", + "12162700", + "12162800", + "12163100", + "12163200", + "12163600", + "12164100", + "12164300", + "12164400", + "12164500", + "12164900", + "12165100", + "12170000", + "12171500", + "12171600", + "12171700", + "12180000", + "12181500", + "12181600", + "12190000", + "12191500", + "12350000", + "12352000", + "12352100", + "12352200", + "12352300", + "12352324", + "12352400", + "12352500", + "13000000", + "13100000", + "13101500", + "13101600", + "13101700", + "13101900", + "13102000", + "13110000", + "13111000", + "13111100", + "13111200", + "13111201", + "13111202", + "13111203", + "13111204", + "13111205", + "13111206", + "13111207", + "13111208", + "13111209", + "13111210", + "13111211", + "13111212", + "13111213", + "13111214", + "13111215", + "13111216", + "13111217", + "13111218", + "13111219", + "13111220", + "13111300", + "14000000", + "14100000", + "14101500", + "14101501", + "14110000", + "14111500", + "14111501", + "14111502", + "14111503", + "14111504", + "14111505", + "14111506", + "14111507", + "14111508", + "14111509", + "14111510", + "14111511", + "14111512", + "14111513", + "14111514", + "14111515", + "14111516", + "14111518", + "14111519", + "14111520", + "14111523", + "14111524", + "14111525", + "14111526", + "14111527", + "14111528", + "14111529", + "14111530", + "14111531", + "14111532", + "14111533", + "14111534", + "14111535", + "14111536", + "14111537", + "14111538", + "14111539", + "14111540", + "14111541", + "14111542", + "14111543", + "14111544", + "14111545", + "14111546", + "14111600", + "14111601", + "14111604", + "14111605", + "14111606", + "14111607", + "14111608", + "14111609", + "14111610", + "14111611", + "14111613", + "14111614", + "14111615", + "14111616", + "14111617", + "14111618", + "14111700", + "14111701", + "14111702", + "14111703", + "14111704", + "14111705", + "14111706", + "14111800", + "14111801", + "14111802", + "14111803", + "14111804", + "14111805", + "14111806", + "14111807", + "14111808", + "14111809", + "14111810", + "14111811", + "14111812", + "14111813", + "14111814", + "14111815", + "14111816", + "14111817", + "14111818", + "14111819", + "14111820", + "14111821", + "14111822", + "14111823", + "14111824", + "14111825", + "14111826", + "14111827", + "14111828", + "14111829", + "14111830", + "14111831", + "14120000", + "14121500", + "14121501", + "14121502", + "14121503", + "14121504", + "14121505", + "14121506", + "14121507", + "14121508", + "14121509", + "14121510", + "14121600", + "14121601", + "14121602", + "14121603", + "14121604", + "14121605", + "14121700", + "14121701", + "14121702", + "14121703", + "14121800", + "14121801", + "14121802", + "14121803", + "14121804", + "14121805", + "14121806", + "14121807", + "14121808", + "14121809", + "14121810", + "14121811", + "14121812", + "14121813", + "14121900", + "14121901", + "14121902", + "14121903", + "14121904", + "14121905", + "14122100", + "14122101", + "14122102", + "14122103", + "14122104", + "14122105", + "14122106", + "14122107", + "14122108", + "14122200", + "14122201", + "14122202", + "14122203", + "14122204", + "15000000", + "15100000", + "15101500", + "15101502", + "15101503", + "15101504", + "15101505", + "15101506", + "15101507", + "15101508", + "15101509", + "15101510", + "15101513", + "15101600", + "15101605", + "15101609", + "15101615", + "15101700", + "15101800", + "15101801", + "15101802", + "15110000", + "15111500", + "15111501", + "15111502", + "15111503", + "15111504", + "15111505", + "15111506", + "15111507", + "15111508", + "15111509", + "15111510", + "15111511", + "15111700", + "15120000", + "15121500", + "15121501", + "15121504", + "15121508", + "15121800", + "15121807", + "15121900", + "15130000", + "15131500", + "15131502", + "15131503", + "15131504", + "15131505", + "15131506", + "15131600", + "15131601", + "20000000", + "20100000", + "20101500", + "20101501", + "20101502", + "20101600", + "20101700", + "20101709", + "20101800", + "20101900", + "20102000", + "20102100", + "20102200", + "20102300", + "20102301", + "20102302", + "20102303", + "20102304", + "20102305", + "20102306", + "20102307", + "20110000", + "20111500", + "20111504", + "20111505", + "20111600", + "20111700", + "20120000", + "20121400", + "20121449", + "20121600", + "20130000", + "20140000", + "21000000", + "21100000", + "21101500", + "21101501", + "21101502", + "21101503", + "21101504", + "21101505", + "21101506", + "21101507", + "21101508", + "21101509", + "21101517", + "21101600", + "21101601", + "21101700", + "21101701", + "21101703", + "21101705", + "21101708", + "21101709", + "21101800", + "21101801", + "21101802", + "21101803", + "21101804", + "21101805", + "21101806", + "21101807", + "21101808", + "21101810", + "21101900", + "21101901", + "21101903", + "21101905", + "21101906", + "21101916", + "21102000", + "21102001", + "21102002", + "21102009", + "21102100", + "21102200", + "21102300", + "21102305", + "21102400", + "21102401", + "21102500", + "21102501", + "21102502", + "21102503", + "21102600", + "21102601", + "21110000", + "21111500", + "21111501", + "21111504", + "21111600", + "22000000", + "22100000", + "22101500", + "22101501", + "22101502", + "22101504", + "22101505", + "22101507", + "22101508", + "22101509", + "22101511", + "22101513", + "22101514", + "22101516", + "22101518", + "22101519", + "22101520", + "22101521", + "22101522", + "22101523", + "22101524", + "22101525", + "22101526", + "22101527", + "22101528", + "22101529", + "22101530", + "22101531", + "22101532", + "22101533", + "22101534", + "22101535", + "22101536", + "22101537", + "22101538", + "22101539", + "22101600", + "22101632", + "22101633", + "22101700", + "22101701", + "22101702", + "22101703", + "22101704", + "22101705", + "22101709", + "22101710", + "22101711", + "22101712", + "22101713", + "22101714", + "22101715", + "22101716", + "22101717", + "22101718", + "22101719", + "22101720", + "22101721", + "22101722", + "22101723", + "22101724", + "22101800", + "22101801", + "22101802", + "22101803", + "22101804", + "22101900", + "22101901", + "22101902", + "22101904", + "22101905", + "22101906", + "22101907", + "22101908", + "22101909", + "22102000", + "22102001", + "23000000", + "23100000", + "23101500", + "23101501", + "23101502", + "23101505", + "23101506", + "23101507", + "23101508", + "23101509", + "23101510", + "23101511", + "23101512", + "23101513", + "23101514", + "23101537", + "23110000", + "23120000", + "23121500", + "23121501", + "23121506", + "23121507", + "23121600", + "23121614", + "23130000", + "23131500", + "23131501", + "23131503", + "23131600", + "23131700", + "23140000", + "23141600", + "23141601", + "23141700", + "23150000", + "23151500", + "23151600", + "23151700", + "23151800", + "23151816", + "23151817", + "23151900", + "23152000", + "23152100", + "23152200", + "23152900", + "23152901", + "23152912", + "23153000", + "23153100", + "23153145", + "23153200", + "23153400", + "23153500", + "23153600", + "23153605", + "23153700", + "23153800", + "23160000", + "23161500", + "23161501", + "23161600", + "23161700", + "23180000", + "23181500", + "23181501", + "23181502", + "23181507", + "23181514", + "23181519", + "23181522", + "23181523", + "23181600", + "23181601", + "23181700", + "23181800", + "23190000", + "23191000", + "23191001", + "23191100", + "23191101", + "23200000", + "23201000", + "23201200", + "23201201", + "23201202", + "23201203", + "23201204", + "23210000", + "23220000", + "23221000", + "23221001", + "23221100", + "23230000", + "23231000", + "23231001", + "23240000", + "23241400", + "23241401", + "23241500", + "23241600", + "23241615", + "23241700", + "23241800", + "23241900", + "23242100", + "23242200", + "23242300", + "23242400", + "23242500", + "23242600", + "23242612", + "23250000", + "23251500", + "23251501", + "23251600", + "23251700", + "23251800", + "23251900", + "23260000", + "23261500", + "23261501", + "23270000", + "23271400", + "23271401", + "23271423", + "23271500", + "23271600", + "23271603", + "23271700", + "23271712", + "23271800", + "23271812", + "23280000", + "23281500", + "23290000", + "23291500", + "23300000", + "23301500", + "24000000", + "24100000", + "24101500", + "24101501", + "24101502", + "24101503", + "24101504", + "24101505", + "24101506", + "24101507", + "24101508", + "24101509", + "24101510", + "24101511", + "24101512", + "24101513", + "24101514", + "24101515", + "24101516", + "24101517", + "24101600", + "24101601", + "24101602", + "24101603", + "24101604", + "24101605", + "24101606", + "24101608", + "24101609", + "24101610", + "24101611", + "24101612", + "24101613", + "24101615", + "24101625", + "24101626", + "24101629", + "24101630", + "24101633", + "24101643", + "24101644", + "24101655", + "24101656", + "24101658", + "24101659", + "24101661", + "24101663", + "24101675", + "24101700", + "24101706", + "24101751", + "24101800", + "24101900", + "24102000", + "24102006", + "24102100", + "24102101", + "24102102", + "24102103", + "24102104", + "24102105", + "24102106", + "24102107", + "24102108", + "24102109", + "24102200", + "24102300", + "24102400", + "24102401", + "24102402", + "24102403", + "24110000", + "24111500", + "24111501", + "24111502", + "24111503", + "24111507", + "24111508", + "24111509", + "24111510", + "24111511", + "24111512", + "24111513", + "24111514", + "24111515", + "24111800", + "24111801", + "24111802", + "24111803", + "24111804", + "24111805", + "24111806", + "24111807", + "24111808", + "24111809", + "24111810", + "24111811", + "24111812", + "24111813", + "24111814", + "24111815", + "24111816", + "24111817", + "24111825", + "24112000", + "24112003", + "24112004", + "24112005", + "24112006", + "24112007", + "24112100", + "24112101", + "24112113", + "24112200", + "24112204", + "24112209", + "24112400", + "24112401", + "24112402", + "24112412", + "24112500", + "24112501", + "24112600", + "24112603", + "24112700", + "24112701", + "24112702", + "24112800", + "24112801", + "24112802", + "24112803", + "24112805", + "24112806", + "24112807", + "24112900", + "24113000", + "24113003", + "24113100", + "24113101", + "24113102", + "24113103", + "24113104", + "24113105", + "24113106", + "24113107", + "24113108", + "24113109", + "24113110", + "24120000", + "24121500", + "24121502", + "24121511", + "24121512", + "24121513", + "24121514", + "24121800", + "24122000", + "24122002", + "24122003", + "24130000", + "24131500", + "24131501", + "24131502", + "24131503", + "24131504", + "24131505", + "24131506", + "24131513", + "24131515", + "24131516", + "24131600", + "24131601", + "24131602", + "24131603", + "24131604", + "24131605", + "24131606", + "24131607", + "24131900", + "24140000", + "24141500", + "24141501", + "24141504", + "24141506", + "24141510", + "24141521", + "24141600", + "24141700", + "25000000", + "25100000", + "25101500", + "25101501", + "25101502", + "25101503", + "25101504", + "25101505", + "25101506", + "25101507", + "25101508", + "25101509", + "25101510", + "25101600", + "25101601", + "25101602", + "25101604", + "25101609", + "25101610", + "25101611", + "25101612", + "25101613", + "25101614", + "25101615", + "25101700", + "25101702", + "25101703", + "25101704", + "25101705", + "25101706", + "25101707", + "25101708", + "25101709", + "25101710", + "25101711", + "25101712", + "25101713", + "25101714", + "25101715", + "25101716", + "25101717", + "25101718", + "25101719", + "25101800", + "25101801", + "25101802", + "25101803", + "25101804", + "25101900", + "25101901", + "25101902", + "25101903", + "25101904", + "25101905", + "25101906", + "25101907", + "25101908", + "25101909", + "25101910", + "25101911", + "25101912", + "25101913", + "25101914", + "25101915", + "25101916", + "25101917", + "25101918", + "25101919", + "25101920", + "25101921", + "25101922", + "25101923", + "25101924", + "25101925", + "25101926", + "25101927", + "25101928", + "25101929", + "25101930", + "25101931", + "25101932", + "25101933", + "25101934", + "25101935", + "25101936", + "25101937", + "25101938", + "25101939", + "25101940", + "25101941", + "25101942", + "25101943", + "25101944", + "25101945", + "25101946", + "25101947", + "25101948", + "25102000", + "25102001", + "25102002", + "25102003", + "25102100", + "25102101", + "25102102", + "25102103", + "25102104", + "25102105", + "25102106", + "25110000", + "25111500", + "25111501", + "25111502", + "25111503", + "25111504", + "25111505", + "25111506", + "25111507", + "25111508", + "25111509", + "25111510", + "25111511", + "25111512", + "25111513", + "25111514", + "25111515", + "25111516", + "25111517", + "25111518", + "25111520", + "25111524", + "25111527", + "25111528", + "25111529", + "25111532", + "25111533", + "25111600", + "25111601", + "25111602", + "25111603", + "25111700", + "25111722", + "25111724", + "25111725", + "25111726", + "25111800", + "25111801", + "25111802", + "25111803", + "25111804", + "25111805", + "25111806", + "25111807", + "25111808", + "25111809", + "25111900", + "25111901", + "25111902", + "25111903", + "25111904", + "25111905", + "25111906", + "25111907", + "25120000", + "25121500", + "25121501", + "25130000", + "25131400", + "25131401", + "25131402", + "25131403", + "25131500", + "25131504", + "25131505", + "25131506", + "25131507", + "25131508", + "25131509", + "25131510", + "25131511", + "25131512", + "25131513", + "25131600", + "25131601", + "25131602", + "25131604", + "25131700", + "25131705", + "25131707", + "25131709", + "25131800", + "25131900", + "25131902", + "25132100", + "25132101", + "25150000", + "25151700", + "25151701", + "25160000", + "25161500", + "25161505", + "25161506", + "25161507", + "25170000", + "25171500", + "25171507", + "25171600", + "25171700", + "25171702", + "25171713", + "25171900", + "25171901", + "25172000", + "25172100", + "25172200", + "25172300", + "25172400", + "25172406", + "25172500", + "25172502", + "25172503", + "25172504", + "25172505", + "25172506", + "25172509", + "25172511", + "25172512", + "25172514", + "25172600", + "25172607", + "25172614", + "25172700", + "25172709", + "25172710", + "25172711", + "25172800", + "25172804", + "25172805", + "25172900", + "25172908", + "25173000", + "25173100", + "25173107", + "25173108", + "25173110", + "25173111", + "25173112", + "25173113", + "25173114", + "25173115", + "25173116", + "25173117", + "25173118", + "25173119", + "25173120", + "25173121", + "25173122", + "25173123", + "25173124", + "25173125", + "25173126", + "25173127", + "25173128", + "25173129", + "25173130", + "25173131", + "25173132", + "25173133", + "25173134", + "25173135", + "25173300", + "25173700", + "25173800", + "25173900", + "25174000", + "25174100", + "25174200", + "25174213", + "25174400", + "25174414", + "25174600", + "25174700", + "25174800", + "25174900", + "25175000", + "25175100", + "25175101", + "25175102", + "25175103", + "25175106", + "25175200", + "25175201", + "25175202", + "25175203", + "25180000", + "25181600", + "25181601", + "25181604", + "25181605", + "25181606", + "25181610", + "25181612", + "25181614", + "25181700", + "25181701", + "25181703", + "25181708", + "25181719", + "25181720", + "25190000", + "25191500", + "25191501", + "25191502", + "25191503", + "25191504", + "25191505", + "25191506", + "25191507", + "25191508", + "25191509", + "25191510", + "25191511", + "25191512", + "25191513", + "25191514", + "25191515", + "25191516", + "25191517", + "25191518", + "25191519", + "25191520", + "25191521", + "25191522", + "25191523", + "25191524", + "25191525", + "25191526", + "25191527", + "25191528", + "25191529", + "25191530", + "25191531", + "25191532", + "25191533", + "25191534", + "25191535", + "25191536", + "25191537", + "25191538", + "25191539", + "25191540", + "25191541", + "25191542", + "25191543", + "25191544", + "25191545", + "25191546", + "25191547", + "25191548", + "25191549", + "25191550", + "25191551", + "25191552", + "25191553", + "25191554", + "25191600", + "25191700", + "25191800", + "25200000", + "25201700", + "25201701", + "25201702", + "25201800", + "25201801", + "25201900", + "25201901", + "25202100", + "25202300", + "25202301", + "25202800", + "25202801", + "25202802", + "25202803", + "25202900", + "25202901", + "25202902", + "25202903", + "25202904", + "25202905", + "25202906", + "25202907", + "25202908", + "25202909", + "25202910", + "25202911", + "26000000", + "26100000", + "26101100", + "26101200", + "26101300", + "26101400", + "26101412", + "26101500", + "26101501", + "26101502", + "26101503", + "26101504", + "26101505", + "26101506", + "26101507", + "26101508", + "26101509", + "26101511", + "26101513", + "26101515", + "26101700", + "26101720", + "26101732", + "26101736", + "26101740", + "26101764", + "26101900", + "26110000", + "26111500", + "26111600", + "26111601", + "26111602", + "26111603", + "26111604", + "26111605", + "26111606", + "26111607", + "26111608", + "26111609", + "26111610", + "26111611", + "26111612", + "26111613", + "26111614", + "26111700", + "26111701", + "26111702", + "26111703", + "26111704", + "26111705", + "26111706", + "26111707", + "26111708", + "26111709", + "26111710", + "26111711", + "26111712", + "26111713", + "26111714", + "26111715", + "26111716", + "26111717", + "26111718", + "26111719", + "26111720", + "26111721", + "26111722", + "26111723", + "26111724", + "26111725", + "26111726", + "26111727", + "26111728", + "26111729", + "26111800", + "26111801", + "26111900", + "26112000", + "26112001", + "26112003", + "26112004", + "26112100", + "26120000", + "26121500", + "26121536", + "26121600", + "26121609", + "26121613", + "26121629", + "26121630", + "26121635", + "26121636", + "26121700", + "26121800", + "26130000", + "26131500", + "26131501", + "26131502", + "26131503", + "26131504", + "26131505", + "26131506", + "26131507", + "26131508", + "26131509", + "26131510", + "26131511", + "26131600", + "26131700", + "26131800", + "26131900", + "26140000", + "26141600", + "26141700", + "26141800", + "26141900", + "26142000", + "26142100", + "26142200", + "26142300", + "26142302", + "26142400", + "26142407", + "27000000", + "27110000", + "27111500", + "27111504", + "27111509", + "27111600", + "27111700", + "27111701", + "27111704", + "27111800", + "27111801", + "27111900", + "27111913", + "27112000", + "27112004", + "27112035", + "27112100", + "27112200", + "27112300", + "27112400", + "27112500", + "27112600", + "27112700", + "27112712", + "27112800", + "27112841", + "27112900", + "27113000", + "27113100", + "27113200", + "27113201", + "27113203", + "27113204", + "27113205", + "27113300", + "27113400", + "27113401", + "27113402", + "27113403", + "27120000", + "27121500", + "27121504", + "27130000", + "27131500", + "27131501", + "27140000", + "27141000", + "30000000", + "30100000", + "30101500", + "30101700", + "30101800", + "30102000", + "30102200", + "30102300", + "30102306", + "30102400", + "30102800", + "30102900", + "30103100", + "30103200", + "30103500", + "30103600", + "30103619", + "30103700", + "30103800", + "30103900", + "30110000", + "30111500", + "30111501", + "30111502", + "30111503", + "30111504", + "30111505", + "30111506", + "30111507", + "30111508", + "30111509", + "30111600", + "30111601", + "30111602", + "30111603", + "30111604", + "30111605", + "30111607", + "30111700", + "30111701", + "30111800", + "30111900", + "30120000", + "30121500", + "30121504", + "30121600", + "30121601", + "30121602", + "30121603", + "30121604", + "30121605", + "30121700", + "30121701", + "30121702", + "30121703", + "30121704", + "30121705", + "30121706", + "30121707", + "30121708", + "30121709", + "30121710", + "30121711", + "30121712", + "30121713", + "30121714", + "30121715", + "30121716", + "30121717", + "30121718", + "30121719", + "30121720", + "30121721", + "30121800", + "30130000", + "30131500", + "30131502", + "30131503", + "30131504", + "30131505", + "30131506", + "30131507", + "30131508", + "30131509", + "30131510", + "30131511", + "30131512", + "30131513", + "30131514", + "30131515", + "30131516", + "30131517", + "30131518", + "30131600", + "30131602", + "30131603", + "30131604", + "30131605", + "30131606", + "30131607", + "30131608", + "30131609", + "30131610", + "30131611", + "30131700", + "30131703", + "30140000", + "30150000", + "30151500", + "30151501", + "30151502", + "30151503", + "30151505", + "30151507", + "30151508", + "30151509", + "30151510", + "30151511", + "30151512", + "30151513", + "30151514", + "30151515", + "30151600", + "30151700", + "30151800", + "30151900", + "30152000", + "30152100", + "30160000", + "30161500", + "30161600", + "30161700", + "30161702", + "30161800", + "30161803", + "30161900", + "30162000", + "30162100", + "30162200", + "30162300", + "30162400", + "30170000", + "30171500", + "30171501", + "30171502", + "30171503", + "30171504", + "30171505", + "30171506", + "30171507", + "30171508", + "30171509", + "30171510", + "30171511", + "30171512", + "30171513", + "30171514", + "30171515", + "30171516", + "30171517", + "30171518", + "30171519", + "30171520", + "30171521", + "30171522", + "30171523", + "30171524", + "30171525", + "30171526", + "30171527", + "30171600", + "30171700", + "30171701", + "30171703", + "30171704", + "30171705", + "30171706", + "30171707", + "30171708", + "30171709", + "30171710", + "30171711", + "30171712", + "30171800", + "30171900", + "30171901", + "30171902", + "30171903", + "30171904", + "30171905", + "30171906", + "30171907", + "30171908", + "30172000", + "30172100", + "30180000", + "30181500", + "30181501", + "30181502", + "30181503", + "30181504", + "30181505", + "30181506", + "30181507", + "30181508", + "30181511", + "30181514", + "30181515", + "30181518", + "30181519", + "30181600", + "30181601", + "30181602", + "30181603", + "30181604", + "30181605", + "30181606", + "30181607", + "30181608", + "30181609", + "30181610", + "30181611", + "30181612", + "30181613", + "30181614", + "30181700", + "30181701", + "30181702", + "30181800", + "30181801", + "30181802", + "30181803", + "30181804", + "30181805", + "30181806", + "30181807", + "30181808", + "30181809", + "30181810", + "30181811", + "30181812", + "30190000", + "30191500", + "30191600", + "30191700", + "30191800", + "30240000", + "30241500", + "30241501", + "30241502", + "30241503", + "30241504", + "30241505", + "30241506", + "30241507", + "30241508", + "30241509", + "30241510", + "30241511", + "30241512", + "30241513", + "30241514", + "30241515", + "30241600", + "30241601", + "30241602", + "30241603", + "30241604", + "30241700", + "30241701", + "30241702", + "30241705", + "30250000", + "30260000", + "30263900", + "30265000", + "30265001", + "30265002", + "30265003", + "30265004", + "30265005", + "30265006", + "30265007", + "30265008", + "30265009", + "30265010", + "30265011", + "30265012", + "30265400", + "30265401", + "30265402", + "30265403", + "30265404", + "30265800", + "30265802", + "31000000", + "31100000", + "31110000", + "31130000", + "31140000", + "31150000", + "31151500", + "31151600", + "31151700", + "31151800", + "31151900", + "31151902", + "31151904", + "31152000", + "31152100", + "31152200", + "31152300", + "31160000", + "31161500", + "31161600", + "31161700", + "31161800", + "31161900", + "31162000", + "31162100", + "31162200", + "31162300", + "31162400", + "31162500", + "31162600", + "31162700", + "31162800", + "31162900", + "31163000", + "31163100", + "31163200", + "31163300", + "31163400", + "31170000", + "31171500", + "31171504", + "31171600", + "31171700", + "31171800", + "31171900", + "31180000", + "31190000", + "31191500", + "31191506", + "31191600", + "31200000", + "31201500", + "31201505", + "31201600", + "31210000", + "31211500", + "31211507", + "31211523", + "31211600", + "31211700", + "31211800", + "31211900", + "31220000", + "31230000", + "31240000", + "31250000", + "31260000", + "31270000", + "31280000", + "31290000", + "31300000", + "31310000", + "31320000", + "31330000", + "31340000", + "31350000", + "31360000", + "31370000", + "31380000", + "31390000", + "31400000", + "31401500", + "31401503", + "31410000", + "31420000", + "32000000", + "32100000", + "32101500", + "32101600", + "32101601", + "32110000", + "32120000", + "32121700", + "32121701", + "32121702", + "32121703", + "32121704", + "32121705", + "32130000", + "32131000", + "32140000", + "32150000", + "39000000", + "39100000", + "39101600", + "39101601", + "39101602", + "39101603", + "39101605", + "39101608", + "39101612", + "39101613", + "39101616", + "39101800", + "39101900", + "39110000", + "39111500", + "39111510", + "39111527", + "39111530", + "39111531", + "39111542", + "39111600", + "39111608", + "39111610", + "39111612", + "39111613", + "39111616", + "39111617", + "39111621", + "39111622", + "39111623", + "39111624", + "39111625", + "39111626", + "39111627", + "39111628", + "39111629", + "39111630", + "39111700", + "39111800", + "39111810", + "39111900", + "39112000", + "39112001", + "39112100", + "39112200", + "39112300", + "39112400", + "39112500", + "39112600", + "39120000", + "39121000", + "39121001", + "39121004", + "39121006", + "39121011", + "39121017", + "39121036", + "39121040", + "39121100", + "39121101", + "39121300", + "39121400", + "39121402", + "39121406", + "39121500", + "39121534", + "39121600", + "39121621", + "39121635", + "39121700", + "39121701", + "39121721", + "39121800", + "39121801", + "39121803", + "39121900", + "39121901", + "39122000", + "39122001", + "39122100", + "39122200", + "39122216", + "39122300", + "39130000", + "39131500", + "39131600", + "39131700", + "40000000", + "40100000", + "40101500", + "40101503", + "40101512", + "40101600", + "40101601", + "40101602", + "40101604", + "40101609", + "40101700", + "40101701", + "40101702", + "40101703", + "40101704", + "40101707", + "40101709", + "40101710", + "40101711", + "40101712", + "40101713", + "40101714", + "40101716", + "40101717", + "40101719", + "40101720", + "40101721", + "40101722", + "40101723", + "40101800", + "40101801", + "40101802", + "40101805", + "40101806", + "40101807", + "40101808", + "40101900", + "40101901", + "40101902", + "40101903", + "40102000", + "40102100", + "40140000", + "40141600", + "40141700", + "40141900", + "40142000", + "40142200", + "40142500", + "40150000", + "40151500", + "40151503", + "40151506", + "40151507", + "40151510", + "40151583", + "40151585", + "40151600", + "40151601", + "40151607", + "40151700", + "40160000", + "40161500", + "40161504", + "40161505", + "40161600", + "40161602", + "40161608", + "40161609", + "40161700", + "40161800", + "40170000", + "40171600", + "40174700", + "40174712", + "40180000", + "40181800", + "40183000", + "40183001", + "41000000", + "41100000", + "41101500", + "41101502", + "41101503", + "41101504", + "41101515", + "41101516", + "41101518", + "41101519", + "41101700", + "41101701", + "41101703", + "41101705", + "41101706", + "41101707", + "41101708", + "41101709", + "41101800", + "41101801", + "41101802", + "41101803", + "41101804", + "41101805", + "41101806", + "41101807", + "41101808", + "41101809", + "41101810", + "41101811", + "41101812", + "41101813", + "41101900", + "41101901", + "41101902", + "41101903", + "41102400", + "41102401", + "41102402", + "41102403", + "41102404", + "41102405", + "41102406", + "41102407", + "41102410", + "41102412", + "41102421", + "41102422", + "41102423", + "41102424", + "41102425", + "41102426", + "41102427", + "41102428", + "41102429", + "41102430", + "41102500", + "41102501", + "41102502", + "41102503", + "41102504", + "41102505", + "41102506", + "41102507", + "41102508", + "41102509", + "41102510", + "41102511", + "41102512", + "41102513", + "41102600", + "41102601", + "41102602", + "41102603", + "41102604", + "41102605", + "41102606", + "41102608", + "41102610", + "41102611", + "41102612", + "41102613", + "41102614", + "41102700", + "41102701", + "41102702", + "41102703", + "41102704", + "41102705", + "41102900", + "41102901", + "41102905", + "41102909", + "41102910", + "41102911", + "41102912", + "41102913", + "41102914", + "41102915", + "41102916", + "41102917", + "41102918", + "41102919", + "41102920", + "41102921", + "41102922", + "41102923", + "41102928", + "41103000", + "41103001", + "41103003", + "41103004", + "41103005", + "41103006", + "41103007", + "41103008", + "41103010", + "41103011", + "41103012", + "41103013", + "41103014", + "41103015", + "41103017", + "41103019", + "41103020", + "41103021", + "41103022", + "41103023", + "41103024", + "41103025", + "41103026", + "41103027", + "41103028", + "41103029", + "41103030", + "41103031", + "41103032", + "41103033", + "41103034", + "41103035", + "41103036", + "41103037", + "41103200", + "41103201", + "41103202", + "41103203", + "41103205", + "41103206", + "41103207", + "41103208", + "41103209", + "41103210", + "41103211", + "41103212", + "41103213", + "41103300", + "41103301", + "41103302", + "41103303", + "41103305", + "41103306", + "41103307", + "41103308", + "41103309", + "41103310", + "41103311", + "41103312", + "41103313", + "41103314", + "41103315", + "41103316", + "41103317", + "41103318", + "41103319", + "41103320", + "41103321", + "41103322", + "41103323", + "41103324", + "41103325", + "41103326", + "41103327", + "41103328", + "41103400", + "41103401", + "41103403", + "41103406", + "41103407", + "41103408", + "41103409", + "41103410", + "41103411", + "41103412", + "41103413", + "41103414", + "41103415", + "41103416", + "41103417", + "41103418", + "41103419", + "41103420", + "41103421", + "41103500", + "41103501", + "41103502", + "41103504", + "41103506", + "41103507", + "41103508", + "41103509", + "41103510", + "41103511", + "41103512", + "41103513", + "41103514", + "41103515", + "41103516", + "41103517", + "41103700", + "41103701", + "41103702", + "41103703", + "41103704", + "41103705", + "41103706", + "41103707", + "41103708", + "41103709", + "41103710", + "41103711", + "41103712", + "41103713", + "41103714", + "41103715", + "41103716", + "41103717", + "41103718", + "41103800", + "41103801", + "41103802", + "41103803", + "41103804", + "41103805", + "41103806", + "41103807", + "41103808", + "41103809", + "41103810", + "41103811", + "41103812", + "41103813", + "41103814", + "41103815", + "41103816", + "41103817", + "41103818", + "41103819", + "41103900", + "41103901", + "41103902", + "41103903", + "41103904", + "41103905", + "41103906", + "41103907", + "41103908", + "41103909", + "41103910", + "41103911", + "41103912", + "41103913", + "41103914", + "41103915", + "41103916", + "41103917", + "41104000", + "41104001", + "41104002", + "41104003", + "41104004", + "41104005", + "41104006", + "41104007", + "41104008", + "41104009", + "41104010", + "41104011", + "41104012", + "41104013", + "41104014", + "41104015", + "41104017", + "41104018", + "41104020", + "41104021", + "41104022", + "41104023", + "41104100", + "41104101", + "41104102", + "41104103", + "41104104", + "41104105", + "41104106", + "41104107", + "41104108", + "41104109", + "41104110", + "41104111", + "41104112", + "41104114", + "41104115", + "41104116", + "41104117", + "41104118", + "41104119", + "41104120", + "41104121", + "41104122", + "41104123", + "41104124", + "41104125", + "41104126", + "41104127", + "41104128", + "41104129", + "41104130", + "41104131", + "41104132", + "41104133", + "41104134", + "41104135", + "41104136", + "41104137", + "41104138", + "41104200", + "41104201", + "41104202", + "41104203", + "41104204", + "41104205", + "41104206", + "41104207", + "41104208", + "41104209", + "41104210", + "41104211", + "41104212", + "41104213", + "41104214", + "41104300", + "41104301", + "41104302", + "41104303", + "41104304", + "41104305", + "41104306", + "41104307", + "41104308", + "41104309", + "41104400", + "41104401", + "41104402", + "41104403", + "41104404", + "41104405", + "41104406", + "41104413", + "41104414", + "41104415", + "41104416", + "41104417", + "41104418", + "41104419", + "41104420", + "41104423", + "41104424", + "41104425", + "41104426", + "41104427", + "41104500", + "41104501", + "41104502", + "41104503", + "41104504", + "41104505", + "41104506", + "41104507", + "41104508", + "41104509", + "41104510", + "41104511", + "41104512", + "41104513", + "41104600", + "41104601", + "41104602", + "41104603", + "41104604", + "41104605", + "41104609", + "41104610", + "41104611", + "41104612", + "41104613", + "41104700", + "41104701", + "41104702", + "41104703", + "41104704", + "41104800", + "41104801", + "41104802", + "41104803", + "41104804", + "41104805", + "41104806", + "41104810", + "41104811", + "41104812", + "41104813", + "41104814", + "41104815", + "41104816", + "41104817", + "41104818", + "41104819", + "41104820", + "41104821", + "41104900", + "41104901", + "41104902", + "41104903", + "41104904", + "41104905", + "41104907", + "41104908", + "41104909", + "41104910", + "41104911", + "41104912", + "41104913", + "41104914", + "41104915", + "41104916", + "41104917", + "41104918", + "41104919", + "41104920", + "41104921", + "41104922", + "41104923", + "41104924", + "41104925", + "41104927", + "41104928", + "41104929", + "41104930", + "41104931", + "41104932", + "41104933", + "41105000", + "41105001", + "41105002", + "41105003", + "41105100", + "41105101", + "41105102", + "41105103", + "41105104", + "41105105", + "41105106", + "41105107", + "41105108", + "41105109", + "41105200", + "41105201", + "41105202", + "41105203", + "41105204", + "41105205", + "41105206", + "41105207", + "41105208", + "41105209", + "41105300", + "41105301", + "41105302", + "41105303", + "41105304", + "41105305", + "41105307", + "41105308", + "41105309", + "41105310", + "41105311", + "41105312", + "41105313", + "41105314", + "41105315", + "41105316", + "41105317", + "41105319", + "41105320", + "41105321", + "41105322", + "41105323", + "41105325", + "41105326", + "41105327", + "41105328", + "41105329", + "41105330", + "41105331", + "41105332", + "41105333", + "41105334", + "41105335", + "41105336", + "41105337", + "41105338", + "41105339", + "41105340", + "41105341", + "41105342", + "41105343", + "41105344", + "41105345", + "41105500", + "41105501", + "41105502", + "41105504", + "41105506", + "41105508", + "41105509", + "41105510", + "41105511", + "41105512", + "41105513", + "41105514", + "41105515", + "41105516", + "41105517", + "41105518", + "41105519", + "41105520", + "41105521", + "41105600", + "41105601", + "41105700", + "41105800", + "41105803", + "41105804", + "41105900", + "41105902", + "41105903", + "41105906", + "41105907", + "41105908", + "41106000", + "41106004", + "41106005", + "41106100", + "41106101", + "41106102", + "41106103", + "41106104", + "41106200", + "41106203", + "41106204", + "41106210", + "41106211", + "41106212", + "41106213", + "41106214", + "41106215", + "41106216", + "41106217", + "41106218", + "41106219", + "41106220", + "41106221", + "41106222", + "41106223", + "41106224", + "41106232", + "41106300", + "41106302", + "41106303", + "41106306", + "41106307", + "41106308", + "41106309", + "41106311", + "41106313", + "41106314", + "41106315", + "41106400", + "41106401", + "41106402", + "41106403", + "41106500", + "41106501", + "41106502", + "41106505", + "41106506", + "41106507", + "41106508", + "41106509", + "41106510", + "41106511", + "41106512", + "41106513", + "41106514", + "41106515", + "41106516", + "41106600", + "41106601", + "41106604", + "41106605", + "41106606", + "41106607", + "41106608", + "41106609", + "41106610", + "41106611", + "41106612", + "41106615", + "41106616", + "41106617", + "41106619", + "41106620", + "41106621", + "41106622", + "41110000", + "41111500", + "41111501", + "41111502", + "41111503", + "41111504", + "41111505", + "41111506", + "41111507", + "41111508", + "41111509", + "41111510", + "41111511", + "41111512", + "41111513", + "41111515", + "41111516", + "41111517", + "41111518", + "41111519", + "41111520", + "41111521", + "41111522", + "41111523", + "41111524", + "41111525", + "41111526", + "41111528", + "41111529", + "41111530", + "41111531", + "41111600", + "41111601", + "41111602", + "41111603", + "41111604", + "41111605", + "41111606", + "41111607", + "41111613", + "41111614", + "41111615", + "41111616", + "41111617", + "41111618", + "41111619", + "41111620", + "41111621", + "41111622", + "41111623", + "41111624", + "41111625", + "41111626", + "41111627", + "41111628", + "41111629", + "41111630", + "41111631", + "41111632", + "41111633", + "41111634", + "41111635", + "41111636", + "41111637", + "41111638", + "41111639", + "41111640", + "41111641", + "41111642", + "41111643", + "41111644", + "41111645", + "41111646", + "41111647", + "41111648", + "41111649", + "41111650", + "41111651", + "41111652", + "41111700", + "41111701", + "41111702", + "41111703", + "41111704", + "41111705", + "41111706", + "41111707", + "41111708", + "41111709", + "41111710", + "41111711", + "41111712", + "41111713", + "41111714", + "41111715", + "41111716", + "41111717", + "41111718", + "41111719", + "41111720", + "41111721", + "41111722", + "41111723", + "41111724", + "41111725", + "41111726", + "41111727", + "41111728", + "41111729", + "41111730", + "41111731", + "41111733", + "41111734", + "41111735", + "41111736", + "41111737", + "41111738", + "41111739", + "41111740", + "41111741", + "41111742", + "41111743", + "41111744", + "41111745", + "41111746", + "41111747", + "41111748", + "41111749", + "41111750", + "41111751", + "41111752", + "41111753", + "41111754", + "41111755", + "41111756", + "41111757", + "41111758", + "41111759", + "41111760", + "41111761", + "41111762", + "41111763", + "41111764", + "41111765", + "41111766", + "41111767", + "41111768", + "41111769", + "41111770", + "41111771", + "41111772", + "41111800", + "41111808", + "41111809", + "41111810", + "41111811", + "41111812", + "41111815", + "41111816", + "41111817", + "41111818", + "41111819", + "41111820", + "41111900", + "41111901", + "41111902", + "41111903", + "41111904", + "41111905", + "41111906", + "41111907", + "41111908", + "41111909", + "41111910", + "41111911", + "41111912", + "41111913", + "41111914", + "41111915", + "41111916", + "41111917", + "41111918", + "41111919", + "41111920", + "41111921", + "41111922", + "41111923", + "41111924", + "41111926", + "41111927", + "41111928", + "41111929", + "41111930", + "41111931", + "41111932", + "41111933", + "41111934", + "41111935", + "41111936", + "41111937", + "41111938", + "41111939", + "41111940", + "41111941", + "41111942", + "41111943", + "41111944", + "41111945", + "41111946", + "41111947", + "41111948", + "41111949", + "41111950", + "41111951", + "41111952", + "41111953", + "41111954", + "41111955", + "41111956", + "41111957", + "41111958", + "41111959", + "41111960", + "41111961", + "41111962", + "41111963", + "41111964", + "41111965", + "41111966", + "41111967", + "41111968", + "41111969", + "41111970", + "41111971", + "41111972", + "41111973", + "41111974", + "41111975", + "41111976", + "41111977", + "41111978", + "41111979", + "41111980", + "41111981", + "41112100", + "41112101", + "41112103", + "41112104", + "41112105", + "41112106", + "41112107", + "41112108", + "41112109", + "41112110", + "41112111", + "41112112", + "41112113", + "41112114", + "41112200", + "41112201", + "41112202", + "41112203", + "41112204", + "41112205", + "41112206", + "41112207", + "41112209", + "41112210", + "41112211", + "41112212", + "41112213", + "41112214", + "41112215", + "41112216", + "41112217", + "41112219", + "41112220", + "41112221", + "41112222", + "41112223", + "41112224", + "41112225", + "41112226", + "41112227", + "41112228", + "41112229", + "41112230", + "41112231", + "41112232", + "41112233", + "41112234", + "41112235", + "41112236", + "41112237", + "41112238", + "41112239", + "41112240", + "41112241", + "41112242", + "41112243", + "41112244", + "41112300", + "41112301", + "41112302", + "41112303", + "41112304", + "41112305", + "41112306", + "41112307", + "41112400", + "41112401", + "41112402", + "41112403", + "41112404", + "41112405", + "41112406", + "41112407", + "41112408", + "41112409", + "41112410", + "41112411", + "41112412", + "41112413", + "41112414", + "41112415", + "41112416", + "41112417", + "41112418", + "41112419", + "41112420", + "41112421", + "41112422", + "41112423", + "41112500", + "41112501", + "41112502", + "41112503", + "41112504", + "41112505", + "41112506", + "41112508", + "41112509", + "41112510", + "41112511", + "41112512", + "41112513", + "41112514", + "41112516", + "41112517", + "41112518", + "41112519", + "41112520", + "41112521", + "41112522", + "41112523", + "41112600", + "41112601", + "41112602", + "41112700", + "41112701", + "41112702", + "41112704", + "41112800", + "41112801", + "41112802", + "41112803", + "41112900", + "41112901", + "41112902", + "41112903", + "41112904", + "41113000", + "41113001", + "41113002", + "41113003", + "41113004", + "41113005", + "41113006", + "41113007", + "41113008", + "41113009", + "41113010", + "41113023", + "41113024", + "41113025", + "41113026", + "41113027", + "41113029", + "41113030", + "41113031", + "41113033", + "41113034", + "41113035", + "41113036", + "41113037", + "41113038", + "41113039", + "41113040", + "41113041", + "41113042", + "41113043", + "41113044", + "41113045", + "41113046", + "41113047", + "41113048", + "41113049", + "41113050", + "41113051", + "41113052", + "41113053", + "41113054", + "41113055", + "41113056", + "41113057", + "41113100", + "41113107", + "41113108", + "41113109", + "41113110", + "41113115", + "41113116", + "41113117", + "41113118", + "41113119", + "41113124", + "41113300", + "41113301", + "41113309", + "41113310", + "41113311", + "41113312", + "41113313", + "41113318", + "41113319", + "41113320", + "41113322", + "41113323", + "41113325", + "41113327", + "41113328", + "41113331", + "41113332", + "41113333", + "41113400", + "41113600", + "41113601", + "41113602", + "41113603", + "41113604", + "41113605", + "41113606", + "41113607", + "41113608", + "41113611", + "41113612", + "41113613", + "41113614", + "41113615", + "41113616", + "41113617", + "41113618", + "41113619", + "41113620", + "41113621", + "41113622", + "41113623", + "41113624", + "41113625", + "41113626", + "41113627", + "41113628", + "41113629", + "41113630", + "41113631", + "41113632", + "41113633", + "41113634", + "41113635", + "41113636", + "41113637", + "41113638", + "41113639", + "41113640", + "41113641", + "41113642", + "41113643", + "41113644", + "41113645", + "41113646", + "41113647", + "41113649", + "41113650", + "41113651", + "41113652", + "41113653", + "41113654", + "41113655", + "41113656", + "41113657", + "41113658", + "41113659", + "41113660", + "41113661", + "41113662", + "41113663", + "41113664", + "41113665", + "41113666", + "41113667", + "41113668", + "41113669", + "41113670", + "41113671", + "41113672", + "41113673", + "41113674", + "41113675", + "41113676", + "41113677", + "41113678", + "41113679", + "41113680", + "41113681", + "41113682", + "41113683", + "41113684", + "41113685", + "41113686", + "41113687", + "41113688", + "41113689", + "41113700", + "41113701", + "41113702", + "41113703", + "41113704", + "41113705", + "41113706", + "41113708", + "41113709", + "41113710", + "41113711", + "41113712", + "41113713", + "41113714", + "41113716", + "41113717", + "41113726", + "41113727", + "41113728", + "41113800", + "41113801", + "41113802", + "41113803", + "41113804", + "41113805", + "41113806", + "41113807", + "41113808", + "41113809", + "41113810", + "41113811", + "41113812", + "41113813", + "41113814", + "41113815", + "41113816", + "41113817", + "41113818", + "41113819", + "41113820", + "41113821", + "41113822", + "41113823", + "41113824", + "41113825", + "41113826", + "41113827", + "41113828", + "41113829", + "41113830", + "41113831", + "41113900", + "41113901", + "41113902", + "41113903", + "41113904", + "41113905", + "41113906", + "41113907", + "41113908", + "41113909", + "41113910", + "41114000", + "41114001", + "41114100", + "41114102", + "41114103", + "41114104", + "41114105", + "41114106", + "41114107", + "41114108", + "41114200", + "41114201", + "41114202", + "41114203", + "41114207", + "41114300", + "41114301", + "41114302", + "41114303", + "41114400", + "41114401", + "41114402", + "41114403", + "41114404", + "41114405", + "41114406", + "41114407", + "41114408", + "41114409", + "41114410", + "41114411", + "41114412", + "41114413", + "41114414", + "41114415", + "41114416", + "41114417", + "41114418", + "41114419", + "41114420", + "41114421", + "41114422", + "41114423", + "41114424", + "41114425", + "41114426", + "41114427", + "41114428", + "41114429", + "41114430", + "41114431", + "41114500", + "41114501", + "41114502", + "41114503", + "41114504", + "41114505", + "41114506", + "41114507", + "41114508", + "41114509", + "41114510", + "41114511", + "41114512", + "41114513", + "41114514", + "41114515", + "41114516", + "41114517", + "41114518", + "41114519", + "41114520", + "41114521", + "41114522", + "41114523", + "41114524", + "41114525", + "41114526", + "41114527", + "41114528", + "41114529", + "41114530", + "41114600", + "41114601", + "41114602", + "41114603", + "41114604", + "41114605", + "41114606", + "41114607", + "41114608", + "41114609", + "41114610", + "41114611", + "41114612", + "41114613", + "41114614", + "41114615", + "41114616", + "41114617", + "41114618", + "41114619", + "41114620", + "41114621", + "41114622", + "41114623", + "41114624", + "41114625", + "41114626", + "41114627", + "41114628", + "41114629", + "41114630", + "41114631", + "41114632", + "41114633", + "41114634", + "41114635", + "41114636", + "41114637", + "41114638", + "41114639", + "41114640", + "41114641", + "41114642", + "41114643", + "41114644", + "41114645", + "41114646", + "41114647", + "41114648", + "41114649", + "41114650", + "41114700", + "41114800", + "41114802", + "41115100", + "41115102", + "41115200", + "41115300", + "41115301", + "41115302", + "41115303", + "41115304", + "41115307", + "41115308", + "41115310", + "41115311", + "41115312", + "41115314", + "41115315", + "41115316", + "41115317", + "41115318", + "41115319", + "41115320", + "41115321", + "41115322", + "41115323", + "41115324", + "41115325", + "41115326", + "41115327", + "41115330", + "41115335", + "41115340", + "41115400", + "41115401", + "41115402", + "41115403", + "41115404", + "41115405", + "41115406", + "41115407", + "41115408", + "41115409", + "41115411", + "41115412", + "41115413", + "41115414", + "41115415", + "41115416", + "41115417", + "41115418", + "41115500", + "41115505", + "41115600", + "41115601", + "41115602", + "41115603", + "41115609", + "41115700", + "41115703", + "41115704", + "41115705", + "41115707", + "41115708", + "41115709", + "41115800", + "41115801", + "41115802", + "41115803", + "41115804", + "41115805", + "41115806", + "41115807", + "41115808", + "41115809", + "41115810", + "41115811", + "41115812", + "41115813", + "41115814", + "41115815", + "41115816", + "41115817", + "41115818", + "41115819", + "41115820", + "41115821", + "41115822", + "41115823", + "41115824", + "41115825", + "41115826", + "41115827", + "41115828", + "41115829", + "41115830", + "41115831", + "41115832", + "41115833", + "41115834", + "41115835", + "41115836", + "41115837", + "41115838", + "41115839", + "41115840", + "41115841", + "41115842", + "41115843", + "41115844", + "41115845", + "41115846", + "41115847", + "41115848", + "41115849", + "41115850", + "41115851", + "41115852", + "41115853", + "41115854", + "41115855", + "41115856", + "41115857", + "41115858", + "41115859", + "41115860", + "41115861", + "41115862", + "41115863", + "41115864", + "41115865", + "41115866", + "41115867", + "41115868", + "41115872", + "41116000", + "41116001", + "41116002", + "41116003", + "41116004", + "41116005", + "41116006", + "41116007", + "41116008", + "41116009", + "41116010", + "41116011", + "41116012", + "41116013", + "41116014", + "41116015", + "41116016", + "41116017", + "41116018", + "41116019", + "41116020", + "41116021", + "41116022", + "41116023", + "41116024", + "41116025", + "41116026", + "41116027", + "41116029", + "41116100", + "41116101", + "41116102", + "41116103", + "41116104", + "41116105", + "41116106", + "41116107", + "41116108", + "41116109", + "41116110", + "41116111", + "41116112", + "41116113", + "41116116", + "41116117", + "41116118", + "41116119", + "41116120", + "41116121", + "41116122", + "41116123", + "41116124", + "41116125", + "41116126", + "41116127", + "41116128", + "41116129", + "41116130", + "41116131", + "41116132", + "41116133", + "41116134", + "41116135", + "41116136", + "41116137", + "41116138", + "41116139", + "41116140", + "41116141", + "41116142", + "41116143", + "41116144", + "41116145", + "41116146", + "41116147", + "41116148", + "41116149", + "41116150", + "41116151", + "41116152", + "41116153", + "41116154", + "41116155", + "41116156", + "41116157", + "41116158", + "41116159", + "41116160", + "41116161", + "41116162", + "41116163", + "41116164", + "41116165", + "41116166", + "41116167", + "41116200", + "41116201", + "41116202", + "41116203", + "41116205", + "41116206", + "41116207", + "41116208", + "41116209", + "41116210", + "41116211", + "41116212", + "41116213", + "41116214", + "41116215", + "41116216", + "41116217", + "41116218", + "41116219", + "41116220", + "41116221", + "41116222", + "41116223", + "41116224", + "41116225", + "41116300", + "41116301", + "41116302", + "41116303", + "41116304", + "41116400", + "41116500", + "41116501", + "41116502", + "41120000", + "41121500", + "41121501", + "41121502", + "41121503", + "41121504", + "41121505", + "41121506", + "41121507", + "41121508", + "41121509", + "41121510", + "41121511", + "41121513", + "41121514", + "41121515", + "41121516", + "41121517", + "41121518", + "41121519", + "41121520", + "41121521", + "41121522", + "41121523", + "41121600", + "41121601", + "41121602", + "41121603", + "41121604", + "41121605", + "41121606", + "41121607", + "41121608", + "41121609", + "41121610", + "41121700", + "41121701", + "41121702", + "41121703", + "41121704", + "41121705", + "41121706", + "41121707", + "41121708", + "41121709", + "41121710", + "41121711", + "41121712", + "41121713", + "41121714", + "41121715", + "41121800", + "41121801", + "41121802", + "41121803", + "41121804", + "41121805", + "41121806", + "41121807", + "41121808", + "41121809", + "41121810", + "41121811", + "41121812", + "41121813", + "41121814", + "41121815", + "41121816", + "41121817", + "41121818", + "41121819", + "41121820", + "41121821", + "41122000", + "41122001", + "41122002", + "41122003", + "41122004", + "41122100", + "41122101", + "41122102", + "41122103", + "41122104", + "41122105", + "41122106", + "41122107", + "41122108", + "41122109", + "41122110", + "41122111", + "41122112", + "41122113", + "41122114", + "41122200", + "41122201", + "41122202", + "41122203", + "41122300", + "41122301", + "41122400", + "41122401", + "41122402", + "41122403", + "41122404", + "41122405", + "41122406", + "41122407", + "41122408", + "41122409", + "41122410", + "41122411", + "41122412", + "41122413", + "41122414", + "41122415", + "41122416", + "41122417", + "41122418", + "41122419", + "41122420", + "41122421", + "41122500", + "41122501", + "41122502", + "41122503", + "41122600", + "41122601", + "41122602", + "41122603", + "41122604", + "41122605", + "41122606", + "41122607", + "41122608", + "41122700", + "41122701", + "41122702", + "41122703", + "41122704", + "41122800", + "41122801", + "41122802", + "41122803", + "41122804", + "41122805", + "41122806", + "41122807", + "41122808", + "41122809", + "41122810", + "41122811", + "41123000", + "41123001", + "41123002", + "41123003", + "41123004", + "41123005", + "41123006", + "41123100", + "41123101", + "41123102", + "41123103", + "41123104", + "41123105", + "41123106", + "41123200", + "41123201", + "41123202", + "41123203", + "41123204", + "41123300", + "41123302", + "41123303", + "41123304", + "41123305", + "41123306", + "41123307", + "41123308", + "41123309", + "41123310", + "41123311", + "41123312", + "41123313", + "41123314", + "41123400", + "41123401", + "41123402", + "41123403", + "41150000", + "41151500", + "41151600", + "41151629", + "41170000", + "41171600", + "42000000", + "42120000", + "42121500", + "42121501", + "42121506", + "42121507", + "42121518", + "42121600", + "42121700", + "42121800", + "42130000", + "42131500", + "42131501", + "42131502", + "42131503", + "42131504", + "42131505", + "42131506", + "42131507", + "42131508", + "42131509", + "42131510", + "42131511", + "42131512", + "42131513", + "42131514", + "42131600", + "42131601", + "42131602", + "42131603", + "42131604", + "42131607", + "42131608", + "42131609", + "42131610", + "42131611", + "42131612", + "42131613", + "42131615", + "42131700", + "42131701", + "42131702", + "42131704", + "42131706", + "42131707", + "42131708", + "42131709", + "42131710", + "42131711", + "42131713", + "42131716", + "42131717", + "42131719", + "42131721", + "42131722", + "42132100", + "42132101", + "42132102", + "42132103", + "42132104", + "42132105", + "42132106", + "42132107", + "42132108", + "42132109", + "42132110", + "42132111", + "42132112", + "42132113", + "42132114", + "42132115", + "42132116", + "42132200", + "42132201", + "42132202", + "42132203", + "42132204", + "42132205", + "42132300", + "42132301", + "42132302", + "42132303", + "42140000", + "42141500", + "42141501", + "42141502", + "42141503", + "42141504", + "42141507", + "42141600", + "42141601", + "42141602", + "42141603", + "42141605", + "42141606", + "42141607", + "42141608", + "42141700", + "42141701", + "42141800", + "42141801", + "42141802", + "42141803", + "42141804", + "42141805", + "42141806", + "42141807", + "42141808", + "42141809", + "42141810", + "42141811", + "42141812", + "42141813", + "42141814", + "42141815", + "42141816", + "42141817", + "42141819", + "42141822", + "42141900", + "42141903", + "42141904", + "42141905", + "42142100", + "42142101", + "42142102", + "42142103", + "42142104", + "42142105", + "42142106", + "42142107", + "42142108", + "42142109", + "42142110", + "42142111", + "42142112", + "42142113", + "42142114", + "42142119", + "42142120", + "42142121", + "42142130", + "42142200", + "42142201", + "42142300", + "42142301", + "42142302", + "42142303", + "42142500", + "42142501", + "42142502", + "42142503", + "42142504", + "42142506", + "42142509", + "42142510", + "42142511", + "42142512", + "42142513", + "42142514", + "42142516", + "42142518", + "42142519", + "42142520", + "42142521", + "42142523", + "42142525", + "42142527", + "42142528", + "42142529", + "42142530", + "42142531", + "42142532", + "42142533", + "42142534", + "42142535", + "42142536", + "42142537", + "42142538", + "42142600", + "42142601", + "42142602", + "42142603", + "42142604", + "42142605", + "42142606", + "42142607", + "42142608", + "42142609", + "42142610", + "42142611", + "42142612", + "42142613", + "42142614", + "42142615", + "42142616", + "42142617", + "42142618", + "42142619", + "42142620", + "42142627", + "42142628", + "42142629", + "42142630", + "42142700", + "42142701", + "42142702", + "42142703", + "42142704", + "42142705", + "42142706", + "42142707", + "42142708", + "42142709", + "42142710", + "42142712", + "42142713", + "42142714", + "42142715", + "42142716", + "42142717", + "42142718", + "42142719", + "42142720", + "42142721", + "42142733", + "42142734", + "42142736", + "42142800", + "42142801", + "42142802", + "42142900", + "42142901", + "42142902", + "42143100", + "42143101", + "42143102", + "42143103", + "42143104", + "42143105", + "42143106", + "42143107", + "42143108", + "42143109", + "42143110", + "42143111", + "42143112", + "42143113", + "42143114", + "42143115", + "42143116", + "42143117", + "42143118", + "42143119", + "42143120", + "42143121", + "42143122", + "42143123", + "42143124", + "42143125", + "42143126", + "42143127", + "42143128", + "42143129", + "42143130", + "42143131", + "42143132", + "42143133", + "42143134", + "42143135", + "42143136", + "42143200", + "42143201", + "42143203", + "42143204", + "42143300", + "42143301", + "42143302", + "42143303", + "42143304", + "42143307", + "42143400", + "42143500", + "42143515", + "42143516", + "42143523", + "42143600", + "42143601", + "42143602", + "42143603", + "42143604", + "42143605", + "42143606", + "42143607", + "42143608", + "42143609", + "42143700", + "42143701", + "42143702", + "42143703", + "42143704", + "42143705", + "42143706", + "42143707", + "42143708", + "42143709", + "42143713", + "42143800", + "42143801", + "42143802", + "42143803", + "42143900", + "42143901", + "42143902", + "42143903", + "42144000", + "42144100", + "42144101", + "42144102", + "42144103", + "42144200", + "42144400", + "42144401", + "42144406", + "42144500", + "42150000", + "42151500", + "42151501", + "42151502", + "42151503", + "42151504", + "42151600", + "42151614", + "42151636", + "42151686", + "42151700", + "42151705", + "42151800", + "42151900", + "42151901", + "42152000", + "42152008", + "42152016", + "42152017", + "42152100", + "42152200", + "42152234", + "42152300", + "42152400", + "42152423", + "42152424", + "42152425", + "42152434", + "42152446", + "42152465", + "42152500", + "42152501", + "42152502", + "42152503", + "42152504", + "42152505", + "42152506", + "42152507", + "42152508", + "42152509", + "42152511", + "42152512", + "42152513", + "42152600", + "42152700", + "42152800", + "42152900", + "42152902", + "42160000", + "42161500", + "42161501", + "42161502", + "42161503", + "42161504", + "42161505", + "42161506", + "42161507", + "42161508", + "42161509", + "42161510", + "42161600", + "42161601", + "42161602", + "42161603", + "42161604", + "42161605", + "42161606", + "42161607", + "42161608", + "42161609", + "42161610", + "42161611", + "42161612", + "42161613", + "42161614", + "42161615", + "42161616", + "42161617", + "42161618", + "42161619", + "42161620", + "42161621", + "42161622", + "42161623", + "42161624", + "42161625", + "42161627", + "42161628", + "42161629", + "42161630", + "42161631", + "42161632", + "42161633", + "42161634", + "42161635", + "42161659", + "42161700", + "42161701", + "42161702", + "42161703", + "42161704", + "42161800", + "42161803", + "42161900", + "42170000", + "42171500", + "42171501", + "42171502", + "42171503", + "42171600", + "42171601", + "42171602", + "42171603", + "42171604", + "42171605", + "42171606", + "42171607", + "42171608", + "42171609", + "42171610", + "42171611", + "42171612", + "42171613", + "42171614", + "42171700", + "42171701", + "42171702", + "42171703", + "42171704", + "42171800", + "42171801", + "42171805", + "42171810", + "42171900", + "42171922", + "42172000", + "42172001", + "42172002", + "42172003", + "42172004", + "42172005", + "42172006", + "42172008", + "42172009", + "42172010", + "42172011", + "42172014", + "42172015", + "42172016", + "42172017", + "42172100", + "42172101", + "42172103", + "42172104", + "42172105", + "42172106", + "42180000", + "42181500", + "42181501", + "42181502", + "42181503", + "42181506", + "42181514", + "42181516", + "42181540", + "42181541", + "42181542", + "42181547", + "42181600", + "42181601", + "42181602", + "42181603", + "42181604", + "42181605", + "42181606", + "42181607", + "42181608", + "42181609", + "42181610", + "42181611", + "42181700", + "42181701", + "42181713", + "42181720", + "42181721", + "42181725", + "42181800", + "42181801", + "42181802", + "42181803", + "42181804", + "42181805", + "42181900", + "42181902", + "42181903", + "42181904", + "42181905", + "42181907", + "42181908", + "42181918", + "42182000", + "42182001", + "42182003", + "42182004", + "42182005", + "42182006", + "42182013", + "42182015", + "42182017", + "42182100", + "42182101", + "42182102", + "42182103", + "42182107", + "42182200", + "42182201", + "42182202", + "42182203", + "42182204", + "42182205", + "42182206", + "42182207", + "42182208", + "42182209", + "42182210", + "42182211", + "42182300", + "42182301", + "42182302", + "42182303", + "42182304", + "42182306", + "42182307", + "42182308", + "42182311", + "42182313", + "42182314", + "42182315", + "42182316", + "42182327", + "42182400", + "42182401", + "42182416", + "42182500", + "42182600", + "42182601", + "42182602", + "42182603", + "42182604", + "42182700", + "42182701", + "42182702", + "42182703", + "42182704", + "42182705", + "42182706", + "42182707", + "42182708", + "42182800", + "42182801", + "42182802", + "42182803", + "42182804", + "42182805", + "42182806", + "42182807", + "42182808", + "42183000", + "42183002", + "42183010", + "42183013", + "42183015", + "42183018", + "42183021", + "42183029", + "42183031", + "42183037", + "42183050", + "42183076", + "42183078", + "42183080", + "42183200", + "42183201", + "42183400", + "42183403", + "42183500", + "42183503", + "42183509", + "42190000", + "42191500", + "42191501", + "42191502", + "42191600", + "42191601", + "42191602", + "42191603", + "42191605", + "42191607", + "42191611", + "42191612", + "42191614", + "42191700", + "42191701", + "42191705", + "42191707", + "42191710", + "42191711", + "42191713", + "42191800", + "42191801", + "42191802", + "42191803", + "42191804", + "42191805", + "42191806", + "42191807", + "42191808", + "42191810", + "42191811", + "42191812", + "42191813", + "42191814", + "42191819", + "42191900", + "42191901", + "42191902", + "42191903", + "42191905", + "42191906", + "42191907", + "42191908", + "42191911", + "42192000", + "42192001", + "42192002", + "42192003", + "42192005", + "42192006", + "42192100", + "42192101", + "42192102", + "42192103", + "42192104", + "42192107", + "42192108", + "42192110", + "42192200", + "42192201", + "42192202", + "42192203", + "42192204", + "42192205", + "42192206", + "42192207", + "42192208", + "42192209", + "42192210", + "42192211", + "42192212", + "42192214", + "42192215", + "42192217", + "42192220", + "42192300", + "42192301", + "42192302", + "42192303", + "42192304", + "42192305", + "42192400", + "42192401", + "42192402", + "42192403", + "42192404", + "42192405", + "42192406", + "42192407", + "42192409", + "42192410", + "42192412", + "42192413", + "42192414", + "42192415", + "42192416", + "42192417", + "42192418", + "42192419", + "42192420", + "42192421", + "42192422", + "42192423", + "42192424", + "42192425", + "42192426", + "42192427", + "42192428", + "42192429", + "42192431", + "42192433", + "42192434", + "42192435", + "42192500", + "42192501", + "42192502", + "42192600", + "42192601", + "42192602", + "42192603", + "42192604", + "42192606", + "42192617", + "42192700", + "42192701", + "42192702", + "42192706", + "42192707", + "42192800", + "42200000", + "42201500", + "42201501", + "42201502", + "42201508", + "42201509", + "42201511", + "42201600", + "42201601", + "42201602", + "42201607", + "42201608", + "42201609", + "42201611", + "42201700", + "42201704", + "42201705", + "42201706", + "42201707", + "42201708", + "42201709", + "42201710", + "42201711", + "42201712", + "42201713", + "42201718", + "42201723", + "42201728", + "42201800", + "42201803", + "42201804", + "42201805", + "42201806", + "42201807", + "42201808", + "42201809", + "42201810", + "42201811", + "42201812", + "42201813", + "42201814", + "42201815", + "42201816", + "42201817", + "42201818", + "42201819", + "42201820", + "42201821", + "42201822", + "42201823", + "42201824", + "42201825", + "42201826", + "42201827", + "42201828", + "42201829", + "42201830", + "42201831", + "42201832", + "42201833", + "42201834", + "42201835", + "42201836", + "42201837", + "42201838", + "42201839", + "42201840", + "42201841", + "42201843", + "42201844", + "42201845", + "42201846", + "42201847", + "42201848", + "42201849", + "42201850", + "42201851", + "42201852", + "42201853", + "42201855", + "42201858", + "42201860", + "42201861", + "42201863", + "42201900", + "42201901", + "42201902", + "42201903", + "42201904", + "42201905", + "42201906", + "42201907", + "42201908", + "42202000", + "42202100", + "42202101", + "42202102", + "42202103", + "42202104", + "42202105", + "42202106", + "42202200", + "42202300", + "42202301", + "42202302", + "42202303", + "42202400", + "42202401", + "42202500", + "42202600", + "42202700", + "42202702", + "42202900", + "42202901", + "42202902", + "42203000", + "42203200", + "42203201", + "42203400", + "42203402", + "42203403", + "42203404", + "42203405", + "42203406", + "42203407", + "42203408", + "42203409", + "42203410", + "42203413", + "42203414", + "42203415", + "42203416", + "42203417", + "42203418", + "42203420", + "42203421", + "42203422", + "42203423", + "42203424", + "42203425", + "42203426", + "42203427", + "42203428", + "42203429", + "42203430", + "42203436", + "42203447", + "42203500", + "42203501", + "42203502", + "42203503", + "42203504", + "42203505", + "42203506", + "42203600", + "42203601", + "42203602", + "42203603", + "42203605", + "42203606", + "42203608", + "42203613", + "42203700", + "42203701", + "42203702", + "42203703", + "42203704", + "42203705", + "42203706", + "42203707", + "42203708", + "42203709", + "42203710", + "42203711", + "42203712", + "42203800", + "42203801", + "42203802", + "42203803", + "42203804", + "42203900", + "42203901", + "42203902", + "42203903", + "42204000", + "42204001", + "42204002", + "42204003", + "42204004", + "42204005", + "42204006", + "42204007", + "42204008", + "42204009", + "42204100", + "42204101", + "42210000", + "42211500", + "42211501", + "42211502", + "42211503", + "42211504", + "42211505", + "42211506", + "42211508", + "42211600", + "42211700", + "42211701", + "42211702", + "42211703", + "42211704", + "42211705", + "42211706", + "42211707", + "42211708", + "42211709", + "42211710", + "42211711", + "42211712", + "42211800", + "42211900", + "42211901", + "42211902", + "42211903", + "42211904", + "42211905", + "42211906", + "42211907", + "42211908", + "42211909", + "42211910", + "42211911", + "42211912", + "42211913", + "42211914", + "42211915", + "42211916", + "42211917", + "42211918", + "42212000", + "42212001", + "42212002", + "42212003", + "42212004", + "42212005", + "42212006", + "42212007", + "42212100", + "42212200", + "42212300", + "42220000", + "42221500", + "42221501", + "42221502", + "42221503", + "42221504", + "42221506", + "42221507", + "42221508", + "42221509", + "42221512", + "42221514", + "42221515", + "42221516", + "42221600", + "42221601", + "42221602", + "42221603", + "42221604", + "42221605", + "42221606", + "42221607", + "42221608", + "42221609", + "42221610", + "42221611", + "42221612", + "42221613", + "42221614", + "42221615", + "42221616", + "42221617", + "42221618", + "42221619", + "42221700", + "42221701", + "42221703", + "42221704", + "42221705", + "42221706", + "42221707", + "42221800", + "42221801", + "42221802", + "42221803", + "42221900", + "42221901", + "42221902", + "42221903", + "42221904", + "42221905", + "42221906", + "42221907", + "42222000", + "42222001", + "42222002", + "42222003", + "42222004", + "42222005", + "42222006", + "42222007", + "42222008", + "42222009", + "42222011", + "42222100", + "42222101", + "42222102", + "42222103", + "42222104", + "42222200", + "42222201", + "42222202", + "42222300", + "42222301", + "42222302", + "42222303", + "42222304", + "42222305", + "42222307", + "42230000", + "42231500", + "42231501", + "42231504", + "42231505", + "42231510", + "42231600", + "42231601", + "42231613", + "42231700", + "42231703", + "42231800", + "42231801", + "42231802", + "42231806", + "42231810", + "42231812", + "42231813", + "42231814", + "42231815", + "42231816", + "42231817", + "42231818", + "42231900", + "42231901", + "42231902", + "42231903", + "42231904", + "42232000", + "42240000", + "42241500", + "42241502", + "42241503", + "42241504", + "42241505", + "42241506", + "42241507", + "42241509", + "42241510", + "42241511", + "42241512", + "42241513", + "42241514", + "42241516", + "42241517", + "42241600", + "42241602", + "42241603", + "42241604", + "42241606", + "42241700", + "42241701", + "42241702", + "42241703", + "42241705", + "42241706", + "42241707", + "42241708", + "42241709", + "42241800", + "42241801", + "42241802", + "42241803", + "42241804", + "42241805", + "42241806", + "42241807", + "42241808", + "42241809", + "42241811", + "42241900", + "42242000", + "42242100", + "42250000", + "42251500", + "42251501", + "42251502", + "42251503", + "42251504", + "42251505", + "42251506", + "42251600", + "42251608", + "42251613", + "42251623", + "42251624", + "42251700", + "42251701", + "42251702", + "42251703", + "42251704", + "42251705", + "42251706", + "42251800", + "42251805", + "42260000", + "42261500", + "42261501", + "42261502", + "42261503", + "42261504", + "42261505", + "42261506", + "42261507", + "42261508", + "42261509", + "42261510", + "42261511", + "42261512", + "42261513", + "42261514", + "42261516", + "42261600", + "42261601", + "42261602", + "42261604", + "42261605", + "42261606", + "42261607", + "42261608", + "42261609", + "42261610", + "42261611", + "42261612", + "42261613", + "42261700", + "42261703", + "42261800", + "42261801", + "42261802", + "42261803", + "42261804", + "42261805", + "42261806", + "42261807", + "42261808", + "42261809", + "42261810", + "42261900", + "42262000", + "42262100", + "42270000", + "42271500", + "42271502", + "42271503", + "42271504", + "42271505", + "42271517", + "42271600", + "42271602", + "42271604", + "42271609", + "42271610", + "42271651", + "42271700", + "42271701", + "42271702", + "42271703", + "42271704", + "42271705", + "42271706", + "42271707", + "42271708", + "42271709", + "42271710", + "42271711", + "42271712", + "42271713", + "42271714", + "42271715", + "42271716", + "42271717", + "42271718", + "42271719", + "42271720", + "42271721", + "42271722", + "42271728", + "42271729", + "42271730", + "42271800", + "42271801", + "42271802", + "42271803", + "42271807", + "42271900", + "42271902", + "42271903", + "42271904", + "42271905", + "42271910", + "42271919", + "42271931", + "42272000", + "42272001", + "42272003", + "42272004", + "42272005", + "42272006", + "42272007", + "42272008", + "42272009", + "42272017", + "42272020", + "42272100", + "42272200", + "42272202", + "42272203", + "42272204", + "42272205", + "42272207", + "42272215", + "42272216", + "42272217", + "42272218", + "42272219", + "42272220", + "42272222", + "42272223", + "42272224", + "42272225", + "42272230", + "42272300", + "42272301", + "42272306", + "42272500", + "42272501", + "42272502", + "42272503", + "42272505", + "42272506", + "42272507", + "42272509", + "42272510", + "42280000", + "42281500", + "42281501", + "42281502", + "42281508", + "42281509", + "42281519", + "42281521", + "42281530", + "42281531", + "42281532", + "42281600", + "42281604", + "42281700", + "42281701", + "42281703", + "42281704", + "42281714", + "42281800", + "42281801", + "42281802", + "42281803", + "42281804", + "42281805", + "42281806", + "42281807", + "42281808", + "42281809", + "42281810", + "42281811", + "42281900", + "42281901", + "42281902", + "42281903", + "42281904", + "42281905", + "42281906", + "42281907", + "42281908", + "42281909", + "42281912", + "42281913", + "42281914", + "42281915", + "42281916", + "42282000", + "42282001", + "42282010", + "42282017", + "42290000", + "42291500", + "42291600", + "42291614", + "42291632", + "42291700", + "42291701", + "42291800", + "42291801", + "42291900", + "42292000", + "42292001", + "42292100", + "42292300", + "42292400", + "42292403", + "42292500", + "42292600", + "42292700", + "42292800", + "42292801", + "42292802", + "42292803", + "42292900", + "42292901", + "42292903", + "42292904", + "42292907", + "42292908", + "42293000", + "42293001", + "42293002", + "42293003", + "42293004", + "42293005", + "42293006", + "42293100", + "42293106", + "42293300", + "42293400", + "42293500", + "42293511", + "42293514", + "42293515", + "42293518", + "42293519", + "42293521", + "42293522", + "42293523", + "42293524", + "42293525", + "42293528", + "42293529", + "42293600", + "42293605", + "42293700", + "42293800", + "42293900", + "42293901", + "42293902", + "42294000", + "42294100", + "42294200", + "42294201", + "42294202", + "42294203", + "42294204", + "42294205", + "42294206", + "42294207", + "42294212", + "42294214", + "42294218", + "42294219", + "42294222", + "42294300", + "42294400", + "42294401", + "42294402", + "42294500", + "42294600", + "42294601", + "42294602", + "42294603", + "42294604", + "42294605", + "42294606", + "42294607", + "42294611", + "42294700", + "42294701", + "42294702", + "42294713", + "42294900", + "42294902", + "42294903", + "42294904", + "42294905", + "42294906", + "42294907", + "42294908", + "42294909", + "42294910", + "42294913", + "42294914", + "42294915", + "42294917", + "42294919", + "42294920", + "42294921", + "42294922", + "42294923", + "42294924", + "42294925", + "42294926", + "42294927", + "42294928", + "42294929", + "42294930", + "42294931", + "42294933", + "42294934", + "42294936", + "42294937", + "42294938", + "42294939", + "42294941", + "42294942", + "42294943", + "42294944", + "42294946", + "42294948", + "42294949", + "42294950", + "42294951", + "42294952", + "42294953", + "42294954", + "42294955", + "42294956", + "42294957", + "42294958", + "42294959", + "42294972", + "42294978", + "42295000", + "42295001", + "42295002", + "42295003", + "42295004", + "42295005", + "42295006", + "42295013", + "42295014", + "42295015", + "42295016", + "42295100", + "42295101", + "42295104", + "42295106", + "42295108", + "42295112", + "42295114", + "42295119", + "42295120", + "42295121", + "42295122", + "42295123", + "42295124", + "42295137", + "42295148", + "42295150", + "42295157", + "42295159", + "42295167", + "42295200", + "42295201", + "42295202", + "42295203", + "42295204", + "42295300", + "42295313", + "42295400", + "42295401", + "42295402", + "42295406", + "42295408", + "42295409", + "42295410", + "42295411", + "42295413", + "42295414", + "42295415", + "42295417", + "42295418", + "42295419", + "42295421", + "42295422", + "42295423", + "42295424", + "42295426", + "42295427", + "42295435", + "42295440", + "42295446", + "42295448", + "42295451", + "42295452", + "42295453", + "42295454", + "42295456", + "42295458", + "42295459", + "42295460", + "42295461", + "42295462", + "42295464", + "42295465", + "42295470", + "42295471", + "42295472", + "42295480", + "42295484", + "42295500", + "42295502", + "42295513", + "42295600", + "42295800", + "42295900", + "42295910", + "42295911", + "42295912", + "42296000", + "42296100", + "42296200", + "42296201", + "42296202", + "42296203", + "42296204", + "42296205", + "42296206", + "42296207", + "42296208", + "42296209", + "42296210", + "42296211", + "42296212", + "42296300", + "42296304", + "42296305", + "42296308", + "42296311", + "42296313", + "42296314", + "42296317", + "42296318", + "42296323", + "42296324", + "42296326", + "42296334", + "42296335", + "42296400", + "42296401", + "42296402", + "42296404", + "42296406", + "42296407", + "42296408", + "42296409", + "42296411", + "42296412", + "42296413", + "42296414", + "42296500", + "42296502", + "42296507", + "42296600", + "42296700", + "42296701", + "42296702", + "42296703", + "42296704", + "42296705", + "42296800", + "42296812", + "42296818", + "42300000", + "42301500", + "42301501", + "42301502", + "42301503", + "42301504", + "42301505", + "42301506", + "42301507", + "42301508", + "42310000", + "42311500", + "42311501", + "42311502", + "42311503", + "42311506", + "42311510", + "42311512", + "42311513", + "42311515", + "42311517", + "42311518", + "42311519", + "42311520", + "42311523", + "42311524", + "42311527", + "42311528", + "42311531", + "42311537", + "42311539", + "42311540", + "42311541", + "42311543", + "42311546", + "42311548", + "42311551", + "42311552", + "42311555", + "42311600", + "42311606", + "42311607", + "42312000", + "42312010", + "42312014", + "42312100", + "42312101", + "42312102", + "42312103", + "42312104", + "42312105", + "42312106", + "42312107", + "42312108", + "42312109", + "42312110", + "42312111", + "42312112", + "42312113", + "42312115", + "42312200", + "42312201", + "42312202", + "42312203", + "42312204", + "42312206", + "42312207", + "42312208", + "42312209", + "42312300", + "42312301", + "42312302", + "42312303", + "42312304", + "42312305", + "42312306", + "42312307", + "42312309", + "42312310", + "42312311", + "42312312", + "42312313", + "42312400", + "42312401", + "42312402", + "42312403", + "42312500", + "42312501", + "42312502", + "42312503", + "42312504", + "42312600", + "42312603", + "42320000", + "43000000", + "43190000", + "43191500", + "43191501", + "43191502", + "43191503", + "43191504", + "43191505", + "43191507", + "43191508", + "43191509", + "43191510", + "43191511", + "43191512", + "43191513", + "43191514", + "43191515", + "43191516", + "43191517", + "43191518", + "43191519", + "43191520", + "43191521", + "43191600", + "43191601", + "43191602", + "43191603", + "43191604", + "43191605", + "43191606", + "43191607", + "43191608", + "43191609", + "43191610", + "43191611", + "43191612", + "43191614", + "43191615", + "43191616", + "43191618", + "43191619", + "43191621", + "43191622", + "43191623", + "43191624", + "43191625", + "43191626", + "43191627", + "43191628", + "43191629", + "43191630", + "43191631", + "43191632", + "43191633", + "43191634", + "43191635", + "43200000", + "43201400", + "43201401", + "43201402", + "43201403", + "43201404", + "43201405", + "43201406", + "43201407", + "43201409", + "43201410", + "43201411", + "43201412", + "43201413", + "43201414", + "43201415", + "43201416", + "43201417", + "43201500", + "43201501", + "43201502", + "43201503", + "43201507", + "43201508", + "43201509", + "43201513", + "43201522", + "43201531", + "43201533", + "43201534", + "43201535", + "43201537", + "43201538", + "43201539", + "43201540", + "43201541", + "43201542", + "43201543", + "43201544", + "43201545", + "43201546", + "43201547", + "43201549", + "43201550", + "43201552", + "43201553", + "43201554", + "43201555", + "43201556", + "43201557", + "43201558", + "43201559", + "43201560", + "43201600", + "43201601", + "43201602", + "43201603", + "43201604", + "43201605", + "43201608", + "43201609", + "43201610", + "43201611", + "43201612", + "43201614", + "43201615", + "43201616", + "43201617", + "43201618", + "43201619", + "43201800", + "43201801", + "43201802", + "43201803", + "43201806", + "43201807", + "43201808", + "43201809", + "43201810", + "43201811", + "43201812", + "43201813", + "43201814", + "43201815", + "43201816", + "43201817", + "43201818", + "43201819", + "43201820", + "43201821", + "43201822", + "43201823", + "43201825", + "43201826", + "43201827", + "43201828", + "43201829", + "43201830", + "43201831", + "43201832", + "43201833", + "43201834", + "43201835", + "43201900", + "43201902", + "43201903", + "43201904", + "43201905", + "43202000", + "43202001", + "43202002", + "43202003", + "43202004", + "43202005", + "43202006", + "43202007", + "43202008", + "43202009", + "43202010", + "43202100", + "43202101", + "43202102", + "43202103", + "43202104", + "43202105", + "43202106", + "43202107", + "43202108", + "43202200", + "43202201", + "43202202", + "43202204", + "43202205", + "43202206", + "43202207", + "43202208", + "43202209", + "43202210", + "43202211", + "43202212", + "43202213", + "43202214", + "43202215", + "43202216", + "43202217", + "43202218", + "43202219", + "43202220", + "43202221", + "43202222", + "43202223", + "43210000", + "43211500", + "43211501", + "43211502", + "43211503", + "43211504", + "43211505", + "43211506", + "43211507", + "43211508", + "43211509", + "43211510", + "43211511", + "43211512", + "43211513", + "43211514", + "43211515", + "43211516", + "43211517", + "43211518", + "43211519", + "43211520", + "43211521", + "43211522", + "43211600", + "43211601", + "43211602", + "43211603", + "43211604", + "43211605", + "43211606", + "43211607", + "43211608", + "43211609", + "43211610", + "43211611", + "43211612", + "43211613", + "43211614", + "43211615", + "43211616", + "43211617", + "43211618", + "43211619", + "43211700", + "43211701", + "43211702", + "43211704", + "43211705", + "43211706", + "43211707", + "43211708", + "43211709", + "43211710", + "43211711", + "43211712", + "43211713", + "43211714", + "43211715", + "43211717", + "43211718", + "43211719", + "43211720", + "43211721", + "43211722", + "43211723", + "43211724", + "43211725", + "43211726", + "43211727", + "43211728", + "43211729", + "43211730", + "43211731", + "43211732", + "43211733", + "43211734", + "43211800", + "43211801", + "43211802", + "43211803", + "43211804", + "43211805", + "43211806", + "43211807", + "43211900", + "43211901", + "43211902", + "43211903", + "43211904", + "43211905", + "43211906", + "43211907", + "43211908", + "43211909", + "43211910", + "43211911", + "43211912", + "43211913", + "43211914", + "43212000", + "43212001", + "43212002", + "43212003", + "43212100", + "43212101", + "43212102", + "43212103", + "43212104", + "43212105", + "43212106", + "43212107", + "43212108", + "43212109", + "43212110", + "43212111", + "43212112", + "43212113", + "43212114", + "43212115", + "43212116", + "43212117", + "43212118", + "43212200", + "43212201", + "43220000", + "43221500", + "43221501", + "43221502", + "43221503", + "43221504", + "43221505", + "43221506", + "43221507", + "43221508", + "43221509", + "43221510", + "43221513", + "43221514", + "43221515", + "43221516", + "43221517", + "43221518", + "43221519", + "43221520", + "43221521", + "43221522", + "43221523", + "43221524", + "43221525", + "43221526", + "43221527", + "43221528", + "43221529", + "43221530", + "43221531", + "43221532", + "43221533", + "43221534", + "43221537", + "43221600", + "43221601", + "43221602", + "43221603", + "43221604", + "43221700", + "43221701", + "43221702", + "43221703", + "43221704", + "43221705", + "43221706", + "43221707", + "43221708", + "43221709", + "43221710", + "43221711", + "43221712", + "43221713", + "43221714", + "43221715", + "43221716", + "43221717", + "43221718", + "43221719", + "43221720", + "43221721", + "43221722", + "43221723", + "43221724", + "43221725", + "43221726", + "43221727", + "43221728", + "43221729", + "43221730", + "43221731", + "43221732", + "43221733", + "43221734", + "43221735", + "43221736", + "43221737", + "43221738", + "43221739", + "43221740", + "43221741", + "43221742", + "43221743", + "43221744", + "43221745", + "43221746", + "43221747", + "43221748", + "43221749", + "43221750", + "43221800", + "43221801", + "43221802", + "43221803", + "43221804", + "43221805", + "43221806", + "43221807", + "43221808", + "43221809", + "43221810", + "43221811", + "43222500", + "43222501", + "43222502", + "43222503", + "43222504", + "43222600", + "43222602", + "43222604", + "43222605", + "43222606", + "43222607", + "43222608", + "43222609", + "43222610", + "43222611", + "43222612", + "43222615", + "43222619", + "43222620", + "43222621", + "43222622", + "43222623", + "43222624", + "43222625", + "43222626", + "43222627", + "43222628", + "43222629", + "43222630", + "43222631", + "43222632", + "43222633", + "43222634", + "43222635", + "43222636", + "43222637", + "43222638", + "43222639", + "43222640", + "43222641", + "43222642", + "43222643", + "43222644", + "43222700", + "43222701", + "43222702", + "43222703", + "43222704", + "43222800", + "43222801", + "43222802", + "43222803", + "43222805", + "43222806", + "43222811", + "43222813", + "43222814", + "43222815", + "43222816", + "43222817", + "43222818", + "43222819", + "43222820", + "43222822", + "43222823", + "43222824", + "43222825", + "43222826", + "43222827", + "43222900", + "43222901", + "43222902", + "43222903", + "43223000", + "43223001", + "43223100", + "43223101", + "43223102", + "43223103", + "43223104", + "43223105", + "43223106", + "43223107", + "43223108", + "43223109", + "43223110", + "43223111", + "43223112", + "43223113", + "43223200", + "43223201", + "43223202", + "43223203", + "43223204", + "43223205", + "43223206", + "43223207", + "43223208", + "43223209", + "43223210", + "43223211", + "43223212", + "43223300", + "43223301", + "43223302", + "43223303", + "43223305", + "43223306", + "43223307", + "43223308", + "43223309", + "43223310", + "43223311", + "43223312", + "43223313", + "43223314", + "43223315", + "43223316", + "43223317", + "43223318", + "43223319", + "43223320", + "43223321", + "43223322", + "43223323", + "43223324", + "43223325", + "43223326", + "43223327", + "43223328", + "43223329", + "43223330", + "43223331", + "43223332", + "43223333", + "43223334", + "43223335", + "43223336", + "43223337", + "43223338", + "43223339", + "43223340", + "43223341", + "43223342", + "43223343", + "43230000", + "43231500", + "43231501", + "43231503", + "43231505", + "43231506", + "43231507", + "43231508", + "43231509", + "43231510", + "43231511", + "43231512", + "43231513", + "43231514", + "43231515", + "43231516", + "43231517", + "43231600", + "43231601", + "43231602", + "43231603", + "43231604", + "43231605", + "43231606", + "43232000", + "43232001", + "43232002", + "43232003", + "43232004", + "43232005", + "43232100", + "43232101", + "43232102", + "43232103", + "43232104", + "43232105", + "43232106", + "43232107", + "43232108", + "43232110", + "43232111", + "43232112", + "43232200", + "43232201", + "43232202", + "43232203", + "43232204", + "43232205", + "43232300", + "43232301", + "43232302", + "43232303", + "43232304", + "43232305", + "43232306", + "43232307", + "43232309", + "43232310", + "43232311", + "43232312", + "43232313", + "43232314", + "43232400", + "43232401", + "43232402", + "43232403", + "43232404", + "43232405", + "43232406", + "43232407", + "43232408", + "43232409", + "43232500", + "43232501", + "43232502", + "43232503", + "43232504", + "43232505", + "43232506", + "43232507", + "43232508", + "43232509", + "43232510", + "43232600", + "43232601", + "43232602", + "43232603", + "43232604", + "43232605", + "43232606", + "43232607", + "43232608", + "43232609", + "43232610", + "43232611", + "43232612", + "43232613", + "43232614", + "43232615", + "43232616", + "43232617", + "43232618", + "43232619", + "43232620", + "43232700", + "43232701", + "43232702", + "43232703", + "43232704", + "43232705", + "43232800", + "43232801", + "43232802", + "43232803", + "43232804", + "43232805", + "43232900", + "43232901", + "43232902", + "43232903", + "43232904", + "43232905", + "43232906", + "43232907", + "43232908", + "43232909", + "43232910", + "43232911", + "43232912", + "43232913", + "43232914", + "43232915", + "43232916", + "43233000", + "43233001", + "43233002", + "43233004", + "43233005", + "43233006", + "43233200", + "43233201", + "43233203", + "43233204", + "43233205", + "43233400", + "43233401", + "43233402", + "43233403", + "43233404", + "43233405", + "43233406", + "43233407", + "43233410", + "43233411", + "43233413", + "43233414", + "43233415", + "43233416", + "43233417", + "43233418", + "43233419", + "43233420", + "43233421", + "43233500", + "43233501", + "43233502", + "43233503", + "43233504", + "43233505", + "43233506", + "43233507", + "43233508", + "43233509", + "43233510", + "43233511", + "43233512", + "43233513", + "43233600", + "43233601", + "43233602", + "43233603", + "43233700", + "43233701", + "44000000", + "44100000", + "44101500", + "44101501", + "44101503", + "44101504", + "44101505", + "44101506", + "44101507", + "44101508", + "44101509", + "44101510", + "44101511", + "44101600", + "44101601", + "44101602", + "44101603", + "44101604", + "44101605", + "44101606", + "44101607", + "44101608", + "44101700", + "44101701", + "44101702", + "44101703", + "44101704", + "44101705", + "44101706", + "44101707", + "44101708", + "44101709", + "44101710", + "44101711", + "44101712", + "44101713", + "44101714", + "44101715", + "44101716", + "44101718", + "44101719", + "44101720", + "44101721", + "44101722", + "44101723", + "44101724", + "44101725", + "44101726", + "44101727", + "44101728", + "44101729", + "44101730", + "44101800", + "44101802", + "44101803", + "44101804", + "44101805", + "44101806", + "44101807", + "44101808", + "44101809", + "44101810", + "44101900", + "44101901", + "44101902", + "44101903", + "44101904", + "44102000", + "44102001", + "44102002", + "44102003", + "44102004", + "44102100", + "44102101", + "44102102", + "44102103", + "44102104", + "44102105", + "44102106", + "44102107", + "44102108", + "44102109", + "44102200", + "44102201", + "44102202", + "44102203", + "44102300", + "44102301", + "44102302", + "44102303", + "44102304", + "44102305", + "44102306", + "44102307", + "44102400", + "44102402", + "44102403", + "44102404", + "44102405", + "44102406", + "44102407", + "44102408", + "44102409", + "44102411", + "44102412", + "44102413", + "44102414", + "44102500", + "44102501", + "44102502", + "44102503", + "44102504", + "44102600", + "44102602", + "44102603", + "44102604", + "44102605", + "44102606", + "44102607", + "44102608", + "44102609", + "44102610", + "44102800", + "44102801", + "44102802", + "44102803", + "44102804", + "44102805", + "44102806", + "44102900", + "44102901", + "44102902", + "44102903", + "44102904", + "44102905", + "44102906", + "44102907", + "44102908", + "44102909", + "44102910", + "44102911", + "44102912", + "44102913", + "44103000", + "44103001", + "44103002", + "44103003", + "44103004", + "44103005", + "44103100", + "44103101", + "44103103", + "44103104", + "44103105", + "44103106", + "44103107", + "44103108", + "44103109", + "44103110", + "44103111", + "44103112", + "44103113", + "44103114", + "44103116", + "44103117", + "44103118", + "44103119", + "44103120", + "44103121", + "44103122", + "44103123", + "44103124", + "44103125", + "44103126", + "44103127", + "44103200", + "44103201", + "44103202", + "44103203", + "44103204", + "44103205", + "44103206", + "44103207", + "44103500", + "44103502", + "44103503", + "44103504", + "44103505", + "44103506", + "44103507", + "44103508", + "44103600", + "44103601", + "44110000", + "44111500", + "44111501", + "44111502", + "44111503", + "44111506", + "44111507", + "44111509", + "44111510", + "44111511", + "44111512", + "44111513", + "44111514", + "44111515", + "44111516", + "44111517", + "44111518", + "44111519", + "44111520", + "44111521", + "44111522", + "44111523", + "44111600", + "44111601", + "44111603", + "44111604", + "44111605", + "44111607", + "44111608", + "44111609", + "44111610", + "44111611", + "44111612", + "44111613", + "44111614", + "44111615", + "44111616", + "44111617", + "44111618", + "44111800", + "44111801", + "44111802", + "44111803", + "44111804", + "44111805", + "44111806", + "44111807", + "44111808", + "44111809", + "44111810", + "44111812", + "44111813", + "44111814", + "44111815", + "44111816", + "44111817", + "44111818", + "44111900", + "44111901", + "44111902", + "44111903", + "44111904", + "44111905", + "44111906", + "44111907", + "44111908", + "44111909", + "44111910", + "44111911", + "44111912", + "44111913", + "44111914", + "44112000", + "44112001", + "44112002", + "44112004", + "44112005", + "44112006", + "44112007", + "44112008", + "44120000", + "44121500", + "44121501", + "44121503", + "44121504", + "44121505", + "44121506", + "44121507", + "44121508", + "44121509", + "44121510", + "44121511", + "44121512", + "44121513", + "44121600", + "44121604", + "44121605", + "44121611", + "44121612", + "44121613", + "44121614", + "44121615", + "44121617", + "44121618", + "44121619", + "44121620", + "44121621", + "44121622", + "44121623", + "44121624", + "44121625", + "44121626", + "44121627", + "44121628", + "44121630", + "44121631", + "44121632", + "44121633", + "44121634", + "44121635", + "44121636", + "44121700", + "44121701", + "44121702", + "44121703", + "44121704", + "44121705", + "44121706", + "44121707", + "44121708", + "44121709", + "44121710", + "44121711", + "44121712", + "44121713", + "44121714", + "44121715", + "44121716", + "44121717", + "44121718", + "44121719", + "44121720", + "44121721", + "44121800", + "44121801", + "44121802", + "44121804", + "44121805", + "44121806", + "44121807", + "44121808", + "44121809", + "44121900", + "44121902", + "44121904", + "44121905", + "44121906", + "44121907", + "44121908", + "44122000", + "44122001", + "44122002", + "44122003", + "44122005", + "44122008", + "44122009", + "44122010", + "44122011", + "44122012", + "44122013", + "44122014", + "44122015", + "44122016", + "44122017", + "44122018", + "44122019", + "44122020", + "44122021", + "44122022", + "44122023", + "44122024", + "44122025", + "44122026", + "44122027", + "44122028", + "44122029", + "44122030", + "44122031", + "44122032", + "44122033", + "44122034", + "44122035", + "44122036", + "44122037", + "44122100", + "44122101", + "44122103", + "44122104", + "44122105", + "44122106", + "44122107", + "44122109", + "44122110", + "44122111", + "44122112", + "44122113", + "44122114", + "44122115", + "44122116", + "44122117", + "44122118", + "44122119", + "44122120", + "44122121", + "44122122", + "45000000", + "45100000", + "45101500", + "45101501", + "45101502", + "45101503", + "45101504", + "45101505", + "45101506", + "45101507", + "45101508", + "45101509", + "45101510", + "45101511", + "45101512", + "45101513", + "45101514", + "45101515", + "45101516", + "45101517", + "45101518", + "45101520", + "45101600", + "45101602", + "45101603", + "45101604", + "45101606", + "45101607", + "45101608", + "45101609", + "45101610", + "45101611", + "45101612", + "45101613", + "45101614", + "45101615", + "45101616", + "45101700", + "45101701", + "45101702", + "45101703", + "45101704", + "45101705", + "45101706", + "45101707", + "45101708", + "45101709", + "45101710", + "45101711", + "45101800", + "45101801", + "45101802", + "45101803", + "45101804", + "45101805", + "45101806", + "45101807", + "45101808", + "45101900", + "45101901", + "45101902", + "45101903", + "45101904", + "45101905", + "45102000", + "45102001", + "45102002", + "45102003", + "45102004", + "45102005", + "45110000", + "45111400", + "45111401", + "45111402", + "45111500", + "45111501", + "45111502", + "45111503", + "45111504", + "45111600", + "45111601", + "45111602", + "45111603", + "45111604", + "45111605", + "45111606", + "45111607", + "45111608", + "45111609", + "45111610", + "45111612", + "45111613", + "45111614", + "45111615", + "45111616", + "45111617", + "45111618", + "45111619", + "45111620", + "45111700", + "45111701", + "45111702", + "45111703", + "45111704", + "45111705", + "45111706", + "45111707", + "45111708", + "45111709", + "45111710", + "45111711", + "45111712", + "45111713", + "45111714", + "45111715", + "45111716", + "45111717", + "45111718", + "45111719", + "45111720", + "45111721", + "45111722", + "45111723", + "45111724", + "45111725", + "45111800", + "45111801", + "45111802", + "45111803", + "45111804", + "45111805", + "45111806", + "45111807", + "45111808", + "45111809", + "45111810", + "45111811", + "45111812", + "45111813", + "45111814", + "45111815", + "45111816", + "45111817", + "45111818", + "45111819", + "45111820", + "45111821", + "45111822", + "45111823", + "45111824", + "45111825", + "45111826", + "45111827", + "45111828", + "45111829", + "45111900", + "45111901", + "45111902", + "45112000", + "45112001", + "45112002", + "45112003", + "45112004", + "45120000", + "45121500", + "45121501", + "45121502", + "45121503", + "45121504", + "45121505", + "45121506", + "45121510", + "45121511", + "45121512", + "45121513", + "45121514", + "45121515", + "45121516", + "45121517", + "45121518", + "45121519", + "45121520", + "45121521", + "45121522", + "45121523", + "45121600", + "45121601", + "45121602", + "45121603", + "45121604", + "45121605", + "45121606", + "45121607", + "45121608", + "45121609", + "45121610", + "45121611", + "45121612", + "45121613", + "45121614", + "45121615", + "45121616", + "45121617", + "45121618", + "45121619", + "45121620", + "45121621", + "45121622", + "45121623", + "45121624", + "45121625", + "45121626", + "45121627", + "45121628", + "45121629", + "45121630", + "45121631", + "45121632", + "45121700", + "45121701", + "45121702", + "45121703", + "45121704", + "45121705", + "45121706", + "45121707", + "45121708", + "45121709", + "45121710", + "45121711", + "45121712", + "45121713", + "45121714", + "45121715", + "45121716", + "45121717", + "45121718", + "45121719", + "45121720", + "45121721", + "45121800", + "45121801", + "45121802", + "45121803", + "45121804", + "45121805", + "45121806", + "45121807", + "45121808", + "45121809", + "45121810", + "45130000", + "45131500", + "45131501", + "45131502", + "45131503", + "45131505", + "45131506", + "45131507", + "45131508", + "45131509", + "45131510", + "45131600", + "45131601", + "45131604", + "45131700", + "45131701", + "45140000", + "45141500", + "45141501", + "45141502", + "45141503", + "45141504", + "45141600", + "45141601", + "45141602", + "45141603", + "45141604", + "45141605", + "45141606", + "45141607", + "45141608", + "45141609", + "45141610", + "45141611", + "45141612", + "46000000", + "46100000", + "46101500", + "46101504", + "46101505", + "46101600", + "46101700", + "46101800", + "46101802", + "46110000", + "46111500", + "46111504", + "46111505", + "46111506", + "46120000", + "46130000", + "46140000", + "46150000", + "46151500", + "46151501", + "46151502", + "46151503", + "46151504", + "46151505", + "46151506", + "46151507", + "46151508", + "46151509", + "46151600", + "46151601", + "46151602", + "46151604", + "46151605", + "46151606", + "46151607", + "46151608", + "46151609", + "46151610", + "46151700", + "46151702", + "46151703", + "46151704", + "46151705", + "46151706", + "46151707", + "46151708", + "46151709", + "46151710", + "46151711", + "46151712", + "46151713", + "46151714", + "46151715", + "46151716", + "46151717", + "46151800", + "46151801", + "46151802", + "46151900", + "46151901", + "46160000", + "46161500", + "46161501", + "46161502", + "46161503", + "46161504", + "46161506", + "46161516", + "46161528", + "46161534", + "46161535", + "46161536", + "46161537", + "46161538", + "46161600", + "46161601", + "46161602", + "46161603", + "46161604", + "46161605", + "46161700", + "46161701", + "46161702", + "46161703", + "46161704", + "46161705", + "46161706", + "46161707", + "46161708", + "46161710", + "46161711", + "46161712", + "46161713", + "46161714", + "46161715", + "46170000", + "46171500", + "46171525", + "46171600", + "46171602", + "46171603", + "46171604", + "46171605", + "46171606", + "46171607", + "46171608", + "46171609", + "46171610", + "46171611", + "46171612", + "46171613", + "46171615", + "46171616", + "46171617", + "46171618", + "46171619", + "46171620", + "46171621", + "46171622", + "46171623", + "46171624", + "46171625", + "46171626", + "46171627", + "46171628", + "46171629", + "46171630", + "46171631", + "46171632", + "46171633", + "46171634", + "46171635", + "46171636", + "46171637", + "46171638", + "46171639", + "46171640", + "46171641", + "46171642", + "46171643", + "46171644", + "46171645", + "46171646", + "46171648", + "46171649", + "46171650", + "46171700", + "46171701", + "46180000", + "46181500", + "46181501", + "46181502", + "46181503", + "46181504", + "46181506", + "46181507", + "46181508", + "46181509", + "46181512", + "46181532", + "46181540", + "46181541", + "46181543", + "46181552", + "46181555", + "46181566", + "46181600", + "46181601", + "46181602", + "46181603", + "46181604", + "46181605", + "46181606", + "46181612", + "46181700", + "46181701", + "46181702", + "46181704", + "46181705", + "46181800", + "46181801", + "46181802", + "46181804", + "46181810", + "46181812", + "46181900", + "46181902", + "46182000", + "46182001", + "46182002", + "46182003", + "46182004", + "46182005", + "46182006", + "46182007", + "46182008", + "46182010", + "46182100", + "46182101", + "46182103", + "46182104", + "46182105", + "46182107", + "46182200", + "46182300", + "46182301", + "46182302", + "46182306", + "46182307", + "46182309", + "46182314", + "46182400", + "46182401", + "46182402", + "46182407", + "46182500", + "46182504", + "46182505", + "46190000", + "46191500", + "46191501", + "46191502", + "46191503", + "46191504", + "46191505", + "46191506", + "46191507", + "46191508", + "46191509", + "46191510", + "46191511", + "46191600", + "46191601", + "46191602", + "46191603", + "46191604", + "46191605", + "46191606", + "46191607", + "46191608", + "46191609", + "46191610", + "46191611", + "46191612", + "46191613", + "46191614", + "46191615", + "46191616", + "46191617", + "46191618", + "46191619", + "46191620", + "46191621", + "46191623", + "46191624", + "46191625", + "46200000", + "46201000", + "46201001", + "46201002", + "46201100", + "46201101", + "46201102", + "46210000", + "46211500", + "46211501", + "46211502", + "46211503", + "46211504", + "46211600", + "46211601", + "46211602", + "46211603", + "46211604", + "46220000", + "46221500", + "46221501", + "46221502", + "46221503", + "46221504", + "46221505", + "46221506", + "46221507", + "46221508", + "46221509", + "46221510", + "46221511", + "46221512", + "46221513", + "47000000", + "47100000", + "47101500", + "47101501", + "47101502", + "47101503", + "47101504", + "47101506", + "47101507", + "47101508", + "47101510", + "47101512", + "47101513", + "47101514", + "47101517", + "47101521", + "47101522", + "47101523", + "47101524", + "47101525", + "47101528", + "47101529", + "47101530", + "47101531", + "47101532", + "47101534", + "47101535", + "47101536", + "47101537", + "47101538", + "47101576", + "47101600", + "47101601", + "47101605", + "47101606", + "47101609", + "47101611", + "47101614", + "47110000", + "47111500", + "47111501", + "47111502", + "47111503", + "47111507", + "47111509", + "47111510", + "47111600", + "47111700", + "47120000", + "47121500", + "47121501", + "47121502", + "47121600", + "47121602", + "47121605", + "47121606", + "47121608", + "47121700", + "47121701", + "47121702", + "47121703", + "47121704", + "47121705", + "47121706", + "47121707", + "47121708", + "47121709", + "47121710", + "47121800", + "47121801", + "47121802", + "47121803", + "47121804", + "47121805", + "47121806", + "47121807", + "47121808", + "47121809", + "47121810", + "47121811", + "47121812", + "47121813", + "47121814", + "47121815", + "47121816", + "47121900", + "47121901", + "47121902", + "47121903", + "47130000", + "47131500", + "47131501", + "47131502", + "47131600", + "47131601", + "47131602", + "47131603", + "47131604", + "47131605", + "47131608", + "47131611", + "47131617", + "47131618", + "47131700", + "47131701", + "47131702", + "47131703", + "47131704", + "47131800", + "47131801", + "47131803", + "47131804", + "47131805", + "47131807", + "47131808", + "47131810", + "47131811", + "47131824", + "47131829", + "47131900", + "47131901", + "47131902", + "47131903", + "47132100", + "47132101", + "47132102", + "48000000", + "48100000", + "48101500", + "48101501", + "48101502", + "48101503", + "48101504", + "48101505", + "48101506", + "48101507", + "48101508", + "48101509", + "48101510", + "48101511", + "48101512", + "48101513", + "48101514", + "48101515", + "48101516", + "48101517", + "48101518", + "48101519", + "48101520", + "48101521", + "48101522", + "48101523", + "48101524", + "48101525", + "48101526", + "48101527", + "48101528", + "48101529", + "48101530", + "48101531", + "48101532", + "48101533", + "48101534", + "48101535", + "48101536", + "48101537", + "48101538", + "48101539", + "48101540", + "48101541", + "48101542", + "48101543", + "48101544", + "48101545", + "48101546", + "48101600", + "48101601", + "48101602", + "48101603", + "48101604", + "48101605", + "48101606", + "48101607", + "48101608", + "48101609", + "48101610", + "48101611", + "48101612", + "48101613", + "48101614", + "48101615", + "48101616", + "48101617", + "48101618", + "48101619", + "48101700", + "48101701", + "48101702", + "48101703", + "48101704", + "48101705", + "48101706", + "48101707", + "48101708", + "48101709", + "48101710", + "48101711", + "48101712", + "48101713", + "48101714", + "48101715", + "48101716", + "48101800", + "48101801", + "48101802", + "48101803", + "48101804", + "48101805", + "48101806", + "48101807", + "48101808", + "48101809", + "48101810", + "48101811", + "48101812", + "48101813", + "48101814", + "48101815", + "48101816", + "48101817", + "48101818", + "48101819", + "48101820", + "48101821", + "48101900", + "48101901", + "48101902", + "48101903", + "48101904", + "48101905", + "48101906", + "48101907", + "48101908", + "48101909", + "48101910", + "48101911", + "48101912", + "48101913", + "48101914", + "48101915", + "48101916", + "48101917", + "48101918", + "48101919", + "48101920", + "48101921", + "48101926", + "48102000", + "48102001", + "48102002", + "48102003", + "48102004", + "48102005", + "48102006", + "48102007", + "48102008", + "48102009", + "48102010", + "48102100", + "48102101", + "48102102", + "48102103", + "48102104", + "48102105", + "48102106", + "48102107", + "48102108", + "48110000", + "48120000", + "48130000", + "48131500", + "48131502", + "49000000", + "49100000", + "49101600", + "49101602", + "49101700", + "49101701", + "49101702", + "49120000", + "49121500", + "49121502", + "49121503", + "49121504", + "49121505", + "49121506", + "49121507", + "49121508", + "49121509", + "49121510", + "49121600", + "49121601", + "49121602", + "49121603", + "49130000", + "49131500", + "49131501", + "49140000", + "49141500", + "49141501", + "49141502", + "49141503", + "49141504", + "49141505", + "49141506", + "49141507", + "49141508", + "49141509", + "49150000", + "49151500", + "49151501", + "49151502", + "49160000", + "49161500", + "49161501", + "49161503", + "49161504", + "49161505", + "49161506", + "49161509", + "49161600", + "49161601", + "49161602", + "49161603", + "49161604", + "49161607", + "49161608", + "49161700", + "49161702", + "49170000", + "49171500", + "49171501", + "49171503", + "49171600", + "49171601", + "49180000", + "49181500", + "49181501", + "49181507", + "49200000", + "49201500", + "49201501", + "49201503", + "49201504", + "49201512", + "49201518", + "49201600", + "49201601", + "49201603", + "49201612", + "49210000", + "49211600", + "49211800", + "49211802", + "49211803", + "49211804", + "49211805", + "49211806", + "49211807", + "49211808", + "49211809", + "49211811", + "49220000", + "49221500", + "49221501", + "49221502", + "49221505", + "49221506", + "49221511", + "49240000", + "49241500", + "49241501", + "49241503", + "49241700", + "49241701", + "49241704", + "50000000", + "50100000", + "50101700", + "50110000", + "50111500", + "50111513", + "50120000", + "50121500", + "50121537", + "50121538", + "50121539", + "50121541", + "50121542", + "50130000", + "50131600", + "50131700", + "50131701", + "50131704", + "50131800", + "50131801", + "50131802", + "50131803", + "50150000", + "50151500", + "50151513", + "50151514", + "50151517", + "50151518", + "50151519", + "50151520", + "50151521", + "50151600", + "50151604", + "50160000", + "50161500", + "50161509", + "50161800", + "50161816", + "50170000", + "50171500", + "50171548", + "50171550", + "50171551", + "50171552", + "50180000", + "50181700", + "50181708", + "50181709", + "50181710", + "50181900", + "50181901", + "50190000", + "50191500", + "50191505", + "50191506", + "50191507", + "50192100", + "50192300", + "50192400", + "50192500", + "50192600", + "50192700", + "50192800", + "50192900", + "50193000", + "50193100", + "50193200", + "50200000", + "50201700", + "50201706", + "50201709", + "50201710", + "50201711", + "50201713", + "50201714", + "50201715", + "50201717", + "50202200", + "50202300", + "50202301", + "50202306", + "50202312", + "50210000", + "50220000", + "50221000", + "50221002", + "50221100", + "50221102", + "50221108", + "50221111", + "50221112", + "50221113", + "50221114", + "50221115", + "50221300", + "50221301", + "50221303", + "50221304", + "50221305", + "50221306", + "50221307", + "50300000", + "50301500", + "50301501", + "50301502", + "50301503", + "50301504", + "50301505", + "50301506", + "50301507", + "50301508", + "50301509", + "50301510", + "50301511", + "50301512", + "50301513", + "50301514", + "50301515", + "50301516", + "50301517", + "50310000", + "50311500", + "50311501", + "50311502", + "50311503", + "50311504", + "50311505", + "50311506", + "50311507", + "50311508", + "50311509", + "50311510", + "50311511", + "50311512", + "50311513", + "50311514", + "50311515", + "50311516", + "50311517", + "50320000", + "50321500", + "50321501", + "50330000", + "50331500", + "50331501", + "50331502", + "50340000", + "50341500", + "50341501", + "50360000", + "50361500", + "50361501", + "50370000", + "50371500", + "50371501", + "50380000", + "50400000", + "50401500", + "50401501", + "50403400", + "50404500", + "50404509", + "50407000", + "50408000", + "50410000", + "50411500", + "50411501", + "50420000", + "50421500", + "50421501", + "50421800", + "50421834", + "50421853", + "50421854", + "50421855", + "50421856", + "50421857", + "50424000", + "50424006", + "50424007", + "50425400", + "50425407", + "50425408", + "50425409", + "50425410", + "50425600", + "50425610", + "50430000", + "50431500", + "50431501", + "50440000", + "50441500", + "50441501", + "50450000", + "50451500", + "50451501", + "50460000", + "50461500", + "50461501", + "50465300", + "50465307", + "50466800", + "50466818", + "50470000", + "50471500", + "50471501", + "50500000", + "50501500", + "50501501", + "50501502", + "50501503", + "50501504", + "50501505", + "50501506", + "50501507", + "50501508", + "50501509", + "50501510", + "50501511", + "50501512", + "50501513", + "50501600", + "50501700", + "50501708", + "50501709", + "50501710", + "50501711", + "50501712", + "50501713", + "50501714", + "50501715", + "50501716", + "50501717", + "50501718", + "50501719", + "50501720", + "50501721", + "50501722", + "50501723", + "50501724", + "50501725", + "50501726", + "50501727", + "50501800", + "50501804", + "50501900", + "50501901", + "50501902", + "50501903", + "50501904", + "51000000", + "51100000", + "51101600", + "51101602", + "51101604", + "51101607", + "51101612", + "51101613", + "51101614", + "51101616", + "51101618", + "51101620", + "51101629", + "51101630", + "51101636", + "51101680", + "51101693", + "51101900", + "51101902", + "51101903", + "51101904", + "51101905", + "51101906", + "51101907", + "51101908", + "51101911", + "51101912", + "51101913", + "51101914", + "51101915", + "51101923", + "51101928", + "51101929", + "51102800", + "51102811", + "51102818", + "51102821", + "51102822", + "51102823", + "51102832", + "51102842", + "51102844", + "51102852", + "51102856", + "51102858", + "51102862", + "51102863", + "51102864", + "51102871", + "51102872", + "51102878", + "51102900", + "51102901", + "51102904", + "51102905", + "51102907", + "51102909", + "51102910", + "51110000", + "51111600", + "51111602", + "51111606", + "51111610", + "51111617", + "51111625", + "51111629", + "51111642", + "51111650", + "51111659", + "51111700", + "51111704", + "51111716", + "51111717", + "51111728", + "51111731", + "51111733", + "51111736", + "51111739", + "51111740", + "51111742", + "51111746", + "51111758", + "51111761", + "51111765", + "51111766", + "51111767", + "51111772", + "51111778", + "51111779", + "51111780", + "51111781", + "51111782", + "51111783", + "51111784", + "51111785", + "51111786", + "51111800", + "51111802", + "51111803", + "51111805", + "51111807", + "51111815", + "51111820", + "51111824", + "51111828", + "51111830", + "51111833", + "51111838", + "51111842", + "51111855", + "51111856", + "51111862", + "51111863", + "51111873", + "51111874", + "51111875", + "51111876", + "51111877", + "51111878", + "51111900", + "51111901", + "51111904", + "51111906", + "51112000", + "51112001", + "51112002", + "51112004", + "51112005", + "51112006", + "51112008", + "51112010", + "51112012", + "51112014", + "51112015", + "51112016", + "51112017", + "51112020", + "51112021", + "51112022", + "51112023", + "51112026", + "51112027", + "51112028", + "51112029", + "51112030", + "51112031", + "51112032", + "51112033", + "51112034", + "51112035", + "51112037", + "51112088", + "51112300", + "51112301", + "51112400", + "51112402", + "51112500", + "51112503", + "51112505", + "51112507", + "51112508", + "51112510", + "51112513", + "51112600", + "51112601", + "51112700", + "51112701", + "51112702", + "51112705", + "51112800", + "51112804", + "51112900", + "51112901", + "51112902", + "51113000", + "51113500", + "51113501", + "51113502", + "51113503", + "51120000", + "51121500", + "51121583", + "51122600", + "51122601", + "51122603", + "51122606", + "51123500", + "51123501", + "51123600", + "51123601", + "51123900", + "51123906", + "51124100", + "51124101", + "51124400", + "51124404", + "51124500", + "51124503", + "51130000", + "51131500", + "51131506", + "51131507", + "51131520", + "51131524", + "51131525", + "51131526", + "51131600", + "51131602", + "51131604", + "51131607", + "51131615", + "51131621", + "51131624", + "51131629", + "51131631", + "51131641", + "51131642", + "51131649", + "51131650", + "51131665", + "51131700", + "51131701", + "51131703", + "51131705", + "51131711", + "51131740", + "51131800", + "51131801", + "51131808", + "51131811", + "51131812", + "51131817", + "51131819", + "51131820", + "51131821", + "51131823", + "51131827", + "51131828", + "51131829", + "51131830", + "51131831", + "51131832", + "51131833", + "51131834", + "51131900", + "51131901", + "51131908", + "51131909", + "51131911", + "51132000", + "51132001", + "51132100", + "51132102", + "51132200", + "51132225", + "51132300", + "51132308", + "51140000", + "51141500", + "51141501", + "51141504", + "51141507", + "51141509", + "51141513", + "51141518", + "51141522", + "51141526", + "51141528", + "51141531", + "51141535", + "51141538", + "51141563", + "51141566", + "51141590", + "51141596", + "51142300", + "51142302", + "51142315", + "51142400", + "51142411", + "51142413", + "51142423", + "51142433", + "51142435", + "51142500", + "51142501", + "51142517", + "51142538", + "51142565", + "51142568", + "51143000", + "51143100", + "51143103", + "51143104", + "51143112", + "51143200", + "51143202", + "51143203", + "51143222", + "51143400", + "51143406", + "51143409", + "51143500", + "51143501", + "51143502", + "51143900", + "51143908", + "51144000", + "51144014", + "51144015", + "51144600", + "51144601", + "51150000", + "51151500", + "51151512", + "51151514", + "51151527", + "51151529", + "51151541", + "51151544", + "51151548", + "51151549", + "51151600", + "51151604", + "51151606", + "51151616", + "51151617", + "51151625", + "51151657", + "51151666", + "51151674", + "51151675", + "51151900", + "51151904", + "51152000", + "51152004", + "51152005", + "51152006", + "51152017", + "51152046", + "51152051", + "51152064", + "51152067", + "51152070", + "51152072", + "51152075", + "51160000", + "51161500", + "51161524", + "51161563", + "51161569", + "51161574", + "51161700", + "51161702", + "51161705", + "51161708", + "51161709", + "51161800", + "51162000", + "51162002", + "51162012", + "51162030", + "51162038", + "51162039", + "51162040", + "51162041", + "51162042", + "51162043", + "51162100", + "51162101", + "51162103", + "51162104", + "51162106", + "51162107", + "51162300", + "51162357", + "51162600", + "51162603", + "51162626", + "51162700", + "51162701", + "51162702", + "51162704", + "51162713", + "51162728", + "51162732", + "51162747", + "51170000", + "51171500", + "51171505", + "51171510", + "51171511", + "51171600", + "51171605", + "51171607", + "51171610", + "51171614", + "51171628", + "51171630", + "51171641", + "51171700", + "51171714", + "51171724", + "51171800", + "51171806", + "51171807", + "51171808", + "51171816", + "51171820", + "51171822", + "51171823", + "51171838", + "51171839", + "51171840", + "51171858", + "51171900", + "51171901", + "51171905", + "51171906", + "51171909", + "51171910", + "51171911", + "51171915", + "51171916", + "51171917", + "51171926", + "51171932", + "51171935", + "51171962", + "51171973", + "51171974", + "51171980", + "51171984", + "51172100", + "51172148", + "51172200", + "51172201", + "51172300", + "51172305", + "51172308", + "51172309", + "51172310", + "51172311", + "51172319", + "51172320", + "51172321", + "51172324", + "51172327", + "51172328", + "51172332", + "51172333", + "51172338", + "51172340", + "51172400", + "51172410", + "51172413", + "51172481", + "51172483", + "51172484", + "51172485", + "51172486", + "51172487", + "51172490", + "51172800", + "51172833", + "51180000", + "51181500", + "51181578", + "51181579", + "51181600", + "51181604", + "51181605", + "51181606", + "51181608", + "51181613", + "51181614", + "51181625", + "51181629", + "51181900", + "51181901", + "51181912", + "51181927", + "51181931", + "51181932", + "51182000", + "51182002", + "51182014", + "51182024", + "51182027", + "51182035", + "51182047", + "51182071", + "51182100", + "51182101", + "51182102", + "51182106", + "51182108", + "51182200", + "51182201", + "51182202", + "51182203", + "51182204", + "51182206", + "51182207", + "51182214", + "51182222", + "51182300", + "51182302", + "51182400", + "51182406", + "51182415", + "51182416", + "51182417", + "51182426", + "51182428", + "51182435", + "51182441", + "51182500", + "51182501", + "51182700", + "51182709", + "51182710", + "51182711", + "51183300", + "51183301", + "51183303", + "51183306", + "51183500", + "51183505", + "51183510", + "51183600", + "51183601", + "51183603", + "51183607", + "51183608", + "51183610", + "51183611", + "51183613", + "51183614", + "51183615", + "51183622", + "51183623", + "51183700", + "51183706", + "51183800", + "51183801", + "51184000", + "51184004", + "51184007", + "51190000", + "51191500", + "51191502", + "51191504", + "51191507", + "51191509", + "51191515", + "51191517", + "51191549", + "51191554", + "51191555", + "51191572", + "51191600", + "51191602", + "51191604", + "51191605", + "51191607", + "51191609", + "51191800", + "51191802", + "51191806", + "51191900", + "51191909", + "51191915", + "51191917", + "51191918", + "51191919", + "51191923", + "51191967", + "51191968", + "51191970", + "51192000", + "51192001", + "51192002", + "51192300", + "51192317", + "51192318", + "51192400", + "51192429", + "51192443", + "51192445", + "51192458", + "51192459", + "51200000", + "51201500", + "51201569", + "51201571", + "51201573", + "51201574", + "51201575", + "51201576", + "51201580", + "51201600", + "51201604", + "51201606", + "51201607", + "51201608", + "51201609", + "51201610", + "51201615", + "51201616", + "51201617", + "51201618", + "51201620", + "51201621", + "51201623", + "51201624", + "51201625", + "51201626", + "51201627", + "51201628", + "51201629", + "51201631", + "51201632", + "51201633", + "51201634", + "51201646", + "51201647", + "51201648", + "51201652", + "51201653", + "51201654", + "51201655", + "51201656", + "51201657", + "51201658", + "51201659", + "51201660", + "51201700", + "51201702", + "51201703", + "51201704", + "51201705", + "51201800", + "51201802", + "51201803", + "51201805", + "51201806", + "51201810", + "51201811", + "51201812", + "51201831", + "51201900", + "51201901", + "51202000", + "51202002", + "51202200", + "51202203", + "51202204", + "51202206", + "51202207", + "51202300", + "51202306", + "51202400", + "51202401", + "51202402", + "51202403", + "51202405", + "51202406", + "51202409", + "51202411", + "51202412", + "51202413", + "51202414", + "51202416", + "51202417", + "51202500", + "51202501", + "51202600", + "51202603", + "51202700", + "51202701", + "51202800", + "51202801", + "51202803", + "51202804", + "51202805", + "51203100", + "51203101", + "51203200", + "51203201", + "51203202", + "51203203", + "51203300", + "51203301", + "51203302", + "51203303", + "51203400", + "51203401", + "51203402", + "51203403", + "51203600", + "51203605", + "51203800", + "51203801", + "51204000", + "51204001", + "51204200", + "51204201", + "51204202", + "51204203", + "51204204", + "51204205", + "51240000", + "51241100", + "51241103", + "51241110", + "51241128", + "51241131", + "51241133", + "51241143", + "51241144", + "51241200", + "51241205", + "51241209", + "51241215", + "51241227", + "51241232", + "51241235", + "51241237", + "51241243", + "51241246", + "51241262", + "51241263", + "51241500", + "51241513", + "51241522", + "51241544", + "51241555", + "51241560", + "51241565", + "51241600", + "51241603", + "51241605", + "51241660", + "51241800", + "51241886", + "51242200", + "51242209", + "51242300", + "51242302", + "51260000", + "51261700", + "51261701", + "51261702", + "51261703", + "51261704", + "51261705", + "51261706", + "51262000", + "51262002", + "51262400", + "51262404", + "51262410", + "51262414", + "51262900", + "51262907", + "51262914", + "51263000", + "51263002", + "51263009", + "51263100", + "51263101", + "51263105", + "51263122", + "51263139", + "51263151", + "51263162", + "51263169", + "51263175", + "51263400", + "51263406", + "51270000", + "51271600", + "51271613", + "51271622", + "51271623", + "51271629", + "51271636", + "51272000", + "51272006", + "51272100", + "51272111", + "51272200", + "51272207", + "51272300", + "51272302", + "51272400", + "51272401", + "51272406", + "51272408", + "51272900", + "51272901", + "51273000", + "51273009", + "51273900", + "51273921", + "51273937", + "51273950", + "51280000", + "51281500", + "51281501", + "51281502", + "51281503", + "51281504", + "51281507", + "51281509", + "51281513", + "51281518", + "51281519", + "51281520", + "51281521", + "51281600", + "51281607", + "51281614", + "51281616", + "51281618", + "51281624", + "51281626", + "51281627", + "51281632", + "51281651", + "51281659", + "51281675", + "51281700", + "51281702", + "51281703", + "51281710", + "51281711", + "51281712", + "51281713", + "51281714", + "51281716", + "51281717", + "51281800", + "51281801", + "51281803", + "51281805", + "51281806", + "51281818", + "51281819", + "51281821", + "51281823", + "51281900", + "51281902", + "51282000", + "51282001", + "51282003", + "51282004", + "51282005", + "51282100", + "51282101", + "51282109", + "51282200", + "51282201", + "51282202", + "51282208", + "51282300", + "51282301", + "51282302", + "51282303", + "51282304", + "51282308", + "51282309", + "51282310", + "51282317", + "51282327", + "51282400", + "51282404", + "51282407", + "51282409", + "51282411", + "51282500", + "51282502", + "51282506", + "51282511", + "51282514", + "51282517", + "51282523", + "51282600", + "51282602", + "51282610", + "51282700", + "51282701", + "51282702", + "51282703", + "51282800", + "51282801", + "51282804", + "51282808", + "51282900", + "51282901", + "51282902", + "51282909", + "51282916", + "51282921", + "51282926", + "51282931", + "51282932", + "51282944", + "51282951", + "51282953", + "51282956", + "51283000", + "51283002", + "51283003", + "51283006", + "51283100", + "51283101", + "51283106", + "51283107", + "51283108", + "51283110", + "51283112", + "51283200", + "51283210", + "51283300", + "51283301", + "51283303", + "51283400", + "51283401", + "51283402", + "51283403", + "51283404", + "51283405", + "51283406", + "51283407", + "51283408", + "51283409", + "51283410", + "51283411", + "51283412", + "51283413", + "51283414", + "51283415", + "51283416", + "51283417", + "51283418", + "51283419", + "51283420", + "51283421", + "51283422", + "51283423", + "51283424", + "51283500", + "51283501", + "51283502", + "51283505", + "51283507", + "51283509", + "51283600", + "51283601", + "51283602", + "51283603", + "51283604", + "51283700", + "51283701", + "51283702", + "51283705", + "51283706", + "51283709", + "51283711", + "51283712", + "51283717", + "51283718", + "51283719", + "51283724", + "51283725", + "51283726", + "51283800", + "51283801", + "51283804", + "51283900", + "51283901", + "51283904", + "51283908", + "51283941", + "51284000", + "51284002", + "51284004", + "51284006", + "51284012", + "51284014", + "51284017", + "51284027", + "51284035", + "51284043", + "51284100", + "51284103", + "51284104", + "51284106", + "51284108", + "51284109", + "51284115", + "51284119", + "51284121", + "51284135", + "51284136", + "51284141", + "51284150", + "51284300", + "51284303", + "51284500", + "51284502", + "51284600", + "51284603", + "51284605", + "51284610", + "51284613", + "51284900", + "51284903", + "51284911", + "51285000", + "51285003", + "51285004", + "51285005", + "51285006", + "51285100", + "51285101", + "51285300", + "51285302", + "51285307", + "51285500", + "51285502", + "51285600", + "51285900", + "51285907", + "51286200", + "51286201", + "51286206", + "51286500", + "51286501", + "51286800", + "51286801", + "51287000", + "51287004", + "51290000", + "51291700", + "51291712", + "51292000", + "51292011", + "51292012", + "51292019", + "51292023", + "51292027", + "51292900", + "51292908", + "51292921", + "51293000", + "51293002", + "51293012", + "51293400", + "51293402", + "51294000", + "51294001", + "51294400", + "51294403", + "51294500", + "51294513", + "51300000", + "51301800", + "51301802", + "51301900", + "51301904", + "51302000", + "51302004", + "51302300", + "51302308", + "51302309", + "51302318", + "51302320", + "51302325", + "51302336", + "51302337", + "51302400", + "51302401", + "51302403", + "51302404", + "51302500", + "51302503", + "51302700", + "51302701", + "51302900", + "51302901", + "51303000", + "51303001", + "51303002", + "51303100", + "51303104", + "51303400", + "51303402", + "51303403", + "51303407", + "51303600", + "51303611", + "51310000", + "51311900", + "51311901", + "51312100", + "51312105", + "51312200", + "51312204", + "51312300", + "51312304", + "51312309", + "51312400", + "51312401", + "51312405", + "51313000", + "51313100", + "51313101", + "51313111", + "51313112", + "51313120", + "51313200", + "51313205", + "51313218", + "51313300", + "51313301", + "51313305", + "51313400", + "51313401", + "51313415", + "51313421", + "51313422", + "51313424", + "51313700", + "51313702", + "51313709", + "51313800", + "51313801", + "51313802", + "51320000", + "51321500", + "51321501", + "51321505", + "51321600", + "51321604", + "51321700", + "51321701", + "51321708", + "51321800", + "51321804", + "51321808", + "51321900", + "51321901", + "51321904", + "51322200", + "51322201", + "51322205", + "51322300", + "51322301", + "51322700", + "51322704", + "51330000", + "51331900", + "51331901", + "51332000", + "51332003", + "51332006", + "51332500", + "51332501", + "51332700", + "51332703", + "51332800", + "51332807", + "51332812", + "51332814", + "51332822", + "51332831", + "51332840", + "51332855", + "51332880", + "51333200", + "51333202", + "51333400", + "51333410", + "51333413", + "51333500", + "51333502", + "51333600", + "51333601", + "51334200", + "51334204", + "51334207", + "51334300", + "51334303", + "51334306", + "51340000", + "51341500", + "51341501", + "51341600", + "51341604", + "51341800", + "51341801", + "51341802", + "51341803", + "51341805", + "51341806", + "51341807", + "51341900", + "51341901", + "51341903", + "51341904", + "51342300", + "51342301", + "51342304", + "51342305", + "51342307", + "51342308", + "51342309", + "51342310", + "51342311", + "51342313", + "51342316", + "51342400", + "51342402", + "51342500", + "51342501", + "51342503", + "51342506", + "51342700", + "51342701", + "51342702", + "51342709", + "51342710", + "51342715", + "51342900", + "51342901", + "51342902", + "51342904", + "51343000", + "51343002", + "51343004", + "51343005", + "51343100", + "51343101", + "51343110", + "51343115", + "51343116", + "51343200", + "51343201", + "51343203", + "51343204", + "51343500", + "51343502", + "51343504", + "51343509", + "51343511", + "51343700", + "51343702", + "51343704", + "51343800", + "51343801", + "51343803", + "51343804", + "51343806", + "51343808", + "51343809", + "51343810", + "51343811", + "51343812", + "51343813", + "51343814", + "51343816", + "51343820", + "51343821", + "51343822", + "51343826", + "51343827", + "51343828", + "51350000", + "51351500", + "51351509", + "51351510", + "51351511", + "51351514", + "51351600", + "51351605", + "51351606", + "51351608", + "51351609", + "51351612", + "51351613", + "51351627", + "51351635", + "51351636", + "51351637", + "51351800", + "51351804", + "51351900", + "51351912", + "51352000", + "51352005", + "51352006", + "51352008", + "51352400", + "51352404", + "51352413", + "51352414", + "51352422", + "51352426", + "51352435", + "51352436", + "51360000", + "51361500", + "51361501", + "51361800", + "51361809", + "51361900", + "51361918", + "51362600", + "51362601", + "51362604", + "51370000", + "51371600", + "51371601", + "51371604", + "51371800", + "51371803", + "51371900", + "51371910", + "51372000", + "51372003", + "51372015", + "51372022", + "51372031", + "51372036", + "51372040", + "51372100", + "51372107", + "51372108", + "51372125", + "51372127", + "51372300", + "51372305", + "51372321", + "51373200", + "51373204", + "51373300", + "51373341", + "51380000", + "51381500", + "51381502", + "51381504", + "51381505", + "51381700", + "51381701", + "51382700", + "51382702", + "51383300", + "51383304", + "51383315", + "51383400", + "51383401", + "51383500", + "51383507", + "51383510", + "51383900", + "51383905", + "51384500", + "51384509", + "51384511", + "51384514", + "51384522", + "51384600", + "51384607", + "51384627", + "51384800", + "51384802", + "51384803", + "51385600", + "51385608", + "51385800", + "51385804", + "51385805", + "51386600", + "51386609", + "51386615", + "51390000", + "51391600", + "51391602", + "51391616", + "51391700", + "51391703", + "51391717", + "51391722", + "51391726", + "51391734", + "51391739", + "51391743", + "51391746", + "51392400", + "51392403", + "51392408", + "51392412", + "51393400", + "51393405", + "51393600", + "51393604", + "51393606", + "51400000", + "51401500", + "51401501", + "51401505", + "51401516", + "51401518", + "51401525", + "51401533", + "51401538", + "51401550", + "51401569", + "51401570", + "51401700", + "51401705", + "51402200", + "51402206", + "51410000", + "51411600", + "51411605", + "51412000", + "51412004", + "51412600", + "51412601", + "51412700", + "51412702", + "51413200", + "51413204", + "51413207", + "51413212", + "51413300", + "51413301", + "51413500", + "51413504", + "51420000", + "51421500", + "51421501", + "51421504", + "51421505", + "51421800", + "51421802", + "51422100", + "51422101", + "51422122", + "51422200", + "51422202", + "51422205", + "51422206", + "51422300", + "51422302", + "51422303", + "51422306", + "51422315", + "51422327", + "51422331", + "51422340", + "51422342", + "51422354", + "51422356", + "51422364", + "51422400", + "51422408", + "51422415", + "51422417", + "51422421", + "51422425", + "51422434", + "51430000", + "51431500", + "51431507", + "51431600", + "51431602", + "51431609", + "51431614", + "51431700", + "51431708", + "51431800", + "51431801", + "51431803", + "51431900", + "51431902", + "51432300", + "51432305", + "51432313", + "51432315", + "51432400", + "51432401", + "51432500", + "51432503", + "51432600", + "51432606", + "51432700", + "51432705", + "51432800", + "51432803", + "51432805", + "51432806", + "51433300", + "51433303", + "51433305", + "51433700", + "51433707", + "51433708", + "51433800", + "51433804", + "51433900", + "51433902", + "51433903", + "51433915", + "51433924", + "51433925", + "51434500", + "51434502", + "51434900", + "51434907", + "51434908", + "51434909", + "51434931", + "51434938", + "51434945", + "51434949", + "51434958", + "51434959", + "51434960", + "51434961", + "51434962", + "51434963", + "51434964", + "51440000", + "51441600", + "51441619", + "51442000", + "51442001", + "51442004", + "51442007", + "51450000", + "51451600", + "51451604", + "51451800", + "51451801", + "51451900", + "51451907", + "51452100", + "51452101", + "51452200", + "51452201", + "51452202", + "51452300", + "51452301", + "51452302", + "51452305", + "51452307", + "51452400", + "51452401", + "51452402", + "51452500", + "51452501", + "51452502", + "51452600", + "51452601", + "51452700", + "51452701", + "51452800", + "51452801", + "51452900", + "51452901", + "51453000", + "51453001", + "51453200", + "51453201", + "51453400", + "51453401", + "51453404", + "51453500", + "51453501", + "51453502", + "51453600", + "51453601", + "51460000", + "51461600", + "51461606", + "51461607", + "51470000", + "51471500", + "51471502", + "51471505", + "51472000", + "51472002", + "51472300", + "51472302", + "51472600", + "51472601", + "51472800", + "51472802", + "51472803", + "51472805", + "51472900", + "51472901", + "51472902", + "51473000", + "51473001", + "51473003", + "51473013", + "51473016", + "51473020", + "51473100", + "51473104", + "51473200", + "51473203", + "51473300", + "51473302", + "51473307", + "51473500", + "51473502", + "51473503", + "51473504", + "51473600", + "51473602", + "51473700", + "51473704", + "51474000", + "51474001", + "52000000", + "52100000", + "52101500", + "52101517", + "52120000", + "52121500", + "52121501", + "52121505", + "52121508", + "52121600", + "52121700", + "52130000", + "52131500", + "52131600", + "52131700", + "52140000", + "52141500", + "52141501", + "52141502", + "52141509", + "52141600", + "52141700", + "52141800", + "52141804", + "52150000", + "52151500", + "52151501", + "52151504", + "52151600", + "52151700", + "52151800", + "52151900", + "52152000", + "52152100", + "52152101", + "52152200", + "52152300", + "52160000", + "52161500", + "52161502", + "52161505", + "52161511", + "52161512", + "52161514", + "52161515", + "52161516", + "52161518", + "52161520", + "52161523", + "52161524", + "52161526", + "52161535", + "52161542", + "52161543", + "52161553", + "52161600", + "52170000", + "53000000", + "53100000", + "53101500", + "53101600", + "53101606", + "53101700", + "53101800", + "53101806", + "53101807", + "53101900", + "53102000", + "53102100", + "53102200", + "53102300", + "53102305", + "53102400", + "53102402", + "53102500", + "53102501", + "53102504", + "53102505", + "53102511", + "53102516", + "53102600", + "53102700", + "53102701", + "53102702", + "53102703", + "53102704", + "53102705", + "53102706", + "53102707", + "53102708", + "53102709", + "53102710", + "53102712", + "53102715", + "53102716", + "53102717", + "53102718", + "53102719", + "53102800", + "53102900", + "53103000", + "53103005", + "53103100", + "53103101", + "53103200", + "53103201", + "53103300", + "53110000", + "53111500", + "53111501", + "53111502", + "53111503", + "53111504", + "53111505", + "53111600", + "53111700", + "53111800", + "53111900", + "53112000", + "53112100", + "53120000", + "53121500", + "53121501", + "53121502", + "53121503", + "53121600", + "53121601", + "53121602", + "53121603", + "53121700", + "53121701", + "53121705", + "53121706", + "53121800", + "53121801", + "53121802", + "53130000", + "53131500", + "53131501", + "53131502", + "53131503", + "53131504", + "53131505", + "53131506", + "53131507", + "53131508", + "53131509", + "53131510", + "53131600", + "53131601", + "53131602", + "53131603", + "53131604", + "53131605", + "53131606", + "53131607", + "53131608", + "53131609", + "53131610", + "53131611", + "53131612", + "53131613", + "53131614", + "53131615", + "53131616", + "53131617", + "53131618", + "53131621", + "53131622", + "53131624", + "53131625", + "53131626", + "53131627", + "53131628", + "53131629", + "53131630", + "53131634", + "53131635", + "53131637", + "53131639", + "53131641", + "53131643", + "53131647", + "53131648", + "53131649", + "53131651", + "53131652", + "53131662", + "53131663", + "53131664", + "53131665", + "53131666", + "53131667", + "53131700", + "53131702", + "53140000", + "53141600", + "53141602", + "54000000", + "54100000", + "54110000", + "54111500", + "54111501", + "54111600", + "54111601", + "54111603", + "54111700", + "54111701", + "54111709", + "54111710", + "54120000", + "55000000", + "55100000", + "55101500", + "55101501", + "55101502", + "55101503", + "55101504", + "55101505", + "55101506", + "55101507", + "55101509", + "55101510", + "55101513", + "55101514", + "55101515", + "55101516", + "55101517", + "55101518", + "55101519", + "55101520", + "55101521", + "55101522", + "55101523", + "55101524", + "55101525", + "55101526", + "55101527", + "55101528", + "55101529", + "55101530", + "55101531", + "55101532", + "55110000", + "55111500", + "55111501", + "55120000", + "55121500", + "55121501", + "55121502", + "55121503", + "55121600", + "55121601", + "55121602", + "55121604", + "55121605", + "55121606", + "55121607", + "55121608", + "55121609", + "55121700", + "55121701", + "55121702", + "55121703", + "55121704", + "55121705", + "55121706", + "55121707", + "55121708", + "55121710", + "55121715", + "55121800", + "55121801", + "55121802", + "55121803", + "55121804", + "55121806", + "55121807", + "55121808", + "55121900", + "55121901", + "55121902", + "55121903", + "55121904", + "55121905", + "55121906", + "55121907", + "55121908", + "56000000", + "56100000", + "56101500", + "56101502", + "56101503", + "56101504", + "56101507", + "56101508", + "56101509", + "56101510", + "56101513", + "56101514", + "56101515", + "56101516", + "56101518", + "56101519", + "56101520", + "56101529", + "56101530", + "56101531", + "56101532", + "56101535", + "56101539", + "56101542", + "56101543", + "56101547", + "56101600", + "56101700", + "56101701", + "56101702", + "56101703", + "56101704", + "56101705", + "56101706", + "56101707", + "56101708", + "56101710", + "56101711", + "56101712", + "56101715", + "56101716", + "56101718", + "56101719", + "56101722", + "56101800", + "56101900", + "56110000", + "56111500", + "56111501", + "56111507", + "56111509", + "56111511", + "56111513", + "56111514", + "56111600", + "56111601", + "56111602", + "56111603", + "56111604", + "56111605", + "56111606", + "56111700", + "56111701", + "56111800", + "56111802", + "56111806", + "56111900", + "56111906", + "56112000", + "56112100", + "56112106", + "56112108", + "56112109", + "56112200", + "56112300", + "56120000", + "56121000", + "56121400", + "56121500", + "56121501", + "56121502", + "56121503", + "56121504", + "56121505", + "56121506", + "56121507", + "56121508", + "56121509", + "56121510", + "56121700", + "56121900", + "56122000", + "56122001", + "56130000", + "56140000", + "57000000", + "57010000", + "57010100", + "57010101", + "57010102", + "57010103", + "57020000", + "57020100", + "57020101", + "57020102", + "57030000", + "57030100", + "57030101", + "57030102", + "57030103", + "57030104", + "57030105", + "57030106", + "57030107", + "57030108", + "57030109", + "57030110", + "57030111", + "57030112", + "57030200", + "57030300", + "57030301", + "57030302", + "57030303", + "57030304", + "57030305", + "57030400", + "57030401", + "57040000", + "57040100", + "57040101", + "57040102", + "57040103", + "57040104", + "57040105", + "57040200", + "57040201", + "57040300", + "57040301", + "57050000", + "57050100", + "57050101", + "57050102", + "57050103", + "57050104", + "57050105", + "57050200", + "57050201", + "57050202", + "57050203", + "57050204", + "57050205", + "57050300", + "57050301", + "57060000", + "57060100", + "57060101", + "57060102", + "57060200", + "57060201", + "57060202", + "57060203", + "57060204", + "57060205", + "57060206", + "57060208", + "57060300", + "57060301", + "57060302", + "57060303", + "57060400", + "57060401", + "57070000", + "57070100", + "57070101", + "57070102", + "57070103", + "57070104", + "57070105", + "57080000", + "57080100", + "57080101", + "57080102", + "57080103", + "57080104", + "57111100", + "57222100", + "57333100", + "57333200", + "57333300", + "57333400", + "57444100", + "57444200", + "57444300", + "57555100", + "57555200", + "57555300", + "57666100", + "57666200", + "57666300", + "57666400", + "57777100", + "57888100", + "60000000", + "60100000", + "60101700", + "60101734", + "60103700", + "60103701", + "60103702", + "60103704", + "60103900", + "60103905", + "60103915", + "60104100", + "60104200", + "60104201", + "60104202", + "60104203", + "60104204", + "60104400", + "60104700", + "60104701", + "60104702", + "60105300", + "60105301", + "60105302", + "60105303", + "60105304", + "60105305", + "60105306", + "60105307", + "60105308", + "60105309", + "60105600", + "60105613", + "60105627", + "60105900", + "60105901", + "60105902", + "60105903", + "60105904", + "60105905", + "60105906", + "60105907", + "60105908", + "60105915", + "60106100", + "60106101", + "60106102", + "60106104", + "60106108", + "60106200", + "60106201", + "60106202", + "60106203", + "60106204", + "60106205", + "60106206", + "60106208", + "60106209", + "60106300", + "60106301", + "60106302", + "60110000", + "60120000", + "60121300", + "60121301", + "60121600", + "60121606", + "60130000", + "60131000", + "60131001", + "60131003", + "60131006", + "60131100", + "60131101", + "60131102", + "60131104", + "60131105", + "60131200", + "60131201", + "60131202", + "60131203", + "60131204", + "60131207", + "60131300", + "60131301", + "60131302", + "60131303", + "60131304", + "60131305", + "60131306", + "60131307", + "60131308", + "60131400", + "60131401", + "60131402", + "60131403", + "60131404", + "60131405", + "60131406", + "60131500", + "60131501", + "60131503", + "60131504", + "60131505", + "60131506", + "60131507", + "60131508", + "60131509", + "60131512", + "60131520", + "60131600", + "60131601", + "60131700", + "60131701", + "60131702", + "60131703", + "60131800", + "60131801", + "60131802", + "60131803", + "60140000", + "60141000", + "60141100", + "60141102", + "64000000", + "64100000", + "64101700", + "64101701", + "64101702", + "64101703", + "64110000", + "64111700", + "64111705", + "64120000", + "64121500", + "64140000", + "64141700", + "64141701", + "70000000", + "70100000", + "70101500", + "70101501", + "70101502", + "70101503", + "70101504", + "70101507", + "70101510", + "70101600", + "70101601", + "70101602", + "70101603", + "70101607", + "70101700", + "70101701", + "70101702", + "70101703", + "70101704", + "70101800", + "70101801", + "70101802", + "70101803", + "70101804", + "70101805", + "70101806", + "70101900", + "70101901", + "70101902", + "70101903", + "70101904", + "70101905", + "70110000", + "70111500", + "70111501", + "70111502", + "70111503", + "70111504", + "70111505", + "70111506", + "70111507", + "70111508", + "70111600", + "70111700", + "70111701", + "70111702", + "70111703", + "70111704", + "70111706", + "70111707", + "70111708", + "70111709", + "70111710", + "70111711", + "70111712", + "70111713", + "70120000", + "70121500", + "70121501", + "70121502", + "70121503", + "70121504", + "70121505", + "70121600", + "70121601", + "70121602", + "70121603", + "70121604", + "70121605", + "70121606", + "70121607", + "70121608", + "70121610", + "70121700", + "70121701", + "70121703", + "70121704", + "70121705", + "70121706", + "70121800", + "70121801", + "70121802", + "70121803", + "70121900", + "70121901", + "70121902", + "70121903", + "70122000", + "70122001", + "70122002", + "70122003", + "70122004", + "70122005", + "70122006", + "70122007", + "70122008", + "70122009", + "70122010", + "70130000", + "70131500", + "70131501", + "70131502", + "70131503", + "70131506", + "70131600", + "70131601", + "70131603", + "70131604", + "70131605", + "70131700", + "70131701", + "70131702", + "70131703", + "70131704", + "70131705", + "70131706", + "70140000", + "70141500", + "70141501", + "70141503", + "70141507", + "70141508", + "70141512", + "70141515", + "70141516", + "70141520", + "70141600", + "70141601", + "70141602", + "70141604", + "70141605", + "70141700", + "70141701", + "70141702", + "70141800", + "70141801", + "70141802", + "70141803", + "70141804", + "70141900", + "70141901", + "70141902", + "70141903", + "70141904", + "70142000", + "70142001", + "70142002", + "70142003", + "70142004", + "70142005", + "70142006", + "70142007", + "70142008", + "70142009", + "70142010", + "70142011", + "70150000", + "70151500", + "70151501", + "70151505", + "70151506", + "70151507", + "70151510", + "70151600", + "70151601", + "70151602", + "70151603", + "70151604", + "70151605", + "70151606", + "70151700", + "70151701", + "70151703", + "70151706", + "70151800", + "70151801", + "70151802", + "70151803", + "70151804", + "70151805", + "70151806", + "70151807", + "70151900", + "70151901", + "70151902", + "70151903", + "70160000", + "70161500", + "70161501", + "70161600", + "70161601", + "70161700", + "70161701", + "70161702", + "70161703", + "70161704", + "70161705", + "70161706", + "70161710", + "70161711", + "70170000", + "70171500", + "70171501", + "70171502", + "70171503", + "70171504", + "70171505", + "70171506", + "70171507", + "70171600", + "70171601", + "70171602", + "70171603", + "70171604", + "70171605", + "70171606", + "70171607", + "70171700", + "70171701", + "70171702", + "70171703", + "70171704", + "70171705", + "70171706", + "70171707", + "70171708", + "70171709", + "70171710", + "70171800", + "70171801", + "70171802", + "70171803", + "70190000", + "70190100", + "71000000", + "71100000", + "71101700", + "71110000", + "71112300", + "71120000", + "71130000", + "71140000", + "71141100", + "71141103", + "71150000", + "71151100", + "71160000", + "71161000", + "71161600", + "71161605", + "72000000", + "72100000", + "72101500", + "72101501", + "72101504", + "72101505", + "72101506", + "72101507", + "72101508", + "72101509", + "72101510", + "72101511", + "72101512", + "72101513", + "72101514", + "72101515", + "72101516", + "72101517", + "72101518", + "72101519", + "72101520", + "72101521", + "72102100", + "72102101", + "72102102", + "72102103", + "72102104", + "72102105", + "72102106", + "72102900", + "72102902", + "72102903", + "72102905", + "72102906", + "72103100", + "72103101", + "72103102", + "72103103", + "72103104", + "72103300", + "72103301", + "72103302", + "72103304", + "72103305", + "72110000", + "72111000", + "72111001", + "72111002", + "72111003", + "72111004", + "72111005", + "72111006", + "72111007", + "72111008", + "72111100", + "72111101", + "72111102", + "72111103", + "72111104", + "72111105", + "72111106", + "72111107", + "72111108", + "72111109", + "72111110", + "72111111", + "72120000", + "72121000", + "72121001", + "72121002", + "72121003", + "72121004", + "72121005", + "72121006", + "72121007", + "72121008", + "72121100", + "72121101", + "72121102", + "72121103", + "72121104", + "72121105", + "72121200", + "72121201", + "72121202", + "72121203", + "72121300", + "72121301", + "72121302", + "72121400", + "72121401", + "72121402", + "72121403", + "72121404", + "72121405", + "72121406", + "72121407", + "72121408", + "72121409", + "72121410", + "72121500", + "72121501", + "72121502", + "72121503", + "72121504", + "72121505", + "72121506", + "72121507", + "72121508", + "72121509", + "72121510", + "72121511", + "72121512", + "72121513", + "72121514", + "72121515", + "72121516", + "72121517", + "72140000", + "72141000", + "72141001", + "72141002", + "72141003", + "72141004", + "72141100", + "72141101", + "72141102", + "72141103", + "72141104", + "72141105", + "72141106", + "72141107", + "72141108", + "72141109", + "72141110", + "72141111", + "72141112", + "72141113", + "72141114", + "72141115", + "72141116", + "72141117", + "72141118", + "72141119", + "72141120", + "72141121", + "72141122", + "72141123", + "72141124", + "72141125", + "72141126", + "72141127", + "72141128", + "72141129", + "72141130", + "72141200", + "72141201", + "72141202", + "72141203", + "72141204", + "72141205", + "72141206", + "72141207", + "72141209", + "72141210", + "72141211", + "72141212", + "72141213", + "72141214", + "72141215", + "72141216", + "72141400", + "72141401", + "72141402", + "72141500", + "72141502", + "72141503", + "72141504", + "72141505", + "72141507", + "72141508", + "72141509", + "72141510", + "72141511", + "72141600", + "72141601", + "72141602", + "72141603", + "72141604", + "72141605", + "72141700", + "72141701", + "72141702", + "72150000", + "72151000", + "72151001", + "72151002", + "72151003", + "72151004", + "72151005", + "72151006", + "72151100", + "72151101", + "72151102", + "72151103", + "72151200", + "72151201", + "72151202", + "72151203", + "72151204", + "72151205", + "72151206", + "72151207", + "72151300", + "72151301", + "72151302", + "72151303", + "72151304", + "72151305", + "72151306", + "72151307", + "72151308", + "72151400", + "72151401", + "72151402", + "72151500", + "72151501", + "72151502", + "72151503", + "72151504", + "72151505", + "72151506", + "72151507", + "72151508", + "72151509", + "72151510", + "72151511", + "72151514", + "72151515", + "72151600", + "72151601", + "72151602", + "72151603", + "72151604", + "72151605", + "72151606", + "72151607", + "72151608", + "72151609", + "72151700", + "72151701", + "72151702", + "72151703", + "72151704", + "72151800", + "72151801", + "72151802", + "72151803", + "72151900", + "72151901", + "72151903", + "72151904", + "72151905", + "72151906", + "72151907", + "72151908", + "72151909", + "72151910", + "72151911", + "72152000", + "72152001", + "72152002", + "72152003", + "72152004", + "72152005", + "72152100", + "72152101", + "72152102", + "72152103", + "72152104", + "72152200", + "72152201", + "72152202", + "72152203", + "72152204", + "72152300", + "72152301", + "72152302", + "72152303", + "72152400", + "72152401", + "72152402", + "72152403", + "72152404", + "72152405", + "72152500", + "72152501", + "72152502", + "72152503", + "72152504", + "72152505", + "72152506", + "72152507", + "72152508", + "72152509", + "72152600", + "72152601", + "72152602", + "72152603", + "72152604", + "72152605", + "72152606", + "72152607", + "72152700", + "72152701", + "72152702", + "72152703", + "72152704", + "72152705", + "72152706", + "72152707", + "72152708", + "72152709", + "72152710", + "72152711", + "72152800", + "72152801", + "72152802", + "72152900", + "72152901", + "72152902", + "72152903", + "72152904", + "72152905", + "72152906", + "72152907", + "72152908", + "72152909", + "72153000", + "72153001", + "72153002", + "72153100", + "72153101", + "72153102", + "72153103", + "72153104", + "72153105", + "72153106", + "72153107", + "72153108", + "72153200", + "72153201", + "72153202", + "72153203", + "72153204", + "72153205", + "72153206", + "72153207", + "72153208", + "72153209", + "72153300", + "72153301", + "72153302", + "72153303", + "72153400", + "72153401", + "72153402", + "72153500", + "72153501", + "72153502", + "72153503", + "72153504", + "72153505", + "72153506", + "72153507", + "72153600", + "72153601", + "72153602", + "72153603", + "72153604", + "72153605", + "72153606", + "72153607", + "72153608", + "72153609", + "72153610", + "72153611", + "72153612", + "72153613", + "72153700", + "72153701", + "72153702", + "72153900", + "72153901", + "72153902", + "72154000", + "72154001", + "72154002", + "72154003", + "72154004", + "72154005", + "72154006", + "72154007", + "72154008", + "72154009", + "72154010", + "72154011", + "72154012", + "72154013", + "72154014", + "72154015", + "72154016", + "72154017", + "72154018", + "72154019", + "72154020", + "72154021", + "72154022", + "72154023", + "72154024", + "72154025", + "72154026", + "72154027", + "72154028", + "72154029", + "72154030", + "72154031", + "72154032", + "72154033", + "72154034", + "72154035", + "72154036", + "72154037", + "72154038", + "72154039", + "72154040", + "72154041", + "72154042", + "72154043", + "72154044", + "72154045", + "72154046", + "72154047", + "72154048", + "72154049", + "72154050", + "72154051", + "72154052", + "72154053", + "72154054", + "72154055", + "72154056", + "72154057", + "72154058", + "72154059", + "72154060", + "72154061", + "72154062", + "72154063", + "72154064", + "72154065", + "72154066", + "72154067", + "72154068", + "72154069", + "72154100", + "72154101", + "72154102", + "72154103", + "72154104", + "72154105", + "72154106", + "72154107", + "72154108", + "72154109", + "72154110", + "72154200", + "72154201", + "72154300", + "72154301", + "72154302", + "72154303", + "72154400", + "72154401", + "72154402", + "72154500", + "72154501", + "72154502", + "72154503", + "72154600", + "72154601", + "72154602", + "72154603", + "72154604", + "72154605", + "73000000", + "73100000", + "73101600", + "73110000", + "73111500", + "73120000", + "73130000", + "73131500", + "73131600", + "73131700", + "73131800", + "73131900", + "73140000", + "73141500", + "73141600", + "73141700", + "73141715", + "73150000", + "73151500", + "73151501", + "73151502", + "73151600", + "73151700", + "73151800", + "73151900", + "73152000", + "73152100", + "73152101", + "73152102", + "73152103", + "73152104", + "73152105", + "73152106", + "73152107", + "73152108", + "73152109", + "73152112", + "73160000", + "73161500", + "73161600", + "73170000", + "73171500", + "73171501", + "73171502", + "73171503", + "73171504", + "73171506", + "73171507", + "73171510", + "73171511", + "73171512", + "73171600", + "73171602", + "73171605", + "73180000", + "73181100", + "73181103", + "76000000", + "76100000", + "76101500", + "76101600", + "76101601", + "76101602", + "76110000", + "76111500", + "76111501", + "76111503", + "76111504", + "76111505", + "76111506", + "76111507", + "76111600", + "76111601", + "76111602", + "76111603", + "76111604", + "76111605", + "76111800", + "76111801", + "76120000", + "76121500", + "76121501", + "76121502", + "76121503", + "76121504", + "76121505", + "76121506", + "76121507", + "76121600", + "76121601", + "76121602", + "76121603", + "76121604", + "76121700", + "76121701", + "76121702", + "76121800", + "76121900", + "76121901", + "76121902", + "76121903", + "76121904", + "76121905", + "76122000", + "76122001", + "76122002", + "76122003", + "76122004", + "76122100", + "76122200", + "76122300", + "76122400", + "76122407", + "76130000", + "76131500", + "76131600", + "76131700", + "77000000", + "77100000", + "77101500", + "77101501", + "77101502", + "77101503", + "77101504", + "77101505", + "77101506", + "77101600", + "77101601", + "77101602", + "77101603", + "77101604", + "77101605", + "77101700", + "77101701", + "77101702", + "77101703", + "77101704", + "77101705", + "77101706", + "77101707", + "77101800", + "77101801", + "77101802", + "77101803", + "77101804", + "77101805", + "77101806", + "77101900", + "77101901", + "77101902", + "77101903", + "77101904", + "77101905", + "77101906", + "77101907", + "77101908", + "77101909", + "77101910", + "77102000", + "77102002", + "77102004", + "77110000", + "77111500", + "77111501", + "77111502", + "77111503", + "77111504", + "77111505", + "77111506", + "77111507", + "77111508", + "77111600", + "77111601", + "77111602", + "77111603", + "77120000", + "77121500", + "77121501", + "77121503", + "77121504", + "77121600", + "77121601", + "77121602", + "77121603", + "77121604", + "77121605", + "77121606", + "77121607", + "77121608", + "77121609", + "77121610", + "77121700", + "77121701", + "77121702", + "77121703", + "77121704", + "77121705", + "77121706", + "77121707", + "77121708", + "77121709", + "77130000", + "77131500", + "77131501", + "77131502", + "77131503", + "77131600", + "77131601", + "77131602", + "77131603", + "77131604", + "77131700", + "77140000", + "78000000", + "78100000", + "78101500", + "78101501", + "78101502", + "78101503", + "78101504", + "78101505", + "78101600", + "78101601", + "78101602", + "78101603", + "78101604", + "78101608", + "78101609", + "78101610", + "78101700", + "78101701", + "78101702", + "78101703", + "78101704", + "78101708", + "78101709", + "78101710", + "78101800", + "78101801", + "78101802", + "78101803", + "78101804", + "78101808", + "78101809", + "78101810", + "78101900", + "78101901", + "78101902", + "78101903", + "78101904", + "78101905", + "78102000", + "78102100", + "78102101", + "78102102", + "78102103", + "78102200", + "78102201", + "78102202", + "78102203", + "78102204", + "78102205", + "78102206", + "78110000", + "78111500", + "78111501", + "78111502", + "78111503", + "78111504", + "78111505", + "78111506", + "78111600", + "78111601", + "78111602", + "78111603", + "78111700", + "78111701", + "78111702", + "78111704", + "78111705", + "78111706", + "78111707", + "78111800", + "78111802", + "78111803", + "78111804", + "78111807", + "78111808", + "78111809", + "78111810", + "78111811", + "78111812", + "78111813", + "78111814", + "78111815", + "78111900", + "78120000", + "78121500", + "78121501", + "78121600", + "78121601", + "78121603", + "78130000", + "78131500", + "78131501", + "78131502", + "78131600", + "78131601", + "78131602", + "78131603", + "78131700", + "78131701", + "78131702", + "78131800", + "78131801", + "78131802", + "78131803", + "78131804", + "78131806", + "78131807", + "78140000", + "78141500", + "78141501", + "78141502", + "78141503", + "78141504", + "78141505", + "78141510", + "78141600", + "78141601", + "78141602", + "78141603", + "78141700", + "78141701", + "78141702", + "78141703", + "78141704", + "78141800", + "78141801", + "78141802", + "78141803", + "78141804", + "78141805", + "78141806", + "78141807", + "78141900", + "78142000", + "78142001", + "78142002", + "78142003", + "78180000", + "78181500", + "78181501", + "78181505", + "78181506", + "78181507", + "78181508", + "78181509", + "78181600", + "78181700", + "78181701", + "78181702", + "78181703", + "78181704", + "78181800", + "78181818", + "78181842", + "78200000", + "78201000", + "78202000", + "78203000", + "78204000", + "78204001", + "78204002", + "78204003", + "78204004", + "78204005", + "78204006", + "78204007", + "78204008", + "78204009", + "78204010", + "78204011", + "78204012", + "78204013", + "78204014", + "78204015", + "78204016", + "78204017", + "78204018", + "78204019", + "80000000", + "80100000", + "80101500", + "80101501", + "80101502", + "80101503", + "80101504", + "80101505", + "80101506", + "80101507", + "80101508", + "80101509", + "80101510", + "80101511", + "80101512", + "80101513", + "80101600", + "80101601", + "80101602", + "80101603", + "80101604", + "80101605", + "80101606", + "80101607", + "80101700", + "80101702", + "80101703", + "80101704", + "80101706", + "80110000", + "80111500", + "80111501", + "80111502", + "80111503", + "80111504", + "80111505", + "80111506", + "80111507", + "80111508", + "80111509", + "80111510", + "80111511", + "80111600", + "80111601", + "80111602", + "80111603", + "80111604", + "80111605", + "80111606", + "80111607", + "80111608", + "80111609", + "80111610", + "80111611", + "80111612", + "80111613", + "80111614", + "80111615", + "80111616", + "80111617", + "80111618", + "80111619", + "80111620", + "80111621", + "80111622", + "80111623", + "80111624", + "80111625", + "80111700", + "80111701", + "80111702", + "80111703", + "80111704", + "80111705", + "80111706", + "80111707", + "80111708", + "80111709", + "80111710", + "80111711", + "80111712", + "80111713", + "80111714", + "80111715", + "80111716", + "80111717", + "80111718", + "80111719", + "80120000", + "80121500", + "80121501", + "80121502", + "80121503", + "80121600", + "80121601", + "80121602", + "80121603", + "80121604", + "80121605", + "80121606", + "80121607", + "80121608", + "80121609", + "80121611", + "80121700", + "80121701", + "80121703", + "80121704", + "80121706", + "80121707", + "80121708", + "80121800", + "80121801", + "80121802", + "80121803", + "80121804", + "80121900", + "80121901", + "80121902", + "80121903", + "80121904", + "80122000", + "80130000", + "80131500", + "80131501", + "80131502", + "80131503", + "80131504", + "80131505", + "80131506", + "80131600", + "80131601", + "80131602", + "80131603", + "80131604", + "80131605", + "80131700", + "80131701", + "80131702", + "80131703", + "80131800", + "80131801", + "80131802", + "80131803", + "80140000", + "80141400", + "80141401", + "80141402", + "80141403", + "80141404", + "80141405", + "80141406", + "80141407", + "80141408", + "80141409", + "80141410", + "80141411", + "80141412", + "80141500", + "80141501", + "80141502", + "80141503", + "80141504", + "80141505", + "80141506", + "80141507", + "80141508", + "80141509", + "80141510", + "80141511", + "80141512", + "80141513", + "80141514", + "80141600", + "80141601", + "80141603", + "80141604", + "80141605", + "80141606", + "80141607", + "80141609", + "80141612", + "80141613", + "80141618", + "80141619", + "80141624", + "80141625", + "80141626", + "80141630", + "80141633", + "80141635", + "80141700", + "80141701", + "80141702", + "80141703", + "80141704", + "80141705", + "80141706", + "80141800", + "80141801", + "80141802", + "80141803", + "80141900", + "80141901", + "80141902", + "80150000", + "80151500", + "80151501", + "80151502", + "80151503", + "80151504", + "80151505", + "80151600", + "80151601", + "80151602", + "80151603", + "80151604", + "80151605", + "80160000", + "80161500", + "80161501", + "80161502", + "80161503", + "80161504", + "80161505", + "80161506", + "80161507", + "80161508", + "80161600", + "80161601", + "80161602", + "80161603", + "80161700", + "80161701", + "80161702", + "80161703", + "80161800", + "80161801", + "80170000", + "80171500", + "80171501", + "80171502", + "80171503", + "80171504", + "80171505", + "80171600", + "80171602", + "80171800", + "80171801", + "80171802", + "80171803", + "80171900", + "80171902", + "80171903", + "80171904", + "80171905", + "80171906", + "80171907", + "80171908", + "80171909", + "80172000", + "80172001", + "80172002", + "80172003", + "80172100", + "80172101", + "80172102", + "80172103", + "80172104", + "81000000", + "81100000", + "81101500", + "81101501", + "81101502", + "81101503", + "81101505", + "81101506", + "81101507", + "81101508", + "81101509", + "81101510", + "81101511", + "81101512", + "81101513", + "81101514", + "81101515", + "81101516", + "81101517", + "81101518", + "81101519", + "81101520", + "81101521", + "81101522", + "81101523", + "81101524", + "81101525", + "81101526", + "81101527", + "81101528", + "81101529", + "81101530", + "81101600", + "81101700", + "81101701", + "81101702", + "81101703", + "81101706", + "81101707", + "81101710", + "81101711", + "81101713", + "81101800", + "81101900", + "81101902", + "81102000", + "81102001", + "81102100", + "81102101", + "81102200", + "81102201", + "81102202", + "81102203", + "81102300", + "81102301", + "81102302", + "81102400", + "81102401", + "81102402", + "81102500", + "81102501", + "81102502", + "81102503", + "81102600", + "81102601", + "81102800", + "81102801", + "81102802", + "81102803", + "81102804", + "81102805", + "81102806", + "81102807", + "81102808", + "81102809", + "81102810", + "81102811", + "81102815", + "81110000", + "81111500", + "81111501", + "81111502", + "81111503", + "81111504", + "81111505", + "81111506", + "81111507", + "81111508", + "81111509", + "81111510", + "81111511", + "81111512", + "81111600", + "81111601", + "81111602", + "81111603", + "81111604", + "81111605", + "81111606", + "81111607", + "81111608", + "81111609", + "81111610", + "81111611", + "81111612", + "81111613", + "81111700", + "81111701", + "81111702", + "81111703", + "81111704", + "81111705", + "81111706", + "81111707", + "81111708", + "81111709", + "81111800", + "81111801", + "81111802", + "81111803", + "81111804", + "81111805", + "81111806", + "81111808", + "81111809", + "81111810", + "81111811", + "81111812", + "81111814", + "81111818", + "81111819", + "81111820", + "81111900", + "81111901", + "81111902", + "81112000", + "81112001", + "81112002", + "81112003", + "81112004", + "81112005", + "81112006", + "81112007", + "81112008", + "81112009", + "81112010", + "81112100", + "81112101", + "81112102", + "81112103", + "81112104", + "81112105", + "81112106", + "81112107", + "81112200", + "81112201", + "81112202", + "81112203", + "81112204", + "81112205", + "81112206", + "81112207", + "81112208", + "81112209", + "81112210", + "81112211", + "81112212", + "81112213", + "81112214", + "81112215", + "81112216", + "81112217", + "81112218", + "81112219", + "81112220", + "81112221", + "81112222", + "81112223", + "81112224", + "81112300", + "81112301", + "81112302", + "81112303", + "81112304", + "81112305", + "81112306", + "81112307", + "81112308", + "81112309", + "81112310", + "81112400", + "81112401", + "81112500", + "81112501", + "81112502", + "81120000", + "81121500", + "81121501", + "81121502", + "81121503", + "81121504", + "81121505", + "81121600", + "81121601", + "81121602", + "81121603", + "81121604", + "81121605", + "81121606", + "81121607", + "81130000", + "81131500", + "81131501", + "81131502", + "81131503", + "81131504", + "81131505", + "81140000", + "81141500", + "81141501", + "81141502", + "81141503", + "81141504", + "81141505", + "81141506", + "81141600", + "81141601", + "81141602", + "81141603", + "81141604", + "81141605", + "81141606", + "81141700", + "81141701", + "81141702", + "81141703", + "81141704", + "81141800", + "81141801", + "81141802", + "81141803", + "81141804", + "81141805", + "81141806", + "81141807", + "81141900", + "81141901", + "81141902", + "81150000", + "81151500", + "81151501", + "81151502", + "81151503", + "81151600", + "81151601", + "81151602", + "81151603", + "81151604", + "81151700", + "81151701", + "81151702", + "81151703", + "81151704", + "81151705", + "81151800", + "81151801", + "81151802", + "81151803", + "81151804", + "81151805", + "81151806", + "81151900", + "81151901", + "81151902", + "81151903", + "81151904", + "81160000", + "81161500", + "81161501", + "81161502", + "81161503", + "81161600", + "81161601", + "81161700", + "81161701", + "81161702", + "81161703", + "81161704", + "81161705", + "81161706", + "81161707", + "81161708", + "81161709", + "81161710", + "81161711", + "81161712", + "81161713", + "81161714", + "81161800", + "81161801", + "81162000", + "81162100", + "81162200", + "81162202", + "81170000", + "81171500", + "81171501", + "81171600", + "81171601", + "81171700", + "81171701", + "81171702", + "81171800", + "81171801", + "81171900", + "81171901", + "82000000", + "82100000", + "82101500", + "82101600", + "82101603", + "82101700", + "82101701", + "82101702", + "82101800", + "82101900", + "82101901", + "82101902", + "82101903", + "82101904", + "82101905", + "82110000", + "82111400", + "82111401", + "82111402", + "82111403", + "82111404", + "82111405", + "82111406", + "82111500", + "82111501", + "82111502", + "82111503", + "82111600", + "82111601", + "82111602", + "82111603", + "82111604", + "82111700", + "82111701", + "82111702", + "82111703", + "82111704", + "82111705", + "82111800", + "82111801", + "82111802", + "82111803", + "82111804", + "82111900", + "82111901", + "82111902", + "82111903", + "82111904", + "82112000", + "82112001", + "82112002", + "82112003", + "82112004", + "82112005", + "82112006", + "82112007", + "82112008", + "82112009", + "82112010", + "82112011", + "82112012", + "82112013", + "82112014", + "82112015", + "82112016", + "82112017", + "82112018", + "82112019", + "82112020", + "82112021", + "82112022", + "82112023", + "82112024", + "82112025", + "82112026", + "82112027", + "82112028", + "82112029", + "82112030", + "82112031", + "82112032", + "82112033", + "82112034", + "82112035", + "82112036", + "82112037", + "82112038", + "82112039", + "82112040", + "82112041", + "82112042", + "82112043", + "82112044", + "82112045", + "82112046", + "82112047", + "82112048", + "82112049", + "82112050", + "82112051", + "82112052", + "82112053", + "82112054", + "82112055", + "82112056", + "82112057", + "82112058", + "82112059", + "82112060", + "82112061", + "82112062", + "82112063", + "82112064", + "82112065", + "82112066", + "82112067", + "82120000", + "82121500", + "82121501", + "82121502", + "82121503", + "82121504", + "82121505", + "82121506", + "82121507", + "82121508", + "82121509", + "82121510", + "82121511", + "82121512", + "82121513", + "82121600", + "82121601", + "82121602", + "82121603", + "82121700", + "82121701", + "82121702", + "82121800", + "82121801", + "82121802", + "82121900", + "82121901", + "82121902", + "82121903", + "82121904", + "82121905", + "82121906", + "82121907", + "82121908", + "82130000", + "82131500", + "82131501", + "82131502", + "82131503", + "82131504", + "82131505", + "82131600", + "82131601", + "82131602", + "82131603", + "82131604", + "82140000", + "82141500", + "82141501", + "82141502", + "82141503", + "82141504", + "82141505", + "82141506", + "82141507", + "82141600", + "82141601", + "82141602", + "82150000", + "82151500", + "82151501", + "82151502", + "82151503", + "82151504", + "82151505", + "82151506", + "82151507", + "82151508", + "82151509", + "82151510", + "82151511", + "82151512", + "82151700", + "82151701", + "82151702", + "82151703", + "82151704", + "82151705", + "82151706", + "82160000", + "83000000", + "83100000", + "83101500", + "83101501", + "83101502", + "83101503", + "83101504", + "83101505", + "83101506", + "83101507", + "83101508", + "83101509", + "83101510", + "83101600", + "83101601", + "83101602", + "83101603", + "83101604", + "83101605", + "83101606", + "83101800", + "83101801", + "83101802", + "83101803", + "83101804", + "83101805", + "83101806", + "83101807", + "83101808", + "83101900", + "83101901", + "83101902", + "83101903", + "83110000", + "83111500", + "83111501", + "83111502", + "83111503", + "83111504", + "83111505", + "83111506", + "83111507", + "83111508", + "83111510", + "83111511", + "83111600", + "83111601", + "83111602", + "83111603", + "83111604", + "83111605", + "83111606", + "83111700", + "83111701", + "83111702", + "83111703", + "83111800", + "83111801", + "83111802", + "83111803", + "83111804", + "83111900", + "83111901", + "83111902", + "83111903", + "83111904", + "83111905", + "83112200", + "83112201", + "83112202", + "83112203", + "83112204", + "83112205", + "83112206", + "83112300", + "83112301", + "83112302", + "83112303", + "83112304", + "83112400", + "83112401", + "83112402", + "83112403", + "83112404", + "83112405", + "83112406", + "83112500", + "83112501", + "83112502", + "83112503", + "83112504", + "83112505", + "83112506", + "83112600", + "83112601", + "83112602", + "83112603", + "83112604", + "83112605", + "83112606", + "83120000", + "83121500", + "83121501", + "83121502", + "83121503", + "83121504", + "83121600", + "83121601", + "83121602", + "83121603", + "83121604", + "83121605", + "83121606", + "83121700", + "83121701", + "83121702", + "83121703", + "83121704", + "84000000", + "84100000", + "84101500", + "84101501", + "84101502", + "84101503", + "84101600", + "84101601", + "84101602", + "84101603", + "84101604", + "84101700", + "84101701", + "84101702", + "84101703", + "84101704", + "84101705", + "84110000", + "84111500", + "84111501", + "84111502", + "84111503", + "84111504", + "84111505", + "84111506", + "84111507", + "84111508", + "84111600", + "84111601", + "84111602", + "84111603", + "84111700", + "84111701", + "84111702", + "84111703", + "84111800", + "84111801", + "84111802", + "84120000", + "84121500", + "84121501", + "84121502", + "84121503", + "84121504", + "84121600", + "84121601", + "84121602", + "84121603", + "84121604", + "84121605", + "84121606", + "84121607", + "84121608", + "84121700", + "84121701", + "84121702", + "84121703", + "84121704", + "84121705", + "84121706", + "84121800", + "84121801", + "84121802", + "84121803", + "84121804", + "84121805", + "84121806", + "84121900", + "84121901", + "84121902", + "84121903", + "84122000", + "84122001", + "84130000", + "84131500", + "84131501", + "84131502", + "84131503", + "84131504", + "84131505", + "84131506", + "84131507", + "84131508", + "84131509", + "84131510", + "84131511", + "84131512", + "84131513", + "84131514", + "84131515", + "84131516", + "84131517", + "84131518", + "84131519", + "84131600", + "84131601", + "84131602", + "84131603", + "84131604", + "84131605", + "84131606", + "84131607", + "84131608", + "84131609", + "84131610", + "84131611", + "84131613", + "84131700", + "84131701", + "84131702", + "84131800", + "84131801", + "84131802", + "84140000", + "84141500", + "84141501", + "84141502", + "84141503", + "84141600", + "84141601", + "84141602", + "84141700", + "84141701", + "84141702", + "85000000", + "85100000", + "85101500", + "85101501", + "85101502", + "85101503", + "85101504", + "85101505", + "85101506", + "85101508", + "85101509", + "85101600", + "85101700", + "85101701", + "85101702", + "85101703", + "85101705", + "85101707", + "85110000", + "85111500", + "85111501", + "85111502", + "85111503", + "85111504", + "85111505", + "85111506", + "85111507", + "85111508", + "85111509", + "85111510", + "85111511", + "85111512", + "85111513", + "85111514", + "85111600", + "85111601", + "85111602", + "85111603", + "85111604", + "85111605", + "85111606", + "85111607", + "85111608", + "85111609", + "85111610", + "85111611", + "85111612", + "85111613", + "85111614", + "85111615", + "85111616", + "85111617", + "85111700", + "85111701", + "85111702", + "85111703", + "85111704", + "85120000", + "85121500", + "85121501", + "85121502", + "85121503", + "85121504", + "85121600", + "85121608", + "85121613", + "85121700", + "85121800", + "85121801", + "85121802", + "85121803", + "85121804", + "85121805", + "85121806", + "85121807", + "85121808", + "85121809", + "85121810", + "85121811", + "85121900", + "85121901", + "85121902", + "85122000", + "85122001", + "85122002", + "85122003", + "85122004", + "85122005", + "85122100", + "85122101", + "85122102", + "85122103", + "85122109", + "85122200", + "85122201", + "85130000", + "85131500", + "85131600", + "85131700", + "85140000", + "85141500", + "85141600", + "85141601", + "85141602", + "85141700", + "85150000", + "85151500", + "85151501", + "85151502", + "85151503", + "85151600", + "85151601", + "85151604", + "85151606", + "85151700", + "85151701", + "85151702", + "85151703", + "85151704", + "85151705", + "85160000", + "85161500", + "85161501", + "85161502", + "85161503", + "85161504", + "85161505", + "85170000", + "85171500", + "85171501", + "85171600", + "85171601", + "85210000", + "85217100", + "85260000", + "85261600", + "85270000", + "85380000", + "85383300", + "85400000", + "85470000", + "85472000", + "85472700", + "85472742", + "85700000", + "85760000", + "85765500", + "85765508", + "86000000", + "86100000", + "86101400", + "86101401", + "86101402", + "86101403", + "86101404", + "86101405", + "86101406", + "86101407", + "86101408", + "86101409", + "86101410", + "86101411", + "86101412", + "86101413", + "86101414", + "86101415", + "86101416", + "86101417", + "86101418", + "86101419", + "86101420", + "86101500", + "86101501", + "86101502", + "86101503", + "86101504", + "86101505", + "86101506", + "86101507", + "86101508", + "86101509", + "86101600", + "86101601", + "86101602", + "86101603", + "86101604", + "86101605", + "86101606", + "86101607", + "86101608", + "86101609", + "86101610", + "86101700", + "86101701", + "86101702", + "86101703", + "86101704", + "86101705", + "86101706", + "86101708", + "86101709", + "86101710", + "86101711", + "86101712", + "86101713", + "86101714", + "86101715", + "86101716", + "86101718", + "86101719", + "86101800", + "86101802", + "86101803", + "86101806", + "86101810", + "86110000", + "86111500", + "86111501", + "86111502", + "86111503", + "86111504", + "86111505", + "86111600", + "86111601", + "86111602", + "86111603", + "86111604", + "86111700", + "86111701", + "86111702", + "86111800", + "86111801", + "86111802", + "86120000", + "86121500", + "86121600", + "86121601", + "86121602", + "86121700", + "86121701", + "86121702", + "86121800", + "86121802", + "86121803", + "86121804", + "86130000", + "86131500", + "86131501", + "86131502", + "86131503", + "86131504", + "86131600", + "86131601", + "86131602", + "86131603", + "86131700", + "86131701", + "86131800", + "86131803", + "86131900", + "86132000", + "86132001", + "86132100", + "86132101", + "86132102", + "86132200", + "86132201", + "86140000", + "86141500", + "86141501", + "86141600", + "86141700", + "86141702", + "86141703", + "86141704", + "90000000", + "90100000", + "90101500", + "90101501", + "90101502", + "90101503", + "90101504", + "90101600", + "90101601", + "90101602", + "90101603", + "90101604", + "90101605", + "90101700", + "90101701", + "90101800", + "90101801", + "90101802", + "90101900", + "90101901", + "90101902", + "90110000", + "90111500", + "90111501", + "90111502", + "90111503", + "90111504", + "90111600", + "90111601", + "90111602", + "90111603", + "90111604", + "90111700", + "90111701", + "90111702", + "90111703", + "90111800", + "90111801", + "90111802", + "90111803", + "90111900", + "90111901", + "90111902", + "90120000", + "90121500", + "90121502", + "90121600", + "90121601", + "90121602", + "90121603", + "90121700", + "90121800", + "90121801", + "90130000", + "90140000", + "90150000", + "91000000", + "91100000", + "91101500", + "91101501", + "91110000", + "91111500", + "91111502", + "91111600", + "91111700", + "91111800", + "91111900", + "92000000", + "92100000", + "92101500", + "92101501", + "92101502", + "92101503", + "92101504", + "92101505", + "92101600", + "92101601", + "92101602", + "92101603", + "92101604", + "92101700", + "92101701", + "92101702", + "92101703", + "92101704", + "92101800", + "92101900", + "92101901", + "92101902", + "92101903", + "92101904", + "92110000", + "92111500", + "92111501", + "92111502", + "92111503", + "92111504", + "92111505", + "92111506", + "92111507", + "92111600", + "92111601", + "92111602", + "92111603", + "92111604", + "92111605", + "92111606", + "92111607", + "92111608", + "92111609", + "92111610", + "92111611", + "92111612", + "92111613", + "92111614", + "92111615", + "92111616", + "92111700", + "92111800", + "92111900", + "92112000", + "92112100", + "92112200", + "92112300", + "92112400", + "92120000", + "92121500", + "92121502", + "92121503", + "92121504", + "92121600", + "92121601", + "92121602", + "92121603", + "92121604", + "92121700", + "92121701", + "92121702", + "92121703", + "92121708", + "92121709", + "92121710", + "92121800", + "92121802", + "93000000", + "93100000", + "93101500", + "93101504", + "93101600", + "93101601", + "93101602", + "93101603", + "93101604", + "93101605", + "93101607", + "93101608", + "93101700", + "93101701", + "93101702", + "93101703", + "93101704", + "93101705", + "93101706", + "93101707", + "93110000", + "93111500", + "93111501", + "93111502", + "93111503", + "93111504", + "93111505", + "93111506", + "93111507", + "93111600", + "93111601", + "93111602", + "93111603", + "93111604", + "93111605", + "93111606", + "93111607", + "93111608", + "93120000", + "93121500", + "93121501", + "93121502", + "93121503", + "93121504", + "93121505", + "93121506", + "93121507", + "93121508", + "93121509", + "93121600", + "93121601", + "93121604", + "93121605", + "93121606", + "93121607", + "93121608", + "93121609", + "93121610", + "93121612", + "93121613", + "93121614", + "93121615", + "93121700", + "93121701", + "93121703", + "93121704", + "93121706", + "93121707", + "93121708", + "93121709", + "93121710", + "93130000", + "93131500", + "93131501", + "93131502", + "93131503", + "93131504", + "93131505", + "93131506", + "93131507", + "93131600", + "93131601", + "93131602", + "93131603", + "93131609", + "93131610", + "93131611", + "93131700", + "93131702", + "93131703", + "93131704", + "93131705", + "93131800", + "93131801", + "93131802", + "93131803", + "93140000", + "93141500", + "93141501", + "93141502", + "93141503", + "93141506", + "93141507", + "93141508", + "93141509", + "93141510", + "93141511", + "93141513", + "93141600", + "93141601", + "93141602", + "93141603", + "93141604", + "93141605", + "93141608", + "93141609", + "93141610", + "93141612", + "93141700", + "93141701", + "93141702", + "93141706", + "93141707", + "93141709", + "93141710", + "93141711", + "93141712", + "93141713", + "93141715", + "93141800", + "93141801", + "93141802", + "93141803", + "93141804", + "93141805", + "93141806", + "93141807", + "93141808", + "93141810", + "93141811", + "93141812", + "93141813", + "93141814", + "93141900", + "93141902", + "93141905", + "93141906", + "93141907", + "93141908", + "93141909", + "93142000", + "93142001", + "93142002", + "93142003", + "93142004", + "93142005", + "93142006", + "93142007", + "93142008", + "93142009", + "93142100", + "93142101", + "93142102", + "93142103", + "93142104", + "93150000", + "93151500", + "93151501", + "93151502", + "93151503", + "93151504", + "93151505", + "93151506", + "93151507", + "93151508", + "93151509", + "93151510", + "93151511", + "93151512", + "93151513", + "93151514", + "93151515", + "93151516", + "93151517", + "93151518", + "93151519", + "93151600", + "93151601", + "93151602", + "93151603", + "93151605", + "93151606", + "93151607", + "93151608", + "93151610", + "93151611", + "93151700", + "93160000", + "93161500", + "93161501", + "93161502", + "93161503", + "93161504", + "93161600", + "93161601", + "93161602", + "93161603", + "93161604", + "93161605", + "93161606", + "93161607", + "93161608", + "93161609", + "93161700", + "93161701", + "93161702", + "93161703", + "93161704", + "93161800", + "93161801", + "93161802", + "93161804", + "93161805", + "93161808", + "93170000", + "93171500", + "93171501", + "93171502", + "93171503", + "93171504", + "93171600", + "93171601", + "93171602", + "93171603", + "93171604", + "93171700", + "93171800", + "93171801", + "93171802", + "93171803", + "94000000", + "94100000", + "94110000", + "94120000", + "94130000", + "94131500", + "94131501", + "94131600", + "94131601", + "94131602", + "94131603", + "94131604", + "94131605", + "94131700", + "94131701", + "94131702", + "94131703", + "94131704", + "94131800", + "94131801", + "94131802", + "94131803", + "94131804", + "94131805", + "94131900", + "94131901", + "94131902", + "94131903", + "94132000", + "94132001", + "94132004", + "95000000", + "95100000", + "95101500", + "95101600", + "95101700", + "95101707", + "95101800", + "95101900", + "95110000", + "95111500", + "95111503", + "95111504", + "95111600", + "95111609", + "95111610", + "95111611", + "95111612", + "95111615", + "95120000", + "95121500", + "95121600", + "95121601", + "95121602", + "95121603", + "95121604", + "95121605", + "95121606", + "95121607", + "95121608", + "95121611", + "95121612", + "95121613", + "95121614", + "95121620", + "95121621", + "95121624", + "95121625", + "95121626", + "95121627", + "95121628", + "95121629", + "95121630", + "95121631", + "95121632", + "95121634", + "95121635", + "95121636", + "95121639", + "95121640", + "95121641", + "95121642", + "95121643", + "95121644", + "95121645", + "95121647", + "95121700", + "95121701", + "95121702", + "95121703", + "95121704", + "95121705", + "95121706", + "95121707", + "95121708", + "95121709", + "95121710", + "95121711", + "95121712", + "95121713", + "95121714", + "95121715", + "95121800", + "95121801", + "95121802", + "95121803", + "95121804", + "95121805", + "95121806", + "95121807", + "95121808", + "95121809", + "95121810", + "95121811", + "95121812", + "95121900", + "95121901", + "95121902", + "95121903", + "95121904", + "95121905", + "95121906", + "95121907", + "95121908", + "95121909", + "95121910", + "95121911", + "95121913", + "95122000", + "95122001", + "95122002", + "95122003", + "95122004", + "95122005", + "95122006", + "95122007", + "95122008", + "95122100", + "95122101", + "95122102", + "95122103", + "95122104", + "95122105", + "95122106", + "95122300", + "95122400", + "95122500", + "95122600", + "95122700", + "95130000", + "95131500", + "95131600", + "95131601", + "95131602", + "95131603", + "95131604", + "95131605", + "95131606", + "95131700", + "95140000", + "95141500", + "95141501", + "95141502", + "95141600", + "95141601", + "95141602", + "95141603", + "95141604", + "95141605", + "95141606", + "95141700", + "95141701", + "95141702", + "95141703", + "95141704", + "95141705", + "95141706", + "95141707", + "95141708", + "95141709", + "95141710", + "95141711", + "95141713", + "95141714", + "95141715", + "95141800", + "95141801", + "95141802", + "95141803", + "95141804", + "95141900", + "95141901", + "95141902", + "95141903", + "95141904" + ], + "synthesized_ancestors": [ + "57110000", + "57220000", + "57330000", + "57440000", + "57550000", + "57660000", + "57770000", + "57880000" + ], + "synthesized_note": "Family rows absent from the UNGM export but implied by live classes beneath them (a class cannot exist without its family); synthesized for ancestor-closure, flagged here." +} diff --git a/tests/capabilities/unspsc/__init__.py b/tests/capabilities/unspsc/__init__.py new file mode 100644 index 00000000..3b443c79 --- /dev/null +++ b/tests/capabilities/unspsc/__init__.py @@ -0,0 +1 @@ +"""unspsc capability tests (scaffold).""" diff --git a/tests/capabilities/unspsc/test_capability.py b/tests/capabilities/unspsc/test_capability.py new file mode 100644 index 00000000..47a93d12 --- /dev/null +++ b/tests/capabilities/unspsc/test_capability.py @@ -0,0 +1,106 @@ +"""Tests for UNSPSCCapability wiring and the presentation seam.""" + +import pytest + +from paxman.api import canonicalize +from paxman.capabilities.UNSPSC.capability import UNSPSCCapability +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.core.discovery import register_capability, reset_registry +from paxman.core.domain import Resolution + + +@pytest.mark.capability +class TestUNSPSCCapability: + """Capability wiring — grammars, rules, factory, format_value.""" + + def setup_method(self) -> None: + self.capability = UNSPSCCapability() + + def test_metadata(self) -> None: + assert self.capability.name == "unspsc" + + def test_wiring_counts(self) -> None: + grammars = self.capability.get_grammars() + assert [g.name for g in grammars] == ["unspsc_recognition"] + assert [r.name for r in self.capability.get_rules()] == [ + "Section 1-hierarchy-structure", + "Section 2-level-padding", + "Section 3-codeset-membership", + "Section 4-business-function-suffix", + ] + + def test_create_contract_defaults(self) -> None: + contract = self.capability.create_contract() + assert isinstance(contract, UNSPSCContract) + assert contract.output_format == "unspsc" + assert contract.include_business_function is True + + @pytest.mark.parametrize( + ("value", "output_format", "notation", "expected"), + [ + ("43211503", None, (8, ""), "43211503"), + ("43211503", "unspsc", (8, ""), "43211503"), + ("43211503", "labeled", (8, ""), "UNSPSC 43211503"), + ("43211503", "native", (8, ""), "43211503"), + ("44121700", "native", (6, ""), "441217"), + ("44103103", "native", (10, "14"), "4410310314"), + ], + ) + def test_format_value_round_trips( + self, + value: str, + output_format: str | None, + notation: tuple[int, str], + expected: str, + ) -> None: + native_length, function = notation + assert ( + self.capability.format_value( + value, + output_format, + UNSPSCNotation( + digits=value, + level="commodity", + function=function, + native_length=native_length, + ), + ) + == expected + ) + + +@pytest.mark.capability +class TestUNSPSCCapabilityPipeline: + """End-to-end smoke: label, MDM, alias, and BFI forms resolve.""" + + @pytest.fixture(autouse=True) + def _clean_registry(self) -> None: + reset_registry() + yield + reset_registry() + + @pytest.mark.parametrize( + ("text", "expected"), + [ + ("44103103", "44103103"), + ("UNSPSC 44103103", "44103103"), + ("UNSPSC000.44103103", "44103103"), + ("441217", "44121700"), + ("4410310314", "44103103"), + ("43000000", "43000000"), + ], + ) + def test_canonicalize_smoke(self, text: str, expected: str) -> None: + register_capability(UNSPSCCapability()) + contract = UNSPSCCapability.create_contract() + result = canonicalize(text, contract) + assert result.status == Resolution.SUCCESS + assert result.canonicalized_value == expected + + def test_scaffold_probe_missing(self) -> None: + register_capability(UNSPSCCapability()) + contract = UNSPSCCapability.create_contract() + result = canonicalize("scaffold probe", contract) + assert result.status == Resolution.MISSING + assert result.canonicalized_value is None diff --git a/tests/capabilities/unspsc/test_codeset_data.py b/tests/capabilities/unspsc/test_codeset_data.py new file mode 100644 index 00000000..282087f5 --- /dev/null +++ b/tests/capabilities/unspsc/test_codeset_data.py @@ -0,0 +1,99 @@ +"""Codeset snapshot data tests (Task 3). + +The membership table is generated, never hand-edited: +paxman/shared_data/unspsc_snapshot.json --(tools/regenerate_unspsc_data.py)--> +paxman/capabilities/UNSPSC/rules/data/unspsc_codeset.py. +""" + +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + +import pytest + +from paxman.capabilities.UNSPSC.rules.data.unspsc_codeset import ( + CODESET_VERSION, + LIVE_STEMS, + SYNTHESIZED_ANCESTORS, +) + +KNOWN_LIVE = ( + "44103103", # printer/facsimile toner + "43211503", # notebook computers + "10101501", # cats + "25101703", # ambulances + "44121706", # wooden pencils + "43211602", # docking stations + "43000000", # segment 43 + "43210000", # family 4321 + "43211500", # class 432115 +) + +KNOWN_ABSENT = ( + "44103199", # well-formed, unissued (illustrative) + "99999999", # no segment 99 +) + + +@pytest.mark.capability +class TestCodesetData: + def test_version_pinned(self) -> None: + assert isinstance(CODESET_VERSION, str) and CODESET_VERSION + + def test_covers_known_live_stems(self) -> None: + for stem in KNOWN_LIVE: + assert stem in LIVE_STEMS, stem + + def test_excludes_unissued(self) -> None: + for stem in KNOWN_ABSENT: + assert stem not in LIVE_STEMS, stem + + def test_all_stems_are_8_ascii_digits(self) -> None: + assert len(LIVE_STEMS) == 13482 + for stem in LIVE_STEMS: + assert len(stem) == 8 and stem.isascii() and stem.isdigit(), stem + + def test_synthesized_ancestors_flagged_and_disjoint(self) -> None: + assert ( + frozenset( + { + "57110000", + "57220000", + "57330000", + "57440000", + "57550000", + "57660000", + "57770000", + "57880000", + } + ) + == SYNTHESIZED_ANCESTORS + ) + assert not (SYNTHESIZED_ANCESTORS & LIVE_STEMS) + + def test_prefix_closure_over_union(self) -> None: + live = LIVE_STEMS | SYNTHESIZED_ANCESTORS + missing = [ + ancestor + for stem in live + for ancestor in ( + stem[:2] + "000000", + stem[:4] + "0000", + stem[:6] + "00", + ) + if ancestor not in live + ] + assert missing == [] + + def test_regenerate_check_is_clean(self) -> None: + root = Path(__file__).resolve().parents[3] + script = str(root / "tools" / "regenerate_unspsc_data.py") + proc = subprocess.run( + [sys.executable, script, "--check"], + capture_output=True, + text=True, + cwd=root, + ) + assert proc.returncode == 0, proc.stderr or proc.stdout diff --git a/tests/capabilities/unspsc/test_contract.py b/tests/capabilities/unspsc/test_contract.py new file mode 100644 index 00000000..7e7e853e --- /dev/null +++ b/tests/capabilities/unspsc/test_contract.py @@ -0,0 +1,64 @@ +"""Tests for UNSPSCContract.""" + +import pytest + +from paxman.capabilities.UNSPSC.capability import UNSPSCCapability +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.core.capability_contract import CapabilityContract +from paxman.core.errors import ContractError + + +@pytest.mark.capability +class TestUNSPSCContract: + """Contract defaults, offered formats, and feature flags.""" + + def test_defaults(self) -> None: + contract = UNSPSCContract() + assert contract.capability_name == "unspsc" + assert contract.output_format == "unspsc" + assert contract.excluded_rules == () + assert contract.pinned_rules is None + assert contract.year is None + assert contract.extra_grammars == () + assert contract.include_business_function is True + + def test_inherits_capability_contract(self) -> None: + assert issubclass(UNSPSCContract, CapabilityContract) + assert UNSPSCContract.__dataclass_params__.frozen is True + assert "__slots__" not in UNSPSCContract.__dict__ + contract = UNSPSCContract() + assert isinstance(contract, CapabilityContract) + assert "__dict__" in dir(contract) + + def test_offered_formats(self) -> None: + assert UNSPSCContract.DEFAULT_OUTPUT_FORMAT == "unspsc" + assert frozenset({"labeled", "native"}) == ( + UNSPSCContract.OFFERED_OUTPUT_FORMATS + ) + assert "unspsc" not in UNSPSCContract.OFFERED_OUTPUT_FORMATS + assert ( + UNSPSCCapability.create_contract(output_format="labeled").output_format + == "labeled" + ) + assert ( + UNSPSCCapability.create_contract(output_format="native").output_format + == "native" + ) + + def test_segmented_not_offered(self) -> None: + with pytest.raises(ContractError): + UNSPSCCapability.create_contract(output_format="segmented") + + def test_rejects_unknown_format(self) -> None: + with pytest.raises(ContractError): + UNSPSCCapability.create_contract(output_format="bogus") + + def test_forwards_common_block_and_flags(self) -> None: + contract = UNSPSCCapability.create_contract( + excluded_rules=("Section 1-hierarchy-structure",), + year=2023, + include_business_function=False, + ) + assert contract.excluded_rules == ("Section 1-hierarchy-structure",) + assert contract.year == 2023 + assert contract.include_business_function is False diff --git a/tests/capabilities/unspsc/test_grammar.py b/tests/capabilities/unspsc/test_grammar.py new file mode 100644 index 00000000..91879f03 --- /dev/null +++ b/tests/capabilities/unspsc/test_grammar.py @@ -0,0 +1,102 @@ +"""Tests for UNSPSCRecognitionGrammar (§2.1 inventory, §2.2 wild shapes).""" + +import pytest + +from paxman.capabilities.UNSPSC.grammar.unspsc_recognition import ( + UNSPSCRecognitionGrammar, +) + + +@pytest.mark.capability +class TestUNSPSCRecognitionGrammar: + """unspsc_recognition claims every §2.1 RECOGNIZE row with exact spans.""" + + def setup_method(self) -> None: + self.grammar = UNSPSCRecognitionGrammar() + + def test_identity(self) -> None: + assert self.grammar.name == "unspsc_recognition" + assert self.grammar.semantics == "unspsc_recognition" + assert self.grammar.single_value is True + + @pytest.mark.parametrize( + ("text", "digits", "level", "function", "native_length", "span"), + [ + ("44103103", "44103103", "commodity", "", 8, (0, 8)), + ("43211503", "43211503", "commodity", "", 8, (0, 8)), + ("10101501", "10101501", "commodity", "", 8, (0, 8)), + ("25101703", "25101703", "commodity", "", 8, (0, 8)), + ("43000000", "43000000", "segment", "", 8, (0, 8)), + ("43210000", "43210000", "family", "", 8, (0, 8)), + ("43211500", "43211500", "class", "", 8, (0, 8)), + ("441217", "44121700", "class", "", 6, (0, 6)), + ("UNSPSC 44103103", "44103103", "commodity", "", 8, (0, 15)), + ("UNSPSC: 44103103", "44103103", "commodity", "", 8, (0, 16)), + ("UNSPSC #43211507", "43211507", "commodity", "", 8, (0, 16)), + ("unspsc 44103103", "44103103", "commodity", "", 8, (0, 15)), + ("UNSPSC000.44103103", "44103103", "commodity", "", 8, (0, 18)), + ("4410310314", "44103103", "commodity", "14", 10, (0, 10)), + ("unspsc,43211509", "43211509", "commodity", "", 8, (7, 15)), + ("44103103.0", "44103103", "commodity", "", 8, (0, 8)), + ( + "see UNSPSC 44103103 (Printers)", + "44103103", + "commodity", + "", + 8, + (4, 19), + ), + ( + "Printers (44103103) approved", + "44103103", + "commodity", + "", + 8, + (10, 18), + ), + ], + ) + def test_recognize_rows( + self, + text: str, + digits: str, + level: str, + function: str, + native_length: int, + span: tuple[int, int], + ) -> None: + matches = self.grammar.recognize(text) + assert len(matches) == 1 + assert matches[0].notation.digits == digits + assert matches[0].notation.level == level + assert matches[0].notation.function == function + assert matches[0].notation.native_length == native_length + assert (matches[0].start, matches[0].end) == span + assert matches[0].raw_text == text[span[0] : span[1]] + + def test_multiple_matches(self) -> None: + matches = self.grammar.recognize("44103103, 43211503") + assert [(m.start, m.end) for m in matches] == [(0, 8), (10, 18)] + assert [m.notation.digits for m in matches] == ["44103103", "43211503"] + + @pytest.mark.parametrize( + "text", + [ + "43", + "4321", + "43 21 15 03", + "43.21.15.03", + "4410-3103", + "44103103-14", + "44-44103103", + "4410310", + "441031031", + "44103103144", + "X44103103", + "44103103Y", + "A4410310314B", + "", + ], + ) + def test_reject_rows(self, text: str) -> None: + assert self.grammar.recognize(text) == [] diff --git a/tests/capabilities/unspsc/test_notation.py b/tests/capabilities/unspsc/test_notation.py new file mode 100644 index 00000000..e369c64b --- /dev/null +++ b/tests/capabilities/unspsc/test_notation.py @@ -0,0 +1,58 @@ +"""Tests for UNSPSCNotation.""" + +import dataclasses + +import pytest + +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation + + +@pytest.mark.capability +class TestUNSPSCNotation: + """UNSPSC notation carries the 8-digit stem plus level/function facets.""" + + def test_field_invariants(self) -> None: + n = UNSPSCNotation( + digits="43211503", level="commodity", function="", native_length=8 + ) + assert n.digits == "43211503" + assert n.level == "commodity" + assert n.function == "" + assert n.native_length == 8 + assert len(n.digits) == 8 + + def test_frozen_slots_hashable(self) -> None: + n = UNSPSCNotation( + digits="43211503", level="commodity", function="", native_length=8 + ) + with pytest.raises(dataclasses.FrozenInstanceError): + n.digits = "other" # type: ignore[misc] + assert hasattr(n, "__slots__") + assert hash(n) == hash( + UNSPSCNotation( + digits="43211503", level="commodity", function="", native_length=8 + ) + ) + + def test_level_derivation(self) -> None: + cases = { + "43000000": "segment", + "43210000": "family", + "43211500": "class", + "43211503": "commodity", + } + for digits, level in cases.items(): + n = UNSPSCNotation(digits=digits, level=level, function="", native_length=8) + assert n.level == level + + def test_native_length_lane(self) -> None: + alias = UNSPSCNotation( + digits="44121700", level="class", function="", native_length=6 + ) + assert alias.native_length == 6 + assert alias.digits == "44121700" + bfi = UNSPSCNotation( + digits="44103103", level="commodity", function="14", native_length=10 + ) + assert bfi.native_length == 10 + assert bfi.function == "14" diff --git a/tests/capabilities/unspsc/test_rules.py b/tests/capabilities/unspsc/test_rules.py new file mode 100644 index 00000000..5d7c2036 --- /dev/null +++ b/tests/capabilities/unspsc/test_rules.py @@ -0,0 +1,221 @@ +"""Tests for UNSPSC rules (UNGM structure, UNDP codeset, UNECE BFI).""" + +import pytest + +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.capabilities.UNSPSC.rules.undp_unspsc_codeset_ed2026 import ( + Section3CodesetMembership, +) +from paxman.capabilities.UNSPSC.rules.undp_unspsc_structure_ed2025 import ( + Section1HierarchyStructure, + Section2LevelPadding, +) +from paxman.capabilities.UNSPSC.rules.unece_bfi_ed2005 import ( + Section4BusinessFunctionSuffix, +) +from paxman.core.domain import RuleStrategy + + +def _notation( + digits: str, native_length: int = 8, function: str = "" +) -> UNSPSCNotation: + if digits.endswith("000000"): + level = "segment" + elif digits.endswith("0000"): + level = "family" + elif digits.endswith("00"): + level = "class" + else: + level = "commodity" + return UNSPSCNotation( + digits=digits, level=level, function=function, native_length=native_length + ) + + +@pytest.mark.capability +class TestSection1HierarchyStructure: + """Section 1-hierarchy-structure: 6/8/10 lane, ASCII digits.""" + + def setup_method(self) -> None: + self.rule = Section1HierarchyStructure() + self.contract = UNSPSCContract() + + def test_metadata(self) -> None: + assert self.rule.name == "Section 1-hierarchy-structure" + assert self.rule.strategy is RuleStrategy.PARSER + assert self.rule.target_semantics == frozenset({"unspsc_recognition"}) + assert self.rule.requires_features == frozenset() + assert self.rule.provenance.authority == "United Nations Development Programme" + assert self.rule.provenance.kind == "specification" + assert self.rule.provenance.version == "2025-07-08" + assert self.rule.provenance.publication_year == 2025 + + @pytest.mark.parametrize( + ("digits", "native_length", "function"), + [ + ("44103103", 8, ""), + ("43000000", 8, ""), + ("44121700", 6, ""), + ("44103103", 10, "14"), + ], + ) + def test_accepts_lanes( + self, digits: str, native_length: int, function: str + ) -> None: + notation = _notation(digits, native_length, function) + assert self.rule.matches(notation, self.contract) is True + + @pytest.mark.parametrize( + ("digits", "native_length", "function"), + [ + ("4410310", 7, ""), + ("441031", 6, ""), + ("44103103", 8, "1"), + ("44103A03", 8, ""), + ], + ) + def test_rejects_bad_shapes( + self, digits: str, native_length: int, function: str + ) -> None: + notation = _notation(digits, native_length, function) + assert self.rule.matches(notation, self.contract) is False + + def test_normalize_returns_stem(self) -> None: + assert ( + self.rule.normalize(_notation("44121700", 6), self.contract) == "44121700" + ) + assert ( + self.rule.normalize(_notation("44103103", 10, "14"), self.contract) + == "44103103" + ) + + +@pytest.mark.capability +class TestSection2LevelPadding: + """Section 2-level-padding: 00-pair lattice consistency.""" + + def setup_method(self) -> None: + self.rule = Section2LevelPadding() + self.contract = UNSPSCContract() + + def test_metadata(self) -> None: + assert self.rule.name == "Section 2-level-padding" + assert self.rule.strategy is RuleStrategy.PARSER + assert self.rule.target_semantics == frozenset({"unspsc_recognition"}) + assert self.rule.requires_features == frozenset() + assert self.rule.provenance is Section1HierarchyStructure.provenance + + @pytest.mark.parametrize( + "digits", + ["43000000", "43210000", "43211500", "43211503", "44103103", "10101501"], + ) + def test_accepts_lattice(self, digits: str) -> None: + assert self.rule.matches(_notation(digits), self.contract) is True + + @pytest.mark.parametrize("digits", ["43001503", "00101501"]) + def test_rejects_mid_zero(self, digits: str) -> None: + assert self.rule.matches(_notation(digits), self.contract) is False + + def test_wellformed_unissued_passes_padding(self) -> None: + # "43111503" is lattice-consistent; unissued-ness is Section 3's job. + assert self.rule.matches(_notation("43111503"), self.contract) is True + + def test_normalize_returns_stem(self) -> None: + assert self.rule.normalize(_notation("43211503"), self.contract) == "43211503" + + +@pytest.mark.capability +class TestSection3CodesetMembership: + """Section 3-codeset-membership: stem + live ancestors in the snapshot.""" + + def setup_method(self) -> None: + self.rule = Section3CodesetMembership() + self.contract = UNSPSCContract() + + def test_metadata(self) -> None: + assert self.rule.name == "Section 3-codeset-membership" + assert self.rule.strategy is RuleStrategy.LOOKUP_TABLE + assert self.rule.target_semantics == frozenset({"unspsc_recognition"}) + assert self.rule.requires_features == frozenset() + assert self.rule.provenance.kind == "registry" + assert self.rule.provenance.version.startswith("UNGM live export") + + @pytest.mark.parametrize( + "digits", + [ + "44103103", + "43211503", + "10101501", + "25101703", + "43000000", + "43210000", + "43211500", + "44121700", + ], + ) + def test_accepts_issued(self, digits: str) -> None: + assert self.rule.matches(_notation(digits), self.contract) is True + + @pytest.mark.parametrize("digits", ["44103199", "99999999", "43111503"]) + def test_rejects_unissued(self, digits: str) -> None: + assert self.rule.matches(_notation(digits), self.contract) is False + + def test_requires_live_ancestors(self) -> None: + # Synthetic stem with a dead family ancestor: well-formed and + # 8-digit but no live row for the stem or its ancestors. + assert self.rule.matches(_notation("43991503"), self.contract) is False + + def test_synthesized_ancestor_alone_is_invalid(self) -> None: + # 57110000 serves the ancestor walk only — not stem membership. + assert self.rule.matches(_notation("57110000"), self.contract) is False + # Classes beneath a synthesized ancestor still pass the walk. + assert self.rule.matches(_notation("57111100"), self.contract) is True + + def test_normalize_returns_stem(self) -> None: + assert self.rule.normalize(_notation("44103103"), self.contract) == "44103103" + + +@pytest.mark.capability +class TestSection4BusinessFunctionSuffix: + """Section 4-business-function-suffix: informative-only suffix lane.""" + + def setup_method(self) -> None: + self.rule = Section4BusinessFunctionSuffix() + self.contract = UNSPSCContract() + + def test_metadata(self) -> None: + assert self.rule.name == "Section 4-business-function-suffix" + assert self.rule.strategy is RuleStrategy.PARSER + assert self.rule.target_semantics == frozenset({"unspsc_recognition"}) + assert self.rule.requires_features == frozenset({"include_business_function"}) + assert ( + self.rule.provenance.authority + == "United Nations Economic Commission for Europe" + ) + assert self.rule.provenance.kind == "specification" + assert self.rule.provenance.version == "v2.04" + + @pytest.mark.parametrize("function", ["00", "14", "99"]) + def test_passes_any_suffix(self, function: str) -> None: + notation = _notation("44103103", 10, function) + assert self.rule.matches(notation, self.contract) is True + + @pytest.mark.parametrize( + ("digits", "native_length"), + [("44103103", 8), ("44121700", 6)], + ) + def test_rejects_short_lanes(self, digits: str, native_length: int) -> None: + # The rule speaks only to the 10-digit lane: on shorter lanes it + # abstains (False), so no UNECE provenance attaches to suffix-less + # inputs and a pinned-Section-4 contract cannot validate garbage. + notation = _notation(digits, native_length) + assert self.rule.matches(notation, self.contract) is False + + def test_rejects_malformed_suffix(self) -> None: + notation = _notation("44103103", 10, "1") + assert self.rule.matches(notation, self.contract) is False + + def test_normalize_returns_stem(self) -> None: + notation = _notation("44103103", 10, "14") + assert self.rule.normalize(notation, self.contract) == "44103103" diff --git a/tests/integration/test_unspsc_pipeline.py b/tests/integration/test_unspsc_pipeline.py new file mode 100644 index 00000000..f0ecfe69 --- /dev/null +++ b/tests/integration/test_unspsc_pipeline.py @@ -0,0 +1,204 @@ +"""Integration tests for the UNSPSC capability through the full pipeline. + +Resolution-state map: research `2026-09-30-unspsc-canonicalization.md` §9. +Every vector below was executed against the pipeline +(`register_all_shipped` + `canonicalize`); statuses are observed, not assumed. +""" + +from __future__ import annotations + +from collections.abc import Iterator + +import pytest + +import paxman +from paxman.capabilities.UNSPSC.capability import UNSPSCCapability +from paxman.core.discovery import reset_registry +from paxman.core.domain import Resolution +from paxman.core.errors import MultipleMentionsError + + +@pytest.fixture(autouse=True) +def _clean_registry() -> Iterator[None]: + """Reset the capability registry before and after each test.""" + reset_registry() + yield + reset_registry() + + +@pytest.mark.integration +class TestUNSPSCSuccess: + """Valid commodity/parent/alias/label/MDM/BFI inputs resolve SUCCESS.""" + + @pytest.mark.parametrize( + ("text", "expected"), + [ + ("44103103", "44103103"), + ("43211503", "43211503"), + ("10101501", "10101501"), + ("25101703", "25101703"), + ("43000000", "43000000"), + ("43210000", "43210000"), + ("43211500", "43211500"), + ("441217", "44121700"), + ("UNSPSC 44103103", "44103103"), + ("UNSPSC: 44103103", "44103103"), + ("UNSPSC000.44103103", "44103103"), + ("unspsc,43211509", "43211509"), + ("4410310314", "44103103"), + ("Printers (44103103) approved", "44103103"), + ], + ) + def test_success_rows(self, text: str, expected: str) -> None: + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + result = paxman.canonicalize(text, contract) + assert result.status == Resolution.SUCCESS + assert result.canonicalized_value == expected + + def test_label_vs_bare_dedups_to_one(self) -> None: + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + result = paxman.canonicalize("44103103 (UNSPSC 44103103)", contract) + assert result.status == Resolution.SUCCESS + assert result.canonicalized_value == "44103103" + + def test_span_bearing_match(self) -> None: + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + result = paxman.canonicalize("see UNSPSC 44103103 (Printers)", contract) + assert result.status == Resolution.SUCCESS + assert result.span == (4, 19) + + def test_output_formats(self) -> None: + paxman.register_all_shipped() + assert ( + paxman.canonicalize( + "44103103", + UNSPSCCapability.create_contract(output_format="labeled"), + ).canonicalized_value + == "UNSPSC 44103103" + ) + assert ( + paxman.canonicalize( + "441217", UNSPSCCapability.create_contract(output_format="native") + ).canonicalized_value + == "441217" + ) + assert ( + paxman.canonicalize( + "4410310314", UNSPSCCapability.create_contract(output_format="native") + ).canonicalized_value + == "4410310314" + ) + + def test_determinism(self) -> None: + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + first = paxman.canonicalize("UNSPSC 44103103", contract) + second = paxman.canonicalize("UNSPSC 44103103", contract) + assert first.status == second.status == Resolution.SUCCESS + assert first.canonicalized_value == second.canonicalized_value == "44103103" + assert first.version_stamp == second.version_stamp + + +@pytest.mark.integration +class TestUNSPSCMissing: + """Unclaimed surfaces resolve MISSING (grammar never fires).""" + + @pytest.mark.parametrize( + "text", + [ + "43 21 15 03", + "43.21.15.03", + "4410-3103", + "43", + "4321", + "4410310", + "441031031", + "scaffold probe", + "", + ], + ) + def test_missing_rows(self, text: str) -> None: + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + result = paxman.canonicalize(text, contract) + assert result.status == Resolution.MISSING + + +@pytest.mark.integration +class TestUNSPSCInvalid: + """Claimed but rejected inputs resolve INVALID (rule veto).""" + + @pytest.mark.parametrize( + "text", + [ + "43001503", + "00101501", + "44103199", + "99999999", + "11101803", + "57110000", + ], + ) + def test_invalid_rows(self, text: str) -> None: + # "11101803" (Wikidata-cited platinum) is absent from the pinned + # UNGM-export snapshot, so it is INVALID under this snapshot by + # design — not a claim about the full UNDP codeset. + # "57110000" is a synthesized ancestor: it serves the ancestor walk + # only, never stem membership. + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + result = paxman.canonicalize(text, contract) + assert result.status == Resolution.INVALID + + def test_bfi_gated_off_drops_suffix_candidate(self) -> None: + # Dropping Section 4 removes its candidate/provenance but the stem + # is still validated by Sections 1-3, so the verdict stays SUCCESS + # (ISBN include_range_validation precedent — corroborating-rule + # gating changes provenance, not the verdict). + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract(include_business_function=False) + result = paxman.canonicalize("4410310314", contract) + assert result.status == Resolution.SUCCESS + assert result.canonicalized_value == "44103103" + assert all( + c.validation_rule != "Section 4-business-function-suffix" + for c in result.candidates + ) + assert any( + c.validation_rule == "Section 4-business-function-suffix" + for c in paxman.canonicalize( + "4410310314", UNSPSCCapability.create_contract() + ).candidates + ) + + def test_year_filter_drops_structure_and_codeset(self) -> None: + # year=2023 drops the 2025/2026 rules, leaving only the 2005 BFI + # rule: 8-digit inputs go INVALID (Section 4 abstains off-lane). + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract(year=2023) + result = paxman.canonicalize("44103103", contract) + assert result.status == Resolution.INVALID + + def test_year_filter_leaves_bfi_shape_alone(self) -> None: + # Residual (disclosed in the Section 4 module docstring): with only + # the 2005 rule standing, a 10-digit input SUCCESSes on suffix shape + # alone with no codeset check (ADR-0012 vacuity). + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract(year=2023) + result = paxman.canonicalize("4410310314", contract) + assert result.status == Resolution.SUCCESS + assert result.canonicalized_value == "44103103" + + +@pytest.mark.integration +class TestUNSPSCAmbiguity: + """Two distinct stems in one slice raise MultipleMentionsError.""" + + def test_two_distinct_raise(self) -> None: + paxman.register_all_shipped() + contract = UNSPSCCapability.create_contract() + with pytest.raises(MultipleMentionsError): + paxman.canonicalize("44103103, 43211503", contract) diff --git a/tests/property/test_output_format_preservation.py b/tests/property/test_output_format_preservation.py index bac7d3f7..b7c1249f 100644 --- a/tests/property/test_output_format_preservation.py +++ b/tests/property/test_output_format_preservation.py @@ -73,6 +73,7 @@ ISSN, LEI, ORCID, + UNSPSC, UUID, ChemicalElement, Coordinates, @@ -231,6 +232,15 @@ def _default_kwargs(row: _ReEntryRow) -> dict[str, object]: ("uuid", "compact"): "encoding", ("uuid", "braced"): "encoding", ("uuid", "urn"): "encoding", + # -- UNSPSC -------------------------------------------------------------- + # labeled: fixed "UNSPSC " carrier-only re-encoding of the wire stem; + # the rendering re-enters the default contract onto the stem via the + # fused label lane (measured in TestUNSPSCCapability). + ("unspsc", "labeled"): "encoding", + # native: spelling-preserving re-encoding (6-digit alias unpadded, + # 10-digit keeps its suffix); injective across length lanes and + # re-enters via the 6/8/10 alternation (measured). + ("unspsc", "native"): "encoding", } _CLASS_VALUES: frozenset[str] = frozenset( @@ -521,6 +531,15 @@ class _InjectivityPair: "10.1000/182", "", ), + _InjectivityPair("unspsc", UNSPSC, "labeled", "44103103", "43211503", ""), + _InjectivityPair( + "unspsc", + UNSPSC, + "native", + "441217", + "43211503", + "alias vs commodity lanes", + ), ) _INJECTIVITY_PARAMS: list[pytest.param] = [ diff --git a/tests/property/test_reentry_invariant.py b/tests/property/test_reentry_invariant.py index 4a7e2d50..cdbebe3e 100644 --- a/tests/property/test_reentry_invariant.py +++ b/tests/property/test_reentry_invariant.py @@ -60,6 +60,7 @@ ISSN, LEI, ORCID, + UNSPSC, URL, UUID, ChemicalElement, @@ -242,6 +243,12 @@ def _row( "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "6ba7b810-9dad-11d1-80b4-00c04fd430c8", ), + # UNSPSC: tests/capabilities/unspsc/test_capability.py — 8-digit wire + # canonical; the offered labeled rendering re-enters via the fused + # label lane and native re-enters as the spelled lane (6/8/10 all + # recognized). Segmented display is deliberately unoffered (hyphens + # never re-enter by design). + _row(UNSPSC, "UNSPSC 44103103", "44103103"), ) # ADR-0010, Consequences: a new capability cannot land without a re-entry row diff --git a/tests/property/test_unspsc_properties.py b/tests/property/test_unspsc_properties.py new file mode 100644 index 00000000..82a2ba31 --- /dev/null +++ b/tests/property/test_unspsc_properties.py @@ -0,0 +1,122 @@ +"""Hypothesis property tests for the UNSPSC capability. + +- a stem sampled from the pinned snapshot self-canonicalizes through the + full pipeline (membership fixed point); +- random 8-digit input never raises and resolves INVALID with high + probability (≈1 − 13490/10⁸; a sampled live stem legitimately succeeds); +- a 6-digit alias and its padded stem share every rule's ``normalize()``; +- non-digit mutations of a live stem never match the grammar; +- snapshot self-consistency: every stem's pair-prefix ancestors are live + rows, and every rule's ``target_semantics`` is produced by the shipped + grammar. + +Fixture-row self-canonicalization lives in +``tests/property/test_reentry_invariant.py`` ROWS; the ADR-0011 classes +live in ``tests/property/test_output_format_preservation.py`` CLASS_MAP. + +Registry posture: the fuzz properties drive the full pipeline +(robustness cannot be observed off-pipeline), so this module uses a +local ``_fresh_registry`` fixture registering only UNSPSC — the +documented ``test_money_properties.py`` exception pattern. +""" + +from __future__ import annotations + +from collections.abc import Iterator + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +from paxman.api.canonicalize import canonicalize +from paxman.capabilities.UNSPSC.capability import UNSPSCCapability +from paxman.capabilities.UNSPSC.contract import UNSPSCContract +from paxman.capabilities.UNSPSC.grammar.unspsc_recognition import ( + UNSPSCRecognitionGrammar, +) +from paxman.capabilities.UNSPSC.notation import UNSPSCNotation +from paxman.capabilities.UNSPSC.rules.data.unspsc_codeset import LIVE_STEMS +from paxman.core.discovery import register_capability, reset_registry +from paxman.core.domain import Resolution + +pytestmark = pytest.mark.property + +_STEMS = sorted(LIVE_STEMS) + + +@pytest.fixture(autouse=True) +def _fresh_registry() -> Iterator[None]: + """Reset the registry and register UNSPSC around each test.""" + reset_registry() + register_capability(UNSPSCCapability()) + yield + reset_registry() + + +def _grammar_notation(text: str) -> UNSPSCNotation: + matches = UNSPSCRecognitionGrammar().recognize(text) + assert len(matches) == 1 + return matches[0].notation + + +@given(stem=st.sampled_from(_STEMS)) +def test_live_stem_self_canonicalizes(stem: str) -> None: + """Every snapshot stem canonicalizes to itself (membership fixed point).""" + contract = UNSPSCCapability.create_contract() + result = canonicalize(stem, contract) + assert result.status is Resolution.SUCCESS + assert result.canonicalized_value == stem + + +@given(body=st.from_regex(r"[0-9]{8}", fullmatch=True)) +def test_random_8_digit_never_raises(body: str) -> None: + """Random 8-digit input resolves without raising (usually INVALID).""" + contract = UNSPSCCapability.create_contract() + result = canonicalize(body, contract) + assert result.status in (Resolution.SUCCESS, Resolution.INVALID) + if body not in LIVE_STEMS: + assert result.status is Resolution.INVALID + + +@given(stem=st.sampled_from(_STEMS)) +def test_alias_and_padded_share_normalize(stem: str) -> None: + """All four rules agree on the 8-digit stem as the dedup key.""" + capability = UNSPSCCapability() + contract = UNSPSCContract() + notation = UNSPSCNotation( + digits=stem, level="commodity", function="", native_length=8 + ) + assert {rule.normalize(notation, contract) for rule in capability.get_rules()} == { + stem + } + + +@given(stem=st.sampled_from(_STEMS), pos=st.integers(0, 7)) +def test_nondigit_mutation_never_matches(stem: str, pos: int) -> None: + """Replacing one digit with a letter kills recognition (no carving).""" + mutated = stem[:pos] + "X" + stem[pos + 1 :] + assert UNSPSCRecognitionGrammar().recognize(mutated) == [] + + +def test_snapshot_prefix_closure() -> None: + """Every stem's pair-prefix ancestors resolve (live + synthesized).""" + from paxman.capabilities.UNSPSC.rules.data.unspsc_codeset import ( + SYNTHESIZED_ANCESTORS, + ) + + live = LIVE_STEMS | SYNTHESIZED_ANCESTORS + missing = [ + ancestor + for stem in live + for ancestor in (stem[:2] + "000000", stem[:4] + "0000", stem[:6] + "00") + if ancestor not in live + ] + assert missing == [] + + +def test_target_semantics_covered_by_grammar() -> None: + """Every rule's target_semantics is produced by the shipped grammar.""" + capability = UNSPSCCapability() + produced = {grammar.semantics for grammar in capability.get_grammars()} + for rule in capability.get_rules(): + assert set(rule.target_semantics) <= produced diff --git a/tests/unit/test_api_coverage_fix.py b/tests/unit/test_api_coverage_fix.py index 768ba425..84c5f933 100644 --- a/tests/unit/test_api_coverage_fix.py +++ b/tests/unit/test_api_coverage_fix.py @@ -29,7 +29,7 @@ def test_list_shipped_and_registered(): assert "gtin" in shipped assert "credit_card" in shipped assert "domain" in shipped - assert len(shipped) == 28 + assert len(shipped) == 29 registered = paxman.list_registered_capabilities() assert isinstance(registered, tuple) # after register, registered should equal shipped diff --git a/tests/unit/test_bootstrap.py b/tests/unit/test_bootstrap.py index f2a7e079..1458e646 100644 --- a/tests/unit/test_bootstrap.py +++ b/tests/unit/test_bootstrap.py @@ -52,6 +52,7 @@ def test_registers_all_shipped(_clean_registry) -> None: "phone", "si_unit", "timezone", + "unspsc", "url", "utc_offset", "uuid", @@ -73,7 +74,7 @@ def test_preserves_caller_registration(_clean_registry) -> None: register_capability(mine) names = paxman.register_all_shipped() assert "email" not in names - assert len(names) == 27 + assert len(names) == 28 assert get_capability("email") is mine diff --git a/tests/unit/test_capability_exports.py b/tests/unit/test_capability_exports.py index a7b2f38b..5a672365 100644 --- a/tests/unit/test_capability_exports.py +++ b/tests/unit/test_capability_exports.py @@ -23,6 +23,7 @@ Phone, SIUnit, Timezone, + UNSPSC, URL, UtcOffset, ) @@ -244,6 +245,18 @@ def test_timezone_capability_name(self) -> None: assert Timezone.name == "timezone" +class TestUNSPSCCapabilityExports: + @pytest.mark.unit + def test_unspsc_capability_importable(self) -> None: + """UNSPSC capability is importable from paxman.capabilities.""" + assert UNSPSC is not None + + @pytest.mark.unit + def test_unspsc_capability_name(self) -> None: + """UNSPSC capability has correct name.""" + assert UNSPSC.name == "unspsc" + + class TestUtcOffsetCapabilityExports: @pytest.mark.unit def test_utc_offset_capability_importable(self) -> None: @@ -298,6 +311,7 @@ def test_export_list_contains_all_shipped_names(self) -> None: "Phone", "SIUnit", "Timezone", + "UNSPSC", "URL", "UUID", "UtcOffset", diff --git a/tests/unit/test_capability_lazy_import.py b/tests/unit/test_capability_lazy_import.py index c9de14a3..0c0946b1 100644 --- a/tests/unit/test_capability_lazy_import.py +++ b/tests/unit/test_capability_lazy_import.py @@ -53,7 +53,7 @@ def test_import_email_does_not_import_url_data() -> None: def test_all_still_exported_via_all() -> None: - """`__all__` must still list all twenty-eight capabilities for star-import.""" + """`__all__` must still list all twenty-nine capabilities for star-import.""" import paxman.capabilities as cap_mod assert set(cap_mod.__all__) == { @@ -82,6 +82,7 @@ def test_all_still_exported_via_all() -> None: "Phone", "SIUnit", "Timezone", + "UNSPSC", "URL", "UUID", "UtcOffset", diff --git a/tests/unit/test_capability_surface.py b/tests/unit/test_capability_surface.py index aae4f53e..78cd1be1 100644 --- a/tests/unit/test_capability_surface.py +++ b/tests/unit/test_capability_surface.py @@ -67,6 +67,8 @@ from paxman.capabilities.SIUnit.notation import SIUnitNotation from paxman.capabilities.Timezone.capability import TimezoneCapability from paxman.capabilities.Timezone.contract import TimezoneContract +from paxman.capabilities.UNSPSC.capability import UNSPSCCapability +from paxman.capabilities.UNSPSC.contract import UNSPSCContract from paxman.capabilities.URL.capability import URLCapability from paxman.capabilities.URL.contract import URLCapabilityContract from paxman.capabilities.URL.notation import URLNotation @@ -236,6 +238,12 @@ "url", id="url", ), + pytest.param( + UNSPSCCapability, + UNSPSCContract, + "unspsc", + id="unspsc", + ), pytest.param( TimezoneCapability, TimezoneContract, diff --git a/tests/unit/test_offered_format_class_declarations.py b/tests/unit/test_offered_format_class_declarations.py index d747f703..b76173f4 100644 --- a/tests/unit/test_offered_format_class_declarations.py +++ b/tests/unit/test_offered_format_class_declarations.py @@ -37,6 +37,7 @@ ISSN, LEI, ORCID, + UNSPSC, URL, UUID, ChemicalElement, @@ -86,6 +87,7 @@ "chemical_element": ChemicalElement, "si_unit": SIUnit, "timezone": Timezone, + "unspsc": UNSPSC, "url": URL, "utc_offset": UtcOffset, "uuid": UUID, diff --git a/tools/generate_readme_table.py b/tools/generate_readme_table.py index 169b3bcd..f320bbec 100644 --- a/tools/generate_readme_table.py +++ b/tools/generate_readme_table.py @@ -77,6 +77,10 @@ "phone": ("Phone numbers", "ITU-T E.164, RFC 3966, NANP"), "si_unit": ("SI unit expressions", "BIPM SI Brochure, ISO 80000-1"), "timezone": ("Timezone identifiers", "IANA Time Zone Database"), + "unspsc": ( + "Product/service codes", + "UNDP UNSPSC (UNGM structure, UNGM live-export snapshot, UNECE BFI)", + ), "url": ("URLs", "WHATWG URL Standard"), "utc_offset": ("UTC offsets", "ISO 8601-1:2019, RFC 3339"), "uuid": ("UUIDs", "IETF RFC 9562"), @@ -108,6 +112,7 @@ "phone": "Phone", "si_unit": "SI Unit", "timezone": "Timezone", + "unspsc": "UNSPSC", "url": "URL", "utc_offset": "UtcOffset", "uuid": "UUID", diff --git a/tools/regenerate_unspsc_data.py b/tools/regenerate_unspsc_data.py new file mode 100644 index 00000000..9ce70391 --- /dev/null +++ b/tools/regenerate_unspsc_data.py @@ -0,0 +1,140 @@ +"""Regenerate the UNSPSC codeset membership module from the shared snapshot. + +Source: paxman/shared_data/unspsc_snapshot.json + (UNGM Public/UNSPSC Excel export, fetched 2026-09-30; the UNDP + v26.0801 XLSX download is access-gated (403), so the snapshot holds + the live-directory subset until the full 158,448-row codeset can be + ingested — see the snapshot's ``full_codeset_note``). +Output (1 file, deterministic, sorted): +- paxman/capabilities/UNSPSC/rules/data/unspsc_codeset.py + +Step 0 (XLSX -> snapshot, one-time bootstrap, stdlib only): download the +UNGM export (https://www.ungm.org/Public/UNSPSC/Excel), unzip, read the +Code column (C) of xl/worksheets/sheet1.xml resolving shared strings via +xl/sharedStrings.xml, keep fullmatch(r'\\d{8}') codes, synthesize any +pair-prefix family ancestors implied by live classes (flagged in +``synthesized_ancestors``), and write the sorted stems to the snapshot. + +Usage: + uv run python tools/regenerate_unspsc_data.py + uv run python tools/regenerate_unspsc_data.py --check +""" + +from __future__ import annotations + +import argparse +import json +import sys +import textwrap +from pathlib import Path +from typing import cast + +ROOT = Path(__file__).resolve().parents[1] +SNAPSHOT = ROOT / "paxman" / "shared_data" / "unspsc_snapshot.json" +OUTPUT = ( + ROOT / "paxman" / "capabilities" / "UNSPSC" / "rules" / "data" / "unspsc_codeset.py" +) + +_GENERATED_HEADER = ( + "GENERATED by tools/regenerate_unspsc_data.py — do not edit by hand." +) + + +def _load_snapshot() -> dict[str, object]: + data: dict[str, object] = json.loads(SNAPSHOT.read_text(encoding="utf-8")) + return data + + +def _render_module(version: str, count: int, synth: list[str], stems: list[str]) -> str: + doc_lines = [ + _GENERATED_HEADER, + "", + "UNDP UNSPSC codeset snapshot (live-directory subset).", + "Source: UNGM Public/UNSPSC Excel export, fetched 2026-09-30.", + f"Stems: {count} live 8-digit codes.", + "Coverage: partial — the UNDP v26.0801 XLSX (158,448 items) is", + "access-gated; this table holds the live-directory subset until the", + "full codeset can be ingested. Do not cite stem absence as", + "codeset absence beyond this pinned snapshot.", + "SYNTHESIZED_ANCESTORS are family rows absent from the export but", + "implied by live classes beneath them (flagged in the snapshot).", + "They serve ancestor-liveness ONLY — never stem membership — so a", + "synthesized code alone resolves INVALID while classes beneath it", + "still pass the ancestor walk.", + "", + "Regenerate with: uv run python tools/regenerate_unspsc_data.py", + ] + wrapped = ['"""'] + for line in doc_lines: + wrapped += textwrap.wrap(line, width=88) if line else [""] + wrapped += ['"""', "", "from __future__ import annotations", ""] + wrapped += [ + f'CODESET_VERSION: str = "{version}"', + "", + "LIVE_STEMS: frozenset[str] = frozenset(", + " {", + ] + wrapped += [f' "{stem}",' for stem in stems] + wrapped += [ + " }", + ")", + "", + "SYNTHESIZED_ANCESTORS: frozenset[str] = frozenset(", + " {", + ] + wrapped += [f' "{stem}",' for stem in synth] + wrapped += [" }", ")", ""] + return "\n".join(wrapped) + + +def _modules() -> list[tuple[Path, str]]: + snap = _load_snapshot() + version = str(snap["codeset_version"]) + raw_stems = cast("list[str]", snap["stems"]) + stems = sorted(raw_stems) + raw_synth = cast("list[str]", snap.get("synthesized_ancestors", [])) + synth = sorted(raw_synth) + for stem in stems: + if len(stem) != 8 or not stem.isascii() or not stem.isdigit(): + raise SystemExit(f"snapshot holds non-8-digit stem: {stem!r}") + for stem in synth: + if len(stem) != 8 or not stem.isascii() or not stem.isdigit(): + raise SystemExit(f"snapshot holds non-8-digit ancestor: {stem!r}") + if set(stems) & set(synth): + raise SystemExit("snapshot stems and synthesized ancestors overlap") + text = _render_module(version, len(stems), synth, stems) + return [(OUTPUT, text)] + + +def main() -> None: + parser = argparse.ArgumentParser(description="Regenerate UNSPSC codeset data.") + parser.add_argument( + "--check", + action="store_true", + help="regenerate in memory and exit non-zero if the module drifts", + ) + args = parser.parse_args() + modules = _modules() + if args.check: + drifted = [ + path + for path, text in modules + if not path.exists() or path.read_text(encoding="utf-8") != text + ] + if drifted: + for path in drifted: + print( + f"DRIFT: {path.relative_to(ROOT)} differs from generated output", + file=sys.stderr, + ) + raise SystemExit(1) + print("UNSPSC codeset data module is up to date") + return + for path, text in modules: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(text, encoding="utf-8") + print(f"wrote {path.relative_to(ROOT)}") + + +if __name__ == "__main__": + main()