New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@qudtlib/core

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@qudtlib/core - npm Package Compare versions

Comparing version 2.0.0-preview3 to 2.0.0

1086

dist/cjs/qudtlib.js

@@ -1,2 +0,1084 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Qudt=exports.QUDT_PREFIX_BASE_IRI=exports.QUDT_QUANTITYKIND_BASE_IRI=exports.QUDT_UNIT_BASE_IRI=exports.Unit=exports.FactorUnitSelection=exports.FactorUnitSelector=exports.FactorUnitMatch=exports.FactorUnit=exports.FactorUnitMatchingMode=exports.DerivedUnitSearchMode=exports.QuantityKind=exports.QuantityValue=exports.Prefix=exports.ScaleFactor=exports.LangString=exports.config=exports.QudtlibConfig=void 0;const decimal_js_1=require("decimal.js");class QudtlibConfig{constructor(){this.units=new Map,this.quantityKinds=new Map,this.prefixes=new Map}}exports.QudtlibConfig=QudtlibConfig,exports.config=new QudtlibConfig;class LangString{constructor(t,i){this.text=t,this.languageTag=i}equals(t){return!!t&&this.text===t.text&&this.languageTag===t.languageTag}toString(){return this.text+(this.languageTag?"@"+this.languageTag:"")}}exports.LangString=LangString;class ScaleFactor{constructor(t=new decimal_js_1.Decimal(1)){this.factor=t}copy(){return new ScaleFactor(this.factor)}multiplyBy(t){return new ScaleFactor(this.factor.mul(t))}toString(){return""+this.factor.toString()}equals(t){return!!t&&this.factor===t.factor}}exports.ScaleFactor=ScaleFactor;class Prefix{constructor(t,i,e,n,r){this.iri=t,this.multiplier=i,this.symbol=e,this.ucumCode=n,this.labels=void 0===r?[]:r}equals(t){return!!t&&this.iri===t.iri&&this.multiplier.equals(t.multiplier)&&this.symbol===t.symbol&&this.ucumCode===t.ucumCode&&this.labels.length==t.labels.length&&arrayEquals(this.labels,t.labels,compareUsingEquals)}toString(){return this.symbol||"prefix:"+getLastIriElement(this.iri)}addLabel(t){this.labels.push(t)}}exports.Prefix=Prefix;class QuantityValue{constructor(t,i){this.quantity=t,this.unit=i}equals(t){return!!t&&this.quantity.equals(t.quantity)&&this.unit.equals(t.unit)}toString(){return this.quantity.toString()+this.unit.toString()}}exports.QuantityValue=QuantityValue;class QuantityKind{constructor(t,i,e,n){this.iri=t,this.applicableUnitIris=[],this.broaderQuantityKindIris=[],this.dimensionVectorIri=i,this.symbol=e,this.labels=void 0===n?[]:n}addLabel(t){this.labels.push(t)}hasLabel(i){return this.labels.some(t=>i===t.text)}getLabelForLanguageTag(i){return this.labels.find(t=>i===t.languageTag)?.text}addApplicableUnitIri(t){this.applicableUnitIris.push(t)}addBroaderQuantityKindIri(t){this.broaderQuantityKindIris.push(t)}equals(t){return!!t&&this.iri===t.iri}toString(){return this.symbol||"quantityKind:"+getLastIriElement(this.iri)}}function checkInteger(t,i){if(!Number.isInteger(t))throw i+` must be integer, ${t} (type ${typeof t}) is not`}var DerivedUnitSearchMode,FactorUnitMatchingMode;exports.QuantityKind=QuantityKind,function(t){t[t.EXACT=0]="EXACT",t[t.EXACT_ONLY_ONE=1]="EXACT_ONLY_ONE",t[t.ALLOW_SCALED=2]="ALLOW_SCALED",t[t.BEST_EFFORT_ONLY_ONE=3]="BEST_EFFORT_ONLY_ONE"}(DerivedUnitSearchMode=exports.DerivedUnitSearchMode||(exports.DerivedUnitSearchMode={})),function(t){t[t.EXACT=0]="EXACT",t[t.ALLOW_SCALED=1]="ALLOW_SCALED"}(FactorUnitMatchingMode=exports.FactorUnitMatchingMode||(exports.FactorUnitMatchingMode={}));class FactorUnit{constructor(t,i){checkInteger(i,"exponent"),this.exponent=i,this.unit=t}withExponentMultiplied(t){return checkInteger(t,"by"),new FactorUnit(this.unit,this.exponent*t)}getExponentCumulated(t){return checkInteger(t,"cumulatedExponent"),this.exponent*t}equals(t){return!!t&&this.exponent===t.exponent&&this.unit.equals(t.unit)}toString(){return this.unit.toString()+"^"+this.exponent}static combine(t,i){if(t.getKind()!==i.getKind())throw`Cannot combine UnitFactors of different kind (left: ${t}, right: `+i;return new FactorUnit(t.unit,t.exponent+i.exponent)}getKind(){return this.unit.iri+(0===this.exponent?"0":0<this.exponent?"1":"-1")}match(t,i,e,n,r){const a=[];return t.forEach(t=>a.push(t)),this.unit.match(a,this.getExponentCumulated(i),e,n,r)}getLeafFactorUnitsWithCumulativeExponents(){var t=this.unit.getLeafFactorUnitsWithCumulativeExponents();return t?.length?t.map(t=>t.withExponentMultiplied(this.exponent)):[this]}}exports.FactorUnit=FactorUnit;class FactorUnitMatch{constructor(t,i,e,n){this.matchedFactorUnit=t,this.matchedMultiplier=i,this.matchedPath=[...e],this.scaleFactor=n}equals(t){return!!t&&this.matchedFactorUnit.equals(t.matchedFactorUnit)&&arrayEquals(this.matchedPath,t.matchedPath,compareUsingEquals)&&this.matchedMultiplier.eq(t.matchedMultiplier)&&this.scaleFactor.equals(t.scaleFactor)}toString(){return this.getPathAsString()+(this.matchedMultiplier.eq(new decimal_js_1.Decimal(1))?"":"*"+this.matchedMultiplier.toString())+(this.scaleFactor.factor.eq(new decimal_js_1.Decimal(1))?"":"*"+this.scaleFactor.toString())}getPathAsString(){let t="/";return this.matchedPath&&(t+=this.matchedPath.map(t=>t.toString()).reduce((t,i)=>t+"/"+i)),t}}exports.FactorUnitMatch=FactorUnitMatch;class FactorUnitSelector{constructor(t,i,e){this.unit=t,this.exponent=i,this.factorUnitMatch=e}equals(t){return!!t&&this.exponent===t.exponent&&this.unit.equals(t.unit)&&(this.factorUnitMatch===t.factorUnitMatch||!!this.factorUnitMatch&&this.factorUnitMatch.equals(t.factorUnitMatch))}isAvailable(){return!this.isBound()}isBound(){return!!this.factorUnitMatch}copy(){return new FactorUnitSelector(this.unit,this.exponent,this.factorUnitMatch)}matched(t){return new FactorUnitSelector(this.unit,this.exponent,t)}matches(t,i,e){switch(e){case FactorUnitMatchingMode.EXACT:return this.unit.equals(t.unit)&&this.exponentMatches(t,i);case FactorUnitMatchingMode.ALLOW_SCALED:return this.unit.isSameScaleAs(t.unit)&&this.exponentMatches(t,i)}throw"Cannot handle matching mode "+e}exponentMatches(t,i){t=t.getExponentCumulated(i);return 0<Math.abs(this.exponent)&&Math.abs(this.exponent)>=Math.abs(t)&&Math.sign(this.exponent)===Math.sign(t)}forMatch(t,i,e,n){if(!this.isAvailable())throw"not available - selector is already bound";if(checkInteger(i,"cumulativeExponent"),!this.exponentMatches(t,i))throw"exponents do not match";var r,i=t.getExponentCumulated(i),a=this.calculateMatchedMultiplier(t,i);if(a)return i=this.exponent-i,(r=[]).push(this.matched(new FactorUnitMatch(t,a,e,n))),0!=i&&r.push(new FactorUnitSelector(this.unit,i)),r;throw"units do not match"}calculateMatchedMultiplier(t,i){if(this.unit.isConvertible(t.unit))return t.unit.getConversionMultiplier(this.unit).pow(i)}toString(){return this.unit.toString()+(1===this.exponent?"":"^"+this.exponent)+"@"+(this.factorUnitMatch?this.factorUnitMatch.toString():"?")}}exports.FactorUnitSelector=FactorUnitSelector;class FactorUnitSelection{constructor(t){this.selectors=t}static fromFactorUnitSpec(...i){if(i.length%2!=0)throw"An even number of arguments is required";if(14<i.length)throw"No more than 14 arguments (7 factor units) are supported";var e=[];for(let t=0;t<i.length;t+=2){var n=i[t],r=i[t+1];if(!(n instanceof Unit))throw`argument at 0-based position ${t} is not of type Unit. The input must be between 1 and 7 Unit, exponent pairs`;if("number"!=typeof r||!Number.isInteger(r))throw`argument at 0-based position ${t+1} is not of type number or not an integer. The input must be between 1 and 7 Unit, exponent pairs`;e.push(new FactorUnitSelector(n,r))}return new FactorUnitSelection(e)}equals(t){return!!t&&arrayEquals(this.selectors,t.selectors,compareUsingEquals)}toString(){return"Select ["+this.selectors.map(t=>t.toString()).reduce((t,i)=>t+", "+i)+"]"}isCompleteMatch(){var t,i;return!!this.selectors.every(t=>t.isBound())&&(t=this.selectors.reduce((t,i)=>i.factorUnitMatch?i.factorUnitMatch.scaleFactor.factor.mul(t):t,new decimal_js_1.Decimal("1")),i=this.selectors.reduce((t,i)=>i.factorUnitMatch?i.factorUnitMatch.matchedMultiplier.mul(t):t,new decimal_js_1.Decimal("1")),t.mul(i).eq(new decimal_js_1.Decimal("1")))}forPotentialMatch(t,i,e,n,r){const a=[];let s=!1;for(const o of this.selectors)!s&&o.isAvailable()&&o.matches(t,i,r)?(s=!0,o.forMatch(t,i,e,n).forEach(t=>a.push(t))):a.push(o.copy());return new FactorUnitSelection(a)}}exports.FactorUnitSelection=FactorUnitSelection;class Unit{constructor(t,i,e,n,r,a,s,o,c,u){this.quantityKinds=[],this.factorUnits=[],this.iri=t,this.prefixIri=a,this.conversionMultiplier=n,this.conversionOffset=r,this.symbol=c,this.scalingOfIri=s,this.scalingOf=o,this.dimensionVectorIri=e,this.prefix=void 0,this.quantityKindIris=void 0===i?[]:i,this.labels=void 0===u?[]:u}equals(t){return!!t&&this.iri===t.iri}toString(){return this.symbol||(this.scalingOf?.symbol&&this.prefix?.symbol?this.prefix.symbol+this.scalingOf.symbol:"unit:"+getLastIriElement(this.iri))}match(t,i,e,n,r){checkInteger(i,"cumulativeExponent");const a=[];return e.push(this),this.hasFactorUnits()?this.matchFactorUnits(t,i,e,n,r).forEach(t=>a.push(t)):this.scalingOf&&this.prefix&&this.scalingOf.hasFactorUnits()&&this.scalingOf.match(t,i,e,n.multiplyBy(this.prefix.multiplier),r).forEach(t=>a.push(t)),this.matchThisUnit(t,i,e,n,r).forEach(t=>a.push(t)),e.pop(),a}matchFactorUnits(t,i,e,n,r){let a=t,s=t;for(const o of this.factorUnits){if(arrayEquals(s=o.match(a,i,e,n,r),a))return t;a=s}return s}matchThisUnit(t,i,e,n,r){var a=[];for(const o of t){var s=o.forPotentialMatch(new FactorUnit(this,1),i,e,n,r);s.equals(o)||a.push(s)}return a}matchesFactorUnitSpec(...t){return this.matches(FactorUnitSelection.fromFactorUnitSpec(...t))}matches(t,i=FactorUnitMatchingMode.EXACT){t=this.match([t],1,[],new ScaleFactor,i);return!(!t||0==t.length)&&t.some(t=>t.isCompleteMatch())}hasFactorUnits(){return this.factorUnits&&0<this.factorUnits.length}isScaled(){return!!this.scalingOfIri}isConvertible(t){return this.dimensionVectorIri===t.dimensionVectorIri}getConversionMultiplier(t){if(this.equals(t))return new decimal_js_1.Decimal(1);if(this.conversionOffset||t.conversionOffset)throw`Cannot convert from ${this} to ${t} just by multiplication, one of them has a conversion offset!`;var i=this.conversionMultiplier||new decimal_js_1.Decimal(1),t=t.conversionMultiplier||new decimal_js_1.Decimal(1);return i.div(t)}findInBasesRecursively(t){if(!this.isScaled())return this.equals(t);if(this.scalingOf)return this.scalingOf.findInBasesRecursively(t);throw`No base unit found for ${this} - this is a bug`}isSameScaleAs(t){return!!this.equals(t)||(!(!this.scalingOfIri||this.scalingOfIri!==t.scalingOfIri)||(this.findInBasesRecursively(t)||t.findInBasesRecursively(this)))}static isUnitless(t){return"http://qudt.org/vocab/unit/UNITLESS"===t.iri}convert(t,i){if(!t)throw"Parameter 'value' is required";if(!i)throw"Parameter 'toUnit' is required";if(this.equals(i))return t;if(Unit.isUnitless(this)||Unit.isUnitless(i))return t;var e,n,r,a;if(this.isConvertible(i))return e=this.conversionOffset||new decimal_js_1.Decimal(0),n=this.conversionMultiplier||new decimal_js_1.Decimal(1),r=i.conversionOffset||new decimal_js_1.Decimal(0),a=i.conversionMultiplier||new decimal_js_1.Decimal(1),t.add(e).mul(n).div(a).minus(r);throw`Not convertible: ${this} -> `+i}addLabel(t){this.labels.push(t)}addQuantityKindIri(t){this.quantityKindIris.push(t)}hasLabel(i){return this.labels.some(t=>i===t.text)}getLabelForLanguageTag(i){return this.labels.find(t=>i===t.languageTag)?.text}addQuantityKind(t){this.quantityKinds.push(t)}addFactorUnit(t){this.factorUnits.push(t)}setPrefix(t){if(t.iri!==this.prefixIri)throw"prefix.iri does not equal this.prefixIri";this.prefix=t}setScalingOf(t){if(t.iri!==this.scalingOfIri)throw"scalingOf.iri does not equal this.scalingOfIri";this.scalingOf=t}getLeafFactorUnitsWithCumulativeExponents(){return this.factorUnits?this.factorUnits.flatMap(t=>t.getLeafFactorUnitsWithCumulativeExponents()):[]}}function findInIterable(t,i){for(const e of t)if(i(e))return e}exports.Unit=Unit,exports.QUDT_UNIT_BASE_IRI="http://qudt.org/vocab/unit/",exports.QUDT_QUANTITYKIND_BASE_IRI="http://qudt.org/vocab/quantitykind/",exports.QUDT_PREFIX_BASE_IRI="http://qudt.org/vocab/prefix/";class Qudt{static unitFromLabel(t){const i=new CaseInsensitiveUnderscoreIgnoringLabelMatcher(t);return findInIterable(exports.config.units.values(),t=>i.matchesLangStrings(t.labels))}static unitFromLabelRequired(t){var i=this.unitFromLabel(t);if(i)return i;throw"No unit found for label "+t}static unitFromLocalname(t){return Qudt.unit(Qudt.unitIriFromLocalname(t))}static unitFromLocalnameRequired(t){return Qudt.unitRequired(Qudt.unitIriFromLocalname(t))}static quantityKindFromLocalname(t){return Qudt.quantityKind(Qudt.quantityKindIriFromLocalname(t))}static quantityKindFromLocalnameRequired(t){return Qudt.quantityKindRequired(Qudt.quantityKindIriFromLocalname(t))}static prefixFromLabelRequired(t){var i=this.prefixFromLabel(t);if(i)return i;throw"No prefix found for label "+t}static prefixFromLabel(t){const i=new CaseInsensitiveUnderscoreIgnoringLabelMatcher(t);return findInIterable(exports.config.prefixes.values(),t=>i.matchesLangStrings(t.labels))}static prefixFromLocalname(t){return Qudt.prefix(Qudt.prefixIriFromLocalname(t))}static prefixFromLocalnameRequired(t){return Qudt.prefixRequired(Qudt.prefixIriFromLocalname(t))}static unitIriFromLocalname(t){return exports.QUDT_UNIT_BASE_IRI+t}static quantityKindIriFromLocalname(t){return exports.QUDT_QUANTITYKIND_BASE_IRI+t}static prefixIriFromLocalname(t){return exports.QUDT_PREFIX_BASE_IRI+t}static unit(t){return exports.config.units.get(t)}static unitRequired(t){var i=Qudt.unit(t);if(void 0===i)throw`Unit ${t} not found`;return i}static quantityKind(t){return exports.config.quantityKinds.get(t)}static quantityKindRequired(t){var i=Qudt.quantityKind(t);if(void 0===i)throw`QuantityKind ${t} not found`;return i}static prefix(t){return exports.config.prefixes.get(t)}static prefixRequired(t){var i=Qudt.prefix(t);if(void 0===i)throw`Prefix ${t} not found`;return i}static quantityKinds(t){return t.quantityKindIris.map(t=>Qudt.quantityKindRequired(t))}static quantityKindsBroad(t){let i=Qudt.quantityKinds(t);const e=[];for(i.forEach(t=>e.push(t));i.length;)(i=i.flatMap(t=>t.broaderQuantityKindIris).map(t=>Qudt.quantityKindRequired(t))).forEach(t=>e.includes(t)||e.push(t));return e}static derivedUnitsFromMap(t,i){var e,n,r=[];for([e,n]of i.entries())r.push(e,n);return this.derivedUnitsFromExponentUnitPairs(t,...r)}static derivedUnitsFromFactorUnits(t,...i){i=i.flatMap(t=>[t.unit,t.exponent]);return this.derivedUnitsFromExponentUnitPairs(t,...i)}static derivedUnitsFromExponentUnitPairs(t,...e){var n=[];for(let i=0;i<e.length;i++){var r=e[i];if(i%2==0&&r instanceof Unit)n[i]=r;else if(i%2==0&&"string"==typeof r){var a=r;let t=Qudt.unit(a);if(void 0===(t=void 0===(t=void 0===t?Qudt.unitFromLocalname(a):t)?Qudt.unitFromLabel(a):t))throw`Unable to find unit for string ${a}, interpreted as iri, label or localname`;n[i]=t}else{if(i%2!=1||"number"!=typeof r)throw`Cannot handle input ${r} at 0-based position `+i;n[i]=r}}var i=FactorUnitSelection.fromFactorUnitSpec(...n);return Qudt.derivedUnitsFromFactorUnitSelection(t,i)}static derivedUnitsFromFactorUnitSelection(t,i){var e=t==DerivedUnitSearchMode.EXACT||t==DerivedUnitSearchMode.EXACT_ONLY_ONE||t==DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE?FactorUnitMatchingMode.EXACT:FactorUnitMatchingMode.ALLOW_SCALED;let n=this.findMatchingUnits(i,e);if(t==DerivedUnitSearchMode.EXACT||t==DerivedUnitSearchMode.ALLOW_SCALED)return n;if(t==DerivedUnitSearchMode.EXACT_ONLY_ONE)return[Qudt.retainOnlyOne(n)];if(t==DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE)return 0==n.length&&(n=this.findMatchingUnits(i,FactorUnitMatchingMode.ALLOW_SCALED)),[this.retainOnlyOne(n)];throw`Search mode ${t} was not handled properly, this should never happen - please report as bug`}static retainOnlyOne(t){return t.reduce((t,i)=>t.iri>i.iri?i:t)}static findMatchingUnits(t,i){var e=[];for(const n of exports.config.units.values())n.matches(t,i)&&!e.includes(n)&&e.push(n);return e}static scaledUnit(t,i){for(const e of exports.config.units.values())if(e.prefix?.equals(t)&&e.scalingOf?.equals(i))return e;throw`No scaled unit found with base unit ${i} and prefix `+t}static scaledUnitFromLabels(t,i){return this.scaledUnit(Qudt.prefixFromLabelRequired(t),Qudt.unitFromLabelRequired(i))}static factorUnits(t){return Qudt.simplifyFactorUnits(t.getLeafFactorUnitsWithCumulativeExponents())}static simplifyFactorUnits(t){var i=[];for(const e of t.reduce((t,i)=>{var e=i.getKind(),n=t.get(e);return n?t.set(e,FactorUnit.combine(n,i)):t.set(e,i),t},new Map).values())i.push(e);return i}static unscaledUnit(t){return t.scalingOfIri?this.unitRequired(t.scalingOfIri):t}static unscaledFactorUnits(t){return t.map(t=>new FactorUnit(Qudt.unscaledUnit(t.unit),t.exponent))}}exports.Qudt=Qudt;class CaseInsensitiveUnderscoreIgnoringLabelMatcher{constructor(t){this.compareForEquality=this.convert(t)}convert(t){return t.replaceAll("_"," ").toLocaleUpperCase("en-US")}matchesString(t){return this.convert(t)===this.compareForEquality}matchesLangString(t){return this.convert(t.text)===this.compareForEquality}matchesLangStrings(t){return t.some(t=>this.convert(t.text)===this.compareForEquality)}}function getLastIriElement(t){return t.replaceAll(/.+\/([^\/]+)/g,"$1")}function compareUsingEquals(t,i){return t.equals(i)}function arrayEquals(t,e,n=(t,i)=>t===i){return!!t&&!!e&&t.length===e.length&&t.every((t,i)=>n(t,e[i]))}
//# sourceMappingURL=qudtlib.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Qudt = exports.QUDT_PREFIX_BASE_IRI = exports.QUDT_QUANTITYKIND_BASE_IRI = exports.QUDT_UNIT_BASE_IRI = exports.Unit = exports.FactorUnitSelection = exports.FactorUnitSelector = exports.FactorUnitMatch = exports.FactorUnit = exports.FactorUnitMatchingMode = exports.DerivedUnitSearchMode = exports.QuantityKind = exports.QuantityValue = exports.Prefix = exports.LangString = exports.config = exports.QudtlibConfig = void 0;
const decimal_js_1 = require("decimal.js");
class QudtlibConfig {
constructor() {
this.units = new Map();
this.quantityKinds = new Map();
this.prefixes = new Map();
}
}
exports.QudtlibConfig = QudtlibConfig;
exports.config = new QudtlibConfig();
class LangString {
constructor(text, languageTag) {
this.text = text;
this.languageTag = languageTag;
}
equals(other) {
return (!!other &&
this.text === other.text &&
this.languageTag === other.languageTag);
}
toString() {
return this.text + (this.languageTag ? `@${this.languageTag}` : "");
}
}
exports.LangString = LangString;
class Prefix {
constructor(iri, multiplier, symbol, ucumCode, labels) {
this.iri = iri;
this.multiplier = multiplier;
this.symbol = symbol;
this.ucumCode = ucumCode;
if (typeof labels === "undefined") {
this.labels = [];
}
else {
this.labels = labels;
}
}
equals(other) {
return (!!other &&
this.iri === other.iri &&
this.multiplier.equals(other.multiplier) &&
this.symbol === other.symbol &&
this.ucumCode === other.ucumCode &&
this.labels.length == other.labels.length &&
arrayEquals(this.labels, other.labels, compareUsingEquals));
}
toString() {
if (this.symbol) {
return this.symbol;
}
return "prefix:" + getLastIriElement(this.iri);
}
addLabel(label) {
this.labels.push(label);
}
}
exports.Prefix = Prefix;
class QuantityValue {
constructor(quantity, unit) {
this.value = quantity;
this.unit = unit;
}
equals(other) {
return (!!other && this.value.equals(other.value) && this.unit.equals(other.unit));
}
toString() {
return this.value.toString() + this.unit.toString();
}
convert(to) {
return new QuantityValue(this.unit.convert(this.value, to), to);
}
}
exports.QuantityValue = QuantityValue;
class QuantityKind {
constructor(iri, dimensionVector, symbol, labels) {
this.iri = iri;
this.applicableUnitIris = [];
this.broaderQuantityKindIris = [];
this.dimensionVectorIri = dimensionVector;
this.symbol = symbol;
if (typeof labels === "undefined") {
this.labels = [];
}
else {
this.labels = labels;
}
}
addLabel(label) {
this.labels.push(label);
}
hasLabel(label) {
return this.labels.some((l) => label === l.text);
}
getLabelForLanguageTag(languageTag) {
const label = this.labels.find((l) => languageTag === l.languageTag);
return label?.text;
}
addApplicableUnitIri(unit) {
this.applicableUnitIris.push(unit);
}
addBroaderQuantityKindIri(quantityKind) {
this.broaderQuantityKindIris.push(quantityKind);
}
equals(other) {
return !!other && this.iri === other.iri;
}
toString() {
if (this.symbol) {
return this.symbol;
}
return "quantityKind:" + getLastIriElement(this.iri);
}
}
exports.QuantityKind = QuantityKind;
function checkInteger(arg, argName) {
if (!Number.isInteger(arg)) {
throw `${argName} must be integer, ${arg} (type ${typeof arg}) is not`;
}
}
/**
* Governs the algorithm used to find units based on their derived units. The DerivedUnitSearchMode
* is mapped to the {@link FactorUnitMatchingMode} which governs individual unit/factor unit
* matching.
*/
var DerivedUnitSearchMode;
(function (DerivedUnitSearchMode) {
/** Only select exact matches. */
DerivedUnitSearchMode[DerivedUnitSearchMode["EXACT"] = 0] = "EXACT";
/**
* Only select exact matches, and if there are multiple matches, select only one of them. The
* Unit's IRI is used as the tie-breaker, so the result is stable over multiple executions.
*/
DerivedUnitSearchMode[DerivedUnitSearchMode["EXACT_ONLY_ONE"] = 1] = "EXACT_ONLY_ONE";
/**
* Select exact matches and units whose factor units have different scale, but the scale of the
* result is equivalent to the cumulative scale of the original factor units
*/
DerivedUnitSearchMode[DerivedUnitSearchMode["ALLOW_SCALED"] = 2] = "ALLOW_SCALED";
/**
* Select only one unit. Try EXACT mode first. If no match is found, try ALLOW_SCALED. Break
* ties using the matching units' IRIs.
*/
DerivedUnitSearchMode[DerivedUnitSearchMode["BEST_EFFORT_ONLY_ONE"] = 3] = "BEST_EFFORT_ONLY_ONE";
})(DerivedUnitSearchMode = exports.DerivedUnitSearchMode || (exports.DerivedUnitSearchMode = {}));
/** Specifies the check whether a Unit matches a given set of factor units. */
var FactorUnitMatchingMode;
(function (FactorUnitMatchingMode) {
/** Only select exact matches. */
FactorUnitMatchingMode[FactorUnitMatchingMode["EXACT"] = 0] = "EXACT";
/**
* Select exact matches and units whose factor units have different scale, but the scale of the
* result is equivalent to the cumulative scale of the original factor units
*/
FactorUnitMatchingMode[FactorUnitMatchingMode["ALLOW_SCALED"] = 1] = "ALLOW_SCALED";
})(FactorUnitMatchingMode = exports.FactorUnitMatchingMode || (exports.FactorUnitMatchingMode = {}));
/**
* Combines a {@link Unit} and an exponent; some Units are a combination of {@link FactorUnit}s. If
* a unit is such a 'derived unit', its {@link Unit#getFactorUnits()} method returns a non-empty Set
* of FactorUnits.
*
*/
class FactorUnit {
constructor(unit, exponent) {
checkInteger(exponent, "exponent");
this.exponent = exponent;
this.unit = unit;
}
withExponentMultiplied(by) {
checkInteger(by, "by");
return new FactorUnit(this.unit, this.exponent * by);
}
getExponentCumulated(cumulatedExponent) {
checkInteger(cumulatedExponent, "cumulatedExponent");
return this.exponent * cumulatedExponent;
}
equals(other) {
return (!!other &&
this.exponent === other.exponent &&
this.unit.equals(other.unit));
}
toString() {
return (this.unit.toString() + (this.exponent === 1 ? "" : "^" + this.exponent));
}
static combine(left, right) {
if (left.getKind() !== right.getKind()) {
throw `Cannot combine UnitFactors of different kind (left: ${left}, right: ${right}`;
}
return new FactorUnit(left.unit, left.exponent + right.exponent);
}
/**
* Combines unit IRI and sign of exponent in one string.
*/
getKind() {
return (this.unit.iri +
(this.exponent === 0 ? "0" : this.exponent > 0 ? "1" : "-1"));
}
match(factorUnitSelection, cumulativeExponent, matchedPath, matchingMode) {
const mySelection = [];
factorUnitSelection.forEach((fus) => mySelection.push(fus));
return this.unit.match(mySelection, this.getExponentCumulated(cumulativeExponent), matchedPath, matchingMode);
}
getLeafFactorUnitsWithCumulativeExponents() {
const leafFactorUnits = this.unit.getLeafFactorUnitsWithCumulativeExponents();
if (!!leafFactorUnits?.length) {
return leafFactorUnits.map((fu) => fu.withExponentMultiplied(this.exponent));
}
return [this];
}
}
exports.FactorUnit = FactorUnit;
/** Represents a unit that has been matched in a FactorUnitSelection. */
class FactorUnitMatch {
constructor(matchedFactorUnit, matchedMultiplier, matchedPath) {
this.matchedFactorUnit = matchedFactorUnit;
this.matchedMultiplier = matchedMultiplier;
this.matchedPath = [...matchedPath];
}
equals(other) {
return (!!other &&
this.matchedFactorUnit.equals(other.matchedFactorUnit) &&
arrayEquals(this.matchedPath, other.matchedPath, compareUsingEquals) &&
this.matchedMultiplier.eq(other.matchedMultiplier));
}
toString() {
return (this.getPathAsString() +
(this.matchedMultiplier.eq(new decimal_js_1.Decimal(1))
? ""
: "*" + this.matchedMultiplier.toString()));
}
getPathAsString() {
let result = "/";
if (!!this.matchedPath) {
result += this.matchedPath
.map((u) => u.toString())
.reduce((p, n) => p + "/" + n);
}
return result;
}
}
exports.FactorUnitMatch = FactorUnitMatch;
class FactorUnitSelector {
constructor(unit, exponent, factorUnitMatch) {
this.unit = unit;
this.exponent = exponent;
this.factorUnitMatch = factorUnitMatch;
}
equals(other) {
return (!!other &&
this.exponent === other.exponent &&
this.unit.equals(other.unit) &&
(this.factorUnitMatch === other.factorUnitMatch ||
(!!this.factorUnitMatch &&
this.factorUnitMatch.equals(other.factorUnitMatch))));
}
isAvailable() {
return !this.isBound();
}
isBound() {
return !!this.factorUnitMatch;
}
copy() {
return new FactorUnitSelector(this.unit, this.exponent, this.factorUnitMatch);
}
matched(factorUnitMatch) {
return new FactorUnitSelector(this.unit, this.exponent, factorUnitMatch);
}
matches(factorUnit, cumulativeExponent, mode) {
switch (mode) {
case FactorUnitMatchingMode.EXACT:
return (this.unit.equals(factorUnit.unit) &&
this.exponentMatches(factorUnit, cumulativeExponent));
case FactorUnitMatchingMode.ALLOW_SCALED:
return (this.unit.isSameScaleAs(factorUnit.unit) &&
this.exponentMatches(factorUnit, cumulativeExponent));
default:
}
throw `Cannot handle matching mode ${mode}`;
}
exponentMatches(factorUnit, cumulativeExponent) {
const cumulatedFactorUnitExponent = factorUnit.getExponentCumulated(cumulativeExponent);
return (Math.abs(this.exponent) > 0 &&
Math.abs(this.exponent) >= Math.abs(cumulatedFactorUnitExponent) &&
Math.sign(this.exponent) === Math.sign(cumulatedFactorUnitExponent));
}
forMatch(factorUnit, cumulativeExponent, matchedPath) {
if (!this.isAvailable()) {
throw "not available - selector is already bound";
}
checkInteger(cumulativeExponent, "cumulativeExponent");
if (!this.exponentMatches(factorUnit, cumulativeExponent)) {
throw "exponents do not match";
}
const matchedPower = factorUnit.getExponentCumulated(cumulativeExponent);
const matchedMultiplier = this.calculateMatchedMultiplier(factorUnit, matchedPower);
if (!matchedMultiplier) {
throw "units do not match";
}
const remainingPower = this.exponent - matchedPower;
const ret = [];
ret.push(this.matched(new FactorUnitMatch(factorUnit, matchedMultiplier, matchedPath)));
if (remainingPower !== 0) {
ret.push(new FactorUnitSelector(this.unit, remainingPower));
}
return ret;
}
calculateMatchedMultiplier(factorUnit, matchedExponent) {
if (!this.unit.isConvertible(factorUnit.unit)) {
return undefined;
}
const conversionMultiplier = factorUnit.unit.getConversionMultiplier(this.unit);
return conversionMultiplier.pow(matchedExponent);
}
toString() {
return (this.unit.toString() +
(this.exponent === 1 ? "" : "^" + this.exponent) +
"@" +
(!!this.factorUnitMatch ? this.factorUnitMatch.toString() : "?"));
}
}
exports.FactorUnitSelector = FactorUnitSelector;
class FactorUnitSelection {
constructor(selectors, scaleFactor = new decimal_js_1.Decimal(1)) {
this.selectors = selectors;
this.scaleFactor = scaleFactor;
}
/**
* Returns a new FactorUnitSelection with the same selectors as this one, whose <code>
* scaleFactor</code> is this FactorUnitSelection's <code>scaleFactor</code> multiplied with the
* specified one.
*
* @param scaleFactor
* @return
*/
scale(scaleFactor) {
return new FactorUnitSelection(this.selectors, this.scaleFactor.mul(scaleFactor));
}
static fromFactorUnitSpec(...factorUnitSpec) {
if (factorUnitSpec.length % 2 !== 0) {
throw "An even number of arguments is required";
}
if (factorUnitSpec.length > 14) {
throw "No more than 14 arguments (7 factor units) are supported";
}
const selectors = [];
for (let i = 0; i < factorUnitSpec.length; i += 2) {
const requestedUnit = factorUnitSpec[i];
const requestedExponent = factorUnitSpec[i + 1];
if (!(requestedUnit instanceof Unit)) {
throw `argument at 0-based position ${i} is not of type Unit. The input must be between 1 and 7 Unit, exponent pairs`;
}
if (typeof requestedExponent !== "number" ||
!Number.isInteger(requestedExponent)) {
throw `argument at 0-based position ${i + 1} is not of type number or not an integer. The input must be between 1 and 7 Unit, exponent pairs`;
}
selectors.push(new FactorUnitSelector(requestedUnit, requestedExponent));
}
return new FactorUnitSelection(selectors);
}
equals(other) {
return (!!other &&
arrayEquals(this.selectors, other.selectors, compareUsingEquals));
}
toString() {
return ((this.scaleFactor.eq(new decimal_js_1.Decimal(1))
? ""
: this.scaleFactor.toString() + "*") +
"[" +
this.selectors.map((s) => s.toString()).reduce((p, n) => p + ", " + n) +
"]");
}
isCompleteMatch() {
if (!this.selectors.every((s) => s.isBound())) {
return false;
}
const accumulatedMatchedMultipliers = this.selectors.reduce((prev, cur) => !!cur.factorUnitMatch
? cur.factorUnitMatch.matchedMultiplier.mul(prev)
: prev, new decimal_js_1.Decimal("1"));
const cumulativeScale = this.scaleFactor.mul(accumulatedMatchedMultipliers);
return cumulativeScale.eq(new decimal_js_1.Decimal("1"));
}
/**
* If there are matches for the specified data, return all selections resulting from such
* matches. If there are no matches, the result is an empty set
*
* @param factorUnit the factor unit to match
* @param cumulativeExponent the exponent accumulated on the path from the root unit to the
* factor unit
* @param matchedPath the path from the root unit to the factor unit
* @param mode the matching mode
* @return FactorUnitSelections resulting from the match, empty set if no matches are found.
*/
forPotentialMatch(factorUnit, cumulativeExponent, matchedPath, matchingMode) {
const newSelections = [];
// we have to iterate by index as we need to replace selectors, which may exist in multiple,
// equal instances in the selection
for (let index = 0; index < this.selectors.length; index++) {
const s = this.selectors[index];
if (s.isAvailable() &&
s.matches(factorUnit, cumulativeExponent, matchingMode)) {
const origSelectorsWithOneMatch = [];
for (let i = 0; i < this.selectors.length; i++) {
if (i === index) {
s.forMatch(factorUnit, cumulativeExponent, matchedPath).forEach((sMatched) => origSelectorsWithOneMatch.push(sMatched));
}
else {
origSelectorsWithOneMatch.push(this.selectors[i]);
}
}
newSelections.push(new FactorUnitSelection(origSelectorsWithOneMatch, this.scaleFactor));
}
}
return newSelections;
}
}
exports.FactorUnitSelection = FactorUnitSelection;
class Unit {
constructor(iri, quantityKindIris, dimensionVectorIri, conversionMultiplier, conversionOffset, prefixIri, scalingOfIri, scalingOf, symbol, labels) {
this.quantityKinds = [];
this.factorUnits = [];
this.iri = iri;
this.prefixIri = prefixIri;
this.conversionMultiplier = conversionMultiplier;
this.conversionOffset = conversionOffset;
this.symbol = symbol;
this.scalingOfIri = scalingOfIri;
this.scalingOf = scalingOf;
this.dimensionVectorIri = dimensionVectorIri;
this.prefix = undefined;
if (typeof quantityKindIris === "undefined") {
this.quantityKindIris = [];
}
else {
this.quantityKindIris = quantityKindIris;
}
if (typeof labels === "undefined") {
this.labels = [];
}
else {
this.labels = labels;
}
}
equals(other) {
return !!other && this.iri === other.iri;
}
toString() {
if (this.symbol) {
return this.symbol;
}
if (this.scalingOf?.symbol && this.prefix?.symbol) {
return this.prefix.symbol + this.scalingOf.symbol;
}
return "unit:" + getLastIriElement(this.iri);
}
match(selections, cumulativeExponent, matchedPath, matchingMode) {
checkInteger(cumulativeExponent, "cumulativeExponent");
const results = [];
matchedPath.push(this);
if (this.hasFactorUnits()) {
this.matchFactorUnits(selections, cumulativeExponent, matchedPath, matchingMode).forEach((s) => results.push(s));
}
else {
if (this.scalingOf?.hasFactorUnits()) {
const baseUnit = this.scalingOf;
const scaleFactor = this.getConversionMultiplier(baseUnit);
baseUnit
.match(selections, cumulativeExponent, matchedPath, FactorUnitMatchingMode.ALLOW_SCALED //if we do not allow to scale here, we will miss exact matches
)
.forEach((s) => results.push(s.scale(scaleFactor)));
}
}
// match this unit - even if it has factor units, the unit itself may also match,
// e.g. if the unit is KiloN__M and the selectors contain M^1 as well as N.
this.matchThisUnit(selections, cumulativeExponent, matchedPath, matchingMode).forEach((s) => results.push(s));
matchedPath.pop();
return results;
}
matchFactorUnits(selections, cumulativeExponent, matchedPath, matchingMode) {
let lastResults = selections;
let subResults = selections;
for (const factorUnit of this.factorUnits) {
subResults = factorUnit.match(lastResults, cumulativeExponent, matchedPath, matchingMode);
if (arrayEquals(subResults, lastResults)) {
//no new matches for current factor unit - abort
return selections;
}
lastResults = subResults;
}
return subResults;
}
matchThisUnit(selections, cumulativeExponent, matchedPath, matchingMode) {
const result = [];
for (const factorUnitSelection of selections) {
factorUnitSelection
.forPotentialMatch(new FactorUnit(this, 1), cumulativeExponent, matchedPath, matchingMode)
.forEach((s) => result.push(s));
}
return result;
}
matchesFactorUnitSpec(...factorUnitSpec) {
return this.matches(FactorUnitSelection.fromFactorUnitSpec(...factorUnitSpec));
}
matches(selection, matchingMode = FactorUnitMatchingMode.EXACT) {
const selections = this.match([selection], 1, [], matchingMode);
if (!selections || selections.length == 0) {
return false;
}
return selections.some((sel) => sel.isCompleteMatch());
}
hasFactorUnits() {
return this.factorUnits && this.factorUnits.length > 0;
}
isScaled() {
return !!this.scalingOfIri;
}
isConvertible(toUnit) {
return this.dimensionVectorIri === toUnit.dimensionVectorIri;
}
getConversionMultiplier(toUnit) {
if (this.equals(toUnit)) {
return new decimal_js_1.Decimal(1);
}
if (this.conversionOffsetDiffers(toUnit)) {
throw `Cannot convert from ${this} to ${toUnit} just by multiplication as their conversion offsets differ`;
}
const fromMultiplier = this.conversionMultiplier
? this.conversionMultiplier
: new decimal_js_1.Decimal(1);
const toMultiplier = toUnit.conversionMultiplier
? toUnit.conversionMultiplier
: new decimal_js_1.Decimal(1);
return fromMultiplier.div(toMultiplier);
}
findInBasesRecursively(toFind) {
if (!this.isScaled()) {
return this.equals(toFind);
}
if (!!this.scalingOf) {
return this.scalingOf.findInBasesRecursively(toFind);
}
else {
throw `No base unit found for ${this} - this is a bug`;
}
}
isSameScaleAs(other) {
if (this.equals(other)) {
return true;
}
if (!!this.scalingOfIri && this.scalingOfIri === other.scalingOfIri) {
return true;
}
return (this.findInBasesRecursively(other) || other.findInBasesRecursively(this));
}
static isUnitless(unit) {
return unit.iri === "http://qudt.org/vocab/unit/UNITLESS";
}
convert(value, toUnit) {
if (!value) {
throw "Parameter 'value' is required";
}
if (!toUnit) {
throw "Parameter 'toUnit' is required";
}
if (this.equals(toUnit)) {
return value;
}
if (Unit.isUnitless(this) || Unit.isUnitless(toUnit)) {
return value;
}
if (!this.isConvertible(toUnit)) {
throw `Not convertible: ${this} -> ${toUnit}`;
}
const fromOffset = this.conversionOffset
? this.conversionOffset
: new decimal_js_1.Decimal(0);
const fromMultiplier = this.conversionMultiplier
? this.conversionMultiplier
: new decimal_js_1.Decimal(1);
const toOffset = toUnit.conversionOffset
? toUnit.conversionOffset
: new decimal_js_1.Decimal(0);
const toMultiplier = toUnit.conversionMultiplier
? toUnit.conversionMultiplier
: new decimal_js_1.Decimal(1);
return value
.add(fromOffset)
.mul(fromMultiplier)
.div(toMultiplier)
.minus(toOffset);
}
addLabel(label) {
this.labels.push(label);
}
addQuantityKindIri(quantityKindIri) {
this.quantityKindIris.push(quantityKindIri);
}
hasLabel(label) {
return this.labels.some((l) => label === l.text);
}
getLabelForLanguageTag(languageTag) {
const label = this.labels.find((l) => languageTag === l.languageTag);
return label?.text;
}
addQuantityKind(quantityKind) {
this.quantityKinds.push(quantityKind);
}
addFactorUnit(factorUnit) {
this.factorUnits.push(factorUnit);
}
setPrefix(prefix) {
if (prefix.iri !== this.prefixIri)
throw "prefix.iri does not equal this.prefixIri";
this.prefix = prefix;
}
setScalingOf(scalingOf) {
if (scalingOf.iri !== this.scalingOfIri)
throw "scalingOf.iri does not equal this.scalingOfIri";
this.scalingOf = scalingOf;
}
getLeafFactorUnitsWithCumulativeExponents() {
if (!this.factorUnits) {
return [];
}
return this.factorUnits.flatMap((fu) => fu.getLeafFactorUnitsWithCumulativeExponents());
}
conversionOffsetDiffers(other) {
if (this.hasNonzeroConversionOffset() &&
other.hasNonzeroConversionOffset()) {
if (!!this.conversionOffset && !!other.conversionOffset) {
return !this.conversionOffset.eq(other.conversionOffset);
}
}
return false;
}
hasNonzeroConversionOffset() {
return !!this.conversionOffset && !this.conversionOffset.eq(new decimal_js_1.Decimal(0));
}
}
exports.Unit = Unit;
exports.QUDT_UNIT_BASE_IRI = "http://qudt.org/vocab/unit/";
exports.QUDT_QUANTITYKIND_BASE_IRI = "http://qudt.org/vocab/quantitykind/";
exports.QUDT_PREFIX_BASE_IRI = "http://qudt.org/vocab/prefix/";
function findInIterable(iterable, predicate) {
for (const elem of iterable) {
if (predicate(elem)) {
return elem;
}
}
return undefined;
}
class Qudt {
/**
* Returns the first unit found whose label matches the specified label after replacing any
* underscore with space and ignoring case (US locale). If more intricate matching is needed,
* clients can use `{@link #allUnits()}.filter(...)`.
*
* @param label the matched label
* @return the first unit found
*/
static unitFromLabel(label) {
const matcher = new CaseInsensitiveUnderscoreIgnoringLabelMatcher(label);
const firstMatch = findInIterable(exports.config.units.values(), (u) => matcher.matchesLangStrings(u.labels));
return firstMatch;
}
static unitFromLabelRequired(label) {
const match = this.unitFromLabel(label);
if (!match)
throw `No unit found for label ${label}`;
return match;
}
static unitFromLocalname(localname) {
return Qudt.unit(Qudt.unitIriFromLocalname(localname));
}
static unitFromLocalnameRequired(localname) {
return Qudt.unitRequired(Qudt.unitIriFromLocalname(localname));
}
static quantityKindFromLocalname(localname) {
return Qudt.quantityKind(Qudt.quantityKindIriFromLocalname(localname));
}
static quantityKindFromLocalnameRequired(localname) {
return Qudt.quantityKindRequired(Qudt.quantityKindIriFromLocalname(localname));
}
static prefixFromLabelRequired(label) {
const match = this.prefixFromLabel(label);
if (!match)
throw `No prefix found for label ${label}`;
return match;
}
static prefixFromLabel(label) {
const matcher = new CaseInsensitiveUnderscoreIgnoringLabelMatcher(label);
const firstMatch = findInIterable(exports.config.prefixes.values(), (u) => matcher.matchesLangStrings(u.labels));
return firstMatch;
}
static prefixFromLocalname(localname) {
return Qudt.prefix(Qudt.prefixIriFromLocalname(localname));
}
static prefixFromLocalnameRequired(localname) {
return Qudt.prefixRequired(Qudt.prefixIriFromLocalname(localname));
}
static unitIriFromLocalname(localname) {
return exports.QUDT_UNIT_BASE_IRI + localname;
}
static quantityKindIriFromLocalname(localname) {
return exports.QUDT_QUANTITYKIND_BASE_IRI + localname;
}
static prefixIriFromLocalname(localname) {
return exports.QUDT_PREFIX_BASE_IRI + localname;
}
/**
* Returns the {@link Unit} identified the specified IRI. For example, <code>
* unit("http://qudt.org/vocab/unit/N-PER-M2")</code> yields `Units.N__PER__M2`,
* if that unit has been loaded;
*
* @param iri the requested unit IRI
* @return the unit or `undefined` if no unit is found
*/
static unit(unitIri) {
return exports.config.units.get(unitIri);
}
/**
* Same as {@link #unit(string)} but throws an exception if no unit is found.
* @param unitIri the unit IRI
* @return the unit
*/
static unitRequired(unitIri) {
const ret = Qudt.unit(unitIri);
if (typeof ret === "undefined") {
throw `Unit ${unitIri} not found`;
}
return ret;
}
static quantityKind(quantityKindIri) {
return exports.config.quantityKinds.get(quantityKindIri);
}
static quantityKindRequired(quantityKindIri) {
const ret = Qudt.quantityKind(quantityKindIri);
if (typeof ret === "undefined") {
throw `QuantityKind ${quantityKindIri} not found`;
}
return ret;
}
static prefix(prefixIri) {
return exports.config.prefixes.get(prefixIri);
}
static prefixRequired(prefixIri) {
const ret = Qudt.prefix(prefixIri);
if (typeof ret === "undefined") {
throw `Prefix ${prefixIri} not found`;
}
return ret;
}
static quantityKinds(unit) {
return unit.quantityKindIris.map((iri) => Qudt.quantityKindRequired(iri));
}
static quantityKindsBroad(unit) {
let current = Qudt.quantityKinds(unit);
const result = [];
current.forEach((qk) => result.push(qk));
while (current.length) {
current = current
.flatMap((qk) => qk.broaderQuantityKindIris)
.map((iri) => Qudt.quantityKindRequired(iri));
current.forEach((qk) => result.includes(qk) || result.push(qk));
}
return result;
}
/**
* Obtains units based on factor units, using the specified {@link FactorUnitMatchingMode}.
*
* For example,
*
* ```
* const spec = new Map<Unit, number>();
* spec.set(Units.M, 1);
* spec.set(Units.KiloGM, 1);
* spec.set(Units.SEC, -2);
* Qudt.derivedUnitsFrom Map(
* FactorUnitMatchingMode.EXACT, spec);
* ```
*
* will yield an array containing the Newton Unit ({@code Qudt.Units.N})
*
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param factorUnits a map containing unit to exponent entries.
* @return the derived units that match the given factor units
*/
static derivedUnitsFromMap(searchMode, factorUnits) {
const flattened = [];
for (const [key, value] of factorUnits.entries()) {
flattened.push(key, value);
}
return this.derivedUnitsFromExponentUnitPairs(searchMode, ...flattened);
}
/**
* Obtains units based on factor units.
*
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param factorUnits the factor units
* @return the derived unit that match the given factor units
* @see #derivedUnitsFromMap(DerivedUnitSearchMode, Map)
*/
static derivedUnitsFromFactorUnits(searchMode, ...factorUnits) {
const flattened = factorUnits.flatMap((fu) => [fu.unit, fu.exponent]);
return this.derivedUnitsFromExponentUnitPairs(searchMode, ...flattened);
}
/**
* Vararg method, must be an even number of arguments, always alternating types of Unit|String
* and Integer.
*
* @param factorUnitSpec alternating Unit (representing a unit IRI) and Decimal|number (the
* exponent)
* @return the units that match
*/
static derivedUnitsFromExponentUnitPairs(searchMode, ...factorUnitSpecs) {
const spec = [];
for (let i = 0; i < factorUnitSpecs.length; i++) {
const specAtI = factorUnitSpecs[i];
if (i % 2 == 0 && specAtI instanceof Unit) {
spec[i] = specAtI;
}
else if (i % 2 == 0 && typeof specAtI === "string") {
const unitString = specAtI;
let unit = Qudt.unit(unitString);
if (typeof unit === "undefined") {
unit = Qudt.unitFromLocalname(unitString);
}
if (typeof unit === "undefined") {
unit = Qudt.unitFromLabel(unitString);
}
if (typeof unit === "undefined") {
throw `Unable to find unit for string ${unitString}, interpreted as iri, label or localname`;
}
spec[i] = unit;
}
else if (i % 2 == 1 && typeof specAtI === "number") {
spec[i] = specAtI;
}
else {
throw `Cannot handle input ${specAtI} at 0-based position ${i}`;
}
}
const initialFactorUnitSelection = FactorUnitSelection.fromFactorUnitSpec(...spec);
return Qudt.derivedUnitsFromFactorUnitSelection(searchMode, initialFactorUnitSelection);
}
/**
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param selection the factor unit selection
* @return the units that match
* @see #derivedUnitsFromMap(DerivedUnitSearchMode, Map)
*/
static derivedUnitsFromFactorUnitSelection(searchMode, initialFactorUnitSelection) {
const matchingMode = searchMode == DerivedUnitSearchMode.EXACT ||
searchMode == DerivedUnitSearchMode.EXACT_ONLY_ONE ||
searchMode == DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE
? FactorUnitMatchingMode.EXACT
: FactorUnitMatchingMode.ALLOW_SCALED;
let matchingUnits = this.findMatchingUnits(initialFactorUnitSelection, matchingMode);
if (searchMode == DerivedUnitSearchMode.EXACT ||
searchMode == DerivedUnitSearchMode.ALLOW_SCALED) {
return matchingUnits;
}
if (searchMode == DerivedUnitSearchMode.EXACT_ONLY_ONE) {
return [Qudt.retainOnlyOne(matchingUnits)];
}
if (searchMode == DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE) {
if (matchingUnits.length == 0) {
matchingUnits = this.findMatchingUnits(initialFactorUnitSelection, FactorUnitMatchingMode.ALLOW_SCALED);
}
return [this.retainOnlyOne(matchingUnits)];
}
throw `Search mode ${searchMode} was not handled properly, this should never happen - please report as bug`;
}
static retainOnlyOne(matchingUnits) {
return matchingUnits.reduce((p, n) => (p.iri > n.iri ? n : p));
}
static findMatchingUnits(initialFactorUnitSelection, matchingMode) {
const matchingUnits = [];
for (const unit of exports.config.units.values()) {
if (unit.matches(initialFactorUnitSelection, matchingMode) &&
!matchingUnits.includes(unit)) {
matchingUnits.push(unit);
}
}
return matchingUnits;
}
/**
* Returns the unit resulting from scaling the specified `unit` with the specified `prefix`.
*
* @param prefix the prefix to use for scaling or its IRI
* @param baseUnit the unit to scale or its IRI
* @return the resulting unit
* @throws exception if no such unit is found
*/
static scale(prefix, baseUnit) {
const thePrefix = prefix instanceof Prefix ? prefix : this.prefixRequired(prefix);
const theUnit = baseUnit instanceof Unit ? baseUnit : this.unitRequired(baseUnit);
for (const u of exports.config.units.values()) {
if (u.prefix?.equals(thePrefix) && u.scalingOf?.equals(theUnit)) {
return u;
}
}
throw `No scaled unit found with base unit ${theUnit.toString()} and prefix ${thePrefix.toString()}`;
}
static scaleUnitFromLabels(prefixLabel, baseUnit) {
return this.scale(Qudt.prefixFromLabelRequired(prefixLabel), Qudt.unitFromLabelRequired(baseUnit));
}
/**
* Returns the list of {@link FactorUnit}s of the specified `unit`.
*
* @param unit the unit to get factors for
* @return the factors of the unit or an empty list if the unit is not a derived unit
*/
static factorUnits(unit) {
return Qudt.simplifyFactorUnits(unit.getLeafFactorUnitsWithCumulativeExponents());
}
/**
* Perform mathematical simplification on factor units. For example, `
* `N per M per M -> N per M^2`
*
* @param factorUnits the factor units to simplify
* @return the simplified factor units.
*/
static simplifyFactorUnits(factorUnits) {
const ret = [];
const factorUnitsByKind = factorUnits.reduce((mapping, cur) => {
const kind = cur.getKind();
const prevUnit = mapping.get(kind);
if (prevUnit) {
mapping.set(kind, FactorUnit.combine(prevUnit, cur));
}
else {
mapping.set(kind, cur);
}
return mapping;
}, new Map());
for (const fu of factorUnitsByKind.values()) {
ret.push(fu);
}
return ret;
}
static unscale(unit) {
if (!unit.scalingOfIri) {
return unit;
}
return this.unitRequired(unit.scalingOfIri);
}
/**
* Return a list of {@link FactorUnit}s with the same exponents as the specified `factorUnits` but their base units as units.
*
* @param factorUnits the factor units to unscale
* @return the unscaled factor units
*/
static unscaleFactorUnits(factorUnits) {
return factorUnits.map((fu) => new FactorUnit(Qudt.unscale(fu.unit), fu.exponent));
}
/**
* Instantiates a QuantityValue.
* @param value a Decimal
* @param unit a Unit or unit IRI.
* @return a QuantityValue with the specified data
*/
static quantityValue(value, unit) {
if (typeof unit === "string") {
return new QuantityValue(value, Qudt.unitRequired(unit));
}
return new QuantityValue(value, unit);
}
/**
* Converts the specified value from the unit it is in (`fromUnit`) to the specified target unit (`toUnit`).
* @param value: a Decimal, the value to convert.
* @param fromUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @param toUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @return the resulting value
*/
static convert(value, fromUnit, toUnit) {
if (!fromUnit) {
throw "Parameter 'fromUnit' is required";
}
if (!toUnit) {
throw "Parameter 'toUnit' is required";
}
const from = typeof fromUnit === "string" ? Qudt.unitRequired(fromUnit) : fromUnit;
const to = typeof toUnit === "string" ? Qudt.unitRequired(toUnit) : toUnit;
return from.convert(value, to);
}
/**
* Converts the specified QuantityValue from to the specified target unit (`toUnit`).
* @param value: a Decimal, the value to convert.
* @param fromUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @param toUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @return a QuantityValue holding the result
*/
static convertQuantityValue(from, toUnit) {
if (!from) {
throw "Parameter 'from' is required";
}
if (!toUnit) {
throw "Parameter 'toUnit' is required";
}
const to = typeof toUnit === "string" ? Qudt.unitRequired(toUnit) : toUnit;
return from.convert(to);
}
/**
* Returns `true` if the two units can be converted into each other.
* @param fromUnit a Unit or unit IRI
* @param toUnit a Unit or unit IRI
* @return a boolean indicating whether the units are convertible.
*/
static isConvertible(fromUnit, toUnit) {
const from = typeof fromUnit === "string" ? Qudt.unitRequired(fromUnit) : fromUnit;
const to = typeof toUnit === "string" ? Qudt.unitRequired(toUnit) : toUnit;
return from.isConvertible(to);
}
/**
* Returns a [Unit, Decimal] tuple containing the base unit of the specified `unit`
* along with the scale factor needed to convert values from the base unit to
* the specified unit.
*
* @param unit the unit to scale to its base
* @return a [Unit, Decimal] tuple with the base unit and the required scale factor
*/
static scaleToBaseUnit(unit) {
if (!unit.scalingOf) {
return { unit: unit, factor: new decimal_js_1.Decimal(1) };
}
const baseUnit = unit.scalingOf;
return { unit: baseUnit, factor: unit.getConversionMultiplier(baseUnit) };
}
static allUnits() {
const ret = [];
for (const unit of exports.config.units.values()) {
ret.push(unit);
}
return ret;
}
static allQuantityKinds() {
const ret = [];
for (const quantityKind of exports.config.quantityKinds.values()) {
ret.push(quantityKind);
}
return ret;
}
static allPrefixes() {
const ret = [];
for (const prefix of exports.config.prefixes.values()) {
ret.push(prefix);
}
return ret;
}
}
exports.Qudt = Qudt;
class CaseInsensitiveUnderscoreIgnoringLabelMatcher {
constructor(searchTerm) {
this.compareForEquality = this.convert(searchTerm);
}
convert(term) {
return term.replaceAll("_", " ").toLocaleUpperCase("en-US");
}
matchesString(searchTerm) {
return this.convert(searchTerm) === this.compareForEquality;
}
matchesLangString(searchTerm) {
return this.convert(searchTerm.text) === this.compareForEquality;
}
matchesLangStrings(searchTerms) {
return searchTerms.some((st) => this.convert(st.text) === this.compareForEquality);
}
}
function getLastIriElement(iri) {
return iri.replaceAll(/.+\/([^\/]+)/g, "$1");
}
function compareUsingEquals(a, b) {
return a.equals(b);
}
function arrayEquals(left, right, cmp = (a, b) => a === b) {
return (!!left &&
!!right &&
left.length === right.length &&
left.every((e, i) => cmp(e, right[i])));
}
//# sourceMappingURL=qudtlib.js.map

