Merge branch 'develop' into feature/bicycle_road
							
								
								
									
										
											BIN
										
									
								
								Docs/Misc/Climbing.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 135 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Docs/Misc/Kakampink.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.6 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								Docs/Misc/StatisticsOnwheels.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 197 KiB  | 
| 
		 Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Docs/Misc/shop_selection.gif
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 300 KiB  | 
							
								
								
									
										53
									
								
								Docs/Presentations/SOTM2022-workshop.abstract.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
# What do I want to tell at SOTM '22?
 | 
			
		||||
 | 
			
		||||
4 main topics:
 | 
			
		||||
 | 
			
		||||
The MapComplete Editor:
 | 
			
		||||
 | 
			
		||||
- What is MapComplete? The vision
 | 
			
		||||
   + Simple to use viewer
 | 
			
		||||
   + Simple to contribute
 | 
			
		||||
   + Packed with features under the hood (where applicable)
 | 
			
		||||
   + Pareto frontier
 | 
			
		||||
 | 
			
		||||
- What is a theme?
 | 
			
		||||
  + One or more layers + introduction text + some meta (such as icon)
 | 
			
		||||
  + Vision on what the target group is (who will use it? For what purpose?)
 | 
			
		||||
  + Written in a .json-file
 | 
			
		||||
 | 
			
		||||
- What is a .json-file
 | 
			
		||||
  + A flat text-file (create a .txt)
 | 
			
		||||
 | 
			
		||||
- What is a layer?
 | 
			
		||||
  + One logical type of feature
 | 
			
		||||
    - Specifiy the tags that are needed to match
 | 
			
		||||
    - Uses OSM as default datasource, but an online (sliced) geojson is an option too, e.g. to show/import
 | 
			
		||||
  + Specifies the elements to show in the popup
 | 
			
		||||
  + Specifies how it is rendered
 | 
			
		||||
  + Specifies if new elements can be added and with which tags
 | 
			
		||||
  -> Don't mix, e.g. don't mix post-boxes with post offices
 | 
			
		||||
  -> Don't use an adverb, e.g. "all shops ~~which accept cash~~". What if the shop is already there but the payment methods are not known yet? (use a filter instead)
 | 
			
		||||
 | 
			
		||||
- What is a TagRendering?
 | 
			
		||||
  + Converts the objects attributes into a text on the screen
 | 
			
		||||
  + If a question is added, it'll ask the user the right answer
 | 
			
		||||
  -> Do use full sentences
 | 
			
		||||
  -> Start with the step 'attributes to text', then add the question
 | 
			
		||||
  -> Don't write "yes, this POI has ..." or even worse "yes"/"no"
 | 
			
		||||
 | 
			
		||||
- Deploying
 | 
			
		||||
  + copy paste into a base64-decoder
 | 
			
		||||
  + Go to "mapcomplete.osm.be/index?userlayout=true#<paste your encoded file here>"
 | 
			
		||||
  + Oh Noes! An error msg!
 | 
			
		||||
 | 
			
		||||
