Add chrono_orezeno
parent
18c7abc427
commit
a6d3a426c4
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mUy4cA///38WnOsn8FrNx/8NzN5js1IFkk23ZkgSOyXbsmQCJsCpdtyVACRsJlu2pJLPiVIAocQCRdJkA+DtARKJQQFCptsLhNJJQSDBgOt2wRJSoZxBgIFBCJKVCyQFBidbkmALIwRBAomWpOkVo0JCIkAggpB0kSCIsBCIoABrdtaI4RHgGt3TRGF4LaHq6tEZAkBBI0pNwyABkEEIQwvHNwMAyTwEDoZuGyCoCRg44EFgKEJBYRcFAYLJBNA4+IHAJpFKwQFHbYPaWYp5EAokS6Q5FQYoFEhZyFQYoFFhoxFJRT3CGIhKKPgxKLAAzOGeQISJBYrKBUYoLKagI4JdAw+GLhSDCHBESDow4BLhwaJF5QIB+AIFnKzFHAl4A4kHNwxxEF4iSBRhILCbwQFFAA0DyQmBAQdPTxMB5IREpPgCRKzCCIYQLI5wA/ABIA=="))
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
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();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,14 @@
|
|||
{ "id": "chrono_orezeno",
|
||||
"name": "Stopwatch",
|
||||
"shortName":"Stopwatch",
|
||||
"version":"1.0",
|
||||
"description": "Chronograph with lap timer. Saves state so it is able to run in the background",
|
||||
"icon": "icons8-stopwatch-50.png",
|
||||
"tags": "",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"chrono.app.js", "url":"chrono.app.js"},
|
||||
{"name":"chrono.img", "url":"app-icon.js", "evaluate":true}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue