rep: working display, fixed unit problems with reps etc
parent
ef26eae665
commit
057ee7df03
134
apps/rep/app.ts
134
apps/rep/app.ts
|
|
@ -8,6 +8,7 @@ const Layout = require("Layout");
|
|||
type Rep = {
|
||||
dur: number,
|
||||
label: string,
|
||||
accDur: number,
|
||||
};
|
||||
|
||||
const reps: Rep[] = [
|
||||
|
|
@ -21,8 +22,8 @@ const reps: Rep[] = [
|
|||
{dur:3/60, label:"1st-sec"},
|
||||
{dur:5/60, label:"5-sec"},
|
||||
|
||||
// {dur:4, label:"jog"},
|
||||
// {dur:4, label:"recovery"},
|
||||
{dur:4/60, label:"jog"},
|
||||
{dur:4/60, label:"recovery"},
|
||||
|
||||
// {dur:2, label:"jog"},
|
||||
// {dur:2, label:"recovery"},
|
||||
|
|
@ -49,7 +50,17 @@ const reps: Rep[] = [
|
|||
|
||||
// {dur:3, label:"static recovery"},
|
||||
// {dur:4, label:"finish"},
|
||||
];
|
||||
].map(((r: Rep, i: number, a: Rep[]): Rep => {
|
||||
const r2 = r as Rep;
|
||||
|
||||
r2.dur = r2.dur * 60 * 1000;
|
||||
|
||||
r2.accDur = i > 0
|
||||
? a[i-1]!.accDur + r.dur
|
||||
: r.dur;
|
||||
|
||||
return r as Rep;
|
||||
}) as any);
|
||||
|
||||
const fontSzMain = 64;
|
||||
const fontSzRep = 20;
|
||||
|
|
@ -64,11 +75,17 @@ const fontSzRepDesc = 12;
|
|||
const layout = new Layout({
|
||||
type: "v",
|
||||
c: [
|
||||
{
|
||||
id: "repIdx",
|
||||
type: "txt",
|
||||
label: "Rep 1", // TODO: update in render
|
||||
font: `Vector:${fontSzRepDesc}`,
|
||||
},
|
||||
{
|
||||
id: "duration",
|
||||
lazyBuster: 1,
|
||||
type: "custom",
|
||||
font: `Vector:${fontSzMain}` as FontNameWithScaleFactor, // modified in draw
|
||||
font: `Vector:${fontSzMain}` as FontNameWithScaleFactor,
|
||||
fillx: 1,
|
||||
filly: 1,
|
||||
render: (l: Layout_.RenderedHierarchy) => {
|
||||
|
|
@ -77,25 +94,26 @@ const layout = new Layout({
|
|||
g.clearRect(l.x, l.y, l.x+l.w, l.y+l.h);
|
||||
|
||||
if(state){
|
||||
const elapsed = getElapsed(state);
|
||||
const i = currentRepIndex(elapsed);
|
||||
// TODO: inefficient
|
||||
const i = state.currentRepIndex();
|
||||
const repElapsed = state.getElapsedForRep();
|
||||
|
||||
if(i == null){
|
||||
// FIXME: dodgy end-of-rep handling
|
||||
lbl = msToHM(elapsed);
|
||||
}else{
|
||||
const thisDur = repDuration(reps[i]!);
|
||||
const remaining = thisDur - elapsed;
|
||||
lbl = msToHM(remaining);
|
||||
if(i !== null){
|
||||
let thisDur = reps[i]!.dur;
|
||||
|
||||
const fract = elapsed / thisDur;
|
||||
g.setColor("#00f")
|
||||
const remaining = thisDur - repElapsed;
|
||||
lbl = msToMinSec(remaining);
|
||||
|
||||
const fract = repElapsed / thisDur;
|
||||
g.setColor("#86caf7")
|
||||
.fillRect(
|
||||
l.x,
|
||||
l.y,
|
||||
l.x + fract * l.w,
|
||||
l.y+l.h
|
||||
l.y + l.h
|
||||
);
|
||||
}else{
|
||||
lbl = msToMinSec(repElapsed);
|
||||
}
|
||||
}else{
|
||||
lbl = "RDY";
|
||||
|
|
@ -167,16 +185,9 @@ const layout = new Layout({
|
|||
}, {lazy: true});
|
||||
|
||||
const onToggle = () => {
|
||||
if(!state){
|
||||
state = {
|
||||
begin: Date.now(),
|
||||
accumulated: 0,
|
||||
};
|
||||
play(true, state);
|
||||
}else{
|
||||
play(paused, state);
|
||||
}
|
||||
|
||||
if(!state)
|
||||
state = new State();
|
||||
state.toggle();
|
||||
drawRep();
|
||||
};
|
||||
|
||||
|
|
@ -186,47 +197,55 @@ const onPrev = () => {
|
|||
const onNext = () => {
|
||||
};
|
||||
|
||||
const play = (p: boolean, state: State) => {
|
||||
if(p){
|
||||
layout["play"]!.label = "Pause";
|
||||
class State {
|
||||
paused: boolean = true;
|
||||
begin: number = Date.now(); // only valid if !paused
|
||||
accumulated: number = 0;
|
||||
|
||||
state.begin = Date.now();
|
||||
toggle() {
|
||||
if(this.paused){
|
||||
this.begin = Date.now();
|
||||
|
||||
// TODO: move draw out
|
||||
drawInterval = setInterval(drawRep, 1000);
|
||||
}else{
|
||||
layout["play"]!.label = "Play";
|
||||
|
||||
const diff = Date.now() - state.begin;
|
||||
state.accumulated += diff;
|
||||
const diff = Date.now() - this.begin;
|
||||
this.accumulated += diff;
|
||||
|
||||
clearInterval(drawInterval!);
|
||||
}
|
||||
|
||||
paused = !p;
|
||||
this.paused = !this.paused;
|
||||
}
|
||||
|
||||
getElapsedTotal() {
|
||||
return (this.paused ? 0 : Date.now() - this.begin) + this.accumulated;
|
||||
}
|
||||
|
||||
getElapsedForRep() {
|
||||
const elapsed = this.getElapsedTotal();
|
||||
const i = this.currentRepIndex();
|
||||
|
||||
return elapsed - (i! > 0 ? reps[i!-1]!.accDur : 0);
|
||||
}
|
||||
|
||||
currentRepIndex() {
|
||||
const elapsed = this.getElapsedTotal();
|
||||
let ent;
|
||||
for(let i = 0; ent = reps[i]; i++)
|
||||
if(elapsed < ent.accDur)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
type State = { begin: number, accumulated: number };
|
||||
|
||||
let state: State | undefined;
|
||||
//let drawTimeout: number | undefined;
|
||||
let paused = false; // TODO: ditch this, used drawInterval
|
||||
let drawInterval: IntervalId | undefined;
|
||||
|
||||
const currentRepIndex = (elapsedMs: number) => {
|
||||
let total = 0;
|
||||
let ent;
|
||||
for(let i = 0; ent = reps[i]; i++){
|
||||
total += repDuration(ent);
|
||||
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} / ${rep.dur.toFixed(0)}m`;
|
||||
layout[`${id}_name`]!.label = `${rep.label} / ${msToMinSec(rep.dur)}`;
|
||||
// FIXME: display time, i.e. hh:mm
|
||||
//layout[`${id}_dur`]!.label = ``;
|
||||
}else{
|
||||
|
|
@ -240,12 +259,7 @@ const emptyLabel = (id: string) => {
|
|||
|
||||
const pad2 = (s: number) => ('0' + s.toFixed(0)).slice(-2);
|
||||
|
||||
const repDuration = (rep: Rep) => rep.dur * 60 * 1000;
|
||||
|
||||
const getElapsed = (state: State) =>
|
||||
Date.now() - state.begin + state.accumulated;
|
||||
|
||||
const msToHM = (ms: number) => {
|
||||
const msToMinSec = (ms: number) => {
|
||||
const sec = Math.round(ms / 1000);
|
||||
const min = Math.round(sec / 60);
|
||||
return min.toFixed(0) + ":" + pad2(sec % 60);
|
||||
|
|
@ -257,8 +271,9 @@ const drawRep = () => {
|
|||
if(state){
|
||||
// TODO: layout.clear(layout.next_name); layout.render(layout.next_name)
|
||||
|
||||
const elapsed = getElapsed(state);
|
||||
const i = currentRepIndex(elapsed);
|
||||
layout["play"]!.label = state.paused ? "Play" : "Pause";
|
||||
|
||||
const i = state.currentRepIndex();
|
||||
if(i !== null){
|
||||
repToLabel(i, "cur");
|
||||
repToLabel(i+1, "next");
|
||||
|
|
@ -272,6 +287,7 @@ const drawRep = () => {
|
|||
|
||||
/*
|
||||
// TODO: figure out next rep change time? or every 5s, then countdown from 10-->0
|
||||
// TODO: and then use that to Bangle.buzz() on next rep
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
|
|
|
|||
Loading…
Reference in New Issue