UNPKG

foobot-graphql

Version:

GraphQL server for Foobot device data.

149 lines (129 loc) 4.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); exports.bucketize = bucketize; exports.average = average; exports.averageBucket = averageBucket; exports.toAveragedData = toAveragedData; var _decimal = require('decimal.js'); var _decimal2 = _interopRequireDefault(_decimal); var _client = require('./client'); var _client2 = _interopRequireDefault(_client); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Instead of requesting averaged data from the API, which uses up our request * limit, we can instead always request the highest-resolution data and perform * the averaging ourselves. Not only will this help stay under the request * limit, but it will also be faster since we don't need to fetch data we * already have. This module implements helpers for averaging data as reasonably * close to the real API as possible, so that results are indistinguishable * from the real thing. * * Run this file as a standalone script to compare our results with live API * results. */ var debug = require('debug')('foobot-graphql:average-by'); /** * Given an array of datapoints, group them into buckets using `averageBy` to * determine the bucket size. */ function bucketize(datapoints, period, averageBy) { datapoints = datapoints.slice(); averageBy = averageBy || 300; var bucket = []; var buckets = [bucket]; var lastTime = datapoints[datapoints.length - 1][0]; var cutoff = lastTime - period + averageBy; while (datapoints.length) { var datapoint = datapoints[0]; if (datapoint[0] < cutoff) { datapoints.shift(); bucket.push([cutoff - averageBy].concat((0, _toConsumableArray3.default)(datapoint.slice(1)))); } else { cutoff += averageBy; bucket = []; buckets.push(bucket); } } var beforeLength = buckets.length; buckets = buckets.filter(function (bucket) { return bucket.length !== 0; }); var afterLength = buckets.length; var removed = beforeLength - afterLength; debug('Bucketizing resulted in ' + afterLength + ' bucket(s) (' + removed + ' removed).'); return buckets; } /** * Return the average of the `data` array, calculated using the arbitrary * precision Decimal type to avoid summation errors. */ function average(data) { if (data.length) { var sum = data.reduce(function (sum, x) { return sum.plus(x); }, new _decimal2.default(0)); var avg = sum.dividedBy(data.length); return parseFloat(avg.toPrecision(9)); } return 0; } function averageBucket(datapoints) { var first = datapoints[0]; if (first) { return first.map(function (value, i) { return i === 0 ? value : average(datapoints.map(function (datapoint) { return datapoint[i]; })); }); } return []; } function toAveragedData(data, period, averageBy) { debug('Averaging dataset. period=' + period + ' averageBy=' + averageBy); var buckets = bucketize(data.datapoints, period, averageBy); var datapoints = buckets.map(averageBucket); var first = datapoints[0]; var last = datapoints[datapoints.length - 1]; return (0, _extends3.default)({}, data, { start: first ? first[0] : null, end: last ? last[0] : null, datapoints: datapoints }); } if (require.main === module) { (function () { require('dotenv').config(); var _require = require('./util'), logObject = _require.logObject, logError = _require.logError, safeExit = _require.safeExit; var client = new _client2.default(); var uuid = process.argv[2]; var period = parseInt(process.argv[3] || 0, 10); var averageBy = parseInt(process.argv[4] || 300, 10); client.datapoints(uuid, { period: period, averageBy: averageBy }).then(function (data) { console.log('API result:'); logObject(data.datapoints.map(function (datapoint) { return [new Date(datapoint[0] * 1000)].concat(datapoint.slice(1)); })); return client.datapoints(uuid, { period: period, averageBy: 0 }); }).then(function (data) { console.log('Local result:'); if (averageBy >= 300) { data = toAveragedData(data, period, averageBy); } logObject(data.datapoints.map(function (datapoint) { return [new Date(datapoint[0] * 1000)].concat(datapoint.slice(1)); })); }).catch(function (err) { logError(err); safeExit(1); }); })(); }