-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3448 from slynchDev/master
Burn - Simple Calorie Counter
- Loading branch information
Showing
8 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.prettierignore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
0.01: New App! | ||
0.02: Added README.md | ||
0.03: Icon update | ||
0.04: Icon Fix | ||
0.05: Misc cleanup for PR | ||
0.06: Implementing fixes from PR comments | ||
0.07: Bug fix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Burn: Calorie Counter | ||
|
||
Burn is a simple calorie counter application. It is based on the original Counter app and has been enhanced with additional features (I recommend using | ||
it with the "Digital Clock Widget", if you intend to keep it running). | ||
|
||
## Features | ||
|
||
- **Persistent counter**: The counter value is saved to flash, so it persists even when the app is closed or the device is restarted. | ||
- **Daily reset**: The counter resets each day, allowing you to track your calorie intake on a daily basis. | ||
- **Adjustable increment value**: You can adjust the increment value to suit your needs. | ||
|
||
## Controls | ||
|
||
### Bangle.js 1 | ||
|
||
- **BTN1**: Increase (or tap right) | ||
- **BTN3**: Decrease (or tap left) | ||
- **Press BTN2**: Change increment | ||
|
||
### Bangle.js 2 | ||
|
||
- **Swipe up**: Increase | ||
- **Swipe down**: Decrease | ||
- **Press BTN**: Change increment | ||
|
||
## How it Works | ||
|
||
The counter value and the date are stored in a file named "kcal.txt". The counter value is read from the file when the app starts and written to the file whenever the counter value is updated. | ||
|
||
The app uses the current date to determine whether to reset the counter. If the date has changed since the last time the counter was updated, the counter is reset to 0. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
/* | ||
* Burn: Calories Counter for Bangle.js (Espruino). Based on the original Counter app. | ||
* Features: | ||
* - Persistent counter: saved to a file. | ||
* - Daily reset: counter resets each day. | ||
* - Adjustable increment value. | ||
* | ||
* Bangle.js 1 Controls: | ||
* - BTN1: Increase (or tap right) | ||
* - BTN3: Decrease (or tap left) | ||
* - Press BTN2: Change increment | ||
* | ||
* Bangle.js 2 Controls: | ||
* - Swipe up: Increase | ||
* - Swipe down: Decrease | ||
* - Press BTN: Change increment | ||
*/ | ||
|
||
// File variable to handle file operations | ||
let file; | ||
|
||
// Check if the hardware version is Bangle.js 2 | ||
const BANGLEJS2 = process.env.HWVERSION == 2; | ||
|
||
// Importing the Storage module for file operations | ||
const Storage = require("Storage"); | ||
|
||
// File path for the counter data | ||
const PATH = "kcal.txt"; | ||
|
||
// Function to get the current date as a string | ||
function dayString() { | ||
const date = new Date(); | ||
// Month is 0-indexed, so we add 1 to get the correct month number | ||
return `${date.getMonth() + 1}-${date.getDate()}-${date.getFullYear()}`; | ||
} | ||
|
||
// Counter object to keep track of the count and the date | ||
let counter = { count: 0, date: dayString() }; | ||
|
||
// Function to read the counter from the file | ||
function readCounterFromFile() { | ||
try { | ||
// Open the file in read mode | ||
file = Storage.open(PATH, "r"); | ||
let line = file.readLine(); | ||
|
||
// If the file has content, parse it and update the counter | ||
if (line) { | ||
let splitLine = line.trim().split(","); | ||
counter = { count: parseInt(splitLine[0]), date: splitLine[1] }; | ||
} | ||
} catch (err) { | ||
// If the file does not exist, the counter will remain 0 | ||
} | ||
} | ||
|
||
// Function to write the counter to the file | ||
function writeCounterToFile() { | ||
// Open the file in write mode | ||
file = Storage.open(PATH, "w"); | ||
// Write the counter and date to the file | ||
file.write(counter.count.toString() + "," + counter.date + "\n"); | ||
} | ||
|
||
// Function to reset the counter | ||
function resetCounter() { | ||
// Reset the counter to 0 and update the date | ||
counter = { count: 0, date: dayString() }; | ||
} | ||
|
||
// Function to update the counter value | ||
function updateCounterValue(value) { | ||
// Update the counter with the new value, ensuring it's not less than 0 | ||
counter = { count: Math.max(0, value), date: dayString() }; | ||
} | ||
|
||
// Function to update the counter | ||
function updateCounter(value) { | ||
// If the date has changed, reset the counter | ||
if (counter.date != dayString()) { | ||
resetCounter(); | ||
} else { | ||
// Otherwise, update the counter value | ||
updateCounterValue(value); | ||
} | ||
|
||
// Write the updated counter to the file | ||
writeCounterToFile(); | ||
// Update the screen with the new counter value | ||
updateScreen(); | ||
} | ||
|
||
// Function to set a watch on a button to update the counter when pressed | ||
function counterButtonWatch(button, increment) { | ||
setWatch( | ||
() => { | ||
// If the button is for incrementing, or the counter is greater than 0, update the counter | ||
if (increment || counter.count > 0) { | ||
updateCounter( | ||
counter.count + (increment ? getInterval() : -getInterval()) | ||
); | ||
// Update the screen with the new counter value | ||
updateScreen(); | ||
} | ||
}, | ||
button, | ||
{ repeat: true } | ||
); | ||
} | ||
|
||
// Function to create interval functions | ||
const createIntervalFunctions = function () { | ||
// Array of intervals | ||
const intervals = [50, 100, 200, 10]; | ||
// Current location in the intervals array | ||
let location = 0; | ||
|
||
// Function to get the current interval | ||
const getInterval = function () { | ||
return intervals[location]; | ||
}; | ||
|
||
// Function to rotate the increment | ||
const rotateIncrement = function () { | ||
// Update the location to the next index in the intervals array, wrapping around if necessary | ||
location = (location + 1) % intervals.length; | ||
// Update the screen with the new increment | ||
updateScreen(); | ||
}; | ||
|
||
// Return the getInterval and rotateIncrement functions | ||
return { getInterval, rotateIncrement }; | ||
}; | ||
|
||
// Create the interval functions | ||
const intervalFunctions = createIntervalFunctions(); | ||
const getInterval = intervalFunctions.getInterval; | ||
const rotateIncrement = intervalFunctions.rotateIncrement; | ||
|
||
// Function to update the screen | ||
function updateScreen() { | ||
// Clear the screen area for the counter | ||
g.clearRect(0, 50, 250, BANGLEJS2 ? 130 : 150) | ||
.setBgColor(g.theme.bg) | ||
.setColor(g.theme.fg) | ||
.setFont("Vector", 40) | ||
.setFontAlign(0, 0) | ||
// Draw the counter value | ||
.drawString(Math.floor(counter.count), g.getWidth() / 2, 100) | ||
.setFont("6x8") | ||
// Clear the screen area for the increment | ||
.clearRect(g.getWidth() / 2 - 50, 140, g.getWidth() / 2 + 50, 160) | ||
// Draw the increment value | ||
.drawString("Increment: " + getInterval(), g.getWidth() / 2, 150); | ||
|
||
// If the hardware version is Bangle.js 1, draw the increment and decrement buttons | ||
if (!BANGLEJS2) { | ||
g.drawString("-", 45, 100).drawString("+", 185, 100); | ||
} | ||
} | ||
|
||
// If the hardware version is Bangle.js 2, set up the drag handling and button watch | ||
|
||
let drag; | ||
|
||
if (BANGLEJS2) { | ||
// Set up drag handling | ||
Bangle.on("drag", (e) => { | ||
// If this is the start of a drag, record the initial coordinates | ||
if (!drag) { | ||
drag = { x: e.x, y: e.y }; | ||
return; | ||
} | ||
|
||
// If the button is still being pressed, ignore this event | ||
if (e.b) return; | ||
|
||
// Calculate the change in x and y from the start of the drag | ||
const dx = e.x - drag.x; | ||
const dy = e.y - drag.y; | ||
// Reset the drag start coordinates | ||
drag = null; | ||
|
||
// Determine if the drag is primarily horizontal or vertical | ||
const isHorizontalDrag = Math.abs(dx) > Math.abs(dy) + 10; | ||
const isVerticalDrag = Math.abs(dy) > Math.abs(dx) + 10; | ||
|
||
// If the drag is primarily horizontal, ignore it | ||
if (isHorizontalDrag) { | ||
return; | ||
} | ||
|
||
// If the drag is primarily vertical, update the counter | ||
if (isVerticalDrag) { | ||
// If the drag is downwards and the counter is greater than 0, decrease the counter | ||
if (dy > 0 && counter.count > 0) { | ||
updateCounter(counter.count - getInterval()); | ||
} else if (dy < 0) { | ||
// If the drag is upwards, increase the counter | ||
updateCounter(counter.count + getInterval()); | ||
} | ||
// Update the screen with the new counter value | ||
updateScreen(); | ||
} | ||
}); | ||
|
||
// Set a watch on the button to rotate the increment when pressed | ||
setWatch(rotateIncrement, BTN1, { repeat: true }); | ||
} else { | ||
// If the hardware version is Bangle.js 1, set up the button watches | ||
|
||
// Set watch on button to increase the counter | ||
counterButtonWatch(BTN1, true); | ||
counterButtonWatch(BTN5, true); // screen tap | ||
// Set watch on button to decrease the counter | ||
counterButtonWatch(BTN3, false); | ||
counterButtonWatch(BTN4, false); // screen tap | ||
|
||
// Set a watch on button to rotate the increment when pressed | ||
setWatch( | ||
() => { | ||
rotateIncrement(); | ||
}, | ||
BTN2, | ||
{ repeat: true } | ||
); | ||
} | ||
|
||
// clear the screen | ||
g.clear(); | ||
|
||
// Set the background and foreground colors | ||
g.setBgColor(g.theme.bg).setColor(g.theme.fg); | ||
|
||
// Load and draw the widgets | ||
Bangle.loadWidgets(); | ||
Bangle.drawWidgets(); | ||
|
||
// Read the counter from the file | ||
readCounterFromFile(); | ||
// Update the screen with the counter value | ||
updateScreen(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"id": "burn", | ||
"name": "Burn", | ||
"version": "0.07", | ||
"description": "Simple Calorie Counter -- saves to flash and resets at midnight. I often keep mine running while the digital clock widget is at the top", | ||
"icon": "app-icon.png", | ||
"tags": "tool", | ||
"readme":"README.md", | ||
"supports": ["BANGLEJS", "BANGLEJS2"], | ||
"screenshots": [{"url":"app-screenshot.png"}], | ||
"allow_emulator": true, | ||
"storage": [ | ||
{"name":"burn.app.js","url":"app.js"}, | ||
{"name":"burn.img","url":"app-icon.js","evaluate":true} | ||
] | ||
} |