cql-execution
Version:
An execution framework for the Clinical Quality Language (CQL)
461 lines (419 loc) • 17.2 kB
JavaScript
// Generated by CoffeeScript 1.12.7
(function() {
var DateTime, Interval, ThreeValuedLogic, Uncertainty, cmp, maxValueForInstance, minValueForInstance, predecessor, ref, successor;
DateTime = require('./datetime').DateTime;
Uncertainty = require('./uncertainty').Uncertainty;
ThreeValuedLogic = require('./logic').ThreeValuedLogic;
ref = require('../util/math'), successor = ref.successor, predecessor = ref.predecessor, maxValueForInstance = ref.maxValueForInstance, minValueForInstance = ref.minValueForInstance;
cmp = require('../util/comparison');
module.exports.Interval = Interval = (function() {
var areDateTimes, areNumeric, highestNumericUncertainty, lowestNumericUncertainty;
function Interval(low1, high1, lowClosed, highClosed) {
this.low = low1;
this.high = high1;
this.lowClosed = lowClosed != null ? lowClosed : true;
this.highClosed = highClosed != null ? highClosed : true;
}
Object.defineProperties(Interval.prototype, {
isInterval: {
get: function() {
return true;
}
}
});
Interval.prototype.copy = function() {
var newHigh, newLow;
newLow = this.low;
newHigh = this.high;
if ((this.low != null) && typeof this.low.copy === 'function') {
newLow = this.low.copy();
}
if ((this.high != null) && typeof this.high.copy === 'function') {
newHigh = this.high.copy();
}
return new Interval(newLow, newHigh, this.lowClosed, this.highClosed);
};
Interval.prototype.contains = function(item, precision) {
var closed;
if (item instanceof Interval) {
throw new Error("Argument to contains must be a point");
}
closed = this.toClosed();
return ThreeValuedLogic.and(cmp.lessThanOrEquals(closed.low, item, precision), cmp.greaterThanOrEquals(closed.high, item, precision));
};
Interval.prototype.properlyIncludes = function(other, precision) {
if (!(other instanceof Interval)) {
throw new Error("Argument to properlyIncludes must be an interval");
}
return ThreeValuedLogic.and(this.includes(other, precision), ThreeValuedLogic.not(other.includes(this, precision)));
};
Interval.prototype.includes = function(other, precision) {
var a, b;
if (!(other instanceof Interval)) {
return this.contains(other, precision);
}
a = this.toClosed();
b = other.toClosed();
return ThreeValuedLogic.and(cmp.lessThanOrEquals(a.low, b.low, precision), cmp.greaterThanOrEquals(a.high, b.high, precision));
};
Interval.prototype.includedIn = function(other, precision) {
if (!(other instanceof Interval)) {
return this.contains(other, precision);
} else {
return other.includes(this);
}
};
Interval.prototype.overlaps = function(item, precision) {
var closed, high, itemClosed, low, ref1;
closed = this.toClosed();
ref1 = item instanceof Interval ? (itemClosed = item.toClosed(), [itemClosed.low, itemClosed.high]) : [item, item], low = ref1[0], high = ref1[1];
return ThreeValuedLogic.and(cmp.lessThanOrEquals(closed.low, high, precision), cmp.greaterThanOrEquals(closed.high, low, precision));
};
Interval.prototype.overlapsAfter = function(item, precision) {
var closed, high;
closed = this.toClosed();
high = item instanceof Interval ? item.toClosed().high : item;
return ThreeValuedLogic.and(cmp.lessThanOrEquals(closed.low, high, precision), cmp.greaterThan(closed.high, high, precision));
};
Interval.prototype.overlapsBefore = function(item, precision) {
var closed, low;
closed = this.toClosed();
low = item instanceof Interval ? item.toClosed().low : item;
return ThreeValuedLogic.and(cmp.lessThan(closed.low, low, precision), cmp.greaterThanOrEquals(closed.high, low, precision));
};
areDateTimes = function(x, y) {
return [x, y].every(function(z) {
return z instanceof DateTime;
});
};
areNumeric = function(x, y) {
return [x, y].every(function(z) {
return typeof z === 'number' || (z instanceof Uncertainty && typeof z.low === 'number');
});
};
lowestNumericUncertainty = function(x, y) {
var high, low;
if (!(x instanceof Uncertainty)) {
x = new Uncertainty(x);
}
if (!(y instanceof Uncertainty)) {
y = new Uncertainty(y);
}
low = x.low < y.low ? x.low : y.low;
high = x.high < y.high ? x.high : y.high;
if (low !== high) {
return new Uncertainty(low, high);
} else {
return low;
}
};
highestNumericUncertainty = function(x, y) {
var high, low;
if (!(x instanceof Uncertainty)) {
x = new Uncertainty(x);
}
if (!(y instanceof Uncertainty)) {
y = new Uncertainty(y);
}
low = x.low > y.low ? x.low : y.low;
high = x.high > y.high ? x.high : y.high;
if (low !== high) {
return new Uncertainty(low, high);
} else {
return low;
}
};
Interval.prototype.union = function(other) {
var a, b, h, hc, l, lc, ref1, ref2, ref3;
if (!(other instanceof Interval)) {
throw new Error("Argument to union must be an interval");
}
if (this.overlaps(other) || this.meets(other)) {
ref1 = [this.toClosed(), other.toClosed()], a = ref1[0], b = ref1[1];
ref2 = (function() {
switch (false) {
case !cmp.lessThanOrEquals(a.low, b.low):
return [this.low, this.lowClosed];
case !cmp.greaterThanOrEquals(a.low, b.low):
return [other.low, other.lowClosed];
case !areNumeric(a.low, b.low):
return [lowestNumericUncertainty(a.low, b.low), true];
case !(areDateTimes(a.low, b.low) && a.low.isMorePrecise(b.low)):
return [other.low, other.lowClosed];
default:
return [this.low, this.lowClosed];
}
}).call(this), l = ref2[0], lc = ref2[1];
ref3 = (function() {
switch (false) {
case !cmp.greaterThanOrEquals(a.high, b.high):
return [this.high, this.highClosed];
case !cmp.lessThanOrEquals(a.high, b.high):
return [other.high, other.highClosed];
case !areNumeric(a.high, b.high):
return [highestNumericUncertainty(a.high, b.high), true];
case !(areDateTimes(a.high, b.high) && a.high.isMorePrecise(b.high)):
return [other.high, other.highClosed];
default:
return [this.high, this.highClosed];
}
}).call(this), h = ref3[0], hc = ref3[1];
return new Interval(l, h, lc, hc);
} else {
return null;
}
};
Interval.prototype.intersect = function(other) {
var a, b, h, hc, l, lc, ref1, ref2, ref3;
if (!(other instanceof Interval)) {
throw new Error("Argument to union must be an interval");
}
if (this.overlaps(other)) {
ref1 = [this.toClosed(), other.toClosed()], a = ref1[0], b = ref1[1];
ref2 = (function() {
switch (false) {
case !cmp.greaterThanOrEquals(a.low, b.low):
return [this.low, this.lowClosed];
case !cmp.lessThanOrEquals(a.low, b.low):
return [other.low, other.lowClosed];
case !areNumeric(a.low, b.low):
return [highestNumericUncertainty(a.low, b.low), true];
case !(areDateTimes(a.low, b.low) && b.low.isMorePrecise(a.low)):
return [other.low, other.lowClosed];
default:
return [this.low, this.lowClosed];
}
}).call(this), l = ref2[0], lc = ref2[1];
ref3 = (function() {
switch (false) {
case !cmp.lessThanOrEquals(a.high, b.high):
return [this.high, this.highClosed];
case !cmp.greaterThanOrEquals(a.high, b.high):
return [other.high, other.highClosed];
case !areNumeric(a.high, b.high):
return [lowestNumericUncertainty(a.high, b.high), true];
case !(areDateTimes(a.high, b.high) && b.high.isMorePrecise(a.high)):
return [other.high, other.highClosed];
default:
return [this.high, this.highClosed];
}
}).call(this), h = ref3[0], hc = ref3[1];
return new Interval(l, h, lc, hc);
} else {
return null;
}
};
Interval.prototype.except = function(other) {
var ol, ola, olb;
if (other === null) {
return null;
}
if (!(other instanceof Interval)) {
throw new Error("Argument to except must be an interval");
}
ol = this.overlaps(other);
if (ol === true) {
olb = this.overlapsBefore(other);
ola = this.overlapsAfter(other);
if (olb === true && ola === false) {
return new Interval(this.low, other.low, this.lowClosed, !other.lowClosed);
} else if (ola === true && olb === false) {
return new Interval(other.high, this.high, !other.highClosed, this.highClosed);
} else {
return null;
}
} else if (ol === false) {
return this;
} else {
return null;
}
};
Interval.prototype.sameAs = function(other, precision) {
if (((this.low != null) && (other.low != null) && (this.high == null) && (other.high != null) && !this.highClosed) || ((this.low != null) && (other.low != null) && (this.high != null) && (other.high == null) && !other.highClosed) || ((this.low != null) && (other.low != null) && (this.high == null) && (other.high == null) && !other.highClosed && !this.highClosed)) {
if (typeof this.low === 'number') {
if (!(this.start() === other.start())) {
return false;
}
} else {
if (!(this.start().sameAs(other.start(), precision))) {
return false;
}
}
} else if (((this.low != null) && (other.low == null) && (this.high != null) && (other.high != null)) || ((this.low == null) && (other.low != null) && (this.high != null) && (other.high != null)) || ((this.low == null) && (other.low == null) && (this.high != null) && (other.high != null))) {
if (typeof this.high === 'number') {
if (!(this.end() === other.end())) {
return false;
}
} else {
if (!(this.end().sameAs(other.end(), precision))) {
return false;
}
}
}
if (((this.low == null) && !this.lowClosed) || ((this.high == null) && !this.highClosed) || ((other.low == null) && !other.lowClosed) || ((other.high == null) && !other.highClosed)) {
return null;
}
if (this.lowClosed && (this.low == null) && this.highClosed && (this.high == null)) {
return other.lowClosed && (other.low == null) && other.highClosed && (other.high == null);
}
if (other.lowClosed && (other.low == null) && other.highClosed && (other.high == null)) {
return false;
}
if (typeof this.low === 'number') {
return this.start() === other.start() && this.end() === other.end();
} else {
return this.start().sameAs(other.start(), precision) && this.end().sameAs(other.end(), precision);
}
};
Interval.prototype.equals = function(other) {
var a, b, ref1;
if (other instanceof Interval) {
ref1 = [this.toClosed(), other.toClosed()], a = ref1[0], b = ref1[1];
return ThreeValuedLogic.and(cmp.equals(a.low, b.low), cmp.equals(a.high, b.high));
} else {
return false;
}
};
Interval.prototype.after = function(other, precision) {
var closed;
closed = this.toClosed();
if (!!other.toClosed) {
return cmp.greaterThan(closed.low, other.toClosed().high, precision);
} else {
return cmp.greaterThan(closed.low, other, precision);
}
};
Interval.prototype.before = function(other, precision) {
var closed;
closed = this.toClosed();
if (!!other.toClosed) {
return cmp.lessThan(closed.high, other.toClosed().low, precision);
} else {
return cmp.lessThan(closed.high, other, precision);
}
};
Interval.prototype.meets = function(other, precision) {
return ThreeValuedLogic.or(this.meetsBefore(other, precision), this.meetsAfter(other, precision));
};
Interval.prototype.meetsAfter = function(other, precision) {
var ref1;
try {
if ((precision != null) && this.low instanceof DateTime) {
return this.toClosed().low.sameAs((ref1 = other.toClosed().high) != null ? ref1.add(1, precision) : void 0, precision);
} else {
return cmp.equals(this.toClosed().low, successor(other.toClosed().high));
}
} catch (error) {
return false;
}
};
Interval.prototype.meetsBefore = function(other, precision) {
var ref1;
try {
if ((precision != null) && this.high instanceof DateTime) {
return this.toClosed().high.sameAs((ref1 = other.toClosed().low) != null ? ref1.add(-1, precision) : void 0, precision);
} else {
return cmp.equals(this.toClosed().high, predecessor(other.toClosed().low));
}
} catch (error) {
return false;
}
};
Interval.prototype.start = function() {
if (this.low == null) {
if (this.lowClosed) {
return minValueForInstance(this.high);
} else {
return this.low;
}
}
return this.toClosed().low;
};
Interval.prototype.end = function() {
if (this.high == null) {
if (this.highClosed) {
return maxValueForInstance(this.low);
} else {
return this.high;
}
}
return this.toClosed().high;
};
Interval.prototype.starts = function(other, precision) {
var endLessThanOrEqual, startEqual;
if ((precision != null) && this.low instanceof DateTime) {
startEqual = this.low.sameAs(other.low, precision);
} else {
startEqual = cmp.equals(this.low, other.low);
}
endLessThanOrEqual = cmp.lessThanOrEquals(this.high, other.high, precision);
return startEqual && endLessThanOrEqual;
};
Interval.prototype.ends = function(other, precision) {
var endEqual, startGreaterThanOrEqual;
startGreaterThanOrEqual = cmp.greaterThanOrEquals(this.low, other.low, precision);
if ((precision != null) && this.low instanceof DateTime) {
endEqual = this.high.sameAs(other.high, precision);
} else {
endEqual = cmp.equals(this.high, other.high);
}
return startGreaterThanOrEqual && endEqual;
};
Interval.prototype.width = function() {
var closed, diff;
if (this.low instanceof DateTime || this.high instanceof DateTime) {
throw new Error("Width of DateTime intervals is not supported");
}
closed = this.toClosed();
if (closed.low instanceof Uncertainty || closed.high instanceof Uncertainty) {
return null;
} else {
diff = Math.abs(closed.high - closed.low);
return Math.round(diff * Math.pow(10, 8)) / Math.pow(10, 8);
}
};
Interval.prototype.toClosed = function() {
var high, low, point, ref1;
point = (ref1 = this.low) != null ? ref1 : this.high;
if (typeof point === 'number' || point instanceof DateTime || (point != null ? point.isQuantity : void 0) || (point != null ? point.isDate : void 0)) {
low = (function() {
switch (false) {
case !(this.lowClosed && (this.low == null)):
return minValueForInstance(point);
case !(!this.lowClosed && (this.low != null)):
return successor(this.low);
default:
return this.low;
}
}).call(this);
high = (function() {
switch (false) {
case !(this.highClosed && (this.high == null)):
return maxValueForInstance(point);
case !(!this.highClosed && (this.high != null)):
return predecessor(this.high);
default:
return this.high;
}
}).call(this);
if (low == null) {
low = new Uncertainty(minValueForInstance(point), high);
}
if (high == null) {
high = new Uncertainty(low, maxValueForInstance(point));
}
return new Interval(low, high, true, true);
} else {
return new Interval(this.low, this.high, true, true);
}
};
Interval.prototype.toString = function() {
var end, start;
start = this.lowClosed ? '[' : '(';
end = this.highClosed ? ']' : ')';
return start + this.low.toString() + ', ' + this.high.toString() + end;
};
return Interval;
})();
}).call(this);
//# sourceMappingURL=interval.js.map