diff --git a/apps.json b/apps.json index 2413febeb..3dbdbe3e2 100644 --- a/apps.json +++ b/apps.json @@ -1094,5 +1094,30 @@ {"name":"minionclk.app.js","url":"app.js"}, {"name":"minionclk.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "openstmap", + "name": "OpenStreetMap", + "shortName":"OpenStMap", + "icon": "app.png", + "version":"0.01", + "description": "[BETA] Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are", + "tags": "outdoors,gps", + "custom": "custom.html", + "storage": [ + {"name":"openstmap.app.js","url":"app.js"}, + {"name":"openstmap.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "tabata", + "name": "Tabata", + "shortName": "Tabata - Control High-Intensity Interval Training", + "icon": "tabata.png", + "version":"0.01", + "description": "Control high-intensity interval training (according to tabata: https://en.wikipedia.org/wiki/Tabata_method).", + "tags": "workout,health", + "storage": [ + {"name":"tabata.app.js","url":"tabata.js"}, + {"name":"tabata.img","url":"tabata-icon.js","evaluate":true} + ] } ] diff --git a/apps/openstmap/ChangeLog b/apps/openstmap/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/openstmap/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/openstmap/app-48.png b/apps/openstmap/app-48.png new file mode 100644 index 000000000..b3e3c1047 Binary files /dev/null and b/apps/openstmap/app-48.png differ diff --git a/apps/openstmap/app-icon.js b/apps/openstmap/app-icon.js new file mode 100644 index 000000000..be06afe32 --- /dev/null +++ b/apps/openstmap/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AAOxAAIFCABmrwwRP/2yBJAvCAAYZJ2Wr1eHAAYSLAAQwP1YYHF4xEGCQovT2IYGFwIwDCIWAq1cwIABrtWwAaETZIuFCgIVDA4QvEBoNcq2s6/X2ezCQIDBwIKB2QBBF5ulAYQvI2IvBEQQAD1gACGQVXwKQPLwQwERwmrwFXLAJTDGAoACxFWF55VCGYSqCXYKOBrqHCAAXXAIQyExABBrjAOFQKSDMYQIBw9W2a7CFYiUGw4wBwTwPSQhmCGAJ7BAB4wDqwvIcwTnFYggFBrrjDRonX2ZnCSImHAQMrF5IAFLQQ3DrgtCRoYvDAQLJDF4ZgJOpAvBFgLtBXoIvHLgQCBF4QuCMAeIF5otCLwIuCw2B1mzEwQBB2etAAouEFoJgBSAwtE2IBCRYQvCwGIE4wACGQI0DGAwvGLopaBMIQvDwztBFQopBMQRkEF47AFRoy8Ga4KOBGAgpCSBoABF5mxRous1eBR4jmCSpAvHR4qJBAAYtCAYIvCAgWBEYZDDF4+yFwuyF4gmBGA4zD1gvCrovHE4JeFF4gNCLwgwBLQYvFAoOsw+rwQvDDwQwHBQ2y69dF4wnCGIelAga+B1bwBSAYkGLQQHF2fX2a+FSAoEB0oDCDwQvDlbxCKo4AGFwPXq4uFeAwuCF4RNBR4OswUslYvPFoPXxAuHF4ruEbAgvBq8rlgvN6wuB1iNGSAwrBMAitCcQOIq0rGBgtC2YTB1gvIQQLpDd4esAoIfCFwUrAYOBRZWzrtdVAIvISA+lFwIEBwGk1YuCF4IABEQIvG2eBq2I1eHF5RfCAAeIMIOxrgqBGIMrmNWrlcwAhBrmBAAdWwAWBxAMB1ZfLFoWsxBkCFwQABv9/qweBwAwDagQABAwIACwIgBLxLkCAAKSDFwiMCwWr2SACLYQ2BHIQACHIKRBF5CiBVIguIldcxGsJwIPCLAYsCwwABF4OswIvJc4QuLq2BfIIwDCYaRBRwiaCqwvILoIWB2IDBFxGAWoOIZgIUDa4YtEMQQuJCoYdBqwuIcoWrxJgBCwaVCFgQBCAALuJPQYuLAARDBSIJdBaoYuDAAdcF5QYB1guJLgOlFwKKCGAaUCXwxeJL4ZdJwLhCLoQAD1jDBF4ZeFF5mHFxGHRghdCGAg3C1YuGF5SbCFw1cFwexwFWCYJnBGAgvCFgmGXpIAD0mrFworB1YsDAAr4CGAQDBJoIsNAAfP1QuCg8AlcGC51cHxIAN1Wjg4wBDSoAUldVF1gA/AH4A5A")) diff --git a/apps/openstmap/app.js b/apps/openstmap/app.js new file mode 100644 index 000000000..ec6dfdfd9 --- /dev/null +++ b/apps/openstmap/app.js @@ -0,0 +1,68 @@ +var s = require("Storage"); +var map = s.readJSON("openstmap.json"); + +map.center = Bangle.project({lat:map.lat,lon:map.lon}); +var lat = map.lat, lon = map.lon; +var fix = {}; + + +function redraw() { + var cx = g.getWidth()/2; + var cy = g.getHeight()/2; + var p = Bangle.project({lat:lat,lon:lon}); + var ix = (p.x-map.center.x)*4096/map.scale + (map.imgx/2) - cx; + var iy = (map.center.y-p.y)*4096/map.scale + (map.imgy/2) - cy; + //console.log(ix,iy); + var tx = 0|(ix/map.tilesize); + var ty = 0|(iy/map.tilesize); + var ox = (tx*map.tilesize)-ix; + var oy = (ty*map.tilesize)-iy; + for (var x=ox,ttx=tx;x + + + + + + + +
+
+
+

