From 077ee58eef1a37735a2a2e57a663c99f4be8009e Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 13:06:12 +0200 Subject: [PATCH 01/77] Updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b83632eaa..f1811806d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .htaccess node_modules package-lock.json +.DS_Store From ae738e9d99b9f54f20b230ea23a5e0ad043b7471 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 20 Apr 2020 15:57:26 +0200 Subject: [PATCH 02/77] chronowid 0.03 --- apps/chronowid/ChangeLog | 5 +- apps/chronowid/widget.js | 184 +++++++++++++++++++-------------------- 2 files changed, 95 insertions(+), 94 deletions(-) diff --git a/apps/chronowid/ChangeLog b/apps/chronowid/ChangeLog index 263145407..e173467a1 100644 --- a/apps/chronowid/ChangeLog +++ b/apps/chronowid/ChangeLog @@ -1,2 +1,3 @@ -0.01: New widget and app! -0.02: Setting to reset values, timer buzzes at 00:00 and not later (see readme) \ No newline at end of file +0.01: New widget and app! +0.02: Setting to reset values, timer buzzes at 00:00 and not later (see readme) +0.03: Display only minutes:seconds when less than 1 hour left \ No newline at end of file diff --git a/apps/chronowid/widget.js b/apps/chronowid/widget.js index 557104d92..0c9366b86 100644 --- a/apps/chronowid/widget.js +++ b/apps/chronowid/widget.js @@ -1,93 +1,93 @@ -(() => { - const storage = require('Storage'); - settingsChronowid = storage.readJSON("chronowid.json",1)||{}; //read settingsChronowid from file - var height = 23; - var width = 58; - var interval = 0; //used for the 1 second interval timer - var now = new Date(); - - var time = 0; - var diff = settingsChronowid.goal - now; - - //Convert ms to time - function getTime(t) { - var milliseconds = parseInt((t % 1000) / 100), - seconds = Math.floor((t / 1000) % 60), - minutes = Math.floor((t / (1000 * 60)) % 60), - hours = Math.floor((t / (1000 * 60 * 60)) % 24); - - hours = (hours < 10) ? "0" + hours : hours; - minutes = (minutes < 10) ? "0" + minutes : minutes; - seconds = (seconds < 10) ? "0" + seconds : seconds; - - return hours + ":" + minutes + ":" + seconds; - } - - function printDebug() { - print ("Nowtime: " + getTime(now)); - print ("Now: " + now); - print ("Goaltime: " + getTime(settingsChronowid.goal)); - print ("Goal: " + settingsChronowid.goal); - print("Difftime: " + getTime(diff)); - print("Diff: " + diff); - print ("Started: " + settingsChronowid.started); - print ("----"); - } - - //counts down, calculates and displays - function countDown() { - now = new Date(); - diff = settingsChronowid.goal - now; //calculate difference - WIDGETS["chronowid"].draw(); - //time is up - if (settingsChronowid.started && diff < 1000) { - Bangle.buzz(1500); - //write timer off to file - settingsChronowid.started = false; - storage.writeJSON('chronowid.json', settingsChronowid); - clearInterval(interval); //stop interval - } - //printDebug(); - } - - // draw your widget - function draw() { - if (!settingsChronowid.started) { - width = 0; - return; //do not draw anything if timer is not started - } - g.reset(); - if (diff >= 0) { - if (diff < 600000) { //less than 1 hour left - width = 58; - g.clearRect(this.x,this.y,this.x+width,this.y+height); - g.setFont("6x8", 2); - g.drawString(getTime(diff).substring(3), this.x+1, this.y+5); //remove hour part 00:00:00 -> 00:00 - } - if (diff >= 600000) { //one hour or more left - width = 48; - g.clearRect(this.x,this.y,this.x+width,this.y+height); - g.setFont("6x8", 1); - g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00 - } - } - // not needed anymoe, because we check if diff < 1000 now, so 00:00 is displayed. - // else { - // width = 58; - // g.clearRect(this.x,this.y,this.x+width,this.y+height); - // g.setFont("6x8", 2); - // g.drawString("END", this.x+15, this.y+5); - // } - } - - if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second - - // add the widget - WIDGETS["chronowid"]={area:"bl",width:width,draw:draw,reload:function() { - reload(); - Bangle.drawWidgets(); // relayout all widgets - }}; - - //printDebug(); - countDown(); +(() => { + const storage = require('Storage'); + settingsChronowid = storage.readJSON("chronowid.json",1)||{}; //read settingsChronowid from file + var height = 23; + var width = 58; + var interval = 0; //used for the 1 second interval timer + var now = new Date(); + + var time = 0; + var diff = settingsChronowid.goal - now; + + //Convert ms to time + function getTime(t) { + var milliseconds = parseInt((t % 1000) / 100), + seconds = Math.floor((t / 1000) % 60), + minutes = Math.floor((t / (1000 * 60)) % 60), + hours = Math.floor((t / (1000 * 60 * 60)) % 24); + + hours = (hours < 10) ? "0" + hours : hours; + minutes = (minutes < 10) ? "0" + minutes : minutes; + seconds = (seconds < 10) ? "0" + seconds : seconds; + + return hours + ":" + minutes + ":" + seconds; + } + + function printDebug() { + print ("Nowtime: " + getTime(now)); + print ("Now: " + now); + print ("Goaltime: " + getTime(settingsChronowid.goal)); + print ("Goal: " + settingsChronowid.goal); + print("Difftime: " + getTime(diff)); + print("Diff: " + diff); + print ("Started: " + settingsChronowid.started); + print ("----"); + } + + //counts down, calculates and displays + function countDown() { + now = new Date(); + diff = settingsChronowid.goal - now; //calculate difference + WIDGETS["chronowid"].draw(); + //time is up + if (settingsChronowid.started && diff < 1000) { + Bangle.buzz(1500); + //write timer off to file + settingsChronowid.started = false; + storage.writeJSON('chronowid.json', settingsChronowid); + clearInterval(interval); //stop interval + } + //printDebug(); + } + + // draw your widget + function draw() { + if (!settingsChronowid.started) { + width = 0; + return; //do not draw anything if timer is not started + } + g.reset(); + if (diff >= 0) { + if (diff < 3600000) { //less than 1 hour left + width = 58; + g.clearRect(this.x,this.y,this.x+width,this.y+height); + g.setFont("6x8", 2); + g.drawString(getTime(diff).substring(3), this.x+1, this.y+5); //remove hour part 00:00:00 -> 00:00 + } + if (diff >= 3600000) { //one hour or more left + width = 48; + g.clearRect(this.x,this.y,this.x+width,this.y+height); + g.setFont("6x8", 1); + g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00 + } + } + // not needed anymoe, because we check if diff < 1000 now, so 00:00 is displayed. + // else { + // width = 58; + // g.clearRect(this.x,this.y,this.x+width,this.y+height); + // g.setFont("6x8", 2); + // g.drawString("END", this.x+15, this.y+5); + // } + } + + if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second + + // add the widget + WIDGETS["chronowid"]={area:"bl",width:width,draw:draw,reload:function() { + reload(); + Bangle.drawWidgets(); // relayout all widgets + }}; + + //printDebug(); + countDown(); })(); \ No newline at end of file From af0ac4041cb772856b7c12ac6d3ada6f360a246e Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 20 Apr 2020 15:58:05 +0200 Subject: [PATCH 03/77] chronowid 0.03 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index d7bd6a7a1..274a3a8b2 100644 --- a/apps.json +++ b/apps.json @@ -1142,7 +1142,7 @@ "name": "Chrono Widget", "shortName":"Chrono Widget", "icon": "app.png", - "version":"0.02", + "version":"0.03", "description": "Chronometer (timer) which runs as widget.", "tags": "tools,widget", "readme": "README.md", From 74bd784b091ad97964a7923fa888816fd8770412 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Mon, 20 Apr 2020 15:00:06 +0100 Subject: [PATCH 04/77] Initial commit of BuffGym 5x5 training program --- apps.json | 14 ++ apps/buffgym/.eslintrc.json | 33 ++++ apps/buffgym/buffgym-exercise.js | 187 +++++++++++++++++++ apps/buffgym/buffgym-icon.js | 1 + apps/buffgym/buffgym-program.js | 68 +++++++ apps/buffgym/buffgym-set.js | 46 +++++ apps/buffgym/buffgym.app.js | 311 +++++++++++++++++++++++++++++++ apps/buffgym/buffgym.png | Bin 0 -> 1800 bytes 8 files changed, 660 insertions(+) create mode 100644 apps/buffgym/.eslintrc.json create mode 100644 apps/buffgym/buffgym-exercise.js create mode 100644 apps/buffgym/buffgym-icon.js create mode 100644 apps/buffgym/buffgym-program.js create mode 100644 apps/buffgym/buffgym-set.js create mode 100755 apps/buffgym/buffgym.app.js create mode 100644 apps/buffgym/buffgym.png diff --git a/apps.json b/apps.json index 60b47dbd8..e993f0e18 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,19 @@ "evaluate": true } ] + }, + { + "id": "buffgym", + "name": "BuffGym", + "icon": "buffgym.png", + "version":"0.01", + "description": "BuffGym is the famous 5x5 workout program for the BangleJS", + "tags": "tool,outdoors", + "type": "app", + "storage": [ + {"name":"buffgym"}, + {"name":"buffgym.app.js"}, + {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} + ] } ] diff --git a/apps/buffgym/.eslintrc.json b/apps/buffgym/.eslintrc.json new file mode 100644 index 000000000..c91a72544 --- /dev/null +++ b/apps/buffgym/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es6": true + }, + "extends": "eslint:recommended", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "windows" + ], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "always" + ] + } +} \ No newline at end of file diff --git a/apps/buffgym/buffgym-exercise.js b/apps/buffgym/buffgym-exercise.js new file mode 100644 index 000000000..b7a1e3e15 --- /dev/null +++ b/apps/buffgym/buffgym-exercise.js @@ -0,0 +1,187 @@ +const STARTED = 1; +const RESTING = 2; +const COMPLETED = 3; +const ONE_SECOND = 1000; +const INCREMENT = "increment"; +const DECREMENT = "decrement"; + +class Exercise { + constructor(params /*{title, weight, unit, restPeriod}*/) { + const DEFAULTS = { + title: "Unknown", + weight: 0, + unit: "Kg", + restPeriod: 90, + weightIncrement: 2.5, + }; + const p = Object.assign({}, DEFAULTS, params); + + this._title = p.title; + this._weight = p.weight; + this._unit = p.unit; + this._originalRestPeriod = p.restPeriod; // Used when reseting _restPeriod + this._restPeriod = p.restPeriod; + this._weightIncrement = p.weightIncrement; + this._started = new Date(); + this._completed = false; + this._sets = []; + this._restTimeout = null; + this._restInterval = null; + this._state = null; + } + + get title() { + return this._title; + } + + get humanTitle() { + return `${this._title} ${this._weight}${this._unit}`; + } + + get subTitle() { + const totalSets = this._sets.length; + const uncompletedSets = this._sets.filter((set) => !set.isCompleted()).length; + const currentSet = (totalSets - uncompletedSets) + 1; + return `Set ${currentSet} of ${totalSets}`; + } + + get restPeriod() { + return this._restPeriod; + } + + decRestPeriod() { + this._restPeriod--; + } + + get weight() { + return this._weight; + } + + get unit() { + return this._unit; + } + + get started() { + return this._started; + } + + addSet(set) { + this._sets.push(set); + } + + addSets(sets) { + sets.forEach(set => this.addSet(set)); + } + + get currentSet() { + return this._sets.filter(set => !set.isCompleted())[0]; + } + + isLastSet() { + return this._sets.filter(set => !set.isCompleted()).length === 1; + } + + isCompleted() { + return !!this._completed; + } + + canSetCompleted() { + return this._sets.filter(set => set.isCompleted()).length === this._sets.length; + } + + setCompleted() { + if (!this.canSetCompleted()) throw "All sets must be completed"; + if (this.canProgress) this._weight += this._weightIncrement; + this._completed = true; + } + + get canProgress() { + let completedRepsTotalSum = 0; + let targetRepsTotalSum = 0; + + const completedRepsTotal = this._sets.forEach(set => completedRepsTotalSum += set.reps); + const targetRepsTotal = this._sets.forEach(set => targetRepsTotalSum += set.maxReps); + + return (targetRepsTotalSum - completedRepsTotalSum) === 0; + } + + startRestTimer(program) { + this._restTimeout = setTimeout(() => { + this.next(); + }, ONE_SECOND * this._restPeriod); + + this._restInterval = setInterval(() => { + program.emit("redraw"); + }, ONE_SECOND); + } + + resetRestTimer() { + clearTimeout(this._restTimeout); + clearInterval(this._restInterval); + this._restTimeout = null; + this._restInterval = null; + this._restPeriod = this._originalRestPeriod; + } + + isRestTimerRunning() { + return this._restTimeout != null; + } + + setupStartedButtons(program) { + clearWatch(); + + setWatch(() => { + this.currentSet.incReps(); + program.emit("redraw"); + }, BTN1, {repeat: true}); + + setWatch(program.next.bind(program), BTN2, {repeat: false}); + + setWatch(() => { + this.currentSet.decReps(); + program.emit("redraw"); + }, BTN3, {repeat: true}); + } + + setupRestingButtons(program) { + clearWatch(); + setWatch(program.next.bind(program), BTN2, {repeat: true}); + } + + next(program) { + global.poo = this; + switch(this._state) { + case null: + console.log("XXX 1 moving null -> STARTED"); + this._state = STARTED; + this.setupStartedButtons(program); + break; + case STARTED: + console.log("XXX 2 moving STARTED -> RESTING"); + this._state = RESTING; + this.startRestTimer(program); + this.setupRestingButtons(program); + break; + case RESTING: + this.resetRestTimer(); + this.currentSet.setCompleted(); + + if (this.canSetCompleted()) { + console.log("XXX 3b moving RESTING -> COMPLETED"); + this._state = COMPLETED; + this.setCompleted(); + } else { + console.log("XXX 3a moving RESTING -> null"); + this._state = null; + } + // As we are changing state and require it to be reprocessed + // invoke the next step of program + program.next(program); + break; + default: + throw "Exercise: Attempting to move to an unknown state"; + } + + program.emit("redraw"); + } +} \ No newline at end of file diff --git a/apps/buffgym/buffgym-icon.js b/apps/buffgym/buffgym-icon.js new file mode 100644 index 000000000..949b0e45b --- /dev/null +++ b/apps/buffgym/buffgym-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AFEEolAC6lN7vdDCcECwPd6guVGCYuDC4cCBQMikQXQJAMjkECmcyIx4XDmUjmYvLC4XUDARHBIoIWLgATCGQdA7tEonQC5ouDDYg0BOxgSEAggwKRwgUCC6ZIDSwoXNogWDDgNCAgIWIkUEoUk6kiCgMkokipsiBIQXIki2CAgNCAoYADC5Eic4Mic4ICCAIIJCC5MzAAcykYGEAAIXOABAXTmUzGoIXVAIIXLB4SICDIovjO76PZbYR3PDI4XiI6530MIh3SC6R33C/oAOC48CCxsgC44A/ADY=")) diff --git a/apps/buffgym/buffgym-program.js b/apps/buffgym/buffgym-program.js new file mode 100644 index 000000000..22f39f10b --- /dev/null +++ b/apps/buffgym/buffgym-program.js @@ -0,0 +1,68 @@ +class Program { + constructor(params) { + const DEFAULTS = { + title: "Unknown", + trainDay: "", // Day of week + }; + const p = Object.assign({}, DEFAULTS, params); + + this._title = p.title; + this._trainDay = p.trainDay; + this._exercises = []; + + this.on("redraw", redraw.bind(null, this)); + } + + get title() { + return `${this._title} - ${this._trainDay}`; + } + + addExercise(exercise) { + this._exercises.push(exercise); + } + + addExercises(exercises) { + exercises.forEach(exercise => this.addExercise(exercise)); + } + + currentExercise() { + return ( + this._exercises + .filter(exercise => !exercise.isCompleted())[0] + ); + } + + canComplete() { + return ( + this._exercises + .filter(exercise => exercise.isCompleted()) + .length === this._exercises.length + ); + } + + setCompleted() { + if (!this.canComplete()) throw "All exercises must be completed"; + this._completed = true; + } + + isCompleted() { + return !!this._completed; + } + + // State machine + next() { + console.log("XXX Program.next"); + const exercise = this.currentExercise(); + + // All exercises are completed so mark the + // Program as comleted + if (this.canComplete()) { + this.setCompleted(); + this.emit("redraw"); + + return; + } + + exercise.next(this); + } +} \ No newline at end of file diff --git a/apps/buffgym/buffgym-set.js b/apps/buffgym/buffgym-set.js new file mode 100644 index 000000000..d7d610a78 --- /dev/null +++ b/apps/buffgym/buffgym-set.js @@ -0,0 +1,46 @@ +class Set { + constructor(maxReps) { + this._minReps = 0; + this._maxReps = maxReps; + this._reps = 0; + this._completed = false; + } + + get title() { + return this._title; + } + + get weight() { + return this._weight; + } + + isCompleted() { + return !!this._completed; + } + + setCompleted() { + this._completed = true; + } + + get reps() { + return this._reps; + } + + get maxReps() { + return this._maxReps; + } + + incReps() { + if (this._completed) return; + if (this._reps >= this._maxReps) return; + + this._reps++; + } + + decReps() { + if (this._completed) return; + if (this._reps <= this._minReps) return; + + this._reps--; + } +} \ No newline at end of file diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js new file mode 100755 index 000000000..e74b7062a --- /dev/null +++ b/apps/buffgym/buffgym.app.js @@ -0,0 +1,311 @@ +/* global g, setWatch, clearWatch, reset, BTN1, BTN2, BTN3 */ + +(() => { + const W = g.getWidth(); + const H = g.getHeight(); + const RED = "#d32e29"; + const PINK = "#f05a56"; + const WHITE = "#ffffff"; + + const Set = require("set.js"); + const Exercise = require("exercise.js"); + const Program = require("program.js"); + + function centerStringX(str) { + return (W - g.stringWidth(str)) / 2; + } + + function iconIncrement() { + const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglHA4IpJBYwTHA4RMJCY5oDJo4THKIQKET5IMGCaY7TMaKLTWajbTFJIlICgoVBFYXJYQYSGCggAGCRAVIBgw")); + return img; + } + + function iconDecrement() { + const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCRYABCYQmOFAhNMKIw6FTw4LHCaY7TMaKLTWajbTFJglFCgoVBFYXJYQYSGCggAGCRAVIBgw=")); + return img; + } + + function iconOk() { + const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCJQxCCYQmMIwZoDJpQMCKIg6KBYwTGFQgeHHYouCCRI7EMYTXFRhILEK5SfFRgYSIborbSbpglFCgoVBFYXJYQYSGCggAGCRAVIBgwA==")); + return img; + } + + function drawMenu(params) { + const DEFAULT_PARAMS = { + showBTN1: false, + showBTN2: false, + showBTN3: false, + }; + const p = Object.assign({}, DEFAULT_PARAMS, params); + if (p.showBTN1) g.drawImage(iconIncrement(), W - 30, 10); + if (p.showBTN2) g.drawImage(iconOk(), W - 30, 110); + if (p.showBTN3) g.drawImage(iconDecrement(), W - 30, 210); + } + + function clearScreen() { + g.setColor(RED); + g.fillRect(0,0,W,H); + } + + function drawTitle(exercise) { + const title = exercise.humanTitle; + + g.setFont("Vector",20); + g.setColor(WHITE); + g.drawString(title, centerStringX(title), 5); + } + + function drawReps(exercise) { + const set = exercise.currentSet; + if (set.isCompleted()) return; + + g.setColor(PINK); + g.fillCircle(W / 2, H / 2, 50); + g.setColor(WHITE); + g.setFont("Vector", 40); + g.drawString(set.reps, centerStringX(set.reps), (H - 45) / 2); + g.setFont("Vector", 15); + const note = `of ${set.maxReps}`; + g.drawString(note, centerStringX(note), (H / 2) + 25); + } + + function drawSets(exercise) { + const sets = exercise.subTitle; + + g.setColor(WHITE); + g.setFont("Vector", 15); + g.drawString(sets, centerStringX(sets), H - 25); + } + + function drawSetProgress(exercise) { + drawTitle(exercise); + drawReps(exercise); + drawSets(exercise); + drawMenu({showBTN1: true, showBTN2: true, showBTN3: true}); + } + + function drawStartNextExercise() { + const title = "Good work"; + const msg = "No need to rest\nmove straight on\nto the next exercise"; + + g.setColor(WHITE); + g.setFont("Vector", 35); + g.drawString(title, centerStringX(title), 10); + g.setFont("Vector", 15); + g.drawString(msg, 30, 150); + drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); + } + + function drawProgramCompleted() { + const title1 = "You did"; + const title2 = "GREAT!"; + const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest."; + + clearWatch(); + setWatch(reset, BTN2, {repeat: false}); + + g.setColor(WHITE); + g.setFont("Vector", 35); + g.drawString(title1, centerStringX(title1), 10); + g.setFont("Vector", 40); + g.drawString(title2, centerStringX(title2), 50); + g.setFont("Vector", 15); + g.drawString(msg, 30, 150); + drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); + } + + /* + function drawExerciseCompleted(program) { + const exercise = program.currentExercise(); + const title = exercise.canProgress? + "WELL DONE!" : + "NOT BAD!"; + const msg = exercise.canProgress? + `You weight is automatically increased\nfor ${exercise.title} to ${exercise.weight}${exercise.unit}` : + "It looks like you struggled\non a few sets, your weight will\nstay the same"; + const action = "Move straight on to the next exercise"; + + clearScreen(); + g.setColor(WHITE); + g.setFont("Vector", 20); + g.drawString(title, centerStringX(title), 10); + g.setFont("Vector", 10); + g.drawString(msg, centerStringX(msg), 180); + g.drawString(action, centerStringX(action), 210); + drawMenu({showBTN2: true}); + + clearWatch(); + setWatch(() => { + init(program); + }, BTN2, {repeat: false}); + } + */ + + function drawRestTimer(program) { + const exercise = program.currentExercise(); + const motivation = "Take a breather.."; + clearScreen(); + drawMenu({showBTN2: true}); + + g.setColor(PINK); + g.fillCircle(W / 2, H / 2, 50); + g.setColor(WHITE); + g.setFont("Vector", 15); + g.drawString(motivation, centerStringX(motivation), 25); + g.setFont("Vector", 40); + g.drawString(exercise.restPeriod, centerStringX(exercise.restPeriod), (H - 45) / 2); + exercise.decRestPeriod(); + + if (exercise.restPeriod <= 0) { + exercise.resetRestTimer(); + redraw(program); + } + } + + function redraw(program) { + const exercise = program.currentExercise(); + + clearScreen(); + + if (program.isCompleted()) { + drawProgramCompleted(program); + return; + } + + if (exercise.isRestTimerRunning()) { + if (exercise.isLastSet()) { + drawStartNextExercise(program); + } else { + drawRestTimer(program); + } + + return; + } + + drawSetProgress(exercise); + } + + function init(program) { + clearWatch(); + program.next(); + } + + // Setup training program. This should come from file + + // Squats + function buildPrograms() { + const squats = new Exercise({ + title: "Squats", + weight: 40, + unit: "Kg", + }); + squats.addSets([ + new Set(5), + new Set(5), + new Set(5), + new Set(5), + new Set(5), + ]); + + const bench = new Exercise({ + title: "Bench press", + weight: 20, + unit: "Kg", + }); + bench.addSets([ + new Set(5), + new Set(5), + new Set(5), + new Set(5), + new Set(5), + ]); + + const row = new Exercise({ + title: "Row", + weight: 20, + unit: "Kg", + }); + row.addSets([ + new Set(5), + new Set(5), + new Set(5), + new Set(5), + new Set(5), + ]); + + const ohPress = new Exercise({ + title: "Overhead press", + weight: 20, + unit: "Kg", + }); + ohPress.addSets([ + new Set(5), + new Set(5), + new Set(5), + new Set(5), + new Set(5), + ]); + + const deadlift = new Exercise({ + title: "Deadlift", + weight: 20, + unit: "Kg", + }); + deadlift.addSets([ + new Set(5), + ]); + + const pullups = new Exercise({ + title: "Pullups", + weight: 0, + unit: "Kg", + }); + pullups.addSets([ + new Set(10), + new Set(10), + new Set(10), + ]); + + const triceps = new Exercise({ + title: "Tricep extension", + weight: 20, + unit: "Kg", + }); + triceps.addSets([ + new Set(10), + new Set(10), + new Set(10), + ]); + + const programA = new Program({ + title: "Program A", + }); + programA.addExercises([ + squats, + ohPress, + deadlift, + pullups, + ]); + + const programB = new Program({ + title: "Program B", + }); + programB.addExercises([ + squats, + bench, + row, + triceps, + ]); + + const programs = [ + programA, + programB, + ]; + return programs; + } + + // For this spike, just run the first program, what will + // really happen is the user picks a program to do from + // some menu on a start page. + init(buildPrograms()[0]); +})(); \ No newline at end of file diff --git a/apps/buffgym/buffgym.png b/apps/buffgym/buffgym.png new file mode 100644 index 0000000000000000000000000000000000000000..93a29a4a686f172e5e6dbd2ecb2a1d3edf4751c0 GIT binary patch literal 1800 zcmV+j2lx1iP)tlxqC9)f@Omu&Na^VuQ3o*OkLX&0x0b91a zC7LC3CR;|G&UwKyoC)@U)%oe$2-|YHkk(v4M!t35mBz$@a#wDU>?rxOl>4iDU0;K~&^NeJ~rZV1qG0 z2VEWRN{fW6B-AV=vyLG{LNQb2i6*D;)z1+>HV9oV)YY-AYv;CEAGyt1BxHeIB6`O1 zgNbCKvH5&(h}tjTY&oMqX-z=6c>c(BKect-eBUPt!g0uGg&+h40X>Fzw5_e#pVR#$ zXoP~+BFSrtk0nGN171%U%*9ZeH|HLjvY%#M?bNRbI9pq_zjAQwp^ph~HbFcpN~ZRz z(p@Mo-ho770lfp=4bOss8*F%I4msLmKr#xaD)J*)`yvYx`ky+nJwKX`iBeY-qKGqH z?QS=3P!M$53s7Hu5JniTm@SU>rp6YK0dui1iN|DU+@DO!eyGs{ttdh(`FAE0vla{o z?WidZt%?gW#AR7;<X-pbXX@H zNxpMYdq4RMO4a}WV;wc05JSkxHD~SsCa-dTj zNTxVqQheR_7dUJ%8VslVKYYW7jWB?j;7(;1x|h0^D=>+_|8G8A);PQcVdy~=1vqUM z=Bmmm)pMW?ZosIy0KK;IbR&uXN!$f_n-$fCGwJquLBgH9YRnj{JTt}EHBxNEeXlt^ z=25u`mrr_dyKd3t92OJZd{9ZwAii{~WsvTQjEnfS8xO2y_@!_U?;}HwP2R(Ijz)}m zit&g9Oe?63KH;Lj-FATAd+p`e9q7aT9cJ8VbS}; zQ^kGnzzKFl@TSGDoSS-YQ$q_XStXt~30!=tPYtT;z`;H5V0>y6M#+fsq8;frcBVm9 z*_*JM9oV^KK>zTcC~y_yt(v2JXX>jDabwn+OJjC>_p^QzY!*8o^Zl)_Rq0Y~0Idq0 zS2Ejbz57Z043707FgeP1%EK<&HQJ?2qjG*1bTS%v z%ubCHDDjk|*z-F39AIq&YmVQ|gsn7eCKBY&B;IDWBhQ|XP-F^P(QUxw%mhX!9y3?4 za|0-g(DPbUZ?Ai9XPitl89;gYdW9(B>6do0 z&{d=<|EJJx0R4iRi$%B)8xs*{tC-D)*IL!li9sItRi$t8xdUT=@j7sD@4L`~ZUg#< z@9|7Teoy(EeEDwwZ_kbU;PA;c-%(!VWd_vn&m{hDmP)mv+W`74ORG=SmA{Aypl2;4 z5^=uzMCz^;-3HXM(oa{4%%IK%Ex`EHFzC+|RLpt@yWwJmOe>of#Mu@=51VEH#S6s{ z9o#%D1JN_>#7hfe`U6y8YJ?wyDGkFo zERDt!OF!~i5Yltbc`JfdVhJF1ywFnv_&cBz%HNa*=^#c>zCWO1`&}!lb?WRyb7@D_ zoMJQ4ZGbZ)W6%m}S;fo+s9pL&qm@ky;%p0`2i^anc~wxo1C;V!MN}J*?VR%}kkbG~ qkv|qi@hCO{S(a~Li!HWTm;V6Sm{)4DoNDL*0000 Date: Mon, 20 Apr 2020 15:27:21 +0100 Subject: [PATCH 05/77] Update apps.json --- apps.json | 4 + apps/buffgym/buffgym-programs.json | 101 ++++++++++++++++++++++++ apps/buffgym/buffgym.app.js | 121 +++++------------------------ 3 files changed, 125 insertions(+), 101 deletions(-) create mode 100644 apps/buffgym/buffgym-programs.json diff --git a/apps.json b/apps.json index e993f0e18..bff5fe66b 100644 --- a/apps.json +++ b/apps.json @@ -1305,6 +1305,10 @@ "storage": [ {"name":"buffgym"}, {"name":"buffgym.app.js"}, + {"name":"buffgym-set.js","url":"buffgym-set.js"}, + {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, + {"name":"buffgym-program.js","url":"buffgym-program.js"}, + {"name":"buffgym-programs.json","url":"buffgym-program.json"}, {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} ] } diff --git a/apps/buffgym/buffgym-programs.json b/apps/buffgym/buffgym-programs.json new file mode 100644 index 000000000..bf5aa0e0d --- /dev/null +++ b/apps/buffgym/buffgym-programs.json @@ -0,0 +1,101 @@ +[ + { + title: "Program A", + exercises: [ + { + title: "Squats", + weight: 40, + unit: "Kg", + sets: [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + title: "Overhead press", + weight: 20, + unit: "Kg", + sets: [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + title: "Deadlift", + weight: 20, + unit: "Kg", + sets: [ + 5 + ] + }, + { + title: "Pullups", + weight: 0, + unit: "Kg", + sets: [ + 10, + 10, + 10 + ] + } + ] + }, + { + title: "Program B", + exercises: [ + { + title: "Squats", + weight: 40, + unit: "Kg", + sets: [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + title: "Bench press", + weight: 20, + unit: "Kg", + sets: [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + title: "Row", + weight: 20, + unit:"Kg", + sets: [ + 5, + 5, + 5, + 5, + 5 + ] + + }, + { + title: "Tricep extension", + weight: 20, + unit: "Kg", + sets: [ + 10, + 10, + 10 + ] + } + ] + } +] \ No newline at end of file diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index e74b7062a..d3a4e6834 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -194,113 +194,32 @@ // Squats function buildPrograms() { - const squats = new Exercise({ - title: "Squats", - weight: 40, - unit: "Kg", - }); - squats.addSets([ - new Set(5), - new Set(5), - new Set(5), - new Set(5), - new Set(5), - ]); + const programsJSON = require("Storage").readJSON("buffgym-programs.json", 1); - const bench = new Exercise({ - title: "Bench press", - weight: 20, - unit: "Kg", - }); - bench.addSets([ - new Set(5), - new Set(5), - new Set(5), - new Set(5), - new Set(5), - ]); + if (!programsJSON) throw "No programs JSON found"; - const row = new Exercise({ - title: "Row", - weight: 20, - unit: "Kg", - }); - row.addSets([ - new Set(5), - new Set(5), - new Set(5), - new Set(5), - new Set(5), - ]); + const programs = []; - const ohPress = new Exercise({ - title: "Overhead press", - weight: 20, - unit: "Kg", - }); - ohPress.addSets([ - new Set(5), - new Set(5), - new Set(5), - new Set(5), - new Set(5), - ]); + programsJSON.forEach(programJSON => { + const program = new Program({ + title: programJSON.title, + }); + const exercises = programJSON.exercises.map(exerciseJSON => { + const exercise = new Exercise({ + title: exerciseJSON.title, + weight: exerciseJSON.weight, + unit: exerciseJSON.unit, + }); + exerciseJSON.sets.forEach(setJSON => { + exercise.addSet(new Set(setJSON)); + }); - const deadlift = new Exercise({ - title: "Deadlift", - weight: 20, - unit: "Kg", + return exercise; + }); + program.addExercises(exercises); + programs.push(program); }); - deadlift.addSets([ - new Set(5), - ]); - const pullups = new Exercise({ - title: "Pullups", - weight: 0, - unit: "Kg", - }); - pullups.addSets([ - new Set(10), - new Set(10), - new Set(10), - ]); - - const triceps = new Exercise({ - title: "Tricep extension", - weight: 20, - unit: "Kg", - }); - triceps.addSets([ - new Set(10), - new Set(10), - new Set(10), - ]); - - const programA = new Program({ - title: "Program A", - }); - programA.addExercises([ - squats, - ohPress, - deadlift, - pullups, - ]); - - const programB = new Program({ - title: "Program B", - }); - programB.addExercises([ - squats, - bench, - row, - triceps, - ]); - - const programs = [ - programA, - programB, - ]; return programs; } From 8238bb766a6f4fc80c14e2c781f5dd1ff25da22a Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 16:40:26 +0200 Subject: [PATCH 06/77] Create app.js --- apps/hamloc/app.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/hamloc/app.js diff --git a/apps/hamloc/app.js b/apps/hamloc/app.js new file mode 100644 index 000000000..ac608a5f4 --- /dev/null +++ b/apps/hamloc/app.js @@ -0,0 +1,21 @@ +latLonToGridSquare=function(o,a){var t,e,n,s,l,i,r,h,M,f=-100,g=0,u="ABCDEFGHIJKLMNOPQRSTUVWX",d=u.toLowerCase();function N(o){return"number"==typeof o?o:"string"==typeof o?parseFloat(o):"function"==typeof o?parseFloat(o()):void E.showMessage("can't convert \ninput: "+o)}return"object"==typeof o?2===o.length?(f=N(o[0]),g=N(o[1])):"lat"in o&&"lon"in o?(f=N(o.lat),g=N(o.lon)):"latitude"in o&&"longitude"in o?(f=N(o.latitude),g=N(o.longitude)):E.showMessage("can't convert \nobject "+o):(f=N(o),g=N(a)),isNaN(f)&&E.showMessage("lat is NaN"),isNaN(g)&&E.showMessage("lon is NaN"),90===Math.abs(f)&&E.showMessage("grid invalid \nat N/S"),90 Date: Mon, 20 Apr 2020 16:43:00 +0200 Subject: [PATCH 07/77] Add files via upload --- apps/hamloc/app.png | Bin 0 -> 3697 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/hamloc/app.png diff --git a/apps/hamloc/app.png b/apps/hamloc/app.png new file mode 100644 index 0000000000000000000000000000000000000000..54dac5882e4aa4b14cb1e20d04471c4a5efc027b GIT binary patch literal 3697 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 Date: Mon, 20 Apr 2020 16:44:35 +0200 Subject: [PATCH 08/77] Create app-icon.js --- apps/hamloc/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/hamloc/app-icon.js diff --git a/apps/hamloc/app-icon.js b/apps/hamloc/app-icon.js new file mode 100644 index 000000000..175b492c7 --- /dev/null +++ b/apps/hamloc/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4ACwVeAAM6nQECJsYqDFYItCAgQ0DFrxWE2ZhBxOJA4ICBGwhbbxGtAYOz2etnWt2YwBnQCBGgWtxBjXJQQpBLgQABEQIDBMAgwE2YYBwRcUxOtDwgABGgYvGTQQLCMSRNGEQaODF4SQDHgYwUFIlfAgY2DYQQGDsouCGAQSEGBouEKANl1onEwQvGA4QACA4IwQaIISFFwIwDXwI2ExL2BB4YABJgwwKnQAkRpzYDAAbuBA4oABe4aaDD44uGxCNEQwStEdwgAFR4IHGF4iRBxJeLBwIdCcwgvJxLwFFIRgLBo4dBcwj2CF45xIKIxeLAww4FAAuINIYbKMAteso8FAwovPCQllQQtlF4gLFUYwvDsq/HfIShEDhCQDIgIAFnQHGBBITRnWIXwdfAAYGFSYblBNI5KBsobEDo4GCdxyFDr2tR4+tDQrwNF5YlEnQvJaZIvKr4RIEoovaSAIvyXArbBF6OJR6mCXAgvBDwIlFd5IfBd6tfSQQRGCgeIBJE6DIIAFDoIGGF4OCAgIAEnQHGBBITRnWIF4P+V4ZMCWxBoBRw5PBNI7IGnQuCSAIfE1oSB1oADF4WIXxAvHsoIFH4IvEdIJWEDg4vICRTuJSAwABxAcJF5A5C1ovKRwhgCwSQGF6CpEXxBeGMA59JZIIvGA4hhBLw+JF4xRFSBBNDFIhHFe4VfLxhgCAEguIMAJSB1oABSA4HEB4RwBAgQXHss6LxKRDPQTxBsovIRIdexCOGRpwwIr5gFAwbuEAoheBFyQwFRIrwDLwZuBdwgTBC4IuRYYowGRAq+BAoeCAoRABFyIABD4IsCGAgpFGoguBd4eIFyRiEFoIwCEoKJDRwYqCCAJcUGJICBK4JgDKgOtOIQtce4s6AAI2EBAgteAAizBGgYECwQsiAD4")) From 9f5cbc6022ee275ed40e6942cb69388f4d6c6e07 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 16:49:49 +0200 Subject: [PATCH 09/77] Update apps.json --- apps.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps.json b/apps.json index b58fad5ce..e55190ec0 100644 --- a/apps.json +++ b/apps.json @@ -1400,5 +1400,17 @@ {"name":"rclock.app.js","url":"rclock.app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "hamloc", + "name": "QTH Locator / Maidenhead Locator System", + "shortName": "QTH Locator", + "icon": "app.png", + "version":"0.01", + "description": "Convert your current GPS location to the Maidenhead locator system used by HAM amateur radio operators", + "tags": "tool,outdoors,gps", + "storage": [ + {"name":"hamloc.app.js","url":"app.js"}, + {"name":"hamloc.img","url":"app-icon.js","evaluate":true} + ] } ] From 02af1e4b1518b35d09e541df63f4130924df29d2 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 16:55:59 +0200 Subject: [PATCH 10/77] Create ChangeLog --- apps/hamloc/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/hamloc/ChangeLog diff --git a/apps/hamloc/ChangeLog b/apps/hamloc/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/hamloc/ChangeLog @@ -0,0 +1 @@ +0.01: New App! From e513031a8770146f7fbe34c672d283d177e31f4a Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:11:51 +0200 Subject: [PATCH 11/77] Create README.md --- apps/hamloc/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 apps/hamloc/README.md diff --git a/apps/hamloc/README.md b/apps/hamloc/README.md new file mode 100644 index 000000000..493afa899 --- /dev/null +++ b/apps/hamloc/README.md @@ -0,0 +1,14 @@ +# QTH Locator + +Convert your current GPS location to the [Maidenhead](https://en.wikipedia.org/wiki/Maidenhead_Locator_System) locator system used by HAM amateur radio operators. + +## Description + +A Maidenhead locator compresses latitude and longitude into a short string of characters, which is similar in concept to the World Geographic Reference System or GEOREF. This position information is presented in a limited level of precision to limit the number of characters needed for its transmission using voice, Morse code, or any other operating mode.[4] + +The chosen coding uses alternating pairs of letters and digits, like so: + +* BL11bh + +support Paul Brewer KI6CQ HamGridSquare.js +support Chris Veness 2002-2012 LatLon library From 5f9ee09daf8b9baf63e19d067efddd589da20648 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:13:07 +0200 Subject: [PATCH 12/77] Update README.md --- apps/hamloc/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/hamloc/README.md b/apps/hamloc/README.md index 493afa899..273e1f54b 100644 --- a/apps/hamloc/README.md +++ b/apps/hamloc/README.md @@ -4,11 +4,12 @@ Convert your current GPS location to the [Maidenhead](https://en.wikipedia.org/w ## Description -A Maidenhead locator compresses latitude and longitude into a short string of characters, which is similar in concept to the World Geographic Reference System or GEOREF. This position information is presented in a limited level of precision to limit the number of characters needed for its transmission using voice, Morse code, or any other operating mode.[4] +A Maidenhead locator compresses latitude and longitude into a short string of characters, which is similar in concept to the World Geographic Reference System or GEOREF. This position information is presented in a limited level of precision to limit the number of characters needed for its transmission using voice, Morse code, or any other operating mode. The chosen coding uses alternating pairs of letters and digits, like so: * BL11bh -support Paul Brewer KI6CQ HamGridSquare.js -support Chris Veness 2002-2012 LatLon library + +* support Paul Brewer KI6CQ HamGridSquare.js +* support Chris Veness 2002-2012 LatLon library From a47ebfaf4841be23a45f4b64533e1c7e55769a95 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:14:16 +0200 Subject: [PATCH 13/77] Update README.md --- apps/hamloc/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/hamloc/README.md b/apps/hamloc/README.md index 273e1f54b..5710493bb 100644 --- a/apps/hamloc/README.md +++ b/apps/hamloc/README.md @@ -9,7 +9,6 @@ A Maidenhead locator compresses latitude and longitude into a short string of ch The chosen coding uses alternating pairs of letters and digits, like so: * BL11bh - - +## * support Paul Brewer KI6CQ HamGridSquare.js * support Chris Veness 2002-2012 LatLon library From 4b512af0e2012986ea1d5f3e2f916cb2f88e47b8 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:34:33 +0200 Subject: [PATCH 14/77] activepedom 0.03 --- apps/activepedom/ChangeLog | 3 +- apps/activepedom/README.md | 20 +++++- apps/activepedom/app.js | 133 +++++++++++++++++++++++++++++++++++++ apps/activepedom/widget.js | 51 +++++++++----- 4 files changed, 190 insertions(+), 17 deletions(-) create mode 100644 apps/activepedom/app.js diff --git a/apps/activepedom/ChangeLog b/apps/activepedom/ChangeLog index fb0bc78e5..c1b9ec011 100644 --- a/apps/activepedom/ChangeLog +++ b/apps/activepedom/ChangeLog @@ -1,2 +1,3 @@ 0.01: New Widget! -0.02: Distance calculation and display \ No newline at end of file +0.02: Distance calculation and display +0.03: Data logging and display \ No newline at end of file diff --git a/apps/activepedom/README.md b/apps/activepedom/README.md index 055a91f56..f45297e57 100644 --- a/apps/activepedom/README.md +++ b/apps/activepedom/README.md @@ -1,4 +1,4 @@ -# Active Pedometer +# Active Pedometer Pedometer that filters out arm movement and displays a step goal progress. I changed the step counting algorithm completely. @@ -6,6 +6,8 @@ Now every step is counted when in status 'active', if the time difference betwee To get in 'active' mode, you have to reach the step threshold before the active timer runs out. When you reach the step threshold, the steps needed to reach the threshold are counted as well. +Steps are saved to a datafile every 5 minutes. You can watch a graph using the app. + ## Screenshots * 600 steps ![](600.png) @@ -30,6 +32,22 @@ When you reach the step threshold, the steps needed to reach the threshold are c * Steps are saved to a file and read-in at start (to not lose step progress) * Settings can be changed in Settings - App/widget settings - Active Pedometer +## Data storage + +* Data is stored to a file +* Format: now,stepsCounted,active,stepsTooShort,stepsTooLong,stepsOutsideTime +* now is UNIX timestamp in ms +* You can chose the app to watch a steps graph +* You can import the file into Excel +* The file does not include a header +* You can convert UNIX timestamp to a date in Excel using this formula: =DATUM(1970;1;1)+(LINKS(A2;10)/86400) +* You have to format the cell with the formula to a date cell. Example: JJJJ-MM-TT-hh-mm-ss + +## App + +* The app accesses the data stored for the current day +* Timespan is choseable (1h, 4h, 8h, 12h, 16h, 20, 24h), standard is 24h, the whole current day + ## Settings * Max time (ms): Maximum time between two steps in milliseconds, steps will not be counted if exceeded. Standard: 1100 diff --git a/apps/activepedom/app.js b/apps/activepedom/app.js new file mode 100644 index 000000000..f966530d0 --- /dev/null +++ b/apps/activepedom/app.js @@ -0,0 +1,133 @@ +(() => { + +const storage = require("Storage"); +var history = 86400000; // 28800000=8h 43200000=12h //86400000=24h + +//Convert ms to time +function getTime(t) { + date = new Date(t); + offset = date.getTimezoneOffset() / 60; + //var milliseconds = parseInt((t % 1000) / 100), + seconds = Math.floor((t / 1000) % 60); + minutes = Math.floor((t / (1000 * 60)) % 60); + hours = Math.floor((t / (1000 * 60 * 60)) % 24); + hours = hours - offset; + hours = (hours < 10) ? "0" + hours : hours; + minutes = (minutes < 10) ? "0" + minutes : minutes; + seconds = (seconds < 10) ? "0" + seconds : seconds; + return hours + ":" + minutes + ":" + seconds; +} + +function getDate(t) { + date = new Date(t*1); + year = date.getFullYear(); + month = date.getMonth()+1; //month is zero-based + day = date.getDate(); + month = (month < 10) ? "0" + month : month; + day = (day < 10) ? "0" + day : day; + return year + "-" + month + "-" + day; +} + +//columns: 0=time, 1=stepsCounted, 2=active, 3=stepsTooShort, 4=stepsTooLong, 5=stepsOutsideTime +function getArrayFromCSV(file, column) { + i = 0; + array = []; + now = new Date(); + while ((nextLine = file.readLine())) { //as long as there is a next line + if(nextLine) { + dataSplitted = nextLine.split(','); //split line, + diff = now - dataSplitted[0]; //calculate difference between now and stored time + if (diff <= history) { //only entries from the last x ms + array.push(dataSplitted[column]); + } + } + i++; + } + return array; +} + +function drawGraph() { + //times + // actives = getArrayFromCSV(csvFile, 2); + // shorts = getArrayFromCSV(csvFile, 3); + // longs = getArrayFromCSV(csvFile, 4); + // outsides = getArrayFromCSV(csvFile, 5); //array.push(dataSplitted[5].slice(0,-1)); + now = new Date(); + month = now.getMonth() + 1; + if (month < 10) month = "0" + month; + filename = filename = "activepedom-" + now.getFullYear() + month + now.getDate() + ".data"; + var csvFile = storage.open(filename, "r"); + times = getArrayFromCSV(csvFile, 0); + first = getDate(times[0]) + " " + getTime(times[0]); + last = getDate (times[times.length-1]) + " " + getTime(times[times.length-1]); + //free memory + csvFile = undefined; + times = undefined; + + //steps + var csvFile = storage.open(filename, "r"); + steps = getArrayFromCSV(csvFile, 1); + //define y-axis grid labels + stepsLastEntry = steps[steps.length-1]; + if (stepsLastEntry < 1000) gridyValue = 100; + if (stepsLastEntry >= 1000 && stepsLastEntry < 10000) gridyValue = 500; + if (stepsLastEntry > 10000) gridyValue = 5000; + + //draw + drawMenu(); + g.drawString("First: " + first, 40, 30); + g.drawString(" Last: " + last, 40, 40); + require("graph").drawLine(g, steps, { + //title: "Steps Counted", + axes : true, + gridy : gridyValue, + y : 50, //offset on screen + x : 5, //offset on screen + }); + //free memory from big variables + allData = undefined; + allDataFile = undefined; + csvFile = undefined; + times = undefined; +} + +function drawMenu () { + g.clear(); + g.setFont("6x8", 1); + g.drawString("BTN1:Timespan | BTN2:Draw", 20, 10); + g.drawString("Timespan: " + history/1000/60/60 + " hours", 20, 20); +} + +setWatch(function() { //BTN1 + switch(history) { + case 3600000 : //1h + history = 14400000; //4h + break; + case 86400000 : //24 + history = 3600000; //1h + break; + default : + history = history + 14400000; //4h + break; + } + drawMenu(); +}, BTN1, {edge:"rising", debounce:50, repeat:true}); + +setWatch(function() { //BTN2 + g.setFont("6x8", 2); + g.drawString ("Drawing...",30,60); + drawGraph(); +}, BTN2, {edge:"rising", debounce:50, repeat:true}); + +setWatch(function() { //BTN3 +}, BTN3, {edge:"rising", debounce:50, repeat:true}); + +setWatch(function() { //BTN4 +}, BTN4, {edge:"rising", debounce:50, repeat:true}); + +setWatch(function() { //BTN5 +}, BTN5, {edge:"rising", debounce:50, repeat:true}); + +drawMenu(); + +})(); \ No newline at end of file diff --git a/apps/activepedom/widget.js b/apps/activepedom/widget.js index d569716ec..7879b2056 100644 --- a/apps/activepedom/widget.js +++ b/apps/activepedom/widget.js @@ -3,13 +3,14 @@ var startTimeStep = new Date(); //set start time var stopTimeStep = 0; //Time after one step var timerResetActive = 0; //timer to reset active + var timerStoreData = 0; //timer to store data var steps = 0; //steps taken var stepsCounted = 0; //active steps counted var active = 0; //x steps in y seconds achieved var stepGoalPercent = 0; //percentage of step goal var stepGoalBarLength = 0; //length og progress bar var lastUpdate = new Date(); //used to reset counted steps on new day - var width = 45; //width of widget + var width = 46; //width of widget //used for statistics and debugging var stepsTooShort = 0; @@ -18,13 +19,33 @@ var distance = 0; //distance travelled + const s = require('Storage'); const SETTINGS_FILE = 'activepedom.settings.json'; const PEDOMFILE = "activepedom.steps.json"; + var dataFile; + var storeDataInterval = 5*60*1000; //ms let settings; //load settings function loadSettings() { - settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; + settings = s.readJSON(SETTINGS_FILE, 1) || {}; + } + + function storeData() { + now = new Date(); + month = now.getMonth() + 1; + if (month < 10) month = "0" + month; + filename = filename = "activepedom-" + now.getFullYear() + month + now.getDate() + ".data"; + dataFile = s.open(filename,"a"); + if (dataFile) dataFile.write([ + now.getTime(), + stepsCounted, + active, + stepsTooShort, + stepsTooLong, + stepsOutsideTime, + ].join(",")+"\n"); + dataFile = undefined; } //return setting @@ -77,20 +98,20 @@ //Remove step if time between first and second step is too long if (stepTimeDiff >= setting('cMaxTime')) { //milliseconds - stepsTooLong++; //count steps which are note counted, because time too long + stepsTooLong++; //count steps which are not counted, because time too long steps--; } - //Remove step if time between first and second step is too short if (stepTimeDiff <= setting('cMinTime')) { //milliseconds - stepsTooShort++; //count steps which are note counted, because time too short + stepsTooShort++; //count steps which are not counted, because time too short steps--; } + //Step threshold reached if (steps >= setting('stepThreshold')) { if (active == 0) { stepsCounted = stepsCounted + (setting('stepThreshold') -1) ; //count steps needed to reach active status, last step is counted anyway, so treshold -1 - stepsOutsideTime = stepsOutsideTime - 10; //substract steps needed to reac active status + stepsOutsideTime = stepsOutsideTime - 10; //substract steps needed to reach active status } active = 1; clearInterval(timerResetActive); //stop timer which resets active @@ -109,14 +130,17 @@ function draw() { var height = 23; //width is deined globally - distance = (stepsCounted * setting('stepLength')) / 100 /1000 //distance in km + distance = (stepsCounted * setting('stepLength')) / 100 /1000; //distance in km //Check if same day let date = new Date(); if (lastUpdate.getDate() == date.getDate()){ //if same day } - else { - stepsCounted = 1; //set stepcount to 1 + else { //different day, set all steps to 0 + stepsCounted = 0; + stepsTooShort = 0; + stepsTooLong = 0; + stepsOutsideTime = 0; } lastUpdate = date; @@ -166,7 +190,7 @@ stepsTooLong : stepsTooLong, stepsOutsideTime : stepsOutsideTime }; - require("Storage").write(PEDOMFILE,d); //write array to file + s.write(PEDOMFILE,d); //write array to file }); //When Step is registered by firmware @@ -182,8 +206,7 @@ }); //Read data from file and set variables - let pedomData = require("Storage").readJSON(PEDOMFILE,1); - + let pedomData = s.readJSON(PEDOMFILE,1); if (pedomData) { if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); stepsCounted = pedomData.stepsToday|0; @@ -191,12 +214,10 @@ stepsTooLong = pedomData.stepsTooLong; stepsOutsideTime = pedomData.stepsOutsideTime; } - pedomdata = 0; //reset pedomdata to save memory setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive) - + timerStoreData = setInterval(storeData, storeDataInterval); //store data regularly //Add widget WIDGETS["activepedom"]={area:"tl",width:width,draw:draw}; - })(); \ No newline at end of file From 35583eb8371551bc055dfd55316c8f2216aedb9e Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:36:42 +0200 Subject: [PATCH 15/77] activepedom 0.03 --- apps.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 274a3a8b2..eda9203bc 100644 --- a/apps.json +++ b/apps.json @@ -1127,15 +1127,15 @@ "name": "Active Pedometer", "shortName":"Active Pedometer", "icon": "app.png", - "version":"0.02", - "description": "Pedometer that filters out arm movement and displays a step goal progress.", + "version":"0.03", + "description": "Pedometer that filters out arm movement and displays a step goal progress. Steps are saved to a daily file and can be viewed as graph.", "tags": "outdoors,widget", - "type":"widget", "readme": "README.md", "storage": [ {"name":"activepedom.wid.js","url":"widget.js"}, {"name":"activepedom.settings.js","url":"settings.js"}, - {"name":"activepedom.img","url":"app-icon.js","evaluate":true} + {"name":"activepedom.img","url":"app-icon.js","evaluate":true}, + {"name":"activepedom.app.js","url":"app.js"}, ] }, { "id": "chronowid", From 5d3264e51eb68116677838fc4d3c5e545448b729 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:37:45 +0200 Subject: [PATCH 16/77] activepedom 0.03 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index eda9203bc..36498423e 100644 --- a/apps.json +++ b/apps.json @@ -1135,7 +1135,7 @@ {"name":"activepedom.wid.js","url":"widget.js"}, {"name":"activepedom.settings.js","url":"settings.js"}, {"name":"activepedom.img","url":"app-icon.js","evaluate":true}, - {"name":"activepedom.app.js","url":"app.js"}, + {"name":"activepedom.app.js","url":"app.js"} ] }, { "id": "chronowid", From 3e9f581b9fb3adcf23421fff4956490f20fdc452 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Mon, 20 Apr 2020 17:09:27 +0100 Subject: [PATCH 17/77] Fix apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bff5fe66b..7a1a3f5fb 100644 --- a/apps.json +++ b/apps.json @@ -1308,7 +1308,7 @@ {"name":"buffgym-set.js","url":"buffgym-set.js"}, {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, {"name":"buffgym-program.js","url":"buffgym-program.js"}, - {"name":"buffgym-programs.json","url":"buffgym-program.json"}, + {"name":"buffgym-programs.json","url":"buffgym-programs.json"}, {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} ] } From 900805e71b2a670ef5098f87a71525c0b7672c36 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Mon, 20 Apr 2020 17:20:23 +0100 Subject: [PATCH 18/77] Fix apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7a1a3f5fb..4eeee4e32 100644 --- a/apps.json +++ b/apps.json @@ -1304,7 +1304,7 @@ "type": "app", "storage": [ {"name":"buffgym"}, - {"name":"buffgym.app.js"}, + {"name":"buffgym.app.js", "url": "buffgym.app.js"}, {"name":"buffgym-set.js","url":"buffgym-set.js"}, {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, {"name":"buffgym-program.js","url":"buffgym-program.js"}, From fae5b02277014aae97e31109ffd01adc66f04430 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 20:39:59 +0200 Subject: [PATCH 19/77] Create osmpoi.html --- apps/osmpoi/osmpoi.html | 228 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 apps/osmpoi/osmpoi.html diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html new file mode 100644 index 000000000..56a1f8eb6 --- /dev/null +++ b/apps/osmpoi/osmpoi.html @@ -0,0 +1,228 @@ + + + + + + + + +
+
+ +
+ +

Click

+

If ok, Click

+
+ + + + + + + + + From 83253aa5be1e48b6cfabe9fa77d4520e994067f2 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 20:40:28 +0200 Subject: [PATCH 20/77] Add files via upload --- apps/osmpoi/app.png | Bin 0 -> 1989 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/osmpoi/app.png diff --git a/apps/osmpoi/app.png b/apps/osmpoi/app.png new file mode 100644 index 0000000000000000000000000000000000000000..31f09b5316318426fe64e8e427541af999cc72ae GIT binary patch literal 1989 zcmV;$2RitPP)<|5#K+5}}kD(!|)9(u%gVg{sw(nl_lqL$MVQDH;j|7FN0}AX{0Khb+6W@0r<| zojY^q-h2AT?8590%RDZWH1V5EGWVSGdwkFDJbvdK_&QOkEyJ_by8*nGm+3wY})8rT{P> zXe?AmAq0ZJI#tug&41xVW858IoL;E0q43XN|EjkB^-WWO$AMP?D__}s2q?f$fG2MI z#=jzaCK2q2C_s3V*$yiJRo&es;M=lqE@xVsS@AofQ_b1=TDN`pq zbu<$f>gpPzT^)KN95%x(7mY|$lYRE!foa0FM*_2f1G#kMBCr^ES@n27l4MC_R;b>R z-bdg0#|&9f)MA`BV$taHcYoCf)Bv488_?1BzXR9~#B%9z<*45PoJl40ETTp{zP{_+ zx$~95V6af<0TfNs00G<$*v068+yr94?jh=QA@ZJUSx{8B8%O}9K)6^va?u`K2S~Eq z1C%+@aZ?G%E>{dFcckMw`BD_zUT+k*#fgqwbKr);TUH*|Bax~>#lwI~uB?zY5b676 zP4=4_f#IV^r+~2;MazJTD9XQ3l!Hi8J(6^k^b%{4USdy?PR$p=O^!fd`~*03Ff#&o zdB6XI1lt6j8t2#JYoi<$~eOw(7ftMt=`)f*hc{^^m zEc^VDYh2{UREj2;570G6`WjI}m9;znk==1^6bgUY&9K z33b}^S=W+FH5?bf5x6pm`+8GkhprD&X`qz!uDO`>3LzwfqbO*8pPO_9zKbMn7`AlT zx#7<|I~!TP)@_L}PoJJlI)}PUzyj)xrlzw)Nx6f;8G(lu#U)jJ5cmxsgzb!gyVS1% z6Og2Jfi=GmdFITWnM=m}@IN17Stf8SlK{Yb$zw;anf=Lu!05okk5nKl-vffCksLB& zc@gmXJb=f)Z24)|l&N_og}rZVZUeSn_9>%ohk5DJ;7uh9Qb|c!>4F7GBq^HGgy)}JNv&g3H%$&@>{W3doCreF=KC)-0lmhcsx~*$Ak5FJYK+a ztu`VakH*%$ycZ#a-PzGfDm4n&*I%DWzy@klr%s;9%evw+jJWP_2zkALB8=44JHocj z@baY}B(}aa%lzd0C;Iknr+~er({La=l{jpC^l@HJ$(lPE4|O|=fF#Qjpxe<%B&*Ui zjnG32>#UX*6ZmO(>5?*i%Nx^y^_k5ErxJUt_O>79WnA-^y`5b}pQQRByIftOt1Cgp zh$~l)mSu&OJW_A9x5a?(0C9xa0#pID1LOzkdtX@A2s;$I&|lE|?ymRD)=Q_d2zWhq zytBjcZmfDd5xb-F%IYVC9e!-dA?xDBDDZ6{-dEE+*!imwFoD16hiXm(#1Gc&PBxtQ zO3$W^n%UNNa)6-EM{hXf_-7Lhzmb^LvfIlP~8$TcU z^DFxkwTGqwv$5?}JsbX7VYXhnd~+t3_+&j4cKp8JtEe#SmSzLMI9z)yS+jo%aDP6| z4@ICJm~Vx{yMR0TzW;&{D|rY2(1qOMdj5g0qxwpyAck3K#|7-jg X&}z;-%?VoU00000NkvXXu0mjfBg)CA literal 0 HcmV?d00001 From 4bdedc08fbb7f12c67094666256953a6c2af5a24 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 20:46:00 +0200 Subject: [PATCH 21/77] Update apps.json --- apps.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps.json b/apps.json index e55190ec0..95669f250 100644 --- a/apps.json +++ b/apps.json @@ -1412,5 +1412,17 @@ {"name":"hamloc.app.js","url":"app.js"}, {"name":"hamloc.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "osmpoi", + "name": "POI Compass", + "icon": "app.png", + "version":"0.01", + "description": "Uploads all the points of interest in an area onto your watch, same as Beer Compass with more p.o.i.", + "tags": "tool,outdoors,gps", + "custom": "osmpoi.html", + "storage": [ + {"name":"osmpoi.app.js"}, + {"name":"osmpoi.img"} + ] } ] From 95ddcbf4670c1e50376b9c7640221f72dcb698d6 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 20:48:07 +0200 Subject: [PATCH 22/77] Create ChangeLog --- apps/osmpoi/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/osmpoi/ChangeLog diff --git a/apps/osmpoi/ChangeLog b/apps/osmpoi/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/osmpoi/ChangeLog @@ -0,0 +1 @@ +0.01: New App! From 3363999e806864910ecb252c636bf92eb2694bcd Mon Sep 17 00:00:00 2001 From: bengwalker <63957296+bengwalker@users.noreply.github.com> Date: Mon, 20 Apr 2020 20:49:54 +0200 Subject: [PATCH 23/77] add ChangeLog, attribute to source for icon --- apps/metronome/ChangeLog | 3 +++ apps/metronome/README.md | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 apps/metronome/ChangeLog diff --git a/apps/metronome/ChangeLog b/apps/metronome/ChangeLog new file mode 100644 index 000000000..a65efbaaf --- /dev/null +++ b/apps/metronome/ChangeLog @@ -0,0 +1,3 @@ +0.01: New App! +0.02: Watch vibrates with every beat +0.03: Uses mean of three time intervalls to calculate bmp diff --git a/apps/metronome/README.md b/apps/metronome/README.md index 19d489327..aab2d5a3f 100644 --- a/apps/metronome/README.md +++ b/apps/metronome/README.md @@ -8,3 +8,7 @@ This metronome makes your watch blink and vibrate with a given rate. * Use `BTN1` to increase the bmp value by one. * Use `BTN3` to decrease the bmp value by one. * You can change the bpm value any time by tapping the screen or using `BTN1` and `BTN3`. + +## Attributions + +"Icon made by Roundicons from www.flaticon.com" \ No newline at end of file From 7d8700a3e91e17bdccbdb940ffa2ec45627e772e Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Mon, 20 Apr 2020 20:50:55 +0200 Subject: [PATCH 24/77] Create README.md --- apps/osmpoi/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/osmpoi/README.md diff --git a/apps/osmpoi/README.md b/apps/osmpoi/README.md new file mode 100644 index 000000000..4c59e16f6 --- /dev/null +++ b/apps/osmpoi/README.md @@ -0,0 +1,5 @@ +# Points Of Interest Compass + +## Description + +Uploads all the points of interest in an area onto your watch, same as Beer Compass with more p.o.i. From 707f4a1ccdd4e3f89095529060de429d6d1fa827 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Mon, 20 Apr 2020 21:39:30 +0100 Subject: [PATCH 25/77] More fixes --- apps/buffgym/buffgym-exercise.js | 4 +- apps/buffgym/buffgym-program.js | 2 +- apps/buffgym/buffgym-programs.json | 102 +---- apps/buffgym/buffgym-programs.json.unminified | 101 +++++ apps/buffgym/buffgym-set.js | 2 +- apps/buffgym/buffgym.app.js | 420 +++++++++--------- 6 files changed, 313 insertions(+), 318 deletions(-) create mode 100644 apps/buffgym/buffgym-programs.json.unminified diff --git a/apps/buffgym/buffgym-exercise.js b/apps/buffgym/buffgym-exercise.js index b7a1e3e15..99d658571 100644 --- a/apps/buffgym/buffgym-exercise.js +++ b/apps/buffgym/buffgym-exercise.js @@ -2,10 +2,8 @@ const STARTED = 1; const RESTING = 2; const COMPLETED = 3; const ONE_SECOND = 1000; -const INCREMENT = "increment"; -const DECREMENT = "decrement"; -class Exercise { +exports = class Exercise { constructor(params /*{title, weight, unit, restPeriod}*/) { const DEFAULTS = { title: "Unknown", diff --git a/apps/buffgym/buffgym-program.js b/apps/buffgym/buffgym-program.js index 22f39f10b..956827f56 100644 --- a/apps/buffgym/buffgym-program.js +++ b/apps/buffgym/buffgym-program.js @@ -1,4 +1,4 @@ -class Program { +exports = class Program { constructor(params) { const DEFAULTS = { title: "Unknown", diff --git a/apps/buffgym/buffgym-programs.json b/apps/buffgym/buffgym-programs.json index bf5aa0e0d..7551c7a47 100644 --- a/apps/buffgym/buffgym-programs.json +++ b/apps/buffgym/buffgym-programs.json @@ -1,101 +1 @@ -[ - { - title: "Program A", - exercises: [ - { - title: "Squats", - weight: 40, - unit: "Kg", - sets: [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - title: "Overhead press", - weight: 20, - unit: "Kg", - sets: [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - title: "Deadlift", - weight: 20, - unit: "Kg", - sets: [ - 5 - ] - }, - { - title: "Pullups", - weight: 0, - unit: "Kg", - sets: [ - 10, - 10, - 10 - ] - } - ] - }, - { - title: "Program B", - exercises: [ - { - title: "Squats", - weight: 40, - unit: "Kg", - sets: [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - title: "Bench press", - weight: 20, - unit: "Kg", - sets: [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - title: "Row", - weight: 20, - unit:"Kg", - sets: [ - 5, - 5, - 5, - 5, - 5 - ] - - }, - { - title: "Tricep extension", - weight: 20, - unit: "Kg", - sets: [ - 10, - 10, - 10 - ] - } - ] - } -] \ No newline at end of file +[{"title":"Program A","exercises":[{"title":"Squats","weight":40,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Overhead press","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Deadlift","weight":20,"unit":"Kg","sets":[5]},{"title":"Pullups","weight":0,"unit":"Kg","sets":[10,10,10]}]},{"title":"Program B","exercises":[{"title":"Squats","weight":40,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Bench press","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Row","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Tricep extension","weight":20,"unit":"Kg","sets":[10,10,10]}]}] \ No newline at end of file diff --git a/apps/buffgym/buffgym-programs.json.unminified b/apps/buffgym/buffgym-programs.json.unminified new file mode 100644 index 000000000..cd005eeab --- /dev/null +++ b/apps/buffgym/buffgym-programs.json.unminified @@ -0,0 +1,101 @@ +[ + { + "title": "Program A", + "exercises": [ + { + "title": "Squats", + "weight": 40, + "unit": "Kg", + "sets": [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + "title": "Overhead press", + "weight": 20, + "unit": "Kg", + "sets": [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + "title": "Deadlift", + "weight": 20, + "unit": "Kg", + "sets": [ + 5 + ] + }, + { + "title": "Pullups", + "weight": 0, + "unit": "Kg", + "sets": [ + 10, + 10, + 10 + ] + } + ] + }, + { + "title": "Program B", + "exercises": [ + { + "title": "Squats", + "weight": 40, + "unit": "Kg", + "sets": [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + "title": "Bench press", + "weight": 20, + "unit": "Kg", + "sets": [ + 5, + 5, + 5, + 5, + 5 + ] + }, + { + "title": "Row", + "weight": 20, + "unit":"Kg", + "sets": [ + 5, + 5, + 5, + 5, + 5 + ] + + }, + { + "title": "Tricep extension", + "weight": 20, + "unit": "Kg", + "sets": [ + 10, + 10, + 10 + ] + } + ] + } +] \ No newline at end of file diff --git a/apps/buffgym/buffgym-set.js b/apps/buffgym/buffgym-set.js index d7d610a78..aed6df260 100644 --- a/apps/buffgym/buffgym-set.js +++ b/apps/buffgym/buffgym-set.js @@ -1,4 +1,4 @@ -class Set { +exports = class Set { constructor(maxReps) { this._minReps = 0; this._maxReps = maxReps; diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index d3a4e6834..11005900a 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -1,230 +1,226 @@ -/* global g, setWatch, clearWatch, reset, BTN1, BTN2, BTN3 */ +const W = g.getWidth(); +const H = g.getHeight(); +const RED = "#d32e29"; +const PINK = "#f05a56"; +const WHITE = "#ffffff"; -(() => { - const W = g.getWidth(); - const H = g.getHeight(); - const RED = "#d32e29"; - const PINK = "#f05a56"; - const WHITE = "#ffffff"; +const Set = require("buffgym-set.js"); +const Exercise = require("buffgym-exercise.js"); +const Program = require("buffgym-program.js"); - const Set = require("set.js"); - const Exercise = require("exercise.js"); - const Program = require("program.js"); +function centerStringX(str) { + return (W - g.stringWidth(str)) / 2; +} - function centerStringX(str) { - return (W - g.stringWidth(str)) / 2; +function iconIncrement() { + const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglHA4IpJBYwTHA4RMJCY5oDJo4THKIQKET5IMGCaY7TMaKLTWajbTFJIlICgoVBFYXJYQYSGCggAGCRAVIBgw")); + return img; +} + +function iconDecrement() { + const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCRYABCYQmOFAhNMKIw6FTw4LHCaY7TMaKLTWajbTFJglFCgoVBFYXJYQYSGCggAGCRAVIBgw=")); + return img; +} + +function iconOk() { + const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCJQxCCYQmMIwZoDJpQMCKIg6KBYwTGFQgeHHYouCCRI7EMYTXFRhILEK5SfFRgYSIborbSbpglFCgoVBFYXJYQYSGCggAGCRAVIBgwA==")); + return img; +} + +function drawMenu(params) { + const DEFAULT_PARAMS = { + showBTN1: false, + showBTN2: false, + showBTN3: false, + }; + const p = Object.assign({}, DEFAULT_PARAMS, params); + if (p.showBTN1) g.drawImage(iconIncrement(), W - 30, 10); + if (p.showBTN2) g.drawImage(iconOk(), W - 30, 110); + if (p.showBTN3) g.drawImage(iconDecrement(), W - 30, 210); +} + +function clearScreen() { + g.setColor(RED); + g.fillRect(0,0,W,H); +} + +function drawTitle(exercise) { + const title = exercise.humanTitle; + + g.setFont("Vector",20); + g.setColor(WHITE); + g.drawString(title, centerStringX(title), 5); +} + +function drawReps(exercise) { + const set = exercise.currentSet; + if (set.isCompleted()) return; + + g.setColor(PINK); + g.fillCircle(W / 2, H / 2, 50); + g.setColor(WHITE); + g.setFont("Vector", 40); + g.drawString(set.reps, centerStringX(set.reps), (H - 45) / 2); + g.setFont("Vector", 15); + const note = `of ${set.maxReps}`; + g.drawString(note, centerStringX(note), (H / 2) + 25); +} + +function drawSets(exercise) { + const sets = exercise.subTitle; + + g.setColor(WHITE); + g.setFont("Vector", 15); + g.drawString(sets, centerStringX(sets), H - 25); +} + +function drawSetProgress(exercise) { + drawTitle(exercise); + drawReps(exercise); + drawSets(exercise); + drawMenu({showBTN1: true, showBTN2: true, showBTN3: true}); +} + +function drawStartNextExercise() { + const title = "Good work"; + const msg = "No need to rest\nmove straight on\nto the next exercise"; + + g.setColor(WHITE); + g.setFont("Vector", 35); + g.drawString(title, centerStringX(title), 10); + g.setFont("Vector", 15); + g.drawString(msg, 30, 150); + drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); +} + +function drawProgramCompleted() { + const title1 = "You did"; + const title2 = "GREAT!"; + const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest."; + + clearWatch(); + setWatch(reset, BTN2, {repeat: false}); + + g.setColor(WHITE); + g.setFont("Vector", 35); + g.drawString(title1, centerStringX(title1), 10); + g.setFont("Vector", 40); + g.drawString(title2, centerStringX(title2), 50); + g.setFont("Vector", 15); + g.drawString(msg, 30, 150); + drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); +} + +/* +function drawExerciseCompleted(program) { + const exercise = program.currentExercise(); + const title = exercise.canProgress? + "WELL DONE!" : + "NOT BAD!"; + const msg = exercise.canProgress? + `You weight is automatically increased\nfor ${exercise.title} to ${exercise.weight}${exercise.unit}` : + "It looks like you struggled\non a few sets, your weight will\nstay the same"; + const action = "Move straight on to the next exercise"; + + clearScreen(); + g.setColor(WHITE); + g.setFont("Vector", 20); + g.drawString(title, centerStringX(title), 10); + g.setFont("Vector", 10); + g.drawString(msg, centerStringX(msg), 180); + g.drawString(action, centerStringX(action), 210); + drawMenu({showBTN2: true}); + + clearWatch(); + setWatch(() => { + init(program); + }, BTN2, {repeat: false}); +} +*/ + +function drawRestTimer(program) { + const exercise = program.currentExercise(); + const motivation = "Take a breather.."; + clearScreen(); + drawMenu({showBTN2: true}); + + g.setColor(PINK); + g.fillCircle(W / 2, H / 2, 50); + g.setColor(WHITE); + g.setFont("Vector", 15); + g.drawString(motivation, centerStringX(motivation), 25); + g.setFont("Vector", 40); + g.drawString(exercise.restPeriod, centerStringX(exercise.restPeriod), (H - 45) / 2); + exercise.decRestPeriod(); + + if (exercise.restPeriod <= 0) { + exercise.resetRestTimer(); + redraw(program); + } +} + +function redraw(program) { + const exercise = program.currentExercise(); + + clearScreen(); + + if (program.isCompleted()) { + drawProgramCompleted(program); + return; } - function iconIncrement() { - const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglHA4IpJBYwTHA4RMJCY5oDJo4THKIQKET5IMGCaY7TMaKLTWajbTFJIlICgoVBFYXJYQYSGCggAGCRAVIBgw")); - return img; - } - - function iconDecrement() { - const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCRYABCYQmOFAhNMKIw6FTw4LHCaY7TMaKLTWajbTFJglFCgoVBFYXJYQYSGCggAGCRAVIBgw=")); - return img; - } - - function iconOk() { - const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCJQxCCYQmMIwZoDJpQMCKIg6KBYwTGFQgeHHYouCCRI7EMYTXFRhILEK5SfFRgYSIborbSbpglFCgoVBFYXJYQYSGCggAGCRAVIBgwA==")); - return img; - } - - function drawMenu(params) { - const DEFAULT_PARAMS = { - showBTN1: false, - showBTN2: false, - showBTN3: false, - }; - const p = Object.assign({}, DEFAULT_PARAMS, params); - if (p.showBTN1) g.drawImage(iconIncrement(), W - 30, 10); - if (p.showBTN2) g.drawImage(iconOk(), W - 30, 110); - if (p.showBTN3) g.drawImage(iconDecrement(), W - 30, 210); - } - - function clearScreen() { - g.setColor(RED); - g.fillRect(0,0,W,H); - } - - function drawTitle(exercise) { - const title = exercise.humanTitle; - - g.setFont("Vector",20); - g.setColor(WHITE); - g.drawString(title, centerStringX(title), 5); - } - - function drawReps(exercise) { - const set = exercise.currentSet; - if (set.isCompleted()) return; - - g.setColor(PINK); - g.fillCircle(W / 2, H / 2, 50); - g.setColor(WHITE); - g.setFont("Vector", 40); - g.drawString(set.reps, centerStringX(set.reps), (H - 45) / 2); - g.setFont("Vector", 15); - const note = `of ${set.maxReps}`; - g.drawString(note, centerStringX(note), (H / 2) + 25); - } - - function drawSets(exercise) { - const sets = exercise.subTitle; - - g.setColor(WHITE); - g.setFont("Vector", 15); - g.drawString(sets, centerStringX(sets), H - 25); - } - - function drawSetProgress(exercise) { - drawTitle(exercise); - drawReps(exercise); - drawSets(exercise); - drawMenu({showBTN1: true, showBTN2: true, showBTN3: true}); - } - - function drawStartNextExercise() { - const title = "Good work"; - const msg = "No need to rest\nmove straight on\nto the next exercise"; - - g.setColor(WHITE); - g.setFont("Vector", 35); - g.drawString(title, centerStringX(title), 10); - g.setFont("Vector", 15); - g.drawString(msg, 30, 150); - drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); - } - - function drawProgramCompleted() { - const title1 = "You did"; - const title2 = "GREAT!"; - const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest."; - - clearWatch(); - setWatch(reset, BTN2, {repeat: false}); - - g.setColor(WHITE); - g.setFont("Vector", 35); - g.drawString(title1, centerStringX(title1), 10); - g.setFont("Vector", 40); - g.drawString(title2, centerStringX(title2), 50); - g.setFont("Vector", 15); - g.drawString(msg, 30, 150); - drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); - } - - /* - function drawExerciseCompleted(program) { - const exercise = program.currentExercise(); - const title = exercise.canProgress? - "WELL DONE!" : - "NOT BAD!"; - const msg = exercise.canProgress? - `You weight is automatically increased\nfor ${exercise.title} to ${exercise.weight}${exercise.unit}` : - "It looks like you struggled\non a few sets, your weight will\nstay the same"; - const action = "Move straight on to the next exercise"; - - clearScreen(); - g.setColor(WHITE); - g.setFont("Vector", 20); - g.drawString(title, centerStringX(title), 10); - g.setFont("Vector", 10); - g.drawString(msg, centerStringX(msg), 180); - g.drawString(action, centerStringX(action), 210); - drawMenu({showBTN2: true}); - - clearWatch(); - setWatch(() => { - init(program); - }, BTN2, {repeat: false}); - } - */ - - function drawRestTimer(program) { - const exercise = program.currentExercise(); - const motivation = "Take a breather.."; - clearScreen(); - drawMenu({showBTN2: true}); - - g.setColor(PINK); - g.fillCircle(W / 2, H / 2, 50); - g.setColor(WHITE); - g.setFont("Vector", 15); - g.drawString(motivation, centerStringX(motivation), 25); - g.setFont("Vector", 40); - g.drawString(exercise.restPeriod, centerStringX(exercise.restPeriod), (H - 45) / 2); - exercise.decRestPeriod(); - - if (exercise.restPeriod <= 0) { - exercise.resetRestTimer(); - redraw(program); - } - } - - function redraw(program) { - const exercise = program.currentExercise(); - - clearScreen(); - - if (program.isCompleted()) { - drawProgramCompleted(program); - return; + if (exercise.isRestTimerRunning()) { + if (exercise.isLastSet()) { + drawStartNextExercise(program); + } else { + drawRestTimer(program); } - if (exercise.isRestTimerRunning()) { - if (exercise.isLastSet()) { - drawStartNextExercise(program); - } else { - drawRestTimer(program); - } - - return; - } - - drawSetProgress(exercise); + return; } - function init(program) { - clearWatch(); - program.next(); - } + drawSetProgress(exercise); +} - // Setup training program. This should come from file +function init(program) { + clearWatch(); + program.next(); +} - // Squats - function buildPrograms() { - const programsJSON = require("Storage").readJSON("buffgym-programs.json", 1); +// Setup training program. This should come from file - if (!programsJSON) throw "No programs JSON found"; +// Squats +function buildPrograms() { + const programsJSON = require("Storage").readJSON("buffgym-programs.json", 1); - const programs = []; + if (!programsJSON) throw "No programs JSON found"; - programsJSON.forEach(programJSON => { - const program = new Program({ - title: programJSON.title, - }); - const exercises = programJSON.exercises.map(exerciseJSON => { - const exercise = new Exercise({ - title: exerciseJSON.title, - weight: exerciseJSON.weight, - unit: exerciseJSON.unit, - }); - exerciseJSON.sets.forEach(setJSON => { - exercise.addSet(new Set(setJSON)); - }); + const programs = []; - return exercise; - }); - program.addExercises(exercises); - programs.push(program); + programsJSON.forEach(programJSON => { + const program = new Program({ + title: programJSON.title, }); + const exercises = programJSON.exercises.map(exerciseJSON => { + const exercise = new Exercise({ + title: exerciseJSON.title, + weight: exerciseJSON.weight, + unit: exerciseJSON.unit, + }); + exerciseJSON.sets.forEach(setJSON => { + exercise.addSet(new Set(setJSON)); + }); - return programs; - } + return exercise; + }); + program.addExercises(exercises); + programs.push(program); + }); - // For this spike, just run the first program, what will - // really happen is the user picks a program to do from - // some menu on a start page. - init(buildPrograms()[0]); -})(); \ No newline at end of file + return programs; +} + +// For this spike, just run the first program, what will +// really happen is the user picks a program to do from +// some menu on a start page. +init(buildPrograms()[0]); \ No newline at end of file From 6deb376d99b4dab29c9ec31bd78432e08b08510e Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Mon, 20 Apr 2020 22:02:55 +0100 Subject: [PATCH 26/77] Return to launcher on exit --- apps/buffgym/buffgym.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index 11005900a..e1ab3e66b 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -99,7 +99,7 @@ function drawProgramCompleted() { const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest."; clearWatch(); - setWatch(reset, BTN2, {repeat: false}); + setWatch(Bangle.showLauncher, BTN2, {repeat: false}); g.setColor(WHITE); g.setFont("Vector", 35); From 15a92c1b38006dfd908c91e69b060ca457d35e9b Mon Sep 17 00:00:00 2001 From: singintime Date: Tue, 21 Apr 2020 01:10:10 +0200 Subject: [PATCH 27/77] Minion clock v0.02 --- apps.json | 2 +- apps/minionclk/ChangeLog | 1 + apps/minionclk/app.js | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index b58fad5ce..924d2e75c 100644 --- a/apps.json +++ b/apps.json @@ -1126,7 +1126,7 @@ { "id": "minionclk", "name": "Minion clock", "icon": "minionclk.png", - "version": "0.01", + "version": "0.02", "description": "Minion themed clock.", "tags": "clock,minion", "type": "clock", diff --git a/apps/minionclk/ChangeLog b/apps/minionclk/ChangeLog index 7b83706bf..dbe920a80 100755 --- a/apps/minionclk/ChangeLog +++ b/apps/minionclk/ChangeLog @@ -1 +1,2 @@ 0.01: First release +0.02: Improved date readability, fixed drawing of widgets diff --git a/apps/minionclk/app.js b/apps/minionclk/app.js index 88fe446ae..7f00cd362 100755 --- a/apps/minionclk/app.js +++ b/apps/minionclk/app.js @@ -1,4 +1,4 @@ -const bob = require("heatshrink").decompress(atob("nk8hAaXlYLWAEsqvN/0gBBql5lQ2tquj1XV5wBJ52j0hACPsdP1QsBAQQAGBIIBF51/P8OkN5R1GIxF5HLmAFgoDLPZfOpzmZ6vPFwomCPaA6DAYOjeq2A1YyCdI4HGQJQ8F1T2SJ4Oq1XW1es1mtAQOrPoPUAIh3J54ZHIAR5S62s64cBwIBGQIOqHQK4HKQYVDAAIFC1g+BHh9VHAQAFDwQDDHoJ5E54BB6AaBKQ5YGqo6MwJzGHQ4BDeIj/BR4JxDABY8BvI6OOYgaEHwZADHgQ6BZA42GAIusPJNW64eFqzJDlcrERA8BHQI2FqwaBDYYGBPI45GCoIgCLoVWQ5NWXA2rKhaiGLAwOGEAmADxJPDVA51ElQaMC4ouEWALdEHRg8Dc4woCDJo8EAIYxCHQQIFHiwaRegJ5EcYWsHgbrKbBA8GDSrNDO4wfRKgR3FDSh3CN4UrdwZbSHYZ5DHajMFHYQGCHalWO4jtQDQwABwAGCAAQfTKoK0EHahwCeARdFHakASIZWVZ4Q8CO4YgWO4QbCO6hWGEIKYZKzZ3DLog7UG4I6C1lWDSdWO4bpCO4bwUwKYEHajMDwOAlUkLojTUd4gaTZoRWC0YIB1eJLqo4EWiqRE0mjlcr1QkEeKFWOooBCHiB2CC4WA5wzB52rEQgfPHQwABAYJXOHQ2iO4XO6omFEJh1BEAgBGPJlWDIQbC0ej50qgHV1XPEwohKcwRbEvJ3EBQTrLFomkOwOjlR3C5w8GMAR8ClYuBLIgOCvN4HgIZFDQYbBlaOBR4YNCwA5B0XOpzvBHgWqTw4AFxB1EvQ6BAAI8GDZILEdgQBCqp3DPIRfIEQwABvJ1CvGkvGiwA6IAYoBCv6wCAAVOlQ6DAIWkL5ABEwN40Z1CAYJfCv7zEAJNWOYZ3KAIWq5yYHFYLOBLIrVCAIh7BOIzpECoYDDpw7BHAQDG1WqwGkAIN/CwIABLY4LDAAZ9BwAABvLCBC5IBBvOrO44BEAAmjAIPN0XOAJyHIAAgPEquBHBi4BAId+HwWiHxqJDRpYBDq2I1R3LIAQ6BAAOpPogABGgIDDOomk0nP5pIGd42Aq1ewI8CeZI6CHAJhCEAIDCdIo2B0er1esAQIZBC4Z9JlVW1leeKGp0es5+s6+s6ABB0oFBAIervWr0ulub7OqtWmdexJ4BGxB5G0V6pF6wItB0t6p9PvQABvINBudJudPzwXCHQwBDlY6BO4WIwPPPJbvDvA0BFgNzAAIDGugGCzrtHdYh1DAIOBrzxBPIgAIeIXNHgoBCGwYADzoVB0fNOpMyHQdW5+Bro7BHgQAB6jxJAAOjOYhxCAIukOoPN5ujdZFWqyyD0d6AwUrquBwAuB1I1FHgRJBMoQ9BWg1zzw0BDYI6B0R3DAAJ1BvMyp8rAAV4IQWBIodewAeCHAZ5IAAJoBAAXHHAJWDO4TtEdYQvEHgejAwIKClcqIQRdDXYbzFeoQBIGwIDDOot/VgQ6FAAIGBlgBCAAMzmZPBF4LzDACB1FAAOi1WjvFVr0zGYQ7GAAMAAYpPBwNeAIOIwOrfYOA1eA1WkAIWjAIekv4PBwCVBruBq5eBEYIABlcBF4wCEHw55CHwQABIQQBBABkzAILlCHQR1CFYavEPgsAAAIDEDQNdAwQAaHQNWEwQ0DHAh3KleBLoI7dHQKuFWQo0EAIsISoKdBHbyyHNgwADlVVpwEBDANWro7fd4Q6HO495vF5QgIYCd75eBHYUINAN5lQ3EA")); +const bob = require("heatshrink").decompress(atob("nk8hAaXlYLWAEsqvN/0gBBql5lQ2tquj1XV5wBJ52j0hACPsdP1QsBAQQAGBIIBF51/P8OkN5R1GIxF5HLmAFgoDLPZfOpzmZ6vPFwomCPaA6DAYOjeq2A1YyCdI4HGQJQ8F1T2SJ4Oq1XW1es1mtAQOrPoPUAIh3J54ZHIAR5S62s64cBwIBGQIOqHQK4HKQYVDAAIFC1g+BHh9VHAQAFDwQDDHoJ5E54BB6AaBKQ5YGqo6MwJzGHQ4BDeIj/BR4JxDABY8BvI6OOYgaEHwZADHgQ6BZA42GAIusPJNW64eFqzJDlcrERA8BHQI2FqwaBDYYGBPI45GCoIgCLoVWQ5NWXA2rKhaiGLAwOGEAmADxJPDVA51ElQaMC4ouEWALdEHRg8Dc4woCDJo8EAIYxCHQQIFHiwaRegJ5EcYWsHgbrKbBA8GDSrNDO4wfRKgR3FDSh3CN4UrdwZbSHYZ5DHajMFHYQGCHalWO4jtQDQwABwAGCAAQfTKoK0EHahwCeARdFHakASIZWVZ4Q8CO4YgWO4QbCO6hWGEIKYZKzZ3DLog7UG4I6C1lWDSdWO4bpCO4bwUwKYEHajMDwOAlUkLojTUd4gaTZoRWC0YIB1eJLqo4EWiqRE0mjlcr1QkEeKFWOooBCHiB2CC4WA5wzB52rEQgfPHQwABAYJXOHQ2iO4XO6omFEJh1BEAgBGPJlWDIQbC0ej50qgHV1XPEwohKcwRbEvJ3EBQTrLFomkOwOjlR3C5w8GMAR8ClYuBLIgOCvN4HgIZFDQYbBlaOBR4YNCwA5B0XOpzvBHgWqTw4AFxB1EvQ6BAAI8GDZILEdgQBCqp3DPIRfIEQwABvJ1CvGkvGiwA6IAYoBCv6wCAAVOlQ6DAIWkL5ABEwN40Z1CAYJfCv7zEAJNWOYZ3KAIWq5yYHFYLOBLIrVCAIh7BOIzpECoYDDpw7BHAQDG1WqwGkAIN/CwIABLY4LDAAZ9BwAABvLCBC5IBBvOrO44BEAAmjAIPN0XOAJyHIAAgPEquBHBi4BAId+HwWiHxqJDRpYBDq2I1R3LIAQ6BAAOpPogABGgIDDOomk0nP5pIGd42Aq1ewI8CeZI6CHAJhCEAIDCdIo2B0er1esAQIZBC4Z9JlVW1leeKGp0es5+s6+s6ABB0oFBAIervWr0ultr7OqtWmdexJ4BGxB5G0V6pF6wItB0t6p9PvQABvINBttJttPzwXCHQwBDlY6BO4WIwPPPJbvDvA0BFgNtAAIDGtwGCzrtHdYh1DAIOBrzxBPIgAIeIXNHgoBCGwYADzoVB0fNOpMOHQdW5+Bro7BHgQAB6jxJAAOjOYhxCAIukOoPN5ujdZFWqyyD0d6AwUrquBwAuB1I1FHgRJBMoQ9BWg1tzw0BDYI6B0R3DAAJ1BvMOp8rAAV4IQWBIodewAeCHAZ5IAAJoBAAXHHAJWDO4TtEdYQvEHgejAwIKClcqIQRdDXYbzFeoQBIGwIDDOot/VgQ6FAAIGBlgBCAAMzmZPBF4LzDACB1FAAOi1WjvFVr0zGYQ7GAAMAAYpPBwNeAIOIwOrfYOA1eA1WkAIWjAIekv4PBwCVBruBq5eBEYIABlcBF4wCEHw8zgAAiFYivEPgoSEAYo9jGgY4EO5Q7kVwiyFGggBFhASBHkhsKAAcqqtOAgMzd8o6HO495vF5QgMzrw7lhBoBvMqG4g")); const locale = require("locale"); @@ -37,7 +37,7 @@ function draw() { } if (newDate !== date) { - g.setFontVector(12); + g.setFont('6x8', 2); g.setColor(black); g.drawString(date, 120, 228); g.setColor(0xFFFF); @@ -51,6 +51,8 @@ function drawAll() { minute = ''; date = ''; g.drawImage(bob, 0, 0, { scale: 4 }); + Bangle.loadWidgets(); + Bangle.drawWidgets(); draw(); } @@ -60,9 +62,7 @@ Bangle.on('lcdPower', function(on) { } }); -Bangle.loadWidgets(); -Bangle.drawWidgets(); setInterval(draw, 1000); drawAll(); -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: 'falling' }); From bc4a05e314c1efd71d66a44788ee04ac81bb9cc8 Mon Sep 17 00:00:00 2001 From: singintime Date: Tue, 21 Apr 2020 10:43:54 +0200 Subject: [PATCH 28/77] Addressing review comments --- apps/minionclk/app.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/minionclk/app.js b/apps/minionclk/app.js index 7f00cd362..0f92b28bc 100755 --- a/apps/minionclk/app.js +++ b/apps/minionclk/app.js @@ -9,6 +9,8 @@ let hour; let minute; let date; +let timer; + function draw() { const d = new Date(); @@ -51,7 +53,6 @@ function drawAll() { minute = ''; date = ''; g.drawImage(bob, 0, 0, { scale: 4 }); - Bangle.loadWidgets(); Bangle.drawWidgets(); draw(); } @@ -59,10 +60,13 @@ function drawAll() { Bangle.on('lcdPower', function(on) { if (on) { drawAll(); + timer = setInterval(draw, 1000); + } else if (timer) { + clearInterval(timer); } }); -setInterval(draw, 1000); +Bangle.loadWidgets(); drawAll(); setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: 'falling' }); From a8cf48c794706420404136190fbdfede3e6080b4 Mon Sep 17 00:00:00 2001 From: singintime Date: Tue, 21 Apr 2020 11:52:36 +0200 Subject: [PATCH 29/77] Addressing review comments 2 --- apps/minionclk/app.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/minionclk/app.js b/apps/minionclk/app.js index 0f92b28bc..0725f8fa6 100755 --- a/apps/minionclk/app.js +++ b/apps/minionclk/app.js @@ -48,25 +48,30 @@ function draw() { } } -function drawAll() { +function startDrawing() { hour = ''; minute = ''; date = ''; g.drawImage(bob, 0, 0, { scale: 4 }); Bangle.drawWidgets(); draw(); + setInterval(draw, 1000); +} + +function stopDrawing() { + if (timer) { + clearInterval(timer); + } } Bangle.on('lcdPower', function(on) { + stopDrawing(); if (on) { - drawAll(); - timer = setInterval(draw, 1000); - } else if (timer) { - clearInterval(timer); + startDrawing(); } }); Bangle.loadWidgets(); -drawAll(); +startDrawing(); setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: 'falling' }); From 7735a2ba97d6156c79450869a7f716d52cd9cffb Mon Sep 17 00:00:00 2001 From: fredericrous Date: Tue, 21 Apr 2020 11:18:29 +0100 Subject: [PATCH 30/77] =?UTF-8?q?New=20game:=20Pong=F0=9F=95=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps.json | 14 +++ apps/pong/ChangeLog | 1 + apps/pong/app-icon.js | 1 + apps/pong/app.js | 282 ++++++++++++++++++++++++++++++++++++++++++ apps/pong/pong.png | Bin 0 -> 894 bytes 5 files changed, 298 insertions(+) create mode 100644 apps/pong/ChangeLog create mode 100644 apps/pong/app-icon.js create mode 100644 apps/pong/app.js create mode 100644 apps/pong/pong.png diff --git a/apps.json b/apps.json index 95669f250..9b381e6f4 100644 --- a/apps.json +++ b/apps.json @@ -1424,5 +1424,19 @@ {"name":"osmpoi.app.js"}, {"name":"osmpoi.img"} ] + }, + { "id": "pong", + "name": "Pong", + "shortName": "Pong", + "icon": "pong.png", + "version": "0.01", + "description": "A clone of the Atari game Pong", + "tags": "game", + "type": "app", + "allow_emulator": true, + "storage": [ + {"name":"pong.app.js","url":"app.js"}, + {"name":"pong.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/pong/ChangeLog b/apps/pong/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/pong/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/pong/app-icon.js b/apps/pong/app-icon.js new file mode 100644 index 000000000..881e60ba9 --- /dev/null +++ b/apps/pong/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIEBgOABQYFD8AUEApoXFDqIXV4BYGKZIANsIRE+IFE/IFEvCIFGrgXLDqIAOgc/9/2hv+g8///3AoUwvE3xuABYP4m3NzwFB7E2tu/CIMYm09wYFDjoFCj4pB/8HkEP+EBFII7EAosDJxYA=")) diff --git a/apps/pong/app.js b/apps/pong/app.js new file mode 100644 index 000000000..4531b3af8 --- /dev/null +++ b/apps/pong/app.js @@ -0,0 +1,282 @@ +/** + * BangleJS Pong game + * + * Original Author: Frederic Rousseau https://github.com/fredericrous + * Created: April 2020 + * + * Inspired by: + * - Let's make pong, One Man Army Studios, Youtube + * - Pong.js, KanoComputing, Github + * - Coding Challenge #67: Pong!, The Coding Train, Youtube + */ + +const SCREEN_WIDTH = 240; +const FPS = 16; +const MAX_SCORE = 11; +let scores = [0, 0]; +let aiSpeedRandom = 0; + +function Vector(x, y) { + this.x = x; + this.y = y; +} +Vector.prototype.add = function (x) { + this.x += x.x || 0; + this.y += x.y || 0; + return this; +}; + +const constrain = (n, low, high) => Math.max(Math.min(n, high), low); +const random = (min, max) => Math.random() * (max - min) + min; +const intersects = (circ, rect) => { + var c1 = circ.pos, c2 = {x: circ.pos.x+circ.r, y: circ.pos.y+circ.r}; + var r1 = rect.pos, r2 = {x: rect.pos.x+rect.width*2, y: rect.pos.y+rect.height}; + return !(c1.x > r2.x || c2.x < r1.x || + c1.y > r2.y || c2.y < r1.y); +}; + +///////////////////////////// Ball ////////////////////////////////////////// + +function Ball() { + this.r = 4; + this.prevPos = null; + this.originalSpeed = 4; + this.maxSpeed = 6; + + this.reset(); +} +Ball.prototype.show = function () { + if (this.prevPos != null) { + g.setColor(0); + g.fillCircle(this.prevPos.x, this.prevPos.y, this.prevPos.r); + } + g.setColor(-1); + g.fillCircle(this.pos.x, this.pos.y, this.r); + this.prevPos = { + x: this.pos.x, + y: this.pos.y, + r: this.r + }; +}; +Ball.prototype.bouncePlayer = function (multiplyX, multiplyY, player) { + this.speed = constrain(this.speed + 2, this.originalSpeed, this.maxSpeed); + var relativeIntersectY = (player.pos.y+(player.height/2)) - this.pos.y; + var normalizedRelativeIntersectionY = (relativeIntersectY/(player.height/2)); + var MAX_BOUNCE_ANGLE = 4 * Math.PI/12; + var bounceAngle = normalizedRelativeIntersectionY * MAX_BOUNCE_ANGLE; + this.velocity.x = this.speed * Math.cos(bounceAngle) * multiplyX; + this.velocity.y = this.speed * -Math.sin(bounceAngle) * multiplyY; +}; +Ball.prototype.bounce = function (multiplyX, multiplyY, player) { + if (player) + return this.bouncePlayer(multiplyX, multiplyY, player); + + if (multiplyX) { + this.velocity.x = Math.abs(this.velocity.x) * multiplyX; + } + if (multiplyY) { + this.velocity.y = Math.abs(this.velocity.y) * multiplyY; + } +}; +Ball.prototype.checkWallsCollision = function () { + if (this.pos.y < 0) { + this.bounce(0, 1); + } else if (this.pos.y > SCREEN_WIDTH) { + this.bounce(0, -1); + } else if (this.pos.x < 0) { + scores[1]++; + if (scores[1] >= MAX_SCORE) { + this.restart(); + state = 3; + winnerMessage = "AI Wins!"; + } else { + this.reset(); + } + } else if (this.pos.x > SCREEN_WIDTH) { + scores[0]++; + if (scores[0] >= MAX_SCORE) { + this.restart(); + state = 3; + winnerMessage = "You Win!"; + } else { + this.reset(); + } + } else { + return false; + } + return true; +}; +Ball.prototype.checkPlayerCollision = function (player) { + if (intersects(this, player)) { + if (this.pos.x < SCREEN_WIDTH/2) { + this.bounce(1, 1, player); + this.pos.add(new Vector(this.width, 0)); + aiSpeedRandom = random(-1.6, 1.6); + } else { + this.bounce(-1, 1, player); + this.pos.add(new Vector(-(this.width / 2 + 1), 0)); + } + return true; + } + return false; +}; +Ball.prototype.checkCollisions = function () { + return this.checkWallsCollision() || this.checkPlayerCollision(player) || this.checkPlayerCollision(ai); +}; +Ball.prototype.updatePosition = function () { + var elapsed = new Date().getTime() - this.lastUpdate; + var x = (elapsed / 50) * this.velocity.x; + var y = (elapsed / 50) * this.velocity.y; + this.pos.add(new Vector(x, y)); +}; +Ball.prototype.update = function () { + this.updatePosition(); + this.lastUpdate = new Date().getTime(); + this.checkCollisions(); +}; +Ball.prototype.reset = function() { + this.speed = this.originalSpeed; + var x = scores[0] < scores[1] || (scores[0] === 0 && scores[1] === 0) ? -this.speed : this.speed; + var bounceAngle = Math.PI/6; + this.velocity = new Vector(x * Math.cos(bounceAngle), this.speed * -Math.sin(bounceAngle)); + this.pos = new Vector(SCREEN_WIDTH/2, random(0, SCREEN_WIDTH)); +}; +Ball.prototype.restart = function() { + ai.pos = new Vector(SCREEN_WIDTH - ai.width*2, SCREEN_WIDTH/2 - ai.height/2); + player.pos = new Vector(player.width*2, SCREEN_WIDTH/2 - player.height/2); + this.pos = new Vector(SCREEN_WIDTH/2, SCREEN_WIDTH/2); +}; + +//////////////////////////// Player ///////////////////////////////////////// + +function Player() { + this.width = 4; + this.height = 30; + this.pos = new Vector(this.width*2, SCREEN_WIDTH/2 - this.height/2); + this.acc = new Vector(0, 0); + this.speed = 15; + this.maxSpeed = 25; + this.prevPos = null; +} +Player.prototype.show = function () { + if (this.prevPos != null) { + g.setColor(0); + g.fillRect(this.prevPos.x1, this.prevPos.y1, this.prevPos.x2, this.prevPos.y2); + } + g.setColor(-1); + g.fillRect(this.pos.x, this.pos.y, this.pos.x+this.width, this.pos.y+this.height); + this.prevPos = { + x1: this.pos.x, + y1: this.pos.y, + x2: this.pos.x+this.width, + y2: this.pos.y+this.height + }; +}; +Player.prototype.up = function () { + this.acc.y -= this.speed; +}; +Player.prototype.down = function () { + this.acc.y += this.speed; +}; +Player.prototype.stop = function () { + this.acc.y = 0; +}; +Player.prototype.update = function () { + this.acc.y = constrain(this.acc.y, -this.maxSpeed, this.maxSpeed); + this.pos.add(this.acc); + this.pos.y = constrain(this.pos.y, 0, SCREEN_WIDTH-this.height); +}; + +////////////////////////////// AI /////////////////////////////////////////// + +function AI() { + Player.call(this); + this.pos = new Vector(SCREEN_WIDTH-this.width*2, SCREEN_WIDTH/2 - this.height/2); +} +AI.prototype = Object.create(Player.prototype); +AI.prototype.constructor = Player; +AI.prototype.update = function () { + var y = ball.pos.y - (this.height/2 * aiSpeedRandom); + var yConstrained = constrain(y, 0, SCREEN_WIDTH-this.height); + this.pos = new Vector(this.pos.x, yConstrained); +}; + +function net() { + var dashSize = 5; + for (let y = dashSize/2; y < SCREEN_WIDTH; y += dashSize*2) { + g.setColor(-1); + let halfScreen = SCREEN_WIDTH/2; + g.fillRect(halfScreen-dashSize/2, y, halfScreen+dashSize/2, y+dashSize); + } +} + +var player = new Player(); +var ai = new AI(); +var ball = new Ball(); +var state = 0; +var prevScores = [0, 0]; + +function drawScores() { + let x1 = SCREEN_WIDTH/4-5; + let x2 = SCREEN_WIDTH*3/4-5; + + g.setColor(0); + g.setFont('Vector', 20); + g.drawString(prevScores[0], x1, 7); + g.drawString(prevScores[1], x2, 7); + g.setColor(-1); + g.setFont('Vector', 20); + g.drawString(scores[0], x1, 7); + g.drawString(scores[1], x2, 7); + prevScores = scores.slice(); +} + +function drawGameOver() { + g.setFont("Vector", 20); + g.drawString(winnerMessage, 75, SCREEN_WIDTH/2 - 10); +} + +function draw() { + if (state === 1) { + ball.update(); + player.update(); + ai.update(); + ball.show(); + player.show(); + ai.show(); + net(); + ball.show(); + } else if (state === 3) { + g.clear(); + g.setColor(0); + g.fillRect(0,0,240,240); + state++; + } else if (state === 4) { + drawGameOver(); + } else { + player.show(); + ai.show(); + net(); + } + drawScores(); +} + +g.clear(); +g.setColor(0); +g.fillRect(0,0,240,240); + +setInterval(draw, 1000 / FPS); + +setWatch(o => o.state ? player.up() : player.stop(), BTN1, {repeat: true, edge: 'both'}); +setWatch(o => o.state ? player.down() : player.stop(), BTN3, {repeat: true, edge: 'both'}); +//setWatch(o => o.state ? player.down() : player.stop(), BTN5, {repeat: true, edge: 'both'}); +setWatch(o => { + state++; + if (state >= 2) { + ball.restart(); + g.setColor(0); + g.fillRect(0,0,240,240); + scores = [0, 0]; + state = 1; + } +}, BTN2, {repeat: true}); diff --git a/apps/pong/pong.png b/apps/pong/pong.png new file mode 100644 index 0000000000000000000000000000000000000000..cc97f58f7826efaf0e2fafa1b7322a4d17d86f2c GIT binary patch literal 894 zcmV-^1A+XBP)fQkj&A4+ z8^a&FIPdd5`=9@LKc4dekPw)j2~5u*kvfUS5ju7aCH~Xa(S0~!hr{V`I8pjKq9KH! znX*PhOQWF$i4+<`YPCwORw0qfyG4B(iOThBSCQ!C@wPuAgMA0;}Q^Gn(3nfI?o>1%Xt0A&)LYqt!7?yz6xjKWMe}S#5neaHCKt872;E z#Khzj7th(EcDr2*!9@VT-|cOJIRCcy9gMG1^eROoF?1NlyZQ zrf1JvxtK<)(`a>h;tdpdVLXLIg^9C%zyJI45)!pS1Yu!B^MH0yMk3KcW+<0c@t9*$ zI02g^DI*AJdbi89^M0dL3V%p&xtt^^0|3x8#g7XH_oLC!0zXtF-^WQ(_B$3!2w^l? zYU}C+yAp|nQmGpF@Nqp9PB|A0lB8@s6c+r|*41;#Z5`cE4K{bSJwZstIR2)`8jVD_ zJQ0RHe)JFkfMG=dfYujne^{35JtL7kxPK2Gi^cfFl>g?9@)TPHAuTH{ne+uVH-FO9 zp3z!f+V>`ttV7XAq`9eqYbup0Xb3Xqal`3@7)=)LI2L18R#w+TVTD|tK26?nFJCqz zNkbL4Dn!^zI1C~TlSm}lt9ZvgVHjpKTSiBQ?e_lk1fA~grOQ{iX29>`Uml;Nq2jZW z;;Kr1Unso6vT-Og zb*`**@!Jy1vPDH$N@BC2!Dj7+$DLiB2k2ybFT-)1zxhR2>M0?bJJoKFr>wLj6yD&+ zX`0Hi3S?_&U?8if3!0`Ba=FoL;fji0U!&L8@N>jsJcFUNwIBAup@82fm=W;%Oy;M8 zT`rds$MLz@Jx|j#O^uEW&&|$2S;0Sk_Ks(|wA>+37<0?7t*z;=v-vw<`2_&rA3^G( Uj#*TE-v9sr07*qoM6N<$g3p|vv;Y7A literal 0 HcmV?d00001 From 6f00f0ee0b25d504a69be770ed70d3af0bb7d830 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 21 Apr 2020 11:35:32 +0100 Subject: [PATCH 31/77] minor tweaks --- apps/minionclk/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/minionclk/app.js b/apps/minionclk/app.js index 0725f8fa6..3453f49e1 100755 --- a/apps/minionclk/app.js +++ b/apps/minionclk/app.js @@ -1,5 +1,3 @@ -const bob = require("heatshrink").decompress(atob("nk8hAaXlYLWAEsqvN/0gBBql5lQ2tquj1XV5wBJ52j0hACPsdP1QsBAQQAGBIIBF51/P8OkN5R1GIxF5HLmAFgoDLPZfOpzmZ6vPFwomCPaA6DAYOjeq2A1YyCdI4HGQJQ8F1T2SJ4Oq1XW1es1mtAQOrPoPUAIh3J54ZHIAR5S62s64cBwIBGQIOqHQK4HKQYVDAAIFC1g+BHh9VHAQAFDwQDDHoJ5E54BB6AaBKQ5YGqo6MwJzGHQ4BDeIj/BR4JxDABY8BvI6OOYgaEHwZADHgQ6BZA42GAIusPJNW64eFqzJDlcrERA8BHQI2FqwaBDYYGBPI45GCoIgCLoVWQ5NWXA2rKhaiGLAwOGEAmADxJPDVA51ElQaMC4ouEWALdEHRg8Dc4woCDJo8EAIYxCHQQIFHiwaRegJ5EcYWsHgbrKbBA8GDSrNDO4wfRKgR3FDSh3CN4UrdwZbSHYZ5DHajMFHYQGCHalWO4jtQDQwABwAGCAAQfTKoK0EHahwCeARdFHakASIZWVZ4Q8CO4YgWO4QbCO6hWGEIKYZKzZ3DLog7UG4I6C1lWDSdWO4bpCO4bwUwKYEHajMDwOAlUkLojTUd4gaTZoRWC0YIB1eJLqo4EWiqRE0mjlcr1QkEeKFWOooBCHiB2CC4WA5wzB52rEQgfPHQwABAYJXOHQ2iO4XO6omFEJh1BEAgBGPJlWDIQbC0ej50qgHV1XPEwohKcwRbEvJ3EBQTrLFomkOwOjlR3C5w8GMAR8ClYuBLIgOCvN4HgIZFDQYbBlaOBR4YNCwA5B0XOpzvBHgWqTw4AFxB1EvQ6BAAI8GDZILEdgQBCqp3DPIRfIEQwABvJ1CvGkvGiwA6IAYoBCv6wCAAVOlQ6DAIWkL5ABEwN40Z1CAYJfCv7zEAJNWOYZ3KAIWq5yYHFYLOBLIrVCAIh7BOIzpECoYDDpw7BHAQDG1WqwGkAIN/CwIABLY4LDAAZ9BwAABvLCBC5IBBvOrO44BEAAmjAIPN0XOAJyHIAAgPEquBHBi4BAId+HwWiHxqJDRpYBDq2I1R3LIAQ6BAAOpPogABGgIDDOomk0nP5pIGd42Aq1ewI8CeZI6CHAJhCEAIDCdIo2B0er1esAQIZBC4Z9JlVW1leeKGp0es5+s6+s6ABB0oFBAIervWr0ultr7OqtWmdexJ4BGxB5G0V6pF6wItB0t6p9PvQABvINBttJttPzwXCHQwBDlY6BO4WIwPPPJbvDvA0BFgNtAAIDGtwGCzrtHdYh1DAIOBrzxBPIgAIeIXNHgoBCGwYADzoVB0fNOpMOHQdW5+Bro7BHgQAB6jxJAAOjOYhxCAIukOoPN5ujdZFWqyyD0d6AwUrquBwAuB1I1FHgRJBMoQ9BWg1tzw0BDYI6B0R3DAAJ1BvMOp8rAAV4IQWBIodewAeCHAZ5IAAJoBAAXHHAJWDO4TtEdYQvEHgejAwIKClcqIQRdDXYbzFeoQBIGwIDDOot/VgQ6FAAIGBlgBCAAMzmZPBF4LzDACB1FAAOi1WjvFVr0zGYQ7GAAMAAYpPBwNeAIOIwOrfYOA1eA1WkAIWjAIekv4PBwCVBruBq5eBEYIABlcBF4wCEHw8zgAAiFYivEPgoSEAYo9jGgY4EO5Q7kVwiyFGggBFhASBHkhsKAAcqqtOAgMzd8o6HO495vF5QgMzrw7lhBoBvMqG4g")); - const locale = require("locale"); const black = 0x0000; @@ -52,15 +50,17 @@ function startDrawing() { hour = ''; minute = ''; date = ''; + var bob = require("heatshrink").decompress(atob("nk8hAaXlYLWAEsqvN/0gBBql5lQ2tquj1XV5wBJ52j0hACPsdP1QsBAQQAGBIIBF51/P8OkN5R1GIxF5HLmAFgoDLPZfOpzmZ6vPFwomCPaA6DAYOjeq2A1YyCdI4HGQJQ8F1T2SJ4Oq1XW1es1mtAQOrPoPUAIh3J54ZHIAR5S62s64cBwIBGQIOqHQK4HKQYVDAAIFC1g+BHh9VHAQAFDwQDDHoJ5E54BB6AaBKQ5YGqo6MwJzGHQ4BDeIj/BR4JxDABY8BvI6OOYgaEHwZADHgQ6BZA42GAIusPJNW64eFqzJDlcrERA8BHQI2FqwaBDYYGBPI45GCoIgCLoVWQ5NWXA2rKhaiGLAwOGEAmADxJPDVA51ElQaMC4ouEWALdEHRg8Dc4woCDJo8EAIYxCHQQIFHiwaRegJ5EcYWsHgbrKbBA8GDSrNDO4wfRKgR3FDSh3CN4UrdwZbSHYZ5DHajMFHYQGCHalWO4jtQDQwABwAGCAAQfTKoK0EHahwCeARdFHakASIZWVZ4Q8CO4YgWO4QbCO6hWGEIKYZKzZ3DLog7UG4I6C1lWDSdWO4bpCO4bwUwKYEHajMDwOAlUkLojTUd4gaTZoRWC0YIB1eJLqo4EWiqRE0mjlcr1QkEeKFWOooBCHiB2CC4WA5wzB52rEQgfPHQwABAYJXOHQ2iO4XO6omFEJh1BEAgBGPJlWDIQbC0ej50qgHV1XPEwohKcwRbEvJ3EBQTrLFomkOwOjlR3C5w8GMAR8ClYuBLIgOCvN4HgIZFDQYbBlaOBR4YNCwA5B0XOpzvBHgWqTw4AFxB1EvQ6BAAI8GDZILEdgQBCqp3DPIRfIEQwABvJ1CvGkvGiwA6IAYoBCv6wCAAVOlQ6DAIWkL5ABEwN40Z1CAYJfCv7zEAJNWOYZ3KAIWq5yYHFYLOBLIrVCAIh7BOIzpECoYDDpw7BHAQDG1WqwGkAIN/CwIABLY4LDAAZ9BwAABvLCBC5IBBvOrO44BEAAmjAIPN0XOAJyHIAAgPEquBHBi4BAId+HwWiHxqJDRpYBDq2I1R3LIAQ6BAAOpPogABGgIDDOomk0nP5pIGd42Aq1ewI8CeZI6CHAJhCEAIDCdIo2B0er1esAQIZBC4Z9JlVW1leeKGp0es5+s6+s6ABB0oFBAIervWr0ultr7OqtWmdexJ4BGxB5G0V6pF6wItB0t6p9PvQABvINBttJttPzwXCHQwBDlY6BO4WIwPPPJbvDvA0BFgNtAAIDGtwGCzrtHdYh1DAIOBrzxBPIgAIeIXNHgoBCGwYADzoVB0fNOpMOHQdW5+Bro7BHgQAB6jxJAAOjOYhxCAIukOoPN5ujdZFWqyyD0d6AwUrquBwAuB1I1FHgRJBMoQ9BWg1tzw0BDYI6B0R3DAAJ1BvMOp8rAAV4IQWBIodewAeCHAZ5IAAJoBAAXHHAJWDO4TtEdYQvEHgejAwIKClcqIQRdDXYbzFeoQBIGwIDDOot/VgQ6FAAIGBlgBCAAMzmZPBF4LzDACB1FAAOi1WjvFVr0zGYQ7GAAMAAYpPBwNeAIOIwOrfYOA1eA1WkAIWjAIekv4PBwCVBruBq5eBEYIABlcBF4wCEHw8zgAAiFYivEPgoSEAYo9jGgY4EO5Q7kVwiyFGggBFhASBHkhsKAAcqqtOAgMzd8o6HO495vF5QgMzrw7lhBoBvMqG4g")); g.drawImage(bob, 0, 0, { scale: 4 }); Bangle.drawWidgets(); draw(); - setInterval(draw, 1000); + timer = setInterval(draw, 1000); } function stopDrawing() { if (timer) { clearInterval(timer); + timer = undefined; } } From 4a53e768d60837f2554e0b1935529aadc16e8662 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:03:17 +0200 Subject: [PATCH 32/77] change img_nofix --- apps/osmpoi/osmpoi.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index 56a1f8eb6..e0275784e 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,7 +141,7 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwxH+AH4A0PgYurg9kr0rGM4nBg9dsgADmUHGUYtHAAddGIJcgFpIxEMTsAlYtMAAZiaLh4AFmQwXLiSTaLiosBnMymUrGCYTBAAgvPCgjwaMh4raF/4v/F/4vUg4vulZgDgAAIF8EyEQUAh0cAAkVisHGA4+HF6gVBiwwFjkONo0HAAMOAAIvTnIhEiovMFQQADNgYvQroUDg4uGjj9EF448DF6a+HAAS+EF5CQCF6SMIeAQvFXYYwHF59eLpSOBF4hgKGAIvPskAFxKOFF80VM4KOFSBs5F6EWRY4xBF43+F5UyF6DuEizZBKwIuHSBQvXdIwvKMYsHlYvQW4IuPYAYRBMggvRgIvCFxwwCTYZlEg4vPlcHjkVFx6WJF6YuXMoTwCF58yVgIvXY4YvQrqqDGDAvvPYIvPsguaYQYv/F7owBF/4vfg4AGTIIAHF7gA/AH4AwA=")); +var img_nofix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); var img_fix = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG2JnYv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwqTGh4uMFS40LEcIA/AH4A/ACQA=")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js From 2814e367c0dda1cb3787f1f151416372d16f5c65 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:09:03 +0200 Subject: [PATCH 33/77] Update ChangeLog --- apps/osmpoi/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/osmpoi/ChangeLog b/apps/osmpoi/ChangeLog index 5560f00bc..8e73a192e 100644 --- a/apps/osmpoi/ChangeLog +++ b/apps/osmpoi/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Change img when no fix From 25f2e3d99732017e64b86e3dfcca212d19f3684a Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:32:55 +0200 Subject: [PATCH 34/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index e0275784e..b4a954c24 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -142,7 +142,7 @@ document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; var img_nofix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); -var img_fix = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG2JnYv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwqTGh4uMFS40LEcIA/AH4A/ACQA=")); +var img_fix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js function project(latlong) { From c23c11eb51b9411772a52e048761c779a89bbdb9 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:50:44 +0200 Subject: [PATCH 35/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index b4a954c24..fa22bead5 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,8 +141,8 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); -var img_fix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); +var img_nofix = require("heatshrink").decompress(atob("mEwxH+h8dj3+AB8eCYsejkYhEVAAMIjEcBwQTBh4bE/8ViUVCAgrIjMWifX68VjMHjETi8bHAMPCAIJChATBiMdEAsZxlH0nsD4IzDNYIrB6/WB4NGAIURicb///FgUcjhYBBAMHinsx0aF4sd61FowABGYOP68UiYrDo1FrwDB0nXjIkChETiURiMS60Tiw6CjMRhCAG64uCAAkao4qDAAIEBLoMH/8cinW0kZjOko4ACxgyBB4MdiccGAsWKYQAHF4tHiUd/8YiWOFAIwBjQCBAwICBxkSi//j0TYIrABFo44BF4aeB65NBjHXLAYACMQIWBo8aGIPWixhCcQLAEF5tex0YVoIuDjSgBGAYDD0gbB6xhBjbCEh7AIF4tGiUPjsRW4SIEfIIGDHIIFCiT1BiqREi0aGBDwCruPjX/imOxhTCX4YvBBIIzDBITDBI4MWF4caxovIrwwC68PjiNBFoaRCAQQIDAgiRBJALBEg+PBgQwFdYNe0jYBhGPcoJQBQYLpCMYQABF4aQCx8Ta4MaF4UYZoIZEGYZeBRwLQBP4WkEYIwBAoQJBGQg0D60Rj0deIUPihcGGoQ5C60cj3WWIKiBSIeMAYOkxwDBAQTJDiTuBh8VF4Me64tGLYIhBrtd9hEBx5uFX4ZCCAYR8EVAMaYAIvCg+OF5NGrpfBj0cx1FFwooCCoKsDXgQvCjMHjIvDi4RCdgteo9er1FF4Md6xUCXoQjBSYUZxhkBY4QMBJAMdjZfDXwJYCLwgGCAQKPBjsd69HxrhEdAQCDd4gwBiUPjEcX4UeiZXBAAlFRwQDBr2OjRBBL4SCDAAh9BY4T7DFQMVPQMWXxKnCr5hC0kI/8WxotBQoLuDF4YDCS4VHx0YI4P/UgK+BjRZCF4yOBeYUTh8bSAMaWoQnCFwQJESoS+BFgK+Bjv+izuCr7BFX4YAB60bh8Tx2NXAsZowGCAYLOBx2k68cicej0Vh/+jONLASjCGoRiDEgUT/8HMAIqBQgTEDXYOMxg7Dx0SLwMIg/+/0d6wmCeQIsCPAJkFx4YBi+PL4QkBAQONxmOLQIzCJAPsiv/jpeC/x8BK4YAEBA2Pi3/h8I62M64oBxmNRIJjCYIUZFwMPjyQBFwIABhDwBFwxfFxwZB/4wCiTDBXYaVBLQJqCiUWh8PiiNCAAUaxqNBGIYFBDIONx0ZFwgACjUT9iLBxsaXYJcBxvW68a/5dBjAuEYAgqBGQNFoukiMVKwMRFwkZEAMPjUV6/Wx/WAAUVjITBjcTx8IF4rABF4QtBAgMZiIkBIwUIFwfXV4McBgUcjQ4BjkeBALpBKgXXdoTAEjK3EFwMbLIceiUIh4uBXAOk60UjAqBNgQ0BjEU60aVwXWjovFjWOFxRhDiZMCfYTNB9gzBBgXsxwMBrqBBr2NjIvFjePo4QBFxBhDxgrBAAR1EHAbZBb4IGCxzwGi+kBYLqBFxAABjBfCFIY0EFAVfBQYGB9iPFh8UIAJdKF4fsEoZdGM47vCjwvEj3Xr0aFxkdiMZF5FGRIIAHo8VXw2No4uOf4QvHXAgAEoukXw+PFzIvFr1eeILyBXw3+iYuRLxIvDSQy+GjguSF44pCo9fFwy+GEAMHFxmlPYJUBr4vFBQLsIXxEIjJdNFgIlCjQvBGoRYDrzJI6y+FicdFxUSxgrB0mO68ThEVienGYS+EMYVHCYcXh4vEisaFxXXxnWFYMajoZCj0cjEU6+OGYIABFYgTEdwxgHFwMSFYoAHGYcSFZYAEjYwGFwMZC5gzGCaIwFFwQtRACowBjZ6BF1LDCisTikbFcwA==")); +var img_fix = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG1Omwv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwpEprTPGhouLFTA0LEcIA/AH4A/ACQA=")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js function project(latlong) { From f938dc3de0933f3b81f9f25a7fff50e9ae57ac5f Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:59:52 +0200 Subject: [PATCH 36/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index fa22bead5..e0275784e 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,8 +141,8 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwxH+h8dj3+AB8eCYsejkYhEVAAMIjEcBwQTBh4bE/8ViUVCAgrIjMWifX68VjMHjETi8bHAMPCAIJChATBiMdEAsZxlH0nsD4IzDNYIrB6/WB4NGAIURicb///FgUcjhYBBAMHinsx0aF4sd61FowABGYOP68UiYrDo1FrwDB0nXjIkChETiURiMS60Tiw6CjMRhCAG64uCAAkao4qDAAIEBLoMH/8cinW0kZjOko4ACxgyBB4MdiccGAsWKYQAHF4tHiUd/8YiWOFAIwBjQCBAwICBxkSi//j0TYIrABFo44BF4aeB65NBjHXLAYACMQIWBo8aGIPWixhCcQLAEF5tex0YVoIuDjSgBGAYDD0gbB6xhBjbCEh7AIF4tGiUPjsRW4SIEfIIGDHIIFCiT1BiqREi0aGBDwCruPjX/imOxhTCX4YvBBIIzDBITDBI4MWF4caxovIrwwC68PjiNBFoaRCAQQIDAgiRBJALBEg+PBgQwFdYNe0jYBhGPcoJQBQYLpCMYQABF4aQCx8Ta4MaF4UYZoIZEGYZeBRwLQBP4WkEYIwBAoQJBGQg0D60Rj0deIUPihcGGoQ5C60cj3WWIKiBSIeMAYOkxwDBAQTJDiTuBh8VF4Me64tGLYIhBrtd9hEBx5uFX4ZCCAYR8EVAMaYAIvCg+OF5NGrpfBj0cx1FFwooCCoKsDXgQvCjMHjIvDi4RCdgteo9er1FF4Md6xUCXoQjBSYUZxhkBY4QMBJAMdjZfDXwJYCLwgGCAQKPBjsd69HxrhEdAQCDd4gwBiUPjEcX4UeiZXBAAlFRwQDBr2OjRBBL4SCDAAh9BY4T7DFQMVPQMWXxKnCr5hC0kI/8WxotBQoLuDF4YDCS4VHx0YI4P/UgK+BjRZCF4yOBeYUTh8bSAMaWoQnCFwQJESoS+BFgK+Bjv+izuCr7BFX4YAB60bh8Tx2NXAsZowGCAYLOBx2k68cicej0Vh/+jONLASjCGoRiDEgUT/8HMAIqBQgTEDXYOMxg7Dx0SLwMIg/+/0d6wmCeQIsCPAJkFx4YBi+PL4QkBAQONxmOLQIzCJAPsiv/jpeC/x8BK4YAEBA2Pi3/h8I62M64oBxmNRIJjCYIUZFwMPjyQBFwIABhDwBFwxfFxwZB/4wCiTDBXYaVBLQJqCiUWh8PiiNCAAUaxqNBGIYFBDIONx0ZFwgACjUT9iLBxsaXYJcBxvW68a/5dBjAuEYAgqBGQNFoukiMVKwMRFwkZEAMPjUV6/Wx/WAAUVjITBjcTx8IF4rABF4QtBAgMZiIkBIwUIFwfXV4McBgUcjQ4BjkeBALpBKgXXdoTAEjK3EFwMbLIceiUIh4uBXAOk60UjAqBNgQ0BjEU60aVwXWjovFjWOFxRhDiZMCfYTNB9gzBBgXsxwMBrqBBr2NjIvFjePo4QBFxBhDxgrBAAR1EHAbZBb4IGCxzwGi+kBYLqBFxAABjBfCFIY0EFAVfBQYGB9iPFh8UIAJdKF4fsEoZdGM47vCjwvEj3Xr0aFxkdiMZF5FGRIIAHo8VXw2No4uOf4QvHXAgAEoukXw+PFzIvFr1eeILyBXw3+iYuRLxIvDSQy+GjguSF44pCo9fFwy+GEAMHFxmlPYJUBr4vFBQLsIXxEIjJdNFgIlCjQvBGoRYDrzJI6y+FicdFxUSxgrB0mO68ThEVienGYS+EMYVHCYcXh4vEisaFxXXxnWFYMajoZCj0cjEU6+OGYIABFYgTEdwxgHFwMSFYoAHGYcSFZYAEjYwGFwMZC5gzGCaIwFFwQtRACowBjZ6BF1LDCisTikbFcwA==")); -var img_fix = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG1Omwv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwpEprTPGhouLFTA0LEcIA/AH4A/ACQA=")); +var img_nofix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); +var img_fix = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG2JnYv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwqTGh4uMFS40LEcIA/AH4A/ACQA=")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js function project(latlong) { From 9a64b8aa35a4108b1745c812dac119b0943290f8 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 15:17:57 +0200 Subject: [PATCH 37/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index e0275784e..3b1fc5ba8 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,8 +141,8 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwxH+6+s6/+AB4TB1gGFq1WlYABAgOBEQQnH68rlQRBD4orGwIkDleBAwQoBEgIABCAY4CgAjGwNbw1bmJFCDYIrGB4OwAIUAGIIrDCIICBA4WBlcxquBF4uslex2AABGYgrE2GxB4WAFoY8ClS0BPwJLCBgUAqyAGlYuCAAmGxgqDF4ZdBEIJSBHoWGwACBAANbTwRqBAYIwFqxTCAAmMF4+GlSDBq0qqotEGYQxDlVWGATBFYAJgIFYIvEJoSKBE4gADxgFESgIwC67AFF51VDQKMBFxAAErg0BGATQBYBy7D2OrlRJBgCGFLgVcGZEqOoKRFYBOGF4WymIXCqovCAQmwrYDBxgJGI4RgEYBQvBGAKlBUILnHdQaPEYQhgGwMxBgQuDRQIvCwCnBqwQCEwY/BFQeAFgQvEmJJBwOBR4dcLIQAD2J6BF4KODEAQhBwA0CSwoMBBAIxClcASAgeCRo2rDIICBOQKOBWoTLBFYYDBrdVG4NVFgK/EDQIrBF4IeCAApbBEgOydwIvBmJuFAAYJBFwIVBAAeMrlWRoIvDwNVF5AeB62xUgVVBAIsGPIRpBHoovBFwIvEXwYvHd4SPDb4ThEAob4DZoQvBDAIvEXwQkBFwpIBAQKPDCILeBwGAEYQnCdQIGDGAcq69WX4YdBKgQAE2GM1YDB2NVIgS0CABFcXwZnDFQJ6Cqy+HMQZeCGoLWBI4KDDAA46EF4VVC4LaCwK+BwBaDAAi+DAgIVCMAJeJAooGBXwusF4JMBQwLAFA4srCwVVCgK4DAQOwrYDErgQBFQJIBAQSPBra3BGIL/CF4ICBA4QoBMAhXCYg2AFwI0CR4MqI4NWRwLvDLQQAB1erD4IuBM4cxDAUxLYKDCFIdVNYT0DmJeF/x8BRgoABdwQAEmLZBGAMrQAIoBLIoAEFwi9BAATwDE4gwBAwlVDIIACq0qFwYRBLQZqClRDCbAIuDYARbCMAgZCqqnBFwgABYYMxBoIwBMAZqBFQJdCqwuEYAQsCFwexrcACYMqgAtFEAIxCAAKGBAAYMEUwIvFM4OMFoY0Bw0AC4RGCLgokD1msG4OBAgIVDler2LtDYAi3FFwgACVQQuBCQOAEQNWFYJrEfgMrwBSCdwrACqouLa4QAB2DKBCIVbRosxagOx2SuDd4ovBmLSBFxRhCrYuBAASmBAAQ4DVoeG1eGqrAGq1cCQLqBFxPXP4ImBOIYADAoOMFoIrBBAWwmKPFP4LKBLpYvCmIlBaQheDNA4ABd4z7B2OAFxmsgBVCF4xbBFo4SBla+GrZdNFwL/BWoYvHAwruCXw8xFyBeIFAIKDFoYABXw3+lYuRF44lCBQIEDXxWBFyQvJFwa+MEAIuNqx7EF4oqC2OrFwy+HqxdOFoewwAvBGwjuHAAWMla+FAwIuKlVb2OMwFVlcrqwCBqozCMAeML4WGrgTDXwsrL5IuBldbC4WBIIKmCwIzFAAI/ECYi/GMA4uBlQXKDQYzCIQITNAAOBGAwuBNIIXLGYwTRGAouCFqIAVGAJyBwIupGATRBewIrmA==")); -var img_fix = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG2JnYv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwqTGh4uMFS40LEcIA/AH4A/ACQA=")); +var img_nofix = require("heatshrink").decompress(atob("mEwhHX1nX/wAPCYOsAwtWq0rAAIEBwIiCE4/XlcqCIIfFFY2BEgcrwIGCFAIkBAAIQDHAUAEY2BreGrcxIoQbBFYwPB2ABCgAxBFYYRBAQIHCwMrmNVwIvF1kr2OwAAIzEFYmw2IPCwAtDHgUqWYJ+BJYQMCgFWQA0rFwQAEw2MFQYvDLoIhBKQI9Cw2AAQIABraeCNQIDBGAtWKYQAExgvHw0qQYNWlVVFogzCGIcqqwwCYIrABMBArBF4hNCRQInEAAeMAoiUBGAXXYAovOqoaBRgIuIAAlcGgIwCaALAOXYex1cqJIMAQwpcCrgzIlR1BSIrAJwwvC2UxC4VVF4QCE2FbAYOMBIxHCMAjAKF4IwBUoKhBc47qDR4jCEMA2BmIMCFwaKBF4WAU4NWCAQmDH4IqDwAsCF4kxJIOBwKPDrhZCAAexPQIvBRwYgCEIOAGgSWFBgIIBGIUrgCQEDwSNG1YZBAQJyBRwK1CZYIrDAYNbqo3BqosBX4gaBFYIvBDwQAFLYIkB2TuBF4MxNwoADBIIuBCoIADxlcqyNBF4eBqovIDwPW2KkCqoIBFgx5CNII9FF4IuBF4i+DF47vCR4bfCcIgFDfAbNCF4IYBF4i+CEgIuFJAICBR4YRBbwOAwAjCE4TqBAwYwDlXXqy/DDoJUCAAmwxmrAYOxqpECWgQAIri+DM4YqBPQVWXw5iDLwQ1BawJHBQYYAHHQgvCqoXBbQWBXwOALQYAEXwYEBCoRgBLxIFFAwK+F1gvBJgKGBYAoHFlYWCqoUBXAYCB2FbAYlcCAIqBJAICCR4NbW4IxBf4QvBAQIHCFAJgEK4TEGwAuBGgSPBlRHBqyOBd4ZaCAAOr1YfBFwJnDmIYCmJbBQYQpDqprCegcxLwv+PgKMFAALuCAAkxbIIwBlaABFAJZFAAguEXoIACeAYnEGAIGEqoZBAAVWlQuDCIJaDNQUqIYTYBFwbACLYRgEDIVVU4IuEAALDBmINBGAJgDNQIqBLoVWFwjACFgQuD2NbgATBlUAFoogBGIQABQwIADBgimBF4pnBxgtDGgOGgAXCIwRcFEges1g3BwIEBCocr1exdobAEW4ouEAASqCFwISBwAiBqwrBNYj8BleAKQTuFYAVVFxbXCAAOwZQIRCraNFmLUB2OyVwbvFF4MxaQIuKMIVbFwIACUwIACHAatDw2rw1VYA1WrgSBdQIuJ65/BEwJxDAAYFBxgtBFYIIC2ExR4p/BZQJdLF4UxEoLSELwZoHAALvGfYOxwAuM1kAKoQvGLYItHCQMrXw1bLpouBf4K1DF44GFdwS+HmIuQLxAoBBQYtDAAK+G/0rFyIvHEoQKBAga+KwIuSF5IuDXxggBFxtWPYgvFFQWx1YuGXw9WLpwtD2GAF4I2Edw4ACxkrXwoGBFxUqrexxmAqsrldWAQNVGYRgDxhfCw1cCYa+FlZfJFwMrrYXCwJBBUwWBGYoABH4gTEX4xgHFwMqC5QaDGYRCBCZoABwIwGFwJpBC5YzGCaIwFFwQtRACowBOQOBF1IwCaIL2BFcw")); +var img_fix = require("heatshrink").decompress(atob("mEwhH+AH4A/AH4A/AGuJnYv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwqTGh4uMFS40LEcIA/AH4A/ACQA=")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js function project(latlong) { From b711e10d4f09293bb9a9e0bbe615777268cd1321 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 15:31:26 +0200 Subject: [PATCH 38/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index 3b1fc5ba8..58a182721 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,8 +141,8 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwhHX1nX/wAPCYOsAwtWq0rAAIEBwIiCE4/XlcqCIIfFFY2BEgcrwIGCFAIkBAAIQDHAUAEY2BreGrcxIoQbBFYwPB2ABCgAxBFYYRBAQIHCwMrmNVwIvF1kr2OwAAIzEFYmw2IPCwAtDHgUqWYJ+BJYQMCgFWQA0rFwQAEw2MFQYvDLoIhBKQI9Cw2AAQIABraeCNQIDBGAtWKYQAExgvHw0qQYNWlVVFogzCGIcqqwwCYIrABMBArBF4hNCRQInEAAeMAoiUBGAXXYAovOqoaBRgIuIAAlcGgIwCaALAOXYex1cqJIMAQwpcCrgzIlR1BSIrAJwwvC2UxC4VVF4QCE2FbAYOMBIxHCMAjAKF4IwBUoKhBc47qDR4jCEMA2BmIMCFwaKBF4WAU4NWCAQmDH4IqDwAsCF4kxJIOBwKPDrhZCAAexPQIvBRwYgCEIOAGgSWFBgIIBGIUrgCQEDwSNG1YZBAQJyBRwK1CZYIrDAYNbqo3BqosBX4gaBFYIvBDwQAFLYIkB2TuBF4MxNwoADBIIuBCoIADxlcqyNBF4eBqovIDwPW2KkCqoIBFgx5CNII9FF4IuBF4i+DF47vCR4bfCcIgFDfAbNCF4IYBF4i+CEgIuFJAICBR4YRBbwOAwAjCE4TqBAwYwDlXXqy/DDoJUCAAmwxmrAYOxqpECWgQAIri+DM4YqBPQVWXw5iDLwQ1BawJHBQYYAHHQgvCqoXBbQWBXwOALQYAEXwYEBCoRgBLxIFFAwK+F1gvBJgKGBYAoHFlYWCqoUBXAYCB2FbAYlcCAIqBJAICCR4NbW4IxBf4QvBAQIHCFAJgEK4TEGwAuBGgSPBlRHBqyOBd4ZaCAAOr1YfBFwJnDmIYCmJbBQYQpDqprCegcxLwv+PgKMFAALuCAAkxbIIwBlaABFAJZFAAguEXoIACeAYnEGAIGEqoZBAAVWlQuDCIJaDNQUqIYTYBFwbACLYRgEDIVVU4IuEAALDBmINBGAJgDNQIqBLoVWFwjACFgQuD2NbgATBlUAFoogBGIQABQwIADBgimBF4pnBxgtDGgOGgAXCIwRcFEges1g3BwIEBCocr1exdobAEW4ouEAASqCFwISBwAiBqwrBNYj8BleAKQTuFYAVVFxbXCAAOwZQIRCraNFmLUB2OyVwbvFF4MxaQIuKMIVbFwIACUwIACHAatDw2rw1VYA1WrgSBdQIuJ65/BEwJxDAAYFBxgtBFYIIC2ExR4p/BZQJdLF4UxEoLSELwZoHAALvGfYOxwAuM1kAKoQvGLYItHCQMrXw1bLpouBf4K1DF44GFdwS+HmIuQLxAoBBQYtDAAK+G/0rFyIvHEoQKBAga+KwIuSF5IuDXxggBFxtWPYgvFFQWx1YuGXw9WLpwtD2GAF4I2Edw4ACxkrXwoGBFxUqrexxmAqsrldWAQNVGYRgDxhfCw1cCYa+FlZfJFwMrrYXCwJBBUwWBGYoABH4gTEX4xgHFwMqC5QaDGYRCBCZoABwIwGFwJpBC5YzGCaIwFFwQtRACowBOQOBF1IwCaIL2BFcw")); -var img_fix = require("heatshrink").decompress(atob("mEwhH+AH4A/AH4A/AGuJnYv/FzovBGFgvuFwIvCGFQvuFwQvDGFAvuFwYvEGEwvuFwgvFGEgvuFwovGGEQvuFwwvHGEAvuFw4vIGDwvuFxAvJGDgvuFxIvKGDQvuFxQvLGDAvuFxYvMGCwvuFxgvNGCgvuFxovOGCQvuFxwvPGCAvuFx4vQGBwtOCQYvbFRwAJGCwqTGh4uMFS40LEcIA/AH4A/ACQA=")); +var img_nofix = require("heatshrink").decompress(atob("mEwhBC/AH4AS6+sq0AgMrBo8rgICB1mBgIABAoNWAAusDYOBwWBF5IPBldWwAhCGQQJBgOBwNWqsxmIoF64AC1g2ClcGmIvKgGAwGwrcxqtWwItBFYdbw2x2APBG4IqBKgI0CLQIIBDISCBABAlBmOxAAOww1bqtVrY5BBIPVBYMxlYkBKoIFBAAJHBAoI6BQQSwIAANWmJQBAAIyCxmx6xbCBANbFwIhCwuGAAZHCBQKZBSgQvIgNWQQYACDgIHD6tcFwKBBSwIADrgFEGIJiBqASBSBFWrYvGMAIIB2OGJwJdBrYMBwArEAAWAxgwBewQvJwNVF4uMM4IvCquA68rqoqHGgQ3DUIT8BeJNVRAhgCfAWGmPXwExRoIlB2AsB2FbSwSTBAIOwQYLCBSBWFFwgvErYZBXgS+FLgoDCSIRFBwIvLC4WMMoIACqusbIKACEoYCCeAYLDwEAwLBBX5ExXgmG1eGwoCBRwL+BEQVcEYKMCAQxKBqovBC4LvOLYLwC1aoCwqGEIAR1BL4QLEqtWF5RQBF4+M62GF4QnCAAoHBeQILFrmBR5VVKwIvFA4PVw1VR4eAAAIkDA4L3CTIILBwtW1mAL48r1kxc4YADF4KPBF4gpCF4TmCeoYECraOBR5C+DAAjyB1YDB2NV1gPBQQgxDBA8xq1QF5EBV4KOEVIQvBAANbVAMrQoQAKRwREBSAJhBX4y+CLgQACFwewVQJIBmKRD2C4BxlbAwKLBrlbRwQVC1gvGq2FLIWGxiKB1YCBJwUrwRgDeAmMAYQsBrYKBlbkBMIK/Ira2CFgIyBGoOrGoQcB6+BmOAKgIyBFQVbqr0CGwMGXoReHd4aLBRQbuCBAVbJYIcBlcxSYIADYAgRBwARBCQIvGGANV1fVFIiPBTAJeCFwIABwIwBQ4SPCCIJiBKIIuBqAuIF4NWSAKRDAAJIBAAQuDAAKuBmIKBrcxqoCBDwJvCgwuJSAYtEFwMAwOBqEBFgY1D1mBqxZBFgOBBIJsBMYKOJgEBJQJdFgBaDDAIDBUIJWBFAZoEGwMxwvWwC/BMBVWWwK6BrcBEAowBJwLNCwpTBKgIABqqSBDgPV6uGL5TADFwS4GGAUGc4WMfYQABwuFAYJ5CPwOGTQIvJIgOMdQQuHXoWGL4WwGgQzCFgOr1Y8BDwKPKd4XWFxTeCLoYyEFQI6EL4IvBL5MrwGGwC7GLwkBToIlFEwKHBBAqtCRxMBwFVFxkxV4IvLX4QGBq1QF5UGgAuKlYuBKo7oCdobuDq2BFxLJBFxrlCFwwnBFgSOEXxTeBFxdVKAbuEK4erFwgEBriOKqGBFxHXFwerfoOAMAKGEXwmwxmGrdVRxMALxSMBDQNcqtWPgICBGYOFMIaaBCAIRBqAPBF5ILBRg8BgFcFYeBA4IGCA4IoCHoYsBwItKF4UrSAq7BLAgXIwErgIQDwArLGBQuBDYIZPLQIsQGAqSBLoQbUGCquDF1IA/AH4AKA==")); +var img_fix = require("heatshrink").decompress(atob("mEwhBC/AH4A/AH4A/AE0rg4vtq8PF1kHxM7gJesF4Jgrg+IF4M6MFReBF4JgqXoIvDMFJeCF4RgoLwYvDnZgmLwYvEMEpeEF4jBlmYvIMEheFF4pgjXogvGMEReGF407MEBeGF45gfg+IF5rBfLw4vHMDxeIF5BgdLxAvIMDkHFxAvJMDZeJF5JgaLxQvKnZgYLxQvLMC5eLF5bBXmYvWMCxeMF5hgVXpYvNMCheNF5s7MCReNF5xgRg+IFZNersylcHhEPmjBbLw1er1XlkHIhI0CnRgUmQqEKwKnRgIzBiBpBnUICpszryCCFiIyGM4TBRAH4A/AH4A/AH4AFA")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js function project(latlong) { From 3e55bc973ca9c95cb4887eec26bd9650e3af13a1 Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 15:38:52 +0200 Subject: [PATCH 39/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index 58a182721..651e34e7a 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,7 +141,7 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwhBC/AH4AS6+sq0AgMrBo8rgICB1mBgIABAoNWAAusDYOBwWBF5IPBldWwAhCGQQJBgOBwNWqsxmIoF64AC1g2ClcGmIvKgGAwGwrcxqtWwItBFYdbw2x2APBG4IqBKgI0CLQIIBDISCBABAlBmOxAAOww1bqtVrY5BBIPVBYMxlYkBKoIFBAAJHBAoI6BQQSwIAANWmJQBAAIyCxmx6xbCBANbFwIhCwuGAAZHCBQKZBSgQvIgNWQQYACDgIHD6tcFwKBBSwIADrgFEGIJiBqASBSBFWrYvGMAIIB2OGJwJdBrYMBwArEAAWAxgwBewQvJwNVF4uMM4IvCquA68rqoqHGgQ3DUIT8BeJNVRAhgCfAWGmPXwExRoIlB2AsB2FbSwSTBAIOwQYLCBSBWFFwgvErYZBXgS+FLgoDCSIRFBwIvLC4WMMoIACqusbIKACEoYCCeAYLDwEAwLBBX5ExXgmG1eGwoCBRwL+BEQVcEYKMCAQxKBqovBC4LvOLYLwC1aoCwqGEIAR1BL4QLEqtWF5RQBF4+M62GF4QnCAAoHBeQILFrmBR5VVKwIvFA4PVw1VR4eAAAIkDA4L3CTIILBwtW1mAL48r1kxc4YADF4KPBF4gpCF4TmCeoYECraOBR5C+DAAjyB1YDB2NV1gPBQQgxDBA8xq1QF5EBV4KOEVIQvBAANbVAMrQoQAKRwREBSAJhBX4y+CLgQACFwewVQJIBmKRD2C4BxlbAwKLBrlbRwQVC1gvGq2FLIWGxiKB1YCBJwUrwRgDeAmMAYQsBrYKBlbkBMIK/Ira2CFgIyBGoOrGoQcB6+BmOAKgIyBFQVbqr0CGwMGXoReHd4aLBRQbuCBAVbJYIcBlcxSYIADYAgRBwARBCQIvGGANV1fVFIiPBTAJeCFwIABwIwBQ4SPCCIJiBKIIuBqAuIF4NWSAKRDAAJIBAAQuDAAKuBmIKBrcxqoCBDwJvCgwuJSAYtEFwMAwOBqEBFgY1D1mBqxZBFgOBBIJsBMYKOJgEBJQJdFgBaDDAIDBUIJWBFAZoEGwMxwvWwC/BMBVWWwK6BrcBEAowBJwLNCwpTBKgIABqqSBDgPV6uGL5TADFwS4GGAUGc4WMfYQABwuFAYJ5CPwOGTQIvJIgOMdQQuHXoWGL4WwGgQzCFgOr1Y8BDwKPKd4XWFxTeCLoYyEFQI6EL4IvBL5MrwGGwC7GLwkBToIlFEwKHBBAqtCRxMBwFVFxkxV4IvLX4QGBq1QF5UGgAuKlYuBKo7oCdobuDq2BFxLJBFxrlCFwwnBFgSOEXxTeBFxdVKAbuEK4erFwgEBriOKqGBFxHXFwerfoOAMAKGEXwmwxmGrdVRxMALxSMBDQNcqtWPgICBGYOFMIaaBCAIRBqAPBF5ILBRg8BgFcFYeBA4IGCA4IoCHoYsBwItKF4UrSAq7BLAgXIwErgIQDwArLGBQuBDYIZPLQIsQGAqSBLoQbUGCquDF1IA/AH4AKA==")); +var img_nofix = require("heatshrink").decompress(atob("mEwhBC/AH4A/AGnXwMrgMrBg4KBgOBwIOBldWwNWAAmBCIOB1kBF5mBlVVCwInBqwzBAQIcBEQNVqtcFwIRB64AD1gPBlcGGYIAMFIOG2FbrdcFgVWrgHBw2x2Owqss1h0Bq0slcsGoIIClR8IQQ2BrYjBEgOGwwrC2AIB6uwlVWEgMxqo6BAAcxq2s1hsBGB1b2AAExg1CGAUxRQNWlQ9BAA1blQOCqzBMQ4KQBAAYFBF4aYBD4NVNoQAIGAJhOBoIvFxhgBAgOrmJdJwAwGeoRgMqyQGdYReBJoMqZAIBBAQ1cAgOwrZxCeZlWrmMF5ExPgIuEXYiRHMAOBL5oVDGYItB6uGqxeBFBCPDBQcqMAQuKlgvBXAWMw2rDIOxraOBLwaMEwAHCBQhQBF5jvGLoIZB6wvBwKwBLopABXgIAFq2BF5krqy+FF4OxF5ItBIgJaBBQlcCYLUBFxMBq1VRwRfEX4IvCqqCBRISSFSAQEBqumL5krwNc6orBAARMBAYOAJQIvBAB0xWAIvMXwIqBFweMAgSrB1kxwCLCABVbXwKPMgCOBFoYABLwQGBmIaBmKyCR5UxwJeBGIK/KQAOw1ereQIsCLwOMYAPXlQnBF4VcMoIFBXwdbWAKOBR5mAdgerw+G1YuBBIJgBwMxrdcGQQrCqo3C2AvBFwOBgLvMRoRdCw6XElRNBwMqmNVFoVbwDtEFwKiBXxZgCXwgECJoStB64ABGASICBoWGqsqFwUrlYuLgA9BdIex6orBlcxgwuD1gABegIyBAAaJBHgMGLpgvDraJFlgnCqwuB0wqBwIyCwIACHIdVMgOBGB1cRoQuBFQQABGAOmmLjCLAWmGQQsBFoJJBBYJgPEIIuGGAUAWwQOBwzABFYLEC6p5Cra/NF4Nb2GMFw4ABlYvCxgxCAAYrB1b2CqrANd4YuJF4YAExg2BBIIEBBAS/OF4SuBFxFWlQkELYZmBBAmGLxsAldcLpVWgxXCF44EDAANcF55hBFxSbBKwooCBQIABBASOOlcrFxuxFw+MFoYACmJQBXxouK2PV6pWEFQWx1aVGRx4uIwLqBDoNVqtWquAGIhnBGgOGwFVmOsgIvN1hdHgFbrcxq2BAwIDCmNbwwACBwI8BwMsRxodBMA2BZAWmDYJMFlgmCVAIPJGCIFBwJ3OwIpQGBCSBAYJ2OADYsCAQIupAH4A/AH4AoA")); var img_fix = require("heatshrink").decompress(atob("mEwhBC/AH4A/AH4A/AE0rg4vtq8PF1kHxM7gJesF4Jgrg+IF4M6MFReBF4JgqXoIvDMFJeCF4RgoLwYvDnZgmLwYvEMEpeEF4jBlmYvIMEheFF4pgjXogvGMEReGF407MEBeGF45gfg+IF5rBfLw4vHMDxeIF5BgdLxAvIMDkHFxAvJMDZeJF5JgaLxQvKnZgYLxQvLMC5eLF5bBXmYvWMCxeMF5hgVXpYvNMCheNF5s7MCReNF5xgRg+IFZNersylcHhEPmjBbLw1er1XlkHIhI0CnRgUmQqEKwKnRgIzBiBpBnUICpszryCCFiIyGM4TBRAH4A/AH4A/AH4AFA")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js From 00c37da578024838586fbbb0b78e91da12e2b93b Mon Sep 17 00:00:00 2001 From: RenaudG <34276398+renaudgweb@users.noreply.github.com> Date: Tue, 21 Apr 2020 15:45:31 +0200 Subject: [PATCH 40/77] Update osmpoi.html --- apps/osmpoi/osmpoi.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/osmpoi/osmpoi.html b/apps/osmpoi/osmpoi.html index 651e34e7a..0096b78a0 100644 --- a/apps/osmpoi/osmpoi.html +++ b/apps/osmpoi/osmpoi.html @@ -141,7 +141,7 @@ }); document.getElementById("upload").addEventListener("click", function() { var app = `var features = ${JSON.stringify(features)}; -var img_nofix = require("heatshrink").decompress(atob("mEwhBC/AH4A/AGnXwMrgMrBg4KBgOBwIOBldWwNWAAmBCIOB1kBF5mBlVVCwInBqwzBAQIcBEQNVqtcFwIRB64AD1gPBlcGGYIAMFIOG2FbrdcFgVWrgHBw2x2Owqss1h0Bq0slcsGoIIClR8IQQ2BrYjBEgOGwwrC2AIB6uwlVWEgMxqo6BAAcxq2s1hsBGB1b2AAExg1CGAUxRQNWlQ9BAA1blQOCqzBMQ4KQBAAYFBF4aYBD4NVNoQAIGAJhOBoIvFxhgBAgOrmJdJwAwGeoRgMqyQGdYReBJoMqZAIBBAQ1cAgOwrZxCeZlWrmMF5ExPgIuEXYiRHMAOBL5oVDGYItB6uGqxeBFBCPDBQcqMAQuKlgvBXAWMw2rDIOxraOBLwaMEwAHCBQhQBF5jvGLoIZB6wvBwKwBLopABXgIAFq2BF5krqy+FF4OxF5ItBIgJaBBQlcCYLUBFxMBq1VRwRfEX4IvCqqCBRISSFSAQEBqumL5krwNc6orBAARMBAYOAJQIvBAB0xWAIvMXwIqBFweMAgSrB1kxwCLCABVbXwKPMgCOBFoYABLwQGBmIaBmKyCR5UxwJeBGIK/KQAOw1ereQIsCLwOMYAPXlQnBF4VcMoIFBXwdbWAKOBR5mAdgerw+G1YuBBIJgBwMxrdcGQQrCqo3C2AvBFwOBgLvMRoRdCw6XElRNBwMqmNVFoVbwDtEFwKiBXxZgCXwgECJoStB64ABGASICBoWGqsqFwUrlYuLgA9BdIex6orBlcxgwuD1gABegIyBAAaJBHgMGLpgvDraJFlgnCqwuB0wqBwIyCwIACHIdVMgOBGB1cRoQuBFQQABGAOmmLjCLAWmGQQsBFoJJBBYJgPEIIuGGAUAWwQOBwzABFYLEC6p5Cra/NF4Nb2GMFw4ABlYvCxgxCAAYrB1b2CqrANd4YuJF4YAExg2BBIIEBBAS/OF4SuBFxFWlQkELYZmBBAmGLxsAldcLpVWgxXCF44EDAANcF55hBFxSbBKwooCBQIABBASOOlcrFxuxFw+MFoYACmJQBXxouK2PV6pWEFQWx1aVGRx4uIwLqBDoNVqtWquAGIhnBGgOGwFVmOsgIvN1hdHgFbrcxq2BAwIDCmNbwwACBwI8BwMsRxodBMA2BZAWmDYJMFlgmCVAIPJGCIFBwJ3OwIpQGBCSBAYJ2OADYsCAQIupAH4A/AH4AoA")); +var img_nofix = require("heatshrink").decompress(atob("mEwhBC/AH4A/AH4A/AC2swMllcrBQoHBktWwIEBlYEBqwAEgAICF6FWldbrgDBAIMrFIIhBrlbAAIIBwOsAAgsClcxF6ErrmG2GGw1cqsxrmAwuG2OxxkxFoOCq1VFANVLgIyBPI4vLq2F2OwAAQrCAgPVw0xEgVVMoQ7BwsxmOm1iUCMCIuD2GM2AvC2IuDFQIACwADCrZrCGCOBqovI2NcEAIuBTwQAHlZhCL6FVYAKQG2NV1i3BZYIpDrZiFlb1BYSFWwAvG6tbwOCmIuFF4YAC2FVwOBMCFWraBCRwReDBYIpELQOAAQQ5CqpgBF57RBFYK+C2IcBw4vBEQIwDrYEDrlbGYOMmMr64vQd4hcBX4VcF4LsGOIYGCxhMBYAKORGAhhBF4TtBAAzvFwuAwIvPlbuBXIQAE2BMBHgIoBE4QvEricBqtWF4KPOF4KICAAReCd4WBdoYAJmKPCF50lrhYCYIuxreBwUxR5RrBrmCwIABF54pCFwrkBJoMxFAKGBF4lcFwNbR4JxBX6GGFYeHSoOGSQJgBGARVBFoIqCMIWMlS+ClbvRMIbFEJ4PXwMrmIqBAARjDleB67ABFxowCYAgDBQQVbFwIAB00xGAQMDA4OCNoJdOAAWBYAex6uGNAIcBFwSvB1mCq1VFYMxqwICA4IvRDgKKDw0qwQrBPgIuBX4IoCAAmBDILQCF6AwBwBgBFwgwCldVTQKJBqtcwB1BSgXV6uAXyAvCrYuHAAMrrYuBGIQABwoGBOgWxF6SEBFwWmFwpgBF4IADxgyC2IFCR6Z5BLpHX1krLoQADLYQHEqrvRWQMrFxKOEF4eMxgyBGgVWkovRgCMH1kqZIInBLwwtCRwZfQqxdLEYQuFAQYHCraORq2BXZPVKwIABEoIGBFoYCCRwNWRyIuIquGrgfBldWwGAwqMBFYVbrlcqovSL42sksrwCsBD4QDBkoyBqsxFQINBmItRL4UrGAZdBLIIABCQ8lgAsBH4IsSGA4uBDq4wTq0xmIuqAH4A/AH4A/AH4AHA=")); var img_fix = require("heatshrink").decompress(atob("mEwhBC/AH4A/AH4A/AE0rg4vtq8PF1kHxM7gJesF4Jgrg+IF4M6MFReBF4JgqXoIvDMFJeCF4RgoLwYvDnZgmLwYvEMEpeEF4jBlmYvIMEheFF4pgjXogvGMEReGF407MEBeGF45gfg+IF5rBfLw4vHMDxeIF5BgdLxAvIMDkHFxAvJMDZeJF5JgaLxQvKnZgYLxQvLMC5eLF5bBXmYvWMCxeMF5hgVXpYvNMCheNF5s7MCReNF5xgRg+IFZNersylcHhEPmjBbLw1er1XlkHIhI0CnRgUmQqEKwKnRgIzBiBpBnUICpszryCCFiIyGM4TBRAH4A/AH4A/AH4AFA")); // https://github.com/Leaflet/Leaflet/blob/master/src/geo/projection/Projection.SphericalMercator.js From 9d678772943b6e19cdfa53113b18933f31524911 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Tue, 21 Apr 2020 16:04:56 +0200 Subject: [PATCH 41/77] ActivePedom 0.03 --- apps/activepedom/app.js | 44 ++++++++++++++++++++++++++++++++------ apps/activepedom/widget.js | 26 ++++++++++++++-------- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/apps/activepedom/app.js b/apps/activepedom/app.js index f966530d0..0680e2d1a 100644 --- a/apps/activepedom/app.js +++ b/apps/activepedom/app.js @@ -1,8 +1,31 @@ (() => { +//Graph module, as long as modules are not added by the app loader +Modules.addCached("graph",function(){exports.drawAxes=function(b,c,a){function h(a){return e+m*(a-t)/x}function l(a){return f+g-g*(a-n)/u}var k=a.padx||0,d=a.pady||0,t=-k,w=c.length+k-1,n=(void 0!==a.miny?a.miny:a.miny=c.reduce(function(a,b){return Math.min(a,b)},c[0]))-d;c=(void 0!==a.maxy?a.maxy:a.maxy=c.reduce(function(a,b){return Math.max(a,b)},c[0]))+d;a.gridy&&(d=a.gridy,n=d*Math.floor(n/d),c=d*Math.ceil(c/d));var e=a.x||0,f=a.y||0,m=a.width||b.getWidth()-(e+1),g=a.height||b.getHeight()-(f+1);a.axes&&(null!==a.ylabel&& + (e+=6,m-=6),null!==a.xlabel&&(g-=6));a.title&&(f+=6,g-=6);a.axes&&(b.drawLine(e,f,e,f+g),b.drawLine(e,f+g,e+m,f+g));a.title&&(b.setFontAlign(0,-1),b.drawString(a.title,e+m/2,f-6));var x=w-t,u=c-n;u||(u=1);if(a.gridx){b.setFontAlign(0,-1,0);var v=a.gridx;for(d=Math.ceil((t+k)/v)*v;d<=w-k;d+=v){var r=h(d),p=a.xlabel?a.xlabel(d):d;b.setPixel(r,f+g-1);var q=b.stringWidth(p)/2;null!==a.xlabel&&r>q&&b.getWidth()>r+q&&b.drawString(p,r,f+g+2)}}if(a.gridy)for(b.setFontAlign(0,0,1),d=n;d<=c;d+=a.gridy)k=l(d), + p=a.ylabel?a.ylabel(d):d,b.setPixel(e+1,k),q=b.stringWidth(p)/2,null!==a.ylabel&&k>q&&b.getHeight()>k+q&&b.drawString(p,e-5,k+1);b.setFontAlign(-1,-1,0);return{x:e,y:f,w:m,h:g,getx:h,gety:l}};exports.drawLine=function(b,c,a){a=a||{};a=exports.drawAxes(b,c,a);var h=!0,l;for(l in c)h?b.moveTo(a.getx(l),a.gety(c[l])):b.lineTo(a.getx(l),a.gety(c[l])),h=!1;return a};exports.drawBar=function(b,c,a){a=a||{};a.padx=1;a=exports.drawAxes(b,c,a);for(var h in c)b.fillRect(a.getx(h-.5)+1,a.gety(c[h]),a.getx(h+ + .5)-1,a.gety(0));return a}}); + const storage = require("Storage"); +const SETTINGS_FILE = 'activepedom.settings.json'; var history = 86400000; // 28800000=8h 43200000=12h //86400000=24h +//return setting +function setting(key) { +//define default settings +const DEFAULTS = { + 'cMaxTime' : 1100, + 'cMinTime' : 240, + 'stepThreshold' : 30, + 'intervalResetActive' : 30000, + 'stepSensitivity' : 80, + 'stepGoal' : 10000, + 'stepLength' : 75, +}; +if (!settings) { loadSettings(); } +return (key in settings) ? settings[key] : DEFAULTS[key]; +} + //Convert ms to time function getTime(t) { date = new Date(t); @@ -58,8 +81,8 @@ function drawGraph() { filename = filename = "activepedom-" + now.getFullYear() + month + now.getDate() + ".data"; var csvFile = storage.open(filename, "r"); times = getArrayFromCSV(csvFile, 0); - first = getDate(times[0]) + " " + getTime(times[0]); - last = getDate (times[times.length-1]) + " " + getTime(times[times.length-1]); + first = getDate(times[0]) + " " + getTime(times[0]); //first entry in datafile + last = getDate (times[times.length-1]) + " " + getTime(times[times.length-1]); //last entry in datafile //free memory csvFile = undefined; times = undefined; @@ -67,21 +90,24 @@ function drawGraph() { //steps var csvFile = storage.open(filename, "r"); steps = getArrayFromCSV(csvFile, 1); + first = first + " " + steps[0] + "/" + setting('stepGoal'); + last = last + " " + steps[steps.length-1] + "/" + setting('stepGoal'); + //define y-axis grid labels stepsLastEntry = steps[steps.length-1]; if (stepsLastEntry < 1000) gridyValue = 100; - if (stepsLastEntry >= 1000 && stepsLastEntry < 10000) gridyValue = 500; + if (stepsLastEntry >= 1000 && stepsLastEntry < 10000) gridyValue = 1000; if (stepsLastEntry > 10000) gridyValue = 5000; //draw drawMenu(); - g.drawString("First: " + first, 40, 30); - g.drawString(" Last: " + last, 40, 40); + g.drawString("First: " + first, 10, 30); + g.drawString(" Last: " + last, 10, 40); require("graph").drawLine(g, steps, { //title: "Steps Counted", axes : true, gridy : gridyValue, - y : 50, //offset on screen + y : 60, //offset on screen x : 5, //offset on screen }); //free memory from big variables @@ -128,6 +154,12 @@ setWatch(function() { //BTN4 setWatch(function() { //BTN5 }, BTN5, {edge:"rising", debounce:50, repeat:true}); +//load settings +let settings; +function loadSettings() { +settings = storage.readJSON(SETTINGS_FILE, 1) || {}; +} + drawMenu(); })(); \ No newline at end of file diff --git a/apps/activepedom/widget.js b/apps/activepedom/widget.js index 7879b2056..c6bd410ce 100644 --- a/apps/activepedom/widget.js +++ b/apps/activepedom/widget.js @@ -35,16 +35,24 @@ now = new Date(); month = now.getMonth() + 1; if (month < 10) month = "0" + month; - filename = filename = "activepedom-" + now.getFullYear() + month + now.getDate() + ".data"; + filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data"; dataFile = s.open(filename,"a"); - if (dataFile) dataFile.write([ - now.getTime(), - stepsCounted, - active, - stepsTooShort, - stepsTooLong, - stepsOutsideTime, - ].join(",")+"\n"); + if (dataFile) { + if (dataFile.getLength() == 0) { + stepsToWrite = 0; + } + else { + stepsToWrite = stepsCounted; + } + dataFile.write([ + now.getTime(), + stepsToWrite, + active, + stepsTooShort, + stepsTooLong, + stepsOutsideTime, + ].join(",")+"\n"); + } dataFile = undefined; } From 8dd71947bdc0f791717add161121d053e423e91c Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Tue, 21 Apr 2020 16:32:15 +0200 Subject: [PATCH 42/77] Fix typo --- apps/activepedom/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/activepedom/app.js b/apps/activepedom/app.js index 0680e2d1a..0a9b3b93f 100644 --- a/apps/activepedom/app.js +++ b/apps/activepedom/app.js @@ -78,7 +78,7 @@ function drawGraph() { now = new Date(); month = now.getMonth() + 1; if (month < 10) month = "0" + month; - filename = filename = "activepedom-" + now.getFullYear() + month + now.getDate() + ".data"; + filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data"; var csvFile = storage.open(filename, "r"); times = getArrayFromCSV(csvFile, 0); first = getDate(times[0]) + " " + getTime(times[0]); //first entry in datafile @@ -162,4 +162,4 @@ settings = storage.readJSON(SETTINGS_FILE, 1) || {}; drawMenu(); -})(); \ No newline at end of file +})(); From 8272b19bb6517b96950502ff3f422cab8e6fecea Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 19:38:02 +0100 Subject: [PATCH 43/77] Finish BuffGym app --- apps/buffgym/buffgym-exercise.js | 115 ++---- apps/buffgym/buffgym-icon.js | 2 +- apps/buffgym/buffgym-program-a.json | 33 ++ apps/buffgym/buffgym-program-b.json | 33 ++ apps/buffgym/buffgym-program-index.json | 10 + apps/buffgym/buffgym-program.js | 62 ++- apps/buffgym/buffgym-programs.json | 1 - apps/buffgym/buffgym-programs.json.unminified | 101 ----- apps/buffgym/buffgym-set.js | 42 +- apps/buffgym/buffgym.app.js | 373 ++++++++++-------- apps/buffgym/buffgym.png | Bin 1800 -> 7576 bytes 11 files changed, 363 insertions(+), 409 deletions(-) create mode 100644 apps/buffgym/buffgym-program-a.json create mode 100644 apps/buffgym/buffgym-program-b.json create mode 100644 apps/buffgym/buffgym-program-index.json delete mode 100644 apps/buffgym/buffgym-programs.json delete mode 100644 apps/buffgym/buffgym-programs.json.unminified mode change 100644 => 100755 apps/buffgym/buffgym.png diff --git a/apps/buffgym/buffgym-exercise.js b/apps/buffgym/buffgym-exercise.js index 99d658571..68e49be84 100644 --- a/apps/buffgym/buffgym-exercise.js +++ b/apps/buffgym/buffgym-exercise.js @@ -1,116 +1,76 @@ -const STARTED = 1; -const RESTING = 2; -const COMPLETED = 3; -const ONE_SECOND = 1000; - exports = class Exercise { - constructor(params /*{title, weight, unit, restPeriod}*/) { - const DEFAULTS = { - title: "Unknown", - weight: 0, - unit: "Kg", - restPeriod: 90, - weightIncrement: 2.5, - }; - const p = Object.assign({}, DEFAULTS, params); - - this._title = p.title; - this._weight = p.weight; - this._unit = p.unit; - this._originalRestPeriod = p.restPeriod; // Used when reseting _restPeriod - this._restPeriod = p.restPeriod; - this._weightIncrement = p.weightIncrement; - this._started = new Date(); - this._completed = false; - this._sets = []; + constructor(params) { + this.title = params.title; + this.weight = params.weight; + this.unit = params.unit; + this.restPeriod = params.restPeriod; + this.completed = false; + this.sets = []; this._restTimeout = null; this._restInterval = null; this._state = null; - } - - get title() { - return this._title; + this._originalRestPeriod = params.restPeriod; + this._weightIncrement = params.weightIncrement || 2.5; } get humanTitle() { - return `${this._title} ${this._weight}${this._unit}`; + return `${this.title} ${this.weight}${this.unit}`; } get subTitle() { - const totalSets = this._sets.length; - const uncompletedSets = this._sets.filter((set) => !set.isCompleted()).length; + const totalSets = this.sets.length; + const uncompletedSets = this.sets.filter((set) => !set.isCompleted()).length; const currentSet = (totalSets - uncompletedSets) + 1; return `Set ${currentSet} of ${totalSets}`; } - get restPeriod() { - return this._restPeriod; - } - decRestPeriod() { - this._restPeriod--; - } - - get weight() { - return this._weight; - } - - get unit() { - return this._unit; - } - - get started() { - return this._started; + this.restPeriod--; } addSet(set) { - this._sets.push(set); + this.sets.push(set); } - addSets(sets) { - sets.forEach(set => this.addSet(set)); - } - - get currentSet() { - return this._sets.filter(set => !set.isCompleted())[0]; + currentSet() { + return this.sets.filter(set => !set.isCompleted())[0]; } isLastSet() { - return this._sets.filter(set => !set.isCompleted()).length === 1; + return this.sets.filter(set => !set.isCompleted()).length === 1; } isCompleted() { - return !!this._completed; + return !!this.completed; } canSetCompleted() { - return this._sets.filter(set => set.isCompleted()).length === this._sets.length; + return this.sets.filter(set => set.isCompleted()).length === this.sets.length; } setCompleted() { if (!this.canSetCompleted()) throw "All sets must be completed"; - if (this.canProgress) this._weight += this._weightIncrement; - this._completed = true; + if (this.canProgress()) this.weight += this._weightIncrement; + this.completed = true; } - get canProgress() { + canProgress() { let completedRepsTotalSum = 0; let targetRepsTotalSum = 0; - - const completedRepsTotal = this._sets.forEach(set => completedRepsTotalSum += set.reps); - const targetRepsTotal = this._sets.forEach(set => targetRepsTotalSum += set.maxReps); + this.sets.forEach(set => completedRepsTotalSum += set.reps); + this.sets.forEach(set => targetRepsTotalSum += set.maxReps); return (targetRepsTotalSum - completedRepsTotalSum) === 0; } startRestTimer(program) { this._restTimeout = setTimeout(() => { - this.next(); - }, ONE_SECOND * this._restPeriod); + this.next(program); + }, 1000 * this.restPeriod); this._restInterval = setInterval(() => { program.emit("redraw"); - }, ONE_SECOND); + }, 1000 ); } resetRestTimer() { @@ -118,7 +78,7 @@ exports = class Exercise { clearInterval(this._restInterval); this._restTimeout = null; this._restInterval = null; - this._restPeriod = this._originalRestPeriod; + this.restPeriod = this._originalRestPeriod; } isRestTimerRunning() { @@ -129,52 +89,51 @@ exports = class Exercise { clearWatch(); setWatch(() => { - this.currentSet.incReps(); + this.currentSet().incReps(); program.emit("redraw"); }, BTN1, {repeat: true}); setWatch(program.next.bind(program), BTN2, {repeat: false}); setWatch(() => { - this.currentSet.decReps(); + this.currentSet().decReps(); program.emit("redraw"); }, BTN3, {repeat: true}); } setupRestingButtons(program) { clearWatch(); - setWatch(program.next.bind(program), BTN2, {repeat: true}); + setWatch(program.next.bind(program), BTN2, {repeat: false}); } next(program) { - global.poo = this; + const STARTED = 1; + const RESTING = 2; + const COMPLETED = 3; + switch(this._state) { case null: - console.log("XXX 1 moving null -> STARTED"); this._state = STARTED; this.setupStartedButtons(program); break; case STARTED: - console.log("XXX 2 moving STARTED -> RESTING"); this._state = RESTING; this.startRestTimer(program); this.setupRestingButtons(program); break; case RESTING: this.resetRestTimer(); - this.currentSet.setCompleted(); + this.currentSet().setCompleted(); if (this.canSetCompleted()) { - console.log("XXX 3b moving RESTING -> COMPLETED"); this._state = COMPLETED; this.setCompleted(); } else { - console.log("XXX 3a moving RESTING -> null"); this._state = null; } // As we are changing state and require it to be reprocessed // invoke the next step of program - program.next(program); + program.next(); break; default: throw "Exercise: Attempting to move to an unknown state"; diff --git a/apps/buffgym/buffgym-icon.js b/apps/buffgym/buffgym-icon.js index 949b0e45b..31764acbb 100644 --- a/apps/buffgym/buffgym-icon.js +++ b/apps/buffgym/buffgym-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwhC/AFEEolAC6lN7vdDCcECwPd6guVGCYuDC4cCBQMikQXQJAMjkECmcyIx4XDmUjmYvLC4XUDARHBIoIWLgATCGQdA7tEonQC5ouDDYg0BOxgSEAggwKRwgUCC6ZIDSwoXNogWDDgNCAgIWIkUEoUk6kiCgMkokipsiBIQXIki2CAgNCAoYADC5Eic4Mic4ICCAIIJCC5MzAAcykYGEAAIXOABAXTmUzGoIXVAIIXLB4SICDIovjO76PZbYR3PDI4XiI6530MIh3SC6R33C/oAOC48CCxsgC44A/ADY=")) +require("heatshrink").decompress(atob("mEwxH+ACPI5AUSADAtB5vNGFQtBAIfNF95hoF4wwoF5AwmF5BhmXYbAEF/6QbF1QwIF04qB54ADAwIwoF4oRKBoIvsB4gvZ58kkgCDFxoxaF5wuHGDQcMF5IwXDZwLDGDmlDIWlkgJDSwIABCRAwPDQohCFgIABDQIOCFwYABr4RCCQIvQDYguEAAwtFF5owJDZAvHFw4vFOYQvKFAowMBxIvFMQwvPAB4wFUQ4vJGDYvUGC4vNdgyuEGDIsNFwYwGNAgAPExAvMGIdfTIovfTpYvrfRCOkZ44ugF44NGF05gUFyQvKGIoueGKIufGJ4uhG5oupGItfr4vvAAgvlGAQvt/wrEF9oEGF841IF9QGHX0oGIAD8kAAYJOFzwEBBQoMFACA=")); \ No newline at end of file diff --git a/apps/buffgym/buffgym-program-a.json b/apps/buffgym/buffgym-program-a.json new file mode 100644 index 000000000..7ebaf3741 --- /dev/null +++ b/apps/buffgym/buffgym-program-a.json @@ -0,0 +1,33 @@ +{ + "title": "Program A", + "exercises": [ + { + "title": "Squats", + "weight": 40, + "unit": "Kg", + "sets": [5, 5, 5, 5, 5], + "restPeriod": 90 + }, + { + "title": "Overhead press", + "weight": 20, + "unit": "Kg", + "sets": [5, 5, 5, 5, 5], + "restPeriod": 90 + }, + { + "title": "Deadlift", + "weight": 20, + "unit": "Kg", + "sets": [5], + "restPeriod": 90 + }, + { + "title": "Pullups", + "weight": 0, + "unit": "Kg", + "sets": [10, 10, 10], + "restPeriod": 90 + } + ] +} \ No newline at end of file diff --git a/apps/buffgym/buffgym-program-b.json b/apps/buffgym/buffgym-program-b.json new file mode 100644 index 000000000..b93348621 --- /dev/null +++ b/apps/buffgym/buffgym-program-b.json @@ -0,0 +1,33 @@ +{ + "title": "Program B", + "exercises": [ + { + "title": "Squats", + "weight": 40, + "unit": "Kg", + "sets": [5, 5, 5, 5, 5], + "restPeriod": 90 + }, + { + "title": "Bench press", + "weight": 20, + "unit": "Kg", + "sets": [5, 5, 5, 5, 5], + "restPeriod": 90 + }, + { + "title": "Row", + "weight": 20, + "unit":"Kg", + "sets": [5, 5, 5, 5, 5], + "restPeriod": 90 + }, + { + "title": "Tricep extension", + "weight": 20, + "unit": "Kg", + "sets": [10, 10, 10], + "restPeriod": 90 + } + ] +} \ No newline at end of file diff --git a/apps/buffgym/buffgym-program-index.json b/apps/buffgym/buffgym-program-index.json new file mode 100644 index 000000000..3bb51f1b5 --- /dev/null +++ b/apps/buffgym/buffgym-program-index.json @@ -0,0 +1,10 @@ +[ + { + "title": "Program A", + "file": "buffgym-program-a.json" + }, + { + "title": "Program B", + "file": "buffgym-program-b.json" + } +] \ No newline at end of file diff --git a/apps/buffgym/buffgym-program.js b/apps/buffgym/buffgym-program.js index 956827f56..68a069da5 100644 --- a/apps/buffgym/buffgym-program.js +++ b/apps/buffgym/buffgym-program.js @@ -1,68 +1,56 @@ exports = class Program { constructor(params) { - const DEFAULTS = { - title: "Unknown", - trainDay: "", // Day of week - }; - const p = Object.assign({}, DEFAULTS, params); - - this._title = p.title; - this._trainDay = p.trainDay; - this._exercises = []; - + this.title = params.title; + this.exercises = []; + this.completed = false; this.on("redraw", redraw.bind(null, this)); } - get title() { - return `${this._title} - ${this._trainDay}`; - } - - addExercise(exercise) { - this._exercises.push(exercise); - } - addExercises(exercises) { - exercises.forEach(exercise => this.addExercise(exercise)); + exercises.forEach(exercise => this.exercises.push(exercise)); } currentExercise() { - return ( - this._exercises - .filter(exercise => !exercise.isCompleted())[0] - ); + return this.exercises.filter(exercise => !exercise.isCompleted())[0]; } canComplete() { - return ( - this._exercises - .filter(exercise => exercise.isCompleted()) - .length === this._exercises.length - ); + return this.exercises.filter(exercise => exercise.isCompleted()).length === this.exercises.length; } setCompleted() { if (!this.canComplete()) throw "All exercises must be completed"; - this._completed = true; + this.completed = true; } isCompleted() { - return !!this._completed; + return !!this.completed; + } + + toJSON() { + return { + title: this.title, + exercises: this.exercises.map(exercise => { + return { + title: exercise.title, + weight: exercise.weight, + unit: exercise.unit, + sets: exercise.sets.map(set => set.maxReps), + restPeriod: exercise.restPeriod, + }; + }), + }; } // State machine next() { - console.log("XXX Program.next"); - const exercise = this.currentExercise(); - - // All exercises are completed so mark the - // Program as comleted if (this.canComplete()) { this.setCompleted(); this.emit("redraw"); - return; } - exercise.next(this); + // Call current exercise state machine + this.currentExercise().next(this); } } \ No newline at end of file diff --git a/apps/buffgym/buffgym-programs.json b/apps/buffgym/buffgym-programs.json deleted file mode 100644 index 7551c7a47..000000000 --- a/apps/buffgym/buffgym-programs.json +++ /dev/null @@ -1 +0,0 @@ -[{"title":"Program A","exercises":[{"title":"Squats","weight":40,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Overhead press","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Deadlift","weight":20,"unit":"Kg","sets":[5]},{"title":"Pullups","weight":0,"unit":"Kg","sets":[10,10,10]}]},{"title":"Program B","exercises":[{"title":"Squats","weight":40,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Bench press","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Row","weight":20,"unit":"Kg","sets":[5,5,5,5,5]},{"title":"Tricep extension","weight":20,"unit":"Kg","sets":[10,10,10]}]}] \ No newline at end of file diff --git a/apps/buffgym/buffgym-programs.json.unminified b/apps/buffgym/buffgym-programs.json.unminified deleted file mode 100644 index cd005eeab..000000000 --- a/apps/buffgym/buffgym-programs.json.unminified +++ /dev/null @@ -1,101 +0,0 @@ -[ - { - "title": "Program A", - "exercises": [ - { - "title": "Squats", - "weight": 40, - "unit": "Kg", - "sets": [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - "title": "Overhead press", - "weight": 20, - "unit": "Kg", - "sets": [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - "title": "Deadlift", - "weight": 20, - "unit": "Kg", - "sets": [ - 5 - ] - }, - { - "title": "Pullups", - "weight": 0, - "unit": "Kg", - "sets": [ - 10, - 10, - 10 - ] - } - ] - }, - { - "title": "Program B", - "exercises": [ - { - "title": "Squats", - "weight": 40, - "unit": "Kg", - "sets": [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - "title": "Bench press", - "weight": 20, - "unit": "Kg", - "sets": [ - 5, - 5, - 5, - 5, - 5 - ] - }, - { - "title": "Row", - "weight": 20, - "unit":"Kg", - "sets": [ - 5, - 5, - 5, - 5, - 5 - ] - - }, - { - "title": "Tricep extension", - "weight": 20, - "unit": "Kg", - "sets": [ - 10, - 10, - 10 - ] - } - ] - } -] \ No newline at end of file diff --git a/apps/buffgym/buffgym-set.js b/apps/buffgym/buffgym-set.js index aed6df260..4bd12d7ec 100644 --- a/apps/buffgym/buffgym-set.js +++ b/apps/buffgym/buffgym-set.js @@ -1,46 +1,28 @@ exports = class Set { constructor(maxReps) { - this._minReps = 0; - this._maxReps = maxReps; - this._reps = 0; - this._completed = false; - } - - get title() { - return this._title; - } - - get weight() { - return this._weight; + this.minReps = 0; + this.maxReps = maxReps; + this.reps = 0; + this.completed = false; } isCompleted() { - return !!this._completed; + return !!this.completed; } setCompleted() { - this._completed = true; - } - - get reps() { - return this._reps; - } - - get maxReps() { - return this._maxReps; + this.completed = true; } incReps() { - if (this._completed) return; - if (this._reps >= this._maxReps) return; - - this._reps++; + if (this.completed) return; + if (this.reps >= this.maxReps) return; + this.reps++; } decReps() { - if (this._completed) return; - if (this._reps <= this._minReps) return; - - this._reps--; + if (this.completed) return; + if (this.reps <= this.minReps) return; + this.reps--; } } \ No newline at end of file diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index e1ab3e66b..eeabd5c29 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -1,177 +1,135 @@ +Bangle.setLCDMode("120x120"); + const W = g.getWidth(); const H = g.getHeight(); const RED = "#d32e29"; const PINK = "#f05a56"; const WHITE = "#ffffff"; -const Set = require("buffgym-set.js"); -const Exercise = require("buffgym-exercise.js"); -const Program = require("buffgym-program.js"); - -function centerStringX(str) { - return (W - g.stringWidth(str)) / 2; -} - -function iconIncrement() { - const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglHA4IpJBYwTHA4RMJCY5oDJo4THKIQKET5IMGCaY7TMaKLTWajbTFJIlICgoVBFYXJYQYSGCggAGCRAVIBgw")); - return img; -} - -function iconDecrement() { - const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCRYABCYQmOFAhNMKIw6FTw4LHCaY7TMaKLTWajbTFJglFCgoVBFYXJYQYSGCggAGCRAVIBgw=")); - return img; -} - -function iconOk() { - const img = require("heatshrink").decompress(atob("ikUxH+AA3XAAgNHCJIVMBYXQ5PC4XJ6AUJCIQQBAAoVCCQwjCAA/JCgglKFJADBCJQxCCYQmMIwZoDJpQMCKIg6KBYwTGFQgeHHYouCCRI7EMYTXFRhILEK5SfFRgYSIborbSbpglFCgoVBFYXJYQYSGCggAGCRAVIBgwA==")); - return img; -} - function drawMenu(params) { + const hs = require("heatshrink"); + const incImg = hs.decompress(atob("gsFwMAkM+oUA")); + const decImg = hs.decompress(atob("gsFwIEBnwCBA")); + const okImg = hs.decompress(atob("gsFwMAhGFo0A")); const DEFAULT_PARAMS = { showBTN1: false, showBTN2: false, showBTN3: false, }; const p = Object.assign({}, DEFAULT_PARAMS, params); - if (p.showBTN1) g.drawImage(iconIncrement(), W - 30, 10); - if (p.showBTN2) g.drawImage(iconOk(), W - 30, 110); - if (p.showBTN3) g.drawImage(iconDecrement(), W - 30, 210); + if (p.showBTN1) g.drawImage(incImg, W - 10, 10); + if (p.showBTN2) g.drawImage(okImg, W - 10, 60); + if (p.showBTN3) g.drawImage(decImg, W - 10, 110); } -function clearScreen() { - g.setColor(RED); - g.fillRect(0,0,W,H); -} - -function drawTitle(exercise) { - const title = exercise.humanTitle; - - g.setFont("Vector",20); - g.setColor(WHITE); - g.drawString(title, centerStringX(title), 5); -} - -function drawReps(exercise) { - const set = exercise.currentSet; +function drawSet(exercise) { + const set = exercise.currentSet(); if (set.isCompleted()) return; + g.clear(); + + // Draw exercise title g.setColor(PINK); - g.fillCircle(W / 2, H / 2, 50); + g.fillRect(15, 0, W - 15, 18); + g.setFontAlign(0, -1); + g.setFont("6x8", 1); g.setColor(WHITE); - g.setFont("Vector", 40); - g.drawString(set.reps, centerStringX(set.reps), (H - 45) / 2); - g.setFont("Vector", 15); - const note = `of ${set.maxReps}`; - g.drawString(note, centerStringX(note), (H / 2) + 25); -} - -function drawSets(exercise) { - const sets = exercise.subTitle; - + g.drawString(exercise.title, W / 2, 5); + g.setFont("6x8", 1); + g.drawString(exercise.weight + " " + exercise.unit, W / 2, 27); + // Draw completed reps counter + g.setFontAlign(0, 0); + g.setColor(PINK); + g.fillRect(15, 42, W - 15, 80); g.setColor(WHITE); - g.setFont("Vector", 15); - g.drawString(sets, centerStringX(sets), H - 25); -} + g.setFont("6x8", 5); + g.drawString(set.reps, (W / 2) + 2, (H / 2) + 1); + g.setFont("6x8", 1); + const note = `Target reps: ${set.maxReps}`; + g.drawString(note, W / 2, H - 24); + // Draw sets monitor + g.drawString(exercise.subTitle, W / 2, H - 12); -function drawSetProgress(exercise) { - drawTitle(exercise); - drawReps(exercise); - drawSets(exercise); drawMenu({showBTN1: true, showBTN2: true, showBTN3: true}); + + g.flip(); } -function drawStartNextExercise() { - const title = "Good work"; - const msg = "No need to rest\nmove straight on\nto the next exercise"; - - g.setColor(WHITE); - g.setFont("Vector", 35); - g.drawString(title, centerStringX(title), 10); - g.setFont("Vector", 15); - g.drawString(msg, 30, 150); - drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); -} - -function drawProgramCompleted() { +function drawProgDone() { const title1 = "You did"; const title2 = "GREAT!"; const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest."; clearWatch(); setWatch(Bangle.showLauncher, BTN2, {repeat: false}); - - g.setColor(WHITE); - g.setFont("Vector", 35); - g.drawString(title1, centerStringX(title1), 10); - g.setFont("Vector", 40); - g.drawString(title2, centerStringX(title2), 50); - g.setFont("Vector", 15); - g.drawString(msg, 30, 150); - drawMenu({showBTN1: false, showBTN2: true, showBTN3: false}); -} - -/* -function drawExerciseCompleted(program) { - const exercise = program.currentExercise(); - const title = exercise.canProgress? - "WELL DONE!" : - "NOT BAD!"; - const msg = exercise.canProgress? - `You weight is automatically increased\nfor ${exercise.title} to ${exercise.weight}${exercise.unit}` : - "It looks like you struggled\non a few sets, your weight will\nstay the same"; - const action = "Move straight on to the next exercise"; - - clearScreen(); - g.setColor(WHITE); - g.setFont("Vector", 20); - g.drawString(title, centerStringX(title), 10); - g.setFont("Vector", 10); - g.drawString(msg, centerStringX(msg), 180); - g.drawString(action, centerStringX(action), 210); drawMenu({showBTN2: true}); - clearWatch(); - setWatch(() => { - init(program); - }, BTN2, {repeat: false}); + g.setFontAlign(0, -1); + g.setColor(WHITE); + g.setFont("6x8", 2); + g.drawString(title1, W / 2, 10); + g.drawString(title2, W / 2, 30); + g.setFont("6x8", 1); + g.drawString(msg, (W / 2) + 3, 70); + g.flip(); +} + +function drawSetComp() { + const title = "Good work"; + const msg = "No need to rest\nmove straight on\nto the next\nexercise.Your\nweight has been\nincreased for\nnext time!"; + + g.clear(); + drawMenu({showBTN2: true}); + + g.setFontAlign(0, -1); + g.setColor(WHITE); + g.setFont("6x8", 2); + g.drawString(title, W / 2, 10); + g.setFont("6x8", 1); + g.drawString(msg, (W / 2) - 2, 45); + + g.flip(); } -*/ function drawRestTimer(program) { const exercise = program.currentExercise(); const motivation = "Take a breather.."; - clearScreen(); - drawMenu({showBTN2: true}); - - g.setColor(PINK); - g.fillCircle(W / 2, H / 2, 50); - g.setColor(WHITE); - g.setFont("Vector", 15); - g.drawString(motivation, centerStringX(motivation), 25); - g.setFont("Vector", 40); - g.drawString(exercise.restPeriod, centerStringX(exercise.restPeriod), (H - 45) / 2); - exercise.decRestPeriod(); if (exercise.restPeriod <= 0) { exercise.resetRestTimer(); - redraw(program); + program.next(); + + return; } + + g.clear(); + drawMenu({showBTN2: true}); + g.setFontAlign(0, -1); + g.setColor(PINK); + g.fillRect(15, 42, W - 15, 80); + g.setColor(WHITE); + g.setFont("6x8", 1); + g.drawString("Have a short\nrest period.", W / 2, 10); + g.setFont("6x8", 5); + g.drawString(exercise.restPeriod, (W / 2) + 2, (H / 2) - 19); + g.flip(); + + exercise.decRestPeriod(); } function redraw(program) { const exercise = program.currentExercise(); - - clearScreen(); + g.clear(); if (program.isCompleted()) { - drawProgramCompleted(program); + saveProg(program); + drawProgDone(program); return; } if (exercise.isRestTimerRunning()) { if (exercise.isLastSet()) { - drawStartNextExercise(program); + drawSetComp(program); } else { drawRestTimer(program); } @@ -179,48 +137,141 @@ function redraw(program) { return; } - drawSetProgress(exercise); + drawSet(exercise); } -function init(program) { - clearWatch(); - program.next(); -} +function drawProgMenu(programs, selProgIdx) { + g.clear(); + g.setFontAlign(0, -1); + g.setColor(WHITE); + g.setFont("6x8", 2); + g.drawString("BuffGym", W / 2, 10); -// Setup training program. This should come from file - -// Squats -function buildPrograms() { - const programsJSON = require("Storage").readJSON("buffgym-programs.json", 1); - - if (!programsJSON) throw "No programs JSON found"; - - const programs = []; - - programsJSON.forEach(programJSON => { - const program = new Program({ - title: programJSON.title, - }); - const exercises = programJSON.exercises.map(exerciseJSON => { - const exercise = new Exercise({ - title: exerciseJSON.title, - weight: exerciseJSON.weight, - unit: exerciseJSON.unit, - }); - exerciseJSON.sets.forEach(setJSON => { - exercise.addSet(new Set(setJSON)); - }); - - return exercise; - }); - program.addExercises(exercises); - programs.push(program); + g.setFont("6x8", 1); + g.setFontAlign(-1, -1); + let selectedProgram = programs[selProgIdx].title; + let yPos = 50; + programs.forEach(program => { + g.setColor("#f05a56"); + g.fillRect(0, yPos, W, yPos + 11); + g.setColor("#ffffff"); + if (selectedProgram === program.title) { + g.drawRect(0, yPos, W - 1, yPos + 11); + } + g.drawString(program.title, 10, yPos + 2); + yPos += 15; }); - - return programs; + g.flip(); } -// For this spike, just run the first program, what will -// really happen is the user picks a program to do from -// some menu on a start page. -init(buildPrograms()[0]); \ No newline at end of file +function setupMenu() { + clearWatch(); + const progs = getProgIndex(); + let selProgIdx = 0; + drawProgMenu(progs, selProgIdx); + + setWatch(()=>{ + selProgIdx--; + if (selProgIdx< 0) selProgIdx = 0; + drawProgMenu(progs, selProgIdx); + }, BTN1, {repeat: true}); + + setWatch(()=>{ + const prog = buildProg(progs[selProgIdx].file); + prog.next(); + }, BTN2, {repeat: false}); + + setWatch(()=>{ + selProgIdx++; + if (selProgIdx > progs.length - 1) selProgIdx = progs.length - 1; + drawProgMenu(progs, selProgIdx); + }, BTN3, {repeat: true}); +} + +function drawSplash() { + g.reset(); + g.setBgColor(RED); + g.clear(); + g.setColor(WHITE); + g.setFontAlign(0,-1); + g.setFont("6x8", 2); + g.drawString("BuffGym", W / 2, 10); + g.setFont("6x8", 1); + g.drawString("5x5", W / 2, 42); + g.drawString("training app", W / 2, 55); + g.drawRect(19, 38, 100, 99); + const img = require("heatshrink").decompress(atob("lkdxH+AB/I5ASQACwpB5vNFkwpBAIfNFdZZkFYwskFZAsiFZBZiVYawEFf6ETFUwsIFUYmB54ADAwIskFYoRKBoIroB4grV58kkgCDFRotWFZwqHFiwYMFZIsTC5wLDFjGlCoWlkgJDRQIABCRAsLCwodCFAIABCwIOCFQYABr4RCCQIrMC4gqEAAwpFFZosFC5ArHFQ4rFNYQrGEgosMBxIrFLQwrLAB4sFSw4rFFjYrQFi4rNbASeEFjIoJFQYsGMAgAPEQgAIGwosCRoorbA=")); + g.drawImage(img, 40, 70); + g.flip(); + + let flasher = false; + let bgCol, txtCol; + const i = setInterval(() => { + if (flasher) { + bgCol = WHITE; + txtCol = RED; + } else { + bgCol = RED; + txtCol = WHITE; + } + flasher = !flasher; + g.setColor(bgCol); + g.fillRect(0, 108, W, 120); + g.setColor(txtCol); + g.drawString("Press btn to begin", W / 2, 110); + g.flip(); + }, 250); + + setWatch(()=>{ + clearInterval(i); + setupMenu(); + }, BTN1, {repeat: false}); + + setWatch(()=>{ + clearInterval(i); + setupMenu(); + }, BTN2, {repeat: false}); + + setWatch(()=>{ + clearInterval(i); + setupMenu(); + }, BTN3, {repeat: false}); +} + +function getProgIndex() { + const progIdx = require("Storage").readJSON("buffgym-program-index.json"); + return progIdx; +} + +function buildProg(fName) { + const Set = require("buffgym-set.js"); + const Exercise = require("buffgym-exercise.js"); + const Program = require("buffgym-program.js"); + const progJSON = require("Storage").readJSON(fName); + const prog = new Program({ + title: progJSON.title, + }); + const exercises = progJSON.exercises.map(exerciseJSON => { + const exercise = new Exercise({ + title: exerciseJSON.title, + weight: exerciseJSON.weight, + unit: exerciseJSON.unit, + restPeriod: exerciseJSON.restPeriod, + }); + exerciseJSON.sets.forEach(setJSON => { + exercise.addSet(new Set(setJSON)); + }); + + return exercise; + }); + prog.addExercises(exercises); + + return prog; +} + +function saveProg(program) { + const fName = getProgIndex().find(prog => prog.title === program.title).file; + require("Storage").writeJSON(fName, program.toJSON()); +} + +drawSplash(); \ No newline at end of file diff --git a/apps/buffgym/buffgym.png b/apps/buffgym/buffgym.png old mode 100644 new mode 100755 index 93a29a4a686f172e5e6dbd2ecb2a1d3edf4751c0..9bde64cc4b4a6cbea919ae5d61fe2f01694da589 GIT binary patch literal 7576 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 Date: Tue, 21 Apr 2020 20:10:56 +0100 Subject: [PATCH 44/77] Add README --- apps/buffgym/README.md | 43 +++++++++++++++++++++++++++++++++ apps/buffgym/buffgym-scrn1.png | Bin 0 -> 4141 bytes apps/buffgym/buffgym-scrn2.png | Bin 0 -> 2801 bytes apps/buffgym/buffgym-scrn3.png | Bin 0 -> 3569 bytes apps/buffgym/buffgym-scrn4.png | Bin 0 -> 3299 bytes apps/buffgym/buffgym-scrn5.png | Bin 0 -> 4500 bytes apps/buffgym/buffgym-scrn6.png | Bin 0 -> 3912 bytes 7 files changed, 43 insertions(+) create mode 100644 apps/buffgym/README.md create mode 100755 apps/buffgym/buffgym-scrn1.png create mode 100755 apps/buffgym/buffgym-scrn2.png create mode 100755 apps/buffgym/buffgym-scrn3.png create mode 100755 apps/buffgym/buffgym-scrn4.png create mode 100755 apps/buffgym/buffgym-scrn5.png create mode 100755 apps/buffgym/buffgym-scrn6.png diff --git a/apps/buffgym/README.md b/apps/buffgym/README.md new file mode 100644 index 000000000..e9e217828 --- /dev/null +++ b/apps/buffgym/README.md @@ -0,0 +1,43 @@ +# BuffGym + +This gym training assistant trains you on the famous [Stronglifts 5x5 workout](https://stronglifts.com/5x5) program. + +## Usage + +When you start the app it will wait on a splash screen until you are ready to start the work out. Press any of the buttons to start + +![](buffgym-scrn1.png) + +You are then presented with the programs menu, use BTN1 to move up the list, and BTN3 to move down the list. Once you have made your selection, press BTN2 to select the program. + +![](buffgym-scrn2.png) + +You will now begin moving through the exercises in the program. You will see the exercise information on the display. +1. At the top is the exercise name, e.g 'Squats' +2. Next is the weight you must train +3. In the center is where you record the number of *reps* you completed (more on that shortly) +4. Below the *reps* value, is the target reps you must try to reach. +5. Below the target reps is the current set you are training, out of the total sets for the exercise. +6. The *reps* value is used to store what you achieved for the current set, you enter this after you have trained on your current set. To alter this value, use BTN1 to increase the value (it will stop at the maximum required reps) and BTN3 to decreas the value to a minimum of 0 (this is the default value). Pressing BTN2 will confirm your reps + +![](buffgym-scrn3.png) + +You will then be presented with a rest timer screen, it counts down and automatically moves to the next exercise when it reaches 0. You can cancel the timer early if you wish by pressing BTN2. If it is the last set of an exercise, you don't need to rest, so it lets you know you have completed all the sets in the exercise and can start the next exercise. + +![](buffgym-scrn4.png) +![](buffgym-scrn5.png) + +Once all exercises are done, you are presented with a pat-on-the-back screen to tell you how awesome you are. + +![](buffgym-scrn6.png) + +## Features + +* If you successfully complete all reps and sets for an exercise, it will automatically update your weights for next time +* Has a neat rest timer to make sure you are training optimally +* Doesn't require a mobile phone, most 'smart watches' are just a visual presentation of the mobile phone app, this runs purley on the watch. So why not leave your phone and its distractions out of the gym! +* Clear and simple user interface + +## Created by + +[Paul Cockrell](https://github.com/paulcockrell) April 2020. \ No newline at end of file diff --git a/apps/buffgym/buffgym-scrn1.png b/apps/buffgym/buffgym-scrn1.png new file mode 100755 index 0000000000000000000000000000000000000000..07b79386f1503317acee9ff894d8dcf4c0035bc4 GIT binary patch literal 4141 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 literal 0 HcmV?d00001 diff --git a/apps/buffgym/buffgym-scrn2.png b/apps/buffgym/buffgym-scrn2.png new file mode 100755 index 0000000000000000000000000000000000000000..ec70fb79110bb029f286b66194fea8be4fe50e28 GIT binary patch literal 2801 zcmeHJT~t%q6~6c81_G&qM!*3faZNQ;$Kps?APU64A}vE?AV8rImeMlH@MAS3CI33M zqYDUQDJ}(*ahQUVhJb>^0Lf)hfhARHF+@}#%M1uyNPv(Z5<+@yANtg{K6I_l!#U^S z?C(4KoW1wA&(%{YiJN?beE|U2lyvg=r`Wpmeh|E{Ii4|h9RPe)Nym?*bMh7^KED3l zz!vc;_?1rXtTOE$w@lwq zGKKDX&lXDA&&3fCZ7Sa+4ZI@|=0SMw5pGLAEXyFI`s&)}D#jzyc76FHFaLGp$ zBzp328kK@P1H>Uj!ctZA$O|7rTjYNM##{No;WRU|Lp>I|u*1ZR6BHdN$@?({8NTXy zlg~mjB*FtX%CCq38Si+8_vcmz^}<;yqL0PNaStoji_YG9IxR&ea1QmAiIGaV1VJmR zrBma^%)CUUa^Aj*LOl++A+)U#_kw>UPVITS_{hBk^>B!I&c{przYj7z_NIw~a0xue zu(!%p_h;W^R&T5ygKytgXpdYUH?rMn+78XiZ*%FLG99l;Ni1_j{4Cx3o9;eFehV(! zidHixm{xAD)T^mQ$!l@PR`lk|Om65SL>L>%psBr+MQQD1J+TcSE|KBG;{Kq9`F*FN zc%9%JsVQfwSDQWcoZg``hQAX-?i2RCZi*pKhx1gc!weZ$JVl1p*;Nj0(!%*%vz^%!Aa3~-}7^U>M(7v z(iM6lnx=DhTTq*F;9pcWxFk-DcPxDA96YJOWf#-!0cx&Lr*%~uXP05sUbRg?&!-#4 zhz)>pQvv%T7-+~4$#G-+!RP!VoJHYk;TzNXUWrbR&%%80gPiWMQKeHapJwH%+tB^KBMlz(>hx@?mh39_RmaohvYJt2rt7&? zIe@lyRe(uK_PcK9#<0-K1YPv20X$hMbku4#l?EdnnnP1MJF(0Xu`7M*Qn_sVoL8pz z%IvZnb9!s6O^v;@AH9}ZW@EBLL-g9}@<)I&uWebmtE@BV%c8j#54IRy4TTc%a7=%I z;jeU7I0gCOYoJijats8Y0r(h8+9&zxG*RMO6t%{OP&U(i3%M%-Br8QJ6p}v%h!UrQ zVA!<2fwr51+?1Vz8X@TL6Xij1GEEejpo4#khdH&(3(!r`ds3fDU&2zjb_PCxv9G6- zwg>ndQUy*xeL1)qxrr%N)5AP?b6{4W!Hg?S(HAaWX5Zg# zI+LK1p&E5PpbXRuIUwFwRWY34VO)>(ny2FHhZ~;33i?bA0_YI2j@`k($*))LDqj2>rsu%SaG+Tkeg$b4Fn) z^{(r0IvWf3A@aw&C>JgXG0g8nC#fDZhO6z=I13FX;uC5ATPf;8SgIFz1sc#R#g8lN z@SMj5lI^2i_Y=c|je8(yoljMlK2qKn&n$l~9>hDwUl&`=SRR`nHjY`s#ah^rD(}jI z%sUO4Kbks2R=m9f30}JIgp`h(cVbrUl8oh3ASjp}$gyz=geC4mBjYeuEM)a^ojVMp z4|9DM;1}RnS!8-v^*&_vS{+{qf*Ma)cHd<@?C7g6owEn|8(ii)0f)0NT+dpa;NJ$- zeoK=~A#cC)?|-r|pKv?-@Q!nbu0Kl@rS;|LFzvNwLL<&Ir^&C|?fIqd1#~b*r_Ss0 zEF_f7BrcW&AQ$gL>%qxj%1Et~gl{Do6x3f@kIgEx5+}6mc-^lVmV2$4#!`h){!HRv zorvIT0k%w~%XwkK!p)4OWXj&C0W%-^Ry^yqyH{A0J6E`{8gZ;gFs6)`bGI_%>bqyC zNMam_=jg>3M%y8*yVwH+R#J>RP`%PR!|bJ{>*X7|L)T2!k_5X1t9kB zL@e3M=Hv_#b0k literal 0 HcmV?d00001 diff --git a/apps/buffgym/buffgym-scrn3.png b/apps/buffgym/buffgym-scrn3.png new file mode 100755 index 0000000000000000000000000000000000000000..0888fc507c229f1eb1b757770531a56ffa63b63e GIT binary patch literal 3569 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 DipYXY literal 0 HcmV?d00001 diff --git a/apps/buffgym/buffgym-scrn4.png b/apps/buffgym/buffgym-scrn4.png new file mode 100755 index 0000000000000000000000000000000000000000..3078d25dce7b2b114c17804571e16c858aaf2d7f GIT binary patch literal 3299 zcmeH~X;4#H7RSTO6M|w4FcAR*aRC((5k#D@7(g}`pxJ^5Bx<)oY(bHL>^zsYU2#Ag zv;`S)5E3BTfRF@8zy)PT36Uibki||Q1n2+)N#@zse3+@44>M&=)lAKY_g=lKbN}bu zbL#)Qb+7n%xvyMqupEIvtn~EQ>kEHnpC6Pu{B{iZH3NarqI>Rj@;?_gk>ix1`$lK) zWkdP-W$r^BYp*O@5xMhNSKbbZ)m2$x%pI!Pz(6wNw)=3?IWw%z^T(4>Q7Ywg6&?YZ zXeK#}OxkV~tdn^mAbk*JegFaKIobzbMgZ1GOi(rg*q(H*9IXZ(SI0lGR0G52W#Kpg z)vQIN905?(vcV1lh{@JZ%1c9&p?l;a3sg)UKaX;pgH zx-?!h0$gpH##>=*RN{hw?yCKLLLI2mcwj)FSXy!oP8B>nw8%cGLM7?_`cl$t)>xb@ zr1dqSLU8^xg+(4Sm>O7HHcJz%#mhn;=`pPtn?L`Z;a2m~k&b|aV^hF|)3Ko~+=RTc z;Ro`m_k!-Sr#-4aO-|9MW3*SaXH+?3j9i0;Qgxk0>G?xC>d@9@4W-*RovsL#=gf`c zxa>^(QZlwyOs)yzGo#r|W*6sNuCRmQO%$_8A%UEmJT7;2{A?OqBVSxe7bGWF7(rWy z+E}&sd1Bl@0JKp(wx*ujwAaEPy8GZUitF>#zc5^Jv~*KN^fif_1%REr6qvgbO7?MeGbio^Q`lkR&Xm>MpOTA7Vg0 zFZ~4p&M{2#1oyBzHorGLv8LzoNfl$bx|m0L0JY_I(A5YWWihq0BmEGphC1L*xoanj84gDQ zx)`FU&ZW>X82!q7ahfxi99MIq&e*_3RF~O9dm`?kWj$F5;rY(Fe0{}> zGsBFO`ayJYZc-Euc(9aAfhT~c4Nx#un+n(qBglG>VV|b3QBTw z7)p3<>(h9b_gs>q(ST}wJN6fjvW}G?bU&xuikTwK0vCnQI7m zCs<}yT;gToP!q&F*e`bFK`Wp)D7@@j4QD&dM|dXaZC%b3D*$ER4Yi{|*o##z*D5gC z*AaksEWR8G!OoSoAKeC;Zh#g4_hc}-^Aj_@-);`q06u^z%K1MUz4ai9)Xjf#&V!qc zU03QtISMytYOvh^Gy_l}+Cv1;6y}evF}lR*pM>lSRn2bm`y>$@5DI5cKD^E|y)~OH zR8Oc>+*4PF4&odWn@>6Ghh}u{jc1)0=V-dEp-ujjW;h zP*twCd&m*oh)}txQ$dd}puy5x8VWDmF<29qDz(R!2a{U%=eTzm0}PFi!H>~_5tKd! zYo_z8kAxmyG(!}T!GcfeJw<<85U{(V^j;QW73fBxxeW-4E-=yMcHYA4u#DdvWAtv< zly(p3d-EHOtu~fYWna8m_?LJouMgtukD!zqAtxeJkxx&mf= z$Les|c25ZTeGm&tDyzo@)mT63pAy2w&@~f7NWYgOLO0`raym?;JbE_$w6uEl_|(g# zEx+x49#%h&{2-00tnS~b#dH%Lx!8i3Bic4)H3=0HKaqf03nFEE8==Lao%XVSd0Z-I zL>|8CKN7bFJ3rAdH}^wIigLZptL;zwklT(#nMco69u7lR9NPleZFbz?f?J|?23q-X zV|-bU7X04p3qr6}iDSv-@MazCX+C`WIreS5S(bllWUH$YFrXD;@fb~C8y=Revv(vz z+;*LH)kSpGN6aP^7Abwt7l!yMgh@uIBoNEZocHV$_ADj{q%B&}e4?Vp-6?I|A{4H;f1YvGMVi}Mg~3So(G&#HW_pibrn}>1h@G89CPi_>{uy7st0LT*=&_Ufis<^!u7w) zF1k{{$d;>#d3^f{&wp7?4;zFte}`W(&NS$R4Nb63d41$7nE2nJMaCM`Mil<^d4kP4 z3XCz+TQ7)sCj_M1S){3^s|JH+qdK4opzh~+9YkfLV4`f?f$@M31CSQs%-f5A8Fd9B zo<{(i3jK5eQ=k|1{gA5`_{?QdiF#eu|B09E2|~2v1k9 Ky`|2S^M3`WxUwt& literal 0 HcmV?d00001 diff --git a/apps/buffgym/buffgym-scrn5.png b/apps/buffgym/buffgym-scrn5.png new file mode 100755 index 0000000000000000000000000000000000000000..b34a5b124aba6acacdcd671c2401563958faa509 GIT binary patch literal 4500 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 HT+Y7%cOZEH literal 0 HcmV?d00001 From a49397ed3dac75b38e3fd3537fe080d2a661a5a4 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 20:11:32 +0100 Subject: [PATCH 45/77] Disable emulator --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 4eeee4e32..139192339 100644 --- a/apps.json +++ b/apps.json @@ -1302,6 +1302,7 @@ "description": "BuffGym is the famous 5x5 workout program for the BangleJS", "tags": "tool,outdoors", "type": "app", + "allow_emulator": false, "storage": [ {"name":"buffgym"}, {"name":"buffgym.app.js", "url": "buffgym.app.js"}, From 5f19c8bd80688b8f78c139b7185b5e19b2812f5d Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 21 Apr 2020 20:22:26 +0100 Subject: [PATCH 46/77] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 0b7001a5e..8df240cf6 100644 --- a/apps.json +++ b/apps.json @@ -297,6 +297,7 @@ "version":"0.01", "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording", "tags": "tool,outdoors,gps", + "readme": "README.md", "storage": [ {"name":"gpsnav.app.js","url":"app.js"}, {"name":"waypoints.json","url":"waypoints.json","evaluate":false}, From b5fd14b4fb39e313544758f35950d9068f738fe0 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 20:45:02 +0100 Subject: [PATCH 47/77] Add training programs to apps file --- apps.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 139192339..4b51a4689 100644 --- a/apps.json +++ b/apps.json @@ -1309,7 +1309,9 @@ {"name":"buffgym-set.js","url":"buffgym-set.js"}, {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, {"name":"buffgym-program.js","url":"buffgym-program.js"}, - {"name":"buffgym-programs.json","url":"buffgym-programs.json"}, + {"name":"buffgym-program-a.json","url":"buffgym-program-a.json"}, + {"name":"buffgym-program-b.json","url":"buffgym-program-b.json"}, + {"name":"buffgym-program-index.json","url":"buffgym-program-index.json"}, {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} ] } From 7e305033814aa2946c68686d82e94f85e70cbf6f Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 20:46:30 +0100 Subject: [PATCH 48/77] Add readme to apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 4b51a4689..d800050ee 100644 --- a/apps.json +++ b/apps.json @@ -1303,6 +1303,7 @@ "tags": "tool,outdoors", "type": "app", "allow_emulator": false, + "readme": "README.md", "storage": [ {"name":"buffgym"}, {"name":"buffgym.app.js", "url": "buffgym.app.js"}, From 14e209b020c0eca0e54fc591c378c8a52f1fab4b Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 20:47:45 +0100 Subject: [PATCH 49/77] Add tags to buffgym app in apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index d800050ee..96f758c07 100644 --- a/apps.json +++ b/apps.json @@ -1300,7 +1300,7 @@ "icon": "buffgym.png", "version":"0.01", "description": "BuffGym is the famous 5x5 workout program for the BangleJS", - "tags": "tool,outdoors", + "tags": "tools,outdoors,gym,exercise", "type": "app", "allow_emulator": false, "readme": "README.md", From bb9747da0924adbef19929b29c833bdc707fd70d Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 20:51:15 +0100 Subject: [PATCH 50/77] Add app comments --- apps/buffgym/buffgym.app.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index eeabd5c29..4dc6ffd5a 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -1,3 +1,14 @@ +/** + * BangleJS Stronglifts 5x5 training aid + * + * Original Author: Paul Cockrell https://github.com/paulcockrell + * Created: April 2020 + * + * Inspired by: + * - Stronglifts 5x5 training program https://stronglifts.com/5x5/ + * - Stronglifts smart watch app + */ + Bangle.setLCDMode("120x120"); const W = g.getWidth(); From 94bb31889cba0b31be983a6dcfda7d506c367fa0 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 21 Apr 2020 21:14:18 +0100 Subject: [PATCH 51/77] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 96f758c07..65f0090b3 100644 --- a/apps.json +++ b/apps.json @@ -1300,7 +1300,7 @@ "icon": "buffgym.png", "version":"0.01", "description": "BuffGym is the famous 5x5 workout program for the BangleJS", - "tags": "tools,outdoors,gym,exercise", + "tags": "tool,outdoors,gym,exercise", "type": "app", "allow_emulator": false, "readme": "README.md", From 26d8855ea20bba5d7833fe331d4696f15d602e98 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 21 Apr 2020 23:13:04 +0200 Subject: [PATCH 52/77] locale: Measure temperature in Kelvin Because that is what Gadgetbridge sends for the weather --- apps.json | 2 +- apps/locale/ChangeLog | 1 + apps/locale/locale.html | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 1cacc920e..95a845f54 100644 --- a/apps.json +++ b/apps.json @@ -65,7 +65,7 @@ { "id": "locale", "name": "Languages", "icon": "locale.png", - "version":"0.06", + "version":"0.07", "description": "Translations for different countries", "tags": "tool,system,locale,translate", "type": "locale", diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index 3d983150d..a3cc0c9a3 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -6,3 +6,4 @@ Add correct scaling for speed/distance/temperature 0.06: Remove translations if not required Ensure 'on' is always supplied for translations +0.07: Measure temperature in Kelvin diff --git a/apps/locale/locale.html b/apps/locale/locale.html index 21bf37f29..936d2e9f0 100644 --- a/apps/locale/locale.html +++ b/apps/locale/locale.html @@ -112,8 +112,8 @@ exports = { name : "en_GB", currencySym:"£", `${js(locale.currency_symbol)} + n.toFixed(2)`: `n.toFixed(2) + ${js(locale.currency_symbol)}`; var temperature; - if (locale.temperature=='°C') temperature="t"; - else if (locale.temperature=='°F') temperature="(t*9/5)+32"; + if (locale.temperature=='°C') temperature="(t-273.15)"; + else if (locale.temperature=='°F') temperature="((t-273.15)*9/5)+32"; else throw new Error("Unknown temperature unit "+locale.temperature); var localeModule = `var l = ${JSON.stringify({ From 319307cdd1831b27a94b6a9150cf24e24379ae22 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 21 Apr 2020 23:18:21 +0200 Subject: [PATCH 53/77] weather: Show Gadgetbridge weather reports Based on http://forum.espruino.com/comments/15194626/, where NebbishHacker did most of the actual work :-) --- apps.json | 17 ++++ apps/weather/app.js | 54 +++++++++++ apps/weather/icon.js | 1 + apps/weather/icon.png | Bin 0 -> 1173 bytes apps/weather/lib.js | 176 ++++++++++++++++++++++++++++++++++++ apps/weather/readme.md | 16 ++++ apps/weather/screenshot.png | Bin 0 -> 4039 bytes apps/weather/widget.js | 40 ++++++++ 8 files changed, 304 insertions(+) create mode 100644 apps/weather/app.js create mode 100644 apps/weather/icon.js create mode 100644 apps/weather/icon.png create mode 100644 apps/weather/lib.js create mode 100644 apps/weather/readme.md create mode 100644 apps/weather/screenshot.png create mode 100644 apps/weather/widget.js diff --git a/apps.json b/apps.json index 95a845f54..3921e8ae1 100644 --- a/apps.json +++ b/apps.json @@ -348,6 +348,23 @@ {"name":"files.img","url":"files-icon.js","evaluate":true} ] }, + { "id": "weather", + "name": "Weather", + "icon": "icon.png", + "version":"0.01", + "description": "Show Gadgetbridge weather report", + "readme": "readme.md", + "tags": "widget,outdoors", + "storage": [ + {"name":"weather.app.js","url":"app.js"}, + {"name":"weather.wid.js","url":"widget.js"}, + {"name":"weather","url":"lib.js"}, + {"name":"weather.img","url":"icon.js","evaluate":true} + ], + "data": [ + {"name": "weather.json"} + ] + }, { "id": "widbat", "name": "Battery Level Widget", "icon": "widget.png", diff --git a/apps/weather/app.js b/apps/weather/app.js new file mode 100644 index 000000000..fdf28f0e0 --- /dev/null +++ b/apps/weather/app.js @@ -0,0 +1,54 @@ +(() => { + function draw(w) { + g.reset(); + g.setColor(0).fillRect(0, 24, 239, 239); + + require('weather').drawIcon(w.txt, 65, 90, 55); + const locale = require("locale"); + + g.setColor(-1); + + const temp = locale.temp(w.temp).match(/^(\D*\d*)(.*)$/); + let width = g.setFont("Vector", 40).stringWidth(temp[1]); + width += g.setFont("Vector", 20).stringWidth(temp[2]); + g.setFont("Vector", 40).setFontAlign(-1, -1, 0); + g.drawString(temp[1], 180-width/2, 70); + g.setFont("Vector", 20).setFontAlign(1, -1, 0); + g.drawString(temp[2], 180+width/2, 70); + + g.setFont("6x8", 1); + g.setFontAlign(-1, 0, 0); + g.drawString("Humidity", 135, 130); + g.drawString("Wind", 135, 142); + g.setFontAlign(1, 0, 0); + g.drawString(w.hum+"%", 225, 130); + g.drawString(locale.speed(w.wind), 225, 142); + + g.setFont("6x8", 2).setFontAlign(0, 0, 0); + g.drawString(w.loc, 120, 170); + + g.setFont("6x8", 1).setFontAlign(0, 0, 0); + g.drawString(w.txt.charAt(0).toUpperCase()+w.txt.slice(1), 120, 190); + + g.flip(); + } + + const _GB = global.GB; + global.GB = (event) => { + if (event.t==="weather") draw(event); + if (_GB) setTimeout(_GB, 0, event); + }; + + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + const weather = require('weather').load(); + if (weather) { + draw(weather); + } else { + E.showMessage('Weather unknown\n\nIs Gadgetbridge\nconnected?'); + } + + // Show launcher when middle button pressed + setWatch(Bangle.showLauncher, BTN2, {repeat: false, edge: 'falling'}) +})() diff --git a/apps/weather/icon.js b/apps/weather/icon.js new file mode 100644 index 000000000..18ca2b0c9 --- /dev/null +++ b/apps/weather/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AE8N6AXV7vdFyoXBGCQUBAAoXp73u93tC6YWBAAIXSFwQwDRiAWDGASSBmYABIx5IDgYXCmC7KCoYRBnvUCwQwKC4gSEAAgwKC5gwKCwPjC6inBC6owBC6wVKPBXd6YXMDBAuNJJQXWfwZITC/6QIBw073ezR6m73anOJAwuHeBAYFIw4WJAAsL3YQOAAxeBCiWIC4e72AJChGACpMIxAXBIwIwEBIIXKBgouDEIYuLC4ghEC6ELLoYXPU4YXFLxQNBBgcLEQqqQFwYA/AH4AYA==")) diff --git a/apps/weather/icon.png b/apps/weather/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bbfc0ace0b8d25c4afefcb336ea04df799a70f22 GIT binary patch literal 1173 zcmV;G1Zw+fgKelF z+6!B~5F)8y)e1%MqEWnPiWg$RgkaGND+=ED(@M!jy(#RCC2ci@HZ&m;H8wSEeq1-3 zna_*eO*h%I$(hL}OJN@v*!|9#@4WBKnQzV+C{Un)Z={DV>E%eib@(DFUXn-NOejAm zNe^8p4lfCJt4`j{fhJF^Xh3?ARSnST?;@FEt!47{!1jEGWkFpPY~BdvcO+sr|AoPp7;j(Z^c9nYrv8 zkRG}g{?t`1FFr+i3Dj4?(4UDMy&OqZr_)1HX<73JfL%aC@{G&CN!PWHJ+npq?bSfm z3XxGNw?6LPs7g_(j(pdPtX6NkmEpEmb0c6>eVOf?QhKnNuV{Lt@F=40(L-~ zBr4U6#P%`av@$0Zg!qTMN57+X49^FVjkbLQP)KEm&RPQbv6&-%R5y%N$)W|^G z3HAX4eumxfNt%QZOugspBgMdEG}xzWFfy>SLB*_~-Ht~Sp@@Yn(5USLDV>K=tk6T&Gr@s zpI_!oxJY!Hg>_~@60*CA@DI5jXU)oJfI#||^z>SYhgIBx&7a<=4-nV|vaT9J`>ZY?00000NkvXXu0mjfi9tF% literal 0 HcmV?d00001 diff --git a/apps/weather/lib.js b/apps/weather/lib.js new file mode 100644 index 000000000..f87984fe5 --- /dev/null +++ b/apps/weather/lib.js @@ -0,0 +1,176 @@ +exports = { + save: weather => { + let json = require('Storage').readJSON('weather.json')||{} + json.weather = Object.assign({}, weather) // don't mutate GB events + delete json.weather.t // don't save the event type (if present) + require('Storage').write('weather.json', json) + }, + load: () => { + let json = require('Storage').readJSON('weather.json')||{} + return json.weather + }, + drawIcon: (cond, x, y, r) => { + function drawSun(x, y, r) { + g.setColor("#FF7700"); + g.fillCircle(x, y, r); + } + + function drawCloud(x, y, r, c) { + const u = r/12; + if (c==null) c = "#EEEEEE"; + g.setColor(c); + g.fillCircle(x-8*u, y+3*u, 4*u); + g.fillCircle(x-4*u, y-2*u, 5*u); + g.fillCircle(x+4*u, y+0*u, 4*u); + g.fillCircle(x+9*u, y+4*u, 3*u); + g.fillPoly([ + x-8*u, y+7*u, + x-8*u, y+3*u, + x-4*u, y-2*u, + x+4*u, y+0*u, + x+9*u, y+4*u, + x+9*u, y+7*u, + ]); + } + + function drawBrokenClouds(x, y, r) { + drawCloud(x+1/8*r, y-1/8*r, 7/8*r, "#777777"); + drawCloud(x-1/8*r, y+1/8*r, 7/8*r); + } + + function drawFewClouds(x, y, r) { + drawSun(x+3/8*r, y-1/8*r, 5/8*r); + drawCloud(x-1/8*r, y+1/8*r, 7/8*r); + } + + function drawRainLines(x, y, r) { + g.setColor("#FFFFFF"); + const y1 = y+1/2*r; + const y2 = y+1*r; + g.fillPoly([ + x-6/12*r+1, y1, + x-8/12*r+1, y2, + x-7/12*r, y2, + x-5/12*r, y1, + ]); + g.fillPoly([ + x-2/12*r+1, y1, + x-4/12*r+1, y2, + x-3/12*r, y2, + x-1/12*r, y1, + ]); + g.fillPoly([ + x+2/12*r+1, y1, + x+0/12*r+1, y2, + x+1/12*r, y2, + x+3/12*r, y1, + ]); + } + + function drawShowerRain(x, y, r) { + drawFewClouds(x, y-1/3*r, r); + drawRainLines(x, y, r); + } + + function drawRain(x, y, r) { + drawBrokenClouds(x, y-1/3*r, r); + drawRainLines(x, y, r); + } + + function drawThunderstorm(x, y, r) { + function drawLightning(x, y, r) { + g.setColor("#FF7700"); + g.fillPoly([ + x-2/6*r, y-r, + x-4/6*r, y+1/6*r, + x-1/6*r, y+1/6*r, + x-3/6*r, y+1*r, + x+3/6*r, y-1/6*r, + x+0/6*r, y-1/6*r, + x+3/6*r, y-r, + ]); + } + + drawBrokenClouds(x, y-1/3*r, r); + drawLightning(x-1/12*r, y+1/2*r, 1/2*r); + } + + function drawSnow(x, y, r) { + function rotatePoints(points, pivotX, pivotY, angle) { + for(let i = 0; i {}; + condition = condition.toLowerCase(); + if (condition.includes("thunderstorm")) return drawThunderstorm; + if (condition.includes("freezing")||condition.includes("snow")|| + condition.includes("sleet")) { + return drawSnow; + } + if (condition.includes("drizzle")|| + condition.includes("shower")) { + return drawRain; + } + if (condition.includes("rain")) return drawShowerRain; + if (condition.includes("clear")) return drawSun; + if (condition.includes("few clouds")) return drawFewClouds; + if (condition.includes("scattered clouds")) return drawCloud; + if (condition.includes("clouds")) return drawBrokenClouds; + return drawMist; + } + + chooseIcon(cond)(x, y, r) + }, +} diff --git a/apps/weather/readme.md b/apps/weather/readme.md new file mode 100644 index 000000000..a326b67dd --- /dev/null +++ b/apps/weather/readme.md @@ -0,0 +1,16 @@ +# Weather + +Shows Gadgetbridge weather reports. + +This adds a widget with a weather pictogram and the temperature. +You can view the full report through the app: +![Screenshot](screenshot.png) + +## Setup + +See [this guide](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather) +to setup Gadgetbridge weather reporting. + +## Controls + +BTN2: opens the launcher diff --git a/apps/weather/screenshot.png b/apps/weather/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..ce79b3b646bfebdad6c29f57779c018ce0ce457e GIT binary patch literal 4039 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 Fe*nCRR)+up literal 0 HcmV?d00001 diff --git a/apps/weather/widget.js b/apps/weather/widget.js new file mode 100644 index 000000000..7488b7657 --- /dev/null +++ b/apps/weather/widget.js @@ -0,0 +1,40 @@ +(() => { + function draw() { + const w = require('weather').load() + if (!w) return; + g.reset(); + g.setColor(0).fillRect(this.x, this.y, this.x+this.width, this.y+24) + if (w.txt) { + require('weather').drawIcon(w.txt, this.x+10, this.y+8, 8); + } + if (w.temp) { + let t = require('locale').temp(w.temp); // applies conversion + t = t.substr(0, t.length-2); // but we have no room for units + g.setFontAlign(0, 1); // center horizontally at bottom of widget + g.setFont('6x8', 1); + g.setColor(-1) + g.drawString(t, this.x+10, this.y+24) + } + } + + function update(weather) { + require('weather').save(weather); + if (!WIDGETS["weather"].width) { + WIDGETS["weather"].width = 20 + Bangle.drawWidgets() + } else if (Bangle.isLCDOn()) { + WIDGETS["weather"].draw() + } + } + + const _GB = global.GB; + global.GB = (event) => { + if (event.t==="weather") update(event); + if (_GB) setTimeout(_GB, 0, event); + }; + + WIDGETS["weather"] = {area: "tl", width: 20, draw: draw}; + if (!require('weather').load()) { + WIDGETS["weather"].width = 0 + } +})(); From 06fc54f83171cf175af359e2113cc239e24cad4c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 22 Apr 2020 08:56:50 +0100 Subject: [PATCH 54/77] oops - fix sanity check errors --- apps.json | 3 +-- apps/buffgym/buffgym-icon.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 70fb6cac7..84b8fb643 100644 --- a/apps.json +++ b/apps.json @@ -1332,7 +1332,6 @@ "allow_emulator": false, "readme": "README.md", "storage": [ - {"name":"buffgym"}, {"name":"buffgym.app.js", "url": "buffgym.app.js"}, {"name":"buffgym-set.js","url":"buffgym-set.js"}, {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, @@ -1438,7 +1437,7 @@ { "id": "osmpoi", "name": "POI Compass", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Uploads all the points of interest in an area onto your watch, same as Beer Compass with more p.o.i.", "tags": "tool,outdoors,gps", "custom": "osmpoi.html", diff --git a/apps/buffgym/buffgym-icon.js b/apps/buffgym/buffgym-icon.js index 31764acbb..523ed35b6 100644 --- a/apps/buffgym/buffgym-icon.js +++ b/apps/buffgym/buffgym-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwxH+ACPI5AUSADAtB5vNGFQtBAIfNF95hoF4wwoF5AwmF5BhmXYbAEF/6QbF1QwIF04qB54ADAwIwoF4oRKBoIvsB4gvZ58kkgCDFxoxaF5wuHGDQcMF5IwXDZwLDGDmlDIWlkgJDSwIABCRAwPDQohCFgIABDQIOCFwYABr4RCCQIvQDYguEAAwtFF5owJDZAvHFw4vFOYQvKFAowMBxIvFMQwvPAB4wFUQ4vJGDYvUGC4vNdgyuEGDIsNFwYwGNAgAPExAvMGIdfTIovfTpYvrfRCOkZ44ugF44NGF05gUFyQvKGIoueGKIufGJ4uhG5oupGItfr4vvAAgvlGAQvt/wrEF9oEGF841IF9QGHX0oGIAD8kAAYJOFzwEBBQoMFACA=")); \ No newline at end of file +require("heatshrink").decompress(atob("mEwxH+ACPI5AUSADAtB5vNGFQtBAIfNF95hoF4wwoF5AwmF5BhmXYbAEF/6QbF1QwIF04qB54ADAwIwoF4oRKBoIvsB4gvZ58kkgCDFxoxaF5wuHGDQcMF5IwXDZwLDGDmlDIWlkgJDSwIABCRAwPDQohCFgIABDQIOCFwYABr4RCCQIvQDYguEAAwtFF5owJDZAvHFw4vFOYQvKFAowMBxIvFMQwvPAB4wFUQ4vJGDYvUGC4vNdgyuEGDIsNFwYwGNAgAPExAvMGIdfTIovfTpYvrfRCOkZ44ugF44NGF05gUFyQvKGIoueGKIufGJ4uhG5oupGItfr4vvAAgvlGAQvt/wrEF9oEGF841IF9QGHX0oGIAD8kAAYJOFzwEBBQoMFACA=")) From 6d07882eae4bb6a8b4d17c7bdac38c9ec6cbe0af Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 22 Apr 2020 10:59:00 +0200 Subject: [PATCH 55/77] Revert "locale: Measure temperature in Kelvin" This reverts commit 26d8855e --- apps.json | 2 +- apps/locale/ChangeLog | 1 - apps/locale/locale.html | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 3921e8ae1..3a76c645b 100644 --- a/apps.json +++ b/apps.json @@ -65,7 +65,7 @@ { "id": "locale", "name": "Languages", "icon": "locale.png", - "version":"0.07", + "version":"0.06", "description": "Translations for different countries", "tags": "tool,system,locale,translate", "type": "locale", diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index a3cc0c9a3..3d983150d 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -6,4 +6,3 @@ Add correct scaling for speed/distance/temperature 0.06: Remove translations if not required Ensure 'on' is always supplied for translations -0.07: Measure temperature in Kelvin diff --git a/apps/locale/locale.html b/apps/locale/locale.html index 936d2e9f0..21bf37f29 100644 --- a/apps/locale/locale.html +++ b/apps/locale/locale.html @@ -112,8 +112,8 @@ exports = { name : "en_GB", currencySym:"£", `${js(locale.currency_symbol)} + n.toFixed(2)`: `n.toFixed(2) + ${js(locale.currency_symbol)}`; var temperature; - if (locale.temperature=='°C') temperature="(t-273.15)"; - else if (locale.temperature=='°F') temperature="((t-273.15)*9/5)+32"; + if (locale.temperature=='°C') temperature="t"; + else if (locale.temperature=='°F') temperature="(t*9/5)+32"; else throw new Error("Unknown temperature unit "+locale.temperature); var localeModule = `var l = ${JSON.stringify({ From c3940972b58039afc7a60df46a49b512f3ab3b54 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 22 Apr 2020 11:00:16 +0200 Subject: [PATCH 56/77] weather: Convert Gadgetbridge temperature from Kelvin to Celsius --- apps/weather/app.js | 2 +- apps/weather/widget.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/weather/app.js b/apps/weather/app.js index fdf28f0e0..8493144f7 100644 --- a/apps/weather/app.js +++ b/apps/weather/app.js @@ -8,7 +8,7 @@ g.setColor(-1); - const temp = locale.temp(w.temp).match(/^(\D*\d*)(.*)$/); + const temp = locale.temp(w.temp-273.15).match(/^(\D*\d*)(.*)$/); let width = g.setFont("Vector", 40).stringWidth(temp[1]); width += g.setFont("Vector", 20).stringWidth(temp[2]); g.setFont("Vector", 40).setFontAlign(-1, -1, 0); diff --git a/apps/weather/widget.js b/apps/weather/widget.js index 7488b7657..e02591543 100644 --- a/apps/weather/widget.js +++ b/apps/weather/widget.js @@ -8,7 +8,7 @@ require('weather').drawIcon(w.txt, this.x+10, this.y+8, 8); } if (w.temp) { - let t = require('locale').temp(w.temp); // applies conversion + let t = require('locale').temp(w.temp-273.15); // applies conversion t = t.substr(0, t.length-2); // but we have no room for units g.setFontAlign(0, 1); // center horizontally at bottom of widget g.setFont('6x8', 1); From bf5bf91967eb37d703533ce775f57aa8b31696f8 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 22 Apr 2020 13:17:31 +0100 Subject: [PATCH 57/77] mclock: Improve performance, attempt to remove occasional glitch when LCD on (fix #279) --- apps.json | 2 +- apps/mclock/ChangeLog | 1 + apps/mclock/clock-morphing.js | 107 ++++++++++++++++++++-------------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/apps.json b/apps.json index 837b94669..65b681390 100644 --- a/apps.json +++ b/apps.json @@ -108,7 +108,7 @@ { "id": "mclock", "name": "Morphing Clock", "icon": "clock-morphing.png", - "version":"0.03", + "version":"0.04", "description": "7 segment clock that morphs between minutes and hours", "tags": "clock", "type":"clock", diff --git a/apps/mclock/ChangeLog b/apps/mclock/ChangeLog index e6a689e9e..4bc1ea352 100644 --- a/apps/mclock/ChangeLog +++ b/apps/mclock/ChangeLog @@ -1,2 +1,3 @@ 0.02: Modified for use with new bootloader and firmware 0.03: Added Locale based date +0.04: Improve performance, attempt to remove occasional glitch when LCD on (fix #279) diff --git a/apps/mclock/clock-morphing.js b/apps/mclock/clock-morphing.js index ce30ad033..e9365db52 100644 --- a/apps/mclock/clock-morphing.js +++ b/apps/mclock/clock-morphing.js @@ -1,14 +1,15 @@ var locale = require("locale"); +var CHARW = 34; // how tall are digits? +var CHARP = 2; // how chunky are digits? +var Y = 50; // start height // Offscreen buffer -var buf = Graphics.createArrayBuffer(240,86,1,{msb:true}); -function flip() { - g.setColor(1,1,1); - g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},0,50); -} +var buf = Graphics.createArrayBuffer(CHARW+CHARP*2,CHARW*2 + CHARP*2,1,{msb:true}); +var bufimg = {width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer}; // The last time that we displayed var lastTime = " "; // If animating, this is the interval's id var animInterval; +var timeInterval; /* Get array of lines from digit d to d+1. n is the amount (0..1) @@ -49,7 +50,7 @@ const DIGITS = { [0,1,1,1], [1,1,1,2], [1-n,2,1,2]], -"5": (n,maxFive)=>maxFive ? [ // 5 -> 0 +"5to0": n=>[ // 5 -> 0 [0,0,0,1], [0,0,1,0], [n,1,1,1], @@ -57,7 +58,8 @@ const DIGITS = { [0,2,1,2], [0,2,0,2], [1,1-n,1,1], -[0,1,0,1+n]] : [ // 5 -> 6 +[0,1,0,1+n]], +"5to6": n=>[ // 5 -> 6 [0,0,0,1], [0,0,1,0], [0,1,1,1], @@ -109,59 +111,66 @@ const DIGITS = { /* Draw a transition between lastText and thisText. 'n' is the amount - 0..1 */ -function draw(lastText,thisText,n) { - buf.clear(); - var x = 1; // x offset - const p = 2; // padding around digits - var y = p; // y offset - const s = 34; // character size +function drawDigits(lastText,thisText,n) { + const p = CHARP; // padding around digits + const s = CHARW; // character size + var x = 0; // x offset + g.reset(); for (var i=0;i{ + if (c[0]!=c[2]) // horiz + buf.fillRect(p+c[0]*s,c[1]*s,p+c[2]*s,2*p+c[3]*s); + else if (c[1]!=c[3]) // vert + buf.fillRect(c[0]*s,p+c[1]*s,2*p+c[2]*s,p+c[3]*s); + }); + g.drawImage(bufimg,x,Y); } - var l = DIGITS[ch](chn,lastCh==5 && thisCh==0); - l.forEach(c=>{ - if (c[0]!=c[2]) // horiz - buf.fillRect(x+c[0]*s,y+c[1]*s-p,x+c[2]*s,y+c[3]*s+p); - else if (c[1]!=c[3]) // vert - buf.fillRect(x+c[0]*s-p,y+c[1]*s,x+c[2]*s+p,y+c[3]*s); - }); if (thisCh==":") x-=4; x+=s+p+7; } - y += 2*s; +} +function drawSeconds() { + var x = (CHARW + CHARP + 6)*5; + var y = Y + 2*CHARW + CHARP; var d = new Date(); - buf.setFont("6x8"); - buf.setFontAlign(-1,-1); - buf.drawString(("0"+d.getSeconds()).substr(-2), x, y-8); + g.reset(); + g.setFont("6x8"); + g.setFontAlign(-1,-1); + g.drawString(("0"+d.getSeconds()).substr(-2), x, y-8, true); // date - buf.setFontAlign(0,-1); + g.setFontAlign(0,-1); var date = locale.date(d,false); - buf.drawString(date, buf.getWidth()/2, y+8); - flip(); + g.drawString(date, g.getWidth()/2, y+8, true); } /* Show the current time, and animate if needed */ function showTime() { - if (!Bangle.isLCDOn()) return; if (animInterval) return; // in animation - quit var d = new Date(); var t = (" "+d.getHours()).substr(-2)+":"+ ("0"+d.getMinutes()).substr(-2); var l = lastTime; // same - don't animate - if (t==l) { - draw(t,l,0); + if (t==l || l==" ") { + drawDigits(l,t,0); + drawSeconds(); + lastTime = t; return; } var n = 0; @@ -170,23 +179,35 @@ function showTime() { if (n>=1) { n=1; clearInterval(animInterval); - animInterval=0; + animInterval = undefined; } - draw(l,t,n); + drawDigits(l,t,n); }, 20); lastTime = t; } Bangle.on('lcdPower',function(on) { - if (on) + if (animInterval) { + clearInterval(animInterval); + animInterval = undefined; + } + if (timeInterval) { + clearInterval(timeInterval); + timeInterval = undefined; + } + if (on) { showTime(); + timeInterval = setInterval(showTime, 1000); + } else { + lastTime = " "; + } }); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); // Update time once a second -setInterval(showTime, 1000); +timeInterval = setInterval(showTime, 1000); showTime(); // Show launcher when middle button pressed From 9e8dea08e4888ea602e6440402a3a3d5d9a873cb Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 06:54:08 +0100 Subject: [PATCH 58/77] Rename program to workout --- apps/buffgym/buffgym-exercise.js | 40 ++++----- apps/buffgym/buffgym-program-index.json | 10 --- apps/buffgym/buffgym-set.js | 6 +- ...-program-a.json => buffgym-workout-a.json} | 2 +- ...-program-b.json => buffgym-workout-b.json} | 2 +- apps/buffgym/buffgym-workout-index.json | 10 +++ ...{buffgym-program.js => buffgym-workout.js} | 6 +- apps/buffgym/buffgym.app.js | 87 ++++++++++--------- 8 files changed, 84 insertions(+), 79 deletions(-) delete mode 100644 apps/buffgym/buffgym-program-index.json rename apps/buffgym/{buffgym-program-a.json => buffgym-workout-a.json} (96%) rename apps/buffgym/{buffgym-program-b.json => buffgym-workout-b.json} (96%) create mode 100644 apps/buffgym/buffgym-workout-index.json rename apps/buffgym/{buffgym-program.js => buffgym-workout.js} (95%) diff --git a/apps/buffgym/buffgym-exercise.js b/apps/buffgym/buffgym-exercise.js index 68e49be84..078e206de 100644 --- a/apps/buffgym/buffgym-exercise.js +++ b/apps/buffgym/buffgym-exercise.js @@ -1,16 +1,16 @@ exports = class Exercise { constructor(params) { + this.completed = false; + this.sets = []; this.title = params.title; this.weight = params.weight; this.unit = params.unit; this.restPeriod = params.restPeriod; - this.completed = false; - this.sets = []; + this._originalRestPeriod = params.restPeriod; + this._weightIncrement = params.weightIncrement; this._restTimeout = null; this._restInterval = null; this._state = null; - this._originalRestPeriod = params.restPeriod; - this._weightIncrement = params.weightIncrement || 2.5; } get humanTitle() { @@ -63,13 +63,13 @@ exports = class Exercise { return (targetRepsTotalSum - completedRepsTotalSum) === 0; } - startRestTimer(program) { + startRestTimer(workout) { this._restTimeout = setTimeout(() => { - this.next(program); + this.next(workout); }, 1000 * this.restPeriod); this._restInterval = setInterval(() => { - program.emit("redraw"); + workout.emit("redraw"); }, 1000 ); } @@ -85,28 +85,28 @@ exports = class Exercise { return this._restTimeout != null; } - setupStartedButtons(program) { + setupStartedButtons(workout) { clearWatch(); setWatch(() => { this.currentSet().incReps(); - program.emit("redraw"); + workout.emit("redraw"); }, BTN1, {repeat: true}); - setWatch(program.next.bind(program), BTN2, {repeat: false}); + setWatch(workout.next.bind(workout), BTN2, {repeat: false}); setWatch(() => { this.currentSet().decReps(); - program.emit("redraw"); + workout.emit("redraw"); }, BTN3, {repeat: true}); } - setupRestingButtons(program) { + setupRestingButtons(workout) { clearWatch(); - setWatch(program.next.bind(program), BTN2, {repeat: false}); + setWatch(workout.next.bind(workout), BTN2, {repeat: false}); } - next(program) { + next(workout) { const STARTED = 1; const RESTING = 2; const COMPLETED = 3; @@ -114,12 +114,12 @@ exports = class Exercise { switch(this._state) { case null: this._state = STARTED; - this.setupStartedButtons(program); + this.setupStartedButtons(workout); break; case STARTED: this._state = RESTING; - this.startRestTimer(program); - this.setupRestingButtons(program); + this.startRestTimer(workout); + this.setupRestingButtons(workout); break; case RESTING: this.resetRestTimer(); @@ -132,13 +132,13 @@ exports = class Exercise { this._state = null; } // As we are changing state and require it to be reprocessed - // invoke the next step of program - program.next(); + // invoke the next step of workout + workout.next(); break; default: throw "Exercise: Attempting to move to an unknown state"; } - program.emit("redraw"); + workout.emit("redraw"); } } \ No newline at end of file diff --git a/apps/buffgym/buffgym-program-index.json b/apps/buffgym/buffgym-program-index.json deleted file mode 100644 index 3bb51f1b5..000000000 --- a/apps/buffgym/buffgym-program-index.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "title": "Program A", - "file": "buffgym-program-a.json" - }, - { - "title": "Program B", - "file": "buffgym-program-b.json" - } -] \ No newline at end of file diff --git a/apps/buffgym/buffgym-set.js b/apps/buffgym/buffgym-set.js index 4bd12d7ec..dc0c05671 100644 --- a/apps/buffgym/buffgym-set.js +++ b/apps/buffgym/buffgym-set.js @@ -1,9 +1,9 @@ exports = class Set { constructor(maxReps) { - this.minReps = 0; - this.maxReps = maxReps; - this.reps = 0; this.completed = false; + this.minReps = 0; + this.reps = 0; + this.maxReps = maxReps; } isCompleted() { diff --git a/apps/buffgym/buffgym-program-a.json b/apps/buffgym/buffgym-workout-a.json similarity index 96% rename from apps/buffgym/buffgym-program-a.json rename to apps/buffgym/buffgym-workout-a.json index 7ebaf3741..8eb8611d6 100644 --- a/apps/buffgym/buffgym-program-a.json +++ b/apps/buffgym/buffgym-workout-a.json @@ -1,5 +1,5 @@ { - "title": "Program A", + "title": "Workout A", "exercises": [ { "title": "Squats", diff --git a/apps/buffgym/buffgym-program-b.json b/apps/buffgym/buffgym-workout-b.json similarity index 96% rename from apps/buffgym/buffgym-program-b.json rename to apps/buffgym/buffgym-workout-b.json index b93348621..43845a98b 100644 --- a/apps/buffgym/buffgym-program-b.json +++ b/apps/buffgym/buffgym-workout-b.json @@ -1,5 +1,5 @@ { - "title": "Program B", + "title": "Workout B", "exercises": [ { "title": "Squats", diff --git a/apps/buffgym/buffgym-workout-index.json b/apps/buffgym/buffgym-workout-index.json new file mode 100644 index 000000000..af74d5e3b --- /dev/null +++ b/apps/buffgym/buffgym-workout-index.json @@ -0,0 +1,10 @@ +[ + { + "title": "Workout A", + "file": "buffgym-workout-a.json" + }, + { + "title": "Workout B", + "file": "buffgym-workout-b.json" + } +] \ No newline at end of file diff --git a/apps/buffgym/buffgym-program.js b/apps/buffgym/buffgym-workout.js similarity index 95% rename from apps/buffgym/buffgym-program.js rename to apps/buffgym/buffgym-workout.js index 68a069da5..811125293 100644 --- a/apps/buffgym/buffgym-program.js +++ b/apps/buffgym/buffgym-workout.js @@ -1,4 +1,4 @@ -exports = class Program { +exports = class Workout { constructor(params) { this.title = params.title; this.exercises = []; @@ -27,6 +27,10 @@ exports = class Program { return !!this.completed; } + static fromJSON(workout) { + + } + toJSON() { return { title: this.title, diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index 4dc6ffd5a..b92b2bb98 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -5,7 +5,7 @@ * Created: April 2020 * * Inspired by: - * - Stronglifts 5x5 training program https://stronglifts.com/5x5/ + * - Stronglifts 5x5 training workout https://stronglifts.com/5x5/ * - Stronglifts smart watch app */ @@ -66,10 +66,10 @@ function drawSet(exercise) { g.flip(); } -function drawProgDone() { +function drawWorkoutDone() { const title1 = "You did"; const title2 = "GREAT!"; - const msg = "That's the program\ncompleted. Now eat\nsome food and\nget plenty of rest."; + const msg = "That's the workout\ncompleted. Now eat\nsome food and\nget plenty of rest."; clearWatch(); setWatch(Bangle.showLauncher, BTN2, {repeat: false}); @@ -102,13 +102,13 @@ function drawSetComp() { g.flip(); } -function drawRestTimer(program) { - const exercise = program.currentExercise(); +function drawRestTimer(workout) { + const exercise = workout.currentExercise(); const motivation = "Take a breather.."; if (exercise.restPeriod <= 0) { exercise.resetRestTimer(); - program.next(); + workout.next(); return; } @@ -128,21 +128,21 @@ function drawRestTimer(program) { exercise.decRestPeriod(); } -function redraw(program) { - const exercise = program.currentExercise(); +function redraw(workout) { + const exercise = workout.currentExercise(); g.clear(); - if (program.isCompleted()) { - saveProg(program); - drawProgDone(program); + if (workout.isCompleted()) { + saveWorkout(workout); + drawWorkoutDone(workout); return; } if (exercise.isRestTimerRunning()) { if (exercise.isLastSet()) { - drawSetComp(program); + drawSetComp(workout); } else { - drawRestTimer(program); + drawRestTimer(workout); } return; @@ -151,7 +151,7 @@ function redraw(program) { drawSet(exercise); } -function drawProgMenu(programs, selProgIdx) { +function drawWorkoutMenu(workouts, selWorkoutIdx) { g.clear(); g.setFontAlign(0, -1); g.setColor(WHITE); @@ -160,16 +160,16 @@ function drawProgMenu(programs, selProgIdx) { g.setFont("6x8", 1); g.setFontAlign(-1, -1); - let selectedProgram = programs[selProgIdx].title; + let selectedWorkout = workouts[selWorkoutIdx].title; let yPos = 50; - programs.forEach(program => { + workouts.forEach(workout => { g.setColor("#f05a56"); g.fillRect(0, yPos, W, yPos + 11); g.setColor("#ffffff"); - if (selectedProgram === program.title) { + if (selectedWorkout === workout.title) { g.drawRect(0, yPos, W - 1, yPos + 11); } - g.drawString(program.title, 10, yPos + 2); + g.drawString(workout.title, 10, yPos + 2); yPos += 15; }); g.flip(); @@ -177,25 +177,25 @@ function drawProgMenu(programs, selProgIdx) { function setupMenu() { clearWatch(); - const progs = getProgIndex(); - let selProgIdx = 0; - drawProgMenu(progs, selProgIdx); + const workouts = getWorkoutIndex(); + let selWorkoutIdx = 0; + drawWorkoutMenu(workouts, selWorkoutIdx); setWatch(()=>{ - selProgIdx--; - if (selProgIdx< 0) selProgIdx = 0; - drawProgMenu(progs, selProgIdx); + selWorkoutIdx--; + if (selWorkoutIdx< 0) selWorkoutIdx = 0; + drawWorkoutMenu(workouts, selWorkoutIdx); }, BTN1, {repeat: true}); setWatch(()=>{ - const prog = buildProg(progs[selProgIdx].file); - prog.next(); + const workout = buildWorkout(workouts[selWorkoutIdx].file); + workout.next(); }, BTN2, {repeat: false}); setWatch(()=>{ - selProgIdx++; - if (selProgIdx > progs.length - 1) selProgIdx = progs.length - 1; - drawProgMenu(progs, selProgIdx); + selWorkoutIdx++; + if (selWorkoutIdx > workouts.length - 1) selWorkoutIdx = workouts.length - 1; + drawWorkoutMenu(workouts, selWorkoutIdx); }, BTN3, {repeat: true}); } @@ -249,23 +249,24 @@ function drawSplash() { }, BTN3, {repeat: false}); } -function getProgIndex() { - const progIdx = require("Storage").readJSON("buffgym-program-index.json"); - return progIdx; +function getWorkoutIndex() { + const workoutIdx = require("Storage").readJSON("buffgym-workout-index.json"); + return workoutIdx; } -function buildProg(fName) { +function buildWorkout(fName) { const Set = require("buffgym-set.js"); const Exercise = require("buffgym-exercise.js"); - const Program = require("buffgym-program.js"); - const progJSON = require("Storage").readJSON(fName); - const prog = new Program({ - title: progJSON.title, + const Workout = require("buffgym-workout.js"); + const workoutJSON = require("Storage").readJSON(fName); + const workout = new Workout({ + title: workoutJSON.title, }); - const exercises = progJSON.exercises.map(exerciseJSON => { + const exercises = workoutJSON.exercises.map(exerciseJSON => { const exercise = new Exercise({ title: exerciseJSON.title, weight: exerciseJSON.weight, + weightIncrement: exerciseJSON.weightIncrement, unit: exerciseJSON.unit, restPeriod: exerciseJSON.restPeriod, }); @@ -275,14 +276,14 @@ function buildProg(fName) { return exercise; }); - prog.addExercises(exercises); + workout.addExercises(exercises); - return prog; + return workout; } -function saveProg(program) { - const fName = getProgIndex().find(prog => prog.title === program.title).file; - require("Storage").writeJSON(fName, program.toJSON()); +function saveWorkout(workout) { + const fName = getWorkoutIndex().find(workout => workout.title === workout.title).file; + require("Storage").writeJSON(fName, workout.toJSON()); } drawSplash(); \ No newline at end of file From bf1fe5de4e7d383fd2be7184ca4012e696c6d61a Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 06:58:14 +0100 Subject: [PATCH 59/77] Fix logic leak, make sure draw functions only deal with drawing UI --- apps/buffgym/buffgym-exercise.js | 9 +++++++++ apps/buffgym/buffgym.app.js | 10 ---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/buffgym/buffgym-exercise.js b/apps/buffgym/buffgym-exercise.js index 078e206de..7d631182e 100644 --- a/apps/buffgym/buffgym-exercise.js +++ b/apps/buffgym/buffgym-exercise.js @@ -69,6 +69,15 @@ exports = class Exercise { }, 1000 * this.restPeriod); this._restInterval = setInterval(() => { + this.decRestPeriod(); + + if (this.restPeriod < 0) { + this.resetRestTimer(); + this.next(); + + return; + } + workout.emit("redraw"); }, 1000 ); } diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index b92b2bb98..d1c0386ff 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -104,14 +104,6 @@ function drawSetComp() { function drawRestTimer(workout) { const exercise = workout.currentExercise(); - const motivation = "Take a breather.."; - - if (exercise.restPeriod <= 0) { - exercise.resetRestTimer(); - workout.next(); - - return; - } g.clear(); drawMenu({showBTN2: true}); @@ -124,8 +116,6 @@ function drawRestTimer(workout) { g.setFont("6x8", 5); g.drawString(exercise.restPeriod, (W / 2) + 2, (H / 2) - 19); g.flip(); - - exercise.decRestPeriod(); } function redraw(workout) { From 3384f493e250fff949d032e57a4fed6b609e427b Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 07:06:25 +0100 Subject: [PATCH 60/77] Fix set complete UI message --- apps/buffgym/buffgym.app.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index d1c0386ff..2c7416dba 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -85,9 +85,12 @@ function drawWorkoutDone() { g.flip(); } -function drawSetComp() { +function drawSetComp(exercise) { const title = "Good work"; - const msg = "No need to rest\nmove straight on\nto the next\nexercise.Your\nweight has been\nincreased for\nnext time!"; + const msg1= "No need to rest\nmove straight on\nto the next\nexercise."; + const msg2 = exercise.canProgress()? + "Your\nweight has been\nincreased for\nnext time!": + "You'll\nsmash it next\ntime!"; g.clear(); drawMenu({showBTN2: true}); @@ -97,14 +100,12 @@ function drawSetComp() { g.setFont("6x8", 2); g.drawString(title, W / 2, 10); g.setFont("6x8", 1); - g.drawString(msg, (W / 2) - 2, 45); + g.drawString(msg1 + msg2, (W / 2) - 2, 45); g.flip(); } -function drawRestTimer(workout) { - const exercise = workout.currentExercise(); - +function drawRestTimer(exercise) { g.clear(); drawMenu({showBTN2: true}); g.setFontAlign(0, -1); @@ -124,15 +125,15 @@ function redraw(workout) { if (workout.isCompleted()) { saveWorkout(workout); - drawWorkoutDone(workout); + drawWorkoutDone(); return; } if (exercise.isRestTimerRunning()) { if (exercise.isLastSet()) { - drawSetComp(workout); + drawSetComp(exercise); } else { - drawRestTimer(workout); + drawRestTimer(exercise); } return; From d3c58fb323cf50439a831b50930fed678e834380 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 09:41:57 +0100 Subject: [PATCH 61/77] Add interface to set weight values, update README --- apps/buffgym/README.md | 25 +++- apps/buffgym/buffgym.html | 245 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 apps/buffgym/buffgym.html diff --git a/apps/buffgym/README.md b/apps/buffgym/README.md index e9e217828..bcadf22c4 100644 --- a/apps/buffgym/README.md +++ b/apps/buffgym/README.md @@ -2,17 +2,32 @@ This gym training assistant trains you on the famous [Stronglifts 5x5 workout](https://stronglifts.com/5x5) program. +## Configuration + +### Setting your start weight values + +You will want to set your own starting weight values for your 5x5 training program. To do this is easy! After installing this app, go to the BangleJS app store, connect to your watch, and navigate to the `My Apps` tab. In there you will find this app in the list, and an icon (a down arrow) to the right of the app title. Click that icon to reveal a configuration page. Enter your weights and other details, and click upload. That is it, you are now ready to train! + ## Usage +### Start screen + When you start the app it will wait on a splash screen until you are ready to start the work out. Press any of the buttons to start ![](buffgym-scrn1.png) -You are then presented with the programs menu, use BTN1 to move up the list, and BTN3 to move down the list. Once you have made your selection, press BTN2 to select the program. +### Workouts menu + +You are then presented with the workouts menu, use BTN1 to move up the list, and BTN3 to move down the list. Once you have made your selection, press BTN2 to select the workout. ![](buffgym-scrn2.png) -You will now begin moving through the exercises in the program. You will see the exercise information on the display. +### Recording your training + +You will now begin moving through the exercises in the workout. You will see the exercise information on the display. + +![](buffgym-scrn3.png) + 1. At the top is the exercise name, e.g 'Squats' 2. Next is the weight you must train 3. In the center is where you record the number of *reps* you completed (more on that shortly) @@ -20,13 +35,15 @@ You will now begin moving through the exercises in the program. You will see the 5. Below the target reps is the current set you are training, out of the total sets for the exercise. 6. The *reps* value is used to store what you achieved for the current set, you enter this after you have trained on your current set. To alter this value, use BTN1 to increase the value (it will stop at the maximum required reps) and BTN3 to decreas the value to a minimum of 0 (this is the default value). Pressing BTN2 will confirm your reps -![](buffgym-scrn3.png) +### Rest timers You will then be presented with a rest timer screen, it counts down and automatically moves to the next exercise when it reaches 0. You can cancel the timer early if you wish by pressing BTN2. If it is the last set of an exercise, you don't need to rest, so it lets you know you have completed all the sets in the exercise and can start the next exercise. ![](buffgym-scrn4.png) ![](buffgym-scrn5.png) +### Workout completed + Once all exercises are done, you are presented with a pat-on-the-back screen to tell you how awesome you are. ![](buffgym-scrn6.png) @@ -40,4 +57,4 @@ Once all exercises are done, you are presented with a pat-on-the-back screen to ## Created by -[Paul Cockrell](https://github.com/paulcockrell) April 2020. \ No newline at end of file +[Paul Cockrell](https://github.com/paulcockrell) April 2020. diff --git a/apps/buffgym/buffgym.html b/apps/buffgym/buffgym.html new file mode 100644 index 000000000..c5766bcfa --- /dev/null +++ b/apps/buffgym/buffgym.html @@ -0,0 +1,245 @@ + + + + + +

BuffGym

+

+ Enter in your weights for each exercise, start light and keep consistent with your training. The weight increment field is how much the app will increase your weights for an exercise if you successfully complete all the reps and sets for an exercise. Make sure its a value that matches the weights in your gym. +

+

+ For more information on how to train this program refer the Stronglifts website +

+
+

Workout A

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExerciseSets / RepsWeightWeight increment
+ Squats + + 5x5 + + + + +
+ Overhead press + + 5x5 + + + + +
+ Deadlift + + 1x5 + + + + +
+ Pullups + + 3x10 + + + + +
+

Workout B

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExerciseSets / RepsWeightWeight increment
+ Squats + + 5x5 + + + + +
+ Bench press + + 5x5 + + + + +
+ Row + + 5x5 + + + + +
+ Tricep extension + + 3x10 + + + + +
+
+

+ + + + + + + From 04f1e523e85676a16b3058ba6718cf9519efccd4 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 09:48:31 +0100 Subject: [PATCH 62/77] Serialise uploading. Add buzz on watch to indicate completed --- apps/buffgym/buffgym.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/buffgym/buffgym.html b/apps/buffgym/buffgym.html index c5766bcfa..4025ee19d 100644 --- a/apps/buffgym/buffgym.html +++ b/apps/buffgym/buffgym.html @@ -237,8 +237,13 @@ } document.getElementById("upload").addEventListener("click", function() { - Puck.eval(`require("Storage").writeJSON("buffgym-workout-a.json",${JSON.stringify(workoutA())})`, ()=>{console.log("Done uploading workout A")}); - Puck.eval(`require("Storage").writeJSON("buffgym-workout-b.json",${JSON.stringify(workoutB())})`, ()=>{console.log("Done uploading workout B")}); + Puck.eval(`require("Storage").writeJSON("buffgym-workout-a.json",${JSON.stringify(workoutA())})`, ()=>{ + Puck.eval(`require("Storage").writeJSON("buffgym-workout-b.json",${JSON.stringify(workoutB())})`, ()=>{ + Puck.eval(`Bangle.buzz();`, () => { + console.log("all done"); + }) + }) + }); }); From a0d6f8741e81f2861f491a857594fb844b8537ef Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 09:51:15 +0100 Subject: [PATCH 63/77] Add interface to apps.json for BuffGym app --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 65b681390..4f0346bd8 100644 --- a/apps.json +++ b/apps.json @@ -1347,6 +1347,7 @@ "description": "BuffGym is the famous 5x5 workout program for the BangleJS", "tags": "tool,outdoors,gym,exercise", "type": "app", + "interface": "buffgym.html", "allow_emulator": false, "readme": "README.md", "storage": [ From edd1b73bc00dcb2a2e9c43d5d5aa9d7da4224b25 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 10:11:28 +0100 Subject: [PATCH 64/77] Update apps.json to use new buffgym file names. Fix buzz command --- apps.json | 8 ++++---- apps/buffgym/buffgym.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 4f0346bd8..60d973e23 100644 --- a/apps.json +++ b/apps.json @@ -1354,10 +1354,10 @@ {"name":"buffgym.app.js", "url": "buffgym.app.js"}, {"name":"buffgym-set.js","url":"buffgym-set.js"}, {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, - {"name":"buffgym-program.js","url":"buffgym-program.js"}, - {"name":"buffgym-program-a.json","url":"buffgym-program-a.json"}, - {"name":"buffgym-program-b.json","url":"buffgym-program-b.json"}, - {"name":"buffgym-program-index.json","url":"buffgym-program-index.json"}, + {"name":"buffgym-workout.js","url":"buffgym-workout.js"}, + {"name":"buffgym-workout-a.json","url":"buffgym-workout-a.json"}, + {"name":"buffgym-workout-b.json","url":"buffgym-workout-b.json"}, + {"name":"buffgym-workout-index.json","url":"buffgym-workout-index.json"}, {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} ] }, diff --git a/apps/buffgym/buffgym.html b/apps/buffgym/buffgym.html index 4025ee19d..3c18932e9 100644 --- a/apps/buffgym/buffgym.html +++ b/apps/buffgym/buffgym.html @@ -239,7 +239,7 @@ document.getElementById("upload").addEventListener("click", function() { Puck.eval(`require("Storage").writeJSON("buffgym-workout-a.json",${JSON.stringify(workoutA())})`, ()=>{ Puck.eval(`require("Storage").writeJSON("buffgym-workout-b.json",${JSON.stringify(workoutB())})`, ()=>{ - Puck.eval(`Bangle.buzz();`, () => { + Puck.eval(`Bangle.buzz()`, () => { console.log("all done"); }) }) From a389ed5dbee7108ca55eb7853da3f307d962ec87 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 23 Apr 2020 10:28:42 +0100 Subject: [PATCH 65/77] Torch: Change start sequence to BTN1/3/1/3 to avoid accidental turning on (fix #342) --- apps.json | 4 ++-- apps/torch/ChangeLog | 1 + apps/torch/widget.js | 24 ++++++++++++++++-------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/apps.json b/apps.json index 65b681390..4c5910a6f 100644 --- a/apps.json +++ b/apps.json @@ -921,8 +921,8 @@ "name": "Torch", "shortName":"Torch", "icon": "app.png", - "version":"0.01", - "description": "Turns screen white to help you see in the dark. Select from the launcher or press BTN3 four times in quick succession to start when in normal clock mode", + "version":"0.02", + "description": "Turns screen white to help you see in the dark. Select from the launcher or press BTN1,BTN3,BTN1,BTN3 quickly to start when in any app that shows widgets", "tags": "tool,torch", "storage": [ {"name":"torch.app.js","url":"app.js"}, diff --git a/apps/torch/ChangeLog b/apps/torch/ChangeLog index 5560f00bc..8e76b717a 100644 --- a/apps/torch/ChangeLog +++ b/apps/torch/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Change start sequence to BTN1/3/1/3 to avoid accidental turning on (fix #342) diff --git a/apps/torch/widget.js b/apps/torch/widget.js index e3d1ea22f..a5002ea71 100644 --- a/apps/torch/widget.js +++ b/apps/torch/widget.js @@ -1,18 +1,26 @@ +(function() { var clickTimes = []; -var CLICK_COUNT = 4; // number of taps -var CLICK_PERIOD = 1; // second +var clickPattern = ""; +var TAPS = 4; // number of taps +var PERIOD = 1; // seconds // we don't actually create/draw a widget here at all... - Bangle.on("lcdPower",function(on) { // First click (that turns LCD on) isn't given to // setWatch, so handle it here - if (on) clickTimes=[getTime()]; + if (!on) return; + clickTimes=[getTime()]; + clickPattern="x"; }); -setWatch(function(e) { - while (clickTimes.length>=CLICK_COUNT) clickTimes.shift(); +function tap(e,c) { + clickPattern = clickPattern.substr(-3)+c; + while (clickTimes.length>=TAPS) clickTimes.shift(); clickTimes.push(e.time); var clickPeriod = e.time-clickTimes[0]; - if (clickTimes.length==CLICK_COUNT && clickPeriod Date: Thu, 23 Apr 2020 10:53:09 +0100 Subject: [PATCH 66/77] stopwatch: Ensure seconds counter is in sync with subseconds (fix #341) --- apps.json | 2 +- apps/swatch/ChangeLog | 1 + apps/swatch/stopwatch.js | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4c5910a6f..127d87d89 100644 --- a/apps.json +++ b/apps.json @@ -452,7 +452,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.06", + "version":"0.07", "interface": "interface.html", "description": "Simple stopwatch with Lap Time logging to a JSON file", "tags": "health", diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index 9a037fa41..caa74a1ba 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -6,3 +6,4 @@ 0.04: Changed save file filename, add interface.html to allow laps to be loaded 0.05: Added widgets 0.06: Added total running time, moved lap time to smaller display, total run time now appends as first entry in array, saving now saves last lap as well +0.07: Ensure seconds counter is in sync with subseconds (fix #341) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 659f0606d..478de2712 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -94,7 +94,8 @@ setWatch(function() { // Start/stop displayInterval = setInterval(function() { var last = tCurrent; if (started) tCurrent = Date.now(); - if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) + if (Math.floor((last-tStart)/1000)!=Math.floor((tCurrent-tStart)/1000) || + Math.floor((last-tTotal)/1000)!=Math.floor((tCurrent-tTotal)/1000)) drawsecs(); else drawms(); From c36bd7f97f7b89c2d7445a62255686f399333ed7 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 23 Apr 2020 10:57:59 +0100 Subject: [PATCH 67/77] Add readme to example apps (fix #300) --- apps/_example_app/README.md | 25 +++++++++++++++++++++++++ apps/_example_app/add_to_apps.json | 1 + apps/_example_widget/README.md | 25 +++++++++++++++++++++++++ apps/_example_widget/add_to_apps.json | 1 + 4 files changed, 52 insertions(+) create mode 100644 apps/_example_app/README.md create mode 100644 apps/_example_widget/README.md diff --git a/apps/_example_app/README.md b/apps/_example_app/README.md new file mode 100644 index 000000000..dc139bc9a --- /dev/null +++ b/apps/_example_app/README.md @@ -0,0 +1,25 @@ +# App Name + +Describe the app... + +Add screen shots (if possible) to the app folder and link then into this file with ![](.png) + +## Usage + +Describe how to use it + +## Features + +Name the function + +## Controls + +Name the buttons and what they are used for + +## Requests + +Name who should be contacted for support/update requests + +## Creator + +Your name diff --git a/apps/_example_app/add_to_apps.json b/apps/_example_app/add_to_apps.json index ca75a7bd8..bb0377b66 100644 --- a/apps/_example_app/add_to_apps.json +++ b/apps/_example_app/add_to_apps.json @@ -6,6 +6,7 @@ "version":"0.01", "description": "A detailed description of my great app", "tags": "", + "readme": "README.md", "storage": [ {"name":"7chname.app.js","url":"app.js"}, {"name":"7chname.img","url":"app-icon.js","evaluate":true} diff --git a/apps/_example_widget/README.md b/apps/_example_widget/README.md new file mode 100644 index 000000000..a909e9e7e --- /dev/null +++ b/apps/_example_widget/README.md @@ -0,0 +1,25 @@ +# Widget Name + +Describe the app... + +Add screen shots (if possible) to the app folder and link then into this file with ![](.png) + +## Usage + +Describe how to use it + +## Features + +Name the function + +## Controls + +Name the buttons and what they are used for + +## Requests + +Name who should be contacted for support/update requests + +## Creator + +Your name diff --git a/apps/_example_widget/add_to_apps.json b/apps/_example_widget/add_to_apps.json index 5d0057960..527c698a0 100644 --- a/apps/_example_widget/add_to_apps.json +++ b/apps/_example_widget/add_to_apps.json @@ -7,6 +7,7 @@ "description": "A detailed description of my great widget", "tags": "widget", "type": "widget", + "readme": "README.md", "storage": [ {"name":"7chname.wid.js","url":"widget.js"} ] From f8590bdcf58df24f66f88f694c24c51159354f02 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 11:18:10 +0100 Subject: [PATCH 68/77] Refactor workout json loading. Fix file name matching bug --- apps/buffgym/buffgym-exercise.js | 4 ++-- apps/buffgym/buffgym-workout.js | 25 ++++++++++++++++++++++++- apps/buffgym/buffgym.app.js | 23 ++--------------------- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/apps/buffgym/buffgym-exercise.js b/apps/buffgym/buffgym-exercise.js index 7d631182e..ea20aa132 100644 --- a/apps/buffgym/buffgym-exercise.js +++ b/apps/buffgym/buffgym-exercise.js @@ -4,10 +4,10 @@ exports = class Exercise { this.sets = []; this.title = params.title; this.weight = params.weight; + this.weightIncrement = params.weightIncrement; this.unit = params.unit; this.restPeriod = params.restPeriod; this._originalRestPeriod = params.restPeriod; - this._weightIncrement = params.weightIncrement; this._restTimeout = null; this._restInterval = null; this._state = null; @@ -50,7 +50,7 @@ exports = class Exercise { setCompleted() { if (!this.canSetCompleted()) throw "All sets must be completed"; - if (this.canProgress()) this.weight += this._weightIncrement; + if (this.canProgress()) this.weight += this.weightIncrement; this.completed = true; } diff --git a/apps/buffgym/buffgym-workout.js b/apps/buffgym/buffgym-workout.js index 811125293..124c27f4b 100644 --- a/apps/buffgym/buffgym-workout.js +++ b/apps/buffgym/buffgym-workout.js @@ -27,8 +27,30 @@ exports = class Workout { return !!this.completed; } - static fromJSON(workout) { + static fromJSON(workoutJSON) { + const Set = require("buffgym-set.js"); + const Exercise = require("buffgym-exercise.js"); + const workout = new this({ + title: workoutJSON.title, + }); + const exercises = workoutJSON.exercises.map(exerciseJSON => { + const exercise = new Exercise({ + title: exerciseJSON.title, + weight: exerciseJSON.weight, + weightIncrement: exerciseJSON.weightIncrement, + unit: exerciseJSON.unit, + restPeriod: exerciseJSON.restPeriod, + }); + exerciseJSON.sets.forEach(setJSON => { + exercise.addSet(new Set(setJSON)); + }); + return exercise; + }); + + workout.addExercises(exercises); + + return workout; } toJSON() { @@ -38,6 +60,7 @@ exports = class Workout { return { title: exercise.title, weight: exercise.weight, + weightIncrement: exercise.weightIncrement, unit: exercise.unit, sets: exercise.sets.map(set => set.maxReps), restPeriod: exercise.restPeriod, diff --git a/apps/buffgym/buffgym.app.js b/apps/buffgym/buffgym.app.js index 2c7416dba..fc2be83f9 100755 --- a/apps/buffgym/buffgym.app.js +++ b/apps/buffgym/buffgym.app.js @@ -246,34 +246,15 @@ function getWorkoutIndex() { } function buildWorkout(fName) { - const Set = require("buffgym-set.js"); - const Exercise = require("buffgym-exercise.js"); const Workout = require("buffgym-workout.js"); const workoutJSON = require("Storage").readJSON(fName); - const workout = new Workout({ - title: workoutJSON.title, - }); - const exercises = workoutJSON.exercises.map(exerciseJSON => { - const exercise = new Exercise({ - title: exerciseJSON.title, - weight: exerciseJSON.weight, - weightIncrement: exerciseJSON.weightIncrement, - unit: exerciseJSON.unit, - restPeriod: exerciseJSON.restPeriod, - }); - exerciseJSON.sets.forEach(setJSON => { - exercise.addSet(new Set(setJSON)); - }); - - return exercise; - }); - workout.addExercises(exercises); + const workout = Workout.fromJSON(workoutJSON); return workout; } function saveWorkout(workout) { - const fName = getWorkoutIndex().find(workout => workout.title === workout.title).file; + const fName = getWorkoutIndex().find(w => w.title === workout.title).file; require("Storage").writeJSON(fName, workout.toJSON()); } From 2ebdf0c6c309e8983b08b8906cd1bc5cb96fb6e1 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 23 Apr 2020 11:45:45 +0100 Subject: [PATCH 69/77] Add Changelog and bump version in apps.json --- apps.json | 2 +- apps/buffgym/ChangeLog | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 apps/buffgym/ChangeLog diff --git a/apps.json b/apps.json index 60d973e23..009f510b9 100644 --- a/apps.json +++ b/apps.json @@ -1343,7 +1343,7 @@ "id": "buffgym", "name": "BuffGym", "icon": "buffgym.png", - "version":"0.01", + "version":"0.02", "description": "BuffGym is the famous 5x5 workout program for the BangleJS", "tags": "tool,outdoors,gym,exercise", "type": "app", diff --git a/apps/buffgym/ChangeLog b/apps/buffgym/ChangeLog new file mode 100644 index 000000000..6efdd865a --- /dev/null +++ b/apps/buffgym/ChangeLog @@ -0,0 +1,2 @@ +0.01: Create BuffGym app +0.02: Add web interface for personalising workout From e40829ea73f2402dc1abf0e0edad7d6fd23f1205 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Thu, 23 Apr 2020 13:46:06 +0000 Subject: [PATCH 70/77] 0.06: Complete rewrite in 80x80, better perf, add settings --- apps.json | 6 +- apps/toucher/ChangeLog | 2 +- apps/toucher/app.js | 299 +++++++++++++++++++++++---------------- apps/toucher/settings.js | 59 ++++++++ 4 files changed, 239 insertions(+), 127 deletions(-) create mode 100644 apps/toucher/settings.js diff --git a/apps.json b/apps.json index 43e7e4b9d..ad5b20820 100644 --- a/apps.json +++ b/apps.json @@ -1092,14 +1092,16 @@ }, { "id": "toucher", "name": "Touch Launcher", - "shortName":"Menu", + "shortName":"Toucher", "icon": "app.png", "version":"0.06", "description": "Touch enable left to right launcher.", "tags": "tool,system,launcher", "type":"launch", "storage": [ - {"name":"toucher.app.js","url":"app.js"} + {"name":"toucher.app.js","url":"app.js"}, + {"name":"toucher.settings.js","url":"settings.js"}, + {"name":"toucher.json"} ], "sortorder" : -10 }, diff --git a/apps/toucher/ChangeLog b/apps/toucher/ChangeLog index 0c97d9e13..494110d55 100644 --- a/apps/toucher/ChangeLog +++ b/apps/toucher/ChangeLog @@ -3,4 +3,4 @@ 0.03: Close launcher when lcd turn off 0.04: Complete rewrite to add animation and loop ( issue #210 ) 0.05: Improve perf -0.06: Only store relevant app data (saves RAM when many apps) +0.06: Complete rewrite in 80x80, better perf, add settings \ No newline at end of file diff --git a/apps/toucher/app.js b/apps/toucher/app.js index cf7d5333b..5aac55134 100644 --- a/apps/toucher/app.js +++ b/apps/toucher/app.js @@ -1,160 +1,206 @@ -Bangle.setLCDMode("120x120"); +const Storage = require("Storage"); +const filename = 'toucher.json'; +let settings = Storage.readJSON(filename,1) || { + hightres: true, + animation : true, + frame : 3, + debug: false +}; + +if(!settings.highres) Bangle.setLCDMode("80x80"); +else Bangle.setLCDMode(); + g.clear(); g.flip(); -const Storage = require("Storage"); - -function getApps(){ - return Storage.list(/\.info$/).map(app=>{var a=Storage.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src,version:a.version}}) - .filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)) - .sort((a,b)=>{ - var n=(0|a.sortorder)-(0|b.sortorder); - if (n) return n; // do sortorder first - if (a.nameb.name) return 1; - return 0; - }); -} +let icons = {}; const HEIGHT = g.getHeight(); const WIDTH = g.getWidth(); const HALF = WIDTH/2; -const ANIMATION_FRAME = 4; -const ANIMATION_STEP = HALF / ANIMATION_FRAME; +const ORIGINAL_ICON_SIZE = 48; + +const STATE = { + settings_open: false, + index: 0, + target: 240, + offset: 0 +}; function getPosition(index){ return (index*HALF); } -let current_app = 0; -let target = 0; -let slideOffset = 0; +function getApps(){ + const exit_app = { + name: 'Exit', + special: true + }; + const raw_apps = Storage.list(/\.info$/).filter(app => app.endsWith('.info')).map(app => Storage.readJSON(app,1) || { name: "DEAD: "+app.substr(1) }) + .filter(app=>app.type=="app" || app.type=="clock" || !app.type) + .sort((a,b)=>{ + var n=(0|a.sortorder)-(0|b.sortorder); + if (n) return n; // do sortorder first + if (a.nameb.name) return 1; + return 0; + }).map(raw => ({ + name: raw.name, + src: raw.src, + icon: raw.icon, + version: raw.version + })); -const back = { - name: 'BACK', - back: true -}; - -let icons = {}; - -const apps = [back].concat(getApps()); -apps.push(back); - -function noIcon(x, y, size){ - const half = size/2; - g.setColor(1,1,1); - g.setFontAlign(-0,0); - const fontSize = Math.floor(size / 30 * 2); - g.setFont('6x8', fontSize); - if(fontSize) g.drawString('-?-', x+1.5, y); - g.drawRect(x-half, y-half, x+half, y+half); + const apps = [Object.assign({}, exit_app)].concat(raw_apps); + apps.push(exit_app); + return apps.map((app, i) => { + app.x = getPosition(i); + return app; + }); } -function drawIcons(offset){ - apps.forEach((app, i) => { - const x = getPosition(i) + HALF - offset; - const y = HALF - (HALF*0.3);//-(HALF*0.7); - let diff = (x - HALF); - if(diff < 0) diff *=-1; +const APPS = getApps(); - const dontRender = x+(HALF/2)<0 || x-(HALF/2)>120; - if(dontRender) { - delete icons[app.name]; +function noIcon(x, y, scale){ + if(scale < 0.2) return; + g.setColor(scale, scale, scale); + g.setFontAlign(0,0); + g.setFont('6x8',settings.highres ? 6:3); + g.drawString('x_x', x+1.5, y); + const h = (ORIGINAL_ICON_SIZE/3); + g.drawRect(x-h, y-h, x+h, y+h); +} + +function render(){ + const start = Date.now(); + + const ANIMATION_FRAME = settings.frame; + const ANIMATION_STEP = Math.floor(HALF / ANIMATION_FRAME); + const THRESHOLD = ANIMATION_STEP - 1; + + g.clear(); + const visibleApps = APPS.filter(app => app.x >= STATE.offset-HALF && app.x <= STATE.offset+WIDTH-HALF ); + + visibleApps.forEach(app => { + + const x = app.x+HALF-STATE.offset; + const y = HALF - (HALF*0.3); + + let dist = HALF - x; + if(dist < 0) dist *= -1; + + const scale = 1 - (dist / HALF); + + if(!scale) return; + + if(app.special){ + const font = settings.highres ? '6x8' : '4x6'; + const fontSize = settings.highres ? 2 : 1; + g.setFont(font, fontSize); + g.setColor(scale,scale,scale); + g.setFontAlign(0,0); + g.drawString(app.name, HALF, HALF); return; } - let size = 30; - if((diff*0.5) < size) size -= (diff*0.5); - else size = 0; - const scale = size / 30; - if(size){ - let c = size / 30 * 2; - c = c -1; - if(c < 0) c = 0; + //draw icon + const icon = app.icon ? + icons[app.name] ? icons[app.name] : Storage.read(app.icon) + : null; - if(app.back){ - g.setFont('6x8', 1); - g.setFontAlign(0, -1); - g.setColor(c,c,c); - g.drawString('Back', HALF, HALF); - return; + if(icon){ + icons[app.name] = icon; + try { + const rescale = settings.highres ? scale*ORIGINAL_ICON_SIZE : (scale*(ORIGINAL_ICON_SIZE/2)); + const imageScale = settings.highres ? scale*2 : scale; + g.drawImage(icon, x-rescale, y-rescale, { scale: imageScale }); + } catch(e){ + noIcon(x, y, scale); } - // icon - - const icon = app.icon ? - icons[app.name] ? icons[app.name] : Storage.read(app.icon) - : null; - if(icon){ - icons[app.name] = icon; - try { - g.drawImage(icon, x-(scale*24), y-(scale*24), { scale: scale }); - } catch(e){ - noIcon(x, y, size); - } - }else{ - noIcon(x, y, size); - } - //text - g.setFont('6x8', 1); - g.setFontAlign(0, -1); - g.setColor(c,c,c); - g.drawString(app.name, HALF, HEIGHT - (HALF*0.7)); - - const type = app.type ? app.type : 'App'; - const version = app.version ? app.version : '0.00'; - const info = type+' v'+version; - g.setFontAlign(0,1); - g.setFont('4x6', 0.25); - g.setColor(c,c,c); - g.drawString(info, HALF, 110, { scale: scale }); + }else{ + noIcon(x, y, scale); } - }); -} -function draw(ignoreLoop){ - g.setColor(0,0,0); - g.fillRect(0,0,WIDTH,HEIGHT); - drawIcons(slideOffset); + //draw text + g.setColor(scale,scale,scale); + if(scale > 0.1){ + const font = settings.highres ? '6x8': '4x6'; + const fontSize = settings.highres ? 2 : 1; + g.setFont(font, fontSize); + g.setFontAlign(0,0); + g.drawString(app.name, HALF, HEIGHT/4*3); + } + + if(settings.highres){ + const type = app.type ? app.type : 'App'; + const version = app.version ? app.version : '0.00'; + const info = type+' v'+version; + g.setFontAlign(0,1); + g.setFont('6x8', 1.5); + g.setColor(scale,scale,scale); + g.drawString(info, HALF, 215, { scale: scale }); + } + + }); + + const duration = Math.floor(Date.now()-start); + if(settings.debug){ + g.setFontAlign(0,1); + g.setColor(0, 1, 0); + const fontSize = settings.highres ? 2 : 1; + g.setFont('4x6',fontSize); + g.drawString('Render: '+duration+'ms', HALF, HEIGHT); + } g.flip(); - if(slideOffset == target) return; - if(slideOffset < target) slideOffset+= ANIMATION_STEP; - else if(slideOffset > target) slideOffset -= ANIMATION_STEP; - if(!ignoreLoop) draw(); + if(STATE.offset == STATE.target) return; + + if(STATE.offset < STATE.target) STATE.offset += ANIMATION_STEP; + else if(STATE.offset > STATE.target) STATE.offset -= ANIMATION_STEP; + + if(STATE.offset >= STATE.target-THRESHOLD && STATE.offset < STATE.target) STATE.offset = STATE.target; + if(STATE.offset <= STATE.target+THRESHOLD && STATE.offset > STATE.target) STATE.offset = STATE.target; + setTimeout(render, 0); } function animateTo(index){ - target = getPosition(index); - draw(); -} -function goTo(index){ - current_app = index; - target = getPosition(index); - slideOffset = target; - draw(true); + STATE.index = index; + STATE.target = getPosition(index); + render(); } -goTo(1); +function jumpTo(index){ + STATE.index = index; + STATE.target = getPosition(index); + STATE.offset = STATE.target; + render(); +} function prev(){ - if(current_app == 0) goTo(apps.length-1); - current_app -= 1; - if(current_app < 0) current_app = 0; - animateTo(current_app); + if(STATE.settings_open) return; + if(STATE.index == 0) jumpTo(APPS.length-1); + setTimeout(() => { + if(!settings.animation) jumpTo(STATE.index-1); + else animateTo(STATE.index-1); + },1); } function next(){ - if(current_app == apps.length-1) goTo(0); - current_app += 1; - if(current_app > apps.length-1) current_app = apps.length-1; - animateTo(current_app); + if(STATE.settings_open) return; + if(STATE.index == APPS.length-1) jumpTo(0); + setTimeout(() => { + if(!settings.animation) jumpTo(STATE.index+1); + else animateTo(STATE.index+1); + },1); } -function run() { - const app = apps[current_app]; - if(app.back) return load(); +function run(){ + + const app = APPS[STATE.index]; + if(app.name == 'Exit') return load(); + if (Storage.read(app.src)===undefined) { E.showMessage("App Source\nNot found"); - setTimeout(draw, 2000); + setTimeout(render, 2000); } else { Bangle.setLCDMode(); g.clear(); @@ -162,15 +208,12 @@ function run() { E.showMessage("Loading..."); load(app.src); } + } - -setWatch(prev, BTN1, { repeat: true }); -setWatch(next, BTN3, { repeat: true }); -setWatch(run, BTN2, {repeat:true,edge:"falling"}); - // Screen event Bangle.on('touch', function(button){ + if(STATE.settings_open) return; switch(button){ case 1: prev(); @@ -185,6 +228,7 @@ Bangle.on('touch', function(button){ }); Bangle.on('swipe', dir => { + if(STATE.settings_open) return; if(dir == 1) prev(); else next(); }); @@ -193,3 +237,10 @@ Bangle.on('swipe', dir => { Bangle.on('lcdPower', on => { if(!on) return load(); }); + + +setWatch(prev, BTN1, { repeat: true }); +setWatch(next, BTN3, { repeat: true }); +setWatch(run, BTN2, { repeat:true }); + +jumpTo(1); \ No newline at end of file diff --git a/apps/toucher/settings.js b/apps/toucher/settings.js new file mode 100644 index 000000000..6f7320513 --- /dev/null +++ b/apps/toucher/settings.js @@ -0,0 +1,59 @@ +(function(back) { + + const Storage = require("Storage"); + const filename = 'toucher.json'; + let settings = Storage.readJSON(filename,1)|| null; + + function getSettings(){ + return { + highres: true, + animation : true, + frame : 3, + debug: true + }; + } + + function updateSettings() { + require("Storage").writeJSON(filename, settings); + Bangle.buzz(); + } + + if(!settings){ + settings = getSettings(); + updateSettings(); + } + + function saveChange(name){ + return function(v){ + settings[name] = v; + updateSettings(); + } + } + + E.showMenu({ + '': { 'title': 'Toucher settings' }, + "Resolution" : { + value : settings.highres, + format : v => v?"High":"Low", + onchange: v => { + saveChange('highres')(!settings.highres); + } + }, + "Animation" : { + value : settings.animation, + format : v => v?"On":"Off", + onchange : saveChange('animation') + }, + "Frame rate" : { + value : settings.frame, + min: 1, max: 10, step: 1, + onchange : saveChange('frame') + }, + "Debug" : { + value : settings.debug, + format : v => v?"On":"Off", + onchange : saveChange('debug') + }, + '< Back': back + }); +}); \ No newline at end of file From 1cdbe79bac650fa639cf57ea4378c5148711ac10 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 23 Apr 2020 15:47:57 +0100 Subject: [PATCH 71/77] Tweak favourite apps code to remove the duplicated app uploader --- js/index.js | 130 +++++++++++++++++++++------------------------------- js/utils.js | 13 ------ 2 files changed, 51 insertions(+), 92 deletions(-) diff --git a/js/index.js b/js/index.js index 51b1d71c3..665b5b62b 100644 --- a/js/index.js +++ b/js/index.js @@ -1,7 +1,6 @@ var appJSON = []; // List of apps and info from apps.json var appsInstalled = []; // list of app JSON var files = []; // list of files on Bangle -var favourites = []; // list of user favourite app const FAVOURITE = "favouriteapps.json"; httpGet("apps.json").then(apps=>{ @@ -144,7 +143,13 @@ function handleAppInterface(app) { }); } -function handleAppFavourite(favourite, app){ +function getAppFavourites() { + var f = localStorage.getItem(FAVOURITE); + return (f === null) ? ["boot","launch","setting"] : JSON.parse(f); +} + +function changeAppFavourite(favourite, app) { + var favourites = getAppFavourites(); if (favourite) { favourites = favourites.concat([app.id]); } else { @@ -154,7 +159,7 @@ function handleAppFavourite(favourite, app){ favourites = favourites.filter(e => e != app.id); } } - localStorage.setItem("favouriteapps.json", JSON.stringify(favourites)); + localStorage.setItem(FAVOURITE, JSON.stringify(favourites)); refreshLibrary(); } @@ -187,6 +192,7 @@ function refreshFilter(){ function refreshLibrary() { var panelbody = document.querySelector("#librarycontainer .panel-body"); var visibleApps = appJSON; + var favourites = getAppFavourites(); if (activeFilter) { if ( activeFilter == "favourites" ) { @@ -200,8 +206,6 @@ function refreshLibrary() { visibleApps = visibleApps.filter(app => app.name.toLowerCase().includes(currentSearch) || app.tags.includes(currentSearch)); } - favourites = (localStorage.getItem(FAVOURITE)) === null ? JSON.parse('["boot","launch","setting"]') : JSON.parse(localStorage.getItem("favouriteapps.json")); - panelbody.innerHTML = visibleApps.map((app,idx) => { var appInstalled = appsInstalled.find(a=>a.id==app.id); var version = getVersionInfo(app, appInstalled); @@ -275,9 +279,9 @@ function refreshLibrary() { } else if (icon.classList.contains("icon-download")) { handleAppInterface(app); } else if ( button.innerText == String.fromCharCode(0x2661)) { - handleAppFavourite(true, app); + changeAppFavourite(true, app); } else if ( button.innerText == String.fromCharCode(0x2665) ) { - handleAppFavourite(false, app); + changeAppFavourite(false, app); } }); }); @@ -478,6 +482,43 @@ function getInstalledApps(refresh) { }); } +/// Removes everything and install the given apps, eg: installMultipleApps(["boot","mclock"], "minimal") +function installMultipleApps(appIds, promptName) { + var apps = appIds.map( appid => appJSON.find(app=>app.id==appid) ); + if (apps.some(x=>x===undefined)) + return Promise.reject("Not all apps found"); + var appCount = apps.length; + return showPrompt("Install Defaults",`Remove everything and install ${promptName} apps?`).then(() => { + return Comms.removeAllApps(); + }).then(()=>{ + Progress.hide({sticky:true}); + appsInstalled = []; + showToast(`Existing apps removed. Installing ${appCount} apps...`); + return new Promise((resolve,reject) => { + function upload() { + var app = apps.shift(); + if (app===undefined) return resolve(); + Progress.show({title:`${app.name} (${appCount-apps.length}/${appCount})`,sticky:true}); + Comms.uploadApp(app,"skip_reset").then((appJSON) => { + Progress.hide({sticky:true}); + if (appJSON) appsInstalled.push(appJSON); + showToast(`(${appCount-apps.length}/${appCount}) ${app.name} Uploaded`); + upload(); + }).catch(function() { + Progress.hide({sticky:true}); + reject(); + }); + } + upload(); + }); + }).then(()=>{ + return Comms.setTime(); + }).then(()=>{ + showToast("Apps successfully installed!","success"); + return getInstalledApps(true); + }); +} + var connectMyDeviceBtn = document.getElementById("connectmydevice"); function handleConnectionChange(connected) { @@ -571,42 +612,8 @@ document.getElementById("removeall").addEventListener("click",event=>{ }); // Install all default apps in one go document.getElementById("installdefault").addEventListener("click",event=>{ - var defaultApps, appCount; httpGet("defaultapps.json").then(json=>{ - defaultApps = JSON.parse(json); - defaultApps = defaultApps.map( appid => appJSON.find(app=>app.id==appid) ); - if (defaultApps.some(x=>x===undefined)) - throw "Not all apps found"; - appCount = defaultApps.length; - return showPrompt("Install Defaults","Remove everything and install default apps?"); - }).then(() => { - return Comms.removeAllApps(); - }).then(()=>{ - Progress.hide({sticky:true}); - appsInstalled = []; - showToast(`Existing apps removed. Installing ${appCount} apps...`); - return new Promise((resolve,reject) => { - function upload() { - var app = defaultApps.shift(); - if (app===undefined) return resolve(); - Progress.show({title:`${app.name} (${appCount-defaultApps.length}/${appCount})`,sticky:true}); - Comms.uploadApp(app,"skip_reset").then((appJSON) => { - Progress.hide({sticky:true}); - if (appJSON) appsInstalled.push(appJSON); - showToast(`(${appCount-defaultApps.length}/${appCount}) ${app.name} Uploaded`); - upload(); - }).catch(function() { - Progress.hide({sticky:true}); - reject(); - }); - } - upload(); - }); - }).then(()=>{ - return Comms.setTime(); - }).then(()=>{ - showToast("Default apps successfully installed!","success"); - return getInstalledApps(true); + return installMultipleApps(JSON.parse(json), "default"); }).catch(err=>{ Progress.hide({sticky:true}); showToast("App Install failed, "+err,"error"); @@ -615,43 +622,8 @@ document.getElementById("installdefault").addEventListener("click",event=>{ // Install all favoutrie apps in one go document.getElementById("installfavourite").addEventListener("click",event=>{ - var defaultApps, appCount; - asyncLocalStorage.getItem(FAVOURITE).then(json=>{ - defaultApps = JSON.parse(json); - defaultApps = defaultApps.map( appid => appJSON.find(app=>app.id==appid) ); - if (defaultApps.some(x=>x===undefined)) - throw "Not all apps found"; - appCount = defaultApps.length; - return showPrompt("Install Defaults","Remove everything and install favourite apps?"); - }).then(() => { - return Comms.removeAllApps(); - }).then(()=>{ - Progress.hide({sticky:true}); - appsInstalled = []; - showToast(`Existing apps removed. Installing ${appCount} apps...`); - return new Promise((resolve,reject) => { - function upload() { - var app = defaultApps.shift(); - if (app===undefined) return resolve(); - Progress.show({title:`${app.name} (${appCount-defaultApps.length}/${appCount})`,sticky:true}); - Comms.uploadApp(app,"skip_reset").then((appJSON) => { - Progress.hide({sticky:true}); - if (appJSON) appsInstalled.push(appJSON); - showToast(`(${appCount-defaultApps.length}/${appCount}) ${app.name} Uploaded`); - upload(); - }).catch(function() { - Progress.hide({sticky:true}); - reject(); - }); - } - upload(); - }); - }).then(()=>{ - return Comms.setTime(); - }).then(()=>{ - showToast("Favourites apps successfully installed!","success"); - return getInstalledApps(true); - }).catch(err=>{ + var favApps = getAppFavourites(); + installMultipleApps(favApps, "favourite").catch(err=>{ Progress.hide({sticky:true}); showToast("App Install failed, "+err,"error"); }); diff --git a/js/utils.js b/js/utils.js index f4670da3c..53eeb1868 100644 --- a/js/utils.js +++ b/js/utils.js @@ -79,16 +79,3 @@ function getVersionInfo(appListing, appInstalled) { canUpdate : canUpdate } } - -const asyncLocalStorage = { - setItem: function (key, value) { - return Promise.resolve().then(function () { - localStorage.setItem(key, value); - }); - }, - getItem: function (key) { - return Promise.resolve().then(function () { - return localStorage.getItem(key); - }); - } -}; From e93a9125e4a5999f189364d5860e6ce0546802e3 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Thu, 23 Apr 2020 15:53:51 +0000 Subject: [PATCH 72/77] put toucher.json correctly in the apps.json --- apps.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index ad5b20820..6d67d8b40 100644 --- a/apps.json +++ b/apps.json @@ -1098,10 +1098,12 @@ "description": "Touch enable left to right launcher.", "tags": "tool,system,launcher", "type":"launch", + "data": [ + {"name":"toucher.json"} + ], "storage": [ {"name":"toucher.app.js","url":"app.js"}, - {"name":"toucher.settings.js","url":"settings.js"}, - {"name":"toucher.json"} + {"name":"toucher.settings.js","url":"settings.js"} ], "sortorder" : -10 }, From 4441f3055cf5db49660e2b5ec07e78b1ba0ca161 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Thu, 23 Apr 2020 19:05:22 +0200 Subject: [PATCH 73/77] Added local and support for 12h clock --- apps/rclock/rclock.app.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index bd8395116..a8debe282 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -4,6 +4,8 @@ var hours; var date; var first = true; + var locale = require('locale'); + var _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||false; const screen = { width: g.getWidth(), @@ -41,17 +43,7 @@ }; const dateStr = function (date) { - day = date.getDate(); - month = date.getMonth(); - year = date.getFullYear(); - if (day < 10) { - day = "0" + day; - } - if (month < 10) { - month = "0" + month; - } - - return year + "-" + month + "-" + day; + return locale.date(new Date(),1); }; const getArcXY = function (centerX, centerY, radius, angle) { @@ -133,9 +125,22 @@ //Write the time as configured in the settings hours = currentTime.getHours(); + if(_12hour && hours>13) { + hours=hours-12; + } + + var medidian=locale.medidian(new Date()); + var timestr; + + if(medidian.length>0) { + timestr=hour+" "+medidian; + } else { + timestr=hour; + } + g.setColor(settings.time.color); g.setFont(settings.time.font, settings.time.size); - g.drawString(hours, settings.time.center, settings.time.middle); + g.drawString(timestr, settings.time.center, settings.time.middle); //Write the date as configured in the settings g.setColor(settings.date.color); From 9ce908761a2d826f801e8289123ad195bfce8d3f Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Thu, 23 Apr 2020 19:09:31 +0200 Subject: [PATCH 74/77] Updated changelog --- apps/rclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog index a8f708a0a..23b1a6e87 100644 --- a/apps/rclock/ChangeLog +++ b/apps/rclock/ChangeLog @@ -1 +1,2 @@ 0.01: First published version of app +0.02: Added support for locale and 12H clock \ No newline at end of file From 0874fb698a882b22fa473a4b59d7fa7acf36555b Mon Sep 17 00:00:00 2001 From: bengwalker <63957296+bengwalker@users.noreply.github.com> Date: Thu, 23 Apr 2020 19:14:18 +0200 Subject: [PATCH 75/77] Update README.md --- apps/metronome/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/metronome/README.md b/apps/metronome/README.md index aab2d5a3f..1bb9a893c 100644 --- a/apps/metronome/README.md +++ b/apps/metronome/README.md @@ -11,4 +11,4 @@ This metronome makes your watch blink and vibrate with a given rate. ## Attributions -"Icon made by Roundicons from www.flaticon.com" \ No newline at end of file +Icon made by Roundicons from www.flaticon.com From 5c3e5ff2eeb7b7e396ef5193f9a911c24329bce0 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Thu, 23 Apr 2020 19:35:18 +0200 Subject: [PATCH 76/77] Fixing so that hour is shown right --- apps/rclock/rclock.app.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index a8debe282..15bc3caf0 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -129,13 +129,20 @@ hours=hours-12; } - var medidian=locale.medidian(new Date()); + var meridian; + + if (typeof locale.meridian === "function") { + meridian=locale.meridian(new Date()); + } else { + meridian=""; + } + var timestr; - if(medidian.length>0) { - timestr=hour+" "+medidian; + if(meridian.length>0 && _12hour) { + timestr=hours+" "+meridian; } else { - timestr=hour; + timestr=hours; } g.setColor(settings.time.color); From 43ae16f1c0154024ececda3c1786483a911b4bdb Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Thu, 23 Apr 2020 19:43:48 +0200 Subject: [PATCH 77/77] Clean up code format --- apps/rclock/rclock.app.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 15bc3caf0..4e63fe36a 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -5,7 +5,7 @@ var date; var first = true; var locale = require('locale'); - var _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||false; + var _12hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"] || false; const screen = { width: g.getWidth(), @@ -43,7 +43,7 @@ }; const dateStr = function (date) { - return locale.date(new Date(),1); + return locale.date(new Date(), 1); }; const getArcXY = function (centerX, centerY, radius, angle) { @@ -64,7 +64,7 @@ //g.setPixel(r[0],r[1]); g.drawLine(r1[0], r1[1], r2[0], r2[1]); g.setColor('#333333'); - g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width-4) + g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width - 4) }; const drawSecArc = function (sections, color) { @@ -76,7 +76,7 @@ //g.setPixel(r[0],r[1]); g.drawLine(r1[0], r1[1], r2[0], r2[1]); g.setColor('#333333'); - g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width-4) + g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width - 4) }; const drawClock = function () { @@ -96,7 +96,7 @@ } first = false; } - + // Reset seconds if (seconds == 59) { g.setColor('#000000'); @@ -120,29 +120,29 @@ //Update seconds when needed if (seconds != currentTime.getSeconds()) { seconds = currentTime.getSeconds(); - drawSecArc(seconds, settings.circle.colorsec); + drawSecArc(seconds, settings.circle.colorsec); } //Write the time as configured in the settings hours = currentTime.getHours(); - if(_12hour && hours>13) { - hours=hours-12; + if (_12hour && hours > 13) { + hours = hours - 12; } var meridian; - if (typeof locale.meridian === "function") { - meridian=locale.meridian(new Date()); + if (typeof locale.meridian === "function") { + meridian = locale.meridian(new Date()); } else { - meridian=""; + meridian = ""; } var timestr; - if(meridian.length>0 && _12hour) { - timestr=hours+" "+meridian; + if (meridian.length > 0 && _12hour) { + timestr = hours + " " + meridian; } else { - timestr=hours; + timestr = hours; } g.setColor(settings.time.color); @@ -161,7 +161,7 @@ // clean app screen g.clear(); - g.setFontAlign( 0, 0, 0); + g.setFontAlign(0, 0, 0); Bangle.loadWidgets(); Bangle.drawWidgets();