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.01: first release
0.02: added interface for configuration from app loader 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, so slides number don't have to be consecutive,
some can be skipped and they can even be short texts. some can be skipped and they can even be short texts.
At the moment the app is just quick and dirty In case the series of slide numbers/names is strictly increasing and doesn't
but it should do its job. 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 ## Screenshots

View File

@ -1,7 +1,7 @@
{ {
"id": "presentation_timer", "id": "presentation_timer",
"name": "Presentation Timer", "name": "Presentation Timer",
"version": "0.02", "version": "0.03",
"description": "A touch based presentation timer for Bangle JS 2", "description": "A touch based presentation timer for Bangle JS 2",
"icon": "presentation_timer.png", "icon": "presentation_timer.png",
"screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot4.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.app.js","url":"presentation_timer.app.js"},
{"name":"presentation_timer.img","url":"presentation_timer.icon.js","evaluate":true} {"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 w = g.getWidth();
let h = g.getHeight(); let h = g.getHeight();
let tTotal = Date.now(); let tTotal = config.state.total;
let tStart = tTotal; let tStart = config.state.start;
let tCurrent = tTotal; let tCurrent = config.state.current;
let running = false; let running = config.state.running;
let timeY = 2*h/5; let timeY = 2*h/5;
let displayInterval; let displayInterval;
let redrawButtons = true; 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 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=="); 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 const margin = 0.5; //half a minute tolerance
//dummy default values //dummy default values
@ -29,6 +49,25 @@ function log_debug(o) {
//console.log(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 //first must be a number
function readSlides() { function readSlides() {
let csv = require("Storage").read("presentation_timer.csv"); let csv = require("Storage").read("presentation_timer.csv");
@ -36,6 +75,11 @@ function readSlides() {
let lines = csv.split("\n").filter(e=>e); let lines = csv.split("\n").filter(e=>e);
log_debug("Loading "+lines.length+" slides"); log_debug("Loading "+lines.length+" slides");
slides = lines.map(line=>{let s=line.split(";");return [+s[0],s[1]];}); 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 { } else {
draw(); draw();
} }
saveState();
} }
function setButtonImages() { function setButtonImages() {
@ -171,6 +216,7 @@ function lapReset() {
g.clearRect(0,24,w,h); g.clearRect(0,24,w,h);
draw(); draw();
} }
saveState();
} }
// simple on screen button class // simple on screen button class
@ -268,5 +314,10 @@ g.fillRect(0,0,w,h);
Bangle.loadWidgets(); Bangle.loadWidgets();
Bangle.drawWidgets(); Bangle.drawWidgets();
readSlides(); readSlides();
draw(); setButtonImages();
if (running) {
startTimer();
} else {
draw();
}
setWatch(() => load(), BTN, { repeat: false, edge: "falling" }); setWatch(() => load(), BTN, { repeat: false, edge: "falling" });