health: calculate distance from steps

- multiplies step counts with stride length
- distance menu under step counting is only available if stride length is
set
pull/3120/head
Erik Andresen 2023-12-03 20:45:28 +01:00
parent 4f38e475a8
commit dbf8995b14
4 changed files with 118 additions and 52 deletions

View File

@ -29,3 +29,4 @@
0.26: Implement API for activity fetching
0.27: Fix typo in daily summary graph code causing graph not to load
Fix daily summaries for 31st of the month
0.28: Calculate distance from steps if new stride length setting is set

View File

@ -1,3 +1,5 @@
let settings;
function menuMain() {
E.showMenu({
"": { title: /*LANG*/"Health Tracking" },
@ -5,16 +7,30 @@ function menuMain() {
/*LANG*/"Step Counting": () => menuStepCount(),
/*LANG*/"Movement": () => menuMovement(),
/*LANG*/"Heart Rate": () => menuHRM(),
/*LANG*/"Settings": () => eval(require("Storage").read("health.settings.js"))(()=>menuMain())
/*LANG*/"Settings": () => eval(require("Storage").read("health.settings.js"))(()=>{loadSettings();menuMain();})
});
}
function menuStepCount() {
E.showMenu({
const menu = {
"": { title:/*LANG*/"Steps" },
/*LANG*/"< Back": () => menuMain(),
/*LANG*/"per hour": () => stepsPerHour(),
/*LANG*/"per day": () => stepsPerDay()
/*LANG*/"per hour": () => stepsPerHour(menuStepCount),
/*LANG*/"per day": () => stepsPerDay(menuStepCount)
};
if (settings.strideLength) {
menu[/*LANG*/"distance"] = () => menuDistance();
}
E.showMenu(menu);
}
function menuDistance() {
E.showMenu({
"": { title:/*LANG*/"Distance" },
/*LANG*/"< Back": () => menuStepCount(),
/*LANG*/"per hour": () => stepsPerHour(menuDistance, settings.strideLength),
/*LANG*/"per day": () => stepsPerDay(menuDistance, settings.strideLength)
});
}
@ -36,23 +52,23 @@ function menuHRM() {
});
}
function stepsPerHour() {
function stepsPerHour(back, mult) {
E.showMessage(/*LANG*/"Loading...");
current_selection = "stepsPerHour";
var data = new Uint16Array(24);
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
setButton(menuStepCount);
barChart(/*LANG*/"HOUR", data);
setButton(back, mult);
barChart(/*LANG*/"HOUR", data, mult);
}
function stepsPerDay() {
function stepsPerDay(back, mult) {
E.showMessage(/*LANG*/"Loading...");
current_selection = "stepsPerDay";
var data = new Uint16Array(32);
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps);
setButton(menuStepCount);
barChart(/*LANG*/"DAY", data);
drawHorizontalLine(settings.stepGoal);
setButton(back, mult);
barChart(/*LANG*/"DAY", data, mult);
drawHorizontalLine(settings.stepGoal * (mult || 1));
}
function hrmPerHour() {
@ -139,7 +155,11 @@ function get_data_length(arr) {
return nlen;
}
function barChart(label, dt) {
function barChart(label, dt, mult) {
if (mult !== undefined) {
// Calculate distance from steps
dt.forEach((val, i) => dt[i] = val*mult);
}
data_len = get_data_length(dt);
chart_index = Math.max(data_len - 5, -5); // choose initial index that puts the last day on the end
chart_max_datum = max(dt); // find highest bar, for scaling
@ -180,7 +200,7 @@ function drawHorizontalLine(value) {
g.setColor(g.theme.fg).drawLine(0, top ,g.getWidth(), top);
}
function setButton(fn) {
function setButton(fn, mult) {
Bangle.setUI({mode:"custom",
back:fn,
swipe:(lr,ud) => {
@ -194,12 +214,16 @@ function setButton(fn) {
}
drawBarChart();
if (current_selection == "stepsPerDay") {
drawHorizontalLine(settings.stepGoal);
drawHorizontalLine(settings.stepGoal * (mult || 1));
}
}});
}
function loadSettings() {
settings = require("Storage").readJSON("health.json",1)||{};
}
Bangle.loadWidgets();
Bangle.drawWidgets();
var settings = require("Storage").readJSON("health.json",1)||{};
loadSettings();
menuMain();

View File

@ -2,7 +2,7 @@
"id": "health",
"name": "Health Tracking",
"shortName": "Health",
"version": "0.27",
"version": "0.28",
"description": "Logs health data and provides an app to view it",
"icon": "app.png",
"tags": "tool,system,health",

View File

@ -8,44 +8,85 @@
function setSettings() {
require("Storage").writeJSON("health.json", settings);
}
E.showMenu({
"": { title: /*LANG*/"Health Tracking" },
/*LANG*/"< Back": () => back(),
function settingsMenu() {
E.showMenu({
"": { title: /*LANG*/"Health Tracking" },
/*LANG*/"HRM Interval": {
value: settings.hrm,
min: 0,
max: 3,
format: v => [
/*LANG*/"Off",
/*LANG*/"3 min",
/*LANG*/"10 min",
/*LANG*/"Always"
][v],
onchange: v => {
settings.hrm = v;
setSettings();
}
},
/*LANG*/"< Back": () => back(),
/*LANG*/"Daily Step Goal": {
value: settings.stepGoal,
min: 0,
max: 20000,
step: 250,
onchange: v => {
settings.stepGoal = v;
/*LANG*/"HRM Interval": {
value: settings.hrm,
min: 0,
max: 3,
format: v => [
/*LANG*/"Off",
/*LANG*/"3 min",
/*LANG*/"10 min",
/*LANG*/"Always"
][v],
onchange: v => {
settings.hrm = v;
setSettings();
}
},
/*LANG*/"Daily Step Goal": {
value: settings.stepGoal,
min: 0,
max: 20000,
step: 250,
onchange: v => {
settings.stepGoal = v;
setSettings();
}
},
/*LANG*/"Step Goal Notification": {
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
onchange: () => {
settings.stepGoalNotification = !settings.stepGoalNotification;
setSettings();
}
},
/*LANG*/"Stride length": () => strideLengthMenu()
});
}
function strideLengthMenu() {
const menu = {
"" : { title : /*LANG*/"Stride length" },
"< Back" : () => {
setSettings();
}
},
/*LANG*/"Step Goal Notification": {
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
onchange: () => {
settings.stepGoalNotification = !settings.stepGoalNotification;
setSettings();
}
}
});
settingsMenu();
},
"x 0.01" : {
value : settings.strideLength === undefined ? 0 : settings.strideLength,
min:0,
step:0.01,
format: v => require("locale").distance(v, 2),
onchange : v => {
settings.strideLength=v;
menu["x 0.1"].value = v;
},
},
"x 0.1" : {
value : settings.strideLength === undefined ? 0 : settings.strideLength,
min:0,
step:0.1,
format: v => require("locale").distance(v, 2),
onchange : v => {
settings.strideLength=v;
menu["x 0.01"].value = v;
},
},
};
E.showMenu(menu);
}
settingsMenu();
})