Add possibility of creating a custom exercise

master
Erovia 2024-02-23 17:06:16 +00:00
parent 42389fd9b4
commit 551a5db611
5 changed files with 105 additions and 39 deletions

View File

@ -1,3 +1,4 @@
0.01: New App! 0.01: New App!
0.02: Add rep info to time screen 0.02: Add rep info to time screen
0.03: Add option to pause/resume workout (Bangle.js 1 only) 0.03: Add option to pause/resume workout (Bangle.js 1 only)
0.04: Add possibility of creating a custom exercise

View File

@ -50,6 +50,21 @@ For example `w6d1(r:6|w:3|x2)` means:
--- ---
### Create a custom excercise
Under the `Custom run` menu, it's possible to create a custom excercise.
![](c25k-scrn9.png)
Some important details/limitations:
- To disable walking: set `walk` to `0`
- When walking is set to `0`, the repetition count is set to `1`.
- When repetition is set to `2` or higher, `walk` is set to `1`.
**Unfortunately, the value in the menu do not update to reflect the changes, so I recommend setting the values with the rules above in mind.**
---
### Show extra info: ### Show extra info:
If you ever need to peek at the time, just press the middle (or only) physical button on the watch: If you ever need to peek at the time, just press the middle (or only) physical button on the watch:

View File

