From d436ce60dddb8645b094428394d1548e42bf081f Mon Sep 17 00:00:00 2001 From: Marco H Date: Wed, 26 Oct 2022 13:31:52 +0200 Subject: [PATCH] Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16 --- apps/circlesclock/ChangeLog | 1 + apps/circlesclock/app.js | 289 ++++++++++++++++++-------------- apps/circlesclock/metadata.json | 2 +- 3 files changed, 161 insertions(+), 131 deletions(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index d74badcad..71729d050 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -27,3 +27,4 @@ 0.13: Load step goal from Bangle health app as fallback Memory optimizations 0.14: Support to show big weather info +0.15: Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16 diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 824445ff6..4ccec3f4b 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -1,5 +1,5 @@ -const locale = require("locale"); -const storage = require("Storage"); +let locale = require("locale"); +let storage = require("Storage"); Graphics.prototype.setFontRobotoRegular50NumericOnly = function(scale) { // Actual height 39 (40 - 2) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAB8AAAAAAAfAAAAAAAPwAAAAAAB8AAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA4AAAAAAB+AAAAAAD/gAAAAAD/4AAAAAH/4AAAAAP/wAAAAAP/gAAAAAf/gAAAAAf/AAAAAA/+AAAAAB/+AAAAAB/8AAAAAD/4AAAAAH/4AAAAAD/wAAAAAA/wAAAAAAPgAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wAAAB////gAAA////8AAA/////gAAP////8AAH8AAA/gAB8AAAD4AA+AAAAfAAPAAAADwADwAAAA8AA8AAAAPAAPAAAADwADwAAAA8AA8AAAAPAAPgAAAHwAB8AAAD4AAfwAAD+AAD/////AAA/////wAAH////4AAAf///4AAAB///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAPgAAAAAADwAAAAAAB8AAAAAAAfAAAAAAAHgAAAAAAD4AAAAAAA+AAAAAAAPAAAAAAAH/////wAB/////8AA//////AAP/////wAD/////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAfgAADwAAP4AAB8AAH+AAA/AAD/gAAfwAB/AAAf8AAfAAAP/AAPgAAH7wAD4AAD88AA8AAB+PAAPAAA/DwADwAAfg8AA8AAPwPAAPAAH4DwADwAH8A8AA+AD+APAAPwB/ADwAB/D/gA8AAf//gAPAAD//wADwAAf/wAA8AAD/4AAPAAAHwAADwAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAADgAAAHwAA+AAAD8AAP4AAB/AAD/AAA/wAA/wAAf4AAD+AAHwAAAPgAD4APAB8AA+ADwAPAAPAA8ADwADwAPAA8AA8ADwAPAAPAA8ADwADwAfAA8AA8AH4APAAPgD+AHwAB8B/wD4AAf7/+B+AAD//v//AAA//x//wAAD/4P/4AAAf8B/4AAAAYAH4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAHwAAAAAAH8AAAAAAD/AAAAAAD/wAAAAAD/8AAAAAB/vAAAAAB/jwAAAAA/g8AAAAA/wPAAAAAfwDwAAAAf4A8AAAAf4APAAAAP8ADwAAAP8AA8AAAH8AAPAAAD/////8AA//////AAP/////wAD/////8AA//////AAAAAAPAAAAAAADwAAAAAAA8AAAAAAAPAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAB/APwAAH//wD+AAD//8A/wAA///AH+AAP//wAPgAD/B4AB8AA8A+AAfAAPAPAADwADwDwAA8AA8A8AAPAAPAPAADwADwD4AA8AA8A+AAPAAPAPwAHwADwD8AD4AA8AfwD+AAPAH///AADwA///wAA8AH//4AAPAAf/4AAAAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAD//+AAAAD///4AAAD////AAAB////4AAA/78D/AAAfw8AH4AAPweAA+AAD4PgAHwAB8DwAA8AAfA8AAPAAHgPAADwAD4DwAA8AA+A8AAPAAPAPgAHwADwD4AB8AA8AfgA+AAPAH+B/gAAAA///wAAAAH//4AAAAA//8AAAAAH/8AAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAA8AAAAAAAPAAAAAAADwAAAAAAA8AAAABAAPAAAABwADwAAAB8AA8AAAB/AAPAAAB/wADwAAD/8AA8AAD/8AAPAAD/4AADwAD/4AAA8AD/4AAAPAH/wAAADwH/wAAAA8H/wAAAAPH/wAAAAD3/gAAAAA//gAAAAAP/gAAAAAD/gAAAAAA/AAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwA/4AAAH/Af/AAAH/8P/4AAD//n//AAA//7//4AAfx/+A+AAHwD+AHwAD4AfgB8AA8AHwAPAAPAA8ADwADwAPAA8AA8ADwAPAAPAA8ADwADwAfAA8AA+AH4AfAAHwD+AHwAB/D/4D4AAP/+/n+AAD//n//AAAf/w//gAAB/wH/wAAAHwA/4AAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAAAAAD/8AAAAAD//wAAAAB//+AAAAA///wAAAAf4H+APAAH4AfgDwAD8AB8A8AA+AAfAPAAPAADwDwADwAA8B8AA8AAPAfAAPAADwHgADwAA8D4AA+AAeB+AAHwAHg/AAB+ADwfgAAP8D4/4AAD////8AAAf///8AAAB///+AAAAP//+AAAAAP/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAOAAAB8AAHwAAAfgAD8AAAH4AA/AAAB8AAHwAAAOAAA4AAAAAAAAAAAAAAAAAAAAAAAAAA"), 46, atob("DRUcHBwcHBwcHBwcDA=="), 50+(scale<<8)+(1<<16)); @@ -12,7 +12,7 @@ Graphics.prototype.setFontRobotoRegular21 = function(scale) { return this; }; -const SETTINGS_FILE = "circlesclock.json"; +let SETTINGS_FILE = "circlesclock.json"; let settings = Object.assign( storage.readJSON("circlesclock.default.json", true) || {}, storage.readJSON(SETTINGS_FILE, true) || {} @@ -23,12 +23,15 @@ if (settings.stepGoal == undefined) { let d = storage.readJSON("health.json", true) || {}; settings.stepGoal = d != undefined && d.settings != undefined ? d.settings.stepGoal : undefined; - if (settings.stepGoal == undefined) { + if (settings.stepGoal == undefined) { d = storage.readJSON("wpedom.json", true) || {}; settings.stepGoal = d != undefined && d.settings != undefined ? d.settings.goal : 10000; } } +let timerHrm; +let drawTimeout; + /* * Read location from myLocation app */ @@ -37,30 +40,30 @@ function getLocation() { } let location = getLocation(); -const showWidgets = settings.showWidgets || false; -const circleCount = settings.circleCount || 3; -const showBigWeather = settings.showBigWeather || false; +let showWidgets = settings.showWidgets || false; +let circleCount = settings.circleCount || 3; +let showBigWeather = settings.showBigWeather || false; let hrtValue; let now = Math.round(new Date().getTime() / 1000); // layout values: -const colorFg = g.theme.dark ? '#fff' : '#000'; -const colorBg = g.theme.dark ? '#000' : '#fff'; -const colorGrey = '#808080'; -const colorRed = '#ff0000'; -const colorGreen = '#008000'; -const colorBlue = '#0000ff'; -const colorYellow = '#ffff00'; -const widgetOffset = showWidgets ? 24 : 0; -const dowOffset = circleCount == 3 ? 20 : 22; // dow offset relative to date -const h = g.getHeight() - widgetOffset; -const w = g.getWidth(); -const hOffset = (circleCount == 3 ? 34 : 30) - widgetOffset; -const h1 = Math.round(1 * h / 5 - hOffset); -const h2 = Math.round(3 * h / 5 - hOffset); -const h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position +let colorFg = g.theme.dark ? '#fff' : '#000'; +let colorBg = g.theme.dark ? '#000' : '#fff'; +let colorGrey = '#808080'; +let colorRed = '#ff0000'; +let colorGreen = '#008000'; +let colorBlue = '#0000ff'; +let colorYellow = '#ffff00'; +let widgetOffset = showWidgets ? 24 : 0; +let dowOffset = circleCount == 3 ? 20 : 22; // dow offset relative to date +let h = g.getHeight() - widgetOffset; +let w = g.getWidth(); +let hOffset = (circleCount == 3 ? 34 : 30) - widgetOffset; +let h1 = Math.round(1 * h / 5 - hOffset); +let h2 = Math.round(3 * h / 5 - hOffset); +let h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position /* * circle x positions @@ -74,21 +77,21 @@ const h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position * | (1) (2) (3) (4) | * => circles start at 1,3,5,7 / 8 */ -const parts = circleCount * 2; -const circlePosX = [ +let parts = circleCount * 2; +let circlePosX = [ Math.round(1 * w / parts), // circle1 Math.round(3 * w / parts), // circle2 Math.round(5 * w / parts), // circle3 Math.round(7 * w / parts), // circle4 ]; -const radiusOuter = circleCount == 3 ? 25 : 20; -const radiusInner = circleCount == 3 ? 20 : 15; -const circleFontSmall = circleCount == 3 ? "Vector:14" : "Vector:10"; -const circleFont = circleCount == 3 ? "Vector:15" : "Vector:11"; -const circleFontBig = circleCount == 3 ? "Vector:16" : "Vector:12"; -const iconOffset = circleCount == 3 ? 6 : 8; -const defaultCircleTypes = ["steps", "hr", "battery", "weather"]; +let radiusOuter = circleCount == 3 ? 25 : 20; +let radiusInner = circleCount == 3 ? 20 : 15; +let circleFontSmall = circleCount == 3 ? "Vector:14" : "Vector:10"; +let circleFont = circleCount == 3 ? "Vector:15" : "Vector:11"; +let circleFontBig = circleCount == 3 ? "Vector:16" : "Vector:12"; +let iconOffset = circleCount == 3 ? 6 : 8; +let defaultCircleTypes = ["steps", "hr", "battery", "weather"]; function hideWidgets() { /* @@ -142,13 +145,13 @@ function draw() { // weather if (showBigWeather) { - const weather = getWeather(); - const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; + let weather = getWeather(); + let tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; g.setFontAlign(1, 0); if (tempString) g.drawString(tempString, w, h2); - const code = weather ? weather.code : -1; - const icon = getWeatherIconByCode(code, true); + let code = weather ? weather.code : -1; + let icon = getWeatherIconByCode(code, true); if (icon) g.drawImage(icon, w - 48, h1, {scale:0.75}); } @@ -156,12 +159,14 @@ function draw() { drawCircle(2); drawCircle(3); if (circleCount >= 4) drawCircle(4); + + queueDraw(); } function drawCircle(index) { let type = settings['circle' + index]; if (!type) type = defaultCircleTypes[index - 1]; - const w = getCircleXPosition(type); + let w = getCircleXPosition(type); switch (type) { case "steps": @@ -213,7 +218,7 @@ function getCirclePosition(type) { return circlePositionsCache[type]; } for (let i = 1; i <= circleCount; i++) { - const setting = settings['circle' + i]; + let setting = settings['circle' + i]; if (setting == type) { circlePositionsCache[type] = i - 1; return i - 1; @@ -229,7 +234,7 @@ function getCirclePosition(type) { } function getCircleXPosition(type) { - const circlePos = getCirclePosition(type); + let circlePos = getCirclePosition(type); if (circlePos != undefined) { return circlePosX[circlePos]; } @@ -241,14 +246,14 @@ function isCircleEnabled(type) { } function getCircleColor(type) { - const pos = getCirclePosition(type); - const color = settings["circle" + (pos + 1) + "color"]; + let pos = getCirclePosition(type); + let color = settings["circle" + (pos + 1) + "color"]; if (color && color != "") return color; } function getCircleIconColor(type, color, percent) { - const pos = getCirclePosition(type); - const colorizeIcon = settings["circle" + (pos + 1) + "colorizeIcon"] == true; + let pos = getCirclePosition(type); + let colorizeIcon = settings["circle" + (pos + 1) + "colorizeIcon"] == true; if (colorizeIcon) { return getGradientColor(color, percent); } else { @@ -259,18 +264,18 @@ function getCircleIconColor(type, color, percent) { function getGradientColor(color, percent) { if (isNaN(percent)) percent = 0; if (percent > 1) percent = 1; - const colorList = [ + let colorList = [ '#00FF00', '#80FF00', '#FFFF00', '#FF8000', '#FF0000' ]; if (color == "fg") { color = colorFg; } if (color == "green-red") { - const colorIndex = Math.round(colorList.length * percent); + let colorIndex = Math.round(colorList.length * percent); return colorList[Math.min(colorIndex, colorList.length) - 1] || "#00ff00"; } if (color == "red-green") { - const colorIndex = colorList.length - Math.round(colorList.length * percent); + let colorIndex = colorList.length - Math.round(colorList.length * percent); return colorList[Math.min(colorIndex, colorList.length)] || "#ff0000"; } return color; @@ -293,14 +298,14 @@ function getImage(graphic, color) { function drawSteps(w) { if (!w) w = getCircleXPosition("steps"); - const steps = getSteps(); + let steps = getSteps(); drawCircleBackground(w); - const color = getCircleColor("steps"); + let color = getCircleColor("steps"); let percent; - const stepGoal = settings.stepGoal; + let stepGoal = settings.stepGoal; if (stepGoal > 0) { percent = steps / stepGoal; if (stepGoal < steps) percent = 1; @@ -316,16 +321,16 @@ function drawSteps(w) { function drawStepsDistance(w) { if (!w) w = getCircleXPosition("stepsDistance"); - const steps = getSteps(); - const stepDistance = settings.stepLength; - const stepsDistance = Math.round(steps * stepDistance); + let steps = getSteps(); + let stepDistance = settings.stepLength; + let stepsDistance = Math.round(steps * stepDistance); drawCircleBackground(w); - const color = getCircleColor("stepsDistance"); + let color = getCircleColor("stepsDistance"); let percent; - const stepDistanceGoal = settings.stepDistanceGoal; + let stepDistanceGoal = settings.stepDistanceGoal; if (stepDistanceGoal > 0) { percent = stepsDistance / stepDistanceGoal; if (stepDistanceGoal < stepsDistance) percent = 1; @@ -342,16 +347,16 @@ function drawStepsDistance(w) { function drawHeartRate(w) { if (!w) w = getCircleXPosition("hr"); - const heartIcon = atob("EBCBAAAAAAAeeD/8P/x//n/+P/w//B/4D/AH4APAAYAAAAAA"); + let heartIcon = atob("EBCBAAAAAAAeeD/8P/x//n/+P/w//B/4D/AH4APAAYAAAAAA"); drawCircleBackground(w); - const color = getCircleColor("hr"); + let color = getCircleColor("hr"); let percent; if (hrtValue != undefined) { - const minHR = settings.minHR; - const maxHR = settings.maxHR; + let minHR = settings.minHR; + let maxHR = settings.maxHR; percent = (hrtValue - minHR) / (maxHR - minHR); if (isNaN(percent)) percent = 0; drawGauge(w, h3, percent, color); @@ -366,9 +371,9 @@ function drawHeartRate(w) { function drawBattery(w) { if (!w) w = getCircleXPosition("battery"); - const battery = E.getBattery(); + let battery = E.getBattery(); - const powerIcon = atob("EBCBAAAAA8ADwA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AH4AAA"); + let powerIcon = atob("EBCBAAAAA8ADwA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AH4AAA"); drawCircleBackground(w); @@ -396,18 +401,18 @@ function drawBattery(w) { function drawWeather(w) { if (!w) w = getCircleXPosition("weather"); - const weather = getWeather(); - const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; - const code = weather ? weather.code : -1; + let weather = getWeather(); + let tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; + let code = weather ? weather.code : -1; drawCircleBackground(w); - const color = getCircleColor("weather"); + let color = getCircleColor("weather"); let percent; - const data = settings.weatherCircleData; + let data = settings.weatherCircleData; switch (data) { case "humidity": - const humidity = weather ? weather.hum : undefined; + let humidity = weather ? weather.hum : undefined; if (humidity >= 0) { percent = humidity / 100; drawGauge(w, h3, percent, color); @@ -415,7 +420,7 @@ function drawWeather(w) { break; case "wind": if (weather) { - const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); + let wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); if (wind[1] >= 0) { if (wind[2] == "kmh") { wind[1] = windAsBeaufort(wind[1]); @@ -435,7 +440,7 @@ function drawWeather(w) { writeCircleText(w, tempString ? tempString : "?"); if (code > 0) { - const icon = getWeatherIconByCode(code); + let icon = getWeatherIconByCode(code); if (icon) g.drawImage(getImage(icon, getCircleIconColor("weather", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); } else { g.drawString("?", w, h3 + radiusOuter); @@ -444,15 +449,15 @@ function drawWeather(w) { function drawSunProgress(w) { if (!w) w = getCircleXPosition("sunprogress"); - const percent = getSunProgress(); + let percent = getSunProgress(); // sunset icons: - const sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA"); - const sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA"); + let sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA"); + let sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA"); drawCircleBackground(w); - const color = getCircleColor("sunprogress"); + let color = getCircleColor("sunprogress"); drawGauge(w, h3, percent, color); @@ -460,15 +465,15 @@ function drawSunProgress(w) { let icon = sunSetDown; let text = "?"; - const times = getSunData(); + let times = getSunData(); if (times != undefined) { - const sunRise = Math.round(times.sunrise.getTime() / 1000); - const sunSet = Math.round(times.sunset.getTime() / 1000); + let sunRise = Math.round(times.sunrise.getTime() / 1000); + let sunSet = Math.round(times.sunset.getTime() / 1000); if (!isDay()) { // night if (now > sunRise) { // after sunRise - const upcomingSunRise = sunRise + 60 * 60 * 24; + let upcomingSunRise = sunRise + 60 * 60 * 24; text = formatSeconds(upcomingSunRise - now); } else { text = formatSeconds(sunRise - now); @@ -492,12 +497,12 @@ function drawTemperature(w) { getPressureValue("temperature").then((temperature) => { drawCircleBackground(w); - const color = getCircleColor("temperature"); + let color = getCircleColor("temperature"); let percent; if (temperature) { - const min = -40; - const max = 85; + let min = -40; + let max = 85; percent = (temperature - min) / (max - min); drawGauge(w, h3, percent, color); } @@ -506,7 +511,7 @@ function drawTemperature(w) { if (temperature) writeCircleText(w, locale.temp(temperature)); - + g.drawImage(getImage(atob("EBCBAAAAAYADwAJAAkADwAPAA8ADwAfgB+AH4AfgA8ABgAAA"), getCircleIconColor("temperature", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); }); @@ -518,12 +523,12 @@ function drawPressure(w) { getPressureValue("pressure").then((pressure) => { drawCircleBackground(w); - const color = getCircleColor("pressure"); + let color = getCircleColor("pressure"); let percent; if (pressure && pressure > 0) { - const minPressure = 950; - const maxPressure = 1050; + let minPressure = 950; + let maxPressure = 1050; percent = (pressure - minPressure) / (maxPressure - minPressure); drawGauge(w, h3, percent, color); } @@ -544,12 +549,12 @@ function drawAltitude(w) { getPressureValue("altitude").then((altitude) => { drawCircleBackground(w); - const color = getCircleColor("altitude"); + let color = getCircleColor("altitude"); let percent; if (altitude) { - const min = 0; - const max = 10000; + let min = 0; + let max = 10000; percent = (altitude - min) / (max - min); drawGauge(w, h3, percent, color); } @@ -568,7 +573,7 @@ function drawAltitude(w) { * wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale) */ function windAsBeaufort(windInKmh) { - const beaufort = [2, 6, 12, 20, 29, 39, 50, 62, 75, 89, 103, 118]; + let beaufort = [2, 6, 12, 20, 29, 39, 50, 62, 75, 89, 103, 118]; let l = 0; while (l < beaufort.length && beaufort[l] < windInKmh) { l++; @@ -582,21 +587,21 @@ function windAsBeaufort(windInKmh) { * https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2 */ function getWeatherIconByCode(code, big) { - const codeGroup = Math.round(code / 100); + let codeGroup = Math.round(code / 100); if (big == undefined) big = false; // weather icons: - const weatherCloudy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAAAAAfg+AAAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAAAAAHvAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD3gAAAAAAAAeeAAAAAAAAB58AAAAAAAAPj4AAAAAAAB8H4AAAAAAAfgP////////8Af////////gA////////8AAf//////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAAAAAfgD/Af8H/4//7///////9//z/+AAAAAAAA"); - const weatherSunny = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAwADwADAAAAHgAPAAeAAAAfAA8AD4AAAA+ADwAfAAAAB8APAD4AAAAD4B+AfAAAAAHw//D4AAAAAPv//fAAAAAAf///4AAAAAA/4H/AAAAAAB+AH4AAAAAAPgAHwAAAAAA8AAPAAAAAAHwAA+AAAAAAeAAB4AAAAAB4AAHgAAAAAPAAAPAAAA//8AAA//8AD//wAAD//wAP//AAAP//AA//8AAA//8AAADwAADwAAAAAHgAAeAAAAAAeAAB4AAAAAB8AAPgAAAAADwAA8AAAAAAPgAHwAAAAAAfgB+AAAAAAD/gf8AAAAAAf///4AAAAAD7//3wAAAAAfD/8PgAAAAD4B+AfAAAAAfADwA+AAAAD4APAB8AAAAfAA8AD4AAAB4ADwAHgAAADAAPAAMAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAQCBAIA8AH4A/wb/YP8A/gB+ARiBAIAYABgAAA"); - const weatherMoon = big ? atob("QEDBAP//wxgAAAYAAAAPAAAAD4AAAA8AAAAPwAAADwAAAA/gAAAPAAAAB/APAP/wAAAH+A8A//AAAAf4DwD/8AAAB/wPAP/wAAAH/gAADwAAAAe+AAAPAAAAB54AAA8AAAAHngAADwAAAAePAAAAAAAAD48OAAAAAAAPDw+AAAAAAB8PD8AAAAAAHg8P4AAAAAA+DwPwAAAAAHwfAfgAAAAB+D4A/AAA8AfwfgB/8AD//+D+AD/8AP//wfgAH/4Af/8B8AAf/wB//APgAAgfgD+AA8AAAAfAH8AHwAAAA+AP8B+AAAAB4Af//4AAAAHgA///gAAAAPAA//8AAAAA8AAf/wAAAADwAAAAAAAAAPAAAAAAAAAA8AcAAAAAAADwD+AAAAAAAfAfgAAAAAAB+D4AAAAAAAB8fAAAAAAAAD54AAAAAAAAHngAAAAAAAAe8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAPeAAAAAAAAB54AAAAAAAAHnwAAAAAAAA+PgAAAAAAAHwfgAAAAAAB+A/////////wB////////+AD////////wAB///////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAP8B/4P/w//D/8f/5//j/8P/w//B/4D/ABgAAA"); - const weatherPartlyCloudy = big ? atob("QEDBAP//wxgAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAABwAPAA4AAAAHgA8AHgAAAAfADwA+AAAAA+AfgHwAAAAB8P/w+AAAAAD7//3wAAAAAH///+BAAAAAP+B/wOAAAAAfgB+B8AAAAD4AD8H4AAAAPAA/wPwAAAB8AH+Af/AAAHgA/AA//AAAeAH4AB/+AADwAfAAH/8A//AD4AAIH4D/8AfAAAAHwP/wB4AAAAPg//AHgAAAAeAA8B+AAAAB4AB4fwAAAADwAHn/AAAAAPAAff8AAAAA8AA/8AAAAADwAD/AAAAAAPAEH4AAAAAA8A4PgAAAAAHwHgcAAAAAAfg+AwAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAAAAAHvAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD3gAAAAAAAAeeAAAAAAAAB58AAAAAAAAPj4AAAAAAAB8H4AAAAAAAfgP////////8Af////////gA////////8AAf//////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAAYQAMAD8AIQBhoW+AOYBwwOBBgHGAGP/wf+AAA"); - const weatherRainy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4APAA8AAfg+AA8ADwAAfHwADwAPAAA+eAAPAA8AAB54AAAAAAAAHvAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AADw8PDwAP8AAPDw8PAA/wAA8PDw8AD3gADw8PDwAeeAAAAAAAAB58AAAAAAAAPj4AAAAAAAB8H4AAAAAAAfgP/w8PDw8P8Af/Dw8PDw/gA/8PDw8PD8AAfw8PDw8OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAPAAAAAAAPAA8AAAAAAA8ADwAAAAAADwAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAH4AwwOBBgGEAOQAJBgjPOEkgGYAZgA8ABgAAA"); - const weatherPartlyRainy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAA8AAfg+AAAADwAAfHwAAAAPAAA+eAAAAA8AAB54AAAADwAAHvAAAAAPAAAP8AAAAA8AAA/wAAAADwAAD/AAAA8PAAAP8AAADw8AAA/wAAAPDwAAD3gAAA8PAAAeeAAADw8AAB58AAAPDwAAPj4AAA8PAAB8H4AADw8AAfgP//8PDw//8Af//w8PD//gA///Dw8P/8AAf/8PDw/+AAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAEEAQAAeADMAYaFvoTmAMMDgQIBxhhiGGG9wDwAGA"); - const weatherSnowy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAADwAfg+AAAAAPAAfHwAAAAA8AA+eAAAAADwAB54AA8AD/8AHvAADwAP/wAP8AAPAA//AA/wAA8AD/8AD/AA//AA8AAP8AD/8ADwAA/wAP/wAPAAD3gA//AA8AAeeAAPAAAAAB58AA8AAAAAPj4ADwAAAAB8H4APAAAAAfgP/wAA8A//8Af/AADwD//gA/8AAPAP/8AAfwAA8A/+AAAAAA//AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAADwAGAEYg73C50BCAEIC50O9wRiAGAA8AAAAAA"); - const weatherFoggy = big ? atob("QEDBAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAwADwADAAAAHgAPAAeAAAAfAA8AD4AAAA+ADwAfAAAAB8APAD4AAAAD4B+AfAAAAAHw//D4AAAAAPv//fAAAAAAf///4AAAAAA/4H/AAAAAAB+AH4AAAAAAPgAHwAAAAAA8AAPAAAAAAHwAA+AAAAAAeAAB4AAAAAB4AAHgAAAAAPAAAPAAAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AD///AADwAAAP//8AAeAAAA///wAB4AAAD///AAPgAAAAAAAAA8AAAAAAAAAHwAAAAAAAAB+AAAAAAAAAf8AAAAD///D/4AAAAP//8P3wAAAA///w8PgAAAD///CAfAAAAAAAAAA+AAAAAAAAAB8AAAAAAAAAD4AAAAAAAAAHgAAP//8PAAMAAA///w8AAAAAD///DwAAAAAP//8PAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAADwAZgDDA4EGAcQAZAAgAAf74AAAAAd/4AAAAA"); - const weatherStormy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAAAAAfg+AAAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAD/AAHvAAAAAf4AAP8AAAAB/gAA/wAAAAP8AAD/AAAAA/gAAP8AAAAH+AAA/wAAAAfwAAD3gAAAD/AAAeeAAAAP4AAB58AAAB/AAAPj4AAAH8AAB8H4AAA/gAAfgP//+D//D/8Af//4f/4P/gA///B//B/8AAf/8P/8P+AAAAAAAPgAAAAAAAAB8AAAAAAAAAHwAAAAAAAAA+AAAAAAAAADwAAAAAAAAAfAAAAAAAAAB4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAH4AwwOBBgGEAOQMJAgjmOGcgAgACAAAAAAAAA"); - const unknown = big ? atob("QEDBAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAf/4AAAAAAAH//4AAAAAAA///wAAAAAAH+B/gAAAAAA/AA/AAAAAAH4AB+AAAAAA/AAD4AAAAAD4H4HwAAAAAfB/4PgAAAAB8P/weAAAAAHg//h4AAAAA+Hw+HwAAAAD4eB8PAAAAAP/wDw8AAAAA//APDwAAAAD/8A8PAAAAAH/gDw8AAAAAAAAfDwAAAAAAAH4fAAAAAAAB/B4AAAAAAAf4HgAAAAAAD/A+AAAAAAAfwHwAAAAAAD8A+AAAAAAAPgH4AAAAAAB8B/AAAAAAAHgf4AAAAAAA+H+AAAAAAADwfwAAAAAAAPD8AAAAAAAA8PAAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf+AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAADw8AAAAAAAAPDwAAAAAAAA8PAAAAAAAADw8AAAAAAAAP/wAAAAAAAA//AAAAAAAAD/8AAAAAAAAH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : undefined; - + let weatherCloudy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAAAAAfg+AAAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAAAAAHvAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD3gAAAAAAAAeeAAAAAAAAB58AAAAAAAAPj4AAAAAAAB8H4AAAAAAAfgP////////8Af////////gA////////8AAf//////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAAAAAfgD/Af8H/4//7///////9//z/+AAAAAAAA"); + let weatherSunny = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAwADwADAAAAHgAPAAeAAAAfAA8AD4AAAA+ADwAfAAAAB8APAD4AAAAD4B+AfAAAAAHw//D4AAAAAPv//fAAAAAAf///4AAAAAA/4H/AAAAAAB+AH4AAAAAAPgAHwAAAAAA8AAPAAAAAAHwAA+AAAAAAeAAB4AAAAAB4AAHgAAAAAPAAAPAAAA//8AAA//8AD//wAAD//wAP//AAAP//AA//8AAA//8AAADwAADwAAAAAHgAAeAAAAAAeAAB4AAAAAB8AAPgAAAAADwAA8AAAAAAPgAHwAAAAAAfgB+AAAAAAD/gf8AAAAAAf///4AAAAAD7//3wAAAAAfD/8PgAAAAD4B+AfAAAAAfADwA+AAAAD4APAB8AAAAfAA8AD4AAAB4ADwAHgAAADAAPAAMAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAQCBAIA8AH4A/wb/YP8A/gB+ARiBAIAYABgAAA"); + let weatherMoon = big ? atob("QEDBAP//wxgAAAYAAAAPAAAAD4AAAA8AAAAPwAAADwAAAA/gAAAPAAAAB/APAP/wAAAH+A8A//AAAAf4DwD/8AAAB/wPAP/wAAAH/gAADwAAAAe+AAAPAAAAB54AAA8AAAAHngAADwAAAAePAAAAAAAAD48OAAAAAAAPDw+AAAAAAB8PD8AAAAAAHg8P4AAAAAA+DwPwAAAAAHwfAfgAAAAB+D4A/AAA8AfwfgB/8AD//+D+AD/8AP//wfgAH/4Af/8B8AAf/wB//APgAAgfgD+AA8AAAAfAH8AHwAAAA+AP8B+AAAAB4Af//4AAAAHgA///gAAAAPAA//8AAAAA8AAf/wAAAADwAAAAAAAAAPAAAAAAAAAA8AcAAAAAAADwD+AAAAAAAfAfgAAAAAAB+D4AAAAAAAB8fAAAAAAAAD54AAAAAAAAHngAAAAAAAAe8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAPeAAAAAAAAB54AAAAAAAAHnwAAAAAAAA+PgAAAAAAAHwfgAAAAAAB+A/////////wB////////+AD////////wAB///////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAP8B/4P/w//D/8f/5//j/8P/w//B/4D/ABgAAA"); + let weatherPartlyCloudy = big ? atob("QEDBAP//wxgAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAABwAPAA4AAAAHgA8AHgAAAAfADwA+AAAAA+AfgHwAAAAB8P/w+AAAAAD7//3wAAAAAH///+BAAAAAP+B/wOAAAAAfgB+B8AAAAD4AD8H4AAAAPAA/wPwAAAB8AH+Af/AAAHgA/AA//AAAeAH4AB/+AADwAfAAH/8A//AD4AAIH4D/8AfAAAAHwP/wB4AAAAPg//AHgAAAAeAA8B+AAAAB4AB4fwAAAADwAHn/AAAAAPAAff8AAAAA8AA/8AAAAADwAD/AAAAAAPAEH4AAAAAA8A4PgAAAAAHwHgcAAAAAAfg+AwAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAAAAAHvAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD3gAAAAAAAAeeAAAAAAAAB58AAAAAAAAPj4AAAAAAAB8H4AAAAAAAfgP////////8Af////////gA////////8AAf//////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAAYQAMAD8AIQBhoW+AOYBwwOBBgHGAGP/wf+AAA"); + let weatherRainy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4APAA8AAfg+AA8ADwAAfHwADwAPAAA+eAAPAA8AAB54AAAAAAAAHvAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AADw8PDwAP8AAPDw8PAA/wAA8PDw8AD3gADw8PDwAeeAAAAAAAAB58AAAAAAAAPj4AAAAAAAB8H4AAAAAAAfgP/w8PDw8P8Af/Dw8PDw/gA/8PDw8PD8AAfw8PDw8OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAPAAAAAAAPAA8AAAAAAA8ADwAAAAAADwAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAH4AwwOBBgGEAOQAJBgjPOEkgGYAZgA8ABgAAA"); + let weatherPartlyRainy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAA8AAfg+AAAADwAAfHwAAAAPAAA+eAAAAA8AAB54AAAADwAAHvAAAAAPAAAP8AAAAA8AAA/wAAAADwAAD/AAAA8PAAAP8AAADw8AAA/wAAAPDwAAD3gAAA8PAAAeeAAADw8AAB58AAAPDwAAPj4AAA8PAAB8H4AADw8AAfgP//8PDw//8Af//w8PD//gA///Dw8P/8AAf/8PDw/+AAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAEEAQAAeADMAYaFvoTmAMMDgQIBxhhiGGG9wDwAGA"); + let weatherSnowy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAADwAfg+AAAAAPAAfHwAAAAA8AA+eAAAAADwAB54AA8AD/8AHvAADwAP/wAP8AAPAA//AA/wAA8AD/8AD/AA//AA8AAP8AD/8ADwAA/wAP/wAPAAD3gA//AA8AAeeAAPAAAAAB58AA8AAAAAPj4ADwAAAAB8H4APAAAAAfgP/wAA8A//8Af/AADwD//gA/8AAPAP/8AAfwAA8A/+AAAAAA//AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAADwAGAEYg73C50BCAEIC50O9wRiAGAA8AAAAAA"); + let weatherFoggy = big ? atob("QEDBAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAwADwADAAAAHgAPAAeAAAAfAA8AD4AAAA+ADwAfAAAAB8APAD4AAAAD4B+AfAAAAAHw//D4AAAAAPv//fAAAAAAf///4AAAAAA/4H/AAAAAAB+AH4AAAAAAPgAHwAAAAAA8AAPAAAAAAHwAA+AAAAAAeAAB4AAAAAB4AAHgAAAAAPAAAPAAAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AD///AADwAAAP//8AAeAAAA///wAB4AAAD///AAPgAAAAAAAAA8AAAAAAAAAHwAAAAAAAAB+AAAAAAAAAf8AAAAD///D/4AAAAP//8P3wAAAA///w8PgAAAD///CAfAAAAAAAAAA+AAAAAAAAAB8AAAAAAAAAD4AAAAAAAAAHgAAP//8PAAMAAA///w8AAAAAD///DwAAAAAP//8PAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAADwAZgDDA4EGAcQAZAAgAAf74AAAAAd/4AAAAA"); + let weatherStormy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAAAAAfg+AAAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAD/AAHvAAAAAf4AAP8AAAAB/gAA/wAAAAP8AAD/AAAAA/gAAP8AAAAH+AAA/wAAAAfwAAD3gAAAD/AAAeeAAAAP4AAB58AAAB/AAAPj4AAAH8AAB8H4AAA/gAAfgP//+D//D/8Af//4f/4P/gA///B//B/8AAf/8P/8P+AAAAAAAPgAAAAAAAAB8AAAAAAAAAHwAAAAAAAAA+AAAAAAAAADwAAAAAAAAAfAAAAAAAAAB4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAH4AwwOBBgGEAOQMJAgjmOGcgAgACAAAAAAAAA"); + let unknown = big ? atob("QEDBAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAf/4AAAAAAAH//4AAAAAAA///wAAAAAAH+B/gAAAAAA/AA/AAAAAAH4AB+AAAAAA/AAD4AAAAAD4H4HwAAAAAfB/4PgAAAAB8P/weAAAAAHg//h4AAAAA+Hw+HwAAAAD4eB8PAAAAAP/wDw8AAAAA//APDwAAAAD/8A8PAAAAAH/gDw8AAAAAAAAfDwAAAAAAAH4fAAAAAAAB/B4AAAAAAAf4HgAAAAAAD/A+AAAAAAAfwHwAAAAAAD8A+AAAAAAAPgH4AAAAAAB8B/AAAAAAAHgf4AAAAAAA+H+AAAAAAADwfwAAAAAAAPD8AAAAAAAA8PAAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf+AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAADw8AAAAAAAAPDwAAAAAAAA8PAAAAAAAADw8AAAAAAAAP/wAAAAAAAA//AAAAAAAAD/8AAAAAAAAH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : undefined; + switch (codeGroup) { case 2: return weatherStormy; @@ -639,10 +644,10 @@ function getWeatherIconByCode(code, big) { function isDay() { - const times = getSunData(); + let times = getSunData(); if (times == undefined) return true; - const sunRise = Math.round(times.sunrise.getTime() / 1000); - const sunSet = Math.round(times.sunset.getTime() / 1000); + let sunRise = Math.round(times.sunrise.getTime() / 1000); + let sunSet = Math.round(times.sunset.getTime() / 1000); return (now > sunRise && now < sunSet); } @@ -659,7 +664,7 @@ function formatSeconds(s) { function getSunData() { if (location != undefined && location.lat != undefined) { - const SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); + let SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); // get today's sunlight times for lat/lon return SunCalc ? SunCalc.getTimes(new Date(), location.lat, location.lon) : undefined; } @@ -672,14 +677,14 @@ function getSunData() { * Taken from rebble app and modified */ function getSunProgress() { - const times = getSunData(); + let times = getSunData(); if (times == undefined) return 0; - const sunRise = Math.round(times.sunrise.getTime() / 1000); - const sunSet = Math.round(times.sunset.getTime() / 1000); + let sunRise = Math.round(times.sunrise.getTime() / 1000); + let sunSet = Math.round(times.sunset.getTime() / 1000); if (isDay()) { // during day - const dayLength = sunSet - sunRise; + let dayLength = sunSet - sunRise; if (now > sunRise) { return (now - sunRise) / dayLength; } else { @@ -688,10 +693,10 @@ function getSunProgress() { } else { // during night if (now < sunRise) { - const prevSunSet = sunSet - 60 * 60 * 24; + let prevSunSet = sunSet - 60 * 60 * 24; return 1 - (sunRise - now) / (sunRise - prevSunSet); } else { - const upcomingSunRise = sunRise + 60 * 60 * 24; + let upcomingSunRise = sunRise + 60 * 60 * 24; return (upcomingSunRise - now) / (upcomingSunRise - sunSet); } } @@ -726,16 +731,16 @@ function radians(a) { * This draws the actual gauge consisting out of lots of little filled circles */ function drawGauge(cx, cy, percent, color) { - const offset = 15; - const end = 360 - offset; - const radius = radiusInner + (circleCount == 3 ? 3 : 2); - const size = radiusOuter - radiusInner - 2; + let offset = 15; + let end = 360 - offset; + let radius = radiusInner + (circleCount == 3 ? 3 : 2); + let size = radiusOuter - radiusInner - 2; if (percent <= 0) return; // no gauge needed if (percent > 1) percent = 1; - const startRotation = -offset; - const endRotation = startRotation - ((end - offset) * percent); + let startRotation = -offset; + let endRotation = startRotation - ((end - offset) * percent); color = getGradientColor(color, percent); g.setColor(color); @@ -749,7 +754,7 @@ function drawGauge(cx, cy, percent, color) { function writeCircleText(w, content) { if (content == undefined) return; - const font = String(content).length > 4 ? circleFontSmall : String(content).length > 3 ? circleFont : circleFontBig; + let font = String(content).length > 4 ? circleFontSmall : String(content).length > 3 ? circleFont : circleFontBig; g.setFont(font); g.setFontAlign(0, 0); @@ -781,7 +786,7 @@ function getSteps() { } function getWeather() { - const jsonWeather = storage.readJSON('weather.json'); + let jsonWeather = storage.readJSON('weather.json'); return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined; } @@ -822,7 +827,7 @@ function getPressureValue(type) { }); } -Bangle.on('lock', function(isLocked) { +function onLock(isLocked) { if (!isLocked) { draw(); if (isCircleEnabled("hr")) { @@ -831,11 +836,10 @@ Bangle.on('lock', function(isLocked) { } else { Bangle.setHRMPower(0, "circleclock"); } -}); +} +Bangle.on('lock', onLock); - -let timerHrm; -Bangle.on('HRM', function(hrm) { +function onHRM(hrm) { if (isCircleEnabled("hr")) { if (hrm.confidence >= (settings.confidence)) { hrtValue = hrm.bpm; @@ -852,23 +856,48 @@ Bangle.on('HRM', function(hrm) { }, settings.hrmValidity * 1000); } } -}); +} +Bangle.on('HRM', onHRM); -Bangle.on('charging', function(charging) { +function onCharging(charging) { if (isCircleEnabled("battery")) drawBattery(); -}); +} +Bangle.on('charging', onCharging); + if (isCircleEnabled("hr")) { enableHRMSensor(); } -Bangle.setUI("clock"); +Bangle.setUI({ + mode : "clock", + remove : function() { + // Called to unload all of the clock app + Bangle.removeListener('charging', onCharging); + Bangle.removeListener('lock', onLock); + Bangle.removeListener('HRM', onHRM); + + Bangle.setHRMPower(0, "circleclock"); + + if (timerHrm) clearTimeout(timerHrm); + timerHrm = undefined; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + + delete Graphics.prototype.setFontRobotoRegular50NumericOnly; + delete Graphics.prototype.setFontRobotoRegular21; + }}); + Bangle.loadWidgets(); -// schedule a draw for the next minute -setTimeout(function() { - // draw in interval - setInterval(draw, settings.updateInterval * 1000); -}, 60000 - (Date.now() % 60000)); +// schedule a draw for the next second or minute +function queueDraw() { + let queueMillis = settings.updateInterval * 1000; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, queueMillis - (Date.now() % queueMillis)); +} draw(); diff --git a/apps/circlesclock/metadata.json b/apps/circlesclock/metadata.json index a1a291546..e8d5cbbb7 100644 --- a/apps/circlesclock/metadata.json +++ b/apps/circlesclock/metadata.json @@ -1,7 +1,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.14", + "version":"0.15", "description": "A clock with three or four circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}, {"url":"screenshot-dark-4.png"}, {"url":"screenshot-light-4.png"}],