web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit 4fd76e51cf04470600f23831df83ec641f17a74e
parent 58358b68676bafc3023fefc8256fdc8956b0196f
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Tue,  8 Oct 2024 10:23:57 +0000

geocoder: edit geocoder reverse method, update error message types, edit utils, types

Diffstat:
Mgeocoder/src/geocoder.ts | 34+++++++++++++++++++++++-----------
Mgeocoder/src/types.ts | 5++++-
Mgeocoder/src/utils.ts | 21++++++++++++---------
3 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/geocoder/src/geocoder.ts b/geocoder/src/geocoder.ts @@ -1,8 +1,10 @@ -import type { GeolocationCoordinatesPoint } from "@radroots/utils"; +import { err_msg, type ErrorMessage, type GeolocationCoordinatesPoint, type ResultsList } from "@radroots/utils"; import type { Database } from "sql.js"; -import type { GeocoderErrorMessage, GeocoderReverseResult } from "./types"; +import type { GeocoderDegreeOffset, GeocoderErrorMessage, GeocoderReverseResult } from "./types"; import { parse_geocode_reverse_result } from "./utils"; +const KM_PER_DEGREE_LATITUDE = 111; + export class Geocoder { private _db: Database | null = null; private _database_name: string; @@ -12,7 +14,7 @@ export class Geocoder { this._database_name = database_name; } - public async connect(): Promise<true | GeocoderErrorMessage> { + public async connect(): Promise<true | ErrorMessage<GeocoderErrorMessage>> { try { const init_sqljs = await import("sql.js"); const sql = await init_sqljs.default(); @@ -22,28 +24,38 @@ export class Geocoder { return true; } catch (e) { console.log(`Error: Geocoder connect `, e); - return `*`; + return err_msg(`*`); }; } + + public async reverse(opts: { point: GeolocationCoordinatesPoint; - }): Promise<{ results: GeocoderReverseResult[] } | GeocoderErrorMessage> { + degree_offset?: GeocoderDegreeOffset; + limit?: number | false; + }): Promise<ResultsList<GeocoderReverseResult> | ErrorMessage<GeocoderErrorMessage>> { try { - const stmt = this._db?.prepare(`SELECT * FROM geonames WHERE id IN (SELECT feature_id FROM coordinates WHERE latitude BETWEEN $lat - 1.5 AND $lat + 1.5 AND longitude BETWEEN $lng - 1.5 AND $lng + 1.5 ORDER BY (($lat - latitude) * ($lat - latitude) + ($lng - longitude) * ($lng - longitude) * $scale) ASC LIMIT 1)`); - if (!stmt) return `*-statement`; + if (!this._db) return err_msg(`*-db`); + const limit = typeof opts.limit === `boolean` ? `` : opts.limit ? Math.round(opts.limit) : `1`; + const deg_offset = opts.degree_offset || 0.5; + const query = `SELECT * FROM geonames WHERE id IN (SELECT feature_id FROM coordinates WHERE latitude BETWEEN $lat - ${deg_offset} AND $lat + ${deg_offset} AND longitude BETWEEN $lng - ${deg_offset} AND $lng + ${deg_offset} ORDER BY (($lat - latitude) * ($lat - latitude) + ($lng - longitude) * ($lng - longitude) * $scale) ASC${limit ? ` LIMIT ${limit}` : ``});` + const stmt = this._db.prepare(query); + if (!stmt) return err_msg(`*-statement`); const { lat: $lat, lng: $lng } = opts.point; - stmt.bind({ $lat, $lng, $scale: Math.pow(Math.cos($lat * Math.PI / 180), 2) }); + const latScale = KM_PER_DEGREE_LATITUDE; + const lngScale = KM_PER_DEGREE_LATITUDE * Math.cos($lat * (Math.PI / 180)); + const $scale = (latScale + lngScale) / 2; + stmt.bind({ $lat, $lng, $scale }); const results: GeocoderReverseResult[] = []; while (stmt.step()) { - const row = stmt.getAsObject(); - const result = parse_geocode_reverse_result(row); + const result = parse_geocode_reverse_result(stmt.getAsObject()); if (result) results.push(result); }; return { results }; } catch (e) { console.log(`Error: Geocoder reverse `, e); - return `*`; + return err_msg(`*`); }; } } \ No newline at end of file diff --git a/geocoder/src/types.ts b/geocoder/src/types.ts @@ -1,14 +1,17 @@ export type GeocoderErrorMessage = | `*-statement` + | `*-db` | `*` export type GeocoderReverseResult = { id: number; name: string; - admin1_id: number; + admin1_id: string | number; admin1_name: string; country_id: string; country_name: string; latitude: number; longitude: number; }; + +export type GeocoderDegreeOffset = 0.5 | 1.0 | 1.5 | 2.0 | 2.5 | 3 diff --git a/geocoder/src/utils.ts b/geocoder/src/utils.ts @@ -3,17 +3,19 @@ import type { GeocoderReverseResult } from "./types"; export const parse_geocode_reverse_result = (obj: any): GeocoderReverseResult | undefined => { if (typeof obj !== 'object' || !obj) return undefined; const { id, name, admin1_id, admin1_name, country_id, country_name, latitude, longitude } = obj; - if (typeof id !== "number" || - typeof name !== "string" || !name || - typeof admin1_id !== "number" || - typeof admin1_name !== "string" || !admin1_name || - typeof country_id !== "string" || !country_id || - typeof country_name !== "string" || !country_name || - typeof latitude !== "number" || - typeof longitude !== "number") { + if ( + typeof id !== `number` || + typeof name !== `string` || + typeof admin1_id !== `string` || + typeof admin1_name !== `string` || + typeof country_id !== `string` || + typeof country_name !== `string` || + typeof latitude !== `number` || + typeof longitude !== `number` + ) { return undefined; } - return { + const result: GeocoderReverseResult = { id, name, admin1_id, @@ -23,4 +25,5 @@ export const parse_geocode_reverse_result = (obj: any): GeocoderReverseResult | latitude, longitude }; + return result; };