@qudtlib/core
Version:
Data model for QUDTLib
1 lines • 13.5 kB
Source Map (JSON)
{"version":3,"sources":["unit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,qBAAa,IAAK,YAAW,cAAc,CAAC,IAAI,CAAC;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;IAC9B,QAAQ,CAAC,YAAY,qBAAC;IACtB,QAAQ,CAAC,cAAc,qBAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,YAAY,EAAE,CAAM;IAC5C,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,WAAW,EAAE,WAAW,CAAuB;IAE/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAA2B;gBAE9D,GAAG,EAAE,MAAM,EACX,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,EACzB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,oBAAoB,CAAC,EAAE,OAAO,EAC9B,gBAAgB,CAAC,EAAE,OAAO,EAC1B,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,IAAI,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,UAAU,EAAE,EACrB,YAAY,CAAC,EAAE,MAAM,EACrB,cAAc,CAAC,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,OAAO,EACpB,SAAS,CAAC,EAAE,OAAO;IA6CrB,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,OAAO;IAI7B,QAAQ,IAAI,MAAM;IAUlB,eAAe,IAAI,MAAM;IAIzB,iBAAiB,IAAI,MAAM;IAI3B,cAAc,IAAI,OAAO;IAIzB,qBAAqB,CAAC,GAAG,cAAc,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAAG,OAAO;IAIpE,OAAO,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO;IAMxC,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,oBAAoB,IAAI,OAAO;IAI/B,QAAQ,IAAI,OAAO;IAInB,SAAS,IAAI,OAAO;IAGpB,aAAa,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO;IAIpC,uBAAuB,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO;IAgB9C,OAAO,CAAC,sBAAsB;IAW9B,aAAa,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO;IAYnC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAItC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO;IA6C3E,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAIjC,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI;IAGjD,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAI7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK/D,eAAe,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAIjD,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAI9C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAM/B,YAAY,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI;IAMnC;;;;OAIG;IACH,SAAS,IAAI,WAAW;IAcxB,yCAAyC,IAAI,UAAU,EAAE;IAWzD,oCAAoC,IAAI,UAAU,EAAE,EAAE;IAqB/C,uBAAuB,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO;IAY7C,0BAA0B,IAAI,OAAO;CAG7C","file":"unit.d.ts","sourcesContent":["import { SupportsEquals } from \"./baseTypes.js\";\nimport { LangString } from \"./langString.js\";\nimport { Prefix } from \"./prefix.js\";\nimport { QuantityKind } from \"./quantityKind.js\";\nimport { FactorUnit } from \"./factorUnit.js\";\nimport { arrayContains, getLastIriElement, isNullish, ZERO } from \"./utils.js\";\nimport { FactorUnits } from \"./factorUnits.js\";\nimport { Decimal } from \"decimal.js\";\nimport { QudtNamespaces } from \"./qudtNamespaces.js\";\n\nexport class Unit implements SupportsEquals<Unit> {\n readonly iri: string;\n readonly labels: LangString[];\n readonly currencyCode;\n readonly currencyNumber;\n readonly prefixIri?: string;\n prefix?: Prefix;\n readonly conversionMultiplier: Decimal;\n readonly conversionOffset: Decimal;\n readonly quantityKindIris: string[];\n readonly quantityKinds: QuantityKind[] = [];\n readonly exactMatchIris: string[];\n readonly symbol?: string;\n readonly dependents: number;\n readonly deprecated: boolean;\n readonly generated: boolean;\n readonly scalingOfIri?: string;\n scalingOf?: Unit;\n readonly dimensionVectorIri?: string;\n factorUnits: FactorUnits = FactorUnits.empty();\n\n readonly unitOfSystemIris: string[];\n private static TEMPERATURE_DIFFERENCE = \"TemperatureDifference\";\n constructor(\n iri: string,\n quantityKindIris?: string[],\n exactMatchIris?: string[],\n dimensionVectorIri?: string,\n conversionMultiplier?: Decimal,\n conversionOffset?: Decimal,\n prefixIri?: string,\n scalingOfIri?: string,\n scalingOf?: Unit,\n symbol?: string,\n labels?: LangString[],\n currencyCode?: string,\n currencyNumber?: number,\n unitOfSystemIris?: string[],\n dependents?: number,\n deprecated?: boolean,\n generated?: boolean\n ) {\n this.iri = iri;\n this.prefixIri = prefixIri;\n this.conversionMultiplier =\n typeof conversionMultiplier === \"undefined\"\n ? new Decimal(\"1.0\")\n : conversionMultiplier;\n this.conversionOffset =\n typeof conversionOffset === \"undefined\"\n ? new Decimal(\"0.0\")\n : conversionOffset;\n this.symbol = symbol;\n this.scalingOfIri = scalingOfIri;\n this.scalingOf = scalingOf;\n this.dimensionVectorIri = dimensionVectorIri;\n this.prefix = undefined;\n if (typeof quantityKindIris === \"undefined\") {\n this.quantityKindIris = [];\n } else {\n this.quantityKindIris = quantityKindIris;\n }\n if (typeof exactMatchIris === \"undefined\") {\n this.exactMatchIris = [];\n } else {\n this.exactMatchIris = exactMatchIris;\n }\n if (typeof labels === \"undefined\") {\n this.labels = [];\n } else {\n this.labels = labels;\n }\n this.currencyCode = currencyCode;\n this.currencyNumber = currencyNumber;\n if (typeof unitOfSystemIris === \"undefined\") {\n this.unitOfSystemIris = [];\n } else {\n this.unitOfSystemIris = unitOfSystemIris;\n }\n this.factorUnits = FactorUnits.ofUnit(this); //might be replaced later by this.setFactorUnits().\n this.dependents = dependents ?? 0;\n this.deprecated = deprecated ?? false;\n this.generated = generated ?? false;\n }\n\n equals(other?: Unit): boolean {\n return !!other && this.iri === other.iri;\n }\n\n toString(): string {\n if (this.symbol) {\n return this.symbol;\n }\n if (this.scalingOf?.symbol && this.prefix?.symbol) {\n return this.prefix.symbol + this.scalingOf.symbol;\n }\n return \"unit:\" + getLastIriElement(this.iri);\n }\n\n getIriLocalname(): string {\n return getLastIriElement(this.iri);\n }\n\n getIriAbbreviated(): string {\n return QudtNamespaces.unit.abbreviate(this.iri);\n }\n\n isCurrencyUnit(): boolean {\n return this.getIriLocalname().startsWith(\"CCY_\");\n }\n\n matchesFactorUnitSpec(...factorUnitSpec: (number | Unit)[]): boolean {\n return this.matches(FactorUnits.ofFactorUnitSpec(...factorUnitSpec));\n }\n\n matches(selection: FactorUnits): boolean {\n const thisNormalized: FactorUnits = this.normalize();\n const selectionNormalized: FactorUnits = selection.normalize();\n return thisNormalized.equals(selectionNormalized);\n }\n\n hasFactorUnits(): boolean {\n return this.factorUnits.hasFactorUnits();\n }\n\n /**\n * Returns true if this unit is defined to be another unit, such as litre is defined as cubic decimetre.\n */\n isDefinedAsOtherUnit(): boolean {\n return this.factorUnits.isOneOtherUnitWithExponentOne();\n }\n\n isScaled(): boolean {\n return !!this.scalingOfIri;\n }\n\n hasSymbol(): boolean {\n return typeof this.symbol !== \"undefined\";\n }\n isConvertible(toUnit: Unit): boolean {\n return this.dimensionVectorIri === toUnit.dimensionVectorIri;\n }\n\n getConversionMultiplier(toUnit: Unit): Decimal {\n if (this.equals(toUnit)) {\n return new Decimal(1);\n }\n if (this.conversionOffsetDiffers(toUnit)) {\n throw `Cannot convert from ${this} to ${toUnit} just by multiplication as their conversion offsets differ`;\n }\n const fromMultiplier = this.conversionMultiplier\n ? this.conversionMultiplier\n : new Decimal(1);\n const toMultiplier = toUnit.conversionMultiplier\n ? toUnit.conversionMultiplier\n : new Decimal(1);\n return fromMultiplier.div(toMultiplier);\n }\n\n private findInBasesRecursively(toFind: Unit): boolean {\n if (!this.isScaled()) {\n return this.equals(toFind);\n }\n if (!!this.scalingOf) {\n return this.scalingOf.findInBasesRecursively(toFind);\n } else {\n throw `No base unit found for ${this} - this is a bug`;\n }\n }\n\n isSameScaleAs(other: Unit): boolean {\n if (this.equals(other)) {\n return true;\n }\n if (!!this.scalingOfIri && this.scalingOfIri === other.scalingOfIri) {\n return true;\n }\n return (\n this.findInBasesRecursively(other) || other.findInBasesRecursively(this)\n );\n }\n\n static isUnitless(unit: Unit): boolean {\n return unit.iri === \"http://qudt.org/vocab/unit/UNITLESS\";\n }\n\n convert(value: Decimal, toUnit: Unit, quantityKind?: QuantityKind): Decimal {\n if (isNullish(value)) {\n throw \"Parameter 'value' is required\";\n }\n if (isNullish(toUnit)) {\n throw \"Parameter 'toUnit' is required\";\n }\n let ignoreOffset = false;\n if (!isNullish(quantityKind)) {\n if (quantityKind?.getIriLocalname() === Unit.TEMPERATURE_DIFFERENCE) {\n ignoreOffset = true;\n }\n }\n if (this.equals(toUnit)) {\n return value;\n }\n if (Unit.isUnitless(this) || Unit.isUnitless(toUnit)) {\n return value;\n }\n if (!this.isConvertible(toUnit)) {\n throw `Not convertible: ${this} -> ${toUnit}`;\n }\n const fromOffset = ignoreOffset\n ? ZERO\n : this.conversionOffset\n ? this.conversionOffset\n : ZERO;\n const fromMultiplier = this.conversionMultiplier\n ? this.conversionMultiplier\n : new Decimal(1);\n const toOffset = ignoreOffset\n ? ZERO\n : toUnit.conversionOffset\n ? toUnit.conversionOffset\n : ZERO;\n const toMultiplier = toUnit.conversionMultiplier\n ? toUnit.conversionMultiplier\n : new Decimal(1);\n return value\n .add(fromOffset)\n .mul(fromMultiplier)\n .div(toMultiplier)\n .minus(toOffset);\n }\n\n addLabel(label: LangString): void {\n this.labels.push(label);\n }\n\n addQuantityKindIri(quantityKindIri: string): void {\n this.quantityKindIris.push(quantityKindIri);\n }\n addExactMatchIri(exactMatchIri: string): void {\n this.exactMatchIris.push(exactMatchIri);\n }\n\n hasLabel(label: string): boolean {\n return this.labels.some((l) => label === l.text);\n }\n\n getLabelForLanguageTag(languageTag: string): string | undefined {\n const label = this.labels.find((l) => languageTag === l.languageTag);\n return label?.text;\n }\n\n addQuantityKind(quantityKind: QuantityKind): void {\n this.quantityKinds.push(quantityKind);\n }\n\n setFactorUnits(factorUnits: FactorUnits): void {\n this.factorUnits = factorUnits;\n }\n\n setPrefix(prefix: Prefix): void {\n if (prefix.iri !== this.prefixIri)\n throw \"prefix.iri does not equal this.prefixIri\";\n this.prefix = prefix;\n }\n\n setScalingOf(scalingOf: Unit): void {\n if (scalingOf.iri !== this.scalingOfIri)\n throw \"scalingOf.iri does not equal this.scalingOfIri\";\n this.scalingOf = scalingOf;\n }\n\n /**\n * Returns this unit as a set of exponent-reduced factors, unless they are two factors that cancel each other out, in\n * which case return the unit as a factor unit with exponent 1. For example, Steradian is m²/m² and will\n * therefore return SR.\n */\n normalize(): FactorUnits {\n if (this.hasFactorUnits()) {\n return this.factorUnits.normalize();\n } else if (\n this.scalingOf !== null &&\n typeof this.scalingOf !== \"undefined\"\n ) {\n return this.scalingOf\n .normalize()\n .scale(this.getConversionMultiplier(this.scalingOf));\n }\n return this.factorUnits;\n }\n\n getLeafFactorUnitsWithCumulativeExponents(): FactorUnit[] {\n if (this.hasFactorUnits()) {\n const result = this.factorUnits.factorUnits.flatMap((fu) =>\n fu.getLeafFactorUnitsWithCumulativeExponents()\n );\n return result;\n } else {\n return [FactorUnit.ofUnit(this)];\n }\n }\n\n getAllPossibleFactorUnitCombinations(): FactorUnit[][] {\n if (!this.hasFactorUnits()) {\n if (!!this.scalingOf) {\n return this.scalingOf.getAllPossibleFactorUnitCombinations();\n }\n return [[FactorUnit.ofUnit(this)]];\n }\n const result = FactorUnit.getAllPossibleFactorUnitCombinations(\n this.factorUnits.factorUnits\n );\n const thisAsResult = [FactorUnit.ofUnit(this)];\n if (\n !arrayContains(result, thisAsResult, (l, r) =>\n l.every((le) => r.some((re) => le.equals(re)))\n )\n ) {\n result.push(thisAsResult);\n }\n return result;\n }\n\n public conversionOffsetDiffers(other: Unit): boolean {\n if (\n this.hasNonzeroConversionOffset() &&\n other.hasNonzeroConversionOffset()\n ) {\n if (!!this.conversionOffset && !!other.conversionOffset) {\n return !this.conversionOffset.eq(other.conversionOffset);\n }\n }\n return false;\n }\n\n public hasNonzeroConversionOffset(): boolean {\n return !!this.conversionOffset && !this.conversionOffset.eq(ZERO);\n }\n}\n"]}