@@ -1,2 +0,1070 @@

import{Decimal}from"decimal.js";class QudtlibConfig{constructor(){this.units=new Map,this.quantityKinds=new Map,this.prefixes=new Map}}const config=new QudtlibConfig;class LangString{constructor(t,i){this.text=t,this.languageTag=i}equals(t){return!!t&&this.text===t.text&&this.languageTag===t.languageTag}toString(){return this.text+(this.languageTag?"@"+this.languageTag:"")}}class ScaleFactor{constructor(t=new Decimal(1)){this.factor=t}copy(){return new ScaleFactor(this.factor)}multiplyBy(t){return new ScaleFactor(this.factor.mul(t))}toString(){return""+this.factor.toString()}equals(t){return!!t&&this.factor===t.factor}}class Prefix{constructor(t,i,e,n,r){this.iri=t,this.multiplier=i,this.symbol=e,this.ucumCode=n,this.labels=void 0===r?[]:r}equals(t){return!!t&&this.iri===t.iri&&this.multiplier.equals(t.multiplier)&&this.symbol===t.symbol&&this.ucumCode===t.ucumCode&&this.labels.length==t.labels.length&&arrayEquals(this.labels,t.labels,compareUsingEquals)}toString(){return this.symbol||"prefix:"+getLastIriElement(this.iri)}addLabel(t){this.labels.push(t)}}class QuantityValue{constructor(t,i){this.quantity=t,this.unit=i}equals(t){return!!t&&this.quantity.equals(t.quantity)&&this.unit.equals(t.unit)}toString(){return this.quantity.toString()+this.unit.toString()}}class QuantityKind{constructor(t,i,e,n){this.iri=t,this.applicableUnitIris=[],this.broaderQuantityKindIris=[],this.dimensionVectorIri=i,this.symbol=e,this.labels=void 0===n?[]:n}addLabel(t){this.labels.push(t)}hasLabel(i){return this.labels.some(t=>i===t.text)}getLabelForLanguageTag(i){return this.labels.find(t=>i===t.languageTag)?.text}addApplicableUnitIri(t){this.applicableUnitIris.push(t)}addBroaderQuantityKindIri(t){this.broaderQuantityKindIris.push(t)}equals(t){return!!t&&this.iri===t.iri}toString(){return this.symbol||"quantityKind:"+getLastIriElement(this.iri)}}function checkInteger(t,i){if(!Number.isInteger(t))throw i+` must be integer, ${t} (type ${typeof t}) is not`}var DerivedUnitSearchMode,FactorUnitMatchingMode;!function(t){t[t.EXACT=0]="EXACT",t[t.EXACT_ONLY_ONE=1]="EXACT_ONLY_ONE",t[t.ALLOW_SCALED=2]="ALLOW_SCALED",t[t.BEST_EFFORT_ONLY_ONE=3]="BEST_EFFORT_ONLY_ONE"}(DerivedUnitSearchMode=DerivedUnitSearchMode||{}),function(t){t[t.EXACT=0]="EXACT",t[t.ALLOW_SCALED=1]="ALLOW_SCALED"}(FactorUnitMatchingMode=FactorUnitMatchingMode||{});class FactorUnit{constructor(t,i){checkInteger(i,"exponent"),this.exponent=i,this.unit=t}withExponentMultiplied(t){return checkInteger(t,"by"),new FactorUnit(this.unit,this.exponent*t)}getExponentCumulated(t){return checkInteger(t,"cumulatedExponent"),this.exponent*t}equals(t){return!!t&&this.exponent===t.exponent&&this.unit.equals(t.unit)}toString(){return this.unit.toString()+"^"+this.exponent}static combine(t,i){if(t.getKind()!==i.getKind())throw`Cannot combine UnitFactors of different kind (left: ${t}, right: `+i;return new FactorUnit(t.unit,t.exponent+i.exponent)}getKind(){return this.unit.iri+(0===this.exponent?"0":0<this.exponent?"1":"-1")}match(t,i,e,n,r){const a=[];return t.forEach(t=>a.push(t)),this.unit.match(a,this.getExponentCumulated(i),e,n,r)}getLeafFactorUnitsWithCumulativeExponents(){var t=this.unit.getLeafFactorUnitsWithCumulativeExponents();return t?.length?t.map(t=>t.withExponentMultiplied(this.exponent)):[this]}}class FactorUnitMatch{constructor(t,i,e,n){this.matchedFactorUnit=t,this.matchedMultiplier=i,this.matchedPath=[...e],this.scaleFactor=n}equals(t){return!!t&&this.matchedFactorUnit.equals(t.matchedFactorUnit)&&arrayEquals(this.matchedPath,t.matchedPath,compareUsingEquals)&&this.matchedMultiplier.eq(t.matchedMultiplier)&&this.scaleFactor.equals(t.scaleFactor)}toString(){return this.getPathAsString()+(this.matchedMultiplier.eq(new Decimal(1))?"":"*"+this.matchedMultiplier.toString())+(this.scaleFactor.factor.eq(new Decimal(1))?"":"*"+this.scaleFactor.toString())}getPathAsString(){let t="/";return this.matchedPath&&(t+=this.matchedPath.map(t=>t.toString()).reduce((t,i)=>t+"/"+i)),t}}class FactorUnitSelector{constructor(t,i,e){this.unit=t,this.exponent=i,this.factorUnitMatch=e}equals(t){return!!t&&this.exponent===t.exponent&&this.unit.equals(t.unit)&&(this.factorUnitMatch===t.factorUnitMatch||!!this.factorUnitMatch&&this.factorUnitMatch.equals(t.factorUnitMatch))}isAvailable(){return!this.isBound()}isBound(){return!!this.factorUnitMatch}copy(){return new FactorUnitSelector(this.unit,this.exponent,this.factorUnitMatch)}matched(t){return new FactorUnitSelector(this.unit,this.exponent,t)}matches(t,i,e){switch(e){case FactorUnitMatchingMode.EXACT:return this.unit.equals(t.unit)&&this.exponentMatches(t,i);case FactorUnitMatchingMode.ALLOW_SCALED:return this.unit.isSameScaleAs(t.unit)&&this.exponentMatches(t,i)}throw"Cannot handle matching mode "+e}exponentMatches(t,i){t=t.getExponentCumulated(i);return 0<Math.abs(this.exponent)&&Math.abs(this.exponent)>=Math.abs(t)&&Math.sign(this.exponent)===Math.sign(t)}forMatch(t,i,e,n){if(!this.isAvailable())throw"not available - selector is already bound";if(checkInteger(i,"cumulativeExponent"),!this.exponentMatches(t,i))throw"exponents do not match";var r,i=t.getExponentCumulated(i),a=this.calculateMatchedMultiplier(t,i);if(a)return i=this.exponent-i,(r=[]).push(this.matched(new FactorUnitMatch(t,a,e,n))),0!=i&&r.push(new FactorUnitSelector(this.unit,i)),r;throw"units do not match"}calculateMatchedMultiplier(t,i){if(this.unit.isConvertible(t.unit))return t.unit.getConversionMultiplier(this.unit).pow(i)}toString(){return this.unit.toString()+(1===this.exponent?"":"^"+this.exponent)+"@"+(this.factorUnitMatch?this.factorUnitMatch.toString():"?")}}class FactorUnitSelection{constructor(t){this.selectors=t}static fromFactorUnitSpec(...i){if(i.length%2!=0)throw"An even number of arguments is required";if(14<i.length)throw"No more than 14 arguments (7 factor units) are supported";var e=[];for(let t=0;t<i.length;t+=2){var n=i[t],r=i[t+1];if(!(n instanceof Unit))throw`argument at 0-based position ${t} is not of type Unit. The input must be between 1 and 7 Unit, exponent pairs`;if("number"!=typeof r||!Number.isInteger(r))throw`argument at 0-based position ${t+1} is not of type number or not an integer. The input must be between 1 and 7 Unit, exponent pairs`;e.push(new FactorUnitSelector(n,r))}return new FactorUnitSelection(e)}equals(t){return!!t&&arrayEquals(this.selectors,t.selectors,compareUsingEquals)}toString(){return"Select ["+this.selectors.map(t=>t.toString()).reduce((t,i)=>t+", "+i)+"]"}isCompleteMatch(){var t,i;return!!this.selectors.every(t=>t.isBound())&&(t=this.selectors.reduce((t,i)=>i.factorUnitMatch?i.factorUnitMatch.scaleFactor.factor.mul(t):t,new Decimal("1")),i=this.selectors.reduce((t,i)=>i.factorUnitMatch?i.factorUnitMatch.matchedMultiplier.mul(t):t,new Decimal("1")),t.mul(i).eq(new Decimal("1")))}forPotentialMatch(t,i,e,n,r){const a=[];let s=!1;for(const o of this.selectors)!s&&o.isAvailable()&&o.matches(t,i,r)?(s=!0,o.forMatch(t,i,e,n).forEach(t=>a.push(t))):a.push(o.copy());return new FactorUnitSelection(a)}}class Unit{constructor(t,i,e,n,r,a,s,o,c,u){this.quantityKinds=[],this.factorUnits=[],this.iri=t,this.prefixIri=a,this.conversionMultiplier=n,this.conversionOffset=r,this.symbol=c,this.scalingOfIri=s,this.scalingOf=o,this.dimensionVectorIri=e,this.prefix=void 0,this.quantityKindIris=void 0===i?[]:i,this.labels=void 0===u?[]:u}equals(t){return!!t&&this.iri===t.iri}toString(){return this.symbol||(this.scalingOf?.symbol&&this.prefix?.symbol?this.prefix.symbol+this.scalingOf.symbol:"unit:"+getLastIriElement(this.iri))}match(t,i,e,n,r){checkInteger(i,"cumulativeExponent");const a=[];return e.push(this),this.hasFactorUnits()?this.matchFactorUnits(t,i,e,n,r).forEach(t=>a.push(t)):this.scalingOf&&this.prefix&&this.scalingOf.hasFactorUnits()&&this.scalingOf.match(t,i,e,n.multiplyBy(this.prefix.multiplier),r).forEach(t=>a.push(t)),this.matchThisUnit(t,i,e,n,r).forEach(t=>a.push(t)),e.pop(),a}matchFactorUnits(t,i,e,n,r){let a=t,s=t;for(const o of this.factorUnits){if(arrayEquals(s=o.match(a,i,e,n,r),a))return t;a=s}return s}matchThisUnit(t,i,e,n,r){var a=[];for(const o of t){var s=o.forPotentialMatch(new FactorUnit(this,1),i,e,n,r);s.equals(o)||a.push(s)}return a}matchesFactorUnitSpec(...t){return this.matches(FactorUnitSelection.fromFactorUnitSpec(...t))}matches(t,i=FactorUnitMatchingMode.EXACT){t=this.match([t],1,[],new ScaleFactor,i);return!(!t||0==t.length)&&t.some(t=>t.isCompleteMatch())}hasFactorUnits(){return this.factorUnits&&0<this.factorUnits.length}isScaled(){return!!this.scalingOfIri}isConvertible(t){return this.dimensionVectorIri===t.dimensionVectorIri}getConversionMultiplier(t){if(this.equals(t))return new Decimal(1);if(this.conversionOffset||t.conversionOffset)throw`Cannot convert from ${this} to ${t} just by multiplication, one of them has a conversion offset!`;var i=this.conversionMultiplier||new Decimal(1),t=t.conversionMultiplier||new Decimal(1);return i.div(t)}findInBasesRecursively(t){if(!this.isScaled())return this.equals(t);if(this.scalingOf)return this.scalingOf.findInBasesRecursively(t);throw`No base unit found for ${this} - this is a bug`}isSameScaleAs(t){return!!this.equals(t)||(!(!this.scalingOfIri||this.scalingOfIri!==t.scalingOfIri)||(this.findInBasesRecursively(t)||t.findInBasesRecursively(this)))}static isUnitless(t){return"http://qudt.org/vocab/unit/UNITLESS"===t.iri}convert(t,i){if(!t)throw"Parameter 'value' is required";if(!i)throw"Parameter 'toUnit' is required";if(this.equals(i))return t;if(Unit.isUnitless(this)||Unit.isUnitless(i))return t;var e,n,r,a;if(this.isConvertible(i))return e=this.conversionOffset||new Decimal(0),n=this.conversionMultiplier||new Decimal(1),r=i.conversionOffset||new Decimal(0),a=i.conversionMultiplier||new Decimal(1),t.add(e).mul(n).div(a).minus(r);throw`Not convertible: ${this} -> `+i}addLabel(t){this.labels.push(t)}addQuantityKindIri(t){this.quantityKindIris.push(t)}hasLabel(i){return this.labels.some(t=>i===t.text)}getLabelForLanguageTag(i){return this.labels.find(t=>i===t.languageTag)?.text}addQuantityKind(t){this.quantityKinds.push(t)}addFactorUnit(t){this.factorUnits.push(t)}setPrefix(t){if(t.iri!==this.prefixIri)throw"prefix.iri does not equal this.prefixIri";this.prefix=t}setScalingOf(t){if(t.iri!==this.scalingOfIri)throw"scalingOf.iri does not equal this.scalingOfIri";this.scalingOf=t}getLeafFactorUnitsWithCumulativeExponents(){return this.factorUnits?this.factorUnits.flatMap(t=>t.getLeafFactorUnitsWithCumulativeExponents()):[]}}const QUDT_UNIT_BASE_IRI="http://qudt.org/vocab/unit/",QUDT_QUANTITYKIND_BASE_IRI="http://qudt.org/vocab/quantitykind/",QUDT_PREFIX_BASE_IRI="http://qudt.org/vocab/prefix/";function findInIterable(t,i){for(const e of t)if(i(e))return e}class Qudt{static unitFromLabel(t){const i=new CaseInsensitiveUnderscoreIgnoringLabelMatcher(t);return findInIterable(config.units.values(),t=>i.matchesLangStrings(t.labels))}static unitFromLabelRequired(t){var i=this.unitFromLabel(t);if(i)return i;throw"No unit found for label "+t}static unitFromLocalname(t){return Qudt.unit(Qudt.unitIriFromLocalname(t))}static unitFromLocalnameRequired(t){return Qudt.unitRequired(Qudt.unitIriFromLocalname(t))}static quantityKindFromLocalname(t){return Qudt.quantityKind(Qudt.quantityKindIriFromLocalname(t))}static quantityKindFromLocalnameRequired(t){return Qudt.quantityKindRequired(Qudt.quantityKindIriFromLocalname(t))}static prefixFromLabelRequired(t){var i=this.prefixFromLabel(t);if(i)return i;throw"No prefix found for label "+t}static prefixFromLabel(t){const i=new CaseInsensitiveUnderscoreIgnoringLabelMatcher(t);return findInIterable(config.prefixes.values(),t=>i.matchesLangStrings(t.labels))}static prefixFromLocalname(t){return Qudt.prefix(Qudt.prefixIriFromLocalname(t))}static prefixFromLocalnameRequired(t){return Qudt.prefixRequired(Qudt.prefixIriFromLocalname(t))}static unitIriFromLocalname(t){return QUDT_UNIT_BASE_IRI+t}static quantityKindIriFromLocalname(t){return QUDT_QUANTITYKIND_BASE_IRI+t}static prefixIriFromLocalname(t){return QUDT_PREFIX_BASE_IRI+t}static unit(t){return config.units.get(t)}static unitRequired(t){var i=Qudt.unit(t);if(void 0===i)throw`Unit ${t} not found`;return i}static quantityKind(t){return config.quantityKinds.get(t)}static quantityKindRequired(t){var i=Qudt.quantityKind(t);if(void 0===i)throw`QuantityKind ${t} not found`;return i}static prefix(t){return config.prefixes.get(t)}static prefixRequired(t){var i=Qudt.prefix(t);if(void 0===i)throw`Prefix ${t} not found`;return i}static quantityKinds(t){return t.quantityKindIris.map(t=>Qudt.quantityKindRequired(t))}static quantityKindsBroad(t){let i=Qudt.quantityKinds(t);const e=[];for(i.forEach(t=>e.push(t));i.length;)(i=i.flatMap(t=>t.broaderQuantityKindIris).map(t=>Qudt.quantityKindRequired(t))).forEach(t=>e.includes(t)||e.push(t));return e}static derivedUnitsFromMap(t,i){var e,n,r=[];for([e,n]of i.entries())r.push(e,n);return this.derivedUnitsFromExponentUnitPairs(t,...r)}static derivedUnitsFromFactorUnits(t,...i){i=i.flatMap(t=>[t.unit,t.exponent]);return this.derivedUnitsFromExponentUnitPairs(t,...i)}static derivedUnitsFromExponentUnitPairs(t,...e){var n=[];for(let i=0;i<e.length;i++){var r=e[i];if(i%2==0&&r instanceof Unit)n[i]=r;else if(i%2==0&&"string"==typeof r){var a=r;let t=Qudt.unit(a);if(void 0===(t=void 0===(t=void 0===t?Qudt.unitFromLocalname(a):t)?Qudt.unitFromLabel(a):t))throw`Unable to find unit for string ${a}, interpreted as iri, label or localname`;n[i]=t}else{if(i%2!=1||"number"!=typeof r)throw`Cannot handle input ${r} at 0-based position `+i;n[i]=r}}var i=FactorUnitSelection.fromFactorUnitSpec(...n);return Qudt.derivedUnitsFromFactorUnitSelection(t,i)}static derivedUnitsFromFactorUnitSelection(t,i){var e=t==DerivedUnitSearchMode.EXACT||t==DerivedUnitSearchMode.EXACT_ONLY_ONE||t==DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE?FactorUnitMatchingMode.EXACT:FactorUnitMatchingMode.ALLOW_SCALED;let n=this.findMatchingUnits(i,e);if(t==DerivedUnitSearchMode.EXACT||t==DerivedUnitSearchMode.ALLOW_SCALED)return n;if(t==DerivedUnitSearchMode.EXACT_ONLY_ONE)return[Qudt.retainOnlyOne(n)];if(t==DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE)return 0==n.length&&(n=this.findMatchingUnits(i,FactorUnitMatchingMode.ALLOW_SCALED)),[this.retainOnlyOne(n)];throw`Search mode ${t} was not handled properly, this should never happen - please report as bug`}static retainOnlyOne(t){return t.reduce((t,i)=>t.iri>i.iri?i:t)}static findMatchingUnits(t,i){var e=[];for(const n of config.units.values())n.matches(t,i)&&!e.includes(n)&&e.push(n);return e}static scaledUnit(t,i){for(const e of config.units.values())if(e.prefix?.equals(t)&&e.scalingOf?.equals(i))return e;throw`No scaled unit found with base unit ${i} and prefix `+t}static scaledUnitFromLabels(t,i){return this.scaledUnit(Qudt.prefixFromLabelRequired(t),Qudt.unitFromLabelRequired(i))}static factorUnits(t){return Qudt.simplifyFactorUnits(t.getLeafFactorUnitsWithCumulativeExponents())}static simplifyFactorUnits(t){var i=[];for(const e of t.reduce((t,i)=>{var e=i.getKind(),n=t.get(e);return n?t.set(e,FactorUnit.combine(n,i)):t.set(e,i),t},new Map).values())i.push(e);return i}static unscaledUnit(t){return t.scalingOfIri?this.unitRequired(t.scalingOfIri):t}static unscaledFactorUnits(t){return t.map(t=>new FactorUnit(Qudt.unscaledUnit(t.unit),t.exponent))}}class CaseInsensitiveUnderscoreIgnoringLabelMatcher{constructor(t){this.compareForEquality=this.convert(t)}convert(t){return t.replaceAll("_"," ").toLocaleUpperCase("en-US")}matchesString(t){return this.convert(t)===this.compareForEquality}matchesLangString(t){return this.convert(t.text)===this.compareForEquality}matchesLangStrings(t){return t.some(t=>this.convert(t.text)===this.compareForEquality)}}function getLastIriElement(t){return t.replaceAll(/.+\/([^\/]+)/g,"$1")}function compareUsingEquals(t,i){return t.equals(i)}function arrayEquals(t,e,n=(t,i)=>t===i){return!!t&&!!e&&t.length===e.length&&t.every((t,i)=>n(t,e[i]))}export{QudtlibConfig,config,LangString,ScaleFactor,Prefix,QuantityValue,QuantityKind,DerivedUnitSearchMode,FactorUnitMatchingMode,FactorUnit,FactorUnitMatch,FactorUnitSelector,FactorUnitSelection,Unit,QUDT_UNIT_BASE_IRI,QUDT_QUANTITYKIND_BASE_IRI,QUDT_PREFIX_BASE_IRI,Qudt};
//# sourceMappingURL=qudtlib.js.map
import { Decimal } from "decimal.js";
export class QudtlibConfig {
constructor() {
this.units = new Map();
this.quantityKinds = new Map();
this.prefixes = new Map();
}
}
export const config = new QudtlibConfig();
export class LangString {
constructor(text, languageTag) {
this.text = text;
this.languageTag = languageTag;
}
equals(other) {
return (!!other &&
this.text === other.text &&
this.languageTag === other.languageTag);
}
toString() {
return this.text + (this.languageTag ? `@${this.languageTag}` : "");
}
}
export class Prefix {
constructor(iri, multiplier, symbol, ucumCode, labels) {
this.iri = iri;
this.multiplier = multiplier;
this.symbol = symbol;
this.ucumCode = ucumCode;
if (typeof labels === "undefined") {
this.labels = [];
}
else {
this.labels = labels;
}
}
equals(other) {
return (!!other &&
this.iri === other.iri &&
this.multiplier.equals(other.multiplier) &&
this.symbol === other.symbol &&
this.ucumCode === other.ucumCode &&
this.labels.length == other.labels.length &&
arrayEquals(this.labels, other.labels, compareUsingEquals));
}
toString() {
if (this.symbol) {
return this.symbol;
}
return "prefix:" + getLastIriElement(this.iri);
}
addLabel(label) {
this.labels.push(label);
}
}
export class QuantityValue {
constructor(quantity, unit) {
this.value = quantity;
this.unit = unit;
}
equals(other) {
return (!!other && this.value.equals(other.value) && this.unit.equals(other.unit));
}
toString() {
return this.value.toString() + this.unit.toString();
}
convert(to) {
return new QuantityValue(this.unit.convert(this.value, to), to);
}
}
export class QuantityKind {
constructor(iri, dimensionVector, symbol, labels) {
this.iri = iri;
this.applicableUnitIris = [];
this.broaderQuantityKindIris = [];
this.dimensionVectorIri = dimensionVector;
this.symbol = symbol;
if (typeof labels === "undefined") {
this.labels = [];
}
else {
this.labels = labels;
}
}
addLabel(label) {
this.labels.push(label);
}
hasLabel(label) {
return this.labels.some((l) => label === l.text);
}
getLabelForLanguageTag(languageTag) {
const label = this.labels.find((l) => languageTag === l.languageTag);
return label?.text;
}
addApplicableUnitIri(unit) {
this.applicableUnitIris.push(unit);
}
addBroaderQuantityKindIri(quantityKind) {
this.broaderQuantityKindIris.push(quantityKind);
}
equals(other) {
return !!other && this.iri === other.iri;
}
toString() {
if (this.symbol) {
return this.symbol;
}
return "quantityKind:" + getLastIriElement(this.iri);
}
}
function checkInteger(arg, argName) {
if (!Number.isInteger(arg)) {
throw `${argName} must be integer, ${arg} (type ${typeof arg}) is not`;
}
}
/**
* Governs the algorithm used to find units based on their derived units. The DerivedUnitSearchMode
* is mapped to the {@link FactorUnitMatchingMode} which governs individual unit/factor unit
* matching.
*/
export var DerivedUnitSearchMode;
(function (DerivedUnitSearchMode) {
/** Only select exact matches. */
DerivedUnitSearchMode[DerivedUnitSearchMode["EXACT"] = 0] = "EXACT";
/**
* Only select exact matches, and if there are multiple matches, select only one of them. The
* Unit's IRI is used as the tie-breaker, so the result is stable over multiple executions.
*/
DerivedUnitSearchMode[DerivedUnitSearchMode["EXACT_ONLY_ONE"] = 1] = "EXACT_ONLY_ONE";
/**
* Select exact matches and units whose factor units have different scale, but the scale of the
* result is equivalent to the cumulative scale of the original factor units
*/
DerivedUnitSearchMode[DerivedUnitSearchMode["ALLOW_SCALED"] = 2] = "ALLOW_SCALED";
/**
* Select only one unit. Try EXACT mode first. If no match is found, try ALLOW_SCALED. Break
* ties using the matching units' IRIs.
*/
DerivedUnitSearchMode[DerivedUnitSearchMode["BEST_EFFORT_ONLY_ONE"] = 3] = "BEST_EFFORT_ONLY_ONE";
})(DerivedUnitSearchMode || (DerivedUnitSearchMode = {}));
/** Specifies the check whether a Unit matches a given set of factor units. */
export var FactorUnitMatchingMode;
(function (FactorUnitMatchingMode) {
/** Only select exact matches. */
FactorUnitMatchingMode[FactorUnitMatchingMode["EXACT"] = 0] = "EXACT";
/**
* Select exact matches and units whose factor units have different scale, but the scale of the
* result is equivalent to the cumulative scale of the original factor units
*/
FactorUnitMatchingMode[FactorUnitMatchingMode["ALLOW_SCALED"] = 1] = "ALLOW_SCALED";
})(FactorUnitMatchingMode || (FactorUnitMatchingMode = {}));
/**
* Combines a {@link Unit} and an exponent; some Units are a combination of {@link FactorUnit}s. If
* a unit is such a 'derived unit', its {@link Unit#getFactorUnits()} method returns a non-empty Set
* of FactorUnits.
*
*/
export class FactorUnit {
constructor(unit, exponent) {
checkInteger(exponent, "exponent");
this.exponent = exponent;
this.unit = unit;
}
withExponentMultiplied(by) {
checkInteger(by, "by");
return new FactorUnit(this.unit, this.exponent * by);
}
getExponentCumulated(cumulatedExponent) {
checkInteger(cumulatedExponent, "cumulatedExponent");
return this.exponent * cumulatedExponent;
}
equals(other) {
return (!!other &&
this.exponent === other.exponent &&
this.unit.equals(other.unit));
}
toString() {
return (this.unit.toString() + (this.exponent === 1 ? "" : "^" + this.exponent));
}
static combine(left, right) {
if (left.getKind() !== right.getKind()) {
throw `Cannot combine UnitFactors of different kind (left: ${left}, right: ${right}`;
}
return new FactorUnit(left.unit, left.exponent + right.exponent);
}
/**
* Combines unit IRI and sign of exponent in one string.
*/
getKind() {
return (this.unit.iri +
(this.exponent === 0 ? "0" : this.exponent > 0 ? "1" : "-1"));
}
match(factorUnitSelection, cumulativeExponent, matchedPath, matchingMode) {
const mySelection = [];
factorUnitSelection.forEach((fus) => mySelection.push(fus));
return this.unit.match(mySelection, this.getExponentCumulated(cumulativeExponent), matchedPath, matchingMode);
}
getLeafFactorUnitsWithCumulativeExponents() {
const leafFactorUnits = this.unit.getLeafFactorUnitsWithCumulativeExponents();
if (!!leafFactorUnits?.length) {
return leafFactorUnits.map((fu) => fu.withExponentMultiplied(this.exponent));
}
return [this];
}
}
/** Represents a unit that has been matched in a FactorUnitSelection. */
export class FactorUnitMatch {
constructor(matchedFactorUnit, matchedMultiplier, matchedPath) {
this.matchedFactorUnit = matchedFactorUnit;
this.matchedMultiplier = matchedMultiplier;
this.matchedPath = [...matchedPath];
}
equals(other) {
return (!!other &&
this.matchedFactorUnit.equals(other.matchedFactorUnit) &&
arrayEquals(this.matchedPath, other.matchedPath, compareUsingEquals) &&
this.matchedMultiplier.eq(other.matchedMultiplier));
}
toString() {
return (this.getPathAsString() +
(this.matchedMultiplier.eq(new Decimal(1))
? ""
: "*" + this.matchedMultiplier.toString()));
}
getPathAsString() {
let result = "/";
if (!!this.matchedPath) {
result += this.matchedPath
.map((u) => u.toString())
.reduce((p, n) => p + "/" + n);
}
return result;
}
}
export class FactorUnitSelector {
constructor(unit, exponent, factorUnitMatch) {
this.unit = unit;
this.exponent = exponent;
this.factorUnitMatch = factorUnitMatch;
}
equals(other) {
return (!!other &&
this.exponent === other.exponent &&
this.unit.equals(other.unit) &&
(this.factorUnitMatch === other.factorUnitMatch ||
(!!this.factorUnitMatch &&
this.factorUnitMatch.equals(other.factorUnitMatch))));
}
isAvailable() {
return !this.isBound();
}
isBound() {
return !!this.factorUnitMatch;
}
copy() {
return new FactorUnitSelector(this.unit, this.exponent, this.factorUnitMatch);
}
matched(factorUnitMatch) {
return new FactorUnitSelector(this.unit, this.exponent, factorUnitMatch);
}
matches(factorUnit, cumulativeExponent, mode) {
switch (mode) {
case FactorUnitMatchingMode.EXACT:
return (this.unit.equals(factorUnit.unit) &&
this.exponentMatches(factorUnit, cumulativeExponent));
case FactorUnitMatchingMode.ALLOW_SCALED:
return (this.unit.isSameScaleAs(factorUnit.unit) &&
this.exponentMatches(factorUnit, cumulativeExponent));
default:
}
throw `Cannot handle matching mode ${mode}`;
}
exponentMatches(factorUnit, cumulativeExponent) {
const cumulatedFactorUnitExponent = factorUnit.getExponentCumulated(cumulativeExponent);
return (Math.abs(this.exponent) > 0 &&
Math.abs(this.exponent) >= Math.abs(cumulatedFactorUnitExponent) &&
Math.sign(this.exponent) === Math.sign(cumulatedFactorUnitExponent));
}
forMatch(factorUnit, cumulativeExponent, matchedPath) {
if (!this.isAvailable()) {
throw "not available - selector is already bound";
}
checkInteger(cumulativeExponent, "cumulativeExponent");
if (!this.exponentMatches(factorUnit, cumulativeExponent)) {
throw "exponents do not match";
}
const matchedPower = factorUnit.getExponentCumulated(cumulativeExponent);
const matchedMultiplier = this.calculateMatchedMultiplier(factorUnit, matchedPower);
if (!matchedMultiplier) {
throw "units do not match";
}
const remainingPower = this.exponent - matchedPower;
const ret = [];
ret.push(this.matched(new FactorUnitMatch(factorUnit, matchedMultiplier, matchedPath)));
if (remainingPower !== 0) {
ret.push(new FactorUnitSelector(this.unit, remainingPower));
}
return ret;
}
calculateMatchedMultiplier(factorUnit, matchedExponent) {
if (!this.unit.isConvertible(factorUnit.unit)) {
return undefined;
}
const conversionMultiplier = factorUnit.unit.getConversionMultiplier(this.unit);
return conversionMultiplier.pow(matchedExponent);
}
toString() {
return (this.unit.toString() +
(this.exponent === 1 ? "" : "^" + this.exponent) +
"@" +
(!!this.factorUnitMatch ? this.factorUnitMatch.toString() : "?"));
}
}
export class FactorUnitSelection {
constructor(selectors, scaleFactor = new Decimal(1)) {
this.selectors = selectors;
this.scaleFactor = scaleFactor;
}
/**
* Returns a new FactorUnitSelection with the same selectors as this one, whose <code>
* scaleFactor</code> is this FactorUnitSelection's <code>scaleFactor</code> multiplied with the
* specified one.
*
* @param scaleFactor
* @return
*/
scale(scaleFactor) {
return new FactorUnitSelection(this.selectors, this.scaleFactor.mul(scaleFactor));
}
static fromFactorUnitSpec(...factorUnitSpec) {
if (factorUnitSpec.length % 2 !== 0) {
throw "An even number of arguments is required";
}
if (factorUnitSpec.length > 14) {
throw "No more than 14 arguments (7 factor units) are supported";
}
const selectors = [];
for (let i = 0; i < factorUnitSpec.length; i += 2) {
const requestedUnit = factorUnitSpec[i];
const requestedExponent = factorUnitSpec[i + 1];
if (!(requestedUnit instanceof Unit)) {
throw `argument at 0-based position ${i} is not of type Unit. The input must be between 1 and 7 Unit, exponent pairs`;
}
if (typeof requestedExponent !== "number" ||
!Number.isInteger(requestedExponent)) {
throw `argument at 0-based position ${i + 1} is not of type number or not an integer. The input must be between 1 and 7 Unit, exponent pairs`;
}
selectors.push(new FactorUnitSelector(requestedUnit, requestedExponent));
}
return new FactorUnitSelection(selectors);
}
equals(other) {
return (!!other &&
arrayEquals(this.selectors, other.selectors, compareUsingEquals));
}
toString() {
return ((this.scaleFactor.eq(new Decimal(1))
? ""
: this.scaleFactor.toString() + "*") +
"[" +
this.selectors.map((s) => s.toString()).reduce((p, n) => p + ", " + n) +
"]");
}
isCompleteMatch() {
if (!this.selectors.every((s) => s.isBound())) {
return false;
}
const accumulatedMatchedMultipliers = this.selectors.reduce((prev, cur) => !!cur.factorUnitMatch
? cur.factorUnitMatch.matchedMultiplier.mul(prev)
: prev, new Decimal("1"));
const cumulativeScale = this.scaleFactor.mul(accumulatedMatchedMultipliers);
return cumulativeScale.eq(new Decimal("1"));
}
/**
* If there are matches for the specified data, return all selections resulting from such
* matches. If there are no matches, the result is an empty set
*
* @param factorUnit the factor unit to match
* @param cumulativeExponent the exponent accumulated on the path from the root unit to the
* factor unit
* @param matchedPath the path from the root unit to the factor unit
* @param mode the matching mode
* @return FactorUnitSelections resulting from the match, empty set if no matches are found.
*/
forPotentialMatch(factorUnit, cumulativeExponent, matchedPath, matchingMode) {
const newSelections = [];
// we have to iterate by index as we need to replace selectors, which may exist in multiple,
// equal instances in the selection
for (let index = 0; index < this.selectors.length; index++) {
const s = this.selectors[index];
if (s.isAvailable() &&
s.matches(factorUnit, cumulativeExponent, matchingMode)) {
const origSelectorsWithOneMatch = [];
for (let i = 0; i < this.selectors.length; i++) {
if (i === index) {
s.forMatch(factorUnit, cumulativeExponent, matchedPath).forEach((sMatched) => origSelectorsWithOneMatch.push(sMatched));
}
else {
origSelectorsWithOneMatch.push(this.selectors[i]);
}
}
newSelections.push(new FactorUnitSelection(origSelectorsWithOneMatch, this.scaleFactor));
}
}
return newSelections;
}
}
export class Unit {
constructor(iri, quantityKindIris, dimensionVectorIri, conversionMultiplier, conversionOffset, prefixIri, scalingOfIri, scalingOf, symbol, labels) {
this.quantityKinds = [];
this.factorUnits = [];
this.iri = iri;
this.prefixIri = prefixIri;
this.conversionMultiplier = conversionMultiplier;
this.conversionOffset = conversionOffset;
this.symbol = symbol;
this.scalingOfIri = scalingOfIri;
this.scalingOf = scalingOf;
this.dimensionVectorIri = dimensionVectorIri;
this.prefix = undefined;
if (typeof quantityKindIris === "undefined") {
this.quantityKindIris = [];
}
else {
this.quantityKindIris = quantityKindIris;
}
if (typeof labels === "undefined") {
this.labels = [];
}
else {
this.labels = labels;
}
}
equals(other) {
return !!other && this.iri === other.iri;
}
toString() {
if (this.symbol) {
return this.symbol;
}
if (this.scalingOf?.symbol && this.prefix?.symbol) {
return this.prefix.symbol + this.scalingOf.symbol;
}
return "unit:" + getLastIriElement(this.iri);
}
match(selections, cumulativeExponent, matchedPath, matchingMode) {
checkInteger(cumulativeExponent, "cumulativeExponent");
const results = [];
matchedPath.push(this);
if (this.hasFactorUnits()) {
this.matchFactorUnits(selections, cumulativeExponent, matchedPath, matchingMode).forEach((s) => results.push(s));
}
else {
if (this.scalingOf?.hasFactorUnits()) {
const baseUnit = this.scalingOf;
const scaleFactor = this.getConversionMultiplier(baseUnit);
baseUnit
.match(selections, cumulativeExponent, matchedPath, FactorUnitMatchingMode.ALLOW_SCALED //if we do not allow to scale here, we will miss exact matches
)
.forEach((s) => results.push(s.scale(scaleFactor)));
}
}
// match this unit - even if it has factor units, the unit itself may also match,
// e.g. if the unit is KiloN__M and the selectors contain M^1 as well as N.
this.matchThisUnit(selections, cumulativeExponent, matchedPath, matchingMode).forEach((s) => results.push(s));
matchedPath.pop();
return results;
}
matchFactorUnits(selections, cumulativeExponent, matchedPath, matchingMode) {
let lastResults = selections;
let subResults = selections;
for (const factorUnit of this.factorUnits) {
subResults = factorUnit.match(lastResults, cumulativeExponent, matchedPath, matchingMode);
if (arrayEquals(subResults, lastResults)) {
//no new matches for current factor unit - abort
return selections;
}
lastResults = subResults;
}
return subResults;
}
matchThisUnit(selections, cumulativeExponent, matchedPath, matchingMode) {
const result = [];
for (const factorUnitSelection of selections) {
factorUnitSelection
.forPotentialMatch(new FactorUnit(this, 1), cumulativeExponent, matchedPath, matchingMode)
.forEach((s) => result.push(s));
}
return result;
}
matchesFactorUnitSpec(...factorUnitSpec) {
return this.matches(FactorUnitSelection.fromFactorUnitSpec(...factorUnitSpec));
}
matches(selection, matchingMode = FactorUnitMatchingMode.EXACT) {
const selections = this.match([selection], 1, [], matchingMode);
if (!selections || selections.length == 0) {
return false;
}
return selections.some((sel) => sel.isCompleteMatch());
}
hasFactorUnits() {
return this.factorUnits && this.factorUnits.length > 0;
}
isScaled() {
return !!this.scalingOfIri;
}
isConvertible(toUnit) {
return this.dimensionVectorIri === toUnit.dimensionVectorIri;
}
getConversionMultiplier(toUnit) {
if (this.equals(toUnit)) {
return new Decimal(1);
}
if (this.conversionOffsetDiffers(toUnit)) {
throw `Cannot convert from ${this} to ${toUnit} just by multiplication as their conversion offsets differ`;
}
const fromMultiplier = this.conversionMultiplier
? this.conversionMultiplier
: new Decimal(1);
const toMultiplier = toUnit.conversionMultiplier
? toUnit.conversionMultiplier
: new Decimal(1);
return fromMultiplier.div(toMultiplier);
}
findInBasesRecursively(toFind) {
if (!this.isScaled()) {
return this.equals(toFind);
}
if (!!this.scalingOf) {
return this.scalingOf.findInBasesRecursively(toFind);
}
else {
throw `No base unit found for ${this} - this is a bug`;
}
}
isSameScaleAs(other) {
if (this.equals(other)) {
return true;
}
if (!!this.scalingOfIri && this.scalingOfIri === other.scalingOfIri) {
return true;
}
return (this.findInBasesRecursively(other) || other.findInBasesRecursively(this));
}
static isUnitless(unit) {
return unit.iri === "http://qudt.org/vocab/unit/UNITLESS";
}
convert(value, toUnit) {
if (!value) {
throw "Parameter 'value' is required";
}
if (!toUnit) {
throw "Parameter 'toUnit' is required";
}
if (this.equals(toUnit)) {
return value;
}
if (Unit.isUnitless(this) || Unit.isUnitless(toUnit)) {
return value;
}
if (!this.isConvertible(toUnit)) {
throw `Not convertible: ${this} -> ${toUnit}`;
}
const fromOffset = this.conversionOffset
? this.conversionOffset
: new Decimal(0);
const fromMultiplier = this.conversionMultiplier
? this.conversionMultiplier
: new Decimal(1);
const toOffset = toUnit.conversionOffset
? toUnit.conversionOffset
: new Decimal(0);
const toMultiplier = toUnit.conversionMultiplier
? toUnit.conversionMultiplier
: new Decimal(1);
return value
.add(fromOffset)
.mul(fromMultiplier)
.div(toMultiplier)
.minus(toOffset);
}
addLabel(label) {
this.labels.push(label);
}
addQuantityKindIri(quantityKindIri) {
this.quantityKindIris.push(quantityKindIri);
}
hasLabel(label) {
return this.labels.some((l) => label === l.text);
}
getLabelForLanguageTag(languageTag) {
const label = this.labels.find((l) => languageTag === l.languageTag);
return label?.text;
}
addQuantityKind(quantityKind) {
this.quantityKinds.push(quantityKind);
}
addFactorUnit(factorUnit) {
this.factorUnits.push(factorUnit);
}
setPrefix(prefix) {
if (prefix.iri !== this.prefixIri)
throw "prefix.iri does not equal this.prefixIri";
this.prefix = prefix;
}
setScalingOf(scalingOf) {
if (scalingOf.iri !== this.scalingOfIri)
throw "scalingOf.iri does not equal this.scalingOfIri";
this.scalingOf = scalingOf;
}
getLeafFactorUnitsWithCumulativeExponents() {
if (!this.factorUnits) {
return [];
}
return this.factorUnits.flatMap((fu) => fu.getLeafFactorUnitsWithCumulativeExponents());
}
conversionOffsetDiffers(other) {
if (this.hasNonzeroConversionOffset() &&
other.hasNonzeroConversionOffset()) {
if (!!this.conversionOffset && !!other.conversionOffset) {
return !this.conversionOffset.eq(other.conversionOffset);
}
}
return false;
}
hasNonzeroConversionOffset() {
return !!this.conversionOffset && !this.conversionOffset.eq(new Decimal(0));
}
}
export const QUDT_UNIT_BASE_IRI = "http://qudt.org/vocab/unit/";
export const QUDT_QUANTITYKIND_BASE_IRI = "http://qudt.org/vocab/quantitykind/";
export const QUDT_PREFIX_BASE_IRI = "http://qudt.org/vocab/prefix/";
function findInIterable(iterable, predicate) {
for (const elem of iterable) {
if (predicate(elem)) {
return elem;
}
}
return undefined;
}
export class Qudt {
/**
* Returns the first unit found whose label matches the specified label after replacing any
* underscore with space and ignoring case (US locale). If more intricate matching is needed,
* clients can use `{@link #allUnits()}.filter(...)`.
*
* @param label the matched label
* @return the first unit found
*/
static unitFromLabel(label) {
const matcher = new CaseInsensitiveUnderscoreIgnoringLabelMatcher(label);
const firstMatch = findInIterable(config.units.values(), (u) => matcher.matchesLangStrings(u.labels));
return firstMatch;
}
static unitFromLabelRequired(label) {
const match = this.unitFromLabel(label);
if (!match)
throw `No unit found for label ${label}`;
return match;
}
static unitFromLocalname(localname) {
return Qudt.unit(Qudt.unitIriFromLocalname(localname));
}
static unitFromLocalnameRequired(localname) {
return Qudt.unitRequired(Qudt.unitIriFromLocalname(localname));
}
static quantityKindFromLocalname(localname) {
return Qudt.quantityKind(Qudt.quantityKindIriFromLocalname(localname));
}
static quantityKindFromLocalnameRequired(localname) {
return Qudt.quantityKindRequired(Qudt.quantityKindIriFromLocalname(localname));
}
static prefixFromLabelRequired(label) {
const match = this.prefixFromLabel(label);
if (!match)
throw `No prefix found for label ${label}`;
return match;
}
static prefixFromLabel(label) {
const matcher = new CaseInsensitiveUnderscoreIgnoringLabelMatcher(label);
const firstMatch = findInIterable(config.prefixes.values(), (u) => matcher.matchesLangStrings(u.labels));
return firstMatch;
}
static prefixFromLocalname(localname) {
return Qudt.prefix(Qudt.prefixIriFromLocalname(localname));
}
static prefixFromLocalnameRequired(localname) {
return Qudt.prefixRequired(Qudt.prefixIriFromLocalname(localname));
}
static unitIriFromLocalname(localname) {
return QUDT_UNIT_BASE_IRI + localname;
}
static quantityKindIriFromLocalname(localname) {
return QUDT_QUANTITYKIND_BASE_IRI + localname;
}
static prefixIriFromLocalname(localname) {
return QUDT_PREFIX_BASE_IRI + localname;
}
/**
* Returns the {@link Unit} identified the specified IRI. For example, <code>
* unit("http://qudt.org/vocab/unit/N-PER-M2")</code> yields `Units.N__PER__M2`,
* if that unit has been loaded;
*
* @param iri the requested unit IRI
* @return the unit or `undefined` if no unit is found
*/
static unit(unitIri) {
return config.units.get(unitIri);
}
/**
* Same as {@link #unit(string)} but throws an exception if no unit is found.
* @param unitIri the unit IRI
* @return the unit
*/
static unitRequired(unitIri) {
const ret = Qudt.unit(unitIri);
if (typeof ret === "undefined") {
throw `Unit ${unitIri} not found`;
}
return ret;
}
static quantityKind(quantityKindIri) {
return config.quantityKinds.get(quantityKindIri);
}
static quantityKindRequired(quantityKindIri) {
const ret = Qudt.quantityKind(quantityKindIri);
if (typeof ret === "undefined") {
throw `QuantityKind ${quantityKindIri} not found`;
}
return ret;
}
static prefix(prefixIri) {
return config.prefixes.get(prefixIri);
}
static prefixRequired(prefixIri) {
const ret = Qudt.prefix(prefixIri);
if (typeof ret === "undefined") {
throw `Prefix ${prefixIri} not found`;
}
return ret;
}
static quantityKinds(unit) {
return unit.quantityKindIris.map((iri) => Qudt.quantityKindRequired(iri));
}
static quantityKindsBroad(unit) {
let current = Qudt.quantityKinds(unit);
const result = [];
current.forEach((qk) => result.push(qk));
while (current.length) {
current = current
.flatMap((qk) => qk.broaderQuantityKindIris)
.map((iri) => Qudt.quantityKindRequired(iri));
current.forEach((qk) => result.includes(qk) || result.push(qk));
}
return result;
}
/**
* Obtains units based on factor units, using the specified {@link FactorUnitMatchingMode}.
*
* For example,
*
* ```
* const spec = new Map<Unit, number>();
* spec.set(Units.M, 1);
* spec.set(Units.KiloGM, 1);
* spec.set(Units.SEC, -2);
* Qudt.derivedUnitsFrom Map(
* FactorUnitMatchingMode.EXACT, spec);
* ```
*
* will yield an array containing the Newton Unit ({@code Qudt.Units.N})
*
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param factorUnits a map containing unit to exponent entries.
* @return the derived units that match the given factor units
*/
static derivedUnitsFromMap(searchMode, factorUnits) {
const flattened = [];
for (const [key, value] of factorUnits.entries()) {
flattened.push(key, value);
}
return this.derivedUnitsFromExponentUnitPairs(searchMode, ...flattened);
}
/**
* Obtains units based on factor units.
*
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param factorUnits the factor units
* @return the derived unit that match the given factor units
* @see #derivedUnitsFromMap(DerivedUnitSearchMode, Map)
*/
static derivedUnitsFromFactorUnits(searchMode, ...factorUnits) {
const flattened = factorUnits.flatMap((fu) => [fu.unit, fu.exponent]);
return this.derivedUnitsFromExponentUnitPairs(searchMode, ...flattened);
}
/**
* Vararg method, must be an even number of arguments, always alternating types of Unit|String
* and Integer.
*
* @param factorUnitSpec alternating Unit (representing a unit IRI) and Decimal|number (the
* exponent)
* @return the units that match
*/
static derivedUnitsFromExponentUnitPairs(searchMode, ...factorUnitSpecs) {
const spec = [];
for (let i = 0; i < factorUnitSpecs.length; i++) {
const specAtI = factorUnitSpecs[i];
if (i % 2 == 0 && specAtI instanceof Unit) {
spec[i] = specAtI;
}
else if (i % 2 == 0 && typeof specAtI === "string") {
const unitString = specAtI;
let unit = Qudt.unit(unitString);
if (typeof unit === "undefined") {
unit = Qudt.unitFromLocalname(unitString);
}
if (typeof unit === "undefined") {
unit = Qudt.unitFromLabel(unitString);
}
if (typeof unit === "undefined") {
throw `Unable to find unit for string ${unitString}, interpreted as iri, label or localname`;
}
spec[i] = unit;
}
else if (i % 2 == 1 && typeof specAtI === "number") {
spec[i] = specAtI;
}
else {
throw `Cannot handle input ${specAtI} at 0-based position ${i}`;
}
}
const initialFactorUnitSelection = FactorUnitSelection.fromFactorUnitSpec(...spec);
return Qudt.derivedUnitsFromFactorUnitSelection(searchMode, initialFactorUnitSelection);
}
/**
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param selection the factor unit selection
* @return the units that match
* @see #derivedUnitsFromMap(DerivedUnitSearchMode, Map)
*/
static derivedUnitsFromFactorUnitSelection(searchMode, initialFactorUnitSelection) {
const matchingMode = searchMode == DerivedUnitSearchMode.EXACT ||
searchMode == DerivedUnitSearchMode.EXACT_ONLY_ONE ||
searchMode == DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE
? FactorUnitMatchingMode.EXACT
: FactorUnitMatchingMode.ALLOW_SCALED;
let matchingUnits = this.findMatchingUnits(initialFactorUnitSelection, matchingMode);
if (searchMode == DerivedUnitSearchMode.EXACT ||
searchMode == DerivedUnitSearchMode.ALLOW_SCALED) {
return matchingUnits;
}
if (searchMode == DerivedUnitSearchMode.EXACT_ONLY_ONE) {
return [Qudt.retainOnlyOne(matchingUnits)];
}
if (searchMode == DerivedUnitSearchMode.BEST_EFFORT_ONLY_ONE) {
if (matchingUnits.length == 0) {
matchingUnits = this.findMatchingUnits(initialFactorUnitSelection, FactorUnitMatchingMode.ALLOW_SCALED);
}
return [this.retainOnlyOne(matchingUnits)];
}
throw `Search mode ${searchMode} was not handled properly, this should never happen - please report as bug`;
}
static retainOnlyOne(matchingUnits) {
return matchingUnits.reduce((p, n) => (p.iri > n.iri ? n : p));
}
static findMatchingUnits(initialFactorUnitSelection, matchingMode) {
const matchingUnits = [];
for (const unit of config.units.values()) {
if (unit.matches(initialFactorUnitSelection, matchingMode) &&
!matchingUnits.includes(unit)) {
matchingUnits.push(unit);
}
}
return matchingUnits;
}
/**
* Returns the unit resulting from scaling the specified `unit` with the specified `prefix`.
*
* @param prefix the prefix to use for scaling or its IRI
* @param baseUnit the unit to scale or its IRI
* @return the resulting unit
* @throws exception if no such unit is found
*/
static scale(prefix, baseUnit) {
const thePrefix = prefix instanceof Prefix ? prefix : this.prefixRequired(prefix);
const theUnit = baseUnit instanceof Unit ? baseUnit : this.unitRequired(baseUnit);
for (const u of config.units.values()) {
if (u.prefix?.equals(thePrefix) && u.scalingOf?.equals(theUnit)) {
return u;
}
}
throw `No scaled unit found with base unit ${theUnit.toString()} and prefix ${thePrefix.toString()}`;
}
static scaleUnitFromLabels(prefixLabel, baseUnit) {
return this.scale(Qudt.prefixFromLabelRequired(prefixLabel), Qudt.unitFromLabelRequired(baseUnit));
}
/**
* Returns the list of {@link FactorUnit}s of the specified `unit`.
*
* @param unit the unit to get factors for
* @return the factors of the unit or an empty list if the unit is not a derived unit
*/
static factorUnits(unit) {
return Qudt.simplifyFactorUnits(unit.getLeafFactorUnitsWithCumulativeExponents());
}
/**
* Perform mathematical simplification on factor units. For example, `
* `N per M per M -> N per M^2`
*
* @param factorUnits the factor units to simplify
* @return the simplified factor units.
*/
static simplifyFactorUnits(factorUnits) {
const ret = [];
const factorUnitsByKind = factorUnits.reduce((mapping, cur) => {
const kind = cur.getKind();
const prevUnit = mapping.get(kind);
if (prevUnit) {
mapping.set(kind, FactorUnit.combine(prevUnit, cur));
}
else {
mapping.set(kind, cur);
}
return mapping;
}, new Map());
for (const fu of factorUnitsByKind.values()) {
ret.push(fu);
}
return ret;
}
static unscale(unit) {
if (!unit.scalingOfIri) {
return unit;
}
return this.unitRequired(unit.scalingOfIri);
}
/**
* Return a list of {@link FactorUnit}s with the same exponents as the specified `factorUnits` but their base units as units.
*
* @param factorUnits the factor units to unscale
* @return the unscaled factor units
*/
static unscaleFactorUnits(factorUnits) {
return factorUnits.map((fu) => new FactorUnit(Qudt.unscale(fu.unit), fu.exponent));
}
/**
* Instantiates a QuantityValue.
* @param value a Decimal
* @param unit a Unit or unit IRI.
* @return a QuantityValue with the specified data
*/
static quantityValue(value, unit) {
if (typeof unit === "string") {
return new QuantityValue(value, Qudt.unitRequired(unit));
}
return new QuantityValue(value, unit);
}
/**
* Converts the specified value from the unit it is in (`fromUnit`) to the specified target unit (`toUnit`).
* @param value: a Decimal, the value to convert.
* @param fromUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @param toUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @return the resulting value
*/
static convert(value, fromUnit, toUnit) {
if (!fromUnit) {
throw "Parameter 'fromUnit' is required";
}
if (!toUnit) {
throw "Parameter 'toUnit' is required";
}
const from = typeof fromUnit === "string" ? Qudt.unitRequired(fromUnit) : fromUnit;
const to = typeof toUnit === "string" ? Qudt.unitRequired(toUnit) : toUnit;
return from.convert(value, to);
}
/**
* Converts the specified QuantityValue from to the specified target unit (`toUnit`).
* @param value: a Decimal, the value to convert.
* @param fromUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @param toUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @return a QuantityValue holding the result
*/
static convertQuantityValue(from, toUnit) {
if (!from) {
throw "Parameter 'from' is required";
}
if (!toUnit) {
throw "Parameter 'toUnit' is required";
}
const to = typeof toUnit === "string" ? Qudt.unitRequired(toUnit) : toUnit;
return from.convert(to);
}
/**
* Returns `true` if the two units can be converted into each other.
* @param fromUnit a Unit or unit IRI
* @param toUnit a Unit or unit IRI
* @return a boolean indicating whether the units are convertible.
*/
static isConvertible(fromUnit, toUnit) {
const from = typeof fromUnit === "string" ? Qudt.unitRequired(fromUnit) : fromUnit;
const to = typeof toUnit === "string" ? Qudt.unitRequired(toUnit) : toUnit;
return from.isConvertible(to);
}
/**
* Returns a [Unit, Decimal] tuple containing the base unit of the specified `unit`
* along with the scale factor needed to convert values from the base unit to
* the specified unit.
*
* @param unit the unit to scale to its base
* @return a [Unit, Decimal] tuple with the base unit and the required scale factor
*/
static scaleToBaseUnit(unit) {
if (!unit.scalingOf) {
return { unit: unit, factor: new Decimal(1) };
}
const baseUnit = unit.scalingOf;
return { unit: baseUnit, factor: unit.getConversionMultiplier(baseUnit) };
}
static allUnits() {
const ret = [];
for (const unit of config.units.values()) {
ret.push(unit);
}
return ret;
}
static allQuantityKinds() {
const ret = [];
for (const quantityKind of config.quantityKinds.values()) {
ret.push(quantityKind);
}
return ret;
}
static allPrefixes() {
const ret = [];
for (const prefix of config.prefixes.values()) {
ret.push(prefix);
}
return ret;
}
}
class CaseInsensitiveUnderscoreIgnoringLabelMatcher {
constructor(searchTerm) {
this.compareForEquality = this.convert(searchTerm);
}
convert(term) {
return term.replaceAll("_", " ").toLocaleUpperCase("en-US");
}
matchesString(searchTerm) {
return this.convert(searchTerm) === this.compareForEquality;
}
matchesLangString(searchTerm) {
return this.convert(searchTerm.text) === this.compareForEquality;
}
matchesLangStrings(searchTerms) {
return searchTerms.some((st) => this.convert(st.text) === this.compareForEquality);
}
}
function getLastIriElement(iri) {
return iri.replaceAll(/.+\/([^\/]+)/g, "$1");
}
function compareUsingEquals(a, b) {
return a.equals(b);
}
function arrayEquals(left, right, cmp = (a, b) => a === b) {
return (!!left &&
!!right &&
left.length === right.length &&
left.every((e, i) => cmp(e, right[i])));
}
//# sourceMappingURL=qudtlib.js.map

