Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #4991 - Now selects basal profile based day by day #5572

Merged
merged 13 commits into from
Jun 12, 2020
25 changes: 25 additions & 0 deletions lib/api/profile/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ function configure (app, wares, ctx) {
api.use(wares.bodyParser.urlencoded({ extended: true }));

api.use(ctx.authorization.isPermitted('api:profile:read'));


/**
* @function query_models
* Perform the standard query logic, translating API parameters into mongo
* db queries in a fairly regimented manner.
* This middleware executes the query, returning the results as JSON
*/
function query_models (req, res, next) {
var query = req.query;

// If "?count=" is present, use that number to decide how many to return.
if (!query.count) {
query.count = consts.ENTRIES_DEFAULT_COUNT;
}

// perform the query
ctx.profile.list_query(query, function payload(err, profiles) {
return res.json(profiles);
});
}

// List profiles available
api.get('/profiles/', query_models);

// List profiles available
api.get('/profile/', function(req, res) {
ctx.profile.list(function (err, attribute) {
Expand Down
1 change: 1 addition & 0 deletions lib/client/browser-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ function init (client, serverSettings, $) {
settings.thresholds = serverSettings.settings.thresholds;
}


if (serverSettings.settings.enable) {
settings.enable = serverSettings.settings.enable;
}
Expand Down
101 changes: 64 additions & 37 deletions lib/profilefunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,28 @@ function init (profileData) {
};

profile.getCurrentProfile = function getCurrentProfile (time, spec_profile) {
if (spec_profile) {
return spec_profile;
} else {
time = time || new Date().getTime();

time = time || Date.now();
var minuteTime = Math.round(time / 60000) * 60000;
var cacheKey = ("profile" + minuteTime + spec_profile);
var returnValue = cache.get(cacheKey);

if (returnValue) {
return returnValue;
}

time = time || Date.now();
var minuteTime = Math.round(time / 60000) * 60000;
var cacheKey = ("profile" + minuteTime + spec_profile);
var returnValue = cache.get(cacheKey);
var pdataActive = profile.profileFromTime(time);
var data = profile.hasData() ? pdataActive : null;
var timeprofile = profile.activeProfileToTime(time);
returnValue = data && data.store[timeprofile] ? data.store[timeprofile] : {};

if (returnValue) {
cache.put(cacheKey, returnValue, cacheTTL);
return returnValue;
}

var data = profile.hasData() ? profile.data[0] : null;
var timeprofile = spec_profile || profile.activeProfileToTime(time);
returnValue = data && data.store[timeprofile] ? data.store[timeprofile] : {};

cache.put(cacheKey, returnValue, cacheTTL);
return returnValue;
};

profile.getUnits = function getUnits (spec_profile) {
Expand Down Expand Up @@ -225,10 +231,13 @@ function init (profileData) {

profile.activeProfileToTime = function activeProfileToTime (time) {
if (profile.hasData()) {
var timeprofile = profile.data[0].defaultProfile;
time = Number(time) || new Date().getTime();

var pdataActive = profile.profileFromTime(time);
var timeprofile = pdataActive.defaultProfile;
var treatment = profile.activeProfileTreatmentToTime(time);
if (treatment && profile.data[0].store && profile.data[0].store[treatment.profile]) {

if (treatment && pdataActive.store && pdataActive.store[treatment.profile]) {
timeprofile = treatment.profile;
}
return timeprofile;
Expand All @@ -248,30 +257,31 @@ function init (profileData) {

var treatment = null;
if (profile.hasData()) {
profile.profiletreatments.forEach(function eachTreatment (t) {
if (time >= t.mills && t.mills >= profile.data[0].mills) {
var duration = times.mins(t.duration || 0).msecs;
if (duration != 0 && time < t.mills + duration) {
treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !profile.data[0].store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills;
let json = JSON.parse(treatment.profileJson);
profile.data[0].store[treatment.profile] = json;
}
}
if (duration == 0) {
treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !profile.data[0].store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills;
let json = JSON.parse(treatment.profileJson);
profile.data[0].store[treatment.profile] = json;
}
var pdataActive = profile.profileFromTime(time);
profile.profiletreatments.forEach(function eachTreatment(t) {
if (time >= t.mills && t.mills >= pdataActive.mills) {
var duration = times.mins(t.duration || 0).msecs;
if (duration != 0 && time < t.mills + duration) {
treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !pdataActive.store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills;
let json = JSON.parse(treatment.profileJson);
pdataActive.store[treatment.profile] = json;
}
}
if (duration == 0) {
treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !pdataActive.store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills;
let json = JSON.parse(treatment.profileJson);
pdataActive.store[treatment.profile] = json;
}
}
}
}
});
}

Expand All @@ -286,6 +296,23 @@ function init (profileData) {
else return name.substring(0, index);
}

profile.profileFromTime = function profileFromTime (time) {
var profileData = null;

if (profile.hasData()) {
profileData = profile.data[0];
for (var i = 0; i < profile.data.length; i++)
{
if (Number(time) >= Number(profile.data[i].mills)) {
profileData = profile.data[i];
break;
}
}
}

return profileData;
}

profile.tempBasalTreatment = function tempBasalTreatment (time) {

// Most queries for the data in reporting will match the latest found value, caching that hugely improves performance
Expand Down
2 changes: 2 additions & 0 deletions lib/report_plugins/daytoday.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
data.netBasalNegative[hour] = 0;
});

profile.loadData(datastorage.profiles);

profile.updateTreatments(datastorage.profileSwitchTreatments, datastorage.tempbasalTreatments, datastorage.combobolusTreatments);

var bolusInsulin = 0;
Expand Down
8 changes: 5 additions & 3 deletions lib/report_plugins/profiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,12 @@ profiles.report = function report_profiles (datastorage) {

function displayRanges (array, array2) {
var text = '';
for (var i = 0; i < array.length; i++) {
text += array[i].time + '&nbsp:&nbsp' + array[i].value + (array2 ? ' - ' + array2[i].value : '') + '<br>';
}

if (array && array2) {
for (var i = 0; i < array.length; i++) {
text += array[i].time + '&nbsp:&nbsp' + array[i].value + (array2 ? ' - ' + array2[i].value : '') + '<br>';
}
}
return text;
}
};
45 changes: 45 additions & 0 deletions lib/server/profile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var find_options = require('./query');

function storage (collection, ctx) {
var ObjectID = require('mongodb').ObjectID;

Expand Down Expand Up @@ -27,6 +29,48 @@ function storage (collection, ctx) {
return api( ).find({ }).sort({startDate: -1}).toArray(fn);
}

function list_query (opts, fn) {

storage.queryOpts = {
walker: {}
, dateField: 'startDate'
};

function limit () {
if (opts && opts.count) {
return this.limit(parseInt(opts.count));
}
return this;
}

return limit.call(api()
.find(query_for(opts))
.sort(opts && opts.sort && query_sort(opts) || { startDate: -1 }), opts)
.toArray(fn);
}

function query_for (opts) {
var retVal = find_options(opts, storage.queryOpts);
return retVal;
}

function query_sort (opts) {
if (opts && opts.sort) {
var sortKeys = Object.keys(opts.sort);

for (var i = 0; i < sortKeys.length; i++) {
if (opts.sort[sortKeys[i]] == '1') {
opts.sort[sortKeys[i]] = 1;
}
else {
opts.sort[sortKeys[i]] = -1;
}
}
return opts.sort;
}
}


function last (fn) {
return api().find().sort({startDate: -1}).limit(1).toArray(fn);
}
Expand All @@ -43,6 +87,7 @@ function storage (collection, ctx) {
}

api.list = list;
api.list_query = list_query;
api.create = create;
api.save = save;
api.remove = remove;
Expand Down
72 changes: 69 additions & 3 deletions static/report/js/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,14 @@
if (loadeddays === dayscount) {
sorteddaystoshow.sort();
var from = sorteddaystoshow[0];
var dFrom = sorteddaystoshow[0];
var dTo = sorteddaystoshow[(sorteddaystoshow.length - 1)];

if (options.order === report_plugins.consts.ORDER_NEWESTONTOP) {
sorteddaystoshow.reverse();
}
loadProfileSwitch(from, function loadProfileSwitchCallback() {
loadProfiles(function loadProfilesCallback() {
loadProfileSwitch(dFrom, function loadProfileSwitchCallback() {
loadProfilesRange(dFrom, dTo, sorteddaystoshow.length, function loadProfilesCallback() {
$('#info > b').html('<b>' + translate('Rendering') + ' ...</b>');
window.setTimeout(function () {
showreports(options);
Expand Down Expand Up @@ -709,7 +712,7 @@
});
}

function loadProfileSwitch(from, callback) {
function loadProfileSwitch (from, callback) {
$('#info > b').html('<b>'+translate('Loading profile switch data') + ' ...</b>');
var tquery = '?find[eventType]=Profile Switch' + '&find[created_at][$lte]=' + new Date(from).toISOString() + '&count=1';
$.ajax('/api/v1/treatments.json'+tquery, {
Expand Down Expand Up @@ -743,6 +746,69 @@
}).done(callback);
}

function loadProfilesRange (dateFrom, dateTo, dayCount, callback) {
$('#info > b').html('<b>' + translate('Loading profile range') + ' ...</b>');

$.when(
loadProfilesRangeCore(dateFrom, dateTo, dayCount),
loadProfilesRangePrevious(dateFrom),
loadProfilesRangeNext(dateTo)
)
.done(callback)
.fail(function () {
datastorage.profiles = [];
});
}

function loadProfilesRangeCore (dateFrom, dateTo, dayCount) {
$('#info > b').html('<b>' + translate('Loading core profiles') + ' ...</b>');

//The results must be returned in descending order to work with key logic in routines such as getCurrentProfile
var tquery = '?find[startDate][$gte]=' + new Date(dateFrom).toISOString() + '&find[startDate][$lte]=' + new Date(dateTo).toISOString() + '&sort[startDate]=-1&count=' + dayCount;

return $.ajax('/api/v1/profiles' + tquery, {
headers: client.headers(),
async: false,
success: function (records) {
datastorage.profiles = records;
}
});
}

function loadProfilesRangePrevious (dateFrom) {
$('#info > b').html('<b>' + translate('Loading previous profile') + ' ...</b>');

//Find first one before the start date and add to datastorage.profiles
var tquery = '?find[startDate][$lt]=' + new Date(dateFrom).toISOString() + '&sort[startDate]=-1&count=1';

return $.ajax('/api/v1/profiles' + tquery, {
headers: client.headers(),
async: false,
success: function (records) {
records.forEach(function (r) {
datastorage.profiles.push(r);
});
}
});
}

function loadProfilesRangeNext (dateTo) {
$('#info > b').html('<b>' + translate('Loading next profile') + ' ...</b>');

//Find first one after the end date and add to datastorage.profiles
var tquery = '?find[startDate][$gt]=' + new Date(dateTo).toISOString() + '&sort[startDate]=1&count=1';

return $.ajax('/api/v1/profiles' + tquery, {
headers: client.headers(),
async: false,
success: function (records) {
records.forEach(function (r) {
//must be inserted as top to maintain profiles being sorted by date in descending order
datastorage.profiles.unshift(r);
});
}
});
}

function processData(data, day, options, callback) {
if (daystoshow[day].treatmentsonly) {
Expand Down
Loading