forked from MapComplete/MapComplete
		
	Small improvements to units
This commit is contained in:
		
							parent
							
								
									e9df77db58
								
							
						
					
					
						commit
						89c5c78f41
					
				
					 3 changed files with 46 additions and 10 deletions
				
			
		| 
						 | 
					@ -7,14 +7,31 @@ import Combine from "../../UI/Base/Combine";
 | 
				
			||||||
export class Unit {
 | 
					export class Unit {
 | 
				
			||||||
    public readonly appliesToKeys: Set<string>;
 | 
					    public readonly appliesToKeys: Set<string>;
 | 
				
			||||||
    public readonly denominations: Denomination[];
 | 
					    public readonly denominations: Denomination[];
 | 
				
			||||||
 | 
					    public readonly denominationsSorted: Denomination[];
 | 
				
			||||||
    public readonly defaultDenom: Denomination;
 | 
					    public readonly defaultDenom: Denomination;
 | 
				
			||||||
    public readonly eraseInvalid : boolean;
 | 
					    public readonly eraseInvalid: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(appliesToKeys: string[], applicableUnits: Denomination[], eraseInvalid: boolean) {
 | 
					    constructor(appliesToKeys: string[], applicableUnits: Denomination[], eraseInvalid: boolean) {
 | 
				
			||||||
        this.appliesToKeys = new Set(appliesToKeys);
 | 
					        this.appliesToKeys = new Set(appliesToKeys);
 | 
				
			||||||
        this.denominations = applicableUnits;
 | 
					        this.denominations = applicableUnits;
 | 
				
			||||||
        this.defaultDenom = applicableUnits.filter(denom => denom.default)[0]
 | 
					        this.defaultDenom = applicableUnits.filter(denom => denom.default)[0]
 | 
				
			||||||
        this.eraseInvalid = eraseInvalid
 | 
					        this.eraseInvalid = eraseInvalid
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const seenUnitExtensions = new Set<string>();
 | 
				
			||||||
 | 
					        for (const denomination of this.denominations) {
 | 
				
			||||||
 | 
					            if(seenUnitExtensions.has(denomination.canonical)){
 | 
				
			||||||
 | 
					                throw "This canonical unit is already defined in another denomination: "+denomination.canonical
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const duplicate = denomination.alternativeDenominations.filter(denom => seenUnitExtensions.has(denom))
 | 
				
			||||||
 | 
					            if(duplicate.length > 0){
 | 
				
			||||||
 | 
					                throw "A denomination is used multiple times: "+duplicate.join(", ")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            seenUnitExtensions.add(denomination.canonical)
 | 
				
			||||||
 | 
					            denomination.alternativeDenominations.forEach(d => seenUnitExtensions.add(d))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.denominationsSorted = [...this.denominations]
 | 
				
			||||||
 | 
					        this.denominationsSorted.sort((a, b) => b.canonical.length - a.canonical.length)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isApplicableToKey(key: string | undefined): boolean {
 | 
					    isApplicableToKey(key: string | undefined): boolean {
 | 
				
			||||||
| 
						 | 
					@ -29,7 +46,10 @@ export class Unit {
 | 
				
			||||||
     * Finds which denomination is applicable and gives the stripped value back
 | 
					     * Finds which denomination is applicable and gives the stripped value back
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    findDenomination(valueWithDenom: string): [string, Denomination] {
 | 
					    findDenomination(valueWithDenom: string): [string, Denomination] {
 | 
				
			||||||
        for (const denomination of this.denominations) {
 | 
					        if(valueWithDenom === undefined){
 | 
				
			||||||
 | 
					            return undefined;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (const denomination of this.denominationsSorted) {
 | 
				
			||||||
            const bare = denomination.StrippedValue(valueWithDenom)
 | 
					            const bare = denomination.StrippedValue(valueWithDenom)
 | 
				
			||||||
            if (bare !== null) {
 | 
					            if (bare !== null) {
 | 
				
			||||||
                return [bare, denomination]
 | 
					                return [bare, denomination]
 | 
				
			||||||
| 
						 | 
					@ -56,12 +76,12 @@ export class Denomination {
 | 
				
			||||||
    readonly default: boolean;
 | 
					    readonly default: boolean;
 | 
				
			||||||
    readonly prefix: boolean;
 | 
					    readonly prefix: boolean;
 | 
				
			||||||
    private readonly _human: Translation;
 | 
					    private readonly _human: Translation;
 | 
				
			||||||
    private readonly alternativeDenominations: string [];
 | 
					    public readonly alternativeDenominations: string [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(json: UnitConfigJson, context: string) {
 | 
					    constructor(json: UnitConfigJson, context: string) {
 | 
				
			||||||
        context = `${context}.unit(${json.canonicalDenomination})`
 | 
					        context = `${context}.unit(${json.canonicalDenomination})`
 | 
				
			||||||
        this.canonical = json.canonicalDenomination.trim()
 | 
					        this.canonical = json.canonicalDenomination.trim()
 | 
				
			||||||
        if ((this.canonical ?? "") === "") {
 | 
					        if (this.canonical === undefined) {
 | 
				
			||||||
            throw `${context}: this unit has no decent canonical value defined`
 | 
					            throw `${context}: this unit has no decent canonical value defined`
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,6 +129,7 @@ export class Denomination {
 | 
				
			||||||
            return undefined;
 | 
					            return undefined;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        value = value.toLowerCase()
 | 
				
			||||||
        if (this.prefix) {
 | 
					        if (this.prefix) {
 | 
				
			||||||
            if (value.startsWith(this.canonical)) {
 | 
					            if (value.startsWith(this.canonical)) {
 | 
				
			||||||
                return value.substring(this.canonical.length).trim();
 | 
					                return value.substring(this.canonical.length).trim();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -354,8 +354,14 @@ export default class TagRenderingQuestion extends UIElement {
 | 
				
			||||||
            input = new CombinedInputElement(
 | 
					            input = new CombinedInputElement(
 | 
				
			||||||
                input,
 | 
					                input,
 | 
				
			||||||
                unitDropDown,
 | 
					                unitDropDown,
 | 
				
			||||||
                (text, denom) => denom?.canonicalValue(text, true) ?? text,
 | 
					                (text, denom) => {
 | 
				
			||||||
                (valueWithDenom: string) => unit.findDenomination(valueWithDenom)
 | 
					                    console.log("text:", text, "denom:", denom, "canon: ",denom?.canonicalValue(text, true))
 | 
				
			||||||
 | 
					                    return denom?.canonicalValue(text, true) ?? text;
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                (valueWithDenom: string) => {
 | 
				
			||||||
 | 
					                    console.log("ToSplit: ", valueWithDenom, "becomes", unit.findDenomination(valueWithDenom))
 | 
				
			||||||
 | 
					                    return unit.findDenomination(valueWithDenom) ?? [valueWithDenom, undefined];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            ).SetClass("flex")
 | 
					            ).SetClass("flex")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -842,12 +842,15 @@
 | 
				
			||||||
  "units": [
 | 
					  "units": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "appliesToKey": [
 | 
					      "appliesToKey": [
 | 
				
			||||||
        "climbing:length"
 | 
					        "climbing:length",
 | 
				
			||||||
 | 
					        "climbing:length:min",
 | 
				
			||||||
 | 
					        "climbing:length:max"
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "applicableUnits": [
 | 
					      "applicableUnits": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "canonicalDenomination": "m",
 | 
					          "canonicalDenomination": "",
 | 
				
			||||||
          "alternativeDenomination": [
 | 
					          "alternativeDenomination": [
 | 
				
			||||||
 | 
					            "m",
 | 
				
			||||||
            "meter",
 | 
					            "meter",
 | 
				
			||||||
            "meters"
 | 
					            "meters"
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
| 
						 | 
					@ -1363,7 +1366,7 @@
 | 
				
			||||||
  "overrideAll": {
 | 
					  "overrideAll": {
 | 
				
			||||||
    "titleIcons": [
 | 
					    "titleIcons": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "render": "<div style='display:block ruby;' class='m-1 '><img src='./assets/themes/climbing/height.svg' style='width:2rem; height:2rem'/>{climbing:length}</div>",
 | 
					        "render": "<div style='display:block ruby;' class='m-1 '><img src='./assets/themes/climbing/height.svg' style='width:2rem; height:2rem'/>{climbing:length}m</div>",
 | 
				
			||||||
        "freeform": {
 | 
					        "freeform": {
 | 
				
			||||||
          "key": "climbing:length"
 | 
					          "key": "climbing:length"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1372,7 +1375,13 @@
 | 
				
			||||||
        "render": "<div style='display:block ruby;' class='m-1 '><img src='./assets/themes/climbing/carabiner.svg' style='width:2rem; height:2rem'/>{climbing:bolted}</div>",
 | 
					        "render": "<div style='display:block ruby;' class='m-1 '><img src='./assets/themes/climbing/carabiner.svg' style='width:2rem; height:2rem'/>{climbing:bolted}</div>",
 | 
				
			||||||
        "freeform": {
 | 
					        "freeform": {
 | 
				
			||||||
          "key": "climbing:bolted"
 | 
					          "key": "climbing:bolted"
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        "mappings": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "if": "climbing:bolted=yes",
 | 
				
			||||||
 | 
					            "then": "<img src='./assets/themes/climbing/carabiner.svg' style='width:2rem; height:2rem'/>"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "defaults"
 | 
					      "defaults"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue