From 1ffad21c62008ec6dec12466281675b0de0b194b Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Mon, 22 Mar 2021 02:17:00 +0100 Subject: [PATCH] Refactoring of tagsFilters, fix conditional 'hideInAnswer' --- Customizations/JSON/TagRenderingConfigJson.ts | 15 +++- Logic/Tags.ts | 58 ++++++++-------- UI/Popup/TagRenderingQuestion.ts | 2 +- .../bike_repair_station.json | 3 +- test/Tag.spec.ts | 69 +++++++++---------- 5 files changed, 79 insertions(+), 68 deletions(-) diff --git a/Customizations/JSON/TagRenderingConfigJson.ts b/Customizations/JSON/TagRenderingConfigJson.ts index ec12afb..918b98d 100644 --- a/Customizations/JSON/TagRenderingConfigJson.ts +++ b/Customizations/JSON/TagRenderingConfigJson.ts @@ -97,8 +97,21 @@ export interface TagRenderingConfigJson { * then: "Maintained by Agentschap Natuur en Bos" * hideInAnswer: true * } + * + * Hide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate + * + * e.g. + * + * + * Also have a look for the meta-tags + * + * { + * if: "operator=Agentschap Natuur en Bos", + * then: "Maintained by Agentschap Natuur en Bos", + * hideInAnswer: "_country!=be" + * } */ - hideInAnswer?: boolean, + hideInAnswer?: boolean | string | AndOrTagConfigJson, /** * Only applicable if 'multiAnswer' is set. * This is for situations such as: diff --git a/Logic/Tags.ts b/Logic/Tags.ts index ec3d733..7a36612 100644 --- a/Logic/Tags.ts +++ b/Logic/Tags.ts @@ -1,7 +1,6 @@ import {Utils} from "../Utils"; export abstract class TagsFilter { - abstract matches(tags: { k: string, v: string }[]): boolean abstract asOverpass(): string[] @@ -11,13 +10,19 @@ export abstract class TagsFilter { abstract isEquivalent(other: TagsFilter): boolean; - matchesProperties(properties: Map): boolean { - return this.matches(TagUtils.proprtiesToKV(properties)); - } + abstract matchesProperties(properties: any): boolean; abstract asHumanString(linkToWiki: boolean, shorten: boolean); abstract usedKeys(): string[]; + + public matches(tags: {k: string, v: string}[]){ + const properties = {}; + for (const kv of tags) { + properties[kv.k] = kv.v; + } + return this.matchesProperties(properties); + } } @@ -59,14 +64,15 @@ export class RegexTag extends TagsFilter { isUsableAsAnswer(): boolean { return false; } - - matches(tags: { k: string; v: string }[]): boolean { - for (const tag of tags) { - if (RegexTag.doesMatch(tag.k, this.key)) { - return RegexTag.doesMatch(tag.v, this.value) != this.invert; + + matchesProperties(tags: any): boolean { + for (const key in tags) { + if (RegexTag.doesMatch(key, this.key)) { + const value = tags[key] + return RegexTag.doesMatch(value, this.value) != this.invert; } } - if(this.matchesEmpty){ + if (this.matchesEmpty) { // The value is 'empty' return !this.invert; } @@ -123,14 +129,14 @@ export class Tag extends TagsFilter { } } - matches(tags: { k: string; v: string }[]): boolean { - - for (const tag of tags) { - if (this.key == tag.k) { - return this.value === tag.v; + + matchesProperties(properties: any): boolean { + for (const propertiesKey in properties) { + if(this.key === propertiesKey){ + const value = properties[propertiesKey]; + return value === this.value; } - } - + } // The tag was not found if (this.value === "") { // and it shouldn't be found! @@ -192,10 +198,10 @@ export class Or extends TagsFilter { super(); this.or = or; } - - matches(tags: { k: string; v: string }[]): boolean { + + matchesProperties(properties: any): boolean { for (const tagsFilter of this.or) { - if (tagsFilter.matches(tags)) { + if (tagsFilter.matchesProperties(properties)) { return true; } } @@ -270,9 +276,9 @@ export class And extends TagsFilter { return values; } - matches(tags: { k: string; v: string }[]): boolean { + matchesProperties(tags: any): boolean { for (const tagsFilter of this.and) { - if (!tagsFilter.matches(tags)) { + if (!tagsFilter.matchesProperties(tags)) { return false; } } @@ -374,14 +380,6 @@ export class And extends TagsFilter { export class TagUtils { - static proprtiesToKV(properties: any): { k: string, v: string }[] { - const result = []; - for (const k in properties) { - result.push({k: k, v: properties[k]}) - } - return result; - } - static ApplyTemplate(template: string, tags: any): string { for (const k in tags) { while (template.indexOf("{" + k + "}") >= 0) { diff --git a/UI/Popup/TagRenderingQuestion.ts b/UI/Popup/TagRenderingQuestion.ts index 4242951..db5c922 100644 --- a/UI/Popup/TagRenderingQuestion.ts +++ b/UI/Popup/TagRenderingQuestion.ts @@ -221,7 +221,7 @@ export default class TagRenderingQuestion extends UIElement { if (mapping.hideInAnswer === true) { return undefined; } - if(typeof(mapping.hideInAnswer) !== "boolean" && mapping.hideInAnswer.matches(this._tags.data)){ + if(typeof(mapping.hideInAnswer) !== "boolean" && mapping.hideInAnswer.matchesProperties(this._tags.data)){ return undefined; } return new FixedInputElement( diff --git a/assets/layers/bike_repair_station/bike_repair_station.json b/assets/layers/bike_repair_station/bike_repair_station.json index 6667aac..862de26 100644 --- a/assets/layers/bike_repair_station/bike_repair_station.json +++ b/assets/layers/bike_repair_station/bike_repair_station.json @@ -188,7 +188,8 @@ "mappings": [ { "if": "operator=De Fietsambassade Gent", - "then": "De Fietsambassade Gent" + "then": "De Fietsambassade Gent", + "hideInAnswer": "_country!=be" } ] }, diff --git a/test/Tag.spec.ts b/test/Tag.spec.ts index bb82861..2d9dc49 100644 --- a/test/Tag.spec.ts +++ b/test/Tag.spec.ts @@ -27,24 +27,24 @@ new T("Tags", [ const tag = FromJSON.Tag("key=value") as Tag; equal(tag.key, "key"); equal(tag.value, "value"); - equal(tag.matches([{k:"key",v:"value"}]), true) - equal(tag.matches([{k:"key",v:"z"}]), false) - equal(tag.matches([{k:"key",v:""}]), false) - equal(tag.matches([{k:"other_key",v:""}]), false) - equal(tag.matches([{k:"other_key",v:"value"}]), false) + equal(tag.matchesProperties({"key":"value"}), true) + equal(tag.matchesProperties({"key":"z"}), false) + equal(tag.matchesProperties({"key":""}), false) + equal(tag.matchesProperties({"other_key":""}), false) + equal(tag.matchesProperties({"other_key":"value"}), false) const isEmpty = FromJSON.Tag("key=") as Tag; - equal(isEmpty.matches([{k:"key",v:"value"}]), false) - equal(isEmpty.matches([{k:"key",v:""}]), true) - equal(isEmpty.matches([{k:"other_key",v:""}]), true) - equal(isEmpty.matches([{k:"other_key",v:"value"}]), true) + equal(isEmpty.matchesProperties({"key":"value"}), false) + equal(isEmpty.matchesProperties({"key":""}), true) + equal(isEmpty.matchesProperties({"other_key":""}), true) + equal(isEmpty.matchesProperties({"other_key":"value"}), true) const isNotEmpty = FromJSON.Tag("key!="); - equal(isNotEmpty.matches([{k:"key",v:"value"}]), true) - equal(isNotEmpty.matches([{k:"key",v:"other_value"}]), true) - equal(isNotEmpty.matches([{k:"key",v:""}]), false) - equal(isNotEmpty.matches([{k:"other_key",v:""}]), false) - equal(isNotEmpty.matches([{k:"other_key",v:"value"}]), false) + equal(isNotEmpty.matchesProperties({"key":"value"}), true) + equal(isNotEmpty.matchesProperties({"key":"other_value"}), true) + equal(isNotEmpty.matchesProperties({"key":""}), false) + equal(isNotEmpty.matchesProperties({"other_key":""}), false) + equal(isNotEmpty.matchesProperties({"other_key":"value"}), false) @@ -54,29 +54,29 @@ new T("Tags", [ const notReg = FromJSON.Tag("x!~y") as And; - equal(notReg.matches([{k:"x",v:"y"}]), false) - equal(notReg.matches([{k:"x",v:"z"}]), true) - equal(notReg.matches([{k:"x",v:""}]), true) - equal(notReg.matches([]), true) + equal(notReg.matchesProperties({"x":"y"}), false) + equal(notReg.matchesProperties({"x":"z"}), true) + equal(notReg.matchesProperties({"x":""}), true) + equal(notReg.matchesProperties({}), true) const noMatch = FromJSON.Tag("key!=value") as Tag; - equal(noMatch.matches([{k:"key",v:"value"}]), false) - equal(noMatch.matches([{k:"key",v:"otherValue"}]), true) - equal(noMatch.matches([{k:"key",v:""}]), true) - equal(noMatch.matches([{k:"otherKey",v:""}]), true) + equal(noMatch.matchesProperties({"key":"value"}), false) + equal(noMatch.matchesProperties({"key":"otherValue"}), true) + equal(noMatch.matchesProperties({"key":""}), true) + equal(noMatch.matchesProperties({"otherKey":""}), true) const multiMatch = FromJSON.Tag("vending~.*bicycle_tube.*") as Tag; - equal(multiMatch.matches([{k:"vending",v:"bicycle_tube"}]), true) - equal(multiMatch.matches([{k:"vending",v:"something;bicycle_tube"}]), true) - equal(multiMatch.matches([{k:"vending",v:"bicycle_tube;something"}]), true) - equal(multiMatch.matches([{k:"vending",v:"xyz;bicycle_tube;something"}]), true) + equal(multiMatch.matchesProperties({"vending":"bicycle_tube"}), true) + equal(multiMatch.matchesProperties({"vending":"something;bicycle_tube"}), true) + equal(multiMatch.matchesProperties({"vending":"bicycle_tube;something"}), true) + equal(multiMatch.matchesProperties({"vending":"xyz;bicycle_tube;something"}), true) const nameStartsWith = FromJSON.Tag("name~[sS]peelbos.*") - equal(nameStartsWith.matches([{k:"name",v: "Speelbos Sint-Anna"}]), true) - equal(nameStartsWith.matches([{k:"name",v: "speelbos Sint-Anna"}]), true) - equal(nameStartsWith.matches([{k:"name",v: "Sint-Anna"}]), false) - equal(nameStartsWith.matches([{k:"name",v: ""}]), false) + equal(nameStartsWith.matchesProperties({"name": "Speelbos Sint-Anna"}), true) + equal(nameStartsWith.matchesProperties({"name": "speelbos Sint-Anna"}), true) + equal(nameStartsWith.matchesProperties({"name": "Sint-Anna"}), false) + equal(nameStartsWith.matchesProperties({"name": ""}), false) })], ["Is equivalent test", (() => { @@ -143,7 +143,7 @@ new T("Tags", [ "Empty match test", () => { const t = new Tag("key",""); - equal(false, t.matches([{k: "key", v:"somevalue"}])) + equal(false, t.matchesProperties({ "key":"somevalue"})) } ], [ @@ -238,8 +238,7 @@ new T("Tags", [ equal(r.startHour,10 ); equal(r.endHour, 12) - } - ], + }], ["Parse OH 1",() => { const rules = OH.ParseRule("11:00-19:00"); equal(rules.length, 7); @@ -382,5 +381,5 @@ new T("Tags", [ equal(Utils.Round(-0.5), "-0.5") equal(Utils.Round(-1.6), "-1.6") - }] -]); + } +]]);