@@ -19,10 +19,2 @@ import { Decimal } from "decimal.js";

}
export declare class ScaleFactor implements SupportsEquals<ScaleFactor> {
readonly factor: Decimal;
constructor(factor?: Decimal);
copy(): ScaleFactor;
multiplyBy(by: Decimal): ScaleFactor;
toString(): string;
equals(other?: ScaleFactor): boolean;
}
export declare class Prefix implements SupportsEquals<Prefix> {

@@ -40,3 +32,3 @@ iri: string;

export declare class QuantityValue implements SupportsEquals<QuantityValue> {
quantity: Decimal;
value: Decimal;
unit: Unit;

@@ -46,2 +38,3 @@ constructor(quantity: Decimal, unit: Unit);

toString(): string;
convert(to: Unit): QuantityValue;
}

@@ -117,3 +110,3 @@ export declare class QuantityKind implements SupportsEquals<QuantityKind> {

getKind(): string;
match(factorUnitSelection: FactorUnitSelection[], cumulativeExponent: number, matchedPath: Unit[], scaleFactor: ScaleFactor, matchingMode: FactorUnitMatchingMode): FactorUnitSelection[];
match(factorUnitSelection: FactorUnitSelection[], cumulativeExponent: number, matchedPath: Unit[], matchingMode: FactorUnitMatchingMode): FactorUnitSelection[];
getLeafFactorUnitsWithCumulativeExponents(): FactorUnit[];

@@ -126,4 +119,3 @@ }

readonly matchedMultiplier: Decimal;
readonly scaleFactor: ScaleFactor;
constructor(matchedFactorUnit: FactorUnit, matchedMultiplier: Decimal, matchedPath: Unit[], scaleFactor: ScaleFactor);
constructor(matchedFactorUnit: FactorUnit, matchedMultiplier: Decimal, matchedPath: Unit[]);
equals(other?: FactorUnitMatch): boolean;

@@ -145,3 +137,3 @@ toString(): string;

exponentMatches(factorUnit: FactorUnit, cumulativeExponent: number): boolean;
forMatch(factorUnit: FactorUnit, cumulativeExponent: number, matchedPath: Unit[], scaleFactor: ScaleFactor): FactorUnitSelector[];
forMatch(factorUnit: FactorUnit, cumulativeExponent: number, matchedPath: Unit[]): FactorUnitSelector[];
private calculateMatchedMultiplier;

@@ -151,4 +143,22 @@ toString(): string;

export declare class FactorUnitSelection implements SupportsEquals<FactorUnitSelection> {
/**
* If the matched units required scaling to match the unit being checked, the scale factor is
* accumulated in this property.
*/
readonly scaleFactor: Decimal;
/**
* The selectors of this selection, defining the individual units that are being searched or
* have already been found.
*/
readonly selectors: FactorUnitSelector[];
constructor(selectors: FactorUnitSelector[]);
constructor(selectors: FactorUnitSelector[], scaleFactor?: Decimal);
/**
* Returns a new FactorUnitSelection with the same selectors as this one, whose <code>
* scaleFactor</code> is this FactorUnitSelection's <code>scaleFactor</code> multiplied with the
* specified one.
*
* @param scaleFactor
* @return
*/
scale(scaleFactor: Decimal): FactorUnitSelection;
static fromFactorUnitSpec(...factorUnitSpec: (Unit | number)[]): FactorUnitSelection;

@@ -158,3 +168,14 @@ equals(other: FactorUnitSelection): boolean;

isCompleteMatch(): boolean;
forPotentialMatch(factorUnit: FactorUnit, cumulativeExponent: number, matchedPath: Unit[], scaleFactor: ScaleFactor, matchingMode: FactorUnitMatchingMode): FactorUnitSelection;
/**
* If there are matches for the specified data, return all selections resulting from such
* matches. If there are no matches, the result is an empty set
*
* @param factorUnit the factor unit to match
* @param cumulativeExponent the exponent accumulated on the path from the root unit to the
* factor unit
* @param matchedPath the path from the root unit to the factor unit
* @param mode the matching mode
* @return FactorUnitSelections resulting from the match, empty set if no matches are found.
*/
forPotentialMatch(factorUnit: FactorUnit, cumulativeExponent: number, matchedPath: Unit[], matchingMode: FactorUnitMatchingMode): FactorUnitSelection[];
}

@@ -178,3 +199,3 @@ export declare class Unit implements SupportsEquals<Unit> {

toString(): string;
match(selections: FactorUnitSelection[], cumulativeExponent: number, matchedPath: Unit[], scaleFactor: ScaleFactor, matchingMode: FactorUnitMatchingMode): FactorUnitSelection[];
match(selections: FactorUnitSelection[], cumulativeExponent: number, matchedPath: Unit[], matchingMode: FactorUnitMatchingMode): FactorUnitSelection[];
private matchFactorUnits;

@@ -201,2 +222,4 @@ private matchThisUnit;

getLeafFactorUnitsWithCumulativeExponents(): FactorUnit[];
conversionOffsetDiffers(other: Unit): boolean;
hasNonzeroConversionOffset(): boolean;
}

@@ -207,2 +230,10 @@ export declare const QUDT_UNIT_BASE_IRI = "http://qudt.org/vocab/unit/";

export declare class Qudt {
/**
* Returns the first unit found whose label matches the specified label after replacing any
* underscore with space and ignoring case (US locale). If more intricate matching is needed,
* clients can use `{@link #allUnits()}.filter(...)`.
*
* @param label the matched label
* @return the first unit found
*/
static unitFromLabel(label: string): Unit | undefined;

@@ -221,3 +252,16 @@ static unitFromLabelRequired(label: string): Unit;

static prefixIriFromLocalname(localname: string): string;
/**
* Returns the {@link Unit} identified the specified IRI. For example, <code>
* unit("http://qudt.org/vocab/unit/N-PER-M2")</code> yields `Units.N__PER__M2`,
* if that unit has been loaded;
*
* @param iri the requested unit IRI
* @return the unit or `undefined` if no unit is found
*/
static unit(unitIri: string): Unit | undefined;
/**
* Same as {@link #unit(string)} but throws an exception if no unit is found.
* @param unitIri the unit IRI
* @return the unit
*/
static unitRequired(unitIri: string): Unit;

@@ -230,3 +274,31 @@ static quantityKind(quantityKindIri: string): QuantityKind | undefined;

static quantityKindsBroad(unit: Unit): QuantityKind[];
/**
* Obtains units based on factor units, using the specified {@link FactorUnitMatchingMode}.
*
* For example,
*
* ```
* const spec = new Map<Unit, number>();
* spec.set(Units.M, 1);
* spec.set(Units.KiloGM, 1);
* spec.set(Units.SEC, -2);
* Qudt.derivedUnitsFrom Map(
* FactorUnitMatchingMode.EXACT, spec);
* ```
*
* will yield an array containing the Newton Unit ({@code Qudt.Units.N})
*
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param factorUnits a map containing unit to exponent entries.
* @return the derived units that match the given factor units
*/
static derivedUnitsFromMap(searchMode: DerivedUnitSearchMode, factorUnits: Map<Unit, number>): Unit[];
/**
* Obtains units based on factor units.
*
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param factorUnits the factor units
* @return the derived unit that match the given factor units
* @see #derivedUnitsFromMap(DerivedUnitSearchMode, Map)
*/
static derivedUnitsFromFactorUnits(searchMode: DerivedUnitSearchMode, ...factorUnits: FactorUnit[]): Unit[];

@@ -242,13 +314,91 @@ /**

static derivedUnitsFromExponentUnitPairs(searchMode: DerivedUnitSearchMode, ...factorUnitSpecs: (Unit | string | number)[]): Unit[];
/**
* @param searchMode the {@link DerivedUnitSearchMode} to use
* @param selection the factor unit selection
* @return the units that match
* @see #derivedUnitsFromMap(DerivedUnitSearchMode, Map)
*/
static derivedUnitsFromFactorUnitSelection(searchMode: DerivedUnitSearchMode, initialFactorUnitSelection: FactorUnitSelection): Unit[];
private static retainOnlyOne;
private static findMatchingUnits;
static scaledUnit(prefix: Prefix, baseUnit: Unit): Unit;
static scaledUnitFromLabels(prefixLabel: string, baseUnit: string): Unit;
/**
* Returns the unit resulting from scaling the specified `unit` with the specified `prefix`.
*
* @param prefix the prefix to use for scaling or its IRI
* @param baseUnit the unit to scale or its IRI
* @return the resulting unit
* @throws exception if no such unit is found
*/
static scale(prefix: Prefix | string, baseUnit: Unit | string): Unit;
static scaleUnitFromLabels(prefixLabel: string, baseUnit: string): Unit;
/**
* Returns the list of {@link FactorUnit}s of the specified `unit`.
*
* @param unit the unit to get factors for
* @return the factors of the unit or an empty list if the unit is not a derived unit
*/
static factorUnits(unit: Unit): FactorUnit[];
/**
* Perform mathematical simplification on factor units. For example, `
* `N per M per M -> N per M^2`
*
* @param factorUnits the factor units to simplify
* @return the simplified factor units.
*/
static simplifyFactorUnits(factorUnits: FactorUnit[]): FactorUnit[];
static unscaledUnit(unit: Unit): Unit;
static unscaledFactorUnits(factorUnits: FactorUnit[]): FactorUnit[];
static unscale(unit: Unit): Unit;
/**
* Return a list of {@link FactorUnit}s with the same exponents as the specified `factorUnits` but their base units as units.
*
* @param factorUnits the factor units to unscale
* @return the unscaled factor units
*/
static unscaleFactorUnits(factorUnits: FactorUnit[]): FactorUnit[];
/**
* Instantiates a QuantityValue.
* @param value a Decimal
* @param unit a Unit or unit IRI.
* @return a QuantityValue with the specified data
*/
static quantityValue(value: Decimal, unit: Unit | string): QuantityValue;
/**
* Converts the specified value from the unit it is in (`fromUnit`) to the specified target unit (`toUnit`).
* @param value: a Decimal, the value to convert.
* @param fromUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @param toUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @return the resulting value
*/
static convert(value: Decimal, fromUnit: Unit | string, toUnit: Unit | string): Decimal;
/**
* Converts the specified QuantityValue from to the specified target unit (`toUnit`).
* @param value: a Decimal, the value to convert.
* @param fromUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @param toUnit: a Unit or string. A string is interpreted as a Unit IRI.
* @return a QuantityValue holding the result
*/
static convertQuantityValue(from: QuantityValue, toUnit: Unit | string): QuantityValue;
/**
* Returns `true` if the two units can be converted into each other.
* @param fromUnit a Unit or unit IRI
* @param toUnit a Unit or unit IRI
* @return a boolean indicating whether the units are convertible.
*/
static isConvertible(fromUnit: Unit | string, toUnit: Unit | string): boolean;
/**
* Returns a [Unit, Decimal] tuple containing the base unit of the specified `unit`
* along with the scale factor needed to convert values from the base unit to
* the specified unit.
*
* @param unit the unit to scale to its base
* @return a [Unit, Decimal] tuple with the base unit and the required scale factor
*/
static scaleToBaseUnit(unit: Unit): {
unit: Unit;
factor: Decimal;
};
static allUnits(): Unit[];
static allQuantityKinds(): QuantityKind[];
static allPrefixes(): Prefix[];
}
export {};
//# sourceMappingURL=qudtlib.d.ts.map

22

package.json
{
"name": "@qudtlib/core",
"version": "2.0.0-preview3",
"version": "2.0.0",
"description": "Data model for QUDTLib",

@@ -34,4 +34,9 @@ "main": "dist/cjs/qudtlib.js",

"devDependencies": {
"@types/jest": "^28.1.4",
"@types/jest": "^29.2.0",
"@typescript-eslint/eslint-plugin": "^5.38.1",
"@typescript-eslint/parser": "^5.38.1",
"del": "^7.0.0",
"eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"gulp": "^4.0.2",

@@ -42,11 +47,12 @@ "gulp-cli": "^2.3.0",

"gulp-uglify": "^3.0.2",
"jest": "^28.1.2",
"lerna": "^5.6.2",
"ts-jest": "^28.0.5",
"ts-node": "^10.8.2",
"jest": "^29.2.1",
"lerna": "^6.0.1",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typescript": "^4.7.4"
},
"dependencies": {
"decimal.js": "^10.4.0"
}
"decimal.js": "10.4.2"
},
"gitHead": "11f5f30b4bacb8b52797ecf6a7e632ded6a244ec"
}
# QUDTLib: JS Unit Conversion Library based on QUDT
[Changelog](https://github.com/qudtlib/qudtlib-js/CHANGELOG.md)
Provides unit conversion and related functionality for Javascript (Typescript).

@@ -35,4 +37,4 @@

Qudt.convert(...): Convert a value
Qudt.scaledUnit(...): Scale a unit (e.g., make KiloM from M and kilo)
Qudt.unscaledUnit(..): Unscale a unit:
Qudt.scaleUnit(...): Scale a unit (e.g., make KiloM from M and kilo)
Qudt.unscaleUnit(..): Unscale a unit:
Qudt.unit(...): Get Unit by IRI

@@ -39,0 +41,0 @@ Qudt.quantityKind(...): Get QuantityKind by IRI

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc