Skip to content
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