mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
fix(area): accept "State of Texas" and "USA" as the units they name
resolve_area compared the spoken name with the unit's name literally, so "State of Texas" (admin1) and "USA" or "UK" (country) were refused with AREA_IDENTITY_MISMATCH although the bundled matcher found exactly those units. Both identity checks, the bundled one and the outline ladder's, now also accept the prefix forms and same-unit country aliases the matcher reads, at the level they imply, so the level check still applies. "Great Britain", "Britain", "America" and "Korea" still need their own names, and the natural-region check stays literal.
This commit is contained in:
1 parent
540629a0fc
commit
68667e2e3c
5 files changed
+128
-6
No files matched your search
@@ -421,6 +421,49 @@ const COUNTRY_TARGET_ALIASES = new Map([
|
||||
['drc', 'democratic republic of the congo'],
|
||||
]);
|
||||
|
||||
/**
|
||||
* Country aliases that are another name for the very same unit. "Great
|
||||
* Britain" and "Britain" are islands, "America" is also two continents and
|
||||
* "Korea" two countries, so those find a country without naming it.
|
||||
*/
|
||||
const COUNTRY_IDENTITY_ALIASES = new Set([
|
||||
'usa',
|
||||
'us',
|
||||
'u s',
|
||||
'u s a',
|
||||
'united states',
|
||||
'uk',
|
||||
'u k',
|
||||
'russian federation',
|
||||
'czechia',
|
||||
'tanzania',
|
||||
'drc',
|
||||
]);
|
||||
|
||||
/**
|
||||
* The unit an ask names in the matcher's own terms, when its words differ
|
||||
* from the unit's name: "State of Texas" names Texas at admin level 1, and
|
||||
* "USA" or "Country of USA" names United States of America. Null when the
|
||||
* ask is just a name. Names are folded with `normalizeAdminName`.
|
||||
* @param {string} text
|
||||
* @returns {{name: string, level: 'country'|'admin1'}|null}
|
||||
*/
|
||||
export function adminQueryIdentity(text) {
|
||||
const parsed = parseAdminQuery(text);
|
||||
if (!parsed?.name) return null;
|
||||
if (parsed.kind === 'state' && parsed.form === 'prefix')
|
||||
return { name: parsed.name, level: 'admin1' };
|
||||
if (parsed.kind !== 'country' && parsed.kind !== 'any') return null;
|
||||
if (COUNTRY_IDENTITY_ALIASES.has(parsed.name))
|
||||
return {
|
||||
name: COUNTRY_TARGET_ALIASES.get(parsed.name),
|
||||
level: 'country',
|
||||
};
|
||||
return parsed.kind === 'country'
|
||||
? { name: parsed.name, level: 'country' }
|
||||
: null;
|
||||
}
|
||||
|
||||
const COUNTRY_ALIASES = new Map([
|
||||
...COUNTRY_TARGET_ALIASES,
|
||||
['england', 'united kingdom'],
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
import { AREA_LEVELS } from './areaStore.js';
|
||||
import { pointInPreparedArea, prepareArea } from './areaGeometry.js';
|
||||
import { adminQueryIdentity, normalizeAdminName } from './adminBoundaries.js';
|
||||
import {
|
||||
isAreaCandidateId,
|
||||
MAX_AREA_CANDIDATE_ID_LENGTH,
|
||||
@@ -149,8 +150,18 @@ function explicitAdminName(text) {
|
||||
};
|
||||
}
|
||||
|
||||
/** Fail closed when a bundled unit's own name contradicts the requested unit. */
|
||||
function bundledAdminIdentityRefusal(admin, query, wantedLevel) {
|
||||
/**
|
||||
* Fail closed when a bundled unit's own name contradicts the requested unit.
|
||||
* With `aliases`, an ask the administrative matcher reads as naming this very
|
||||
* unit at its level ("State of Texas", "USA") also matches; the natural-region
|
||||
* check leaves it off, since "Great Britain" is not the United Kingdom.
|
||||
*/
|
||||
function bundledAdminIdentityRefusal(
|
||||
admin,
|
||||
query,
|
||||
wantedLevel,
|
||||
{ aliases = true } = {},
|
||||
) {
|
||||
const source = explicitAdminName(admin?.name || '');
|
||||
const requested = explicitAdminName(query);
|
||||
const expectedLevel = wantedLevel || requested.level;
|
||||
@@ -161,8 +172,16 @@ function bundledAdminIdentityRefusal(admin, query, wantedLevel) {
|
||||
code: 'AREA_IDENTITY_UNVERIFIED',
|
||||
error: `The bundled boundary is ${admin?.name || 'an unverified administrative unit'}, not a verified current match for "${query}".`,
|
||||
};
|
||||
const alias = aliases ? adminQueryIdentity(query) : null;
|
||||
const named =
|
||||
source.bare === requested.bare ||
|
||||
Boolean(
|
||||
alias &&
|
||||
alias.level === emittedLevel &&
|
||||
alias.name === normalizeAdminName(admin.name),
|
||||
);
|
||||
if (
|
||||
source.bare !== requested.bare ||
|
||||
!named ||
|
||||
(source.level && expectedLevel && source.level !== expectedLevel) ||
|
||||
(expectedLevel && emittedLevel !== expectedLevel)
|
||||
)
|
||||
@@ -343,7 +362,10 @@ export function createAreaResolver({
|
||||
places.length > 0 &&
|
||||
level !== 'natural' &&
|
||||
(await findAdminCandidates(query, { signal }).catch(() => [])).some(
|
||||
(admin) => !bundledAdminIdentityRefusal(admin, query, null),
|
||||
(admin) =>
|
||||
!bundledAdminIdentityRefusal(admin, query, null, {
|
||||
aliases: false,
|
||||
}),
|
||||
);
|
||||
signal?.throwIfAborted?.();
|
||||
if (places.length > 1 && !shadowsAdmin) {
|
||||
|
||||
Reference in new issue
Block a user