1
0
Fork 0

Merge pull request #2507 from glemco/master

presentation_timer: merged save state and interpolating non-defined numeric slides
master
Gordon Williams 2023-01-18 10:44:22 +00:00 committed by GitHub
commit 2d82c4e178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 9 deletions

View File

@ -1,2 +1,3 @@
0.01: first release
0.02: added interface for configuration from app loader
0.03: merged save state and interpolating non-defined numeric slides

View File

@ -26,8 +26,12 @@ The only requirement is that timings are increasing,
so slides number don't have to be consecutive,
some can be skipped and they can even be short texts.
At the moment the app is just quick and dirty
but it should do its job.
In case the series of slide numbers/names is strictly increasing and doesn't
contain strings, but numbers are not consecutive integers, the app will
interpolate intermediate slides (i.e. the first slide in the csv is 5 at minute
5, the app will add slide 1 at minute 1, slide 2 at minute 2, etc.)
At the moment the app is just quick and dirty but it should do its job.
## Screenshots

View File

@ -1,7 +1,7 @@
{
"id": "presentation_timer",
"name": "Presentation Timer",
"version": "0.02",
"version": "0.03",
"description": "A touch based presentation timer for Bangle JS 2",
"icon": "presentation_timer.png",
"screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot4.png"}],
@ -13,5 +13,8 @@
{"name":"presentation_timer.app.js","url":"presentation_timer.app.js"},
{"name":"presentation_timer.img","url":"presentation_timer.icon.js","evaluate":true}
],
"data": [{ "name": "presentation_timer.csv" }]
"data": [
{"name":"presentation_timer.json"},
{ "name": "presentation_timer.csv" }
]
}

View File

@ -1,9 +1,21 @@
const CONFIGFILE = "presentation_timer.json";
const now = Date.now();
const config = Object.assign({
state: {
total: now,
start: now,
current: now,
running: false,
}
}, require("Storage").readJSON(CONFIGFILE,1) || {});
let w = g.getWidth();
let h = g.getHeight();
let tTotal = Date.now();
let tStart = tTotal;
let tCurrent = tTotal;
let running = false;
let tTotal = config.state.total;
let tStart = config.state.start;
let tCurrent = config.state.current;
let running = config.state.running;
let timeY = 2*h/5;
let displayInterval;
let redrawButtons = true;
@ -15,6 +27,14 @@ const pause_img = atob("GBiBAf////////////////wYP/wYP/wYP/wYP/wYP/wYP/wYP/wYP/wY
const play_img = atob("GBjBAP//AAAAAAAAAAAIAAAOAAAPgAAP4AAP+AAP/AAP/wAP/8AP//AP//gP//gP//AP/8AP/wAP/AAP+AAP4AAPgAAOAAAIAAAAAAAAAAA=");
const reset_img = atob("GBiBAf////////////AAD+AAB+f/5+f/5+f/5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+f/5+f/5+f/5+AAB/AAD////////////w==");
function saveState() {
config.state.total = tTotal;
config.state.start = tStart;
config.state.current = tCurrent;
config.state.running = running;
require("Storage").writeJSON(CONFIGFILE, config);
}
const margin = 0.5; //half a minute tolerance
//dummy default values
@ -29,6 +49,25 @@ function log_debug(o) {
//console.log(o);
}
function fillBlanks(slides) {
start = 1;
time = 0;
let arr = [];
for(let idx in slides) {
s = slides[idx];
if(s[1] != start) {
step = (s[0] - time) / (s[1] - start + 1);
for(let i=0; i<s[1]-start; ++i) {
arr.push([+(step*(i+1)+time).toFixed(2), start+i]);
}
}
arr.push([s[0],+s[1]]);
start = (+s[1]) + 1;
time = s[0];
}
return arr;
}
//first must be a number
function readSlides() {
let csv = require("Storage").read("presentation_timer.csv");
@ -36,6 +75,11 @@ function readSlides() {
let lines = csv.split("\n").filter(e=>e);
log_debug("Loading "+lines.length+" slides");
slides = lines.map(line=>{let s=line.split(";");return [+s[0],s[1]];});
//all numbers and always strictly increasing
if(slides.filter(s=>isNaN(+s[1])).length == 0 &&
slides.map((p,i,a)=>p[1]-(a[i-1]?a[i-1][1]:undefined)).filter(p=>p<=0).length == 0) {
slides = fillBlanks(slides);
}
}
@ -147,6 +191,7 @@ function stopStart() {
} else {
draw();
}
saveState();
}
function setButtonImages() {
@ -171,6 +216,7 @@ function lapReset() {
g.clearRect(0,24,w,h);
draw();
}
saveState();
}
// simple on screen button class
@ -268,5 +314,10 @@ g.fillRect(0,0,w,h);
Bangle.loadWidgets();
Bangle.drawWidgets();
readSlides();
draw();
setButtonImages();
if (running) {
startTimer();
} else {
draw();
}
setWatch(() => load(), BTN, { repeat: false, edge: "falling" });