|
|
@@ -8,57 +8,53 @@
|
|
|
* @constructor
|
|
|
**/
|
|
|
var AvgAccumulator = module.exports = function AvgAccumulator(){
|
|
|
- this.subTotalName = "subTotal";
|
|
|
- this.countName = "count";
|
|
|
- this.totalIsANumber = true;
|
|
|
- this.total = 0;
|
|
|
- this.count = 0;
|
|
|
+ this.reset();
|
|
|
base.call(this);
|
|
|
}, klass = AvgAccumulator, Accumulator = require("./Accumulator"), base = Accumulator, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
|
|
|
|
|
|
-// NOTE: Skipping the create function, using the constructor instead
|
|
|
-
|
|
|
-// DEPENDENCIES
|
|
|
var Value = require("../Value");
|
|
|
|
|
|
-// MEMBER FUNCTIONS
|
|
|
+var SUB_TOTAL_NAME = "subTotal";
|
|
|
+var COUNT_NAME = "count";
|
|
|
+
|
|
|
proto.processInternal = function processInternal(input, merging) {
|
|
|
if (!merging) {
|
|
|
- if (typeof input !== "number") {
|
|
|
- return;
|
|
|
- }
|
|
|
- this.total += input;
|
|
|
- this.count += 1;
|
|
|
+ // non numeric types have no impact on average
|
|
|
+ if (typeof input != "number") return;
|
|
|
+
|
|
|
+ this._total += input;
|
|
|
+ this._count += 1;
|
|
|
} else {
|
|
|
- Value.verifyDocument(input);
|
|
|
- this.total += input[this.subTotalName];
|
|
|
- this.count += input[this.countName];
|
|
|
+ // We expect an object that contains both a subtotal and a count.
|
|
|
+ // This is what getValue(true) produced below.
|
|
|
+ if (!(input instanceof Object)) throw new Error("Assertion error");
|
|
|
+ this._total += input[SUB_TOTAL_NAME];
|
|
|
+ this._count += input[COUNT_NAME];
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-proto.getValue = function getValue(toBeMerged){
|
|
|
+klass.create = function create() {
|
|
|
+ return new AvgAccumulator();
|
|
|
+};
|
|
|
+
|
|
|
+proto.getValue = function getValue(toBeMerged) {
|
|
|
if (!toBeMerged) {
|
|
|
- if (this.totalIsANumber && this.count > 0) {
|
|
|
- return this.total / this.count;
|
|
|
- } else if (this.count === 0) {
|
|
|
- return 0;
|
|
|
- } else {
|
|
|
- throw new Error("$sum resulted in a non-numeric type");
|
|
|
- }
|
|
|
+ if (this._count === 0)
|
|
|
+ return 0.0;
|
|
|
+ return this._total / this._count;
|
|
|
} else {
|
|
|
- var ret = {};
|
|
|
- ret[this.subTotalName] = this.total;
|
|
|
- ret[this.countName] = this.count;
|
|
|
-
|
|
|
- return ret;
|
|
|
+ var doc = {};
|
|
|
+ doc[SUB_TOTAL_NAME] = this._total;
|
|
|
+ doc[COUNT_NAME] = this._count;
|
|
|
+ return doc;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
proto.reset = function reset() {
|
|
|
- this.total = 0;
|
|
|
- this.count = 0;
|
|
|
+ this._total = 0;
|
|
|
+ this._count = 0;
|
|
|
};
|
|
|
|
|
|
-proto.getOpName = function getOpName(){
|
|
|
+proto.getOpName = function getOpName() {
|
|
|
return "$avg";
|
|
|
};
|