mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix the remaining voice review gaps
keep analyst counts, speech, cards, cancellation, pointer capture, tool schema boundaries, and session lifetime consistent add the exact Alps fallback and focused regression coverage
This commit is contained in:
1 parent
6858976b01
commit
0343b4495e
21 files changed
+1745
-441
No files matched your search
@@ -0,0 +1,72 @@
|
||||
import { findNaturalRegion, pointInRing } from '../data/naturalEarthRegions.js';
|
||||
|
||||
/**
|
||||
* The unqualified Alps ask names the European range, not a same-named peak
|
||||
* or local POI. Keep this correction exact and Alps-only: other ranges and
|
||||
* geographic qualifiers retain the caller's configured geocoder semantics.
|
||||
*/
|
||||
export function createAlpsGeocoder({ lookupRegion = findNaturalRegion } = {}) {
|
||||
return {
|
||||
async geocode(query, { signal } = {}) {
|
||||
signal?.throwIfAborted();
|
||||
const name = String(query ?? '')
|
||||
.trim()
|
||||
.replace(/\s+/g, ' ');
|
||||
if (!/^(?:the )?alps(?: mountains)?$/i.test(name))
|
||||
return { place: null, answered: true };
|
||||
|
||||
const region = await lookupRegion('Alps');
|
||||
signal?.throwIfAborted();
|
||||
if (
|
||||
region?.name !== 'Alps' ||
|
||||
region.kind !== 'natural' ||
|
||||
!Array.isArray(region.polygons) ||
|
||||
region.polygons.length === 0 ||
|
||||
!region.polygons.every(
|
||||
(ring) =>
|
||||
Array.isArray(ring) &&
|
||||
ring.length >= 3 &&
|
||||
ring.every(
|
||||
(point) =>
|
||||
Array.isArray(point) &&
|
||||
point.length === 2 &&
|
||||
point.every(Number.isFinite) &&
|
||||
Math.abs(point[0]) <= 180 &&
|
||||
Math.abs(point[1]) <= 90,
|
||||
),
|
||||
)
|
||||
)
|
||||
throw new Error('Bundled Alps geometry unavailable');
|
||||
const vertices = region.polygons.flat();
|
||||
const west = Math.min(...vertices.map(([lon]) => lon));
|
||||
const east = Math.max(...vertices.map(([lon]) => lon));
|
||||
const south = Math.min(...vertices.map(([, lat]) => lat));
|
||||
const north = Math.max(...vertices.map(([, lat]) => lat));
|
||||
const lat = (south + north) / 2;
|
||||
const lng = (west + east) / 2;
|
||||
if (
|
||||
![west, east, south, north, lat, lng].every(Number.isFinite) ||
|
||||
!region.polygons.some((ring) => pointInRing(ring, lat, lng))
|
||||
) {
|
||||
// A broken pack is not permission to cache an unrelated network peak
|
||||
// as the canonical range. Existing search error/retry handling owns it.
|
||||
throw new Error('Bundled Alps geometry unavailable');
|
||||
}
|
||||
return {
|
||||
answered: true,
|
||||
place: {
|
||||
lat,
|
||||
lng,
|
||||
name: region.name,
|
||||
label: region.name,
|
||||
types: ['natural_feature'],
|
||||
exact: true,
|
||||
viewport: {
|
||||
southwest: { lat: south, lng: west },
|
||||
northeast: { lat: north, lng: east },
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -6,9 +6,10 @@ import { createGoogleGeocoder } from './google.js';
|
||||
import { createPhotonGeocoder } from '../keylessGeocoder.js';
|
||||
import { createCoordinateGeocoder } from './coordinateGeocoder.js';
|
||||
import { createPresetGeocoder } from './presetGeocoder.js';
|
||||
import { createAlpsGeocoder } from './alpsGeocoder.js';
|
||||
|
||||
/**
|
||||
* Coordinates and bundled names first — both answer offline and with no key —
|
||||
* Coordinates, bundled names and the unqualified Alps first — all offline —
|
||||
* then Google when configured, then keyless Photon, then the local Nominatim
|
||||
* route as a last resort. Transport stays local to setup.
|
||||
*
|
||||
@@ -37,6 +38,7 @@ export function createDefaultPlaceSearch({
|
||||
providers: providers.geocode || [
|
||||
createCoordinateGeocoder(),
|
||||
...(presets ? [createPresetGeocoder({ presets })] : []),
|
||||
createAlpsGeocoder(),
|
||||
...(selected
|
||||
? [selected]
|
||||
: [
|
||||
|
||||
Reference in new issue
Block a user