From 71b1e80a1f0bc4593448815abfdd6d65151dc83d Mon Sep 17 00:00:00 2001 From: Pieter Fiers Date: Wed, 29 Jul 2020 17:16:59 +0200 Subject: [PATCH] Switched to regex for service:bicycle: --- Customizations/Layers/BikeCafes.ts | 39 +++++++----------- Customizations/Layers/BikeOtherShops.ts | 15 +------ Logic/TagsFilter.ts | 53 +++++++++++++++++++------ 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/Customizations/Layers/BikeCafes.ts b/Customizations/Layers/BikeCafes.ts index 29ff9ef27..2f9ca6f10 100644 --- a/Customizations/Layers/BikeCafes.ts +++ b/Customizations/Layers/BikeCafes.ts @@ -12,37 +12,27 @@ import CafePump from "../Questions/bike/CafePump"; export default class BikeCafes extends LayerDefinition { - private readonly repairsBikes = anyValueExcept("service:bicycle:repair", "no") - private readonly hasPump = new Tag("service:bicycle:pump", "yes") - private readonly diy = new Tag("service:bicycle:diy", "yes") - private readonly bikeServices = [ - this.diy, - this.repairsBikes, - this.hasPump - ] private readonly to = Translations.t.cyclofix.cafe constructor() { - super(); - this.name = this.to.name; - this.icon = "./assets/bike/cafe.svg"; + super() + this.name = this.to.name + this.icon = "./assets/bike/cafe.svg" this.overpassFilter = new And([ + new Tag("amenity", /^pub|bar|cafe$/), new Or([ - new Regex("amenity", "^pub|bar|cafe") - ]), - new Or([ - ...this.bikeServices, + new Tag(/^service:bicycle:/, "*"), new Tag("pub", "cycling") ]) ]) this.newElementTags = [ new Tag("amenity", "pub"), new Tag("pub", "cycling"), - ]; - this.maxAllowedOverlapPercentage = 10; + ] + this.maxAllowedOverlapPercentage = 10 - this.minzoom = 13; - this.style = this.generateStyleFunction(); + this.minzoom = 13 + this.style = this.generateStyleFunction() this.title = new FixedText(this.to.title) this.elementsToShow = [ new ImageCarouselWithUploadConstructor(), @@ -52,13 +42,12 @@ export default class BikeCafes extends LayerDefinition { new CafeRepair(), new CafeDiy(), new CafePump() - ]; - this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY; - + ] + this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY } private generateStyleFunction() { - const self = this; + const self = this return function (properties: any) { return { color: "#00bb00", @@ -67,7 +56,7 @@ export default class BikeCafes extends LayerDefinition { iconSize: [50, 50], iconAnchor: [25,50] } - }; - }; + } + } } } diff --git a/Customizations/Layers/BikeOtherShops.ts b/Customizations/Layers/BikeOtherShops.ts index 5c8bacc6e..95d218ff8 100644 --- a/Customizations/Layers/BikeOtherShops.ts +++ b/Customizations/Layers/BikeOtherShops.ts @@ -16,19 +16,6 @@ import Website from "../Questions/Website"; export default class BikeOtherShops extends LayerDefinition { private readonly sellsBikes = new Tag("service:bicycle:retail", "yes") - private readonly repairsBikes = anyValueExcept("service:bicycle:repair", "no") - private readonly rentsBikes = new Tag("service:bicycle:rental", "yes") - private readonly hasPump = new Tag("service:bicycle:pump", "yes") - private readonly hasDiy = new Tag("service:bicycle:diy", "yes") - private readonly sellsSecondHand = anyValueExcept("service:bicycle:repair", "no") - private readonly hasBikeServices = new Or([ - this.sellsBikes, - this.repairsBikes, - // this.rentsBikes, - // this.hasPump, - // this.hasDiy, - // this.sellsSecondHand - ]) private readonly to = Translations.t.cyclofix.nonBikeShop @@ -38,7 +25,7 @@ export default class BikeOtherShops extends LayerDefinition { this.icon = "./assets/bike/non_bike_repair_shop.svg" this.overpassFilter = new And([ anyValueExcept("shop", "bicycle"), - this.hasBikeServices + new Tag(/^service:bicycle:/, "*"), ]) this.newElementTags = undefined this.maxAllowedOverlapPercentage = 10 diff --git a/Logic/TagsFilter.ts b/Logic/TagsFilter.ts index 0a2d3a556..827548ad3 100644 --- a/Logic/TagsFilter.ts +++ b/Logic/TagsFilter.ts @@ -55,24 +55,37 @@ export class Regex extends TagsFilter { export class Tag extends TagsFilter { - public key: string - public value: string + public key: string | RegExp + public value: string | RegExp public invertValue: boolean - constructor(key: string, value: string, invertValue = false) { + constructor(key: string | RegExp, value: string | RegExp, invertValue = false) { + if (value === "*" && invertValue) { + throw new Error("Invalid combination: invertValue && value == *") + } + + if (value instanceof RegExp && invertValue) { + throw new Error("Unsupported combination: RegExp value and inverted value (use regex to invert the match)") + } + super() this.key = key this.value = value this.invertValue = invertValue + } - if (value === "*" && invertValue) { - throw new Error("Invalid combination: invertValue && value == *") + private static regexOrStrMatches(regexOrStr: string | RegExp, testStr: string) { + if (typeof regexOrStr === 'string') { + return regexOrStr === testStr + } else if (regexOrStr instanceof RegExp) { + return (regexOrStr as RegExp).test(testStr) } + throw new Error(" must be of type RegExp or string") } matches(tags: { k: string; v: string }[]): boolean { for (const tag of tags) { - if (tag.k === this.key) { + if (Tag.regexOrStrMatches(this.key, tag.k)) { if (tag.v === "") { // This tag has been removed return this.value === "" @@ -82,7 +95,7 @@ export class Tag extends TagsFilter { return true; } - return this.value === tag.v !== this.invertValue + return Tag.regexOrStrMatches(this.value, tag.v) !== this.invertValue } } @@ -94,19 +107,33 @@ export class Tag extends TagsFilter { } asOverpass(): string[] { - if (this.value === "*") { - return ['["' + this.key + '"]']; + const keyIsRegex = this.key instanceof RegExp + const key = keyIsRegex ? (this.key as RegExp).source : this.key + + const valIsRegex = this.value instanceof RegExp + const val = valIsRegex ? (this.value as RegExp).source : this.value + + const regexKeyPrefix = keyIsRegex ? '~' : '' + const anyVal = this.value === "*" + + if (anyVal && !keyIsRegex) { + return [`[${regexKeyPrefix}"${key}"]`]; } if (this.value === "") { // NOT having this key - return ['[!"' + this.key + '"]']; + return ['[!"' + key + '"]']; } - const compareOperator = this.invertValue ? '!=' : '=' - return ['["' + this.key + '"' + compareOperator + '"' + this.value + '"]']; + + const compareOperator = (valIsRegex || keyIsRegex) ? '~' : (this.invertValue ? '!=' : '=') + return [`[${regexKeyPrefix}"${key}"${compareOperator}"${keyIsRegex && anyVal ? '.' : val}"]`]; } substituteValues(tags: any) { - return new Tag(this.key, TagUtils.ApplyTemplate(this.value, tags)); + if (typeof this.value !== 'string') { + throw new Error("substituteValues() only possible with tag value of type string") + } + + return new Tag(this.key, TagUtils.ApplyTemplate(this.value as string, tags)); } }