@ -1,6 +1,10 @@
var week = 1; var week = 1; // Stock plan: programme week
var day = 1; var day = 1; // Stock plan: programe day
var time; var run = 1; // Custom plan: running time
var walk = 0; // Custom plan: walking time
var reps = 1; // Custom plan: repetition count
var time; // To store the date
var loop; // To store how many times we will have to do a countdown var loop; // To store how many times we will have to do a countdown
var rep; // The current rep counter var rep; // The current rep counter
@ -11,8 +15,9 @@ var activityInterval; // Ticks every second, doing the countdown
var extraInfoWatch; // Watch for button presses to show additional info var extraInfoWatch; // Watch for button presses to show additional info
var paused = false; // Track pause state var paused = false; // Track pause state
var pauseOrResumeWatch; // Watch for button presses to pause/resume countdown var pauseOrResumeWatch; // Watch for button presses to pause/resume countdown
var defaultFontSize = (process.env.HWVERSION == 2) ? 7 : 8; // Default font size, Banglejs 2 has smaller var defaultFontSize = (process.env.HWVERSION == 2) ? 7 : 9; // Default font size, Banglejs 2 has smaller
var activityBgColour; // Background colour of current activity var activityBgColour; // Background colour of current activity
var currentActivity; // To store the current activity
function outOfTime() { function outOfTime() {
buzz(); buzz();
@ -27,6 +32,7 @@ function outOfTime() {
setTimeout(E.showMenu, 5000, mainmenu); // Show the main menu again after 5secs setTimeout(E.showMenu, 5000, mainmenu); // Show the main menu again after 5secs
clearInterval(mainInterval); // Stop the main interval from starting a new activity clearInterval(mainInterval); // Stop the main interval from starting a new activity
mainInterval = undefined; mainInterval = undefined;
currentMode = undefined;
} }
} }
@ -51,11 +57,9 @@ function countDown() {
var text = ""; var text = "";
var size = defaultFontSize; var size = defaultFontSize;
if (time) { if (time) {
var w = week -1; var total = ("walk" in currentActivity) ? currentActivity.repetition : 1;
var d = day - 1;
var total = ("walk" in PLAN[w][d]) ? PLAN[w][d].repetition : 1;
text += rep + "/" + total + "\n"; // Show the current/total rep count when time is shown text += rep + "/" + total + "\n"; // Show the current/total rep count when time is shown
size -= (process.env.HWVERSION == 2) ? 2 : 1; // Use smaller font size to fit everything nicely on the screen size -= 2; // Use smaller font size to fit everything nicely on the screen
} }
text += (currentMode === "run") ? "Run\n" + counter : "Walk\n" + counter; // Switches output text text += (currentMode === "run") ? "Run\n" + counter : "Walk\n" + counter; // Switches output text
if (time) text += "\n" + time; if (time) text += "\n" + time;
@ -74,7 +78,7 @@ function countDown() {
} }
} }
function startTimer(w, d) { function startTimer() {
// If something is already running, do nothing // If something is already running, do nothing
if (activityInterval) return; if (activityInterval) return;
@ -82,12 +86,12 @@ function startTimer(w, d) {
if (!currentMode || currentMode === "walk") { if (!currentMode || currentMode === "walk") {
currentMode = "run"; currentMode = "run";
rep++; // Increase the rep counter every time a "run" activity starts rep++; // Increase the rep counter every time a "run" activity starts
counter = PLAN[w][d].run * 60; counter = currentActivity.run * 60;
activityBgColour = "#ff5733"; // Red background for running activityBgColour = "#ff5733"; // Red background for running
} }
else { else {
currentMode = "walk"; currentMode = "walk";
counter = PLAN[w][d].walk * 60; counter = currentActivity.walk * 60;
activityBgColour = "#4da80a"; // Green background for walking activityBgColour = "#4da80a"; // Green background for walking
} }
@ -128,27 +132,23 @@ function populatePlan() {
} }
} }
// Helper function to generate functions for the PLAN menu // Helper function to generate functions for the activePlan menu
function getFunc(i, j) { function getFunc(i, j) {
return function() { return function() {
week = i + 1; currentActivity = PLAN[i][j];
day = j + 1;
startActivity(); startActivity();
}; };
} }
function startActivity() { function startActivity() {
var w = week - 1; loop = ("walk" in currentActivity) ? currentActivity.repetition * 2 : 1;
var d = day - 1;
loop = ("walk" in PLAN[w][d]) ? PLAN[w][d].repetition * 2 : 1;
rep = 0; rep = 0;
E.showMenu(); // Hide the main menu E.showMenu(); // Hide the main menu
extraInfoWatch = setWatch(showTime, (process.env.HWVERSION == 2) ? BTN1 : BTN2, {repeat: true}); // Show the clock on button press extraInfoWatch = setWatch(showTime, (process.env.HWVERSION == 2) ? BTN1 : BTN2, {repeat: true}); // Show the clock on button press
if (process.env.HWVERSION == 1) pauseOrResumeWatch = setWatch(pauseOrResumeActivity, BTN1, {repeat: true}); // Pause or resume on button press (Bangle.js 1 only) if (process.env.HWVERSION == 1) pauseOrResumeWatch = setWatch(pauseOrResumeActivity, BTN1, {repeat: true}); // Pause or resume on button press (Bangle.js 1 only)
buzz(); buzz();
mainInterval = setInterval(function() {startTimer(w, d);}, 1000); // Check every second if we need to do something mainInterval = setInterval(function() {startTimer();}, 1000); // Check every second if we need to do something
} }
// Pause or resume current activity // Pause or resume current activity
@ -207,35 +207,84 @@ const PLAN = [
], ],
]; ];
var customRun = {"run": 1};
// Main menu // Main menu
var mainmenu = { var mainmenu = {
"" : { "": { "title": "-- C25K --" },
"title" : "-- C25K --" "Week": {
}, value: week,
"Week" : { min: 1, max: PLAN.length, step: 1,
value : week,
min:1,max:PLAN.length,step:1,
onchange : v => { week = v; } onchange : v => { week = v; }
}, },
"Day" : { "Day": {
value : day, value: day,
min:1,max:3,step:1, min: 1, max: 3, step: 1,
onchange : v => { day = v; } onchange: v => { day = v; }
}, },
"View plan" : function() { E.showMenu(planmenu); }, "View plan": function() { E.showMenu(planmenu); },
"Start" : function() { startActivity(); }, "Custom run": function() { E.showMenu(custommenu); },
"Exit" : function() { load(); }, "Start": function() {
currentActivity = PLAN[week - 1][day -1];
startActivity();
},
"Exit": function() { load(); },
}; };
// Plan view // Plan view
var planmenu = { var planmenu = {
"" : { "": { title: "-- Plan --" },
title : "-- Plan --", "< Back": function() { E.showMenu(mainmenu);},
back : function() { E.showMenu(mainmenu);},
}
}; };
// Populate the PLAN menu view // Custom view
var custommenu = {
"": { title : "-- Cust. run --" },
"< Back": function() { E.showMenu(mainmenu);},
"Run (mins)": {
value: run,
min: 1, max: 150, step: 1,
wrap: true,
onchange: v => { customRun.run = v; }
},
"Walk (mins)": {
value: walk,
min: 0, max: 10, step: 1,
onchange: v => {
if (v > 0) {
if (reps == 1) { reps = 2; } // Walking only makes sense with multiple reps
customRun.repetition = reps;
customRun.walk = v;
}
else {
// If no walking, delete both the reps and walk data
delete customRun.repetition;
delete customRun.walk;
}
walk = v;
}
},
"Reps": {
value: reps,
min: 1, max: 10, step: 1,
onchange: v => {
if (v > 1) {
if (walk == 0) { walk = 1; } // Multiple reps only make sense with walking phases
customRun.walk = walk;
customRun.repetition = v;
}
else {
// If no multiple reps, delete both the reps and walk data
delete customRun.repetition;
delete customRun.walk;
}
reps = v;
}
},
"Start": function() { currentActivity = customRun; startActivity(); }
};
// Populate the activePlan menu view
populatePlan(); populatePlan();
// Actually display the menu // Actually display the menu
E.showMenu(mainmenu); E.showMenu(mainmenu);

BIN
apps/c25k/c25k-scrn9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -2,7 +2,7 @@
"id": "c25k", "id": "c25k",
"name": "C25K", "name": "C25K",
"icon": "app.png", "icon": "app.png",
"version":"0.03", "version":"0.04",
"description": "Unofficial app for the Couch to 5k training plan", "description": "Unofficial app for the Couch to 5k training plan",
"readme": "README.md", "readme": "README.md",
"type": "app", "type": "app",
@ -24,6 +24,7 @@
{"url": "c25k-scrn5.png"}, {"url": "c25k-scrn5.png"},
{"url": "c25k-scrn6.png"}, {"url": "c25k-scrn6.png"},
{"url": "c25k-scrn7.png"}, {"url": "c25k-scrn7.png"},
{"url": "c25k-scrn8.png"} {"url": "c25k-scrn8.png"},
{"url": "c25k-scrn9.png"}
] ]
} }