mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
* Cherry picks the ES language changes from #4690 * Fix small issues found in linting * * Fix all but one eslint complaint in the bundled code * Add eslint and js-beautify rc files into the repo
215 lines
6.4 KiB
JavaScript
215 lines
6.4 KiB
JavaScript
'use strict';
|
|
|
|
var times = require('../times');
|
|
|
|
var success = {
|
|
name: 'success'
|
|
, label: 'Weekly success'
|
|
, pluginType: 'report'
|
|
};
|
|
|
|
function init () {
|
|
return success;
|
|
}
|
|
|
|
module.exports = init;
|
|
|
|
success.html = function html (client) {
|
|
var translate = client.translate;
|
|
var ret =
|
|
'<h2>' + translate('Weekly Success') + '</h2>' +
|
|
'<div id="success-grid"></div>';
|
|
return ret;
|
|
};
|
|
|
|
success.css =
|
|
`#success-placeholder td {
|
|
border: 1px #ccc solid;
|
|
margin: 0;
|
|
padding: 1px;
|
|
text-align:center;
|
|
}
|
|
#success-placeholder .bad {
|
|
background-color: #fcc;
|
|
}
|
|
#success-placeholder .good {
|
|
background-color: #cfc;
|
|
}
|
|
#success-placeholder th:first-child {
|
|
width: 30%;
|
|
}
|
|
#success-placeholder th {
|
|
width: 10%;
|
|
}
|
|
#success-placeholder table {
|
|
width: 100%;
|
|
}`;
|
|
|
|
success.report = function report_success (datastorage, sorteddaystoshow, options) {
|
|
var Nightscout = window.Nightscout;
|
|
var client = Nightscout.client;
|
|
var translate = client.translate;
|
|
|
|
var ss = require('simple-statistics');
|
|
|
|
var low = options.targetLow
|
|
, high = options.targetHigh;
|
|
|
|
var data = datastorage.allstatsrecords;
|
|
|
|
var now = Date.now();
|
|
var period = 7 * times.hours(24).msecs;
|
|
var firstDataPoint = data.reduce(function(min, record) {
|
|
return Math.min(min, record.displayTime);
|
|
}, Number.MAX_VALUE);
|
|
if (firstDataPoint < 1390000000000) {
|
|
firstDataPoint = 1390000000000;
|
|
}
|
|
var quarters = Math.floor((Date.now() - firstDataPoint) / period);
|
|
|
|
var grid = $('#success-grid');
|
|
grid.empty();
|
|
var table = $('<table/>');
|
|
|
|
if (quarters === 0) {
|
|
// insufficent data
|
|
grid.append('<p>' + translate('There is not sufficient data to run this report. Select more days.') + '</p>');
|
|
return;
|
|
}
|
|
|
|
var dim = function(n) {
|
|
var a = [];
|
|
for (var i = 0; i < n; i++) {
|
|
a[i] = 0;
|
|
}
|
|
return a;
|
|
};
|
|
var sum = function(a) {
|
|
return a.reduce(function(sum, v) {
|
|
return sum + v;
|
|
}, 0);
|
|
};
|
|
var averages = {
|
|
percentLow: 0
|
|
, percentInRange: 0
|
|
, percentHigh: 0
|
|
, standardDeviation: 0
|
|
, lowerQuartile: 0
|
|
, upperQuartile: 0
|
|
, average: 0
|
|
};
|
|
quarters = dim(quarters).map(function(blank, n) {
|
|
var starting = new Date(now - (n + 1) * period)
|
|
, ending = new Date(now - n * period);
|
|
return {
|
|
starting: starting
|
|
, ending: ending
|
|
, records: data.filter(function(record) {
|
|
return record.displayTime > starting && record.displayTime <= ending;
|
|
})
|
|
};
|
|
}).filter(function(quarter) {
|
|
return quarter.records.length > 0;
|
|
}).map(function(quarter, ix, all) {
|
|
var bgValues = quarter.records.map(function(record) {
|
|
return record.sgv;
|
|
});
|
|
quarter.standardDeviation = ss.standard_deviation(bgValues);
|
|
quarter.average = bgValues.length > 0 ? (sum(bgValues) / bgValues.length) : 'N/A';
|
|
quarter.lowerQuartile = ss.quantile(bgValues, 0.25);
|
|
quarter.upperQuartile = ss.quantile(bgValues, 0.75);
|
|
quarter.numberLow = bgValues.filter(function(bg) {
|
|
return bg < low;
|
|
}).length;
|
|
quarter.numberHigh = bgValues.filter(function(bg) {
|
|
return bg >= high;
|
|
}).length;
|
|
quarter.numberInRange = bgValues.length - (quarter.numberHigh + quarter.numberLow);
|
|
|
|
quarter.percentLow = (quarter.numberLow / bgValues.length) * 100;
|
|
quarter.percentInRange = (quarter.numberInRange / bgValues.length) * 100;
|
|
quarter.percentHigh = (quarter.numberHigh / bgValues.length) * 100;
|
|
|
|
averages.percentLow += quarter.percentLow / all.length;
|
|
averages.percentInRange += quarter.percentInRange / all.length;
|
|
averages.percentHigh += quarter.percentHigh / all.length;
|
|
averages.lowerQuartile += quarter.lowerQuartile / all.length;
|
|
averages.upperQuartile += quarter.upperQuartile / all.length;
|
|
averages.average += quarter.average / all.length;
|
|
averages.standardDeviation += quarter.standardDeviation / all.length;
|
|
return quarter;
|
|
});
|
|
|
|
var lowComparison = function(quarter, averages, field, invert) {
|
|
if (quarter[field] < averages[field] * 0.8) {
|
|
return (invert ? 'bad' : 'good');
|
|
} else if (quarter[field] > averages[field] * 1.2) {
|
|
return (invert ? 'good' : 'bad');
|
|
} else {
|
|
return '';
|
|
}
|
|
};
|
|
|
|
var lowQuartileEvaluation = function(quarter, averages) {
|
|
if (quarter.lowerQuartile < low) {
|
|
return 'bad';
|
|
} else {
|
|
return lowComparison(quarter, averages, 'lowerQuartile');
|
|
}
|
|
};
|
|
|
|
var upperQuartileEvaluation = function(quarter, averages) {
|
|
if (quarter.upperQuartile > high) {
|
|
return 'bad';
|
|
} else {
|
|
return lowComparison(quarter, averages, 'upperQuartile');
|
|
}
|
|
};
|
|
|
|
table.append('<thead><tr><th>' + translate('Period') + '</th><th>' + translate('Low') + '</th><th>' + translate('In Range') + '</th><th>' + translate('High') + '</th><th>' + translate('Standard Deviation') + '</th><th>' + translate('Low Quartile') + '</th><th>' + translate('Average') + '</th><th>' + translate('Upper Quartile') + '</th></tr></thead>');
|
|
table.append('<tbody>' + quarters.filter(function(quarter) {
|
|
return quarter.records.length > 0;
|
|
}).map(function(quarter) {
|
|
var INVERT = true;
|
|
return '<tr>' + [
|
|
quarter.starting.toLocaleDateString() + ' - ' + quarter.ending.toLocaleDateString()
|
|
, {
|
|
klass: lowComparison(quarter, averages, 'percentLow')
|
|
, text: Math.round(quarter.percentLow) + '%'
|
|
}
|
|
, {
|
|
klass: lowComparison(quarter, averages, 'percentInRange', INVERT)
|
|
, text: Math.round(quarter.percentInRange) + '%'
|
|
}
|
|
, {
|
|
klass: lowComparison(quarter, averages, 'percentHigh')
|
|
, text: Math.round(quarter.percentHigh) + '%'
|
|
}
|
|
, {
|
|
klass: lowComparison(quarter, averages, 'standardDeviation')
|
|
, text: (quarter.standardDeviation > 10 ? Math.round(quarter.standardDeviation) : quarter.standardDeviation.toFixed(1))
|
|
}
|
|
, {
|
|
klass: lowQuartileEvaluation(quarter, averages)
|
|
, text: quarter.lowerQuartile
|
|
}
|
|
, {
|
|
klass: lowComparison(quarter, averages, 'average')
|
|
, text: quarter.average.toFixed(1)
|
|
}
|
|
, {
|
|
klass: upperQuartileEvaluation(quarter, averages)
|
|
, text: quarter.upperQuartile
|
|
}
|
|
].map(function(v) {
|
|
if (typeof v === 'object') {
|
|
return '<td class="' + v.klass + '">' + v.text + '</td>';
|
|
} else {
|
|
return '<td>' + v + '</td>';
|
|
}
|
|
}).join('') + '</tr>';
|
|
}).join('') + '</tbody>');
|
|
table.appendTo(grid);
|
|
|
|
};
|