mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
fix(geocode): prefer the settlement when a POI also fits the region
When several candidates fit a "place, region" query, take a settlement or administrative area over a POI of the same name, so a cafe called "Paris" in Lyon cannot win "Paris, France" from the nearby pass. Tests: region queries without a camera bias, whole-word and every-word region matching, city and county regions, the nearby whole-name answer when the unbiased request fails, and the settlement preference. The new tests sit with the other Paris, Texas tests. The station fixture uses its real city. CURRENT-STATE now describes the order the code applies.
This commit is contained in:
1 parent
81680c5a15
commit
7788168d73
3 files changed
+218
-121
No files matched your search
+19
-4
@@ -284,6 +284,13 @@ export function selectPhotonFeature(
|
||||
/** Short country names people type that Photon's fields don't carry. */
|
||||
const COUNTRY_ALIASES = Object.freeze({ US: 'usa', GB: 'uk' });
|
||||
|
||||
/**
|
||||
* OSM keys of settlements and administrative areas. Among candidates that fit
|
||||
* a "place, region" query, these are what the region names a place in: a cafe
|
||||
* called "Paris" in Lyon is in France too, but "Paris, France" means the city.
|
||||
*/
|
||||
const SETTLEMENT_OSM_KEYS = Object.freeze(new Set(['place', 'boundary']));
|
||||
|
||||
/** The region part of a "place, region" query, normalized ('' if none). */
|
||||
function queryRegion(query) {
|
||||
const [, ...rest] = String(query ?? '').split(',');
|
||||
@@ -294,7 +301,8 @@ function queryRegion(query) {
|
||||
* For a "place, region" query, pick the candidate named for the place that
|
||||
* actually lies in the region. "Paris, Texas" is also the name of a pub in
|
||||
* Budapest: matched as one name it beat the town, so the region has to be
|
||||
* checked against where each candidate is, not against its name.
|
||||
* checked against where each candidate is, not against its name. When several
|
||||
* candidates fit, a settlement or administrative area wins over a POI.
|
||||
* @param {object[]} features - Photon features, in the order returned.
|
||||
* @param {string} query - The query as typed.
|
||||
* @returns {?object} null when the query names no region or nothing fits.
|
||||
@@ -305,8 +313,8 @@ export function selectQualifiedFeature(features, query) {
|
||||
const head = normalizeToponym(headText);
|
||||
if (!head || !region) return null;
|
||||
const words = region.split(' ');
|
||||
return (
|
||||
(Array.isArray(features) ? features : []).find((feature) => {
|
||||
const qualified = (Array.isArray(features) ? features : []).filter(
|
||||
(feature) => {
|
||||
const properties = feature?.properties ?? {};
|
||||
const name = normalizeToponym(properties.name);
|
||||
// Exactly the place: "Paris Gare de Lyon" is in France too, but it
|
||||
@@ -323,7 +331,14 @@ export function selectQualifiedFeature(features, query) {
|
||||
].join(' '),
|
||||
)} `;
|
||||
return words.every((word) => where.includes(` ${word} `));
|
||||
}) ?? null
|
||||
},
|
||||
);
|
||||
return (
|
||||
qualified.find((feature) =>
|
||||
SETTLEMENT_OSM_KEYS.has(feature?.properties?.osm_key),
|
||||
) ??
|
||||
qualified[0] ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user