Finish BuffGym app

master
Paul Cockrell 2020-04-21 19:38:02 +01:00
parent 6deb376d99
commit 8272b19bb6
11 changed files with 363 additions and 409 deletions

View File

@ -1,116 +1,76 @@
const STARTED = 1;
const RESTING = 2;
const COMPLETED = 3;
const ONE_SECOND = 1000;
exports = class Exercise {
constructor(params /*{title, weight, unit, restPeriod}*/) {
const DEFAULTS = {
title: "Unknown",
weight: 0,
unit: "Kg",
restPeriod: 90,
weightIncrement: 2.5,
};
const p = Object.assign({}, DEFAULTS, params);
this._title = p.title;
this._weight = p.weight;
this._unit = p.unit;
this._originalRestPeriod = p.restPeriod; // Used when reseting _restPeriod
this._restPeriod = p.restPeriod;
this._weightIncrement = p.weightIncrement;
this._started = new Date();
this._completed = false;
this._sets = [];
constructor(params) {
this.title = params.title;
this.weight = params.weight;
this.unit = params.unit;
this.restPeriod = params.restPeriod;
this.completed = false;
this.sets = [];
this._restTimeout = null;
this._restInterval = null;
this._state = null;
}
get title() {
return this._title;
this._originalRestPeriod = params.restPeriod;
this._weightIncrement = params.weightIncrement || 2.5;
}
get humanTitle() {
return `${this._title} ${this._weight}${this._unit}`;
return `${this.title} ${this.weight}${this.unit}`;
}
get subTitle() {
const totalSets = this._sets.length;
const uncompletedSets = this._sets.filter((set) => !set.isCompleted()).length;
const totalSets = this.sets.length;
const uncompletedSets = this.sets.filter((set) => !set.isCompleted()).length;
const currentSet = (totalSets - uncompletedSets) + 1;
return `Set ${currentSet} of ${totalSets}`;
}
get restPeriod() {
return this._restPeriod;
}
decRestPeriod() {
this._restPeriod--;
}
get weight() {
return this._weight;
}
get unit() {
return this._unit;
}
get started() {
return this._started;
this.restPeriod--;
}
addSet(set) {
this._sets.push(set);
this.sets.push(set);
}
addSets(sets) {
sets.forEach(set => this.addSet(set));
}
get currentSet() {
return this._sets.filter(set => !set.isCompleted())[0];
currentSet() {
return this.sets.filter(set => !set.isCompleted())[0];
}
isLastSet() {
return this._sets.filter(set => !set.isCompleted()).length === 1;
return this.sets.filter(set => !set.isCompleted()).length === 1;
}
isCompleted() {
return !!this._completed;
return !!this.completed;
}
canSetCompleted() {
return this._sets.filter(set => set.isCompleted()).length === this._sets.length;
return this.sets.filter(set => set.isCompleted()).length === this.sets.length;
}
setCompleted() {
if (!this.canSetCompleted()) throw "All sets must be completed";
if (this.canProgress) this._weight += this._weightIncrement;
this._completed = true;
if (this.canProgress()) this.weight += this._weightIncrement;
this.completed = true;
}
get canProgress() {
canProgress() {
let completedRepsTotalSum = 0;
let targetRepsTotalSum = 0;
const completedRepsTotal = this._sets.forEach(set => completedRepsTotalSum += set.reps);
const targetRepsTotal = this._sets.forEach(set => targetRepsTotalSum += set.maxReps);
this.sets.forEach(set => completedRepsTotalSum += set.reps);
this.sets.forEach(set => targetRepsTotalSum += set.maxReps);
return (targetRepsTotalSum - completedRepsTotalSum) === 0;
}
startRestTimer(program) {
this._restTimeout = setTimeout(() => {
this.next();
}, ONE_SECOND * this._restPeriod);
this.next(program);
}, 1000 * this.restPeriod);
this._restInterval = setInterval(() => {
program.emit("redraw");
}, ONE_SECOND);
}, 1000 );
}
resetRestTimer() {
@ -118,7 +78,7 @@ exports = class Exercise {
clearInterval(this._restInterval);
this._restTimeout = null;
this._restInterval = null;
this._restPeriod = this._originalRestPeriod;
this.restPeriod = this._originalRestPeriod;
}
isRestTimerRunning() {
@ -129,52 +89,51 @@ exports = class Exercise {
clearWatch();
setWatch(() => {
this.currentSet.incReps();
this.currentSet().incReps();
program.emit("redraw");
}, BTN1, {repeat: true});
setWatch(program.next.bind(program), BTN2, {repeat: false});
setWatch(() => {
this.currentSet.decReps();
this.currentSet().decReps();
program.emit("redraw");
}, BTN3, {repeat: true});
}
setupRestingButtons(program) {
clearWatch();
setWatch(program.next.bind(program), BTN2, {repeat: true});
setWatch(program.next.bind(program), BTN2, {repeat: false});
}
next(program) {
global.poo = this;
const STARTED = 1;
const RESTING = 2;
const COMPLETED = 3;
switch(this._state) {
case null:
console.log("XXX 1 moving null -> STARTED");
this._state = STARTED;
this.setupStartedButtons(program);
break;
case STARTED:
console.log("XXX 2 moving STARTED -> RESTING");
this._state = RESTING;
this.startRestTimer(program);
this.setupRestingButtons(program);
break;
case RESTING:
this.resetRestTimer();
this.currentSet.setCompleted();
this.currentSet().setCompleted();
if (this.canSetCompleted()) {
console.log("XXX 3b moving RESTING -> COMPLETED");
this._state = COMPLETED;
this.setCompleted();
} else {
console.log("XXX 3a moving RESTING -> null");
this._state = null;
}
// As we are changing state and require it to be reprocessed
// invoke the next step of program
program.next(program);
program.next();
break;
default:
throw "Exercise: Attempting to move to an unknown state";

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwwhC/AFEEolAC6lN7vdDCcECwPd6guVGCYuDC4cCBQMikQXQJAMjkECmcyIx4XDmUjmYvLC4XUDARHBIoIWLgATCGQdA7tEonQC5ouDDYg0BOxgSEAggwKRwgUCC6ZIDSwoXNogWDDgNCAgIWIkUEoUk6kiCgMkokipsiBIQXIki2CAgNCAoYADC5Eic4Mic4ICCAIIJCC5MzAAcykYGEAAIXOABAXTmUzGoIXVAIIXLB4SICDIovjO76PZbYR3PDI4XiI6530MIh3SC6R33C/oAOC48CCxsgC44A/ADY="))
require("heatshrink").decompress(atob("mEwxH+ACPI5AUSADAtB5vNGFQtBAIfNF95hoF4wwoF5AwmF5BhmXYbAEF/6QbF1QwIF04qB54ADAwIwoF4oRKBoIvsB4gvZ58kkgCDFxoxaF5wuHGDQcMF5IwXDZwLDGDmlDIWlkgJDSwIABCRAwPDQohCFgIABDQIOCFwYABr4RCCQIvQDYguEAAwtFF5owJDZAvHFw4vFOYQvKFAowMBxIvFMQwvPAB4wFUQ4vJGDYvUGC4vNdgyuEGDIsNFwYwGNAgAPExAvMGIdfTIovfTpYvrfRCOkZ44ugF44NGF05gUFyQvKGIoueGKIufGJ4uhG5oupGItfr4vvAAgvlGAQvt/wrEF9oEGF841IF9QGHX0oGIAD8kAAYJOFzwEBBQoMFACA="));

View File

@ -0,0 +1,33 @@
{
"title": "Program A",
"exercises": [
{
"title": "Squats",
"weight": 40,
"unit": "Kg",
"sets": [5, 5, 5, 5, 5],
"restPeriod": 90
},
{
"title": "Overhead press",
"weight": 20,
"unit": "Kg",
"sets": [5, 5, 5, 5, 5],
"restPeriod": 90
},
{
"title": "Deadlift",
"weight": 20,
"unit": "Kg",
"sets": [5],
"restPeriod": 90
},
{
"title": "Pullups",
"weight": 0,
"unit": "Kg",
"sets": [10, 10, 10],
"restPeriod": 90
}
]
}

View File

@ -0,0 +1,33 @@
{
"title": "Program B",
"exercises": [
{
"title": "Squats",
"weight": 40,
"unit": "Kg",
"sets": [5, 5, 5, 5, 5],
"restPeriod": 90
},
{
"title": "Bench press",
"weight": 20,
"unit": "Kg",
"sets": [5, 5, 5, 5, 5],
"restPeriod": 90
},
{
"title": "Row",
"weight": 20,
"unit":"Kg",
"sets": [5, 5, 5, 5, 5],
"restPeriod": 90
},
{
"title": "Tricep extension",
"weight": 20,
"unit": "Kg",
"sets": [10, 10, 10],
"restPeriod": 90
}
]
}

View File

@ -0,0 +1,10 @@
[
{
"title": "Program A",
"file": "buffgym-program-a.json"
},
{
"title": "Program B",
"file": "buffgym-program-b.json"
}
]

View File

@ -1,68 +1,56 @@
exports = class Program {
constructor(params) {
const DEFAULTS = {
title: "Unknown",
trainDay: "", // Day of week
};
const p = Object.assign({}, DEFAULTS, params);
this._title = p.title;
this._trainDay = p.trainDay;
this._exercises = [];
this.title = params.title;
this.exercises = [];
this.completed = false;
this.on("redraw", redraw.bind(null, this));
}
get title() {
return `${this._title} - ${this._trainDay}`;
}
addExercise(exercise) {
this._exercises.push(exercise);
}
addExercises(exercises) {
exercises.forEach(exercise => this.addExercise(exercise));
exercises.forEach(exercise => this.exercises.push(exercise));
}
currentExercise() {
return (
this._exercises
.filter(exercise => !exercise.isCompleted())[0]
);
return this.exercises.filter(exercise => !exercise.isCompleted())[0];
}
canComplete() {
return (
this._exercises
.filter(exercise => exercise.isCompleted())
.length === this._exercises.length
);
return this.exercises.filter(exercise => exercise.isCompleted()).length === this.exercises.length;
}
setCompleted() {
if (!this.canComplete()) throw "All exercises must be completed";
this._completed = true;
this.completed = true;
}
isCompleted() {
return !!this._completed;
return !!this.completed;
}
toJSON() {
return {
title: this.title,
exercises: this.exercises.map(exercise => {
return {
title: exercise.title,
weight: exercise.weight,
unit: exercise.unit,
sets: exercise.sets.map(set => set.maxReps),
restPeriod: exercise.restPeriod,
};
}),
};
}
// State machine
next() {
console.log("XXX Program.next");
const exercise = this.currentExercise();
// All exercises are completed so mark the
// Program as comleted
if (this.canComplete()) {
this.setCompleted();
this.emit("redraw");
return;
}
exercise.next(this);
// Call current exercise state machine
this.currentExercise().next(this);
}
}

View File

@ -1 +0,0 @@
[{"title":"Program A","exercises":[{"title":"Squats","weight":40,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Overhead press","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Deadlift","weight":20,"unit":"Kg","sets":[5]},{"title":"Pullups","weight":0,"unit":"Kg","sets":[10,10,10]}]},{"title":"Program B","exercises":[{"title":"Squats","weight":40,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Bench press","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Row","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Tricep extension","weight":20,"unit":"Kg","sets":[10,10,10]}]}]

View File

@ -1,101 +0,0 @@
[
{
"title": "Program A",
"exercises": [
{
"title": "Squats",
"weight": 40,
"unit": "Kg",
"sets": [
5,
5,
5,
5,
5
]
},
{
"title": "Overhead press",
"weight": 20,
"unit": "Kg",
"sets": [
5,
5,
5,
5,
5
]
},
{
"title": "Deadlift",
"weight": 20,
"unit": "Kg",
"sets": [
5
]
},
{
"title": "Pullups",
"weight": 0,
"unit": "Kg",
"sets": [
10,
10,
10
]
}
]
},
{
"title": "Program B",
"exercises": [
{
"title": "Squats",
"weight": 40,
"unit": "Kg",
"sets": [
5,
5,
5,
5,
5
]
},
{
"title": "Bench press",
"weight": 20,
"unit": "Kg",
"sets": [
5,
5,
5,
5,
5
]
},
{
"title": "Row",
"weight": 20,
"unit":"Kg",
"sets": [
5,
5,
5,
5,
5
]
},
{
"title": "Tricep extension",
"weight": 20,
"unit": "Kg",
"sets": [
10,
10,
10
]
}
]
}
]

View File

@ -1,46 +1,28 @@
exports = class Set {
constructor(maxReps) {
this._minReps = 0;
this._maxReps = maxReps;
this._reps = 0;
this._completed = false;
}
get title() {
return this._title;
}
get weight() {
return this._weight;
this.minReps = 0;
this.maxReps = maxReps;
this.reps = 0;
this.completed = false;
}
isCompleted() {
return !!this._completed;
return !!this.completed;
}
setCompleted() {
this._completed = true;
}
get reps() {
return this._reps;
}
get maxReps() {
return this._maxReps;
this.completed = true;
}
incReps() {
if (this._completed) return;
if (this._reps >= this._maxReps) return;
this._reps++;
if (this.completed) return;
if (this.reps >= this.maxReps) return;
this.reps++;
}
decReps() {
if (this._completed) return;
if (this._reps <= this._minReps) return;
this._reps--;
if (this.completed) return;
if (this.reps <= this.minReps) return;
this.reps--;
}
}

View File

@ -1,177 +1,135 @@
Bangle.setLCDMode("120x120");
const W = g.getWidth();
const H = g.getHeight();
const RED = "#d32e29";
const PINK = "#f05a56";
const WHITE = "#ffffff";
const Set = require("buffgym-set.js");
const Exercise = require("buffgym-exercise.js");
const Program = require("buffgym-program.js");
function centerStringX(str) {
return (W - g.stringWidth(str)) / 2;
}
function iconIncrement() {
const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglHA4IpJBYwTHA4RMJCY5oDJo4THKIQKET5IMGCaY7TMaKLTWajbTFJIlICgoVBFYXJYQYSGCggAGCRAVIBgw"));
return img;
}
function iconDecrement() {
const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCRYABCYQmOFAhNMKIw6FTw4LHCaY7TMaKLTWajbTFJglFCgoVBFYXJYQYSGCggAGCRAVIBgw="));
return img;
}
function iconOk() {
const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCJQxCCYQmMIwZoDJpQMCKIg6KBYwTGFQgeHHYouCCRI7EMYTXFRhILEK5SfFRgYSIborbSbpglFCgoVBFYXJYQYSGCggAGCRAVIBgwA=="));
return img;
}
function drawMenu(params) {
const hs = require("heatshrink");
const incImg = hs.decompress(atob("gsFwMAkM+oUA"));
const decImg = hs.decompress(atob("gsFwIEBnwCBA"));
const okImg = hs.decompress(atob("gsFwMAhGFo0A"));
const DEFAULT_PARAMS = {
showBTN1: false,
showBTN2: false,
showBTN3: false,
};
const p = Object.assign({}, DEFAULT_PARAMS, params);
if (p.showBTN1) g.drawImage(iconIncrement(), W - 30, 10);
if (p.showBTN2) g.drawImage(iconOk(), W - 30, 110);
if (p.showBTN3) g.drawImage(iconDecrement(), W - 30, 210);
if (p.showBTN1) g.drawImage(incImg, W - 10, 10);
if (p.showBTN2) g.drawImage(okImg, W - 10, 60);
if (p.showBTN3) g.drawImage(decImg, W - 10, 110);
}
function clearScreen() {
g.setColor(RED);
g.fillRect(0,0,W,H);
}
function drawTitle(exercise) {
const title = exercise.humanTitle;
g.setFont("Vector",20);
g.setColor(WHITE);
g.drawString(title, centerStringX(title), 5);
}
function drawReps(exercise) {
const set = exercise.currentSet;
function drawSet(exercise) {
const set = exercise.currentSet();
if (set.isCompleted()) return;
g.clear();
// Draw exercise title
g.setColor(PINK);
g.fillCircle(W / 2, H / 2, 50);
g.fillRect(15, 0, W - 15, 18);
g.setFontAlign(0, -1);
g.setFont("6x8", 1);
g.setColor(WHITE);
g.setFont("Vector", 40);
g.drawString(set.reps, centerStringX(set.reps), (H - 45) / 2);
g.setFont("Vector", 15);
const note = `of ${set.maxReps}`;
g.drawString(note, centerStringX(note), (H / 2) + 25);
}
function drawSets(exercise) {
const sets = exercise.subTitle;
g.drawString(exercise.title, W / 2, 5);
g.setFont("6x8", 1);
g.drawString(exercise.weight + " " + exercise.unit, W / 2, 27);
// Draw completed reps counter
g.setFontAlign(0, 0);
g.setColor(PINK);
g.fillRect(15, 42, W - 15, 80);
g.setColor(WHITE);
g.setFont("Vector", 15);
g.drawString(sets, centerStringX(sets), H - 25);
}
g.setFont("6x8", 5);
g.drawString(set.reps, (W / 2) + 2, (H / 2) + 1);
g.setFont("6x8", 1);
const note = `Target reps: ${set.maxReps}`;
g.drawString(note, W / 2, H - 24);
// Draw sets monitor
g.drawString(exercise.subTitle, W / 2, H - 12);
function drawSetProgress(exercise) {
drawTitle(exercise);
drawReps(exercise);
drawSets(exercise);
drawMenu({showBTN1: true, showBTN2: true, showBTN3: true});
g.flip();
}
function drawStartNextExercise() {
const title = "Good work";
const msg = "No need to rest\nmove straight on\nto the next exercise";
g.setColor(WHITE);
g.setFont("Vector", 35);
g.drawString(title, centerStringX(title), 10);
g.setFont("Vector", 15);
g.drawString(msg, 30, 150);
drawMenu({showBTN1: false, showBTN2: true, showBTN3: false});
}
function drawProgramCompleted() {
function drawProgDone() {
const title1 = "You did";
const title2 = "GREAT!";
const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest.";
clearWatch();
setWatch(Bangle.showLauncher, BTN2, {repeat: false});
g.setColor(WHITE);
g.setFont("Vector", 35);
g.drawString(title1, centerStringX(title1), 10);
g.setFont("Vector", 40);
g.drawString(title2, centerStringX(title2), 50);
g.setFont("Vector", 15);
g.drawString(msg, 30, 150);
drawMenu({showBTN1: false, showBTN2: true, showBTN3: false});
}
/*
function drawExerciseCompleted(program) {
const exercise = program.currentExercise();
const title = exercise.canProgress?
"WELL DONE!" :
"NOT BAD!";
const msg = exercise.canProgress?
`You weight is automatically increased\nfor ${exercise.title} to ${exercise.weight}${exercise.unit}` :
"It looks like you struggled\non a few sets, your weight will\nstay the same";
const action = "Move straight on to the next exercise";
clearScreen();
g.setColor(WHITE);
g.setFont("Vector", 20);
g.drawString(title, centerStringX(title), 10);
g.setFont("Vector", 10);
g.drawString(msg, centerStringX(msg), 180);
g.drawString(action, centerStringX(action), 210);
drawMenu({showBTN2: true});
clearWatch();
setWatch(() => {
init(program);
}, BTN2, {repeat: false});
g.setFontAlign(0, -1);
g.setColor(WHITE);
g.setFont("6x8", 2);
g.drawString(title1, W / 2, 10);
g.drawString(title2, W / 2, 30);
g.setFont("6x8", 1);
g.drawString(msg, (W / 2) + 3, 70);
g.flip();
}
function drawSetComp() {
const title = "Good work";
const msg = "No need to rest\nmove straight on\nto the next\nexercise.Your\nweight has been\nincreased for\nnext time!";
g.clear();
drawMenu({showBTN2: true});
g.setFontAlign(0, -1);
g.setColor(WHITE);
g.setFont("6x8", 2);
g.drawString(title, W / 2, 10);
g.setFont("6x8", 1);
g.drawString(msg, (W / 2) - 2, 45);
g.flip();
}
*/
function drawRestTimer(program) {
const exercise = program.currentExercise();
const motivation = "Take a breather..";
clearScreen();
drawMenu({showBTN2: true});
g.setColor(PINK);
g.fillCircle(W / 2, H / 2, 50);
g.setColor(WHITE);
g.setFont("Vector", 15);
g.drawString(motivation, centerStringX(motivation), 25);
g.setFont("Vector", 40);
g.drawString(exercise.restPeriod, centerStringX(exercise.restPeriod), (H - 45) / 2);
exercise.decRestPeriod();
if (exercise.restPeriod <= 0) {
exercise.resetRestTimer();
redraw(program);
program.next();
return;
}
g.clear();
drawMenu({showBTN2: true});
g.setFontAlign(0, -1);
g.setColor(PINK);
g.fillRect(15, 42, W - 15, 80);
g.setColor(WHITE);
g.setFont("6x8", 1);
g.drawString("Have a short\nrest period.", W / 2, 10);
g.setFont("6x8", 5);
g.drawString(exercise.restPeriod, (W / 2) + 2, (H / 2) - 19);
g.flip();
exercise.decRestPeriod();
}
function redraw(program) {
const exercise = program.currentExercise();
clearScreen();
g.clear();
if (program.isCompleted()) {
drawProgramCompleted(program);
saveProg(program);
drawProgDone(program);
return;
}
if (exercise.isRestTimerRunning()) {
if (exercise.isLastSet()) {
drawStartNextExercise(program);
drawSetComp(program);
} else {
drawRestTimer(program);
}
@ -179,33 +137,126 @@ function redraw(program) {
return;
}
drawSetProgress(exercise);
drawSet(exercise);
}
function init(program) {
clearWatch();
program.next();
}
function drawProgMenu(programs, selProgIdx) {
g.clear();
g.setFontAlign(0, -1);
g.setColor(WHITE);
g.setFont("6x8", 2);
g.drawString("BuffGym", W / 2, 10);
// Setup training program. This should come from file
// Squats
function buildPrograms() {
const programsJSON = require("Storage").readJSON("buffgym-programs.json", 1);
if (!programsJSON) throw "No programs JSON found";
const programs = [];
programsJSON.forEach(programJSON => {
const program = new Program({
title: programJSON.title,
g.setFont("6x8", 1);
g.setFontAlign(-1, -1);
let selectedProgram = programs[selProgIdx].title;
let yPos = 50;
programs.forEach(program => {
g.setColor("#f05a56");
g.fillRect(0, yPos, W, yPos + 11);
g.setColor("#ffffff");
if (selectedProgram === program.title) {
g.drawRect(0, yPos, W - 1, yPos + 11);
}
g.drawString(program.title, 10, yPos + 2);
yPos += 15;
});
const exercises = programJSON.exercises.map(exerciseJSON => {
g.flip();
}
function setupMenu() {
clearWatch();
const progs = getProgIndex();
let selProgIdx = 0;
drawProgMenu(progs, selProgIdx);
setWatch(()=>{
selProgIdx--;
if (selProgIdx< 0) selProgIdx = 0;
drawProgMenu(progs, selProgIdx);
}, BTN1, {repeat: true});
setWatch(()=>{
const prog = buildProg(progs[selProgIdx].file);
prog.next();
}, BTN2, {repeat: false});
setWatch(()=>{
selProgIdx++;
if (selProgIdx > progs.length - 1) selProgIdx = progs.length - 1;
drawProgMenu(progs, selProgIdx);
}, BTN3, {repeat: true});
}
function drawSplash() {
g.reset();
g.setBgColor(RED);
g.clear();
g.setColor(WHITE);
g.setFontAlign(0,-1);
g.setFont("6x8", 2);
g.drawString("BuffGym", W / 2, 10);
g.setFont("6x8", 1);
g.drawString("5x5", W / 2, 42);
g.drawString("training app", W / 2, 55);
g.drawRect(19, 38, 100, 99);
const img = require("heatshrink").decompress(atob("lkdxH+AB/I5ASQACwpB5vNFkwpBAIfNFdZZkFYwskFZAsiFZBZiVYawEFf6ETFUwsIFUYmB54ADAwIskFYoRKBoIroB4grV58kkgCDFRotWFZwqHFiwYMFZIsTC5wLDFjGlCoWlkgJDRQIABCRAsLCwodCFAIABCwIOCFQYABr4RCCQIrMC4gqEAAwpFFZosFC5ArHFQ4rFNYQrGEgosMBxIrFLQwrLAB4sFSw4rFFjYrQFi4rNbASeEFjIoJFQYsGMAgAPEQgAIGwosCRoorbA="));
g.drawImage(img, 40, 70);
g.flip();
let flasher = false;
let bgCol, txtCol;
const i = setInterval(() => {
if (flasher) {
bgCol = WHITE;
txtCol = RED;
} else {
bgCol = RED;
txtCol = WHITE;
}
flasher = !flasher;
g.setColor(bgCol);
g.fillRect(0, 108, W, 120);
g.setColor(txtCol);
g.drawString("Press btn to begin", W / 2, 110);
g.flip();
}, 250);
setWatch(()=>{
clearInterval(i);
setupMenu();
}, BTN1, {repeat: false});
setWatch(()=>{
clearInterval(i);
setupMenu();
}, BTN2, {repeat: false});
setWatch(()=>{
clearInterval(i);
setupMenu();
}, BTN3, {repeat: false});
}
function getProgIndex() {
const progIdx = require("Storage").readJSON("buffgym-program-index.json");
return progIdx;
}
function buildProg(fName) {
const Set = require("buffgym-set.js");
const Exercise = require("buffgym-exercise.js");
const Program = require("buffgym-program.js");
const progJSON = require("Storage").readJSON(fName);
const prog = new Program({
title: progJSON.title,
});
const exercises = progJSON.exercises.map(exerciseJSON => {
const exercise = new Exercise({
title: exerciseJSON.title,
weight: exerciseJSON.weight,
unit: exerciseJSON.unit,
restPeriod: exerciseJSON.restPeriod,
});
exerciseJSON.sets.forEach(setJSON => {
exercise.addSet(new Set(setJSON));
@ -213,14 +264,14 @@ function buildPrograms() {
return exercise;
});
program.addExercises(exercises);
programs.push(program);
});
prog.addExercises(exercises);
return programs;
return prog;
}
// For this spike, just run the first program, what will
// really happen is the user picks a program to do from
// some menu on a start page.
init(buildPrograms()[0]);
function saveProg(program) {
const fName = getProgIndex().find(prog => prog.title === program.title).file;
require("Storage").writeJSON(fName, program.toJSON());
}
drawSplash();

BIN
apps/buffgym/buffgym.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB