Add chrono_orezeno

master
Bryan 2024-06-15 13:16:28 -06:00
parent 18c7abc427
commit a6d3a426c4
4 changed files with 235 additions and 0 deletions

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mUy4cA///38WnOsn8FrNx/8NzN5js1IFkk23ZkgSOyXbsmQCJsCpdtyVACRsJlu2pJLPiVIAocQCRdJkA+DtARKJQQFCptsLhNJJQSDBgOt2wRJSoZxBgIFBCJKVCyQFBidbkmALIwRBAomWpOkVo0JCIkAggpB0kSCIsBCIoABrdtaI4RHgGt3TRGF4LaHq6tEZAkBBI0pNwyABkEEIQwvHNwMAyTwEDoZuGyCoCRg44EFgKEJBYRcFAYLJBNA4+IHAJpFKwQFHbYPaWYp5EAokS6Q5FQYoFEhZyFQYoFFhoxFJRT3CGIhKKPgxKLAAzOGeQISJBYrKBUYoLKagI4JdAw+GLhSDCHBESDow4BLhwaJF5QIB+AIFnKzFHAl4A4kHNwxxEF4iSBRhILCbwQFFAA0DyQmBAQdPTxMB5IREpPgCRKzCCIYQLI5wA/ABIA=="))

View File

@ -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

View File

@ -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}
]
}