cql-execution
Version:
An execution framework for the Clinical Quality Language (CQL)
439 lines (392 loc) • 11.5 kB
JavaScript
// Generated by CoffeeScript 1.12.7
(function() {
var Code, Exception, Expression, FunctionRef, Quantity, ValueSet, build, clean_unit, coalesceToOne, convert_value, createQuantity, decimalAdjust, doScaledAddition, isValidDecimal, is_valid_ucum_unit, ref, ref1, ucum, ucum_multiply, ucum_time_units, ucum_to_cql_units, ucum_unit, unitValidityCache, units_to_string,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
Expression = require('./expression').Expression;
FunctionRef = require('./reusable').FunctionRef;
ref = require('../util/math'), decimalAdjust = ref.decimalAdjust, isValidDecimal = ref.isValidDecimal;
ref1 = require('../datatypes/datatypes'), ValueSet = ref1.ValueSet, Code = ref1.Code;
Exception = require('../datatypes/exception').Exception;
build = require('./builder').build;
ucum = require('ucum');
module.exports.Quantity = Quantity = (function(superClass) {
extend(Quantity, superClass);
function Quantity(json) {
Quantity.__super__.constructor.apply(this, arguments);
this.unit = json.unit;
if (json.value == null) {
throw new Error("Cannot create a quantity with an undefined value");
} else {
this.value = parseFloat(json.value);
if (!isValidDecimal(this.value)) {
throw new Error("Cannot create a quantity with an invalid decimal value");
}
}
if ((this.unit != null) && !is_valid_ucum_unit(this.unit)) {
throw new Error("\'" + this.unit + "\' is not a valid UCUM unit.");
}
}
Object.defineProperties(Quantity.prototype, {
isQuantity: {
get: function() {
return true;
}
}
});
Quantity.prototype.clone = function() {
return new Quantity({
value: this.value,
unit: this.unit
});
};
Quantity.prototype.exec = function(ctx) {
return this;
};
Quantity.prototype.toString = function() {
return this.value + " '" + this.unit + "'";
};
Quantity.prototype.sameOrBefore = function(other) {
var other_v;
if (other instanceof Quantity) {
other_v = convert_value(other.value, ucum_unit(other.unit), ucum_unit(this.unit));
if (other_v == null) {
return null;
} else {
return this.value <= other_v;
}
}
};
Quantity.prototype.sameOrAfter = function(other) {
var other_v;
if (other instanceof Quantity) {
other_v = convert_value(other.value, ucum_unit(other.unit), ucum_unit(this.unit));
if (other_v == null) {
return null;
} else {
return this.value >= other_v;
}
}
};
Quantity.prototype.after = function(other) {
var other_v;
if (other instanceof Quantity) {
other_v = convert_value(other.value, ucum_unit(other.unit), ucum_unit(this.unit));
if (other_v == null) {
return null;
} else {
return this.value > other_v;
}
}
};
Quantity.prototype.before = function(other) {
var other_v;
if (other instanceof Quantity) {
other_v = convert_value(other.value, ucum_unit(other.unit), ucum_unit(this.unit));
if (other_v == null) {
return null;
} else {
return this.value < other_v;
}
}
};
Quantity.prototype.equals = function(other) {
var other_v;
if (other instanceof Quantity) {
if ((!this.unit && other.unit) || (this.unit && !other.unit)) {
return false;
} else if (!this.unit && !other.unit) {
return this.value === other.value;
} else {
other_v = convert_value(other.value, ucum_unit(other.unit), ucum_unit(this.unit));
if (other_v == null) {
return null;
} else {
return decimalAdjust("round", this.value, -8) === decimalAdjust("round", other_v, -8);
}
}
}
};
Quantity.prototype.convertUnits = function(to_units) {
return convert_value(this.value, this.unit, to_units);
};
Quantity.prototype.dividedBy = function(other) {
return this.multiplyDivide(other, "/");
};
Quantity.prototype.multiplyBy = function(other) {
return this.multiplyDivide(other, ".");
};
Quantity.prototype.multiplyDivide = function(other, operator) {
var a, b, can_val, other_can_value, ucum_value, value;
if (other instanceof Quantity) {
a = this.unit != null ? this : new Quantity({
value: this.value,
unit: "1"
});
b = other.unit != null ? other : new Quantity({
value: other.value,
unit: "1"
});
can_val = a.to_ucum();
other_can_value = b.to_ucum();
ucum_value = ucum_multiply(can_val, [[operator, other_can_value]]);
try {
return createQuantity(ucum_value.value, units_to_string(ucum_value.units));
} catch (error) {
return null;
}
} else {
value = operator === "/" ? this.value / other : this.value * other;
try {
return createQuantity(decimalAdjust("round", value, -8), coalesceToOne(this.unit));
} catch (error) {
return null;
}
}
};
Quantity.prototype.to_ucum = function() {
var u;
u = ucum.parse(ucum_unit(this.unit));
u.value *= this.value;
return u;
};
return Quantity;
})(Expression);
clean_unit = function(units) {
if (ucum_time_units[units]) {
return ucum_to_cql_units[ucum_time_units[units]];
} else {
return units;
}
};
ucum_time_units = {
'years': 'a_g',
'year': 'a_g',
'YEARS': 'a_g',
'YEAR': 'a_g',
'a_g': 'a_g',
'a': 'a_j',
'ANN': 'a_j',
'ann': 'a_j',
'A': 'a_j',
'a_j': 'a_j',
'months': 'mo_g',
'month': 'mo_g',
'mo_g': 'mo_g',
'mo': 'mo_j',
'MO': 'mo_j',
'mo_j': 'mo_j',
'weeks': 'wk',
'week': 'wk',
'wk': 'wk',
'WK': 'wk',
'days': 'd',
'day': 'd',
'd': 'd',
'D': 'd',
'hours': 'h',
'hour': 'h',
'h': 'h',
'H': 'h',
'minutes': 'min',
'minute': 'min',
'min': 'min',
'MIN': 'min',
'seconds': 's',
'second': 's',
's': 's',
'S': 's',
'milliseconds': 'ms',
'millisecond': 'ms',
'ms': 'ms',
'MS': 'ms'
};
ucum_to_cql_units = {
'a_j': 'year',
'a_g': 'year',
'mo_j': 'month',
'mo_g': 'month',
'wk': 'week',
'd': 'day',
'h': 'hour',
'min': 'minute',
's': 'second',
'ms': 'millisecond'
};
ucum_unit = function(unit) {
return ucum_time_units[unit] || unit || '';
};
convert_value = function(value, from, to) {
var e;
try {
if (from === to) {
return value;
} else {
return decimalAdjust("round", ucum.convert(value, ucum_unit(from), ucum_unit(to)), -8);
}
} catch (error) {
e = error;
return null;
}
};
unitValidityCache = {};
is_valid_ucum_unit = function(unit) {
if (unitValidityCache.hasOwnProperty(unit)) {
return unitValidityCache[unit];
} else {
try {
ucum.parse(ucum_unit(unit));
unitValidityCache[unit] = true;
return true;
} catch (error) {
unitValidityCache[unit] = false;
return false;
}
}
};
module.exports.convert_value = convert_value;
units_to_string = function(units) {
var denom, i, key, len, numer, pow, ref2, str, unit_string, v;
if (units == null) {
units = {};
}
numer = [];
denom = [];
ref2 = Object.keys(units);
for (i = 0, len = ref2.length; i < len; i++) {
key = ref2[i];
v = units[key];
pow = Math.abs(v);
str = pow === 1 ? key : key + pow;
if (v < 0) {
denom.push(str);
} else {
numer.push(str);
}
}
unit_string = "";
unit_string += numer.join(".");
if (denom.length > 0) {
unit_string += "/" + denom.join("/");
}
if (unit_string === "") {
return "1";
} else {
return unit_string;
}
};
ucum_multiply = function(t, ms) {
var b, i, k, len, mterm, ref2, ret, sign, v;
if (ms == null) {
ms = [];
}
if (ms.length === 0) {
return t;
}
ret = t;
for (i = 0, len = ms.length; i < len; i++) {
mterm = ms[i];
sign = mterm[0] === '.' ? 1 : -1;
b = mterm[1];
ret.value *= Math.pow(b.value, sign);
ref2 = b.units;
for (k in ref2) {
v = ref2[k];
ret.units[k] = ret.units[k] || 0;
ret.units[k] = ret.units[k] + sign * v;
if (ret.units[k] === 0) {
delete ret.units[k];
}
}
}
return ret;
};
module.exports.createQuantity = createQuantity = function(value, unit) {
return new Quantity({
value: value,
unit: unit
});
};
module.exports.parseQuantity = function(str) {
var components, unit, value;
components = /([+|-]?\d+\.?\d*)\s*('(.+)')?/.exec(str);
if ((components != null) && (components[1] != null)) {
value = parseFloat(components[1]);
if (!isValidDecimal(value)) {
return null;
}
if (components[3] != null) {
unit = components[3].trim();
} else {
unit = "";
}
return new Quantity({
value: value,
unit: unit
});
} else {
return null;
}
};
doScaledAddition = function(a, b, scaleForB) {
var a_unit, b_unit, ref2, val;
if (a instanceof Quantity && b instanceof Quantity) {
ref2 = [coalesceToOne(a.unit), coalesceToOne(b.unit)], a_unit = ref2[0], b_unit = ref2[1];
val = convert_value(b.value * scaleForB, b_unit, a_unit);
if (val == null) {
return null;
}
return new Quantity({
unit: a_unit,
value: a.value + val
});
} else if (a.copy && a.add) {
b_unit = b instanceof Quantity ? coalesceToOne(b.unit) : b.unit;
return a.copy().add(b.value * scaleForB, clean_unit(b_unit));
} else {
throw new Error("Unsupported argument types.");
}
};
module.exports.doAddition = function(a, b) {
return doScaledAddition(a, b, 1);
};
module.exports.doSubtraction = function(a, b) {
return doScaledAddition(a, b, -1);
};
module.exports.doDivision = function(a, b) {
if (a instanceof Quantity) {
return a.dividedBy(b);
}
};
module.exports.doMultiplication = function(a, b) {
if (a instanceof Quantity) {
return a.multiplyBy(b);
} else {
return b.multiplyBy(a);
}
};
coalesceToOne = function(o) {
if ((o == null) || ((o.trim != null) && !o.trim())) {
return '1';
} else {
return o;
}
};
module.exports.compare_units = function(unit_a, unit_b) {
var c, e;
try {
c = ucum.convert(1, ucum_unit(unit_a), ucum_unit(unit_b));
if (c > 1) {
return 1;
}
if (c < 1) {
return -1;
}
return 0;
} catch (error) {
e = error;
return null;
}
};
}).call(this);
//# sourceMappingURL=quantity.js.map