From 02a931f5fd675c4e0b7610e4262eafe455728d63 Mon Sep 17 00:00:00 2001 From: hugh Date: Sat, 5 Nov 2022 00:27:49 +0000 Subject: [PATCH] Added PrimeTimeLato app --- apps/primetimelato/README.md | 13 ++++ apps/primetimelato/app.js | 106 ++++++++++++++++++++++++++++++ apps/primetimelato/app.png | Bin 0 -> 710 bytes apps/primetimelato/icon.js | 1 + apps/primetimelato/metadata.json | 15 +++++ apps/primetimelato/screenshot.png | Bin 0 -> 2287 bytes 6 files changed, 135 insertions(+) create mode 100644 apps/primetimelato/README.md create mode 100644 apps/primetimelato/app.js create mode 100644 apps/primetimelato/app.png create mode 100644 apps/primetimelato/icon.js create mode 100644 apps/primetimelato/metadata.json create mode 100644 apps/primetimelato/screenshot.png diff --git a/apps/primetimelato/README.md b/apps/primetimelato/README.md new file mode 100644 index 000000000..6760fe41a --- /dev/null +++ b/apps/primetimelato/README.md @@ -0,0 +1,13 @@ +# Prime Time Lato (clock) + +A watchface that displays time and its prime factors in the Lato font. +For example when the time is 21:05, the prime factors are 5,421. +Displays 'Prime Time!' when the time is a prime number. + +![](screenshot.jpg) + +Written by: [Hugh Barney](https://github.com/hughbarney) + +Adapted from primetime by [Eve Bury](https://www.github.com/eveeeon) + +For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/primetimelato/app.js b/apps/primetimelato/app.js new file mode 100644 index 000000000..2031fd53b --- /dev/null +++ b/apps/primetimelato/app.js @@ -0,0 +1,106 @@ +const h = g.getHeight(); +const w = g.getWidth(); + +Graphics.prototype.setFontLato = function(scale) { + // Actual height 41 (43 - 3) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('ACEfAokB/AGEn+AAocDBgsfBgkB+A6Yg4FEgYgF/4FEv/gHIhAEh/+DwgYEgP/4AeJn4eF/hDEDwxrE/4eFKAgeFgJDERQ5DEXJI0Eh//IIZlB/4pDAoP/HgQYBAAIaBPARDDv4JBj5WBh5ZCv4CBPATPCeQcPwDYECAIMGPId4gEeSIYMHDIYMCExZAGh6ICn5QEK4RnGOgqBGaoKOECYSiDn78FAFgxFR4bcCKISOBgF+RwYCBTgQMCOIQMCj5eCBgIfDBgQfCBgSbDWoSHC/61CAwYMUAAYzCAAZNCBkYAfgYmBgJ7CTYsPTYQMBgJnBgYMCn4MBv64CBgMPXYSBBD4cfBgQIBgf3RwK7CvybCGQXPBgIfBGQIMBeoU/DoIMCF4IMDgP8BgQmBn8AEwb+BBgQIBIQJAC4BYBIgTNBDYIMBg///xRDn//OoIMBcYISBBgUHNATpCgjCngIEDFIM+AoV8TYKYCMIJQBAQLCCgZcBYQIJBX4UHCwSJBYQaSCMYQDCYQabEBgngW4V4WoQBBOgIMN+AoCEwY+BGYZfBYwQIBv+AG4X+j/8K4TCB+bECM4P+YgcD//B/67Ch/4h//K4SSBv5IBAAdAWqMYAokDD4t+AokfBgi0DAAX/Bgkf7wSE/IME/6PBCQfBBgcD/AME/ypCCQXABgYSBBgg+BBgYSBBgatBBggSBBgYSBBgcB/4ACZ4QGDZ4IMLFARAEAAJaEBjQAUhAnFMgIABuD5CVwWAboUDLwZ0DNYKLBM4IMBh50C55rBCoWACAIMC+EPFIN4EQQMBg4MSHgYzEBgIzBIAUAvhND+EH8DZCBAN/bIfwMQP/OgIMBLgalCBgKlDg//V4kfCQIAqWgYzC/gFDIAJgBZoS3CAwV//4TDh/+j5UCCQOAn4SD8DPCCQSbCCQR/BNAV/3i1CB4PzAYLCBgP8AYIMCv+HBgcP+AMDCQMHEwb2BYQLPDgYMBIAKoBOYLPCwDNBZ4UQBQPhJ4J0EDYJbCZ4R7EAoZiDSoaUDADBNBFQj5EKwQMEGAoMEOgQFCnAMEQIYFBgaOCBgTRBBgc/AYIMCaIQMCgb2CBgX/JQIMCDAQMCh/8JoYYBJoiNDBgIYDBgIYDBgPzUwkfUwisBOokfDAYMCQIq/ERwwAcn4pCgfwg42D//B/6hBCAP+KwYQBMQKbBgF//9+g5EBh4YB4CfC/EHDwK1Dn7PD8A0BgF4gEeAIUHBgQBBBi4mEGYpAEAIMP4BNELQpnGOgM/ZYaBFGQMPYos/JAIAuj4xEKgJrBfoX//hEE/4TDCQJSCCoN/gZfBjCBCj+AgaOCAIiKBg4OCgKKBvgbCWYMDToK1CgE8JIQMC4ZCBBgU4HYTNCz4JBEwV7KoQzCUIYvBLYZNBn60CLQPfCQcDM4LHCEALHDZ4TaCCYaODHYK8fh6FDEwKSCF4Uf4COCBgJsBn4MDDIJPDVgYAZA='))), + 46, + atob("CxMeHh4eHh4eHh4eDQ=="), + 52+(scale<<8)+(1<<16) + ); + return this; +}; + +Graphics.prototype.setFontLatoSmall = function(scale) { + // Actual height 21 (20 - 0) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 32, + atob("BAcIDAwRDwUGBggMBAcECAwMDAwMDAwMDAwFBQwMDAgRDg4OEAwMDxAGCQ4LExARDREOCwwPDhUODQ0GCAYMCAYLDAoMCwcLDAUFCwURDAwMDAgJCAwLEAsLCgYGBgwA"), + 21+(scale<<8)+(1<<16) + ); + return this; +}; + +// creates a list of prime factors of n and outputs them as a string, if n is prime outputs "Prime Time!" +function primeFactors(n) { + const factors = []; + let divisor = 2; + + while (n >= 2) { + if (n % divisor == 0) { + factors.push(divisor); + n = n / divisor; + } else { + divisor++; + } + } + if (factors.length === 1) { + return "Prime Time!"; + } + else + return factors.toString(); +} + + +// converts time HR:MIN to integer HRMIN e.g. 15:35 => 1535 +function timeToInt(t) { + var arr = t.split(':'); + var intTime = parseInt(arr[0])*100+parseInt(arr[1]); + + return intTime; +} + +function draw() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var primeStr = primeFactors(timeToInt(timeStr)); + + g.reset(); + g.setColor(0,0,0); + g.fillRect(Bangle.appRect); + + //g.setFont("6x8", w/30); + g.setFontLato(); + g.setFontAlign(0, 0); + g.setColor(100,100,100); + g.drawString(timeStr, w/2, h/2); + + //g.setFont("6x8", w/60); + g.setFontLatoSmall(); + g.drawString(primeStr, w/2, 3*h/4); + queueDraw(); +} + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + + +g.clear(); +// Show launcher when middle button pressed +Bangle.setUI("clock"); + +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); +draw(); diff --git a/apps/primetimelato/app.png b/apps/primetimelato/app.png new file mode 100644 index 0000000000000000000000000000000000000000..2a84c62a07e71744a3721a4a7f8e3caa3721d71c GIT binary patch literal 710 zcmV;%0y+JOP)Px%fJsC_R9Hvtm^+TbFc5|(bXUD~@YEpQpp&!1vedHBEsjPT^cG zM;ybcdbe!c0b3UI$(&QzDXb~rLc)cF3yHL2;5Q1RAQ}#bY@%AN((!nFiCZidxfVfv zq8@m6zu)su!T0{Zv>2;NWb5I8d`y=R4S}elv5oT zp@7cHvoaD^fhBfzqXILTObFX76JR{ETrNp=IeN$>g@uvANx-k1=n7-f;;h%}JSysL zCJB~1XHvi?g~U6+dIzBR{eF)eohZ9Tz)=(9)udA$MNK+2bW#IGKE=$J^n=tSX-$t| zbzi6hOL`P&gasz8WR#?^Fjg3b;uemmED^O32&9AUmcGzol?iP_O(r z;Iv2Ke=3Yr)#-G?>I~TgUpu8*)7!rp1#1eQPN#>@ut-yCZq?hLLR$ewZGe(d77XNN zwYb;YpTZi~5=joEw%u;GwApOJ599iWa%m^o%Pg&_OR|)WrYo3fC#-~osWThTIba(q sW){O~!&=J{S%8WU7sF|*{dEfe0H(cp6H7fzivR!s07*qoM6N<$f*j~OtpET3 literal 0 HcmV?d00001 diff --git a/apps/primetimelato/icon.js b/apps/primetimelato/icon.js new file mode 100644 index 000000000..06f93e2ef --- /dev/null +++ b/apps/primetimelato/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) diff --git a/apps/primetimelato/metadata.json b/apps/primetimelato/metadata.json new file mode 100644 index 000000000..ab30724ba --- /dev/null +++ b/apps/primetimelato/metadata.json @@ -0,0 +1,15 @@ +{ "id": "primetime", + "name": "Prime Time Lato Clock", + "version": "0.01", + "type": "clock", + "description": "A clock that tells you the primes of the time in the Lato font", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "tags": "clock", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"primetimelato.app.js","url":"app.js"}, + {"name":"primetimelato.img","url":"icon.js","evaluate":true} + ] +} diff --git a/apps/primetimelato/screenshot.png b/apps/primetimelato/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..7f6e7cc0d173c5b79feb938a18255d874f9359cc GIT binary patch literal 2287 zcmeHJX*3)79{nc~QA_bG)1c8|rnc5ndzIpd&}xy!5~(ngaZIbqYsMB^MyaKkE*MiK zGc;6-L~E-hQcYV`RCr>kiL}O+sH8NhSn7G_ypQkG`}ofL@cZ3!&%K}S`JH=y`2lA! zYRY=b001>#A1~}4GXFJ7ihG;U{ugl%AY?4Y6EqDQECZla@9X7(OD2A(iLt^)+4 zvcPRC>h5+5D!;ck!c5jns;t}KwT3zOd`v9$!i5Mj0YQQq3e%uXEax;Qs6BLeSS$1n z-0gw31HuTNL9>c_PK=0qIy=oRt$?pj1RYWpSoruGbF_X+V&HF>&kc0yE(ixHb)Rsl z?Z|7ewDUhGvU|FoV2)gQscotvX$_AFS(&zC3zpln3N_)QVEd=z zzZ=w{hu8zF4>*P89%p-@wh-3bYIJtTTeVpTv$e)tJ-bk2=f=<=5RCb~Rbkry`o^xf zbvNjc8hbGXn=&bM&Iwo~CG2nG!J0msF?HBU>fwzkZE&-7@sv2IJNrpnv%CQFz0d!Ldg9V~wik zuh5VvyHEEO*eGfLnR?KREg97{lhc}0)k78Ea^~i_y6L54&mof zV3CR3SylIX_*2{xzEBU3Dp3fvnV(L!J5a{ti5gMW!t)-+r=LxT<^jrPLBmLS zKYFsRybjfEPxDCf*RD$q_3mrQMPU$u;nf^}8J{aU5)3-NTXXR%V)>4bsf&JdhiB@RxQd_>PtabxK%w4O zurlUk4nHta;4XNJ+0g;C#5vuOfevn}?O<^?%S+jSlWRv?~pGlHX6qd{2%9Zu|< z0(8^-&yP&LqJE_iiq!9>;biU(wr$#MK6&zziyz0#i=)SrH!of*-xnuTKNdzaPvIy; z>ensl_pz$2j6Uq&wxqf`X8UiJN0=2TT2fpY-oY8pR9BLh1KCKJA9_`@uk(xn1A{Dy zP0OR?=8rBiO)0LqQtU-)us&+Q1~qFUN2pzeCf=@j9@a z|8^9%qLZl2=bpgJU(Kp;w=AW_8L2ISq|;zq;UjlRYWH+Y{>4SLXxjN`IwiBYgls8utH{dTL+#Kr<%-j6cnIR54mF`+ACH6*RQ24Go z8NQhgsrpt~#0vyeQ8JqDs0^$_OM(IQ^jpkFpbGnU`JVvK+%LdEM@zc4I@>xR3<4}; z4WGlTRsS37OeA}YZcH1Vg~tNc->26b-FR_Egx(#|&@6nW#vibpG8C6o38GyFyM?7H z373QJ3aA>D_Qm@5wQv$`V0OqYQJ_yHP$|6^rDJl7J~j5iref&*V)aIBxBTGIG8K3v z_mO5^b?==43eYCt%~h#z7mUEQ4F0`GBt{9Sye}%=FWi?C(C6=iJ1CTzb0Exj*l+Ck zt=)1R>Pn*~)lgdme^Ef&p)lkY9GIl&dW|ikv<|v$e&Lfr3fwf60t7D*$fJ3~?~>eQ zX@6TB65CM5LqP`Uh}vv+afAFg--a64z~`|DYE*v;UUHY7?$NN)HenEhIC(X_^%hw$ z8xM=0Rok`Lgf}CO#IYW4uPuWW<_N{~ahYs^AQDTC1DEr%)hd1(X8H9!sN`7i>XZ@? iFK-