xxxxxxxxxx
163
// I can leave some dummy data in maybe that would be nice
const MARG = 15;
var HASHEADERS = true;
var DELIM = ";";
PRESETS = ["com.sec.android.app.shealth"];
PRESET = "com.sec.android.app.shealth";
function setup() {
var canvas = createCanvas(4000, 400);
canvas.parent("sketch-holder");
createButton('save!').mousePressed( function (e) {
switch (PRESET) {
case "com.sec.android.app.shealth":
fn = 'heartrate-graph'
break;
default:
fn = 'unknown-graph'
break;
}
saveCanvas(fn, 'png')
})
select("#data-input").input(function () {
data = this.value();
// show some data in the console
print(data.slice(0, 100));
// god i wish i just had python here
var lines = data.split("\n");
var headers = [];
if (HASHEADERS) {
headers = lines.shift().split(DELIM);
print(lines[0]);
print(`headers found: ${headers}`);
}
// sadly i dont know how to do this otherwise,
// so we have to loop over the array to calculate how to scale everything
if (PRESETS.includes(PRESET)) {
switch (PRESET) {
case "com.sec.android.app.shealth":
/*
FORMAT:
Date;Time;Heart rate;App
"Aug 17, 2022";"14:03:54";76;com.sec.android.app.shealth
"Aug 17, 2022";"14:50:55";79;com.sec.android.app.shealth
"Aug 17, 2022";"15:50:29";71;com.sec.android.app.shealth
*/
parseSamsungHR(lines);
break;
default:
print("unimplemented");
break;
}
} else {
print("UNKNOWN PRESET");
}
});
createRadio();
}
function fixDate(samsungHRRow) {
[d, t] = samsungHRRow.split(DELIM);
if (d && t) {
dd = d.split('"').join("");
tt = t.split('"').join("");
return Date.parse(`${dd} ${tt}`);
}
print(d,t, "incorrect format")
}
function getValue(row, index){
return row.split(DELIM)[index]
}
function parseSamsungHR(lines) {
background(255,255,255);
print("parsing com.sec.android.app.shealth, not finished yet though");
dates = lines.map(fixDate).filter(e => e != null); // last value seems to come out as undefined sometimes
// having undefined in the array makes min/max not function correctly so we have to filter them out.
[highest, lowest] = [max(dates), min(dates)];
print(`highest:${highest} lowest:${lowest}`)
diff = (highest-lowest)/ 1000; // direct conversion from millis
scaler = width/diff;
print(`scaling factor: ${scaler} (diff = ${diff}) probably`)
// same filter needed for values probably.
// mAAAAAAAAAAYbe its better to prune beforehand. (TODO)
yvals = lines.map(e => getValue(e, 2)).filter(e => e != null)
print("y",yvals[1])
yvals = yvals.map((v) => {
return map( parseFloat(v), 0, 250, 300, 100)
})
print("y mapped", yvals[1])
var [maxVal, minVal] = [max(yvals), min(yvals)];
print(`highest ${maxVal} lowest ${minVal}:`);
xvals = yvals.map(
function(val, index){
return map(map((highest-dates[index])/1000, 0, diff, 0, lines.length), 0, lines.length, width-MARG, MARG);
}
);
print(xvals[1])
print(xvals[xvals.length-2])
px = xvals[0];
py = yvals[0];
line(MARG, 100, MARG, 300);
text(`250`, MARG, 100);
text(`0`, MARG, 300);
const red = color('red')
const green = color('green')
for (var i = 0; i < xvals.length ; i++) {
const x = xvals[i];
const y = yvals[i];
line(px,py,x,y);
stroke(lerpColor(red, green, y/250));
px = x;
py = y;
}
}
function draw() {
noLoop();
}