diff --git a/.nvmrc b/.nvmrc index b6a7d89..3c03207 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16 +18 diff --git a/DATA.md b/DATA.md index 3ca830a..d64983e 100644 --- a/DATA.md +++ b/DATA.md @@ -1,18 +1,18 @@ -Static data files -================= +How to generate static data files +================================= Load GNAF database ------------------ -* Install PostgreSQL 14 and PostGIS +* Install PostgreSQL and PostGIS (tested against PostgreSQL versions 14 and 15) * Create database (name assumed to be `gnaf` but can be anything) * Enable PostGIS extension on database: * `CREATE EXTENSION IF NOT EXISTS postgis;` -* Download database dumps from [gnaf-loader](https://github.com/minus34/gnaf-loader) (see Option 3) +* Download database dumps from [gnaf-loader](https://github.com/minus34/gnaf-loader) (see Option 3, GDA2020 version) * Import database dumps using pg_restore - * `pg_restore -d gnaf gnaf-202111.dmp` - * `pg_restore -d gnaf admin-bdys-202111.dmp` + * `pg_restore -d gnaf gnaf-202208.dmp` + * `pg_restore -d gnaf admin-bdys-202208.dmp` Generate data files @@ -21,6 +21,6 @@ Generate data files * Run bin/data.ts with PostgreSQL environment variables: * `PGDATABASE=gnaf ./bin/data.ts` * Optional: Pre-compress data files: - * `gzip -9 *.txt` - * Or ideally, if server handles brotli: `brotli --rm *.txt` + * `gzip -r -v -9 data/` + * Or for even smaller files: `pigz -r -v -11 data/` * Upload files to static hosting service / S3 bucket / etc. diff --git a/INDEXES.md b/INDEXES.md new file mode 100644 index 0000000..dcf2ab4 --- /dev/null +++ b/INDEXES.md @@ -0,0 +1,77 @@ +Address index format +==================== + + +How addresses are indexed and stored +------------------------------------ + +Address indexes are stored in static text files containing newline-delimetered JSON. + +Each file contains a subset of addresses that share a common street number and metaphone (a phonetic representation) of the street name or suburb. + + +JSON structure +-------------- + +Each line of JSON represents a "street" containing the street name, suburb, state/territory and postcode. + +Within each street there is an array of "blocks" on that street. Each block has a street number and coordinates. Coordinates are stored as a 9-character [geohash](https://en.wikipedia.org/wiki/Geohash) to conserve space and improve compression. + +Optionally, within each "block" there may an object mapping unit types to an array of unit numbers. + +For a TypeScript type definition, refer to the `Street` type in `src/types.ts`. + + +Where addresses are indexed +--------------------------- + +Addresses are indexed by words in the street name and suburb. Additionally, addresses are indexed by the street number. + +For each word in the street name and suburb, we take the first letter of the word and the metaphone (a phonetic represenation) of the word. We then index by a combination of the first letter and first three characters of the metaphone. We also index by a combination of the first letter, the street number modulo 20 and the first two characters of the metaphone. + +For example, this address: + +__Shop 17, Australia Square, 264-278 George Street, Sydney NSW 2000__ + +...will appear in the following indexes: + +* `G/4/JR` (G = first letter of GEORGE, 4 = 264 modulo 20, JR = 2-character metaphone of GEORGE) +* `G/_/JRJ` (G = first letter of GEORGE, _ = no street number, JRJ = 3-character metaphone of GEORGE) +* `S/4/ST` (S = first letter of SYDNEY, 4 = 264 modulo 20, ST = 2-character metaphone of SYDNEY) +* `S/_/STN` (S = first letter of SYDNEY, _ = no street number, STN = 3-character metaphone of SYDNEY) + + +How an address look will search indexes +--------------------------------------- + +Address lookups are first cleaned up by removing anything that's not a letter, number or space. + +We then analyse each word. Words that includes a digit somewhere (e.g. "123", "123A") require an exact match in the address. Words that do not include a digit (e.g. "sydney", "sidney", "syd") will be searched using a "fuzzy" algorithm that allows for misspellings and prefixes. + +For example, the following query: + +`17/264 george st sidney` + +...would be searched for in the following indexes: + +* `G/17/JR` (G = first letter of GEORGE, 17 = 17 modulo 20, JR = 2-character metaphone of GEORGE) +* `G/4/JR` (G = first letter of GEORGE, 4 = 264 modulo 20, JR = 2-character metaphone of GEORGE) +* `S/17/ST` (S = first letter of ST, 17 = 17 modulo 20, ST = 2-character metaphone of ST) +* `S/4/ST` (S = first letter of ST, 4 = 264 modulo 20, ST = 2-character metaphone of ST) +* `S/17/ST` (S = first letter of SIDNEY, 17 = 17 modulo 20, ST = 2-character metaphone of SIDNEY) +* `S/4/ST` (S = first letter of SIDNEY, 4 = 264 modulo 20, ST = 2-character metaphone of SIDNEY) + +If the query does not include a number then we have to widen the search to more potential addresses. We use the 3-character metaphones to offset the increase in potential addresses with a stricter fuzzy search. + +For example, the following query: + +`george st sidney` + +...would be searched for in the following indexes: + +* `G/_/JRJ` (G = first letter of GEORGE, _ = no number, JRJ = 3-character metaphone of GEORGE) +* `G/_/JRJ` (G = first letter of GEORGE, _ = no number, JRJ = 3-character metaphone of GEORGE) +* `S/_/ST` (S = first letter of ST, _ = no number, ST = 3-character metaphone of ST) +* `S/_/ST` (S = first letter of ST, _ = no number, ST = 3-character metaphone of ST) +* `S/_/STN` (S = first letter of SIDNEY, _ = no number, STN = 3-character metaphone of SIDNEY) +* `S/_/STN` (S = first letter of SIDNEY, _ = no number, STN = 3-character metaphone of SIDNEY) diff --git a/README.md b/README.md index 90ba9a1..103c896 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Browser-based geocoder for Australian addresses. Features -------- -* Based on GNAF (Geocoded National Address File of Australia) database +* Based on GNAF (Geocoded National Address File of Australia) database version 202208 * Very fast (e.g. fast enough for search-as-you-type) * Fuzzy search (typo tolerant, word prefixes, etc.) * Infinitely scalable when served via a CDN @@ -17,11 +17,11 @@ Function and return type ------------------------ ```typescript -function geocode(input: string, options?: { limit?: number }): Promise +function geocode(input: string, options?: { limit?: number, abortPrevious?: boolean }): Promise type GeocodeResult = { input: string, - group: string, + startTime: number, duration: number, results: Array<{ address: string, @@ -33,6 +33,12 @@ type GeocodeResult = { } ``` +Options +------- + +* `limit`: Set to a positive integer to limit results, or leave undefined for no limit. (Default: `undefined`) +* `abortPrevious`: Set to `true` to abort unresolved calls to geocode() before starting this one. Intended for use with search-as-you-type user interfaces. Will abort pending HTTP requests that are no longer needed, and abort unresolved calls to geocode() by throwing a `GeocodeAbortError`. (Default: `false`) + Example ------- @@ -40,7 +46,7 @@ Example ```typescript import geocode from 'geocoder'; -geocode('114 grey', { limit: 5 }).then(result => console.log(result)); +geocode('114 grey', { limit: 5, abortPrevious: true }).then(result => console.log(result)).catch(e => console.error(e)); /* Returns addresses: @@ -82,7 +88,7 @@ See [DATA.md](DATA.md) Demo ---- -https://www.abc.net.au/res/sites/news-projects/geocoder/0.1.0/ +https://www.abc.net.au/res/sites/news-projects/geocoder/0.6.0/ Authors diff --git a/bin/data.ts b/bin/data.ts index fc96706..e5ec60d 100755 --- a/bin/data.ts +++ b/bin/data.ts @@ -1,5 +1,7 @@ #!/usr/bin/env -S npx ts-eager +// Refer to DATA.md and INDEXES.md for more information about how this data is structured. + import { Street, Block, AddressNumber } from '../src/types'; import { resolve } from 'node:path'; import fs from 'node:fs'; @@ -7,7 +9,9 @@ import { once } from 'events'; import postgres from 'postgres'; import dotenv from 'dotenv'; import Geohash from 'latlon-geohash'; -//@ts-expect-error - missing types +import LRUMap from 'mnemonist/lru-map'; +import MultiMap from 'mnemonist/multi-map'; +//@ts-ignore - missing types import metaphone from 'metaphone'; declare function metaphone(word: string): string; @@ -18,147 +22,238 @@ function numberOrString(text: string): number | string { return isFinite(number) ? number : text; } +// We want users to see address suggestions once they have entered part of their street name or suburb. +// Assign streets to groups based on the street number, and each word from their street name and suburb +// e.g. "114 GREY STREET, SOUTH BRISBANE QLD 4101" => ["G/4/KR", "G/_/KR", "S/4/S0", "S/_/S0", "B/4/BR", "B/_/BRS"] +function getGroups(streetNumber: number | string, streetName: string, suburb: string): string[] { + let groups: string[] = []; + let words = [streetName, suburb] + .join(' ') + .toUpperCase() + .replace(/[^A-Z0-9 ]/g, '') + .replace(/ {2,}/g, ' ') + .split(' '); + let number = getStreetNumberGroup(streetNumber); + for (let word of words) { + let letter = word.substring(0, 1); + let phonetic3 = metaphone(word).substring(0, 3); + if (phonetic3.length > 0) { + groups.push([letter, '_', phonetic3].join('/')); + } + if (number !== null) { + let phonetic2 = phonetic3.substring(0, 2); + if (phonetic2.length > 0) { + groups.push([letter, number, phonetic2].join('/')); + } + } + } + return groups; +} + +// Assign street number to a numbered group between 0-19. +// e.g. "2" => 2, "9A" => 9, "20" => 0, "123" => 3, "234" => 14 +function getStreetNumberGroup(streetNumber: number | string): number | null { + let group = +streetNumber.toString().replace(/[^\d]/g, '') % 20; + return isFinite(group) ? group : null; +} + async function data() { - let dataDirectory = resolve(__dirname, '../data'); - let parentDirectory = resolve(__dirname, '..'); - fs.mkdirSync(dataDirectory, { mode: 0o755, recursive: true }); - let outputStreams = new Map(); - let outputGroups = new Set(); + let directory = resolve(__dirname, '../data/202208'); + let writeStreams = new LRUMap(2000); + let knownGroups = new Set(); let street: Street | undefined; let numOutput = 0; - let saveStreet = () => { + let saveStreet = async () => { if (!street) return; - // We want users to see address suggestions once they have entered part of their street name. - // Group data by first letter of street name, then by metaphone of street name. - // Metaphone length is limited to three characters. - // e.g. EXAMPLE => EEKS - let group = (street.a.substring(0, 1) + metaphone(street.a).substring(0, 3)).toUpperCase(); - let outputStream = outputStreams.get(group); - if (!outputStream) { - // create new output stream for this group - outputStream = fs.createWriteStream(resolve(dataDirectory, `${group}.txt`)); - outputStreams.set(group, outputStream); + let groupBlocks = new MultiMap(); + for (let block of street.b) { + if (!street) return; + let groups = getGroups(block.n, street.a, street.s); + for (let group of groups) { + groupBlocks.set(group, block); + } + } + for (let [group, blocks] of groupBlocks.associations()) { + let data: Street = { ...street, b: blocks }; + let writeStream = writeStreams.get(group); + if (!writeStream) { + // create new output stream for this group + let parentDirectory = resolve(directory, group, '..'); + if (!fs.existsSync(parentDirectory)) { + fs.mkdirSync(parentDirectory, { mode: 0o755, recursive: true }); + } + writeStream = fs.createWriteStream(resolve(directory, `${group}.txt`), { flags: 'a' }); + let evictedWriteStream = writeStreams.setpop(group, writeStream); + if (evictedWriteStream?.evicted) { + // Too many files open. Close the least-recently-used file + await (async () => { + evictedWriteStream.value.close(); + return once(evictedWriteStream.value, 'close'); + })(); + } + } + await (async () => { + if (writeStream) { + let jsonLines = JSON.stringify(data) + '\n'; // Minified JSON, new line delimited (aka JSONL, ND-JSON, JSON-ND) + if (!writeStream.write(jsonLines)) { + // Stream has reached high water mark. Wait for it to drain. + return once(writeStream, 'drain'); + } + } + })(); + knownGroups.add(group); + numOutput++; + console.log(numOutput, group, data.b.length, data.a, data.s, data.t, data.p); } - outputStream.write(JSON.stringify(street)+'\n'); // Minified JSON, new line delimited (aka JSONL, ND-JSON, JSON-ND) - outputGroups.add(group); - numOutput++; - console.log(numOutput, group, street.b.length, street.a, street.s, street.t, street.p); }; let sql = postgres(); + await sql`SET search_path TO gnaf_202208_gda2020,public`; await sql` - CREATE MATERIALIZED VIEW IF NOT EXISTS gnaf_202111_gda2020.aggregated_address_principals AS + CREATE MATERIALIZED VIEW IF NOT EXISTS aggregated_address_principals AS SELECT building_name, coalesce(number_first, lot_number) AS number_first, number_first IS NULL AS is_lot, number_last, street_name, street_type, street_suffix, locality_name, postcode, state, avg(latitude) AS latitude, avg(longitude) AS longitude, array_agg(flat_number ORDER BY flat_number) AS flat_numbers - FROM gnaf_202111_gda2020.address_principals + FROM address_principals GROUP BY street_name, street_type, street_suffix, locality_name, state, postcode, building_name, coalesce(number_first, lot_number), number_last, number_first IS NULL ORDER BY street_name, street_type, street_suffix, locality_name, state, postcode, building_name, coalesce(number_first, lot_number), number_last, number_first IS NULL `; - await sql`SELECT * FROM gnaf_202111_gda2020.aggregated_address_principals`.stream(a => { - if (!a.number_first || !a.street_name || !a.locality_name || !a.state || !a.postcode || !a.latitude || !a.longitude) { - console.error('Skip incomplete address', a); - return; - } - if (street === undefined || street.a !== a.street_name || street.r !== (a.street_type ?? undefined) || street.x !== (a.street_suffix ?? undefined) || street.s !== a.locality_name || street.t !== a.state || street.p !== a.postcode) { - // time for a new street and set of metaphones - if (street) { - // save the existing street - saveStreet(); + let cursor = sql` + SELECT * + FROM aggregated_address_principals + ORDER BY street_name, street_type, street_suffix, locality_name, state, postcode, building_name, number_first, number_last, number_first IS NULL + `.cursor(2000); + for await (const rows of cursor) { + for (let a of rows) { + if ( + !a.number_first || + !a.street_name || + !a.locality_name || + !a.state || + !a.postcode || + !a.latitude || + !a.longitude + ) { + console.error('Skip incomplete address', a); + continue; } - street = { - a: a.street_name, - r: a.street_type ?? undefined, - x: a.street_suffix ?? undefined, - s: a.locality_name, - t: a.state, - p: a.postcode, - b: [], - }; - } - // Add block to street - let block: Block = { - a: a.building_name ?? undefined, - n: numberOrString(a.number_first), - m: a.number_last && !a.is_lot ? numberOrString(a.number_last) : undefined, - l: a.is_lot ? true : undefined, - g: Geohash.encode(+a.latitude, +a.longitude, 9), // 9 character geohash gives maximum error of +/- 2.4 metres from exact location - see https://gis.stackexchange.com/a/115501 - }; - if (a.flat_numbers && a.flat_numbers.length > 0) { - let unitLookup = new Map>(); - for (let str of a.flat_numbers) { - if (str === null || str === 'NULL') { - continue; - } - let lastSpace = str.lastIndexOf(' '); - let unitType = ''; - let unitNumber: number | string = str; - if (lastSpace !== -1) { - unitType = str.substring(0, lastSpace); - unitNumber = str.substring(lastSpace+1); + if ( + street === undefined || + street.a !== a.street_name || + street.r !== (a.street_type ?? undefined) || + street.x !== (a.street_suffix ?? undefined) || + street.s !== a.locality_name || + street.t !== a.state || + street.p !== a.postcode + ) { + // time for a new street + if (street) { + // save the existing street + await saveStreet(); } - unitNumber = numberOrString(unitNumber); - let unitSet = unitLookup.get(unitType); - if (unitSet === undefined) { - unitSet = new Set(); - unitLookup.set(unitType, unitSet); - } - unitSet.add(unitNumber); + street = { + a: a.street_name, + r: a.street_type ?? undefined, + x: a.street_suffix ?? undefined, + s: a.locality_name, + t: a.state, + p: a.postcode, + b: [] + }; } - for (let [unitType, unitSet] of unitLookup) { - let sortedUnits = Array.from(unitSet.values()).sort((a, b) => { - if (typeof a !== typeof b) { - return (typeof a).localeCompare(typeof b); // numbers before strings + // Add block to street + let block: Block = { + a: a.building_name ?? undefined, + n: numberOrString(a.number_first), + m: a.number_last && !a.is_lot ? numberOrString(a.number_last) : undefined, + l: a.is_lot ? true : undefined, + g: Geohash.encode(+a.latitude, +a.longitude, 9) // 9 character geohash gives maximum error of +/- 2.4 metres from exact location - see https://gis.stackexchange.com/a/115501 + }; + if (a.flat_numbers && a.flat_numbers.length > 0) { + let unitLookup = new Map>(); + for (let str of a.flat_numbers) { + if (str === null || str === 'NULL') { + continue; } - if (typeof a === 'number' && typeof b === 'number') { - return a - b; // ascending number order + let lastSpace = str.lastIndexOf(' '); + let unitType = ''; + let unitNumber: number | string = str; + if (lastSpace !== -1) { + unitType = str.substring(0, lastSpace); + unitNumber = str.substring(lastSpace + 1); } - return a.toString().localeCompare(b.toString()); // ascending string order - }); - let aggregatedUnits: AddressNumber[] = []; - let runOfUnits: number[] = []; - let endRun = () => { - if (runOfUnits.length > 2) { // add range of numbers: [first, last] - aggregatedUnits.push([ - runOfUnits[0], - runOfUnits[runOfUnits.length-1], - ]); - runOfUnits = []; + unitNumber = numberOrString(unitNumber); + let unitSet = unitLookup.get(unitType); + if (unitSet === undefined) { + unitSet = new Set(); + unitLookup.set(unitType, unitSet); } - else if (runOfUnits.length > 0) { // add all numbers individually - aggregatedUnits.push(...runOfUnits); + unitSet.add(unitNumber); + } + for (let [unitType, unitSet] of unitLookup) { + let sortedUnits = Array.from(unitSet.values()).sort((a, b) => { + if (typeof a !== typeof b) { + return (typeof a).localeCompare(typeof b); // numbers before strings + } + if (typeof a === 'number' && typeof b === 'number') { + return a - b; // ascending number order + } + return a.toString().localeCompare(b.toString()); // ascending string order + }); + let aggregatedUnits: AddressNumber[] = []; + let runOfUnits: number[] = []; + let endRun = () => { + if (runOfUnits.length > 2) { + // add range of numbers: [first, last] + aggregatedUnits.push([runOfUnits[0], runOfUnits[runOfUnits.length - 1]]); + runOfUnits = []; + } else if (runOfUnits.length > 0) { + // add all numbers individually + aggregatedUnits.push(...runOfUnits); + runOfUnits = []; + } runOfUnits = []; + }; + for (let unit of sortedUnits) { + if ( + typeof unit === 'number' && + (runOfUnits[runOfUnits.length - 1] === unit - 1 || runOfUnits[runOfUnits.length - 1] === undefined) + ) { + runOfUnits.push(unit); + } else { + endRun(); + aggregatedUnits.push(unit); + } } - runOfUnits = []; - }; - for (let unit of sortedUnits) { - if (typeof unit === 'number' && (runOfUnits[runOfUnits.length-1] === unit-1 || runOfUnits[runOfUnits.length-1] === undefined)) { - runOfUnits.push(unit); - } - else { - endRun(); - aggregatedUnits.push(unit); - } - } - endRun(); - if (aggregatedUnits.length > 0) { - if (!block.u) { - block.u = {}; + endRun(); + if (aggregatedUnits.length > 0) { + if (!block.u) { + block.u = {}; + } + block.u[unitType] = aggregatedUnits; } - block.u[unitType] = aggregatedUnits; } } + street.b.push(block); } - street.b.push(block); - }); + } if (street) { - saveStreet(); + await saveStreet(); } - let closePromises: Promise[] = []; - for (let [metaphone, outputStream] of outputStreams) { - outputStream.close(); - closePromises.push(once(outputStream, 'close')); + // Close all open write streams + let closingWriteStreams: Promise[] = []; + for (let [word, writeStream] of writeStreams) { + writeStream.close(); + closingWriteStreams.push(once(writeStream, 'close')); + } + await Promise.all(closingWriteStreams); + let knownGroupsSorted = Array.from(knownGroups.values()).sort(); + let wordNumbers = new MultiMap(); + for (let knownGroup of knownGroupsSorted) { + let [letter, number, word] = knownGroup.split('/'); + let n = +number; + if (isFinite(n)) { + wordNumbers.set(word, n); + } } - await Promise.all(closePromises); - let groupList = Array.from(outputGroups.values()).sort(); - fs.writeFileSync(resolve(parentDirectory, `groups.json`), JSON.stringify(groupList)); // single line of minified JSON + fs.writeFileSync(resolve(directory, `groups.json`), JSON.stringify(Array.from(knownGroups.values()).sort())); // single line of minified JSON console.log('Done!'); process.exit(0); } @@ -166,17 +261,17 @@ async function data() { data(); type AggregatedAddressRow = { - building_name: string | null, - flat_numbers: (string | null)[] | null, - number_first: string | null, - number_last: string | null, - is_lot: boolean, - street_name: string | null, - street_type: string | null, - street_suffix: string | null, - locality_name: string | null, - postcode: string | null, - state: string | null, - latitude: string | null, - longitude: string | null, + building_name: string | null; + flat_numbers: (string | null)[] | null; + number_first: string | null; + number_last: string | null; + is_lot: boolean; + street_name: string | null; + street_type: string | null; + street_suffix: string | null; + locality_name: string | null; + postcode: string | null; + state: string | null; + latitude: string | null; + longitude: string | null; }; diff --git a/bin/package-lock.json b/bin/package-lock.json index 90e7865..28fa677 100644 --- a/bin/package-lock.json +++ b/bin/package-lock.json @@ -1,19 +1,18 @@ { "name": "bin", - "version": "1.0.0", + "version": "0.6.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "bin", - "version": "1.0.0", - "license": "ISC", + "version": "0.6.0", "dependencies": { "dotenv": "^16.0.0", - "esbuild": "^0.14.20", + "esbuild": "^0.16.10", "latlon-geohash": "^1.1.0", "metaphone": "^1.0.6", - "postgres": "^2.0.0-beta.11", + "mnemonist": "^0.39.5", + "postgres": "^3.3.1", "ts-eager": "^2.0.2", "typescript": "^4.5.5" }, @@ -22,86 +21,70 @@ "@types/latlon-geohash": "^1.1.1" } }, - "node_modules/@types/dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", - "deprecated": "This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "dotenv": "*" + "node_modules/@esbuild/android-arm": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.10.tgz", + "integrity": "sha512-RmJjQTRrO6VwUWDrzTBLmV4OJZTarYsiepLGlF2rYTVB701hSorPywPGvP6d8HCuuRibyXa5JX4s3jN2kHEtjQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/latlon-geohash": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/latlon-geohash/-/latlon-geohash-1.1.1.tgz", - "integrity": "sha512-obZL84PZyI/8p5Jav+LAAsSDIzp1/F+kl1i5szR9pTsuTVRsRXz1ZUReoDo83/ZM40fXFbMEx8kWt8+nL8Sjtw==", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/dotenv": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", - "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", + "node_modules/@esbuild/android-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.10.tgz", + "integrity": "sha512-47Y+NwVKTldTlDhSgJHZ/RpvBQMUDG7eKihqaF/u6g7s0ZPz4J1vy8A3rwnnUOF2CuDn7w7Gj/QcMoWz3U3SJw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=12" } }, - "node_modules/esbuild": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.20.tgz", - "integrity": "sha512-7aRJRnTjHZ6rFEre52tsAYZxatVELSA/QvYGUBf1iOsYKCnSJICE5seugQFFJgV1Gyl0/mngxQPhxBIqgYG2BA==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.10.tgz", + "integrity": "sha512-C4PfnrBMcuAcOurQzpF1tTtZz94IXO5JmICJJ3NFJRHbXXsQUg9RFG45KvydKqtFfBaFLCHpduUkUfXwIvGnRg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=12" - }, - "optionalDependencies": { - "esbuild-android-arm64": "0.14.20", - "esbuild-darwin-64": "0.14.20", - "esbuild-darwin-arm64": "0.14.20", - "esbuild-freebsd-64": "0.14.20", - "esbuild-freebsd-arm64": "0.14.20", - "esbuild-linux-32": "0.14.20", - "esbuild-linux-64": "0.14.20", - "esbuild-linux-arm": "0.14.20", - "esbuild-linux-arm64": "0.14.20", - "esbuild-linux-mips64le": "0.14.20", - "esbuild-linux-ppc64le": "0.14.20", - "esbuild-linux-s390x": "0.14.20", - "esbuild-netbsd-64": "0.14.20", - "esbuild-openbsd-64": "0.14.20", - "esbuild-sunos-64": "0.14.20", - "esbuild-windows-32": "0.14.20", - "esbuild-windows-64": "0.14.20", - "esbuild-windows-arm64": "0.14.20" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.20.tgz", - "integrity": "sha512-MPKVDe3TMjGDRB5WmY9XnBaXEsPiiTpkz6GjXgBhBkMFZm27PhvZT4JE0vZ1fsLb5hnGC/fYsfAnp9rsxTZhIg==", + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.10.tgz", + "integrity": "sha512-bH/bpFwldyOKdi9HSLCLhhKeVgRYr9KblchwXgY2NeUHBB/BzTUHtUSBgGBmpydB1/4E37m+ggXXfSrnD7/E7g==", "cpu": [ "arm64" ], "optional": true, "os": [ - "android" + "darwin" ], "engines": { "node": ">=12" } }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.20.tgz", - "integrity": "sha512-09PPWejM3rRFsGHvtaTuRlG+KOQlOMwPW4HwwzRlO4TuP+FNV1nTW4x2Nid3dYLzCkcjznJWQ0oylLBQvGTRyQ==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.10.tgz", + "integrity": "sha512-OXt7ijoLuy+AjDSKQWu+KdDFMBbdeaL6wtgMKtDUXKWHiAMKHan5+R1QAG6HD4+K0nnOvEJXKHeA9QhXNAjOTQ==", "cpu": [ "x64" ], @@ -113,25 +96,25 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.20.tgz", - "integrity": "sha512-jYLrSXAwygoFF2lpRJSUAghre+9IThbcPvJQbcZMONBQaaZft9nclNsrN3k4u7zQaC8v+xZDVSHkmw593tQvkg==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.10.tgz", + "integrity": "sha512-shSQX/3GHuspE3Uxtq5kcFG/zqC+VuMnJkqV7LczO41cIe6CQaXHD3QdMLA4ziRq/m0vZo7JdterlgbmgNIAlQ==", "cpu": [ "arm64" ], "optional": true, "os": [ - "darwin" + "freebsd" ], "engines": { "node": ">=12" } }, - "node_modules/esbuild-freebsd-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.20.tgz", - "integrity": "sha512-XShznPLW3QsK8/7iCx1euZTowWaWlcrlkq4YTlRqDKXkJRe98FJ6+V2QyoSTwwCoo5koaYwc+h/SYdglF5369A==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.10.tgz", + "integrity": "sha512-5YVc1zdeaJGASijZmTzSO4h6uKzsQGG3pkjI6fuXvolhm3hVRhZwnHJkforaZLmzvNv5Tb7a3QL2FAVmrgySIA==", "cpu": [ "x64" ], @@ -143,25 +126,40 @@ "node": ">=12" } }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.20.tgz", - "integrity": "sha512-flb3tDd6SScKhBqzWAESVCErpaqrGmMSRrssjx1aC+Ai5ZQrEyhfs5OWL4A9qHuixkhfmXffci7rFD+bNeXmZg==", + "node_modules/@esbuild/linux-arm": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.10.tgz", + "integrity": "sha512-c360287ZWI2miBnvIj23bPyVctgzeMT2kQKR+x94pVqIN44h3GF8VMEs1SFPH1UgyDr3yBbx3vowDS1SVhyVhA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.10.tgz", + "integrity": "sha512-2aqeNVxIaRfPcIaMZIFoblLh588sWyCbmj1HHCCs9WmeNWm+EIN0SmvsmPvTa/TsNZFKnxTcvkX2eszTcCqIrA==", "cpu": [ "arm64" ], "optional": true, "os": [ - "freebsd" + "linux" ], "engines": { "node": ">=12" } }, - "node_modules/esbuild-linux-32": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.20.tgz", - "integrity": "sha512-Avtxbd0MHFJ2QhNxj/e8VGGm1/VnEJZq9qiHUl3wQZ4S0o2Wf4ReAfhqmgAbOPFTuxuZm070rRDZYiZifWzFGQ==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.10.tgz", + "integrity": "sha512-sqMIEWeyrLGU7J5RB5fTkLRIFwsgsQ7ieWXlDLEmC2HblPYGb3AucD7inw2OrKFpRPKsec1l+lssiM3+NV5aOw==", "cpu": [ "ia32" ], @@ -173,12 +171,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.20.tgz", - "integrity": "sha512-ugisoRA/ajCr9JMszsQnT9hKkpbD7Gr1yl1mWdZhWQnGt6JKGIndGiihMURcrR44IK/2OMkixVe66D4gCHKdPA==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.10.tgz", + "integrity": "sha512-O7Pd5hLEtTg37NC73pfhUOGTjx/+aXu5YoSq3ahCxcN7Bcr2F47mv+kG5t840thnsEzrv0oB70+LJu3gUgchvg==", "cpu": [ - "x64" + "loong64" ], "optional": true, "os": [ @@ -188,12 +186,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-arm": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.20.tgz", - "integrity": "sha512-uo++Mo31+P2EA38oQgOeSIWgD7GMCMpZkaLfsCqtKJTIIL9fVzQHQYLDRIiFGpLHvs1faWWHDCEcXEFSP1Ou0g==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.10.tgz", + "integrity": "sha512-FN8mZOH7531iPHM0kaFhAOqqNHoAb6r/YHW2ZIxNi0a85UBi2DO4Vuyn7t1p4UN8a4LoAnLOT1PqNgHkgBJgbA==", "cpu": [ - "arm" + "mips64el" ], "optional": true, "os": [ @@ -203,12 +201,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.20.tgz", - "integrity": "sha512-hsrMbNzhh+ud3zUyhONlR41vpYMjINS7BHEzXHbzo4YiCsG9Ht3arbiSuNGrhR/ybLr+8J/0fYVCipiVeAjy3Q==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.10.tgz", + "integrity": "sha512-Dg9RiqdvHOAWnOKIOTsIx8dFX9EDlY2IbPEY7YFzchrCiTZmMkD7jWA9UdZbNUygPjdmQBVPRCrLydReFlX9yg==", "cpu": [ - "arm64" + "ppc64" ], "optional": true, "os": [ @@ -218,12 +216,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.20.tgz", - "integrity": "sha512-MBUu2Q+pzdTBWclPe7AwmRUMTUL0R99ONa8Hswpb987fXgFUdN4XBNBcEa5zy/l2UrIJK+9FUN1jjedZlxgP2A==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.10.tgz", + "integrity": "sha512-XMqtpjwzbmlar0BJIxmzu/RZ7EWlfVfH68Vadrva0Wj5UKOdKvqskuev2jY2oPV3aoQUyXwnMbMrFmloO2GfAw==", "cpu": [ - "mips64el" + "riscv64" ], "optional": true, "os": [ @@ -233,12 +231,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.20.tgz", - "integrity": "sha512-xkYjQtITA6q/b+/5aAf5n2L063pOxLyXUIad+zYT8GpZh0Sa7aSn18BmrFa2fHb0QSGgTEeRfYkTcBGgoPDjBA==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.10.tgz", + "integrity": "sha512-fu7XtnoeRNFMx8DjK3gPWpFBDM2u5ba+FYwg27SjMJwKvJr4bDyKz5c+FLXLUSSAkMAt/UL+cUbEbra+rYtUgw==", "cpu": [ - "ppc64" + "s390x" ], "optional": true, "os": [ @@ -248,12 +246,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-s390x": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.20.tgz", - "integrity": "sha512-AAcj3x80TXIedpNVuZgjYNETXr2iciOBQv5pGdNGAy6rv7k6Y6sT6SXQ58l2LH2AHbaeTPQjze+Y6qgX1efzrA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.10.tgz", + "integrity": "sha512-61lcjVC/RldNNMUzQQdyCWjCxp9YLEQgIxErxU9XluX7juBdGKb0pvddS0vPNuCvotRbzijZ1pzII+26haWzbA==", "cpu": [ - "s390x" + "x64" ], "optional": true, "os": [ @@ -263,10 +261,10 @@ "node": ">=12" } }, - "node_modules/esbuild-netbsd-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.20.tgz", - "integrity": "sha512-30GQKCnsID1WddUi6tr5HFUxJD0t7Uitf6tO9Cf1WqF6C44pf8EflwrhyDFmUyvkddlyfb4OrYI6NNLC/G3ajg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.10.tgz", + "integrity": "sha512-JeZXCX3viSA9j4HqSoygjssdqYdfHd6yCFWyfSekLbz4Ef+D2EjvsN02ZQPwYl5a5gg/ehdHgegHhlfOFP0HCA==", "cpu": [ "x64" ], @@ -278,10 +276,10 @@ "node": ">=12" } }, - "node_modules/esbuild-openbsd-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.20.tgz", - "integrity": "sha512-zVrf8fY46BK57AkxDdqu2S8TV3p7oLmYIiW707IOHrveI0TwJ2iypAxnwOQuCvowM3UWqVBO2RDBzV7S7t0klg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.10.tgz", + "integrity": "sha512-3qpxQKuEVIIg8SebpXsp82OBrqjPV/OwNWmG+TnZDr3VGyChNnGMHccC1xkbxCHDQNnnXjxhMQNyHmdFJbmbRA==", "cpu": [ "x64" ], @@ -293,10 +291,10 @@ "node": ">=12" } }, - "node_modules/esbuild-sunos-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.20.tgz", - "integrity": "sha512-MYRsS1O7+aBr2T/0aA4OJrju6eMku4rm81fwGF1KLFwmymIpPGmj7n69n5JW3NKyW5j+FBt0GcyDh9nEnUL1FQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.10.tgz", + "integrity": "sha512-z+q0xZ+et/7etz7WoMyXTHZ1rB8PMSNp/FOqURLJLOPb3GWJ2aj4oCqFCjPwEbW1rsT7JPpxeH/DwGAWk/I1Bg==", "cpu": [ "x64" ], @@ -308,12 +306,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-32": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.20.tgz", - "integrity": "sha512-7VqDITqTU65LQ1Uka/4jx4sUIZc1L8NPlvc7HBRdR15TUyPxmHRQaxMGXd8aakI1FEBcImpJ9SQ4JLmPwRlS1w==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.10.tgz", + "integrity": "sha512-+YYu5sbQ9npkNT9Dec+tn1F/kjg6SMgr6bfi/6FpXYZvCRfu2YFPZGb+3x8K30s8eRxFpoG4sGhiSUkr1xbHEw==", "cpu": [ - "ia32" + "arm64" ], "optional": true, "os": [ @@ -323,12 +321,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.20.tgz", - "integrity": "sha512-q4GxY4m5+nXSgqCKx6Cc5pavnhd2g5mHn+K8kNdfCMZsWPDlHLMRjYF5NVQ3/5mJ1M7iR3/Ai4ISjxmsCeGOGA==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.10.tgz", + "integrity": "sha512-Aw7Fupk7XNehR1ftHGYwUteyJ2q+em/aE+fVU3YMTBN2V5A7Z4aVCSV+SvCp9HIIHZavPFBpbdP3VfjQpdf6Xg==", "cpu": [ - "x64" + "ia32" ], "optional": true, "os": [ @@ -338,12 +336,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.20.tgz", - "integrity": "sha512-vOxfU7YwuBMjsUNUygMBhC8T60aCzeYptnHu4k7azqqOVo5EAyoueyWSkFR5GpX6bae5cXyB0vcOV/bfwqRwAg==", + "node_modules/@esbuild/win32-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.10.tgz", + "integrity": "sha512-qddWullt3sC1EIpfHvCRBq3H4g3L86DZpD6n8k2XFjFVyp01D++uNbN1hT/JRsHxTbyyemZcpwL5aRlJwc/zFw==", "cpu": [ - "arm64" + "x64" ], "optional": true, "os": [ @@ -353,10 +351,75 @@ "node": ">=12" } }, + "node_modules/@types/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", + "deprecated": "This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "dotenv": "*" + } + }, + "node_modules/@types/latlon-geohash": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/latlon-geohash/-/latlon-geohash-1.1.1.tgz", + "integrity": "sha512-obZL84PZyI/8p5Jav+LAAsSDIzp1/F+kl1i5szR9pTsuTVRsRXz1ZUReoDo83/ZM40fXFbMEx8kWt8+nL8Sjtw==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.10.tgz", + "integrity": "sha512-z5dIViHoVnw2l+NCJ3zj5behdXjYvXne9gL18OOivCadXDUhyDkeSvEtLcGVAJW2fNmh33TDUpsi704XYlDodw==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.16.10", + "@esbuild/android-arm64": "0.16.10", + "@esbuild/android-x64": "0.16.10", + "@esbuild/darwin-arm64": "0.16.10", + "@esbuild/darwin-x64": "0.16.10", + "@esbuild/freebsd-arm64": "0.16.10", + "@esbuild/freebsd-x64": "0.16.10", + "@esbuild/linux-arm": "0.16.10", + "@esbuild/linux-arm64": "0.16.10", + "@esbuild/linux-ia32": "0.16.10", + "@esbuild/linux-loong64": "0.16.10", + "@esbuild/linux-mips64el": "0.16.10", + "@esbuild/linux-ppc64": "0.16.10", + "@esbuild/linux-riscv64": "0.16.10", + "@esbuild/linux-s390x": "0.16.10", + "@esbuild/linux-x64": "0.16.10", + "@esbuild/netbsd-x64": "0.16.10", + "@esbuild/openbsd-x64": "0.16.10", + "@esbuild/sunos-x64": "0.16.10", + "@esbuild/win32-arm64": "0.16.10", + "@esbuild/win32-ia32": "0.16.10", + "@esbuild/win32-x64": "0.16.10" + } + }, "node_modules/latlon-geohash": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/latlon-geohash/-/latlon-geohash-1.1.0.tgz", - "integrity": "sha1-er4VIkxIAOPq7Kxxx1OiC/tsv2U=" + "integrity": "sha512-K1zIBU1Wtdw0Uam+Jvu4eC7mq+XBeZ/cTVGRczfE8Wbhb0pZ7+m+gbrlu0sN2i4MkHMxRu/jBc3XKo4wMXxIlg==" }, "node_modules/metaphone": { "version": "1.0.6", @@ -370,10 +433,27 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/mnemonist": { + "version": "0.39.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.5.tgz", + "integrity": "sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==", + "dependencies": { + "obliterator": "^2.0.1" + } + }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + }, "node_modules/postgres": { - "version": "2.0.0-beta.11", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-2.0.0-beta.11.tgz", - "integrity": "sha512-eJOrEIM2RtgrCcAjXhDN7S32SpHrPrXv/B9+gBX6bJFPZwSxBTszDj/Ot4BaEQJUVhf15fVrxIEFR4s0W0vlRA==" + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.3.2.tgz", + "integrity": "sha512-NaPqFpUC6C7aCQkJXLvuO/3RKNKL4en8opY53YrcXK3//xXra6CZ2qX6290lxuQ1dW1LbRGYCmsawRlCxSBonQ==", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } }, "node_modules/source-map": { "version": "0.6.1", @@ -418,9 +498,9 @@ } }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -431,178 +511,219 @@ } }, "dependencies": { - "@types/dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", - "dev": true, - "requires": { - "dotenv": "*" - } + "@esbuild/android-arm": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.10.tgz", + "integrity": "sha512-RmJjQTRrO6VwUWDrzTBLmV4OJZTarYsiepLGlF2rYTVB701hSorPywPGvP6d8HCuuRibyXa5JX4s3jN2kHEtjQ==", + "optional": true }, - "@types/latlon-geohash": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/latlon-geohash/-/latlon-geohash-1.1.1.tgz", - "integrity": "sha512-obZL84PZyI/8p5Jav+LAAsSDIzp1/F+kl1i5szR9pTsuTVRsRXz1ZUReoDo83/ZM40fXFbMEx8kWt8+nL8Sjtw==", - "dev": true + "@esbuild/android-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.10.tgz", + "integrity": "sha512-47Y+NwVKTldTlDhSgJHZ/RpvBQMUDG7eKihqaF/u6g7s0ZPz4J1vy8A3rwnnUOF2CuDn7w7Gj/QcMoWz3U3SJw==", + "optional": true }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "@esbuild/android-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.10.tgz", + "integrity": "sha512-C4PfnrBMcuAcOurQzpF1tTtZz94IXO5JmICJJ3NFJRHbXXsQUg9RFG45KvydKqtFfBaFLCHpduUkUfXwIvGnRg==", + "optional": true }, - "dotenv": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", - "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" + "@esbuild/darwin-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.10.tgz", + "integrity": "sha512-bH/bpFwldyOKdi9HSLCLhhKeVgRYr9KblchwXgY2NeUHBB/BzTUHtUSBgGBmpydB1/4E37m+ggXXfSrnD7/E7g==", + "optional": true }, - "esbuild": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.20.tgz", - "integrity": "sha512-7aRJRnTjHZ6rFEre52tsAYZxatVELSA/QvYGUBf1iOsYKCnSJICE5seugQFFJgV1Gyl0/mngxQPhxBIqgYG2BA==", - "requires": { - "esbuild-android-arm64": "0.14.20", - "esbuild-darwin-64": "0.14.20", - "esbuild-darwin-arm64": "0.14.20", - "esbuild-freebsd-64": "0.14.20", - "esbuild-freebsd-arm64": "0.14.20", - "esbuild-linux-32": "0.14.20", - "esbuild-linux-64": "0.14.20", - "esbuild-linux-arm": "0.14.20", - "esbuild-linux-arm64": "0.14.20", - "esbuild-linux-mips64le": "0.14.20", - "esbuild-linux-ppc64le": "0.14.20", - "esbuild-linux-s390x": "0.14.20", - "esbuild-netbsd-64": "0.14.20", - "esbuild-openbsd-64": "0.14.20", - "esbuild-sunos-64": "0.14.20", - "esbuild-windows-32": "0.14.20", - "esbuild-windows-64": "0.14.20", - "esbuild-windows-arm64": "0.14.20" - } - }, - "esbuild-android-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.20.tgz", - "integrity": "sha512-MPKVDe3TMjGDRB5WmY9XnBaXEsPiiTpkz6GjXgBhBkMFZm27PhvZT4JE0vZ1fsLb5hnGC/fYsfAnp9rsxTZhIg==", + "@esbuild/darwin-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.10.tgz", + "integrity": "sha512-OXt7ijoLuy+AjDSKQWu+KdDFMBbdeaL6wtgMKtDUXKWHiAMKHan5+R1QAG6HD4+K0nnOvEJXKHeA9QhXNAjOTQ==", "optional": true }, - "esbuild-darwin-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.20.tgz", - "integrity": "sha512-09PPWejM3rRFsGHvtaTuRlG+KOQlOMwPW4HwwzRlO4TuP+FNV1nTW4x2Nid3dYLzCkcjznJWQ0oylLBQvGTRyQ==", + "@esbuild/freebsd-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.10.tgz", + "integrity": "sha512-shSQX/3GHuspE3Uxtq5kcFG/zqC+VuMnJkqV7LczO41cIe6CQaXHD3QdMLA4ziRq/m0vZo7JdterlgbmgNIAlQ==", "optional": true }, - "esbuild-darwin-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.20.tgz", - "integrity": "sha512-jYLrSXAwygoFF2lpRJSUAghre+9IThbcPvJQbcZMONBQaaZft9nclNsrN3k4u7zQaC8v+xZDVSHkmw593tQvkg==", + "@esbuild/freebsd-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.10.tgz", + "integrity": "sha512-5YVc1zdeaJGASijZmTzSO4h6uKzsQGG3pkjI6fuXvolhm3hVRhZwnHJkforaZLmzvNv5Tb7a3QL2FAVmrgySIA==", "optional": true }, - "esbuild-freebsd-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.20.tgz", - "integrity": "sha512-XShznPLW3QsK8/7iCx1euZTowWaWlcrlkq4YTlRqDKXkJRe98FJ6+V2QyoSTwwCoo5koaYwc+h/SYdglF5369A==", + "@esbuild/linux-arm": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.10.tgz", + "integrity": "sha512-c360287ZWI2miBnvIj23bPyVctgzeMT2kQKR+x94pVqIN44h3GF8VMEs1SFPH1UgyDr3yBbx3vowDS1SVhyVhA==", "optional": true }, - "esbuild-freebsd-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.20.tgz", - "integrity": "sha512-flb3tDd6SScKhBqzWAESVCErpaqrGmMSRrssjx1aC+Ai5ZQrEyhfs5OWL4A9qHuixkhfmXffci7rFD+bNeXmZg==", + "@esbuild/linux-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.10.tgz", + "integrity": "sha512-2aqeNVxIaRfPcIaMZIFoblLh588sWyCbmj1HHCCs9WmeNWm+EIN0SmvsmPvTa/TsNZFKnxTcvkX2eszTcCqIrA==", "optional": true }, - "esbuild-linux-32": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.20.tgz", - "integrity": "sha512-Avtxbd0MHFJ2QhNxj/e8VGGm1/VnEJZq9qiHUl3wQZ4S0o2Wf4ReAfhqmgAbOPFTuxuZm070rRDZYiZifWzFGQ==", + "@esbuild/linux-ia32": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.10.tgz", + "integrity": "sha512-sqMIEWeyrLGU7J5RB5fTkLRIFwsgsQ7ieWXlDLEmC2HblPYGb3AucD7inw2OrKFpRPKsec1l+lssiM3+NV5aOw==", "optional": true }, - "esbuild-linux-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.20.tgz", - "integrity": "sha512-ugisoRA/ajCr9JMszsQnT9hKkpbD7Gr1yl1mWdZhWQnGt6JKGIndGiihMURcrR44IK/2OMkixVe66D4gCHKdPA==", + "@esbuild/linux-loong64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.10.tgz", + "integrity": "sha512-O7Pd5hLEtTg37NC73pfhUOGTjx/+aXu5YoSq3ahCxcN7Bcr2F47mv+kG5t840thnsEzrv0oB70+LJu3gUgchvg==", "optional": true }, - "esbuild-linux-arm": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.20.tgz", - "integrity": "sha512-uo++Mo31+P2EA38oQgOeSIWgD7GMCMpZkaLfsCqtKJTIIL9fVzQHQYLDRIiFGpLHvs1faWWHDCEcXEFSP1Ou0g==", + "@esbuild/linux-mips64el": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.10.tgz", + "integrity": "sha512-FN8mZOH7531iPHM0kaFhAOqqNHoAb6r/YHW2ZIxNi0a85UBi2DO4Vuyn7t1p4UN8a4LoAnLOT1PqNgHkgBJgbA==", "optional": true }, - "esbuild-linux-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.20.tgz", - "integrity": "sha512-hsrMbNzhh+ud3zUyhONlR41vpYMjINS7BHEzXHbzo4YiCsG9Ht3arbiSuNGrhR/ybLr+8J/0fYVCipiVeAjy3Q==", + "@esbuild/linux-ppc64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.10.tgz", + "integrity": "sha512-Dg9RiqdvHOAWnOKIOTsIx8dFX9EDlY2IbPEY7YFzchrCiTZmMkD7jWA9UdZbNUygPjdmQBVPRCrLydReFlX9yg==", "optional": true }, - "esbuild-linux-mips64le": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.20.tgz", - "integrity": "sha512-MBUu2Q+pzdTBWclPe7AwmRUMTUL0R99ONa8Hswpb987fXgFUdN4XBNBcEa5zy/l2UrIJK+9FUN1jjedZlxgP2A==", + "@esbuild/linux-riscv64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.10.tgz", + "integrity": "sha512-XMqtpjwzbmlar0BJIxmzu/RZ7EWlfVfH68Vadrva0Wj5UKOdKvqskuev2jY2oPV3aoQUyXwnMbMrFmloO2GfAw==", "optional": true }, - "esbuild-linux-ppc64le": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.20.tgz", - "integrity": "sha512-xkYjQtITA6q/b+/5aAf5n2L063pOxLyXUIad+zYT8GpZh0Sa7aSn18BmrFa2fHb0QSGgTEeRfYkTcBGgoPDjBA==", + "@esbuild/linux-s390x": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.10.tgz", + "integrity": "sha512-fu7XtnoeRNFMx8DjK3gPWpFBDM2u5ba+FYwg27SjMJwKvJr4bDyKz5c+FLXLUSSAkMAt/UL+cUbEbra+rYtUgw==", "optional": true }, - "esbuild-linux-s390x": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.20.tgz", - "integrity": "sha512-AAcj3x80TXIedpNVuZgjYNETXr2iciOBQv5pGdNGAy6rv7k6Y6sT6SXQ58l2LH2AHbaeTPQjze+Y6qgX1efzrA==", + "@esbuild/linux-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.10.tgz", + "integrity": "sha512-61lcjVC/RldNNMUzQQdyCWjCxp9YLEQgIxErxU9XluX7juBdGKb0pvddS0vPNuCvotRbzijZ1pzII+26haWzbA==", "optional": true }, - "esbuild-netbsd-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.20.tgz", - "integrity": "sha512-30GQKCnsID1WddUi6tr5HFUxJD0t7Uitf6tO9Cf1WqF6C44pf8EflwrhyDFmUyvkddlyfb4OrYI6NNLC/G3ajg==", + "@esbuild/netbsd-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.10.tgz", + "integrity": "sha512-JeZXCX3viSA9j4HqSoygjssdqYdfHd6yCFWyfSekLbz4Ef+D2EjvsN02ZQPwYl5a5gg/ehdHgegHhlfOFP0HCA==", "optional": true }, - "esbuild-openbsd-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.20.tgz", - "integrity": "sha512-zVrf8fY46BK57AkxDdqu2S8TV3p7oLmYIiW707IOHrveI0TwJ2iypAxnwOQuCvowM3UWqVBO2RDBzV7S7t0klg==", + "@esbuild/openbsd-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.10.tgz", + "integrity": "sha512-3qpxQKuEVIIg8SebpXsp82OBrqjPV/OwNWmG+TnZDr3VGyChNnGMHccC1xkbxCHDQNnnXjxhMQNyHmdFJbmbRA==", "optional": true }, - "esbuild-sunos-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.20.tgz", - "integrity": "sha512-MYRsS1O7+aBr2T/0aA4OJrju6eMku4rm81fwGF1KLFwmymIpPGmj7n69n5JW3NKyW5j+FBt0GcyDh9nEnUL1FQ==", + "@esbuild/sunos-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.10.tgz", + "integrity": "sha512-z+q0xZ+et/7etz7WoMyXTHZ1rB8PMSNp/FOqURLJLOPb3GWJ2aj4oCqFCjPwEbW1rsT7JPpxeH/DwGAWk/I1Bg==", "optional": true }, - "esbuild-windows-32": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.20.tgz", - "integrity": "sha512-7VqDITqTU65LQ1Uka/4jx4sUIZc1L8NPlvc7HBRdR15TUyPxmHRQaxMGXd8aakI1FEBcImpJ9SQ4JLmPwRlS1w==", + "@esbuild/win32-arm64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.10.tgz", + "integrity": "sha512-+YYu5sbQ9npkNT9Dec+tn1F/kjg6SMgr6bfi/6FpXYZvCRfu2YFPZGb+3x8K30s8eRxFpoG4sGhiSUkr1xbHEw==", "optional": true }, - "esbuild-windows-64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.20.tgz", - "integrity": "sha512-q4GxY4m5+nXSgqCKx6Cc5pavnhd2g5mHn+K8kNdfCMZsWPDlHLMRjYF5NVQ3/5mJ1M7iR3/Ai4ISjxmsCeGOGA==", + "@esbuild/win32-ia32": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.10.tgz", + "integrity": "sha512-Aw7Fupk7XNehR1ftHGYwUteyJ2q+em/aE+fVU3YMTBN2V5A7Z4aVCSV+SvCp9HIIHZavPFBpbdP3VfjQpdf6Xg==", "optional": true }, - "esbuild-windows-arm64": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.20.tgz", - "integrity": "sha512-vOxfU7YwuBMjsUNUygMBhC8T60aCzeYptnHu4k7azqqOVo5EAyoueyWSkFR5GpX6bae5cXyB0vcOV/bfwqRwAg==", + "@esbuild/win32-x64": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.10.tgz", + "integrity": "sha512-qddWullt3sC1EIpfHvCRBq3H4g3L86DZpD6n8k2XFjFVyp01D++uNbN1hT/JRsHxTbyyemZcpwL5aRlJwc/zFw==", "optional": true }, + "@types/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", + "dev": true, + "requires": { + "dotenv": "*" + } + }, + "@types/latlon-geohash": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/latlon-geohash/-/latlon-geohash-1.1.1.tgz", + "integrity": "sha512-obZL84PZyI/8p5Jav+LAAsSDIzp1/F+kl1i5szR9pTsuTVRsRXz1ZUReoDo83/ZM40fXFbMEx8kWt8+nL8Sjtw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, + "esbuild": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.10.tgz", + "integrity": "sha512-z5dIViHoVnw2l+NCJ3zj5behdXjYvXne9gL18OOivCadXDUhyDkeSvEtLcGVAJW2fNmh33TDUpsi704XYlDodw==", + "requires": { + "@esbuild/android-arm": "0.16.10", + "@esbuild/android-arm64": "0.16.10", + "@esbuild/android-x64": "0.16.10", + "@esbuild/darwin-arm64": "0.16.10", + "@esbuild/darwin-x64": "0.16.10", + "@esbuild/freebsd-arm64": "0.16.10", + "@esbuild/freebsd-x64": "0.16.10", + "@esbuild/linux-arm": "0.16.10", + "@esbuild/linux-arm64": "0.16.10", + "@esbuild/linux-ia32": "0.16.10", + "@esbuild/linux-loong64": "0.16.10", + "@esbuild/linux-mips64el": "0.16.10", + "@esbuild/linux-ppc64": "0.16.10", + "@esbuild/linux-riscv64": "0.16.10", + "@esbuild/linux-s390x": "0.16.10", + "@esbuild/linux-x64": "0.16.10", + "@esbuild/netbsd-x64": "0.16.10", + "@esbuild/openbsd-x64": "0.16.10", + "@esbuild/sunos-x64": "0.16.10", + "@esbuild/win32-arm64": "0.16.10", + "@esbuild/win32-ia32": "0.16.10", + "@esbuild/win32-x64": "0.16.10" + } + }, "latlon-geohash": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/latlon-geohash/-/latlon-geohash-1.1.0.tgz", - "integrity": "sha1-er4VIkxIAOPq7Kxxx1OiC/tsv2U=" + "integrity": "sha512-K1zIBU1Wtdw0Uam+Jvu4eC7mq+XBeZ/cTVGRczfE8Wbhb0pZ7+m+gbrlu0sN2i4MkHMxRu/jBc3XKo4wMXxIlg==" }, "metaphone": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/metaphone/-/metaphone-1.0.6.tgz", "integrity": "sha512-1xKourcr1sNyZh+6+PApMx6EFHrGd63M/M1m6sG4TqlNfYIzXgnFoOJhdf3TIqOdb2gEil56sRdm3sc/xRbdFQ==" }, + "mnemonist": { + "version": "0.39.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.5.tgz", + "integrity": "sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==", + "requires": { + "obliterator": "^2.0.1" + } + }, + "obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + }, "postgres": { - "version": "2.0.0-beta.11", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-2.0.0-beta.11.tgz", - "integrity": "sha512-eJOrEIM2RtgrCcAjXhDN7S32SpHrPrXv/B9+gBX6bJFPZwSxBTszDj/Ot4BaEQJUVhf15fVrxIEFR4s0W0vlRA==" + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.3.2.tgz", + "integrity": "sha512-NaPqFpUC6C7aCQkJXLvuO/3RKNKL4en8opY53YrcXK3//xXra6CZ2qX6290lxuQ1dW1LbRGYCmsawRlCxSBonQ==" }, "source-map": { "version": "0.6.1", @@ -635,9 +756,9 @@ } }, "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==" + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" } } } diff --git a/bin/package.json b/bin/package.json index 85ee37d..e26bc32 100644 --- a/bin/package.json +++ b/bin/package.json @@ -1,10 +1,12 @@ { + "version": "0.6.0", "dependencies": { "dotenv": "^16.0.0", - "esbuild": "^0.14.20", + "esbuild": "^0.16.10", "latlon-geohash": "^1.1.0", "metaphone": "^1.0.6", - "postgres": "^2.0.0-beta.11", + "mnemonist": "^0.39.5", + "postgres": "^3.3.1", "ts-eager": "^2.0.2", "typescript": "^4.5.5" }, diff --git a/dist/geocode.d.ts b/dist/geocode.d.ts index c1d98bc..c77d09f 100644 --- a/dist/geocode.d.ts +++ b/dist/geocode.d.ts @@ -1,18 +1,23 @@ declare type GeocodeResult = { input: string; - group: string; + results: GeocodeResultItem[]; + startTime: number; duration: number; - results: Array<{ - address: string; - latitude: number; - longitude: number; - score: number; - id: number; - }>; +}; +declare type GeocodeResultItem = { + address: string; + latitude: number; + longitude: number; + score: number; + id: number; }; declare type GeocodeOptions = { limit?: number; + abortPrevious?: boolean; }; +declare class GeocodeAbortError extends Error { + constructor(); +} declare function geocode(input: string, options?: GeocodeOptions): Promise; -export { GeocodeResult, geocode as default }; +export { GeocodeAbortError, GeocodeResult, geocode as default, geocode }; diff --git a/dist/geocode.global.js b/dist/geocode.global.js index c53a924..0eb9c12 100644 --- a/dist/geocode.global.js +++ b/dist/geocode.global.js @@ -1,1601 +1,2 @@ -var __GEOCODE__ = (() => { - var __create = Object.create; - var __defProp = Object.defineProperty; - var __getOwnPropDesc = Object.getOwnPropertyDescriptor; - var __getOwnPropNames = Object.getOwnPropertyNames; - var __getProtoOf = Object.getPrototypeOf; - var __hasOwnProp = Object.prototype.hasOwnProperty; - var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); - var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; - }; - var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); - }; - var __reExport = (target, module, copyDefault, desc) => { - if (module && typeof module === "object" || typeof module === "function") { - for (let key of __getOwnPropNames(module)) - if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default")) - __defProp(target, key, { get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable }); - } - return target; - }; - var __toESM = (module, isNodeMode) => { - return __reExport(__markAsModule(__defProp(module != null ? __create(__getProtoOf(module)) : {}, "default", !isNodeMode && module && module.__esModule ? { get: () => module.default, enumerable: true } : { value: module, enumerable: true })), module); - }; - var __toCommonJS = /* @__PURE__ */ ((cache) => { - return (module, temp) => { - return cache && cache.get(module) || (temp = __reExport(__markAsModule({}), module, 1), cache && cache.set(module, temp), temp); - }; - })(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0); - - // node_modules/latlon-geohash/latlon-geohash.js - var require_latlon_geohash = __commonJS({ - "node_modules/latlon-geohash/latlon-geohash.js"(exports, module) { - "use strict"; - var Geohash2 = {}; - Geohash2.base32 = "0123456789bcdefghjkmnpqrstuvwxyz"; - Geohash2.encode = function(lat, lon, precision) { - if (typeof precision == "undefined") { - for (var p = 1; p <= 12; p++) { - var hash = Geohash2.encode(lat, lon, p); - var posn = Geohash2.decode(hash); - if (posn.lat == lat && posn.lon == lon) - return hash; - } - precision = 12; - } - lat = Number(lat); - lon = Number(lon); - precision = Number(precision); - if (isNaN(lat) || isNaN(lon) || isNaN(precision)) - throw new Error("Invalid geohash"); - var idx = 0; - var bit = 0; - var evenBit = true; - var geohash = ""; - var latMin = -90, latMax = 90; - var lonMin = -180, lonMax = 180; - while (geohash.length < precision) { - if (evenBit) { - var lonMid = (lonMin + lonMax) / 2; - if (lon >= lonMid) { - idx = idx * 2 + 1; - lonMin = lonMid; - } else { - idx = idx * 2; - lonMax = lonMid; - } - } else { - var latMid = (latMin + latMax) / 2; - if (lat >= latMid) { - idx = idx * 2 + 1; - latMin = latMid; - } else { - idx = idx * 2; - latMax = latMid; - } - } - evenBit = !evenBit; - if (++bit == 5) { - geohash += Geohash2.base32.charAt(idx); - bit = 0; - idx = 0; - } - } - return geohash; - }; - Geohash2.decode = function(geohash) { - var bounds = Geohash2.bounds(geohash); - var latMin = bounds.sw.lat, lonMin = bounds.sw.lon; - var latMax = bounds.ne.lat, lonMax = bounds.ne.lon; - var lat = (latMin + latMax) / 2; - var lon = (lonMin + lonMax) / 2; - lat = lat.toFixed(Math.floor(2 - Math.log(latMax - latMin) / Math.LN10)); - lon = lon.toFixed(Math.floor(2 - Math.log(lonMax - lonMin) / Math.LN10)); - return { lat: Number(lat), lon: Number(lon) }; - }; - Geohash2.bounds = function(geohash) { - if (geohash.length === 0) - throw new Error("Invalid geohash"); - geohash = geohash.toLowerCase(); - var evenBit = true; - var latMin = -90, latMax = 90; - var lonMin = -180, lonMax = 180; - for (var i = 0; i < geohash.length; i++) { - var chr = geohash.charAt(i); - var idx = Geohash2.base32.indexOf(chr); - if (idx == -1) - throw new Error("Invalid geohash"); - for (var n = 4; n >= 0; n--) { - var bitN = idx >> n & 1; - if (evenBit) { - var lonMid = (lonMin + lonMax) / 2; - if (bitN == 1) { - lonMin = lonMid; - } else { - lonMax = lonMid; - } - } else { - var latMid = (latMin + latMax) / 2; - if (bitN == 1) { - latMin = latMid; - } else { - latMax = latMid; - } - } - evenBit = !evenBit; - } - } - var bounds = { - sw: { lat: latMin, lon: lonMin }, - ne: { lat: latMax, lon: lonMax } - }; - return bounds; - }; - Geohash2.adjacent = function(geohash, direction) { - geohash = geohash.toLowerCase(); - direction = direction.toLowerCase(); - if (geohash.length === 0) - throw new Error("Invalid geohash"); - if ("nsew".indexOf(direction) == -1) - throw new Error("Invalid direction"); - var neighbour = { - n: ["p0r21436x8zb9dcf5h7kjnmqesgutwvy", "bc01fg45238967deuvhjyznpkmstqrwx"], - s: ["14365h7k9dcfesgujnmqp0r2twvyx8zb", "238967debc01fg45kmstqrwxuvhjyznp"], - e: ["bc01fg45238967deuvhjyznpkmstqrwx", "p0r21436x8zb9dcf5h7kjnmqesgutwvy"], - w: ["238967debc01fg45kmstqrwxuvhjyznp", "14365h7k9dcfesgujnmqp0r2twvyx8zb"] - }; - var border = { - n: ["prxz", "bcfguvyz"], - s: ["028b", "0145hjnp"], - e: ["bcfguvyz", "prxz"], - w: ["0145hjnp", "028b"] - }; - var lastCh = geohash.slice(-1); - var parent = geohash.slice(0, -1); - var type = geohash.length % 2; - if (border[direction][type].indexOf(lastCh) != -1 && parent !== "") { - parent = Geohash2.adjacent(parent, direction); - } - return parent + Geohash2.base32.charAt(neighbour[direction][type].indexOf(lastCh)); - }; - Geohash2.neighbours = function(geohash) { - return { - "n": Geohash2.adjacent(geohash, "n"), - "ne": Geohash2.adjacent(Geohash2.adjacent(geohash, "n"), "e"), - "e": Geohash2.adjacent(geohash, "e"), - "se": Geohash2.adjacent(Geohash2.adjacent(geohash, "s"), "e"), - "s": Geohash2.adjacent(geohash, "s"), - "sw": Geohash2.adjacent(Geohash2.adjacent(geohash, "s"), "w"), - "w": Geohash2.adjacent(geohash, "w"), - "nw": Geohash2.adjacent(Geohash2.adjacent(geohash, "n"), "w") - }; - }; - if (typeof module != "undefined" && module.exports) - module.exports = Geohash2; - } - }); - - // node_modules/metaphone/index.js - var require_metaphone = __commonJS({ - "node_modules/metaphone/index.js"(exports, module) { - "use strict"; - module.exports = metaphone2; - var sh = "X"; - var th = "0"; - function metaphone2(value) { - var phonized = ""; - var index = 0; - var skip; - var next; - var current; - var prev; - function phonize(characters) { - phonized += characters; - } - function at(offset) { - return value.charAt(index + offset).toUpperCase(); - } - function atFactory(offset) { - return function() { - return at(offset); - }; - } - value = String(value || ""); - if (!value) { - return ""; - } - next = atFactory(1); - current = atFactory(0); - prev = atFactory(-1); - while (!alpha(current())) { - if (!current()) { - return ""; - } - index++; - } - switch (current()) { - case "A": - if (next() === "E") { - phonize("E"); - index += 2; - } else { - phonize("A"); - index++; - } - break; - case "G": - case "K": - case "P": - if (next() === "N") { - phonize("N"); - index += 2; - } - break; - case "W": - if (next() === "R") { - phonize(next()); - index += 2; - } else if (next() === "H") { - phonize(current()); - index += 2; - } else if (vowel(next())) { - phonize("W"); - index += 2; - } - break; - case "X": - phonize("S"); - index++; - break; - case "E": - case "I": - case "O": - case "U": - phonize(current()); - index++; - break; - default: - break; - } - while (current()) { - skip = 1; - if (!alpha(current()) || current() === prev() && current() !== "C") { - index += skip; - continue; - } - switch (current()) { - case "B": - if (prev() !== "M") { - phonize("B"); - } - break; - case "C": - if (soft(next())) { - if (next() === "I" && at(2) === "A") { - phonize(sh); - } else if (prev() !== "S") { - phonize("S"); - } - } else if (next() === "H") { - phonize(sh); - skip++; - } else { - phonize("K"); - } - break; - case "D": - if (next() === "G" && soft(at(2))) { - phonize("J"); - skip++; - } else { - phonize("T"); - } - break; - case "G": - if (next() === "H") { - if (!(noGhToF(at(-3)) || at(-4) === "H")) { - phonize("F"); - skip++; - } - } else if (next() === "N") { - if (!(!alpha(at(2)) || at(2) === "E" && at(3) === "D")) { - phonize("K"); - } - } else if (soft(next()) && prev() !== "G") { - phonize("J"); - } else { - phonize("K"); - } - break; - case "H": - if (vowel(next()) && !dipthongH(prev())) { - phonize("H"); - } - break; - case "K": - if (prev() !== "C") { - phonize("K"); - } - break; - case "P": - if (next() === "H") { - phonize("F"); - } else { - phonize("P"); - } - break; - case "Q": - phonize("K"); - break; - case "S": - if (next() === "I" && (at(2) === "O" || at(2) === "A")) { - phonize(sh); - } else if (next() === "H") { - phonize(sh); - skip++; - } else { - phonize("S"); - } - break; - case "T": - if (next() === "I" && (at(2) === "O" || at(2) === "A")) { - phonize(sh); - } else if (next() === "H") { - phonize(th); - skip++; - } else if (!(next() === "C" && at(2) === "H")) { - phonize("T"); - } - break; - case "V": - phonize("F"); - break; - case "W": - if (vowel(next())) { - phonize("W"); - } - break; - case "X": - phonize("KS"); - break; - case "Y": - if (vowel(next())) { - phonize("Y"); - } - break; - case "Z": - phonize("S"); - break; - case "F": - case "J": - case "L": - case "M": - case "N": - case "R": - phonize(current()); - break; - } - index += skip; - } - return phonized; - } - function noGhToF(character) { - character = char(character); - return character === "B" || character === "D" || character === "H"; - } - function soft(character) { - character = char(character); - return character === "E" || character === "I" || character === "Y"; - } - function vowel(character) { - character = char(character); - return character === "A" || character === "E" || character === "I" || character === "O" || character === "U"; - } - function dipthongH(character) { - character = char(character); - return character === "C" || character === "G" || character === "P" || character === "S" || character === "T"; - } - function alpha(character) { - var code = charCode(character); - return code >= 65 && code <= 90; - } - function charCode(character) { - return char(character).charCodeAt(0); - } - function char(character) { - return String(character).charAt(0).toUpperCase(); - } - } - }); - - // groups.json - var require_groups = __commonJS({ - "groups.json"(exports, module) { - module.exports = ["1MLH", "30PR", "3LK", "4AK", "4T", "AA", "AA0B", "AA0L", "AA0N", "AA0R", "AA0S", "AAB", "AABB", "AABF", "AABH", "AABJ", "AABK", "AABL", "AABM", "AABN", "AABP", "AABR", "AABS", "AABT", "AABW", "AABY", "AAF", "AAFB", "AAFF", "AAFK", "AAFL", "AAFM", "AAFN", "AAFR", "AAFS", "AAFT", "AAFW", "AAFX", "AAHN", "AAHR", "AAJ", "AAJK", "AAJL", "AAJN", "AAJR", "AAJS", "AAJT", "AAK", "AAK0", "AAKB", "AAKF", "AAKH", "AAKK", "AAKL", "AAKM", "AAKN", "AAKP", "AAKR", "AAKS", "AAKT", "AAKW", "AAKX", "AAL", "AAL0", "AALB", "AALF", "AALH", "AALJ", "AALK", "AALL", "AALM", "AALN", "AALP", "AALR", "AALS", "AALT", "AALW", "AALX", "AALY", "AAM", "AAM0", "AAMB", "AAMF", "AAMH", "AAMJ", "AAMK", "AAML", "AAMM", "AAMN", "AAMP", "AAMR", "AAMS", "AAMT", "AAMW", "AAMX", "AAMY", "AAN", "AAN0", "AANB", "AANF", "AANH", "AANJ", "AANK", "AANL", "AANM", "AANN", "AANP", "AANR", "AANS", "AANT", "AANW", "AANX", "AANY", "AAP", "AAPJ", "AAPK", "AAPL", "AAPM", "AAPN", "AAPP", "AAPR", "AAPS", "AAPT", "AAPX", "AAR", "AAR0", "AARB", "AARF", "AARH", "AARJ", "AARK", "AARL", "AARM", "AARN", "AARP", "AARR", "AARS", "AART", "AARW", "AARX", "AARY", "AAS", "AAS0", "AASB", "AASF", "AASH", "AASK", "AASL", "AASM", "AASN", "AASP", "AASR", "AASS", "AAST", "AASW", "AASX", "AAT", "AATB", "AATF", "AATH", "AATJ", "AATK", "AATL", "AATM", "AATN", "AATP", "AATR", "AATS", "AATT", "AATW", "AATX", "AATY", "AAW", "AAWB", "AAWL", "AAWN", "AAWR", "AAWS", "AAWT", "AAX", "AAXB", "AAXF", "AAXK", "AAXL", "AAXM", "AAXN", "AAXP", "AAXR", "AAXS", "AAXT", "AAXW", "AAXY", "AAY", "AAYB", "AAYL", "AAYM", "AAYN", "AAYP", "AAYR", "AAYS", "AAYW", "AAYX", "AE0L", "AEJN", "AEJR", "AEL", "AELN", "AELS", "AEML", "AENN", "AER", "AERK", "AERL", "AERN", "AERP", "AERT", "AESP", "AESX", "BB", "BB0", "BB0B", "BB0F", "BB0K", "BB0L", "BB0M", "BB0N", "BB0P", "BB0R", "BB0S", "BB0T", "BB0W", "BB0X", "BBB", "BBBB", "BBBH", "BBBJ", "BBBK", "BBBL", "BBBM", "BBBN", "BBBR", "BBBS", "BBBT", "BBBW", "BBBX", "BBBY", "BBF", "BBFF", "BBFH", "BBFK", "BBFL", "BBFN", "BBFP", "BBFR", "BBFS", "BBFT", "BBFW", "BBFX", "BBH", "BBHF", "BBHK", "BBHL", "BBHM", "BBHN", "BBHR", "BBHS", "BBHT", "BBHW", "BBHX", "BBJ", "BBJB", "BBJJ", "BBJK", "BBJL", "BBJM", "BBJN", "BBJR", "BBJS", "BBJT", "BBJW", "BBK", "BBK0", "BBKB", "BBKF", "BBKH", "BBKJ", "BBKK", "BBKL", "BBKM", "BBKN", "BBKP", "BBKR", "BBKS", "BBKT", "BBKW", "BBKX", "BBKY", "BBL", "BBL0", "BBLB", "BBLF", "BBLH", "BBLJ", "BBLK", "BBLL", "BBLM", "BBLN", "BBLP", "BBLR", "BBLS", "BBLT", "BBLW", "BBLX", "BBLY", "BBM", "BBM0", "BBMB", "BBMF", "BBMJ", "BBMK", "BBML", "BBMM", "BBMN", "BBMP", "BBMR", "BBMS", "BBMT", "BBMW", "BBMX", "BBN", "BBN0", "BBNB", "BBNF", "BBNH", "BBNJ", "BBNK", "BBNL", "BBNM", "BBNN", "BBNP", "BBNR", "BBNS", "BBNT", "BBNW", "BBNX", "BBNY", "BBP", "BBPL", "BBPM", "BBPN", "BBPP", "BBPR", "BBPS", "BBPT", "BBPX", "BBR", "BBR0", "BBRB", "BBRF", "BBRH", "BBRJ", "BBRK", "BBRL", "BBRM", "BBRN", "BBRP", "BBRR", "BBRS", "BBRT", "BBRW", "BBRX", "BBRY", "BBS", "BBS0", "BBSB", "BBSF", "BBSH", "BBSJ", "BBSK", "BBSL", "BBSM", "BBSN", "BBSP", "BBSR", "BBSS", "BBST", "BBSW", "BBSX", "BBT", "BBT0", "BBTB", "BBTF", "BBTH", "BBTJ", "BBTK", "BBTL", "BBTM", "BBTN", "BBTP", "BBTR", "BBTS", "BBTT", "BBTW", "BBTX", "BBTY", "BBW", "BBWK", "BBWL", "BBWN", "BBWR", "BBWS", "BBWT", "BBWY", "BBX", "BBXB", "BBXF", "BBXH", "BBXK", "BBXL", "BBXM", "BBXN", "BBXP", "BBXR", "BBXS", "BBXT", "BBXW", "BBXX", "BBY", "BBY0", "BBYB", "BBYH", "BBYJ", "BBYK", "BBYL", "BBYM", "BBYN", "BBYP", "BBYR", "BBYS", "BBYT", "BBYW", "BBYY", "CK", "CK0", "CK0B", "CK0K", "CK0L", "CK0M", "CK0N", "CK0R", "CK0S", "CK0T", "CK0W", "CKB", "CKBB", "CKBF", "CKBH", "CKBJ", "CKBK", "CKBL", "CKBM", "CKBN", "CKBR", "CKBS", "CKBT", "CKBW", "CKBX", "CKBY", "CKF", "CKFB", "CKFF", "CKFH", "CKFK", "CKFL", "CKFN", "CKFP", "CKFR", "CKFS", "CKFT", "CKFX", "CKH", "CKHL", "CKHN", "CKHR", "CKHT", "CKJ", "CKJB", "CKJK", "CKJL", "CKJN", "CKJP", "CKJR", "CKJT", "CKJW", "CKK", "CKK0", "CKKB", "CKKF", "CKKH", "CKKJ", "CKKK", "CKKL", "CKKM", "CKKN", "CKKP", "CKKR", "CKKS", "CKKT", "CKKW", "CKKX", "CKKY", "CKL", "CKL0", "CKLB", "CKLF", "CKLH", "CKLJ", "CKLK", "CKLL", "CKLM", "CKLN", "CKLP", "CKLR", "CKLS", "CKLT", "CKLW", "CKLX", "CKLY", "CKM", "CKMB", "CKMF", "CKMJ", "CKMK", "CKML", "CKMM", "CKMN", "CKMP", "CKMR", "CKMS", "CKMT", "CKMW", "CKMY", "CKN", "CKN0", "CKNB", "CKNF", "CKNH", "CKNJ", "CKNK", "CKNL", "CKNM", "CKNN", "CKNP", "CKNR", "CKNS", "CKNT", "CKNW", "CKNX", "CKNY", "CKP", "CKP0", "CKPB", "CKPF", "CKPH", "CKPJ", "CKPK", "CKPL", "CKPM", "CKPN", "CKPP", "CKPR", "CKPS", "CKPT", "CKPW", "CKPX", "CKPY", "CKR", "CKR0", "CKRB", "CKRF", "CKRH", "CKRJ", "CKRK", "CKRL", "CKRM", "CKRN", "CKRP", "CKRR", "CKRS", "CKRT", "CKRW", "CKRX", "CKRY", "CKS", "CKSB", "CKSF", "CKSH", "CKSJ", "CKSK", "CKSL", "CKSM", "CKSN", "CKSP", "CKSR", "CKSS", "CKST", "CKSW", "CKSX", "CKT", "CKT0", "CKTB", "CKTF", "CKTH", "CKTJ", "CKTK", "CKTL", "CKTM", "CKTN", "CKTP", "CKTR", "CKTS", "CKTT", "CKTW", "CKTX", "CKTY", "CKW", "CKWB", "CKWL", "CKWM", "CKWN", "CKWP", "CKWR", "CKWS", "CKWT", "CKX", "CKXB", "CKXF", "CKXH", "CKXK", "CKXL", "CKXM", "CKXN", "CKXP", "CKXR", "CKXS", "CKXT", "CKXW", "CKY", "CKYB", "CKYK", "CKYL", "CKYM", "CKYN", "CKYP", "CKYR", "CKYT", "CKYY", "CS0N", "CSB", "CSBL", "CSBR", "CSBS", "CSF", "CSFK", "CSFL", "CSFN", "CSFR", "CSFS", "CSFT", "CSJ", "CSKK", "CSKL", "CSKN", "CSKS", "CSKT", "CSKW", "CSKX", "CSL", "CSLB", "CSLF", "CSLH", "CSLK", "CSLM", "CSLN", "CSLR", "CSLS", "CSLT", "CSLW", "CSLX", "CSM", "CSML", "CSMN", "CSMR", "CSMS", "CSMT", "CSN", "CSN0", "CSNB", "CSNK", "CSNL", "CSNM", "CSNR", "CSNS", "CSNT", "CSNX", "CSP", "CSPL", "CSPR", "CSR", "CSRB", "CSRF", "CSRK", "CSRL", "CSRM", "CSRN", "CSRS", "CSRT", "CSSF", "CSSK", "CSSL", "CSSN", "CSSR", "CSSS", "CSST", "CST", "CSTB", "CSTF", "CSTH", "CSTK", "CSTL", "CSTM", "CSTN", "CSTP", "CSTR", "CSTS", "CSTT", "CSTW", "CSTX", "CSXL", "CSXN", "CSY0", "CSYN", "CX", "CX0M", "CXB", "CXBH", "CXBK", "CXBL", "CXBN", "CXBR", "CXBT", "CXF", "CXFK", "CXFL", "CXFM", "CXFN", "CXFP", "CXFR", "CXFS", "CXFT", "CXHL", "CXJ", "CXJS", "CXK", "CXKB", "CXKK", "CXKL", "CXKM", "CXKN", "CXKP", "CXKR", "CXKS", "CXKT", "CXKW", "CXKX", "CXL", "CXLB", "CXLF", "CXLH", "CXLK", "CXLM", "CXLN", "CXLP", "CXLR", "CXLS", "CXLT", "CXLW", "CXLY", "CXM", "CXMK", "CXML", "CXMM", "CXMN", "CXMP", "CXMR", "CXMS", "CXN", "CXN0", "CXNB", "CXNF", "CXNH", "CXNJ", "CXNK", "CXNL", "CXNM", "CXNN", "CXNP", "CXNR", "CXNS", "CXNT", "CXNW", "CXNX", "CXP", "CXPH", "CXPL", "CXPM", "CXPN", "CXPR", "CXPS", "CXPT", "CXPW", "CXPX", "CXR", "CXR0", "CXRB", "CXRF", "CXRH", "CXRJ", "CXRK", "CXRL", "CXRM", "CXRN", "CXRP", "CXRR", "CXRS", "CXRT", "CXRW", "CXRX", "CXS", "CXSB", "CXSF", "CXSL", "CXSM", "CXSN", "CXSP", "CXSR", "CXSS", "CXST", "CXSW", "CXT", "CXTB", "CXTF", "CXTK", "CXTL", "CXTM", "CXTN", "CXTR", "CXTS", "CXTW", "CXTX", "CXWB", "CXWL", "CXWN", "CXWR", "CXX", "CXXL", "CXXM", "CXXN", "CXXR", "CXXS", "CXYN", "DT", "DT0", "DT0H", "DT0R", "DT0S", "DT0T", "DT0W", "DTB", "DTBB", "DTBF", "DTBH", "DTBJ", "DTBK", "DTBL", "DTBM", "DTBN", "DTBP", "DTBR", "DTBS", "DTBT", "DTBW", "DTBX", "DTBY", "DTF", "DTFB", "DTFF", "DTFH", "DTFJ", "DTFK", "DTFL", "DTFM", "DTFN", "DTFP", "DTFR", "DTFS", "DTFT", "DTFX", "DTH", "DTHF", "DTHJ", "DTHK", "DTHL", "DTHM", "DTHN", "DTHR", "DTHT", "DTHY", "DTJ", "DTJB", "DTJH", "DTJJ", "DTJK", "DTJL", "DTJM", "DTJN", "DTJP", "DTJR", "DTJS", "DTJT", "DTK", "DTK0", "DTKB", "DTKF", "DTKH", "DTKK", "DTKL", "DTKM", "DTKN", "DTKP", "DTKR", "DTKS", "DTKT", "DTKW", "DTKX", "DTKY", "DTL", "DTL0", "DTLB", "DTLF", "DTLH", "DTLJ", "DTLK", "DTLL", "DTLM", "DTLN", "DTLP", "DTLR", "DTLS", "DTLT", "DTLW", "DTLX", "DTLY", "DTM", "DTMB", "DTMF", "DTMJ", "DTMK", "DTML", "DTMM", "DTMN", "DTMP", "DTMR", "DTMS", "DTMT", "DTMX", "DTMY", "DTN", "DTN0", "DTNB", "DTNF", "DTNH", "DTNJ", "DTNK", "DTNL", "DTNM", "DTNN", "DTNP", "DTNR", "DTNS", "DTNT", "DTNW", "DTNX", "DTNY", "DTP", "DTPB", "DTPF", "DTPK", "DTPL", "DTPM", "DTPN", "DTPP", "DTPR", "DTPS", "DTPT", "DTPW", "DTPX", "DTR", "DTR0", "DTRB", "DTRF", "DTRH", "DTRJ", "DTRK", "DTRL", "DTRM", "DTRN", "DTRP", "DTRR", "DTRS", "DTRT", "DTRW", "DTRX", "DTRY", "DTS", "DTS0", "DTSB", "DTSF", "DTSH", "DTSK", "DTSL", "DTSM", "DTSN", "DTSP", "DTSR", "DTSS", "DTST", "DTSW", "DTSX", "DTSY", "DTT", "DTTB", "DTTF", "DTTH", "DTTK", "DTTL", "DTTM", "DTTN", "DTTP", "DTTR", "DTTS", "DTTT", "DTTW", "DTW", "DTWK", "DTWL", "DTWN", "DTWR", "DTWS", "DTWT", "DTWX", "DTX", "DTXF", "DTXL", "DTXM", "DTXN", "DTXP", "DTXR", "DTXS", "DTXT", "DTXW", "DTY", "DTYL", "DTYM", "DTYN", "DTYR", "DTYS", "DTYT", "EE", "EE0", "EE0L", "EE0M", "EE0N", "EE0R", "EE0S", "EEB", "EEBL", "EEBN", "EEBR", "EEBS", "EEBT", "EEF", "EEF0", "EEFB", "EEFF", "EEFK", "EEFL", "EEFM", "EEFN", "EEFR", "EEFS", "EEFT", "EEFW", "EEFX", "EEHL", "EEHW", "EEJ", "EEJB", "EEJF", "EEJH", "EEJK", "EEJL", "EEJM", "EEJN", "EEJP", "EEJR", "EEJS", "EEJT", "EEJW", "EEK", "EEKB", "EEKF", "EEKH", "EEKK", "EEKL", "EEKM", "EEKN", "EEKP", "EEKR", "EEKS", "EEKT", "EEKX", "EEL", "EEL0", "EELB", "EELF", "EELH", "EELJ", "EELK", "EELL", "EELM", "EELN", "EELP", "EELR", "EELS", "EELT", "EELW", "EELX", "EELY", "EEM", "EEMB", "EEMF", "EEMH", "EEMJ", "EEMK", "EEML", "EEMM", "EEMN", "EEMP", "EEMR", "EEMS", "EEMT", "EEMW", "EEN", "EENB", "EENF", "EENH", "EENJ", "EENK", "EENL", "EENM", "EENN", "EENR", "EENS", "EENT", "EENX", "EENY", "EEP", "EEPF", "EEPK", "EEPL", "EEPN", "EEPR", "EEPS", "EEPT", "EEPW", "EER", "EER0", "EERB", "EERF", "EERH", "EERJ", "EERK", "EERL", "EERM", "EERN", "EERP", "EERR", "EERS", "EERT", "EERW", "EERX", "EERY", "EES", "EES0", "EESB", "EESK", "EESL", "EESM", "EESN", "EESP", "EESR", "EESS", "EEST", "EESX", "EET", "EET0", "EETB", "EETF", "EETH", "EETJ", "EETK", "EETL", "EETM", "EETN", "EETP", "EETR", "EETS", "EETT", "EETW", "EETX", "EETY", "EEW", "EEWL", "EEWN", "EEWR", "EEWS", "EEWT", "EEX", "EEXB", "EEXF", "EEXH", "EEXK", "EEXL", "EEXM", "EEXN", "EEXP", "EEXR", "EEXT", "EEYB", "EEYN", "EEYR", "FF", "FF0", "FF0F", "FF0L", "FF0M", "FF0R", "FFB", "FFBJ", "FFBK", "FFBL", "FFBN", "FFBR", "FFBS", "FFF", "FFF0", "FFFB", "FFFF", "FFFK", "FFFL", "FFFM", "FFFN", "FFFP", "FFFR", "FFFS", "FFFT", "FFFW", "FFFX", "FFH", "FFHL", "FFHN", "FFHS", "FFHT", "FFJ", "FFJN", "FFJR", "FFK", "FFKB", "FFKF", "FFKH", "FFKK", "FFKL", "FFKM", "FFKN", "FFKR", "FFKS", "FFKT", "FFKW", "FFKX", "FFL", "FFL0", "FFLB", "FFLF", "FFLH", "FFLJ", "FFLK", "FFLL", "FFLM", "FFLN", "FFLP", "FFLR", "FFLS", "FFLT", "FFLW", "FFLX", "FFLY", "FFM", "FFMB", "FFMK", "FFML", "FFMN", "FFMP", "FFMR", "FFMS", "FFMT", "FFMX", "FFN", "FFN0", "FFNB", "FFNF", "FFNH", "FFNJ", "FFNK", "FFNL", "FFNM", "FFNN", "FFNP", "FFNR", "FFNS", "FFNT", "FFNW", "FFNX", "FFPL", "FFR", "FFR0", "FFRB", "FFRF", "FFRH", "FFRJ", "FFRK", "FFRL", "FFRM", "FFRN", "FFRP", "FFRR", "FFRS", "FFRT", "FFRW", "FFRX", "FFRY", "FFS", "FFSB", "FFSF", "FFSK", "FFSL", "FFSN", "FFSR", "FFSS", "FFST", "FFSX", "FFT", "FFTB", "FFTK", "FFTL", "FFTM", "FFTN", "FFTP", "FFTR", "FFTS", "FFTT", "FFTW", "FFTX", "FFW", "FFWL", "FFWN", "FFWS", "FFWT", "FFX", "FFXB", "FFXF", "FFXH", "FFXK", "FFXL", "FFXM", "FFXN", "FFXP", "FFXR", "FFXS", "FFXT", "FFXW", "FFXX", "FFY", "FFYB", "FFYL", "FFYN", "FFYS", "FFYT", "GFKR", "GFLF", "GFLK", "GFLN", "GFLS", "GFN", "GFNF", "GFNN", "GFNT", "GFR", "GFRK", "GFRL", "GFRN", "GFRS", "GFSL", "GFSP", "GFST", "GFTL", "GJ", "GJ0N", "GJB", "GJBH", "GJBK", "GJBL", "GJBM", "GJBN", "GJBR", "GJBS", "GJBT", "GJF", "GJFB", "GJFF", "GJFK", "GJFL", "GJFN", "GJFR", "GJFS", "GJFT", "GJFW", "GJFX", "GJH", "GJHK", "GJHM", "GJHT", "GJJ", "GJJL", "GJJN", "GJJR", "GJJS", "GJJT", "GJJY", "GJK", "GJKB", "GJKK", "GJKL", "GJKM", "GJKN", "GJKR", "GJKS", "GJL", "GJLB", "GJLF", "GJLH", "GJLJ", "GJLK", "GJLL", "GJLM", "GJLN", "GJLP", "GJLR", "GJLS", "GJLT", "GJLW", "GJLX", "GJM", "GJMB", "GJMF", "GJMH", "GJMK", "GJML", "GJMN", "GJMP", "GJMR", "GJMS", "GJMW", "GJN", "GJN0", "GJNB", "GJNF", "GJNJ", "GJNK", "GJNL", "GJNM", "GJNN", "GJNR", "GJNS", "GJNT", "GJNX", "GJP", "GJPN", "GJPR", "GJPS", "GJPT", "GJR", "GJR0", "GJRB", "GJRF", "GJRH", "GJRJ", "GJRK", "GJRL", "GJRM", "GJRN", "GJRR", "GJRS", "GJRT", "GJRW", "GJRX", "GJS", "GJSB", "GJSK", "GJSL", "GJSM", "GJSN", "GJSP", "GJSR", "GJST", "GJT", "GJTB", "GJTF", "GJTJ", "GJTL", "GJTN", "GJTP", "GJTR", "GJTS", "GJTT", "GJTW", "GJTX", "GJTY", "GJW", "GJWN", "GJX", "GJXL", "GJXM", "GJY", "GJYR", "GK", "GK0", "GK0K", "GK0L", "GK0M", "GK0N", "GK0R", "GK0S", "GK0W", "GKB", "GKBB", "GKBK", "GKBL", "GKBN", "GKBR", "GKBS", "GKBT", "GKBW", "GKBX", "GKBY", "GKF", "GKFJ", "GKFK", "GKFL", "GKFN", "GKFR", "GKFS", "GKFT", "GKHK", "GKHL", "GKHN", "GKHR", "GKJ", "GKJK", "GKJL", "GKJN", "GKJR", "GKJS", "GKJT", "GKK", "GKKK", "GKKL", "GKKM", "GKKN", "GKKP", "GKKR", "GKKS", "GKKT", "GKKX", "GKL", "GKL0", "GKLB", "GKLF", "GKLH", "GKLJ", "GKLK", "GKLL", "GKLM", "GKLN", "GKLP", "GKLR", "GKLS", "GKLT", "GKLW", "GKLX", "GKLY", "GKM", "GKMB", "GKMF", "GKMH", "GKMJ", "GKMK", "GKML", "GKMM", "GKMN", "GKMP", "GKMR", "GKMS", "GKMT", "GKMW", "GKMY", "GKN", "GKN0", "GKNB", "GKNF", "GKNH", "GKNJ", "GKNK", "GKNL", "GKNM", "GKNN", "GKNP", "GKNR", "GKNS", "GKNT", "GKNW", "GKNX", "GKNY", "GKP", "GKPB", "GKPF", "GKPH", "GKPK", "GKPL", "GKPP", "GKPR", "GKPS", "GKPW", "GKR", "GKR0", "GKRB", "GKRF", "GKRH", "GKRJ", "GKRK", "GKRL", "GKRM", "GKRN", "GKRP", "GKRR", "GKRS", "GKRT", "GKRW", "GKRX", "GKRY", "GKS", "GKS0", "GKSB", "GKSF", "GKSH", "GKSJ", "GKSK", "GKSL", "GKSM", "GKSN", "GKSP", "GKSR", "GKSS", "GKST", "GKSW", "GKSX", "GKT", "GKTB", "GKTF", "GKTH", "GKTJ", "GKTK", "GKTL", "GKTM", "GKTN", "GKTP", "GKTR", "GKTS", "GKTT", "GKTW", "GKTX", "GKTY", "GKW", "GKW0", "GKWB", "GKWL", "GKWM", "GKWN", "GKWR", "GKWT", "GKX", "GKXK", "GKXM", "GKXN", "GKXR", "GKXS", "GKY", "GKYK", "GKYM", "GKYN", "GKYR", "GKYT", "GNBR", "GNL", "GNLS", "GNLY", "GNNK", "GNNT", "GNR", "GNRB", "GNRK", "GNRL", "GNRM", "GNRN", "GNRP", "GNRW", "GNSH", "GNT", "GNTK", "GNTN", "GNWL", "GNWN", "H0", "H0RT", "HBL", "HBLS", "HBN", "HBN0", "HBNS", "HBRM", "HBRT", "HBST", "HFJL", "HFLT", "HFR", "HFRS", "HH", "HH0", "HH0B", "HH0F", "HH0H", "HH0K", "HH0L", "HH0M", "HH0N", "HH0P", "HH0R", "HH0S", "HH0T", "HH0W", "HHB", "HHBB", "HHBH", "HHBK", "HHBL", "HHBN", "HHBR", "HHBS", "HHBT", "HHBW", "HHBX", "HHBY", "HHF", "HHFB", "HHFF", "HHFH", "HHFJ", "HHFK", "HHFL", "HHFM", "HHFN", "HHFP", "HHFR", "HHFS", "HHFT", "HHFW", "HHFX", "HHH", "HHHN", "HHHR", "HHHS", "HHJ", "HHJF", "HHJL", "HHJM", "HHJN", "HHJR", "HHJS", "HHJT", "HHJW", "HHJY", "HHK", "HHKB", "HHKF", "HHKH", "HHKK", "HHKL", "HHKM", "HHKN", "HHKP", "HHKR", "HHKS", "HHKT", "HHKW", "HHKX", "HHL", "HHL0", "HHLB", "HHLF", "HHLH", "HHLJ", "HHLK", "HHLL", "HHLM", "HHLN", "HHLP", "HHLR", "HHLS", "HHLT", "HHLW", "HHLX", "HHLY", "HHM", "HHMB", "HHMF", "HHMH", "HHMJ", "HHMK", "HHML", "HHMM", "HHMN", "HHMP", "HHMR", "HHMS", "HHMT", "HHMW", "HHMX", "HHMY", "HHN", "HHN0", "HHNB", "HHNF", "HHNH", "HHNJ", "HHNK", "HHNL", "HHNM", "HHNN", "HHNP", "HHNR", "HHNS", "HHNT", "HHNW", "HHNX", "HHNY", "HHP", "HHP0", "HHPB", "HHPF", "HHPH", "HHPJ", "HHPK", "HHPL", "HHPM", "HHPN", "HHPP", "HHPR", "HHPS", "HHPT", "HHPW", "HHR", "HHR0", "HHRB", "HHRF", "HHRH", "HHRJ", "HHRK", "HHRL", "HHRM", "HHRN", "HHRP", "HHRR", "HHRS", "HHRT", "HHRW", "HHRX", "HHRY", "HHS", "HHS0", "HHSB", "HHSF", "HHSH", "HHSK", "HHSL", "HHSM", "HHSN", "HHSP", "HHSR", "HHSS", "HHST", "HHSW", "HHSX", "HHT", "HHTB", "HHTF", "HHTH", "HHTK", "HHTL", "HHTM", "HHTN", "HHTP", "HHTR", "HHTS", "HHTT", "HHTW", "HHTX", "HHTY", "HHW", "HHW0", "HHWK", "HHWL", "HHWN", "HHWR", "HHWS", "HHWT", "HHWX", "HHX", "HHXB", "HHXF", "HHXK", "HHXL", "HHXM", "HHXN", "HHXP", "HHXR", "HHXS", "HHXT", "HHXW", "HHY", "HHYK", "HHYN", "HHYR", "HHYS", "HJ", "HJR0", "HJRT", "HJT", "HKRF", "HLKL", "HLNT", "HLS", "HLTN", "HLTS", "HM0", "HMBS", "HMKS", "HMLR", "HMN", "HMNS", "HMS", "HMSB", "HMSS", "HMTS", "HMXL", "HN", "HNM", "HNMK", "HNS", "HNST", "HNTF", "HNTM", "HNTS", "HNX", "HPRN", "HPX", "HR", "HRBL", "HRM", "HRT", "HSKR", "HSLP", "HSM0", "HSN", "HSP", "HSTN", "HT", "HTBR", "HTFL", "HTHL", "HTHR", "HTKR", "HTN", "HTNL", "HTNM", "HTNN", "HTNS", "HTPR", "HTR", "HTRB", "HTRF", "HTRJ", "HTRL", "HTRN", "HTRS", "HTS", "HTSK", "HTSP", "HTTL", "HTTS", "HTWB", "HWLR", "HWLT", "HX", "HXRK", "HXRS", "HYLN", "HYM", "HYMS", "HYNT", "HYRN", "HYSN", "HYT", "HYTS", "II", "II0K", "II0M", "IIBB", "IIBK", "IIBL", "IIBR", "IIBS", "IIBT", "IIBY", "IIF", "IIF0", "IIFB", "IIFF", "IIFH", "IIFK", "IIFL", "IIFM", "IIFN", "IIFR", "IIFS", "IIFT", "IIHF", "IIJB", "IIJN", "IIJR", "IIJS", "IIK", "IIKK", "IIKL", "IIKN", "IIKR", "IIKS", "IIKT", "IIKW", "IIL", "IILB", "IILF", "IILH", "IILJ", "IILK", "IILL", "IILM", "IILN", "IILP", "IILR", "IILS", "IILT", "IILW", "IILX", "IILY", "IIM", "IIMF", "IIMH", "IIMJ", "IIMK", "IIML", "IIMN", "IIMP", "IIMR", "IIMS", "IIMT", "IIMY", "IIN", "IIN0", "IINB", "IINF", "IINH", "IINJ", "IINK", "IINL", "IINM", "IINN", "IINP", "IINR", "IINS", "IINT", "IINW", "IINX", "IINY", "IIP", "IIPL", "IIPM", "IIPN", "IIPR", "IIPS", "IIPT", "IIR", "IIRB", "IIRF", "IIRJ", "IIRK", "IIRL", "IIRM", "IIRN", "IIRP", "IIRR", "IIRS", "IIRT", "IIRW", "IIRX", "IIS", "IISB", "IISF", "IISK", "IISL", "IISM", "IISN", "IISP", "IISR", "IISS", "IIST", "IISW", "IISX", "IIT", "IITB", "IITF", "IITH", "IITJ", "IITK", "IITL", "IITM", "IITN", "IITR", "IITS", "IITT", "IITW", "IIW", "IIWN", "IIWR", "IIWS", "IIWT", "IIX", "IIXB", "IIXL", "IIXM", "IIXN", "IIXR", "IIXT", "IIYP", "JJ", "JJ0", "JJ0R", "JJ0W", "JJB", "JJBF", "JJBJ", "JJBK", "JJBL", "JJBN", "JJBR", "JJBS", "JJBT", "JJBW", "JJF", "JJFH", "JJFJ", "JJFK", "JJFL", "JJFN", "JJFR", "JJFS", "JJFX", "JJH", "JJHK", "JJHL", "JJHN", "JJHP", "JJHR", "JJHS", "JJJ", "JJJH", "JJJL", "JJJN", "JJJR", "JJJS", "JJJT", "JJK", "JJK0", "JJKB", "JJKF", "JJKH", "JJKJ", "JJKK", "JJKL", "JJKM", "JJKN", "JJKP", "JJKR", "JJKS", "JJKT", "JJKW", "JJL", "JJLB", "JJLF", "JJLJ", "JJLK", "JJLL", "JJLM", "JJLN", "JJLP", "JJLR", "JJLS", "JJLT", "JJLW", "JJLY", "JJM", "JJMB", "JJMF", "JJMH", "JJMJ", "JJMK", "JJML", "JJMM", "JJMN", "JJMP", "JJMR", "JJMS", "JJMT", "JJMW", "JJMX", "JJN", "JJN0", "JJNB", "JJNF", "JJNH", "JJNJ", "JJNK", "JJNL", "JJNM", "JJNN", "JJNP", "JJNR", "JJNS", "JJNT", "JJNW", "JJNX", "JJNY", "JJP", "JJPJ", "JJPK", "JJPL", "JJPN", "JJPR", "JJPS", "JJPT", "JJPX", "JJR", "JJRB", "JJRF", "JJRJ", "JJRK", "JJRL", "JJRM", "JJRN", "JJRP", "JJRR", "JJRS", "JJRT", "JJRW", "JJRX", "JJS", "JJSB", "JJSF", "JJSH", "JJSJ", "JJSK", "JJSL", "JJSM", "JJSN", "JJSP", "JJSR", "JJSS", "JJST", "JJSW", "JJSX", "JJT", "JJT0", "JJTB", "JJTF", "JJTJ", "JJTK", "JJTL", "JJTM", "JJTN", "JJTP", "JJTR", "JJTS", "JJTT", "JJTX", "JJW", "JJWK", "JJWL", "JJWN", "JJWR", "JJWS", "JJWT", "JJX", "JJXK", "JJXM", "JJXN", "JJXR", "JJXS", "JJY", "JJYF", "JJYL", "JJYN", "JJYR", "JJYS", "KK", "KK0", "KK0B", "KK0F", "KK0H", "KK0J", "KK0K", "KK0L", "KK0M", "KK0N", "KK0P", "KK0R", "KK0S", "KK0T", "KK0W", "KK0X", "KKB", "KKBB", "KKBJ", "KKBK", "KKBL", "KKBN", "KKBR", "KKBS", "KKBT", "KKBX", "KKBY", "KKF", "KKFB", "KKFK", "KKFL", "KKFM", "KKFN", "KKFP", "KKFR", "KKFS", "KKFT", "KKH", "KKHB", "KKHL", "KKHM", "KKHN", "KKHP", "KKHR", "KKHS", "KKHT", "KKHY", "KKJ", "KKJB", "KKJK", "KKJL", "KKJN", "KKJR", "KKJS", "KKJT", "KKJY", "KKK", "KKK0", "KKKB", "KKKK", "KKKL", "KKKM", "KKKN", "KKKP", "KKKR", "KKKS", "KKKT", "KKKW", "KKKY", "KKL", "KKL0", "KKLB", "KKLF", "KKLH", "KKLJ", "KKLK", "KKLL", "KKLM", "KKLN", "KKLP", "KKLR", "KKLS", "KKLT", "KKLW", "KKLX", "KKLY", "KKM", "KKM0", "KKMB", "KKMF", "KKMH", "KKMJ", "KKMK", "KKML", "KKMM", "KKMN", "KKMP", "KKMR", "KKMS", "KKMT", "KKMX", "KKN", "KKN0", "KKNB", "KKNF", "KKNH", "KKNJ", "KKNK", "KKNL", "KKNM", "KKNN", "KKNP", "KKNR", "KKNS", "KKNT", "KKNW", "KKNX", "KKNY", "KKP", "KKPB", "KKPF", "KKPH", "KKPK", "KKPL", "KKPM", "KKPN", "KKPR", "KKPS", "KKPT", "KKPW", "KKPX", "KKPY", "KKR", "KKR0", "KKRB", "KKRF", "KKRH", "KKRJ", "KKRK", "KKRL", "KKRM", "KKRN", "KKRP", "KKRR", "KKRS", "KKRT", "KKRW", "KKRX", "KKRY", "KKS", "KKS0", "KKSB", "KKSF", "KKSK", "KKSL", "KKSM", "KKSN", "KKSP", "KKSR", "KKSS", "KKST", "KKSW", "KKSX", "KKSY", "KKT", "KKTB", "KKTF", "KKTH", "KKTJ", "KKTK", "KKTL", "KKTM", "KKTN", "KKTP", "KKTR", "KKTS", "KKTT", "KKTW", "KKTX", "KKTY", "KKW", "KKWB", "KKWF", "KKWH", "KKWK", "KKWL", "KKWN", "KKWR", "KKWS", "KKWT", "KKWW", "KKWX", "KKX", "KKXF", "KKXJ", "KKXK", "KKXL", "KKXM", "KKXN", "KKXR", "KKXS", "KKY", "KKYB", "KKYK", "KKYL", "KKYM", "KKYN", "KKYP", "KKYR", "KKYS", "KKYT", "KKYW", "KN", "KN0", "KNB", "KNBK", "KNBL", "KNBN", "KNBS", "KNBW", "KNF", "KNFL", "KNFT", "KNK", "KNKB", "KNKF", "KNKL", "KNKP", "KNKR", "KNKS", "KNKT", "KNL", "KNLB", "KNLJ", "KNLM", "KNLN", "KNLR", "KNLS", "KNLT", "KNLW", "KNN", "KNNJ", "KNNK", "KNP", "KNPH", "KNPK", "KNPM", "KNPS", "KNPT", "KNPW", "KNR", "KNRH", "KNS", "KNSL", "KNST", "KNT", "KNTL", "KNTN", "KNTR", "KNTS", "KNTW", "KNW", "KNWN", "KNX", "KNYR", "LL", "LL0", "LL0B", "LL0F", "LL0J", "LL0K", "LL0L", "LL0M", "LL0N", "LL0P", "LL0R", "LL0S", "LL0T", "LL0W", "LLB", "LLB0", "LLBB", "LLBH", "LLBJ", "LLBK", "LLBL", "LLBM", "LLBN", "LLBR", "LLBS", "LLBT", "LLBW", "LLBX", "LLBY", "LLF", "LLF0", "LLFB", "LLFF", "LLFH", "LLFJ", "LLFK", "LLFL", "LLFM", "LLFN", "LLFP", "LLFR", "LLFS", "LLFT", "LLFW", "LLFX", "LLFY", "LLH", "LLHF", "LLHL", "LLHM", "LLHN", "LLHR", "LLHS", "LLHT", "LLJ", "LLJB", "LLJF", "LLJK", "LLJL", "LLJM", "LLJN", "LLJP", "LLJR", "LLJS", "LLJT", "LLJW", "LLJY", "LLK", "LLKB", "LLKF", "LLKH", "LLKJ", "LLKK", "LLKL", "LLKM", "LLKN", "LLKP", "LLKR", "LLKS", "LLKT", "LLKW", "LLKX", "LLKY", "LLL", "LLL0", "LLLB", "LLLF", "LLLH", "LLLJ", "LLLK", "LLLL", "LLLM", "LLLN", "LLLP", "LLLR", "LLLS", "LLLT", "LLLW", "LLLX", "LLLY", "LLM", "LLM0", "LLMB", "LLMF", "LLMH", "LLMJ", "LLMK", "LLML", "LLMM", "LLMN", "LLMP", "LLMR", "LLMS", "LLMT", "LLMW", "LLMX", "LLMY", "LLN", "LLN0", "LLNB", "LLNF", "LLNH", "LLNJ", "LLNK", "LLNL", "LLNM", "LLNN", "LLNP", "LLNR", "LLNS", "LLNT", "LLNW", "LLNX", "LLNY", "LLP", "LLP0", "LLPF", "LLPJ", "LLPK", "LLPL", "LLPM", "LLPN", "LLPR", "LLPS", "LLPT", "LLPW", "LLPX", "LLR", "LLR0", "LLRB", "LLRF", "LLRH", "LLRJ", "LLRK", "LLRL", "LLRM", "LLRN", "LLRP", "LLRR", "LLRS", "LLRT", "LLRW", "LLRX", "LLS", "LLSB", "LLSF", "LLSH", "LLSJ", "LLSK", "LLSL", "LLSM", "LLSN", "LLSP", "LLSR", "LLSS", "LLST", "LLSW", "LLSX", "LLSY", "LLT", "LLTB", "LLTF", "LLTH", "LLTJ", "LLTK", "LLTL", "LLTM", "LLTN", "LLTP", "LLTR", "LLTS", "LLTT", "LLTW", "LLTX", "LLTY", "LLW", "LLWK", "LLWL", "LLWN", "LLWR", "LLWS", "LLWT", "LLWX", "LLX", "LLXB", "LLXF", "LLXK", "LLXL", "LLXM", "LLXN", "LLXP", "LLXR", "LLXS", "LLXT", "LLXW", "LLY", "LLYK", "LLYL", "LLYM", "LLYN", "LLYR", "LLYT", "MM", "MM0", "MM0F", "MM0H", "MM0K", "MM0L", "MM0M", "MM0N", "MM0R", "MM0S", "MM0T", "MM0W", "MMB", "MMBH", "MMBJ", "MMBK", "MMBL", "MMBN", "MMBR", "MMBS", "MMBT", "MMBX", "MMF", "MMFH", "MMFJ", "MMFK", "MMFL", "MMFM", "MMFN", "MMFR", "MMFS", "MMFT", "MMH", "MMHB", "MMHF", "MMHH", "MMHK", "MMHL", "MMHM", "MMHN", "MMHR", "MMHS", "MMHT", "MMJ", "MMJB", "MMJF", "MMJK", "MMJL", "MMJM", "MMJN", "MMJP", "MMJR", "MMJS", "MMJT", "MMJW", "MMJY", "MMK", "MMK0", "MMKB", "MMKF", "MMKH", "MMKJ", "MMKK", "MMKL", "MMKM", "MMKN", "MMKP", "MMKR", "MMKS", "MMKT", "MMKW", "MMKX", "MMKY", "MML", "MML0", "MMLB", "MMLF", "MMLH", "MMLJ", "MMLK", "MMLL", "MMLM", "MMLN", "MMLP", "MMLR", "MMLS", "MMLT", "MMLW", "MMLX", "MMLY", "MMM", "MMM0", "MMMB", "MMMF", "MMMH", "MMMK", "MMML", "MMMM", "MMMN", "MMMP", "MMMR", "MMMS", "MMMT", "MMMW", "MMMX", "MMN", "MMN0", "MMNB", "MMNF", "MMNH", "MMNJ", "MMNK", "MMNL", "MMNM", "MMNN", "MMNP", "MMNR", "MMNS", "MMNT", "MMNW", "MMNX", "MMNY", "MMP", "MMPK", "MMPL", "MMPN", "MMPR", "MMPS", "MMPT", "MMPW", "MMPY", "MMR", "MMR0", "MMRB", "MMRF", "MMRH", "MMRJ", "MMRK", "MMRL", "MMRM", "MMRN", "MMRP", "MMRR", "MMRS", "MMRT", "MMRW", "MMRX", "MMRY", "MMS", "MMS0", "MMSB", "MMSF", "MMSH", "MMSJ", "MMSK", "MMSL", "MMSM", "MMSN", "MMSP", "MMSR", "MMSS", "MMST", "MMSW", "MMSX", "MMSY", "MMT", "MMTB", "MMTF", "MMTH", "MMTJ", "MMTK", "MMTL", "MMTM", "MMTN", "MMTP", "MMTR", "MMTS", "MMTT", "MMTW", "MMTX", "MMTY", "MMW", "MMWB", "MMWK", "MMWL", "MMWM", "MMWN", "MMWR", "MMWS", "MMWT", "MMX", "MMXB", "MMXF", "MMXK", "MMXL", "MMXM", "MMXN", "MMXP", "MMXR", "MMXS", "MMXT", "MMXW", "MMXX", "MMY", "MMYB", "MMYK", "MMYL", "MMYM", "MMYN", "MMYP", "MMYR", "MMYS", "MMYT", "NN", "NN0", "NN0B", "NN0F", "NN0L", "NN0M", "NN0N", "NN0R", "NN0S", "NN0T", "NN0X", "NNB", "NNB0", "NNBH", "NNBJ", "NNBK", "NNBL", "NNBN", "NNBP", "NNBR", "NNBS", "NNBT", "NNBW", "NNBX", "NNF", "NNF0", "NNFB", "NNFH", "NNFJ", "NNFK", "NNFL", "NNFN", "NNFR", "NNFS", "NNFT", "NNFX", "NNH0", "NNHF", "NNHK", "NNHL", "NNHM", "NNHN", "NNHR", "NNJ", "NNJB", "NNJL", "NNJM", "NNJN", "NNJR", "NNJY", "NNK", "NNKB", "NNKJ", "NNKK", "NNKL", "NNKM", "NNKN", "NNKP", "NNKR", "NNKS", "NNKT", "NNKW", "NNKX", "NNKY", "NNL", "NNL0", "NNLB", "NNLF", "NNLH", "NNLJ", "NNLK", "NNLL", "NNLM", "NNLN", "NNLP", "NNLR", "NNLS", "NNLT", "NNLW", "NNLX", "NNLY", "NNM", "NNM0", "NNMF", "NNMJ", "NNMK", "NNML", "NNMN", "NNMP", "NNMR", "NNMS", "NNMT", "NNMW", "NNMX", "NNMY", "NNN", "NNN0", "NNNB", "NNNF", "NNNH", "NNNJ", "NNNK", "NNNL", "NNNM", "NNNN", "NNNP", "NNNR", "NNNS", "NNNT", "NNNW", "NNNX", "NNNY", "NNP", "NNP0", "NNPK", "NNPL", "NNPN", "NNPR", "NNPT", "NNR", "NNR0", "NNRB", "NNRF", "NNRH", "NNRJ", "NNRK", "NNRL", "NNRM", "NNRN", "NNRP", "NNRR", "NNRS", "NNRT", "NNRW", "NNRX", "NNRY", "NNS", "NNS0", "NNSB", "NNSF", "NNSK", "NNSL", "NNSM", "NNSN", "NNSP", "NNSR", "NNSS", "NNST", "NNSW", "NNSX", "NNT", "NNT0", "NNTB", "NNTF", "NNTH", "NNTJ", "NNTK", "NNTL", "NNTM", "NNTN", "NNTP", "NNTR", "NNTS", "NNTT", "NNTW", "NNTX", "NNTY", "NNW", "NNWK", "NNWL", "NNWN", "NNWR", "NNWS", "NNWT", "NNX", "NNXB", "NNXF", "NNXJ", "NNXK", "NNXL", "NNXM", "NNXN", "NNXP", "NNXR", "NNXS", "NNXT", "NNXW", "NNY", "NNYB", "NNYK", "NNYL", "NNYM", "NNYN", "NNYP", "NNYR", "NNYS", "NNYT", "NNYW", "NNYY", "OO", "OO0", "OO0K", "OO0L", "OO0N", "OO0W", "OOB", "OOBB", "OOBF", "OOBK", "OOBL", "OOBM", "OOBN", "OOBR", "OOBS", "OOBT", "OOF", "OOF0", "OOFB", "OOFF", "OOFH", "OOFK", "OOFL", "OOFM", "OOFN", "OOFP", "OOFR", "OOFS", "OOFT", "OOFW", "OOFX", "OOH", "OOHH", "OOHK", "OOHL", "OOHN", "OOHR", "OOJL", "OOJM", "OOJR", "OOK", "OOKB", "OOKF", "OOKH", "OOKJ", "OOKK", "OOKL", "OOKM", "OOKN", "OOKP", "OOKR", "OOKS", "OOKT", "OOKW", "OOKX", "OOL", "OOLB", "OOLF", "OOLK", "OOLL", "OOLM", "OOLN", "OOLP", "OOLR", "OOLS", "OOLT", "OOLW", "OOLY", "OOM", "OOMB", "OOMF", "OOMH", "OOMK", "OOML", "OOMM", "OOMN", "OOMR", "OOMT", "OOMX", "OON", "OON0", "OONF", "OONJ", "OONK", "OONL", "OONM", "OONN", "OONP", "OONR", "OONS", "OONT", "OONW", "OONX", "OONY", "OOP", "OOPK", "OOPL", "OOPN", "OOPR", "OOPS", "OOPT", "OOPW", "OOR", "OOR0", "OORB", "OORF", "OORJ", "OORK", "OORL", "OORM", "OORN", "OORP", "OORR", "OORS", "OORT", "OORW", "OORX", "OORY", "OOS", "OOSB", "OOSJ", "OOSK", "OOSL", "OOSM", "OOSN", "OOSP", "OOSR", "OOSS", "OOST", "OOSW", "OOSX", "OOT", "OOTB", "OOTF", "OOTH", "OOTK", "OOTL", "OOTM", "OOTN", "OOTP", "OOTR", "OOTS", "OOTT", "OOTW", "OOTY", "OOWN", "OOWR", "OOX", "OOXL", "OOXN", "OOXR", "OOXS", "OOXT", "OOYM", "OOYN", "PF", "PFB", "PFBS", "PFF", "PFFL", "PFKN", "PFL", "PFLB", "PFLH", "PFLK", "PFLM", "PFLN", "PFLP", "PFLR", "PFLS", "PFLT", "PFLW", "PFM", "PFN", "PFNK", "PFNS", "PFNT", "PFP", "PFPR", "PFPS", "PFR", "PFRL", "PFRS", "PFRW", "PFS", "PFSF", "PFSK", "PFSM", "PFSN", "PFTK", "PFTN", "PFTS", "PNMN", "PP", "PP0", "PP0B", "PP0F", "PP0J", "PP0K", "PP0M", "PP0N", "PP0R", "PP0S", "PPB", "PPBJ", "PPBK", "PPBL", "PPBM", "PPBN", "PPBR", "PPBS", "PPBT", "PPBW", "PPF", "PPFF", "PPFK", "PPFL", "PPFM", "PPFN", "PPFR", "PPFS", "PPFT", "PPH", "PPHL", "PPHN", "PPHS", "PPHT", "PPJ", "PPJB", "PPJK", "PPJL", "PPJM", "PPJN", "PPJR", "PPJS", "PPJT", "PPJW", "PPK", "PPK0", "PPKB", "PPKF", "PPKH", "PPKK", "PPKL", "PPKM", "PPKN", "PPKP", "PPKR", "PPKS", "PPKT", "PPKW", "PPKX", "PPL", "PPL0", "PPLB", "PPLF", "PPLH", "PPLJ", "PPLK", "PPLL", "PPLM", "PPLN", "PPLP", "PPLR", "PPLS", "PPLT", "PPLW", "PPLX", "PPLY", "PPM", "PPMF", "PPMJ", "PPMK", "PPML", "PPMM", "PPMN", "PPMP", "PPMR", "PPMS", "PPMT", "PPMW", "PPMX", "PPN", "PPN0", "PPNB", "PPNF", "PPNH", "PPNJ", "PPNK", "PPNL", "PPNM", "PPNN", "PPNP", "PPNR", "PPNS", "PPNT", "PPNW", "PPNX", "PPNY", "PPP", "PPP0", "PPPB", "PPPF", "PPPH", "PPPJ", "PPPK", "PPPL", "PPPN", "PPPP", "PPPR", "PPPS", "PPPT", "PPPW", "PPPY", "PPR", "PPR0", "PPRB", "PPRF", "PPRH", "PPRJ", "PPRK", "PPRL", "PPRM", "PPRN", "PPRP", "PPRR", "PPRS", "PPRT", "PPRW", "PPRX", "PPRY", "PPS", "PPS0", "PPSB", "PPSF", "PPSH", "PPSJ", "PPSK", "PPSL", "PPSM", "PPSN", "PPSP", "PPSR", "PPSS", "PPST", "PPSW", "PPSX", "PPT", "PPT0", "PPTB", "PPTF", "PPTH", "PPTJ", "PPTK", "PPTL", "PPTM", "PPTN", "PPTP", "PPTR", "PPTS", "PPTT", "PPTW", "PPTX", "PPTY", "PPW", "PPWL", "PPWN", "PPWR", "PPWS", "PPWT", "PPX", "PPXB", "PPXF", "PPXK", "PPXL", "PPXM", "PPXN", "PPXP", "PPXR", "PPXS", "PPXT", "PPXW", "PPY", "PPYL", "PPYN", "PPYP", "PPYR", "PPYS", "PPYT", "PPYW", "QK", "QKB0", "QKBK", "QKBN", "QKBR", "QKBS", "QKBT", "QKF", "QKFN", "QKFP", "QKFR", "QKFS", "QKFT", "QKH", "QKK", "QKKB", "QKKL", "QKKM", "QKKN", "QKKR", "QKKS", "QKL", "QKLB", "QKLJ", "QKLK", "QKLM", "QKLN", "QKLP", "QKLR", "QKLS", "QKLT", "QKLX", "QKM", "QKMB", "QKMK", "QKMN", "QKMS", "QKMT", "QKN", "QKNB", "QKNF", "QKNH", "QKNJ", "QKNK", "QKNL", "QKNM", "QKNN", "QKNS", "QKNT", "QKNW", "QKNX", "QKPL", "QKPR", "QKR", "QKRB", "QKRF", "QKRH", "QKRK", "QKRL", "QKRM", "QKRN", "QKRP", "QKRR", "QKRS", "QKRT", "QKS", "QKS0", "QKSN", "QKSR", "QKST", "QKT", "QKTF", "QKTJ", "QKTK", "QKTL", "QKTN", "QKTR", "QKTS", "QKTT", "QKX", "QKYR", "RR", "RR0", "RR0B", "RR0F", "RR0H", "RR0J", "RR0K", "RR0L", "RR0M", "RR0N", "RR0R", "RR0S", "RR0T", "RR0W", "RRB", "RRB0", "RRBB", "RRBF", "RRBH", "RRBJ", "RRBK", "RRBL", "RRBM", "RRBN", "RRBR", "RRBS", "RRBT", "RRBW", "RRBX", "RRBY", "RRF", "RRFB", "RRFF", "RRFH", "RRFJ", "RRFK", "RRFL", "RRFM", "RRFN", "RRFP", "RRFR", "RRFS", "RRFT", "RRFW", "RRFX", "RRH", "RRHB", "RRHF", "RRHK", "RRHL", "RRHM", "RRHN", "RRHP", "RRHR", "RRHS", "RRHT", "RRJ", "RRJF", "RRJH", "RRJK", "RRJL", "RRJM", "RRJN", "RRJP", "RRJR", "RRJS", "RRJT", "RRJW", "RRJY", "RRK", "RRKB", "RRKF", "RRKH", "RRKJ", "RRKK", "RRKL", "RRKM", "RRKN", "RRKP", "RRKR", "RRKS", "RRKT", "RRKW", "RRKX", "RRL", "RRLB", "RRLF", "RRLJ", "RRLK", "RRLM", "RRLN", "RRLP", "RRLR", "RRLS", "RRLT", "RRLW", "RRLX", "RRLY", "RRM", "RRMB", "RRMF", "RRMH", "RRMJ", "RRMK", "RRML", "RRMM", "RRMN", "RRMP", "RRMR", "RRMS", "RRMT", "RRMW", "RRMX", "RRMY", "RRN", "RRN0", "RRNB", "RRNF", "RRNH", "RRNJ", "RRNK", "RRNL", "RRNM", "RRNN", "RRNP", "RRNR", "RRNS", "RRNT", "RRNW", "RRNX", "RRNY", "RRP", "RRPB", "RRPF", "RRPH", "RRPK", "RRPL", "RRPN", "RRPR", "RRPS", "RRPT", "RRPX", "RRPY", "RRR", "RRRH", "RRRK", "RRRL", "RRRM", "RRRN", "RRRP", "RRRS", "RRRT", "RRRW", "RRS", "RRS0", "RRSB", "RRSF", "RRSH", "RRSJ", "RRSK", "RRSL", "RRSM", "RRSN", "RRSP", "RRSR", "RRSS", "RRST", "RRSW", "RRSX", "RRT", "RRT0", "RRTB", "RRTF", "RRTH", "RRTJ", "RRTK", "RRTL", "RRTM", "RRTN", "RRTP", "RRTR", "RRTS", "RRTT", "RRTW", "RRTX", "RRTY", "RRW", "RRWL", "RRWN", "RRWR", "RRWS", "RRWT", "RRX", "RRXB", "RRXF", "RRXK", "RRXL", "RRXM", "RRXN", "RRXR", "RRXS", "RRXT", "RRXW", "RRY", "RRYB", "RRYF", "RRYK", "RRYL", "RRYN", "RRYP", "RRYR", "RRYS", "RRYT", "SS", "SS0", "SS0B", "SS0F", "SS0H", "SS0J", "SS0K", "SS0L", "SS0M", "SS0N", "SS0P", "SS0R", "SS0S", "SS0T", "SS0W", "SS0X", "SS0Y", "SSB", "SSB0", "SSBK", "SSBL", "SSBM", "SSBN", "SSBR", "SSBS", "SSBT", "SSBW", "SSBX", "SSF", "SSFJ", "SSFK", "SSFL", "SSFM", "SSFN", "SSFP", "SSFR", "SSFS", "SSFT", "SSFY", "SSH", "SSH0", "SSHF", "SSHJ", "SSHK", "SSHL", "SSHM", "SSHN", "SSHR", "SSHS", "SSJ", "SSJB", "SSJF", "SSJH", "SSJJ", "SSJL", "SSJM", "SSJN", "SSJR", "SSJS", "SSJT", "SSJW", "SSK", "SSK0", "SSKB", "SSKF", "SSKH", "SSKK", "SSKL", "SSKM", "SSKN", "SSKP", "SSKR", "SSKS", "SSKT", "SSKW", "SSKX", "SSKY", "SSL", "SSL0", "SSLB", "SSLF", "SSLH", "SSLJ", "SSLK", "SSLL", "SSLM", "SSLN", "SSLP", "SSLR", "SSLS", "SSLT", "SSLW", "SSLX", "SSLY", "SSM", "SSM0", "SSMB", "SSMF", "SSMH", "SSMJ", "SSMK", "SSML", "SSMM", "SSMN", "SSMP", "SSMR", "SSMS", "SSMT", "SSMW", "SSMX", "SSMY", "SSN", "SSN0", "SSNB", "SSNF", "SSNH", "SSNJ", "SSNK", "SSNL", "SSNM", "SSNN", "SSNP", "SSNR", "SSNS", "SSNT", "SSNW", "SSNX", "SSNY", "SSP", "SSP0", "SSPB", "SSPF", "SSPJ", "SSPK", "SSPL", "SSPM", "SSPN", "SSPR", "SSPS", "SSPT", "SSPW", "SSPX", "SSR", "SSR0", "SSRB", "SSRF", "SSRH", "SSRJ", "SSRK", "SSRL", "SSRM", "SSRN", "SSRP", "SSRR", "SSRS", "SSRT", "SSRW", "SSRX", "SSRY", "SSS", "SSSB", "SSSF", "SSSJ", "SSSK", "SSSL", "SSSM", "SSSN", "SSSP", "SSSR", "SSSS", "SSST", "SSSW", "SSSX", "SSSY", "SST", "SST0", "SSTB", "SSTF", "SSTH", "SSTJ", "SSTK", "SSTL", "SSTM", "SSTN", "SSTP", "SSTR", "SSTS", "SSTT", "SSTW", "SSTX", "SSTY", "SSW", "SSW0", "SSWB", "SSWF", "SSWJ", "SSWK", "SSWL", "SSWM", "SSWN", "SSWP", "SSWR", "SSWS", "SSWT", "SSWX", "SSX", "SSXB", "SSXF", "SSXK", "SSXL", "SSXM", "SSXN", "SSXP", "SSXR", "SSXS", "SSXT", "SSXW", "SSXX", "SSY", "SSYN", "SSYR", "SSYS", "SX", "SX0B", "SX0R", "SX0T", "SXB", "SXBH", "SXBL", "SXBN", "SXBR", "SXBS", "SXF", "SXFL", "SXFM", "SXFN", "SXFR", "SXFS", "SXFT", "SXHN", "SXJM", "SXK", "SXKB", "SXKF", "SXKH", "SXKK", "SXKL", "SXKN", "SXKR", "SXKS", "SXKT", "SXKX", "SXL", "SXLB", "SXLF", "SXLH", "SXLK", "SXLL", "SXLM", "SXLN", "SXLP", "SXLR", "SXLS", "SXLT", "SXLW", "SXLX", "SXM", "SXMH", "SXMK", "SXML", "SXMN", "SXMR", "SXMS", "SXN", "SXNB", "SXNF", "SXNH", "SXNJ", "SXNK", "SXNL", "SXNN", "SXNP", "SXNR", "SXNS", "SXNT", "SXP", "SXPB", "SXPF", "SXPH", "SXPK", "SXPL", "SXPM", "SXPN", "SXPR", "SXPS", "SXPT", "SXPW", "SXPY", "SXR", "SXR0", "SXRB", "SXRF", "SXRH", "SXRJ", "SXRK", "SXRL", "SXRM", "SXRN", "SXRP", "SXRR", "SXRS", "SXRT", "SXRW", "SXRX", "SXS", "SXSF", "SXSK", "SXSM", "SXSP", "SXSR", "SXSS", "SXST", "SXT", "SXTB", "SXTF", "SXTH", "SXTK", "SXTL", "SXTN", "SXTP", "SXTR", "SXTS", "SXTT", "SXTW", "SXWL", "SXWR", "SXWT", "SXXN", "SXXT", "SXYR", "T0", "T00", "T0B", "T0BB", "T0BK", "T0BL", "T0BM", "T0BN", "T0BP", "T0BR", "T0BS", "T0BT", "T0BW", "T0BX", "T0F", "T0FF", "T0FK", "T0FL", "T0FN", "T0FR", "T0FS", "T0H0", "T0HB", "T0HF", "T0HL", "T0HM", "T0HR", "T0HT", "T0HX", "T0JB", "T0JK", "T0JN", "T0JP", "T0JR", "T0JS", "T0JT", "T0K", "T0KB", "T0KF", "T0KK", "T0KL", "T0KM", "T0KN", "T0KP", "T0KR", "T0KS", "T0KT", "T0KX", "T0L", "T0L0", "T0LB", "T0LF", "T0LJ", "T0LK", "T0LM", "T0LN", "T0LP", "T0LR", "T0LS", "T0LT", "T0LX", "T0LY", "T0M", "T0MJ", "T0MK", "T0ML", "T0MN", "T0MP", "T0MR", "T0MS", "T0MT", "T0MX", "T0N", "T0NB", "T0NF", "T0NJ", "T0NK", "T0NL", "T0NM", "T0NN", "T0NP", "T0NR", "T0NS", "T0NT", "T0NW", "T0NX", "T0P", "T0PF", "T0PK", "T0PL", "T0PN", "T0PP", "T0PR", "T0PS", "T0PT", "T0PX", "T0R", "T0RB", "T0RF", "T0RH", "T0RJ", "T0RK", "T0RL", "T0RM", "T0RN", "T0RP", "T0RR", "T0RS", "T0RT", "T0RW", "T0RX", "T0RY", "T0S", "T0S0", "T0SB", "T0SF", "T0SJ", "T0SK", "T0SL", "T0SM", "T0SN", "T0SP", "T0SR", "T0SS", "T0ST", "T0SW", "T0SX", "T0T", "T0TB", "T0TF", "T0TK", "T0TL", "T0TM", "T0TN", "T0TP", "T0TR", "T0TS", "T0TT", "T0TW", "T0W", "T0WF", "T0WL", "T0WN", "T0WR", "T0WT", "T0WX", "T0X", "T0XL", "T0XM", "T0XN", "T0XP", "T0XR", "T0XS", "T0XT", "T0Y", "T0YM", "T0YN", "T0YR", "T0YX", "TT", "TT0", "TT0L", "TT0M", "TT0R", "TT0S", "TTB", "TTB0", "TTBB", "TTBF", "TTBK", "TTBL", "TTBM", "TTBN", "TTBR", "TTBS", "TTBT", "TTBX", "TTF", "TTFF", "TTFH", "TTFK", "TTFL", "TTFM", "TTFN", "TTFR", "TTFS", "TTFT", "TTFW", "TTH", "TTHL", "TTHN", "TTHR", "TTHS", "TTHT", "TTHX", "TTJ", "TTJK", "TTJL", "TTJM", "TTJN", "TTJR", "TTJS", "TTJT", "TTJW", "TTK", "TTKB", "TTKF", "TTKH", "TTKK", "TTKL", "TTKM", "TTKN", "TTKP", "TTKR", "TTKS", "TTKT", "TTKW", "TTKY", "TTL", "TTL0", "TTLB", "TTLF", "TTLH", "TTLJ", "TTLK", "TTLL", "TTLM", "TTLN", "TTLP", "TTLR", "TTLS", "TTLT", "TTLW", "TTLX", "TTLY", "TTM", "TTM0", "TTMB", "TTMF", "TTMH", "TTMJ", "TTMK", "TTML", "TTMM", "TTMN", "TTMP", "TTMR", "TTMS", "TTMT", "TTMW", "TTMX", "TTMY", "TTN", "TTN0", "TTNB", "TTNF", "TTNH", "TTNJ", "TTNK", "TTNL", "TTNM", "TTNN", "TTNP", "TTNR", "TTNS", "TTNT", "TTNW", "TTNX", "TTNY", "TTP", "TTPB", "TTPF", "TTPH", "TTPK", "TTPL", "TTPM", "TTPN", "TTPP", "TTPR", "TTPS", "TTPT", "TTPW", "TTPX", "TTPY", "TTR", "TTR0", "TTRB", "TTRF", "TTRH", "TTRJ", "TTRK", "TTRL", "TTRM", "TTRN", "TTRP", "TTRR", "TTRS", "TTRT", "TTRW", "TTRX", "TTRY", "TTS", "TTSB", "TTSF", "TTSH", "TTSK", "TTSL", "TTSM", "TTSN", "TTSP", "TTSR", "TTSS", "TTST", "TTSW", "TTSX", "TTT", "TTTB", "TTTF", "TTTH", "TTTJ", "TTTK", "TTTL", "TTTM", "TTTN", "TTTP", "TTTR", "TTTS", "TTTT", "TTTW", "TTTX", "TTTY", "TTW", "TTW0", "TTWB", "TTWF", "TTWH", "TTWK", "TTWL", "TTWM", "TTWN", "TTWP", "TTWR", "TTWS", "TTWT", "TTWW", "TTWX", "TTX", "TTXB", "TTXF", "TTXK", "TTXL", "TTXN", "TTXR", "TTXS", "TTY", "TTYB", "TTYK", "TTYL", "TTYM", "TTYN", "TTYP", "TTYR", "TTYS", "TTYT", "TX", "TXBN", "TXFL", "TXLR", "TXM", "TXML", "TXN", "TXNR", "TXPS", "TXR", "TXRL", "TXRN", "TXTK", "UU0M", "UU0R", "UU0W", "UUB", "UUBB", "UUBR", "UUFL", "UUFM", "UUFN", "UUFR", "UUFS", "UUFT", "UUK", "UUKL", "UUKM", "UUKN", "UUKR", "UUKS", "UUKX", "UUL", "UUL0", "UULB", "UULF", "UULJ", "UULK", "UULL", "UULM", "UULN", "UULP", "UULR", "UULS", "UULT", "UULW", "UULY", "UUM", "UUMF", "UUMK", "UUML", "UUMN", "UUMP", "UUMR", "UUMW", "UUN", "UUN0", "UUNF", "UUNJ", "UUNK", "UUNL", "UUNM", "UUNN", "UUNP", "UUNR", "UUNS", "UUNT", "UUNW", "UUNY", "UUP0", "UUPF", "UUPL", "UUPM", "UUPN", "UUPR", "UUPS", "UUPT", "UUPW", "UUPX", "UUR", "UURB", "UURJ", "UURK", "UURL", "UURM", "UURN", "UURP", "UURR", "UURS", "UURT", "UURW", "UURX", "UUSK", "UUSL", "UUSN", "UUSR", "UUST", "UUT", "UUTJ", "UUTK", "UUTL", "UUTN", "UUTP", "UUTR", "UUTS", "UUTY", "UUW", "UUWL", "UUWR", "UUXK", "UUXR", "VF", "VFB", "VFBL", "VFBN", "VFBR", "VFF", "VFFH", "VFFK", "VFFL", "VFFN", "VFFR", "VFFS", "VFFT", "VFFX", "VFFY", "VFHL", "VFJ", "VFJF", "VFJL", "VFJM", "VFJN", "VFJS", "VFK", "VFKB", "VFKK", "VFKL", "VFKN", "VFKR", "VFKS", "VFKT", "VFKX", "VFL", "VFL0", "VFLB", "VFLF", "VFLH", "VFLJ", "VFLK", "VFLL", "VFLM", "VFLN", "VFLP", "VFLR", "VFLS", "VFLT", "VFLW", "VFLX", "VFM", "VFMN", "VFMP", "VFMR", "VFMS", "VFMT", "VFN", "VFN0", "VFNB", "VFNF", "VFNH", "VFNJ", "VFNK", "VFNL", "VFNM", "VFNN", "VFNP", "VFNR", "VFNS", "VFNT", "VFNW", "VFNX", "VFNY", "VFP", "VFPN", "VFPR", "VFR", "VFRB", "VFRF", "VFRH", "VFRJ", "VFRK", "VFRL", "VFRM", "VFRN", "VFRP", "VFRR", "VFRS", "VFRT", "VFRW", "VFRX", "VFRY", "VFS", "VFSF", "VFSH", "VFSJ", "VFSK", "VFSL", "VFSM", "VFSN", "VFSP", "VFSR", "VFST", "VFSX", "VFSY", "VFT", "VFTB", "VFTF", "VFTH", "VFTK", "VFTL", "VFTM", "VFTN", "VFTR", "VFTS", "VFTT", "VFTX", "VFWL", "VFWT", "VFX", "VFXN", "VFXR", "VFXS", "VFY", "VFYJ", "VFYL", "W", "W0BR", "W0S", "WBLN", "WBNK", "WBR", "WBRB", "WBRN", "WBRT", "WFL", "WFLK", "WFLS", "WFLT", "WFRN", "WHTR", "WJ", "WJBL", "WJMS", "WKHM", "WKHT", "WKKS", "WKLF", "WKLS", "WKLW", "WKM", "WKMP", "WKN", "WKNT", "WKRB", "WKS", "WL", "WLB", "WLKR", "WLM", "WLMR", "WLN", "WLNT", "WLPN", "WLPR", "WLR", "WLRS", "WLS", "WLT", "WLTS", "WLTW", "WLXR", "WLY", "WM", "WMFR", "WMHF", "WMLR", "WMLT", "WMN", "WMNT", "WMR", "WMRK", "WMST", "WN", "WNBR", "WNFL", "WNFR", "WNHM", "WNJL", "WNKR", "WNKT", "WNL", "WNM", "WNMN", "WNN", "WNNT", "WNRK", "WNRL", "WNS", "WNSR", "WNST", "WNT", "WNTB", "WNTH", "WNTK", "WNTL", "WNTN", "WNTR", "WNTS", "WNTT", "WNTY", "WNWR", "WNWT", "WNY", "WNYR", "WPMP", "WPR", "WPRF", "WR", "WR0", "WR0L", "WR0M", "WR0S", "WRBR", "WRFR", "WRFT", "WRJR", "WRK", "WRKB", "WRKL", "WRKN", "WRKR", "WRKS", "WRL", "WRLF", "WRM", "WRM0", "WRMK", "WRN", "WRNF", "WRNJ", "WRNK", "WRNS", "WRNT", "WRNX", "WRP", "WRS", "WRSB", "WRST", "WRT", "WRTK", "WRTL", "WRTN", "WRTS", "WS", "WSFR", "WSLS", "WSS", "WSXL", "WTKS", "WTKT", "WTL", "WTLR", "WTN", "WTR", "WTRK", "WTTY", "WTWL", "WW", "WW0", "WW0B", "WW0K", "WW0L", "WW0M", "WW0N", "WW0R", "WW0W", "WWB", "WWBH", "WWBK", "WWBL", "WWBM", "WWBN", "WWBP", "WWBR", "WWBS", "WWBT", "WWBW", "WWBX", "WWBY", "WWF", "WWFB", "WWFH", "WWFK", "WWFL", "WWFM", "WWFN", "WWFP", "WWFR", "WWFS", "WWFT", "WWFX", "WWH", "WWHF", "WWHM", "WWHN", "WWHP", "WWHT", "WWJ", "WWJB", "WWJK", "WWJL", "WWJN", "WWJR", "WWJS", "WWJT", "WWJW", "WWK", "WWKB", "WWKF", "WWKH", "WWKK", "WWKL", "WWKM", "WWKN", "WWKP", "WWKR", "WWKS", "WWKT", "WWKW", "WWKY", "WWL", "WWL0", "WWLB", "WWLF", "WWLH", "WWLJ", "WWLK", "WWLL", "WWLM", "WWLN", "WWLP", "WWLR", "WWLS", "WWLT", "WWLW", "WWLX", "WWLY", "WWM", "WWM0", "WWMB", "WWMF", "WWMJ", "WWMK", "WWML", "WWMN", "WWMP", "WWMR", "WWMS", "WWMT", "WWMW", "WWMY", "WWN", "WWN0", "WWNB", "WWNF", "WWNH", "WWNJ", "WWNK", "WWNL", "WWNM", "WWNN", "WWNP", "WWNR", "WWNS", "WWNT", "WWNW", "WWNX", "WWNY", "WWP", "WWPB", "WWPF", "WWPH", "WWPK", "WWPL", "WWPM", "WWPN", "WWPP", "WWPR", "WWPS", "WWPT", "WWPW", "WWR", "WWR0", "WWRB", "WWRF", "WWRH", "WWRJ", "WWRK", "WWRL", "WWRM", "WWRN", "WWRP", "WWRR", "WWRS", "WWRT", "WWRW", "WWRX", "WWRY", "WWS", "WWS0", "WWSB", "WWSF", "WWSK", "WWSL", "WWSM", "WWSN", "WWSP", "WWSR", "WWSS", "WWST", "WWSW", "WWSX", "WWT", "WWT0", "WWTB", "WWTF", "WWTH", "WWTJ", "WWTK", "WWTL", "WWTM", "WWTN", "WWTP", "WWTR", "WWTS", "WWTT", "WWTW", "WWTX", "WWTY", "WWW", "WWWB", "WWWK", "WWWL", "WWWM", "WWWN", "WWWR", "WWX", "WWXB", "WWXF", "WWXH", "WWXK", "WWXL", "WWXM", "WWXN", "WWXP", "WWXR", "WWXS", "WWXT", "WWXW", "WWY", "WWYL", "WWYM", "WWYN", "WWYR", "WWYT", "WX", "WXBR", "WXKR", "WXL", "WXNK", "WXPR", "WXT", "WXTL", "WXWT", "WY", "WY0", "WYB", "WYFR", "WYK", "WYKK", "WYKT", "WYL", "WYLK", "WYLN", "WYLS", "WYLT", "WYM", "WYMB", "WYMN", "WYMP", "WYN", "WYNB", "WYNK", "WYNN", "WYNT", "WYP", "WYR", "WYRJ", "WYRM", "WYS", "WYT", "WYTF", "WYTP", "WYTR", "WYTS", "XSFR", "XSHF", "XSMS", "XSN", "XSN0", "XSNK", "XSNL", "XSNN", "XSNT", "XSRB", "Y", "YFN", "YFRT", "YFS", "YFT", "YMK", "YN", "YPRS", "YRM", "YSNT", "YST0", "YSTL", "YY", "YY0", "YY0L", "YY0N", "YY0P", "YY0R", "YYB", "YYBK", "YYBL", "YYBM", "YYBN", "YYBR", "YYBS", "YYBT", "YYFL", "YYFN", "YYFR", "YYH", "YYJK", "YYJL", "YYJN", "YYJR", "YYK", "YYKB", "YYKK", "YYKL", "YYKM", "YYKN", "YYKP", "YYKR", "YYKS", "YYKT", "YYKX", "YYL", "YYLB", "YYLF", "YYLH", "YYLJ", "YYLK", "YYLL", "YYLM", "YYLN", "YYLP", "YYLR", "YYLS", "YYLT", "YYLW", "YYLY", "YYM", "YYMB", "YYMK", "YYML", "YYMN", "YYMP", "YYMR", "YYMS", "YYMT", "YYMX", "YYMY", "YYN", "YYN0", "YYNB", "YYNF", "YYNJ", "YYNK", "YYNL", "YYNM", "YYNN", "YYNP", "YYNR", "YYNS", "YYNT", "YYNW", "YYNX", "YYNY", "YYP", "YYPK", "YYPL", "YYPN", "YYPR", "YYPS", "YYPT", "YYR", "YYRB", "YYRF", "YYRH", "YYRJ", "YYRK", "YYRL", "YYRM", "YYRN", "YYRP", "YYRR", "YYRS", "YYRT", "YYRW", "YYRX", "YYRY", "YYS", "YYSB", "YYSF", "YYSK", "YYSM", "YYSN", "YYSP", "YYSR", "YYST", "YYSW", "YYT", "YYTB", "YYTF", "YYTJ", "YYTK", "YYTL", "YYTM", "YYTN", "YYTP", "YYTR", "YYTS", "YYTY", "YYW", "YYWK", "YYWL", "YYWN", "YYWP", "YYWR", "YYX", "YYXT", "YYY", "YYYH", "YYYK", "YYYN", "YYYT", "ZS", "ZSB", "ZSBK", "ZSBL", "ZSBN", "ZSBR", "ZSF", "ZSFL", "ZSFN", "ZSFR", "ZSFS", "ZSFT", "ZSH", "ZSHL", "ZSHN", "ZSHR", "ZSJL", "ZSJN", "ZSK", "ZSKF", "ZSKH", "ZSKK", "ZSKL", "ZSKN", "ZSKR", "ZSKS", "ZSKW", "ZSKX", "ZSL", "ZSLB", "ZSLF", "ZSLK", "ZSLM", "ZSLN", "ZSLR", "ZSLS", "ZSLT", "ZSM", "ZSML", "ZSMN", "ZSMP", "ZSMR", "ZSMS", "ZSMT", "ZSN", "ZSN0", "ZSNB", "ZSNF", "ZSNJ", "ZSNK", "ZSNL", "ZSNN", "ZSNR", "ZSNS", "ZSNT", "ZSP", "ZSPF", "ZSPK", "ZSPL", "ZSPN", "ZSPP", "ZSPS", "ZSR", "ZSRB", "ZSRF", "ZSRK", "ZSRL", "ZSRM", "ZSRN", "ZSRS", "ZSRT", "ZSRX", "ZSS", "ZSSM", "ZSSN", "ZSSS", "ZSST", "ZSSX", "ZST", "ZSTK", "ZSTL", "ZSTN", "ZSTP", "ZSTR", "ZSTS", "ZSTT", "ZSTX", "ZSWK", "ZSWR", "ZSWS", "ZSX", "ZSXN", "ZSXR", "ZSXS", "ZSY"]; - } - }); - - // src/geocode.ts - var geocode_exports = {}; - __export(geocode_exports, { - default: () => geocode - }); - - // node_modules/minisearch/dist/es5m/index.js - var __assign = function() { - __assign = Object.assign || function __assign2(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - }; - function __values(o) { - var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; - if (m) - return m.call(o); - if (o && typeof o.length === "number") - return { - next: function() { - if (o && i >= o.length) - o = void 0; - return { value: o && o[i++], done: !o }; - } - }; - throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); - } - function __read(o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) - return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) - ar.push(r.value); - } catch (error) { - e = { error }; - } finally { - try { - if (r && !r.done && (m = i["return"])) - m.call(i); - } finally { - if (e) - throw e.error; - } - } - return ar; - } - function __spreadArray(to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) - ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - } - var ENTRIES = "ENTRIES"; - var KEYS = "KEYS"; - var VALUES = "VALUES"; - var LEAF = ""; - var TreeIterator = function() { - function TreeIterator2(set, type) { - var node = set._tree; - var keys = Object.keys(node); - this.set = set; - this._type = type; - this._path = keys.length > 0 ? [{ node, keys }] : []; - } - TreeIterator2.prototype.next = function() { - var value = this.dive(); - this.backtrack(); - return value; - }; - TreeIterator2.prototype.dive = function() { - if (this._path.length === 0) { - return { done: true, value: void 0 }; - } - var _a2 = last$1(this._path), node = _a2.node, keys = _a2.keys; - if (last$1(keys) === LEAF) { - return { done: false, value: this.result() }; - } - this._path.push({ node: node[last$1(keys)], keys: Object.keys(node[last$1(keys)]) }); - return this.dive(); - }; - TreeIterator2.prototype.backtrack = function() { - if (this._path.length === 0) { - return; - } - last$1(this._path).keys.pop(); - if (last$1(this._path).keys.length > 0) { - return; - } - this._path.pop(); - this.backtrack(); - }; - TreeIterator2.prototype.key = function() { - return this.set._prefix + this._path.map(function(_a2) { - var keys = _a2.keys; - return last$1(keys); - }).filter(function(key) { - return key !== LEAF; - }).join(""); - }; - TreeIterator2.prototype.value = function() { - return last$1(this._path).node[LEAF]; - }; - TreeIterator2.prototype.result = function() { - if (this._type === VALUES) { - return this.value(); - } - if (this._type === KEYS) { - return this.key(); - } - return [this.key(), this.value()]; - }; - TreeIterator2.prototype[Symbol.iterator] = function() { - return this; - }; - return TreeIterator2; - }(); - var last$1 = function(array) { - return array[array.length - 1]; - }; - var NONE = 0; - var CHANGE = 1; - var ADD = 2; - var DELETE = 3; - var fuzzySearch = function(node, query, maxDistance) { - var stack = [{ distance: 0, i: 0, key: "", node }]; - var results = {}; - var innerStack = []; - var _loop_1 = function() { - var _a2 = stack.pop(), node_1 = _a2.node, distance = _a2.distance, key = _a2.key, i = _a2.i, edit = _a2.edit; - Object.keys(node_1).forEach(function(k) { - if (k === LEAF) { - var totDistance = distance + (query.length - i); - var _a3 = __read(results[key] || [null, Infinity], 2), d = _a3[1]; - if (totDistance <= maxDistance && totDistance < d) { - results[key] = [node_1[k], totDistance]; - } - } else { - withinDistance(query, k, maxDistance - distance, i, edit, innerStack).forEach(function(_a4) { - var d2 = _a4.distance, i2 = _a4.i, edit2 = _a4.edit; - stack.push({ node: node_1[k], distance: distance + d2, key: key + k, i: i2, edit: edit2 }); - }); - } - }); - }; - while (stack.length > 0) { - _loop_1(); - } - return results; - }; - var withinDistance = function(a, b, maxDistance, i, edit, stack) { - stack.push({ distance: 0, ia: i, ib: 0, edit }); - var results = []; - while (stack.length > 0) { - var _a2 = stack.pop(), distance = _a2.distance, ia = _a2.ia, ib = _a2.ib, edit_1 = _a2.edit; - if (ib === b.length) { - results.push({ distance, i: ia, edit: edit_1 }); - continue; - } - if (a[ia] === b[ib]) { - stack.push({ distance, ia: ia + 1, ib: ib + 1, edit: NONE }); - } else { - if (distance >= maxDistance) { - continue; - } - if (edit_1 !== ADD) { - stack.push({ distance: distance + 1, ia, ib: ib + 1, edit: DELETE }); - } - if (ia < a.length) { - if (edit_1 !== DELETE) { - stack.push({ distance: distance + 1, ia: ia + 1, ib, edit: ADD }); - } - if (edit_1 !== DELETE && edit_1 !== ADD) { - stack.push({ distance: distance + 1, ia: ia + 1, ib: ib + 1, edit: CHANGE }); - } - } - } - } - return results; - }; - var SearchableMap = function() { - function SearchableMap2(tree, prefix) { - if (tree === void 0) { - tree = {}; - } - if (prefix === void 0) { - prefix = ""; - } - this._tree = tree; - this._prefix = prefix; - } - SearchableMap2.prototype.atPrefix = function(prefix) { - var _a2; - if (!prefix.startsWith(this._prefix)) { - throw new Error("Mismatched prefix"); - } - var _b = __read(trackDown(this._tree, prefix.slice(this._prefix.length)), 2), node = _b[0], path = _b[1]; - if (node === void 0) { - var _c = __read(last(path), 2), parentNode = _c[0], key_1 = _c[1]; - var nodeKey = Object.keys(parentNode).find(function(k) { - return k !== LEAF && k.startsWith(key_1); - }); - if (nodeKey !== void 0) { - return new SearchableMap2((_a2 = {}, _a2[nodeKey.slice(key_1.length)] = parentNode[nodeKey], _a2), prefix); - } - } - return new SearchableMap2(node || {}, prefix); - }; - SearchableMap2.prototype.clear = function() { - delete this._size; - this._tree = {}; - }; - SearchableMap2.prototype.delete = function(key) { - delete this._size; - return remove(this._tree, key); - }; - SearchableMap2.prototype.entries = function() { - return new TreeIterator(this, ENTRIES); - }; - SearchableMap2.prototype.forEach = function(fn) { - var e_1, _a2; - try { - for (var _b = __values(this), _c = _b.next(); !_c.done; _c = _b.next()) { - var _d = __read(_c.value, 2), key = _d[0], value = _d[1]; - fn(key, value, this); - } - } catch (e_1_1) { - e_1 = { error: e_1_1 }; - } finally { - try { - if (_c && !_c.done && (_a2 = _b.return)) - _a2.call(_b); - } finally { - if (e_1) - throw e_1.error; - } - } - }; - SearchableMap2.prototype.fuzzyGet = function(key, maxEditDistance) { - return fuzzySearch(this._tree, key, maxEditDistance); - }; - SearchableMap2.prototype.get = function(key) { - var node = lookup(this._tree, key); - return node !== void 0 ? node[LEAF] : void 0; - }; - SearchableMap2.prototype.has = function(key) { - var node = lookup(this._tree, key); - return node !== void 0 && node.hasOwnProperty(LEAF); - }; - SearchableMap2.prototype.keys = function() { - return new TreeIterator(this, KEYS); - }; - SearchableMap2.prototype.set = function(key, value) { - if (typeof key !== "string") { - throw new Error("key must be a string"); - } - delete this._size; - var node = createPath(this._tree, key); - node[LEAF] = value; - return this; - }; - Object.defineProperty(SearchableMap2.prototype, "size", { - get: function() { - var _this = this; - if (this._size) { - return this._size; - } - this._size = 0; - this.forEach(function() { - _this._size += 1; - }); - return this._size; - }, - enumerable: false, - configurable: true - }); - SearchableMap2.prototype.update = function(key, fn) { - if (typeof key !== "string") { - throw new Error("key must be a string"); - } - delete this._size; - var node = createPath(this._tree, key); - node[LEAF] = fn(node[LEAF]); - return this; - }; - SearchableMap2.prototype.values = function() { - return new TreeIterator(this, VALUES); - }; - SearchableMap2.prototype[Symbol.iterator] = function() { - return this.entries(); - }; - SearchableMap2.from = function(entries) { - var e_2, _a2; - var tree = new SearchableMap2(); - try { - for (var entries_1 = __values(entries), entries_1_1 = entries_1.next(); !entries_1_1.done; entries_1_1 = entries_1.next()) { - var _b = __read(entries_1_1.value, 2), key = _b[0], value = _b[1]; - tree.set(key, value); - } - } catch (e_2_1) { - e_2 = { error: e_2_1 }; - } finally { - try { - if (entries_1_1 && !entries_1_1.done && (_a2 = entries_1.return)) - _a2.call(entries_1); - } finally { - if (e_2) - throw e_2.error; - } - } - return tree; - }; - SearchableMap2.fromObject = function(object) { - return SearchableMap2.from(Object.entries(object)); - }; - return SearchableMap2; - }(); - var trackDown = function(tree, key, path) { - if (path === void 0) { - path = []; - } - if (key.length === 0 || tree == null) { - return [tree, path]; - } - var nodeKey = Object.keys(tree).find(function(k) { - return k !== LEAF && key.startsWith(k); - }); - if (nodeKey === void 0) { - path.push([tree, key]); - return trackDown(void 0, "", path); - } - path.push([tree, nodeKey]); - return trackDown(tree[nodeKey], key.slice(nodeKey.length), path); - }; - var lookup = function(tree, key) { - if (key.length === 0 || tree == null) { - return tree; - } - var nodeKey = Object.keys(tree).find(function(k) { - return k !== LEAF && key.startsWith(k); - }); - if (nodeKey === void 0) { - return void 0; - } - return lookup(tree[nodeKey], key.slice(nodeKey.length)); - }; - var createPath = function(tree, key) { - var _a2; - if (key.length === 0 || tree == null) { - return tree; - } - var nodeKey = Object.keys(tree).find(function(k) { - return k !== LEAF && key.startsWith(k); - }); - if (nodeKey === void 0) { - var toSplit = Object.keys(tree).find(function(k) { - return k !== LEAF && k.startsWith(key[0]); - }); - if (toSplit === void 0) { - tree[key] = {}; - } else { - var prefix = commonPrefix(key, toSplit); - tree[prefix] = (_a2 = {}, _a2[toSplit.slice(prefix.length)] = tree[toSplit], _a2); - delete tree[toSplit]; - return createPath(tree[prefix], key.slice(prefix.length)); - } - return tree[key]; - } - return createPath(tree[nodeKey], key.slice(nodeKey.length)); - }; - var commonPrefix = function(a, b, i, length, prefix) { - if (i === void 0) { - i = 0; - } - if (length === void 0) { - length = Math.min(a.length, b.length); - } - if (prefix === void 0) { - prefix = ""; - } - if (i >= length) { - return prefix; - } - if (a[i] !== b[i]) { - return prefix; - } - return commonPrefix(a, b, i + 1, length, prefix + a[i]); - }; - var remove = function(tree, key) { - var _a2 = __read(trackDown(tree, key), 2), node = _a2[0], path = _a2[1]; - if (node === void 0) { - return; - } - delete node[LEAF]; - var keys = Object.keys(node); - if (keys.length === 0) { - cleanup(path); - } - if (keys.length === 1) { - merge(path, keys[0], node[keys[0]]); - } - }; - var cleanup = function(path) { - if (path.length === 0) { - return; - } - var _a2 = __read(last(path), 2), node = _a2[0], key = _a2[1]; - delete node[key]; - var keys = Object.keys(node); - if (keys.length === 0) { - cleanup(path.slice(0, -1)); - } - if (keys.length === 1 && keys[0] !== LEAF) { - merge(path.slice(0, -1), keys[0], node[keys[0]]); - } - }; - var merge = function(path, key, value) { - if (path.length === 0) { - return; - } - var _a2 = __read(last(path), 2), node = _a2[0], nodeKey = _a2[1]; - node[nodeKey + key] = value; - delete node[nodeKey]; - }; - var last = function(array) { - return array[array.length - 1]; - }; - var _a; - var OR = "or"; - var AND = "and"; - var AND_NOT = "and_not"; - var MiniSearch = function() { - function MiniSearch2(options) { - if ((options === null || options === void 0 ? void 0 : options.fields) == null) { - throw new Error('MiniSearch: option "fields" must be provided'); - } - this._options = __assign(__assign(__assign({}, defaultOptions), options), { searchOptions: __assign(__assign({}, defaultSearchOptions), options.searchOptions || {}) }); - this._index = new SearchableMap(); - this._documentCount = 0; - this._documentIds = {}; - this._fieldIds = {}; - this._fieldLength = {}; - this._averageFieldLength = {}; - this._nextId = 0; - this._storedFields = {}; - this.addFields(this._options.fields); - } - MiniSearch2.prototype.add = function(document) { - var _this = this; - var _a2 = this._options, extractField = _a2.extractField, tokenize = _a2.tokenize, processTerm = _a2.processTerm, fields = _a2.fields, idField = _a2.idField; - var id = extractField(document, idField); - if (id == null) { - throw new Error('MiniSearch: document does not have ID field "'.concat(idField, '"')); - } - var shortDocumentId = this.addDocumentId(id); - this.saveStoredFields(shortDocumentId, document); - fields.forEach(function(field) { - var fieldValue = extractField(document, field); - if (fieldValue == null) { - return; - } - var tokens = tokenize(fieldValue.toString(), field); - _this.addFieldLength(shortDocumentId, _this._fieldIds[field], _this.documentCount - 1, tokens.length); - tokens.forEach(function(term) { - var processedTerm = processTerm(term, field); - if (processedTerm) { - _this.addTerm(_this._fieldIds[field], shortDocumentId, processedTerm); - } - }); - }); - }; - MiniSearch2.prototype.addAll = function(documents) { - var _this = this; - documents.forEach(function(document) { - return _this.add(document); - }); - }; - MiniSearch2.prototype.addAllAsync = function(documents, options) { - var _this = this; - if (options === void 0) { - options = {}; - } - var _a2 = options.chunkSize, chunkSize = _a2 === void 0 ? 10 : _a2; - var acc = { chunk: [], promise: Promise.resolve() }; - var _b = documents.reduce(function(_a3, document, i) { - var chunk2 = _a3.chunk, promise2 = _a3.promise; - chunk2.push(document); - if ((i + 1) % chunkSize === 0) { - return { - chunk: [], - promise: promise2.then(function() { - return new Promise(function(resolve) { - return setTimeout(resolve, 0); - }); - }).then(function() { - return _this.addAll(chunk2); - }) - }; - } else { - return { chunk: chunk2, promise: promise2 }; - } - }, acc), chunk = _b.chunk, promise = _b.promise; - return promise.then(function() { - return _this.addAll(chunk); - }); - }; - MiniSearch2.prototype.remove = function(document) { - var _this = this; - var _a2 = this._options, tokenize = _a2.tokenize, processTerm = _a2.processTerm, extractField = _a2.extractField, fields = _a2.fields, idField = _a2.idField; - var id = extractField(document, idField); - if (id == null) { - throw new Error('MiniSearch: document does not have ID field "'.concat(idField, '"')); - } - var _b = __read(Object.entries(this._documentIds).find(function(_a3) { - var _b2 = __read(_a3, 2); - _b2[0]; - var longId = _b2[1]; - return id === longId; - }) || [], 1), shortDocumentId = _b[0]; - if (shortDocumentId == null) { - throw new Error("MiniSearch: cannot remove document with ID ".concat(id, ": it is not in the index")); - } - fields.forEach(function(field) { - var fieldValue = extractField(document, field); - if (fieldValue == null) { - return; - } - var tokens = tokenize(fieldValue.toString(), field); - tokens.forEach(function(term) { - var processedTerm = processTerm(term, field); - if (processedTerm) { - _this.removeTerm(_this._fieldIds[field], shortDocumentId, processedTerm); - } - }); - _this.removeFieldLength(shortDocumentId, _this._fieldIds[field], _this.documentCount, tokens.length); - }); - delete this._storedFields[shortDocumentId]; - delete this._documentIds[shortDocumentId]; - delete this._fieldLength[shortDocumentId]; - this._documentCount -= 1; - }; - MiniSearch2.prototype.removeAll = function(documents) { - var _this = this; - if (documents) { - documents.forEach(function(document) { - return _this.remove(document); - }); - } else if (arguments.length > 0) { - throw new Error("Expected documents to be present. Omit the argument to remove all documents."); - } else { - this._index = new SearchableMap(); - this._documentCount = 0; - this._documentIds = {}; - this._fieldLength = {}; - this._averageFieldLength = {}; - this._storedFields = {}; - this._nextId = 0; - } - }; - MiniSearch2.prototype.search = function(query, searchOptions) { - var _this = this; - if (searchOptions === void 0) { - searchOptions = {}; - } - var combinedResults = this.executeQuery(query, searchOptions); - return Object.entries(combinedResults).reduce(function(results, _a2) { - var _b = __read(_a2, 2), docId = _b[0], _c = _b[1], score2 = _c.score, match = _c.match, terms = _c.terms; - var result = { - id: _this._documentIds[docId], - terms: uniq(terms), - score: score2, - match - }; - Object.assign(result, _this._storedFields[docId]); - if (searchOptions.filter == null || searchOptions.filter(result)) { - results.push(result); - } - return results; - }, []).sort(function(_a2, _b) { - var a = _a2.score; - var b = _b.score; - return a < b ? 1 : -1; - }); - }; - MiniSearch2.prototype.autoSuggest = function(queryString, options) { - if (options === void 0) { - options = {}; - } - options = __assign(__assign({}, defaultAutoSuggestOptions), options); - var suggestions = this.search(queryString, options).reduce(function(suggestions2, _a2) { - var score2 = _a2.score, terms = _a2.terms; - var phrase = terms.join(" "); - if (suggestions2[phrase] == null) { - suggestions2[phrase] = { score: score2, terms, count: 1 }; - } else { - suggestions2[phrase].score += score2; - suggestions2[phrase].count += 1; - } - return suggestions2; - }, {}); - return Object.entries(suggestions).map(function(_a2) { - var _b = __read(_a2, 2), suggestion = _b[0], _c = _b[1], score2 = _c.score, terms = _c.terms, count = _c.count; - return { suggestion, terms, score: score2 / count }; - }).sort(function(_a2, _b) { - var a = _a2.score; - var b = _b.score; - return a < b ? 1 : -1; - }); - }; - Object.defineProperty(MiniSearch2.prototype, "documentCount", { - get: function() { - return this._documentCount; - }, - enumerable: false, - configurable: true - }); - MiniSearch2.loadJSON = function(json, options) { - if (options == null) { - throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index"); - } - return MiniSearch2.loadJS(JSON.parse(json), options); - }; - MiniSearch2.getDefault = function(optionName) { - if (defaultOptions.hasOwnProperty(optionName)) { - return getOwnProperty(defaultOptions, optionName); - } else { - throw new Error('MiniSearch: unknown option "'.concat(optionName, '"')); - } - }; - MiniSearch2.loadJS = function(js, options) { - var index = js.index, documentCount = js.documentCount, nextId = js.nextId, documentIds = js.documentIds, fieldIds = js.fieldIds, fieldLength = js.fieldLength, averageFieldLength = js.averageFieldLength, storedFields = js.storedFields; - var miniSearch2 = new MiniSearch2(options); - miniSearch2._index = new SearchableMap(index._tree, index._prefix); - miniSearch2._documentCount = documentCount; - miniSearch2._nextId = nextId; - miniSearch2._documentIds = documentIds; - miniSearch2._fieldIds = fieldIds; - miniSearch2._fieldLength = fieldLength; - miniSearch2._averageFieldLength = averageFieldLength; - miniSearch2._fieldIds = fieldIds; - miniSearch2._storedFields = storedFields || {}; - return miniSearch2; - }; - MiniSearch2.prototype.executeQuery = function(query, searchOptions) { - var _this = this; - if (searchOptions === void 0) { - searchOptions = {}; - } - if (typeof query === "string") { - return this.executeSearch(query, searchOptions); - } else { - var results = query.queries.map(function(subquery) { - var options = __assign(__assign(__assign({}, searchOptions), query), { queries: void 0 }); - return _this.executeQuery(subquery, options); - }); - return this.combineResults(results, query.combineWith); - } - }; - MiniSearch2.prototype.executeSearch = function(queryString, searchOptions) { - var _this = this; - if (searchOptions === void 0) { - searchOptions = {}; - } - var _a2 = this._options, tokenize = _a2.tokenize, processTerm = _a2.processTerm, globalSearchOptions = _a2.searchOptions; - var options = __assign(__assign({ tokenize, processTerm }, globalSearchOptions), searchOptions); - var searchTokenize = options.tokenize, searchProcessTerm = options.processTerm; - var terms = searchTokenize(queryString).map(function(term) { - return searchProcessTerm(term); - }).filter(function(term) { - return !!term; - }); - var queries = terms.map(termToQuerySpec(options)); - var results = queries.map(function(query) { - return _this.executeQuerySpec(query, options); - }); - return this.combineResults(results, options.combineWith); - }; - MiniSearch2.prototype.executeQuerySpec = function(query, searchOptions) { - var _this = this; - var options = __assign(__assign({}, this._options.searchOptions), searchOptions); - var boosts = (options.fields || this._options.fields).reduce(function(boosts2, field) { - var _a3; - return __assign(__assign({}, boosts2), (_a3 = {}, _a3[field] = getOwnProperty(boosts2, field) || 1, _a3)); - }, options.boost || {}); - var boostDocument = options.boostDocument, weights = options.weights, maxFuzzy = options.maxFuzzy; - var _a2 = __assign(__assign({}, defaultSearchOptions.weights), weights), fuzzyWeight = _a2.fuzzy, prefixWeight = _a2.prefix; - var exactMatch = this.termResults(query.term, boosts, boostDocument, this._index.get(query.term)); - if (!query.fuzzy && !query.prefix) { - return exactMatch; - } - var results = [exactMatch]; - if (query.prefix) { - this._index.atPrefix(query.term).forEach(function(term, data) { - var weightedDistance = 0.3 * (term.length - query.term.length) / term.length; - results.push(_this.termResults(term, boosts, boostDocument, data, prefixWeight, weightedDistance)); - }); - } - if (query.fuzzy) { - var fuzzy = query.fuzzy === true ? 0.2 : query.fuzzy; - var maxDistance = fuzzy < 1 ? Math.min(maxFuzzy, Math.round(query.term.length * fuzzy)) : fuzzy; - Object.entries(this._index.fuzzyGet(query.term, maxDistance)).forEach(function(_a3) { - var _b = __read(_a3, 2), term = _b[0], _c = __read(_b[1], 2), data = _c[0], distance = _c[1]; - var weightedDistance = distance / term.length; - results.push(_this.termResults(term, boosts, boostDocument, data, fuzzyWeight, weightedDistance)); - }); - } - return results.reduce(combinators[OR]); - }; - MiniSearch2.prototype.combineResults = function(results, combineWith) { - if (combineWith === void 0) { - combineWith = OR; - } - if (results.length === 0) { - return {}; - } - var operator = combineWith.toLowerCase(); - return results.reduce(combinators[operator]) || {}; - }; - MiniSearch2.prototype.toJSON = function() { - return { - index: this._index, - documentCount: this._documentCount, - nextId: this._nextId, - documentIds: this._documentIds, - fieldIds: this._fieldIds, - fieldLength: this._fieldLength, - averageFieldLength: this._averageFieldLength, - storedFields: this._storedFields - }; - }; - MiniSearch2.prototype.termResults = function(term, boosts, boostDocument, indexData, weight, editDistance) { - var _this = this; - if (editDistance === void 0) { - editDistance = 0; - } - if (indexData == null) { - return {}; - } - return Object.entries(boosts).reduce(function(results, _a2) { - var _b = __read(_a2, 2), field = _b[0], boost = _b[1]; - var fieldId = _this._fieldIds[field]; - var _c = indexData[fieldId] || { ds: {} }, df = _c.df, ds = _c.ds; - Object.entries(ds).forEach(function(_a3) { - var _b2 = __read(_a3, 2), documentId = _b2[0], tf = _b2[1]; - var docBoost = boostDocument ? boostDocument(_this._documentIds[documentId], term) : 1; - if (!docBoost) { - return; - } - var normalizedLength = _this._fieldLength[documentId][fieldId] / _this._averageFieldLength[fieldId]; - results[documentId] = results[documentId] || { score: 0, match: {}, terms: [] }; - results[documentId].terms.push(term); - results[documentId].match[term] = getOwnProperty(results[documentId].match, term) || []; - results[documentId].score += docBoost * score(tf, df, _this._documentCount, normalizedLength, boost, editDistance); - results[documentId].match[term].push(field); - }); - return results; - }, {}); - }; - MiniSearch2.prototype.addTerm = function(fieldId, documentId, term) { - this._index.update(term, function(indexData) { - var _a2; - indexData = indexData || {}; - var fieldIndex = indexData[fieldId] || { df: 0, ds: {} }; - if (fieldIndex.ds[documentId] == null) { - fieldIndex.df += 1; - } - fieldIndex.ds[documentId] = (fieldIndex.ds[documentId] || 0) + 1; - return __assign(__assign({}, indexData), (_a2 = {}, _a2[fieldId] = fieldIndex, _a2)); - }); - }; - MiniSearch2.prototype.removeTerm = function(fieldId, documentId, term) { - var _this = this; - if (!this._index.has(term)) { - this.warnDocumentChanged(documentId, fieldId, term); - return; - } - this._index.update(term, function(indexData) { - var _a2; - var fieldIndex = indexData[fieldId]; - if (fieldIndex == null || fieldIndex.ds[documentId] == null) { - _this.warnDocumentChanged(documentId, fieldId, term); - return indexData; - } - if (fieldIndex.ds[documentId] <= 1) { - if (fieldIndex.df <= 1) { - delete indexData[fieldId]; - return indexData; - } - fieldIndex.df -= 1; - } - if (fieldIndex.ds[documentId] <= 1) { - delete fieldIndex.ds[documentId]; - return indexData; - } - fieldIndex.ds[documentId] -= 1; - return __assign(__assign({}, indexData), (_a2 = {}, _a2[fieldId] = fieldIndex, _a2)); - }); - if (Object.keys(this._index.get(term)).length === 0) { - this._index.delete(term); - } - }; - MiniSearch2.prototype.warnDocumentChanged = function(shortDocumentId, fieldId, term) { - if (console == null || console.warn == null) { - return; - } - var fieldName = Object.entries(this._fieldIds).find(function(_a2) { - var _b = __read(_a2, 2); - _b[0]; - var id = _b[1]; - return id === fieldId; - })[0]; - console.warn("MiniSearch: document with ID ".concat(this._documentIds[shortDocumentId], ' has changed before removal: term "').concat(term, '" was not present in field "').concat(fieldName, '". Removing a document after it has changed can corrupt the index!')); - }; - MiniSearch2.prototype.addDocumentId = function(documentId) { - var shortDocumentId = this._nextId.toString(36); - this._documentIds[shortDocumentId] = documentId; - this._documentCount += 1; - this._nextId += 1; - return shortDocumentId; - }; - MiniSearch2.prototype.addFields = function(fields) { - var _this = this; - fields.forEach(function(field, i) { - _this._fieldIds[field] = i; - }); - }; - MiniSearch2.prototype.addFieldLength = function(documentId, fieldId, count, length) { - this._averageFieldLength[fieldId] = this._averageFieldLength[fieldId] || 0; - var totalLength = this._averageFieldLength[fieldId] * count + length; - this._fieldLength[documentId] = this._fieldLength[documentId] || {}; - this._fieldLength[documentId][fieldId] = length; - this._averageFieldLength[fieldId] = totalLength / (count + 1); - }; - MiniSearch2.prototype.removeFieldLength = function(documentId, fieldId, count, length) { - var totalLength = this._averageFieldLength[fieldId] * count - length; - this._averageFieldLength[fieldId] = totalLength / (count - 1); - }; - MiniSearch2.prototype.saveStoredFields = function(documentId, doc) { - var _this = this; - var _a2 = this._options, storeFields = _a2.storeFields, extractField = _a2.extractField; - if (storeFields == null || storeFields.length === 0) { - return; - } - this._storedFields[documentId] = this._storedFields[documentId] || {}; - storeFields.forEach(function(fieldName) { - var fieldValue = extractField(doc, fieldName); - if (fieldValue === void 0) { - return; - } - _this._storedFields[documentId][fieldName] = fieldValue; - }); - }; - return MiniSearch2; - }(); - var getOwnProperty = function(object, property) { - return Object.prototype.hasOwnProperty.call(object, property) ? object[property] : void 0; - }; - var combinators = (_a = {}, _a[OR] = function(a, b) { - return Object.entries(b).reduce(function(combined, _a2) { - var _b; - var _c = __read(_a2, 2), documentId = _c[0], _d = _c[1], score2 = _d.score, match = _d.match, terms = _d.terms; - if (combined[documentId] == null) { - combined[documentId] = { score: score2, match, terms }; - } else { - combined[documentId].score += score2; - combined[documentId].score *= 1.5; - (_b = combined[documentId].terms).push.apply(_b, __spreadArray([], __read(terms), false)); - Object.assign(combined[documentId].match, match); - } - return combined; - }, a || {}); - }, _a[AND] = function(a, b) { - return Object.entries(b).reduce(function(combined, _a2) { - var _b = __read(_a2, 2), documentId = _b[0], _c = _b[1], score2 = _c.score, match = _c.match, terms = _c.terms; - if (a[documentId] === void 0) { - return combined; - } - combined[documentId] = combined[documentId] || {}; - combined[documentId].score = a[documentId].score + score2; - combined[documentId].match = __assign(__assign({}, a[documentId].match), match); - combined[documentId].terms = __spreadArray(__spreadArray([], __read(a[documentId].terms), false), __read(terms), false); - return combined; - }, {}); - }, _a[AND_NOT] = function(a, b) { - return Object.entries(b).reduce(function(combined, _a2) { - var _b = __read(_a2, 2), documentId = _b[0], _c = _b[1]; - _c.score; - _c.match; - _c.terms; - delete combined[documentId]; - return combined; - }, a || {}); - }, _a); - var tfIdf = function(tf, df, n) { - return tf * Math.log(n / df); - }; - var score = function(termFrequency, documentFrequency, documentCount, normalizedLength, boost, editDistance) { - var weight = boost / (1 + 0.333 * boost * editDistance); - return weight * tfIdf(termFrequency, documentFrequency, documentCount) / normalizedLength; - }; - var termToQuerySpec = function(options) { - return function(term, i, terms) { - var fuzzy = typeof options.fuzzy === "function" ? options.fuzzy(term, i, terms) : options.fuzzy || false; - var prefix = typeof options.prefix === "function" ? options.prefix(term, i, terms) : options.prefix === true; - return { term, fuzzy, prefix }; - }; - }; - var uniq = function(array) { - return array.filter(function(element, i, array2) { - return array2.indexOf(element) === i; - }); - }; - var defaultOptions = { - idField: "id", - extractField: function(document, fieldName) { - return document[fieldName]; - }, - tokenize: function(text, fieldName) { - return text.split(SPACE_OR_PUNCTUATION); - }, - processTerm: function(term, fieldName) { - return term.toLowerCase(); - }, - fields: void 0, - searchOptions: void 0, - storeFields: [] - }; - var defaultSearchOptions = { - combineWith: OR, - prefix: false, - fuzzy: false, - maxFuzzy: 6, - boost: {}, - weights: { fuzzy: 0.9, prefix: 0.75 } - }; - var defaultAutoSuggestOptions = { - prefix: function(term, i, terms) { - return i === terms.length - 1; - } - }; - var SPACE_OR_PUNCTUATION = /[\n\r -#%-*,-/:;?@[-\]_{}\u00A0\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u1680\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2000-\u200A\u2010-\u2029\u202F-\u2043\u2045-\u2051\u2053-\u205F\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u3000-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]+/u; - - // src/geocode.ts - var import_latlon_geohash = __toESM(require_latlon_geohash()); - var import_metaphone = __toESM(require_metaphone()); - var knownGroups = new Set(require_groups()); - var currentGroup = null; - var currentGroupData = null; - var fetchController = new AbortController(); - var miniSearch = new MiniSearch({ fields: ["address"] }); - var searchIndexDocuments = []; - var currentSearchIndexKey = null; - function getSearchIndexKey(group, numericWords) { - return [group, ...numericWords.sort()].join("|"); - } - function getGroup(word) { - let cleanedWord = word.toUpperCase().replace(/[^A-Z]+/g, ""); - let group = cleanedWord.substring(0, 1) + (0, import_metaphone.default)(cleanedWord).substring(0, 3); - return knownGroups.has(group) ? group : null; - } - function loadGroupData(group) { - return new Promise((resolve, reject) => { - if (group === currentGroup && currentGroupData) { - resolve(currentGroupData); - return; - } - fetchController.abort(); - fetchController = new AbortController(); - currentGroup = group; - let url = `https://www.abc.net.au/res/sites/news-projects/geocoder/data/202111/${group}.txt.gz`; - fetch(url, { signal: fetchController.signal }).then((response) => { - response.text().then((data) => { - currentGroupData = data; - resolve(data); - }); - }).catch((e) => { - if (e.name !== "AbortError") - reject(e); - }); - }); - } - function prepareSearchIndex(group, numericWords) { - return new Promise((resolve, reject) => { - let newSearchIndexKey = getSearchIndexKey(group, numericWords); - if (newSearchIndexKey === currentSearchIndexKey) { - resolve(); - return; - } - loadGroupData(group).then((data) => { - var _a2; - searchIndexDocuments = []; - let id = 0; - let lines = data.split("\n"); - for (let line of lines) { - let street; - try { - street = JSON.parse(line); - } catch { - continue; - } - let addressLines = [ - "", - "", - [street.s, street.t, street.p].join(" ") - ]; - for (let block of street.b) { - addressLines[1] = [ - block.l ? "LOT " : "", - block.m ? block.n + "-" + block.m + " " : block.n + " ", - street.a + " ", - street.r ? street.r : "", - street.x ? " " + street.x : "" - ].join(""); - addressLines[0] = (_a2 = block.a) != null ? _a2 : ""; - let address = addressLines.filter((line2) => !!line2).join(", "); - let indexThisBlock = numericWords.length === 0 || numericWords.some((w) => w === block.n || w === block.m || w === street.p); - if (indexThisBlock) { - searchIndexDocuments[id] = { - id, - address, - geohash: block.g, - numericWords: block.m ? [block.n, block.m, street.p] : [block.n, street.p] - }; - id++; - } - if (block.u && numericWords.length > 0) { - for (let unitType in block.u) { - let unitNumbers = block.u[unitType]; - if (unitType) - unitType += " "; - for (let unitNumber of unitNumbers) { - if (Array.isArray(unitNumber) && unitNumber.length === 2) { - for (let i = unitNumber[0]; i <= unitNumber[1]; i++) { - let indexThisUnit = indexThisBlock || numericWords.some((w) => w === i); - if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + i + ", " + address, - geohash: block.g, - numericWords: block.m ? [i, block.n, block.m, +street.p] : [i, block.n, +street.p] - }; - id++; - } - } - } else { - let indexThisUnit = indexThisBlock || numericWords.some((w) => w === unitNumber); - if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + unitNumber + ", " + address, - geohash: block.g, - numericWords: block.m ? [unitNumber, block.n, block.m, +street.p] : [unitNumber, block.n, +street.p] - }; - id++; - } - } - } - } - } - } - if (id > 1e4) { - break; - } - } - miniSearch.removeAll(); - miniSearch.addAll(searchIndexDocuments); - resolve(); - }).catch(reject); - }); - } - var states = /* @__PURE__ */ new Set(["NSW", "VIC", "QLD", "WA", "SA", "TAS", "ACT", "NT"]); - var prettyAddress = (address) => { - return address.toUpperCase().replace(/(^|[^A-Z])(['A-Z]+)/g, (entireMatch, separator, word) => { - let prettyWord = states.has(word) ? word : word.substring(0, 1) + word.substring(1).toLowerCase(); - return separator + prettyWord; - }); - }; - function geocode(input, options = {}) { - return new Promise((resolve, reject) => { - let startTime = Date.now(); - let cleanedInput = input.replace(/'/g, "").replace(/[^\w\d]+/g, " ").replace(/\s+/g, " ").toUpperCase(); - let words = cleanedInput.split(" ").map((word) => isFinite(+word) ? +word : word); - let numericWords = []; - let streetName = null; - for (let word of words) { - let isNumeric = typeof word === "number" || /\d/.test(word); - if (isNumeric) { - numericWords.push(word); - } else if (streetName === null && typeof word === "string" && word.length > 3 && numericWords.length > 0) { - streetName = word; - } - } - if (streetName === null) { - let firstWord = words.find((word) => typeof word === "string" && !/\d/.test(word)); - if (firstWord && typeof firstWord === "string") { - streetName = firstWord; - } - } - let result = { - results: [], - group: "", - input, - duration: 0 - }; - let group = streetName === null ? null : getGroup(streetName); - if (streetName === null || group === null) { - result.duration = Date.now() - startTime; - resolve(result); - return; - } - prepareSearchIndex(group, numericWords).then(() => { - var _a2; - let miniSearchResults = miniSearch.search(input, { - fuzzy: (term) => /\d/.test(term) ? false : 0.333, - prefix: (term) => /\d/.test(term) ? false : true, - weights: { fuzzy: 0.1, prefix: 0.5 }, - filter: numericWords.length === 0 ? void 0 : (result2) => { - let doc = searchIndexDocuments[result2.id]; - if (doc && doc.numericWords.length > 0) { - for (let inputWord of numericWords) { - for (let docWord of doc.numericWords) { - if (inputWord === docWord) { - return true; - } - } - } - } - return false; - } - }); - let highestScoreIsPositive = ((_a2 = miniSearchResults[0]) == null ? void 0 : _a2.score) > 0; - for (let miniSearchResult of miniSearchResults) { - if (miniSearchResult.score === 0 && highestScoreIsPositive) { - break; - } - let doc = searchIndexDocuments[miniSearchResult.id]; - let g = import_latlon_geohash.default.decode(doc.geohash); - result.results.push({ - address: prettyAddress(doc.address), - latitude: g.lat, - longitude: g.lon, - score: miniSearchResult.score, - id: doc.id - }); - if (result.results.length === options.limit) { - break; - } - } - result.duration = Date.now() - startTime; - resolve(result); - }).catch(reject); - }); - } - return __toCommonJS(geocode_exports); -})(); -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ +"use strict";var __GEOCODE__=(()=>{var Ge=Object.create;var J=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var Ke=Object.getOwnPropertyNames;var He=Object.getPrototypeOf,Je=Object.prototype.hasOwnProperty;var te=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Qe=(r,e)=>{for(var t in e)J(r,t,{get:e[t],enumerable:!0})},ge=(r,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ke(e))!Je.call(r,i)&&i!==t&&J(r,i,{get:()=>e[i],enumerable:!(a=Re(e,i))||a.enumerable});return r};var re=(r,e,t)=>(t=r!=null?Ge(He(r)):{},ge(e||!r||!r.__esModule?J(t,"default",{value:r,enumerable:!0}):t,r)),Ye=r=>ge(J({},"__esModule",{value:!0}),r);var Me=te((zt,Z)=>{"use strict";var M={};M.base32="0123456789bcdefghjkmnpqrstuvwxyz";M.encode=function(r,e,t){if(typeof t>"u"){for(var a=1;a<=12;a++){var i=M.encode(r,e,a),n=M.decode(i);if(n.lat==r&&n.lon==e)return i}t=12}if(r=Number(r),e=Number(e),t=Number(t),isNaN(r)||isNaN(e)||isNaN(t))throw new Error("Invalid geohash");for(var o=0,u=0,l=!0,s="",f=-90,c=90,d=-180,v=180;s.length=h?(o=o*2+1,d=h):(o=o*2,v=h)}else{var y=(f+c)/2;r>=y?(o=o*2+1,f=y):(o=o*2,c=y)}l=!l,++u==5&&(s+=M.base32.charAt(o),u=0,o=0)}return s};M.decode=function(r){var e=M.bounds(r),t=e.sw.lat,a=e.sw.lon,i=e.ne.lat,n=e.ne.lon,o=(t+i)/2,u=(a+n)/2;return o=o.toFixed(Math.floor(2-Math.log(i-t)/Math.LN10)),u=u.toFixed(Math.floor(2-Math.log(n-a)/Math.LN10)),{lat:Number(o),lon:Number(u)}};M.bounds=function(r){if(r.length===0)throw new Error("Invalid geohash");r=r.toLowerCase();for(var e=!0,t=-90,a=90,i=-180,n=180,o=0;o=0;s--){var f=l>>s&1;if(e){var c=(i+n)/2;f==1?i=c:n=c}else{var d=(t+a)/2;f==1?t=d:a=d}e=!e}}var v={sw:{lat:t,lon:i},ne:{lat:a,lon:n}};return v};M.adjacent=function(r,e){if(r=r.toLowerCase(),e=e.toLowerCase(),r.length===0)throw new Error("Invalid geohash");if("nsew".indexOf(e)==-1)throw new Error("Invalid direction");var t={n:["p0r21436x8zb9dcf5h7kjnmqesgutwvy","bc01fg45238967deuvhjyznpkmstqrwx"],s:["14365h7k9dcfesgujnmqp0r2twvyx8zb","238967debc01fg45kmstqrwxuvhjyznp"],e:["bc01fg45238967deuvhjyznpkmstqrwx","p0r21436x8zb9dcf5h7kjnmqesgutwvy"],w:["238967debc01fg45kmstqrwxuvhjyznp","14365h7k9dcfesgujnmqp0r2twvyx8zb"]},a={n:["prxz","bcfguvyz"],s:["028b","0145hjnp"],e:["bcfguvyz","prxz"],w:["0145hjnp","028b"]},i=r.slice(-1),n=r.slice(0,-1),o=r.length%2;return a[e][o].indexOf(i)!=-1&&n!==""&&(n=M.adjacent(n,e)),n+M.base32.charAt(t[e][o].indexOf(i))};M.neighbours=function(r){return{n:M.adjacent(r,"n"),ne:M.adjacent(M.adjacent(r,"n"),"e"),e:M.adjacent(r,"e"),se:M.adjacent(M.adjacent(r,"s"),"e"),s:M.adjacent(r,"s"),sw:M.adjacent(M.adjacent(r,"s"),"w"),w:M.adjacent(r,"w"),nw:M.adjacent(M.adjacent(r,"n"),"w")}};typeof Z<"u"&&Z.exports&&(Z.exports=M)});var _e=te((q,Le)=>{(function(r,e){typeof q=="object"&&typeof Le<"u"?e(q):typeof define=="function"&&define.amd?define(["exports"],e):e((r=r||self).lru_map=r.lru_map||{})})(q,function(r){let e=Symbol("newer"),t=Symbol("older");class a{constructor(s,f){typeof s!="number"&&(f=s,s=0),this.size=0,this.limit=s,this.oldest=this.newest=void 0,this._keymap=new Map,f&&(this.assign(f),s<1&&(this.limit=this.size))}_markEntryAsUsed(s){s!==this.newest&&(s[e]&&(s===this.oldest&&(this.oldest=s[e]),s[e][t]=s[t]),s[t]&&(s[t][e]=s[e]),s[e]=void 0,s[t]=this.newest,this.newest&&(this.newest[e]=s),this.newest=s)}assign(s){let f,c=this.limit||Number.MAX_VALUE;this._keymap.clear();let d=s[Symbol.iterator]();for(let v=d.next();!v.done;v=d.next()){let h=new i(v.value[0],v.value[1]);if(this._keymap.set(h.key,h),f?(f[e]=h,h[t]=f):this.oldest=h,f=h,c--==0)throw new Error("overflow")}this.newest=f,this.size=this._keymap.size}get(s){var f=this._keymap.get(s);return f?(this._markEntryAsUsed(f),f.value):void 0}set(s,f){var c=this._keymap.get(s);return c?(c.value=f,this._markEntryAsUsed(c),this):(this._keymap.set(s,c=new i(s,f)),this.newest?(this.newest[e]=c,c[t]=this.newest):this.oldest=c,this.newest=c,++this.size,this.size>this.limit&&this.shift(),this)}shift(){var s=this.oldest;if(s)return this.oldest[e]?(this.oldest=this.oldest[e],this.oldest[t]=void 0):(this.oldest=void 0,this.newest=void 0),s[e]=s[t]=void 0,this._keymap.delete(s.key),--this.size,[s.key,s.value]}find(s){let f=this._keymap.get(s);return f?f.value:void 0}has(s){return this._keymap.has(s)}delete(s){var f=this._keymap.get(s);return f?(this._keymap.delete(f.key),f[e]&&f[t]?(f[t][e]=f[e],f[e][t]=f[t]):f[e]?(f[e][t]=void 0,this.oldest=f[e]):f[t]?(f[t][e]=void 0,this.newest=f[t]):this.oldest=this.newest=void 0,this.size--,f.value):void 0}clear(){this.oldest=this.newest=void 0,this.size=0,this._keymap.clear()}keys(){return new o(this.oldest)}values(){return new u(this.oldest)}entries(){return this}[Symbol.iterator](){return new n(this.oldest)}forEach(s,f){typeof f!="object"&&(f=this);let c=this.oldest;for(;c;)s.call(f,c.value,c.key,this),c=c[e]}toJSON(){for(var s=new Array(this.size),f=0,c=this.oldest;c;)s[f++]={key:c.key,value:c.value},c=c[e];return s}toString(){for(var s="",f=this.oldest;f;)s+=String(f.key)+":"+f.value,f=f[e],f&&(s+=" < ");return s}}r.LRUMap=a;function i(l,s){this.key=l,this.value=s,this[e]=void 0,this[t]=void 0}function n(l){this.entry=l}n.prototype[Symbol.iterator]=function(){return this},n.prototype.next=function(){let l=this.entry;return l?(this.entry=l[e],{done:!1,value:[l.key,l.value]}):{done:!0,value:void 0}};function o(l){this.entry=l}o.prototype[Symbol.iterator]=function(){return this},o.prototype.next=function(){let l=this.entry;return l?(this.entry=l[e],{done:!1,value:l.key}):{done:!0,value:void 0}};function u(l){this.entry=l}u.prototype[Symbol.iterator]=function(){return this},u.prototype.next=function(){let l=this.entry;return l?(this.entry=l[e],{done:!1,value:l.value}):{done:!0,value:void 0}}})});var Ie=te((Ct,Oe)=>{"use strict";Oe.exports=ft;var G="X",lt="0";function ft(r){var e="",t=0,a,i,n,o;function u(f){e+=f}function l(f){return r.charAt(t+f).toUpperCase()}function s(f){return function(){return l(f)}}if(r=String(r||""),!r)return"";for(i=s(1),n=s(0),o=s(-1);!ye(n());){if(!n())return"";t++}switch(n()){case"A":i()==="E"?(u("E"),t+=2):(u("A"),t++);break;case"G":case"K":case"P":i()==="N"&&(u("N"),t+=2);break;case"W":i()==="R"?(u(i()),t+=2):i()==="H"?(u(n()),t+=2):X(i())&&(u("W"),t+=2);break;case"X":u("S"),t++;break;case"E":case"I":case"O":case"U":u(n()),t++;break;default:break}for(;n();){if(a=1,!ye(n())||n()===o()&&n()!=="C"){t+=a;continue}switch(n()){case"B":o()!=="M"&&u("B");break;case"C":ve(i())?i()==="I"&&l(2)==="A"?u(G):o()!=="S"&&u("S"):i()==="H"?(u(G),a++):u("K");break;case"D":i()==="G"&&ve(l(2))?(u("J"),a++):u("T");break;case"G":i()==="H"?ht(l(-3))||l(-4)==="H"||(u("F"),a++):i()==="N"?!ye(l(2))||l(2)==="E"&&l(3)==="D"||u("K"):ve(i())&&o()!=="G"?u("J"):u("K");break;case"H":X(i())&&!ct(o())&&u("H");break;case"K":o()!=="C"&&u("K");break;case"P":i()==="H"?u("F"):u("P");break;case"Q":u("K");break;case"S":i()==="I"&&(l(2)==="O"||l(2)==="A")?u(G):i()==="H"?(u(G),a++):u("S");break;case"T":i()==="I"&&(l(2)==="O"||l(2)==="A")?u(G):i()==="H"?(u(lt),a++):i()==="C"&&l(2)==="H"||u("T");break;case"V":u("F");break;case"W":X(i())&&u("W");break;case"X":u("KS");break;case"Y":X(i())&&u("Y");break;case"Z":u("S");break;case"F":case"J":case"L":case"M":case"N":case"R":u(n());break}t+=a}return e}function ht(r){return r=R(r),r==="B"||r==="D"||r==="H"}function ve(r){return r=R(r),r==="E"||r==="I"||r==="Y"}function X(r){return r=R(r),r==="A"||r==="E"||r==="I"||r==="O"||r==="U"}function ct(r){return r=R(r),r==="C"||r==="G"||r==="P"||r==="S"||r==="T"}function ye(r){var e=dt(r);return e>=65&&e<=90}function dt(r){return R(r).charCodeAt(0)}function R(r){return String(r).charAt(0).toUpperCase()}});var Ft={};Qe(Ft,{GeocodeAbortError:()=>ee,default:()=>xt,geocode:()=>Ue});var _=function(){return _=Object.assign||function(e){for(var t,a=1,i=arguments.length;a0&&n[n.length-1])&&(s[0]===6||s[0]===2)){t=0;continue}if(s[0]===3&&(!n||s[1]>n[0]&&s[1]=r.length&&(r=void 0),{value:r&&r[a++],done:!r}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function I(r,e){var t=typeof Symbol=="function"&&r[Symbol.iterator];if(!t)return r;var a=t.call(r),i,n=[],o;try{for(;(e===void 0||e-- >0)&&!(i=a.next()).done;)n.push(i.value)}catch(u){o={error:u}}finally{try{i&&!i.done&&(t=a.return)&&t.call(a)}finally{if(o)throw o.error}}return n}var Xe="ENTRIES",Ae="KEYS",Se="VALUES",V="",ne=function(){function r(e,t){var a=e._tree,i=Array.from(a.keys());this.set=e,this._type=t,this._path=i.length>0?[{node:a,keys:i}]:[]}return r.prototype.next=function(){var e=this.dive();return this.backtrack(),e},r.prototype.dive=function(){if(this._path.length===0)return{done:!0,value:void 0};var e=W(this._path),t=e.node,a=e.keys;if(W(a)===V)return{done:!1,value:this.result()};var i=t.get(W(a));return this._path.push({node:i,keys:Array.from(i.keys())}),this.dive()},r.prototype.backtrack=function(){if(this._path.length!==0){var e=W(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}},r.prototype.key=function(){return this.set._prefix+this._path.map(function(e){var t=e.keys;return W(t)}).filter(function(e){return e!==V}).join("")},r.prototype.value=function(){return W(this._path).node.get(V)},r.prototype.result=function(){switch(this._type){case Se:return this.value();case Ae:return this.key();default:return[this.key(),this.value()]}},r.prototype[Symbol.iterator]=function(){return this},r}(),W=function(r){return r[r.length-1]},$e=function(r,e,t){var a=new Map;if(e===void 0)return a;for(var i=e.length+1,n=i+t,o=new Uint8Array(n*i).fill(t+1),u=0;ut)continue e}ze(r.get(v),e,t,a,i,y,o,u+v)}}}catch(O){l={error:O}}finally{try{d&&!d.done&&(s=c.return)&&s.call(c)}finally{if(l)throw l.error}}},ie=function(){function r(e,t){e===void 0&&(e=new Map),t===void 0&&(t=""),this._size=void 0,this._tree=e,this._prefix=t}return r.prototype.atPrefix=function(e){var t,a;if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");var i=I(Y(this._tree,e.slice(this._prefix.length)),2),n=i[0],o=i[1];if(n===void 0){var u=I(ce(o),2),l=u[0],s=u[1];try{for(var f=b(l.keys()),c=f.next();!c.done;c=f.next()){var d=c.value;if(d!==V&&d.startsWith(s)){var v=new Map;return v.set(d.slice(s.length),l.get(d)),new r(v,e)}}}catch(h){t={error:h}}finally{try{c&&!c.done&&(a=f.return)&&a.call(f)}finally{if(t)throw t.error}}}return new r(n,e)},r.prototype.clear=function(){this._size=void 0,this._tree.clear()},r.prototype.delete=function(e){return this._size=void 0,et(this._tree,e)},r.prototype.entries=function(){return new ne(this,Xe)},r.prototype.forEach=function(e){var t,a;try{for(var i=b(this),n=i.next();!n.done;n=i.next()){var o=I(n.value,2),u=o[0],l=o[1];e(u,l,this)}}catch(s){t={error:s}}finally{try{n&&!n.done&&(a=i.return)&&a.call(i)}finally{if(t)throw t.error}}},r.prototype.fuzzyGet=function(e,t){return $e(this._tree,e,t)},r.prototype.get=function(e){var t=le(this._tree,e);return t!==void 0?t.get(V):void 0},r.prototype.has=function(e){var t=le(this._tree,e);return t!==void 0&&t.has(V)},r.prototype.keys=function(){return new ne(this,Ae)},r.prototype.set=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var a=ae(this._tree,e);return a.set(V,t),this},Object.defineProperty(r.prototype,"size",{get:function(){if(this._size)return this._size;this._size=0;for(var e=this.entries();!e.next().done;)this._size+=1;return this._size},enumerable:!1,configurable:!0}),r.prototype.update=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var a=ae(this._tree,e);return a.set(V,t(a.get(V))),this},r.prototype.fetch=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var a=ae(this._tree,e),i=a.get(V);return i===void 0&&a.set(V,i=t()),i},r.prototype.values=function(){return new ne(this,Se)},r.prototype[Symbol.iterator]=function(){return this.entries()},r.from=function(e){var t,a,i=new r;try{for(var n=b(e),o=n.next();!o.done;o=n.next()){var u=I(o.value,2),l=u[0],s=u[1];i.set(l,s)}}catch(f){t={error:f}}finally{try{o&&!o.done&&(a=n.return)&&a.call(n)}finally{if(t)throw t.error}}return i},r.fromObject=function(e){return r.from(Object.entries(e))},r}(),Y=function(r,e,t){var a,i;if(t===void 0&&(t=[]),e.length===0||r==null)return[r,t];try{for(var n=b(r.keys()),o=n.next();!o.done;o=n.next()){var u=o.value;if(u!==V&&e.startsWith(u))return t.push([r,u]),Y(r.get(u),e.slice(u.length),t)}}catch(l){a={error:l}}finally{try{o&&!o.done&&(i=n.return)&&i.call(n)}finally{if(a)throw a.error}}return t.push([r,e]),Y(void 0,"",t)},le=function(r,e){var t,a;if(e.length===0||r==null)return r;try{for(var i=b(r.keys()),n=i.next();!n.done;n=i.next()){var o=n.value;if(o!==V&&e.startsWith(o))return le(r.get(o),e.slice(o.length))}}catch(u){t={error:u}}finally{try{n&&!n.done&&(a=i.return)&&a.call(i)}finally{if(t)throw t.error}}},ae=function(r,e){var t,a,i=e.length;e:for(var n=0;r&&n0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new ie,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}},r.prototype.discard=function(e){var t=this,a=this._idToShortId.get(e);if(a==null)throw new Error("MiniSearch: cannot discard document with ID ".concat(e,": it is not in the index"));this._idToShortId.delete(e),this._documentIds.delete(a),this._storedFields.delete(a),(this._fieldLength.get(a)||[]).forEach(function(i,n){t.removeFieldLength(a,n,t._documentCount,i)}),this._fieldLength.delete(a),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()},r.prototype.maybeAutoVacuum=function(){if(this._options.autoVacuum!==!1){var e=this._options.autoVacuum,t=e.minDirtFactor,a=e.minDirtCount,i=e.batchSize,n=e.batchWait;this.conditionalVacuum({batchSize:i,batchWait:n},{minDirtCount:a,minDirtFactor:t})}},r.prototype.discardAll=function(e){var t,a,i=this._options.autoVacuum;try{this._options.autoVacuum=!1;try{for(var n=b(e),o=n.next();!o.done;o=n.next()){var u=o.value;this.discard(u)}}catch(l){t={error:l}}finally{try{o&&!o.done&&(a=n.return)&&a.call(n)}finally{if(t)throw t.error}}}finally{this._options.autoVacuum=i}this.maybeAutoVacuum()},r.prototype.replace=function(e){var t=this._options,a=t.idField,i=t.extractField,n=i(e,a);this.discard(n),this.add(e)},r.prototype.vacuum=function(e){return e===void 0&&(e={}),this.conditionalVacuum(e)},r.prototype.conditionalVacuum=function(e,t){var a=this;return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(function(){var i=a._enqueuedVacuumConditions;return a._enqueuedVacuumConditions=he,a.performVacuuming(e,i)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)},r.prototype.performVacuuming=function(e,t){return Ze(this,void 0,void 0,function(){var a,i,n,o,u,l,s,f,c,d,v,h,y,g,m,w,p,x,A,C,F,z,E,k,L;return qe(this,function(S){switch(S.label){case 0:if(a=this._dirtCount,!this.vacuumConditionsMet(t))return[3,10];i=e.batchSize||fe.batchSize,n=e.batchWait||fe.batchWait,o=1,S.label=1;case 1:S.trys.push([1,7,8,9]),u=b(this._index),l=u.next(),S.label=2;case 2:if(l.done)return[3,6];s=I(l.value,2),f=s[0],c=s[1];try{for(d=(z=void 0,b(c)),v=d.next();!v.done;v=d.next()){h=I(v.value,2),y=h[0],g=h[1];try{for(m=(k=void 0,b(g)),w=m.next();!w.done;w=m.next())p=I(w.value,1),x=p[0],!this._documentIds.has(x)&&(g.size<=1?c.delete(y):g.delete(x))}catch(O){k={error:O}}finally{try{w&&!w.done&&(L=m.return)&&L.call(m)}finally{if(k)throw k.error}}}}catch(O){z={error:O}}finally{try{v&&!v.done&&(E=d.return)&&E.call(d)}finally{if(z)throw z.error}}return this._index.get(f).size===0&&this._index.delete(f),o%i!==0?[3,4]:[4,new Promise(function(O){return setTimeout(O,n)})];case 3:S.sent(),S.label=4;case 4:o+=1,S.label=5;case 5:return l=u.next(),[3,2];case 6:return[3,9];case 7:return A=S.sent(),C={error:A},[3,9];case 8:try{l&&!l.done&&(F=u.return)&&F.call(u)}finally{if(C)throw C.error}return[7];case 9:this._dirtCount-=a,S.label=10;case 10:return[4,null];case 11:return S.sent(),this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null,[2]}})})},r.prototype.vacuumConditionsMet=function(e){if(e==null)return!0;var t=e.minDirtCount,a=e.minDirtFactor;return t=t||se.minDirtCount,a=a||se.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=a},Object.defineProperty(r.prototype,"isVacuuming",{get:function(){return this._currentVacuum!=null},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"dirtCount",{get:function(){return this._dirtCount},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"dirtFactor",{get:function(){return this._dirtCount/(1+this._documentCount+this._dirtCount)},enumerable:!1,configurable:!0}),r.prototype.has=function(e){return this._idToShortId.has(e)},r.prototype.search=function(e,t){var a,i;t===void 0&&(t={});var n=this.executeQuery(e,t),o=[];try{for(var u=b(n),l=u.next();!l.done;l=u.next()){var s=I(l.value,2),f=s[0],c=s[1],d=c.score,v=c.terms,h=c.match,y=v.length,g={id:this._documentIds.get(f),score:d*y,terms:Object.keys(h),match:h};Object.assign(g,this._storedFields.get(f)),(t.filter==null||t.filter(g))&&o.push(g)}}catch(m){a={error:m}}finally{try{l&&!l.done&&(i=u.return)&&i.call(u)}finally{if(a)throw a.error}}return o.sort(xe),o},r.prototype.autoSuggest=function(e,t){var a,i,n,o;t===void 0&&(t={}),t=_(_({},this._options.autoSuggestOptions),t);var u=new Map;try{for(var l=b(this.search(e,t)),s=l.next();!s.done;s=l.next()){var f=s.value,c=f.score,d=f.terms,v=d.join(" "),h=u.get(v);h!=null?(h.score+=c,h.count+=1):u.set(v,{score:c,terms:d,count:1})}}catch(A){a={error:A}}finally{try{s&&!s.done&&(i=l.return)&&i.call(l)}finally{if(a)throw a.error}}var y=[];try{for(var g=b(u),m=g.next();!m.done;m=g.next()){var w=I(m.value,2),h=w[0],p=w[1],c=p.score,d=p.terms,x=p.count;y.push({suggestion:h,terms:d,score:c/x})}}catch(A){n={error:A}}finally{try{m&&!m.done&&(o=g.return)&&o.call(g)}finally{if(n)throw n.error}}return y.sort(xe),y},Object.defineProperty(r.prototype,"documentCount",{get:function(){return this._documentCount},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"termCount",{get:function(){return this._index.size},enumerable:!1,configurable:!0}),r.loadJSON=function(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)},r.getDefault=function(e){if(ue.hasOwnProperty(e))return oe(ue,e);throw new Error('MiniSearch: unknown option "'.concat(e,'"'))},r.loadJS=function(e,t){var a,i,n,o,u,l,s=e.index,f=e.documentCount,c=e.nextId,d=e.documentIds,v=e.fieldIds,h=e.fieldLength,y=e.averageFieldLength,g=e.storedFields,m=e.dirtCount,w=e.serializationVersion;if(w!==1&&w!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");var p=new r(t);p._documentCount=f,p._nextId=c,p._documentIds=Q(d),p._idToShortId=new Map,p._fieldIds=v,p._fieldLength=Q(h),p._avgFieldLength=y,p._storedFields=Q(g),p._dirtCount=m||0,p._index=new ie;try{for(var x=b(p._documentIds),A=x.next();!A.done;A=x.next()){var C=I(A.value,2),F=C[0],z=C[1];p._idToShortId.set(z,F)}}catch(j){a={error:j}}finally{try{A&&!A.done&&(i=x.return)&&i.call(x)}finally{if(a)throw a.error}}try{for(var E=b(s),k=E.next();!k.done;k=E.next()){var L=I(k.value,2),S=L[0],O=L[1],D=new Map;try{for(var N=(u=void 0,b(Object.keys(O))),P=N.next();!P.done;P=N.next()){var T=P.value,B=O[T];w===1&&(B=B.ds),D.set(parseInt(T,10),Q(B))}}catch(j){u={error:j}}finally{try{P&&!P.done&&(l=N.return)&&l.call(N)}finally{if(u)throw u.error}}p._index.set(S,D)}}catch(j){n={error:j}}finally{try{k&&!k.done&&(o=E.return)&&o.call(E)}finally{if(n)throw n.error}}return p},r.prototype.executeQuery=function(e,t){var a=this;if(t===void 0&&(t={}),typeof e!="string"){var i=_(_(_({},t),e),{queries:void 0}),n=e.queries.map(function(g){return a.executeQuery(g,i)});return this.combineResults(n,e.combineWith)}var o=this._options,u=o.tokenize,l=o.processTerm,s=o.searchOptions,f=_(_({tokenize:u,processTerm:l},s),t),c=f.tokenize,d=f.processTerm,v=c(e).flatMap(function(g){return d(g)}).filter(function(g){return!!g}),h=v.map(at(f)),y=h.map(function(g){return a.executeQuerySpec(g,f)});return this.combineResults(y,f.combineWith)},r.prototype.executeQuerySpec=function(e,t){var a,i,n,o,u=_(_({},this._options.searchOptions),t),l=(u.fields||this._options.fields).reduce(function(T,B){var j;return _(_({},T),(j={},j[B]=oe(T,B)||1,j))},u.boost||{}),s=u.boostDocument,f=u.weights,c=u.maxFuzzy,d=u.bm25,v=_(_({},we.weights),f),h=v.fuzzy,y=v.prefix,g=this._index.get(e.term),m=this.termResults(e.term,e.term,1,g,l,s,d),w,p;if(e.prefix&&(w=this._index.atPrefix(e.term)),e.fuzzy){var x=e.fuzzy===!0?.2:e.fuzzy,A=x<1?Math.min(c,Math.round(e.term.length*x)):x;A&&(p=this._index.fuzzyGet(e.term,A))}if(w)try{for(var C=b(w),F=C.next();!F.done;F=C.next()){var z=I(F.value,2),E=z[0],k=z[1],L=E.length-e.term.length;if(!!L){p?.delete(E);var S=y*E.length/(E.length+.3*L);this.termResults(e.term,E,S,k,l,s,d,m)}}}catch(T){a={error:T}}finally{try{F&&!F.done&&(i=C.return)&&i.call(C)}finally{if(a)throw a.error}}if(p)try{for(var O=b(p.keys()),D=O.next();!D.done;D=O.next()){var E=D.value,N=I(p.get(E),2),P=N[0],L=N[1];if(!!L){var S=h*E.length/(E.length+L);this.termResults(e.term,E,S,P,l,s,d,m)}}}catch(T){n={error:T}}finally{try{D&&!D.done&&(o=O.return)&&o.call(O)}finally{if(n)throw n.error}}return m},r.prototype.combineResults=function(e,t){if(t===void 0&&(t=de),e.length===0)return new Map;var a=t.toLowerCase();return e.reduce(rt[a])||new Map},r.prototype.toJSON=function(){var e,t,a,i,n=[];try{for(var o=b(this._index),u=o.next();!u.done;u=o.next()){var l=I(u.value,2),s=l[0],f=l[1],c={};try{for(var d=(a=void 0,b(f)),v=d.next();!v.done;v=d.next()){var h=I(v.value,2),y=h[0],g=h[1];c[y]=Object.fromEntries(g)}}catch(m){a={error:m}}finally{try{v&&!v.done&&(i=d.return)&&i.call(d)}finally{if(a)throw a.error}}n.push([s,c])}}catch(m){e={error:m}}finally{try{u&&!u.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:n,serializationVersion:2}},r.prototype.termResults=function(e,t,a,i,n,o,u,l){var s,f,c,d,v;if(l===void 0&&(l=new Map),i==null)return l;try{for(var h=b(Object.keys(n)),y=h.next();!y.done;y=h.next()){var g=y.value,m=n[g],w=this._fieldIds[g],p=i.get(w);if(p!=null){var x=p.size,A=this._avgFieldLength[w];try{for(var C=(c=void 0,b(p.keys())),F=C.next();!F.done;F=C.next()){var z=F.value;if(!this._documentIds.has(z)){this.removeTerm(w,z,t),x-=1;continue}var E=o?o(this._documentIds.get(z),t):1;if(!!E){var k=p.get(z),L=this._fieldLength.get(z)[w],S=it(k,x,this._documentCount,L,A,u),O=a*m*E*S,D=l.get(z);if(D){D.score+=O,ut(D.terms,e);var N=oe(D.match,t);N?N.push(g):D.match[t]=[g]}else l.set(z,{score:O,terms:[e],match:(v={},v[t]=[g],v)})}}}catch(P){c={error:P}}finally{try{F&&!F.done&&(d=C.return)&&d.call(C)}finally{if(c)throw c.error}}}}}catch(P){s={error:P}}finally{try{y&&!y.done&&(f=h.return)&&f.call(h)}finally{if(s)throw s.error}}return l},r.prototype.addTerm=function(e,t,a){var i=this._index.fetch(a,Fe),n=i.get(e);if(n==null)n=new Map,n.set(t,1),i.set(e,n);else{var o=n.get(t);n.set(t,(o||0)+1)}},r.prototype.removeTerm=function(e,t,a){if(!this._index.has(a)){this.warnDocumentChanged(t,e,a);return}var i=this._index.fetch(a,Fe),n=i.get(e);n==null||n.get(t)==null?this.warnDocumentChanged(t,e,a):n.get(t)<=1?n.size<=1?i.delete(e):n.delete(t):n.set(t,n.get(t)-1),this._index.get(a).size===0&&this._index.delete(a)},r.prototype.warnDocumentChanged=function(e,t,a){var i,n;try{for(var o=b(Object.keys(this._fieldIds)),u=o.next();!u.done;u=o.next()){var l=u.value;if(this._fieldIds[l]===t){this._options.logger("warn","MiniSearch: document with ID ".concat(this._documentIds.get(e),' has changed before removal: term "').concat(a,'" was not present in field "').concat(l,'". Removing a document after it has changed can corrupt the index!'),"version_conflict");return}}}catch(s){i={error:s}}finally{try{u&&!u.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}},r.prototype.addDocumentId=function(e){var t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t},r.prototype.addFields=function(e){for(var t=0;t>>16,2246822507)^Math.imul(a^a>>>13,3266489909),a=Math.imul(a^a>>>16,2246822507)^Math.imul(t^t>>>13,3266489909),4294967296*(2097151&a)+(t>>>0)},ee=class extends Error{constructor(){super(),this.name="GeocodeAbortError"}},Be=new URL("https://www.abc.net.au/res/sites/news-projects/geocoder/data/202208/"),$;async function vt(){return $||($=(async()=>{let e=await(await fetch(new URL("groups.json.gz",Be).toString())).json();return new Set(e)})(),$)}var H=new Map,We=new WeakMap;async function yt(r){let e=H.get(r);if(e)return e;let t=new AbortController;return e=(async()=>{let a=[],n=(await fetch(new URL(`${r}.txt.gz`,Be).toString(),{signal:t.signal})).body?.getReader(),o=new TextDecoder("utf8"),u="",l=!1;for(;n&&!l;){let s=await n.read();l=s.done;let f=o.decode(s.value),c=u+f;u="";let d=c.split(` +`);for(let v=0;v{let s=[],f=await yt(o);for(let c of f){let d=c.a.replace(/[^ -\w]/g,""),v=["","",[c.s,c.t,c.p].join(" ")];for(let h of c.b){v[1]=[h.l?"LOT ":"",h.m?h.n+"-"+h.m+" ":h.n+" ",c.a+" ",c.r?c.r:"",c.x?" "+c.x:""].join(""),v[0]=h.a??"";let y=v.filter(m=>!!m).join(", "),g=e.length===0||e.some(m=>m===h.n||m===h.m||m===c.p);if(g&&s.push({id:me(y),address:y,streetName:d,geohash:h.g,numericWords:h.m?[h.n,h.m,c.p]:[h.n,c.p]}),h.u&&e.length>0)for(let m in h.u){let w=h.u[m];m&&(m+=" ");for(let p of w)if(Array.isArray(p)&&p.length===2){for(let x=p[0];x<=p[1];x++)if(g||e.some(C=>C===x)){let C=m+x+", "+y;s.push({id:me(C),address:C,streetName:d,geohash:h.g,numericWords:h.m?[x,h.n,h.m,+c.p]:[x,h.n,+c.p]})}}else if(g||e.some(A=>A===p)){let A=m+p+", "+y;s.push({id:me(A),address:A,streetName:d,geohash:h.g,numericWords:h.m?[p,h.n,h.m,+c.p]:[p,h.n,+c.p]})}}}}return s})(),Ve.set(o,l)),a.push(l)}let i=new Map,n=await Promise.all(a);for(let o of n){for(let u of o)i.set(u.id,u);if(i.size>1e4)break}return Array.from(i.values())}var wt=new Set(["NSW","VIC","QLD","WA","SA","TAS","ACT","NT"]),bt=r=>r.toUpperCase().replace(/(^|[^A-Z])(['A-Z]+)/g,(e,t,a)=>{let i=wt.has(a)?a:a.substring(0,1)+a.substring(1).toLowerCase();return t+i}),Pe="",K,Ne=new pe.LRUMap(100);async function Ue(r,e={}){let t=Date.now(),a=r.toUpperCase().replace(/[^-A-Z0-9\/,\. ]/g,"").replace(/[^A-Z0-9]+/g," ").trim(),i=Ne.get(a);if(i)return{input:r,results:i,startTime:t,duration:Date.now()-t};let n=a.split(" ").map(h=>isFinite(+h)?+h:h),o=[],u=[];n.forEach(h=>(typeof h=="number"||/\d/.test(h)?u:o).push(h));let l=new Set(u.map(h=>(typeof h=="number"?h:+h.replace(/[^\d]/g,""))%20)),s=new Set,f=await vt();for(let h of o){let y=h.substring(0,1),g=(0,je.default)(h);if(l.size>0){let m=g.substring(0,2);for(let w of l){let p=[y,w,m].join("/");f.has(p)&&s.add(p)}}else{let m=g.substring(0,3),w=[y,"_",m].join("/");f.has(w)&&s.add(w)}}let c=[...Array.from(s.values()),...u].sort().join(" ");if(!K||Pe!==c){Pe=c;let h;try{h=await gt(Array.from(s.values()),u,e.abortPrevious??!1)}catch(y){throw e.abortPrevious&&y instanceof DOMException&&y.name==="AbortError"?new ee:y}K=new De({fields:["address","streetName"],storeFields:["address","geohash"]}),h&&K.documentCount===0&&K.addAll(h)}i=[];let d=K.search(r,{fuzzy:h=>/\d/.test(h)?!1:.333,prefix:h=>!/\d/.test(h),weights:{fuzzy:.25,prefix:.5},boost:{streetName:2},maxFuzzy:4}),v=d[0]?.score>0;for(let h of d){if(h.score===0&&v)break;let y=Te.default.decode(h.geohash);if(i.push({address:bt(h.address),latitude:y.lat,longitude:y.lon,score:h.score,id:h.id}),i.length===e.limit)break}return Ne.set(a,i),{input:r,results:i,startTime:t,duration:Date.now()-t}}var xt=Ue;return Ye(Ft);})(); diff --git a/dist/geocode.js b/dist/geocode.js index ef2bb8e..ee0b4a9 100644 --- a/dist/geocode.js +++ b/dist/geocode.js @@ -1,257 +1,2 @@ -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); -var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; -}; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __reExport = (target, module2, copyDefault, desc) => { - if (module2 && typeof module2 === "object" || typeof module2 === "function") { - for (let key of __getOwnPropNames(module2)) - if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default")) - __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); - } - return target; -}; -var __toESM = (module2, isNodeMode) => { - return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", !isNodeMode && module2 && module2.__esModule ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); -}; -var __toCommonJS = /* @__PURE__ */ ((cache) => { - return (module2, temp) => { - return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp); - }; -})(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0); - -// groups.json -var require_groups = __commonJS({ - "groups.json"(exports, module2) { - module2.exports = ["1MLH", "30PR", "3LK", "4AK", "4T", "AA", "AA0B", "AA0L", "AA0N", "AA0R", "AA0S", "AAB", "AABB", "AABF", "AABH", "AABJ", "AABK", "AABL", "AABM", "AABN", "AABP", "AABR", "AABS", "AABT", "AABW", "AABY", "AAF", "AAFB", "AAFF", "AAFK", "AAFL", "AAFM", "AAFN", "AAFR", "AAFS", "AAFT", "AAFW", "AAFX", "AAHN", "AAHR", "AAJ", "AAJK", "AAJL", "AAJN", "AAJR", "AAJS", "AAJT", "AAK", "AAK0", "AAKB", "AAKF", "AAKH", "AAKK", "AAKL", "AAKM", "AAKN", "AAKP", "AAKR", "AAKS", "AAKT", "AAKW", "AAKX", "AAL", "AAL0", "AALB", "AALF", "AALH", "AALJ", "AALK", "AALL", "AALM", "AALN", "AALP", "AALR", "AALS", "AALT", "AALW", "AALX", "AALY", "AAM", "AAM0", "AAMB", "AAMF", "AAMH", "AAMJ", "AAMK", "AAML", "AAMM", "AAMN", "AAMP", "AAMR", "AAMS", "AAMT", "AAMW", "AAMX", "AAMY", "AAN", "AAN0", "AANB", "AANF", "AANH", "AANJ", "AANK", "AANL", "AANM", "AANN", "AANP", "AANR", "AANS", "AANT", "AANW", "AANX", "AANY", "AAP", "AAPJ", "AAPK", "AAPL", "AAPM", "AAPN", "AAPP", "AAPR", "AAPS", "AAPT", "AAPX", "AAR", "AAR0", "AARB", "AARF", "AARH", "AARJ", "AARK", "AARL", "AARM", "AARN", "AARP", "AARR", "AARS", "AART", "AARW", "AARX", "AARY", "AAS", "AAS0", "AASB", "AASF", "AASH", "AASK", "AASL", "AASM", "AASN", "AASP", "AASR", "AASS", "AAST", "AASW", "AASX", "AAT", "AATB", "AATF", "AATH", "AATJ", "AATK", "AATL", "AATM", "AATN", "AATP", "AATR", "AATS", "AATT", "AATW", "AATX", "AATY", "AAW", "AAWB", "AAWL", "AAWN", "AAWR", "AAWS", "AAWT", "AAX", "AAXB", "AAXF", "AAXK", "AAXL", "AAXM", "AAXN", "AAXP", "AAXR", "AAXS", "AAXT", "AAXW", "AAXY", "AAY", "AAYB", "AAYL", "AAYM", "AAYN", "AAYP", "AAYR", "AAYS", "AAYW", "AAYX", "AE0L", "AEJN", "AEJR", "AEL", "AELN", "AELS", "AEML", "AENN", "AER", "AERK", "AERL", "AERN", "AERP", "AERT", "AESP", "AESX", "BB", "BB0", "BB0B", "BB0F", "BB0K", "BB0L", "BB0M", "BB0N", "BB0P", "BB0R", "BB0S", "BB0T", "BB0W", "BB0X", "BBB", "BBBB", "BBBH", "BBBJ", "BBBK", "BBBL", "BBBM", "BBBN", "BBBR", "BBBS", "BBBT", "BBBW", "BBBX", "BBBY", "BBF", "BBFF", "BBFH", "BBFK", "BBFL", "BBFN", "BBFP", "BBFR", "BBFS", "BBFT", "BBFW", "BBFX", "BBH", "BBHF", "BBHK", "BBHL", "BBHM", "BBHN", "BBHR", "BBHS", "BBHT", "BBHW", "BBHX", "BBJ", "BBJB", "BBJJ", "BBJK", "BBJL", "BBJM", "BBJN", "BBJR", "BBJS", "BBJT", "BBJW", "BBK", "BBK0", "BBKB", "BBKF", "BBKH", "BBKJ", "BBKK", "BBKL", "BBKM", "BBKN", "BBKP", "BBKR", "BBKS", "BBKT", "BBKW", "BBKX", "BBKY", "BBL", "BBL0", "BBLB", "BBLF", "BBLH", "BBLJ", "BBLK", "BBLL", "BBLM", "BBLN", "BBLP", "BBLR", "BBLS", "BBLT", "BBLW", "BBLX", "BBLY", "BBM", "BBM0", "BBMB", "BBMF", "BBMJ", "BBMK", "BBML", "BBMM", "BBMN", "BBMP", "BBMR", "BBMS", "BBMT", "BBMW", "BBMX", "BBN", "BBN0", "BBNB", "BBNF", "BBNH", "BBNJ", "BBNK", "BBNL", "BBNM", "BBNN", "BBNP", "BBNR", "BBNS", "BBNT", "BBNW", "BBNX", "BBNY", "BBP", "BBPL", "BBPM", "BBPN", "BBPP", "BBPR", "BBPS", "BBPT", "BBPX", "BBR", "BBR0", "BBRB", "BBRF", "BBRH", "BBRJ", "BBRK", "BBRL", "BBRM", "BBRN", "BBRP", "BBRR", "BBRS", "BBRT", "BBRW", "BBRX", "BBRY", "BBS", "BBS0", "BBSB", "BBSF", "BBSH", "BBSJ", "BBSK", "BBSL", "BBSM", "BBSN", "BBSP", "BBSR", "BBSS", "BBST", "BBSW", "BBSX", "BBT", "BBT0", "BBTB", "BBTF", "BBTH", "BBTJ", "BBTK", "BBTL", "BBTM", "BBTN", "BBTP", "BBTR", "BBTS", "BBTT", "BBTW", "BBTX", "BBTY", "BBW", "BBWK", "BBWL", "BBWN", "BBWR", "BBWS", "BBWT", "BBWY", "BBX", "BBXB", "BBXF", "BBXH", "BBXK", "BBXL", "BBXM", "BBXN", "BBXP", "BBXR", "BBXS", "BBXT", "BBXW", "BBXX", "BBY", "BBY0", "BBYB", "BBYH", "BBYJ", "BBYK", "BBYL", "BBYM", "BBYN", "BBYP", "BBYR", "BBYS", "BBYT", "BBYW", "BBYY", "CK", "CK0", "CK0B", "CK0K", "CK0L", "CK0M", "CK0N", "CK0R", "CK0S", "CK0T", "CK0W", "CKB", "CKBB", "CKBF", "CKBH", "CKBJ", "CKBK", "CKBL", "CKBM", "CKBN", "CKBR", "CKBS", "CKBT", "CKBW", "CKBX", "CKBY", "CKF", "CKFB", "CKFF", "CKFH", "CKFK", "CKFL", "CKFN", "CKFP", "CKFR", "CKFS", "CKFT", "CKFX", "CKH", "CKHL", "CKHN", "CKHR", "CKHT", "CKJ", "CKJB", "CKJK", "CKJL", "CKJN", "CKJP", "CKJR", "CKJT", "CKJW", "CKK", "CKK0", "CKKB", "CKKF", "CKKH", "CKKJ", "CKKK", "CKKL", "CKKM", "CKKN", "CKKP", "CKKR", "CKKS", "CKKT", "CKKW", "CKKX", "CKKY", "CKL", "CKL0", "CKLB", "CKLF", "CKLH", "CKLJ", "CKLK", "CKLL", "CKLM", "CKLN", "CKLP", "CKLR", "CKLS", "CKLT", "CKLW", "CKLX", "CKLY", "CKM", "CKMB", "CKMF", "CKMJ", "CKMK", "CKML", "CKMM", "CKMN", "CKMP", "CKMR", "CKMS", "CKMT", "CKMW", "CKMY", "CKN", "CKN0", "CKNB", "CKNF", "CKNH", "CKNJ", "CKNK", "CKNL", "CKNM", "CKNN", "CKNP", "CKNR", "CKNS", "CKNT", "CKNW", "CKNX", "CKNY", "CKP", "CKP0", "CKPB", "CKPF", "CKPH", "CKPJ", "CKPK", "CKPL", "CKPM", "CKPN", "CKPP", "CKPR", "CKPS", "CKPT", "CKPW", "CKPX", "CKPY", "CKR", "CKR0", "CKRB", "CKRF", "CKRH", "CKRJ", "CKRK", "CKRL", "CKRM", "CKRN", "CKRP", "CKRR", "CKRS", "CKRT", "CKRW", "CKRX", "CKRY", "CKS", "CKSB", "CKSF", "CKSH", "CKSJ", "CKSK", "CKSL", "CKSM", "CKSN", "CKSP", "CKSR", "CKSS", "CKST", "CKSW", "CKSX", "CKT", "CKT0", "CKTB", "CKTF", "CKTH", "CKTJ", "CKTK", "CKTL", "CKTM", "CKTN", "CKTP", "CKTR", "CKTS", "CKTT", "CKTW", "CKTX", "CKTY", "CKW", "CKWB", "CKWL", "CKWM", "CKWN", "CKWP", "CKWR", "CKWS", "CKWT", "CKX", "CKXB", "CKXF", "CKXH", "CKXK", "CKXL", "CKXM", "CKXN", "CKXP", "CKXR", "CKXS", "CKXT", "CKXW", "CKY", "CKYB", "CKYK", "CKYL", "CKYM", "CKYN", "CKYP", "CKYR", "CKYT", "CKYY", "CS0N", "CSB", "CSBL", "CSBR", "CSBS", "CSF", "CSFK", "CSFL", "CSFN", "CSFR", "CSFS", "CSFT", "CSJ", "CSKK", "CSKL", "CSKN", "CSKS", "CSKT", "CSKW", "CSKX", "CSL", "CSLB", "CSLF", "CSLH", "CSLK", "CSLM", "CSLN", "CSLR", "CSLS", "CSLT", "CSLW", "CSLX", "CSM", "CSML", "CSMN", "CSMR", "CSMS", "CSMT", "CSN", "CSN0", "CSNB", "CSNK", "CSNL", "CSNM", "CSNR", "CSNS", "CSNT", "CSNX", "CSP", "CSPL", "CSPR", "CSR", "CSRB", "CSRF", "CSRK", "CSRL", "CSRM", "CSRN", "CSRS", "CSRT", "CSSF", "CSSK", "CSSL", "CSSN", "CSSR", "CSSS", "CSST", "CST", "CSTB", "CSTF", "CSTH", "CSTK", "CSTL", "CSTM", "CSTN", "CSTP", "CSTR", "CSTS", "CSTT", "CSTW", "CSTX", "CSXL", "CSXN", "CSY0", "CSYN", "CX", "CX0M", "CXB", "CXBH", "CXBK", "CXBL", "CXBN", "CXBR", "CXBT", "CXF", "CXFK", "CXFL", "CXFM", "CXFN", "CXFP", "CXFR", "CXFS", "CXFT", "CXHL", "CXJ", "CXJS", "CXK", "CXKB", "CXKK", "CXKL", "CXKM", "CXKN", "CXKP", "CXKR", "CXKS", "CXKT", "CXKW", "CXKX", "CXL", "CXLB", "CXLF", "CXLH", "CXLK", "CXLM", "CXLN", "CXLP", "CXLR", "CXLS", "CXLT", "CXLW", "CXLY", "CXM", "CXMK", "CXML", "CXMM", "CXMN", "CXMP", "CXMR", "CXMS", "CXN", "CXN0", "CXNB", "CXNF", "CXNH", "CXNJ", "CXNK", "CXNL", "CXNM", "CXNN", "CXNP", "CXNR", "CXNS", "CXNT", "CXNW", "CXNX", "CXP", "CXPH", "CXPL", "CXPM", "CXPN", "CXPR", "CXPS", "CXPT", "CXPW", "CXPX", "CXR", "CXR0", "CXRB", "CXRF", "CXRH", "CXRJ", "CXRK", "CXRL", "CXRM", "CXRN", "CXRP", "CXRR", "CXRS", "CXRT", "CXRW", "CXRX", "CXS", "CXSB", "CXSF", "CXSL", "CXSM", "CXSN", "CXSP", "CXSR", "CXSS", "CXST", "CXSW", "CXT", "CXTB", "CXTF", "CXTK", "CXTL", "CXTM", "CXTN", "CXTR", "CXTS", "CXTW", "CXTX", "CXWB", "CXWL", "CXWN", "CXWR", "CXX", "CXXL", "CXXM", "CXXN", "CXXR", "CXXS", "CXYN", "DT", "DT0", "DT0H", "DT0R", "DT0S", "DT0T", "DT0W", "DTB", "DTBB", "DTBF", "DTBH", "DTBJ", "DTBK", "DTBL", "DTBM", "DTBN", "DTBP", "DTBR", "DTBS", "DTBT", "DTBW", "DTBX", "DTBY", "DTF", "DTFB", "DTFF", "DTFH", "DTFJ", "DTFK", "DTFL", "DTFM", "DTFN", "DTFP", "DTFR", "DTFS", "DTFT", "DTFX", "DTH", "DTHF", "DTHJ", "DTHK", "DTHL", "DTHM", "DTHN", "DTHR", "DTHT", "DTHY", "DTJ", "DTJB", "DTJH", "DTJJ", "DTJK", "DTJL", "DTJM", "DTJN", "DTJP", "DTJR", "DTJS", "DTJT", "DTK", "DTK0", "DTKB", "DTKF", "DTKH", "DTKK", "DTKL", "DTKM", "DTKN", "DTKP", "DTKR", "DTKS", "DTKT", "DTKW", "DTKX", "DTKY", "DTL", "DTL0", "DTLB", "DTLF", "DTLH", "DTLJ", "DTLK", "DTLL", "DTLM", "DTLN", "DTLP", "DTLR", "DTLS", "DTLT", "DTLW", "DTLX", "DTLY", "DTM", "DTMB", "DTMF", "DTMJ", "DTMK", "DTML", "DTMM", "DTMN", "DTMP", "DTMR", "DTMS", "DTMT", "DTMX", "DTMY", "DTN", "DTN0", "DTNB", "DTNF", "DTNH", "DTNJ", "DTNK", "DTNL", "DTNM", "DTNN", "DTNP", "DTNR", "DTNS", "DTNT", "DTNW", "DTNX", "DTNY", "DTP", "DTPB", "DTPF", "DTPK", "DTPL", "DTPM", "DTPN", "DTPP", "DTPR", "DTPS", "DTPT", "DTPW", "DTPX", "DTR", "DTR0", "DTRB", "DTRF", "DTRH", "DTRJ", "DTRK", "DTRL", "DTRM", "DTRN", "DTRP", "DTRR", "DTRS", "DTRT", "DTRW", "DTRX", "DTRY", "DTS", "DTS0", "DTSB", "DTSF", "DTSH", "DTSK", "DTSL", "DTSM", "DTSN", "DTSP", "DTSR", "DTSS", "DTST", "DTSW", "DTSX", "DTSY", "DTT", "DTTB", "DTTF", "DTTH", "DTTK", "DTTL", "DTTM", "DTTN", "DTTP", "DTTR", "DTTS", "DTTT", "DTTW", "DTW", "DTWK", "DTWL", "DTWN", "DTWR", "DTWS", "DTWT", "DTWX", "DTX", "DTXF", "DTXL", "DTXM", "DTXN", "DTXP", "DTXR", "DTXS", "DTXT", "DTXW", "DTY", "DTYL", "DTYM", "DTYN", "DTYR", "DTYS", "DTYT", "EE", "EE0", "EE0L", "EE0M", "EE0N", "EE0R", "EE0S", "EEB", "EEBL", "EEBN", "EEBR", "EEBS", "EEBT", "EEF", "EEF0", "EEFB", "EEFF", "EEFK", "EEFL", "EEFM", "EEFN", "EEFR", "EEFS", "EEFT", "EEFW", "EEFX", "EEHL", "EEHW", "EEJ", "EEJB", "EEJF", "EEJH", "EEJK", "EEJL", "EEJM", "EEJN", "EEJP", "EEJR", "EEJS", "EEJT", "EEJW", "EEK", "EEKB", "EEKF", "EEKH", "EEKK", "EEKL", "EEKM", "EEKN", "EEKP", "EEKR", "EEKS", "EEKT", "EEKX", "EEL", "EEL0", "EELB", "EELF", "EELH", "EELJ", "EELK", "EELL", "EELM", "EELN", "EELP", "EELR", "EELS", "EELT", "EELW", "EELX", "EELY", "EEM", "EEMB", "EEMF", "EEMH", "EEMJ", "EEMK", "EEML", "EEMM", "EEMN", "EEMP", "EEMR", "EEMS", "EEMT", "EEMW", "EEN", "EENB", "EENF", "EENH", "EENJ", "EENK", "EENL", "EENM", "EENN", "EENR", "EENS", "EENT", "EENX", "EENY", "EEP", "EEPF", "EEPK", "EEPL", "EEPN", "EEPR", "EEPS", "EEPT", "EEPW", "EER", "EER0", "EERB", "EERF", "EERH", "EERJ", "EERK", "EERL", "EERM", "EERN", "EERP", "EERR", "EERS", "EERT", "EERW", "EERX", "EERY", "EES", "EES0", "EESB", "EESK", "EESL", "EESM", "EESN", "EESP", "EESR", "EESS", "EEST", "EESX", "EET", "EET0", "EETB", "EETF", "EETH", "EETJ", "EETK", "EETL", "EETM", "EETN", "EETP", "EETR", "EETS", "EETT", "EETW", "EETX", "EETY", "EEW", "EEWL", "EEWN", "EEWR", "EEWS", "EEWT", "EEX", "EEXB", "EEXF", "EEXH", "EEXK", "EEXL", "EEXM", "EEXN", "EEXP", "EEXR", "EEXT", "EEYB", "EEYN", "EEYR", "FF", "FF0", "FF0F", "FF0L", "FF0M", "FF0R", "FFB", "FFBJ", "FFBK", "FFBL", "FFBN", "FFBR", "FFBS", "FFF", "FFF0", "FFFB", "FFFF", "FFFK", "FFFL", "FFFM", "FFFN", "FFFP", "FFFR", "FFFS", "FFFT", "FFFW", "FFFX", "FFH", "FFHL", "FFHN", "FFHS", "FFHT", "FFJ", "FFJN", "FFJR", "FFK", "FFKB", "FFKF", "FFKH", "FFKK", "FFKL", "FFKM", "FFKN", "FFKR", "FFKS", "FFKT", "FFKW", "FFKX", "FFL", "FFL0", "FFLB", "FFLF", "FFLH", "FFLJ", "FFLK", "FFLL", "FFLM", "FFLN", "FFLP", "FFLR", "FFLS", "FFLT", "FFLW", "FFLX", "FFLY", "FFM", "FFMB", "FFMK", "FFML", "FFMN", "FFMP", "FFMR", "FFMS", "FFMT", "FFMX", "FFN", "FFN0", "FFNB", "FFNF", "FFNH", "FFNJ", "FFNK", "FFNL", "FFNM", "FFNN", "FFNP", "FFNR", "FFNS", "FFNT", "FFNW", "FFNX", "FFPL", "FFR", "FFR0", "FFRB", "FFRF", "FFRH", "FFRJ", "FFRK", "FFRL", "FFRM", "FFRN", "FFRP", "FFRR", "FFRS", "FFRT", "FFRW", "FFRX", "FFRY", "FFS", "FFSB", "FFSF", "FFSK", "FFSL", "FFSN", "FFSR", "FFSS", "FFST", "FFSX", "FFT", "FFTB", "FFTK", "FFTL", "FFTM", "FFTN", "FFTP", "FFTR", "FFTS", "FFTT", "FFTW", "FFTX", "FFW", "FFWL", "FFWN", "FFWS", "FFWT", "FFX", "FFXB", "FFXF", "FFXH", "FFXK", "FFXL", "FFXM", "FFXN", "FFXP", "FFXR", "FFXS", "FFXT", "FFXW", "FFXX", "FFY", "FFYB", "FFYL", "FFYN", "FFYS", "FFYT", "GFKR", "GFLF", "GFLK", "GFLN", "GFLS", "GFN", "GFNF", "GFNN", "GFNT", "GFR", "GFRK", "GFRL", "GFRN", "GFRS", "GFSL", "GFSP", "GFST", "GFTL", "GJ", "GJ0N", "GJB", "GJBH", "GJBK", "GJBL", "GJBM", "GJBN", "GJBR", "GJBS", "GJBT", "GJF", "GJFB", "GJFF", "GJFK", "GJFL", "GJFN", "GJFR", "GJFS", "GJFT", "GJFW", "GJFX", "GJH", "GJHK", "GJHM", "GJHT", "GJJ", "GJJL", "GJJN", "GJJR", "GJJS", "GJJT", "GJJY", "GJK", "GJKB", "GJKK", "GJKL", "GJKM", "GJKN", "GJKR", "GJKS", "GJL", "GJLB", "GJLF", "GJLH", "GJLJ", "GJLK", "GJLL", "GJLM", "GJLN", "GJLP", "GJLR", "GJLS", "GJLT", "GJLW", "GJLX", "GJM", "GJMB", "GJMF", "GJMH", "GJMK", "GJML", "GJMN", "GJMP", "GJMR", "GJMS", "GJMW", "GJN", "GJN0", "GJNB", "GJNF", "GJNJ", "GJNK", "GJNL", "GJNM", "GJNN", "GJNR", "GJNS", "GJNT", "GJNX", "GJP", "GJPN", "GJPR", "GJPS", "GJPT", "GJR", "GJR0", "GJRB", "GJRF", "GJRH", "GJRJ", "GJRK", "GJRL", "GJRM", "GJRN", "GJRR", "GJRS", "GJRT", "GJRW", "GJRX", "GJS", "GJSB", "GJSK", "GJSL", "GJSM", "GJSN", "GJSP", "GJSR", "GJST", "GJT", "GJTB", "GJTF", "GJTJ", "GJTL", "GJTN", "GJTP", "GJTR", "GJTS", "GJTT", "GJTW", "GJTX", "GJTY", "GJW", "GJWN", "GJX", "GJXL", "GJXM", "GJY", "GJYR", "GK", "GK0", "GK0K", "GK0L", "GK0M", "GK0N", "GK0R", "GK0S", "GK0W", "GKB", "GKBB", "GKBK", "GKBL", "GKBN", "GKBR", "GKBS", "GKBT", "GKBW", "GKBX", "GKBY", "GKF", "GKFJ", "GKFK", "GKFL", "GKFN", "GKFR", "GKFS", "GKFT", "GKHK", "GKHL", "GKHN", "GKHR", "GKJ", "GKJK", "GKJL", "GKJN", "GKJR", "GKJS", "GKJT", "GKK", "GKKK", "GKKL", "GKKM", "GKKN", "GKKP", "GKKR", "GKKS", "GKKT", "GKKX", "GKL", "GKL0", "GKLB", "GKLF", "GKLH", "GKLJ", "GKLK", "GKLL", "GKLM", "GKLN", "GKLP", "GKLR", "GKLS", "GKLT", "GKLW", "GKLX", "GKLY", "GKM", "GKMB", "GKMF", "GKMH", "GKMJ", "GKMK", "GKML", "GKMM", "GKMN", "GKMP", "GKMR", "GKMS", "GKMT", "GKMW", "GKMY", "GKN", "GKN0", "GKNB", "GKNF", "GKNH", "GKNJ", "GKNK", "GKNL", "GKNM", "GKNN", "GKNP", "GKNR", "GKNS", "GKNT", "GKNW", "GKNX", "GKNY", "GKP", "GKPB", "GKPF", "GKPH", "GKPK", "GKPL", "GKPP", "GKPR", "GKPS", "GKPW", "GKR", "GKR0", "GKRB", "GKRF", "GKRH", "GKRJ", "GKRK", "GKRL", "GKRM", "GKRN", "GKRP", "GKRR", "GKRS", "GKRT", "GKRW", "GKRX", "GKRY", "GKS", "GKS0", "GKSB", "GKSF", "GKSH", "GKSJ", "GKSK", "GKSL", "GKSM", "GKSN", "GKSP", "GKSR", "GKSS", "GKST", "GKSW", "GKSX", "GKT", "GKTB", "GKTF", "GKTH", "GKTJ", "GKTK", "GKTL", "GKTM", "GKTN", "GKTP", "GKTR", "GKTS", "GKTT", "GKTW", "GKTX", "GKTY", "GKW", "GKW0", "GKWB", "GKWL", "GKWM", "GKWN", "GKWR", "GKWT", "GKX", "GKXK", "GKXM", "GKXN", "GKXR", "GKXS", "GKY", "GKYK", "GKYM", "GKYN", "GKYR", "GKYT", "GNBR", "GNL", "GNLS", "GNLY", "GNNK", "GNNT", "GNR", "GNRB", "GNRK", "GNRL", "GNRM", "GNRN", "GNRP", "GNRW", "GNSH", "GNT", "GNTK", "GNTN", "GNWL", "GNWN", "H0", "H0RT", "HBL", "HBLS", "HBN", "HBN0", "HBNS", "HBRM", "HBRT", "HBST", "HFJL", "HFLT", "HFR", "HFRS", "HH", "HH0", "HH0B", "HH0F", "HH0H", "HH0K", "HH0L", "HH0M", "HH0N", "HH0P", "HH0R", "HH0S", "HH0T", "HH0W", "HHB", "HHBB", "HHBH", "HHBK", "HHBL", "HHBN", "HHBR", "HHBS", "HHBT", "HHBW", "HHBX", "HHBY", "HHF", "HHFB", "HHFF", "HHFH", "HHFJ", "HHFK", "HHFL", "HHFM", "HHFN", "HHFP", "HHFR", "HHFS", "HHFT", "HHFW", "HHFX", "HHH", "HHHN", "HHHR", "HHHS", "HHJ", "HHJF", "HHJL", "HHJM", "HHJN", "HHJR", "HHJS", "HHJT", "HHJW", "HHJY", "HHK", "HHKB", "HHKF", "HHKH", "HHKK", "HHKL", "HHKM", "HHKN", "HHKP", "HHKR", "HHKS", "HHKT", "HHKW", "HHKX", "HHL", "HHL0", "HHLB", "HHLF", "HHLH", "HHLJ", "HHLK", "HHLL", "HHLM", "HHLN", "HHLP", "HHLR", "HHLS", "HHLT", "HHLW", "HHLX", "HHLY", "HHM", "HHMB", "HHMF", "HHMH", "HHMJ", "HHMK", "HHML", "HHMM", "HHMN", "HHMP", "HHMR", "HHMS", "HHMT", "HHMW", "HHMX", "HHMY", "HHN", "HHN0", "HHNB", "HHNF", "HHNH", "HHNJ", "HHNK", "HHNL", "HHNM", "HHNN", "HHNP", "HHNR", "HHNS", "HHNT", "HHNW", "HHNX", "HHNY", "HHP", "HHP0", "HHPB", "HHPF", "HHPH", "HHPJ", "HHPK", "HHPL", "HHPM", "HHPN", "HHPP", "HHPR", "HHPS", "HHPT", "HHPW", "HHR", "HHR0", "HHRB", "HHRF", "HHRH", "HHRJ", "HHRK", "HHRL", "HHRM", "HHRN", "HHRP", "HHRR", "HHRS", "HHRT", "HHRW", "HHRX", "HHRY", "HHS", "HHS0", "HHSB", "HHSF", "HHSH", "HHSK", "HHSL", "HHSM", "HHSN", "HHSP", "HHSR", "HHSS", "HHST", "HHSW", "HHSX", "HHT", "HHTB", "HHTF", "HHTH", "HHTK", "HHTL", "HHTM", "HHTN", "HHTP", "HHTR", "HHTS", "HHTT", "HHTW", "HHTX", "HHTY", "HHW", "HHW0", "HHWK", "HHWL", "HHWN", "HHWR", "HHWS", "HHWT", "HHWX", "HHX", "HHXB", "HHXF", "HHXK", "HHXL", "HHXM", "HHXN", "HHXP", "HHXR", "HHXS", "HHXT", "HHXW", "HHY", "HHYK", "HHYN", "HHYR", "HHYS", "HJ", "HJR0", "HJRT", "HJT", "HKRF", "HLKL", "HLNT", "HLS", "HLTN", "HLTS", "HM0", "HMBS", "HMKS", "HMLR", "HMN", "HMNS", "HMS", "HMSB", "HMSS", "HMTS", "HMXL", "HN", "HNM", "HNMK", "HNS", "HNST", "HNTF", "HNTM", "HNTS", "HNX", "HPRN", "HPX", "HR", "HRBL", "HRM", "HRT", "HSKR", "HSLP", "HSM0", "HSN", "HSP", "HSTN", "HT", "HTBR", "HTFL", "HTHL", "HTHR", "HTKR", "HTN", "HTNL", "HTNM", "HTNN", "HTNS", "HTPR", "HTR", "HTRB", "HTRF", "HTRJ", "HTRL", "HTRN", "HTRS", "HTS", "HTSK", "HTSP", "HTTL", "HTTS", "HTWB", "HWLR", "HWLT", "HX", "HXRK", "HXRS", "HYLN", "HYM", "HYMS", "HYNT", "HYRN", "HYSN", "HYT", "HYTS", "II", "II0K", "II0M", "IIBB", "IIBK", "IIBL", "IIBR", "IIBS", "IIBT", "IIBY", "IIF", "IIF0", "IIFB", "IIFF", "IIFH", "IIFK", "IIFL", "IIFM", "IIFN", "IIFR", "IIFS", "IIFT", "IIHF", "IIJB", "IIJN", "IIJR", "IIJS", "IIK", "IIKK", "IIKL", "IIKN", "IIKR", "IIKS", "IIKT", "IIKW", "IIL", "IILB", "IILF", "IILH", "IILJ", "IILK", "IILL", "IILM", "IILN", "IILP", "IILR", "IILS", "IILT", "IILW", "IILX", "IILY", "IIM", "IIMF", "IIMH", "IIMJ", "IIMK", "IIML", "IIMN", "IIMP", "IIMR", "IIMS", "IIMT", "IIMY", "IIN", "IIN0", "IINB", "IINF", "IINH", "IINJ", "IINK", "IINL", "IINM", "IINN", "IINP", "IINR", "IINS", "IINT", "IINW", "IINX", "IINY", "IIP", "IIPL", "IIPM", "IIPN", "IIPR", "IIPS", "IIPT", "IIR", "IIRB", "IIRF", "IIRJ", "IIRK", "IIRL", "IIRM", "IIRN", "IIRP", "IIRR", "IIRS", "IIRT", "IIRW", "IIRX", "IIS", "IISB", "IISF", "IISK", "IISL", "IISM", "IISN", "IISP", "IISR", "IISS", "IIST", "IISW", "IISX", "IIT", "IITB", "IITF", "IITH", "IITJ", "IITK", "IITL", "IITM", "IITN", "IITR", "IITS", "IITT", "IITW", "IIW", "IIWN", "IIWR", "IIWS", "IIWT", "IIX", "IIXB", "IIXL", "IIXM", "IIXN", "IIXR", "IIXT", "IIYP", "JJ", "JJ0", "JJ0R", "JJ0W", "JJB", "JJBF", "JJBJ", "JJBK", "JJBL", "JJBN", "JJBR", "JJBS", "JJBT", "JJBW", "JJF", "JJFH", "JJFJ", "JJFK", "JJFL", "JJFN", "JJFR", "JJFS", "JJFX", "JJH", "JJHK", "JJHL", "JJHN", "JJHP", "JJHR", "JJHS", "JJJ", "JJJH", "JJJL", "JJJN", "JJJR", "JJJS", "JJJT", "JJK", "JJK0", "JJKB", "JJKF", "JJKH", "JJKJ", "JJKK", "JJKL", "JJKM", "JJKN", "JJKP", "JJKR", "JJKS", "JJKT", "JJKW", "JJL", "JJLB", "JJLF", "JJLJ", "JJLK", "JJLL", "JJLM", "JJLN", "JJLP", "JJLR", "JJLS", "JJLT", "JJLW", "JJLY", "JJM", "JJMB", "JJMF", "JJMH", "JJMJ", "JJMK", "JJML", "JJMM", "JJMN", "JJMP", "JJMR", "JJMS", "JJMT", "JJMW", "JJMX", "JJN", "JJN0", "JJNB", "JJNF", "JJNH", "JJNJ", "JJNK", "JJNL", "JJNM", "JJNN", "JJNP", "JJNR", "JJNS", "JJNT", "JJNW", "JJNX", "JJNY", "JJP", "JJPJ", "JJPK", "JJPL", "JJPN", "JJPR", "JJPS", "JJPT", "JJPX", "JJR", "JJRB", "JJRF", "JJRJ", "JJRK", "JJRL", "JJRM", "JJRN", "JJRP", "JJRR", "JJRS", "JJRT", "JJRW", "JJRX", "JJS", "JJSB", "JJSF", "JJSH", "JJSJ", "JJSK", "JJSL", "JJSM", "JJSN", "JJSP", "JJSR", "JJSS", "JJST", "JJSW", "JJSX", "JJT", "JJT0", "JJTB", "JJTF", "JJTJ", "JJTK", "JJTL", "JJTM", "JJTN", "JJTP", "JJTR", "JJTS", "JJTT", "JJTX", "JJW", "JJWK", "JJWL", "JJWN", "JJWR", "JJWS", "JJWT", "JJX", "JJXK", "JJXM", "JJXN", "JJXR", "JJXS", "JJY", "JJYF", "JJYL", "JJYN", "JJYR", "JJYS", "KK", "KK0", "KK0B", "KK0F", "KK0H", "KK0J", "KK0K", "KK0L", "KK0M", "KK0N", "KK0P", "KK0R", "KK0S", "KK0T", "KK0W", "KK0X", "KKB", "KKBB", "KKBJ", "KKBK", "KKBL", "KKBN", "KKBR", "KKBS", "KKBT", "KKBX", "KKBY", "KKF", "KKFB", "KKFK", "KKFL", "KKFM", "KKFN", "KKFP", "KKFR", "KKFS", "KKFT", "KKH", "KKHB", "KKHL", "KKHM", "KKHN", "KKHP", "KKHR", "KKHS", "KKHT", "KKHY", "KKJ", "KKJB", "KKJK", "KKJL", "KKJN", "KKJR", "KKJS", "KKJT", "KKJY", "KKK", "KKK0", "KKKB", "KKKK", "KKKL", "KKKM", "KKKN", "KKKP", "KKKR", "KKKS", "KKKT", "KKKW", "KKKY", "KKL", "KKL0", "KKLB", "KKLF", "KKLH", "KKLJ", "KKLK", "KKLL", "KKLM", "KKLN", "KKLP", "KKLR", "KKLS", "KKLT", "KKLW", "KKLX", "KKLY", "KKM", "KKM0", "KKMB", "KKMF", "KKMH", "KKMJ", "KKMK", "KKML", "KKMM", "KKMN", "KKMP", "KKMR", "KKMS", "KKMT", "KKMX", "KKN", "KKN0", "KKNB", "KKNF", "KKNH", "KKNJ", "KKNK", "KKNL", "KKNM", "KKNN", "KKNP", "KKNR", "KKNS", "KKNT", "KKNW", "KKNX", "KKNY", "KKP", "KKPB", "KKPF", "KKPH", "KKPK", "KKPL", "KKPM", "KKPN", "KKPR", "KKPS", "KKPT", "KKPW", "KKPX", "KKPY", "KKR", "KKR0", "KKRB", "KKRF", "KKRH", "KKRJ", "KKRK", "KKRL", "KKRM", "KKRN", "KKRP", "KKRR", "KKRS", "KKRT", "KKRW", "KKRX", "KKRY", "KKS", "KKS0", "KKSB", "KKSF", "KKSK", "KKSL", "KKSM", "KKSN", "KKSP", "KKSR", "KKSS", "KKST", "KKSW", "KKSX", "KKSY", "KKT", "KKTB", "KKTF", "KKTH", "KKTJ", "KKTK", "KKTL", "KKTM", "KKTN", "KKTP", "KKTR", "KKTS", "KKTT", "KKTW", "KKTX", "KKTY", "KKW", "KKWB", "KKWF", "KKWH", "KKWK", "KKWL", "KKWN", "KKWR", "KKWS", "KKWT", "KKWW", "KKWX", "KKX", "KKXF", "KKXJ", "KKXK", "KKXL", "KKXM", "KKXN", "KKXR", "KKXS", "KKY", "KKYB", "KKYK", "KKYL", "KKYM", "KKYN", "KKYP", "KKYR", "KKYS", "KKYT", "KKYW", "KN", "KN0", "KNB", "KNBK", "KNBL", "KNBN", "KNBS", "KNBW", "KNF", "KNFL", "KNFT", "KNK", "KNKB", "KNKF", "KNKL", "KNKP", "KNKR", "KNKS", "KNKT", "KNL", "KNLB", "KNLJ", "KNLM", "KNLN", "KNLR", "KNLS", "KNLT", "KNLW", "KNN", "KNNJ", "KNNK", "KNP", "KNPH", "KNPK", "KNPM", "KNPS", "KNPT", "KNPW", "KNR", "KNRH", "KNS", "KNSL", "KNST", "KNT", "KNTL", "KNTN", "KNTR", "KNTS", "KNTW", "KNW", "KNWN", "KNX", "KNYR", "LL", "LL0", "LL0B", "LL0F", "LL0J", "LL0K", "LL0L", "LL0M", "LL0N", "LL0P", "LL0R", "LL0S", "LL0T", "LL0W", "LLB", "LLB0", "LLBB", "LLBH", "LLBJ", "LLBK", "LLBL", "LLBM", "LLBN", "LLBR", "LLBS", "LLBT", "LLBW", "LLBX", "LLBY", "LLF", "LLF0", "LLFB", "LLFF", "LLFH", "LLFJ", "LLFK", "LLFL", "LLFM", "LLFN", "LLFP", "LLFR", "LLFS", "LLFT", "LLFW", "LLFX", "LLFY", "LLH", "LLHF", "LLHL", "LLHM", "LLHN", "LLHR", "LLHS", "LLHT", "LLJ", "LLJB", "LLJF", "LLJK", "LLJL", "LLJM", "LLJN", "LLJP", "LLJR", "LLJS", "LLJT", "LLJW", "LLJY", "LLK", "LLKB", "LLKF", "LLKH", "LLKJ", "LLKK", "LLKL", "LLKM", "LLKN", "LLKP", "LLKR", "LLKS", "LLKT", "LLKW", "LLKX", "LLKY", "LLL", "LLL0", "LLLB", "LLLF", "LLLH", "LLLJ", "LLLK", "LLLL", "LLLM", "LLLN", "LLLP", "LLLR", "LLLS", "LLLT", "LLLW", "LLLX", "LLLY", "LLM", "LLM0", "LLMB", "LLMF", "LLMH", "LLMJ", "LLMK", "LLML", "LLMM", "LLMN", "LLMP", "LLMR", "LLMS", "LLMT", "LLMW", "LLMX", "LLMY", "LLN", "LLN0", "LLNB", "LLNF", "LLNH", "LLNJ", "LLNK", "LLNL", "LLNM", "LLNN", "LLNP", "LLNR", "LLNS", "LLNT", "LLNW", "LLNX", "LLNY", "LLP", "LLP0", "LLPF", "LLPJ", "LLPK", "LLPL", "LLPM", "LLPN", "LLPR", "LLPS", "LLPT", "LLPW", "LLPX", "LLR", "LLR0", "LLRB", "LLRF", "LLRH", "LLRJ", "LLRK", "LLRL", "LLRM", "LLRN", "LLRP", "LLRR", "LLRS", "LLRT", "LLRW", "LLRX", "LLS", "LLSB", "LLSF", "LLSH", "LLSJ", "LLSK", "LLSL", "LLSM", "LLSN", "LLSP", "LLSR", "LLSS", "LLST", "LLSW", "LLSX", "LLSY", "LLT", "LLTB", "LLTF", "LLTH", "LLTJ", "LLTK", "LLTL", "LLTM", "LLTN", "LLTP", "LLTR", "LLTS", "LLTT", "LLTW", "LLTX", "LLTY", "LLW", "LLWK", "LLWL", "LLWN", "LLWR", "LLWS", "LLWT", "LLWX", "LLX", "LLXB", "LLXF", "LLXK", "LLXL", "LLXM", "LLXN", "LLXP", "LLXR", "LLXS", "LLXT", "LLXW", "LLY", "LLYK", "LLYL", "LLYM", "LLYN", "LLYR", "LLYT", "MM", "MM0", "MM0F", "MM0H", "MM0K", "MM0L", "MM0M", "MM0N", "MM0R", "MM0S", "MM0T", "MM0W", "MMB", "MMBH", "MMBJ", "MMBK", "MMBL", "MMBN", "MMBR", "MMBS", "MMBT", "MMBX", "MMF", "MMFH", "MMFJ", "MMFK", "MMFL", "MMFM", "MMFN", "MMFR", "MMFS", "MMFT", "MMH", "MMHB", "MMHF", "MMHH", "MMHK", "MMHL", "MMHM", "MMHN", "MMHR", "MMHS", "MMHT", "MMJ", "MMJB", "MMJF", "MMJK", "MMJL", "MMJM", "MMJN", "MMJP", "MMJR", "MMJS", "MMJT", "MMJW", "MMJY", "MMK", "MMK0", "MMKB", "MMKF", "MMKH", "MMKJ", "MMKK", "MMKL", "MMKM", "MMKN", "MMKP", "MMKR", "MMKS", "MMKT", "MMKW", "MMKX", "MMKY", "MML", "MML0", "MMLB", "MMLF", "MMLH", "MMLJ", "MMLK", "MMLL", "MMLM", "MMLN", "MMLP", "MMLR", "MMLS", "MMLT", "MMLW", "MMLX", "MMLY", "MMM", "MMM0", "MMMB", "MMMF", "MMMH", "MMMK", "MMML", "MMMM", "MMMN", "MMMP", "MMMR", "MMMS", "MMMT", "MMMW", "MMMX", "MMN", "MMN0", "MMNB", "MMNF", "MMNH", "MMNJ", "MMNK", "MMNL", "MMNM", "MMNN", "MMNP", "MMNR", "MMNS", "MMNT", "MMNW", "MMNX", "MMNY", "MMP", "MMPK", "MMPL", "MMPN", "MMPR", "MMPS", "MMPT", "MMPW", "MMPY", "MMR", "MMR0", "MMRB", "MMRF", "MMRH", "MMRJ", "MMRK", "MMRL", "MMRM", "MMRN", "MMRP", "MMRR", "MMRS", "MMRT", "MMRW", "MMRX", "MMRY", "MMS", "MMS0", "MMSB", "MMSF", "MMSH", "MMSJ", "MMSK", "MMSL", "MMSM", "MMSN", "MMSP", "MMSR", "MMSS", "MMST", "MMSW", "MMSX", "MMSY", "MMT", "MMTB", "MMTF", "MMTH", "MMTJ", "MMTK", "MMTL", "MMTM", "MMTN", "MMTP", "MMTR", "MMTS", "MMTT", "MMTW", "MMTX", "MMTY", "MMW", "MMWB", "MMWK", "MMWL", "MMWM", "MMWN", "MMWR", "MMWS", "MMWT", "MMX", "MMXB", "MMXF", "MMXK", "MMXL", "MMXM", "MMXN", "MMXP", "MMXR", "MMXS", "MMXT", "MMXW", "MMXX", "MMY", "MMYB", "MMYK", "MMYL", "MMYM", "MMYN", "MMYP", "MMYR", "MMYS", "MMYT", "NN", "NN0", "NN0B", "NN0F", "NN0L", "NN0M", "NN0N", "NN0R", "NN0S", "NN0T", "NN0X", "NNB", "NNB0", "NNBH", "NNBJ", "NNBK", "NNBL", "NNBN", "NNBP", "NNBR", "NNBS", "NNBT", "NNBW", "NNBX", "NNF", "NNF0", "NNFB", "NNFH", "NNFJ", "NNFK", "NNFL", "NNFN", "NNFR", "NNFS", "NNFT", "NNFX", "NNH0", "NNHF", "NNHK", "NNHL", "NNHM", "NNHN", "NNHR", "NNJ", "NNJB", "NNJL", "NNJM", "NNJN", "NNJR", "NNJY", "NNK", "NNKB", "NNKJ", "NNKK", "NNKL", "NNKM", "NNKN", "NNKP", "NNKR", "NNKS", "NNKT", "NNKW", "NNKX", "NNKY", "NNL", "NNL0", "NNLB", "NNLF", "NNLH", "NNLJ", "NNLK", "NNLL", "NNLM", "NNLN", "NNLP", "NNLR", "NNLS", "NNLT", "NNLW", "NNLX", "NNLY", "NNM", "NNM0", "NNMF", "NNMJ", "NNMK", "NNML", "NNMN", "NNMP", "NNMR", "NNMS", "NNMT", "NNMW", "NNMX", "NNMY", "NNN", "NNN0", "NNNB", "NNNF", "NNNH", "NNNJ", "NNNK", "NNNL", "NNNM", "NNNN", "NNNP", "NNNR", "NNNS", "NNNT", "NNNW", "NNNX", "NNNY", "NNP", "NNP0", "NNPK", "NNPL", "NNPN", "NNPR", "NNPT", "NNR", "NNR0", "NNRB", "NNRF", "NNRH", "NNRJ", "NNRK", "NNRL", "NNRM", "NNRN", "NNRP", "NNRR", "NNRS", "NNRT", "NNRW", "NNRX", "NNRY", "NNS", "NNS0", "NNSB", "NNSF", "NNSK", "NNSL", "NNSM", "NNSN", "NNSP", "NNSR", "NNSS", "NNST", "NNSW", "NNSX", "NNT", "NNT0", "NNTB", "NNTF", "NNTH", "NNTJ", "NNTK", "NNTL", "NNTM", "NNTN", "NNTP", "NNTR", "NNTS", "NNTT", "NNTW", "NNTX", "NNTY", "NNW", "NNWK", "NNWL", "NNWN", "NNWR", "NNWS", "NNWT", "NNX", "NNXB", "NNXF", "NNXJ", "NNXK", "NNXL", "NNXM", "NNXN", "NNXP", "NNXR", "NNXS", "NNXT", "NNXW", "NNY", "NNYB", "NNYK", "NNYL", "NNYM", "NNYN", "NNYP", "NNYR", "NNYS", "NNYT", "NNYW", "NNYY", "OO", "OO0", "OO0K", "OO0L", "OO0N", "OO0W", "OOB", "OOBB", "OOBF", "OOBK", "OOBL", "OOBM", "OOBN", "OOBR", "OOBS", "OOBT", "OOF", "OOF0", "OOFB", "OOFF", "OOFH", "OOFK", "OOFL", "OOFM", "OOFN", "OOFP", "OOFR", "OOFS", "OOFT", "OOFW", "OOFX", "OOH", "OOHH", "OOHK", "OOHL", "OOHN", "OOHR", "OOJL", "OOJM", "OOJR", "OOK", "OOKB", "OOKF", "OOKH", "OOKJ", "OOKK", "OOKL", "OOKM", "OOKN", "OOKP", "OOKR", "OOKS", "OOKT", "OOKW", "OOKX", "OOL", "OOLB", "OOLF", "OOLK", "OOLL", "OOLM", "OOLN", "OOLP", "OOLR", "OOLS", "OOLT", "OOLW", "OOLY", "OOM", "OOMB", "OOMF", "OOMH", "OOMK", "OOML", "OOMM", "OOMN", "OOMR", "OOMT", "OOMX", "OON", "OON0", "OONF", "OONJ", "OONK", "OONL", "OONM", "OONN", "OONP", "OONR", "OONS", "OONT", "OONW", "OONX", "OONY", "OOP", "OOPK", "OOPL", "OOPN", "OOPR", "OOPS", "OOPT", "OOPW", "OOR", "OOR0", "OORB", "OORF", "OORJ", "OORK", "OORL", "OORM", "OORN", "OORP", "OORR", "OORS", "OORT", "OORW", "OORX", "OORY", "OOS", "OOSB", "OOSJ", "OOSK", "OOSL", "OOSM", "OOSN", "OOSP", "OOSR", "OOSS", "OOST", "OOSW", "OOSX", "OOT", "OOTB", "OOTF", "OOTH", "OOTK", "OOTL", "OOTM", "OOTN", "OOTP", "OOTR", "OOTS", "OOTT", "OOTW", "OOTY", "OOWN", "OOWR", "OOX", "OOXL", "OOXN", "OOXR", "OOXS", "OOXT", "OOYM", "OOYN", "PF", "PFB", "PFBS", "PFF", "PFFL", "PFKN", "PFL", "PFLB", "PFLH", "PFLK", "PFLM", "PFLN", "PFLP", "PFLR", "PFLS", "PFLT", "PFLW", "PFM", "PFN", "PFNK", "PFNS", "PFNT", "PFP", "PFPR", "PFPS", "PFR", "PFRL", "PFRS", "PFRW", "PFS", "PFSF", "PFSK", "PFSM", "PFSN", "PFTK", "PFTN", "PFTS", "PNMN", "PP", "PP0", "PP0B", "PP0F", "PP0J", "PP0K", "PP0M", "PP0N", "PP0R", "PP0S", "PPB", "PPBJ", "PPBK", "PPBL", "PPBM", "PPBN", "PPBR", "PPBS", "PPBT", "PPBW", "PPF", "PPFF", "PPFK", "PPFL", "PPFM", "PPFN", "PPFR", "PPFS", "PPFT", "PPH", "PPHL", "PPHN", "PPHS", "PPHT", "PPJ", "PPJB", "PPJK", "PPJL", "PPJM", "PPJN", "PPJR", "PPJS", "PPJT", "PPJW", "PPK", "PPK0", "PPKB", "PPKF", "PPKH", "PPKK", "PPKL", "PPKM", "PPKN", "PPKP", "PPKR", "PPKS", "PPKT", "PPKW", "PPKX", "PPL", "PPL0", "PPLB", "PPLF", "PPLH", "PPLJ", "PPLK", "PPLL", "PPLM", "PPLN", "PPLP", "PPLR", "PPLS", "PPLT", "PPLW", "PPLX", "PPLY", "PPM", "PPMF", "PPMJ", "PPMK", "PPML", "PPMM", "PPMN", "PPMP", "PPMR", "PPMS", "PPMT", "PPMW", "PPMX", "PPN", "PPN0", "PPNB", "PPNF", "PPNH", "PPNJ", "PPNK", "PPNL", "PPNM", "PPNN", "PPNP", "PPNR", "PPNS", "PPNT", "PPNW", "PPNX", "PPNY", "PPP", "PPP0", "PPPB", "PPPF", "PPPH", "PPPJ", "PPPK", "PPPL", "PPPN", "PPPP", "PPPR", "PPPS", "PPPT", "PPPW", "PPPY", "PPR", "PPR0", "PPRB", "PPRF", "PPRH", "PPRJ", "PPRK", "PPRL", "PPRM", "PPRN", "PPRP", "PPRR", "PPRS", "PPRT", "PPRW", "PPRX", "PPRY", "PPS", "PPS0", "PPSB", "PPSF", "PPSH", "PPSJ", "PPSK", "PPSL", "PPSM", "PPSN", "PPSP", "PPSR", "PPSS", "PPST", "PPSW", "PPSX", "PPT", "PPT0", "PPTB", "PPTF", "PPTH", "PPTJ", "PPTK", "PPTL", "PPTM", "PPTN", "PPTP", "PPTR", "PPTS", "PPTT", "PPTW", "PPTX", "PPTY", "PPW", "PPWL", "PPWN", "PPWR", "PPWS", "PPWT", "PPX", "PPXB", "PPXF", "PPXK", "PPXL", "PPXM", "PPXN", "PPXP", "PPXR", "PPXS", "PPXT", "PPXW", "PPY", "PPYL", "PPYN", "PPYP", "PPYR", "PPYS", "PPYT", "PPYW", "QK", "QKB0", "QKBK", "QKBN", "QKBR", "QKBS", "QKBT", "QKF", "QKFN", "QKFP", "QKFR", "QKFS", "QKFT", "QKH", "QKK", "QKKB", "QKKL", "QKKM", "QKKN", "QKKR", "QKKS", "QKL", "QKLB", "QKLJ", "QKLK", "QKLM", "QKLN", "QKLP", "QKLR", "QKLS", "QKLT", "QKLX", "QKM", "QKMB", "QKMK", "QKMN", "QKMS", "QKMT", "QKN", "QKNB", "QKNF", "QKNH", "QKNJ", "QKNK", "QKNL", "QKNM", "QKNN", "QKNS", "QKNT", "QKNW", "QKNX", "QKPL", "QKPR", "QKR", "QKRB", "QKRF", "QKRH", "QKRK", "QKRL", "QKRM", "QKRN", "QKRP", "QKRR", "QKRS", "QKRT", "QKS", "QKS0", "QKSN", "QKSR", "QKST", "QKT", "QKTF", "QKTJ", "QKTK", "QKTL", "QKTN", "QKTR", "QKTS", "QKTT", "QKX", "QKYR", "RR", "RR0", "RR0B", "RR0F", "RR0H", "RR0J", "RR0K", "RR0L", "RR0M", "RR0N", "RR0R", "RR0S", "RR0T", "RR0W", "RRB", "RRB0", "RRBB", "RRBF", "RRBH", "RRBJ", "RRBK", "RRBL", "RRBM", "RRBN", "RRBR", "RRBS", "RRBT", "RRBW", "RRBX", "RRBY", "RRF", "RRFB", "RRFF", "RRFH", "RRFJ", "RRFK", "RRFL", "RRFM", "RRFN", "RRFP", "RRFR", "RRFS", "RRFT", "RRFW", "RRFX", "RRH", "RRHB", "RRHF", "RRHK", "RRHL", "RRHM", "RRHN", "RRHP", "RRHR", "RRHS", "RRHT", "RRJ", "RRJF", "RRJH", "RRJK", "RRJL", "RRJM", "RRJN", "RRJP", "RRJR", "RRJS", "RRJT", "RRJW", "RRJY", "RRK", "RRKB", "RRKF", "RRKH", "RRKJ", "RRKK", "RRKL", "RRKM", "RRKN", "RRKP", "RRKR", "RRKS", "RRKT", "RRKW", "RRKX", "RRL", "RRLB", "RRLF", "RRLJ", "RRLK", "RRLM", "RRLN", "RRLP", "RRLR", "RRLS", "RRLT", "RRLW", "RRLX", "RRLY", "RRM", "RRMB", "RRMF", "RRMH", "RRMJ", "RRMK", "RRML", "RRMM", "RRMN", "RRMP", "RRMR", "RRMS", "RRMT", "RRMW", "RRMX", "RRMY", "RRN", "RRN0", "RRNB", "RRNF", "RRNH", "RRNJ", "RRNK", "RRNL", "RRNM", "RRNN", "RRNP", "RRNR", "RRNS", "RRNT", "RRNW", "RRNX", "RRNY", "RRP", "RRPB", "RRPF", "RRPH", "RRPK", "RRPL", "RRPN", "RRPR", "RRPS", "RRPT", "RRPX", "RRPY", "RRR", "RRRH", "RRRK", "RRRL", "RRRM", "RRRN", "RRRP", "RRRS", "RRRT", "RRRW", "RRS", "RRS0", "RRSB", "RRSF", "RRSH", "RRSJ", "RRSK", "RRSL", "RRSM", "RRSN", "RRSP", "RRSR", "RRSS", "RRST", "RRSW", "RRSX", "RRT", "RRT0", "RRTB", "RRTF", "RRTH", "RRTJ", "RRTK", "RRTL", "RRTM", "RRTN", "RRTP", "RRTR", "RRTS", "RRTT", "RRTW", "RRTX", "RRTY", "RRW", "RRWL", "RRWN", "RRWR", "RRWS", "RRWT", "RRX", "RRXB", "RRXF", "RRXK", "RRXL", "RRXM", "RRXN", "RRXR", "RRXS", "RRXT", "RRXW", "RRY", "RRYB", "RRYF", "RRYK", "RRYL", "RRYN", "RRYP", "RRYR", "RRYS", "RRYT", "SS", "SS0", "SS0B", "SS0F", "SS0H", "SS0J", "SS0K", "SS0L", "SS0M", "SS0N", "SS0P", "SS0R", "SS0S", "SS0T", "SS0W", "SS0X", "SS0Y", "SSB", "SSB0", "SSBK", "SSBL", "SSBM", "SSBN", "SSBR", "SSBS", "SSBT", "SSBW", "SSBX", "SSF", "SSFJ", "SSFK", "SSFL", "SSFM", "SSFN", "SSFP", "SSFR", "SSFS", "SSFT", "SSFY", "SSH", "SSH0", "SSHF", "SSHJ", "SSHK", "SSHL", "SSHM", "SSHN", "SSHR", "SSHS", "SSJ", "SSJB", "SSJF", "SSJH", "SSJJ", "SSJL", "SSJM", "SSJN", "SSJR", "SSJS", "SSJT", "SSJW", "SSK", "SSK0", "SSKB", "SSKF", "SSKH", "SSKK", "SSKL", "SSKM", "SSKN", "SSKP", "SSKR", "SSKS", "SSKT", "SSKW", "SSKX", "SSKY", "SSL", "SSL0", "SSLB", "SSLF", "SSLH", "SSLJ", "SSLK", "SSLL", "SSLM", "SSLN", "SSLP", "SSLR", "SSLS", "SSLT", "SSLW", "SSLX", "SSLY", "SSM", "SSM0", "SSMB", "SSMF", "SSMH", "SSMJ", "SSMK", "SSML", "SSMM", "SSMN", "SSMP", "SSMR", "SSMS", "SSMT", "SSMW", "SSMX", "SSMY", "SSN", "SSN0", "SSNB", "SSNF", "SSNH", "SSNJ", "SSNK", "SSNL", "SSNM", "SSNN", "SSNP", "SSNR", "SSNS", "SSNT", "SSNW", "SSNX", "SSNY", "SSP", "SSP0", "SSPB", "SSPF", "SSPJ", "SSPK", "SSPL", "SSPM", "SSPN", "SSPR", "SSPS", "SSPT", "SSPW", "SSPX", "SSR", "SSR0", "SSRB", "SSRF", "SSRH", "SSRJ", "SSRK", "SSRL", "SSRM", "SSRN", "SSRP", "SSRR", "SSRS", "SSRT", "SSRW", "SSRX", "SSRY", "SSS", "SSSB", "SSSF", "SSSJ", "SSSK", "SSSL", "SSSM", "SSSN", "SSSP", "SSSR", "SSSS", "SSST", "SSSW", "SSSX", "SSSY", "SST", "SST0", "SSTB", "SSTF", "SSTH", "SSTJ", "SSTK", "SSTL", "SSTM", "SSTN", "SSTP", "SSTR", "SSTS", "SSTT", "SSTW", "SSTX", "SSTY", "SSW", "SSW0", "SSWB", "SSWF", "SSWJ", "SSWK", "SSWL", "SSWM", "SSWN", "SSWP", "SSWR", "SSWS", "SSWT", "SSWX", "SSX", "SSXB", "SSXF", "SSXK", "SSXL", "SSXM", "SSXN", "SSXP", "SSXR", "SSXS", "SSXT", "SSXW", "SSXX", "SSY", "SSYN", "SSYR", "SSYS", "SX", "SX0B", "SX0R", "SX0T", "SXB", "SXBH", "SXBL", "SXBN", "SXBR", "SXBS", "SXF", "SXFL", "SXFM", "SXFN", "SXFR", "SXFS", "SXFT", "SXHN", "SXJM", "SXK", "SXKB", "SXKF", "SXKH", "SXKK", "SXKL", "SXKN", "SXKR", "SXKS", "SXKT", "SXKX", "SXL", "SXLB", "SXLF", "SXLH", "SXLK", "SXLL", "SXLM", "SXLN", "SXLP", "SXLR", "SXLS", "SXLT", "SXLW", "SXLX", "SXM", "SXMH", "SXMK", "SXML", "SXMN", "SXMR", "SXMS", "SXN", "SXNB", "SXNF", "SXNH", "SXNJ", "SXNK", "SXNL", "SXNN", "SXNP", "SXNR", "SXNS", "SXNT", "SXP", "SXPB", "SXPF", "SXPH", "SXPK", "SXPL", "SXPM", "SXPN", "SXPR", "SXPS", "SXPT", "SXPW", "SXPY", "SXR", "SXR0", "SXRB", "SXRF", "SXRH", "SXRJ", "SXRK", "SXRL", "SXRM", "SXRN", "SXRP", "SXRR", "SXRS", "SXRT", "SXRW", "SXRX", "SXS", "SXSF", "SXSK", "SXSM", "SXSP", "SXSR", "SXSS", "SXST", "SXT", "SXTB", "SXTF", "SXTH", "SXTK", "SXTL", "SXTN", "SXTP", "SXTR", "SXTS", "SXTT", "SXTW", "SXWL", "SXWR", "SXWT", "SXXN", "SXXT", "SXYR", "T0", "T00", "T0B", "T0BB", "T0BK", "T0BL", "T0BM", "T0BN", "T0BP", "T0BR", "T0BS", "T0BT", "T0BW", "T0BX", "T0F", "T0FF", "T0FK", "T0FL", "T0FN", "T0FR", "T0FS", "T0H0", "T0HB", "T0HF", "T0HL", "T0HM", "T0HR", "T0HT", "T0HX", "T0JB", "T0JK", "T0JN", "T0JP", "T0JR", "T0JS", "T0JT", "T0K", "T0KB", "T0KF", "T0KK", "T0KL", "T0KM", "T0KN", "T0KP", "T0KR", "T0KS", "T0KT", "T0KX", "T0L", "T0L0", "T0LB", "T0LF", "T0LJ", "T0LK", "T0LM", "T0LN", "T0LP", "T0LR", "T0LS", "T0LT", "T0LX", "T0LY", "T0M", "T0MJ", "T0MK", "T0ML", "T0MN", "T0MP", "T0MR", "T0MS", "T0MT", "T0MX", "T0N", "T0NB", "T0NF", "T0NJ", "T0NK", "T0NL", "T0NM", "T0NN", "T0NP", "T0NR", "T0NS", "T0NT", "T0NW", "T0NX", "T0P", "T0PF", "T0PK", "T0PL", "T0PN", "T0PP", "T0PR", "T0PS", "T0PT", "T0PX", "T0R", "T0RB", "T0RF", "T0RH", "T0RJ", "T0RK", "T0RL", "T0RM", "T0RN", "T0RP", "T0RR", "T0RS", "T0RT", "T0RW", "T0RX", "T0RY", "T0S", "T0S0", "T0SB", "T0SF", "T0SJ", "T0SK", "T0SL", "T0SM", "T0SN", "T0SP", "T0SR", "T0SS", "T0ST", "T0SW", "T0SX", "T0T", "T0TB", "T0TF", "T0TK", "T0TL", "T0TM", "T0TN", "T0TP", "T0TR", "T0TS", "T0TT", "T0TW", "T0W", "T0WF", "T0WL", "T0WN", "T0WR", "T0WT", "T0WX", "T0X", "T0XL", "T0XM", "T0XN", "T0XP", "T0XR", "T0XS", "T0XT", "T0Y", "T0YM", "T0YN", "T0YR", "T0YX", "TT", "TT0", "TT0L", "TT0M", "TT0R", "TT0S", "TTB", "TTB0", "TTBB", "TTBF", "TTBK", "TTBL", "TTBM", "TTBN", "TTBR", "TTBS", "TTBT", "TTBX", "TTF", "TTFF", "TTFH", "TTFK", "TTFL", "TTFM", "TTFN", "TTFR", "TTFS", "TTFT", "TTFW", "TTH", "TTHL", "TTHN", "TTHR", "TTHS", "TTHT", "TTHX", "TTJ", "TTJK", "TTJL", "TTJM", "TTJN", "TTJR", "TTJS", "TTJT", "TTJW", "TTK", "TTKB", "TTKF", "TTKH", "TTKK", "TTKL", "TTKM", "TTKN", "TTKP", "TTKR", "TTKS", "TTKT", "TTKW", "TTKY", "TTL", "TTL0", "TTLB", "TTLF", "TTLH", "TTLJ", "TTLK", "TTLL", "TTLM", "TTLN", "TTLP", "TTLR", "TTLS", "TTLT", "TTLW", "TTLX", "TTLY", "TTM", "TTM0", "TTMB", "TTMF", "TTMH", "TTMJ", "TTMK", "TTML", "TTMM", "TTMN", "TTMP", "TTMR", "TTMS", "TTMT", "TTMW", "TTMX", "TTMY", "TTN", "TTN0", "TTNB", "TTNF", "TTNH", "TTNJ", "TTNK", "TTNL", "TTNM", "TTNN", "TTNP", "TTNR", "TTNS", "TTNT", "TTNW", "TTNX", "TTNY", "TTP", "TTPB", "TTPF", "TTPH", "TTPK", "TTPL", "TTPM", "TTPN", "TTPP", "TTPR", "TTPS", "TTPT", "TTPW", "TTPX", "TTPY", "TTR", "TTR0", "TTRB", "TTRF", "TTRH", "TTRJ", "TTRK", "TTRL", "TTRM", "TTRN", "TTRP", "TTRR", "TTRS", "TTRT", "TTRW", "TTRX", "TTRY", "TTS", "TTSB", "TTSF", "TTSH", "TTSK", "TTSL", "TTSM", "TTSN", "TTSP", "TTSR", "TTSS", "TTST", "TTSW", "TTSX", "TTT", "TTTB", "TTTF", "TTTH", "TTTJ", "TTTK", "TTTL", "TTTM", "TTTN", "TTTP", "TTTR", "TTTS", "TTTT", "TTTW", "TTTX", "TTTY", "TTW", "TTW0", "TTWB", "TTWF", "TTWH", "TTWK", "TTWL", "TTWM", "TTWN", "TTWP", "TTWR", "TTWS", "TTWT", "TTWW", "TTWX", "TTX", "TTXB", "TTXF", "TTXK", "TTXL", "TTXN", "TTXR", "TTXS", "TTY", "TTYB", "TTYK", "TTYL", "TTYM", "TTYN", "TTYP", "TTYR", "TTYS", "TTYT", "TX", "TXBN", "TXFL", "TXLR", "TXM", "TXML", "TXN", "TXNR", "TXPS", "TXR", "TXRL", "TXRN", "TXTK", "UU0M", "UU0R", "UU0W", "UUB", "UUBB", "UUBR", "UUFL", "UUFM", "UUFN", "UUFR", "UUFS", "UUFT", "UUK", "UUKL", "UUKM", "UUKN", "UUKR", "UUKS", "UUKX", "UUL", "UUL0", "UULB", "UULF", "UULJ", "UULK", "UULL", "UULM", "UULN", "UULP", "UULR", "UULS", "UULT", "UULW", "UULY", "UUM", "UUMF", "UUMK", "UUML", "UUMN", "UUMP", "UUMR", "UUMW", "UUN", "UUN0", "UUNF", "UUNJ", "UUNK", "UUNL", "UUNM", "UUNN", "UUNP", "UUNR", "UUNS", "UUNT", "UUNW", "UUNY", "UUP0", "UUPF", "UUPL", "UUPM", "UUPN", "UUPR", "UUPS", "UUPT", "UUPW", "UUPX", "UUR", "UURB", "UURJ", "UURK", "UURL", "UURM", "UURN", "UURP", "UURR", "UURS", "UURT", "UURW", "UURX", "UUSK", "UUSL", "UUSN", "UUSR", "UUST", "UUT", "UUTJ", "UUTK", "UUTL", "UUTN", "UUTP", "UUTR", "UUTS", "UUTY", "UUW", "UUWL", "UUWR", "UUXK", "UUXR", "VF", "VFB", "VFBL", "VFBN", "VFBR", "VFF", "VFFH", "VFFK", "VFFL", "VFFN", "VFFR", "VFFS", "VFFT", "VFFX", "VFFY", "VFHL", "VFJ", "VFJF", "VFJL", "VFJM", "VFJN", "VFJS", "VFK", "VFKB", "VFKK", "VFKL", "VFKN", "VFKR", "VFKS", "VFKT", "VFKX", "VFL", "VFL0", "VFLB", "VFLF", "VFLH", "VFLJ", "VFLK", "VFLL", "VFLM", "VFLN", "VFLP", "VFLR", "VFLS", "VFLT", "VFLW", "VFLX", "VFM", "VFMN", "VFMP", "VFMR", "VFMS", "VFMT", "VFN", "VFN0", "VFNB", "VFNF", "VFNH", "VFNJ", "VFNK", "VFNL", "VFNM", "VFNN", "VFNP", "VFNR", "VFNS", "VFNT", "VFNW", "VFNX", "VFNY", "VFP", "VFPN", "VFPR", "VFR", "VFRB", "VFRF", "VFRH", "VFRJ", "VFRK", "VFRL", "VFRM", "VFRN", "VFRP", "VFRR", "VFRS", "VFRT", "VFRW", "VFRX", "VFRY", "VFS", "VFSF", "VFSH", "VFSJ", "VFSK", "VFSL", "VFSM", "VFSN", "VFSP", "VFSR", "VFST", "VFSX", "VFSY", "VFT", "VFTB", "VFTF", "VFTH", "VFTK", "VFTL", "VFTM", "VFTN", "VFTR", "VFTS", "VFTT", "VFTX", "VFWL", "VFWT", "VFX", "VFXN", "VFXR", "VFXS", "VFY", "VFYJ", "VFYL", "W", "W0BR", "W0S", "WBLN", "WBNK", "WBR", "WBRB", "WBRN", "WBRT", "WFL", "WFLK", "WFLS", "WFLT", "WFRN", "WHTR", "WJ", "WJBL", "WJMS", "WKHM", "WKHT", "WKKS", "WKLF", "WKLS", "WKLW", "WKM", "WKMP", "WKN", "WKNT", "WKRB", "WKS", "WL", "WLB", "WLKR", "WLM", "WLMR", "WLN", "WLNT", "WLPN", "WLPR", "WLR", "WLRS", "WLS", "WLT", "WLTS", "WLTW", "WLXR", "WLY", "WM", "WMFR", "WMHF", "WMLR", "WMLT", "WMN", "WMNT", "WMR", "WMRK", "WMST", "WN", "WNBR", "WNFL", "WNFR", "WNHM", "WNJL", "WNKR", "WNKT", "WNL", "WNM", "WNMN", "WNN", "WNNT", "WNRK", "WNRL", "WNS", "WNSR", "WNST", "WNT", "WNTB", "WNTH", "WNTK", "WNTL", "WNTN", "WNTR", "WNTS", "WNTT", "WNTY", "WNWR", "WNWT", "WNY", "WNYR", "WPMP", "WPR", "WPRF", "WR", "WR0", "WR0L", "WR0M", "WR0S", "WRBR", "WRFR", "WRFT", "WRJR", "WRK", "WRKB", "WRKL", "WRKN", "WRKR", "WRKS", "WRL", "WRLF", "WRM", "WRM0", "WRMK", "WRN", "WRNF", "WRNJ", "WRNK", "WRNS", "WRNT", "WRNX", "WRP", "WRS", "WRSB", "WRST", "WRT", "WRTK", "WRTL", "WRTN", "WRTS", "WS", "WSFR", "WSLS", "WSS", "WSXL", "WTKS", "WTKT", "WTL", "WTLR", "WTN", "WTR", "WTRK", "WTTY", "WTWL", "WW", "WW0", "WW0B", "WW0K", "WW0L", "WW0M", "WW0N", "WW0R", "WW0W", "WWB", "WWBH", "WWBK", "WWBL", "WWBM", "WWBN", "WWBP", "WWBR", "WWBS", "WWBT", "WWBW", "WWBX", "WWBY", "WWF", "WWFB", "WWFH", "WWFK", "WWFL", "WWFM", "WWFN", "WWFP", "WWFR", "WWFS", "WWFT", "WWFX", "WWH", "WWHF", "WWHM", "WWHN", "WWHP", "WWHT", "WWJ", "WWJB", "WWJK", "WWJL", "WWJN", "WWJR", "WWJS", "WWJT", "WWJW", "WWK", "WWKB", "WWKF", "WWKH", "WWKK", "WWKL", "WWKM", "WWKN", "WWKP", "WWKR", "WWKS", "WWKT", "WWKW", "WWKY", "WWL", "WWL0", "WWLB", "WWLF", "WWLH", "WWLJ", "WWLK", "WWLL", "WWLM", "WWLN", "WWLP", "WWLR", "WWLS", "WWLT", "WWLW", "WWLX", "WWLY", "WWM", "WWM0", "WWMB", "WWMF", "WWMJ", "WWMK", "WWML", "WWMN", "WWMP", "WWMR", "WWMS", "WWMT", "WWMW", "WWMY", "WWN", "WWN0", "WWNB", "WWNF", "WWNH", "WWNJ", "WWNK", "WWNL", "WWNM", "WWNN", "WWNP", "WWNR", "WWNS", "WWNT", "WWNW", "WWNX", "WWNY", "WWP", "WWPB", "WWPF", "WWPH", "WWPK", "WWPL", "WWPM", "WWPN", "WWPP", "WWPR", "WWPS", "WWPT", "WWPW", "WWR", "WWR0", "WWRB", "WWRF", "WWRH", "WWRJ", "WWRK", "WWRL", "WWRM", "WWRN", "WWRP", "WWRR", "WWRS", "WWRT", "WWRW", "WWRX", "WWRY", "WWS", "WWS0", "WWSB", "WWSF", "WWSK", "WWSL", "WWSM", "WWSN", "WWSP", "WWSR", "WWSS", "WWST", "WWSW", "WWSX", "WWT", "WWT0", "WWTB", "WWTF", "WWTH", "WWTJ", "WWTK", "WWTL", "WWTM", "WWTN", "WWTP", "WWTR", "WWTS", "WWTT", "WWTW", "WWTX", "WWTY", "WWW", "WWWB", "WWWK", "WWWL", "WWWM", "WWWN", "WWWR", "WWX", "WWXB", "WWXF", "WWXH", "WWXK", "WWXL", "WWXM", "WWXN", "WWXP", "WWXR", "WWXS", "WWXT", "WWXW", "WWY", "WWYL", "WWYM", "WWYN", "WWYR", "WWYT", "WX", "WXBR", "WXKR", "WXL", "WXNK", "WXPR", "WXT", "WXTL", "WXWT", "WY", "WY0", "WYB", "WYFR", "WYK", "WYKK", "WYKT", "WYL", "WYLK", "WYLN", "WYLS", "WYLT", "WYM", "WYMB", "WYMN", "WYMP", "WYN", "WYNB", "WYNK", "WYNN", "WYNT", "WYP", "WYR", "WYRJ", "WYRM", "WYS", "WYT", "WYTF", "WYTP", "WYTR", "WYTS", "XSFR", "XSHF", "XSMS", "XSN", "XSN0", "XSNK", "XSNL", "XSNN", "XSNT", "XSRB", "Y", "YFN", "YFRT", "YFS", "YFT", "YMK", "YN", "YPRS", "YRM", "YSNT", "YST0", "YSTL", "YY", "YY0", "YY0L", "YY0N", "YY0P", "YY0R", "YYB", "YYBK", "YYBL", "YYBM", "YYBN", "YYBR", "YYBS", "YYBT", "YYFL", "YYFN", "YYFR", "YYH", "YYJK", "YYJL", "YYJN", "YYJR", "YYK", "YYKB", "YYKK", "YYKL", "YYKM", "YYKN", "YYKP", "YYKR", "YYKS", "YYKT", "YYKX", "YYL", "YYLB", "YYLF", "YYLH", "YYLJ", "YYLK", "YYLL", "YYLM", "YYLN", "YYLP", "YYLR", "YYLS", "YYLT", "YYLW", "YYLY", "YYM", "YYMB", "YYMK", "YYML", "YYMN", "YYMP", "YYMR", "YYMS", "YYMT", "YYMX", "YYMY", "YYN", "YYN0", "YYNB", "YYNF", "YYNJ", "YYNK", "YYNL", "YYNM", "YYNN", "YYNP", "YYNR", "YYNS", "YYNT", "YYNW", "YYNX", "YYNY", "YYP", "YYPK", "YYPL", "YYPN", "YYPR", "YYPS", "YYPT", "YYR", "YYRB", "YYRF", "YYRH", "YYRJ", "YYRK", "YYRL", "YYRM", "YYRN", "YYRP", "YYRR", "YYRS", "YYRT", "YYRW", "YYRX", "YYRY", "YYS", "YYSB", "YYSF", "YYSK", "YYSM", "YYSN", "YYSP", "YYSR", "YYST", "YYSW", "YYT", "YYTB", "YYTF", "YYTJ", "YYTK", "YYTL", "YYTM", "YYTN", "YYTP", "YYTR", "YYTS", "YYTY", "YYW", "YYWK", "YYWL", "YYWN", "YYWP", "YYWR", "YYX", "YYXT", "YYY", "YYYH", "YYYK", "YYYN", "YYYT", "ZS", "ZSB", "ZSBK", "ZSBL", "ZSBN", "ZSBR", "ZSF", "ZSFL", "ZSFN", "ZSFR", "ZSFS", "ZSFT", "ZSH", "ZSHL", "ZSHN", "ZSHR", "ZSJL", "ZSJN", "ZSK", "ZSKF", "ZSKH", "ZSKK", "ZSKL", "ZSKN", "ZSKR", "ZSKS", "ZSKW", "ZSKX", "ZSL", "ZSLB", "ZSLF", "ZSLK", "ZSLM", "ZSLN", "ZSLR", "ZSLS", "ZSLT", "ZSM", "ZSML", "ZSMN", "ZSMP", "ZSMR", "ZSMS", "ZSMT", "ZSN", "ZSN0", "ZSNB", "ZSNF", "ZSNJ", "ZSNK", "ZSNL", "ZSNN", "ZSNR", "ZSNS", "ZSNT", "ZSP", "ZSPF", "ZSPK", "ZSPL", "ZSPN", "ZSPP", "ZSPS", "ZSR", "ZSRB", "ZSRF", "ZSRK", "ZSRL", "ZSRM", "ZSRN", "ZSRS", "ZSRT", "ZSRX", "ZSS", "ZSSM", "ZSSN", "ZSSS", "ZSST", "ZSSX", "ZST", "ZSTK", "ZSTL", "ZSTN", "ZSTP", "ZSTR", "ZSTS", "ZSTT", "ZSTX", "ZSWK", "ZSWR", "ZSWS", "ZSX", "ZSXN", "ZSXR", "ZSXS", "ZSY"]; - } -}); - -// src/geocode.ts -var geocode_exports = {}; -__export(geocode_exports, { - default: () => geocode -}); -var import_minisearch = __toESM(require("minisearch")); -var import_latlon_geohash = __toESM(require("latlon-geohash")); -var import_metaphone = __toESM(require("metaphone")); -var knownGroups = new Set(require_groups()); -var currentGroup = null; -var currentGroupData = null; -var fetchController = new AbortController(); -var miniSearch = new import_minisearch.default({ fields: ["address"] }); -var searchIndexDocuments = []; -var currentSearchIndexKey = null; -function getSearchIndexKey(group, numericWords) { - return [group, ...numericWords.sort()].join("|"); -} -function getGroup(word) { - let cleanedWord = word.toUpperCase().replace(/[^A-Z]+/g, ""); - let group = cleanedWord.substring(0, 1) + (0, import_metaphone.default)(cleanedWord).substring(0, 3); - return knownGroups.has(group) ? group : null; -} -function loadGroupData(group) { - return new Promise((resolve, reject) => { - if (group === currentGroup && currentGroupData) { - resolve(currentGroupData); - return; - } - fetchController.abort(); - fetchController = new AbortController(); - currentGroup = group; - let url = `https://www.abc.net.au/res/sites/news-projects/geocoder/data/202111/${group}.txt.gz`; - fetch(url, { signal: fetchController.signal }).then((response) => { - response.text().then((data) => { - currentGroupData = data; - resolve(data); - }); - }).catch((e) => { - if (e.name !== "AbortError") - reject(e); - }); - }); -} -function prepareSearchIndex(group, numericWords) { - return new Promise((resolve, reject) => { - let newSearchIndexKey = getSearchIndexKey(group, numericWords); - if (newSearchIndexKey === currentSearchIndexKey) { - resolve(); - return; - } - loadGroupData(group).then((data) => { - var _a; - searchIndexDocuments = []; - let id = 0; - let lines = data.split("\n"); - for (let line of lines) { - let street; - try { - street = JSON.parse(line); - } catch { - continue; - } - let addressLines = [ - "", - "", - [street.s, street.t, street.p].join(" ") - ]; - for (let block of street.b) { - addressLines[1] = [ - block.l ? "LOT " : "", - block.m ? block.n + "-" + block.m + " " : block.n + " ", - street.a + " ", - street.r ? street.r : "", - street.x ? " " + street.x : "" - ].join(""); - addressLines[0] = (_a = block.a) != null ? _a : ""; - let address = addressLines.filter((line2) => !!line2).join(", "); - let indexThisBlock = numericWords.length === 0 || numericWords.some((w) => w === block.n || w === block.m || w === street.p); - if (indexThisBlock) { - searchIndexDocuments[id] = { - id, - address, - geohash: block.g, - numericWords: block.m ? [block.n, block.m, street.p] : [block.n, street.p] - }; - id++; - } - if (block.u && numericWords.length > 0) { - for (let unitType in block.u) { - let unitNumbers = block.u[unitType]; - if (unitType) - unitType += " "; - for (let unitNumber of unitNumbers) { - if (Array.isArray(unitNumber) && unitNumber.length === 2) { - for (let i = unitNumber[0]; i <= unitNumber[1]; i++) { - let indexThisUnit = indexThisBlock || numericWords.some((w) => w === i); - if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + i + ", " + address, - geohash: block.g, - numericWords: block.m ? [i, block.n, block.m, +street.p] : [i, block.n, +street.p] - }; - id++; - } - } - } else { - let indexThisUnit = indexThisBlock || numericWords.some((w) => w === unitNumber); - if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + unitNumber + ", " + address, - geohash: block.g, - numericWords: block.m ? [unitNumber, block.n, block.m, +street.p] : [unitNumber, block.n, +street.p] - }; - id++; - } - } - } - } - } - } - if (id > 1e4) { - break; - } - } - miniSearch.removeAll(); - miniSearch.addAll(searchIndexDocuments); - resolve(); - }).catch(reject); - }); -} -var states = /* @__PURE__ */ new Set(["NSW", "VIC", "QLD", "WA", "SA", "TAS", "ACT", "NT"]); -var prettyAddress = (address) => { - return address.toUpperCase().replace(/(^|[^A-Z])(['A-Z]+)/g, (entireMatch, separator, word) => { - let prettyWord = states.has(word) ? word : word.substring(0, 1) + word.substring(1).toLowerCase(); - return separator + prettyWord; - }); -}; -function geocode(input, options = {}) { - return new Promise((resolve, reject) => { - let startTime = Date.now(); - let cleanedInput = input.replace(/'/g, "").replace(/[^\w\d]+/g, " ").replace(/\s+/g, " ").toUpperCase(); - let words = cleanedInput.split(" ").map((word) => isFinite(+word) ? +word : word); - let numericWords = []; - let streetName = null; - for (let word of words) { - let isNumeric = typeof word === "number" || /\d/.test(word); - if (isNumeric) { - numericWords.push(word); - } else if (streetName === null && typeof word === "string" && word.length > 3 && numericWords.length > 0) { - streetName = word; - } - } - if (streetName === null) { - let firstWord = words.find((word) => typeof word === "string" && !/\d/.test(word)); - if (firstWord && typeof firstWord === "string") { - streetName = firstWord; - } - } - let result = { - results: [], - group: "", - input, - duration: 0 - }; - let group = streetName === null ? null : getGroup(streetName); - if (streetName === null || group === null) { - result.duration = Date.now() - startTime; - resolve(result); - return; - } - prepareSearchIndex(group, numericWords).then(() => { - var _a; - let miniSearchResults = miniSearch.search(input, { - fuzzy: (term) => /\d/.test(term) ? false : 0.333, - prefix: (term) => /\d/.test(term) ? false : true, - weights: { fuzzy: 0.1, prefix: 0.5 }, - filter: numericWords.length === 0 ? void 0 : (result2) => { - let doc = searchIndexDocuments[result2.id]; - if (doc && doc.numericWords.length > 0) { - for (let inputWord of numericWords) { - for (let docWord of doc.numericWords) { - if (inputWord === docWord) { - return true; - } - } - } - } - return false; - } - }); - let highestScoreIsPositive = ((_a = miniSearchResults[0]) == null ? void 0 : _a.score) > 0; - for (let miniSearchResult of miniSearchResults) { - if (miniSearchResult.score === 0 && highestScoreIsPositive) { - break; - } - let doc = searchIndexDocuments[miniSearchResult.id]; - let g = import_latlon_geohash.default.decode(doc.geohash); - result.results.push({ - address: prettyAddress(doc.address), - latitude: g.lat, - longitude: g.lon, - score: miniSearchResult.score, - id: doc.id - }); - if (result.results.length === options.limit) { - break; - } - } - result.duration = Date.now() - startTime; - resolve(result); - }).catch(reject); - }); -} -module.exports = __toCommonJS(geocode_exports); -// Annotate the CommonJS export names for ESM import in node: -0 && (module.exports = {}); +"use strict";var F=Object.create;var k=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var Q=(r,t)=>{for(var s in t)k(r,s,{get:t[s],enumerable:!0})},R=(r,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Z(t))!J.call(r,o)&&o!==s&&k(r,o,{get:()=>t[o],enumerable:!(n=K(t,o))||n.enumerable});return r};var C=(r,t,s)=>(s=r!=null?F(B(r)):{},R(t||!r||!r.__esModule?k(s,"default",{value:r,enumerable:!0}):s,r)),V=r=>R(k({},"__esModule",{value:!0}),r);var re={};Q(re,{GeocodeAbortError:()=>T,default:()=>te,geocode:()=>O});module.exports=V(re);var v=C(require("minisearch")),z=C(require("latlon-geohash")),M=require("lru_map"),U=C(require("metaphone")),G=function(r,t=0){let s=3735928559^t,n=1103547991^t;for(let o=0,f;o>>16,2246822507)^Math.imul(n^n>>>13,3266489909),n=Math.imul(n^n>>>16,2246822507)^Math.imul(s^s>>>13,3266489909),4294967296*(2097151&n)+(s>>>0)},T=class extends Error{constructor(){super(),this.name="GeocodeAbortError"}},L=new URL("https://www.abc.net.au/res/sites/news-projects/geocoder/data/202208/"),N;async function _(){return N||(N=(async()=>{let t=await(await fetch(new URL("groups.json.gz",L).toString())).json();return new Set(t)})(),N)}var P=new Map,E=new WeakMap;async function $(r){let t=P.get(r);if(t)return t;let s=new AbortController;return t=(async()=>{let n=[],f=(await fetch(new URL(`${r}.txt.gz`,L).toString(),{signal:s.signal})).body?.getReader(),d=new TextDecoder("utf8"),l="",m=!1;for(;f&&!m;){let c=await f.read();m=c.done;let S=d.decode(c.value),i=l+S;l="";let p=i.split(` +`);for(let g=0;g{let c=[],S=await $(d);for(let i of S){let p=i.a.replace(/[^ -\w]/g,""),g=["","",[i.s,i.t,i.p].join(" ")];for(let e of i.b){g[1]=[e.l?"LOT ":"",e.m?e.n+"-"+e.m+" ":e.n+" ",i.a+" ",i.r?i.r:"",i.x?" "+i.x:""].join(""),g[0]=e.a??"";let a=g.filter(u=>!!u).join(", "),w=t.length===0||t.some(u=>u===e.n||u===e.m||u===i.p);if(w&&c.push({id:G(a),address:a,streetName:p,geohash:e.g,numericWords:e.m?[e.n,e.m,i.p]:[e.n,i.p]}),e.u&&t.length>0)for(let u in e.u){let y=e.u[u];u&&(u+=" ");for(let h of y)if(Array.isArray(h)&&h.length===2){for(let b=h[0];b<=h[1];b++)if(w||t.some(D=>D===b)){let D=u+b+", "+a;c.push({id:G(D),address:D,streetName:p,geohash:e.g,numericWords:e.m?[b,e.n,e.m,+i.p]:[b,e.n,+i.p]})}}else if(w||t.some(A=>A===h)){let A=u+h+", "+a;c.push({id:G(A),address:A,streetName:p,geohash:e.g,numericWords:e.m?[h,e.n,e.m,+i.p]:[h,e.n,+i.p]})}}}}return c})(),I.set(d,m)),n.push(m)}let o=new Map,f=await Promise.all(n);for(let d of f){for(let l of d)o.set(l.id,l);if(o.size>1e4)break}return Array.from(o.values())}var Y=new Set(["NSW","VIC","QLD","WA","SA","TAS","ACT","NT"]),ee=r=>r.toUpperCase().replace(/(^|[^A-Z])(['A-Z]+)/g,(t,s,n)=>{let o=Y.has(n)?n:n.substring(0,1)+n.substring(1).toLowerCase();return s+o}),j="",x,W=new M.LRUMap(100);async function O(r,t={}){let s=Date.now(),n=r.toUpperCase().replace(/[^-A-Z0-9\/,\. ]/g,"").replace(/[^A-Z0-9]+/g," ").trim(),o=W.get(n);if(o)return{input:r,results:o,startTime:s,duration:Date.now()-s};let f=n.split(" ").map(e=>isFinite(+e)?+e:e),d=[],l=[];f.forEach(e=>(typeof e=="number"||/\d/.test(e)?l:d).push(e));let m=new Set(l.map(e=>(typeof e=="number"?e:+e.replace(/[^\d]/g,""))%20)),c=new Set,S=await _();for(let e of d){let a=e.substring(0,1),w=(0,U.default)(e);if(m.size>0){let u=w.substring(0,2);for(let y of m){let h=[a,y,u].join("/");S.has(h)&&c.add(h)}}else{let u=w.substring(0,3),y=[a,"_",u].join("/");S.has(y)&&c.add(y)}}let i=[...Array.from(c.values()),...l].sort().join(" ");if(!x||j!==i){j=i;let e;try{e=await X(Array.from(c.values()),l,t.abortPrevious??!1)}catch(a){throw t.abortPrevious&&a instanceof DOMException&&a.name==="AbortError"?new T:a}x=new v.default({fields:["address","streetName"],storeFields:["address","geohash"]}),e&&x.documentCount===0&&x.addAll(e)}o=[];let p=x.search(r,{fuzzy:e=>/\d/.test(e)?!1:.333,prefix:e=>!/\d/.test(e),weights:{fuzzy:.25,prefix:.5},boost:{streetName:2},maxFuzzy:4}),g=p[0]?.score>0;for(let e of p){if(e.score===0&&g)break;let a=z.default.decode(e.geohash);if(o.push({address:ee(e.address),latitude:a.lat,longitude:a.lon,score:e.score,id:e.id}),o.length===t.limit)break}return W.set(n,o),{input:r,results:o,startTime:s,duration:Date.now()-s}}var te=O;0&&(module.exports={GeocodeAbortError,geocode}); diff --git a/dist/geocode.mjs b/dist/geocode.mjs index 6cfd51a..6863c88 100644 --- a/dist/geocode.mjs +++ b/dist/geocode.mjs @@ -1,227 +1,2 @@ -var __getOwnPropNames = Object.getOwnPropertyNames; -var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; -}; - -// groups.json -var require_groups = __commonJS({ - "groups.json"(exports, module) { - module.exports = ["1MLH", "30PR", "3LK", "4AK", "4T", "AA", "AA0B", "AA0L", "AA0N", "AA0R", "AA0S", "AAB", "AABB", "AABF", "AABH", "AABJ", "AABK", "AABL", "AABM", "AABN", "AABP", "AABR", "AABS", "AABT", "AABW", "AABY", "AAF", "AAFB", "AAFF", "AAFK", "AAFL", "AAFM", "AAFN", "AAFR", "AAFS", "AAFT", "AAFW", "AAFX", "AAHN", "AAHR", "AAJ", "AAJK", "AAJL", "AAJN", "AAJR", "AAJS", "AAJT", "AAK", "AAK0", "AAKB", "AAKF", "AAKH", "AAKK", "AAKL", "AAKM", "AAKN", "AAKP", "AAKR", "AAKS", "AAKT", "AAKW", "AAKX", "AAL", "AAL0", "AALB", "AALF", "AALH", "AALJ", "AALK", "AALL", "AALM", "AALN", "AALP", "AALR", "AALS", "AALT", "AALW", "AALX", "AALY", "AAM", "AAM0", "AAMB", "AAMF", "AAMH", "AAMJ", "AAMK", "AAML", "AAMM", "AAMN", "AAMP", "AAMR", "AAMS", "AAMT", "AAMW", "AAMX", "AAMY", "AAN", "AAN0", "AANB", "AANF", "AANH", "AANJ", "AANK", "AANL", "AANM", "AANN", "AANP", "AANR", "AANS", "AANT", "AANW", "AANX", "AANY", "AAP", "AAPJ", "AAPK", "AAPL", "AAPM", "AAPN", "AAPP", "AAPR", "AAPS", "AAPT", "AAPX", "AAR", "AAR0", "AARB", "AARF", "AARH", "AARJ", "AARK", "AARL", "AARM", "AARN", "AARP", "AARR", "AARS", "AART", "AARW", "AARX", "AARY", "AAS", "AAS0", "AASB", "AASF", "AASH", "AASK", "AASL", "AASM", "AASN", "AASP", "AASR", "AASS", "AAST", "AASW", "AASX", "AAT", "AATB", "AATF", "AATH", "AATJ", "AATK", "AATL", "AATM", "AATN", "AATP", "AATR", "AATS", "AATT", "AATW", "AATX", "AATY", "AAW", "AAWB", "AAWL", "AAWN", "AAWR", "AAWS", "AAWT", "AAX", "AAXB", "AAXF", "AAXK", "AAXL", "AAXM", "AAXN", "AAXP", "AAXR", "AAXS", "AAXT", "AAXW", "AAXY", "AAY", "AAYB", "AAYL", "AAYM", "AAYN", "AAYP", "AAYR", "AAYS", "AAYW", "AAYX", "AE0L", "AEJN", "AEJR", "AEL", "AELN", "AELS", "AEML", "AENN", "AER", "AERK", "AERL", "AERN", "AERP", "AERT", "AESP", "AESX", "BB", "BB0", "BB0B", "BB0F", "BB0K", "BB0L", "BB0M", "BB0N", "BB0P", "BB0R", "BB0S", "BB0T", "BB0W", "BB0X", "BBB", "BBBB", "BBBH", "BBBJ", "BBBK", "BBBL", "BBBM", "BBBN", "BBBR", "BBBS", "BBBT", "BBBW", "BBBX", "BBBY", "BBF", "BBFF", "BBFH", "BBFK", "BBFL", "BBFN", "BBFP", "BBFR", "BBFS", "BBFT", "BBFW", "BBFX", "BBH", "BBHF", "BBHK", "BBHL", "BBHM", "BBHN", "BBHR", "BBHS", "BBHT", "BBHW", "BBHX", "BBJ", "BBJB", "BBJJ", "BBJK", "BBJL", "BBJM", "BBJN", "BBJR", "BBJS", "BBJT", "BBJW", "BBK", "BBK0", "BBKB", "BBKF", "BBKH", "BBKJ", "BBKK", "BBKL", "BBKM", "BBKN", "BBKP", "BBKR", "BBKS", "BBKT", "BBKW", "BBKX", "BBKY", "BBL", "BBL0", "BBLB", "BBLF", "BBLH", "BBLJ", "BBLK", "BBLL", "BBLM", "BBLN", "BBLP", "BBLR", "BBLS", "BBLT", "BBLW", "BBLX", "BBLY", "BBM", "BBM0", "BBMB", "BBMF", "BBMJ", "BBMK", "BBML", "BBMM", "BBMN", "BBMP", "BBMR", "BBMS", "BBMT", "BBMW", "BBMX", "BBN", "BBN0", "BBNB", "BBNF", "BBNH", "BBNJ", "BBNK", "BBNL", "BBNM", "BBNN", "BBNP", "BBNR", "BBNS", "BBNT", "BBNW", "BBNX", "BBNY", "BBP", "BBPL", "BBPM", "BBPN", "BBPP", "BBPR", "BBPS", "BBPT", "BBPX", "BBR", "BBR0", "BBRB", "BBRF", "BBRH", "BBRJ", "BBRK", "BBRL", "BBRM", "BBRN", "BBRP", "BBRR", "BBRS", "BBRT", "BBRW", "BBRX", "BBRY", "BBS", "BBS0", "BBSB", "BBSF", "BBSH", "BBSJ", "BBSK", "BBSL", "BBSM", "BBSN", "BBSP", "BBSR", "BBSS", "BBST", "BBSW", "BBSX", "BBT", "BBT0", "BBTB", "BBTF", "BBTH", "BBTJ", "BBTK", "BBTL", "BBTM", "BBTN", "BBTP", "BBTR", "BBTS", "BBTT", "BBTW", "BBTX", "BBTY", "BBW", "BBWK", "BBWL", "BBWN", "BBWR", "BBWS", "BBWT", "BBWY", "BBX", "BBXB", "BBXF", "BBXH", "BBXK", "BBXL", "BBXM", "BBXN", "BBXP", "BBXR", "BBXS", "BBXT", "BBXW", "BBXX", "BBY", "BBY0", "BBYB", "BBYH", "BBYJ", "BBYK", "BBYL", "BBYM", "BBYN", "BBYP", "BBYR", "BBYS", "BBYT", "BBYW", "BBYY", "CK", "CK0", "CK0B", "CK0K", "CK0L", "CK0M", "CK0N", "CK0R", "CK0S", "CK0T", "CK0W", "CKB", "CKBB", "CKBF", "CKBH", "CKBJ", "CKBK", "CKBL", "CKBM", "CKBN", "CKBR", "CKBS", "CKBT", "CKBW", "CKBX", "CKBY", "CKF", "CKFB", "CKFF", "CKFH", "CKFK", "CKFL", "CKFN", "CKFP", "CKFR", "CKFS", "CKFT", "CKFX", "CKH", "CKHL", "CKHN", "CKHR", "CKHT", "CKJ", "CKJB", "CKJK", "CKJL", "CKJN", "CKJP", "CKJR", "CKJT", "CKJW", "CKK", "CKK0", "CKKB", "CKKF", "CKKH", "CKKJ", "CKKK", "CKKL", "CKKM", "CKKN", "CKKP", "CKKR", "CKKS", "CKKT", "CKKW", "CKKX", "CKKY", "CKL", "CKL0", "CKLB", "CKLF", "CKLH", "CKLJ", "CKLK", "CKLL", "CKLM", "CKLN", "CKLP", "CKLR", "CKLS", "CKLT", "CKLW", "CKLX", "CKLY", "CKM", "CKMB", "CKMF", "CKMJ", "CKMK", "CKML", "CKMM", "CKMN", "CKMP", "CKMR", "CKMS", "CKMT", "CKMW", "CKMY", "CKN", "CKN0", "CKNB", "CKNF", "CKNH", "CKNJ", "CKNK", "CKNL", "CKNM", "CKNN", "CKNP", "CKNR", "CKNS", "CKNT", "CKNW", "CKNX", "CKNY", "CKP", "CKP0", "CKPB", "CKPF", "CKPH", "CKPJ", "CKPK", "CKPL", "CKPM", "CKPN", "CKPP", "CKPR", "CKPS", "CKPT", "CKPW", "CKPX", "CKPY", "CKR", "CKR0", "CKRB", "CKRF", "CKRH", "CKRJ", "CKRK", "CKRL", "CKRM", "CKRN", "CKRP", "CKRR", "CKRS", "CKRT", "CKRW", "CKRX", "CKRY", "CKS", "CKSB", "CKSF", "CKSH", "CKSJ", "CKSK", "CKSL", "CKSM", "CKSN", "CKSP", "CKSR", "CKSS", "CKST", "CKSW", "CKSX", "CKT", "CKT0", "CKTB", "CKTF", "CKTH", "CKTJ", "CKTK", "CKTL", "CKTM", "CKTN", "CKTP", "CKTR", "CKTS", "CKTT", "CKTW", "CKTX", "CKTY", "CKW", "CKWB", "CKWL", "CKWM", "CKWN", "CKWP", "CKWR", "CKWS", "CKWT", "CKX", "CKXB", "CKXF", "CKXH", "CKXK", "CKXL", "CKXM", "CKXN", "CKXP", "CKXR", "CKXS", "CKXT", "CKXW", "CKY", "CKYB", "CKYK", "CKYL", "CKYM", "CKYN", "CKYP", "CKYR", "CKYT", "CKYY", "CS0N", "CSB", "CSBL", "CSBR", "CSBS", "CSF", "CSFK", "CSFL", "CSFN", "CSFR", "CSFS", "CSFT", "CSJ", "CSKK", "CSKL", "CSKN", "CSKS", "CSKT", "CSKW", "CSKX", "CSL", "CSLB", "CSLF", "CSLH", "CSLK", "CSLM", "CSLN", "CSLR", "CSLS", "CSLT", "CSLW", "CSLX", "CSM", "CSML", "CSMN", "CSMR", "CSMS", "CSMT", "CSN", "CSN0", "CSNB", "CSNK", "CSNL", "CSNM", "CSNR", "CSNS", "CSNT", "CSNX", "CSP", "CSPL", "CSPR", "CSR", "CSRB", "CSRF", "CSRK", "CSRL", "CSRM", "CSRN", "CSRS", "CSRT", "CSSF", "CSSK", "CSSL", "CSSN", "CSSR", "CSSS", "CSST", "CST", "CSTB", "CSTF", "CSTH", "CSTK", "CSTL", "CSTM", "CSTN", "CSTP", "CSTR", "CSTS", "CSTT", "CSTW", "CSTX", "CSXL", "CSXN", "CSY0", "CSYN", "CX", "CX0M", "CXB", "CXBH", "CXBK", "CXBL", "CXBN", "CXBR", "CXBT", "CXF", "CXFK", "CXFL", "CXFM", "CXFN", "CXFP", "CXFR", "CXFS", "CXFT", "CXHL", "CXJ", "CXJS", "CXK", "CXKB", "CXKK", "CXKL", "CXKM", "CXKN", "CXKP", "CXKR", "CXKS", "CXKT", "CXKW", "CXKX", "CXL", "CXLB", "CXLF", "CXLH", "CXLK", "CXLM", "CXLN", "CXLP", "CXLR", "CXLS", "CXLT", "CXLW", "CXLY", "CXM", "CXMK", "CXML", "CXMM", "CXMN", "CXMP", "CXMR", "CXMS", "CXN", "CXN0", "CXNB", "CXNF", "CXNH", "CXNJ", "CXNK", "CXNL", "CXNM", "CXNN", "CXNP", "CXNR", "CXNS", "CXNT", "CXNW", "CXNX", "CXP", "CXPH", "CXPL", "CXPM", "CXPN", "CXPR", "CXPS", "CXPT", "CXPW", "CXPX", "CXR", "CXR0", "CXRB", "CXRF", "CXRH", "CXRJ", "CXRK", "CXRL", "CXRM", "CXRN", "CXRP", "CXRR", "CXRS", "CXRT", "CXRW", "CXRX", "CXS", "CXSB", "CXSF", "CXSL", "CXSM", "CXSN", "CXSP", "CXSR", "CXSS", "CXST", "CXSW", "CXT", "CXTB", "CXTF", "CXTK", "CXTL", "CXTM", "CXTN", "CXTR", "CXTS", "CXTW", "CXTX", "CXWB", "CXWL", "CXWN", "CXWR", "CXX", "CXXL", "CXXM", "CXXN", "CXXR", "CXXS", "CXYN", "DT", "DT0", "DT0H", "DT0R", "DT0S", "DT0T", "DT0W", "DTB", "DTBB", "DTBF", "DTBH", "DTBJ", "DTBK", "DTBL", "DTBM", "DTBN", "DTBP", "DTBR", "DTBS", "DTBT", "DTBW", "DTBX", "DTBY", "DTF", "DTFB", "DTFF", "DTFH", "DTFJ", "DTFK", "DTFL", "DTFM", "DTFN", "DTFP", "DTFR", "DTFS", "DTFT", "DTFX", "DTH", "DTHF", "DTHJ", "DTHK", "DTHL", "DTHM", "DTHN", "DTHR", "DTHT", "DTHY", "DTJ", "DTJB", "DTJH", "DTJJ", "DTJK", "DTJL", "DTJM", "DTJN", "DTJP", "DTJR", "DTJS", "DTJT", "DTK", "DTK0", "DTKB", "DTKF", "DTKH", "DTKK", "DTKL", "DTKM", "DTKN", "DTKP", "DTKR", "DTKS", "DTKT", "DTKW", "DTKX", "DTKY", "DTL", "DTL0", "DTLB", "DTLF", "DTLH", "DTLJ", "DTLK", "DTLL", "DTLM", "DTLN", "DTLP", "DTLR", "DTLS", "DTLT", "DTLW", "DTLX", "DTLY", "DTM", "DTMB", "DTMF", "DTMJ", "DTMK", "DTML", "DTMM", "DTMN", "DTMP", "DTMR", "DTMS", "DTMT", "DTMX", "DTMY", "DTN", "DTN0", "DTNB", "DTNF", "DTNH", "DTNJ", "DTNK", "DTNL", "DTNM", "DTNN", "DTNP", "DTNR", "DTNS", "DTNT", "DTNW", "DTNX", "DTNY", "DTP", "DTPB", "DTPF", "DTPK", "DTPL", "DTPM", "DTPN", "DTPP", "DTPR", "DTPS", "DTPT", "DTPW", "DTPX", "DTR", "DTR0", "DTRB", "DTRF", "DTRH", "DTRJ", "DTRK", "DTRL", "DTRM", "DTRN", "DTRP", "DTRR", "DTRS", "DTRT", "DTRW", "DTRX", "DTRY", "DTS", "DTS0", "DTSB", "DTSF", "DTSH", "DTSK", "DTSL", "DTSM", "DTSN", "DTSP", "DTSR", "DTSS", "DTST", "DTSW", "DTSX", "DTSY", "DTT", "DTTB", "DTTF", "DTTH", "DTTK", "DTTL", "DTTM", "DTTN", "DTTP", "DTTR", "DTTS", "DTTT", "DTTW", "DTW", "DTWK", "DTWL", "DTWN", "DTWR", "DTWS", "DTWT", "DTWX", "DTX", "DTXF", "DTXL", "DTXM", "DTXN", "DTXP", "DTXR", "DTXS", "DTXT", "DTXW", "DTY", "DTYL", "DTYM", "DTYN", "DTYR", "DTYS", "DTYT", "EE", "EE0", "EE0L", "EE0M", "EE0N", "EE0R", "EE0S", "EEB", "EEBL", "EEBN", "EEBR", "EEBS", "EEBT", "EEF", "EEF0", "EEFB", "EEFF", "EEFK", "EEFL", "EEFM", "EEFN", "EEFR", "EEFS", "EEFT", "EEFW", "EEFX", "EEHL", "EEHW", "EEJ", "EEJB", "EEJF", "EEJH", "EEJK", "EEJL", "EEJM", "EEJN", "EEJP", "EEJR", "EEJS", "EEJT", "EEJW", "EEK", "EEKB", "EEKF", "EEKH", "EEKK", "EEKL", "EEKM", "EEKN", "EEKP", "EEKR", "EEKS", "EEKT", "EEKX", "EEL", "EEL0", "EELB", "EELF", "EELH", "EELJ", "EELK", "EELL", "EELM", "EELN", "EELP", "EELR", "EELS", "EELT", "EELW", "EELX", "EELY", "EEM", "EEMB", "EEMF", "EEMH", "EEMJ", "EEMK", "EEML", "EEMM", "EEMN", "EEMP", "EEMR", "EEMS", "EEMT", "EEMW", "EEN", "EENB", "EENF", "EENH", "EENJ", "EENK", "EENL", "EENM", "EENN", "EENR", "EENS", "EENT", "EENX", "EENY", "EEP", "EEPF", "EEPK", "EEPL", "EEPN", "EEPR", "EEPS", "EEPT", "EEPW", "EER", "EER0", "EERB", "EERF", "EERH", "EERJ", "EERK", "EERL", "EERM", "EERN", "EERP", "EERR", "EERS", "EERT", "EERW", "EERX", "EERY", "EES", "EES0", "EESB", "EESK", "EESL", "EESM", "EESN", "EESP", "EESR", "EESS", "EEST", "EESX", "EET", "EET0", "EETB", "EETF", "EETH", "EETJ", "EETK", "EETL", "EETM", "EETN", "EETP", "EETR", "EETS", "EETT", "EETW", "EETX", "EETY", "EEW", "EEWL", "EEWN", "EEWR", "EEWS", "EEWT", "EEX", "EEXB", "EEXF", "EEXH", "EEXK", "EEXL", "EEXM", "EEXN", "EEXP", "EEXR", "EEXT", "EEYB", "EEYN", "EEYR", "FF", "FF0", "FF0F", "FF0L", "FF0M", "FF0R", "FFB", "FFBJ", "FFBK", "FFBL", "FFBN", "FFBR", "FFBS", "FFF", "FFF0", "FFFB", "FFFF", "FFFK", "FFFL", "FFFM", "FFFN", "FFFP", "FFFR", "FFFS", "FFFT", "FFFW", "FFFX", "FFH", "FFHL", "FFHN", "FFHS", "FFHT", "FFJ", "FFJN", "FFJR", "FFK", "FFKB", "FFKF", "FFKH", "FFKK", "FFKL", "FFKM", "FFKN", "FFKR", "FFKS", "FFKT", "FFKW", "FFKX", "FFL", "FFL0", "FFLB", "FFLF", "FFLH", "FFLJ", "FFLK", "FFLL", "FFLM", "FFLN", "FFLP", "FFLR", "FFLS", "FFLT", "FFLW", "FFLX", "FFLY", "FFM", "FFMB", "FFMK", "FFML", "FFMN", "FFMP", "FFMR", "FFMS", "FFMT", "FFMX", "FFN", "FFN0", "FFNB", "FFNF", "FFNH", "FFNJ", "FFNK", "FFNL", "FFNM", "FFNN", "FFNP", "FFNR", "FFNS", "FFNT", "FFNW", "FFNX", "FFPL", "FFR", "FFR0", "FFRB", "FFRF", "FFRH", "FFRJ", "FFRK", "FFRL", "FFRM", "FFRN", "FFRP", "FFRR", "FFRS", "FFRT", "FFRW", "FFRX", "FFRY", "FFS", "FFSB", "FFSF", "FFSK", "FFSL", "FFSN", "FFSR", "FFSS", "FFST", "FFSX", "FFT", "FFTB", "FFTK", "FFTL", "FFTM", "FFTN", "FFTP", "FFTR", "FFTS", "FFTT", "FFTW", "FFTX", "FFW", "FFWL", "FFWN", "FFWS", "FFWT", "FFX", "FFXB", "FFXF", "FFXH", "FFXK", "FFXL", "FFXM", "FFXN", "FFXP", "FFXR", "FFXS", "FFXT", "FFXW", "FFXX", "FFY", "FFYB", "FFYL", "FFYN", "FFYS", "FFYT", "GFKR", "GFLF", "GFLK", "GFLN", "GFLS", "GFN", "GFNF", "GFNN", "GFNT", "GFR", "GFRK", "GFRL", "GFRN", "GFRS", "GFSL", "GFSP", "GFST", "GFTL", "GJ", "GJ0N", "GJB", "GJBH", "GJBK", "GJBL", "GJBM", "GJBN", "GJBR", "GJBS", "GJBT", "GJF", "GJFB", "GJFF", "GJFK", "GJFL", "GJFN", "GJFR", "GJFS", "GJFT", "GJFW", "GJFX", "GJH", "GJHK", "GJHM", "GJHT", "GJJ", "GJJL", "GJJN", "GJJR", "GJJS", "GJJT", "GJJY", "GJK", "GJKB", "GJKK", "GJKL", "GJKM", "GJKN", "GJKR", "GJKS", "GJL", "GJLB", "GJLF", "GJLH", "GJLJ", "GJLK", "GJLL", "GJLM", "GJLN", "GJLP", "GJLR", "GJLS", "GJLT", "GJLW", "GJLX", "GJM", "GJMB", "GJMF", "GJMH", "GJMK", "GJML", "GJMN", "GJMP", "GJMR", "GJMS", "GJMW", "GJN", "GJN0", "GJNB", "GJNF", "GJNJ", "GJNK", "GJNL", "GJNM", "GJNN", "GJNR", "GJNS", "GJNT", "GJNX", "GJP", "GJPN", "GJPR", "GJPS", "GJPT", "GJR", "GJR0", "GJRB", "GJRF", "GJRH", "GJRJ", "GJRK", "GJRL", "GJRM", "GJRN", "GJRR", "GJRS", "GJRT", "GJRW", "GJRX", "GJS", "GJSB", "GJSK", "GJSL", "GJSM", "GJSN", "GJSP", "GJSR", "GJST", "GJT", "GJTB", "GJTF", "GJTJ", "GJTL", "GJTN", "GJTP", "GJTR", "GJTS", "GJTT", "GJTW", "GJTX", "GJTY", "GJW", "GJWN", "GJX", "GJXL", "GJXM", "GJY", "GJYR", "GK", "GK0", "GK0K", "GK0L", "GK0M", "GK0N", "GK0R", "GK0S", "GK0W", "GKB", "GKBB", "GKBK", "GKBL", "GKBN", "GKBR", "GKBS", "GKBT", "GKBW", "GKBX", "GKBY", "GKF", "GKFJ", "GKFK", "GKFL", "GKFN", "GKFR", "GKFS", "GKFT", "GKHK", "GKHL", "GKHN", "GKHR", "GKJ", "GKJK", "GKJL", "GKJN", "GKJR", "GKJS", "GKJT", "GKK", "GKKK", "GKKL", "GKKM", "GKKN", "GKKP", "GKKR", "GKKS", "GKKT", "GKKX", "GKL", "GKL0", "GKLB", "GKLF", "GKLH", "GKLJ", "GKLK", "GKLL", "GKLM", "GKLN", "GKLP", "GKLR", "GKLS", "GKLT", "GKLW", "GKLX", "GKLY", "GKM", "GKMB", "GKMF", "GKMH", "GKMJ", "GKMK", "GKML", "GKMM", "GKMN", "GKMP", "GKMR", "GKMS", "GKMT", "GKMW", "GKMY", "GKN", "GKN0", "GKNB", "GKNF", "GKNH", "GKNJ", "GKNK", "GKNL", "GKNM", "GKNN", "GKNP", "GKNR", "GKNS", "GKNT", "GKNW", "GKNX", "GKNY", "GKP", "GKPB", "GKPF", "GKPH", "GKPK", "GKPL", "GKPP", "GKPR", "GKPS", "GKPW", "GKR", "GKR0", "GKRB", "GKRF", "GKRH", "GKRJ", "GKRK", "GKRL", "GKRM", "GKRN", "GKRP", "GKRR", "GKRS", "GKRT", "GKRW", "GKRX", "GKRY", "GKS", "GKS0", "GKSB", "GKSF", "GKSH", "GKSJ", "GKSK", "GKSL", "GKSM", "GKSN", "GKSP", "GKSR", "GKSS", "GKST", "GKSW", "GKSX", "GKT", "GKTB", "GKTF", "GKTH", "GKTJ", "GKTK", "GKTL", "GKTM", "GKTN", "GKTP", "GKTR", "GKTS", "GKTT", "GKTW", "GKTX", "GKTY", "GKW", "GKW0", "GKWB", "GKWL", "GKWM", "GKWN", "GKWR", "GKWT", "GKX", "GKXK", "GKXM", "GKXN", "GKXR", "GKXS", "GKY", "GKYK", "GKYM", "GKYN", "GKYR", "GKYT", "GNBR", "GNL", "GNLS", "GNLY", "GNNK", "GNNT", "GNR", "GNRB", "GNRK", "GNRL", "GNRM", "GNRN", "GNRP", "GNRW", "GNSH", "GNT", "GNTK", "GNTN", "GNWL", "GNWN", "H0", "H0RT", "HBL", "HBLS", "HBN", "HBN0", "HBNS", "HBRM", "HBRT", "HBST", "HFJL", "HFLT", "HFR", "HFRS", "HH", "HH0", "HH0B", "HH0F", "HH0H", "HH0K", "HH0L", "HH0M", "HH0N", "HH0P", "HH0R", "HH0S", "HH0T", "HH0W", "HHB", "HHBB", "HHBH", "HHBK", "HHBL", "HHBN", "HHBR", "HHBS", "HHBT", "HHBW", "HHBX", "HHBY", "HHF", "HHFB", "HHFF", "HHFH", "HHFJ", "HHFK", "HHFL", "HHFM", "HHFN", "HHFP", "HHFR", "HHFS", "HHFT", "HHFW", "HHFX", "HHH", "HHHN", "HHHR", "HHHS", "HHJ", "HHJF", "HHJL", "HHJM", "HHJN", "HHJR", "HHJS", "HHJT", "HHJW", "HHJY", "HHK", "HHKB", "HHKF", "HHKH", "HHKK", "HHKL", "HHKM", "HHKN", "HHKP", "HHKR", "HHKS", "HHKT", "HHKW", "HHKX", "HHL", "HHL0", "HHLB", "HHLF", "HHLH", "HHLJ", "HHLK", "HHLL", "HHLM", "HHLN", "HHLP", "HHLR", "HHLS", "HHLT", "HHLW", "HHLX", "HHLY", "HHM", "HHMB", "HHMF", "HHMH", "HHMJ", "HHMK", "HHML", "HHMM", "HHMN", "HHMP", "HHMR", "HHMS", "HHMT", "HHMW", "HHMX", "HHMY", "HHN", "HHN0", "HHNB", "HHNF", "HHNH", "HHNJ", "HHNK", "HHNL", "HHNM", "HHNN", "HHNP", "HHNR", "HHNS", "HHNT", "HHNW", "HHNX", "HHNY", "HHP", "HHP0", "HHPB", "HHPF", "HHPH", "HHPJ", "HHPK", "HHPL", "HHPM", "HHPN", "HHPP", "HHPR", "HHPS", "HHPT", "HHPW", "HHR", "HHR0", "HHRB", "HHRF", "HHRH", "HHRJ", "HHRK", "HHRL", "HHRM", "HHRN", "HHRP", "HHRR", "HHRS", "HHRT", "HHRW", "HHRX", "HHRY", "HHS", "HHS0", "HHSB", "HHSF", "HHSH", "HHSK", "HHSL", "HHSM", "HHSN", "HHSP", "HHSR", "HHSS", "HHST", "HHSW", "HHSX", "HHT", "HHTB", "HHTF", "HHTH", "HHTK", "HHTL", "HHTM", "HHTN", "HHTP", "HHTR", "HHTS", "HHTT", "HHTW", "HHTX", "HHTY", "HHW", "HHW0", "HHWK", "HHWL", "HHWN", "HHWR", "HHWS", "HHWT", "HHWX", "HHX", "HHXB", "HHXF", "HHXK", "HHXL", "HHXM", "HHXN", "HHXP", "HHXR", "HHXS", "HHXT", "HHXW", "HHY", "HHYK", "HHYN", "HHYR", "HHYS", "HJ", "HJR0", "HJRT", "HJT", "HKRF", "HLKL", "HLNT", "HLS", "HLTN", "HLTS", "HM0", "HMBS", "HMKS", "HMLR", "HMN", "HMNS", "HMS", "HMSB", "HMSS", "HMTS", "HMXL", "HN", "HNM", "HNMK", "HNS", "HNST", "HNTF", "HNTM", "HNTS", "HNX", "HPRN", "HPX", "HR", "HRBL", "HRM", "HRT", "HSKR", "HSLP", "HSM0", "HSN", "HSP", "HSTN", "HT", "HTBR", "HTFL", "HTHL", "HTHR", "HTKR", "HTN", "HTNL", "HTNM", "HTNN", "HTNS", "HTPR", "HTR", "HTRB", "HTRF", "HTRJ", "HTRL", "HTRN", "HTRS", "HTS", "HTSK", "HTSP", "HTTL", "HTTS", "HTWB", "HWLR", "HWLT", "HX", "HXRK", "HXRS", "HYLN", "HYM", "HYMS", "HYNT", "HYRN", "HYSN", "HYT", "HYTS", "II", "II0K", "II0M", "IIBB", "IIBK", "IIBL", "IIBR", "IIBS", "IIBT", "IIBY", "IIF", "IIF0", "IIFB", "IIFF", "IIFH", "IIFK", "IIFL", "IIFM", "IIFN", "IIFR", "IIFS", "IIFT", "IIHF", "IIJB", "IIJN", "IIJR", "IIJS", "IIK", "IIKK", "IIKL", "IIKN", "IIKR", "IIKS", "IIKT", "IIKW", "IIL", "IILB", "IILF", "IILH", "IILJ", "IILK", "IILL", "IILM", "IILN", "IILP", "IILR", "IILS", "IILT", "IILW", "IILX", "IILY", "IIM", "IIMF", "IIMH", "IIMJ", "IIMK", "IIML", "IIMN", "IIMP", "IIMR", "IIMS", "IIMT", "IIMY", "IIN", "IIN0", "IINB", "IINF", "IINH", "IINJ", "IINK", "IINL", "IINM", "IINN", "IINP", "IINR", "IINS", "IINT", "IINW", "IINX", "IINY", "IIP", "IIPL", "IIPM", "IIPN", "IIPR", "IIPS", "IIPT", "IIR", "IIRB", "IIRF", "IIRJ", "IIRK", "IIRL", "IIRM", "IIRN", "IIRP", "IIRR", "IIRS", "IIRT", "IIRW", "IIRX", "IIS", "IISB", "IISF", "IISK", "IISL", "IISM", "IISN", "IISP", "IISR", "IISS", "IIST", "IISW", "IISX", "IIT", "IITB", "IITF", "IITH", "IITJ", "IITK", "IITL", "IITM", "IITN", "IITR", "IITS", "IITT", "IITW", "IIW", "IIWN", "IIWR", "IIWS", "IIWT", "IIX", "IIXB", "IIXL", "IIXM", "IIXN", "IIXR", "IIXT", "IIYP", "JJ", "JJ0", "JJ0R", "JJ0W", "JJB", "JJBF", "JJBJ", "JJBK", "JJBL", "JJBN", "JJBR", "JJBS", "JJBT", "JJBW", "JJF", "JJFH", "JJFJ", "JJFK", "JJFL", "JJFN", "JJFR", "JJFS", "JJFX", "JJH", "JJHK", "JJHL", "JJHN", "JJHP", "JJHR", "JJHS", "JJJ", "JJJH", "JJJL", "JJJN", "JJJR", "JJJS", "JJJT", "JJK", "JJK0", "JJKB", "JJKF", "JJKH", "JJKJ", "JJKK", "JJKL", "JJKM", "JJKN", "JJKP", "JJKR", "JJKS", "JJKT", "JJKW", "JJL", "JJLB", "JJLF", "JJLJ", "JJLK", "JJLL", "JJLM", "JJLN", "JJLP", "JJLR", "JJLS", "JJLT", "JJLW", "JJLY", "JJM", "JJMB", "JJMF", "JJMH", "JJMJ", "JJMK", "JJML", "JJMM", "JJMN", "JJMP", "JJMR", "JJMS", "JJMT", "JJMW", "JJMX", "JJN", "JJN0", "JJNB", "JJNF", "JJNH", "JJNJ", "JJNK", "JJNL", "JJNM", "JJNN", "JJNP", "JJNR", "JJNS", "JJNT", "JJNW", "JJNX", "JJNY", "JJP", "JJPJ", "JJPK", "JJPL", "JJPN", "JJPR", "JJPS", "JJPT", "JJPX", "JJR", "JJRB", "JJRF", "JJRJ", "JJRK", "JJRL", "JJRM", "JJRN", "JJRP", "JJRR", "JJRS", "JJRT", "JJRW", "JJRX", "JJS", "JJSB", "JJSF", "JJSH", "JJSJ", "JJSK", "JJSL", "JJSM", "JJSN", "JJSP", "JJSR", "JJSS", "JJST", "JJSW", "JJSX", "JJT", "JJT0", "JJTB", "JJTF", "JJTJ", "JJTK", "JJTL", "JJTM", "JJTN", "JJTP", "JJTR", "JJTS", "JJTT", "JJTX", "JJW", "JJWK", "JJWL", "JJWN", "JJWR", "JJWS", "JJWT", "JJX", "JJXK", "JJXM", "JJXN", "JJXR", "JJXS", "JJY", "JJYF", "JJYL", "JJYN", "JJYR", "JJYS", "KK", "KK0", "KK0B", "KK0F", "KK0H", "KK0J", "KK0K", "KK0L", "KK0M", "KK0N", "KK0P", "KK0R", "KK0S", "KK0T", "KK0W", "KK0X", "KKB", "KKBB", "KKBJ", "KKBK", "KKBL", "KKBN", "KKBR", "KKBS", "KKBT", "KKBX", "KKBY", "KKF", "KKFB", "KKFK", "KKFL", "KKFM", "KKFN", "KKFP", "KKFR", "KKFS", "KKFT", "KKH", "KKHB", "KKHL", "KKHM", "KKHN", "KKHP", "KKHR", "KKHS", "KKHT", "KKHY", "KKJ", "KKJB", "KKJK", "KKJL", "KKJN", "KKJR", "KKJS", "KKJT", "KKJY", "KKK", "KKK0", "KKKB", "KKKK", "KKKL", "KKKM", "KKKN", "KKKP", "KKKR", "KKKS", "KKKT", "KKKW", "KKKY", "KKL", "KKL0", "KKLB", "KKLF", "KKLH", "KKLJ", "KKLK", "KKLL", "KKLM", "KKLN", "KKLP", "KKLR", "KKLS", "KKLT", "KKLW", "KKLX", "KKLY", "KKM", "KKM0", "KKMB", "KKMF", "KKMH", "KKMJ", "KKMK", "KKML", "KKMM", "KKMN", "KKMP", "KKMR", "KKMS", "KKMT", "KKMX", "KKN", "KKN0", "KKNB", "KKNF", "KKNH", "KKNJ", "KKNK", "KKNL", "KKNM", "KKNN", "KKNP", "KKNR", "KKNS", "KKNT", "KKNW", "KKNX", "KKNY", "KKP", "KKPB", "KKPF", "KKPH", "KKPK", "KKPL", "KKPM", "KKPN", "KKPR", "KKPS", "KKPT", "KKPW", "KKPX", "KKPY", "KKR", "KKR0", "KKRB", "KKRF", "KKRH", "KKRJ", "KKRK", "KKRL", "KKRM", "KKRN", "KKRP", "KKRR", "KKRS", "KKRT", "KKRW", "KKRX", "KKRY", "KKS", "KKS0", "KKSB", "KKSF", "KKSK", "KKSL", "KKSM", "KKSN", "KKSP", "KKSR", "KKSS", "KKST", "KKSW", "KKSX", "KKSY", "KKT", "KKTB", "KKTF", "KKTH", "KKTJ", "KKTK", "KKTL", "KKTM", "KKTN", "KKTP", "KKTR", "KKTS", "KKTT", "KKTW", "KKTX", "KKTY", "KKW", "KKWB", "KKWF", "KKWH", "KKWK", "KKWL", "KKWN", "KKWR", "KKWS", "KKWT", "KKWW", "KKWX", "KKX", "KKXF", "KKXJ", "KKXK", "KKXL", "KKXM", "KKXN", "KKXR", "KKXS", "KKY", "KKYB", "KKYK", "KKYL", "KKYM", "KKYN", "KKYP", "KKYR", "KKYS", "KKYT", "KKYW", "KN", "KN0", "KNB", "KNBK", "KNBL", "KNBN", "KNBS", "KNBW", "KNF", "KNFL", "KNFT", "KNK", "KNKB", "KNKF", "KNKL", "KNKP", "KNKR", "KNKS", "KNKT", "KNL", "KNLB", "KNLJ", "KNLM", "KNLN", "KNLR", "KNLS", "KNLT", "KNLW", "KNN", "KNNJ", "KNNK", "KNP", "KNPH", "KNPK", "KNPM", "KNPS", "KNPT", "KNPW", "KNR", "KNRH", "KNS", "KNSL", "KNST", "KNT", "KNTL", "KNTN", "KNTR", "KNTS", "KNTW", "KNW", "KNWN", "KNX", "KNYR", "LL", "LL0", "LL0B", "LL0F", "LL0J", "LL0K", "LL0L", "LL0M", "LL0N", "LL0P", "LL0R", "LL0S", "LL0T", "LL0W", "LLB", "LLB0", "LLBB", "LLBH", "LLBJ", "LLBK", "LLBL", "LLBM", "LLBN", "LLBR", "LLBS", "LLBT", "LLBW", "LLBX", "LLBY", "LLF", "LLF0", "LLFB", "LLFF", "LLFH", "LLFJ", "LLFK", "LLFL", "LLFM", "LLFN", "LLFP", "LLFR", "LLFS", "LLFT", "LLFW", "LLFX", "LLFY", "LLH", "LLHF", "LLHL", "LLHM", "LLHN", "LLHR", "LLHS", "LLHT", "LLJ", "LLJB", "LLJF", "LLJK", "LLJL", "LLJM", "LLJN", "LLJP", "LLJR", "LLJS", "LLJT", "LLJW", "LLJY", "LLK", "LLKB", "LLKF", "LLKH", "LLKJ", "LLKK", "LLKL", "LLKM", "LLKN", "LLKP", "LLKR", "LLKS", "LLKT", "LLKW", "LLKX", "LLKY", "LLL", "LLL0", "LLLB", "LLLF", "LLLH", "LLLJ", "LLLK", "LLLL", "LLLM", "LLLN", "LLLP", "LLLR", "LLLS", "LLLT", "LLLW", "LLLX", "LLLY", "LLM", "LLM0", "LLMB", "LLMF", "LLMH", "LLMJ", "LLMK", "LLML", "LLMM", "LLMN", "LLMP", "LLMR", "LLMS", "LLMT", "LLMW", "LLMX", "LLMY", "LLN", "LLN0", "LLNB", "LLNF", "LLNH", "LLNJ", "LLNK", "LLNL", "LLNM", "LLNN", "LLNP", "LLNR", "LLNS", "LLNT", "LLNW", "LLNX", "LLNY", "LLP", "LLP0", "LLPF", "LLPJ", "LLPK", "LLPL", "LLPM", "LLPN", "LLPR", "LLPS", "LLPT", "LLPW", "LLPX", "LLR", "LLR0", "LLRB", "LLRF", "LLRH", "LLRJ", "LLRK", "LLRL", "LLRM", "LLRN", "LLRP", "LLRR", "LLRS", "LLRT", "LLRW", "LLRX", "LLS", "LLSB", "LLSF", "LLSH", "LLSJ", "LLSK", "LLSL", "LLSM", "LLSN", "LLSP", "LLSR", "LLSS", "LLST", "LLSW", "LLSX", "LLSY", "LLT", "LLTB", "LLTF", "LLTH", "LLTJ", "LLTK", "LLTL", "LLTM", "LLTN", "LLTP", "LLTR", "LLTS", "LLTT", "LLTW", "LLTX", "LLTY", "LLW", "LLWK", "LLWL", "LLWN", "LLWR", "LLWS", "LLWT", "LLWX", "LLX", "LLXB", "LLXF", "LLXK", "LLXL", "LLXM", "LLXN", "LLXP", "LLXR", "LLXS", "LLXT", "LLXW", "LLY", "LLYK", "LLYL", "LLYM", "LLYN", "LLYR", "LLYT", "MM", "MM0", "MM0F", "MM0H", "MM0K", "MM0L", "MM0M", "MM0N", "MM0R", "MM0S", "MM0T", "MM0W", "MMB", "MMBH", "MMBJ", "MMBK", "MMBL", "MMBN", "MMBR", "MMBS", "MMBT", "MMBX", "MMF", "MMFH", "MMFJ", "MMFK", "MMFL", "MMFM", "MMFN", "MMFR", "MMFS", "MMFT", "MMH", "MMHB", "MMHF", "MMHH", "MMHK", "MMHL", "MMHM", "MMHN", "MMHR", "MMHS", "MMHT", "MMJ", "MMJB", "MMJF", "MMJK", "MMJL", "MMJM", "MMJN", "MMJP", "MMJR", "MMJS", "MMJT", "MMJW", "MMJY", "MMK", "MMK0", "MMKB", "MMKF", "MMKH", "MMKJ", "MMKK", "MMKL", "MMKM", "MMKN", "MMKP", "MMKR", "MMKS", "MMKT", "MMKW", "MMKX", "MMKY", "MML", "MML0", "MMLB", "MMLF", "MMLH", "MMLJ", "MMLK", "MMLL", "MMLM", "MMLN", "MMLP", "MMLR", "MMLS", "MMLT", "MMLW", "MMLX", "MMLY", "MMM", "MMM0", "MMMB", "MMMF", "MMMH", "MMMK", "MMML", "MMMM", "MMMN", "MMMP", "MMMR", "MMMS", "MMMT", "MMMW", "MMMX", "MMN", "MMN0", "MMNB", "MMNF", "MMNH", "MMNJ", "MMNK", "MMNL", "MMNM", "MMNN", "MMNP", "MMNR", "MMNS", "MMNT", "MMNW", "MMNX", "MMNY", "MMP", "MMPK", "MMPL", "MMPN", "MMPR", "MMPS", "MMPT", "MMPW", "MMPY", "MMR", "MMR0", "MMRB", "MMRF", "MMRH", "MMRJ", "MMRK", "MMRL", "MMRM", "MMRN", "MMRP", "MMRR", "MMRS", "MMRT", "MMRW", "MMRX", "MMRY", "MMS", "MMS0", "MMSB", "MMSF", "MMSH", "MMSJ", "MMSK", "MMSL", "MMSM", "MMSN", "MMSP", "MMSR", "MMSS", "MMST", "MMSW", "MMSX", "MMSY", "MMT", "MMTB", "MMTF", "MMTH", "MMTJ", "MMTK", "MMTL", "MMTM", "MMTN", "MMTP", "MMTR", "MMTS", "MMTT", "MMTW", "MMTX", "MMTY", "MMW", "MMWB", "MMWK", "MMWL", "MMWM", "MMWN", "MMWR", "MMWS", "MMWT", "MMX", "MMXB", "MMXF", "MMXK", "MMXL", "MMXM", "MMXN", "MMXP", "MMXR", "MMXS", "MMXT", "MMXW", "MMXX", "MMY", "MMYB", "MMYK", "MMYL", "MMYM", "MMYN", "MMYP", "MMYR", "MMYS", "MMYT", "NN", "NN0", "NN0B", "NN0F", "NN0L", "NN0M", "NN0N", "NN0R", "NN0S", "NN0T", "NN0X", "NNB", "NNB0", "NNBH", "NNBJ", "NNBK", "NNBL", "NNBN", "NNBP", "NNBR", "NNBS", "NNBT", "NNBW", "NNBX", "NNF", "NNF0", "NNFB", "NNFH", "NNFJ", "NNFK", "NNFL", "NNFN", "NNFR", "NNFS", "NNFT", "NNFX", "NNH0", "NNHF", "NNHK", "NNHL", "NNHM", "NNHN", "NNHR", "NNJ", "NNJB", "NNJL", "NNJM", "NNJN", "NNJR", "NNJY", "NNK", "NNKB", "NNKJ", "NNKK", "NNKL", "NNKM", "NNKN", "NNKP", "NNKR", "NNKS", "NNKT", "NNKW", "NNKX", "NNKY", "NNL", "NNL0", "NNLB", "NNLF", "NNLH", "NNLJ", "NNLK", "NNLL", "NNLM", "NNLN", "NNLP", "NNLR", "NNLS", "NNLT", "NNLW", "NNLX", "NNLY", "NNM", "NNM0", "NNMF", "NNMJ", "NNMK", "NNML", "NNMN", "NNMP", "NNMR", "NNMS", "NNMT", "NNMW", "NNMX", "NNMY", "NNN", "NNN0", "NNNB", "NNNF", "NNNH", "NNNJ", "NNNK", "NNNL", "NNNM", "NNNN", "NNNP", "NNNR", "NNNS", "NNNT", "NNNW", "NNNX", "NNNY", "NNP", "NNP0", "NNPK", "NNPL", "NNPN", "NNPR", "NNPT", "NNR", "NNR0", "NNRB", "NNRF", "NNRH", "NNRJ", "NNRK", "NNRL", "NNRM", "NNRN", "NNRP", "NNRR", "NNRS", "NNRT", "NNRW", "NNRX", "NNRY", "NNS", "NNS0", "NNSB", "NNSF", "NNSK", "NNSL", "NNSM", "NNSN", "NNSP", "NNSR", "NNSS", "NNST", "NNSW", "NNSX", "NNT", "NNT0", "NNTB", "NNTF", "NNTH", "NNTJ", "NNTK", "NNTL", "NNTM", "NNTN", "NNTP", "NNTR", "NNTS", "NNTT", "NNTW", "NNTX", "NNTY", "NNW", "NNWK", "NNWL", "NNWN", "NNWR", "NNWS", "NNWT", "NNX", "NNXB", "NNXF", "NNXJ", "NNXK", "NNXL", "NNXM", "NNXN", "NNXP", "NNXR", "NNXS", "NNXT", "NNXW", "NNY", "NNYB", "NNYK", "NNYL", "NNYM", "NNYN", "NNYP", "NNYR", "NNYS", "NNYT", "NNYW", "NNYY", "OO", "OO0", "OO0K", "OO0L", "OO0N", "OO0W", "OOB", "OOBB", "OOBF", "OOBK", "OOBL", "OOBM", "OOBN", "OOBR", "OOBS", "OOBT", "OOF", "OOF0", "OOFB", "OOFF", "OOFH", "OOFK", "OOFL", "OOFM", "OOFN", "OOFP", "OOFR", "OOFS", "OOFT", "OOFW", "OOFX", "OOH", "OOHH", "OOHK", "OOHL", "OOHN", "OOHR", "OOJL", "OOJM", "OOJR", "OOK", "OOKB", "OOKF", "OOKH", "OOKJ", "OOKK", "OOKL", "OOKM", "OOKN", "OOKP", "OOKR", "OOKS", "OOKT", "OOKW", "OOKX", "OOL", "OOLB", "OOLF", "OOLK", "OOLL", "OOLM", "OOLN", "OOLP", "OOLR", "OOLS", "OOLT", "OOLW", "OOLY", "OOM", "OOMB", "OOMF", "OOMH", "OOMK", "OOML", "OOMM", "OOMN", "OOMR", "OOMT", "OOMX", "OON", "OON0", "OONF", "OONJ", "OONK", "OONL", "OONM", "OONN", "OONP", "OONR", "OONS", "OONT", "OONW", "OONX", "OONY", "OOP", "OOPK", "OOPL", "OOPN", "OOPR", "OOPS", "OOPT", "OOPW", "OOR", "OOR0", "OORB", "OORF", "OORJ", "OORK", "OORL", "OORM", "OORN", "OORP", "OORR", "OORS", "OORT", "OORW", "OORX", "OORY", "OOS", "OOSB", "OOSJ", "OOSK", "OOSL", "OOSM", "OOSN", "OOSP", "OOSR", "OOSS", "OOST", "OOSW", "OOSX", "OOT", "OOTB", "OOTF", "OOTH", "OOTK", "OOTL", "OOTM", "OOTN", "OOTP", "OOTR", "OOTS", "OOTT", "OOTW", "OOTY", "OOWN", "OOWR", "OOX", "OOXL", "OOXN", "OOXR", "OOXS", "OOXT", "OOYM", "OOYN", "PF", "PFB", "PFBS", "PFF", "PFFL", "PFKN", "PFL", "PFLB", "PFLH", "PFLK", "PFLM", "PFLN", "PFLP", "PFLR", "PFLS", "PFLT", "PFLW", "PFM", "PFN", "PFNK", "PFNS", "PFNT", "PFP", "PFPR", "PFPS", "PFR", "PFRL", "PFRS", "PFRW", "PFS", "PFSF", "PFSK", "PFSM", "PFSN", "PFTK", "PFTN", "PFTS", "PNMN", "PP", "PP0", "PP0B", "PP0F", "PP0J", "PP0K", "PP0M", "PP0N", "PP0R", "PP0S", "PPB", "PPBJ", "PPBK", "PPBL", "PPBM", "PPBN", "PPBR", "PPBS", "PPBT", "PPBW", "PPF", "PPFF", "PPFK", "PPFL", "PPFM", "PPFN", "PPFR", "PPFS", "PPFT", "PPH", "PPHL", "PPHN", "PPHS", "PPHT", "PPJ", "PPJB", "PPJK", "PPJL", "PPJM", "PPJN", "PPJR", "PPJS", "PPJT", "PPJW", "PPK", "PPK0", "PPKB", "PPKF", "PPKH", "PPKK", "PPKL", "PPKM", "PPKN", "PPKP", "PPKR", "PPKS", "PPKT", "PPKW", "PPKX", "PPL", "PPL0", "PPLB", "PPLF", "PPLH", "PPLJ", "PPLK", "PPLL", "PPLM", "PPLN", "PPLP", "PPLR", "PPLS", "PPLT", "PPLW", "PPLX", "PPLY", "PPM", "PPMF", "PPMJ", "PPMK", "PPML", "PPMM", "PPMN", "PPMP", "PPMR", "PPMS", "PPMT", "PPMW", "PPMX", "PPN", "PPN0", "PPNB", "PPNF", "PPNH", "PPNJ", "PPNK", "PPNL", "PPNM", "PPNN", "PPNP", "PPNR", "PPNS", "PPNT", "PPNW", "PPNX", "PPNY", "PPP", "PPP0", "PPPB", "PPPF", "PPPH", "PPPJ", "PPPK", "PPPL", "PPPN", "PPPP", "PPPR", "PPPS", "PPPT", "PPPW", "PPPY", "PPR", "PPR0", "PPRB", "PPRF", "PPRH", "PPRJ", "PPRK", "PPRL", "PPRM", "PPRN", "PPRP", "PPRR", "PPRS", "PPRT", "PPRW", "PPRX", "PPRY", "PPS", "PPS0", "PPSB", "PPSF", "PPSH", "PPSJ", "PPSK", "PPSL", "PPSM", "PPSN", "PPSP", "PPSR", "PPSS", "PPST", "PPSW", "PPSX", "PPT", "PPT0", "PPTB", "PPTF", "PPTH", "PPTJ", "PPTK", "PPTL", "PPTM", "PPTN", "PPTP", "PPTR", "PPTS", "PPTT", "PPTW", "PPTX", "PPTY", "PPW", "PPWL", "PPWN", "PPWR", "PPWS", "PPWT", "PPX", "PPXB", "PPXF", "PPXK", "PPXL", "PPXM", "PPXN", "PPXP", "PPXR", "PPXS", "PPXT", "PPXW", "PPY", "PPYL", "PPYN", "PPYP", "PPYR", "PPYS", "PPYT", "PPYW", "QK", "QKB0", "QKBK", "QKBN", "QKBR", "QKBS", "QKBT", "QKF", "QKFN", "QKFP", "QKFR", "QKFS", "QKFT", "QKH", "QKK", "QKKB", "QKKL", "QKKM", "QKKN", "QKKR", "QKKS", "QKL", "QKLB", "QKLJ", "QKLK", "QKLM", "QKLN", "QKLP", "QKLR", "QKLS", "QKLT", "QKLX", "QKM", "QKMB", "QKMK", "QKMN", "QKMS", "QKMT", "QKN", "QKNB", "QKNF", "QKNH", "QKNJ", "QKNK", "QKNL", "QKNM", "QKNN", "QKNS", "QKNT", "QKNW", "QKNX", "QKPL", "QKPR", "QKR", "QKRB", "QKRF", "QKRH", "QKRK", "QKRL", "QKRM", "QKRN", "QKRP", "QKRR", "QKRS", "QKRT", "QKS", "QKS0", "QKSN", "QKSR", "QKST", "QKT", "QKTF", "QKTJ", "QKTK", "QKTL", "QKTN", "QKTR", "QKTS", "QKTT", "QKX", "QKYR", "RR", "RR0", "RR0B", "RR0F", "RR0H", "RR0J", "RR0K", "RR0L", "RR0M", "RR0N", "RR0R", "RR0S", "RR0T", "RR0W", "RRB", "RRB0", "RRBB", "RRBF", "RRBH", "RRBJ", "RRBK", "RRBL", "RRBM", "RRBN", "RRBR", "RRBS", "RRBT", "RRBW", "RRBX", "RRBY", "RRF", "RRFB", "RRFF", "RRFH", "RRFJ", "RRFK", "RRFL", "RRFM", "RRFN", "RRFP", "RRFR", "RRFS", "RRFT", "RRFW", "RRFX", "RRH", "RRHB", "RRHF", "RRHK", "RRHL", "RRHM", "RRHN", "RRHP", "RRHR", "RRHS", "RRHT", "RRJ", "RRJF", "RRJH", "RRJK", "RRJL", "RRJM", "RRJN", "RRJP", "RRJR", "RRJS", "RRJT", "RRJW", "RRJY", "RRK", "RRKB", "RRKF", "RRKH", "RRKJ", "RRKK", "RRKL", "RRKM", "RRKN", "RRKP", "RRKR", "RRKS", "RRKT", "RRKW", "RRKX", "RRL", "RRLB", "RRLF", "RRLJ", "RRLK", "RRLM", "RRLN", "RRLP", "RRLR", "RRLS", "RRLT", "RRLW", "RRLX", "RRLY", "RRM", "RRMB", "RRMF", "RRMH", "RRMJ", "RRMK", "RRML", "RRMM", "RRMN", "RRMP", "RRMR", "RRMS", "RRMT", "RRMW", "RRMX", "RRMY", "RRN", "RRN0", "RRNB", "RRNF", "RRNH", "RRNJ", "RRNK", "RRNL", "RRNM", "RRNN", "RRNP", "RRNR", "RRNS", "RRNT", "RRNW", "RRNX", "RRNY", "RRP", "RRPB", "RRPF", "RRPH", "RRPK", "RRPL", "RRPN", "RRPR", "RRPS", "RRPT", "RRPX", "RRPY", "RRR", "RRRH", "RRRK", "RRRL", "RRRM", "RRRN", "RRRP", "RRRS", "RRRT", "RRRW", "RRS", "RRS0", "RRSB", "RRSF", "RRSH", "RRSJ", "RRSK", "RRSL", "RRSM", "RRSN", "RRSP", "RRSR", "RRSS", "RRST", "RRSW", "RRSX", "RRT", "RRT0", "RRTB", "RRTF", "RRTH", "RRTJ", "RRTK", "RRTL", "RRTM", "RRTN", "RRTP", "RRTR", "RRTS", "RRTT", "RRTW", "RRTX", "RRTY", "RRW", "RRWL", "RRWN", "RRWR", "RRWS", "RRWT", "RRX", "RRXB", "RRXF", "RRXK", "RRXL", "RRXM", "RRXN", "RRXR", "RRXS", "RRXT", "RRXW", "RRY", "RRYB", "RRYF", "RRYK", "RRYL", "RRYN", "RRYP", "RRYR", "RRYS", "RRYT", "SS", "SS0", "SS0B", "SS0F", "SS0H", "SS0J", "SS0K", "SS0L", "SS0M", "SS0N", "SS0P", "SS0R", "SS0S", "SS0T", "SS0W", "SS0X", "SS0Y", "SSB", "SSB0", "SSBK", "SSBL", "SSBM", "SSBN", "SSBR", "SSBS", "SSBT", "SSBW", "SSBX", "SSF", "SSFJ", "SSFK", "SSFL", "SSFM", "SSFN", "SSFP", "SSFR", "SSFS", "SSFT", "SSFY", "SSH", "SSH0", "SSHF", "SSHJ", "SSHK", "SSHL", "SSHM", "SSHN", "SSHR", "SSHS", "SSJ", "SSJB", "SSJF", "SSJH", "SSJJ", "SSJL", "SSJM", "SSJN", "SSJR", "SSJS", "SSJT", "SSJW", "SSK", "SSK0", "SSKB", "SSKF", "SSKH", "SSKK", "SSKL", "SSKM", "SSKN", "SSKP", "SSKR", "SSKS", "SSKT", "SSKW", "SSKX", "SSKY", "SSL", "SSL0", "SSLB", "SSLF", "SSLH", "SSLJ", "SSLK", "SSLL", "SSLM", "SSLN", "SSLP", "SSLR", "SSLS", "SSLT", "SSLW", "SSLX", "SSLY", "SSM", "SSM0", "SSMB", "SSMF", "SSMH", "SSMJ", "SSMK", "SSML", "SSMM", "SSMN", "SSMP", "SSMR", "SSMS", "SSMT", "SSMW", "SSMX", "SSMY", "SSN", "SSN0", "SSNB", "SSNF", "SSNH", "SSNJ", "SSNK", "SSNL", "SSNM", "SSNN", "SSNP", "SSNR", "SSNS", "SSNT", "SSNW", "SSNX", "SSNY", "SSP", "SSP0", "SSPB", "SSPF", "SSPJ", "SSPK", "SSPL", "SSPM", "SSPN", "SSPR", "SSPS", "SSPT", "SSPW", "SSPX", "SSR", "SSR0", "SSRB", "SSRF", "SSRH", "SSRJ", "SSRK", "SSRL", "SSRM", "SSRN", "SSRP", "SSRR", "SSRS", "SSRT", "SSRW", "SSRX", "SSRY", "SSS", "SSSB", "SSSF", "SSSJ", "SSSK", "SSSL", "SSSM", "SSSN", "SSSP", "SSSR", "SSSS", "SSST", "SSSW", "SSSX", "SSSY", "SST", "SST0", "SSTB", "SSTF", "SSTH", "SSTJ", "SSTK", "SSTL", "SSTM", "SSTN", "SSTP", "SSTR", "SSTS", "SSTT", "SSTW", "SSTX", "SSTY", "SSW", "SSW0", "SSWB", "SSWF", "SSWJ", "SSWK", "SSWL", "SSWM", "SSWN", "SSWP", "SSWR", "SSWS", "SSWT", "SSWX", "SSX", "SSXB", "SSXF", "SSXK", "SSXL", "SSXM", "SSXN", "SSXP", "SSXR", "SSXS", "SSXT", "SSXW", "SSXX", "SSY", "SSYN", "SSYR", "SSYS", "SX", "SX0B", "SX0R", "SX0T", "SXB", "SXBH", "SXBL", "SXBN", "SXBR", "SXBS", "SXF", "SXFL", "SXFM", "SXFN", "SXFR", "SXFS", "SXFT", "SXHN", "SXJM", "SXK", "SXKB", "SXKF", "SXKH", "SXKK", "SXKL", "SXKN", "SXKR", "SXKS", "SXKT", "SXKX", "SXL", "SXLB", "SXLF", "SXLH", "SXLK", "SXLL", "SXLM", "SXLN", "SXLP", "SXLR", "SXLS", "SXLT", "SXLW", "SXLX", "SXM", "SXMH", "SXMK", "SXML", "SXMN", "SXMR", "SXMS", "SXN", "SXNB", "SXNF", "SXNH", "SXNJ", "SXNK", "SXNL", "SXNN", "SXNP", "SXNR", "SXNS", "SXNT", "SXP", "SXPB", "SXPF", "SXPH", "SXPK", "SXPL", "SXPM", "SXPN", "SXPR", "SXPS", "SXPT", "SXPW", "SXPY", "SXR", "SXR0", "SXRB", "SXRF", "SXRH", "SXRJ", "SXRK", "SXRL", "SXRM", "SXRN", "SXRP", "SXRR", "SXRS", "SXRT", "SXRW", "SXRX", "SXS", "SXSF", "SXSK", "SXSM", "SXSP", "SXSR", "SXSS", "SXST", "SXT", "SXTB", "SXTF", "SXTH", "SXTK", "SXTL", "SXTN", "SXTP", "SXTR", "SXTS", "SXTT", "SXTW", "SXWL", "SXWR", "SXWT", "SXXN", "SXXT", "SXYR", "T0", "T00", "T0B", "T0BB", "T0BK", "T0BL", "T0BM", "T0BN", "T0BP", "T0BR", "T0BS", "T0BT", "T0BW", "T0BX", "T0F", "T0FF", "T0FK", "T0FL", "T0FN", "T0FR", "T0FS", "T0H0", "T0HB", "T0HF", "T0HL", "T0HM", "T0HR", "T0HT", "T0HX", "T0JB", "T0JK", "T0JN", "T0JP", "T0JR", "T0JS", "T0JT", "T0K", "T0KB", "T0KF", "T0KK", "T0KL", "T0KM", "T0KN", "T0KP", "T0KR", "T0KS", "T0KT", "T0KX", "T0L", "T0L0", "T0LB", "T0LF", "T0LJ", "T0LK", "T0LM", "T0LN", "T0LP", "T0LR", "T0LS", "T0LT", "T0LX", "T0LY", "T0M", "T0MJ", "T0MK", "T0ML", "T0MN", "T0MP", "T0MR", "T0MS", "T0MT", "T0MX", "T0N", "T0NB", "T0NF", "T0NJ", "T0NK", "T0NL", "T0NM", "T0NN", "T0NP", "T0NR", "T0NS", "T0NT", "T0NW", "T0NX", "T0P", "T0PF", "T0PK", "T0PL", "T0PN", "T0PP", "T0PR", "T0PS", "T0PT", "T0PX", "T0R", "T0RB", "T0RF", "T0RH", "T0RJ", "T0RK", "T0RL", "T0RM", "T0RN", "T0RP", "T0RR", "T0RS", "T0RT", "T0RW", "T0RX", "T0RY", "T0S", "T0S0", "T0SB", "T0SF", "T0SJ", "T0SK", "T0SL", "T0SM", "T0SN", "T0SP", "T0SR", "T0SS", "T0ST", "T0SW", "T0SX", "T0T", "T0TB", "T0TF", "T0TK", "T0TL", "T0TM", "T0TN", "T0TP", "T0TR", "T0TS", "T0TT", "T0TW", "T0W", "T0WF", "T0WL", "T0WN", "T0WR", "T0WT", "T0WX", "T0X", "T0XL", "T0XM", "T0XN", "T0XP", "T0XR", "T0XS", "T0XT", "T0Y", "T0YM", "T0YN", "T0YR", "T0YX", "TT", "TT0", "TT0L", "TT0M", "TT0R", "TT0S", "TTB", "TTB0", "TTBB", "TTBF", "TTBK", "TTBL", "TTBM", "TTBN", "TTBR", "TTBS", "TTBT", "TTBX", "TTF", "TTFF", "TTFH", "TTFK", "TTFL", "TTFM", "TTFN", "TTFR", "TTFS", "TTFT", "TTFW", "TTH", "TTHL", "TTHN", "TTHR", "TTHS", "TTHT", "TTHX", "TTJ", "TTJK", "TTJL", "TTJM", "TTJN", "TTJR", "TTJS", "TTJT", "TTJW", "TTK", "TTKB", "TTKF", "TTKH", "TTKK", "TTKL", "TTKM", "TTKN", "TTKP", "TTKR", "TTKS", "TTKT", "TTKW", "TTKY", "TTL", "TTL0", "TTLB", "TTLF", "TTLH", "TTLJ", "TTLK", "TTLL", "TTLM", "TTLN", "TTLP", "TTLR", "TTLS", "TTLT", "TTLW", "TTLX", "TTLY", "TTM", "TTM0", "TTMB", "TTMF", "TTMH", "TTMJ", "TTMK", "TTML", "TTMM", "TTMN", "TTMP", "TTMR", "TTMS", "TTMT", "TTMW", "TTMX", "TTMY", "TTN", "TTN0", "TTNB", "TTNF", "TTNH", "TTNJ", "TTNK", "TTNL", "TTNM", "TTNN", "TTNP", "TTNR", "TTNS", "TTNT", "TTNW", "TTNX", "TTNY", "TTP", "TTPB", "TTPF", "TTPH", "TTPK", "TTPL", "TTPM", "TTPN", "TTPP", "TTPR", "TTPS", "TTPT", "TTPW", "TTPX", "TTPY", "TTR", "TTR0", "TTRB", "TTRF", "TTRH", "TTRJ", "TTRK", "TTRL", "TTRM", "TTRN", "TTRP", "TTRR", "TTRS", "TTRT", "TTRW", "TTRX", "TTRY", "TTS", "TTSB", "TTSF", "TTSH", "TTSK", "TTSL", "TTSM", "TTSN", "TTSP", "TTSR", "TTSS", "TTST", "TTSW", "TTSX", "TTT", "TTTB", "TTTF", "TTTH", "TTTJ", "TTTK", "TTTL", "TTTM", "TTTN", "TTTP", "TTTR", "TTTS", "TTTT", "TTTW", "TTTX", "TTTY", "TTW", "TTW0", "TTWB", "TTWF", "TTWH", "TTWK", "TTWL", "TTWM", "TTWN", "TTWP", "TTWR", "TTWS", "TTWT", "TTWW", "TTWX", "TTX", "TTXB", "TTXF", "TTXK", "TTXL", "TTXN", "TTXR", "TTXS", "TTY", "TTYB", "TTYK", "TTYL", "TTYM", "TTYN", "TTYP", "TTYR", "TTYS", "TTYT", "TX", "TXBN", "TXFL", "TXLR", "TXM", "TXML", "TXN", "TXNR", "TXPS", "TXR", "TXRL", "TXRN", "TXTK", "UU0M", "UU0R", "UU0W", "UUB", "UUBB", "UUBR", "UUFL", "UUFM", "UUFN", "UUFR", "UUFS", "UUFT", "UUK", "UUKL", "UUKM", "UUKN", "UUKR", "UUKS", "UUKX", "UUL", "UUL0", "UULB", "UULF", "UULJ", "UULK", "UULL", "UULM", "UULN", "UULP", "UULR", "UULS", "UULT", "UULW", "UULY", "UUM", "UUMF", "UUMK", "UUML", "UUMN", "UUMP", "UUMR", "UUMW", "UUN", "UUN0", "UUNF", "UUNJ", "UUNK", "UUNL", "UUNM", "UUNN", "UUNP", "UUNR", "UUNS", "UUNT", "UUNW", "UUNY", "UUP0", "UUPF", "UUPL", "UUPM", "UUPN", "UUPR", "UUPS", "UUPT", "UUPW", "UUPX", "UUR", "UURB", "UURJ", "UURK", "UURL", "UURM", "UURN", "UURP", "UURR", "UURS", "UURT", "UURW", "UURX", "UUSK", "UUSL", "UUSN", "UUSR", "UUST", "UUT", "UUTJ", "UUTK", "UUTL", "UUTN", "UUTP", "UUTR", "UUTS", "UUTY", "UUW", "UUWL", "UUWR", "UUXK", "UUXR", "VF", "VFB", "VFBL", "VFBN", "VFBR", "VFF", "VFFH", "VFFK", "VFFL", "VFFN", "VFFR", "VFFS", "VFFT", "VFFX", "VFFY", "VFHL", "VFJ", "VFJF", "VFJL", "VFJM", "VFJN", "VFJS", "VFK", "VFKB", "VFKK", "VFKL", "VFKN", "VFKR", "VFKS", "VFKT", "VFKX", "VFL", "VFL0", "VFLB", "VFLF", "VFLH", "VFLJ", "VFLK", "VFLL", "VFLM", "VFLN", "VFLP", "VFLR", "VFLS", "VFLT", "VFLW", "VFLX", "VFM", "VFMN", "VFMP", "VFMR", "VFMS", "VFMT", "VFN", "VFN0", "VFNB", "VFNF", "VFNH", "VFNJ", "VFNK", "VFNL", "VFNM", "VFNN", "VFNP", "VFNR", "VFNS", "VFNT", "VFNW", "VFNX", "VFNY", "VFP", "VFPN", "VFPR", "VFR", "VFRB", "VFRF", "VFRH", "VFRJ", "VFRK", "VFRL", "VFRM", "VFRN", "VFRP", "VFRR", "VFRS", "VFRT", "VFRW", "VFRX", "VFRY", "VFS", "VFSF", "VFSH", "VFSJ", "VFSK", "VFSL", "VFSM", "VFSN", "VFSP", "VFSR", "VFST", "VFSX", "VFSY", "VFT", "VFTB", "VFTF", "VFTH", "VFTK", "VFTL", "VFTM", "VFTN", "VFTR", "VFTS", "VFTT", "VFTX", "VFWL", "VFWT", "VFX", "VFXN", "VFXR", "VFXS", "VFY", "VFYJ", "VFYL", "W", "W0BR", "W0S", "WBLN", "WBNK", "WBR", "WBRB", "WBRN", "WBRT", "WFL", "WFLK", "WFLS", "WFLT", "WFRN", "WHTR", "WJ", "WJBL", "WJMS", "WKHM", "WKHT", "WKKS", "WKLF", "WKLS", "WKLW", "WKM", "WKMP", "WKN", "WKNT", "WKRB", "WKS", "WL", "WLB", "WLKR", "WLM", "WLMR", "WLN", "WLNT", "WLPN", "WLPR", "WLR", "WLRS", "WLS", "WLT", "WLTS", "WLTW", "WLXR", "WLY", "WM", "WMFR", "WMHF", "WMLR", "WMLT", "WMN", "WMNT", "WMR", "WMRK", "WMST", "WN", "WNBR", "WNFL", "WNFR", "WNHM", "WNJL", "WNKR", "WNKT", "WNL", "WNM", "WNMN", "WNN", "WNNT", "WNRK", "WNRL", "WNS", "WNSR", "WNST", "WNT", "WNTB", "WNTH", "WNTK", "WNTL", "WNTN", "WNTR", "WNTS", "WNTT", "WNTY", "WNWR", "WNWT", "WNY", "WNYR", "WPMP", "WPR", "WPRF", "WR", "WR0", "WR0L", "WR0M", "WR0S", "WRBR", "WRFR", "WRFT", "WRJR", "WRK", "WRKB", "WRKL", "WRKN", "WRKR", "WRKS", "WRL", "WRLF", "WRM", "WRM0", "WRMK", "WRN", "WRNF", "WRNJ", "WRNK", "WRNS", "WRNT", "WRNX", "WRP", "WRS", "WRSB", "WRST", "WRT", "WRTK", "WRTL", "WRTN", "WRTS", "WS", "WSFR", "WSLS", "WSS", "WSXL", "WTKS", "WTKT", "WTL", "WTLR", "WTN", "WTR", "WTRK", "WTTY", "WTWL", "WW", "WW0", "WW0B", "WW0K", "WW0L", "WW0M", "WW0N", "WW0R", "WW0W", "WWB", "WWBH", "WWBK", "WWBL", "WWBM", "WWBN", "WWBP", "WWBR", "WWBS", "WWBT", "WWBW", "WWBX", "WWBY", "WWF", "WWFB", "WWFH", "WWFK", "WWFL", "WWFM", "WWFN", "WWFP", "WWFR", "WWFS", "WWFT", "WWFX", "WWH", "WWHF", "WWHM", "WWHN", "WWHP", "WWHT", "WWJ", "WWJB", "WWJK", "WWJL", "WWJN", "WWJR", "WWJS", "WWJT", "WWJW", "WWK", "WWKB", "WWKF", "WWKH", "WWKK", "WWKL", "WWKM", "WWKN", "WWKP", "WWKR", "WWKS", "WWKT", "WWKW", "WWKY", "WWL", "WWL0", "WWLB", "WWLF", "WWLH", "WWLJ", "WWLK", "WWLL", "WWLM", "WWLN", "WWLP", "WWLR", "WWLS", "WWLT", "WWLW", "WWLX", "WWLY", "WWM", "WWM0", "WWMB", "WWMF", "WWMJ", "WWMK", "WWML", "WWMN", "WWMP", "WWMR", "WWMS", "WWMT", "WWMW", "WWMY", "WWN", "WWN0", "WWNB", "WWNF", "WWNH", "WWNJ", "WWNK", "WWNL", "WWNM", "WWNN", "WWNP", "WWNR", "WWNS", "WWNT", "WWNW", "WWNX", "WWNY", "WWP", "WWPB", "WWPF", "WWPH", "WWPK", "WWPL", "WWPM", "WWPN", "WWPP", "WWPR", "WWPS", "WWPT", "WWPW", "WWR", "WWR0", "WWRB", "WWRF", "WWRH", "WWRJ", "WWRK", "WWRL", "WWRM", "WWRN", "WWRP", "WWRR", "WWRS", "WWRT", "WWRW", "WWRX", "WWRY", "WWS", "WWS0", "WWSB", "WWSF", "WWSK", "WWSL", "WWSM", "WWSN", "WWSP", "WWSR", "WWSS", "WWST", "WWSW", "WWSX", "WWT", "WWT0", "WWTB", "WWTF", "WWTH", "WWTJ", "WWTK", "WWTL", "WWTM", "WWTN", "WWTP", "WWTR", "WWTS", "WWTT", "WWTW", "WWTX", "WWTY", "WWW", "WWWB", "WWWK", "WWWL", "WWWM", "WWWN", "WWWR", "WWX", "WWXB", "WWXF", "WWXH", "WWXK", "WWXL", "WWXM", "WWXN", "WWXP", "WWXR", "WWXS", "WWXT", "WWXW", "WWY", "WWYL", "WWYM", "WWYN", "WWYR", "WWYT", "WX", "WXBR", "WXKR", "WXL", "WXNK", "WXPR", "WXT", "WXTL", "WXWT", "WY", "WY0", "WYB", "WYFR", "WYK", "WYKK", "WYKT", "WYL", "WYLK", "WYLN", "WYLS", "WYLT", "WYM", "WYMB", "WYMN", "WYMP", "WYN", "WYNB", "WYNK", "WYNN", "WYNT", "WYP", "WYR", "WYRJ", "WYRM", "WYS", "WYT", "WYTF", "WYTP", "WYTR", "WYTS", "XSFR", "XSHF", "XSMS", "XSN", "XSN0", "XSNK", "XSNL", "XSNN", "XSNT", "XSRB", "Y", "YFN", "YFRT", "YFS", "YFT", "YMK", "YN", "YPRS", "YRM", "YSNT", "YST0", "YSTL", "YY", "YY0", "YY0L", "YY0N", "YY0P", "YY0R", "YYB", "YYBK", "YYBL", "YYBM", "YYBN", "YYBR", "YYBS", "YYBT", "YYFL", "YYFN", "YYFR", "YYH", "YYJK", "YYJL", "YYJN", "YYJR", "YYK", "YYKB", "YYKK", "YYKL", "YYKM", "YYKN", "YYKP", "YYKR", "YYKS", "YYKT", "YYKX", "YYL", "YYLB", "YYLF", "YYLH", "YYLJ", "YYLK", "YYLL", "YYLM", "YYLN", "YYLP", "YYLR", "YYLS", "YYLT", "YYLW", "YYLY", "YYM", "YYMB", "YYMK", "YYML", "YYMN", "YYMP", "YYMR", "YYMS", "YYMT", "YYMX", "YYMY", "YYN", "YYN0", "YYNB", "YYNF", "YYNJ", "YYNK", "YYNL", "YYNM", "YYNN", "YYNP", "YYNR", "YYNS", "YYNT", "YYNW", "YYNX", "YYNY", "YYP", "YYPK", "YYPL", "YYPN", "YYPR", "YYPS", "YYPT", "YYR", "YYRB", "YYRF", "YYRH", "YYRJ", "YYRK", "YYRL", "YYRM", "YYRN", "YYRP", "YYRR", "YYRS", "YYRT", "YYRW", "YYRX", "YYRY", "YYS", "YYSB", "YYSF", "YYSK", "YYSM", "YYSN", "YYSP", "YYSR", "YYST", "YYSW", "YYT", "YYTB", "YYTF", "YYTJ", "YYTK", "YYTL", "YYTM", "YYTN", "YYTP", "YYTR", "YYTS", "YYTY", "YYW", "YYWK", "YYWL", "YYWN", "YYWP", "YYWR", "YYX", "YYXT", "YYY", "YYYH", "YYYK", "YYYN", "YYYT", "ZS", "ZSB", "ZSBK", "ZSBL", "ZSBN", "ZSBR", "ZSF", "ZSFL", "ZSFN", "ZSFR", "ZSFS", "ZSFT", "ZSH", "ZSHL", "ZSHN", "ZSHR", "ZSJL", "ZSJN", "ZSK", "ZSKF", "ZSKH", "ZSKK", "ZSKL", "ZSKN", "ZSKR", "ZSKS", "ZSKW", "ZSKX", "ZSL", "ZSLB", "ZSLF", "ZSLK", "ZSLM", "ZSLN", "ZSLR", "ZSLS", "ZSLT", "ZSM", "ZSML", "ZSMN", "ZSMP", "ZSMR", "ZSMS", "ZSMT", "ZSN", "ZSN0", "ZSNB", "ZSNF", "ZSNJ", "ZSNK", "ZSNL", "ZSNN", "ZSNR", "ZSNS", "ZSNT", "ZSP", "ZSPF", "ZSPK", "ZSPL", "ZSPN", "ZSPP", "ZSPS", "ZSR", "ZSRB", "ZSRF", "ZSRK", "ZSRL", "ZSRM", "ZSRN", "ZSRS", "ZSRT", "ZSRX", "ZSS", "ZSSM", "ZSSN", "ZSSS", "ZSST", "ZSSX", "ZST", "ZSTK", "ZSTL", "ZSTN", "ZSTP", "ZSTR", "ZSTS", "ZSTT", "ZSTX", "ZSWK", "ZSWR", "ZSWS", "ZSX", "ZSXN", "ZSXR", "ZSXS", "ZSY"]; - } -}); - -// src/geocode.ts -import MiniSearch from "minisearch"; -import Geohash from "latlon-geohash"; -import metaphone from "metaphone"; -var knownGroups = new Set(require_groups()); -var currentGroup = null; -var currentGroupData = null; -var fetchController = new AbortController(); -var miniSearch = new MiniSearch({ fields: ["address"] }); -var searchIndexDocuments = []; -var currentSearchIndexKey = null; -function getSearchIndexKey(group, numericWords) { - return [group, ...numericWords.sort()].join("|"); -} -function getGroup(word) { - let cleanedWord = word.toUpperCase().replace(/[^A-Z]+/g, ""); - let group = cleanedWord.substring(0, 1) + metaphone(cleanedWord).substring(0, 3); - return knownGroups.has(group) ? group : null; -} -function loadGroupData(group) { - return new Promise((resolve, reject) => { - if (group === currentGroup && currentGroupData) { - resolve(currentGroupData); - return; - } - fetchController.abort(); - fetchController = new AbortController(); - currentGroup = group; - let url = `https://www.abc.net.au/res/sites/news-projects/geocoder/data/202111/${group}.txt.gz`; - fetch(url, { signal: fetchController.signal }).then((response) => { - response.text().then((data) => { - currentGroupData = data; - resolve(data); - }); - }).catch((e) => { - if (e.name !== "AbortError") - reject(e); - }); - }); -} -function prepareSearchIndex(group, numericWords) { - return new Promise((resolve, reject) => { - let newSearchIndexKey = getSearchIndexKey(group, numericWords); - if (newSearchIndexKey === currentSearchIndexKey) { - resolve(); - return; - } - loadGroupData(group).then((data) => { - var _a; - searchIndexDocuments = []; - let id = 0; - let lines = data.split("\n"); - for (let line of lines) { - let street; - try { - street = JSON.parse(line); - } catch { - continue; - } - let addressLines = [ - "", - "", - [street.s, street.t, street.p].join(" ") - ]; - for (let block of street.b) { - addressLines[1] = [ - block.l ? "LOT " : "", - block.m ? block.n + "-" + block.m + " " : block.n + " ", - street.a + " ", - street.r ? street.r : "", - street.x ? " " + street.x : "" - ].join(""); - addressLines[0] = (_a = block.a) != null ? _a : ""; - let address = addressLines.filter((line2) => !!line2).join(", "); - let indexThisBlock = numericWords.length === 0 || numericWords.some((w) => w === block.n || w === block.m || w === street.p); - if (indexThisBlock) { - searchIndexDocuments[id] = { - id, - address, - geohash: block.g, - numericWords: block.m ? [block.n, block.m, street.p] : [block.n, street.p] - }; - id++; - } - if (block.u && numericWords.length > 0) { - for (let unitType in block.u) { - let unitNumbers = block.u[unitType]; - if (unitType) - unitType += " "; - for (let unitNumber of unitNumbers) { - if (Array.isArray(unitNumber) && unitNumber.length === 2) { - for (let i = unitNumber[0]; i <= unitNumber[1]; i++) { - let indexThisUnit = indexThisBlock || numericWords.some((w) => w === i); - if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + i + ", " + address, - geohash: block.g, - numericWords: block.m ? [i, block.n, block.m, +street.p] : [i, block.n, +street.p] - }; - id++; - } - } - } else { - let indexThisUnit = indexThisBlock || numericWords.some((w) => w === unitNumber); - if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + unitNumber + ", " + address, - geohash: block.g, - numericWords: block.m ? [unitNumber, block.n, block.m, +street.p] : [unitNumber, block.n, +street.p] - }; - id++; - } - } - } - } - } - } - if (id > 1e4) { - break; - } - } - miniSearch.removeAll(); - miniSearch.addAll(searchIndexDocuments); - resolve(); - }).catch(reject); - }); -} -var states = /* @__PURE__ */ new Set(["NSW", "VIC", "QLD", "WA", "SA", "TAS", "ACT", "NT"]); -var prettyAddress = (address) => { - return address.toUpperCase().replace(/(^|[^A-Z])(['A-Z]+)/g, (entireMatch, separator, word) => { - let prettyWord = states.has(word) ? word : word.substring(0, 1) + word.substring(1).toLowerCase(); - return separator + prettyWord; - }); -}; -function geocode(input, options = {}) { - return new Promise((resolve, reject) => { - let startTime = Date.now(); - let cleanedInput = input.replace(/'/g, "").replace(/[^\w\d]+/g, " ").replace(/\s+/g, " ").toUpperCase(); - let words = cleanedInput.split(" ").map((word) => isFinite(+word) ? +word : word); - let numericWords = []; - let streetName = null; - for (let word of words) { - let isNumeric = typeof word === "number" || /\d/.test(word); - if (isNumeric) { - numericWords.push(word); - } else if (streetName === null && typeof word === "string" && word.length > 3 && numericWords.length > 0) { - streetName = word; - } - } - if (streetName === null) { - let firstWord = words.find((word) => typeof word === "string" && !/\d/.test(word)); - if (firstWord && typeof firstWord === "string") { - streetName = firstWord; - } - } - let result = { - results: [], - group: "", - input, - duration: 0 - }; - let group = streetName === null ? null : getGroup(streetName); - if (streetName === null || group === null) { - result.duration = Date.now() - startTime; - resolve(result); - return; - } - prepareSearchIndex(group, numericWords).then(() => { - var _a; - let miniSearchResults = miniSearch.search(input, { - fuzzy: (term) => /\d/.test(term) ? false : 0.333, - prefix: (term) => /\d/.test(term) ? false : true, - weights: { fuzzy: 0.1, prefix: 0.5 }, - filter: numericWords.length === 0 ? void 0 : (result2) => { - let doc = searchIndexDocuments[result2.id]; - if (doc && doc.numericWords.length > 0) { - for (let inputWord of numericWords) { - for (let docWord of doc.numericWords) { - if (inputWord === docWord) { - return true; - } - } - } - } - return false; - } - }); - let highestScoreIsPositive = ((_a = miniSearchResults[0]) == null ? void 0 : _a.score) > 0; - for (let miniSearchResult of miniSearchResults) { - if (miniSearchResult.score === 0 && highestScoreIsPositive) { - break; - } - let doc = searchIndexDocuments[miniSearchResult.id]; - let g = Geohash.decode(doc.geohash); - result.results.push({ - address: prettyAddress(doc.address), - latitude: g.lat, - longitude: g.lon, - score: miniSearchResult.score, - id: doc.id - }); - if (result.results.length === options.limit) { - break; - } - } - result.duration = Date.now() - startTime; - resolve(result); - }).catch(reject); - }); -} -export { - geocode as default -}; +import W from"minisearch";import v from"latlon-geohash";import{LRUMap as R}from"lru_map";import z from"metaphone";var N=function(r,t=0){let s=3735928559^t,n=1103547991^t;for(let a=0,f;a>>16,2246822507)^Math.imul(n^n>>>13,3266489909),n=Math.imul(n^n>>>16,2246822507)^Math.imul(s^s>>>13,3266489909),4294967296*(2097151&n)+(s>>>0)},T=class extends Error{constructor(){super(),this.name="GeocodeAbortError"}},I=new URL("https://www.abc.net.au/res/sites/news-projects/geocoder/data/202208/"),k;async function U(){return k||(k=(async()=>{let t=await(await fetch(new URL("groups.json.gz",I).toString())).json();return new Set(t)})(),k)}var P=new Map,j=new WeakMap;async function L(r){let t=P.get(r);if(t)return t;let s=new AbortController;return t=(async()=>{let n=[],f=(await fetch(new URL(`${r}.txt.gz`,I).toString(),{signal:s.signal})).body?.getReader(),d=new TextDecoder("utf8"),l="",m=!1;for(;f&&!m;){let c=await f.read();m=c.done;let S=d.decode(c.value),o=l+S;l="";let p=o.split(` +`);for(let g=0;g{let c=[],S=await L(d);for(let o of S){let p=o.a.replace(/[^ -\w]/g,""),g=["","",[o.s,o.t,o.p].join(" ")];for(let e of o.b){g[1]=[e.l?"LOT ":"",e.m?e.n+"-"+e.m+" ":e.n+" ",o.a+" ",o.r?o.r:"",o.x?" "+o.x:""].join(""),g[0]=e.a??"";let i=g.filter(u=>!!u).join(", "),w=t.length===0||t.some(u=>u===e.n||u===e.m||u===o.p);if(w&&c.push({id:N(i),address:i,streetName:p,geohash:e.g,numericWords:e.m?[e.n,e.m,o.p]:[e.n,o.p]}),e.u&&t.length>0)for(let u in e.u){let y=e.u[u];u&&(u+=" ");for(let h of y)if(Array.isArray(h)&&h.length===2){for(let b=h[0];b<=h[1];b++)if(w||t.some(D=>D===b)){let D=u+b+", "+i;c.push({id:N(D),address:D,streetName:p,geohash:e.g,numericWords:e.m?[b,e.n,e.m,+o.p]:[b,e.n,+o.p]})}}else if(w||t.some(A=>A===h)){let A=u+h+", "+i;c.push({id:N(A),address:A,streetName:p,geohash:e.g,numericWords:e.m?[h,e.n,e.m,+o.p]:[h,e.n,+o.p]})}}}}return c})(),C.set(d,m)),n.push(m)}let a=new Map,f=await Promise.all(n);for(let d of f){for(let l of d)a.set(l.id,l);if(a.size>1e4)break}return Array.from(a.values())}var K=new Set(["NSW","VIC","QLD","WA","SA","TAS","ACT","NT"]),Z=r=>r.toUpperCase().replace(/(^|[^A-Z])(['A-Z]+)/g,(t,s,n)=>{let a=K.has(n)?n:n.substring(0,1)+n.substring(1).toLowerCase();return s+a}),G="",x,M=new R(100);async function B(r,t={}){let s=Date.now(),n=r.toUpperCase().replace(/[^-A-Z0-9\/,\. ]/g,"").replace(/[^A-Z0-9]+/g," ").trim(),a=M.get(n);if(a)return{input:r,results:a,startTime:s,duration:Date.now()-s};let f=n.split(" ").map(e=>isFinite(+e)?+e:e),d=[],l=[];f.forEach(e=>(typeof e=="number"||/\d/.test(e)?l:d).push(e));let m=new Set(l.map(e=>(typeof e=="number"?e:+e.replace(/[^\d]/g,""))%20)),c=new Set,S=await U();for(let e of d){let i=e.substring(0,1),w=z(e);if(m.size>0){let u=w.substring(0,2);for(let y of m){let h=[i,y,u].join("/");S.has(h)&&c.add(h)}}else{let u=w.substring(0,3),y=[i,"_",u].join("/");S.has(y)&&c.add(y)}}let o=[...Array.from(c.values()),...l].sort().join(" ");if(!x||G!==o){G=o;let e;try{e=await F(Array.from(c.values()),l,t.abortPrevious??!1)}catch(i){throw t.abortPrevious&&i instanceof DOMException&&i.name==="AbortError"?new T:i}x=new W({fields:["address","streetName"],storeFields:["address","geohash"]}),e&&x.documentCount===0&&x.addAll(e)}a=[];let p=x.search(r,{fuzzy:e=>/\d/.test(e)?!1:.333,prefix:e=>!/\d/.test(e),weights:{fuzzy:.25,prefix:.5},boost:{streetName:2},maxFuzzy:4}),g=p[0]?.score>0;for(let e of p){if(e.score===0&&g)break;let i=v.decode(e.geohash);if(a.push({address:Z(e.address),latitude:i.lat,longitude:i.lon,score:e.score,id:e.id}),a.length===t.limit)break}return M.set(n,a),{input:r,results:a,startTime:s,duration:Date.now()-s}}var $=B;export{T as GeocodeAbortError,$ as default,B as geocode}; diff --git a/example.html b/example.html index 40c471e..f2d1da0 100644 --- a/example.html +++ b/example.html @@ -46,34 +46,48 @@
-
+
- - - - - -
- - diff --git a/src/geocode.ts b/src/geocode.ts index 0391429..0e127af 100644 --- a/src/geocode.ts +++ b/src/geocode.ts @@ -1,101 +1,177 @@ import type { Street } from './types'; -import MiniSearch, { SearchResult as MiniSearchResult } from 'minisearch'; +import MiniSearch from 'minisearch'; import Geohash from 'latlon-geohash'; +import { LRUMap } from 'lru_map'; //@ts-ignore - missing types import metaphone from 'metaphone'; declare function metaphone(word: string): string; export type GeocodeResult = { input: string; - group: string; + results: GeocodeResultItem[]; + startTime: number; // milliseconds since epoch - e.g. Date.now() duration: number; // in milliseconds - results: Array<{ - address: string; - latitude: number; - longitude: number; - score: number; - id: number; - }>; +}; + +type GeocodeResultItem = { + address: string; + latitude: number; + longitude: number; + score: number; + id: number; }; type GeocodeOptions = { limit?: number; + abortPrevious?: boolean; }; -type SearchIndexDocument = { +type AddressSearchDocument = { id: number; address: string; + streetName: string; geohash: string; numericWords: NumericWord[]; }; type NumericWord = number | string; -const knownGroups = new Set(require('../groups.json')); -let currentGroup: string | null = null; -let currentGroupData: string | null = null; +// Hash a string to a JavaScript-safe 53-bit integer +// More info: https://stackoverflow.com/a/52171480 +// Source code: https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js +/* + cyrb53 (c) 2018 bryc (github.com/bryc) + A fast and simple hash function with decent collision resistance. + Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity. + Public domain. Attribution appreciated. +*/ +const cyrb53 = function (str: string, seed = 0) { + let h1 = 0xdeadbeef ^ seed, + h2 = 0x41c6ce57 ^ seed; + for (let i = 0, ch: number; i < str.length; i++) { + ch = str.charCodeAt(i); + h1 = Math.imul(h1 ^ ch, 2654435761); + h2 = Math.imul(h2 ^ ch, 1597334677); + } + h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909); + h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909); + return 4294967296 * (2097151 & h2) + (h1 >>> 0); +}; -let fetchController = new AbortController(); +class GeocodeAbortError extends Error { + constructor() { + super(); + this.name = 'GeocodeAbortError'; + } +} -const miniSearch = new MiniSearch({ fields: ['address'] }); -let searchIndexDocuments: SearchIndexDocument[] = []; -let currentSearchIndexKey: string | null = null; +const urlBase = new URL('https://www.abc.net.au/res/sites/news-projects/geocoder/data/202208/'); -function getSearchIndexKey(group: string, numericWords: NumericWord[]) { - return [group, ...numericWords.sort()].join('|'); +let knownGroupsPromise: Promise> | undefined; +async function getKnownGroups(): Promise> { + if (knownGroupsPromise) { + return knownGroupsPromise; + } + knownGroupsPromise = (async () => { + let response = await fetch(new URL(`groups.json.gz`, urlBase).toString()); + let knownGroups = (await response.json()) as string[]; + return new Set(knownGroups); + })(); + return knownGroupsPromise; } -function getGroup(word: string): string | null { - let cleanedWord = word.toUpperCase().replace(/[^A-Z]+/g, ''); - let group = cleanedWord.substring(0, 1) + metaphone(cleanedWord).substring(0, 3); // first letter followed by metaphone of up to 3 characters - return knownGroups.has(group) ? group : null; +let streetsPromises = new Map>(); +let streetsAbortControllers = new WeakMap, AbortController>(); +async function getStreets(group: string): Promise { + let streetsPromise = streetsPromises.get(group); + if (streetsPromise) { + return streetsPromise; + } + let abortController = new AbortController(); + streetsPromise = (async (): Promise => { + let streets: Street[] = []; + let response = await fetch(new URL(`${group}.txt.gz`, urlBase).toString(), { + signal: abortController.signal + }); + let reader = response.body?.getReader(); + let textDecoder = new TextDecoder('utf8'); + let incompleteJsonFromPreviousChunk = ''; + let done = false; + while (reader && !done) { + let r = await reader.read(); + done = r.done; + let chunk = textDecoder.decode(r.value); + let text = incompleteJsonFromPreviousChunk + chunk; + incompleteJsonFromPreviousChunk = ''; + let lines = text.split('\n'); + for (let i = 0; i < lines.length; i++) { + let json = lines[i]; + try { + let street = JSON.parse(json) as Street; + streets.push(street); + } catch (e: unknown) { + if (e instanceof SyntaxError && i === lines.length - 1 && !done) { + // Incomplete JSON on last line. Assume rest of JSON is at beginning of next chunk. + incompleteJsonFromPreviousChunk = json; + } else if (e instanceof SyntaxError && !json) { + // Ignore empty line. Caused by complete JSON on last line of previous chunk and newline delimeter at start of this chunk. + } else { + // Unknown error + throw e; + } + } + } + } + return streets; + })(); + streetsPromises.set(group, streetsPromise); + streetsAbortControllers.set(streetsPromise, abortController); + return streetsPromise; } - -function loadGroupData(group: string): Promise { - return new Promise((resolve, reject) => { - if (group === currentGroup && currentGroupData) { - // group hasn't changed and the data is already loaded - resolve(currentGroupData); - return; +function abortStreets(group: string) { + let streetsPromise = streetsPromises.get(group); + if (streetsPromise) { + let abortController = streetsAbortControllers.get(streetsPromise); + if (abortController) { + abortController.abort(); } - fetchController.abort(); // abort any existing requests - fetchController = new AbortController(); - currentGroup = group; - let url = `https://www.abc.net.au/res/sites/news-projects/geocoder/data/202111/${group}.txt.gz`; - fetch(url, { signal: fetchController.signal }) - .then(response => { - response.text().then(data => { - currentGroupData = data; - resolve(data); - }); - }) - .catch(e => { - // We expect possible AbortErrors, but other issues should be passed on. - if (e.name !== 'AbortError') reject(e); - }); - }); + streetsPromises.delete(group); + } } -function prepareSearchIndex(group: string, numericWords: NumericWord[]): Promise { - return new Promise((resolve, reject) => { - let newSearchIndexKey = getSearchIndexKey(group, numericWords); - if (newSearchIndexKey === currentSearchIndexKey) { - // no need to rebuild search index - resolve(); - return; +function getSearchIndexKey(group: string, numericWords: NumericWord[]) { + return [group, ...numericWords.sort()].join(' '); +} + +let searchDocumentsPromise = new LRUMap>(100); +async function prepareSearchDocuments( + groups: string[], + numericWords: NumericWord[], + abortPrevious: boolean +): Promise { + if (abortPrevious) { + // cancel pending requests that are no longer needed + let groupsToAbort = new Set([...streetsPromises.keys()]); + for (let groupToAbort of groupsToAbort) { + if (groups.includes(groupToAbort)) { + // pending request still needed + groupsToAbort.delete(groupToAbort); + } } - loadGroupData(group) - .then(data => { - searchIndexDocuments = []; - let id = 0; - let lines = data.split('\n'); - for (let line of lines) { - let street: Street; - try { - street = JSON.parse(line); - } catch { - continue; - } + for (let abortGroup of groupsToAbort) { + abortStreets(abortGroup); + } + } + let allPromises: Array> = []; + for (let group of groups) { + let key = getSearchIndexKey(group, numericWords); + let promise = searchDocumentsPromise.get(key); + if (!promise) { + promise = (async () => { + let searchIndex: AddressSearchDocument[] = []; + let streets = await getStreets(group); + for (let street of streets) { + let streetName = street.a.replace(/[^ -\w]/g, ''); let addressLines: string[] = [ '', // building '', // street @@ -116,13 +192,13 @@ function prepareSearchIndex(group: string, numericWords: NumericWord[]): Promise let indexThisBlock = numericWords.length === 0 || numericWords.some(w => w === block.n || w === block.m || w === street.p); if (indexThisBlock) { - searchIndexDocuments[id] = { - id, + searchIndex.push({ + id: cyrb53(address), address, + streetName, geohash: block.g, numericWords: block.m ? [block.n, block.m, street.p] : [block.n, street.p] - }; - id++; + }); } // If we have numeric words in the query, examine unit numbers in this block if (block.u && numericWords.length > 0) { @@ -136,44 +212,54 @@ function prepareSearchIndex(group: string, numericWords: NumericWord[]): Promise for (let i = unitNumber[0]; i <= unitNumber[1]; i++) { let indexThisUnit = indexThisBlock || numericWords.some(w => w === i); if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + i + ', ' + address, + let unitAndAddress = unitType + i + ', ' + address; + searchIndex.push({ + id: cyrb53(unitAndAddress), + address: unitAndAddress, + streetName, geohash: block.g, numericWords: block.m ? [i, block.n, block.m, +street.p] : [i, block.n, +street.p] - }; - id++; + }); } } } else { // single unit number - e.g. 1 or "1A" let indexThisUnit = indexThisBlock || numericWords.some(w => w === unitNumber); if (indexThisUnit) { - searchIndexDocuments[id] = { - id, - address: unitType + unitNumber + ', ' + address, + let unitAndAddress = unitType + unitNumber + ', ' + address; + searchIndex.push({ + id: cyrb53(unitAndAddress), + address: unitAndAddress, + streetName, geohash: block.g, numericWords: block.m ? [unitNumber, block.n, block.m, +street.p] : [unitNumber, block.n, +street.p] - }; - id++; + }); } } } } } } - if (id > 10000) { - break; // search index is getting too big - stop here - } } - miniSearch.removeAll(); - miniSearch.addAll(searchIndexDocuments); // consider using addAllAsync if performance is slow - resolve(); - }) - .catch(reject); - }); + return searchIndex; + })(); + searchDocumentsPromise.set(group, promise); + } + allPromises.push(promise); + } + let combinedSearchIndexDocuments = new Map(); + let allResolvedPromises = await Promise.all(allPromises); + for (let addressSearchDocuments of allResolvedPromises) { + for (let a of addressSearchDocuments) { + combinedSearchIndexDocuments.set(a.id, a); + } + if (combinedSearchIndexDocuments.size > 10000) { + break; // search index is getting too big - stop here + } + } + return Array.from(combinedSearchIndexDocuments.values()); } const states = new Set(['NSW', 'VIC', 'QLD', 'WA', 'SA', 'TAS', 'ACT', 'NT']); @@ -185,89 +271,101 @@ const prettyAddress = (address: string): string => { }); }; -export default function geocode(input: string, options: GeocodeOptions = {}): Promise { - return new Promise((resolve, reject) => { - let startTime = Date.now(); - let cleanedInput = input - .replace(/'/g, '') - .replace(/[^\w\d]+/g, ' ') - .replace(/\s+/g, ' ') - .toUpperCase(); - let words: NumericWord[] = cleanedInput.split(' ').map(word => (isFinite(+word) ? +word : word)); - let numericWords: NumericWord[] = []; - let streetName: string | null = null; // street name will determine the search group - for (let word of words) { - let isNumeric = typeof word === 'number' || /\d/.test(word); - if (isNumeric) { - numericWords.push(word); - } else if (streetName === null && typeof word === 'string' && word.length > 3 && numericWords.length > 0) { - // first >3 letter word after a numeric word is assumed to be the street name - streetName = word; +let currentSearchIndexKey = ''; +let currentSearchIndex: MiniSearch | undefined; +let geocodeCache = new LRUMap(100); +async function geocode(input: string, options: GeocodeOptions = {}): Promise { + let startTime = Date.now(); + let cleanedInput = input + .toUpperCase() + .replace(/[^-A-Z0-9\/,\. ]/g, '') + .replace(/[^A-Z0-9]+/g, ' ') + .trim(); + let results = geocodeCache.get(cleanedInput); + if (results) { + return { input, results, startTime, duration: Date.now() - startTime }; + } + let words: NumericWord[] = cleanedInput.split(' ').map(word => (isFinite(+word) ? +word : word)); + let normalWords: string[] = []; + let numericWords: NumericWord[] = []; + words.forEach(word => (typeof word === 'number' || /\d/.test(word) ? numericWords : normalWords).push(word)); + let numberGroups = new Set( + numericWords.map(n => (typeof n === 'number' ? n : +n.replace(/[^\d]/g, '')) % 20) + ); + let groups: Set = new Set(); + let knownGroups = await getKnownGroups(); + for (let word of normalWords) { + let letter = word.substring(0, 1); + let phonetic = metaphone(word); + if (numberGroups.size > 0) { + let phonetic2 = phonetic.substring(0, 2); + for (let n of numberGroups) { + let group = [letter, n, phonetic2].join('/'); + if (knownGroups.has(group)) { + groups.add(group); + } + } + } else { + let phonetic3 = phonetic.substring(0, 3); + let group = [letter, '_', phonetic3].join('/'); + if (knownGroups.has(group)) { + groups.add(group); } } - if (streetName === null) { - // fallback: use first non-numeric word - let firstWord = words.find(word => typeof word === 'string' && !/\d/.test(word)); - if (firstWord && typeof firstWord === 'string') { - streetName = firstWord; + } + let newSearchIndexKey = [...Array.from(groups.values()), ...numericWords].sort().join(' '); + if (!currentSearchIndex || currentSearchIndexKey !== newSearchIndexKey) { + currentSearchIndexKey = newSearchIndexKey; + let documents: AddressSearchDocument[]; + try { + documents = await prepareSearchDocuments( + Array.from(groups.values()), + numericWords, + options.abortPrevious ?? false + ); + } catch (e: unknown) { + if (options.abortPrevious && e instanceof DOMException && e.name === 'AbortError') { + throw new GeocodeAbortError(); + } else { + throw e; // unexpected error } } - let result: GeocodeResult = { - results: [], - group: '', - input, - duration: 0 - }; - let group = streetName === null ? null : getGroup(streetName); - if (streetName === null || group === null) { - result.duration = Date.now() - startTime; - resolve(result); - return; + currentSearchIndex = new MiniSearch({ + fields: ['address', 'streetName'], + storeFields: ['address', 'geohash'] + }); + if (documents && currentSearchIndex.documentCount === 0) { + currentSearchIndex.addAll(documents); } - prepareSearchIndex(group, numericWords) - .then(() => { - let miniSearchResults: MiniSearchResult[] = miniSearch.search(input, { - fuzzy: term => (/\d/.test(term) ? false : 0.333), // disable fuzzy search for words containing numbers - prefix: term => (/\d/.test(term) ? false : true), // disable prefix search for words containing numbers - weights: { fuzzy: 0.1, prefix: 0.5 }, - filter: - numericWords.length === 0 - ? undefined - : result => { - let doc = searchIndexDocuments[result.id]; - if (doc && doc.numericWords.length > 0) { - for (let inputWord of numericWords) { - for (let docWord of doc.numericWords) { - if (inputWord === docWord) { - return true; - } - } - } - } - return false; - } - }); - let highestScoreIsPositive = miniSearchResults[0]?.score > 0; - for (let miniSearchResult of miniSearchResults) { - if (miniSearchResult.score === 0 && highestScoreIsPositive) { - break; // stop if we reach useless results - } - let doc = searchIndexDocuments[miniSearchResult.id]; - let g = Geohash.decode(doc.geohash); - result.results.push({ - address: prettyAddress(doc.address), - latitude: g.lat, - longitude: g.lon, - score: miniSearchResult.score, - id: doc.id - }); - if (result.results.length === options.limit) { - break; // limit reached - } - } - result.duration = Date.now() - startTime; - resolve(result); - }) - .catch(reject); + } + results = []; + let addressSearchResults = currentSearchIndex.search(input, { + fuzzy: term => (/\d/.test(term) ? false : 0.333), // disable fuzzy search for words containing numbers + prefix: term => (/\d/.test(term) ? false : true), // disable prefix search for words containing numbers + weights: { fuzzy: 0.25, prefix: 0.5 }, + boost: { streetName: 2 }, + maxFuzzy: 4 }); + let highestScoreIsPositive = addressSearchResults[0]?.score > 0; + for (let addressSearchResult of addressSearchResults) { + if (addressSearchResult.score === 0 && highestScoreIsPositive) { + break; // stop if we reach useless results + } + let g = Geohash.decode(addressSearchResult['geohash'] as string); + results.push({ + address: prettyAddress(addressSearchResult['address'] as string), + latitude: g.lat, + longitude: g.lon, + score: addressSearchResult.score, + id: addressSearchResult.id as number + }); + if (results.length === options.limit) { + break; // limit reached + } + } + geocodeCache.set(cleanedInput, results); + return { input, results, startTime, duration: Date.now() - startTime }; } + +export default geocode; +export { geocode, GeocodeAbortError }; diff --git a/src/types.ts b/src/types.ts index e9ece3a..9e149ec 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,20 +1,23 @@ export type Street = { - b: Block[], // blocks - a: string, // name - r?: string, // type - x?: string, // suffix - s: string, // suburb - t: string, // state - p: string, // postcode + b: Block[]; // blocks + a: string; // name + r?: string; // type (street, road, etc.) + x?: string; // suffix (east, west, etc.) + s: string; // suburb + t: string; // state + p: string; // postcode }; export type Block = { - a?: string, // name - u?: { [type: string]: AddressNumber[] }, // units - n: number | string, // number - m?: number | string, // numberLast - l?: true, // lot - g: string, // geohash + a?: string; // building name (none if undefined) + u?: { [type: string]: AddressNumber[] }; // units (none if undefined) + n: number | string; // number + m?: number | string; // last number (none if undefined) + l?: true; // is lot? (false if undefined) + g: string; // geohash }; -export type AddressNumber = number | [number, number] | string; +export type AddressNumber = + | number // single unit number + | [number, number] // range of consecutive unit numbers (e.g. [1,20]) + | string; // single unit number containing non-numeric characters (e.g. "2A")