forked from MapComplete/MapComplete
Rework units to allow picking different default units in different locations, fixes #1011
This commit is contained in:
parent
e981abd2aa
commit
5da76b9418
17 changed files with 149 additions and 100 deletions
|
@ -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
|
||||
}
|
||||
|
||||
// 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(", ")}`
|
||||
if(json.applicableUnits.some(denom => denom.useAsDefaultInput !== undefined)){
|
||||
json.applicableUnits.forEach(denom => {
|
||||
denom.useAsDefaultInput = denom.useAsDefaultInput ?? false
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (const denominationPart of this.possiblePostFixes) {
|
||||
if (str.endsWith(denominationPart)) {
|
||||
return str.substring(0, str.length - denominationPart.length).trim()
|
||||
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 str;
|
||||
return this.denominations[0]
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue