Chore: formatting

This commit is contained in:
Pieter Vander Vennet 2024-06-16 16:06:26 +02:00
parent 35eff07c80
commit c08fe03ed0
422 changed files with 31594 additions and 43019 deletions

View file

@ -27,23 +27,23 @@ export default class LinkedDataLoader {
opening_hours: { "@id": "http://schema.org/openingHoursSpecification" },
openingHours: { "@id": "http://schema.org/openingHours", "@container": "@set" },
geo: { "@id": "http://schema.org/geo" },
alt_name: { "@id": "http://schema.org/alternateName" }
alt_name: { "@id": "http://schema.org/alternateName" },
}
private static COMPACTING_CONTEXT_OH = {
dayOfWeek: { "@id": "http://schema.org/dayOfWeek", "@container": "@set" },
closes: {
"@id": "http://schema.org/closes",
"@type": "http://www.w3.org/2001/XMLSchema#time"
"@type": "http://www.w3.org/2001/XMLSchema#time",
},
opens: {
"@id": "http://schema.org/opens",
"@type": "http://www.w3.org/2001/XMLSchema#time"
}
"@type": "http://www.w3.org/2001/XMLSchema#time",
},
}
private static formatters: Record<"phone" | "email" | "website", Validator> = {
phone: new PhoneValidator(),
email: new EmailValidator(),
website: new UrlValidator(undefined, undefined, true)
website: new UrlValidator(undefined, undefined, true),
}
private static ignoreKeys = [
"http://schema.org/logo",
@ -56,7 +56,7 @@ export default class LinkedDataLoader {
"http://schema.org/description",
"http://schema.org/hasMap",
"http://schema.org/priceRange",
"http://schema.org/contactPoint"
"http://schema.org/contactPoint",
]
private static shapeToPolygon(str: string): Polygon {
@ -69,8 +69,8 @@ export default class LinkedDataLoader {
.trim()
.split(" ")
.map((n) => Number(n))
)
]
),
],
}
}
@ -92,18 +92,18 @@ export default class LinkedDataLoader {
const context = {
lat: {
"@id": "http://schema.org/latitude",
"@type": "http://www.w3.org/2001/XMLSchema#double"
"@type": "http://www.w3.org/2001/XMLSchema#double",
},
lon: {
"@id": "http://schema.org/longitude",
"@type": "http://www.w3.org/2001/XMLSchema#double"
}
"@type": "http://www.w3.org/2001/XMLSchema#double",
},
}
const flattened = await jsonld.compact(geo, context)
return {
type: "Point",
coordinates: [Number(flattened.lon), Number(flattened.lat)]
coordinates: [Number(flattened.lon), Number(flattened.lat)],
}
}
@ -288,7 +288,7 @@ export default class LinkedDataLoader {
if (properties["latitude"] && properties["longitude"]) {
geometry = {
type: "Point",
coordinates: [Number(properties["longitude"]), Number(properties["latitude"])]
coordinates: [Number(properties["longitude"]), Number(properties["latitude"])],
}
delete properties["latitude"]
delete properties["longitude"]
@ -300,7 +300,7 @@ export default class LinkedDataLoader {
const geo: GeoJSON = {
type: "Feature",
properties,
geometry
geometry,
}
delete linkedData.geo
delete properties.shape
@ -323,7 +323,7 @@ export default class LinkedDataLoader {
if (output["type"]?.[0] === "https://data.velopark.be/openvelopark/terms#BicycleLocker") {
output["bicycle_parking"] = ["lockers"]
}
if(output["type"] === undefined){
if (output["type"] === undefined) {
console.error("No type given for", output)
}
delete output["type"]
@ -333,7 +333,7 @@ export default class LinkedDataLoader {
return
}
output[key] = output[key].map((v) => applyF(v))
if (!output[key].some(v => v !== undefined)) {
if (!output[key].some((v) => v !== undefined)) {
delete output[key]
}
}
@ -418,7 +418,7 @@ export default class LinkedDataLoader {
"brede publiek",
"iedereen",
"bezoekers",
"iedereen - vooral bezoekers gemeentehuis of bibliotheek."
"iedereen - vooral bezoekers gemeentehuis of bibliotheek.",
].indexOf(audience.toLowerCase()) >= 0
) {
return "yes"
@ -501,7 +501,7 @@ export default class LinkedDataLoader {
mv: "http://schema.mobivoc.org/",
gr: "http://purl.org/goodrelations/v1#",
vp: "https://data.velopark.be/openvelopark/vocabulary#",
vpt: "https://data.velopark.be/openvelopark/terms#"
vpt: "https://data.velopark.be/openvelopark/terms#",
},
[url],
undefined,
@ -522,7 +522,7 @@ export default class LinkedDataLoader {
mv: "http://schema.mobivoc.org/",
gr: "http://purl.org/goodrelations/v1#",
vp: "https://data.velopark.be/openvelopark/vocabulary#",
vpt: "https://data.velopark.be/openvelopark/terms#"
vpt: "https://data.velopark.be/openvelopark/terms#",
},
[url],
"g",
@ -654,7 +654,10 @@ export default class LinkedDataLoader {
* The id will be saved as `ref:velopark`
* @param url
*/
public static async fetchVeloparkEntry(url: string, includeExtras: boolean = false): Promise<Feature[]> {
public static async fetchVeloparkEntry(
url: string,
includeExtras: boolean = false
): Promise<Feature[]> {
const cacheKey = includeExtras + url
if (this.veloparkCache[cacheKey]) {
return this.veloparkCache[cacheKey]
@ -662,20 +665,20 @@ export default class LinkedDataLoader {
const withProxyUrl = Constants.linkedDataProxy.replace("{url}", encodeURIComponent(url))
const optionalPaths: Record<string, string | Record<string, string>> = {
"schema:interactionService": {
"schema:url": "website"
"schema:url": "website",
},
"mv:operatedBy": {
"gr:legalName": "operator"
"gr:legalName": "operator",
},
"schema:contactPoint": {
"schema:email": "email",
"schema:telephone": "phone"
"schema:telephone": "phone",
},
"schema:dateModified": "_last_edit_timestamp"
"schema:dateModified": "_last_edit_timestamp",
}
if (includeExtras) {
optionalPaths["schema:address"] = {
"schema:streetAddress": "addr"
"schema:streetAddress": "addr",
}
optionalPaths["schema:name"] = "name"
optionalPaths["schema:description"] = "description"
@ -693,19 +696,19 @@ export default class LinkedDataLoader {
"schema:geo": {
"schema:latitude": "latitude",
"schema:longitude": "longitude",
"schema:polygon": "shape"
"schema:polygon": "shape",
},
"schema:priceSpecification": {
"mv:freeOfCharge": "fee",
"schema:price": "charge"
}
"schema:price": "charge",
},
}
const extra = [
"schema:priceSpecification [ mv:dueForTime [ mv:timeStartValue ?chargeStart; mv:timeEndValue ?chargeEnd; mv:timeUnit ?timeUnit ] ]",
"vp:allows [vp:bicycleType <https://data.velopark.be/openvelopark/terms#CargoBicycle>; vp:bicyclesAmount ?capacityCargobike; vp:bicycleType ?cargoBikeType]",
"vp:allows [vp:bicycleType <https://data.velopark.be/openvelopark/terms#ElectricBicycle>; vp:bicyclesAmount ?capacityElectric; vp:bicycleType ?electricBikeType]",
"vp:allows [vp:bicycleType <https://data.velopark.be/openvelopark/terms#TandemBicycle>; vp:bicyclesAmount ?capacityTandem; vp:bicycleType ?tandemBikeType]"
"vp:allows [vp:bicycleType <https://data.velopark.be/openvelopark/terms#TandemBicycle>; vp:bicyclesAmount ?capacityTandem; vp:bicycleType ?tandemBikeType]",
]
const unpatched = await this.fetchEntry(

View file

@ -110,12 +110,12 @@ export class MangroveIdentity {
return []
}
const allReviews = await MangroveReviews.getReviews({
kid: pem
kid: pem,
})
this.allReviewsById.setData(
allReviews.reviews.map((r) => ({
...r,
...r.payload
...r.payload,
}))
)
})
@ -182,10 +182,10 @@ export default class FeatureReviews {
feature.geometry.type === "Polygon"
) {
coordss = feature.geometry.coordinates
}else if(feature.geometry.type === "MultiPolygon"){
} else if (feature.geometry.type === "MultiPolygon") {
coordss = feature.geometry.coordinates[0]
}else{
throw "Invalid feature type: "+feature.geometry.type
} else {
throw "Invalid feature type: " + feature.geometry.type
}
let maxDistance = 0
for (const coords of coordss) {
@ -288,7 +288,7 @@ export default class FeatureReviews {
}
const r: Review = {
sub: this.subjectUri.data,
...review
...review,
}
const keypair: CryptoKeyPair = await this._identity.getKeypair()
const jwt = await MangroveReviews.signReview(keypair, r)
@ -303,7 +303,7 @@ export default class FeatureReviews {
...r,
kid,
signature: jwt,
madeByLoggedInUser: new ImmutableStore(true)
madeByLoggedInUser: new ImmutableStore(true),
}
this._reviews.data.push(reviewWithKid)
this._reviews.ping()
@ -350,7 +350,7 @@ export default class FeatureReviews {
signature: reviewData.signature,
madeByLoggedInUser: this._identity.getKeyId().map((user_key_id) => {
return reviewData.kid === user_key_id
})
}),
})
hasNew = true
}
@ -369,12 +369,16 @@ export default class FeatureReviews {
private ConstructSubjectUri(dontEncodeName: boolean = false): Store<string> {
// https://www.rfc-editor.org/rfc/rfc5870#section-3.4.2
// `u` stands for `uncertainty`, https://www.rfc-editor.org/rfc/rfc5870#section-3.4.3
return this._name.map(name => {
return this._name.map((name) => {
let uri = `geo:${this._lat},${this._lon}?u=${Math.round(this._uncertainty)}`
if (name) {
uri += "&q=" + (dontEncodeName ? name : encodeURIComponent(name))
}else if(this._uncertainty > 1000){
console.error("Not fetching reviews. Only got a point and a very big uncertainty range ("+this._uncertainty+"), so you'd probably only get garbage. Specify a name")
} else if (this._uncertainty > 1000) {
console.error(
"Not fetching reviews. Only got a point and a very big uncertainty range (" +
this._uncertainty +
"), so you'd probably only get garbage. Specify a name"
)
return undefined
}
return uri

View file

@ -48,7 +48,7 @@ export interface NSIItem {
displayName: string
id: string
locationSet: {
include: string[],
include: string[]
exclude: string[]
}
tags: Record<string, string>
@ -56,11 +56,15 @@ export interface NSIItem {
}
export default class NameSuggestionIndex {
private static readonly nsiFile: Readonly<NSIFile> = <any>nsi
private static readonly nsiWdFile: Readonly<Record<string, {
logos: { wikidata?: string, facebook?: string }
}>> = <any>nsiWD["wikidata"]
private static readonly nsiWdFile: Readonly<
Record<
string,
{
logos: { wikidata?: string; facebook?: string }
}
>
> = <any>nsiWD["wikidata"]
private static loco = new LocationConflation(nsiFeatures) // Some additional boundaries
@ -71,9 +75,11 @@ export default class NameSuggestionIndex {
return this._supportedTypes
}
const keys = Object.keys(NameSuggestionIndex.nsiFile.nsi)
const all = keys.map(k => NameSuggestionIndex.nsiFile.nsi[k].properties.path.split("/")[0])
this._supportedTypes = Utils.Dedup(all).map(s => {
if(s.endsWith("s")){
const all = keys.map(
(k) => NameSuggestionIndex.nsiFile.nsi[k].properties.path.split("/")[0]
)
this._supportedTypes = Utils.Dedup(all).map((s) => {
if (s.endsWith("s")) {
s = s.substring(0, s.length - 1)
}
return s
@ -81,7 +87,6 @@ export default class NameSuggestionIndex {
return this._supportedTypes
}
/**
* Fetches the data files for a single country. Note that it contains _all_ entries having this brand, not for a single type of object
* @param type
@ -89,19 +94,24 @@ export default class NameSuggestionIndex {
* @private
*/
private static async fetchFrequenciesFor(type: string, countries: string[]) {
let stats = await Promise.all(countries.map(c => {
try {
return Utils.downloadJsonCached<Record<string, number>>(`./assets/data/nsi/stats/${type}.${c.toUpperCase()}.json`, 24 * 60 * 60 * 1000)
} catch (e) {
console.error("Could not fetch " + type + " statistics due to", e)
return undefined
}
}))
let stats = await Promise.all(
countries.map((c) => {
try {
return Utils.downloadJsonCached<Record<string, number>>(
`./assets/data/nsi/stats/${type}.${c.toUpperCase()}.json`,
24 * 60 * 60 * 1000
)
} catch (e) {
console.error("Could not fetch " + type + " statistics due to", e)
return undefined
}
})
)
stats = Utils.NoNull(stats)
if (stats.length === 1) {
return stats[0]
}
if(stats.length === 0){
if (stats.length === 0) {
return {}
}
const merged = stats[0]
@ -128,7 +138,12 @@ export default class NameSuggestionIndex {
return false
}
public static async generateMappings(type: string, tags: Record<string, string>, country: string[], location?: [number, number]): Promise<Mapping[]> {
public static async generateMappings(
type: string,
tags: Record<string, string>,
country: string[],
location?: [number, number]
): Promise<Mapping[]> {
const mappings: Mapping[] = []
const frequencies = await NameSuggestionIndex.fetchFrequenciesFor(type, country)
for (const key in tags) {
@ -136,8 +151,14 @@ export default class NameSuggestionIndex {
continue
}
const value = tags[key]
const actualBrands = NameSuggestionIndex.getSuggestionsForKV(type, key, value, country.join(";"), location)
if(!actualBrands){
const actualBrands = NameSuggestionIndex.getSuggestionsForKV(
type,
key,
value,
country.join(";"),
location
)
if (!actualBrands) {
continue
}
for (const nsiItem of actualBrands) {
@ -156,7 +177,9 @@ export default class NameSuggestionIndex {
}
mappings.push({
if: new Tag(type, tags[type]),
addExtraTags: Object.keys(tags).filter(k => k !== type).map(k => new Tag(k, tags[k])),
addExtraTags: Object.keys(tags)
.filter((k) => k !== type)
.map((k) => new Tag(k, tags[k])),
then: new TypedTranslation<Record<string, never>>({ "*": nsiItem.displayName }),
hideInAnswer: false,
ifnot: undefined,
@ -164,22 +187,23 @@ export default class NameSuggestionIndex {
icon,
iconClass: "medium",
priorityIf: frequency > 0 ? new RegexTag("id", /.*/) : undefined,
searchTerms: { "*": [nsiItem.displayName, nsiItem.id] }
searchTerms: { "*": [nsiItem.displayName, nsiItem.id] },
})
}
}
return mappings
}
public static supportedTags(type: "operator" | "brand" | "flag" | "transit" | string): Record<string, string[]> {
const tags: Record<string, string []> = {}
public static supportedTags(
type: "operator" | "brand" | "flag" | "transit" | string
): Record<string, string[]> {
const tags: Record<string, string[]> = {}
const keys = Object.keys(NameSuggestionIndex.nsiFile.nsi)
for (const key of keys) {
const nsiItem = NameSuggestionIndex.nsiFile.nsi[key]
const path = nsiItem.properties.path
const [osmType, osmkey, osmvalue] = path.split("/")
if (type !== osmType && (type + "s" !== osmType)) {
if (type !== osmType && type + "s" !== osmType) {
continue
}
if (!tags[osmkey]) {
@ -204,7 +228,7 @@ export default class NameSuggestionIndex {
options.push(...suggestions)
}
}
return (options)
return options
}
/**
@ -212,8 +236,15 @@ export default class NameSuggestionIndex {
* @param country: a string containing one or more country codes, separated by ";"
* @param location: center point of the feature, should be [lon, lat]
*/
public static getSuggestionsFor(type: string, tags: {key: string, value: string}[], country: string = undefined, location: [number, number] = undefined): NSIItem[] {
return tags.flatMap(tag => this.getSuggestionsForKV(type, tag.key, tag.value, country, location))
public static getSuggestionsFor(
type: string,
tags: { key: string; value: string }[],
country: string = undefined,
location: [number, number] = undefined
): NSIItem[] {
return tags.flatMap((tag) =>
this.getSuggestionsForKV(type, tag.key, tag.value, country, location)
)
}
/**
@ -221,18 +252,26 @@ export default class NameSuggestionIndex {
* @param country: a string containing one or more country codes, separated by ";"
* @param location: center point of the feature, should be [lon, lat]
*/
public static getSuggestionsForKV(type: string, key: string, value: string, country: string = undefined, location: [number, number] = undefined): NSIItem[] {
public static getSuggestionsForKV(
type: string,
key: string,
value: string,
country: string = undefined,
location: [number, number] = undefined
): NSIItem[] {
const path = `${type}s/${key}/${value}`
const entry = NameSuggestionIndex.nsiFile.nsi[path]
return entry?.items?.filter(i => {
return entry?.items?.filter((i) => {
if (i.locationSet.include.indexOf("001") >= 0) {
return true
}
if (country === undefined ||
if (
country === undefined ||
// We prefer the countries provided by lonlat2country, they are more precise
// Country might contain multiple countries, separated by ';'
i.locationSet.include.some(c => country.indexOf(c) >= 0)) {
i.locationSet.include.some((c) => country.indexOf(c) >= 0)
) {
return true
}

View file

@ -50,10 +50,8 @@ export default class NearbyImagesSearch {
constructor(options: NearbyImageOptions, features: IndexedFeatureSource) {
this.individualStores = NearbyImagesSearch.services
.filter(s => s !== "kartaview" /*DEAD*/)
.map((s) =>
NearbyImagesSearch.buildPictureFetcher(options, s)
)
.filter((s) => s !== "kartaview" /*DEAD*/)
.map((s) => NearbyImagesSearch.buildPictureFetcher(options, s))
const allDone = new UIEventSource(false)
this.allDone = allDone

View file

@ -19,10 +19,10 @@ export interface TagInfoStats {
}
interface GeofabrikCountryProperties {
id: string,
parent: string | "europe" | "asia",
urls: string[],
name: string,
id: string
parent: string | "europe" | "asia"
urls: string[]
name: string
"iso3166-1:alpha2": string[]
}
@ -38,7 +38,9 @@ export default class TagInfo {
public async getStats(key: string, value?: string): Promise<TagInfoStats> {
let url: string
if (value) {
url = `${this._backend}api/4/tag/stats?key=${encodeURIComponent(key)}&value=${encodeURIComponent(value)}`
url = `${this._backend}api/4/tag/stats?key=${encodeURIComponent(
key
)}&value=${encodeURIComponent(value)}`
} else {
url = `${this._backend}api/4/key/stats?key=${encodeURIComponent(key)}`
}
@ -65,8 +67,13 @@ export default class TagInfo {
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)
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
}
@ -80,7 +87,7 @@ export default class TagInfo {
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)
const country = countries.find((c) => c["iso3166-1:alpha2"]?.indexOf(countryCode) >= 0)
if (!country || !country?.parent || !country?.id) {
return undefined
}
@ -88,7 +95,11 @@ export default class TagInfo {
return new TagInfo(url)
}
private static async getDistributionsFor(countryCode: string, key: string, value?: string): Promise<TagInfoStats>{
private static async getDistributionsFor(
countryCode: string,
key: string,
value?: string
): Promise<TagInfoStats> {
if (!countryCode) {
return undefined
}
@ -99,24 +110,30 @@ export default class TagInfo {
try {
return await ti.getStats(key, value)
} catch (e) {
console.warn("Could not fetch info for", countryCode,key,value, "due to", e)
console.warn("Could not fetch info for", countryCode, key, value, "due to", e)
return undefined
}
}
private static readonly blacklist =["VI","GF","PR"]
private static readonly blacklist = ["VI", "GF", "PR"]
public static async getGlobalDistributionsFor(key: string, value?: string): Promise<Record<string, TagInfoStats>> {
public static async getGlobalDistributionsFor(
key: string,
value?: string
): Promise<Record<string, TagInfoStats>> {
const countriesAll = await this.geofabrikCountries()
const countries = countriesAll.map(c => c["iso3166-1:alpha2"]?.[0]).filter(c => !!c && TagInfo.blacklist.indexOf(c) < 0)
const countries = countriesAll
.map((c) => c["iso3166-1:alpha2"]?.[0])
.filter((c) => !!c && TagInfo.blacklist.indexOf(c) < 0)
const perCountry: Record<string, TagInfoStats> = {}
const results = await Promise.all(countries.map(country => TagInfo.getDistributionsFor(country, key, value)))
for (let i = 0; i < countries.length; i++){
const results = await Promise.all(
countries.map((country) => TagInfo.getDistributionsFor(country, key, value))
)
for (let i = 0; i < countries.length; i++) {
const countryCode = countries[i]
if(results[i]){
perCountry[countryCode] = results[i]
if (results[i]) {
perCountry[countryCode] = results[i]
}
}
return perCountry
}
}