Fetch taginfo: add code to get all countries, imrove docs
This commit is contained in:
parent
6038f0d6ad
commit
f5d1b47bda
1 changed files with 76 additions and 2 deletions
|
@ -1,35 +1,48 @@
|
|||
import { Utils } from "../../Utils"
|
||||
import type { FeatureCollection } from "geojson"
|
||||
|
||||
export interface TagInfoStats {
|
||||
/**
|
||||
* The total number of entries in the data array, **not** the total number of objects known in OSM!
|
||||
*
|
||||
* Use `data.find(item => item.type==="all").count` for this
|
||||
* @deprecated: you probably want to use data.find(item => item.type==="all").count
|
||||
*/
|
||||
total: number
|
||||
data: {
|
||||
type: "all" | "nodes" | "ways" | "relations"
|
||||
// Absolute number
|
||||
count: number
|
||||
// Relative, percentage
|
||||
count_fraction: number
|
||||
}[]
|
||||
}
|
||||
|
||||
interface GeofabrikCountryProperties {
|
||||
id: string,
|
||||
parent: string | "europe" | "asia",
|
||||
urls: string[],
|
||||
name: string,
|
||||
"iso3166-1:alpha2": string[]
|
||||
}
|
||||
|
||||
export default class TagInfo {
|
||||
public static readonly global = new TagInfo()
|
||||
private readonly _backend: string
|
||||
private static _geofabrikCountries = undefined
|
||||
|
||||
constructor(backend = "https://taginfo.openstreetmap.org/") {
|
||||
this._backend = backend
|
||||
}
|
||||
|
||||
public getStats(key: string, value?: string): Promise<TagInfoStats> {
|
||||
public async getStats(key: string, value?: string): Promise<TagInfoStats> {
|
||||
let url: string
|
||||
if (value) {
|
||||
url = `${this._backend}api/4/tag/stats?key=${key}&value=${value}`
|
||||
} else {
|
||||
url = `${this._backend}api/4/key/stats?key=${key}`
|
||||
}
|
||||
return Utils.downloadJsonCached(url, 1000 * 60 * 60)
|
||||
return await Utils.downloadJsonCached<TagInfoStats>(url, 1000 * 60 * 60)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,4 +57,65 @@ export default class TagInfo {
|
|||
return `${this._backend}/keys/${k}#overview`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not work in the browser due to some resources not being CORS-accessible
|
||||
*/
|
||||
public static async geofabrikCountries(): Promise<GeofabrikCountryProperties[]> {
|
||||
if (TagInfo._geofabrikCountries) {
|
||||
return TagInfo._geofabrikCountries
|
||||
}
|
||||
const countriesFC: FeatureCollection = await Utils.downloadJsonCached<FeatureCollection>("https://download.geofabrik.de/index-v1-nogeom.json", 24 * 1000 * 60 * 60)
|
||||
TagInfo._geofabrikCountries = countriesFC.features.map(f => <GeofabrikCountryProperties>f.properties)
|
||||
return TagInfo._geofabrikCountries
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TagInfo-api-object for geofabrik for the given country.
|
||||
* Returns undefined if geofabrik does not have such a country
|
||||
*
|
||||
* Does not work in the browser due to some resources not being CORS-accessible
|
||||
* @param countryCode: an iso3166-1:alpha2 code
|
||||
*/
|
||||
public static async getInstanceFor(countryCode: string) {
|
||||
const countries = await this.geofabrikCountries()
|
||||
countryCode = countryCode.toUpperCase()
|
||||
const country = countries.find(c => c["iso3166-1:alpha2"]?.indexOf(countryCode) >= 0)
|
||||
if (!country || !country?.parent || !country?.id) {
|
||||
return undefined
|
||||
}
|
||||
const url = `https://taginfo.geofabrik.de/${country.parent}:${country.id}/`
|
||||
return new TagInfo(url)
|
||||
}
|
||||
|
||||
private static async getDistributionsFor(countryCode: string, key: string, value?: string): Promise<TagInfoStats>{
|
||||
if (!countryCode) {
|
||||
return undefined
|
||||
}
|
||||
const ti = await TagInfo.getInstanceFor(countryCode)
|
||||
if (!ti) {
|
||||
return undefined
|
||||
}
|
||||
try {
|
||||
return await ti.getStats(key, value)
|
||||
} catch (e) {
|
||||
console.warn("Could not fetch info for", countryCode,key,value, "due to", e)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
public static async getGlobalDistributionsFor(key: string, value?: string): Promise<Record<string, TagInfoStats>> {
|
||||
const countries = await this.geofabrikCountries()
|
||||
const perCountry: Record<string, TagInfoStats> = {}
|
||||
const results = await Promise.all(countries.map(country => TagInfo.getDistributionsFor(country?.["iso3166-1:alpha2"]?.[0], key, value)))
|
||||
for (let i = 0; i < countries.length; i++){
|
||||
const country = countries[i]
|
||||
const countryCode = country["iso3166-1:alpha2"]?.[0]
|
||||
if(results[i]){
|
||||
perCountry[countryCode] = results[i]
|
||||
}
|
||||
}
|
||||
return perCountry
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue