diff --git a/assets/layers/bike_parking/bike_parking.json b/assets/layers/bike_parking/bike_parking.json index bdc89e1a4..403fe0c6b 100644 --- a/assets/layers/bike_parking/bike_parking.json +++ b/assets/layers/bike_parking/bike_parking.json @@ -998,6 +998,16 @@ "weeks", "months" ] + }, + "charge": { + "quantity": "duration", + "inverted": true, + "denominations": [ + "days", + "weeks", + "months", + "years" + ] } } ] diff --git a/src/Logic/SimpleMetaTagger.ts b/src/Logic/SimpleMetaTagger.ts index 90dd0b9a9..15d358668 100644 --- a/src/Logic/SimpleMetaTagger.ts +++ b/src/Logic/SimpleMetaTagger.ts @@ -435,7 +435,7 @@ export default class SimpleMetaTaggers { () => feature.properties["_country"] ) let canonical = - denomination?.canonicalValue(value, defaultDenom == denomination) ?? + denomination?.canonicalValue(value, defaultDenom == denomination, unit.inverted) ?? undefined if (canonical === value) { break diff --git a/src/Models/Denomination.ts b/src/Models/Denomination.ts index c7d898191..f962d7b82 100644 --- a/src/Models/Denomination.ts +++ b/src/Models/Denomination.ts @@ -110,19 +110,21 @@ export class Denomination { * @param value the value from OSM * @param actAsDefault if set and the value can be parsed as number, will be parsed and trimmed * + * import Validators from "../UI/InputElement/Validators" + * * const unit = Denomination.fromJson({ * canonicalDenomination: "m", * alternativeDenomination: ["meter"], * human: { * en: "{quantity} meter" * } - * }, "test") - * unit.canonicalValue("42m", true) // =>"42 m" - * unit.canonicalValue("42", true) // =>"42 m" - * unit.canonicalValue("42 m", true) // =>"42 m" - * unit.canonicalValue("42 meter", true) // =>"42 m" - * unit.canonicalValue("42m", true) // =>"42 m" - * unit.canonicalValue("42", true) // =>"42 m" + * }, Validators.get("float"), "test") + * unit.canonicalValue("42m", true, false) // =>"42 m" + * unit.canonicalValue("42", true, false) // =>"42 m" + * unit.canonicalValue("42 m", true, false) // =>"42 m" + * unit.canonicalValue("42 meter", true, false) // =>"42 m" + * unit.canonicalValue("42m", true, false) // =>"42 m" + * unit.canonicalValue("42", true, false) // =>"42 m" * * // Should be trimmed if canonical is empty * const unit = Denomination.fromJson({ @@ -131,22 +133,26 @@ export class Denomination { * human: { * en: "{quantity} meter" * } - * }, "test") - * unit.canonicalValue("42m", true) // =>"42" - * unit.canonicalValue("42", true) // =>"42" - * unit.canonicalValue("42 m", true) // =>"42" - * unit.canonicalValue("42 meter", true) // =>"42" + * }, Validators.get("float"), "test") + * unit.canonicalValue("42m", true, false) // =>"42" + * unit.canonicalValue("42", true, false) // =>"42" + * unit.canonicalValue("42 m", true, false) // =>"42" + * unit.canonicalValue("42 meter", true, false) // =>"42" * * */ - public canonicalValue(value: string, actAsDefault: boolean): string { + public canonicalValue(value: string, actAsDefault: boolean, inverted: boolean): string { if (value === undefined) { return undefined } - const stripped = this.StrippedValue(value, actAsDefault) + const stripped = this.StrippedValue(value, actAsDefault, inverted) if (stripped === null) { return null } + if(inverted){ + return (stripped + "/" + this.canonical).trim() + + } if (stripped === "1" && this._canonicalSingular !== undefined) { return ("1 " + this._canonicalSingular).trim() } @@ -160,7 +166,7 @@ export class Denomination { * * Returns null if it doesn't match this unit */ - public StrippedValue(value: string, actAsDefault: boolean): string { + public StrippedValue(value: string, actAsDefault: boolean, inverted: boolean): string { if (value === undefined) { return undefined } @@ -178,10 +184,16 @@ export class Denomination { function substr(key) { if (self.prefix) { - return value.substr(key.length).trim() - } else { - return value.substring(0, value.length - key.length).trim() + return value.substring(key.length).trim() } + let trimmed = value.substring(0, value.length - key.length).trim() + if(!inverted){ + return trimmed + } + if(trimmed.endsWith("/")){ + trimmed = trimmed.substring(0, trimmed.length - 1).trim() + } + return trimmed } if (this.canonical !== "" && startsWith(this.canonical.toLowerCase())) { diff --git a/src/Models/ThemeConfig/Json/LayerConfigJson.ts b/src/Models/ThemeConfig/Json/LayerConfigJson.ts index 3b31068ff..a2053e097 100644 --- a/src/Models/ThemeConfig/Json/LayerConfigJson.ts +++ b/src/Models/ThemeConfig/Json/LayerConfigJson.ts @@ -519,6 +519,7 @@ export interface LayerConfigJson { /** * Either a list with [{"key": "unitname", "key2": {"quantity": "unitname", "denominations": ["denom", "denom"]}}] * + * Use `"inverted": true` if the amount should be _divided_ by the denomination, e.g. for charge over time (`€5/day`) * * @see UnitConfigJson * @@ -526,7 +527,7 @@ export interface LayerConfigJson { */ units?: ( | UnitConfigJson - | Record + | Record )[] /** diff --git a/src/Models/Unit.ts b/src/Models/Unit.ts index 8be68110f..2a82a8ee0 100644 --- a/src/Models/Unit.ts +++ b/src/Models/Unit.ts @@ -15,16 +15,19 @@ export class Unit { public readonly eraseInvalid: boolean public readonly quantity: string private readonly _validator: Validator + public readonly inverted: boolean constructor( quantity: string, appliesToKeys: string[], applicableDenominations: Denomination[], eraseInvalid: boolean, - validator: Validator + validator: Validator, + inverted: boolean = false ) { this.quantity = quantity this._validator = validator + this.inverted = inverted this.appliesToKeys = new Set(appliesToKeys) this.denominations = applicableDenominations this.eraseInvalid = eraseInvalid @@ -73,7 +76,7 @@ export class Unit { static fromJson( json: | UnitConfigJson - | Record, + | Record, tagRenderings: TagRenderingConfig[], ctx: string ): Unit[] { @@ -210,7 +213,7 @@ export class Unit { private static loadFromLibrary( spec: Record< string, - string | { quantity: string; denominations: string[]; canonical?: string } + string | { quantity: string; denominations: string[]; canonical?: string, inverted?: boolean } >, types: Record, ctx: string @@ -222,7 +225,7 @@ export class Unit { if (typeof toLoad === "string") { const loaded = this.getFromLibrary(toLoad, ctx) units.push( - new Unit(loaded.quantity, [key], loaded.denominations, loaded.eraseInvalid, validator) + new Unit(loaded.quantity, [key], loaded.denominations, loaded.eraseInvalid, validator, toLoad["inverted"]) ) continue } @@ -252,7 +255,7 @@ export class Unit { const canonical = fetchDenom(toLoad.canonical).withValidator(validator) denoms.unshift(canonical.withBlankCanonical()) } - units.push(new Unit(loaded.quantity, [key], denoms, loaded.eraseInvalid, validator)) + units.push(new Unit(loaded.quantity, [key], denoms, loaded.eraseInvalid, validator, toLoad["inverted"])) } return units } @@ -274,7 +277,7 @@ export class Unit { } const defaultDenom = this.getDefaultDenomination(country) for (const denomination of this.denominationsSorted) { - const bare = denomination.StrippedValue(valueWithDenom, defaultDenom === denomination) + const bare = denomination.StrippedValue(valueWithDenom, defaultDenom === denomination, this.inverted) if (bare !== null) { return [bare, denomination] } @@ -287,10 +290,13 @@ export class Unit { return undefined } const [stripped, denom] = this.findDenomination(value, country) + const human = denom?.human + if(this.inverted ){ + return human.Subs({quantity: stripped+"/"}) + } if (stripped === "1") { return denom?.humanSingular ?? stripped } - const human = denom?.human if (human === undefined) { return stripped ?? value } @@ -300,6 +306,10 @@ export class Unit { public toOsm(value: string, denomination: string) { const denom = this.denominations.find((d) => d.canonical === denomination) + if(this.inverted){ + return value+"/"+denom._canonicalSingular + } + const space = denom.addSpace ? " " : "" if (denom.prefix) { return denom.canonical + space + value @@ -307,7 +317,7 @@ export class Unit { return value + space + denom.canonical } - public getDefaultDenomination(country: () => string) { + public getDefaultDenomination(country: () => string): Denomination { for (const denomination of this.denominations) { if (denomination.useIfNoUnitGiven === true) { return denomination diff --git a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte index 831bd109a..0f3faa293 100644 --- a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte @@ -178,7 +178,9 @@ checkedMappings, tags.data ) - console.log("Constructing change spec from", {freeform: $freeformInput, selectedMapping, checkedMappings, currentTags: tags.data}, " --> ", selectedTags) + if(state.featureSwitches.featureSwitchIsDebugging.data){ + console.log("Constructing change spec from", {freeform: $freeformInput, selectedMapping, checkedMappings, currentTags: tags.data}, " --> ", selectedTags) + } } catch (e) { console.error("Could not calculate changeSpecification:", e) selectedTags = undefined diff --git a/src/UI/Popup/UnitInput.svelte b/src/UI/Popup/UnitInput.svelte index 4efe8500f..f299f75fa 100644 --- a/src/UI/Popup/UnitInput.svelte +++ b/src/UI/Popup/UnitInput.svelte @@ -64,10 +64,14 @@ ) +{#if unit.inverted} +
/
+{/if} +