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
298 lines
7.5 KiB
JavaScript
298 lines
7.5 KiB
JavaScript
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var units = require('./units')();
|
|
var times = require('./times');
|
|
|
|
function init () {
|
|
var sbx = {};
|
|
|
|
function reset () {
|
|
sbx.properties = {};
|
|
}
|
|
|
|
function extend () {
|
|
sbx.unitsLabel = unitsLabel();
|
|
sbx.data = sbx.data || {};
|
|
//default to prevent adding checks everywhere
|
|
sbx.extendedSettings = { empty: true };
|
|
}
|
|
|
|
function withExtendedSettings (plugin, allExtendedSettings, sbx) {
|
|
var sbx2 = _.extend({}, sbx);
|
|
sbx2.extendedSettings = allExtendedSettings && allExtendedSettings[plugin.name] || {};
|
|
return sbx2;
|
|
}
|
|
|
|
/**
|
|
* A view into the safe notification functions for plugins
|
|
*
|
|
* @param ctx
|
|
* @returns {{notification}}
|
|
*/
|
|
function safeNotifications (ctx) {
|
|
return _.pick(ctx.notifications, ['requestNotify', 'requestSnooze', 'requestClear']);
|
|
}
|
|
|
|
/**
|
|
* Initialize the sandbox using server state
|
|
*
|
|
* @param env - .js
|
|
* @param ctx - created from bootevent
|
|
* @returns {{sbx}}
|
|
*/
|
|
sbx.serverInit = function serverInit (env, ctx) {
|
|
reset();
|
|
|
|
sbx.time = Date.now();
|
|
sbx.settings = env.settings;
|
|
sbx.data = ctx.ddata.clone();
|
|
sbx.notifications = safeNotifications(ctx);
|
|
|
|
sbx.levels = ctx.levels;
|
|
sbx.language = ctx.language;
|
|
sbx.translate = ctx.language.translate;
|
|
|
|
var profile = require('./profilefunctions')();
|
|
//Plugins will expect the right profile based on time
|
|
profile.loadData(_.cloneDeep(ctx.ddata.profiles));
|
|
profile.updateTreatments(ctx.ddata.profileTreatments, ctx.ddata.tempbasalTreatments, ctx.ddata.combobolusTreatments);
|
|
sbx.data.profile = profile;
|
|
delete sbx.data.profiles;
|
|
|
|
sbx.properties = {};
|
|
|
|
sbx.withExtendedSettings = function getPluginExtendedSettingsOnly (plugin) {
|
|
return withExtendedSettings(plugin, env.extendedSettings, sbx);
|
|
};
|
|
|
|
extend();
|
|
|
|
return sbx;
|
|
};
|
|
|
|
/**
|
|
* Initialize the sandbox using client state
|
|
*
|
|
* @param settings - specific settings from the client, starting with the defaults
|
|
* @param time - could be a retro time
|
|
* @param pluginBase - used by visualization plugins to update the UI
|
|
* @param data - svgs, treatments, profile, etc
|
|
* @returns {{sbx}}
|
|
*/
|
|
sbx.clientInit = function clientInit (ctx, time, data) {
|
|
reset();
|
|
|
|
sbx.settings = ctx.settings;
|
|
sbx.showPlugins = ctx.settings.showPlugins;
|
|
sbx.time = time;
|
|
sbx.data = data;
|
|
sbx.pluginBase = ctx.pluginBase;
|
|
sbx.notifications = safeNotifications(ctx);
|
|
|
|
sbx.levels = ctx.levels;
|
|
sbx.language = ctx.language;
|
|
sbx.translate = ctx.language.translate;
|
|
|
|
if (sbx.pluginBase) {
|
|
sbx.pluginBase.forecastInfos = [];
|
|
sbx.pluginBase.forecastPoints = [];
|
|
}
|
|
|
|
sbx.extendedSettings = { empty: true };
|
|
sbx.withExtendedSettings = function getPluginExtendedSettingsOnly (plugin) {
|
|
return withExtendedSettings(plugin, sbx.settings.extendedSettings, sbx);
|
|
};
|
|
|
|
extend();
|
|
|
|
return sbx;
|
|
};
|
|
|
|
/**
|
|
* Properties are immutable, first plugin to set it wins, plugins should be in the correct order
|
|
*
|
|
* @param name
|
|
* @param setter
|
|
*/
|
|
sbx.offerProperty = function offerProperty (name, setter) {
|
|
if (!Object.keys(sbx.properties).includes(name)) {
|
|
var value = setter();
|
|
if (value) {
|
|
sbx.properties[name] = value;
|
|
}
|
|
}
|
|
};
|
|
|
|
sbx.isCurrent = function isCurrent (entry) {
|
|
return entry && sbx.time - entry.mills <= times.mins(15).msecs;
|
|
};
|
|
|
|
sbx.lastEntry = function lastEntry (entries) {
|
|
return _.findLast(entries, function notInTheFuture (entry) {
|
|
return sbx.entryMills(entry) <= sbx.time;
|
|
});
|
|
};
|
|
|
|
sbx.lastNEntries = function lastNEntries (entries, n) {
|
|
var lastN = [];
|
|
|
|
_.takeRightWhile(entries, function(entry) {
|
|
if (sbx.entryMills(entry) <= sbx.time) {
|
|
lastN.push(entry);
|
|
}
|
|
return lastN.length < n;
|
|
});
|
|
|
|
lastN.reverse();
|
|
|
|
return lastN;
|
|
};
|
|
|
|
sbx.prevEntry = function prevEntry (entries) {
|
|
var last2 = sbx.lastNEntries(entries, 2);
|
|
return _.first(last2);
|
|
};
|
|
|
|
sbx.prevSGVEntry = function prevSGVEntry () {
|
|
return sbx.prevEntry(sbx.data.sgvs);
|
|
};
|
|
|
|
sbx.lastSGVEntry = function lastSGVEntry () {
|
|
return sbx.lastEntry(sbx.data.sgvs);
|
|
};
|
|
|
|
sbx.lastSGVMgdl = function lastSGVMgdl () {
|
|
var last = sbx.lastSGVEntry();
|
|
return last && last.mgdl;
|
|
};
|
|
|
|
sbx.lastSGVMills = function lastSGVMills () {
|
|
return sbx.entryMills(sbx.lastSGVEntry());
|
|
};
|
|
|
|
sbx.entryMills = function entryMills (entry) {
|
|
return entry && entry.mills;
|
|
};
|
|
|
|
sbx.lastScaledSGV = function lastScaledSVG () {
|
|
return sbx.scaleEntry(sbx.lastSGVEntry());
|
|
};
|
|
|
|
sbx.lastDisplaySVG = function lastDisplaySVG () {
|
|
return sbx.displayBg(sbx.lastSGVEntry());
|
|
};
|
|
|
|
sbx.buildBGNowLine = function buildBGNowLine () {
|
|
var line = 'BG Now: ' + sbx.lastDisplaySVG();
|
|
|
|
var delta = sbx.properties.delta && sbx.properties.delta.display;
|
|
if (delta) {
|
|
line += ' ' + delta;
|
|
}
|
|
|
|
var direction = sbx.properties.direction && sbx.properties.direction.label;
|
|
if (direction) {
|
|
line += ' ' + direction;
|
|
}
|
|
|
|
line += ' ' + sbx.unitsLabel;
|
|
|
|
return line;
|
|
};
|
|
|
|
sbx.propertyLine = function propertyLine (propertyName) {
|
|
return sbx.properties[propertyName] && sbx.properties[propertyName].displayLine;
|
|
};
|
|
|
|
sbx.appendPropertyLine = function appendPropertyLine (propertyName, lines) {
|
|
lines = lines || [];
|
|
|
|
var displayLine = sbx.propertyLine(propertyName);
|
|
if (displayLine) {
|
|
lines.push(displayLine);
|
|
}
|
|
|
|
return lines;
|
|
};
|
|
|
|
sbx.prepareDefaultLines = function prepareDefaultLines () {
|
|
var lines = [sbx.buildBGNowLine()];
|
|
sbx.appendPropertyLine('rawbg', lines);
|
|
sbx.appendPropertyLine('ar2', lines);
|
|
sbx.appendPropertyLine('bwp', lines);
|
|
sbx.appendPropertyLine('iob', lines);
|
|
sbx.appendPropertyLine('cob', lines);
|
|
|
|
return lines;
|
|
};
|
|
|
|
sbx.buildDefaultMessage = function buildDefaultMessage () {
|
|
return sbx.prepareDefaultLines().join('\n');
|
|
};
|
|
|
|
sbx.displayBg = function displayBg (entry) {
|
|
var isDex = entry && (!entry.device || entry.device === 'dexcom');
|
|
if (isDex && Number(entry.mgdl) === 39) {
|
|
return 'LOW';
|
|
} else if (isDex && Number(entry.mgdl) === 401) {
|
|
return 'HIGH';
|
|
} else {
|
|
return sbx.scaleEntry(entry);
|
|
}
|
|
};
|
|
|
|
sbx.scaleEntry = function scaleEntry (entry) {
|
|
|
|
if (entry && entry.scaled === undefined) {
|
|
if (sbx.settings.units === 'mmol') {
|
|
entry.scaled = entry.mmol || units.mgdlToMMOL(entry.mgdl);
|
|
} else {
|
|
entry.scaled = entry.mgdl || units.mmolToMgdl(entry.mmol);
|
|
}
|
|
}
|
|
|
|
return entry && Number(entry.scaled);
|
|
};
|
|
|
|
sbx.scaleMgdl = function scaleMgdl (mgdl) {
|
|
if (sbx.settings.units === 'mmol' && mgdl) {
|
|
return Number(units.mgdlToMMOL(mgdl));
|
|
} else {
|
|
return Number(mgdl);
|
|
}
|
|
};
|
|
|
|
sbx.roundInsulinForDisplayFormat = function roundInsulinForDisplayFormat (insulin) {
|
|
|
|
if (insulin === 0) {
|
|
return '0';
|
|
}
|
|
|
|
if (sbx.properties.roundingStyle === 'medtronic') {
|
|
var denominator = 0.1;
|
|
var digits = 1;
|
|
if (insulin <= 0.5) {
|
|
denominator = 0.05;
|
|
digits = 2;
|
|
}
|
|
return (Math.floor(insulin / denominator) * denominator).toFixed(digits);
|
|
}
|
|
|
|
return (Math.floor(insulin / 0.01) * 0.01).toFixed(2);
|
|
|
|
};
|
|
|
|
function unitsLabel () {
|
|
return sbx.settings.units === 'mmol' ? 'mmol/L' : 'mg/dl';
|
|
}
|
|
|
|
sbx.roundBGToDisplayFormat = function roundBGToDisplayFormat (bg) {
|
|
return sbx.settings.units === 'mmol' ? Math.round(bg * 10) / 10 : Math.round(bg);
|
|
};
|
|
|
|
return sbx;
|
|
}
|
|
|
|
module.exports = init;
|