Zoom in to the area you want as a map

+

Click

+ +
+ + + + + + + + + + diff --git a/apps/tabata/tabata-icon.js b/apps/tabata/tabata-icon.js new file mode 100644 index 000000000..0a360fbbe --- /dev/null +++ b/apps/tabata/tabata-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwg96iOZzORgMZAYMQCxsBCwIAGDBsZyIDCCYQyBBAQuLEwWZCYYJBFx8BL4ITDjJILBgcJDYIGEyBCHFYQoGC4Y2BRBAJBC4wrDC4w9BiC6BC6Q6DAYIXpCIcJC/4X/C/4X/C50BjITCjOZD4IXOhOZCYMBAYIwEC52QC7QMDC/4XCzBH/C/4X/C5OQa6INBC4WRyIvQC5IOBC5YTBAYILByAECBAIXLA4IwBAYITBgMZDYIXGHgZICEAWRAYQfEAgIXIFAIIBiERCwYKCCQQOBBIQAvA")) diff --git a/apps/tabata/tabata.js b/apps/tabata/tabata.js new file mode 100644 index 000000000..603cf96ee --- /dev/null +++ b/apps/tabata/tabata.js @@ -0,0 +1,130 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +var settings = require("Storage").readJSON("tabata.json",1)||{}; +settings.pause = settings.pause || 10; +settings.training = settings.training || 20; +settings.rounds = settings.rounds || 8; + +const MAX_SECONDS = 100; + +function debounce(callback, ms) { + var timer; + return () => { + if (timer) clearTimeout(timer); + timer = setTimeout(callback, ms); + }; +} + +function saveSettings() { + require("Storage").write("tabata.json",JSON.stringify(settings)); +} + +var saveSettingsDebounce = debounce(saveSettings, 250); + +function showMainMenu() { + const menu = { + '': { 'title': 'Tabata Training' }, + '>> Start >>': ()=> { + startTabata(); + }, + 'Pause sec.': { + value: settings.pause, + onchange: function(v){ + if (v<0)v=MAX_SECONDS; + if (v>MAX_SECONDS)v=0; + settings.pause=v; + this.value=v; + saveSettingsDebounce(); + } + }, + 'Trainig sec.': { + value: settings.training, + onchange: function(v){if (v<0)v=MAX_SECONDS;if (v>MAX_SECONDS)v=0;settings.training=v; + this.value=v; + saveSettingsDebounce(); + } + }, + 'Rounds': { + value: settings.rounds, + onchange: function(v){if (v<0)v=MAX_SECONDS;if (v>MAX_SECONDS)v=0;settings.rounds=v;this.value=v; + saveSettingsDebounce(); + } + }, + '< Back': () => load() + }; + menu['< Back'] = ()=>{load();}; + return E.showMenu(menu); +} + +function startTabata() { + g.clear(); + Bangle.setLCDMode("doublebuffered"); + g.flip(); + var pause = settings.pause, + training = settings.training, + round = 1, + active = true, + clearBtn1, clearBtn2, clearBtn3, timer; + Bangle.buzz(1000, 1); + + function exitTraining() { + clearTimeout(timer); + clearWatch(clearBtn1); + clearWatch(clearBtn2); + clearWatch(clearBtn2); + showMainMenu(); + } + + clearBtn1 = setWatch(exitTraining, BTN1); + clearBtn2 = setWatch(exitTraining, BTN2); + clearBtn3 = setWatch(exitTraining, BTN3); + + + timer = setInterval(function() { + if (round > settings.rounds) { + exitTraining(); + return; + } + + if (active) { + drawCountDown(round, training, active); + training--; + } else { + drawCountDown(round, pause, active); + pause--; + if (pause !== 0) { + Bangle.buzz(50, 0.2); + } + } + + if (training === 0) { + training = settings.training; + active = false; + Bangle.buzz(500, 1); + } + if (pause === 0) { + round++; + pause = settings.pause; + active = true; + Bangle.buzz(1000, 1); + } + }, 1000); +} + +function drawCountDown(round, count, active) { + g.clear(); + + g.setFontAlign(0,0); + g.setFont("6x8", 2); + g.drawString("Round " + round + "/" + settings.rounds,120,6); + + g.setFont("6x8", 6); + g.drawString("" + count,120,80); + + g.setFont("6x8",2); + g.drawString(active ? "Training" : "Pause", 120,45); + g.flip(); +} + +showMainMenu(); diff --git a/apps/tabata/tabata.png b/apps/tabata/tabata.png new file mode 100644 index 000000000..f0aaadede Binary files /dev/null and b/apps/tabata/tabata.png differ