{"version":3,"sources":["unit.ts"],"names":[],"mappings":"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","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 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  ) {\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  }\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 this.isCurrencyUnit()\n      ? QudtNamespaces.currency.abbreviate(this.iri)\n      : QudtNamespaces.unit.abbreviate(this.iri);\n  }\n\n  isCurrencyUnit(): boolean {\n    return QudtNamespaces.currency.isFullNamespaceIri(this.iri);\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"]}