UNPKG

@phema/cql-execution

Version:

An execution framework for the Clinical Quality Language (CQL)

291 lines (241 loc) 9.83 kB
"use strict"; function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var _require = require('../util/math'), decimalAdjust = _require.decimalAdjust, isValidDecimal = _require.isValidDecimal, overflowsOrUnderflows = _require.overflowsOrUnderflows; var _require2 = require('../util/units'), checkUnit = _require2.checkUnit, _convertUnit = _require2.convertUnit, normalizeUnitsWhenPossible = _require2.normalizeUnitsWhenPossible, convertToCQLDateUnit = _require2.convertToCQLDateUnit, getProductOfUnits = _require2.getProductOfUnits, getQuotientOfUnits = _require2.getQuotientOfUnits; var Quantity = /*#__PURE__*/function () { function Quantity(value, unit) { _classCallCheck(this, Quantity); this.value = value; this.unit = unit; if (this.value == null || isNaN(this.value)) { throw new Error('Cannot create a quantity with an undefined value'); } else if (!isValidDecimal(this.value)) { throw new Error('Cannot create a quantity with an invalid decimal value'); } // Attempt to parse the unit with UCUM. If it fails, throw a friendly error. if (this.unit != null) { var validation = checkUnit(this.unit); if (!validation.valid) { throw new Error(validation.message); } } } _createClass(Quantity, [{ key: "isQuantity", get: function get() { return true; } }, { key: "clone", value: function clone() { return new Quantity(this.value, this.unit); } }, { key: "toString", value: function toString() { return "".concat(this.value, " '").concat(this.unit, "'"); } }, { key: "sameOrBefore", value: function sameOrBefore(other) { if (other != null && other.isQuantity) { var otherVal = _convertUnit(other.value, other.unit, this.unit); if (otherVal == null) { return null; } else { return this.value <= otherVal; } } } }, { key: "sameOrAfter", value: function sameOrAfter(other) { if (other != null && other.isQuantity) { var otherVal = _convertUnit(other.value, other.unit, this.unit); if (otherVal == null) { return null; } else { return this.value >= otherVal; } } } }, { key: "after", value: function after(other) { if (other != null && other.isQuantity) { var otherVal = _convertUnit(other.value, other.unit, this.unit); if (otherVal == null) { return null; } else { return this.value > otherVal; } } } }, { key: "before", value: function before(other) { if (other != null && other.isQuantity) { var otherVal = _convertUnit(other.value, other.unit, this.unit); if (otherVal == null) { return null; } else { return this.value < otherVal; } } } }, { key: "equals", value: function equals(other) { if (other != null && other.isQuantity) { if (!this.unit && other.unit || this.unit && !other.unit) { return false; } else if (!this.unit && !other.unit) { return this.value === other.value; } else { var otherVal = _convertUnit(other.value, other.unit, this.unit); if (otherVal == null) { return null; } else { return decimalAdjust('round', this.value, -8) === otherVal; } } } } }, { key: "convertUnit", value: function convertUnit(toUnit) { var value = _convertUnit(this.value, this.unit, toUnit); // Need to pass through constructor again to catch invalid units return new Quantity(value, toUnit); } }, { key: "dividedBy", value: function dividedBy(other) { if (other == null || other === 0 || other.value === 0) { return null; } else if (!other.isQuantity) { // convert it to a quantity w/ unit 1 other = new Quantity(other, '1'); } var _normalizeUnitsWhenPo = normalizeUnitsWhenPossible(this.value, this.unit, other.value, other.unit), _normalizeUnitsWhenPo2 = _slicedToArray(_normalizeUnitsWhenPo, 4), val1 = _normalizeUnitsWhenPo2[0], unit1 = _normalizeUnitsWhenPo2[1], val2 = _normalizeUnitsWhenPo2[2], unit2 = _normalizeUnitsWhenPo2[3]; var resultValue = val1 / val2; var resultUnit = getQuotientOfUnits(unit1, unit2); // Check for invalid unit or value if (resultUnit == null || overflowsOrUnderflows(resultValue)) { return null; } return new Quantity(decimalAdjust('round', resultValue, -8), resultUnit); } }, { key: "multiplyBy", value: function multiplyBy(other) { if (other == null) { return null; } else if (!other.isQuantity) { // convert it to a quantity w/ unit 1 other = new Quantity(other, '1'); } var _normalizeUnitsWhenPo3 = normalizeUnitsWhenPossible(this.value, this.unit, other.value, other.unit), _normalizeUnitsWhenPo4 = _slicedToArray(_normalizeUnitsWhenPo3, 4), val1 = _normalizeUnitsWhenPo4[0], unit1 = _normalizeUnitsWhenPo4[1], val2 = _normalizeUnitsWhenPo4[2], unit2 = _normalizeUnitsWhenPo4[3]; var resultValue = val1 * val2; var resultUnit = getProductOfUnits(unit1, unit2); // Check for invalid unit or value if (resultUnit == null || overflowsOrUnderflows(resultValue)) { return null; } return new Quantity(decimalAdjust('round', resultValue, -8), resultUnit); } }]); return Quantity; }(); function parseQuantity(str) { var components = /([+|-]?\d+\.?\d*)\s*('(.+)')?/.exec(str); if (components != null && components[1] != null) { var value = parseFloat(components[1]); if (!isValidDecimal(value)) { return null; } var unit; if (components[3] != null) { unit = components[3].trim(); } else { unit = ''; } return new Quantity(value, unit); } else { return null; } } function doScaledAddition(a, b, scaleForB) { if (a != null && a.isQuantity && b != null && b.isQuantity) { var _normalizeUnitsWhenPo5 = normalizeUnitsWhenPossible(a.value, a.unit, b.value * scaleForB, b.unit), _normalizeUnitsWhenPo6 = _slicedToArray(_normalizeUnitsWhenPo5, 4), val1 = _normalizeUnitsWhenPo6[0], unit1 = _normalizeUnitsWhenPo6[1], val2 = _normalizeUnitsWhenPo6[2], unit2 = _normalizeUnitsWhenPo6[3]; if (unit1 !== unit2) { // not compatible units, so we can't do addition return null; } var sum = val1 + val2; if (overflowsOrUnderflows(sum)) { return null; } return new Quantity(sum, unit1); } else if (a.copy && a.add) { // Date / DateTime require a CQL time unit var cqlUnitB = convertToCQLDateUnit(b.unit) || b.unit; return a.copy().add(b.value * scaleForB, cqlUnitB); } else { throw new Error('Unsupported argument types.'); } } function doAddition(a, b) { return doScaledAddition(a, b, 1); } function doSubtraction(a, b) { return doScaledAddition(a, b, -1); } function doDivision(a, b) { if (a != null && a.isQuantity) { return a.dividedBy(b); } } function doMultiplication(a, b) { if (a != null && a.isQuantity) { return a.multiplyBy(b); } else { return b.multiplyBy(a); } } module.exports = { Quantity: Quantity, parseQuantity: parseQuantity, doAddition: doAddition, doSubtraction: doSubtraction, doDivision: doDivision, doMultiplication: doMultiplication };