| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  | import { Store, UIEventSource } from "../UIEventSource" | 
					
						
							| 
									
										
										
										
											2024-09-03 01:14:08 +02:00
										 |  |  | import GeocodingProvider, { GeocodingOptions, GeocodeResult } from "./GeocodingProvider" | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  | import { OsmId } from "../../Models/OsmFeature" | 
					
						
							|  |  |  | import { SpecialVisualizationState } from "../../UI/SpecialVisualization" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-03 01:14:08 +02:00
										 |  |  | export default class OpenStreetMapIdSearch implements GeocodingProvider<GeocodeResult> { | 
					
						
							|  |  |  |     private static readonly regex = /((https?:\/\/)?(www.)?(osm|openstreetmap).org\/)?(n|node|w|way|r|relation)[/ ]?([0-9]+)/ | 
					
						
							| 
									
										
										
										
											2024-08-29 16:14:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private static readonly types: Readonly<Record<string, "node" | "way" | "relation">> = { | 
					
						
							|  |  |  |         "n":"node", | 
					
						
							|  |  |  |         "w":"way", | 
					
						
							|  |  |  |         "r":"relation", | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private readonly _state: SpecialVisualizationState | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(state: SpecialVisualizationState) { | 
					
						
							|  |  |  |         this._state = state | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("osm.org/node/42") // => "node/42"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("https://openstreetmap.org/node/42#map=19/51.204245/3.212731") // => "node/42"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("node/42") // => "node/42"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("way/42") // => "way/42"
 | 
					
						
							| 
									
										
										
										
											2024-08-29 16:14:12 +02:00
										 |  |  |      * OpenStreetMapIdSearch.extractId("n123456789") // => "node/123456789"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("node123456789") // => "node/123456789"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("node 123456789") // => "node/123456789"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("w123456789") // => "way/123456789"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("way123456789") // => "way/123456789"
 | 
					
						
							|  |  |  |      * OpenStreetMapIdSearch.extractId("way 123456789") // => "way/123456789"
 | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  |      * OpenStreetMapIdSearch.extractId("https://www.openstreetmap.org/node/5212733638") // => "node/5212733638"
 | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public static extractId(query: string): OsmId | undefined { | 
					
						
							|  |  |  |         const match = query.match(OpenStreetMapIdSearch.regex) | 
					
						
							|  |  |  |         if (match) { | 
					
						
							| 
									
										
										
										
											2024-08-29 16:14:12 +02:00
										 |  |  |             let type = match.at(-2) | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  |             const id = match.at(-1) | 
					
						
							| 
									
										
										
										
											2024-08-29 16:14:12 +02:00
										 |  |  |             if(type.length === 1){ | 
					
						
							|  |  |  |                type = OpenStreetMapIdSearch.types[type] | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  |             return <OsmId>(type + "/" + id) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return undefined | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-03 01:14:08 +02:00
										 |  |  |     async search(query: string, options?: GeocodingOptions): Promise<GeocodeResult[]> { | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  |         const id = OpenStreetMapIdSearch.extractId(query) | 
					
						
							|  |  |  |         if (!id) { | 
					
						
							|  |  |  |             return [] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const [osm_type, osm_id] = id.split("/") | 
					
						
							|  |  |  |         const obj = await this._state.osmObjectDownloader.DownloadObjectAsync(id) | 
					
						
							|  |  |  |         if (obj === "deleted") { | 
					
						
							|  |  |  |             return [{ | 
					
						
							|  |  |  |                 display_name: id + " was deleted", | 
					
						
							|  |  |  |                 category: "coordinate", | 
					
						
							|  |  |  |                 osm_type: <"node" | "way" | "relation">osm_type, | 
					
						
							|  |  |  |                 osm_id, | 
					
						
							|  |  |  |                 lat: 0, lon: 0, | 
					
						
							|  |  |  |                 source: "osmid" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const [lat, lon] = obj.centerpoint() | 
					
						
							|  |  |  |         return [{ | 
					
						
							|  |  |  |             lat, lon, | 
					
						
							|  |  |  |             display_name: obj.tags.name ?? obj.tags.alt_name ?? obj.tags.local_name ?? obj.tags.ref ?? id, | 
					
						
							|  |  |  |             osm_type: <"node" | "way" | "relation">osm_type, | 
					
						
							|  |  |  |             osm_id, | 
					
						
							|  |  |  |             source: "osmid" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-03 01:14:08 +02:00
										 |  |  |     suggest?(query: string, options?: GeocodingOptions): Store<GeocodeResult[]> { | 
					
						
							| 
									
										
										
										
											2024-08-25 02:40:56 +02:00
										 |  |  |         return UIEventSource.FromPromise(this.search(query, options)) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |