mirror of https://github.com/espruino/BangleApps
rep: incrementing counter
parent
b4e5e8e1df
commit
223fc5087b
168
apps/rep/app.ts
168
apps/rep/app.ts
|
@ -1,57 +1,70 @@
|
|||
// TODO: buzz on stage change, better setTimeout()
|
||||
// TODO: fastload: scoping, unregister layout handlers etc
|
||||
// TODO: spaces vs tabs
|
||||
// TODO: const colfg=g.theme.fg, colbg=g.theme.bg;
|
||||
|
||||
const Layout = require("Layout");
|
||||
|
||||
const entries /*: {dur: number, label: string}[]*/ = [
|
||||
// 1 X 4 mins - 4 min jog recovery
|
||||
// 2 X 2 mins - 2 min jog recoveries
|
||||
// 4 X 1 min - 1 min jog recoveries (turn for home after the 2nd minute)
|
||||
// 8 X 30 secs - 30 sec jog recoveries
|
||||
type Rep = {
|
||||
dur: number,
|
||||
label: string,
|
||||
};
|
||||
|
||||
const reps: Rep[] = [
|
||||
// 1 X 4 mins - 4 min recovery
|
||||
// 2 X 2 mins - 2 min recoveries
|
||||
// 4 X 1 min - 1 min recoveries (turn for home after the 2nd minute)
|
||||
// 8 X 30 secs - 30 sec recoveries
|
||||
// 3 min static recovery
|
||||
// 1 X 4 mins to finish
|
||||
|
||||
{dur:1/60, label:"1st-sec"},
|
||||
{dur:5/60, label:"5-sec"},
|
||||
|
||||
{dur:4, label:"jog"},
|
||||
{dur:4, label:"jog recovery"},
|
||||
{dur:4, label:"recovery"},
|
||||
|
||||
{dur:2, label:"jog"},
|
||||
{dur:2, label:"jog recovery"},
|
||||
{dur:2, label:"recovery"},
|
||||
{dur:2, label:"jog"},
|
||||
{dur:2, label:"jog recovery"},
|
||||
{dur:2, label:"recovery"},
|
||||
|
||||
{dur:1, label:"jog"},
|
||||
{dur:1, label:"jog recovery"},
|
||||
{dur:1, label:"recovery"},
|
||||
{dur:1, label:"jog"},
|
||||
{dur:1, label:"jog recovery"},
|
||||
{dur:1, label:"recovery"},
|
||||
{dur:1, label:"jog"},
|
||||
{dur:1, label:"jog recovery"},
|
||||
{dur:1, label:"recovery"},
|
||||
{dur:1, label:"jog"},
|
||||
{dur:1, label:"jog recovery"},
|
||||
{dur:1, label:"recovery"},
|
||||
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"jog recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
{dur:0.5, label:"jog"}, {dur:0.5, label:"recovery"},
|
||||
|
||||
{dur:3, label:"static recovery"},
|
||||
{dur:4, label:"finish"},
|
||||
];
|
||||
|
||||
const fontSzMain = 64;
|
||||
const fontSzRep = 20;
|
||||
|
||||
const repLayout = (id: string): (Layout_.Hierarchy & {type:"txt"})[] => [
|
||||
{
|
||||
id: `${id}_name`,
|
||||
type: "txt",
|
||||
font: "Vector:30",
|
||||
font: `Vector:${fontSzRep}`,
|
||||
label: "Name PH",
|
||||
pad: 4,
|
||||
}, {
|
||||
id: `${id}_dur`,
|
||||
type: "txt",
|
||||
font: "Vector:30",
|
||||
font: `Vector:${fontSzRep}`,
|
||||
label: "DURATION",
|
||||
pad: 4,
|
||||
}
|
||||
|
@ -65,16 +78,16 @@ const layout = new Layout({
|
|||
type: "v",
|
||||
c: [
|
||||
{
|
||||
type: "h",
|
||||
c: repLayout("cur"),
|
||||
id: "cur_time",
|
||||
type: "txt",
|
||||
font: `Vector:${fontSzMain}` as FontNameWithScaleFactor, // modified in draw
|
||||
label: "MM:SS", // TODO: empty strings
|
||||
fillx: 1,
|
||||
filly: 1,
|
||||
},
|
||||
{
|
||||
id: "cur_time",
|
||||
type: "txt",
|
||||
font: "Vector:40", // FIXME: bigger
|
||||
label: "MM:SS", // TODO: empty strings
|
||||
fillx: 1,
|
||||
type: "h",
|
||||
c: repLayout("cur"),
|
||||
filly: 1,
|
||||
},
|
||||
{
|
||||
|
@ -85,8 +98,10 @@ const layout = new Layout({
|
|||
{
|
||||
type: "h",
|
||||
c: [{
|
||||
id: "play",
|
||||
type: "btn",
|
||||
label: "Play", // TODO: change
|
||||
fillx: 1,
|
||||
cb: () => {
|
||||
console.log("cb()");
|
||||
},
|
||||
|
@ -97,22 +112,72 @@ const layout = new Layout({
|
|||
}, {lazy: true});
|
||||
|
||||
let index = 0;
|
||||
let begin: Date | undefined;
|
||||
let begin: number | undefined = Date.now(); // TODO: start null
|
||||
let drawTimeout: number | undefined;
|
||||
let paused = true;
|
||||
let paused = false;
|
||||
let positioned = false;
|
||||
|
||||
const pad2 = (s: number) => ('0' + s.toFixed(0)).slice(-2);
|
||||
|
||||
const currentRepIndex = (elapsedMs: number) => {
|
||||
let total = 0;
|
||||
let ent;
|
||||
for(let i = 0; ent = reps[i]; i++){
|
||||
total += ent.dur * 60 * 1000;
|
||||
if(elapsedMs < total)
|
||||
return i;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const repToLabel = (i: number, id: string) => {
|
||||
const rep = reps[i];
|
||||
if(rep){
|
||||
layout[`${id}_name`]!.label = `${i+1}: ${rep.label}`;
|
||||
layout[`${id}_dur`]!.label = `${rep.dur}m`;
|
||||
}else{
|
||||
emptyLabel(id);
|
||||
}
|
||||
};
|
||||
|
||||
const emptyLabel = (id: string) => {
|
||||
layout[`${id}_name`]!.label = "<none>";
|
||||
layout[`${id}_dur`]!.label = `0m`;
|
||||
};
|
||||
|
||||
const drawRep = () => {
|
||||
if(paused || !begin){ // TODO: separate case for paused
|
||||
layout.clear();
|
||||
layout["cur_time"]!.label = "Ready";
|
||||
|
||||
if(!positioned){
|
||||
positioned = true;
|
||||
layout.update(); // position
|
||||
}
|
||||
|
||||
layout.render(layout["play"]);
|
||||
layout.render(layout["cur_time"]);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: layout.clear(layout.next_name); layout.render(layout.next_name)
|
||||
|
||||
layout["next_name"]!.label = "next";
|
||||
layout["next_dur"]!.label = `${30}`;
|
||||
layout["cur_name"]!.label = "next";
|
||||
layout["cur_dur"]!.label = `${30}`;
|
||||
const now = Date.now();
|
||||
|
||||
layout["cur_time"]!.label = "1:23";
|
||||
const elapsed = now - begin;
|
||||
const sec = Math.round(elapsed / 1000);
|
||||
const min = Math.round(sec / 60);
|
||||
const timeStr = min.toFixed(0) + ":" + pad2(sec % 60);
|
||||
layout["cur_time"]!.label = timeStr;
|
||||
|
||||
const i = currentRepIndex(elapsed);
|
||||
if(i !== null){
|
||||
repToLabel(i, "cur");
|
||||
repToLabel(i+1, "next");
|
||||
}else{
|
||||
emptyLabel("cur");
|
||||
emptyLabel("next");
|
||||
}
|
||||
|
||||
if(!positioned){
|
||||
positioned = true;
|
||||
|
@ -121,28 +186,8 @@ const drawRep = () => {
|
|||
|
||||
layout.render();
|
||||
|
||||
|
||||
/*
|
||||
const x = g.getWidth() / 2;
|
||||
const y = g.getHeight() / 2;
|
||||
const now = new Date();
|
||||
|
||||
const elapsed = now.getDate() - begin.getDate();
|
||||
|
||||
const sec = Math.round(elapsed / 1000) % 60;
|
||||
const min = Math.round(sec / 60);
|
||||
|
||||
const timeStr = min + ":" + pad2(sec);
|
||||
let current;
|
||||
let i;
|
||||
let total = 0;
|
||||
for(i = 0; entries[i]; i++){
|
||||
const ent = entries[i];
|
||||
total += ent.dur;
|
||||
if(total > elapsed)
|
||||
break;
|
||||
current = ent;
|
||||
}
|
||||
|
||||
g.reset()
|
||||
.clearRect(Bangle.appRect)
|
||||
.setFontAlign(0, 0)
|
||||
|
@ -151,23 +196,18 @@ const drawRep = () => {
|
|||
.setFont("Vector", 33)
|
||||
.drawString(current ? current.label + " for " + current.dur : "<done>", x, y+48);
|
||||
|
||||
// TODO: figure out next rep change time? or every 5s, then countdown from 10-->0
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
drawRep();
|
||||
}, 1000 - (Date.now() % 1000));
|
||||
|
||||
if(paused){
|
||||
g.reset()
|
||||
.clearRect(Bangle.appRect)
|
||||
.setFontAlign(0, 0)
|
||||
.setFont("Vector", 55)
|
||||
.drawString("Start", g.getWidth() / 2, g.getHeight() / 2);
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
g.clear();
|
||||
var drawInterval = setInterval(drawRep, 1000);
|
||||
drawRep();
|
||||
|
||||
// TODO: widgets
|
||||
|
|
Loading…
Reference in New Issue