-
Notifications
You must be signed in to change notification settings - Fork 45
/
format.js
175 lines (152 loc) · 4.94 KB
/
format.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* jshint browser: true */
/* global module */
var format = function(c) {
var f = {};
f.sgvArray = function(endTime, sgvs, maxSGVs) {
var noEntry = {
'date': Infinity,
'sgv': 0
};
var i;
var graphed = [];
var xs = [];
for(i = 0; i < maxSGVs * c.INTERVAL_SIZE_SECONDS; i += c.INTERVAL_SIZE_SECONDS) {
graphed.push(noEntry);
xs.push(endTime - i * 1000);
}
for(i = 0; i < sgvs.length; i++) {
var min = Infinity;
var xi;
// Don't graph missing sgvs or error codes
if(sgvs[i]['sgv'] === undefined || sgvs[i]['sgv'] <= c.DEXCOM_ERROR_CODE_MAX) {
continue;
}
// Find the x value closest to this sgv's date
for(var j = 0; j < xs.length; j++) {
if(Math.abs(sgvs[i]['date'] - xs[j]) < min) {
min = Math.abs(sgvs[i]['date'] - xs[j]);
xi = j;
}
}
// Assign it if it's the closest sgv to that x
if(min < c.INTERVAL_SIZE_SECONDS * 1000 && Math.abs(sgvs[i]['date'] - xs[xi]) < Math.abs(graphed[xi]['date'] - xs[xi])) {
graphed[xi] = sgvs[i];
}
}
var ys = graphed.map(function(entry) { return entry['sgv']; });
return ys;
};
function _graphIntervals(endTime, maxSGVs) {
var out = [];
for(var i = 0; i < maxSGVs * c.INTERVAL_SIZE_SECONDS; i += c.INTERVAL_SIZE_SECONDS) {
out.push({
start: endTime - 1000 * i - 1000 * c.INTERVAL_SIZE_SECONDS / 2,
end: endTime - 1000 * i + 1000 * c.INTERVAL_SIZE_SECONDS / 2,
});
}
return out;
}
f.bolusGraphArray = function(endTime, bolusHistory, maxSGVs) {
return _graphIntervals(endTime, maxSGVs).map(function(interval) {
var bolusInInterval = false;
for(var j = 0; j < bolusHistory.length; j++) {
var bolusTime = new Date(bolusHistory[j]['created_at']).getTime();
if (interval.start < bolusTime && bolusTime < interval.end) {
bolusInInterval = true;
}
}
return bolusInInterval ? 1 : 0;
});
};
f.basalRateArray = function(endTime, basalHistory, maxSGVs) {
return _graphIntervals(endTime, maxSGVs).map(function(interval) {
var rateTotals = {};
basalHistory.forEach(function(basal, i) {
if (i === basalHistory.length - 1) {
return;
}
var next = basalHistory[i + 1];
if (next.start <= interval.start || basal.start > interval.end) {
return;
}
var duration;
if (basal.start >= interval.start && next.start <= interval.end) {
duration = next.start - basal.start;
} else if (basal.start < interval.start && next.start <= interval.end) {
duration = next.start - interval.start;
} else if (basal.start >= interval.start && next.start > interval.end) {
duration = interval.end - basal.start;
} else {
duration = interval.end - interval.start;
}
rateTotals[basal.absolute] = (basal.absolute in rateTotals ? rateTotals[basal.absolute] : 0) + duration;
});
if (Object.keys(rateTotals).length === 0) {
return 0;
} else {
return parseFloat(
Object.keys(rateTotals).reduce(function(acc, rate) {
return rateTotals[rate] > rateTotals[acc] ? rate : acc;
})
);
}
});
};
function _rescale(arr, pixelHeight) {
var max = Math.max.apply(Math, arr);
return arr.map(function(x) {
return Math.round(x / max * pixelHeight);
});
}
f.basalGraphArray = function(endTime, basalHistory, maxSGVs, config) {
return _rescale(f.basalRateArray(endTime, basalHistory, maxSGVs), config.basalHeight);
};
function _encodeBits(value, offset, bits) {
return Math.min(value, Math.pow(2, bits) - 1) << offset;
}
f.graphExtraArray = function(boluses, basals) {
var out = [];
var bits;
for(var i = 0; i < boluses.length; i++) {
bits = 0;
bits += _encodeBits(boluses[i], c.GRAPH_EXTRA_BOLUS_OFFSET, c.GRAPH_EXTRA_BOLUS_BITS);
bits += _encodeBits(basals[i], c.GRAPH_EXTRA_BASAL_OFFSET, c.GRAPH_EXTRA_BASAL_BITS);
out.push(bits);
}
return out;
};
f.lastTrendNumber = function(sgvs) {
if (sgvs.length === 0) {
return 0;
}
var trend = sgvs[0]['trend'];
if (!isNaN(parseInt(trend)) && trend >= 0 && trend <= 9) {
return trend;
} else if (sgvs[0]['direction'] !== undefined) {
return c.NIGHTSCOUT_DIRECTION_TO_TREND[sgvs[0]['direction']] || 0;
} else {
return 0;
}
};
f.lastSgv = function(sgvs) {
return sgvs.length > 0 ? parseInt(sgvs[0]['sgv'], 10) : 0;
};
f.lastDelta = function(ys) {
if (ys[1] === 0) {
return c.NO_DELTA_VALUE;
} else {
return ys[0] - ys[1];
}
};
f.recency = function(sgvs) {
if (sgvs.length === 0) {
// TODO
return 999 * 60 * 60;
} else {
var seconds = (Date.now() - sgvs[0]['date']) / 1000;
return Math.floor(seconds);
}
};
return f;
};
module.exports = format;