- sharing
 | 
			
		||||
  + Share often and early. I'd rather have a half-finished theme via chat/wiki that can be improved upon then no theme at all
 | 
			
		||||
  + When done: make a pull request via github (you'll get translations, documentation, integration with taginfo and a chatbot for free)
 | 
			
		||||
 | 
			
		||||
- A dash of Magic
 | 
			
		||||
  + Calculated tags
 | 
			
		||||
  + Twin layers (fritures)
 | 
			
		||||
  + Imports
 | 
			
		||||
 | 
			
		||||
- Future work:
 | 
			
		||||
  + Improve this flow
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Docs/Presentations/WikidataAndMapComplete.mp4
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -235,7 +235,7 @@ export default class SimpleMetaTaggers {
 | 
			
		|||
 | 
			
		||||
    private static canonicalize = new SimpleMetaTagger(
 | 
			
		||||
        {
 | 
			
		||||
            doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`)",
 | 
			
		||||
            doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`; `1` will be rewritten to `1m` as well)",
 | 
			
		||||
            keys: ["Theme-defined keys"],
 | 
			
		||||
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -261,13 +261,14 @@ export default class SimpleMetaTaggers {
 | 
			
		|||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    const value = feature.properties[key]
 | 
			
		||||
                    const denom = unit.findDenomination(value)
 | 
			
		||||
                    const denom = unit.findDenomination(value, () => feature.properties["_country"])
 | 
			
		||||
                    if (denom === undefined) {
 | 
			
		||||
                        // no valid value found
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    const [, denomination] = denom;
 | 
			
		||||
                    let canonical = denomination?.canonicalValue(value) ?? undefined;
 | 
			
		||||
                    const defaultDenom = unit.getDefaultDenomination(() => feature.properties["_country"])
 | 
			
		||||
                    let canonical = denomination?.canonicalValue(value, defaultDenom == denomination) ?? undefined;
 | 
			
		||||
                    if (canonical === value) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,21 +1,22 @@
 | 
			
		|||
import {Translation} from "../UI/i18n/Translation";
 | 
			
		||||
import {ApplicableUnitJson} from "./ThemeConfig/Json/UnitConfigJson";
 | 
			
		||||
import {DenominationConfigJson} from "./ThemeConfig/Json/UnitConfigJson";
 | 
			
		||||
import Translations from "../UI/i18n/Translations";
 | 
			
		||||
import {Store, UIEventSource} from "../Logic/UIEventSource";
 | 
			
		||||
import {Store} from "../Logic/UIEventSource";
 | 
			
		||||
import BaseUIElement from "../UI/BaseUIElement";
 | 
			
		||||
import Toggle from "../UI/Input/Toggle";
 | 
			
		||||
 | 
			
		||||
export class Denomination {
 | 
			
		||||
    public readonly canonical: string;
 | 
			
		||||
    public readonly _canonicalSingular: string;
 | 
			
		||||
    public readonly default: boolean;
 | 
			
		||||
    public readonly useAsDefaultInput: boolean | string[]
 | 
			
		||||
    public readonly useIfNoUnitGiven : boolean | string[]
 | 
			
		||||
    public readonly prefix: boolean;
 | 
			
		||||
    public readonly alternativeDenominations: string [];
 | 
			
		||||
    private readonly _human: Translation;
 | 
			
		||||
    private readonly _humanSingular?: Translation;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    constructor(json: ApplicableUnitJson, context: string) {
 | 
			
		||||
    constructor(json: DenominationConfigJson, context: string) {
 | 
			
		||||
        context = `${context}.unit(${json.canonicalDenomination})`
 | 
			
		||||
        this.canonical = json.canonicalDenomination.trim()
 | 
			
		||||
        if (this.canonical === undefined) {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,11 @@ export class Denomination {
 | 
			
		|||
 | 
			
		||||
        this.alternativeDenominations = json.alternativeDenomination?.map(v => v.trim()) ?? []
 | 
			
		||||
 | 
			
		||||
        this.default = json.default ?? false;
 | 
			
		||||
        if(json["default"] !== undefined) {
 | 
			
		||||
            throw `${context} uses the old 'default'-key. Use "useIfNoUnitGiven" or "useAsDefaultInput" instead`
 | 
			
		||||
        }
 | 
			
		||||
        this.useIfNoUnitGiven = json.useIfNoUnitGiven
 | 
			
		||||
        this.useAsDefaultInput = json.useAsDefaultInput ?? json.useIfNoUnitGiven
 | 
			
		||||
        
 | 
			
		||||
        this._human = Translations.T(json.human, context + "human")
 | 
			
		||||
        this._humanSingular = Translations.T(json.humanSingular, context + "humanSingular")
 | 
			
		||||
| 
						 | 
				
			
			@ -68,32 +73,31 @@ export class Denomination {
 | 
			
		|||
     * const unit = new Denomination({
 | 
			
		||||
     *               canonicalDenomination: "m",
 | 
			
		||||
     *               alternativeDenomination: ["meter"],
 | 
			
		||||
     *               'default': true,
 | 
			
		||||
     *               human: {
 | 
			
		||||
     *                   en: "meter"
 | 
			
		||||
     *               }
 | 
			
		||||
     *           }, "test")
 | 
			
		||||
     * unit.canonicalValue("42m") // =>"42 m"
 | 
			
		||||
     * unit.canonicalValue("42") // =>"42 m"
 | 
			
		||||
     * unit.canonicalValue("42 m") // =>"42 m"
 | 
			
		||||
     * unit.canonicalValue("42 meter") // =>"42 m"
 | 
			
		||||
     * 
 | 
			
		||||
     * 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"
 | 
			
		||||
     * 
 | 
			
		||||
     * // Should be trimmed if canonical is empty
 | 
			
		||||
     * const unit = new Denomination({
 | 
			
		||||
     *               canonicalDenomination: "",
 | 
			
		||||
     *               alternativeDenomination: ["meter","m"],
 | 
			
		||||
     *               'default': true,
 | 
			
		||||
     *               human: {
 | 
			
		||||
     *                   en: "meter"
 | 
			
		||||
     *               }
 | 
			
		||||
     *           }, "test")
 | 
			
		||||
     * unit.canonicalValue("42m") // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42") // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42 m") // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42 meter") // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42m", true) // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42", true) // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42 m", true) // =>"42"
 | 
			
		||||
     * unit.canonicalValue("42 meter", true) // =>"42"
 | 
			
		||||
     */
 | 
			
		||||
    public canonicalValue(value: string, actAsDefault?: boolean) : string {
 | 
			
		||||
    public canonicalValue(value: string, actAsDefault: boolean) : string {
 | 
			
		||||
        if (value === undefined) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +118,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): string {
 | 
			
		||||
 | 
			
		||||
        if (value === undefined) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
| 
						 | 
				
			
			@ -153,15 +157,26 @@ export class Denomination {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.default || actAsDefault) {
 | 
			
		||||
        if (!actAsDefault) {
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        const parsed = Number(value.trim())
 | 
			
		||||
        if (!isNaN(parsed)) {
 | 
			
		||||
            return value.trim();
 | 
			
		||||
        }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    isDefaultUnit(country: () => string) {
 | 
			
		||||
        if(this.useIfNoUnitGiven === true){
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
        if(this.useIfNoUnitGiven === false){
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
        return this.useIfNoUnitGiven.indexOf(country()) >= 0
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -13,11 +13,16 @@ import {AddContextToTranslations} from "./AddContextToTranslations";
 | 
			
		|||
class ExpandTagRendering extends Conversion<string | TagRenderingConfigJson | { builtin: string | string[], override: any }, TagRenderingConfigJson[]> {
 | 
			
		||||
    private readonly _state: DesugaringContext;
 | 
			
		||||
    private readonly _self: LayerConfigJson;
 | 
			
		||||
    private readonly _options: {
 | 
			
		||||
        /* If true, will copy the 'osmSource'-tags into the condition */
 | 
			
		||||
        applyCondition?: true | boolean;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    constructor(state: DesugaringContext, self: LayerConfigJson) {
 | 
			
		||||
    constructor(state: DesugaringContext, self: LayerConfigJson, options?: {  applyCondition?: true | boolean;}) {
 | 
			
		||||
        super("Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question", [], "ExpandTagRendering");
 | 
			
		||||
        this._state = state;
 | 
			
		||||
        this._self = self;
 | 
			
		||||
        this._options = options;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convert(json: string | TagRenderingConfigJson | { builtin: string | string[]; override: any }, context: string): { result: TagRenderingConfigJson[]; errors: string[]; warnings: string[] } {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,13 +70,15 @@ class ExpandTagRendering extends Conversion<string | TagRenderingConfigJson | {
 | 
			
		|||
 | 
			
		||||
        const contextWriter = new AddContextToTranslations<TagRenderingConfigJson>("layers:")
 | 
			
		||||
        for (let i = 0; i < matchingTrs.length; i++) {
 | 
			
		||||
            // The matched tagRenderings are 'stolen' from another layer. This means that they must match the layer condition before being shown
 | 
			
		||||
            let found: TagRenderingConfigJson = Utils.Clone(matchingTrs[i]);
 | 
			
		||||
            if(this._options?.applyCondition){
 | 
			
		||||
                // The matched tagRenderings are 'stolen' from another layer. This means that they must match the layer condition before being shown
 | 
			
		||||
                if (found.condition === undefined) {
 | 
			
		||||
                    found.condition = layer.source.osmTags
 | 
			
		||||
                } else {
 | 
			
		||||
                    found.condition = {and: [found.condition, layer.source.osmTags]}
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            found = contextWriter.convertStrict(found, layer.id + ".tagRenderings." + found["id"])
 | 
			
		||||
            matchingTrs[i] = found
 | 
			
		||||
| 
						 | 
				
			
			@ -561,7 +568,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
 | 
			
		|||
            new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
 | 
			
		||||
            new On("tagRenderings", layer => new Concat(new ExpandTagRendering(state, layer))),
 | 
			
		||||
            new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
 | 
			
		||||
            new On("mapRendering", layer => new Each(new On("icon", new FirstOf(new ExpandTagRendering(state, layer))))),
 | 
			
		||||
            new On("mapRendering", layer => new Each(new On("icon", new FirstOf(new ExpandTagRendering(state, layer, {applyCondition: false}))))),
 | 
			
		||||
            new SetDefault("titleIcons", ["defaults"]),
 | 
			
		||||
            new On("titleIcons", layer => new Concat(new ExpandTagRendering(state, layer)))
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -613,6 +613,13 @@ export class ValidateLayer extends DesugaringStep<LayerConfigJson> {
 | 
			
		|||
                information.push(...(r.information ?? []))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
               const hasCondition = json.mapRendering?.filter(mr => mr["icon"] !== undefined && mr["icon"]["condition"] !== undefined)
 | 
			
		||||
                if(hasCondition?.length > 0){
 | 
			
		||||
                    errors.push("At "+context+":\n    One or more icons in the mapRenderings have a condition set. Don't do this, as this will result in an invisible but clickable element. Use extra filters in the source instead. The offending mapRenderings are:\n"+JSON.stringify(hasCondition, null, "  "))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (json.presets !== undefined) {
 | 
			
		||||
 | 
			
		||||
                // Check that a preset will be picked up by the layer itself
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,32 @@ export default interface UnitConfigJson {
 | 
			
		|||
    /**
 | 
			
		||||
     * The possible denominations
 | 
			
		||||
     */
 | 
			
		||||
    applicableUnits: ApplicableUnitJson[]
 | 
			
		||||
    applicableUnits: DenominationConfigJson[]
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApplicableUnitJson {
 | 
			
		||||
export interface DenominationConfigJson {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The canonical value which will be added to the value in OSM.
 | 
			
		||||
     * If this evaluates to true and the value to interpret has _no_ unit given, assumes that this unit is meant.
 | 
			
		||||
     * Alternatively, a list of country codes can be given where this acts as the default interpretation
 | 
			
		||||
     * 
 | 
			
		||||
     * E.g., a denomination using "meter" would probably set this flag to "true";
 | 
			
		||||
     * a denomination for "mp/h" will use the condition "_country=gb" to indicate that it is the default in the UK.
 | 
			
		||||
     * 
 | 
			
		||||
     * If none of the units indicate that they are the default, the first denomination will be used instead
 | 
			
		||||
     */
 | 
			
		||||
    useIfNoUnitGiven?: boolean | string[]
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Use this value as default denomination when the user inputs a value (e.g. to force using 'centimeters' instead of 'meters' by default).
 | 
			
		||||
     * If unset for all values, this will use 'useIfNoUnitGiven'. If at least one denomination has this set, this will default to false
 | 
			
		||||
     */
 | 
			
		||||
    useAsDefaultInput?: boolean | string[]
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The canonical value for this denomination which will be added to the value in OSM.
 | 
			
		||||
     * e.g. "m" for meters
 | 
			
		||||
     * If the user inputs '42', the canonical value will be added and it'll become '42m'.
 | 
			
		||||
     * 
 | 
			
		||||
| 
						 | 
				
			
			@ -28,8 +47,11 @@ export interface ApplicableUnitJson {
 | 
			
		|||
     * In this case, an empty string should be used
 | 
			
		||||
     */
 | 
			
		||||
    canonicalDenomination: string,
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * The canonical denomination in the case that the unit is precisely '1'
 | 
			
		||||
     * The canonical denomination in the case that the unit is precisely '1'.
 | 
			
		||||
     * Used for display purposes
 | 
			
		||||
     */
 | 
			
		||||
    canonicalDenominationSingular?: string,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,9 +85,5 @@ export interface ApplicableUnitJson {
 | 
			
		|||
     */
 | 
			
		||||
    prefix?: boolean
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The default interpretation - only one can be set.
 | 
			
		||||
     * If none is set, the first unit will be considered the default interpretation of a value without a unit
 | 
			
		||||
     */
 | 
			
		||||
    default?: boolean
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -14,8 +14,6 @@ import List from "../../UI/Base/List";
 | 
			
		|||
import {MappingConfigJson, QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson";
 | 
			
		||||
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
 | 
			
		||||
import {Paragraph} from "../../UI/Base/Paragraph";
 | 
			
		||||
import spec = Mocha.reporters.spec;
 | 
			
		||||
import SpecialVisualizations from "../../UI/SpecialVisualizations";
 | 
			
		||||
 | 
			
		||||
export interface Mapping {
 | 
			
		||||
    readonly if: TagsFilter,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,14 +8,11 @@ export class Unit {
 | 
			
		|||
    public readonly appliesToKeys: Set<string>;
 | 
			
		||||
    public readonly denominations: Denomination[];
 | 
			
		||||
    public readonly denominationsSorted: Denomination[];
 | 
			
		||||
    public readonly defaultDenom: Denomination;
 | 
			
		||||
    public readonly eraseInvalid: boolean;
 | 
			
		||||
    private readonly possiblePostFixes: string[] = []
 | 
			
		||||
 | 
			
		||||
    constructor(appliesToKeys: string[], applicableUnits: Denomination[], eraseInvalid: boolean) {
 | 
			
		||||
    constructor(appliesToKeys: string[], applicableDenominations: Denomination[], eraseInvalid: boolean) {
 | 
			
		||||
        this.appliesToKeys = new Set(appliesToKeys);
 | 
			
		||||
        this.denominations = applicableUnits;
 | 
			
		||||
        this.defaultDenom = applicableUnits.filter(denom => denom.default)[0]
 | 
			
		||||
        this.denominations = applicableDenominations;
 | 
			
		||||
        this.eraseInvalid = eraseInvalid
 | 
			
		||||
 | 
			
		||||
        const seenUnitExtensions = new Set<string>();
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +49,6 @@ export class Unit {
 | 
			
		|||
            addPostfixesOf(denomination._canonicalSingular)
 | 
			
		||||
            denomination.alternativeDenominations.forEach(addPostfixesOf)
 | 
			
		||||
        }
 | 
			
		||||
        this.possiblePostFixes = Array.from(possiblePostFixes)
 | 
			
		||||
        this.possiblePostFixes.sort((a, b) => b.length - a.length)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,16 +66,12 @@ export class Unit {
 | 
			
		|||
        }
 | 
			
		||||
        // Some keys do have unit handling
 | 
			
		||||
 | 
			
		||||
        const defaultSet = json.applicableUnits.filter(u => u.default === true)
 | 
			
		||||
        // No default is defined - we pick the first as default
 | 
			
		||||
        if (defaultSet.length === 0) {
 | 
			
		||||
            json.applicableUnits[0].default = true
 | 
			
		||||
        if(json.applicableUnits.some(denom => denom.useAsDefaultInput !== undefined)){
 | 
			
		||||
            json.applicableUnits.forEach(denom => {
 | 
			
		||||
                denom.useAsDefaultInput = denom.useAsDefaultInput ?? false
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check that there are not multiple defaults
 | 
			
		||||
        if (defaultSet.length > 1) {
 | 
			
		||||
            throw `Multiple units are set as default: they have canonical values of ${defaultSet.map(u => u.canonicalDenomination).join(", ")}`
 | 
			
		||||
        }
 | 
			
		||||
        const applicable = json.applicableUnits.map((u, i) => new Denomination(u, `${ctx}.units[${i}]`))
 | 
			
		||||
        return new Unit(appliesTo, applicable, json.eraseInvalidValues ?? false)
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -96,12 +87,13 @@ export class Unit {
 | 
			
		|||
    /**
 | 
			
		||||
     * Finds which denomination is applicable and gives the stripped value back
 | 
			
		||||
     */
 | 
			
		||||
    findDenomination(valueWithDenom: string): [string, Denomination] {
 | 
			
		||||
    findDenomination(valueWithDenom: string, country: () => string): [string, Denomination] {
 | 
			
		||||
        if (valueWithDenom === undefined) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
        const defaultDenom = this.getDefaultDenomination(country)
 | 
			
		||||
        for (const denomination of this.denominationsSorted) {
 | 
			
		||||
            const bare = denomination.StrippedValue(valueWithDenom)
 | 
			
		||||
            const bare = denomination.StrippedValue(valueWithDenom, defaultDenom === denomination)
 | 
			
		||||
            if (bare !== null) {
 | 
			
		||||
                return [bare, denomination]
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -109,11 +101,11 @@ export class Unit {
 | 
			
		|||
        return [undefined, undefined]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    asHumanLongValue(value: string): BaseUIElement {
 | 
			
		||||
    asHumanLongValue(value: string, country: () => string): BaseUIElement {
 | 
			
		||||
        if (value === undefined) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
        const [stripped, denom] = this.findDenomination(value)
 | 
			
		||||
        const [stripped, denom] = this.findDenomination(value, country)
 | 
			
		||||
        const human = stripped === "1" ? denom?.humanSingular : denom?.human
 | 
			
		||||
        if (human === undefined) {
 | 
			
		||||
            return new FixedUiElement(stripped ?? value);
 | 
			
		||||
| 
						 | 
				
			
			@ -124,24 +116,46 @@ export class Unit {
 | 
			
		|||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *   Returns the value without any (sub)parts of any denomination - usefull as preprocessing step for validating inputs.
 | 
			
		||||
     *   E.g.
 | 
			
		||||
     *   if 'megawatt' is a possible denomination, then '5 Meg' will be rewritten to '5' (which can then be validated as a valid pnat)
 | 
			
		||||
     *
 | 
			
		||||
     *   Returns the original string if nothign matches
 | 
			
		||||
     */
 | 
			
		||||
    stripUnitParts(str: string) {
 | 
			
		||||
        if (str === undefined) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
 | 
			
		||||
    public getDefaultInput(country: () => string | string[]) {
 | 
			
		||||
        console.log("Searching the default denomination for input", country)
 | 
			
		||||
        for (const denomination of this.denominations) {
 | 
			
		||||
            if (denomination.useAsDefaultInput === true) {
 | 
			
		||||
                return denomination
 | 
			
		||||
            }
 | 
			
		||||
            if (denomination.useAsDefaultInput === undefined || denomination.useAsDefaultInput === false) {
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
            let countries: string | string[] = country()
 | 
			
		||||
            if (typeof countries === "string") {
 | 
			
		||||
                countries = countries.split(",")
 | 
			
		||||
            }
 | 
			
		||||
            const denominationCountries: string[] = denomination.useAsDefaultInput
 | 
			
		||||
            if (countries.some(country => denominationCountries.indexOf(country) >= 0)) {
 | 
			
		||||
                return denomination
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return this.denominations[0]
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
        for (const denominationPart of this.possiblePostFixes) {
 | 
			
		||||
            if (str.endsWith(denominationPart)) {
 | 
			
		||||
                return str.substring(0, str.length - denominationPart.length).trim()
 | 
			
		||||
    public getDefaultDenomination(country: () => string){
 | 
			
		||||
        for (const denomination of this.denominations) {
 | 
			
		||||
            if (denomination.useIfNoUnitGiven === true || denomination.canonical === "") {
 | 
			
		||||
                return denomination
 | 
			
		||||
            }
 | 
			
		||||
            if (denomination.useIfNoUnitGiven === undefined || denomination.useIfNoUnitGiven === false) {
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
            let countries: string | string[] = country()
 | 
			
		||||
            if (typeof countries === "string") {
 | 
			
		||||
                countries = countries.split(",")
 | 
			
		||||
            }
 | 
			
		||||
            const denominationCountries: string[] = denomination.useIfNoUnitGiven
 | 
			
		||||
            if (countries.some(country => denominationCountries.indexOf(country) >= 0)) {
 | 
			
		||||
                return denomination
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return this.denominations[0]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        return str;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
import BaseUIElement from "../BaseUIElement";
 | 
			
		||||
import {Chart, ChartConfiguration, ChartType, DefaultDataPoint, registerables} from 'chart.js';
 | 
			
		||||
Chart.register(...registerables);
 | 
			
		||||
Chart?.register(...(registerables ?? []));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default class ChartJs<
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,6 @@ export class SubtleButton extends UIElement {
 | 
			
		|||
        })
 | 
			
		||||
        const loading = new Lazy(() => new Loading(loadingText) )
 | 
			
		||||
        return new VariableUiElement(state.map(st => {
 | 
			
		||||
            console.log("State is: ", st)
 | 
			
		||||
            if(st === "idle"){
 | 
			
		||||
                return button
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ import {QueryParameters} from "../../Logic/Web/QueryParameters";
 | 
			
		|||
import {TagUtils} from "../../Logic/Tags/TagUtils";
 | 
			
		||||
import {InputElement} from "../Input/InputElement";
 | 
			
		||||
import {DropDown} from "../Input/DropDown";
 | 
			
		||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
			
		||||
 | 
			
		||||
export default class FilterView extends VariableUiElement {
 | 
			
		||||
    constructor(filteredLayer: UIEventSource<FilteredLayer[]>, 
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +92,7 @@ export default class FilterView extends VariableUiElement {
 | 
			
		|||
        if (filteredLayer.layerDef.name === undefined) {
 | 
			
		||||
            // Name is not defined: we hide this one
 | 
			
		||||
            return new Toggle(
 | 
			
		||||
                filteredLayer?.layerDef?.description?.Clone()?.SetClass("subtle")                ,
 | 
			
		||||
                new FixedUiElement(filteredLayer?.layerDef?.id ).SetClass("block") ,
 | 
			
		||||
                undefined,
 | 
			
		||||
                state?.featureSwitchIsDebugging
 | 
			
		||||
            );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,7 +90,7 @@ export class TextFieldDef {
 | 
			
		|||
        if (options.unit !== undefined) {
 | 
			
		||||
            // Reformatting is handled by the unit in this case
 | 
			
		||||
            options["isValid"] = str => {
 | 
			
		||||
                const denom = options.unit.findDenomination(str);
 | 
			
		||||
                const denom = options.unit.findDenomination(str, options?.country);
 | 
			
		||||
                if (denom === undefined) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ export class TextFieldDef {
 | 
			
		|||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                    )
 | 
			
		||||
            unitDropDown.GetValue().setData(unit.defaultDenom)
 | 
			
		||||
            unitDropDown.GetValue().setData(unit.getDefaultInput(options.country))
 | 
			
		||||
            unitDropDown.SetClass("w-min")
 | 
			
		||||
 | 
			
		||||
            const fixedDenom = unit.denominations.length === 1 ? unit.denominations[0] : undefined
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +169,7 @@ export class TextFieldDef {
 | 
			
		|||
                },
 | 
			
		||||
                (valueWithDenom: string) => {
 | 
			
		||||
                    // Take the value from OSM and feed it into the textfield and the dropdown
 | 
			
		||||
                    const withDenom = unit.findDenomination(valueWithDenom);
 | 
			
		||||
                    const withDenom = unit.findDenomination(valueWithDenom, options?.country);
 | 
			
		||||
                    if (withDenom === undefined) {
 | 
			
		||||
                        // Not a valid value at all - we give it undefined and leave the details up to the other elements (but we keep the previous denomination)
 | 
			
		||||
                        return [undefined, fixedDenom]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -617,6 +617,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
			
		|||
        const tagsData = tags.data;
 | 
			
		||||
        const feature = state?.allElements?.ContainingFeatures?.get(tagsData.id)
 | 
			
		||||
        const center = feature != undefined ? GeoOperations.centerpointCoordinates(feature) : [0, 0]
 | 
			
		||||
        console.log("Creating a tr-question with applicableUnit", applicableUnit)
 | 
			
		||||
        const input: InputElement<string> = ValidatedTextField.ForType(configuration.freeform.type)?.ConstructInputElement({
 | 
			
		||||
            country: () => tagsData._country,
 | 
			
		||||
            location: [center[1], center[0]],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1273,6 +1273,9 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            const tagRendering = layer.tagRenderings.find(tr => tr.id === tagRenderingId)
 | 
			
		||||
                            tagRenderings.push([layer, tagRendering])
 | 
			
		||||
                        }
 | 
			
		||||
                        if(tagRenderings.length === 0){
 | 
			
		||||
                            throw "Could not create stolen tagrenddering: tagRenderings not found"
 | 
			
		||||
                        }
 | 
			
		||||
                        return new VariableUiElement(featureTags.map(tags => {
 | 
			
		||||
                            const featureId = tags[featureIdKey]
 | 
			
		||||
                            if (featureId === undefined) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -151,8 +151,8 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
 | 
			
		|||
        return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static NoNull<T>(array: T[]): T[] {
 | 
			
		||||
        return array?.filter(o => o !== undefined && o !== null)
 | 
			
		||||
    public static NoNull<T>(array: T[]): NonNullable<T>[] {
 | 
			
		||||
        return <any> array?.filter(o => o !== undefined && o !== null)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Hist(array: string[]): Map<string, number> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -271,6 +271,9 @@
 | 
			
		|||
    "smoking",
 | 
			
		||||
    "service:electricity",
 | 
			
		||||
    "dog-access",
 | 
			
		||||
    "internet",
 | 
			
		||||
    "internet-fee",
 | 
			
		||||
    "internet-ssid",
 | 
			
		||||
    "reviews"
 | 
			
		||||
  ],
 | 
			
		||||
  "filter": [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,6 +185,7 @@
 | 
			
		|||
          "alternativeDenomination": [
 | 
			
		||||
            "meter"
 | 
			
		||||
          ],
 | 
			
		||||
          "useIfNoUnitGiven": true,
 | 
			
		||||
          "human": {
 | 
			
		||||
            "en": "meter",
 | 
			
		||||
            "fr": "mètre",
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +194,7 @@
 | 
			
		|||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "default": true,
 | 
			
		||||
          "useAsDefaultInput": true,
 | 
			
		||||
          "canonicalDenomination": "cm",
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "centimeter",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -467,10 +467,12 @@
 | 
			
		|||
  "units": [
 | 
			
		||||
    {
 | 
			
		||||
      "appliesToKey": [
 | 
			
		||||
        "kerb:height"
 | 
			
		||||
        "kerb:height",
 | 
			
		||||
        "width"
 | 
			
		||||
      ],
 | 
			
		||||
      "applicableUnits": [
 | 
			
		||||
        {  
 | 
			
		||||
          "useIfNoUnitGiven": true,
 | 
			
		||||
          "canonicalDenomination": "m",
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "meter"
 | 
			
		||||
| 
						 | 
				
			
			@ -483,7 +485,7 @@
 | 
			
		|||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "default": true,
 | 
			
		||||
          "useAsDefaultInput": true,
 | 
			
		||||
          "canonicalDenomination": "cm",
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "centimeter",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -764,6 +764,9 @@
 | 
			
		|||
    },
 | 
			
		||||
    "service:electricity",
 | 
			
		||||
    "dog-access",
 | 
			
		||||
    "internet",
 | 
			
		||||
    "internet-fee",
 | 
			
		||||
    "internet-ssid",
 | 
			
		||||
    "reviews"
 | 
			
		||||
  ],
 | 
			
		||||
  "filter": [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,10 @@
 | 
			
		|||
    "phone",
 | 
			
		||||
    "email",
 | 
			
		||||
    "website",
 | 
			
		||||
    "wheelchair-access"
 | 
			
		||||
    "wheelchair-access",
 | 
			
		||||
    "internet",
 | 
			
		||||
    "internet-fee",
 | 
			
		||||
    "internet-ssid"
 | 
			
		||||
  ],
 | 
			
		||||
  "allowMove": {
 | 
			
		||||
    "enableImproveAccuracy": true,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,45 @@
 | 
			
		|||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
 | 
			
		||||
  <path d="M 0.5 3 C 0.223 3 0 3.223 0 3.5 L 0 4 L 0 8 L 0 9 L 0 9.5 L 0 11 L 1 11 L 1 9.5 L 1 9 L 13 9 L 13 10.5 L 13 11 L 13.5 11 L 14 11 L 14 10.5 L 14 9 L 14 8 L 14 6 L 14 5.5 C 14 5.223 13.777 5 13.5 5 C 13.223 5 13 5.223 13 5.5 L 13 6 L 13 8 L 1 8 L 1 4 L 1 3.5 C 1 3.223 0.777 3 0.5 3 z M 3.5 4 C 2.671573 4 2 4.671573 2 5.5 C 2 6.328427 2.671573 7 3.5 7 C 4.328427 7 5 6.328427 5 5.5 C 5 4.671573 4.328427 4 3.5 4 z M 6 5 L 6 7 L 12 7 C 12 6 10.963825 5 10 5 L 6 5 z"/>
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<svg
 | 
			
		||||
   width="500"
 | 
			
		||||
   height="500"
 | 
			
		||||
   viewBox="0 0 500 500"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   id="svg4"
 | 
			
		||||
   sodipodi:docname="hotel.svg"
 | 
			
		||||
   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs8" />
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="namedview6"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#111111"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     inkscape:pageshadow="0"
 | 
			
		||||
     inkscape:pageopacity="0"
 | 
			
		||||
     inkscape:pagecheckerboard="1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     showguides="true"
 | 
			
		||||
     inkscape:guide-bbox="true"
 | 
			
		||||
     inkscape:zoom="0.5912918"
 | 
			
		||||
     inkscape:cx="43.125915"
 | 
			
		||||
     inkscape:cy="341.6249"
 | 
			
		||||
     inkscape:window-width="1920"
 | 
			
		||||
     inkscape:window-height="1007"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="0"
 | 
			
		||||
     inkscape:window-maximized="1"
 | 
			
		||||
     inkscape:current-layer="svg4">
 | 
			
		||||
    <sodipodi:guide
 | 
			
		||||
       position="-213.39489,250.02313"
 | 
			
		||||
       orientation="0,-1"
 | 
			
		||||
       id="guide827" />
 | 
			
		||||
  </sodipodi:namedview>
 | 
			
		||||
  <path
 | 
			
		||||
     d="m 20.793355,103.8662 c -9.838754,0 -17.7594848,7.92073 -17.7594848,17.75948 v 17.75948 142.07589 35.51898 17.75949 53.27845 H 38.552842 V 334.73952 316.98003 H 464.78049 v 53.27845 17.75949 h 17.7595 17.75948 v -17.75949 -53.27845 -35.51898 -71.03793 -17.75949 c 0,-9.83876 -7.92073,-17.75949 -17.75948,-17.75949 -9.83876,0 -17.7595,7.92073 -17.7595,17.75949 v 17.75949 71.03793 H 38.552842 V 139.38516 121.62568 c 0,-9.83875 -7.920731,-17.75948 -17.759487,-17.75948 z m 106.556915,35.51896 c -29.424876,0 -53.278458,23.85359 -53.278458,53.27847 0,29.42487 23.853582,53.27845 53.278458,53.27845 29.42487,0 53.27845,-23.85358 53.27845,-53.27845 0,-29.42488 -23.85358,-53.27847 -53.27845,-53.27847 z m 88.79743,35.51898 v 71.03794 h 213.11382 c 0,-35.51896 -36.80387,-71.03794 -71.03793,-71.03794 z"
 | 
			
		||||
     id="path2"
 | 
			
		||||
     style="stroke-width:35.519" />
 | 
			
		||||
</svg>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		 Before Width: | Height: | Size: 569 B After Width: | Height: | Size: 2 KiB  | 
| 
						 | 
				
			
			@ -456,7 +456,6 @@
 | 
			
		|||
    {
 | 
			
		||||
      "applicableUnits": [
 | 
			
		||||
        {
 | 
			
		||||
          "default": true,
 | 
			
		||||
          "canonicalDenomination": "",
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "mm",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -178,8 +178,6 @@
 | 
			
		|||
        "centroid"
 | 
			
		||||
      ],
 | 
			
		||||
      "icon": {
 | 
			
		||||
        "render": null,
 | 
			
		||||
        "condition": "indoor=room",
 | 
			
		||||
        "mappings": [
 | 
			
		||||
          {
 | 
			
		||||
            "if": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -339,8 +339,7 @@
 | 
			
		|||
            "nl": "centimeter",
 | 
			
		||||
            "de": "Zentimeter",
 | 
			
		||||
            "fr": "centimètre"
 | 
			
		||||
          },
 | 
			
		||||
          "default": true
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "canonicalDenomination": "m",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,16 +110,19 @@
 | 
			
		|||
  "allowSplit": true,
 | 
			
		||||
  "mapRendering": [
 | 
			
		||||
    {
 | 
			
		||||
      "render": null,
 | 
			
		||||
      "icon": {
 | 
			
		||||
        "render": null,
 | 
			
		||||
        "mappings": [
 | 
			
		||||
          {
 | 
			
		||||
            "if": "maxspeed~[1-9]0|1[0-4]0",
 | 
			
		||||
            "then": "./assets/themes/maxspeed/maxspeed_{maxspeed} mph.svg"
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "if": "maxspeed~[1-9]0|1[0-4]0 mph",
 | 
			
		||||
            "then": "./assets/themes/maxspeed/maxspeed_{maxspeed}.svg"
 | 
			
		||||
          }
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "condition": "maxspeed!=30",
 | 
			
		||||
      "iconSize": {
 | 
			
		||||
        "render": "32,32,center"
 | 
			
		||||
      },
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +157,6 @@
 | 
			
		|||
            "kmh",
 | 
			
		||||
            "kph"
 | 
			
		||||
          ],
 | 
			
		||||
          "default": true,
 | 
			
		||||
          "human": {
 | 
			
		||||
            "en": "kilometers/hour",
 | 
			
		||||
            "ca": "quilòmetres/hora",
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +174,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "canonicalDenomination": "mph",
 | 
			
		||||
          "useIfNoUnitGiven": ["gb","us"],
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "m/u",
 | 
			
		||||
            "mh",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -164,6 +164,15 @@
 | 
			
		|||
            "fr": "Il n'y a pas de places de stationnement pour personnes à mobilité réduite"
 | 
			
		||||
          },
 | 
			
		||||
          "hideInAnswer": true
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "capacity:disabled=0",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "There are no disabled parking spots",
 | 
			
		||||
            "nl": "Er zijn geen parkeerplaatsen voor gehandicapten",
 | 
			
		||||
            "de": "Es gibt keine barrierefreien Stellplätze",
 | 
			
		||||
            "fr": "Il n'y a pas de places de stationnement pour personnes à mobilité réduite"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "question": {
 | 
			
		||||
| 
						 | 
				
			
			@ -247,9 +256,9 @@
 | 
			
		|||
      "iconBadges": [
 | 
			
		||||
        {
 | 
			
		||||
          "if": {
 | 
			
		||||
            "and": [
 | 
			
		||||
              "capacity:disabled~*",
 | 
			
		||||
              "capacity:disabled!=no"
 | 
			
		||||
            "or": [
 | 
			
		||||
              "capacity:disabled>0",
 | 
			
		||||
              "capacity:disabled=yes"
 | 
			
		||||
            ]
 | 
			
		||||
          },
 | 
			
		||||
          "then": "circle:white;./assets/layers/toilet/wheelchair.svg"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								assets/layers/parking_spaces/license_info.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
[
 | 
			
		||||
  {
 | 
			
		||||
    "path": "parking_space.svg",
 | 
			
		||||
    "license": "CC0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "Robin van der Linde"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": []
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										70
									
								
								assets/layers/parking_spaces/parking_space.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,70 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="500"
 | 
			
		||||
   height="500"
 | 
			
		||||
   viewBox="0 0 132.29166 132.29167"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   id="svg8"
 | 
			
		||||
   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
 | 
			
		||||
   sodipodi:docname="Parking_space.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs2" />
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1.979899"
 | 
			
		||||
     inkscape:cx="105.28861"
 | 
			
		||||
     inkscape:cy="436.23499"
 | 
			
		||||
     inkscape:document-units="mm"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     inkscape:document-rotation="0"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     units="px"
 | 
			
		||||
     inkscape:window-width="3840"
 | 
			
		||||
     inkscape:window-height="2066"
 | 
			
		||||
     inkscape:window-x="2149"
 | 
			
		||||
     inkscape:window-y="-11"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata5">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Laag 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1">
 | 
			
		||||
    <path
 | 
			
		||||
       style="fill:none;stroke:#1d5485;stroke-width:5px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
 | 
			
		||||
       d="m 26.458333,121.70833 0,-111.124997 h 79.374997 l 0,111.124997"
 | 
			
		||||
       id="path833"
 | 
			
		||||
       sodipodi:nodetypes="cccc" />
 | 
			
		||||
    <g
 | 
			
		||||
       aria-label="P"
 | 
			
		||||
       id="text833"
 | 
			
		||||
       style="font-style:normal;font-weight:normal;font-size:68.771px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.71928">
 | 
			
		||||
      <path
 | 
			
		||||
         d="m 82.499093,56.25664 q 0,3.32438 -1.175286,6.178645 -1.141706,2.820686 -3.22364,4.90262 -2.585629,2.585629 -6.111486,3.895233 -3.525857,1.276025 -8.898592,1.276025 H 56.44133 V 91.145836 H 49.792571 V 41.145824 h 13.566155 q 4.499665,0 7.622567,0.772331 3.122902,0.738751 5.540633,2.350571 2.854265,1.914037 4.398926,4.768302 1.578241,2.854265 1.578241,7.219612 z m -6.917396,0.167898 q 0,-2.585628 -0.906649,-4.499665 -0.906649,-1.914037 -2.753526,-3.122902 -1.611821,-1.040968 -3.693755,-1.477502 -2.048355,-0.470115 -5.204837,-0.470115 h -6.5816 v 19.979858 h 5.607792 q 4.029551,0 6.54802,-0.705172 2.51847,-0.738751 4.09671,-2.316992 1.578241,-1.61182 2.216253,-3.391538 0.671592,-1.779719 0.671592,-3.995972 z"
 | 
			
		||||
         style="stroke-width:1.71928"
 | 
			
		||||
         id="path835" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										155
									
								
								assets/layers/parking_spaces/parking_spaces.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,155 @@
 | 
			
		|||
{
 | 
			
		||||
  "id": "parking_spaces",
 | 
			
		||||
  "name": {
 | 
			
		||||
    "en": "Parking Spaces"
 | 
			
		||||
  },
 | 
			
		||||
  "description": {
 | 
			
		||||
    "en": "Layer showing individual parking spaces."
 | 
			
		||||
  },
 | 
			
		||||
  "minzoom": 20,
 | 
			
		||||
  "source": {
 | 
			
		||||
    "osmTags": "amenity=parking_space"
 | 
			
		||||
  },
 | 
			
		||||
  "tagRenderings": [
 | 
			
		||||
    {
 | 
			
		||||
      "id": "type",
 | 
			
		||||
      "question": {
 | 
			
		||||
        "en": "What kind of parking space is this?"
 | 
			
		||||
      },
 | 
			
		||||
      "mappings": [
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a normal parking space"
 | 
			
		||||
          },
 | 
			
		||||
          "hideInAnswer": true
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=normal",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a normal parking space."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=disabled",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a disabled parking space."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=private",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a private parking space."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=charging",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is parking space reserved for charging vehicles."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=delivery",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is parking space reserved for deliveries."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=hgv",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is parking space reserved for heavy goods vehicles."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=caravan",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is parking space reserved for caravans or RVs."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=bus",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is parking space reserved for buses."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=motorcycle",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is parking space reserved for motorcycles."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=parent",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a parking space reserved for parents with children."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=staff",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a parking space reserved for staff."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=taxi",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a parking space reserved for taxis."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=trailer",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a parking space reserved for vehicles towing a trailer."
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "parking_space=car_sharing",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This is a parking space reserved for car sharing."
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "id": "capacity",
 | 
			
		||||
      "render": {
 | 
			
		||||
        "en": "This parking spaces has {capacity} spaces."
 | 
			
		||||
      },
 | 
			
		||||
      "mappings": [
 | 
			
		||||
        {
 | 
			
		||||
          "if": "capacity=1",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "en": "This parking space has 1 space."
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "title": {
 | 
			
		||||
    "render": {
 | 
			
		||||
      "en": "Parking Space"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "mapRendering": [
 | 
			
		||||
    {
 | 
			
		||||
      "icon": {
 | 
			
		||||
        "render": "./assets/layers/parking_spaces/parking_space.svg",
 | 
			
		||||
        "mappings": [
 | 
			
		||||
          {
 | 
			
		||||
            "if": "parking_space=disabled",
 | 
			
		||||
            "then": "./assets/layers/toilet/wheelchair.svg"
 | 
			
		||||
          }
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "iconSize": "20,20,center",
 | 
			
		||||
      "location": [
 | 
			
		||||
        "point",
 | 
			
		||||
        "centroid"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "color": "#696969",
 | 
			
		||||
      "width": "1"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -201,6 +201,9 @@
 | 
			
		|||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "internet",
 | 
			
		||||
    "internet-fee",
 | 
			
		||||
    "internet-ssid",
 | 
			
		||||
    "questions",
 | 
			
		||||
    "reviews"
 | 
			
		||||
  ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -264,7 +264,7 @@
 | 
			
		|||
      },
 | 
			
		||||
      "mappings": [
 | 
			
		||||
        {
 | 
			
		||||
          "if": "access=public",
 | 
			
		||||
          "if": "access=yes",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "nl": "Publiek toegankelijk",
 | 
			
		||||
            "fr": "Accessible au public",
 | 
			
		||||
| 
						 | 
				
			
			@ -309,6 +309,19 @@
 | 
			
		|||
            "de": "Der Sportplatz ist nicht öffentlich zugänglich (es ist ein privater Sportplatz)",
 | 
			
		||||
            "es": "Privada - no accesible al público"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "if": "access=public",
 | 
			
		||||
          "then": {
 | 
			
		||||
            "nl": "Publiek toegankelijk",
 | 
			
		||||
            "fr": "Accessible au public",
 | 
			
		||||
            "en": "Public access",
 | 
			
		||||
            "it": "Aperto al pubblico",
 | 
			
		||||
            "ru": "Свободный доступ",
 | 
			
		||||
            "de": "Der Sportplatz ist öffentlich zugänglich",
 | 
			
		||||
            "es": "Acceso público"
 | 
			
		||||
          },
 | 
			
		||||
          "hideInAnswer": true
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,7 @@
 | 
			
		|||
      ],
 | 
			
		||||
      "applicableUnits": [
 | 
			
		||||
        {
 | 
			
		||||
          "useIfNoUnitGiven": true,
 | 
			
		||||
          "canonicalDenomination": "m",
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "meter"
 | 
			
		||||
| 
						 | 
				
			
			@ -74,16 +75,16 @@
 | 
			
		|||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "default": true,
 | 
			
		||||
          "useAsDefaultInput": true,
 | 
			
		||||
          "canonicalDenomination": "cm",
 | 
			
		||||
          "alternativeDenomination": [
 | 
			
		||||
            "centimeter",
 | 
			
		||||
            "cms"
 | 
			
		||||
          ],
 | 
			
		||||
          "human": {
 | 
			
		||||
            "en": "centimeter",
 | 
			
		||||
            "fr": "centimètre",
 | 
			
		||||
            "de": "Zentimeter"
 | 
			
		||||
            "en": " centimeter",
 | 
			
		||||
            "fr": " centimètre",
 | 
			
		||||
            "de": " Zentimeter"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1148,5 +1148,110 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "internet": {
 | 
			
		||||
    "question": {
 | 
			
		||||
      "en": "Does this place offer internet access?",
 | 
			
		||||
      "nl": "Biedt deze plaats internettoegang aan?"
 | 
			
		||||
    },
 | 
			
		||||
    "mappings": [
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access=wlan",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "This place offers wireless internet access",
 | 
			
		||||
          "nl": "Deze plaats biedt draadloze internettoegang aan"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access=no",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "This place <b>does not</b> offer internet access",
 | 
			
		||||
          "nl": "Deze plaats biedt <b>geen</b> internettoegang aan"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access=yes",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "This place offers internet access",
 | 
			
		||||
          "nl": "Deze plaats biedt internettoegang aan"
 | 
			
		||||
        },
 | 
			
		||||
        "hideInAnswer": true
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access=terminal",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "This place offers internet access via a terminal or computer",
 | 
			
		||||
          "nl": "Deze plaats biedt internettoegang via een terminal of computer aan"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access=wired",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "This place offers wired internet access",
 | 
			
		||||
          "nl": "Deze plaats biedt bedrade internettoegang aan"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "internet-fee": {
 | 
			
		||||
    "condition": {
 | 
			
		||||
      "and": [
 | 
			
		||||
        "internet_access!=no",
 | 
			
		||||
        "internet_access!="
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "question": {
 | 
			
		||||
      "en": "Is there a fee for internet access?",
 | 
			
		||||
      "nl": "Zijn er kosten voor internettoegang?"
 | 
			
		||||
    },
 | 
			
		||||
    "mappings": [
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access:fee=yes",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "There is a fee for the internet access at this place",
 | 
			
		||||
          "nl": "Er zijn kosten voor internettoegang op deze plaats"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access:fee=no",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "Internet access is free at this place",
 | 
			
		||||
          "nl": "Internettoegang is gratis op deze plaats"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access:fee=customers",
 | 
			
		||||
        "then": {
 | 
			
		||||
          "en": "Internet access is free at this place, for customers only",
 | 
			
		||||
          "nl": "Internettoegang is gratis op deze plaats, alleen voor klanten"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "internet-ssid": {
 | 
			
		||||
    "condition": "internet_access=wlan",
 | 
			
		||||
    "question": {
 | 
			
		||||
      "en": "What is the network name for the wireless internet access?",
 | 
			
		||||
      "nl": "Wat is de netwerknaam voor de draadloze internettoegang?"
 | 
			
		||||
    },
 | 
			
		||||
    "freeform": {
 | 
			
		||||
      "key": "internet_access:ssid",
 | 
			
		||||
      "type": "string",
 | 
			
		||||
      "placeholder": {
 | 
			
		||||
        "en": "Enter the network name",
 | 
			
		||||
        "nl": "Voer de netwerknaam in"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "mappings": [
 | 
			
		||||
      {
 | 
			
		||||
        "if": "internet_access:ssid=Telekom",
 | 
			
		||||
        "then": "Telekom",
 | 
			
		||||
        "hideInAnswer": "_country!=de"
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    "render": {
 | 
			
		||||
      "en": "The network name is <b>{internet_access:ssid}</b>",
 | 
			
		||||
      "nl": "De netwerknaam is <b>{internet_access:ssid}</b>"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -132,8 +132,7 @@
 | 
			
		|||
                  "ca": " metre",
 | 
			
		||||
                  "nb_NO": " meter",
 | 
			
		||||
                  "es": " metro"
 | 
			
		||||
                },
 | 
			
		||||
                "default": true
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                "canonicalDenomination": "ft",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								assets/themes/hotels/hotels.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
{
 | 
			
		||||
  "id": "hotels",
 | 
			
		||||
  "title": {
 | 
			
		||||
    "en": "Hotels"
 | 
			
		||||
  },
 | 
			
		||||
  "description": {
 | 
			
		||||
    "en": "On this map, you'll find hotels in your area"
 | 
			
		||||
  },
 | 
			
		||||
  "maintainer": "MapComplete",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "icon": "./assets/layers/hotel/hotel.svg",
 | 
			
		||||
  "startLat": 50.8552,
 | 
			
		||||
  "startLon": 4.3755,
 | 
			
		||||
  "startZoom": 13,
 | 
			
		||||
  "layers": [
 | 
			
		||||
    "hotel"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +207,10 @@
 | 
			
		|||
                "if": "theme=healthcare",
 | 
			
		||||
                "then": "./assets/layers/doctors/doctors.svg"
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                "if": "theme=hotels",
 | 
			
		||||
                "then": "./assets/layers/hotel/hotel.svg"
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                "if": "theme=indoors",
 | 
			
		||||
                "then": "./assets/layers/entrance/entrance.svg"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,142 +1,142 @@
 | 
			
		|||
[
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_10.svg",
 | 
			
		||||
    "path": "maxspeed_10 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_100.svg",
 | 
			
		||||
    "path": "maxspeed_100 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_110.svg",
 | 
			
		||||
    "path": "maxspeed_110 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_120.svg",
 | 
			
		||||
    "path": "maxspeed_120 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_130.svg",
 | 
			
		||||
    "path": "maxspeed_130 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_140.svg",
 | 
			
		||||
    "path": "maxspeed_140 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_20.svg",
 | 
			
		||||
    "path": "maxspeed_20 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_30.svg",
 | 
			
		||||
    "path": "maxspeed_30 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_40.svg",
 | 
			
		||||
    "path": "maxspeed_40 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_50.svg",
 | 
			
		||||
    "path": "maxspeed_50 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_60.svg",
 | 
			
		||||
    "path": "maxspeed_60 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_70.svg",
 | 
			
		||||
    "path": "maxspeed_70 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_80.svg",
 | 
			
		||||
    "path": "maxspeed_80 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "path": "maxspeed_90.svg",
 | 
			
		||||
    "path": "maxspeed_90 mph.svg",
 | 
			
		||||
    "license": "CC 4.0",
 | 
			
		||||
    "authors": [
 | 
			
		||||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +146,7 @@
 | 
			
		|||
      "yopaseopor"
 | 
			
		||||
    ],
 | 
			
		||||
    "sources": [
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
 | 
			
		||||
      "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB  | 
| 
		 Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB  | 
| 
		 Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB  | 
| 
		 Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB  | 
| 
		 Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB  | 
| 
		 Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB  | 
| 
		 Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB  | 
| 
		 Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB  | 
| 
		 Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB  | 
| 
		 Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB  | 
| 
		 Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB  | 
| 
		 Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB  | 
| 
						 | 
				
			
			@ -45,6 +45,7 @@
 | 
			
		|||
  "startZoom": 12,
 | 
			
		||||
  "widenFactor": 1.2,
 | 
			
		||||
  "layers": [
 | 
			
		||||
    "parking"
 | 
			
		||||
    "parking",
 | 
			
		||||
    "parking_spaces"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3566,7 +3566,7 @@
 | 
			
		|||
            },
 | 
			
		||||
            "width": {
 | 
			
		||||
                "question": "Wie breit ist diese Tür bzw. dieser Eingang?",
 | 
			
		||||
                "render": "Diese Tür hat eine Durchgangsbreite von {canonical(width)} Meter"
 | 
			
		||||
                "render": "Diese Tür hat eine Durchgangsbreite von {canonical(width)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4249,10 +4249,51 @@
 | 
			
		|||
                },
 | 
			
		||||
                "question": "Welche Bauform hat der Hydrant?",
 | 
			
		||||
                "render": " Hydranten-Typ: {fire_hydrant:type}"
 | 
			
		||||
            },
 | 
			
		||||
            "hydrant-couplings-diameters": {
 | 
			
		||||
                "question": "Welchen Durchmesser haben die Kupplungen dieses Hydranten?",
 | 
			
		||||
                "freeform": {
 | 
			
		||||
                    "placeholder": "Kupplungsdurchmesser"
 | 
			
		||||
                },
 | 
			
		||||
                "render": "Kupplungsdurchmesser: {couplings:diameters}"
 | 
			
		||||
            },
 | 
			
		||||
            "hydrant-couplings": {
 | 
			
		||||
                "freeform": {
 | 
			
		||||
                    "placeholder": "Art der Kupplung"
 | 
			
		||||
                },
 | 
			
		||||
                "mappings": {
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "then": "Storz-Kupplung"
 | 
			
		||||
                    },
 | 
			
		||||
                    "1": {
 | 
			
		||||
                        "then": "UNI-Kupplung"
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "then": "Barcelona-Kupplung"
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Welche Art von Kupplungen hat dieser Hydrant?",
 | 
			
		||||
                "render": "Kupplungen: {couplings:type}"
 | 
			
		||||
            },
 | 
			
		||||
            "hydrant-diameter": {
 | 
			
		||||
                "freeform": {
 | 
			
		||||
                    "placeholder": "Rohrdurchmesser"
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Was ist der Rohrdurchmesser dieses Hydranten?",
 | 
			
		||||
                "render": "Rohrdurchmesser: {canonical(fire_hydrant:diameter)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
            "render": "Hydrant"
 | 
			
		||||
        },
 | 
			
		||||
        "units": {
 | 
			
		||||
            "0": {
 | 
			
		||||
                "applicableUnits": {
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "human": "Millimeter"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "indoors": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4366,7 +4407,7 @@
 | 
			
		|||
                        "then": "Der Bordstein hat kein taktiles Pflaster."
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "then": "Der Bordstein hat ein taktiles Pflaster, das aber falsch ist"
 | 
			
		||||
                        "then": "Der Bordstein hat ein taktiles Pflaster, das aber falsch ist."
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Gibt es am Bordstein ein taktiles Pflaster?"
 | 
			
		||||
| 
						 | 
				
			
			@ -4648,7 +4689,7 @@
 | 
			
		|||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Wie hoch ist die zulässige Höchstgeschwindigkeit, die man auf dieser Straße fahren darf?",
 | 
			
		||||
                "render": "Die zulässige Höchstgeschwindigkeit auf dieser Straße ist {maxspeed}"
 | 
			
		||||
                "render": "Die zulässige Höchstgeschwindigkeit auf dieser Straße ist {canonical(maxspeed)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3566,7 +3566,7 @@
 | 
			
		|||
            },
 | 
			
		||||
            "width": {
 | 
			
		||||
                "question": "What is the width of this door/entrance?",
 | 
			
		||||
                "render": "This door has a width of {canonical(width)} meter"
 | 
			
		||||
                "render": "This door has a width of {canonical(width)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4438,7 +4438,7 @@
 | 
			
		|||
                        "then": "This kerb does not have tactile paving."
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "then": "This kerb has tactile paving, but it is incorrect"
 | 
			
		||||
                        "then": "This kerb has tactile paving, but it is incorrect."
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Is there tactile paving at this kerb?"
 | 
			
		||||
| 
						 | 
				
			
			@ -4720,7 +4720,7 @@
 | 
			
		|||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "What is the legal maximum speed one is allowed to drive on this road?",
 | 
			
		||||
                "render": "The maximum allowed speed on this road is {maxspeed}"
 | 
			
		||||
                "render": "The maximum allowed speed on this road is {canonical(maxspeed)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3049,7 +3049,7 @@
 | 
			
		|||
                        "then": "Cette bordure n'a pas de revêtement podotactile."
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "then": "Cette bordure a un pavage tactile, mais il est incorrect"
 | 
			
		||||
                        "then": "Cette bordure a un pavage tactile, mais il est incorrect."
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Y a-t-il un revêtement tactile sur cette bordure ?"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3406,6 +3406,9 @@
 | 
			
		|||
        "presets": {
 | 
			
		||||
            "0": {
 | 
			
		||||
                "title": "een toegang"
 | 
			
		||||
            },
 | 
			
		||||
            "1": {
 | 
			
		||||
                "title": "een binnendeur"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "tagRenderings": {
 | 
			
		||||
| 
						 | 
				
			
			@ -3509,7 +3512,7 @@
 | 
			
		|||
            },
 | 
			
		||||
            "width": {
 | 
			
		||||
                "question": "Wat is de breedte van deze deur/toegang?",
 | 
			
		||||
                "render": "Deze deur heeft een breedte van {canonical(width)} meter"
 | 
			
		||||
                "render": "Deze deur heeft een breedte van {canonical(width)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4221,7 +4224,43 @@
 | 
			
		|||
        "description": "Een basis voor indoor-navigatie: toont binnenruimtes",
 | 
			
		||||
        "name": "Binnenruimtes",
 | 
			
		||||
        "title": {
 | 
			
		||||
            "render": "Binnenruimte {name}"
 | 
			
		||||
            "render": "Binnenruimte {name}",
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
                    "then": "Binnenruimte {name}"
 | 
			
		||||
                },
 | 
			
		||||
                "4": {
 | 
			
		||||
                    "then": "Binnendeur {name}"
 | 
			
		||||
                },
 | 
			
		||||
                "3": {
 | 
			
		||||
                    "then": "Gang in gebouw {name}"
 | 
			
		||||
                },
 | 
			
		||||
                "1": {
 | 
			
		||||
                    "then": "Gebied in gebouw {name}"
 | 
			
		||||
                },
 | 
			
		||||
                "5": {
 | 
			
		||||
                    "then": "Verdieping in gebouw {name}"
 | 
			
		||||
                },
 | 
			
		||||
                "2": {
 | 
			
		||||
                    "then": "Muur in gebouw {name}"
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "tagRenderings": {
 | 
			
		||||
            "name": {
 | 
			
		||||
                "render": "Deze ruimte heet {name}",
 | 
			
		||||
                "question": "Wat is de naam van deze ruimte?",
 | 
			
		||||
                "freeform": {
 | 
			
		||||
                    "placeholder": "Naam van de ruimte"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "ref": {
 | 
			
		||||
                "question": "Wat is het referentienummer van deze ruimte?",
 | 
			
		||||
                "freeform": {
 | 
			
		||||
                    "placeholder": "Referentienummer van de ruimte (bv. '1.1' of A1' )"
 | 
			
		||||
                },
 | 
			
		||||
                "render": "Deze ruimte heeft het referentienummer {ref}"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "information_board": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4264,7 +4303,16 @@
 | 
			
		|||
            "1": {
 | 
			
		||||
                "options": {
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "question": "Drempes met of zonder"
 | 
			
		||||
                        "question": "Stoepranden met of zonder voelbare bestrating"
 | 
			
		||||
                    },
 | 
			
		||||
                    "1": {
 | 
			
		||||
                        "question": "Stoeprand met voelbare bestrating"
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "question": "Stoeprand zonder voelbare bestrating"
 | 
			
		||||
                    },
 | 
			
		||||
                    "3": {
 | 
			
		||||
                        "question": "Stoeprand zonder informatie over voelbare bestrating"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -4303,6 +4351,20 @@
 | 
			
		|||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Hoe hoog is deze stoeprand?"
 | 
			
		||||
            },
 | 
			
		||||
            "tactile-paving": {
 | 
			
		||||
                "mappings": {
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "then": "Deze stoeprand heeft voelbare bestrating."
 | 
			
		||||
                    },
 | 
			
		||||
                    "1": {
 | 
			
		||||
                        "then": "Deze stoeprand heeft geen voelbare bestrating."
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "then": "Deze stoeprand heeft voelbare bestrating, maar deze is incorrect."
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "question": "Is er voelbare bestrating bij deze stoeprand?"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4353,6 +4415,10 @@
 | 
			
		|||
                "override": {
 | 
			
		||||
                    "question": "Wanneer is deze kinderopvang geopend?"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "name": {
 | 
			
		||||
                "question": "Wat is de naam van deze faciliteit?",
 | 
			
		||||
                "render": "Deze faciliteit heet <b>{name}</b>"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4423,7 +4489,7 @@
 | 
			
		|||
                        "then": "Dit is een woonerf en heeft dus een maximale snelheid van 20km/h"
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "render": "De maximum toegestane snelheid op deze weg is {maxspeed}"
 | 
			
		||||
                "render": "De maximum toegestane snelheid op deze weg is {canonical(maxspeed)}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -6800,5 +6866,92 @@
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "maproulette": {
 | 
			
		||||
        "filter": {
 | 
			
		||||
            "0": {
 | 
			
		||||
                "options": {
 | 
			
		||||
                    "1": {
 | 
			
		||||
                        "question": "Toon aangemaakte taken"
 | 
			
		||||
                    },
 | 
			
		||||
                    "8": {
 | 
			
		||||
                        "question": "Toon uitgeschakelde taken"
 | 
			
		||||
                    },
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "question": "Toon taken met alle statussen"
 | 
			
		||||
                    },
 | 
			
		||||
                    "3": {
 | 
			
		||||
                        "question": "Toon vals-positieve taken"
 | 
			
		||||
                    },
 | 
			
		||||
                    "4": {
 | 
			
		||||
                        "question": "Toon overgeslagen taken"
 | 
			
		||||
                    },
 | 
			
		||||
                    "5": {
 | 
			
		||||
                        "question": "Toon verwijderde taken"
 | 
			
		||||
                    },
 | 
			
		||||
                    "6": {
 | 
			
		||||
                        "question": "Toon al opgeloste taken"
 | 
			
		||||
                    },
 | 
			
		||||
                    "7": {
 | 
			
		||||
                        "question": "Toon taken die als te lastig gemarkeerd zijn"
 | 
			
		||||
                    },
 | 
			
		||||
                    "2": {
 | 
			
		||||
                        "question": "Toon opgeloste taken"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "1": {
 | 
			
		||||
                "options": {
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "question": "Naam uitdaging bevat {search}"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "2": {
 | 
			
		||||
                "options": {
 | 
			
		||||
                    "0": {
 | 
			
		||||
                        "question": "ID uitdaging is {search}"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "description": "Laag met alle taken uit MapRoulette",
 | 
			
		||||
        "name": "MapRoulette Taken"
 | 
			
		||||
    },
 | 
			
		||||
    "transit_routes": {
 | 
			
		||||
        "tagRenderings": {
 | 
			
		||||
            "operator": {
 | 
			
		||||
                "question": "Welk bedrijf exploiteert deze buslijn?",
 | 
			
		||||
                "render": "Deze buslijn wordt geëxploiteerd door {operator}"
 | 
			
		||||
            },
 | 
			
		||||
            "from": {
 | 
			
		||||
                "render": "Deze buslijn begint bij {from}",
 | 
			
		||||
                "question": "Wat is het beginpunt van deze buslijn?"
 | 
			
		||||
            },
 | 
			
		||||
            "to": {
 | 
			
		||||
                "render": "Deze buslijn eindigt bij {to}",
 | 
			
		||||
                "question": "Wat is het eindpunt van deze buslijn?"
 | 
			
		||||
            },
 | 
			
		||||
            "colour": {
 | 
			
		||||
                "question": "Wat is de kleur van deze buslijn?",
 | 
			
		||||
                "render": "Deze buslijn heeft de kleur {colour}"
 | 
			
		||||
            },
 | 
			
		||||
            "name": {
 | 
			
		||||
                "question": "Wat is de naam van deze buslijn (bv. Bus XX: Van => Via => Naar)"
 | 
			
		||||
            },
 | 
			
		||||
            "network": {
 | 
			
		||||
                "question": "Bij welk netwerk hoort deze buslijn?",
 | 
			
		||||
                "render": "Deze buslijn is onderdeel van het {network} netwerk"
 | 
			
		||||
            },
 | 
			
		||||
            "via": {
 | 
			
		||||
                "question": "Via welk punt gaat deze buslijn?",
 | 
			
		||||
                "render": "Deze buslijn gaat via {via}"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
            "render": "Buslijn"
 | 
			
		||||
        },
 | 
			
		||||
        "description": "Laag met buslijnen",
 | 
			
		||||
        "name": "Buslijnen"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +26,7 @@
 | 
			
		|||
        "readMessages": "Je hebt ongelezen berichten. Je moet deze lezen voordat je een punt verwijderd, een andere bijdrager heeft misschien feedback",
 | 
			
		||||
        "reasons": {
 | 
			
		||||
            "disused": "Het wordt niet meer onderhouden of is verwijderd",
 | 
			
		||||
            "duplicate": "Dit punt is een duplicaat van een ander punt",
 | 
			
		||||
            "duplicate": "Dit object is een duplicaat van een ander object",
 | 
			
		||||
            "notFound": "Het kon niet gevonden worden",
 | 
			
		||||
            "test": "Dit punt was een test en was nooit echt aanwezig"
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -49,19 +49,19 @@
 | 
			
		|||
            "confirmIntro": "<h3>Voeg een {title} toe?</h3>Het punt dat je toevoegt, is <b>zichtbaar voor iedereen</b>. Veel applicaties gebruiken deze data, voeg dus enkel punten toe die echt bestaan.",
 | 
			
		||||
            "disableFilters": "Zet alle filters af",
 | 
			
		||||
            "disableFiltersExplanation": "Interessepunten kunnen verborgen zijn door een filter",
 | 
			
		||||
            "hasBeenImported": "Dit object is reeds geimporteerd",
 | 
			
		||||
            "hasBeenImported": "Dit object is reeds geïmporteerd",
 | 
			
		||||
            "import": {
 | 
			
		||||
                "hasBeenImported": "Dit object is geïmporteerd",
 | 
			
		||||
                "howToTest": "Voor testmode, voeg <b>test=true</b> of <b>backend=osm-test</b> to aan de URL. De wijzigingenset zal in de console geprint worden. Gelieve een PR te openen om dit thema als officieel thema toe te voegen en zo de import-knop te activeren.",
 | 
			
		||||
                "importTags": "Het element zal deze tags krijgen: {tags}",
 | 
			
		||||
                "officialThemesOnly": "In onofficiële thema's is de importeerknop uitgeschakeld om ongelukjes te vermijden",
 | 
			
		||||
                "wrongType": "Dit object is geen punt of lijn, en kan daarom niet geïmporteerd worden",
 | 
			
		||||
                "wrongTypeToConflate": "Dit element is geen punt of weg en kan dus niet samengevoegd worden",
 | 
			
		||||
                "wrongTypeToConflate": "Dit object is geen punt of weg en kan dus niet samengevoegd worden",
 | 
			
		||||
                "zoomInMore": "Zoom verder in om dit object af te handelen"
 | 
			
		||||
            },
 | 
			
		||||
            "importTags": "Het object zal deze tags krijgen: {tags}",
 | 
			
		||||
            "intro": "Kies hieronder welk punt je wilt toevoegen<br/>",
 | 
			
		||||
            "layerNotEnabled": "De laag {layer} is gedeactiveerd. Activeer deze om een punt toe te voegen",
 | 
			
		||||
            "layerNotEnabled": "De laag {layer} is gedeactiveerd. Activeer deze om een object toe te voegen",
 | 
			
		||||
            "openLayerControl": "Open de laag-instellingen",
 | 
			
		||||
            "pleaseLogin": "Gelieve je aan te melden om een punt toe te voegen",
 | 
			
		||||
            "presetInfo": "Het nieuwe object krijgt de attributen {tags}",
 | 
			
		||||
| 
						 | 
				
			
			@ -272,7 +272,8 @@
 | 
			
		|||
                "died": "Gestorven: {value}"
 | 
			
		||||
            },
 | 
			
		||||
            "searchWikidata": "Zoek op Wikidata",
 | 
			
		||||
            "wikipediaboxTitle": "Wikipedia"
 | 
			
		||||
            "wikipediaboxTitle": "Wikipedia",
 | 
			
		||||
            "searchToShort": "Je zoekopdracht is te kort, vul een langere tekst in"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "image": {
 | 
			
		||||
| 
						 | 
				
			
			@ -578,7 +579,8 @@
 | 
			
		|||
                "noNearOrIn": "Sorry, Ik begreep je opdracht niet omdat ik geen <code>dichtbij</code> of <code>in</code> in je zoekopdracht.\nProbeer iets als <code>Zoek drinkwater in Londen</code>, <code>Zoek frituur in Brussel</code><p></p>\n <p>Daarnaast kan je ook <code>info {cmd}</code> proberen, om info te krijgen over een enkel object.</p>",
 | 
			
		||||
                "nothingFound": "Sorry, ik kon niets vinden voor <code>{search}</code>, dus kan ik {layerTitle} niet zoeken",
 | 
			
		||||
                "overview": "Ik heb {length} overeenkomende items gevonden.",
 | 
			
		||||
                "searching": "Aan het zoeken naar {layerTitle} {mode} <code>{search}</code>…"
 | 
			
		||||
                "searching": "Aan het zoeken naar {layerTitle} {mode} <code>{search}</code>…",
 | 
			
		||||
                "docs": "Zoekt voor POIs in of nabij een locatie"
 | 
			
		||||
            },
 | 
			
		||||
            "shutdown": {
 | 
			
		||||
                "argmode": "Geeft aan op welke manier ik moet afsluiten. Dit moet één van de volgende woorden zijn: {verbs}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,47 @@
 | 
			
		|||
            },
 | 
			
		||||
            "question": "Does this place have an audio induction loop for people with reduced hearing?"
 | 
			
		||||
        },
 | 
			
		||||
        "internet": {
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
                    "then": "This place offers wireless internet access"
 | 
			
		||||
                },
 | 
			
		||||
                "1": {
 | 
			
		||||
                    "then": "This place <b>does not</b> offer internet access"
 | 
			
		||||
                },
 | 
			
		||||
                "2": {
 | 
			
		||||
                    "then": "This place offers internet access"
 | 
			
		||||
                },
 | 
			
		||||
                "3": {
 | 
			
		||||
                    "then": "This place offers internet access via a terminal or computer"
 | 
			
		||||
                },
 | 
			
		||||
                "4": {
 | 
			
		||||
                    "then": "This place offers wired internet access"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "question": "Does this place offer internet access?"
 | 
			
		||||
        },
 | 
			
		||||
        "internet-fee": {
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
                    "then": "There is a fee for the internet access at this place"
 | 
			
		||||
                },
 | 
			
		||||
                "1": {
 | 
			
		||||
                    "then": "Internet access is free at this place"
 | 
			
		||||
                },
 | 
			
		||||
                "2": {
 | 
			
		||||
                    "then": "Internet access is free at this place, for customers only"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "question": "Is there a fee for internet access?"
 | 
			
		||||
        },
 | 
			
		||||
        "internet-ssid": {
 | 
			
		||||
            "freeform": {
 | 
			
		||||
                "placeholder": "Enter the network name"
 | 
			
		||||
            },
 | 
			
		||||
            "question": "What is the network name for the wireless internet access?",
 | 
			
		||||
            "render": "The network name is <b>{internet_access:ssid}</b>"
 | 
			
		||||
        },
 | 
			
		||||
        "level": {
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,47 @@
 | 
			
		|||
        "email": {
 | 
			
		||||
            "question": "Wat is het e-mailadres van {title()}?"
 | 
			
		||||
        },
 | 
			
		||||
        "internet": {
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
                    "then": "Deze plaats biedt draadloze internettoegang aan"
 | 
			
		||||
                },
 | 
			
		||||
                "1": {
 | 
			
		||||
                    "then": "Deze plaats biedt <b>geen</b> internettoegang aan"
 | 
			
		||||
                },
 | 
			
		||||
                "2": {
 | 
			
		||||
                    "then": "Deze plaats biedt internettoegang aan"
 | 
			
		||||
                },
 | 
			
		||||
                "3": {
 | 
			
		||||
                    "then": "Deze plaats biedt internettoegang via een terminal of computer aan"
 | 
			
		||||
                },
 | 
			
		||||
                "4": {
 | 
			
		||||
                    "then": "Deze plaats biedt bedrade internettoegang aan"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "question": "Biedt deze plaats internettoegang aan?"
 | 
			
		||||
        },
 | 
			
		||||
        "internet-fee": {
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
                    "then": "Er zijn kosten voor internettoegang op deze plaats"
 | 
			
		||||
                },
 | 
			
		||||
                "1": {
 | 
			
		||||
                    "then": "Internettoegang is gratis op deze plaats"
 | 
			
		||||
                },
 | 
			
		||||
                "2": {
 | 
			
		||||
                    "then": "Internettoegang is gratis op deze plaats, alleen voor klanten"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "question": "Zijn er kosten voor internettoegang?"
 | 
			
		||||
        },
 | 
			
		||||
        "internet-ssid": {
 | 
			
		||||
            "freeform": {
 | 
			
		||||
                "placeholder": "Voer de netwerknaam in"
 | 
			
		||||
            },
 | 
			
		||||
            "question": "Wat is de netwerknaam voor de draadloze internettoegang?",
 | 
			
		||||
            "render": "De netwerknaam is <b>{internet_access:ssid}</b>"
 | 
			
		||||
        },
 | 
			
		||||
        "level": {
 | 
			
		||||
            "mappings": {
 | 
			
		||||
                "0": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -906,6 +906,28 @@
 | 
			
		|||
                "tagRenderings": {
 | 
			
		||||
                    "streetname": {
 | 
			
		||||
                        "render": "Diese Straße heißt {name}"
 | 
			
		||||
                    },
 | 
			
		||||
                    "left-right-questions": {
 | 
			
		||||
                        "renderings": {
 | 
			
		||||
                            "1": {
 | 
			
		||||
                                "question": "Gibt es auf dieser Straßenseite einen Bürgersteig?",
 | 
			
		||||
                                "mappings": {
 | 
			
		||||
                                    "1": {
 | 
			
		||||
                                        "then": "Nein, es gibt keinen Bürgersteig für Fußgänger"
 | 
			
		||||
                                    },
 | 
			
		||||
                                    "0": {
 | 
			
		||||
                                        "then": "Ja, es gibt einen Bürgersteig auf dieser Straßenseite"
 | 
			
		||||
                                    },
 | 
			
		||||
                                    "2": {
 | 
			
		||||
                                        "then": "Es gibt einen separat kartierten Bürgersteig für Fußgänger"
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "2": {
 | 
			
		||||
                                "question": "Wie breit ist der Bürgersteig auf dieser Straßenseite?",
 | 
			
		||||
                                "render": "Dieser Bürgersteig ist {sidewalk:left|right:width}m breit"
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                "title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
        "cannotBeDeleted": "這圖徵無法刪除",
 | 
			
		||||
        "delete": "刪除",
 | 
			
		||||
        "explanations": {
 | 
			
		||||
            "hardDelete": "這個點已經在開放街圖被刪除了,可以被實驗性的貢獻者恢復",
 | 
			
		||||
            "hardDelete": "這個圖徵已經在開放街圖被刪除了,可以被實驗性的貢獻者恢復",
 | 
			
		||||
            "selectReason": "請選擇為什麼這個圖徵應該被刪除",
 | 
			
		||||
            "softDelete": "這個圖徵已經被更新,然後從程式被隱藏了。<span class=\"subtle\">{reason}</span>"
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,22 +7,21 @@ describe("Unit", () => {
 | 
			
		|||
 | 
			
		||||
        it("should convert a value back and forth", () => {
 | 
			
		||||
 | 
			
		||||
            const unit = new Denomination({
 | 
			
		||||
            const denomintion = new Denomination({
 | 
			
		||||
                "canonicalDenomination": "MW",
 | 
			
		||||
                "alternativeDenomination": ["megawatts", "megawatt"],
 | 
			
		||||
                "human": {
 | 
			
		||||
                    "en": " megawatts",
 | 
			
		||||
                    "nl": " megawatt"
 | 
			
		||||
                },
 | 
			
		||||
                "default": true
 | 
			
		||||
            }, "test");
 | 
			
		||||
 | 
			
		||||
            const canonical = unit.canonicalValue("5")
 | 
			
		||||
            const canonical = denomintion.canonicalValue("5", true)
 | 
			
		||||
            expect(canonical).eq( "5 MW")
 | 
			
		||||
            const units = new Unit(["key"], [unit], false)
 | 
			
		||||
            const [detected, detectedDenom] = units.findDenomination("5 MW")
 | 
			
		||||
            const units = new Unit(["key"], [denomintion], false)
 | 
			
		||||
            const [detected, detectedDenom] = units.findDenomination("5 MW", () => "be")
 | 
			
		||||
            expect(detected).eq( "5")
 | 
			
		||||
            expect(detectedDenom).eq( unit)
 | 
			
		||||
            expect(detectedDenom).eq( denomintion)
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||