forked from MapComplete/MapComplete
		
	Fetch taginfo: add code to get all countries, imrove docs
This commit is contained in:
		
							parent
							
								
									68602cba94
								
							
						
					
					
						commit
						5c2823287a
					
				
					 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue