Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/calories/ChangeLog
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
0.01: Initial app based on #4092
0.02: Adjust formula slightly and fix overestimated active calories by scaling based on max HR (#4286)
5 changes: 3 additions & 2 deletions apps/calories/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Tracks calories using [`MyProfile`](https://banglejs.com/apps/?id=myprofile) data and a complex formula that takes age, gender, weight, height, heart rate, and steps into account.
This app also ties in with the [`Health App`](https://banglejs.com/apps/?id=health) for greater integration within the Bangle.js ecosystem.
## Beta Testing:
This app is in beta testing. Any feedback is appreciated on performance, improvements, etc. Additionally, we are looking for users who can test the accuracy of this formula against other smartwatches' calorie tracking formulas. Simply tag `@RKBoss6` in any GitHub discussion/thread and help improve accuracy and performance!
This app is still quite new, and any feedback is appreciated on performance, improvements, etc. Additionally, we are looking for users who can test the accuracy of this formula against other smartwatches' calorie tracking formulas. Simply tag `@RKBoss6` in any GitHub discussion/thread and help improve accuracy and performance!
## Setup:
The app needs the data below to function properly:

Expand Down Expand Up @@ -30,7 +30,8 @@ The app uses the algorithm below:
**Not Set (avg):** `(-37.7495+(0.5390 x Heart Rate)+(0.0362 x Weight)+(0.1375 x Age))/4.184`

4. Blends the two according to the steps taken (Higher steps per min --> steps weighted more due to potential HRM inaccuracy)
5. Returns the total calories burned in that interval, active calories (calories actively burned), and BMR calories (calories passively burned)
5. Uses Max HRM to interpolate between how much it should weight active calories (avoids overestimates)
6. Returns the total calories burned in that interval, active calories (calories actively burned), and BMR calories (calories passively burned)

## Clock Info
This app adds a set of ClockInfos in the `Health` list:
Expand Down
38 changes: 17 additions & 21 deletions apps/calories/lib.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Calories Module
// Calories Module - RKBoss6
// Since these calculations are quite heavy, boot.js offloads BMR to a cache to avoid calculating every 2 minutes

let calcAge = function (rawBday) {
Expand Down Expand Up @@ -93,6 +93,7 @@ exports.calcBMR = function (myProfile) {
}
return bmr / 1440;
};

// Main formula for calculating calories. Takes health data with duration in minutes, and a myprofile data set.
exports.calcCalories = function (healthData, myProfile) {
if (!healthData || !healthData.duration) return;
Expand Down Expand Up @@ -123,13 +124,15 @@ exports.calcCalories = function (healthData, myProfile) {
print("Invalid or missing heart rate data");
return;
}


const lerp = (x, min, max) => Math.min(Math.max((x - min) / (max - min), 0), 1);

let ageMultiplier = 1.0;

let activeCaloriesCoefficient=lerp(hr, myProfile.maxHrm*0.5, myProfile.maxHrm*0.6) // use hr extertion level between 50% and 60% of max HR to determine active calories.

let stepsMet =
(stepsPerMin < 5 ? 1.0 : 2.0 + 0.05 * stepsPerMin) * ageMultiplier; // More realistic scaling with age adjustment

// calculate calories using current HR (not HRR - that was causing inflation)
// calculate calories using current HR
if (myProfile.gender != undefined && myProfile.gender != 2 /*not set*/) {
if (myProfile.gender == 0) {
//male
Expand All @@ -145,32 +148,25 @@ exports.calcCalories = function (healthData, myProfile) {
hrKcalMin =
(-37.7495 + 0.539 * hr + 0.0362 * weight + 0.1375 * age) / 4.184;
}

// extract active portion (subtract BMR)
hrKcalMin = Math.max(0, hrKcalMin - bmr); // formula adds BMR by default

hrKcalMin = Math.max(0, hrKcalMin - bmr) * activeCaloriesCoefficient;
let stepsKcalMin = (stepsMet * 3.5 * weight) / 200;
// blend METs
let finalActiveKcalMin = 0;
if (stepsPerMin > 120) {
if (stepsPerMin > 180) {
// strenuous activity
finalActiveKcalMin = hrKcalMin * 0.8 + stepsKcalMin * 0.2;
} else if (stepsPerMin >= 10) {
// moderate activity
finalActiveKcalMin = hrKcalMin * 0.5 + stepsKcalMin * 0.5;
} else if (stepsPerMin >= 60) {
// moderate activity
finalActiveKcalMin = hrKcalMin * 0.8 + stepsKcalMin * 0.2;
} else {
// sedentary or non-step activity (weights)
// For elderly, don't penalize as much - might be resistance training
if (age > 65) {
finalActiveKcalMin = hrKcalMin * 0.8;
} else {
finalActiveKcalMin = hrKcalMin;
}
finalActiveKcalMin = hrKcalMin*0.96+stepsKcalMin * 0.04;
}

// ensure non-negative
finalActiveKcalMin = Math.max(0, finalActiveKcalMin);

// final Outputs
let activeTotal = finalActiveKcalMin * healthData.duration;
// boot.js adds bmr separately
Expand Down
6 changes: 3 additions & 3 deletions apps/calories/metadata.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"id": "calories",
"name": "Calorie Tracker (BETA)",
"name": "Calorie Tracker",
"shortName":"Calories",
"icon": "icon.png",
"version":"0.01",
"description": "A health-integrated calorie tracker using `MyProfile`. Currently in Beta Testing - see README for more details.",
"version":"0.02",
"description": "A health-integrated calorie tracker using `MyProfile`.",
"type":"app",
"tags": "health,clkinfo",
"author":"RKBoss6",
Expand Down
Loading