221 lines
6.3 KiB
JavaScript
221 lines
6.3 KiB
JavaScript
const dataFile = "chrono_data.json";
|
|
let chronoTime = require("Storage").readJSON(dataFile) || {start: 0, elapsed: 0, laps: [], mode: undefined};
|
|
|
|
const midX = Bangle.appRect.x + Bangle.appRect.x2 / 2;
|
|
const midY = Bangle.appRect.y + Bangle.appRect.y2 / 2;
|
|
const buttonH = 50;
|
|
const buttonsRect = {x: Bangle.appRect.x, y: Bangle.appRect.y2 - buttonH, x2: Bangle.appRect.x2, y2: Bangle.appRect.y2};
|
|
const timeRect = {x: Bangle.appRect.x + 3, y: buttonsRect.y - 55, x2: Bangle.appRect.x2 - 3, y2: buttonsRect.y - 10};
|
|
const lapsRect = {x: Bangle.appRect.x, y: Bangle.appRect.y, x2: Bangle.appRect.x2, y2: timeRect.y - 3};
|
|
|
|
const lapsFont = "Vector:25";
|
|
const timeFont = "Vector:40";
|
|
const lapsStrW = g.setFont(lapsFont).stringWidth("00:00.0");
|
|
const timeStrW = g.setFont(timeFont).stringWidth("00:00.0");
|
|
let updateIntID;
|
|
|
|
const drawButton = function(button) {
|
|
g.setFont("Vector:27").setFontAlign(0,0).setColor(0, 1, 1);
|
|
g.fillRect({x: button.x, y: button.y, x2: button.x + button.w - 1, y2: button.y + button.h - 1, r: 12});
|
|
g.setColor(0, 0, 0).fillRect({x: button.x + 3, y: button.y + 3, x2: button.x + button.w - 4, y2: button.y + button.h - 4, r: 9});
|
|
g.setColor(-1);
|
|
g.setFontAlign(0,0).drawString(button.label, button.x + (button.w / 2), button.y + (button.h / 2));
|
|
};
|
|
|
|
const clearButtons = function() {
|
|
g.clearRect(buttonsRect);
|
|
};
|
|
|
|
const startButton = {x: Bangle.appRect.x, y: Bangle.appRect.y2 - buttonH, w: Bangle.appRect.w, h: buttonH, label: "Start"};
|
|
const lapButton = {x: Bangle.appRect.x, y: Bangle.appRect.y2 - buttonH, w: (Bangle.appRect.w / 2) - 2, h: buttonH, label: "Lap"};
|
|
const pauseButton = {x: this.midX + 1, y: Bangle.appRect.y2 - buttonH, w: (Bangle.appRect.w / 2) - 2, h: buttonH, label: "Stop"};
|
|
const resetButton = {x: Bangle.appRect.x, y: Bangle.appRect.y2 - buttonH, w: (Bangle.appRect.w / 2) - 2, h: buttonH, label: "Reset"};
|
|
const smallStartButton = {x: this.midX + 2, y: Bangle.appRect.y2 - buttonH, w: (Bangle.appRect.w / 2) - 2, h: buttonH, label: "Start"};
|
|
|
|
const drawTime = function(timeStr) {
|
|
g.setBgColor(0, 0.25, 0.25);
|
|
g.clearRect(timeRect);
|
|
g.setFont(timeFont).setFontAlign(0,1);
|
|
g.drawString(timeStr, midX, timeRect.y2);
|
|
g.setBgColor(0, 0, 0);
|
|
};
|
|
|
|
const ms2str = function(ms) {
|
|
const h = Math.floor(ms / 3600000);
|
|
const m = Math.floor((ms / 60000) % 60);
|
|
const s = Math.floor((ms / 1000) % 60);
|
|
const tnth = Math.floor((ms % 1000) / 100);
|
|
const format = (timePart) => (timePart < 10) ? "0" + timePart : timePart;
|
|
|
|
return (h > 0 ? format(h) + ":" : "") + format(m) + ":" + format(s) + (h > 0 ? "" : "." + tnth);
|
|
};
|
|
|
|
const keepUpdated = function(shouldUpdate) {
|
|
if (updateIntID) clearInterval(updateIntID);
|
|
if (shouldUpdate) {
|
|
updateIntID = setInterval(()=> {
|
|
chronoTime.elapsed = getElapsed();
|
|
drawTime(ms2str(chronoTime.elapsed));
|
|
}, 100);
|
|
}
|
|
};
|
|
|
|
const start = function() {
|
|
chronoTime.mode = "running";
|
|
if (chronoTime.start === 0) chronoTime.start = Date.now();
|
|
saveState();
|
|
keepUpdated(true);
|
|
clearButtons();
|
|
drawButton(lapButton);
|
|
drawButton(pauseButton);
|
|
};
|
|
|
|
const pause = function() {
|
|
chronoTime.mode = "stopped";
|
|
const now = Date.now();
|
|
chronoTime.elapsed = now - chronoTime.start;
|
|
saveState();
|
|
keepUpdated(false);
|
|
drawTime(ms2str(chronoTime.elapsed));
|
|
clearButtons();
|
|
drawButton(resetButton);
|
|
drawButton(smallStartButton);
|
|
};
|
|
|
|
const getElapsed = function() {
|
|
return Date.now() - chronoTime.start;
|
|
}
|
|
|
|
const restart = function() {
|
|
chronoTime.mode = "running";
|
|
chronoTime.start = Date.now() - chronoTime.elapsed;
|
|
saveState();
|
|
keepUpdated(true);
|
|
clearButtons();
|
|
drawButton(lapButton);
|
|
drawButton(pauseButton);
|
|
}
|
|
|
|
const reset = function() {
|
|
chronoTime.start = 0;
|
|
chronoTime.elapsed = 0;
|
|
chronoTime.laps = [];
|
|
chronoTime.mode = undefined;
|
|
saveState();
|
|
g.clearRect(lapsRect);
|
|
drawTime(ms2str(chronoTime.elapsed));
|
|
clearButtons();
|
|
drawButton(startButton);
|
|
};
|
|
|
|
const saveState = function() {
|
|
require("Storage").writeJSON(dataFile, chronoTime);
|
|
};
|
|
|
|
const lapScreen = {
|
|
fh: g.setFont(lapsFont).getFontHeight(),
|
|
numX: midX - (timeStrW / 2) + 5,
|
|
strX: midX + (timeStrW / 2) - 5,
|
|
}
|
|
lapScreen.y0 = lapsRect.y2 - (chronoTime.laps.length * lapScreen.fh);
|
|
|
|
const addLap = function() {
|
|
chronoTime.laps.push(chronoTime.elapsed);
|
|
lapScreen.y0 = lapsRect.y2 - (chronoTime.laps.length * lapScreen.fh);
|
|
saveState();
|
|
};
|
|
|
|
const drawLaps = function() {
|
|
g.setFont(lapsFont);
|
|
g.clearRect(lapsRect);
|
|
g.setClipRect(lapsRect.x, lapsRect.y, lapsRect.x2, lapsRect.y2);
|
|
let y = lapScreen.y0;
|
|
let lapNum = 1;
|
|
for (let lap of chronoTime.laps) {
|
|
if (y + lapScreen.fh > lapsRect.y) {
|
|
g.setColor(0.5, 0.5, 0.5).setFontAlign(-1, -1).drawString(lapNum, lapScreen.numX, y);
|
|
g.setColor(-1).setFontAlign(1, -1).drawString(ms2str(lap), lapScreen.strX, y);
|
|
}
|
|
y += lapScreen.fh;
|
|
lapNum++;
|
|
}
|
|
g.setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2);
|
|
};
|
|
|
|
const dragHandler = function(d) {
|
|
const minY = lapsRect.y2 - (chronoTime.laps.length * lapScreen.fh);
|
|
const maxY = minY > lapsRect.y ? lapsRect.y2 - (chronoTime.laps.length * lapScreen.fh) : lapsRect.y;
|
|
if (d.dy && d.b) {
|
|
lapScreen.y0 += d.dy;
|
|
if (lapScreen.y0 < minY - 20) { // overscroll
|
|
lapScreen.y0 = minY - 20;
|
|
} else if (lapScreen.y0 > maxY + 20) {
|
|
lapScreen.y0 = maxY + 20;
|
|
}
|
|
} else if (!d.b) {
|
|
if (lapScreen.y0 < minY) {
|
|
lapScreen.y0 = minY;
|
|
} else if (lapScreen.y0 > maxY) {
|
|
lapScreen.y0 = maxY;
|
|
}
|
|
}
|
|
drawLaps(d.dy);
|
|
};
|
|
|
|
const buttonHandler = function(_n, e) {
|
|
if (e.y < Bangle.appRect.y2 - buttonH) {
|
|
return;
|
|
} else if (e.x < midX) { // button 1
|
|
switch (chronoTime.mode) {
|
|
case undefined:
|
|
start();
|
|
break;
|
|
case "running":
|
|
addLap();
|
|
drawLaps();
|
|
break;
|
|
case "stopped":
|
|
reset();
|
|
chronoTime.mode = undefined;
|
|
break;
|
|
}
|
|
|
|
} else if (e.x > midX) { // button 2
|
|
switch (chronoTime.mode) {
|
|
case undefined:
|
|
start();
|
|
break;
|
|
case "running":
|
|
pause();
|
|
break;
|
|
case "stopped":
|
|
restart();
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
const main = function() {
|
|
|
|
g.clear();
|
|
if (chronoTime.mode == "running") {
|
|
chronoTime.elapsed = getElapsed();
|
|
start();
|
|
drawLaps();
|
|
} else if (chronoTime.mode == "stopped") {
|
|
pause();
|
|
drawLaps();
|
|
} else if (chronoTime.mode == undefined){
|
|
drawTime(ms2str(chronoTime.elapsed));
|
|
drawButton(startButton);
|
|
}
|
|
|
|
Bangle.setUI({mode: "custom",
|
|
touch: (_n, e) => buttonHandler(_n, e),
|
|
drag: (e) => dragHandler(e),
|
|
btn: (_n) => Bangle.showClock()
|
|
});
|
|
};
|
|
|
|
main();
|