From 459df6ef4034ea01582594fcd389bd0f417bedd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bov=C3=A9?= Date: Tue, 4 Feb 2020 22:47:28 +0100 Subject: [PATCH 0001/1189] Added jbm8b --- apps/jbm8b/Changelog | 2 + apps/jbm8b/add_to_apps.json | 23 ++++++++++ apps/jbm8b/app-icon.js | 1 + apps/jbm8b/app.js | 85 ++++++++++++++++++++++++++++++++++++ apps/jbm8b/app.json | 6 +++ apps/jbm8b/app.png | Bin 0 -> 2635 bytes 6 files changed, 117 insertions(+) create mode 100644 apps/jbm8b/Changelog create mode 100644 apps/jbm8b/add_to_apps.json create mode 100644 apps/jbm8b/app-icon.js create mode 100644 apps/jbm8b/app.js create mode 100644 apps/jbm8b/app.json create mode 100644 apps/jbm8b/app.png diff --git a/apps/jbm8b/Changelog b/apps/jbm8b/Changelog new file mode 100644 index 000000000..bd71ffcd5 --- /dev/null +++ b/apps/jbm8b/Changelog @@ -0,0 +1,2 @@ +0.01: First working version +0.02: Added delay in replying for dramatic effect \ No newline at end of file diff --git a/apps/jbm8b/add_to_apps.json b/apps/jbm8b/add_to_apps.json new file mode 100644 index 000000000..ffa033f75 --- /dev/null +++ b/apps/jbm8b/add_to_apps.json @@ -0,0 +1,23 @@ +{ + "id": "jbm8b", + "name": "Magic 8 Ball", + "icon": "app.png", + "description": "A simple fortune telling app", + "tags": "game", + "storage": [ + { + "name": "+jbm8b", + "url": "app.json" + }, + { + "name": "-jbm8b", + "url": "app.js" + }, + { + "name": "*jbm8b", + "url": "app-icon.js", + "evaluate": true + } + ], + "version": "1.1.0" +} \ No newline at end of file diff --git a/apps/jbm8b/app-icon.js b/apps/jbm8b/app-icon.js new file mode 100644 index 000000000..b2da211af --- /dev/null +++ b/apps/jbm8b/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("slkgRC/AF1a1WpoAWSgO//4AB/1QDCNvC4QZCGaELC4gAB/BITAAmAGCoyQGBAABMpkHC5P/8AYLl4YK/pJWPxkDC5ZLLj4YM/gYJv4YM/4YJC5v/4BiVMhUPDBz8IYpbJMPZx9JC559HPZ4AB6AYFg4YQ+CUVSxEfDCCWGn4YQSwytH/2V34YHoCtMRYMBBQ+AC4YNHLAcvZBcCBg30gFZgELZBbfH8DPB8ALHZAjfH4C2B/hWHDAg+HwC2B/yIHKwL4KoCsCDA76EDBYDDAAf8DAZaBDCy7HwF/JRLTDgBzBSox8KBAIYK6CuCdg4YM+DQBAQQAGDBZwBtVARA4YMSQILBSgwYFRgSWGgEBBQ4YMUQa6HDBnwSQPQPhgYH4CuKPhlAfJQYMCgeAHw4YK/ySD4AlIDBP8gYEC6CWG/wYP8D6GDAgkGDBjTDgALGDBn8DAcPBYzDDMY4YLSpn4DAcLUI+/cgoAD+gYDg75HIwJzBBY3wDAZ0DAAfAEIPgJwYYIOgYMFig9I6AYDEo67DVow9BDAZXH/+QEZH/wAYERIwAB1SXCUIwAEXYwAK/wYFLA4AJfAj6IABT4EcJIAJYwjIJABLGEV5QAIVoqvKVpoABl4XO/oYHhYYO+gYHgYYO8AYHPp57HAAM/C5n+C5D7Oe4ziRMRIAB34YLoAYKj7FTWB5JLAAN/JKr8LexB+PGBoABg4wWAAMvSSIAGt4XC/xIPAAkV1WVCyYA/AH4A/AH4Ai")) \ No newline at end of file diff --git a/apps/jbm8b/app.js b/apps/jbm8b/app.js new file mode 100644 index 000000000..0fd5a177c --- /dev/null +++ b/apps/jbm8b/app.js @@ -0,0 +1,85 @@ +const affirmative = [ + 'It is\ncertain.', + 'It is\ndicededly\nso.', + 'Without\na doubt.', + 'Yes\ndefinitely.', + 'You may\nrely\non it.', + 'As I see,\nit yes.', + 'Most\nlikely.', + 'Outlook\ngood.', + 'Yes.', + 'Signs point\nto yes.' +]; +const nonCommittal = [ + 'Reply hazy,\ntry again.', + 'Ask again\nlater.', + 'Better not\ntell you\nnow.', + 'Cannot\npredict\nnow.', + 'Concentrate\nand\nask again.' +]; +const negative = [ + 'Don\'t\ncount on it.', + 'My reply\nis no.', + 'My sources\nsay no.', + 'Outlook\nis not\nso\ngood.', + 'Very\ndoubtful.' +]; + +const title = 'Magic 8 Ball'; + +const answers = [affirmative, nonCommittal, negative]; + +function getRandomArbitrary(min, max) { + return Math.random() * (max - min) + min; +} + +function predict() { + // affirmative, negative or non-committal + let max = answers.length; + const a = Math.floor(getRandomArbitrary(0, max)); + // sets max compared to answer category + max = answers[a].length; + const b = Math.floor(getRandomArbitrary(0, max)); + // get the answer + const response = answers[a][b]; + return response; +} + +function draw(msg) { + // console.log(msg); + g.clear(); + E.showMessage(msg, title); +} + +function reply(button) { + const theButton = (typeof button === 'undefined' || isNaN(button)) ? 1 : button; + const timer = Math.floor(getRandomArbitrary(0, theButton) * 1000); + // Thinking... + draw('...'); + setTimeout('draw(predict());', timer); +} + +function ask() { + draw('Ask me a\nYes or No\nquestion\nand\ntouch the\nscreen'); +} + +g.clear(); + +Bangle.loadWidgets(); + +// Event Handlers + +Bangle.on('touch', (button) => reply(button)); + +setWatch(ask, BTN1, {repeat:true, edge:"falling"}); +setWatch(reply, BTN3, {repeat:true, edge:"falling"}); + +// Back to launcher +setWatch(Bangle.showLauncher, BTN2, {repeat:false, edge:"falling"}); + +Bangle.on('lcdPower', (on) => { + if (on) { + Bangle.drawWidgets(); + ask(); + } +}); \ No newline at end of file diff --git a/apps/jbm8b/app.json b/apps/jbm8b/app.json new file mode 100644 index 000000000..a378c4916 --- /dev/null +++ b/apps/jbm8b/app.json @@ -0,0 +1,6 @@ +{ + "name": "Magic 8 Ball", + "icon": "*jbm8b", + "src": "-jbm8b", + "version": "1.1.0" +} \ No newline at end of file diff --git a/apps/jbm8b/app.png b/apps/jbm8b/app.png new file mode 100644 index 0000000000000000000000000000000000000000..78128d47e33ce69755e21a155ee77979fa35f776 GIT binary patch literal 2635 zcmc&#_ct4gAB|bD#SV>!P$RL5SS_j8YDCoDjXh)bSv4C)?M*$Slv+V3+LEf#KBGmg zs{QO)wbxhwitp!~`?=?H&;9X!&P^~f&|;tk(*ghh1|4k_`i39>0S(2?)>6Sb-w>HU zTI&IzZisjN=Ad*zK12clgcQ092Py!70$`+%(fDH`BO@m#r=Xyqq@<*xqN1jzzIE#s z4Gj$t2&AQ@rK6*xr>AFNU|?iqWMX1sW@ct#VF7_atgNhTY;5f8>>L~%oSd9oTwL7T z++Z-6hlhukmlpzo@bmKv2nYxY3PPb!At51QVc|P>?udwph>3}bi;KfxFgP48DJdx> zB_$&xbNB9DIXO9bd3gi^p`f6ksHmu0K743sXlP_)ghr!HOiVBsjH#*VqeqX-%*@Qq%`Ge}EG;dq ztgNi9t!->B>fm$$dKpPwHNhx7OM z4-5ub93|Z^78ZZ3knK~ zii(Phi%UvMN=r-2%F4>i%PT7@U%!4`RaI48UH#_Go0^)M+S=N>y1M%M`i6!E0)f!j z*x1z6)ZE-mBobR%T3TCM-@bj@*4EbE-u~|0yUxzeuC6W;iPYWQ{pr)Eo}QlG-rl~x zzW)CH&!0bk`SN98U|?`?aA;^~czF2h*RNw^W8c4jA0Ho|n3$NHoSd4Pnx3Bi@#DwL z%*^cU?A+Yk{QUgF!ouR>;?mO6^78V^%F62M>e|}c`uh6D#>VF6=GNBM_V)J9&d%=c z?%v+s{{H^2U%w6x4u1dseRz0ybaZrle0*|pa(a4tc6N4tetvOrad~-pb#--peSH(c z|JRs*Uism17h=eohsy<|H=Xd!Y>QK2gjN-W!MCX z4Y08X`{_ZW-p;lMXid$8l8ShmswjlS=F7aP&dT7aDw`=q{~?E};u95>4tkfB%a_3` zMaq_Z*SFP}|N1B9MBRt{scNcxMDK{)Cc@088fJ%)RRZ=frwK+pJ%PYZmxD8md%KM? z&J4ZsivJT5(6a_G-{Y^ZmVT^=4+x*5F54tvea*VqU`cp z^MyZ8eg9c$A4-Zt6zaxG4?o1M(?PxDxLJFONUrCO2ok;29#_+IOOJsr&Ef`ox}(mm z(bCMCrp)fUyn!Aw5 z;RN{#1ezkCKBTOdA;L?#=tz%!bzkrOSulm@L?*lu zBx}PL4DC|rAV@H9l0KMJr)6#nrqjldYmDv9V+)giU;I!wSfbSS*dbLsu@uEA+Xy!z z7ie4x2-;`ZG>VM^grWB}FI*sHz0+_&4a4c4&SBuSOd>7EaO(;ZOhXZ?WfL zk|3OUT>~#!kf>c^ zf{+wyLs=?MltI9*NUB@Mt5TN(^)j;%&Jmx$%4C#Oh;VO4+6HZ}7-N9tZ9j&0{)g@kO^G{8n*m0#JEFcR$_v;RyxfHV=U=`5nM;7O3WlvK-pg8~!k zL-RER20|539AX*}juyc#lj=Qp((PM?Yzb0A<~B_jFPvT@3#7(!n!sYN=uygZKQ%_+ z4Mu>N9!F^mM=NS_e)dkxk6@ZV8a**Cf4s*a!}6W?lLtL{dFIt9_bJgh7gAL@gWRb^0UC&>X34ixSt&WuYucX$RUE~7HOeXy*Mck zPOBPCN}R1LlwO-lpvRFT#5JGir9s(v8}b&+bR5MgMVm$YEq)Fma^727wjEawen@L! zBrubVP2tfFap%+*gnNqRS@CiB3U*N!3C?C`+C-4bvn|_iEQMKCXHm5>EoBJIr5G7&s#rwzu>H>AuAKBYf@f`oFyUe z>~AOPmCrayM*9^;%#a3?cp>JyTYKC_JGu$CZARS literal 0 HcmV?d00001 From 67b2b08e0967e7c2a0523a855c6cb64f73b5e182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bov=C3=A9?= Date: Tue, 4 Feb 2020 22:55:32 +0100 Subject: [PATCH 0002/1189] Added jbm8b to apps.json --- apps.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps.json b/apps.json index 76151a627..e02bc3d43 100644 --- a/apps.json +++ b/apps.json @@ -751,5 +751,31 @@ {"name":"*demoapp","url":"app-icon.js","evaluate":true} ], "sortorder" : -9 + }, + { + "id": "jbm8b", + "name": "Magic 8 Ball", + "icon": "app.png", + "description": "A simple fortune telling app", + "tags": "game", + "storage": [ + { + "name": "+jbm8b", + "url": "app.json" + }, + { + "name": "-jbm8b", + "url": "app.js" + }, + { + "name": "*jbm8b", + "url": "app-icon.js", + "evaluate": true + } + ], + "allow_emulator":true, + "type":"app", + "version": "0.01", + "sortorder" : -9 } ] From bfe298f615c819c19426a2d779434c7eb4c863fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bov=C3=A9?= Date: Tue, 4 Feb 2020 23:02:54 +0100 Subject: [PATCH 0003/1189] Updated jbm8b --- apps.json | 2 +- apps/jbm8b/add_to_apps.json | 2 +- apps/jbm8b/app.js | 15 +++++---------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/apps.json b/apps.json index e02bc3d43..a9c40569a 100644 --- a/apps.json +++ b/apps.json @@ -775,7 +775,7 @@ ], "allow_emulator":true, "type":"app", - "version": "0.01", + "version": "0.02", "sortorder" : -9 } ] diff --git a/apps/jbm8b/add_to_apps.json b/apps/jbm8b/add_to_apps.json index ffa033f75..200ea5f65 100644 --- a/apps/jbm8b/add_to_apps.json +++ b/apps/jbm8b/add_to_apps.json @@ -19,5 +19,5 @@ "evaluate": true } ], - "version": "1.1.0" + "version": "0.02" } \ No newline at end of file diff --git a/apps/jbm8b/app.js b/apps/jbm8b/app.js index 0fd5a177c..53baa32e3 100644 --- a/apps/jbm8b/app.js +++ b/apps/jbm8b/app.js @@ -66,20 +66,15 @@ function ask() { g.clear(); Bangle.loadWidgets(); +Bangle.drawWidgets(); +ask(); // Event Handlers Bangle.on('touch', (button) => reply(button)); -setWatch(ask, BTN1, {repeat:true, edge:"falling"}); -setWatch(reply, BTN3, {repeat:true, edge:"falling"}); +setWatch(ask, BTN1, { repeat: true, edge: "falling" }); +setWatch(reply, BTN3, { repeat: true, edge: "falling" }); // Back to launcher -setWatch(Bangle.showLauncher, BTN2, {repeat:false, edge:"falling"}); - -Bangle.on('lcdPower', (on) => { - if (on) { - Bangle.drawWidgets(); - ask(); - } -}); \ No newline at end of file +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); \ No newline at end of file From 0c3b38a4c2825f35348acc79912009f591b0b5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bov=C3=A9?= Date: Wed, 5 Feb 2020 21:17:31 +0100 Subject: [PATCH 0004/1189] Fixed app.png for jbm8b --- apps/jbm8b/app-icon.js | 2 +- apps/jbm8b/app.png | Bin 2635 -> 1548 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jbm8b/app-icon.js b/apps/jbm8b/app-icon.js index b2da211af..09bf032a6 100644 --- a/apps/jbm8b/app-icon.js +++ b/apps/jbm8b/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("slkgRC/AF1a1WpoAWSgO//4AB/1QDCNvC4QZCGaELC4gAB/BITAAmAGCoyQGBAABMpkHC5P/8AYLl4YK/pJWPxkDC5ZLLj4YM/gYJv4YM/4YJC5v/4BiVMhUPDBz8IYpbJMPZx9JC559HPZ4AB6AYFg4YQ+CUVSxEfDCCWGn4YQSwytH/2V34YHoCtMRYMBBQ+AC4YNHLAcvZBcCBg30gFZgELZBbfH8DPB8ALHZAjfH4C2B/hWHDAg+HwC2B/yIHKwL4KoCsCDA76EDBYDDAAf8DAZaBDCy7HwF/JRLTDgBzBSox8KBAIYK6CuCdg4YM+DQBAQQAGDBZwBtVARA4YMSQILBSgwYFRgSWGgEBBQ4YMUQa6HDBnwSQPQPhgYH4CuKPhlAfJQYMCgeAHw4YK/ySD4AlIDBP8gYEC6CWG/wYP8D6GDAgkGDBjTDgALGDBn8DAcPBYzDDMY4YLSpn4DAcLUI+/cgoAD+gYDg75HIwJzBBY3wDAZ0DAAfAEIPgJwYYIOgYMFig9I6AYDEo67DVow9BDAZXH/+QEZH/wAYERIwAB1SXCUIwAEXYwAK/wYFLA4AJfAj6IABT4EcJIAJYwjIJABLGEV5QAIVoqvKVpoABl4XO/oYHhYYO+gYHgYYO8AYHPp57HAAM/C5n+C5D7Oe4ziRMRIAB34YLoAYKj7FTWB5JLAAN/JKr8LexB+PGBoABg4wWAAMvSSIAGt4XC/xIPAAkV1WVCyYA/AH4A/AH4Ai")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwhBC/AGMrq2B1gAEwNWlYthq2s64AKGYIydFpoAEGLUrFqIADqxcXFqhiDFymBFy7GCF1owTRjCSVlYudeiGsF7/XlaNqSKBeP1mBwJxQMBReO1gaEleBMDBLN1hAC1hhBAoIwNCwQAGlZINqxvFGAIXOSBAXQN4hPBC5yQIVBxfBCAgvQSBC+NFAYRDMwJHOF654DqxkBYooALF6+sbIhkEF8Z3CRIWBR6AvXFAzvQF6wnIYQJgNd5AWNdoLoGBBAvPO5pfYH4IvUUwS/GVBzXBYCpHCq2s1mBDwKOWDwRgNPAwVVMCRLCwIABCZ6OJJSAATLxZgRACJeLAAMrFz9WFxiRgRpoADwIub1guQGDmsXhqSfRiL0G1jqkMRYxRwKLUGK2sFryVEq2B1gAEwNWFkIA/AH4A/AH4AQ")) \ No newline at end of file diff --git a/apps/jbm8b/app.png b/apps/jbm8b/app.png index 78128d47e33ce69755e21a155ee77979fa35f776..24c3013de011db9c1517ed544e9d383f5c60378c 100644 GIT binary patch delta 1166 zcmV;91abSz6pRcZiBL{Q4GJ0x0000DNk~Le0000m0000m2m=5B0ASn+wUHrVe-#xK z7Z(>87#JBD85$ZI8yg!P9UUJZA0i?mBO@auBqSvzB_<{&D=RB3EG#W8EiW%GGBPqV zGczQb8~ZabaZ%lczJnwfPjF3fq{mG zhKGlTi;IhljEs$qjgF3vkdTm(k&%*;l9ZH`m6es5nVFoNoSmJWo}QkcpP!?nqot*# zrlzK+r>Ci@sj8}~tE;Q5tgNlAt*@`Iu&}VPv9YtWv$eIgx3{;sxw*T$f4jWAyuH1> zzP`S{zrVo1z{0}9!^6YH#l^dCU$jHda$;ryf%FD~k&CSiw(9qG*(bCe=)6>({ z)z#M4*4WtC+1c6J+S=UQ+}+*X-rnBg;^O1uFMg~>g((4?Ck9A?d|UF z?(gsK@bK{Q@$vKX^Yrxe4E6Q(_V)Jo_xJet_>;K;jg#O4W|QCoNPp6yd3yi=010qN zS#tmY79;=w79;_i6~+_*00NasL_t(YOWl>(U(-Mog=d;3l+e-^(Mm;BP!!x3R8&B~ z9T2IYsHiCJyTw9LDzbw)`4u7o8t=)C{Z{zV}z=orTuDO~IA} zn{O?G!GzQtXE2E*2g_g)kh_*)u#g&F3sVkKhs|;f*lRy*Sx)55uaUZ8uA}w`hVqbX z68EZP6a#sg+W;$v9wZJxu-&i|vP)c1J-Men zXVl6CE*OMhC*%wi9d?Lb)ao5|Ze7w9@WR+9$`fXJ$-K0;FLmAl2{p z>^TrnPm2?*EPuEWphTenHeTF^Sz2q-cIjQYG?-oQ0xui|o}Ge~C8nr$J_0O$YZ_ z+Rjfnb(EarfKtf#_xT)3{YKG@Sm z>=V|M><&;#arm3X&o<|J6aN%M9rop6cjxVoVq1vUz|3hBrm$ro_Y);<(_veguYwiq z$m!X3Bu|=JGHounC^l$m$Wq93Hw7Z))}Aki@-|Brsj&LfbF}`1!Nl^AO@0kpH)dDJ zT#EvO6-$5njHwc~*jHtr9;`bS$^M7fuZi;oe~KK}#)DVGV!Z delta 2407 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 Z25u9%h&7af?>ztj002ovPDHLkV1l1vck=)M From b78c056b867ef205dd757c9d1ba7390cd1dd5039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bov=C3=A9?= Date: Fri, 7 Feb 2020 22:22:50 +0100 Subject: [PATCH 0005/1189] adds icon for jbb --- apps.json | 26 +++++++++++++++++++ apps/jbb/ChangeLog | 2 ++ apps/jbb/add_to_apps.json | 23 +++++++++++++++++ apps/jbb/app-icon.js | 1 + apps/jbb/app.js | 53 ++++++++++++++++++++++++++++++++++++++ apps/jbb/app.json | 5 ++++ apps/jbb/app.png | Bin 0 -> 1673 bytes 7 files changed, 110 insertions(+) create mode 100644 apps/jbb/ChangeLog create mode 100644 apps/jbb/add_to_apps.json create mode 100644 apps/jbb/app-icon.js create mode 100644 apps/jbb/app.js create mode 100644 apps/jbb/app.json create mode 100644 apps/jbb/app.png diff --git a/apps.json b/apps.json index a9c40569a..6ca702fe7 100644 --- a/apps.json +++ b/apps.json @@ -778,4 +778,30 @@ "version": "0.02", "sortorder" : -9 } + { + "id": "jbb", + "name": "Battery Level", + "icon": "app.png", + "description": "Battery status and charging indicator", + "tags": "tool", + "storage": [ + { + "name": "+jbb", + "url": "app.json" + }, + { + "name": "-jbb", + "url": "app.js" + }, + { + "name": "*jbb", + "url": "app-icon.js", + "evaluate": true + } + ], + "allow_emulator":true, + "type":"app", + "version": "0.02", + "sortorder" : -9 + } ] diff --git a/apps/jbb/ChangeLog b/apps/jbb/ChangeLog new file mode 100644 index 000000000..b7359ee0e --- /dev/null +++ b/apps/jbb/ChangeLog @@ -0,0 +1,2 @@ +0.01: First version trying out stuff +0.02: First usable version \ No newline at end of file diff --git a/apps/jbb/add_to_apps.json b/apps/jbb/add_to_apps.json new file mode 100644 index 000000000..cc6483ac1 --- /dev/null +++ b/apps/jbb/add_to_apps.json @@ -0,0 +1,23 @@ +{ + "id": "jbb", + "name": "Battery Power", + "icon": "app.png", + "description": "Showing battery level and charging status", + "tags": "tool", + "storage": [ + { + "name": "+jbb", + "url": "app.json" + }, + { + "name": "-jbb", + "url": "app.js" + }, + { + "name": "*jbb", + "url": "app-icon.js", + "evaluate": true + } + ], + "version": "0.02" +} \ No newline at end of file diff --git a/apps/jbb/app-icon.js b/apps/jbb/app-icon.js new file mode 100644 index 000000000..8fbebe9df --- /dev/null +++ b/apps/jbb/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4AvlYAVF7NVABdPAggublfVAAfU5gAKFzReCF4guL0RehFxZedF6Iu/F/hezF1AvB1YvOFzxevF54u/F6Qupqxe/FzovBLxougLxoOBACIvNwAuB6YvbXroANqqdQF4YuYLqBedDgNWdqYuZFp/+qwuC6i6nLzi6RF4nPF1peXFqgvCqouUXSheEABhrHRaovSFw9WFyo8O6vUXTb6SFodPF0xeCXTheVF1AvBwC6pLwjsBqoupF4SLqF2AvCFtYuvF4YurF4NWF1otsAH4AXA==")) \ No newline at end of file diff --git a/apps/jbb/app.js b/apps/jbb/app.js new file mode 100644 index 000000000..f39d06280 --- /dev/null +++ b/apps/jbb/app.js @@ -0,0 +1,53 @@ +/** + * draw the current level value + */ +function draw(level) { + console.log('draw', level); + // Clear the screen + g.clear(); + g.setFontAlign(0, 0); // center font + g.setFont("6x8", 8); // bitmap font, 8x magnified + g.drawString(level + "%", 120, 80); + g.setFont("6x8", 4); + g.drawString("power", 120, 130); +} + +function getBatteryLevel() { + level = E.getBattery(); + console.log('getBatteryLevel', level); + + draw(level); + + checkCharging(Bangle.isCharging()); + + // again, 10 secs later + setTimeout(getBatteryLevel, 10E3); +} + +function checkCharging(charging) { + console.log('checkCharging', charging); + // Green LED + //LED2.write(charging); + if (charging) { + g.setFontAlign(0, 0); // center font + g.setFont("6x8", 3); // bitmap font, 3x magnifier + g.drawString("charging", 120, 160); + } +} + +function main() { + console.log('starting jbb version 0.0.1'); + getBatteryLevel(); +} + +g.clear(); +g.flip(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +Bangle.on('charging', checkCharging); + +main(); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); diff --git a/apps/jbb/app.json b/apps/jbb/app.json new file mode 100644 index 000000000..9e4eb893c --- /dev/null +++ b/apps/jbb/app.json @@ -0,0 +1,5 @@ +{ + "name": "Battery Power", + "icon": "*jbb", + "src": "-jbb" +} \ No newline at end of file diff --git a/apps/jbb/app.png b/apps/jbb/app.png new file mode 100644 index 0000000000000000000000000000000000000000..6f58711b57c4be035b8368e4adbba1a5741e9532 GIT binary patch literal 1673 zcmV;426p+0P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1|CU7K~!i%)md9i z9Yq-a_j0b3mIMINK(MNr%4rG$tUw}>;CI)Rcch}=*!W8dih0DHfr39mRxN(i z7A>y9wG~tJrPFCgR`H~OZTIYIP1m~#2Z&JuZ%h@K-b={HWZFpJ( zME-$$?vPR*$jW<=CzK<0O8UQqO`?6ts`PlBQ`DHXxc z02Yg$=|OmGpb4^!I}RNiu025H4Ff{~`Q(F{)K{K7*@`a}84Noc2On}pp5RJ>j*bqF z^TF&`H~O&9`s!MjY?Z=X#IMsI<{^%j4;x`upp@Lfl>)TTrbb?sQXV$ZBYQxZmkk>@^W%e$h!pD9`hh; z6y|b6b`*lsG&1KC7-*0fh@l}WOPS^1$^-Ac^Q3H9;EI9#tPQ9HNKaWPjQi%nCUN&- zc^efe(AL%_n6w_hPslcu@1T!MuhM}q~S z{X!$CsD&S)W5clr48y=3H-oL*+oeTPo94m!wieQsVU#d6AoO&?d|Q{G!2*> z?Ey`-zRRz77kHxp^Jo(~$RLtKF;PO$98@ZcbyQR?(=)rz=0Y-E46~gbb|ja}TnBo9 z26?5oU6MD!$b7gbc`?5vzeS4}3pZNiG>Mtbind6>c~^cP$G8(0&O`GO=uV-xSK8gz z1ES{FvXK7zB|*$&nAb6FRt55$U?BaTk6PjKADZyUL8Zol9>}btg3_wmzttgctl$S7 zaX` zBl%7F#2dtM_!od3Q-##I77;!~d~9sYHF-jb0+hZQ9=r>g<8HWeO7?n(Hm|_RPmaP9 zZ#9TH{3heew%6W5Cg+emB&%wqCX)Lmt8 z>;i@iDoy#_@1kzsQo;#n!~1Te3jz$2`ue-F7s;=xz;K664a6{hyuCWv4`s8EQ`oOq z0=f=-Ek~YodA9#3q=wq6N}k|J0m7G`pT_d~4DJ~ypgIiGWMZfh{@SY9%{10Gs{_{x zko6TsgZkPHj6=Cg{~AQA<6`9@@t(h0hnReL^1w4s-w$x@MPYekQHA*VHq1IqSbcna zyz1l$t`;$EcFfcueeqs^8=peY>#gwfk}6J5)j0R=2Ui{-rMEXYu+7gP{#;y;r@os_ zo=~v@WPQ4S|J4uBaiSSFCk{0=HJ)G6x<$nyL<(4cLpwG*G~zZY@<3;2rzDTXnQ0t4 zc|t`B(0^tKl;3A(XAhk`q2e`AS66pa^1EYDNI1Fd*uT{-&&Awf!__`;>j2 Date: Fri, 7 Feb 2020 22:24:39 +0100 Subject: [PATCH 0006/1189] fixes apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6ca702fe7..c9c59d34b 100644 --- a/apps.json +++ b/apps.json @@ -777,7 +777,7 @@ "type":"app", "version": "0.02", "sortorder" : -9 - } + }, { "id": "jbb", "name": "Battery Level", From 911c0e454c0525b83a3d3888cb6311b4de0ff6e2 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 16 Feb 2020 09:42:39 +0100 Subject: [PATCH 0007/1189] Initial checkin --- apps/wohrm/ChangeLog | 1 + apps/wohrm/add_to_apps.json | 13 +++ apps/wohrm/app-icon.js | 1 + apps/wohrm/wohrm.js | 166 ++++++++++++++++++++++++++++++++++++ apps/wohrm/wohrm.json | 5 ++ apps/wohrm/wohrm.png | Bin 0 -> 1925 bytes 6 files changed, 186 insertions(+) create mode 100644 apps/wohrm/ChangeLog create mode 100644 apps/wohrm/add_to_apps.json create mode 100644 apps/wohrm/app-icon.js create mode 100644 apps/wohrm/wohrm.js create mode 100644 apps/wohrm/wohrm.json create mode 100644 apps/wohrm/wohrm.png diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog new file mode 100644 index 000000000..bc13085a4 --- /dev/null +++ b/apps/wohrm/ChangeLog @@ -0,0 +1 @@ +0.01: Only tested on the emulator. diff --git a/apps/wohrm/add_to_apps.json b/apps/wohrm/add_to_apps.json new file mode 100644 index 000000000..96ffe838c --- /dev/null +++ b/apps/wohrm/add_to_apps.json @@ -0,0 +1,13 @@ +// Create an entry in apps.json as follows: +{ "id": "wohrm", + "name": "Workout Heart Rate Monitor", + "icon": "wohrm.png", + "version":"0.01", + "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", + "tags": "hrm workout app", + "storage": [ + {"name":"+wohrm","url":"wohrm.json"}, + {"name":"-wohrm","url":"wohrm.js"}, + {"name":"*wohrm","url":"wohrm-icon.js","evaluate":true} + ] +} diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js new file mode 100644 index 000000000..36663d0ed --- /dev/null +++ b/apps/wohrm/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("MDCI/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsK7u8HC/v7+/v7+/v7+/v7+/v7Cwbu7wsL+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7u7u7u7u7vI/v7+/v7+/v7Iu7u7u7u7u7u7u8n+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/ru7u7u7u7u7u7u7u7u7u7v+/v7+u7u7u7u7u7u7u7u7u7u7u/7+/v7+/v7+/v7+u7u7u7u7u7u7u7u7u7u7u7u7/v67u7u7u7u7u7u7u7u7u7u7u7v+/v7+/v7+/v67u7u7u7u7u7u7wci7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7/v7+/v7+/sm7u7u7u7u7u7u7wsm7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7yf7+/v7+/ru7u7u7u7u7u7u7ydC7u7u7u7u7u7u7u7u7u7u7u8LQ19DCu7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u70NfCu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u/7+/v7+wru7u7u7u7u7u7vC19fJu7u7u7u7u7u7u7u7u7u7u9fX19fXu7u7u7u7u8L+/v7+wru7u7u7u7u7u7vJ19fJu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u8L+/v7+u7u7u7u7u7u7u7vQ19fQu7u7u7u7u7u7u7u7u7u7u8nX19DCu7u7u7u7u7v+/v7+wbu7u7u7ybu7u7vX19DXwru7u7u7u7u7u7u7wcnQ19fX0Lu7u7u7u7u7u8H+/v7+wru7u7vC18K7u8LX0MnXybu7u7vCu7u7wc/Q19fX19fX18K7u7u7u7u7u8L+/v7+yLu7u7vJ18m7u8nXycnXybu7u7vJu7u7wtfX19DJydfX19C7u7u7u7u7u8j+/v7+/ru7u8HR19HBu9DXwsLX0Lu7u7vQu7u7wdfX0Lu70NfJ0NfJu7u7u7u7u/7+/v7+/ru7u8nX19fJwtfQu7vQ18K7u8LXu7u7u8HQ18LC19fBwtfXycm7u7u7u/7+/v7+/tDX19fXydfQydfJu7vJ18m7u8nXu7u7u7vBwrvQ18m7u9DX19e7u7u7yf7+/v7+/v7Q19fQu9DX0NfIu7vJ18m7u9DXu7u7u7u7u8HX18K7u8HJycm7u7u7/v7+/v7+/v7+u7u7u8nX19fBu7vC19C7wtfQu7u7u7u7u8nX0Lu7u7u7u7u7u7v+/v7+/v7+/v7+wru7u8HR19C7u7u70NfCz9fJu7u7wru7u9fX18nCu7u7u7u7u8L+/v7+/v7+/v7+/sG7u7vJ18m7u7u7ydfJ0dfBu8HC19C7yNfX19fX0MK7u7u7wf7+/v7+/v7+/v7+/v67u7vC18K7u7u7ydfQ19C7u7vB0NfQ0NfJws/X18G7u7u7/v7+/v7+/v7+/v7+/v7+u7u70Lu7u7u7wtfX18m7u7u7wdDX19e7u8LX18K7u7v+/v7+/v7+/v7+/v7+/v7+/ru7wbu7u7u7u9DX18G7u7u7u8HJ18m7wdDX0Lu7u/7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u8nX0Lu7u7u7u7u7wcG70NfQu7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+wbu7u7u7u8nXyLu7u7u7u7u7u7vJ19fCu7v+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sG7u7u7u8LXwbu7u7u7u7u7u8HX18K7wf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7Cu7u7u7vJu7u7u7u7u7u7u7vCybvC/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7vBu7u7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sm7u7u7u7u7u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsL+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/g==")) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js new file mode 100644 index 000000000..d5f2c1c03 --- /dev/null +++ b/apps/wohrm/wohrm.js @@ -0,0 +1,166 @@ +upperLimit = 130; +lowerLimit = 100; +limitSetter = "lower"; +currentHeartRate = 220; +hrConfidence = 49; + +function drawTrainingHeartRate() { + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + + buzz(); +} + +function renderUpperLimit() { + g.setColor(255,0,0); + g.fillRect(140,40, 230, 70); + g.fillRect(200,70, 230, 210); + + if(limitSetter === "upper"){ + g.setColor(255,255, 255); + g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); + } + + g.setColor(255,255,255); + g.setFontVector(10); + g.drawString("Upper : " + upperLimit, 150,50); +} + +function renderCurrentHeartRate() { + g.setColor(0,255,0); + g.fillRect(55, 110, 175, 140); + g.setColor(0,0,0); + g.setFontVector(13); + g.drawString("Current: " + currentHeartRate, 75,117); +} + +function renderLowerLimit() { + g.setColor(0,0,255); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 40, 40, 180); + + if(limitSetter === "lower"){ + g.setColor(255,255, 255); + g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); + } + + g.setColor(255,255,255); + g.setFontVector(10); + g.drawString("Lower : " + lowerLimit, 20,190); +} + +function renderConfidenceBars(){ + if(hrConfidence >= 85){ + g.setColor(0, 255, 0); + } else if (hrConfidence >= 50) { + g.setColor(255, 255, 0); + } else if(hrConfidence >= 0){ + g.setColor(255, 0, 0); + } else { + g.setColor(0, 0, 0); + } + + g.fillRect(55, 110, 65, 140); + g.fillRect(175, 110, 185, 140); +} + +function buzz() +{ + if(currentHeartRate > upperLimit) + { + Bangle.buzz(70); + setTimeout(() => { Bangle.buzz(70); }, 70); + setTimeout(() => { Bangle.buzz(70); }, 70); + } + + if(currentHeartRate < upperLimit) + { + Bangle.buzz(140); + setTimeout(() => { Bangle.buzz(140); }, 140); + } +} + +function onHrm(hrm){ + currentHeartRate = hrm.bpm; + hrConfidence = hrm.confidence; +} + +function setLimitSetterToLower() { + limitSetter = "lower"; + console.log("Limit setter is lower"); + renderUpperLimit(); + renderLowerLimit(); +} + +function setLimitSetterToUpper() { + limitSetter = "upper"; + console.log("Limit setter is upper"); + renderLowerLimit(); + renderUpperLimit(); +} + +function incrementLimit(){ + if(limitSetter === "upper"){ + upperLimit++; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else { + lowerLimit++; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + +function decrementLimit(){ + if(limitSetter === "upper"){ + upperLimit--; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else { + lowerLimit--; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + +// Show launcher when middle button pressed +function switchOfWidget(){ + Bangle.setHRMPower(0); + Bangle.showLauncher(); +} + +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + // call your app function here + drawTrainingHeartRate(); + } +}); + +Bangle.setHRMPower(1); +Bangle.on('HRM', onHrm); + +// refesh every sec +setInterval(drawTrainingHeartRate, 1000); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawTrainingHeartRate(); + +setWatch(switchOfWidget, BTN2, {repeat:false,edge:"falling"}); + +setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); + +setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); + +setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); + +setWatch(setLimitSetterToUpper, BTN5, {edge:"rising", debounce:50, repeat:true}); \ No newline at end of file diff --git a/apps/wohrm/wohrm.json b/apps/wohrm/wohrm.json new file mode 100644 index 000000000..9b212bfd4 --- /dev/null +++ b/apps/wohrm/wohrm.json @@ -0,0 +1,5 @@ +{ + "name":"Workout HRM", + "icon":"*wohrm", + "src":"-wohrm" +} diff --git a/apps/wohrm/wohrm.png b/apps/wohrm/wohrm.png new file mode 100644 index 0000000000000000000000000000000000000000..8f9c0ea5dc9baa64f7b6586eaba4773699b33b72 GIT binary patch literal 1925 zcmeHH`8(7J82^rOrA9nbvWZeco1+|sax)m$xbKmp+!NzLmunR38dlU~SFI?Kt5gzE zVzr(X5y_FG=MIN6e<6r}(FAlZ?vs6y5G z0ZF2eX%kyoghEK5+FAhhfA3io4x(qw9nArtsc9lkQW8=ra->Vu%9awK!pR`;6N%I=mrJ3Lo^SV<_QIRL8rZ-5N|ld7Yg-- z!~NiJe>fr#jy{dVgdwqENL)A^9|0#sA_-A&Vib}TgCxZv$+1YvIpjPYxo{4-5RYC? zLQ|6w=0)VnWi%rN&A5POUPQA}k?b@ikBJmyp;yz;>~v0c1}7&I%}qyhh0NsSUP1Gi zoPumlVGgG#m-A~rT9S`mD?m#NIVCK#tcY{Hh;yTubF+k7ejUBd=2ZU1t^R{oUCFz9 zhgVa@t*zqJRrBgT6St)id(y&v`jFT5nAg#YwYT%S zo?~5|SobTe=M}H7hu7c7@B0%Ia(_QIG=RMu#72hr!^8N<2sZW}`!I@+PvDbN*z_bm zHH}Yw!l!5WGt>CYoM3hypZmg}pB2o15qw?{EG!DXF7ubZ3KmxcORIwAHU8QvzW$B> zeI4K2z+ni7VH`zp6veq*9OK~_hU2(EAQ0~Q|N2(~%Ch>B!aD&NR3|rKME~Ui+z^R_ z!g#jO$vz1HApPnG2)%LlLWQOR!`hqS78lM)3XTs0=)n=O46WEOhKin+j+TB{*3mEk z5Sg;GGIu9Cd@k|vk~5ddipd~T%rabURHZ~;XJ#DEK0LcO$z?cG@m!a@t3N$IJI%pe z=9-9@<(#qKCDu3dJcD62X`cRJ=g8Rjn?ZANYKrpou?>UU>BDgn+Z#204xK9w zlqdAI-g>kkebXl~n{Y;(`BcACt?G?Jk7hokL$kS4PVj#H-gTR7$O`Fgr)pJXnrgIC zjmdtVlA`)T(U4DCp4xejjZZEzn|jvsgP@DL1!d|Fx))qjthNGr4b1I( zb%Dsy$0Ck?-*ecC6wxL6l1+)!*4@d~Lv$ss(_lP9&QM>a&UY{$VJ3GU8th5KMBbK- zN@O-VXG>1Vb1F!;SfcljkR}U;v{Ch10-vr&%qx|2t!9r&Yo`QNqAwMS3lwR&isBtF zqcm%K7f(G>cbnTarAuLqIgg4f>8EY0u`u?pK7UAWdttpy`gqRuRBfmIY855a_U;3_ zS%F4vj(W1`&TlK%Jokj~lk1zKH0=ahg_#B_BOgq>&CG6$H;07Qp~~3muBbzDk*=6c z8vq4rS1Gj1nUerU?i$0Mx zgo8~Rtt;w8mdBnE`ygozIo9Ct)m5D`f3_IwX!Pu76Uw`~G#s37X?FJ7X|^`r7hc^= e@X?nbXb1>8u*t*8XN-v-AH>eu$*SIhmhlgSO4arN literal 0 HcmV?d00001 From e5624843605dfbf71d57d929031e3ff3ff2ea58e Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 16 Feb 2020 09:48:07 +0100 Subject: [PATCH 0008/1189] Adds Workout Heart Rate Monitor App --- apps.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0c47a9377..212ece336 100644 --- a/apps.json +++ b/apps.json @@ -809,6 +809,17 @@ {"name":"-flagrse","url":"app.js"}, {"name":"*flagrse","url":"app-icon.js","evaluate":true} ] + }, + { "id": "wohrm", + "name": "Workout Heart Rate Monitor", + "icon": "wohrm.png", + "version":"0.01", + "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", + "tags": "hrm workout app", + "storage": [ + {"name":"+wohrm","url":"wohrm.json"}, + {"name":"-wohrm","url":"wohrm.js"}, + {"name":"*wohrm","url":"wohrm-icon.js","evaluate":true} + ] } - ] From 18c69b9e677e22436e3263182b2c52884c54155f Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 16 Feb 2020 09:52:06 +0100 Subject: [PATCH 0009/1189] Fixes type and tags for wohrm --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 212ece336..cb98281fc 100644 --- a/apps.json +++ b/apps.json @@ -815,7 +815,8 @@ "icon": "wohrm.png", "version":"0.01", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "tags": "hrm workout app", + "tags": "hrm,workout,app", + "type": "app", "storage": [ {"name":"+wohrm","url":"wohrm.json"}, {"name":"-wohrm","url":"wohrm.js"}, From 7386330f599165378a1a0a9251f58e56c8ee9a64 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 16 Feb 2020 09:56:01 +0100 Subject: [PATCH 0010/1189] Allow running in the emulator for wohrm --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index cb98281fc..ca784bd37 100644 --- a/apps.json +++ b/apps.json @@ -815,8 +815,9 @@ "icon": "wohrm.png", "version":"0.01", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "tags": "hrm,workout,app", + "tags": "hrm,workout", "type": "app", + "allow_emulator":true, "storage": [ {"name":"+wohrm","url":"wohrm.json"}, {"name":"-wohrm","url":"wohrm.js"}, From f01133bf571abed7082679cf0f36d33be5b7bb2d Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Mon, 17 Feb 2020 21:54:12 +0100 Subject: [PATCH 0011/1189] Uses enum for limit setter values --- apps/wohrm/wohrm.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index d5f2c1c03..7d39f5e63 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -1,8 +1,13 @@ +const Setter = { + UPPER: 'upper', + LOWER: 'lower' +}; + upperLimit = 130; lowerLimit = 100; -limitSetter = "lower"; -currentHeartRate = 220; -hrConfidence = 49; +limitSetter = Setter.LOWER; +currentHeartRate = 0; +hrConfidence = -1; function drawTrainingHeartRate() { renderUpperLimit(); @@ -21,7 +26,7 @@ function renderUpperLimit() { g.fillRect(140,40, 230, 70); g.fillRect(200,70, 230, 210); - if(limitSetter === "upper"){ + if(limitSetter === Setter.UPPER){ g.setColor(255,255, 255); g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); } @@ -44,7 +49,7 @@ function renderLowerLimit() { g.fillRect(10, 180, 100, 210); g.fillRect(10, 40, 40, 180); - if(limitSetter === "lower"){ + if(limitSetter === Setter.LOWER){ g.setColor(255,255, 255); g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); } @@ -91,21 +96,21 @@ function onHrm(hrm){ } function setLimitSetterToLower() { - limitSetter = "lower"; + limitSetter = Setter.LOWER; console.log("Limit setter is lower"); renderUpperLimit(); renderLowerLimit(); } function setLimitSetterToUpper() { - limitSetter = "upper"; + limitSetter = Setter.UPPER; console.log("Limit setter is upper"); renderLowerLimit(); renderUpperLimit(); } function incrementLimit(){ - if(limitSetter === "upper"){ + if(limitSetter === Setter.UPPER){ upperLimit++; renderUpperLimit(); console.log("Upper limit: " + upperLimit); @@ -117,7 +122,7 @@ function incrementLimit(){ } function decrementLimit(){ - if(limitSetter === "upper"){ + if(limitSetter === Setter.UPPER){ upperLimit--; renderUpperLimit(); console.log("Upper limit: " + upperLimit); @@ -163,4 +168,4 @@ setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToUpper, BTN5, {edge:"rising", debounce:50, repeat:true}); \ No newline at end of file +setWatch(setLimitSetterToUpper, BTN5, {edge:"rising", debounce:50, repeat:true}); From d3711e6ae9067777a53fb404a6c41a2bce35bd79 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 18 Feb 2020 21:47:20 +0100 Subject: [PATCH 0012/1189] Icon renamed. --- apps/wohrm/{app-icon.js => wohrm-icon.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/wohrm/{app-icon.js => wohrm-icon.js} (100%) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/wohrm-icon.js similarity index 100% rename from apps/wohrm/app-icon.js rename to apps/wohrm/wohrm-icon.js From 173d9a2dae7885051ff044ec6399d8aaa96f85f5 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 1 Mar 2020 12:10:17 +0100 Subject: [PATCH 0013/1189] Adds rounded corners for upper limit button --- apps/wohrm/.gitignore | 4 ++++ apps/wohrm/wohrm.js | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 apps/wohrm/.gitignore diff --git a/apps/wohrm/.gitignore b/apps/wohrm/.gitignore new file mode 100644 index 000000000..2060ed3f3 --- /dev/null +++ b/apps/wohrm/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.eslintrc.js +/package.json +/package-lock.json \ No newline at end of file diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 7d39f5e63..c30c62eb6 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -1,13 +1,14 @@ +/* eslint-disable no-undef */ const Setter = { UPPER: 'upper', LOWER: 'lower' }; -upperLimit = 130; -lowerLimit = 100; -limitSetter = Setter.LOWER; -currentHeartRate = 0; -hrConfidence = -1; +let upperLimit = 130; +let lowerLimit = 100; +let limitSetter = Setter.LOWER; +let currentHeartRate = 0; +let hrConfidence = -1; function drawTrainingHeartRate() { renderUpperLimit(); @@ -26,6 +27,36 @@ function renderUpperLimit() { g.fillRect(140,40, 230, 70); g.fillRect(200,70, 230, 210); + //Round top left corner + g.setColor(0,0,0); + g.fillRect(140,40, 145, 45); + g.setColor(255,0,0); + g.fillCircle(150,50, 10); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(225,40, 230, 45); + g.setColor(255,0,0); + g.fillCircle(220,50, 10); + + //Round middle left corner + g.setColor(0,0,0); + g.fillRect(140,65, 145, 70); + g.setColor(255,0,0); + g.fillCircle(150,60, 10); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(200,205, 205, 210); + g.setColor(255,0,0); + g.fillCircle(210,200, 10); + + //Round bottom right corner + g.setColor(0,0,0); + g.fillRect(225,205, 230, 210); + g.setColor(255,0,0); + g.fillCircle(220,200, 10); + if(limitSetter === Setter.UPPER){ g.setColor(255,255, 255); g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); From 73dc1d0a7306e489d3a3186ea874240b00daf064 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 1 Mar 2020 21:14:35 +0100 Subject: [PATCH 0014/1189] UI fixes and code cleanup --- apps/wohrm/wohrm.js | 58 ++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index c30c62eb6..2d9553473 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -1,12 +1,16 @@ /* eslint-disable no-undef */ const Setter = { - UPPER: 'upper', - LOWER: 'lower' -}; + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' + }; + +const shortBuzzTimeInMs = 100; +const longBuzzTimeInMs = 200; let upperLimit = 130; let lowerLimit = 100; -let limitSetter = Setter.LOWER; +let limitSetter = Setter.NONE; let currentHeartRate = 0; let hrConfidence = -1; @@ -24,38 +28,28 @@ function drawTrainingHeartRate() { function renderUpperLimit() { g.setColor(255,0,0); - g.fillRect(140,40, 230, 70); - g.fillRect(200,70, 230, 210); + g.fillRect(145,40, 230, 70); + g.fillRect(200,70, 230, 200); - //Round top left corner - g.setColor(0,0,0); - g.fillRect(140,40, 145, 45); + //Round middle left corner g.setColor(255,0,0); - g.fillCircle(150,50, 10); + g.fillEllipse(135,40,155,70); //Round top right corner g.setColor(0,0,0); g.fillRect(225,40, 230, 45); g.setColor(255,0,0); - g.fillCircle(220,50, 10); + g.fillEllipse(210,40,230,50); - //Round middle left corner - g.setColor(0,0,0); - g.fillRect(140,65, 145, 70); + //Round inner corner g.setColor(255,0,0); - g.fillCircle(150,60, 10); - - //Round bottom left corner + g.fillRect(194,71, 199, 76); g.setColor(0,0,0); - g.fillRect(200,205, 205, 210); - g.setColor(255,0,0); - g.fillCircle(210,200, 10); + g.fillEllipse(180,71,199,82); - //Round bottom right corner - g.setColor(0,0,0); - g.fillRect(225,205, 230, 210); + //Round bottom g.setColor(255,0,0); - g.fillCircle(220,200, 10); + g.fillEllipse(200,190, 230, 210); if(limitSetter === Setter.UPPER){ g.setColor(255,255, 255); @@ -68,7 +62,7 @@ function renderUpperLimit() { } function renderCurrentHeartRate() { - g.setColor(0,255,0); + g.setColor(255,255,255); g.fillRect(55, 110, 175, 140); g.setColor(0,0,0); g.setFontVector(13); @@ -109,15 +103,15 @@ function buzz() { if(currentHeartRate > upperLimit) { - Bangle.buzz(70); - setTimeout(() => { Bangle.buzz(70); }, 70); - setTimeout(() => { Bangle.buzz(70); }, 70); + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); } if(currentHeartRate < upperLimit) { - Bangle.buzz(140); - setTimeout(() => { Bangle.buzz(140); }, 140); + Bangle.buzz(longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); } } @@ -165,7 +159,7 @@ function decrementLimit(){ } // Show launcher when middle button pressed -function switchOfWidget(){ +function switchOffApp(){ Bangle.setHRMPower(0); Bangle.showLauncher(); } @@ -191,7 +185,7 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); drawTrainingHeartRate(); -setWatch(switchOfWidget, BTN2, {repeat:false,edge:"falling"}); +setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); From 74dc9e5cbcd1ffa7d7e0435a208de8197ce68175 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sat, 7 Mar 2020 07:18:33 +0100 Subject: [PATCH 0015/1189] Rounds button corners and adds HW button icons --- apps/wohrm/wohrm.js | 86 +++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 2d9553473..199fe9261 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -15,6 +15,8 @@ let currentHeartRate = 0; let hrConfidence = -1; function drawTrainingHeartRate() { + renderButtonIcons(); + renderUpperLimit(); renderCurrentHeartRate(); @@ -28,56 +30,76 @@ function drawTrainingHeartRate() { function renderUpperLimit() { g.setColor(255,0,0); - g.fillRect(145,40, 230, 70); - g.fillRect(200,70, 230, 200); + g.fillRect(135,40, 220, 70); + g.fillRect(190,70, 220, 200); - //Round middle left corner + //Round top left corner g.setColor(255,0,0); - g.fillEllipse(135,40,155,70); + g.fillEllipse(125,40,145,70); //Round top right corner g.setColor(0,0,0); - g.fillRect(225,40, 230, 45); + g.fillRect(215,40, 220, 45); g.setColor(255,0,0); - g.fillEllipse(210,40,230,50); + g.fillEllipse(200,40,220,50); //Round inner corner g.setColor(255,0,0); - g.fillRect(194,71, 199, 76); + g.fillRect(184,71, 189, 76); g.setColor(0,0,0); - g.fillEllipse(180,71,199,82); + g.fillEllipse(170,71,189,82); //Round bottom g.setColor(255,0,0); - g.fillEllipse(200,190, 230, 210); + g.fillEllipse(190,190, 220, 210); - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 255); - g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); - } + // if(limitSetter === Setter.UPPER){ + // g.setColor(255,255, 255); + // g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], false); + // } g.setColor(255,255,255); g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 150,50); + g.drawString("Upper : " + upperLimit, 140,50); } function renderCurrentHeartRate() { g.setColor(255,255,255); - g.fillRect(55, 110, 175, 140); + g.fillRect(45, 110, 165, 140); g.setColor(0,0,0); g.setFontVector(13); - g.drawString("Current: " + currentHeartRate, 75,117); + g.drawString("Current: " + currentHeartRate, 65,117); } function renderLowerLimit() { g.setColor(0,0,255); g.fillRect(10, 180, 100, 210); - g.fillRect(10, 40, 40, 180); + g.fillRect(10, 50, 40, 180); - if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 255); - g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); - } + //Rounded top + g.setColor(0,0,255); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,255); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,255); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,255); + g.fillEllipse(10,200,30,210); + + // if(limitSetter === Setter.LOWER){ + // g.setColor(255,255, 255); + // g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); + // } g.setColor(255,255,255); g.setFontVector(10); @@ -95,8 +117,26 @@ function renderConfidenceBars(){ g.setColor(0, 0, 0); } - g.fillRect(55, 110, 65, 140); - g.fillRect(175, 110, 185, 140); + g.fillRect(45, 110, 55, 140); + g.fillRect(165, 110, 175, 140); +} + +function renderButtonIcons() { + g.setColor(255,255,255); + g.setFontVector(14); + + // + for Btn1 + g.drawString("+", 227,50); + + // Home for Btn2 + g.drawLine(225, 118, 232, 110); + g.drawLine(232, 110, 239, 118); + + g.drawPoly([227,117,227,125,237,125,237,117], false); + g.drawRect(231,120,234,125); + + // - for Btn3 + g.drawString("-", 227,190); } function buzz() From 3ea8201714ad166fc801bff36eedd0c4822e88a0 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sat, 7 Mar 2020 07:33:16 +0100 Subject: [PATCH 0016/1189] Changes button positioning --- apps/wohrm/wohrm.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 199fe9261..a32fded30 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -30,28 +30,28 @@ function drawTrainingHeartRate() { function renderUpperLimit() { g.setColor(255,0,0); - g.fillRect(135,40, 220, 70); - g.fillRect(190,70, 220, 200); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); //Round top left corner g.setColor(255,0,0); - g.fillEllipse(125,40,145,70); + g.fillEllipse(115,40,135,70); //Round top right corner g.setColor(0,0,0); - g.fillRect(215,40, 220, 45); + g.fillRect(205,40, 210, 45); g.setColor(255,0,0); - g.fillEllipse(200,40,220,50); + g.fillEllipse(190,40,210,50); //Round inner corner g.setColor(255,0,0); - g.fillRect(184,71, 189, 76); + g.fillRect(174,71, 179, 76); g.setColor(0,0,0); - g.fillEllipse(170,71,189,82); + g.fillEllipse(160,71,179,82); //Round bottom g.setColor(255,0,0); - g.fillEllipse(190,190, 220, 210); + g.fillEllipse(180,190, 210, 210); // if(limitSetter === Setter.UPPER){ // g.setColor(255,255, 255); @@ -60,7 +60,7 @@ function renderUpperLimit() { g.setColor(255,255,255); g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 140,50); + g.drawString("Upper : " + upperLimit, 130,50); } function renderCurrentHeartRate() { @@ -114,7 +114,7 @@ function renderConfidenceBars(){ } else if(hrConfidence >= 0){ g.setColor(255, 0, 0); } else { - g.setColor(0, 0, 0); + g.setColor(255, 255, 0); } g.fillRect(45, 110, 55, 140); @@ -126,17 +126,17 @@ function renderButtonIcons() { g.setFontVector(14); // + for Btn1 - g.drawString("+", 227,50); + g.drawString("+", 222,50); // Home for Btn2 - g.drawLine(225, 118, 232, 110); - g.drawLine(232, 110, 239, 118); + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); - g.drawPoly([227,117,227,125,237,125,237,117], false); - g.drawRect(231,120,234,125); + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); // - for Btn3 - g.drawString("-", 227,190); + g.drawString("-", 222,165); } function buzz() From 79e70fc023d5c9f49711eed486640178f7e3c92e Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sat, 7 Mar 2020 07:35:20 +0100 Subject: [PATCH 0017/1189] Fixes initial color for confidence bars --- apps/wohrm/wohrm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index a32fded30..306824c79 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -114,7 +114,7 @@ function renderConfidenceBars(){ } else if(hrConfidence >= 0){ g.setColor(255, 0, 0); } else { - g.setColor(255, 255, 0); + g.setColor(255, 255, 255); } g.fillRect(45, 110, 55, 140); From f740b4f57751343500ec85fd61e5fc951d3e7e75 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 8 Mar 2020 09:32:20 +0100 Subject: [PATCH 0018/1189] Improves UX for highlighting the selected limit --- apps/wohrm/wohrm.js | 341 ++++++++++++++++++++++++-------------------- 1 file changed, 183 insertions(+), 158 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 306824c79..e4d31cb27 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -3,8 +3,8 @@ const Setter = { NONE: "none", UPPER: 'upper', LOWER: 'lower' - }; - +}; + const shortBuzzTimeInMs = 100; const longBuzzTimeInMs = 200; @@ -14,223 +14,248 @@ let limitSetter = Setter.NONE; let currentHeartRate = 0; let hrConfidence = -1; +let setterHighlightTimeout; + function drawTrainingHeartRate() { - renderButtonIcons(); - - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - - buzz(); + renderButtonIcons(); + + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + + buzz(); } function renderUpperLimit() { - g.setColor(255,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); + g.setColor(255,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); - //Round top left corner - g.setColor(255,0,0); - g.fillEllipse(115,40,135,70); + //Round top left corner + g.fillEllipse(115,40,135,70); - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(255,0,0); - g.fillEllipse(190,40,210,50); + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(255,0,0); + g.fillEllipse(190,40,210,50); - //Round inner corner - g.setColor(255,0,0); - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); - //Round bottom - g.setColor(255,0,0); - g.fillEllipse(180,190, 210, 210); - - // if(limitSetter === Setter.UPPER){ - // g.setColor(255,255, 255); - // g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], false); - // } + //Round bottom + g.setColor(255,0,0); + g.fillEllipse(180,190, 210, 210); + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { g.setColor(255,255,255); - g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); + } + g.setFontVector(10); + g.drawString("Upper : " + upperLimit, 130,50); } - -function renderCurrentHeartRate() { - g.setColor(255,255,255); - g.fillRect(45, 110, 165, 140); - g.setColor(0,0,0); - g.setFontVector(13); - g.drawString("Current: " + currentHeartRate, 65,117); -} - -function renderLowerLimit() { - g.setColor(0,0,255); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,255); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,255); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,255); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,255); - g.fillEllipse(10,200,30,210); +function renderCurrentHeartRate() { + g.setColor(255,255,255); + g.fillRect(45, 110, 165, 140); + g.setColor(0,0,0); + g.setFontVector(13); - // if(limitSetter === Setter.LOWER){ - // g.setColor(255,255, 255); - // g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); - // } + g.drawString("Current:" , 65,117); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 155, 117); + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); +} + +function renderLowerLimit() { + g.setColor(0,0,255); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,255); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,255); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,255); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,255); + g.fillEllipse(10,200,30,210); + + if(limitSetter === Setter.LOWER){ + g.setColor(255,255, 0); + } else { g.setColor(255,255,255); - g.setFontVector(10); - g.drawString("Lower : " + lowerLimit, 20,190); + } + g.setFontVector(10); + g.drawString("Lower : " + lowerLimit, 20,190); } - + function renderConfidenceBars(){ - if(hrConfidence >= 85){ - g.setColor(0, 255, 0); - } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); - } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); - } else { - g.setColor(255, 255, 255); - } + if(hrConfidence >= 85){ + g.setColor(0, 255, 0); + } else if (hrConfidence >= 50) { + g.setColor(255, 255, 0); + } else if(hrConfidence >= 0){ + g.setColor(255, 0, 0); + } else { + g.setColor(255, 255, 255); + } - g.fillRect(45, 110, 55, 140); - g.fillRect(165, 110, 175, 140); + g.fillRect(45, 110, 55, 140); + g.fillRect(165, 110, 175, 140); } - + function renderButtonIcons() { g.setColor(255,255,255); g.setFontVector(14); - + // + for Btn1 g.drawString("+", 222,50); - + // Home for Btn2 g.drawLine(220, 118, 227, 110); g.drawLine(227, 110, 234, 118); - + g.drawPoly([222,117,222,125,232,125,232,117], false); g.drawRect(226,120,229,125); - + // - for Btn3 g.drawString("-", 222,165); } - + function buzz() { - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - } + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + } - if(currentHeartRate < upperLimit) - { - Bangle.buzz(longBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); - } + if(currentHeartRate < upperLimit) + { + Bangle.buzz(longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); + } } - + function onHrm(hrm){ - currentHeartRate = hrm.bpm; - hrConfidence = hrm.confidence; + currentHeartRate = hrm.bpm; + hrConfidence = hrm.confidence; } - + function setLimitSetterToLower() { - limitSetter = Setter.LOWER; - console.log("Limit setter is lower"); - renderUpperLimit(); - renderLowerLimit(); -} + resetHighlightTimeout(); + limitSetter = Setter.LOWER; + console.log("Limit setter is lower"); + renderUpperLimit(); + renderLowerLimit(); +} + function setLimitSetterToUpper() { - limitSetter = Setter.UPPER; - console.log("Limit setter is upper"); - renderLowerLimit(); - renderUpperLimit(); -} + resetHighlightTimeout(); + limitSetter = Setter.UPPER; + console.log("Limit setter is upper"); + renderLowerLimit(); + renderUpperLimit(); +} + +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + console.log("Limit setter is none"); + renderLowerLimit(); + renderUpperLimit(); +} + function incrementLimit(){ - if(limitSetter === Setter.UPPER){ - upperLimit++; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - } else { - lowerLimit++; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - } -} + resetHighlightTimeout(); + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + function decrementLimit(){ - if(limitSetter === Setter.UPPER){ - upperLimit--; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - } else { - lowerLimit--; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - } -} + resetHighlightTimeout(); + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + +function resetHighlightTimeout() { + if(setterHiglightTimeout !== undefined) + clearTimeout(setterHighlightTimeout); + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 5000); +} + // Show launcher when middle button pressed function switchOffApp(){ - Bangle.setHRMPower(0); - Bangle.showLauncher(); + Bangle.setHRMPower(0); + Bangle.showLauncher(); } - + // special function to handle display switch on Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - // call your app function here - drawTrainingHeartRate(); - } + g.clear(); + if (on) { + Bangle.drawWidgets(); + // call your app function here + drawTrainingHeartRate(); + } }); - + Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); - + // refesh every sec setInterval(drawTrainingHeartRate, 1000); - + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); drawTrainingHeartRate(); - + setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); - + setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); - + setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); - + setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); - -setWatch(setLimitSetterToUpper, BTN5, {edge:"rising", debounce:50, repeat:true}); + +setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); From 054a0c2142c64409787625221b1ef6693df311f3 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 8 Mar 2020 09:36:19 +0100 Subject: [PATCH 0019/1189] Fixes resetHighlightTimeout method --- apps/wohrm/wohrm.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index e4d31cb27..f37483910 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -218,9 +218,11 @@ function decrementLimit(){ } function resetHighlightTimeout() { - if(setterHiglightTimeout !== undefined) + if (setterHighlightTimeout) { clearTimeout(setterHighlightTimeout); - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 5000); + } + + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); } // Show launcher when middle button pressed From cf64c1c2c088c29ca2f80126dbde6d87ed5d5a95 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 24 Mar 2020 17:27:13 +0100 Subject: [PATCH 0020/1189] Adapt to new code layout --- apps.json | 8 ++++---- apps/wohrm/ChangeLog | 1 + apps/wohrm/{wohrm-icon.js => app-icon.js} | 0 apps/wohrm/{wohrm.js => app.js} | 0 apps/wohrm/{wohrm.png => app.png} | Bin 5 files changed, 5 insertions(+), 4 deletions(-) rename apps/wohrm/{wohrm-icon.js => app-icon.js} (100%) rename apps/wohrm/{wohrm.js => app.js} (100%) rename apps/wohrm/{wohrm.png => app.png} (100%) diff --git a/apps.json b/apps.json index 3ffdbe5d4..bbc40a7fd 100644 --- a/apps.json +++ b/apps.json @@ -815,15 +815,15 @@ }, { "id": "wohrm", "name": "Workout Heart Rate Monitor", - "icon": "wohrm.png", - "version":"0.01", + "icon": "app.png", + "version":"0.02", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", "allow_emulator":true, "storage": [ - {"name":"wohrm.app.js","url":"wohrm.js"}, - {"name":"wohrm.img","url":"wohrm-icon.js","evaluate":true} + {"name":"wohrm.app.js","url":"app.js"}, + {"name":"wohrm.img","url":"app-icon.js","evaluate":true} ] }, { "id": "widid", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index bc13085a4..101ac1146 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -1 +1,2 @@ +0.02: Adapted to new App code layout 0.01: Only tested on the emulator. diff --git a/apps/wohrm/wohrm-icon.js b/apps/wohrm/app-icon.js similarity index 100% rename from apps/wohrm/wohrm-icon.js rename to apps/wohrm/app-icon.js diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/app.js similarity index 100% rename from apps/wohrm/wohrm.js rename to apps/wohrm/app.js diff --git a/apps/wohrm/wohrm.png b/apps/wohrm/app.png similarity index 100% rename from apps/wohrm/wohrm.png rename to apps/wohrm/app.png From 83ffb617f26b3857d40fa8481a2b020b06b8888a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 24 Mar 2020 17:34:27 +0100 Subject: [PATCH 0021/1189] Energy saving --- apps/wohrm/app.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f37483910..f6e9baba4 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -17,16 +17,19 @@ let hrConfidence = -1; let setterHighlightTimeout; function drawTrainingHeartRate() { - renderButtonIcons(); - - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderButtonIcons(); + + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + buzz(); } From 08cc44ce9671fd1b7afcf29fbf237a47d6bb6448 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:14:48 +0100 Subject: [PATCH 0022/1189] Render the background only once --- apps/wohrm/add_to_apps.json | 13 ---- apps/wohrm/app.js | 122 +++++++++++++++++++----------------- apps/wohrm/wohrm.json | 5 -- 3 files changed, 66 insertions(+), 74 deletions(-) delete mode 100644 apps/wohrm/add_to_apps.json delete mode 100644 apps/wohrm/wohrm.json diff --git a/apps/wohrm/add_to_apps.json b/apps/wohrm/add_to_apps.json deleted file mode 100644 index 96ffe838c..000000000 --- a/apps/wohrm/add_to_apps.json +++ /dev/null @@ -1,13 +0,0 @@ -// Create an entry in apps.json as follows: -{ "id": "wohrm", - "name": "Workout Heart Rate Monitor", - "icon": "wohrm.png", - "version":"0.01", - "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "tags": "hrm workout app", - "storage": [ - {"name":"+wohrm","url":"wohrm.json"}, - {"name":"-wohrm","url":"wohrm.js"}, - {"name":"*wohrm","url":"wohrm-icon.js","evaluate":true} - ] -} diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f6e9baba4..c80434ae7 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -16,24 +16,7 @@ let hrConfidence = -1; let setterHighlightTimeout; -function drawTrainingHeartRate() { - //Only redraw if the display is on - if (Bangle.isLCDOn()) { - renderButtonIcons(); - - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - } - - buzz(); -} - -function renderUpperLimit() { +function renderUpperLimitBackground() { g.setColor(255,0,0); g.fillRect(125,40, 210, 70); g.fillRect(180,70, 210, 200); @@ -55,31 +38,16 @@ function renderUpperLimit() { //Round bottom g.setColor(255,0,0); g.fillEllipse(180,190, 210, 210); - - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); } - -function renderCurrentHeartRate() { + +function renderCurrentHearRateBackground() { g.setColor(255,255,255); g.fillRect(45, 110, 165, 140); g.setColor(0,0,0); g.setFontVector(13); - - g.drawString("Current:" , 65,117); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 155, 117); - - //Reset alignment to defaults - g.setFontAlign(-1, -1, 0); } - -function renderLowerLimit() { + +function renderLowerLimitBackground() { g.setColor(0,0,255); g.fillRect(10, 180, 100, 210); g.fillRect(10, 50, 40, 180); @@ -103,7 +71,63 @@ function renderLowerLimit() { g.fillRect(10,205, 15, 210); g.setColor(0,0,255); g.fillEllipse(10,200,30,210); +} +function renderButtonIcons() { + g.setColor(255,255,255); + g.setFontVector(14); + + // + for Btn1 + g.drawString("+", 222,50); + + // Home for Btn2 + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); + + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); + + // - for Btn3 + g.drawString("-", 222,165); +} + +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderButtonIcons(); + + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + + buzz(); +} + +function renderUpperLimit() { + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(10); + g.drawString("Upper : " + upperLimit, 130,50); +} + +function renderCurrentHeartRate() { + g.drawString("Current:" , 65,117); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 155, 117); + + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); +} + +function renderLowerLimit() { if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); } else { @@ -128,24 +152,6 @@ function renderConfidenceBars(){ g.fillRect(165, 110, 175, 140); } -function renderButtonIcons() { - g.setColor(255,255,255); - g.setFontVector(14); - - // + for Btn1 - g.drawString("+", 222,50); - - // Home for Btn2 - g.drawLine(220, 118, 227, 110); - g.drawLine(227, 110, 234, 118); - - g.drawPoly([222,117,222,125,232,125,232,117], false); - g.drawRect(226,120,229,125); - - // - for Btn3 - g.drawString("-", 222,165); -} - function buzz() { if(currentHeartRate > upperLimit) @@ -253,7 +259,11 @@ setInterval(drawTrainingHeartRate, 1000); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -drawTrainingHeartRate(); + +renderLowerLimitBackground()); +renderCurrentHearRateBackground(); +renderUpperLimitBackground(); +renderButtonIcons(); setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); diff --git a/apps/wohrm/wohrm.json b/apps/wohrm/wohrm.json deleted file mode 100644 index 9b212bfd4..000000000 --- a/apps/wohrm/wohrm.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name":"Workout HRM", - "icon":"*wohrm", - "src":"-wohrm" -} From 1d3248882cd97deb1194febb830514e7f5e3902a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:16:37 +0100 Subject: [PATCH 0023/1189] Changelog updated --- apps/wohrm/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 101ac1146..36c08b9fd 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -1,2 +1,3 @@ +0.03: Optimized rendering for the background 0.02: Adapted to new App code layout 0.01: Only tested on the emulator. From 1d339c825c443e7c0c15f28e0a82ad9c79adf5c2 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:36:45 +0100 Subject: [PATCH 0024/1189] Typo --- apps/wohrm/app.js | 52 +++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index c80434ae7..30f872066 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -17,7 +17,7 @@ let hrConfidence = -1; let setterHighlightTimeout; function renderUpperLimitBackground() { - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillRect(125,40, 210, 70); g.fillRect(180,70, 210, 200); @@ -27,7 +27,7 @@ function renderUpperLimitBackground() { //Round top right corner g.setColor(0,0,0); g.fillRect(205,40, 210, 45); - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillEllipse(190,40,210,50); //Round inner corner @@ -36,32 +36,33 @@ function renderUpperLimitBackground() { g.fillEllipse(160,71,179,82); //Round bottom - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillEllipse(180,190, 210, 210); } function renderCurrentHearRateBackground() { - g.setColor(255,255,255); + g.setColor(1,1,1); g.fillRect(45, 110, 165, 140); g.setColor(0,0,0); g.setFontVector(13); + g.drawString("Current:" , 65,117); } function renderLowerLimitBackground() { - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillRect(10, 180, 100, 210); g.fillRect(10, 50, 40, 180); //Rounded top - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillEllipse(10,40, 40, 60); //Round bottom right corner - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillEllipse(90,180,110,210); //Round inner corner - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillRect(40,175,45,180); g.setColor(0,0,0); g.fillEllipse(41,170,60,179); @@ -69,12 +70,12 @@ function renderLowerLimitBackground() { //Round bottom left corner g.setColor(0,0,0); g.fillRect(10,205, 15, 210); - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillEllipse(10,200,30,210); } function renderButtonIcons() { - g.setColor(255,255,255); + g.setColor(1,1,1); g.setFontVector(14); // + for Btn1 @@ -88,14 +89,12 @@ function renderButtonIcons() { g.drawRect(226,120,229,125); // - for Btn3 - g.drawString("-", 222,165); + g.drawString("-", 222,170); } function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { - renderButtonIcons(); - renderUpperLimit(); renderCurrentHeartRate(); @@ -110,16 +109,17 @@ function drawTrainingHeartRate() { function renderUpperLimit() { if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); + g.setColor(1, 1, 0); } else { - g.setColor(255,255,255); + g.setColor(1, 1, 1); } + g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); + g.drawString("Upper : " + upperLimit, 130,50); } function renderCurrentHeartRate() { - g.drawString("Current:" , 65,117); + g.setFontVector(13); g.setFontAlign(1, -1, 0); g.drawString(currentHeartRate, 155, 117); @@ -246,21 +246,19 @@ Bangle.on('lcdPower', (on) => { if (on) { Bangle.drawWidgets(); // call your app function here + renderLowerLimitBackground(); + renderCurrentHearRateBackground(); + renderUpperLimitBackground(); + renderButtonIcons(); drawTrainingHeartRate(); } }); -Bangle.setHRMPower(1); -Bangle.on('HRM', onHrm); - -// refesh every sec -setInterval(drawTrainingHeartRate, 1000); - g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLowerLimitBackground()); +renderLowerLimitBackground(); renderCurrentHearRateBackground(); renderUpperLimitBackground(); renderButtonIcons(); @@ -274,3 +272,9 @@ setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); + +Bangle.setHRMPower(1); +Bangle.on('HRM', onHrm); + +// refesh every sec +setInterval(drawTrainingHeartRate, 1000); \ No newline at end of file From 8427b492ee05c2aae14f906f88cd3861bbde3958 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:39:42 +0100 Subject: [PATCH 0025/1189] Wohrm version updated --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bbc40a7fd..28403787f 100644 --- a/apps.json +++ b/apps.json @@ -829,7 +829,7 @@ { "id": "widid", "name": "Bluetooth ID Widget", "icon": "widget.png", - "version":"0.02", + "version":"0.03", "description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!", "tags": "widget,address,mac", "type":"widget", From 84f56faadfd8acdbb49acb5d2085d573447db4c6 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:42:43 +0100 Subject: [PATCH 0026/1189] Fixed version for widid after errneous edit --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 28403787f..ba72123c9 100644 --- a/apps.json +++ b/apps.json @@ -816,7 +816,7 @@ { "id": "wohrm", "name": "Workout Heart Rate Monitor", "icon": "app.png", - "version":"0.02", + "version":"0.03", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", @@ -829,7 +829,7 @@ { "id": "widid", "name": "Bluetooth ID Widget", "icon": "widget.png", - "version":"0.03", + "version":"0.02", "description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!", "tags": "widget,address,mac", "type":"widget", From 784dcf97516192ba849107f6cc5b228402f807b7 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Thu, 26 Mar 2020 13:39:49 +0000 Subject: [PATCH 0027/1189] fix autoFilter behavior --- index.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 8042967d8..dbba7b95e 100644 --- a/index.js +++ b/index.js @@ -251,15 +251,17 @@ function showTab(tabname) { // =========================================== Library -var activeFilter = window.location.hash ? window.location.hash.slice(1) : ''; +var chips = Array.from(document.querySelectorAll('.chip')).map(chip => chip.attributes.filterid.value) +var hash = window.location.hash ? window.location.hash.slice(1) : ''; + +var activeFilter = !!~chips.indexOf(hash) ? hash : ''//window.location.hash ? window.location.hash.slice(1) : ''; var currentSearch = ''; function refreshFilter(){ var filtersContainer = document.querySelector("#librarycontainer .filter-nav"); - if(activeFilter){ - filtersContainer.querySelector('.active').classList.remove('active'); - filtersContainer.querySelector('.chip[filterid="'+activeFilter+'"]').classList.add('active') - } + filtersContainer.querySelector('.active').classList.remove('active'); + if(activeFilter) filtersContainer.querySelector('.chip[filterid="'+activeFilter+'"]').classList.add('active') + else filtersContainer.querySelector('.chip[filterid]').classList.add('active') } function refreshLibrary() { var panelbody = document.querySelector("#librarycontainer .panel-body"); @@ -515,10 +517,10 @@ Comms.watchConnectionChange(handleConnectionChange); var filtersContainer = document.querySelector("#librarycontainer .filter-nav"); filtersContainer.addEventListener('click', ({ target }) => { - if (!target.hasAttribute('filterid')) return; + //if (!target.hasAttribute('filterid')) return; if (target.classList.contains('active')) return; - activeFilter = target.getAttribute('filterid'); + activeFilter = target.getAttribute('filterid') || ''; refreshFilter(); refreshLibrary(); window.location.hash = activeFilter From 90c50f1282a265f0b039345795654ad06e5aab85 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Thu, 26 Mar 2020 13:44:19 +0000 Subject: [PATCH 0028/1189] remove comment --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index dbba7b95e..d08d98cba 100644 --- a/index.js +++ b/index.js @@ -254,7 +254,7 @@ function showTab(tabname) { var chips = Array.from(document.querySelectorAll('.chip')).map(chip => chip.attributes.filterid.value) var hash = window.location.hash ? window.location.hash.slice(1) : ''; -var activeFilter = !!~chips.indexOf(hash) ? hash : ''//window.location.hash ? window.location.hash.slice(1) : ''; +var activeFilter = !!~chips.indexOf(hash) ? hash : ''; var currentSearch = ''; function refreshFilter(){ @@ -517,7 +517,6 @@ Comms.watchConnectionChange(handleConnectionChange); var filtersContainer = document.querySelector("#librarycontainer .filter-nav"); filtersContainer.addEventListener('click', ({ target }) => { - //if (!target.hasAttribute('filterid')) return; if (target.classList.contains('active')) return; activeFilter = target.getAttribute('filterid') || ''; From 595fc18ea65e0b8c4d4084b3b22040a823ade781 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Thu, 26 Mar 2020 17:03:53 +0000 Subject: [PATCH 0029/1189] Groceries app --- apps.json | 14 +++ apps/groceries/groceries.html | 158 ++++++++++++++++++++++++++++++++++ apps/groceries/groceries.png | Bin 0 -> 1800 bytes 3 files changed, 172 insertions(+) create mode 100644 apps/groceries/groceries.html create mode 100644 apps/groceries/groceries.png diff --git a/apps.json b/apps.json index cb0a1bf79..3e3c89bba 100644 --- a/apps.json +++ b/apps.json @@ -823,5 +823,19 @@ "storage": [ {"name":"widid.wid.js","url":"widget.js"} ] + }, + { + "id": "groceries", + "name": "Groceries", + "icon": "groceries.png", + "version":"0.01", + "description": "Simple grocery list - Display a list of product and track if you already put them in your cart.", + "tags": "tool,outdoors", + "type": "app", + "custom":"groceries.html", + "storage": [ + {"name":"groceries.json"}, + {"name":"groceries.app.js"} + ] } ] diff --git a/apps/groceries/groceries.html b/apps/groceries/groceries.html new file mode 100644 index 000000000..9da8b0e6b --- /dev/null +++ b/apps/groceries/groceries.html @@ -0,0 +1,158 @@ + + + + + + +

List of products

+ + + + + + + + + + + +
namequantityactions
+

+

Add a new product

+
+
+
+ +
+
+ +
+
+ +
+
+
+

+ + + + + + + diff --git a/apps/groceries/groceries.png b/apps/groceries/groceries.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: Thu, 26 Mar 2020 17:20:23 +0000 Subject: [PATCH 0030/1189] Change product list style --- apps/groceries/groceries.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/groceries/groceries.html b/apps/groceries/groceries.html index 9da8b0e6b..0f29817ab 100644 --- a/apps/groceries/groceries.html +++ b/apps/groceries/groceries.html @@ -126,8 +126,12 @@ function updateSettings() { require("Storage").writeJSON(filename, settings); Bangle.buzz(); } +function twoChat(n){ + if(n<10) return '0'+n; + return ''+n; +} const mainMenu = settings.products.reduce(function(m, p, i){ - const name = '( '+p.quantity+' ) '+p.name; + const name = twoChat(p.quantity)+' '+p.name; m[name] = { value: p.ok, format: v => v?'[x]':'[ ]', From a78babc7b4058456bb2dcea66bbf7cb98b136489 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 26 Mar 2020 12:45:53 +0000 Subject: [PATCH 0031/1189] Add Mario Clock application Mario Clock is a low-res (80x80) watch face with Mario running through a level. He jumps to hit the bricks, which changes the time displayed. Pressing BTN1 will make Mario jump, and extend the display for a futher 10 seconds. --- apps.json | 13 + apps/marioclock/ChangeLog | 1 + apps/marioclock/marioclock-app.js | 380 +++++++++++++++++++++++++++++ apps/marioclock/marioclock-icon.js | 1 + apps/marioclock/marioclock.png | Bin 0 -> 11222 bytes 5 files changed, 395 insertions(+) create mode 100644 apps/marioclock/ChangeLog create mode 100644 apps/marioclock/marioclock-app.js create mode 100644 apps/marioclock/marioclock-icon.js create mode 100644 apps/marioclock/marioclock.png diff --git a/apps.json b/apps.json index d5b079f7a..95a6e634b 100644 --- a/apps.json +++ b/apps.json @@ -823,5 +823,18 @@ "storage": [ {"name":"widid.wid.js","url":"widget.js"} ] + }, + { "id": "marioclock", + "name": "Mario Clock", + "icon": "marioclock.png", + "version":"0.01", + "description": "Animated Mario clock, jumps to change the time!", + "tags": "clock,mario,retro", + "type": "clock", + "allow_emulator":true, + "storage": [ + {"name":"marioclock.app.js","url":"marioclock-app.js"}, + {"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true} + ] } ] diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog new file mode 100644 index 000000000..5f3bf84db --- /dev/null +++ b/apps/marioclock/ChangeLog @@ -0,0 +1 @@ +0.01: Create mario app diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js new file mode 100644 index 000000000..e8cb8c0e9 --- /dev/null +++ b/apps/marioclock/marioclock-app.js @@ -0,0 +1,380 @@ +/********************************** + BangleJS MARIO CLOCK V0.1.0 + + Based on Espruino Mario Clock V3 https://github.com/paulcockrell/espruino-mario-clock + + Converting images to 1bit BMP: Image > Mode > Indexed and tick the "Use black and white (1-bit) palette", Then export as BMP. + + Online Image convertor: https://www.espruino.com/Image+Converter +**********************************/ + +var locale = require("locale"); + +// Screen dimensions +let W, H; + +let intervalRef, displayTimeoutRef = null; + +// Space to draw watch widgets (e.g battery, bluetooth status) +const WIDGETS_GUTTER = 10; + +// Colours +const LIGHTEST = "#effedd"; +const LIGHT = "#add795"; +const DARK = "#588d77"; +const DARKEST = "#122d3e"; + +// Mario Images +const marioRunningImage1 = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("B8AfwH+B/8f/z4M+KExcnAUSCw87w4L8CJQRNB/YH+AxgCEAPAA=")) +}; + +const marioRunningImage1Neg = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAHwB0DOgY/jt8PDAPAEAB2gOyAAgAAAOAB4AAAA=")) +}; + +const marioRunningImage2 = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("B8AfwH+B/8f/z4M+KExcnAUSCw87w4J6BEsPnSfyT+S+OMAAAAA=")) +}; + +const marioRunningImage2Neg = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAHwB0DOgY/jt8PDAPAGEA7QAYhgMMBhAAAAAAAA=")) +}; + +const pyramid = { + width : 20, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAkAAQgAIEAEAgCAEBAAggAEQAAoAAE=")) +}; + +const pipe = { + width : 9, height : 6, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("/8BxaCRSCA==")) +}; + +const floor = { + width : 8, height : 3, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("/6pE")) +}; + +const sky = { + width : 128, height : 30, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("VVVVVVVVVVVVVVVVVVVVVQAAAAAAAAAAAAAAAAAAAABVVVVVVVVVVVVVVVVVVVVVIiIiIiIiIiIiIiIiIiIiIlVVVVVVVVVVVVVVVVVVVVWIiIiIiIiIiIiIiIiIiIiIVVVVVVVVVVVVVVVVVVVVVSIiIiIiIiICIiIiIiIiIiJVVVVVVVVVAVVVVVVVVVVViIiIiIiIiACIiIiIiIiIiFVVVVVVVVQAVVVVVVVVVVUiIiIiIiIgACIiIiIiIiIiVVVVVVVVUAAVVVUBVVVVUKqqqqqqqggAKCqqAKqqqoBVUBVVVVQAABAVVABVVVUAIiACIiIgAAAgAiAAIiIiAFVABVVVUAAAUAVUABRVVQCqgAKCqqAAACAAAAAgCqoAVUABAVVAAAAAAAAAAAVQAKqAAACqoAAAAAAAAAACgABAAAAAUEAAAAAAAAAABQAAgAAAACAAAAAAAAAAAAIAAAAAAABQAAAAAAAAAAAEAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) +}; + +const brick = { + width : 21, height : 15, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("f//0AABoAAsAABgAAMAABgAAMAABgAAMAABgAAMAABoAAsAABf//wA==")) +}; + +const flower = { + width : 7, height : 7, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("fY3wjW+OAA==")) +}; + +const pipePlant = { + width : 9, height : 15, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("FBsNhsHDWPn/gOLQSKQSKQQ=")) +}; + +const marioSprite = { + frameIdx: 0, + frames: [ + marioRunningImage1, + marioRunningImage2 + ], + negFrames: [ + marioRunningImage1Neg, + marioRunningImage2Neg + ], + x: 35, + y: 55, + jumpCounter: 0, + jumpIncrement: Math.PI / 10, + isJumping: false +}; + +const STATIC_TILES = { + "_": {img: floor, x: 16 * 8, y: 75}, + "X": {img: sky, x: 0, y: 10}, + "#": {img: brick, x: 0, y: 0}, +}; + +const TILES = { + "T": {img: pipe, x: 16 * 8, y: 69}, + "^": {img: pyramid, x: 16 * 8, y: 55}, + "*": {img: flower, x: 16 * 8, y: 68}, + "V": {img: pipePlant, x: 16 * 8, y: 60} +}; + +const ONE_SECOND = 1000; + +let timer = 0; +let backgroundArr = []; + +function incrementTimer() { + if (timer > 1000) { + timer = 0; + } + else { + timer += 50; + } +} + +function drawTile(sprite) { + g.drawImage(sprite.img, sprite.x, sprite.y); +} + +function drawBackground() { + g.setColor(LIGHTEST); + g.fillRect(0, 10, W, H); + + // draw floor + g.setColor(DARK); + for (var x = 0; x < 16; x++) { + var floorSprite = Object.assign({}, STATIC_TILES._, {x: x * 8}); + drawTile(floorSprite); + } + + // draw sky + var skySprite = STATIC_TILES.X; + g.setColor(LIGHT); + drawTile(skySprite); +} + +function drawScenery() { + // new random sprite + const spriteKeys = Object.keys(TILES); + const key = spriteKeys[Math.floor(Math.random() * spriteKeys.length)]; + let newSprite = Object.assign({}, TILES[key]); + + // remove first sprite if offscreen + let firstBackgroundSprite = backgroundArr[0]; + if (firstBackgroundSprite) { + if (firstBackgroundSprite.x < -20) backgroundArr.splice(0, 1); + } + + // set background sprite if array empty + var lastBackgroundSprite = backgroundArr[backgroundArr.length - 1]; + if (!lastBackgroundSprite) { + lastBackgroundSprite = newSprite; + backgroundArr.push(lastBackgroundSprite); + } + + // add random sprites + if (backgroundArr.length < 6 && lastBackgroundSprite.x < (16 * 7)) { + var randIdx = Math.floor(Math.random() * 25); + if (randIdx < spriteKeys.length - 1) { + backgroundArr.push(newSprite); + } + } + + for (x = 0; x < backgroundArr.length; x++) { + let scenerySprite = backgroundArr[x]; + + // clear sprite at previous position + g.setColor(LIGHTEST); + drawTile(scenerySprite); + + // draw sprite in new position + g.setColor(LIGHT); + scenerySprite.x -= 5; + drawTile(scenerySprite); + } +} + +function drawMario() { + // clear old mario frame + g.setColor(LIGHTEST); + g.drawImage( + marioSprite.negFrames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); + g.drawImage( + marioSprite.frames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); + + // calculate jumping + const t = new Date(), + seconds = t.getSeconds(), + milliseconds = t.getMilliseconds(); + + if (seconds == 59 && milliseconds > 800 && !marioSprite.isJumping) { + marioSprite.isJumping = true; + } + + if (marioSprite.isJumping) { + marioSprite.y = (Math.sin(marioSprite.jumpCounter) * -10) + 50 /* Mario Y base value */; + marioSprite.jumpCounter += marioSprite.jumpIncrement; + + if (marioSprite.jumpCounter.toFixed(1) >= 4) { + marioSprite.jumpCounter = 0; + marioSprite.isJumping = false; + } + } + + // calculate animation timing + if (timer % 100 === 0) { + // shift to next frame + marioSprite.frameIdx ^= 1; + } + + // colour in mario + g.setColor(LIGHT); + g.drawImage( + marioSprite.negFrames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); + + // draw mario + g.setColor(DARKEST); + g.drawImage( + marioSprite.frames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); +} + + +function drawBrick(x, y) { + const brickSprite = Object.assign({}, STATIC_TILES['#'], {x: x, y: y}); + + // draw brick background colour + g.setColor(LIGHT); + g.fillRect(x, y, x + 20, y+14); + + // draw brick sprite + g.setColor(DARK); + drawTile(brickSprite); +} + +function drawTime() { + // draw hour brick + drawBrick(20, 25); + // draw minute brick + drawBrick(42, 25); + + const t = new Date(); + const hours = ("0" + t.getHours()).substr(-2); + const mins = ("0" + t.getMinutes()).substr(-2); + + g.setFont("6x8"); + g.setColor(DARKEST); + g.drawString(hours, 25, 29); + g.drawString(mins, 47, 29); +} + +function drawDate() { + const date = new Date(); + const day = locale.dow(date).substr(0, 3); + const dayNum = date.getDay(); + const month = locale.month(date).substr(0, 3); + const year = date.getFullYear(); + + g.setFont("6x8"); + g.setColor(LIGHTEST); + g.drawString(`${day}, ${dayNum} ${month}`, 14, 0, true); +} + +function redraw() { + // Update timers + incrementTimer(); + + // Draw frame + drawScenery(); + drawTime(); + drawDate(); + drawMario(); + + // Render new frame + g.flip(); +} + +function clearTimers(){ + if(intervalRef) { + clearInterval(intervalRef); + intervalRef = null; + } + + if(displayTimeoutRef) { + clearInterval(displayTimeoutRef); + displayTimeoutRef = null; + } +} + +function resetDisplayTimeout() { + if (displayTimeoutRef) clearInterval(displayTimeoutRef); + + displayTimeoutRef = setInterval(() => { + if (Bangle.isLCDOn()) Bangle.setLCDPower(false); + clearTimers(); + }, ONE_SECOND * 10); +} + +function startTimers(){ + if(intervalRef) clearTimers(); + intervalRef = setInterval(redraw, 50); + + resetDisplayTimeout(); + + drawBackground(); + redraw(); +} + +// Main +function init() { + clearInterval(); + + // Initialise display + Bangle.setLCDMode("80x80"); + g.clear(); + + // Store screen dimensions + W = g.getWidth(); + H = g.getHeight(); + + // Get Mario to jump! + setWatch(() => { + if (intervalRef && !marioSprite.isJumping) marioSprite.isJumping = true; + resetDisplayTimeout(); + }, BTN1, {repeat:true}); + + setWatch(() => { + Bangle.setLCDMode(); + Bangle.showLauncher(); + }, BTN2, {repeat:false,edge:"falling"}); + + Bangle.on('lcdPower', (on) => { + if (on) { + startTimers(); + } else { + clearTimers(); + } + }); + + Bangle.on('faceUp',function(up){ + if (up && !Bangle.isLCDOn()) { + clearTimers(); + Bangle.setLCDPower(true); + } + }); +} + +// Initialise! +init(); +startTimers(); diff --git a/apps/marioclock/marioclock-icon.js b/apps/marioclock/marioclock-icon.js new file mode 100644 index 000000000..223d911f4 --- /dev/null +++ b/apps/marioclock/marioclock-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AAmBAEgrFAAZelFo+s1krAEgnBFwo5BBIIAi64nBSQgvnE4QvCwMAM4SRCXsAlFqwvGdsPXF5QHBRsYvJBYXWAD4vdw4ABF9gRBF8xYGF4plLF6xYMw4NBF74SBF9ocHAATvpFwgwOF6J9IFwwNIUIgvZFw4xGF7IABFxwwECxC/WE4gkCAALBMF64uHAYLvfC4xXDF4pflF4aPFBIQvZVo5bFAQYvIDQgvYFIjEFSIwvVAALwJGQyKGDQi/XSIYyDdhjvaYBIwNF8AwOF6LBHRoqVDXpIvUWQ4wGBpAvhSQaNHF7DCNdxwvcSIgRNF659GAAqUJF/4vIXAQGJBgy/hMxov/F6QARF/es64NBAD/XEwQvCqwvBBIYvhEgQvD/3+RoYAkFoOBFoIvqE4IvE/2BwMrAEgnBFwgACXsIADFo4ABeoIAjFQgA=")) diff --git a/apps/marioclock/marioclock.png b/apps/marioclock/marioclock.png new file mode 100644 index 0000000000000000000000000000000000000000..a462cdea1b5037590ac4d5655bb6be0ae95c7437 GIT binary patch literal 11222 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 Al>h($ literal 0 HcmV?d00001 From d0dd4b13af93296dfd66240fe361c076baf2c87a Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Thu, 26 Mar 2020 19:35:17 +0000 Subject: [PATCH 0032/1189] save on remove item --- apps/groceries/groceries.html | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/groceries/groceries.html b/apps/groceries/groceries.html index 0f29817ab..79acb4b59 100644 --- a/apps/groceries/groceries.html +++ b/apps/groceries/groceries.html @@ -87,6 +87,7 @@ function removeProduct(index){ products = products.filter((p,i) => i!==index) + save() renderProducts() } From fa718d87461d73a977aca1bb0e47af1f3d8580bc Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 26 Mar 2020 20:45:16 +0000 Subject: [PATCH 0033/1189] Fix day of the week bug --- apps/marioclock/ChangeLog | 1 + apps/marioclock/marioclock-app.js | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index 5f3bf84db..e81e2f78c 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -1 +1,2 @@ 0.01: Create mario app +0.02: Fix day of the week and add padding diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index e8cb8c0e9..248b15387 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -282,13 +282,12 @@ function drawTime() { function drawDate() { const date = new Date(); const day = locale.dow(date).substr(0, 3); - const dayNum = date.getDay(); + const dayNum = ("0" + date.getDate()).substr(-2); const month = locale.month(date).substr(0, 3); - const year = date.getFullYear(); g.setFont("6x8"); g.setColor(LIGHTEST); - g.drawString(`${day}, ${dayNum} ${month}`, 14, 0, true); + g.drawString(`${day} ${dayNum} ${month}`, 10, 0, true); } function redraw() { From e799dfd2061d430da73c75dc33b11a09cf830717 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Fri, 27 Mar 2020 06:23:43 +0100 Subject: [PATCH 0034/1189] Slight improvements to rendering --- apps/wohrm/app.js | 238 +++++++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 110 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 30f872066..5a9264f0b 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -5,96 +5,29 @@ const Setter = { LOWER: 'lower' }; -const shortBuzzTimeInMs = 100; +const shortBuzzTimeInMs = 50; const longBuzzTimeInMs = 200; -let upperLimit = 130; -let lowerLimit = 100; +let upperLimit = 90; +let upperLimitChanged = true; + +let lowerLimit = 50; +let lowerLimitChanged = true; + let limitSetter = Setter.NONE; + let currentHeartRate = 0; let hrConfidence = -1; +let hrOrConfidenceChanged = true; + let setterHighlightTimeout; -function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); - - //Round top left corner - g.fillEllipse(115,40,135,70); - - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); - - //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); - - //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); -} - -function renderCurrentHearRateBackground() { - g.setColor(1,1,1); - g.fillRect(45, 110, 165, 140); - g.setColor(0,0,0); - g.setFontVector(13); - g.drawString("Current:" , 65,117); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); -} - -function renderButtonIcons() { - g.setColor(1,1,1); - g.setFontVector(14); - - // + for Btn1 - g.drawString("+", 222,50); - - // Home for Btn2 - g.drawLine(220, 118, 227, 110); - g.drawLine(227, 110, 234, 118); - - g.drawPoly([222,117,222,125,232,125,232,117], false); - g.drawRect(226,120,229,125); - - // - for Btn3 - g.drawString("-", 222,170); -} - function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { + renderButtonIcons(); + renderUpperLimit(); renderCurrentHeartRate(); @@ -108,18 +41,50 @@ function drawTrainingHeartRate() { } function renderUpperLimit() { - if(limitSetter === Setter.UPPER){ - g.setColor(1, 1, 0); - } else { - g.setColor(1, 1, 1); - } + if(!upperLimitChanged) { return; } + + g.setColor(255,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); + //Round top left corner + g.fillEllipse(115,40,135,70); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(255,0,0); + g.fillEllipse(190,40,210,50); + + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); + + //Round bottom + g.setColor(255,0,0); + g.fillEllipse(180,190, 210, 210); + + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); + g.drawString("Upper : " + upperLimit, 130,50); + + upperLimitChanged = false; } function renderCurrentHeartRate() { + if(!hrOrConfidenceChanged) { return; } + + g.setColor(255,255,255); + g.fillRect(45, 110, 165, 140); + g.setColor(0,0,0); g.setFontVector(13); + + g.drawString("Current:" , 65,117); g.setFontAlign(1, -1, 0); g.drawString(currentHeartRate, 155, 117); @@ -128,6 +93,32 @@ function renderCurrentHeartRate() { } function renderLowerLimit() { + if(!lowerLimitChanged) { return; } + + g.setColor(0,0,255); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,255); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,255); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,255); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,255); + g.fillEllipse(10,200,30,210); + if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); } else { @@ -135,9 +126,13 @@ function renderLowerLimit() { } g.setFontVector(10); g.drawString("Lower : " + lowerLimit, 20,190); + + lowerLimitChanged = false; } function renderConfidenceBars(){ + if(!hrOrConfidenceChanged) { return; } + if(hrConfidence >= 85){ g.setColor(0, 255, 0); } else if (hrConfidence >= 50) { @@ -152,6 +147,24 @@ function renderConfidenceBars(){ g.fillRect(165, 110, 175, 140); } +function renderButtonIcons() { + g.setColor(255,255,255); + g.setFontVector(14); + + // + for Btn1 + g.drawString("+", 222,50); + + // Home for Btn2 + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); + + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); + + // - for Btn3 + g.drawString("-", 222,165); +} + function buzz() { if(currentHeartRate > upperLimit) @@ -161,7 +174,7 @@ function buzz() setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); } - if(currentHeartRate < upperLimit) + if(currentHeartRate < lowerLimit) { Bangle.buzz(longBuzzTimeInMs); setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); @@ -169,6 +182,7 @@ function buzz() } function onHrm(hrm){ + hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); currentHeartRate = hrm.bpm; hrConfidence = hrm.confidence; } @@ -178,6 +192,10 @@ function setLimitSetterToLower() { limitSetter = Setter.LOWER; console.log("Limit setter is lower"); + + upperLimitChanged = true; + lowerLimitChanged = true; + renderUpperLimit(); renderLowerLimit(); } @@ -187,6 +205,10 @@ function setLimitSetterToUpper() { limitSetter = Setter.UPPER; console.log("Limit setter is upper"); + + upperLimitChanged = true; + lowerLimitChanged = true; + renderLowerLimit(); renderUpperLimit(); } @@ -194,6 +216,10 @@ function setLimitSetterToUpper() { function setLimitSetterToNone() { limitSetter = Setter.NONE; console.log("Limit setter is none"); + + upperLimitChanged = true; + lowerLimitChanged = true; + renderLowerLimit(); renderUpperLimit(); } @@ -205,10 +231,12 @@ function incrementLimit(){ upperLimit++; renderUpperLimit(); console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { lowerLimit++; renderLowerLimit(); console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; } } @@ -219,10 +247,12 @@ function decrementLimit(){ upperLimit--; renderUpperLimit(); console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { lowerLimit--; renderLowerLimit(); console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; } } @@ -246,35 +276,23 @@ Bangle.on('lcdPower', (on) => { if (on) { Bangle.drawWidgets(); // call your app function here - renderLowerLimitBackground(); - renderCurrentHearRateBackground(); - renderUpperLimitBackground(); - renderButtonIcons(); drawTrainingHeartRate(); } }); -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -renderLowerLimitBackground(); -renderCurrentHearRateBackground(); -renderUpperLimitBackground(); -renderButtonIcons(); - -setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); - -setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); - -setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); - -setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); - -setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); - Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); +setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); +setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); +setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); +setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); +setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawTrainingHeartRate(); + // refesh every sec -setInterval(drawTrainingHeartRate, 1000); \ No newline at end of file +setInterval(drawTrainingHeartRate, 1000); From 1a7fb5d2cc33d2712497ca5525ff34c0e3d94dc6 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Fri, 27 Mar 2020 06:49:16 +0100 Subject: [PATCH 0035/1189] Minor tweaks --- apps/wohrm/app.js | 125 ++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 5a9264f0b..75c51a578 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,6 +23,56 @@ let hrOrConfidenceChanged = true; let setterHighlightTimeout; +function renderUpperLimitBackground() { + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); + + //Round top left corner + g.fillEllipse(115,40,135,70); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(1,0,0); + g.fillEllipse(190,40,210,50); + + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); + + //Round bottom + g.setColor(1,0,0); + g.fillEllipse(180,190, 210, 210); +} + +function renderLowerLimitBackground() { + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,1); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,1); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,1); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,1); + g.fillEllipse(10,200,30,210); +} + function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { @@ -37,40 +87,21 @@ function drawTrainingHeartRate() { renderConfidenceBars(); } - buzz(); + //buzz(); } function renderUpperLimit() { if(!upperLimitChanged) { return; } - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); - - //Round top left corner - g.fillEllipse(115,40,135,70); - - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(255,0,0); - g.fillEllipse(190,40,210,50); - - //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); - - //Round bottom - g.setColor(255,0,0); - g.fillEllipse(180,190, 210, 210); - + if(limitSetter === Setter.UPPER){ g.setColor(255,255, 0); } else { g.setColor(255,255,255); } - g.setFontVector(10); + g.setFontVector(13); g.drawString("Upper : " + upperLimit, 130,50); upperLimitChanged = false; @@ -80,13 +111,12 @@ function renderCurrentHeartRate() { if(!hrOrConfidenceChanged) { return; } g.setColor(255,255,255); - g.fillRect(45, 110, 165, 140); - g.setColor(0,0,0); - g.setFontVector(13); + g.fillRect(45, 110, 165, 150); - g.drawString("Current:" , 65,117); + g.setColor(0,0,0); + g.setFontVector(24); g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 155, 117); + g.drawString(currentHeartRate, 130, 117); //Reset alignment to defaults g.setFontAlign(-1, -1, 0); @@ -95,36 +125,15 @@ function renderCurrentHeartRate() { function renderLowerLimit() { if(!lowerLimitChanged) { return; } - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,255); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,255); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,255); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,255); - g.fillEllipse(10,200,30,210); - + if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); } else { g.setColor(255,255,255); } - g.setFontVector(10); + g.setFontVector(13); g.drawString("Lower : " + lowerLimit, 20,190); lowerLimitChanged = false; @@ -143,8 +152,8 @@ function renderConfidenceBars(){ g.setColor(255, 255, 255); } - g.fillRect(45, 110, 55, 140); - g.fillRect(165, 110, 175, 140); + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); } function renderButtonIcons() { @@ -276,6 +285,10 @@ Bangle.on('lcdPower', (on) => { if (on) { Bangle.drawWidgets(); // call your app function here + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; drawTrainingHeartRate(); } }); @@ -292,7 +305,9 @@ setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: tr g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -drawTrainingHeartRate(); +//drawTrainingHeartRate(); // refesh every sec +renderLowerLimitBackground(); +renderUpperLimitBackground(); setInterval(drawTrainingHeartRate, 1000); From 615a384acfd1d3078cc9311e3f4e2722238e5ffa Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 12:19:26 +0100 Subject: [PATCH 0036/1189] Create cliock.app.js --- apps/cliock/cliock.app.js | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 apps/cliock/cliock.app.js diff --git a/apps/cliock/cliock.app.js b/apps/cliock/cliock.app.js new file mode 100644 index 000000000..6fd2574b8 --- /dev/null +++ b/apps/cliock/cliock.app.js @@ -0,0 +1,51 @@ +var line; +var fontsize = 2; +var locale = require("locale"); +var marginTop = 40; +var flag = false; + +var WeekDays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]; + +function updateTime(){ + if (!Bangle.isLCDOn()) return; + line = 0; + var now = new Date(); + var date = locale.date(now,false); + var h = now.getHours(); + var m = now.getMinutes(); + h = h>10?h:"0"+h; + m = m>10?m:"0"+m; + g.clear(); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + g.setFont("6x8",fontsize); + g.setColor("#00ff00"); + writeLine(h+":"+m); + writeLine(WeekDays[now.getDay()]); + writeLine(date); + if(flag){ + writeLine(""); + flag = false; + } + else{ + writeLine("_"); + flag = true; + } +} +function writeLineStart(){ + g.drawString(">",4,marginTop+line*20); +} +function writeLine(str){ + writeLineStart(); + g.drawString(str,17,marginTop+line*20); + line++; +} + +Bangle.on('lcdPower',function(on) { + if (on) + updateTime(); +}); +var click = setInterval(updateTime, 1000); + + + From 576bdece48379084ebcb46d50dadc3d7eeb8004a Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 12:20:53 +0100 Subject: [PATCH 0037/1189] Update cliock.app.js --- apps/cliock/cliock.app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/cliock/cliock.app.js b/apps/cliock/cliock.app.js index 6fd2574b8..a51f98c6b 100644 --- a/apps/cliock/cliock.app.js +++ b/apps/cliock/cliock.app.js @@ -45,6 +45,7 @@ Bangle.on('lcdPower',function(on) { if (on) updateTime(); }); +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); var click = setInterval(updateTime, 1000); From 5031edbe6224bea354239a323278f546278b693f Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 12:46:02 +0100 Subject: [PATCH 0038/1189] Rename cliock.app.js to cliock.js --- apps/cliock/{cliock.app.js => cliock.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/cliock/{cliock.app.js => cliock.js} (100%) diff --git a/apps/cliock/cliock.app.js b/apps/cliock/cliock.js similarity index 100% rename from apps/cliock/cliock.app.js rename to apps/cliock/cliock.js From 8148cb02f6092c06622aeb766d9cdb7fead9f6f2 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 12:46:14 +0100 Subject: [PATCH 0039/1189] Rename cliock.js to app.js --- apps/cliock/{cliock.js => app.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/cliock/{cliock.js => app.js} (100%) diff --git a/apps/cliock/cliock.js b/apps/cliock/app.js similarity index 100% rename from apps/cliock/cliock.js rename to apps/cliock/app.js From 87c19f99c294fe14f05e16249f89a9df988be06d Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 12:51:23 +0100 Subject: [PATCH 0040/1189] Add files via upload --- apps/cliock/app.js.png | Bin 0 -> 305 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/cliock/app.js.png diff --git a/apps/cliock/app.js.png b/apps/cliock/app.js.png new file mode 100644 index 0000000000000000000000000000000000000000..4ad2d056daeb21b44ea8e6de6a57e7995bdf0b33 GIT binary patch literal 305 zcmV-10nYx3P)PpT>|_c>&L0FLoZl(#Csu14IsDVd()pglEvT zwz4x=FeF6QWtCs!zGTDXW0?Jz9TLFdXqlcyi<{iDU-M>#3=H>l-6?~%vz_ih-Ln96 zyaWF+13zQH10vuGC?FK=l@m#;CuK~<EY8 Date: Fri, 27 Mar 2020 12:54:03 +0100 Subject: [PATCH 0041/1189] Delete app.js.png --- apps/cliock/app.js.png | Bin 305 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/cliock/app.js.png diff --git a/apps/cliock/app.js.png b/apps/cliock/app.js.png deleted file mode 100644 index 4ad2d056daeb21b44ea8e6de6a57e7995bdf0b33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYx3P)PpT>|_c>&L0FLoZl(#Csu14IsDVd()pglEvT zwz4x=FeF6QWtCs!zGTDXW0?Jz9TLFdXqlcyi<{iDU-M>#3=H>l-6?~%vz_ih-Ln96 zyaWF+13zQH10vuGC?FK=l@m#;CuK~<EY8 Date: Fri, 27 Mar 2020 12:56:44 +0100 Subject: [PATCH 0042/1189] Create app-icon.js --- apps/cliock/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/cliock/app-icon.js diff --git a/apps/cliock/app-icon.js b/apps/cliock/app-icon.js new file mode 100644 index 000000000..3ce4e4559 --- /dev/null +++ b/apps/cliock/app-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer((atob("kEgwkBiIA/ACBhLB6gqKB6g//B6I4DiDqCB40QB4MBAoIXDB40BAIIPNG44PLAoQvMB5RPEB5JvEBAav1f7wA/ABoA==")) From 57be790c8191c6c5492d381f0a0593ef68cc0ec4 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 13:00:29 +0100 Subject: [PATCH 0043/1189] Update apps.json --- apps.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 15acb3b20..bf4f6d060 100644 --- a/apps.json +++ b/apps.json @@ -836,5 +836,19 @@ {"name":"marioclock.app.js","url":"marioclock-app.js"}, {"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true} ] - } + }, + { "id": "cliock", + "name": "Commandline-Clock", + "shortName":"CLI-Clock", + "icon": "app.png", + "version":"0.01", + "description": "Simple CLI-Styled Clock", + "tags": "cli,command,bash,shell", + "type": "clock", + "allow_emulator":true, + "storage": [ + {"name":"cliock.app.js","url":"app.js"}, + {"name":"cliock.img","url":"app-icon.js","evaluate":true} + ] +} ] From 28cbad640a7e48b9dd19ef3c65290cd90a09a8de Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 13:01:21 +0100 Subject: [PATCH 0044/1189] Add files via upload --- apps/cliock/app.png | Bin 0 -> 305 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/cliock/app.png diff --git a/apps/cliock/app.png b/apps/cliock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..4ad2d056daeb21b44ea8e6de6a57e7995bdf0b33 GIT binary patch literal 305 zcmV-10nYx3P)PpT>|_c>&L0FLoZl(#Csu14IsDVd()pglEvT zwz4x=FeF6QWtCs!zGTDXW0?Jz9TLFdXqlcyi<{iDU-M>#3=H>l-6?~%vz_ih-Ln96 zyaWF+13zQH10vuGC?FK=l@m#;CuK~<EY8 Date: Fri, 27 Mar 2020 13:04:56 +0100 Subject: [PATCH 0045/1189] Update app-icon.js --- apps/cliock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cliock/app-icon.js b/apps/cliock/app-icon.js index 3ce4e4559..fab023339 100644 --- a/apps/cliock/app-icon.js +++ b/apps/cliock/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer((atob("kEgwkBiIA/ACBhLB6gqKB6g//B6I4DiDqCB40QB4MBAoIXDB40BAIIPNG44PLAoQvMB5RPEB5JvEBAav1f7wA/ABoA==")) +require("heatshrink").decompress(atob("kEgwkBiIA/ACBhLB6gqKB6g//B6I4DiDqCB40QB4MBAoIXDB40BAIIPNG44PLAoQvMB5RPEB5JvEBAav1f7wA/ABoA==")) From 09b25f0ab8f62f557eae6b1e846924ba384198fe Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 13:06:02 +0100 Subject: [PATCH 0046/1189] Update app.js --- apps/cliock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index a51f98c6b..47dbb7ec4 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -4,7 +4,7 @@ var locale = require("locale"); var marginTop = 40; var flag = false; -var WeekDays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]; +var WeekDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; function updateTime(){ if (!Bangle.isLCDOn()) return; From a8d04e35527c5b6ebd0825591109b53ee8a711bd Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 13:06:33 +0100 Subject: [PATCH 0047/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bf4f6d060..70c76b41a 100644 --- a/apps.json +++ b/apps.json @@ -841,7 +841,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Simple CLI-Styled Clock", "tags": "cli,command,bash,shell", "type": "clock", From c6d4de79feb14a361fec65da88a947f0e47b4352 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 16:31:18 +0100 Subject: [PATCH 0048/1189] Update app.js --- apps/cliock/app.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index 47dbb7ec4..b4fd7d7e2 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -3,9 +3,16 @@ var fontsize = 2; var locale = require("locale"); var marginTop = 40; var flag = false; +var WeekDays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]; -var WeekDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; - +function drawAll(){ + g.clear(); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + g.setFont("6x8",fontsize); + g.setColor("#00ff00"); + updateTime(); +} function updateTime(){ if (!Bangle.isLCDOn()) return; line = 0; @@ -15,11 +22,6 @@ function updateTime(){ var m = now.getMinutes(); h = h>10?h:"0"+h; m = m>10?m:"0"+m; - g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - g.setFont("6x8",fontsize); - g.setColor("#00ff00"); writeLine(h+":"+m); writeLine(WeekDays[now.getDay()]); writeLine(date); @@ -36,17 +38,15 @@ function writeLineStart(){ g.drawString(">",4,marginTop+line*20); } function writeLine(str){ + g.clearRect(0,marginTop+line*20,(str.length*15+15),marginTop+20+line*20); writeLineStart(); g.drawString(str,17,marginTop+line*20); line++; } +drawAll(); Bangle.on('lcdPower',function(on) { if (on) - updateTime(); + drawAll(); }); -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); var click = setInterval(updateTime, 1000); - - - From 3894a12033ff827cf48eca11d3c7e8d8fb334a74 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 16:31:42 +0100 Subject: [PATCH 0049/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 70c76b41a..9b984376a 100644 --- a/apps.json +++ b/apps.json @@ -841,7 +841,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.02", + "version":"0.03", "description": "Simple CLI-Styled Clock", "tags": "cli,command,bash,shell", "type": "clock", From b0f5c94789aa545bb3fd91b864f47a37f9561148 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 17:01:58 +0100 Subject: [PATCH 0050/1189] Update app.js --- apps/cliock/app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index b4fd7d7e2..9ea1f011a 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -22,6 +22,8 @@ function updateTime(){ var m = now.getMinutes(); h = h>10?h:"0"+h; m = m>10?m:"0"+m; + g.setFont("6x8",fontsize); + g.setColor("#00ff00"); writeLine(h+":"+m); writeLine(WeekDays[now.getDay()]); writeLine(date); @@ -40,7 +42,7 @@ function writeLineStart(){ function writeLine(str){ g.clearRect(0,marginTop+line*20,(str.length*15+15),marginTop+20+line*20); writeLineStart(); - g.drawString(str,17,marginTop+line*20); + g.drawString(str,20,marginTop+line*20); line++; } From b45c89ee0d87b88e26163f49a978a77ea933e819 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 17:02:22 +0100 Subject: [PATCH 0051/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 9b984376a..692979fdd 100644 --- a/apps.json +++ b/apps.json @@ -841,7 +841,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "Simple CLI-Styled Clock", "tags": "cli,command,bash,shell", "type": "clock", From b47b5f5a4f7184b662b6d1d4b187cf065720c7e7 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 01:00:49 +0800 Subject: [PATCH 0052/1189] Update stopwatch.js --- apps/swatch/stopwatch.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 6886bc697..dc79b34da 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -22,7 +22,12 @@ function updateLabels() { g.setFont("6x8",1); g.setFontAlign(-1,-1); for (var i in lapTimes) { - g.drawString(i+": "+timeToText(lapTimes[i]),10,timeY + 30 + i*8); + if (i<18) + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),8,timeY + 30 + i*8);} + else if (i<36) + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),80,timeY + 30 + (i-18)*8);} + else + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),152,timeY + 30 + (i-36)*8);} } drawsecs(); } From 563c445cabf530c4347170a2afa3db4b64a4d13c Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 18:04:46 +0100 Subject: [PATCH 0053/1189] Update app.js --- apps/cliock/app.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index 9ea1f011a..48b225b07 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -3,14 +3,12 @@ var fontsize = 2; var locale = require("locale"); var marginTop = 40; var flag = false; -var WeekDays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]; +var WeekDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; function drawAll(){ g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); - g.setFont("6x8",fontsize); - g.setColor("#00ff00"); updateTime(); } function updateTime(){ @@ -23,7 +21,8 @@ function updateTime(){ h = h>10?h:"0"+h; m = m>10?m:"0"+m; g.setFont("6x8",fontsize); - g.setColor("#00ff00"); + g.setColor(0,1,0); + g.setFontAlign(-1,0); writeLine(h+":"+m); writeLine(WeekDays[now.getDay()]); writeLine(date); From b40f873108421a0f6db0e8e77098de4abe539760 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 18:05:12 +0100 Subject: [PATCH 0054/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 692979fdd..70c76b41a 100644 --- a/apps.json +++ b/apps.json @@ -841,7 +841,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.04", + "version":"0.02", "description": "Simple CLI-Styled Clock", "tags": "cli,command,bash,shell", "type": "clock", From ad67db1a4abbcf51f1dd18c0c2e317e03cfb113c Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 01:07:24 +0800 Subject: [PATCH 0055/1189] Update stopwatch.js Made lap entries count up from 1 Made lap entries scroll to 2nd column after 18th entry to allow for 36 lap entries before scrolling off-screen --- apps/swatch/stopwatch.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index dc79b34da..ed087e66f 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -23,11 +23,9 @@ function updateLabels() { g.setFontAlign(-1,-1); for (var i in lapTimes) { if (i<18) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),8,timeY + 30 + i*8);} - else if (i<36) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),80,timeY + 30 + (i-18)*8);} - else - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),152,timeY + 30 + (i-36)*8);} + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 30 + i*8);} + else + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-18)*8);} } drawsecs(); } From 4696f7e4ecb557281727ec3569e9c0a3d8566cad Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 01:10:45 +0800 Subject: [PATCH 0056/1189] Create ChangeLog Changelog for updated Lap logging feature --- apps/swatch/ChangeLog | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 apps/swatch/ChangeLog diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog new file mode 100644 index 000000000..86f584836 --- /dev/null +++ b/apps/swatch/ChangeLog @@ -0,0 +1,3 @@ +0.01 Original App +0.02 Lap log now counts up from 1 + Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen From 30912d6825d9efe1f800cd1a00c8eedc5a040e07 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 01:13:27 +0800 Subject: [PATCH 0057/1189] Update apps.json Updated Stopwatch app version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 15acb3b20..44a30c1f9 100644 --- a/apps.json +++ b/apps.json @@ -355,7 +355,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.01", + "version":"0.02", "description": "Simple stopwatch with Lap Time recording", "tags": "health", "allow_emulator":true, From bcdd8c7be1f29493a34e79ee0d38c7da0c8aaaa7 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 19:00:12 +0100 Subject: [PATCH 0058/1189] Update app.js --- apps/cliock/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index 48b225b07..e17df9788 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -39,7 +39,7 @@ function writeLineStart(){ g.drawString(">",4,marginTop+line*20); } function writeLine(str){ - g.clearRect(0,marginTop+line*20,(str.length*15+15),marginTop+20+line*20); + g.clearRect(0,marginTop+line*20,((str.length+1)*15+15),marginTop+20+line*20); writeLineStart(); g.drawString(str,20,marginTop+line*20); line++; @@ -51,3 +51,4 @@ Bangle.on('lcdPower',function(on) { drawAll(); }); var click = setInterval(updateTime, 1000); +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); From d21bb41c093ff31441328ffc669a6252b721e590 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 19:00:31 +0100 Subject: [PATCH 0059/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 70c76b41a..9b984376a 100644 --- a/apps.json +++ b/apps.json @@ -841,7 +841,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.02", + "version":"0.03", "description": "Simple CLI-Styled Clock", "tags": "cli,command,bash,shell", "type": "clock", From c07a7baeb96155eadf968528215a5f6f49bd32a9 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 19:34:15 +0100 Subject: [PATCH 0060/1189] Update app.js --- apps/cliock/app.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index e17df9788..056a7a949 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -1,5 +1,5 @@ var line; -var fontsize = 2; +var fontsize = 3; var locale = require("locale"); var marginTop = 40; var flag = false; @@ -18,8 +18,8 @@ function updateTime(){ var date = locale.date(now,false); var h = now.getHours(); var m = now.getMinutes(); - h = h>10?h:"0"+h; - m = m>10?m:"0"+m; + h = h>=10?h:"0"+h; + m = m>=10?m:"0"+m; g.setFont("6x8",fontsize); g.setColor(0,1,0); g.setFontAlign(-1,0); @@ -36,12 +36,12 @@ function updateTime(){ } } function writeLineStart(){ - g.drawString(">",4,marginTop+line*20); + g.drawString(">",4,marginTop+line*25); } function writeLine(str){ - g.clearRect(0,marginTop+line*20,((str.length+1)*15+15),marginTop+20+line*20); + g.clearRect(0,marginTop+line*25,((str.length+1)*15+15),marginTop+20+line*25); writeLineStart(); - g.drawString(str,20,marginTop+line*20); + g.drawString(str,25,marginTop+line*25); line++; } From e6274f267dcfa4da564eac2a164c26ecd1a45b63 Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 19:34:36 +0100 Subject: [PATCH 0061/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 9b984376a..692979fdd 100644 --- a/apps.json +++ b/apps.json @@ -841,7 +841,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "Simple CLI-Styled Clock", "tags": "cli,command,bash,shell", "type": "clock", From be1d8e76ce3213233b5b92e4de7ceae95e8aa49a Mon Sep 17 00:00:00 2001 From: Pascal Gollnick <33615872+unnamed1337@users.noreply.github.com> Date: Fri, 27 Mar 2020 19:42:23 +0100 Subject: [PATCH 0062/1189] Update app.js --- apps/cliock/app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index 056a7a949..607993f63 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -22,12 +22,12 @@ function updateTime(){ m = m>=10?m:"0"+m; g.setFont("6x8",fontsize); g.setColor(0,1,0); - g.setFontAlign(-1,0); + g.setFontAlign(-1,-1); writeLine(h+":"+m); writeLine(WeekDays[now.getDay()]); writeLine(date); if(flag){ - writeLine(""); + writeLine(" "); flag = false; } else{ @@ -36,12 +36,12 @@ function updateTime(){ } } function writeLineStart(){ - g.drawString(">",4,marginTop+line*25); + g.drawString(">",4,marginTop+line*30); } function writeLine(str){ - g.clearRect(0,marginTop+line*25,((str.length+1)*15+15),marginTop+20+line*25); + g.clearRect(0,marginTop+line*30,((str.length+1)*20),marginTop+25+line*30); writeLineStart(); - g.drawString(str,25,marginTop+line*25); + g.drawString(str,25,marginTop+line*30); line++; } From 82feb3b7c102c068c211ae4de9ac9a377fa6b3b9 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Fri, 27 Mar 2020 20:00:37 +0000 Subject: [PATCH 0063/1189] rename the app to have a 7character name & fix issue with saving --- apps.json | 12 ++++++------ .../groceries.html => grocery/grocery.html} | 8 ++++---- .../groceries.png => grocery/grocery.png} | Bin 3 files changed, 10 insertions(+), 10 deletions(-) rename apps/{groceries/groceries.html => grocery/grocery.html} (96%) rename apps/{groceries/groceries.png => grocery/grocery.png} (100%) diff --git a/apps.json b/apps.json index 3e3c89bba..c06cd49a8 100644 --- a/apps.json +++ b/apps.json @@ -825,17 +825,17 @@ ] }, { - "id": "groceries", - "name": "Groceries", - "icon": "groceries.png", + "id": "grocery", + "name": "Grocery", + "icon": "grocery.png", "version":"0.01", "description": "Simple grocery list - Display a list of product and track if you already put them in your cart.", "tags": "tool,outdoors", "type": "app", - "custom":"groceries.html", + "custom":"grocery.html", "storage": [ - {"name":"groceries.json"}, - {"name":"groceries.app.js"} + {"name":"grocery"}, + {"name":"grocery.app.js"} ] } ] diff --git a/apps/groceries/groceries.html b/apps/grocery/grocery.html similarity index 96% rename from apps/groceries/groceries.html rename to apps/grocery/grocery.html index 79acb4b59..12711375d 100644 --- a/apps/groceries/groceries.html +++ b/apps/grocery/grocery.html @@ -111,7 +111,7 @@ var newTime = ${Date.now()} var products = ${JSON.stringify(products)} var newTime = newTime; -var filename = 'groceries.json'; +var filename = 'grocery'; var settings = require("Storage").readJSON(filename,1)|| null; function getSettings(){ return { @@ -152,9 +152,9 @@ E.showMenu(mainMenu); var icon = `require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AQ0QACF1nGAAIxpFoYwqFwwwnRggwGB4eFAggACLzwHCMAeF1WGAgOGw2x2IGCLzYGEF4YpBwotCFwJfWFwo1GSAYtBAIIABRq4vFMhAwBzoAFdzIuKAAOc4IAGGC4qEMZOiF44wXFxovleBYvIGCwmB0WjE4V/AgfG1IvCzujFQOjwoECF6WFwovBDYOFEwN/AgIwCAgOFBwYrBBAQEBzodCF6AAHww1CBpIODAAYvRDAWG2IEBAYYJFBxICCF6Ox1WxAAQfBAYQlCAAIOJAQIvUADQvn1WGR4RfbP4gAFBwgFCF7a5EdwQADF46/cL9wAQF94AGF85bB1TvmF47vdJ4bvFF8qPRFgLv/L7jPCaQq/fYYrvgJgoAGd/7v/F/4v/F5oAdF54weFyAA/AH4A3A="))`; sendCustomizedApp({ storage:[ - {name:"groceries.app.js", content:app}, - {name:"groceries.img", content:icon, evaluate:true}, - {name:"groceries.json"} + {name:"grocery.app.js", content:app}, + {name:"grocery.img", content:icon, evaluate:true}, + {name:"grocery"} ] }); }); diff --git a/apps/groceries/groceries.png b/apps/grocery/grocery.png similarity index 100% rename from apps/groceries/groceries.png rename to apps/grocery/grocery.png From 8aabcf28e8df1a8dcd8ac72635a5968c5f4f5ef7 Mon Sep 17 00:00:00 2001 From: Oli Sanders <35221386+oli-sanders@users.noreply.github.com> Date: Fri, 27 Mar 2020 23:53:38 +0000 Subject: [PATCH 0064/1189] dev clock (#13) --- apps.json | 13 ++++ apps/dclock/ChangeLog | 8 +++ apps/dclock/clock-dev-icon.js | 1 + apps/dclock/clock-dev.js | 111 ++++++++++++++++++++++++++++++++++ apps/dclock/clock-dev.png | Bin 0 -> 2603 bytes 5 files changed, 133 insertions(+) create mode 100644 apps/dclock/ChangeLog create mode 100644 apps/dclock/clock-dev-icon.js create mode 100644 apps/dclock/clock-dev.js create mode 100644 apps/dclock/clock-dev.png diff --git a/apps.json b/apps.json index 15acb3b20..4f29159cb 100644 --- a/apps.json +++ b/apps.json @@ -508,6 +508,19 @@ {"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true} ] }, + { "id": "dclock", + "name": "Dev Clock", + "icon": "clock-dev.png", + "version":"0.08", + "description": "A Digital Clock including timestamp (tst), beats(@), days in current month (dm) and days since new moon (l)", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"dclock.app.js","url":"clock-dev.js"}, + {"name":"dclock.img","url":"clock-dev-icon.js","evaluate":true} + ] + }, { "id": "gesture", "name": "Gesture Test", "icon": "gesture.png", diff --git a/apps/dclock/ChangeLog b/apps/dclock/ChangeLog new file mode 100644 index 000000000..6582ec16e --- /dev/null +++ b/apps/dclock/ChangeLog @@ -0,0 +1,8 @@ +0.01: branched from simple clock and added seconds +0.02: add timestamp (tst) +0.03: fix timestamp round to whole number +0.04: add iso datetime and move day of the week (d) / month names (m) +0.05: add beats (@) +0.06: tidy up +0.07: add days in current month (md) and days since new moon (l) +0.08: update icon \ No newline at end of file diff --git a/apps/dclock/clock-dev-icon.js b/apps/dclock/clock-dev-icon.js new file mode 100644 index 000000000..f36dcaee3 --- /dev/null +++ b/apps/dclock/clock-dev-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkEIf4A5/8wgf/AwUB/8gh/zA4QMCl/xA4cAichgIaBiEDgMgmECDQMAkMA+EgiYvDkQJBkcQgMQDwMggUiiECG4MikEBmQWCgURiEREQIXBCIMxkIIBAoMSiQ4BGoIABKgPykRSBI4JfC+c/iARBl8zmBfEAAUvIgIAUkbAtgalB+ADDBIKSBHgUgmYJCAAa6BmCoBAYMiBIMRC4UQmEAAoQvFmUDAYUSmcxWIKMBEQKrBOw0yh8wmcyj4nBIYQDB+cwBAQA/ABUxgUDkBqBgchkMiiUikMRgSOBkR3BkEhC4MgiQHBiADBC4UQAYMRiUxkECAAITBC4MSiUQF4MTiQTBBAIDBkcCiMxkUTAYIvCAH4A/AH4AKiIPPgMxiESgUQgECgMBdAMiiUgC48ikUBiEBiIXDGQURiIbBF48RkAvCEwIvCkERgQMBRHpDBOoRhBNoJOBJIkiKYMjgcTOoMhLQMQmMDDIMjQQInEC4MhiUSkQHCC4MAkAXCiUjiZ5UiR5jLwLaBAQJ1BAgIAMCgMxMwMgkciAoMjC5pqBRwPxCoMiiUyGBsgiBBBiESVAKzBf+YACA==")) \ No newline at end of file diff --git a/apps/dclock/clock-dev.js b/apps/dclock/clock-dev.js new file mode 100644 index 000000000..39f031fcc --- /dev/null +++ b/apps/dclock/clock-dev.js @@ -0,0 +1,111 @@ +/* jshint esversion: 6 */ +const timeFontSize = 4; +const dateFontSize = 3; +const smallFontSize = 2; +const font = "6x8"; + +const xyCenter = g.getWidth() / 2; +const yposTime = 50; +const yposDate = 85; +const yposTst = 115; +const yposDml = 170; +const yposDayMonth = 195; +const yposGMT = 220; + +// Check settings for what type our clock should be +var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; + +function getUTCTime(d) { + return d.toUTCString().split(' ')[4].split(':').map(function(d){return Number(d)}); +} + +function drawSimpleClock() { + // get date + var d = new Date(); + var da = d.toString().split(" "); + var dutc = getUTCTime(d); + + g.reset(); // default draw styles + // drawSting centered + g.setFontAlign(0, 0); + + // draw time + var time = da[4].split(":"); + var hours = time[0], + minutes = time[1], + seconds = time[2]; + + var meridian = ""; + if (is12Hour) { + hours = parseInt(hours,10); + meridian = "AM"; + if (hours == 0) { + hours = 12; + meridian = "AM"; + } else if (hours >= 12) { + meridian = "PM"; + if (hours>12) hours -= 12; + } + hours = (" "+hours).substr(-2); + } + + // Time + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}:${seconds}`, xyCenter, yposTime, true); + g.setFont(font, smallFontSize); + g.drawString(meridian, xyCenter + 102, yposTime + 10, true); + + // Date String + g.setFont(font, dateFontSize); + g.drawString(`${d.getFullYear()}-${d.getMonth()+1}-${d.getDate()}`, xyCenter, yposDate, true); + + // Timestamp + var tst = Math.round(d.getTime()); + g.setFont(font, smallFontSize); + g.drawString(`tst:${tst}`, xyCenter, yposTst, true); + + //Days in month + var dom = new Date(d.getFullYear(), d.getMonth()+1, 0).getDate(); + + //Days since full moon + var knownnew = new Date(2020,02,24,09,28,0); + + // Get millisecond difference and divide down to cycles + var cycles = (d.getTime()-knownnew.getTime())/1000/60/60/24/29.53; + + // Multiply decimal component back into days since new moon + var sincenew = (cycles % 1)*29.53; + + // Draw days in month and sime since new moon + g.setFont(font, smallFontSize); + g.drawString(`md:${dom} l:${sincenew.toFixed(2)}`, xyCenter, yposDml, true); + + // draw Month name, Day of the week and beats + var beats = Math.floor((((dutc[0] + 1) % 24) + dutc[1] / 60 + dutc[2] / 3600) * 1000 / 24); + g.setFont(font, smallFontSize); + g.drawString(`m:${da[1]} d:${da[0]} @${beats}`, xyCenter, yposDayMonth, true); + + // draw gmt + var gmt = da[5]; + g.setFont(font, smallFontSize); + g.drawString(gmt, xyCenter, yposGMT, true); +} + +// handle switch display on by pressing BTN1 +Bangle.on('lcdPower', function(on) { + if (on) drawSimpleClock(); +}); + +// clean app screen +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// refesh every 100 milliseconds +setInterval(drawSimpleClock, 100); + +// draw now +drawSimpleClock(); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); \ No newline at end of file diff --git a/apps/dclock/clock-dev.png b/apps/dclock/clock-dev.png new file mode 100644 index 0000000000000000000000000000000000000000..0cfbff44c1e6ff1dad206c266e64f43787c846df GIT binary patch literal 2603 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 N002ovPDHLkV1gky Date: Sat, 28 Mar 2020 11:07:14 +0800 Subject: [PATCH 0065/1189] Update stopwatch.js - Remove ability to lap while stopped - Added ability to save log of laps as dated json array while stopped --- apps/swatch/stopwatch.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index ed087e66f..ac1cc0d5b 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -4,6 +4,7 @@ var started = false; var timeY = 60; var hsXPos = 0; var lapTimes = []; +var saveTimes = []; var displayInterval; function timeToText(t) { @@ -18,7 +19,7 @@ function updateLabels() { g.setFontAlign(0,0,3); g.drawString(started?"STOP":"GO",230,120); if (!started) g.drawString("RESET",230,50); - g.drawString("LAP",230,190); + g.drawString(started?"LAP":"SAVE",230,190); g.setFont("6x8",1); g.setFontAlign(-1,-1); for (var i in lapTimes) { @@ -50,6 +51,11 @@ function drawms() { g.clearRect(hsXPos,timeY,220,timeY+20); g.drawString("."+("0"+hs).substr(-2),hsXPos,timeY+10); } +function saveconvert() { + for (var v in lapTimes){ + saveTimes[v]=v+1+"-"+timeToText(lapTimes[(lapTimes.length-1)-v]); + } +} setWatch(function() { // Start/stop started = !started; @@ -85,6 +91,12 @@ setWatch(function() { // Lap if (started) tCurrent = Date.now(); lapTimes.unshift(tCurrent-tStart); tStart = tCurrent; + if (!started) + { + var timenow= Date(); + saveconvert(); + require("Storage").writeJSON("StpWch-"+timenow.toString(), saveTimes); + } updateLabels(); }, BTN3, {repeat:true}); From 661eaa7c3a02127a8fd46ada3b058c2db4970a30 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 11:57:32 +0800 Subject: [PATCH 0066/1189] Update ChangeLog --- apps/swatch/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index 86f584836..119333d94 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -1,3 +1,4 @@ 0.01 Original App 0.02 Lap log now counts up from 1 Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen +0.03 Added ability to save Lap log as a date named JSON file into memory From 72d0de30a52fe7490010d1e02de493eb0e96edc5 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 11:58:14 +0800 Subject: [PATCH 0067/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 44a30c1f9..a8083c619 100644 --- a/apps.json +++ b/apps.json @@ -355,7 +355,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.02", + "version":"0.03", "description": "Simple stopwatch with Lap Time recording", "tags": "health", "allow_emulator":true, From be539e59932c7627cf91e3709082fbc709ce8a7d Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 12:12:22 +0800 Subject: [PATCH 0068/1189] Update stopwatch.js -Swapped functions of BN1 and BN3 --- apps/swatch/stopwatch.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index ac1cc0d5b..73cf0adfc 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -18,8 +18,8 @@ function updateLabels() { g.setFont("6x8",2); g.setFontAlign(0,0,3); g.drawString(started?"STOP":"GO",230,120); - if (!started) g.drawString("RESET",230,50); - g.drawString(started?"LAP":"SAVE",230,190); + if (!started) g.drawString("RESET",230,190); + g.drawString(started?"LAP":"SAVE",230,50); g.setFont("6x8",1); g.setFontAlign(-1,-1); for (var i in lapTimes) { @@ -78,14 +78,6 @@ setWatch(function() { // Start/stop drawms(); }, 20); }, BTN2, {repeat:true}); -setWatch(function() { // Reset - Bangle.beep(); - if (!started) { - tStart = tCurrent = Date.now(); - } - lapTimes = []; - updateLabels(); -}, BTN1, {repeat:true}); setWatch(function() { // Lap Bangle.beep(); if (started) tCurrent = Date.now(); @@ -98,6 +90,14 @@ setWatch(function() { // Lap require("Storage").writeJSON("StpWch-"+timenow.toString(), saveTimes); } updateLabels(); +}, BTN1, {repeat:true}); +setWatch(function() { // Reset + Bangle.beep(); + if (!started) { + tStart = tCurrent = Date.now(); + } + lapTimes = []; + updateLabels(); }, BTN3, {repeat:true}); updateLabels(); From 06b98f0043e99446c5c77b82b3d974ff38fa2c56 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 12:14:40 +0800 Subject: [PATCH 0069/1189] Update stopwatch.js Fixed bug where one could reset lap log even though timer is running --- apps/swatch/stopwatch.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 73cf0adfc..d4136d8ed 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -92,11 +92,11 @@ setWatch(function() { // Lap updateLabels(); }, BTN1, {repeat:true}); setWatch(function() { // Reset - Bangle.beep(); if (!started) { - tStart = tCurrent = Date.now(); - } + Bangle.beep(); + tStart = tCurrent = Date.now(); lapTimes = []; + } updateLabels(); }, BTN3, {repeat:true}); From 7bbc2e7eb14b4101d3b2f67b765f3eebd6c98959 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 12:21:58 +0800 Subject: [PATCH 0070/1189] Update ChangeLog --- apps/swatch/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index 119333d94..d907766c1 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -2,3 +2,4 @@ 0.02 Lap log now counts up from 1 Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen 0.03 Added ability to save Lap log as a date named JSON file into memory + Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running From 11bf84f583bf8b4a00dfdb9d74d46b3067786fc3 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Sat, 28 Mar 2020 16:03:37 +0800 Subject: [PATCH 0071/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a8083c619..0cdd8fd3b 100644 --- a/apps.json +++ b/apps.json @@ -356,7 +356,7 @@ "name": "Stopwatch", "icon": "stopwatch.png", "version":"0.03", - "description": "Simple stopwatch with Lap Time recording", + "description": "Simple stopwatch with Lap Time logging to a JSON file", "tags": "health", "allow_emulator":true, "storage": [ From b7b5d6764b357649fc258c3530c88dec25c168e6 Mon Sep 17 00:00:00 2001 From: Simon Weis Date: Thu, 26 Mar 2020 22:30:34 +0100 Subject: [PATCH 0072/1189] Adds gbridge call notification and refactor widget --- apps.json | 8 +- apps/gbridge/ChangeLog | 1 + apps/gbridge/gbridge-call-ico.js | 1 + apps/gbridge/gbridge-music-ico.js | 1 + apps/gbridge/gbridge-off-ico.js | 1 + apps/gbridge/gbridge-on-ico.js | 1 + apps/gbridge/widget.js | 356 ++++++++++++++++++++---------- 7 files changed, 250 insertions(+), 119 deletions(-) create mode 100644 apps/gbridge/gbridge-call-ico.js create mode 100644 apps/gbridge/gbridge-music-ico.js create mode 100644 apps/gbridge/gbridge-off-ico.js create mode 100644 apps/gbridge/gbridge-on-ico.js diff --git a/apps.json b/apps.json index d5b079f7a..b5350d349 100644 --- a/apps.json +++ b/apps.json @@ -66,13 +66,17 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.04", + "version":"0.05", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "storage": [ {"name":"gbridge.app.js","url":"app.js"}, {"name":"gbridge.img","url":"app-icon.js","evaluate":true}, - {"name":"gbridge.wid.js","url":"widget.js"} + {"name":"gbridge.wid.js","url":"widget.js"}, + {"name":"gbridge-music-ico.img","url":"gbridge-music-ico.js","evaluate":true}, + {"name":"gbridge-off-ico.img","url":"gbridge-off-ico.js","evaluate":true}, + {"name":"gbridge-on-ico.img","url":"gbridge-on-ico.js","evaluate":true}, + {"name":"gbridge-call-ico.img","url":"gbridge-call-ico.js","evaluate":true} ] }, { "id": "mclock", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index 28789ec04..3a6dd3bfd 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -2,3 +2,4 @@ 0.02: Increase contrast (darker notification background, white text) 0.03: Gadgetbridge widget now shows connection state 0.04: Tweaks for variable size widget system +0.05: Show incoming call notification \ No newline at end of file diff --git a/apps/gbridge/gbridge-call-ico.js b/apps/gbridge/gbridge-call-ico.js new file mode 100644 index 000000000..ce722a9a8 --- /dev/null +++ b/apps/gbridge/gbridge-call-ico.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("jEYwIMJj4CCwACJh4CCCIMOAQMGAQMHAQMDAQMBCIMB4PwgHz/EAn4CBj4CBg4CBgACCAAw=")) \ No newline at end of file diff --git a/apps/gbridge/gbridge-music-ico.js b/apps/gbridge/gbridge-music-ico.js new file mode 100644 index 000000000..ff8f80883 --- /dev/null +++ b/apps/gbridge/gbridge-music-ico.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")) \ No newline at end of file diff --git a/apps/gbridge/gbridge-off-ico.js b/apps/gbridge/gbridge-off-ico.js new file mode 100644 index 000000000..1a722f372 --- /dev/null +++ b/apps/gbridge/gbridge-off-ico.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("i0WwQFC1WgAgYFDAgIFClQFCwEK1W/AoIPB1f+CAMq1f7/WqwQPB/fq1Gq1/+/4dC/2/CAIaB/YbBAAO///qAoX/B4QbBDQQ7BDQQrBAAWoIIIACIIIVC0ECB4cACAZiBAoRtCAoIDBA")) \ No newline at end of file diff --git a/apps/gbridge/gbridge-on-ico.js b/apps/gbridge/gbridge-on-ico.js new file mode 100644 index 000000000..f40c4149f --- /dev/null +++ b/apps/gbridge/gbridge-on-ico.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")) \ No newline at end of file diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index a787d7e0b..151dd3ad3 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -1,125 +1,247 @@ -(function() { - var musicState = "stop"; - var musicInfo = {"artist":"","album":"","track":""}; - var scrollPos = 0; - function gb(j) { - Bluetooth.println(JSON.stringify(j)); - } - function show(size,render) { - var oldMode = Bangle.getLCDMode(); - Bangle.setLCDMode("direct"); - g.setClipRect(0,240,239,319); - g.setColor("#222222"); - g.fillRect(1,241,238,318); - render(320-size); - g.setColor("#ffffff"); - g.fillRect(0,240,1,319); - g.fillRect(238,240,239,319); - g.fillRect(2,318,238,319); - Bangle.setLCDPower(1); // light up - Bangle.setLCDMode(oldMode); // clears cliprect - function anim() { - scrollPos-=2; - if (scrollPos<-size) scrollPos=-size; - Bangle.setLCDOffset(scrollPos); - if (scrollPos>-size) setTimeout(anim,10); - } - anim(); - } - function hide() { - function anim() { - scrollPos+=4; - if (scrollPos>0) scrollPos=0; - Bangle.setLCDOffset(scrollPos); - if (scrollPos<0) setTimeout(anim,10); - } - anim(); - } +(() => { - Bangle.on('touch',function() { - if (scrollPos) hide(); - }); - Bangle.on('swipe',function(dir) { - if (musicState=="play") { - gb({t:"music",n:dir>0?"next":"previous"}); - } - }); - gb({t:"status",bat:E.getBattery()}); + const gb = { + musicState: { + STOP: "stop", + PLAY: "play", + PAUSE: "pause" + }, - global.GB = function(j) { - switch (j.t) { - case "notify": - show(80,function(y) { - // TODO: icon based on src? - var x = 120; - g.setFontAlign(0,0); - g.setFont("6x8",1); - g.setColor("#40d040"); - g.drawString(j.src,x,y+7); - g.setColor("#ffffff"); - g.setFont("6x8",2); - g.drawString(j.title,x,y+25); - g.setFont("6x8",1); - g.setColor("#ffffff"); - // split text up a word boundaries - var txt = j.body.split("\n"); - var MAXCHARS = 38; - for (var i=0;iMAXCHARS) { - var p = MAXCHARS; - while (p>MAXCHARS-8 && !" \t-_".includes(l[p])) - p--; - if (p==MAXCHARS-8) p=MAXCHARS; - txt[i] = l.substr(0,p); - txt.splice(i+1,0,l.substr(p)); - } - } - g.setFontAlign(-1,-1); - g.drawString(txt.join("\n"),10,y+40); - Bangle.buzz(); - }); - break; - case "musicinfo": - musicInfo = j; - break; - case "musicstate": - musicState = j.state; - if (musicState=="play") - show(40,function(y) { - g.setColor("#ffffff"); - g.drawImage( require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")),8,y+8); - g.setFontAlign(-1,-1); - g.setFont("6x8",1); - var x = 40; - g.setFont("4x6",2); - g.setColor("#ffffff"); - g.drawString(musicInfo.artist,x,y+8); - g.setFont("6x8",1); - g.setColor("#ffffff"); - g.drawString(musicInfo.track,x,y+22); - }); - if (musicState=="pause") - hide(); - break; + muiscControl: { + NEXT: "next", + PREV: "previous" + }, + + callCommands: { + UNDEFINED: "undefined", + ACCEPT: "accept", + INCOMING: "incoming", + OUTGOING: "outgoing", + REJECT: "reject", + START: "start", + END: "end" + }, + + send: (message) => { + Bluetooth.println(JSON.stringify(message)); + }, + + controlMusic: (operation) => { + gb.send({ t: "music", n: operation }); + }, + + reportBatteryLevel: () => { + gb.send({ t: "status", bat: E.getBattery() }); + }, + }; + + const state = { + music: gb.musicState.STOP, + + musicInfo: { + artist: "", + album: "", + track: "" + }, + debug: false, + }; + + const notification = { + + backgroundColor: "#222222", + frameColor: "#ffffff", + titleColor: "#40d040", + contentColor: "#ffffff", + scrollPos: 0, + + show: (size, content) => { + var oldMode = Bangle.getLCDMode(); + Bangle.setLCDMode("direct"); + + g.setClipRect(0, 240, 239, 319); + g.setColor(notification.backgroundColor); + g.fillRect(1, 241, 238, 318); + + notification.drawContent(320 - size, content); + + g.setColor(notification.frameColor); + g.fillRect(0, 240, 1, 319); + g.fillRect(238, 240, 239, 319); + g.fillRect(2, 318, 238, 319); + + Bangle.setLCDPower(1); // light up + Bangle.setLCDMode(oldMode); // clears cliprect + + function anim() { + notification.scrollPos -= 2; + if (notification.scrollPos < -size) notification.scrollPos = -size; + Bangle.setLCDOffset(notification.scrollPos); + if (notification.scrollPos > -size) setTimeout(anim, 10); + } + anim(); + }, + + drawContent: (y, content) => { + + if (content.icon !== undefined) { + g.setColor(notification.contentColor); + const icon = require("Storage").read(content.icon); + g.drawImage(icon, 8, y + 8); + } + + var x = 120; + g.setFontAlign(0, 0); + + g.setFont("6x8", 1); + g.setColor(notification.titleColor); + g.drawString(content.title, x, y + 7); + + g.setColor(notification.contentColor); + g.setFont("6x8", 2); + g.drawString(content.header, x, y + 25); + + g.setFont("6x8", 1); + g.setColor(notification.contentColor); + g.setFontAlign(-1, -1); + g.drawString(content.body, 10, y + 40); + }, + + hide: () => { + function anim() { + notification.scrollPos += 4; + if (notification.scrollPos > 0) notification.scrollPos = 0; + Bangle.setLCDOffset(notification.scrollPos); + if (notification.scrollPos < 0) setTimeout(anim, 10); + } + anim(); + }, + + isVisible: () => { + return notification.scrollPos != 0; } }; -function draw() { - g.setColor(-1); - if (NRF.getSecurityStatus().connected) - g.drawImage(require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")),this.x+1,this.y+1); - else - g.drawImage(require("heatshrink").decompress(atob("i0WwQFC1WgAgYFDAgIFClQFCwEK1W/AoIPB1f+CAMq1f7/WqwQPB/fq1Gq1/+/4dC/2/CAIaB/YbBAAO///qAoX/B4QbBDQQ7BDQQrBAAWoIIIACIIIVC0ECB4cACAZiBAoRtCAoIDBA")),this.x+1,this.y+1); -} -function changed() { - WIDGETS["gbridgew"].draw(); - g.flip();// turns screen on -} -NRF.on('connected',changed); -NRF.on('disconnected',changed); + function showNotification(src, title, body) { -WIDGETS["gbridgew"]={area:"tl",width:24,draw:draw}; + // split text up at word boundaries + var txt = body.split("\n"); + var MAXCHARS = 38; + for (var i = 0; i < txt.length; i++) { + txt[i] = txt[i].trim(); + var l = txt[i]; + if (l.length > MAXCHARS) { + var p = MAXCHARS; + while (p > MAXCHARS - 8 && !" \t-_".includes(l[p])) + p--; + if (p == MAXCHARS - 8) p = MAXCHARS; + txt[i] = l.substr(0, p); + txt.splice(i + 1, 0, l.substr(p)); + } + } + var content = { + title: src, + header: title, + body: txt.join("\n") + }; + + notification.show(80, content); + Bangle.buzz(); + } + + function updateMusicInfo() { + if (state.music == gb.musicState.PLAY) { + + var content = { + title: "Now playing", + icon: "gbridge-music-ico.img", + header: state.musicInfo.artist, + body: state.musicInfo.track + }; + + notification.show(40, content); + } else { + notification.hide(); + } + } + + function handleCall(cmd, name, number) { + switch(cmd) { + + case gb.callCommands.ACCEPT: + notification.show(80, { + title: "Call incoming", + icon: "gbridge-call-ico.img", + header: name, + body: number + }); + Bangle.buzz(); + break; + + default: + if (state.debug) { + showNotification(cmd, name, number); + } + } + } + + global.GB = (event) => { + switch (event.t) { + case "notify": + showNotification(event.src, event.title, event.body); + break; + case "musicinfo": + state.musicInfo = event; + break; + case "musicstate": + state.musicInfo = event.state; + updateMusicInfo(); + break; + case "call": + handleCall(event.cmd, event.name, event.number); + break; + default: + if (state.debug) { + showNotification("Gadgetbridge", event.t, JSON.stringify(event)); + } + } + }; + + // Touch control + Bangle.on("touch", () => { + if (notification.isVisible()) { + notification.hide(); + } + }); + + Bangle.on("swipe", (dir) => { + if (state.music == gb.musicState.PLAY) { + gb.controlMusic(dir > 0 ? gb.muiscControl.NEXT : gb.muiscControl.PREV); + } + }); + + function drawIcon() { + g.setColor(-1); + + let icon; + if (NRF.getSecurityStatus().connected) { + icon = require("Storage").read("gbridge-on-ico.img"); + } else { + icon = require("Storage").read("gbridge-off-ico.img"); + } + + g.drawImage(icon, this.x + 1, this.y + 1); + } + + function changedConnectionState() { + WIDGETS["gbridgew"].draw(); + g.flip(); // turns screen on + } + + NRF.on("connected", changedConnectionState); + NRF.on("disconnected", changedConnectionState); + + WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: drawIcon }; + + gb.reportBatteryLevel(); })(); From 33a88627d9876ce48fe8d26ffa5d973289fe0c1a Mon Sep 17 00:00:00 2001 From: Simon Weis Date: Sat, 28 Mar 2020 13:30:13 +0100 Subject: [PATCH 0073/1189] Fix music notifications --- apps/gbridge/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 151dd3ad3..0b68d3e1b 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -153,10 +153,10 @@ if (state.music == gb.musicState.PLAY) { var content = { - title: "Now playing", + title: state.musicInfo.artist, icon: "gbridge-music-ico.img", - header: state.musicInfo.artist, - body: state.musicInfo.track + header: state.musicInfo.track, + body:"" }; notification.show(40, content); @@ -194,7 +194,7 @@ state.musicInfo = event; break; case "musicstate": - state.musicInfo = event.state; + state.music = event.state; updateMusicInfo(); break; case "call": From a6fab96de9e8bdf34bbff9d28fcaab4202d0f7e2 Mon Sep 17 00:00:00 2001 From: Oliver Sanders Date: Sat, 28 Mar 2020 22:13:51 +0000 Subject: [PATCH 0074/1189] Use localised month and day of the week from locale --- apps.json | 2 +- apps/dclock/ChangeLog | 3 ++- apps/dclock/clock-dev.js | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 4f29159cb..923ebfecd 100644 --- a/apps.json +++ b/apps.json @@ -511,7 +511,7 @@ { "id": "dclock", "name": "Dev Clock", "icon": "clock-dev.png", - "version":"0.08", + "version":"0.09", "description": "A Digital Clock including timestamp (tst), beats(@), days in current month (dm) and days since new moon (l)", "tags": "clock", "type":"clock", diff --git a/apps/dclock/ChangeLog b/apps/dclock/ChangeLog index 6582ec16e..edf7da4c2 100644 --- a/apps/dclock/ChangeLog +++ b/apps/dclock/ChangeLog @@ -5,4 +5,5 @@ 0.05: add beats (@) 0.06: tidy up 0.07: add days in current month (md) and days since new moon (l) -0.08: update icon \ No newline at end of file +0.08: update icon +0.09: Use localised month and day of the week from locale diff --git a/apps/dclock/clock-dev.js b/apps/dclock/clock-dev.js index 39f031fcc..d2c08726a 100644 --- a/apps/dclock/clock-dev.js +++ b/apps/dclock/clock-dev.js @@ -1,3 +1,4 @@ +var locale = require("locale"); /* jshint esversion: 6 */ const timeFontSize = 4; const dateFontSize = 3; @@ -83,7 +84,7 @@ function drawSimpleClock() { // draw Month name, Day of the week and beats var beats = Math.floor((((dutc[0] + 1) % 24) + dutc[1] / 60 + dutc[2] / 3600) * 1000 / 24); g.setFont(font, smallFontSize); - g.drawString(`m:${da[1]} d:${da[0]} @${beats}`, xyCenter, yposDayMonth, true); + g.drawString(`m:${locale.month(d,true)} d:${locale.dow(d,true)} @${beats}`, xyCenter, yposDayMonth, true); // draw gmt var gmt = da[5]; From e97852cae41f7b28fd9a7b1d86443b31ec900770 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Sun, 29 Mar 2020 02:48:21 +0000 Subject: [PATCH 0075/1189] Fixing issue #147 - No way to open launcher when no clock --- apps/boot/bootloader.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/boot/bootloader.js b/apps/boot/bootloader.js index febc4fc19..76d655671 100644 --- a/apps/boot/bootloader.js +++ b/apps/boot/bootloader.js @@ -12,7 +12,11 @@ if (!settings.welcomed && require("Storage").read("welcome.js")!==undefined) { clockApp = require("Storage").read(clockApps[0].src); delete clockApps; } - if (!clockApp) clockApp='E.showMessage("No Clock Found")'; + if (!clockApp) clockApp=`E.showMessage("No Clock Found"); + setWatch(() => { + Bangle.showLauncher(); + }, BTN2, {repeat:false,edge:"falling"});) + `; delete settings; // check to see if our clock is wrong - if it is use GPS time if ((new Date()).getFullYear()==1970) { From 0bfdb86fcb7a08edd20aeb2a3319b08a68b09b97 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:04:30 +0200 Subject: [PATCH 0076/1189] Fix remove unnecessary file and trim down App name --- apps.json | 2 +- apps/wohrm/.gitignore | 4 - apps/wohrm/app.js | 462 +++++++++++++++++++++--------------------- 3 files changed, 233 insertions(+), 235 deletions(-) delete mode 100644 apps/wohrm/.gitignore diff --git a/apps.json b/apps.json index 9f8b31f1d..e5b0ab15e 100644 --- a/apps.json +++ b/apps.json @@ -814,7 +814,7 @@ ] }, { "id": "wohrm", - "name": "Workout Heart Rate Monitor", + "name": "Workout HRM", "icon": "app.png", "version":"0.03", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", diff --git a/apps/wohrm/.gitignore b/apps/wohrm/.gitignore deleted file mode 100644 index 2060ed3f3..000000000 --- a/apps/wohrm/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/node_modules -/.eslintrc.js -/package.json -/package-lock.json \ No newline at end of file diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 75c51a578..8323779c9 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,160 +1,160 @@ -/* eslint-disable no-undef */ -const Setter = { - NONE: "none", - UPPER: 'upper', - LOWER: 'lower' -}; +// /* eslint-disable no-undef */ +// const Setter = { +// NONE: "none", +// UPPER: 'upper', +// LOWER: 'lower' +// }; -const shortBuzzTimeInMs = 50; -const longBuzzTimeInMs = 200; +// const shortBuzzTimeInMs = 50; +// const longBuzzTimeInMs = 200; -let upperLimit = 90; -let upperLimitChanged = true; +// let upperLimit = 90; +// let upperLimitChanged = true; -let lowerLimit = 50; -let lowerLimitChanged = true; +// let lowerLimit = 50; +// let lowerLimitChanged = true; -let limitSetter = Setter.NONE; +// let limitSetter = Setter.NONE; -let currentHeartRate = 0; -let hrConfidence = -1; -let hrOrConfidenceChanged = true; +// let currentHeartRate = 0; +// let hrConfidence = -1; +// let hrOrConfidenceChanged = true; -let setterHighlightTimeout; +// let setterHighlightTimeout; -function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); +// function renderUpperLimitBackground() { +// g.setColor(1,0,0); +// g.fillRect(125,40, 210, 70); +// g.fillRect(180,70, 210, 200); - //Round top left corner - g.fillEllipse(115,40,135,70); +// //Round top left corner +// g.fillEllipse(115,40,135,70); - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); +// //Round top right corner +// g.setColor(0,0,0); +// g.fillRect(205,40, 210, 45); +// g.setColor(1,0,0); +// g.fillEllipse(190,40,210,50); - //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); +// //Round inner corner +// g.fillRect(174,71, 179, 76); +// g.setColor(0,0,0); +// g.fillEllipse(160,71,179,82); - //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); -} +// //Round bottom +// g.setColor(1,0,0); +// g.fillEllipse(180,190, 210, 210); +// } -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); +// function renderLowerLimitBackground() { +// g.setColor(0,0,1); +// g.fillRect(10, 180, 100, 210); +// g.fillRect(10, 50, 40, 180); - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); +// //Rounded top +// g.setColor(0,0,1); +// g.fillEllipse(10,40, 40, 60); - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); +// //Round bottom right corner +// g.setColor(0,0,1); +// g.fillEllipse(90,180,110,210); - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); +// //Round inner corner +// g.setColor(0,0,1); +// g.fillRect(40,175,45,180); +// g.setColor(0,0,0); +// g.fillEllipse(41,170,60,179); - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); -} +// //Round bottom left corner +// g.setColor(0,0,0); +// g.fillRect(10,205, 15, 210); +// g.setColor(0,0,1); +// g.fillEllipse(10,200,30,210); +// } -function drawTrainingHeartRate() { - //Only redraw if the display is on - if (Bangle.isLCDOn()) { - renderButtonIcons(); +// function drawTrainingHeartRate() { +// //Only redraw if the display is on +// if (Bangle.isLCDOn()) { +// renderButtonIcons(); - renderUpperLimit(); +// renderUpperLimit(); - renderCurrentHeartRate(); +// renderCurrentHeartRate(); - renderLowerLimit(); +// renderLowerLimit(); - renderConfidenceBars(); - } +// renderConfidenceBars(); +// } - //buzz(); -} +// //buzz(); +// } -function renderUpperLimit() { - if(!upperLimitChanged) { return; } +// function renderUpperLimit() { +// if(!upperLimitChanged) { return; } - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); +// g.setColor(1,0,0); +// g.fillRect(125,40, 210, 70); - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Upper : " + upperLimit, 130,50); +// if(limitSetter === Setter.UPPER){ +// g.setColor(255,255, 0); +// } else { +// g.setColor(255,255,255); +// } +// g.setFontVector(13); +// g.drawString("Upper : " + upperLimit, 130,50); - upperLimitChanged = false; -} +// upperLimitChanged = false; +// } -function renderCurrentHeartRate() { - if(!hrOrConfidenceChanged) { return; } +// function renderCurrentHeartRate() { +// if(!hrOrConfidenceChanged) { return; } - g.setColor(255,255,255); - g.fillRect(45, 110, 165, 150); +// g.setColor(255,255,255); +// g.fillRect(45, 110, 165, 150); - g.setColor(0,0,0); - g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); +// g.setColor(0,0,0); +// g.setFontVector(24); +// g.setFontAlign(1, -1, 0); +// g.drawString(currentHeartRate, 130, 117); - //Reset alignment to defaults - g.setFontAlign(-1, -1, 0); -} +// //Reset alignment to defaults +// g.setFontAlign(-1, -1, 0); +// } -function renderLowerLimit() { - if(!lowerLimitChanged) { return; } +// function renderLowerLimit() { +// if(!lowerLimitChanged) { return; } - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); +// g.setColor(0,0,1); +// g.fillRect(10, 180, 100, 210); - if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Lower : " + lowerLimit, 20,190); +// if(limitSetter === Setter.LOWER){ +// g.setColor(255,255, 0); +// } else { +// g.setColor(255,255,255); +// } +// g.setFontVector(13); +// g.drawString("Lower : " + lowerLimit, 20,190); - lowerLimitChanged = false; -} +// lowerLimitChanged = false; +// } -function renderConfidenceBars(){ - if(!hrOrConfidenceChanged) { return; } +// function renderConfidenceBars(){ +// if(!hrOrConfidenceChanged) { return; } - if(hrConfidence >= 85){ - g.setColor(0, 255, 0); - } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); - } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); - } else { - g.setColor(255, 255, 255); - } +// if(hrConfidence >= 85){ +// g.setColor(0, 255, 0); +// } else if (hrConfidence >= 50) { +// g.setColor(255, 255, 0); +// } else if(hrConfidence >= 0){ +// g.setColor(255, 0, 0); +// } else { +// g.setColor(255, 255, 255); +// } - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); -} +// g.fillRect(45, 110, 55, 150); +// g.fillRect(165, 110, 175, 150); +// } function renderButtonIcons() { g.setColor(255,255,255); @@ -174,140 +174,142 @@ function renderButtonIcons() { g.drawString("-", 222,165); } -function buzz() -{ - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - } +// function buzz() +// { +// if(currentHeartRate > upperLimit) +// { +// Bangle.buzz(shortBuzzTimeInMs); +// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); +// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); +// } - if(currentHeartRate < lowerLimit) - { - Bangle.buzz(longBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); - } -} +// if(currentHeartRate < lowerLimit) +// { +// Bangle.buzz(longBuzzTimeInMs); +// setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); +// } +// } -function onHrm(hrm){ - hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); - currentHeartRate = hrm.bpm; - hrConfidence = hrm.confidence; -} +// function onHrm(hrm){ +// hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); +// currentHeartRate = hrm.bpm; +// hrConfidence = hrm.confidence; +// } -function setLimitSetterToLower() { - resetHighlightTimeout(); +// function setLimitSetterToLower() { +// resetHighlightTimeout(); - limitSetter = Setter.LOWER; - console.log("Limit setter is lower"); +// limitSetter = Setter.LOWER; +// console.log("Limit setter is lower"); - upperLimitChanged = true; - lowerLimitChanged = true; +// upperLimitChanged = true; +// lowerLimitChanged = true; - renderUpperLimit(); - renderLowerLimit(); -} +// renderUpperLimit(); +// renderLowerLimit(); +// } -function setLimitSetterToUpper() { - resetHighlightTimeout(); +// function setLimitSetterToUpper() { +// resetHighlightTimeout(); - limitSetter = Setter.UPPER; - console.log("Limit setter is upper"); +// limitSetter = Setter.UPPER; +// console.log("Limit setter is upper"); - upperLimitChanged = true; - lowerLimitChanged = true; +// upperLimitChanged = true; +// lowerLimitChanged = true; - renderLowerLimit(); - renderUpperLimit(); -} +// renderLowerLimit(); +// renderUpperLimit(); +// } -function setLimitSetterToNone() { - limitSetter = Setter.NONE; - console.log("Limit setter is none"); +// function setLimitSetterToNone() { +// limitSetter = Setter.NONE; +// console.log("Limit setter is none"); - upperLimitChanged = true; - lowerLimitChanged = true; +// upperLimitChanged = true; +// lowerLimitChanged = true; - renderLowerLimit(); - renderUpperLimit(); -} +// renderLowerLimit(); +// renderUpperLimit(); +// } -function incrementLimit(){ - resetHighlightTimeout(); +// function incrementLimit(){ +// resetHighlightTimeout(); - if (limitSetter === Setter.UPPER) { - upperLimit++; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit++; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - lowerLimitChanged = true; - } -} +// if (limitSetter === Setter.UPPER) { +// upperLimit++; +// renderUpperLimit(); +// console.log("Upper limit: " + upperLimit); +// upperLimitChanged = true; +// } else if(limitSetter === Setter.LOWER) { +// lowerLimit++; +// renderLowerLimit(); +// console.log("Lower limit: " + lowerLimit); +// lowerLimitChanged = true; +// } +// } -function decrementLimit(){ - resetHighlightTimeout(); +// function decrementLimit(){ +// resetHighlightTimeout(); - if (limitSetter === Setter.UPPER) { - upperLimit--; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit--; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - lowerLimitChanged = true; - } -} +// if (limitSetter === Setter.UPPER) { +// upperLimit--; +// renderUpperLimit(); +// console.log("Upper limit: " + upperLimit); +// upperLimitChanged = true; +// } else if(limitSetter === Setter.LOWER) { +// lowerLimit--; +// renderLowerLimit(); +// console.log("Lower limit: " + lowerLimit); +// lowerLimitChanged = true; +// } +// } -function resetHighlightTimeout() { - if (setterHighlightTimeout) { - clearTimeout(setterHighlightTimeout); - } +// function resetHighlightTimeout() { +// if (setterHighlightTimeout) { +// clearTimeout(setterHighlightTimeout); +// } - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -} +// setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +// } -// Show launcher when middle button pressed -function switchOffApp(){ - Bangle.setHRMPower(0); - Bangle.showLauncher(); -} +// // Show launcher when middle button pressed +// function switchOffApp(){ +// Bangle.setHRMPower(0); +// Bangle.showLauncher(); +// } -// special function to handle display switch on -Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - // call your app function here - renderLowerLimitBackground(); - renderUpperLimitBackground(); - lowerLimitChanged = true; - upperLimitChanged = true; - drawTrainingHeartRate(); - } -}); +// // special function to handle display switch on +// Bangle.on('lcdPower', (on) => { +// g.clear(); +// if (on) { +// Bangle.drawWidgets(); +// // call your app function here +// renderLowerLimitBackground(); +// renderUpperLimitBackground(); +// lowerLimitChanged = true; +// upperLimitChanged = true; +// drawTrainingHeartRate(); +// } +// }); -Bangle.setHRMPower(1); -Bangle.on('HRM', onHrm); +// Bangle.setHRMPower(1); +// Bangle.on('HRM', onHrm); -setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); +// setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); -setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); -//drawTrainingHeartRate(); +renderButtonIcons +// setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); +// setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); +// setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); -// refesh every sec -renderLowerLimitBackground(); -renderUpperLimitBackground(); -setInterval(drawTrainingHeartRate, 1000); +// g.clear(); +// Bangle.loadWidgets(); +// Bangle.drawWidgets(); +// //drawTrainingHeartRate(); + +// // refesh every sec +// renderLowerLimitBackground(); +// renderUpperLimitBackground(); +// setInterval(drawTrainingHeartRate, 1000); From df3935e390ed8492723e3a33d7809469799c379c Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:42:53 +0200 Subject: [PATCH 0077/1189] Icon file size reduced --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 36663d0ed..1bf4c808b 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("MDCI/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsK7u8HC/v7+/v7+/v7+/v7+/v7Cwbu7wsL+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7u7u7u7u7vI/v7+/v7+/v7Iu7u7u7u7u7u7u8n+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/ru7u7u7u7u7u7u7u7u7u7v+/v7+u7u7u7u7u7u7u7u7u7u7u/7+/v7+/v7+/v7+u7u7u7u7u7u7u7u7u7u7u7u7/v67u7u7u7u7u7u7u7u7u7u7u7v+/v7+/v7+/v67u7u7u7u7u7u7wci7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7/v7+/v7+/sm7u7u7u7u7u7u7wsm7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7yf7+/v7+/ru7u7u7u7u7u7u7ydC7u7u7u7u7u7u7u7u7u7u7u8LQ19DCu7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u70NfCu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u/7+/v7+wru7u7u7u7u7u7vC19fJu7u7u7u7u7u7u7u7u7u7u9fX19fXu7u7u7u7u8L+/v7+wru7u7u7u7u7u7vJ19fJu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u8L+/v7+u7u7u7u7u7u7u7vQ19fQu7u7u7u7u7u7u7u7u7u7u8nX19DCu7u7u7u7u7v+/v7+wbu7u7u7ybu7u7vX19DXwru7u7u7u7u7u7u7wcnQ19fX0Lu7u7u7u7u7u8H+/v7+wru7u7vC18K7u8LX0MnXybu7u7vCu7u7wc/Q19fX19fX18K7u7u7u7u7u8L+/v7+yLu7u7vJ18m7u8nXycnXybu7u7vJu7u7wtfX19DJydfX19C7u7u7u7u7u8j+/v7+/ru7u8HR19HBu9DXwsLX0Lu7u7vQu7u7wdfX0Lu70NfJ0NfJu7u7u7u7u/7+/v7+/ru7u8nX19fJwtfQu7vQ18K7u8LXu7u7u8HQ18LC19fBwtfXycm7u7u7u/7+/v7+/tDX19fXydfQydfJu7vJ18m7u8nXu7u7u7vBwrvQ18m7u9DX19e7u7u7yf7+/v7+/v7Q19fQu9DX0NfIu7vJ18m7u9DXu7u7u7u7u8HX18K7u8HJycm7u7u7/v7+/v7+/v7+u7u7u8nX19fBu7vC19C7wtfQu7u7u7u7u8nX0Lu7u7u7u7u7u7v+/v7+/v7+/v7+wru7u8HR19C7u7u70NfCz9fJu7u7wru7u9fX18nCu7u7u7u7u8L+/v7+/v7+/v7+/sG7u7vJ18m7u7u7ydfJ0dfBu8HC19C7yNfX19fX0MK7u7u7wf7+/v7+/v7+/v7+/v67u7vC18K7u7u7ydfQ19C7u7vB0NfQ0NfJws/X18G7u7u7/v7+/v7+/v7+/v7+/v7+u7u70Lu7u7u7wtfX18m7u7u7wdDX19e7u8LX18K7u7v+/v7+/v7+/v7+/v7+/v7+/ru7wbu7u7u7u9DX18G7u7u7u8HJ18m7wdDX0Lu7u/7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u8nX0Lu7u7u7u7u7wcG70NfQu7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+wbu7u7u7u8nXyLu7u7u7u7u7u7vJ19fCu7v+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sG7u7u7u8LXwbu7u7u7u7u7u8HX18K7wf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7Cu7u7u7vJu7u7u7u7u7u7u7vCybvC/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7vBu7u7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sm7u7u7u7u7u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsL+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/g==")) +var img=require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) From de603515073b5cc3e3060f89ba0f84d5d24985aa Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:44:53 +0200 Subject: [PATCH 0078/1189] Image icon code --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 1bf4c808b..1b30302b4 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -var img=require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) +var img = require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) From bcce90d36df407a1b7e2c57bfae288f63cd915ce Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:47:14 +0200 Subject: [PATCH 0079/1189] icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 1b30302b4..84799199d 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -var img = require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) +var img = E.toArrayBuffer(atob("MDCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqAAAACqoAAAAAAqqqqAACqqqoAAAACqqqqgAKqqqqAAAAKqqqqoAqqqqqgAAAqqqqqqCqqqqqoAACqqqqqqqqqqqqqAAKqqquqqqqqqqqqgAKqqq+qqqqqr+qqgAKqqq+qqqqqv/qqgAqqqq+qqqqqv/qqoAqqqr/qqqqqv/qqoAqqqr/qqqqqr+qqoAqq6r/qqqqr/6qqoAqq6r/qqqv//6qqoAqr+v76rqv//+qqoAKr+vr6rqv6//qqgAKv/vr6rqr6+v+qgAP//vr6vqqr+v+qwAD/v+q+vqqr6r+qAAAqv+q+vqqv6qqoAAAqr+q+/qqv+qqoAAAKr+q/+q+v/6qgAAACq6qv+q//v6qAAAAAq6qv6qv+r6oAAAAAKqqv6qr+v6gAAAAACqqv6qqq/qAAAAAAAqqrqqqr+oAAAAAAAKqrqqqr6gAAAAAAACqrqqqqqAAAAAAAAA6qqqqqoAAAAAAAAACqqqqqAAAAAAAAAAAqqqqoAAAAAAAAAAAOqqqgAAAAAAAAAAAAqqoAAAAAAAAAAAAACqwAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) From 5d98017fe7d1519a11ebfa68d2f3af031e6f87a3 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:50:15 +0200 Subject: [PATCH 0080/1189] Icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 84799199d..a95a3d4e0 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -var img = E.toArrayBuffer(atob("MDCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqAAAACqoAAAAAAqqqqAACqqqoAAAACqqqqgAKqqqqAAAAKqqqqoAqqqqqgAAAqqqqqqCqqqqqoAACqqqqqqqqqqqqqAAKqqquqqqqqqqqqgAKqqq+qqqqqr+qqgAKqqq+qqqqqv/qqgAqqqq+qqqqqv/qqoAqqqr/qqqqqv/qqoAqqqr/qqqqqr+qqoAqq6r/qqqqr/6qqoAqq6r/qqqv//6qqoAqr+v76rqv//+qqoAKr+vr6rqv6//qqgAKv/vr6rqr6+v+qgAP//vr6vqqr+v+qwAD/v+q+vqqr6r+qAAAqv+q+vqqv6qqoAAAqr+q+/qqv+qqoAAAKr+q/+q+v/6qgAAACq6qv+q//v6qAAAAAq6qv6qv+r6oAAAAAKqqv6qr+v6gAAAAACqqv6qqq/qAAAAAAAqqrqqqr+oAAAAAAAKqrqqqr6gAAAAAAACqrqqqqqAAAAAAAAA6qqqqqoAAAAAAAAACqqqqqAAAAAAAAAAAqqqqoAAAAAAAAAAAOqqqgAAAAAAAAAAAAqqoAAAAAAAAAAAAACqwAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) +require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) \ No newline at end of file From 94f89db572c529f3e5f2d7e1904049085d6dd624 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:51:49 +0200 Subject: [PATCH 0081/1189] Icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index a95a3d4e0..5a57c6cb1 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) From e23c1ad2e508bd97c0c71ebe315a78cdf4b1dca7 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:53:33 +0200 Subject: [PATCH 0082/1189] Icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 5a57c6cb1..a7f67291e 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) +require("heatshrink").decompress(atob("mEwwhC/AH4AWzIAByAHDhIICCpINDDAgIIFpAADBBQuKE4QIIFxgAKC7g9HABSbIBQQXWGxgXEKQxOMC5AhBC66WMC5AuBJ5h3ICoI3LeAwKBBAICBD4TmHC48ACgQCCfxC/HAgYXDL44vFA4YRDAoiOIHAgXFYRAXFBwwIIOw4OGIxKmIC5ylHGAoXIXpBIGLxxIIIx6IJFxwwNCxQwLFxYwLCxgwJFxowJCxwwHFx4wHCyAwFFyIwFCyQYDCygA/AH4AFA")) \ No newline at end of file From 01483303766627054448bb88f215e944aa44515e Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:56:11 +0200 Subject: [PATCH 0083/1189] Uncomment app code again --- apps/wohrm/app.js | 468 +++++++++++++++++++++++----------------------- 1 file changed, 233 insertions(+), 235 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 8323779c9..cc5dbc286 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,315 +1,313 @@ -// /* eslint-disable no-undef */ -// const Setter = { -// NONE: "none", -// UPPER: 'upper', -// LOWER: 'lower' -// }; +/* eslint-disable no-undef */ +const Setter = { + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' +}; -// const shortBuzzTimeInMs = 50; -// const longBuzzTimeInMs = 200; +const shortBuzzTimeInMs = 50; +const longBuzzTimeInMs = 200; -// let upperLimit = 90; -// let upperLimitChanged = true; +let upperLimit = 90; +let upperLimitChanged = true; -// let lowerLimit = 50; -// let lowerLimitChanged = true; +let lowerLimit = 50; +let lowerLimitChanged = true; -// let limitSetter = Setter.NONE; +let limitSetter = Setter.NONE; -// let currentHeartRate = 0; -// let hrConfidence = -1; -// let hrOrConfidenceChanged = true; +let currentHeartRate = 0; +let hrConfidence = -1; +let hrOrConfidenceChanged = true; -// let setterHighlightTimeout; +let setterHighlightTimeout; -// function renderUpperLimitBackground() { -// g.setColor(1,0,0); -// g.fillRect(125,40, 210, 70); -// g.fillRect(180,70, 210, 200); +function renderUpperLimitBackground() { + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); -// //Round top left corner -// g.fillEllipse(115,40,135,70); + //Round top left corner + g.fillEllipse(115,40,135,70); -// //Round top right corner -// g.setColor(0,0,0); -// g.fillRect(205,40, 210, 45); -// g.setColor(1,0,0); -// g.fillEllipse(190,40,210,50); + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(1,0,0); + g.fillEllipse(190,40,210,50); -// //Round inner corner -// g.fillRect(174,71, 179, 76); -// g.setColor(0,0,0); -// g.fillEllipse(160,71,179,82); + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); -// //Round bottom -// g.setColor(1,0,0); -// g.fillEllipse(180,190, 210, 210); -// } + //Round bottom + g.setColor(1,0,0); + g.fillEllipse(180,190, 210, 210); +} -// function renderLowerLimitBackground() { -// g.setColor(0,0,1); -// g.fillRect(10, 180, 100, 210); -// g.fillRect(10, 50, 40, 180); +function renderLowerLimitBackground() { + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); -// //Rounded top -// g.setColor(0,0,1); -// g.fillEllipse(10,40, 40, 60); + //Rounded top + g.setColor(0,0,1); + g.fillEllipse(10,40, 40, 60); -// //Round bottom right corner -// g.setColor(0,0,1); -// g.fillEllipse(90,180,110,210); + //Round bottom right corner + g.setColor(0,0,1); + g.fillEllipse(90,180,110,210); -// //Round inner corner -// g.setColor(0,0,1); -// g.fillRect(40,175,45,180); -// g.setColor(0,0,0); -// g.fillEllipse(41,170,60,179); + //Round inner corner + g.setColor(0,0,1); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); -// //Round bottom left corner -// g.setColor(0,0,0); -// g.fillRect(10,205, 15, 210); -// g.setColor(0,0,1); -// g.fillEllipse(10,200,30,210); -// } + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,1); + g.fillEllipse(10,200,30,210); +} -// function drawTrainingHeartRate() { -// //Only redraw if the display is on -// if (Bangle.isLCDOn()) { -// renderButtonIcons(); +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderButtonIcons(); -// renderUpperLimit(); + renderUpperLimit(); -// renderCurrentHeartRate(); + renderCurrentHeartRate(); -// renderLowerLimit(); + renderLowerLimit(); -// renderConfidenceBars(); -// } + renderConfidenceBars(); + } -// //buzz(); -// } + //buzz(); +} -// function renderUpperLimit() { -// if(!upperLimitChanged) { return; } +function renderUpperLimit() { + if(!upperLimitChanged) { return; } -// g.setColor(1,0,0); -// g.fillRect(125,40, 210, 70); + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); -// if(limitSetter === Setter.UPPER){ -// g.setColor(255,255, 0); -// } else { -// g.setColor(255,255,255); -// } -// g.setFontVector(13); -// g.drawString("Upper : " + upperLimit, 130,50); + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Upper : " + upperLimit, 130,50); -// upperLimitChanged = false; -// } + upperLimitChanged = false; +} -// function renderCurrentHeartRate() { -// if(!hrOrConfidenceChanged) { return; } +function renderCurrentHeartRate() { + if(!hrOrConfidenceChanged) { return; } -// g.setColor(255,255,255); -// g.fillRect(45, 110, 165, 150); + g.setColor(255,255,255); + g.fillRect(45, 110, 165, 150); -// g.setColor(0,0,0); -// g.setFontVector(24); -// g.setFontAlign(1, -1, 0); -// g.drawString(currentHeartRate, 130, 117); + g.setColor(0,0,0); + g.setFontVector(24); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 130, 117); -// //Reset alignment to defaults -// g.setFontAlign(-1, -1, 0); -// } + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); +} -// function renderLowerLimit() { -// if(!lowerLimitChanged) { return; } +function renderLowerLimit() { + if(!lowerLimitChanged) { return; } -// g.setColor(0,0,1); -// g.fillRect(10, 180, 100, 210); + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); -// if(limitSetter === Setter.LOWER){ -// g.setColor(255,255, 0); -// } else { -// g.setColor(255,255,255); -// } -// g.setFontVector(13); -// g.drawString("Lower : " + lowerLimit, 20,190); + if(limitSetter === Setter.LOWER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Lower : " + lowerLimit, 20,190); -// lowerLimitChanged = false; -// } + lowerLimitChanged = false; +} -// function renderConfidenceBars(){ -// if(!hrOrConfidenceChanged) { return; } +function renderConfidenceBars(){ + if(!hrOrConfidenceChanged) { return; } -// if(hrConfidence >= 85){ -// g.setColor(0, 255, 0); -// } else if (hrConfidence >= 50) { -// g.setColor(255, 255, 0); -// } else if(hrConfidence >= 0){ -// g.setColor(255, 0, 0); -// } else { -// g.setColor(255, 255, 255); -// } + if(hrConfidence >= 85){ + g.setColor(0, 255, 0); + } else if (hrConfidence >= 50) { + g.setColor(255, 255, 0); + } else if(hrConfidence >= 0){ + g.setColor(255, 0, 0); + } else { + g.setColor(255, 255, 255); + } -// g.fillRect(45, 110, 55, 150); -// g.fillRect(165, 110, 175, 150); -// } + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); +} function renderButtonIcons() { g.setColor(255,255,255); g.setFontVector(14); - // + for Btn1 + //+ for Btn1 g.drawString("+", 222,50); - // Home for Btn2 + //Home for Btn2 g.drawLine(220, 118, 227, 110); g.drawLine(227, 110, 234, 118); g.drawPoly([222,117,222,125,232,125,232,117], false); g.drawRect(226,120,229,125); - // - for Btn3 + //- for Btn3 g.drawString("-", 222,165); } -// function buzz() -// { -// if(currentHeartRate > upperLimit) -// { -// Bangle.buzz(shortBuzzTimeInMs); -// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); -// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); -// } +function buzz() +{ + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + } -// if(currentHeartRate < lowerLimit) -// { -// Bangle.buzz(longBuzzTimeInMs); -// setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); -// } -// } + if(currentHeartRate < lowerLimit) + { + Bangle.buzz(longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); + } +} -// function onHrm(hrm){ -// hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); -// currentHeartRate = hrm.bpm; -// hrConfidence = hrm.confidence; -// } +function onHrm(hrm){ + hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); + currentHeartRate = hrm.bpm; + hrConfidence = hrm.confidence; +} -// function setLimitSetterToLower() { -// resetHighlightTimeout(); +function setLimitSetterToLower() { + resetHighlightTimeout(); -// limitSetter = Setter.LOWER; -// console.log("Limit setter is lower"); + limitSetter = Setter.LOWER; + console.log("Limit setter is lower"); -// upperLimitChanged = true; -// lowerLimitChanged = true; + upperLimitChanged = true; + lowerLimitChanged = true; -// renderUpperLimit(); -// renderLowerLimit(); -// } + renderUpperLimit(); + renderLowerLimit(); +} -// function setLimitSetterToUpper() { -// resetHighlightTimeout(); +function setLimitSetterToUpper() { + resetHighlightTimeout(); -// limitSetter = Setter.UPPER; -// console.log("Limit setter is upper"); + limitSetter = Setter.UPPER; + console.log("Limit setter is upper"); -// upperLimitChanged = true; -// lowerLimitChanged = true; + upperLimitChanged = true; + lowerLimitChanged = true; -// renderLowerLimit(); -// renderUpperLimit(); -// } + renderLowerLimit(); + renderUpperLimit(); +} -// function setLimitSetterToNone() { -// limitSetter = Setter.NONE; -// console.log("Limit setter is none"); +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + console.log("Limit setter is none"); -// upperLimitChanged = true; -// lowerLimitChanged = true; + upperLimitChanged = true; + lowerLimitChanged = true; -// renderLowerLimit(); -// renderUpperLimit(); -// } + renderLowerLimit(); + renderUpperLimit(); +} -// function incrementLimit(){ -// resetHighlightTimeout(); +function incrementLimit(){ + resetHighlightTimeout(); -// if (limitSetter === Setter.UPPER) { -// upperLimit++; -// renderUpperLimit(); -// console.log("Upper limit: " + upperLimit); -// upperLimitChanged = true; -// } else if(limitSetter === Setter.LOWER) { -// lowerLimit++; -// renderLowerLimit(); -// console.log("Lower limit: " + lowerLimit); -// lowerLimitChanged = true; -// } -// } + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; + } +} -// function decrementLimit(){ -// resetHighlightTimeout(); +function decrementLimit(){ + resetHighlightTimeout(); -// if (limitSetter === Setter.UPPER) { -// upperLimit--; -// renderUpperLimit(); -// console.log("Upper limit: " + upperLimit); -// upperLimitChanged = true; -// } else if(limitSetter === Setter.LOWER) { -// lowerLimit--; -// renderLowerLimit(); -// console.log("Lower limit: " + lowerLimit); -// lowerLimitChanged = true; -// } -// } + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; + } +} -// function resetHighlightTimeout() { -// if (setterHighlightTimeout) { -// clearTimeout(setterHighlightTimeout); -// } +function resetHighlightTimeout() { + if (setterHighlightTimeout) { + clearTimeout(setterHighlightTimeout); + } -// setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -// } + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +} -// // Show launcher when middle button pressed -// function switchOffApp(){ -// Bangle.setHRMPower(0); -// Bangle.showLauncher(); -// } +// Show launcher when middle button pressed +function switchOffApp(){ + Bangle.setHRMPower(0); + Bangle.showLauncher(); +} -// // special function to handle display switch on -// Bangle.on('lcdPower', (on) => { -// g.clear(); -// if (on) { -// Bangle.drawWidgets(); -// // call your app function here -// renderLowerLimitBackground(); -// renderUpperLimitBackground(); -// lowerLimitChanged = true; -// upperLimitChanged = true; -// drawTrainingHeartRate(); -// } -// }); +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + // call your app function here + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; + drawTrainingHeartRate(); + } +}); -// Bangle.setHRMPower(1); -// Bangle.on('HRM', onHrm); +Bangle.setHRMPower(1); +Bangle.on('HRM', onHrm); -// setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); +setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); +setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); +setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); +setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); -renderButtonIcons -// setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); -// setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); -// setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +//drawTrainingHeartRate(); -// g.clear(); -// Bangle.loadWidgets(); -// Bangle.drawWidgets(); -// //drawTrainingHeartRate(); - -// // refesh every sec -// renderLowerLimitBackground(); -// renderUpperLimitBackground(); -// setInterval(drawTrainingHeartRate, 1000); +// refesh every sec +renderLowerLimitBackground(); +renderUpperLimitBackground(); +setInterval(drawTrainingHeartRate, 1000); From 21b1eaa4237d8a982f589e06373b8497023fb545 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:02:21 +0200 Subject: [PATCH 0084/1189] Fixes eventhandler for BTN2 --- apps/wohrm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index cc5dbc286..f077a9feb 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -297,7 +297,7 @@ Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); +setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true,}); setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); From 7774b095b974e72ba2c979fd45352f37012f167c Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:05:23 +0200 Subject: [PATCH 0085/1189] BTN2 handler --- apps/wohrm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f077a9feb..ec048c8a1 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -297,7 +297,7 @@ Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true,}); +setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true}); setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); From 5507eb04be552a801699f388ff72a8b552e7acd0 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:20:26 +0200 Subject: [PATCH 0086/1189] Only buzz on high confidence --- apps.json | 2 +- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 44 ++++++++++++++++++++++++++++++++------------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/apps.json b/apps.json index e5b0ab15e..93fa75524 100644 --- a/apps.json +++ b/apps.json @@ -816,7 +816,7 @@ { "id": "wohrm", "name": "Workout HRM", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 36c08b9fd..f836f6f71 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -1,3 +1,4 @@ +0.04: Only buzz on high confidence (>85%) 0.03: Optimized rendering for the background 0.02: Adapted to new App code layout 0.01: Only tested on the emulator. diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ec048c8a1..2e147251c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,6 +4,10 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; + +const Confidence = { + NONE +} const shortBuzzTimeInMs = 50; const longBuzzTimeInMs = 200; @@ -18,8 +22,8 @@ let limitSetter = Setter.NONE; let currentHeartRate = 0; let hrConfidence = -1; -let hrOrConfidenceChanged = true; - +let hrChanged = true; +let confidenceChanged = true; let setterHighlightTimeout; @@ -76,7 +80,7 @@ function renderLowerLimitBackground() { function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { - renderButtonIcons(); + renderUpperLimit(); @@ -108,7 +112,7 @@ function renderUpperLimit() { } function renderCurrentHeartRate() { - if(!hrOrConfidenceChanged) { return; } + if(!hrChanged) { return; } g.setColor(255,255,255); g.fillRect(45, 110, 165, 150); @@ -120,6 +124,8 @@ function renderCurrentHeartRate() { //Reset alignment to defaults g.setFontAlign(-1, -1, 0); + + hrChanged = false; } function renderLowerLimit() { @@ -140,7 +146,7 @@ function renderLowerLimit() { } function renderConfidenceBars(){ - if(!hrOrConfidenceChanged) { return; } + if(!confidenceChanged) { return; } if(hrConfidence >= 85){ g.setColor(0, 255, 0); @@ -154,6 +160,8 @@ function renderConfidenceBars(){ g.fillRect(45, 110, 55, 150); g.fillRect(165, 110, 175, 150); + + confidenceChanged = false; } function renderButtonIcons() { @@ -176,24 +184,33 @@ function renderButtonIcons() { function buzz() { + // Do not buzz if not confident + if(hrConfidence < 85) { return; } + if(currentHeartRate > upperLimit) { Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs+10); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs+10); } if(currentHeartRate < lowerLimit) { Bangle.buzz(longBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs+10); } } function onHrm(hrm){ - hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); - currentHeartRate = hrm.bpm; - hrConfidence = hrm.confidence; + if(currentHeartRate !== hrm.bpm){ + currentHeartRate = hrm.bpm; + hrChanged = true; + } + + if(hrConfidence !== hrm.confidence) { + hrConfidence = hrm.confidence; + confidenceChanged = true; + } } function setLimitSetterToLower() { @@ -284,6 +301,7 @@ Bangle.on('lcdPower', (on) => { g.clear(); if (on) { Bangle.drawWidgets(); + renderButtonIcons(); // call your app function here renderLowerLimitBackground(); renderUpperLimitBackground(); @@ -307,7 +325,9 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); //drawTrainingHeartRate(); -// refesh every sec +renderButtonIcons(); renderLowerLimitBackground(); renderUpperLimitBackground(); + +// refesh every sec setInterval(drawTrainingHeartRate, 1000); From 18abff1d2f68ad7b78a3d189ed4c4cf258063e8d Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:22:36 +0200 Subject: [PATCH 0087/1189] Stupid coding error fixed --- apps/wohrm/app.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 2e147251c..979a50205 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,10 +4,6 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; - -const Confidence = { - NONE -} const shortBuzzTimeInMs = 50; const longBuzzTimeInMs = 200; From d273d8860b35cacc4792bd0f64fe2e4f964cff09 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:33:52 +0200 Subject: [PATCH 0088/1189] Re-enable buzzing --- apps/wohrm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 979a50205..dff69d76b 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -87,7 +87,7 @@ function drawTrainingHeartRate() { renderConfidenceBars(); } - //buzz(); + buzz(); } function renderUpperLimit() { From f746b0c67cc3729542a4bbc42c026e6de16ea3ce Mon Sep 17 00:00:00 2001 From: MaBecker Date: Sun, 29 Mar 2020 18:52:10 +0200 Subject: [PATCH 0089/1189] add widget version --- apps.json | 11 +++++++++++ apps/widver/ChangeLog | 1 + apps/widver/widget.js | 11 +++++++++++ apps/widver/widget.png | Bin 0 -> 344 bytes 4 files changed, 23 insertions(+) create mode 100644 apps/widver/ChangeLog create mode 100644 apps/widver/widget.js create mode 100644 apps/widver/widget.png diff --git a/apps.json b/apps.json index 15acb3b20..12903f95d 100644 --- a/apps.json +++ b/apps.json @@ -836,5 +836,16 @@ {"name":"marioclock.app.js","url":"marioclock-app.js"}, {"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true} ] + }, + { "id": "widver", + "name": "Firmware Version Widget", + "icon": "widget.png", + "version":"0.01", + "description": "Display the version of the installed firmware in the top widget section.", + "tags": "widget,tool,system", + "type":"widget", + "storage": [ + {"name":"widver.wid.js","url":"widget.js"} + ] } ] diff --git a/apps/widver/ChangeLog b/apps/widver/ChangeLog new file mode 100644 index 000000000..adb5b038a --- /dev/null +++ b/apps/widver/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget diff --git a/apps/widver/widget.js b/apps/widver/widget.js new file mode 100644 index 000000000..b5edfc08c --- /dev/null +++ b/apps/widver/widget.js @@ -0,0 +1,11 @@ +/* jshint esversion: 6 */ +(() => { + var width = 28, + ver = process.env.VERSION.split('.'); + function draw() { + g.reset().setColor(0, 0.5, 1).setFont("6x8", 1); + g.drawString(ver[0], this.x + 2, this.y + 4, true); + g.setFontAlign(0, -1, 0).drawString(ver[1], this.x + width / 2, this.y + 14, true); + } + WIDGETS["version"] = { area: "tr", width: width, draw: draw }; +})(); diff --git a/apps/widver/widget.png b/apps/widver/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..72e646a30471367725c001956df1274def0dafdc GIT binary patch literal 344 zcmV-e0jK_nP)Jw!7z!$$Z#QY4ycoKvLXQhXuA$3 z8cA3q0O(0%=HA=f%x)9|Qi;zv`9T<=Xq>D{AVnn!D+Pf6C9D+yekHQb=-+)MvOmY# zwN@wa4-}Aw0@6@G8VX250cj{84F#m3fHV}4Ci9>8y6$GK90vufMJXzuK;;FL)+&dk qm%GiLn?7)8QuzcbFF*((vb+J73rQEfJXV?z* literal 0 HcmV?d00001 From 441d5d1882c304b5fbfba430fac92a23d3891267 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 30 Mar 2020 08:39:59 +0100 Subject: [PATCH 0090/1189] bump version --- apps.json | 2 +- apps/boot/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 15acb3b20..27dc2b2e0 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "boot", "name": "Bootloader", "icon": "bootloader.png", - "version":"0.11", + "version":"0.12", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "tags": "tool,system", "type":"bootloader", diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index 3bd9ec71c..93f03b8ad 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -9,3 +9,4 @@ 0.10: Stop users calling save() (fix #125) If Debug info is set to 'show' don't move to Terminal if connected! 0.11: Added vibrate as beep workaround +0.12: Add an event on BTN2 to open launcher when no clock detected (fix #147) From c776cc9222154264dc31b7dee77105f52455ec9a Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:25:40 +0200 Subject: [PATCH 0091/1189] Update app.js --- apps/pipboy/app.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/apps/pipboy/app.js b/apps/pipboy/app.js index 050fd366b..48a87fc5d 100644 --- a/apps/pipboy/app.js +++ b/apps/pipboy/app.js @@ -29,17 +29,23 @@ function topLine() { function bottomLine() { - g.setColor(darkGreen); - g.fillRect(5, 175, 60, 185); - g.fillRect(67, 175, 140, 185); + //first line + g.setColor(darkerGreen); + g.fillRect(5, 175, 100, 185); //DATE + g.fillRect(105, 175, 160, 185);//STIM + g.fillRect(166, 175, 239, 185); // RADAWAY + g.setColor(green); + g.setFont("6x8", tinyFont); + g.drawString("DATE", 20, 177); + g.drawString("STIM (3)", 135, 177); + g.drawString("RADAWAY (8)", 205, 177); + + //second line g.setColor(darkerGreen); g.fillRect(5, 190, 70, 200); g.fillRect(75, 190, 239, 200); - g.setFont("6x8", tinyFont); - g.drawString("STIM (0)", 32, 177); - g.drawString("RADAWAY (0)", 105, 177); g.setColor(green); g.drawString("HP 115/115", 38, 192); g.drawString("LEVEL 6", 100, 192); @@ -55,7 +61,15 @@ function drawClock() { var t = new Date(); var h = t.getHours(); var m = t.getMinutes(); + var dd = t.getDate(); + var mm = t.getMonth()+1; //month is zero-based + var yy = t.getFullYear(); var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); + + //create date string + if (dd.toString().length < 2) dd = '0' + dd; + if (mm.toString().length < 2) mm = '0' + mm; + var date = dd + "." + mm + "." + yy; g.setFont("6x8",bigFont); g.setColor(green); @@ -63,6 +77,10 @@ function drawClock() { g.clearRect(0, 110, 150, 140); g.drawString(time, 70, 110); + + //draw date + g.setFont("6x8", tinyFont); + g.drawString(date, 67, 177); } function drawAll() { @@ -83,4 +101,3 @@ setInterval(drawClock, 1E4); drawAll(); setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); - From 5399f1577023e420ac5d9718d8e281b9add83d5c Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:28:28 +0200 Subject: [PATCH 0092/1189] Create app.js --- apps/pipboydate/app.js | 103 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 apps/pipboydate/app.js diff --git a/apps/pipboydate/app.js b/apps/pipboydate/app.js new file mode 100644 index 000000000..48a87fc5d --- /dev/null +++ b/apps/pipboydate/app.js @@ -0,0 +1,103 @@ +const bigFont = 4; +const smallFont = 2; +const tinyFont = 1; +const green = 0x0661; +const darkGreen = 0x0461; +const darkerGreen = 0x0261; +const pip = require("heatshrink").decompress(atob("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")); + +function topLine() { + + g.setColor(green); + g.setFontAlign(0, -1, 0); + + g.moveTo(0, 50).lineTo(30, 50); + g.lineTo(30, 40); + g.lineTo(35, 40).moveTo(90, 40).lineTo(95, 40); + g.lineTo(95, 50); + g.lineTo(239, 50); + + g.setFont("6x8", smallFont); + g.drawString("STAT", 65, 34); + g.drawString("INV", 130, 34); + g.drawString("DATA", 190, 34); + g.setColor(darkGreen); + g.drawString("STATUS", 45, 55); + g.drawString("SPEC", 122, 55); + g.drawString("PERKS", 195, 55); +} + +function bottomLine() { + + //first line + g.setColor(darkerGreen); + g.fillRect(5, 175, 100, 185); //DATE + g.fillRect(105, 175, 160, 185);//STIM + g.fillRect(166, 175, 239, 185); // RADAWAY + + g.setColor(green); + g.setFont("6x8", tinyFont); + g.drawString("DATE", 20, 177); + g.drawString("STIM (3)", 135, 177); + g.drawString("RADAWAY (8)", 205, 177); + + //second line + g.setColor(darkerGreen); + g.fillRect(5, 190, 70, 200); + g.fillRect(75, 190, 239, 200); + + g.setColor(green); + g.drawString("HP 115/115", 38, 192); + g.drawString("LEVEL 6", 100, 192); + g.drawRect(127, 192, 235, 198); +} + +function boy() { + g.drawImage(pip, 165, 85); +} + +function drawClock() { + + var t = new Date(); + var h = t.getHours(); + var m = t.getMinutes(); + var dd = t.getDate(); + var mm = t.getMonth()+1; //month is zero-based + var yy = t.getFullYear(); + var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); + + //create date string + if (dd.toString().length < 2) dd = '0' + dd; + if (mm.toString().length < 2) mm = '0' + mm; + var date = dd + "." + mm + "." + yy; + + g.setFont("6x8",bigFont); + g.setColor(green); + g.setFontAlign(0, -1, 0); + + g.clearRect(0, 110, 150, 140); + g.drawString(time, 70, 110); + + //draw date + g.setFont("6x8", tinyFont); + g.drawString(date, 67, 177); +} + +function drawAll() { + topLine(); + boy(); + bottomLine(); + drawClock(); +} + +Bangle.on('lcdPower', function(on) { + if (on) drawAll(); +}); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +setInterval(drawClock, 1E4); +drawAll(); + +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); From 0c6c6eb61ede29c151cec25bbae69f64a062a7d6 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:34:58 +0200 Subject: [PATCH 0093/1189] Create app-icon.js --- apps/pipboydate/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/pipboydate/app-icon.js diff --git a/apps/pipboydate/app-icon.js b/apps/pipboydate/app-icon.js new file mode 100644 index 000000000..935210156 --- /dev/null +++ b/apps/pipboydate/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AC4fDDjAuSgwACGFIuBhgACGAJjmLoQvDGAJkhbAguGGYwxbRAoAMGDZZMGBAvSbIpdSGCxYCW5jpDHhKSRDYQgGAwY8ETZYvPDZBXEAAwUFNAowOF44bFNJI2ENISRQdIqzLYhAxDAoRgScZgwFdow1DF54tQdpRMDF5jjHLiDxWF44wJBZIJFF5qPGF5blDLxIvPeAjsOF7RgCc6QvId6AvUd5QACF5pyEKAwlGF5qORcIwoFBgIwHFwwvTU4gvILxYuOXwouKA5AwGFxzuIDYYvkDQ6GIABKqEL6ryGF8QbHF6QXFX6wvuYIQvnFJgMBAAQva/wgMBQT4CF5QPCeB65CABgwCHxYuOF6L5JHYYuPSAyDFBRS6TMA4AME4RdHFyhgCLRLoJLzBgDExa7JFywwVFzQwTFwIADGDC5NRohDBSTQdCGCARCGDRNCGRQuFSobAYGAYxIFwoTDGKpMGWggADA4Q1FYipNGGA7NHYawVBD44qDGIbEHIwwlEA=")) From 6570eb499ea201877c8b0a0510432e569e7d9610 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:35:47 +0200 Subject: [PATCH 0094/1189] Add files via upload --- apps/pipboydate/app.png | Bin 0 -> 12431 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/pipboydate/app.png diff --git a/apps/pipboydate/app.png b/apps/pipboydate/app.png new file mode 100644 index 0000000000000000000000000000000000000000..018b5c7bb8dd8a8a0dcba32fa0450695d92bd67f GIT binary patch literal 12431 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

1C}EjuiQ{0X5=O(KG|og0RysElDc~s4(SYrSm4` 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 N002ovPDHLkV1jo{v#J09 literal 0 HcmV?d00001 From 0aa9374ecb0e018f7d3cd10f4db7722c196253cd Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:45:27 +0200 Subject: [PATCH 0095/1189] Delete app-icon.js --- apps/pipboydate/app-icon.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/pipboydate/app-icon.js diff --git a/apps/pipboydate/app-icon.js b/apps/pipboydate/app-icon.js deleted file mode 100644 index 935210156..000000000 --- a/apps/pipboydate/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEwxH+AC4fDDjAuSgwACGFIuBhgACGAJjmLoQvDGAJkhbAguGGYwxbRAoAMGDZZMGBAvSbIpdSGCxYCW5jpDHhKSRDYQgGAwY8ETZYvPDZBXEAAwUFNAowOF44bFNJI2ENISRQdIqzLYhAxDAoRgScZgwFdow1DF54tQdpRMDF5jjHLiDxWF44wJBZIJFF5qPGF5blDLxIvPeAjsOF7RgCc6QvId6AvUd5QACF5pyEKAwlGF5qORcIwoFBgIwHFwwvTU4gvILxYuOXwouKA5AwGFxzuIDYYvkDQ6GIABKqEL6ryGF8QbHF6QXFX6wvuYIQvnFJgMBAAQva/wgMBQT4CF5QPCeB65CABgwCHxYuOF6L5JHYYuPSAyDFBRS6TMA4AME4RdHFyhgCLRLoJLzBgDExa7JFywwVFzQwTFwIADGDC5NRohDBSTQdCGCARCGDRNCGRQuFSobAYGAYxIFwoTDGKpMGWggADA4Q1FYipNGGA7NHYawVBD44qDGIbEHIwwlEA=")) From 0f73a3aa0f8a3d6b05d3b301b69e86567c49fa41 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:45:35 +0200 Subject: [PATCH 0096/1189] Delete app.js --- apps/pipboydate/app.js | 103 ----------------------------------------- 1 file changed, 103 deletions(-) delete mode 100644 apps/pipboydate/app.js diff --git a/apps/pipboydate/app.js b/apps/pipboydate/app.js deleted file mode 100644 index 48a87fc5d..000000000 --- a/apps/pipboydate/app.js +++ /dev/null @@ -1,103 +0,0 @@ -const bigFont = 4; -const smallFont = 2; -const tinyFont = 1; -const green = 0x0661; -const darkGreen = 0x0461; -const darkerGreen = 0x0261; -const pip = require("heatshrink").decompress(atob("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")); - -function topLine() { - - g.setColor(green); - g.setFontAlign(0, -1, 0); - - g.moveTo(0, 50).lineTo(30, 50); - g.lineTo(30, 40); - g.lineTo(35, 40).moveTo(90, 40).lineTo(95, 40); - g.lineTo(95, 50); - g.lineTo(239, 50); - - g.setFont("6x8", smallFont); - g.drawString("STAT", 65, 34); - g.drawString("INV", 130, 34); - g.drawString("DATA", 190, 34); - g.setColor(darkGreen); - g.drawString("STATUS", 45, 55); - g.drawString("SPEC", 122, 55); - g.drawString("PERKS", 195, 55); -} - -function bottomLine() { - - //first line - g.setColor(darkerGreen); - g.fillRect(5, 175, 100, 185); //DATE - g.fillRect(105, 175, 160, 185);//STIM - g.fillRect(166, 175, 239, 185); // RADAWAY - - g.setColor(green); - g.setFont("6x8", tinyFont); - g.drawString("DATE", 20, 177); - g.drawString("STIM (3)", 135, 177); - g.drawString("RADAWAY (8)", 205, 177); - - //second line - g.setColor(darkerGreen); - g.fillRect(5, 190, 70, 200); - g.fillRect(75, 190, 239, 200); - - g.setColor(green); - g.drawString("HP 115/115", 38, 192); - g.drawString("LEVEL 6", 100, 192); - g.drawRect(127, 192, 235, 198); -} - -function boy() { - g.drawImage(pip, 165, 85); -} - -function drawClock() { - - var t = new Date(); - var h = t.getHours(); - var m = t.getMinutes(); - var dd = t.getDate(); - var mm = t.getMonth()+1; //month is zero-based - var yy = t.getFullYear(); - var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); - - //create date string - if (dd.toString().length < 2) dd = '0' + dd; - if (mm.toString().length < 2) mm = '0' + mm; - var date = dd + "." + mm + "." + yy; - - g.setFont("6x8",bigFont); - g.setColor(green); - g.setFontAlign(0, -1, 0); - - g.clearRect(0, 110, 150, 140); - g.drawString(time, 70, 110); - - //draw date - g.setFont("6x8", tinyFont); - g.drawString(date, 67, 177); -} - -function drawAll() { - topLine(); - boy(); - bottomLine(); - drawClock(); -} - -Bangle.on('lcdPower', function(on) { - if (on) drawAll(); -}); - -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); -setInterval(drawClock, 1E4); -drawAll(); - -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); From a03280c9cf58ee6ad8744cf8ec02988c577557d5 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 15:45:44 +0200 Subject: [PATCH 0097/1189] Delete app.png --- apps/pipboydate/app.png | Bin 12431 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/pipboydate/app.png diff --git a/apps/pipboydate/app.png b/apps/pipboydate/app.png deleted file mode 100644 index 018b5c7bb8dd8a8a0dcba32fa0450695d92bd67f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12431 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

1C}EjuiQ{0X5=O(KG|og0RysElDc~s4(SYrSm4` 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 N002ovPDHLkV1jo{v#J09 From e7282f87769413ad44a953126c2e45fc48c14c19 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 16:46:58 +0200 Subject: [PATCH 0098/1189] Create ChangeLog --- apps/pipboy/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/pipboy/ChangeLog diff --git a/apps/pipboy/ChangeLog b/apps/pipboy/ChangeLog new file mode 100644 index 000000000..134ba4e18 --- /dev/null +++ b/apps/pipboy/ChangeLog @@ -0,0 +1,2 @@ +0.01: New Watch! +0.02: Changed colors for better readability and added current date From 02e9f6b285cb53809702ff04a0ae2326d750a2d4 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 30 Mar 2020 16:52:22 +0200 Subject: [PATCH 0099/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1d1c911ca..8e1679ebd 100644 --- a/apps.json +++ b/apps.json @@ -803,7 +803,7 @@ "id": "pipboy", "name": "Pipboy", "icon": "app.png", - "version": "0.01", + "version": "0.02", "description": "Pipboy themed clock", "tags": "clock", "type":"clock", From 7ff958ad2cc35d620eeb2a6a9191854d0b657f66 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 30 Mar 2020 16:23:45 +0100 Subject: [PATCH 0100/1189] Fixing sanitycheck errors from recent PRs --- apps.json | 7 ++++--- apps/grocery/grocery-icon.js | 1 + apps/swatch/ChangeLog | 10 +++++----- bin/sanitycheck.js | 4 +++- 4 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 apps/grocery/grocery-icon.js diff --git a/apps.json b/apps.json index 8e1679ebd..2110078f6 100644 --- a/apps.json +++ b/apps.json @@ -837,7 +837,7 @@ {"name":"widid.wid.js","url":"widget.js"} ] }, - { + { "id": "grocery", "name": "Grocery", "icon": "grocery.png", @@ -848,13 +848,14 @@ "custom":"grocery.html", "storage": [ {"name":"grocery"}, - {"name":"grocery.app.js"} + {"name":"grocery.app.js"}, + {"name":"grocery.img","url":"grocery-icon.js","evaluate":true} ] }, { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.01", + "version":"0.02", "description": "Animated Mario clock, jumps to change the time!", "tags": "clock,mario,retro", "type": "clock", diff --git a/apps/grocery/grocery-icon.js b/apps/grocery/grocery-icon.js new file mode 100644 index 000000000..949b0e45b --- /dev/null +++ b/apps/grocery/grocery-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AFEEolAC6lN7vdDCcECwPd6guVGCYuDC4cCBQMikQXQJAMjkECmcyIx4XDmUjmYvLC4XUDARHBIoIWLgATCGQdA7tEonQC5ouDDYg0BOxgSEAggwKRwgUCC6ZIDSwoXNogWDDgNCAgIWIkUEoUk6kiCgMkokipsiBIQXIki2CAgNCAoYADC5Eic4Mic4ICCAIIJCC5MzAAcykYGEAAIXOABAXTmUzGoIXVAIIXLB4SICDIovjO76PZbYR3PDI4XiI6530MIh3SC6R33C/oAOC48CCxsgC44A/ADY=")) diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index d907766c1..86a782585 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -1,5 +1,5 @@ -0.01 Original App -0.02 Lap log now counts up from 1 - Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen -0.03 Added ability to save Lap log as a date named JSON file into memory - Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running +0.01: Original App +0.02: Lap log now counts up from 1 + Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen +0.03: Added ability to save Lap log as a date named JSON file into memory + Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index d911a20d6..d55bba4c8 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -51,7 +51,9 @@ apps.forEach((app,addIdx) => { if (app.version != "0.01") WARN(`App ${app.id} has no ChangeLog`); } else { - var versions = fs.readFileSync(appDir+"ChangeLog").toString().match(/\d+\.\d+:/g); + var changeLog = fs.readFileSync(appDir+"ChangeLog").toString(); + var versions = changeLog.match(/\d+\.\d+:/g); + if (!versions) ERROR(`No versions found in ${app.id} ChangeLog (${appDir}ChangeLog)`); var lastChangeLog = versions.pop().slice(0,-1); if (lastChangeLog != app.version) WARN(`App ${app.id} app version (${app.version}) and ChangeLog (${lastChangeLog}) don't agree`); From 83b5b9b8aa80519d6f7ffa985f759cc1f2d72a96 Mon Sep 17 00:00:00 2001 From: Nik Martin Date: Mon, 30 Mar 2020 10:37:59 -0500 Subject: [PATCH 0101/1189] aclock refactor and updates To get my feet wet with Espruino and my new Bangle.js, I dove into the analog clock code and enhanced and refactored a few things to simplify the interface, fix a few bugs, and improve readability: added date added distinct hour markers refactor timers down to a single timer add elapsed seconds display add date --- apps/aclock/clock-analog.js | 188 +++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 68 deletions(-) diff --git a/apps/aclock/clock-analog.js b/apps/aclock/clock-analog.js index 67061af52..af8f88064 100644 --- a/apps/aclock/clock-analog.js +++ b/apps/aclock/clock-analog.js @@ -1,94 +1,146 @@ -const p = Math.PI/2; -const PRad = Math.PI/180; +let g; +let Bangle; -let intervalRefMin = null; -let intervalRefSec = null; +const p = Math.PI / 2; +const pRad = Math.PI / 180; +const faceWidth = 100; // watch face radius +let timer = null; +let currentDate = new Date(); +const centerPx = g.getWidth() / 2; -let minuteDate = new Date(); -let secondDate = new Date(); +const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat']; -function seconds(angle, r) { - const a = angle*PRad; - const x = 120+Math.sin(a)*r; - const y = 120-Math.cos(a)*r; - g.fillRect(x-1,y-1,x+1,y+1); -} -function hand(angle, r1,r2) { - const a = angle*PRad; +const seconds = (angle) => { + const a = angle * pRad; + const x = centerPx + Math.sin(a) * faceWidth; + const y = centerPx - Math.cos(a) * faceWidth; + + // if 15 degrees, make hour marker larger + const radius = (angle % 15) ? 2 : 4; + g.fillCircle(x, y, radius); +}; + +const hand = (angle, r1, r2) => { + const a = angle * pRad; const r3 = 3; - g.fillPoly([ - 120+Math.sin(a)*r1, - 120-Math.cos(a)*r1, - 120+Math.sin(a+p)*r3, - 120-Math.cos(a+p)*r3, - 120+Math.sin(a)*r2, - 120-Math.cos(a)*r2, - 120+Math.sin(a-p)*r3, - 120-Math.cos(a-p)*r3]); -} -function drawAll() { + g.fillPoly([ + Math.round(centerPx + Math.sin(a) * r1), + Math.round(centerPx - Math.cos(a) * r1), + Math.round(centerPx + Math.sin(a + p) * r3), + Math.round(centerPx - Math.cos(a + p) * r3), + Math.round(centerPx + Math.sin(a) * r2), + Math.round(centerPx - Math.cos(a) * r2), + Math.round(centerPx + Math.sin(a - p) * r3), + Math.round(centerPx - Math.cos(a - p) * r3) + ]); +}; + +const drawAll = () => { g.clear(); - secondDate = minuteDate = new Date(); + currentDate = new Date(); // draw hands first onMinute(); // draw seconds - g.setColor(0,0,0.6); - for (let i=0;i<60;i++) - seconds(360*i/60, 90); + const currentSec = currentDate.getSeconds(); + // draw all secs + + for (let i = 0; i < 60; i++) { + if (i > currentSec) { + g.setColor(0, 0, 0.6); + } else { + g.setColor(0.3, 0.3, 1); + } + seconds((360 * i) / 60); + } onSecond(); -} +}; -function onSecond() { - g.setColor(0,0,0.6); - seconds(360*secondDate.getSeconds()/60, 90); - g.setColor(1,0,0); - secondDate = new Date(); - seconds(360*secondDate.getSeconds()/60, 90); - g.setColor(1,1,1); +const resetSeconds = () => { + g.setColor(0, 0, 0.6); + for (let i = 0; i < 60; i++) { + seconds((360 * i) / 60); + } +}; -} +const onSecond = () => { + g.setColor(0.3, 0.3, 1); + seconds((360 * currentDate.getSeconds()) / 60); + if (currentDate.getSeconds() === 59) { + resetSeconds(); + onMinute(); + } + g.setColor(1, 0.7, 0.2); + currentDate = new Date(); + seconds((360 * currentDate.getSeconds()) / 60); + g.setColor(1, 1, 1); +}; -function onMinute() { - g.setColor(0,0,0); - hand(360*(minuteDate.getHours() + (minuteDate.getMinutes()/60))/12, -10, 50); - hand(360*minuteDate.getMinutes()/60, -10, 82); - minuteDate = new Date(); - g.setColor(1,1,1); - hand(360*(minuteDate.getHours() + (minuteDate.getMinutes()/60))/12, -10, 50); - hand(360*minuteDate.getMinutes()/60, -10, 82); - if(minuteDate.getHours() >= 0 && minuteDate.getMinutes() === 0) { +const drawDate = () => { + g.reset(); + g.setColor(1, 0, 0); + g.setFont('6x8', 2); + + const dayString = days[currentDate.getDay()]; + // pad left date + const dateString = (currentDate.getDate() < 10) ? '0' : '' + currentDate.getDate().toString(); + const dateDisplay = `${dayString}-${dateString}`; + // console.log(`${dayString}|${dateString}`); + // center date + const l = (g.getWidth() - g.stringWidth(dateDisplay)) / 2; + const t = centerPx + 37; + g.drawString(dateDisplay, l, t); + // console.log(l, t); +}; +const onMinute = () => { + if (currentDate.getHours() === 0 && currentDate.getMinutes() === 0) { + g.clear(); + resetSeconds(); + } + // clear existing hands + g.setColor(0, 0, 0); + // Hour + hand((360 * (currentDate.getHours() + currentDate.getMinutes() / 60)) / 12, -8, faceWidth - 35); + // Minute + hand((360 * currentDate.getMinutes()) / 60, -8, faceWidth - 10); + + // get new date, then draw new hands + currentDate = new Date(); + g.setColor(1, 0.9, 0.9); + // Hour + hand((360 * (currentDate.getHours() + currentDate.getMinutes() / 60)) / 12, -8, faceWidth - 35); + g.setColor(1, 1, 0.9); + // Minute + hand((360 * currentDate.getMinutes()) / 60, -8, faceWidth - 10); + if (currentDate.getHours() >= 0 && currentDate.getMinutes() === 0) { Bangle.buzz(); } -} + drawDate(); +}; -function clearTimers() { - if(intervalRefMin) {clearInterval(intervalRefMin);} - if(intervalRefSec) {clearInterval(intervalRefSec);} -} +const startTimers = () => { + timer = setInterval(onSecond, 1000); +}; -function startTimers() { - minuteDate = new Date(); - secondDate = new Date(); - intervalRefSec = setInterval(onSecond,1000); - intervalRefMin = setInterval(onMinute,60*1000); - drawAll(); -} - -Bangle.on('lcdPower',function(on) { +Bangle.on('lcdPower', (on) => { if (on) { - g.clear(); - Bangle.drawWidgets(); + // g.clear(); + drawAll(); startTimers(); - }else { - clearTimers(); + Bangle.drawWidgets(); + } else { + if (timer) { + clearInterval(timer); + } } }); g.clear(); +resetSeconds(); +startTimers(); +drawAll(); Bangle.loadWidgets(); Bangle.drawWidgets(); -drawAll(); -startTimers(); + // Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); From 655488dc35a156a93e0d11e598fadd5c37400289 Mon Sep 17 00:00:00 2001 From: Nik Martin Date: Mon, 30 Mar 2020 10:48:22 -0500 Subject: [PATCH 0102/1189] update apps.json vBump aclock to 0.10 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 2110078f6..1d9b82a04 100644 --- a/apps.json +++ b/apps.json @@ -133,7 +133,7 @@ { "id": "aclock", "name": "Analog Clock", "icon": "clock-analog.png", - "version":"0.02", + "version":"0.10", "description": "An Analog Clock", "tags": "clock", "type":"clock", From 7070536dff46aaa3468484fa5a1190a9411d11f9 Mon Sep 17 00:00:00 2001 From: Nik Martin Date: Mon, 30 Mar 2020 12:09:46 -0500 Subject: [PATCH 0103/1189] add locales to Date display --- apps/aclock/clock-analog.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/aclock/clock-analog.js b/apps/aclock/clock-analog.js index af8f88064..419ed0933 100644 --- a/apps/aclock/clock-analog.js +++ b/apps/aclock/clock-analog.js @@ -1,6 +1,8 @@ let g; let Bangle; +// http://forum.espruino.com/conversations/345155/#comment15172813 +const locale = require('locale'); const p = Math.PI / 2; const pRad = Math.PI / 180; const faceWidth = 100; // watch face radius @@ -8,8 +10,6 @@ let timer = null; let currentDate = new Date(); const centerPx = g.getWidth() / 2; -const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat']; - const seconds = (angle) => { const a = angle * pRad; const x = centerPx + Math.sin(a) * faceWidth; @@ -81,7 +81,7 @@ const drawDate = () => { g.setColor(1, 0, 0); g.setFont('6x8', 2); - const dayString = days[currentDate.getDay()]; + const dayString = locale.dow(currentDate, true); // pad left date const dateString = (currentDate.getDate() < 10) ? '0' : '' + currentDate.getDate().toString(); const dateDisplay = `${dayString}-${dateString}`; From 277132e2a497383863a8ac33aa49400f32bd57cf Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Mon, 30 Mar 2020 21:34:44 +0200 Subject: [PATCH 0104/1189] Create Bar Clock --- apps.json | 13 +++++ apps/barclock/ChangeLog | 1 + apps/barclock/clock-bar-icon.js | 1 + apps/barclock/clock-bar.js | 99 ++++++++++++++++++++++++++++++++ apps/barclock/clock-bar.png | Bin 0 -> 159 bytes 5 files changed, 114 insertions(+) create mode 100644 apps/barclock/ChangeLog create mode 100644 apps/barclock/clock-bar-icon.js create mode 100644 apps/barclock/clock-bar.js create mode 100644 apps/barclock/clock-bar.png diff --git a/apps.json b/apps.json index 2110078f6..d42bc2c11 100644 --- a/apps.json +++ b/apps.json @@ -875,5 +875,18 @@ "storage": [ {"name":"widver.wid.js","url":"widget.js"} ] + }, + { "id": "barclock", + "name": "Bar Clock", + "icon": "clock-bar.png", + "version":"0.01", + "description": "A simple 24h digital clock showing seconds as a bar", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"barclock.app.js","url":"clock-bar.js"}, + {"name":"barclock.img","url":"clock-bar-icon.js","evaluate":true} + ] } ] diff --git a/apps/barclock/ChangeLog b/apps/barclock/ChangeLog new file mode 100644 index 000000000..83b3133da --- /dev/null +++ b/apps/barclock/ChangeLog @@ -0,0 +1 @@ +0.01: Created Bar Clock diff --git a/apps/barclock/clock-bar-icon.js b/apps/barclock/clock-bar-icon.js new file mode 100644 index 000000000..29bf0f481 --- /dev/null +++ b/apps/barclock/clock-bar-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgJC/AD8Mgfwh/AhgFFngHBOIM8AovMDIXA5gFFDoUAmYjDAocMSoMz/4FF//P/g1CAopTLDAIABwAFGAH4AfA")) diff --git a/apps/barclock/clock-bar.js b/apps/barclock/clock-bar.js new file mode 100644 index 000000000..100f66db1 --- /dev/null +++ b/apps/barclock/clock-bar.js @@ -0,0 +1,99 @@ +/* jshint esversion: 6 */ +/** + * A simple 24h digital clock showing seconds as a bar + **/ +{ + const timeFont = '6x8' + const timeFontSize = 8 // 'hh:mm' fits exactly + const dateFont = 'Vector' + const dateFontSize = 20 + + const screenSize = g.getWidth() + const screenCenter = screenSize / 2 + + const timeY = screenCenter + const barY = 155 // just below time + const barThickness = 6 // matches time digit size + const dateY = screenSize - dateFontSize // at bottom of screen + + const SECONDS_PER_MINUTE = 60 + + function timeText(date) { + const d = date.toString().split(' ') + const time = d[4].substr(0, 5) + const t = time.split(':') + const hours = t[0], + minutes = t[1] + return `${hours}:${minutes}` + } + + function dateText(date) { + const d = date.toString().split(' ') + const dayName = d[0], + month = d[1], + day = d[2] + return `${dayName} ${day} ${month}` + } + + function drawDateTime(date) { + g.setFontAlign(0, 0) // centered + + g.setFont(timeFont, timeFontSize) + g.drawString(timeText(date), screenCenter, timeY, true) + + g.setFont(dateFont, dateFontSize) + g.drawString(dateText(date), screenCenter, dateY, true) + } + + function drawBar(date) { + const seconds = date.getSeconds() + const fraction = seconds / SECONDS_PER_MINUTE + g.fillRect(0, barY, fraction * screenSize, barY + barThickness) + } + function eraseBar() { + const color = g.getColor() + g.setColor(g.getBgColor()) + g.fillRect(0, barY, screenSize, barY + barThickness) + g.setColor(color) + } + + let lastSeconds + function tick() { + g.reset() + const date = new Date() + const seconds = date.getSeconds() + if (lastSeconds > seconds) { + // new minute + eraseBar() + drawDateTime(date) + } + drawBar(date) + + lastSeconds = seconds + } + + let iTick + function start() { + lastSeconds = 99 // force redraw + tick() + iTick = setInterval(tick, 1000) + } + function stop() { + if (iTick) { + clearInterval(iTick) + iTick = undefined + } + } + + // clean app screen + g.clear() + Bangle.loadWidgets() + Bangle.drawWidgets() + // Show launcher when middle button pressed + setWatch(Bangle.showLauncher, BTN2, {repeat: false, edge: 'falling'}) + + Bangle.on('lcdPower', function (on) { + on ? start() : stop() + }) + start() +} diff --git a/apps/barclock/clock-bar.png b/apps/barclock/clock-bar.png new file mode 100644 index 0000000000000000000000000000000000000000..a580cae69c0b08824b0a0540a691bb636ace9045 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDH3?y^UWFG-iYymzYu0Z<#|Nl#G&c6#}aTa() z7BevDDT6R$#Zvn+prE~{i(`ny<>Z6~#t#zz9jI?$cf0xFgM`G511pRj9x|sVhy-vp z8}iS2lxSe^kALyM`TvAoWE-G$nj`63{3HPgg&ebxsLQ0OcVv A;{X5v literal 0 HcmV?d00001 From 6176c16712136a9ca5d09830bb12a0b4ae88d5bb Mon Sep 17 00:00:00 2001 From: DerGuteWolf Date: Mon, 30 Mar 2020 23:52:41 +0200 Subject: [PATCH 0105/1189] marioclock: use short date format from locale, take timeout from settings --- apps/marioclock/marioclock-app.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index 248b15387..c0ada5e59 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -6,6 +6,9 @@ **********************************/ var locale = require("locale"); +const storage = require('Storage'); +const settings = (storage.readJSON('setting.json',1)||{}); +const timeout = settings.timeout||10; // Screen dimensions let W, H; @@ -280,14 +283,10 @@ function drawTime() { } function drawDate() { - const date = new Date(); - const day = locale.dow(date).substr(0, 3); - const dayNum = ("0" + date.getDate()).substr(-2); - const month = locale.month(date).substr(0, 3); - g.setFont("6x8"); g.setColor(LIGHTEST); - g.drawString(`${day} ${dayNum} ${month}`, 10, 0, true); + const dateStr = locale.date(new Date(), true); + g.drawString(dateStr, (W - g.stringWidth(dateStr))/2, 0, true); } function redraw() { @@ -322,7 +321,7 @@ function resetDisplayTimeout() { displayTimeoutRef = setInterval(() => { if (Bangle.isLCDOn()) Bangle.setLCDPower(false); clearTimers(); - }, ONE_SECOND * 10); + }, ONE_SECOND * timeout); } function startTimers(){ From 249eead69baf85ff8561a63b916c35178b451fd4 Mon Sep 17 00:00:00 2001 From: DerGuteWolf Date: Mon, 30 Mar 2020 23:54:37 +0200 Subject: [PATCH 0106/1189] Update ChangeLog --- apps/marioclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index e81e2f78c..79f103c48 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: Create mario app 0.02: Fix day of the week and add padding +0.03: use short date format from locale, take timeout from settings From 0e8f9405d38c1211b864daf4c2581d428e9ca108 Mon Sep 17 00:00:00 2001 From: DerGuteWolf Date: Mon, 30 Mar 2020 23:55:56 +0200 Subject: [PATCH 0107/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 2110078f6..a24d3babd 100644 --- a/apps.json +++ b/apps.json @@ -855,7 +855,7 @@ { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.02", + "version":"0.03", "description": "Animated Mario clock, jumps to change the time!", "tags": "clock,mario,retro", "type": "clock", From 54346977c4d5f5265084042b4a95fd4cef6cff10 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 31 Mar 2020 00:05:00 +0200 Subject: [PATCH 0108/1189] Bar clock 0.02: Apply locale, 12-hour setting Plus minor bar drawing improvement --- apps.json | 4 +-- apps/barclock/ChangeLog | 1 + apps/barclock/clock-bar.js | 58 ++++++++++++++++++++++++++++---------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/apps.json b/apps.json index d42bc2c11..4958d039b 100644 --- a/apps.json +++ b/apps.json @@ -879,8 +879,8 @@ { "id": "barclock", "name": "Bar Clock", "icon": "clock-bar.png", - "version":"0.01", - "description": "A simple 24h digital clock showing seconds as a bar", + "version":"0.02", + "description": "A simple digital clock showing seconds as a bar", "tags": "clock", "type":"clock", "allow_emulator":true, diff --git a/apps/barclock/ChangeLog b/apps/barclock/ChangeLog index 83b3133da..a8d2f5485 100644 --- a/apps/barclock/ChangeLog +++ b/apps/barclock/ChangeLog @@ -1 +1,2 @@ 0.01: Created Bar Clock +0.02: Apply locale, 12-hour setting diff --git a/apps/barclock/clock-bar.js b/apps/barclock/clock-bar.js index 100f66db1..5ab9c433e 100644 --- a/apps/barclock/clock-bar.js +++ b/apps/barclock/clock-bar.js @@ -1,10 +1,23 @@ /* jshint esversion: 6 */ /** - * A simple 24h digital clock showing seconds as a bar + * A simple digital clock showing seconds as a bar **/ { + // Check settings for what type our clock should be + const is12Hour = (require('Storage').readJSON('setting.json', 1) || {})['12hour'] + const locale = require('locale') + { // add some more info to locale + let date = new Date() + date.setFullYear(1111) + date.setMonth(1, 3) // februari: months are zero-indexed + const localized = locale.date(date, true) + locale.dayFirst = /3.*2/.test(localized) + locale.hasMeridian = (locale.meridian(date) !== '') + } + const timeFont = '6x8' - const timeFontSize = 8 // 'hh:mm' fits exactly + const timeFontSize = (is12Hour && locale.hasMeridian) ? 6 : 8 + const ampmFontSize = 2 const dateFont = 'Vector' const dateFontSize = 20 @@ -18,35 +31,50 @@ const SECONDS_PER_MINUTE = 60 + function timeText(date) { - const d = date.toString().split(' ') - const time = d[4].substr(0, 5) - const t = time.split(':') - const hours = t[0], - minutes = t[1] - return `${hours}:${minutes}` + if (!is12Hour) { + return {time: locale.time(date, true), ampm: ''} + } + const meridian = locale.meridian(date) + const hours = date.getHours() + if (hours === 0) { + date.setHours(12) + } else if (hours > 12) { + date.setHours(hours - 12) + } + return {time: locale.time(date, true), ampm: meridian} } function dateText(date) { - const d = date.toString().split(' ') - const dayName = d[0], - month = d[1], - day = d[2] - return `${dayName} ${day} ${month}` + const dayName = locale.dow(date, true), + month = locale.month(date, true), + day = date.getDate() + return `${dayName} ` + (locale.dayFirst ? `${day} ${month}` : `${month} ${day}`) } function drawDateTime(date) { + const timeTexts = timeText(date) g.setFontAlign(0, 0) // centered - g.setFont(timeFont, timeFontSize) - g.drawString(timeText(date), screenCenter, timeY, true) + g.drawString(timeTexts.time, screenCenter, timeY, true) + if (timeTexts.ampm !== '') { + g.setFontAlign(1, -1) + g.setFont(timeFont, ampmFontSize) + g.drawString(timeTexts.ampm, + // at right edge of screen , aligned with time bottom + (screenSize - ampmFontSize * 2), (timeY + timeFontSize - ampmFontSize), + true) + } + g.setFontAlign(0, 0) // centered g.setFont(dateFont, dateFontSize) g.drawString(dateText(date), screenCenter, dateY, true) } function drawBar(date) { const seconds = date.getSeconds() + if (seconds === 0) return; // zero-size rect stills draws one line of pixels const fraction = seconds / SECONDS_PER_MINUTE g.fillRect(0, barY, fraction * screenSize, barY + barThickness) } From e56035c7c9a3be5dbd626f1ebe544dd3aefa6cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Luk=C3=A1cs?= Date: Tue, 31 Mar 2020 13:17:59 +0200 Subject: [PATCH 0109/1189] Wrong long date pattern for HU locale ooops :) --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index e28d285da..a326d72a8 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -348,7 +348,7 @@ var locales = { temperature: '°C', ampm: {0:"de",1:"du"}, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%Y %d %b", 1: "%Y.%m.%d" }, // 2020 Feb 28" // "2020.03.01."(short) + datePattern: { 0: "%Y %b %d, %A", 1: "%Y.%m.%d" }, // 2020 Feb 28, Péntek" // "2020.03.01."(short) abmonth: "Jan,Feb,Már,Ãpr,Máj,Jún,Júl,Aug,Szep,Okt,Nov,Dec", month: "Január,Február,Március,Ãprilis,Május,Június,Július,Augusztus,Szeptember,Október,November,December", abday: "Vas,Hét,Ke,Szer,Csüt,Pén,Szom", From b40c9031e13d206f751442e5eb410a9fb90a1b95 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 31 Mar 2020 13:18:31 +0100 Subject: [PATCH 0110/1189] refactor - move JS into its own directory --- index.html | 8 ++++---- appinfo.js => js/appinfo.js | 0 comms.js => js/comms.js | 0 index.js => js/index.js | 0 utils.js => js/utils.js | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename appinfo.js => js/appinfo.js (100%) rename comms.js => js/comms.js (100%) rename index.js => js/index.js (100%) rename utils.js => js/utils.js (100%) diff --git a/index.html b/index.html index c256360e7..5ad76064d 100644 --- a/index.html +++ b/index.html @@ -128,10 +128,10 @@ - - - - + + + + diff --git a/appinfo.js b/js/appinfo.js similarity index 100% rename from appinfo.js rename to js/appinfo.js diff --git a/comms.js b/js/comms.js similarity index 100% rename from comms.js rename to js/comms.js diff --git a/index.js b/js/index.js similarity index 100% rename from index.js rename to js/index.js diff --git a/utils.js b/js/utils.js similarity index 100% rename from utils.js rename to js/utils.js From 91e78238bbe418b2efa5d8d3c216eeaf62865adc Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 31 Mar 2020 13:18:50 +0100 Subject: [PATCH 0111/1189] Remove un-needed dependency --- index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/index.html b/index.html index 5ad76064d..efaf84a61 100644 --- a/index.html +++ b/index.html @@ -132,6 +132,5 @@ - From 174cc6d7cfdc5de5877d60e9c042620c2ab5cc52 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 31 Mar 2020 13:19:40 +0100 Subject: [PATCH 0112/1189] Remove firmware js - basically guaranteed to be out of date --- firmware.js | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 firmware.js diff --git a/firmware.js b/firmware.js deleted file mode 100644 index 2a3a697a3..000000000 --- a/firmware.js +++ /dev/null @@ -1,32 +0,0 @@ -// Generated by BangleApps/bin/firmwaremaker.js -reset(1) -var FAIL=0; -require('Storage').write(".boot0","// This ALWAYS runs at boot\nE.setFlags({pretokenise:1});\n// Load settings...\nvar s = require('Storage').readJSON('setting.json',1)||{};\nif (s.ble!==false) {\n if (s.HID) { // Human interface device\n Bangle.HID = E.toUint8Array(atob(\"BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA==\"));\n NRF.setServices({}, {uart:true, hid:Bangle.HID});\n }\n}\nif (s.blerepl===false) { // If not programmable, force terminal off Bluetooth\n if (s.log) Terminal.setConsole(true); // if showing debug, force REPL onto terminal\n else E.setConsole(null,{force:true}); // on new (2v05+) firmware we have E.setConsole which allows a 'null' console\n} else {\n if (s.log) Terminal.setConsole(); // if showing debug, put REPL on terminal (until connection)\n else Bluetooth.setConsole(true); // else if no debug, force REPL to Bluetooth\n}\n// we just reset, so BLE should be on.\n// Don't disconnect if something is already connected to us\nif (s.ble===false && !NRF.getSecurityStatus().connected) NRF.sleep();\n// Set time, vibrate, beep, etc\nif (!s.vibrate) Bangle.buzz=Promise.resolve;\nif (!s.beep) Bangle.beep=Promise.resolve;\nBangle.setLCDTimeout(s.timeout);\nif (!s.timeout) Bangle.setLCDPower(1);\nE.setTimeZone(s.timezone);\ndelete s;\n// check for alarms\nvar alarms = require('Storage').readJSON('alarm.json',1)||[];\nvar time = new Date();\nvar active = alarms.filter(a=>a.on&&(a.last!=time.getDate()));\nif (active.length) {\n active = active.sort((a,b)=>a.hr-b.hr);\n var hr = time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600);\n if (!require('Storage').read(\"alarm.js\")) {\n console.log(\"No alarm app!\");\n require('Storage').write('alarm.json',\"[]\")\n } else {\n var t = 3600000*(active[0].hr-hr);\n if (t<1000) t=1000;\n /* execute alarm at the correct time. We avoid execing immediately\n since this code will get called AGAIN when alarm.js is loaded. alarm.js\n will then clearInterval() to get rid of this call so it can proceed\n normally. */\n setTimeout(function() {\n load(\"alarm.js\");\n },t);\n }\n}\n"); -require('Storage').write(".bootcde","// This runs after a 'fresh' boot\nvar settings=require(\"Storage\").readJSON('setting.json',1)||{};\nif (!settings.welcomed && require(\"Storage\").read(\"welcome.js\")!==undefined) {\n setTimeout(()=>load(\"welcome.js\"));\n} else {\n // load clock if specified\n var clockApp = settings.clock;\n if (clockApp) clockApp = require(\"Storage\").read(clockApp)\n if (!clockApp) {\n var clockApps = require(\"Storage\").list(/\\.info$/).map(app=>require(\"Storage\").readJSON(app,1)||{}).filter(app=>app.type==\"clock\").sort((a, b) => a.sortorder - b.sortorder);\n if (clockApps && clockApps.length > 0)\n clockApp = require(\"Storage\").read(clockApps[0].src);\n delete clockApps;\n }\n if (!clockApp) clockApp='E.showMessage(\"No Clock Found\")';\n delete settings;\n // check to see if our clock is wrong - if it is use GPS time\n if ((new Date()).getFullYear()==1970) {\n E.showMessage(\"Searching for\\nGPS time\");\n Bangle.on('GPS',function cb(g) {\n Bangle.setGPSPower(0);\n Bangle.removeListener(\"GPS\",cb);\n if (!g.time || (g.time.getFullYear()<2000) ||\n (g.time.getFullYear()==2250)) {\n // GPS receiver's time not set - just boot clock anyway\n eval(clockApp);delete clockApp;\n return;\n }\n // We have a GPS time. Set time and reboot (to load alarms properly)\n setTime(g.time.getTime()/1000);\n load();\n });\n Bangle.setGPSPower(1);\n } else {\n eval(clockApp);\n delete clockApp;\n }\n}\n"); -require('Storage').write("boot.info","{\"id\":\"boot\",\"name\":\"Bootloader\",\"type\":\"bootloader\",\"sortorder\":-10,\"version\":\"0.09\",\"files\":\"boot.info,.boot0,.bootcde\"}"); -require('Storage').write("launch.app.js","var s = require(\"Storage\");\nvar apps = s.list(/\\.info$/).map(app=>s.readJSON(app,1)||{name:\"DEAD: \"+app.substr(1)}).filter(app=>app.type==\"app\" || app.type==\"clock\" || !app.type);\napps.sort((a,b)=>{\n var n=(0|a.sortorder)-(0|b.sortorder);\n if (n) return n; // do sortorder first\n if (a.nameb.name) return 1;\n return 0;\n});\nvar selected = 0;\nvar menuScroll = 0;\nvar menuShowing = false;\n\nfunction drawMenu() {\n g.setFont(\"6x8\",2);\n g.setFontAlign(-1,0);\n var n = 3;\n if (selected>=n+menuScroll) menuScroll = 1+selected-n;\n if (selectedn+menuScroll) g.fillPoly([120,239,100,219,140,219]);\n else g.clearRect(100,219,140,239);\n for (var i=0;i0) {\n selected--;\n drawMenu();\n }\n}, BTN1, {repeat:true});\nsetWatch(function() {\n if (selected+1[],\n\"0\":n=>[\n[n,0,1,0],\n[1,0,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[n,1,n,2],\n[n,0,n,1]],\n\"1\":n=>[\n[1-n,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1-n,1,1-n,2],\n[1-n,2,1,2]],\n\"2\":n=>[\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[0,1+n,0,2],\n[1,2-n,1,2],\n[0,2,1,2]],\n\"3\":n=>[\n[0,0,1-n,0],\n[0,0,0,n],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[n,2,1,2]],\n\"4\":n=>[\n[0,0,0,1],\n[1,0,1-n,0],\n[1,0,1,1-n],\n[0,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2]],\n\"5\": (n,maxFive)=>maxFive ? [ // 5 -> 0\n[0,0,0,1],\n[0,0,1,0],\n[n,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2,0,2],\n[1,1-n,1,1],\n[0,1,0,1+n]] : [ // 5 -> 6\n[0,0,0,1],\n[0,0,1,0],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2-n,0,2]],\n\"6\":n=>[\n[0,0,0,1-n],\n[0,0,1,0],\n[n,1,1,1],\n[1,1-n,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[0,1-n,0,2-2*n]],\n\"7\":n=>[\n[0,0,0,n],\n[0,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2],\n[1-n,1,1-n,2]],\n\"8\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,1,0,2-n]],\n\"9\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1-n,1],\n[0,1,0,1+n],\n[1,1,1,2],\n[0,2,1,2]],\n\":\":n=>[\n[0.4,0.4,0.6,0.4],\n[0.6,0.4,0.6,0.6],\n[0.6,0.6,0.4,0.6],\n[0.4,0.4,0.4,0.6],\n[0.4,1.4,0.6,1.4],\n[0.6,1.4,0.6,1.6],\n[0.6,1.6,0.4,1.6],\n[0.4,1.4,0.4,1.6]]\n};\n\n/* Draw a transition between lastText and thisText.\n 'n' is the amount - 0..1 */\nfunction draw(lastText,thisText,n) {\n buf.clear();\n var x = 1; // x offset\n const p = 2; // padding around digits\n var y = p; // y offset\n const s = 34; // character size\n for (var i=0;i{\n if (c[0]!=c[2]) // horiz\n buf.fillRect(x+c[0]*s,y+c[1]*s-p,x+c[2]*s,y+c[3]*s+p);\n else if (c[1]!=c[3]) // vert\n buf.fillRect(x+c[0]*s-p,y+c[1]*s,x+c[2]*s+p,y+c[3]*s);\n });\n if (thisCh==\":\") x-=4;\n x+=s+p+7;\n }\n y += 2*s;\n var d = new Date();\n buf.setFont(\"6x8\");\n buf.setFontAlign(-1,-1);\n buf.drawString((\"0\"+d.getSeconds()).substr(-2), x, y-8);\n // date\n buf.setFontAlign(0,-1);\n var date = d.toString().substr(0,15);\n buf.drawString(date, buf.getWidth()/2, y+8);\n flip();\n}\n\n/* Show the current time, and animate if needed */\nfunction showTime() {\n if (!Bangle.isLCDOn()) return;\n if (animInterval) return; // in animation - quit\n var d = new Date();\n var t = (\" \"+d.getHours()).substr(-2)+\":\"+\n (\"0\"+d.getMinutes()).substr(-2);\n var l = lastTime;\n // same - don't animate\n if (t==l) {\n draw(t,l,0);\n return;\n }\n var n = 0;\n animInterval = setInterval(function() {\n n += 1/10;\n if (n>=1) {\n n=1;\n clearInterval(animInterval);\n animInterval=0;\n }\n draw(l,t,n);\n }, 20);\n lastTime = t;\n}\n\nBangle.on('lcdPower',function(on) {\n if (on)\n showTime();\n});\n\ng.clear();\nBangle.loadWidgets();\nBangle.drawWidgets();\n// Update time once a second\nsetInterval(showTime, 1000);\nshowTime();\n\n// Show launcher when middle button pressed\nsetWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:\"falling\"});\n"); -require('Storage').write("mclock.img",require("heatshrink").decompress(atob("mEwghC/AE8IxAAEwAWVDB4WIDBwWJAAIWPmf//8zDBpFDwYVBAAc4JJYWJDAoXKn4SC+EPAgXzC5JGCx4qDC4n//BIIEIRCEC4v/GBBdHC4xhCIw5dDC5BhCJAgXCRQoXGJAQXEUhAXHJAyNGC5KRCC7p2FC5B4CC5kggQXOBwvyBQMvSA4XL+EIwCoIC8ZHCgYXNO44LBBIiPPCAIwFC5DXGAAMwGAjvPGA4XIwYXHGALBDnAXFhCQHGAaOFwAXGPA4bFC4xIMIxIXDJBJGEC4xICSJCNEIwowEMJBdCFwwXEMJBdCC5BICDA4WDIw4wEAAMzCoMzBAgWIDAwAGCxRJEAAxFJDBgWNDBAWPAH4AYA=="))); -require('Storage').write("mclock.info","{\"id\":\"mclock\",\"name\":\"Morphing Clock\",\"type\":\"clock\",\"src\":\"mclock.app.js\",\"icon\":\"mclock.img\",\"sortorder\":-9,\"version\":\"0.02\",\"files\":\"mclock.info,mclock.app.js,mclock.img\"}"); -require('Storage').write("setting.app.js","Bangle.loadWidgets();\nBangle.drawWidgets();\n\nconst storage = require('Storage');\nlet settings;\n\nfunction updateSettings() {\n //storage.erase('setting.json'); // - not needed, just causes extra writes if settings were the same\n storage.write('setting.json', settings);\n}\n\nfunction resetSettings() {\n settings = {\n ble: true, // Bluetooth enabled by default\n blerepl: true, // Is REPL on Bluetooth - can Espruino IDE be used?\n log: false, // Do log messages appear on screen?\n timeout: 10, // Default LCD timeout in seconds\n vibrate: true, // Vibration enabled by default. App must support\n beep: true, // Beep enabled by default. App must support\n timezone: 0, // Set the timezone for the device\n HID : false, // BLE HID mode, off by default\n clock: null, // a string for the default clock's name\n \"12hour\" : false, // 12 or 24 hour clock?\n // welcomed : undefined/true (whether welcome app should show)\n };\n updateSettings();\n}\n\nsettings = storage.readJSON('setting.json',1);\nif (!settings) resetSettings();\n\nconst boolFormat = v => v ? \"On\" : \"Off\";\n\nfunction showMainMenu() {\n const mainmenu = {\n '': { 'title': 'Settings' },\n 'Make Connectable': makeConnectable,\n 'BLE': {\n value: settings.ble,\n format: boolFormat,\n onchange: () => {\n settings.ble = !settings.ble;\n updateSettings();\n }\n },\n 'Programmable': {\n value: settings.blerepl,\n format: boolFormat,\n onchange: () => {\n settings.blerepl = !settings.blerepl;\n updateSettings();\n }\n },\n 'Debug info': {\n value: settings.log,\n format: v => v ? \"Show\" : \"Hide\",\n onchange: () => {\n settings.log = !settings.log;\n updateSettings();\n }\n },\n 'LCD Timeout': {\n value: settings.timeout,\n min: 0,\n max: 60,\n step: 5,\n onchange: v => {\n settings.timeout = 0 | v;\n updateSettings();\n Bangle.setLCDTimeout(settings.timeout);\n }\n },\n 'Beep': {\n value: settings.beep,\n format: boolFormat,\n onchange: () => {\n settings.beep = !settings.beep;\n updateSettings();\n if (settings.beep) {\n Bangle.beep(1);\n }\n }\n },\n 'Vibration': {\n value: settings.vibrate,\n format: boolFormat,\n onchange: () => {\n settings.vibrate = !settings.vibrate;\n updateSettings();\n if (settings.vibrate) {\n VIBRATE.write(1);\n setTimeout(()=>VIBRATE.write(0), 10);\n }\n }\n },\n 'Welcome App': {\n value: !settings.welcomed,\n format: boolFormat,\n onchange: v => {\n settings.welcomed = v?undefined:true;\n updateSettings();\n }\n },\n 'Locale': showLocaleMenu,\n 'Select Clock': showClockMenu,\n 'HID': {\n value: settings.HID,\n format: boolFormat,\n onchange: () => {\n settings.HID = !settings.HID;\n updateSettings();\n }\n },\n 'Set Time': showSetTimeMenu,\n 'Reset Settings': showResetMenu,\n 'Turn Off': Bangle.off,\n '< Back': ()=> {load();}\n };\n return E.showMenu(mainmenu);\n}\n\nfunction showLocaleMenu() {\n const localemenu = {\n '': { 'title': 'Locale' },\n '< Back': showMainMenu,\n 'Time Zone': {\n value: settings.timezone,\n min: -11,\n max: 12,\n step: 0.5,\n onchange: v => {\n settings.timezone = v || 0;\n updateSettings();\n }\n },\n 'Clock Style': {\n value: !!settings[\"12hour\"],\n format : v => v?\"12hr\":\"24hr\",\n onchange: v => {\n settings[\"12hour\"] = v;\n updateSettings();\n }\n }\n };\n return E.showMenu(localemenu);\n}\n\nfunction showResetMenu() {\n const resetmenu = {\n '': { 'title': 'Reset' },\n '< Back': showMainMenu,\n 'Reset Settings': () => {\n E.showPrompt('Reset Settings?').then((v) => {\n if (v) {\n E.showMessage('Resetting');\n resetSettings();\n }\n setTimeout(showMainMenu, 50);\n });\n }\n };\n return E.showMenu(resetmenu);\n}\n\nfunction makeConnectable() {\n try { NRF.wake(); } catch(e) {}\n Bluetooth.setConsole(1);\n var name=\"Bangle.js \"+NRF.getAddress().substr(-5).replace(\":\",\"\");\n E.showPrompt(name+\"\\nStay Connectable?\",{title:\"Connectable\"}).then(r=>{\n if (settings.ble!=r) {\n settings.ble = r;\n updateSettings();\n }\n if (!r) try { NRF.sleep(); } catch(e) {}\n showMainMenu();\n });\n}\nfunction showClockMenu() {\n var clockApps = require(\"Storage\").list(/\\.info$/).map(app=>{\n try { return require(\"Storage\").readJSON(app); }\n catch (e) {}\n }).filter(app=>app.type==\"clock\").sort((a, b) => a.sortorder - b.sortorder);\n const clockMenu = {\n '': {\n 'title': 'Select Clock',\n },\n '< Back': showMainMenu,\n };\n clockApps.forEach((app,index) => {\n var label = app.name;\n if ((!settings.clock && index === 0) || (settings.clock === app.src)) {\n label = \"* \"+label;\n }\n clockMenu[label] = () => {\n if (settings.clock !== app.src) {\n settings.clock = app.src;\n updateSettings();\n showMainMenu();\n }\n };\n });\n if (clockApps.length === 0) {\n clockMenu[\"No Clocks Found\"] = () => {};\n }\n return E.showMenu(clockMenu);\n}\n\n\n\nfunction showSetTimeMenu() {\n d = new Date();\n const timemenu = {\n '': {\n 'title': 'Set Time',\n 'predraw': function() {\n d = new Date();\n timemenu.Hour.value = d.getHours();\n timemenu.Minute.value = d.getMinutes();\n timemenu.Second.value = d.getSeconds();\n timemenu.Date.value = d.getDate();\n timemenu.Month.value = d.getMonth() + 1;\n timemenu.Year.value = d.getFullYear();\n }\n },\n '< Back': showMainMenu,\n 'Hour': {\n value: d.getHours(),\n min: 0,\n max: 23,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setHours(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Minute': {\n value: d.getMinutes(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMinutes(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Second': {\n value: d.getSeconds(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setSeconds(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Date': {\n value: d.getDate(),\n min: 1,\n max: 31,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setDate(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Month': {\n value: d.getMonth() + 1,\n min: 1,\n max: 12,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMonth(v - 1);\n setTime(d.getTime()/1000);\n }\n },\n 'Year': {\n value: d.getFullYear(),\n min: 2019,\n max: 2100,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setFullYear(v);\n setTime(d.getTime()/1000);\n }\n }\n };\n return E.showMenu(timemenu);\n}\n\nshowMainMenu();\n"); -require('Storage').write("setting.json",{"ble":true,"blerepl":true,"log":false,"timeout":10,"vibrate":true,"beep":true,"timezone":0,"HID":false,"clock":null,"12hour":false}); -require('Storage').write("setting.img",require("heatshrink").decompress(atob("mEwghC/AFEiAAgX/C/4SFkADBgQXFBIgECAAYSCkAWGBIoXGyQTHABBZLkUhiMRiQXLIQwVBAAZlIC44tCAAYxGIxIWFGA4XIFwwwHXBAWHGAwXHFxAwGPAYXTX44XDiAJBgIXGyDAHFAYKDMAq+EGAgXNCwwX/C453XU6IWHa6ZFCC6JJCC4hgEAAoOEC5AwIFwhgEBAgwIBoqmGGBIuFVAgXFGAwLFYAoLFGIYtFeA4MGABMpC4pICkBMGBIpGFC4SuIBIoWFAAxZLC/4X/AFQ"))); -require('Storage').write("setting.info","{\"id\":\"setting\",\"name\":\"Settings\",\"src\":\"setting.app.js\",\"icon\":\"setting.img\",\"sortorder\":-2,\"version\":\"0.06\",\"files\":\"setting.info,setting.app.js,setting.json,setting.img\"}"); -require('Storage').write("about.app.js","var ENV = process.env;\nvar MEM = process.memory();\nvar s = require(\"Storage\");\n\ng.clear(1);\ng.setFont(\"6x8\");\nvar y = 24, h=8;\ng.drawImage(require(\"heatshrink\").decompress(atob(\"vE4gQZWg//AAI3Zh4dCoAd6wAd64Ad2j4d6l4dcn4dC6Adc+AdYv4dUggHG//kgN//AGB1WkDpkOAwsH/gDBgJ4CTRwdGl6RDl/0gHQgJeMDo2/AgcDIAIkBnAdRgJyCAAQdDlgdRgZPDgbWBDoUcDqMPRYcJgEfoA7Uh9AAgQ1BEgIdBngdRKQIACmBbB6AdB2gdRnoEDyB+C8tbbQVpgNAqOkAwMGyEQDoMB1AIBvgdDPYMC+H//7zBg//+fAA4OAgH//twDoMv/4WB3iyEAAPwHINvTYMAv/A/sC6BmBh/wDoP4gIuBdwayBAAP/DoMH4F4ToQSB+EPJQUOgKmDBgIABhAdFB4L7BgfAAYNwjpKChwJBTIQdDiAdFgHgAYIdDmDaCO4MD9Wq14dM+CdCDoU0nDjChyhBAAIdFsgdTZgaVDmPYLJk0LIodDaIcxcILRDSo80jiVECgUAvgDCmG0YQTRHDoTRBgLRCMwJDBnodDeAMDKoUvAIU/DocD6ELDoKRCAIM/LIcGG4PQUIKCBU4PzDoaEB/p3BFQKKCh9ADoXsKIVVqonCtVBoFQcAUKyFwghdB3IPBCwJZCAQMfEgQAL2AGFgZJBDoZgDABEMWYQJFgLwCkACB/gdLWYMCfoQAE35BEDpkH8EfdgYADl4mDl68BABazBFBA2CgK8CABcBUZP/8kBv58CAC1//4ABUQwASn4dgOxoALl4dC4AdYj4d6h4d+wAd6oAd2g4dCAwQA=\")),120,y);\ng.drawString(\"BANGLEJS.COM\",120,y-4);\ng.drawString(\"Powered by Espruino\",0,y+=4+h);\ng.drawString(\"Version \"+ENV.VERSION,0,y+=h);\ng.drawString(\"Commit \"+ENV.GIT_COMMIT,0,y+=h);\nfunction getVersion(name,file) {\n var j = s.readJSON(file,1);\n var v = (\"object\"==typeof j)?j.version:false;\n g.drawString(v?(name+\" \"+(v?\"v\"+v:\"Unknown\")):\"NO \"+name,0,y+=h);\n}\ngetVersion(\"Bootloader\",\"boot.info\");\ngetVersion(\"Launcher\",\"launch.info\");\ngetVersion(\"Settings\",\"setting.info\");\n\ny+=h;\ng.drawString(MEM.total+\" JS Variables available\",0,y+=h);\ng.drawString(\"Storage: \"+(require(\"Storage\").getFree()>>10)+\"k free\",0,y+=h);\nif (ENV.STORAGE) g.drawString(\" \"+(ENV.STORAGE>>10)+\"k total\",0,y+=h);\nif (ENV.SPIFLASH) g.drawString(\"SPI Flash: \"+(ENV.SPIFLASH>>10)+\"k\",0,y+=h);\ng.setFontAlign(0,-1);\ng.drawString(NRF.getAddress(),120,232);\ng.flip();\n\n// Pixel chooser image\ng.drawImage(require(\"heatshrink\").decompress(atob(\"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\")),0,135);\ng.flip();\n"); -require('Storage').write("about.img",require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AQqoAHFtovlFxQzOiEQF0QwJFwIwSFyIwIF6YuTGBQule7IvuEp150d5GBS+DSBwtO5wABGA4vUFxvIFwXO44wJF7hcEAAejYJQvYFpAwJF7ejRQgAHF7BcH44tLF47xGF6QtNF8l5vIqFA4gv/R/4vZABwv25ovudYwAHvIvfp+dFxlPFy4wHp9PvPHFo/HFwIvEFqYxHEINP43G4/H5vNAYIHBBgQuaGAgvEAA4vEFzIxDq0zh5YCAAvHh8zqwud/1lssPh+AF4+ABYIPBFroABnUPnPNFwvNnMPnQRDFzgvCh/OdgKMC5vOBIIvEGC4bESAeB5wAErqODGDIbGMAekFwekLw4wWDY9liAoBrpdEiASIFzdloIpBAAkQoITJF7aSERhQvUDhYATF/4v/F74A/AH4A5A="))); -require('Storage').write("about.info","{\"id\":\"about\",\"name\":\"About\",\"src\":\"about.app.js\",\"icon\":\"about.img\",\"version\":\"0.04\",\"files\":\"about.info,about.app.js,about.img\"}"); -require('Storage').write("alarm.app.js","Bangle.loadWidgets();\nBangle.drawWidgets();\n\nvar alarms = require(\"Storage\").readJSON(\"alarm.json\",1)||[];\n/*alarms = [\n { on : true,\n hr : 6.5, // hours + minutes/60\n msg : \"Eat chocolate\",\n last : 0, // last day of the month we alarmed on - so we don't alarm twice in one day!\n rp : true, // repeat\n }\n];*/\n\nfunction formatTime(t) {\n var hrs = 0|t;\n var mins = Math.round((t-hrs)*60);\n return hrs+\":\"+(\"0\"+mins).substr(-2);\n}\n\nfunction getCurrentHr() {\n var time = new Date();\n return time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600);\n}\n\nfunction showMainMenu() {\n const menu = {\n '': { 'title': 'Alarms' },\n 'New Alarm': ()=>editAlarm(-1)\n };\n alarms.forEach((alarm,idx)=>{\n txt = (alarm.on?\"on \":\"off \")+formatTime(alarm.hr);\n if (alarm.rp) txt += \" (repeat)\";\n menu[txt] = function() {\n editAlarm(idx);\n };\n });\n menu['< Back'] = ()=>{load();};\n return E.showMenu(menu);\n}\n\nfunction editAlarm(alarmIndex) {\n var newAlarm = alarmIndex<0;\n var hrs = 12;\n var mins = 0;\n var en = true;\n var repeat = true;\n if (!newAlarm) {\n var a = alarms[alarmIndex];\n hrs = 0|a.hr;\n mins = Math.round((a.hr-hrs)*60);\n en = a.on;\n repeat = a.rp;\n }\n const menu = {\n '': { 'title': 'Alarms' },\n 'Hours': {\n value: hrs,\n onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this'\n },\n 'Minutes': {\n value: mins,\n onchange: function(v){if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;} // no arrow fn -> preserve 'this'\n },\n 'Enabled': {\n value: en,\n format: v=>v?\"On\":\"Off\",\n onchange: v=>en=v\n },\n 'Repeat': {\n value: en,\n format: v=>v?\"Yes\":\"No\",\n onchange: v=>repeat=v\n }\n };\n function getAlarm() {\n var hr = hrs+(mins/60);\n var day = 0;\n // If alarm is for tomorrow not today (eg, in the past), set day\n if (hr < getCurrentHr())\n day = (new Date()).getDate();\n // Save alarm\n return {\n on : en, hr : hr,\n last : day, rp : repeat\n };\n }\n if (newAlarm) {\n menu[\"> New Alarm\"] = function() {\n alarms.push(getAlarm());\n require(\"Storage\").write(\"alarm.json\",JSON.stringify(alarms));\n showMainMenu();\n };\n } else {\n menu[\"> Save\"] = function() {\n alarms[alarmIndex] = getAlarm();\n require(\"Storage\").write(\"alarm.json\",JSON.stringify(alarms));\n showMainMenu();\n };\n }\n menu['< Back'] = showMainMenu;\n return E.showMenu(menu);\n}\n\nshowMainMenu();\n"); -require('Storage').write("alarm.js","// Chances are boot0.js got run already and scheduled *another*\n// 'load(alarm.js)' - so let's remove it first!\nclearInterval();\n\nfunction formatTime(t) {\n var hrs = 0|t;\n var mins = Math.round((t-hrs)*60);\n return hrs+\":\"+(\"0\"+mins).substr(-2);\n}\n\nfunction getCurrentHr() {\n var time = new Date();\n return time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600);\n}\n\nfunction showAlarm(alarm) {\n var msg = formatTime(alarm.hr);\n var buzzCount = 10;\n if (alarm.msg)\n msg += \"\\n\"+alarm.msg;\n E.showPrompt(msg,{\n title:\"ALARM!\",\n buttons : {\"Sleep\":true,\"Ok\":false} // default is sleep so it'll come back in 10 mins\n }).then(function(sleep) {\n buzzCount = 0;\n if (sleep) {\n alarm.hr += 10/60; // 10 minutes\n } else {\n alarm.last = (new Date()).getDate();\n if (!alarm.rp) alarm.on = false;\n }\n require(\"Storage\").write(\"alarm.json\",JSON.stringify(alarms));\n load();\n });\n function buzz() {\n Bangle.buzz(100).then(()=>{\n setTimeout(()=>{\n Bangle.buzz(100).then(function() {\n if (buzzCount--)\n setTimeout(buzz, 3000);\n });\n },100);\n });\n }\n buzz();\n}\n\n// Check for alarms\nvar day = (new Date()).getDate();\nvar hr = getCurrentHr()+10000; // get current time - 10s in future to ensure we alarm if we've started the app a tad early\nvar alarms = require(\"Storage\").readJSON(\"alarm.json\",1)||[];\nvar active = alarms.filter(a=>a.on&&(a.hra.hr-b.hr);\n showAlarm(active[0]);\n} else {\n // otherwise just go back to default app\n setTimeout(load, 100);\n}\n"); -require('Storage').write("alarm.json","[]"); -require('Storage').write("alarm.img",require("heatshrink").decompress(atob("mEwwkGswAhiMRCCAREAo4eHBIQLEAgwYHsIJDiwHB5gACBpIhHCoYZEGA4gFCw4ABGA4HEjgXJ4IXGAwcUB4VEmf//8zogICoJIFAodMBoNDCoIADmgJB4gXIFwXDCwoABngwFC4guB4k/CQXwh4EC+YMCC44iBp4qDC4n/+gNBC41sEIJCEC4v/GAPGC4dhXYRdFC4xhCCYIXCdQRdDC5HzegQXCsxGHC45IDCwQXCUgwXHJAIXGRogXJSIIXcOw4XIPAYXcBwv/mEDBAwXOgtQC65QGC5vzoEAJAx3Nmk/mEABIiPN+dDAQIwFC4zXGFwKRCGAjvMFwQECGAgXI4YuGGAUvAgU8C4/EFwwGCAgdMC4p4EFwobFOwoXDJAIoEAApGBC4xIEABJGHGAapEAAqNBFwwXD4heI+YuBC5BIBVQhdHIw4wD5inFS4IKCCxFmigNCokzCoMzogICoIWIsMRjgPCAA3BiMWC48RBQIXJEgMRFxAJCCw4lEC44IECooOIBAaBJKwhgIAH4ACA=="))); -require('Storage').write("alarm.wid.js","(() => {\n var alarms = require('Storage').readJSON('alarm.json',1)||[];\n alarms = alarms.filter(alarm=>alarm.on);\n if (!alarms.length) return; // no alarms, no widget!\n delete alarms;\n // add the widget\n WIDGETS[\"alarm\"]={area:\"tl\",width:24,draw:function() {\n g.setColor(-1);\n g.drawImage(atob(\"GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA\"),this.x,this.y);\n }};\n})()\n"); -require('Storage').write("alarm.info","{\"id\":\"alarm\",\"name\":\"Alarms\",\"src\":\"alarm.app.js\",\"icon\":\"alarm.img\",\"version\":\"0.04\",\"files\":\"alarm.info,alarm.app.js,alarm.js,alarm.json,alarm.img,alarm.wid.js\"}"); -require('Storage').write("widbat.wid.js","(function(){\nvar CHARGING = 0x07E0;\n\nfunction setWidth() {\n WIDGETS[\"bat\"].width = 40 + (Bangle.isCharging()?16:0);\n}\nfunction draw() {\n var s = 39;\n var x = this.x, y = this.y;\n if (Bangle.isCharging()) {\n g.setColor(CHARGING).drawImage(atob(\"DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg\"),x,y);\n x+=16;\n }\n g.setColor(-1);\n g.fillRect(x,y+2,x+s-4,y+21);\n g.clearRect(x+2,y+4,x+s-6,y+19);\n g.fillRect(x+s-3,y+10,x+s,y+14);\n g.setColor(CHARGING).fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);\n g.setColor(-1);\n}\nBangle.on('charging',function(charging) {\n if(charging) Bangle.buzz();\n setWidth();\n Bangle.drawWidgets(); // relayout widgets\n g.flip();\n});\nvar batteryInterval;\nBangle.on('lcdPower', function(on) {\n if (on) {\n WIDGETS[\"bat\"].draw();\n // refresh once a minute if LCD on\n if (!batteryInterval)\n batteryInterval = setInterval(draw, 60000);\n } else {\n if (batteryInterval) {\n clearInterval(batteryInterval);\n batteryInterval = undefined;\n }\n }\n});\nWIDGETS[\"bat\"]={area:\"tr\",width:40,draw:draw};\nsetWidth();\n})()\n"); -require('Storage').write("widbat.info","{\"id\":\"widbat\",\"name\":\"Battery Level Widget\",\"type\":\"widget\",\"version\":\"0.04\",\"files\":\"widbat.info,widbat.wid.js\"}"); -require('Storage').write("widbt.wid.js","(function(){\nvar img_bt = E.toArrayBuffer(atob(\"CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA==\"));\n\nfunction draw() {\n g.reset();\n if (NRF.getSecurityStatus().connected)\n g.setColor(0,0.5,1);\n else\n g.setColor(0.3,0.3,0.3);\n g.drawImage(img_bt,10+this.x,2+this.y);\n}\nfunction changed() {\n WIDGETS[\"bluetooth\"].draw();\n g.flip();// turns screen on\n}\nNRF.on('connected',changed);\nNRF.on('disconnected',changed);\nWIDGETS[\"bluetooth\"]={area:\"tr\",width:24,draw:draw};\n})()\n"); -require('Storage').write("widbt.info","{\"id\":\"widbt\",\"name\":\"Bluetooth Widget\",\"type\":\"widget\",\"version\":\"0.03\",\"files\":\"widbt.info,widbt.wid.js\"}"); -require('Storage').write("welcome.js","eval(require(\"Storage\").read(\"welcome.app.js\"))\n"); -require('Storage').write("welcome.app.js","// exec each function from seq one after the other\nfunction animate(seq,period) {\n var i = setInterval(function() {\n if (seq.length) {\n var f = seq.shift();\n if (f) f();\n } else clearInterval(i);\n },period);\n}\n\n// Fade in to FG color with angled lines\nfunction fade(callback) {\n var n = 0;\n function f() {\n for (var i=n;i<240;i+=10) {\n g.drawLine(i,0,0,i);\n g.drawLine(i,240,240,i);\n }\n g.flip();\n n++;\n if (n<10) setTimeout(f,0);\n else callback();\n }\n f();\n}\n\n\nvar scenes = [\n function() {\n g.clear(1);\n g.setFont(\"4x6\",2);\n var n=0;\n var i = setInterval(function() {\n n+=0.04;\n g.setColor(n,n,n);\n g.drawImage(Bangle.getLogo(),(240-222)/2,(240-100)/2);\n if (n>=1) {\n clearInterval(i);\n setTimeout(()=>g.drawString(\"Open\",34,144), 500);\n setTimeout(()=>g.drawString(\"Hackable\",34,156), 1000);\n setTimeout(()=>g.drawString(\"Smart Watch\",34,168), 1500);\n }\n },50);\n },function() {\n var img = require(\"heatshrink\").decompress(atob(\"ptRxH+qYAfvl70mj5gAC0ekvd8FkAAdz3HJAYAH4+eJXWkJJYAF0hK2vfNJaIAB5t7S3fN5/V6wAD6vOTg9SumXy2W3QAB3eXul2JdnO63XAApPEVYvAJQIACJoRQDzBLoJQ3W5/NIwr4GJohMFAAROgJYvVJQiPGABZNN3bsdvYyESwnWJSIAC3RNM3V1JjZAES4nVJSYAB4xMNJrbkE56WD5xLVdB5NbFofNJbgABJh26qREPrFXrlbAAWjFgfWJgRLaTQhMLy5KNJINhsJLDrYrD5xLC6pLa5nGTR7oLq9bJQJMKTAXWJbbnR3RLJSoRMHv4pC5rkec6SaIrBLGw2r2XW1epcoqYeJiOXJYziEsOH2RBBw7lF56Yg5nGc6FScZOGJQPX2TmDFIfVTEBMSc4hLEw5KB6+rsJMH63X6pMf5hMQzBLCq5LD1ZLEJhTlfJiWXTA2GJYpMIcwPNc2O6TAuGRIPX1igDJg/PJmyYDcgXWwxMH1ApC53XcsHAJiVYcg2HJYZME0YpC5vWJkhLNJgLlDTAeFJhF/FQfVJkG6JiGXcomyJgOrJYhMErYqD53NJj7lRzBMDcoeGJhzoBJb3GJiN1qZBCJgWyJYpNF1LigAAXAJiNSJgzlGJgt/JkZLRy9TJgeHJhznFcuSZGw5MHJomjcuhLBqdcJiSaiTChMV1CYxy5LCqdXIAWy6+rJhCalTCN2JgdYH4WHJiGpTF7kDc43W2RMJTUZLQzBLFc4mr6+GJh2jTFmXJYyaEwuyc5Sag4xLZTQmG2WFJhxNaJYZMLJZSaEJoOHTR9/Ja+6JbdTqRNETRRNF1JLV4BLcAANYI5ToK1BLYJhWYJZwABq5NoJZ91JaAABdAZNS0ZLey9SJaRNYv5KM426JZmXuxKUJrKcL0lTzBLKzBKYJrVXvfGSol7EYWXJI27zF1JLQADq5NUrgYB4wAEEIV0comXI7wAFrCcPJgYWBTIIAETIN2JYmWuhMkdSdYCgOeJgueqRLFyzhfTi9bq4TC45MF49TuuXJlpONcogAC0hKB0gHDvZMEqRMpAANSq9crlbJAYADqwRDxGk0mIA4eCTQOeveXJdYAHqxNFdAeIAAQGCrOI0oHEAGVXTRJMGvgGCwRM7TAZMHwQGCvhM1rBMERIhMGAwdZJmtSqVTwNcwJEDJg19cvIADa4d9JhANDJnSLHJgrl6AAhFFAwpZDegjn7vhMGcvwABrJAFJgjl/TQpBBI4jl/AAN8TQhHDcv4ADcJBMDvpM+IYaeDAAhL+qd9SgycEJn7iEAA18Jf7nEcv4AIrJLIcv6aMcv4ADvhMHrJJ/AAbl/c6ZM/AAt9cv7nSIv7nLcv4AHrLl/TRpJBvgnjA==\"));\n g.reset();\n g.setColor(\"#6633ff\");\n g.setBgColor(\"#6633ff\");\n var y = 240, speed = 5;\n function balloon(callback) {\n y-=speed;\n var x = (240-77)/2;\n g.drawImage(img,x,y);\n g.clearRect(x,y+81,x+77,y+81+speed);\n if (y>60) setTimeout(balloon,0,callback);\n else callback();\n }\n fade(function() {\n balloon(function() {\n g.setColor(-1);\n g.setFont(\"6x8\",3);\n g.setFontAlign(0,0);\n g.drawString(\"Welcome.\",120,160);\n });\n });\n setTimeout(function() {\n var n=0;\n var i = setInterval(function() {\n n+=5;\n g.scroll(0,-5);\n if (n>170)\n clearInterval(i);\n },20);\n },3500);\n\n },function() {\n g.reset();\n g.setBgColor(\"#ffa800\");g.clear();\n g.setFont(\"6x8\",2);\n g.setFontAlign(0,0);\n var x = 80, y = 35, h=35;\n animate([\n ()=>g.drawString(\"Your\",x,y+=h),\n ()=>g.drawString(\"Bangle.js\",x,y+=h),\n ()=>g.drawString(\"has\",x,y+=h),\n ()=>g.drawString(\"3 buttons\",x,y+=h),\n ()=>{g.setFont(\"Vector\",36);g.drawString(\"1\",200,40);},\n ()=>g.drawString(\"2\",200,120),\n ()=>g.drawString(\"3\",200,200)\n ],200);\n },\n function() {\n g.reset();\n g.setBgColor(\"#00a8ff\");g.clear();\n g.setFontAlign(0,0);\n g.setFont(\"Vector\",48);\n g.drawString(\"1\",200,40);\n g.setFontAlign(-1,-1);\n g.setFont(\"6x8\",2);\n g.drawString(\"Move up\\nin menus\\n\\nTurn Bangle.js on\\nif it was off\", 20,40);\n },\n function() {\n g.reset();\n g.setBgColor(\"#00a8ff\");g.clear();\n g.setFontAlign(0,0);\n g.setFont(\"Vector\",48);\n g.drawString(\"2\",200,120);\n g.setFontAlign(-1,-1);\n g.setFont(\"6x8\",2);\n g.drawString(\"Select menu\\nitem\\n\\nLaunch app\\nwhen watch\\nis showing\", 20,70);\n },\n function() {\n g.reset();\n g.setBgColor(\"#00a8ff\");g.clear();\n g.setFontAlign(0,0);\n g.setFont(\"Vector\",48);\n g.drawString(\"3\",200,200);\n g.setFontAlign(-1,-1);\n g.setFont(\"6x8\",2);\n g.drawString(\"Move down\\nin menus\\n\\nLong press\\nto exit app\\nand go back\\nto clock\", 20,100);\n },\n function() {\n g.reset();\n g.setBgColor(\"#ff3300\");g.clear();\n g.setFontAlign(0,0);\n g.setFont(\"Vector\",48);\n g.drawString(\"1\",200,40);\n g.drawString(\"2\",200,120);\n g.setFontAlign(-1,-1);\n g.setFont(\"6x8\",2);\n g.drawString(\"If Bangle.js\\never stops,\\nhold buttons\\n1 and 2 for\\naround six\\nseconds.\\n\\n\\n\\nBangle.js will\\nthen reboot.\", 20,20);\n },\n function() {\n g.reset();\n g.setBgColor(\"#00a8ff\");g.clear();\n g.setFont(\"6x8\",2);\n g.setFontAlign(0,0);\n var x = 120, y = 10, h=21;\n animate([\n ()=>{g.drawString(\"Bangle.js has a\",x,y+=h);\n g.drawString(\"simple touchscreen\",x,y+=h);},\n 0,0,\n ()=>{g.drawString(\"It'll detect touch\",x,y+=h*2);\n g.drawString(\"on left and right\",x,y+=h);},\n 0,0,\n ()=>{g.drawString(\"Horizontal swipes\",x,y+=h*2);\n g.drawString(\"work too. Try now\",x,y+=h);\n g.drawString(\"to change page.\",x,y+=h);}\n ],300);\n },\n function() {\n g.reset();\n g.setBgColor(\"#339900\");g.clear();\n g.setFont(\"6x8\",2);\n g.setFontAlign(0,0);\n var x = 120, y = 10, h=21;\n animate([\n ()=>{g.drawString(\"Bangle.js\",x,y+=h);\n g.drawString(\"comes with\",x,y+=h);\n g.drawString(\"a few simple\",x,y+=h);\n g.drawString(\"apps installed\",x,y+=h);},\n 0,0,\n ()=>{g.drawString(\"To add more, visit\",x,y+=h*2);\n g.drawString(\"banglejs.com/apps\",x,y+=h);\n g.drawString(\"with a Bluetooth\",x,y+=h);\n g.drawString(\"capable device\",x,y+=h);},\n ],400);\n },\n function() {\n g.reset();\n g.setBgColor(\"#990066\");g.clear();\n g.setFont(\"6x8\",2);\n g.setFontAlign(0,0);\n var x = 120, y = 10, h=21;\n g.drawString(\"You can also make\",x,y+=h);\n g.drawString(\"your own apps!\",x,y+=h);\n y=160;\n g.drawString(\"Check out\",x,y+=h);\n g.drawString(\"banglejs.com\",x,y+=h);\n\n var rx = 0, ry = 0;\n var h = Graphics.createArrayBuffer(96,96,1,{msb:true});\n // draw a cube\n function draw() {\n // rotate\n rx += 0.1;\n ry += 0.11;\n var rcx=Math.cos(rx),\n rsx=Math.sin(rx),\n rcy=Math.cos(ry),\n rsy=Math.sin(ry);\n // Project 3D coordinates into 2D\n function p(x,y,z) {\n var t;\n t = x*rcy + z*rsy;\n z = z*rcy - x*rsy;\n x=t;\n t = y*rcx + z*rsx;\n z = z*rcx - y*rsx;\n y=t;\n z += 4;\n return [96*(0.5+x/z), 96*(0.5+y/z)];\n }\n\n var a;\n // draw a series of lines to make up our cube\n h.clear();\n a = p(-1,-1,-1); h.moveTo(a[0],a[1]);\n a = p(1,-1,-1); h.lineTo(a[0],a[1]);\n a = p(1,1,-1); h.lineTo(a[0],a[1]);\n a = p(-1,1,-1); h.lineTo(a[0],a[1]);\n a = p(-1,-1,-1); h.lineTo(a[0],a[1]);\n a = p(-1,-1,1); h.moveTo(a[0],a[1]);\n a = p(1,-1,1); h.lineTo(a[0],a[1]);\n a = p(1,1,1); h.lineTo(a[0],a[1]);\n a = p(-1,1,1); h.lineTo(a[0],a[1]);\n a = p(-1,-1,1); h.lineTo(a[0],a[1]);\n a = p(-1,-1,-1); h.moveTo(a[0],a[1]);\n a = p(-1,-1,1); h.lineTo(a[0],a[1]);\n a = p(1,-1,-1); h.moveTo(a[0],a[1]);\n a = p(1,-1,1); h.lineTo(a[0],a[1]);\n a = p(1,1,-1); h.moveTo(a[0],a[1]);\n a = p(1,1,1); h.lineTo(a[0],a[1]);\n a = p(-1,1,-1); h.moveTo(a[0],a[1]);\n a = p(-1,1,1); h.lineTo(a[0],a[1]);\n g.drawImage({width:96,height:96,buffer:h.buffer},(240-96)/2,68);\n }\n\n setInterval(draw,50);\n },\n function() {\n g.reset();\n g.setBgColor(\"#660099\");g.clear();\n g.setFontAlign(0,0);\n g.setFont(\"Vector\",36);\n g.drawString(\"2\",200,120);\n g.setFont(\"6x8\",2);\n\n var x = 90, y = 30, h=21;\n animate([\n ()=>g.drawString(\"That's it!\",x,y+=h),\n ()=>{g.drawString(\"Press\",x,y+=h*3);\n g.drawString(\"Button 2\",x,y+=h);\n g.drawString(\"to start\",x,y+=h);\n g.drawString(\"Bangle.js\",x,y+=h);}\n ],400);\n }\n];\n\nvar sceneNumber = 0;\n\nfunction move(dir) {\n if (dir>0 && sceneNumber+1 == scenes.length) return; // at the end\n sceneNumber = (sceneNumber+dir)%scenes.length;\n if (sceneNumber<0) sceneNumber=0;\n clearInterval();\n scenes[sceneNumber]();\n if (sceneNumber>1) {\n var l = scenes.length;\n for (var i=0;imove(1), BTN3, {repeat:true});\nsetWatch(()=>{\n // If we're on the last page\n if (sceneNumber == scenes.length-1) {\n var settings = require(\"Storage\").readJSON('setting.json',1)||{};\n settings.welcomed = true;\n require(\"Storage\").write('setting.json',settings);\n load();\n }\n}, BTN2, {repeat:true,edge:\"rising\"});\nsetWatch(()=>move(-1), BTN1, {repeat:true});\n\n\n\nBangle.setLCDTimeout(0);\nBangle.setLCDPower(1);\nmove(0);\n"); -require('Storage').write("welcome.img",require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AU5gAEFtoxnEwXN53WAAXO5oJB42Wy26AAIueFoPXFggAD4AwEGTQiB6otBFgwAD3QvFGC5dCFxiRGGClhrdbv67BXAIuLMBIwPsIABF4OpLwXOFxjBCF6gtBw2r1mHXoXWFxqQWFwOH62rL4IeB6xeOAAIvHGBYuC6+rR4QvCXpovXw3X1i/DR4QuPR5AvKFQOs6+GF4eod4IvPd5AvLwvWLwQvCv4fBR54vURwOHF4iQCX0yOCF4aQBX0QvHSAoAN3SOSd4WyF4yQPLyhgD1YvDMCJeIFxhgCF47BN4BeHFxpgDSAiRORpAuPMIYAFGBYuaF5aSHFwQvEFqQwOeggSBLa4xNF4X+4wAC/xeCFjIADrYwGBIIvlMQiPDBAOk0gDBz2XF8BlEF4eIxADFF8lcF9n+wIrFF05bHF9AsGF9wupGAYv/F8QupGAov/F/4wOF1gA/AH4Ap"))); -require('Storage').write("welcome.info","{\"id\":\"welcome\",\"name\":\"Welcome\",\"src\":\"welcome.app.js\",\"icon\":\"welcome.img\",\"version\":\"0.04\",\"files\":\"welcome.info,welcome.js,welcome.app.js,welcome.img\"}"); From 04f8cbcd139409b5ca1b4e6b19d85061abeaf024 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 31 Mar 2020 13:37:03 +0100 Subject: [PATCH 0113/1189] write code in chunks, in case it is too big to fit in RAM (fix #157) --- js/appinfo.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/js/appinfo.js b/js/appinfo.js index 151227f45..613d15379 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -27,14 +27,19 @@ var AppInfo = { // then map each file to a command to load into storage fileContents.forEach(storageFile => { // format ready for Espruino - var js; if (storageFile.evaluate) { - js = storageFile.content.trim(); + let js = storageFile.content.trim(); if (js.endsWith(";")) js = js.slice(0,-1); - } else - js = toJS(storageFile.content); - storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${js});`; + storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${js});`; + } else { + let code = storageFile.content; + // write code in chunks, in case it is too big to fit in RAM (fix #157) + var CHUNKSIZE = 4096; + storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${toJS(code.substr(0,CHUNKSIZE))},0,${code.length});`; + for (var i=CHUNKSIZE;i reject(err)); From 8fce6d7f37609f5f179965f8c3e42840f6dc6d17 Mon Sep 17 00:00:00 2001 From: Nik Martin Date: Tue, 31 Mar 2020 08:36:18 -0500 Subject: [PATCH 0114/1189] bring changelog from dev branch --- apps/aclock/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/aclock/ChangeLog b/apps/aclock/ChangeLog index 7819dbe2a..a179800be 100644 --- a/apps/aclock/ChangeLog +++ b/apps/aclock/ChangeLog @@ -1 +1,7 @@ 0.02: Modified for use with new bootloader and firmware +0.03: add hour ticks, remove timers +0.04: add day-date display +0.07: make date and face bigger +0.08: make dots bigger and date more readable +0.09: center date, remove box around it, internal refactor to remove redundant code. +0.10: remove debug, refactor seconds to show elapsed secs each time app is displayed From dd0e3c89d1b5f3bc57e60f5654acb962f56f4162 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 31 Mar 2020 14:39:59 +0100 Subject: [PATCH 0115/1189] Added showModal/hideModal utility functions Added readStorageFile/eraseStorageFile to handle efficiently downloading large files (fix #119) --- apps/gpsrec/interface.html | 45 ++++++------------------------ apps/heart/interface.html | 45 ++++++------------------------ js/comms.js | 45 ++++++++++++++++++++++++++++++ js/index.js | 8 ++++++ lib/interface.js | 56 +++++++++++++++++++++++++++++++++++--- 5 files changed, 123 insertions(+), 76 deletions(-) diff --git a/apps/gpsrec/interface.html b/apps/gpsrec/interface.html index b87d75b3c..bc8dc48e1 100644 --- a/apps/gpsrec/interface.html +++ b/apps/gpsrec/interface.html @@ -5,32 +5,9 @@

- - + diff --git a/js/comms.js b/js/comms.js index e2cbf0cdd..91ae54b68 100644 --- a/js/comms.js +++ b/js/comms.js @@ -9,14 +9,19 @@ reset : (opt) => new Promise((resolve,reject) => { }); }), uploadApp : (app,skipReset) => { + Progress.show({title:`Uploading ${app.name}`,sticky:true}); return AppInfo.getFiles(app, httpGet).then(fileContents => { return new Promise((resolve,reject) => { console.log("uploadApp",fileContents.map(f=>f.name).join(", ")); + var maxBytes = fileContents.reduce((b,f)=>b+f.content.length, 0)||1; + var currentBytes = 0; + // Upload each file one at a time function doUploadFiles() { // No files left - print 'reboot' message if (fileContents.length==0) { Puck.write(`\x10E.showMessage('Hold BTN3\\nto reload')\n`,(result) => { + Progress.hide({sticky:true}); if (result===null) return reject(""); resolve(app); }); @@ -24,17 +29,27 @@ uploadApp : (app,skipReset) => { } var f = fileContents.shift(); console.log(`Upload ${f.name} => ${JSON.stringify(f.content)}`); + Progress.show({ + min:currentBytes / maxBytes, + max:(currentBytes+f.content.length) / maxBytes}); + currentBytes += f.content.length; // Chould check CRC here if needed instead of returning 'OK'... // E.CRC32(require("Storage").read(${JSON.stringify(app.name)})) Puck.write(`\x10${f.cmd};Bluetooth.println("OK")\n`,(result) => { - if (!result || result.trim()!="OK") return reject("Unexpected response "+(result||"")); + if (!result || result.trim()!="OK") { + Progress.hide({sticky:true}); + return reject("Unexpected response "+(result||"")); + } doUploadFiles(); }, true); // wait for a newline } // Start the upload function doUpload() { Puck.write(`\x10E.showMessage('Uploading\\n${app.id}...')\n`,(result) => { - if (result===null) return reject(""); + if (result===null) { + Progress.hide({sticky:true}); + return reject(""); + } doUploadFiles(); }); } @@ -48,10 +63,15 @@ uploadApp : (app,skipReset) => { }); }, getInstalledApps : () => { + Progress.show({title:`Getting app list...`,sticky:true}); return new Promise((resolve,reject) => { Puck.write("\x03",(result) => { - if (result===null) return reject(""); + if (result===null) { + Progress.hide({sticky:true}); + return reject(""); + } Puck.eval('require("Storage").list(/\.info$/).map(f=>{var j=require("Storage").readJSON(f,1)||{};j.id=f.slice(0,-5);return j})', (appList,err) => { + Progress.hide({sticky:true}); if (appList===null) return reject(err || ""); console.log("getInstalledApps", appList); resolve(appList); @@ -60,6 +80,7 @@ getInstalledApps : () => { }); }, removeApp : app => { // expects an app structure + Progress.show({title:`Removing ${app.name}`,sticky:true}); var storage = [{name:app.id+".info"}].concat(app.storage); var cmds = storage.map(file=>{ return `\x10require("Storage").erase(${toJS(file.name)});\n`; @@ -67,15 +88,21 @@ removeApp : app => { // expects an app structure console.log("removeApp", cmds); return Comms.reset().then(new Promise((resolve,reject) => { Puck.write(`\x03\x10E.showMessage('Erasing\\n${app.id}...')${cmds}\x10E.showMessage('Hold BTN3\\nto reload')\n`,(result) => { + Progress.hide({sticky:true}); if (result===null) return reject(""); resolve(); }); - })); + })).catch(function(reason) { + Progress.hide({sticky:true}); + return Promise.reject(reason); + }); }, removeAllApps : () => { + Progress.show({title:"Removing all apps",progess:"animate",sticky:true}); return new Promise((resolve,reject) => { // Use write with newline here so we wait for it to finish Puck.write('\x10E.showMessage("Erasing...");require("Storage").eraseAll();Bluetooth.println("OK");reset()\n', (result,err) => { + Progress.hide({sticky:true}); if (!result || result.trim()!="OK") return reject(err || ""); resolve(); }, true /* wait for newline */); @@ -171,10 +198,10 @@ readStorageFile : (filename) => { // StorageFiles are different to normal storag fileContent = fileContent.substr(newLineIdx+1); } } else { - showProgress(undefined,100*fileContent.length / (fileSize||1000000)); + Progress.show({percent:100*fileContent.length / (fileSize||1000000)}); } if (finished) { - hideProgress(); + Progress.hide(); connection.received = ""; connection.cb = undefined; resolve(fileContent); @@ -188,7 +215,7 @@ readStorageFile : (filename) => { // StorageFiles are different to normal storag while (l!==undefined) { Bluetooth.print(l); l = f.readLine(); } Bluetooth.print("\xFF"); })()\n`,() => { - showProgress(`Reading ${JSON.stringify(filename)}`,0); + Progress.show({title:`Reading ${JSON.stringify(filename)}`,percent:0}); console.log(`StorageFile read started...`); }); }); diff --git a/js/index.js b/js/index.js index b21fc907d..60b66436a 100644 --- a/js/index.js +++ b/js/index.js @@ -14,119 +14,7 @@ httpGet("apps.json").then(apps=>{ refreshFilter(); }); -// Status // =========================================== Top Navigation -function showToast(message, type) { - // toast-primary, toast-success, toast-warning or toast-error - var style = "toast-primary"; - if (type=="success") style = "toast-success"; - else if (type=="error") style = "toast-error"; - else if (type!==undefined) console.log("showToast: unknown toast "+type); - var toastcontainer = document.getElementById("toastcontainer"); - var msgDiv = htmlElement(`
`); - msgDiv.innerHTML = message; - toastcontainer.append(msgDiv); - setTimeout(function() { - msgDiv.remove(); - }, 5000); -} -var progressToast; // the DOM element -var progressSticky; // showProgress(,,"sticky") don't remove until hideProgress("sticky") -var progressInterval; // the interval used if showProgress(..., "animate") -var progressPercent; // the current progress percentage -function showProgress(text, percent, sticky) { - if (sticky=="sticky") - progressSticky = true; - if (!progressToast) { - if (progressInterval) { - clearInterval(progressInterval); - progressInterval = undefined; - } - if (percent == "animate") { - progressInterval = setInterval(function() { - progressPercent += 2; - if (progressPercent>100) progressPercent=0; - showProgress(undefined, progressPercent); - }, 100); - percent = 0; - } - progressPercent = percent; - - var toastcontainer = document.getElementById("toastcontainer"); - progressToast = htmlElement(`
- ${text ? `
${text}
`:``} -
-
-
-
`); - toastcontainer.append(progressToast); - } else { - var pt=document.getElementById("progressToast"); - pt.setAttribute("aria-valuenow",percent); - pt.style.width = percent+"%"; - } -} -function hideProgress(sticky) { - if (progressSticky && sticky!="sticky") - return; - progressSticky = false; - if (progressInterval) { - clearInterval(progressInterval); - progressInterval = undefined; - } - if (progressToast) progressToast.remove(); - progressToast = undefined; -} - -Puck.writeProgress = function(charsSent, charsTotal) { - if (charsSent===undefined) { - hideProgress(); - return; - } - var percent = Math.round(charsSent*100/charsTotal); - showProgress(undefined, percent); -} -function showPrompt(title, text, buttons) { - if (!buttons) buttons={yes:1,no:1}; - return new Promise((resolve,reject) => { - var modal = htmlElement(``); - document.body.append(modal); - modal.querySelector("a[href='#close']").addEventListener("click",event => { - event.preventDefault(); - reject("User cancelled"); - modal.remove(); - }); - htmlToArray(modal.getElementsByTagName("button")).forEach(button => { - button.addEventListener("click",event => { - event.preventDefault(); - var isYes = event.target.getAttribute("isyes")=="1"; - if (isYes) resolve(); - else reject("User cancelled"); - modal.remove(); - }); - }); - }); -} function showChangeLog(appid) { var app = appNameToApp(appid); function show(contents) { @@ -170,12 +58,11 @@ function handleCustomApp(appTemplate) { Object.keys(appFiles).forEach(k => app[k] = appFiles[k]); console.log("Received custom app", app); modal.remove(); - showProgress(`Uploading ${app.name}`,undefined,"sticky"); Comms.uploadApp(app).then(()=>{ - hideProgress("sticky"); + Progress.hide({sticky:true}); resolve(); }).catch(e => { - hideProgress("sticky"); + Progress.hide({sticky:true}); reject(e); }); }, false); @@ -334,9 +221,8 @@ function refreshLibrary() { // upload icon.classList.remove("icon-upload"); icon.classList.add("loading"); - showProgress(`Uploading ${app.name}`,undefined,"sticky"); Comms.uploadApp(app).then((appJSON) => { - hideProgress("sticky"); + Progress.hide({sticky:true}); if (appJSON) appsInstalled.push(appJSON); showToast(app.name+" Uploaded!", "success"); icon.classList.remove("loading"); @@ -344,7 +230,7 @@ function refreshLibrary() { refreshMyApps(); refreshLibrary(); }).catch(err => { - hideProgress("sticky"); + Progress.hide({sticky:true}); showToast("Upload failed, "+err, "error"); icon.classList.remove("loading"); icon.classList.add("icon-upload"); @@ -403,19 +289,16 @@ function customApp(app) { function updateApp(app) { if (app.custom) return customApp(app); - showProgress(`Upgrading ${app.name}`,undefined,"sticky"); return Comms.removeApp(app).then(()=>{ showToast(app.name+" removed successfully. Updating...",); appsInstalled = appsInstalled.filter(a=>a.id!=app.id); return Comms.uploadApp(app); }).then((appJSON) => { - hideProgress("sticky"); if (appJSON) appsInstalled.push(appJSON); showToast(app.name+" Updated!", "success"); refreshMyApps(); refreshLibrary(); }, err=>{ - hideProgress("sticky"); showToast(app.name+" update failed, "+err,"error"); refreshMyApps(); refreshLibrary(); @@ -488,18 +371,15 @@ return `
function getInstalledApps() { showLoadingIndicator("myappscontainer"); - showProgress(`Getting app list...`,undefined,"sticky"); // Get apps and files return Comms.getInstalledApps() .then(appJSON => { - hideProgress("sticky"); appsInstalled = appJSON; refreshMyApps(); refreshLibrary(); }) .then(() => handleConnectionChange(true)) .catch(err=>{ - hideProgress("sticky"); return Promise.reject(); }); } @@ -555,15 +435,14 @@ document.getElementById("settime").addEventListener("click",event=>{ }); document.getElementById("removeall").addEventListener("click",event=>{ showPrompt("Remove All","Really remove all apps?").then(() => { - showProgress("Removing all apps","animate", "sticky"); return Comms.removeAllApps(); }).then(()=>{ - hideProgress("sticky"); + Progress.hide({sticky:true}); appsInstalled = []; showToast("All apps removed","success"); return getInstalledApps(); }).catch(err=>{ - hideProgress("sticky"); + Progress.hide({sticky:true}); showToast("App removal failed, "+err,"error"); }); }); @@ -578,24 +457,23 @@ document.getElementById("installdefault").addEventListener("click",event=>{ appCount = defaultApps.length; return showPrompt("Install Defaults","Remove everything and install default apps?"); }).then(() => { - showProgress("Removing all apps","animate", "sticky"); return Comms.removeAllApps(); }).then(()=>{ - hideProgress("sticky"); + 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(); - showProgress(`${app.name} (${appCount-defaultApps.length}/${appCount})`,undefined,"sticky"); + Progress.show({title:`${app.name} (${appCount-defaultApps.length}/${appCount})`,sticky:true}); Comms.uploadApp(app,"skip_reset").then((appJSON) => { - hideProgress("sticky"); + Progress.hide({sticky:true}); if (appJSON) appsInstalled.push(appJSON); showToast(`(${appCount-defaultApps.length}/${appCount}) ${app.name} Uploaded`); upload(); }).catch(function() { - hideProgress("sticky"); + Progress.hide({sticky:true}); reject() }); } @@ -607,7 +485,7 @@ document.getElementById("installdefault").addEventListener("click",event=>{ showToast("Default apps successfully installed!","success"); return getInstalledApps(); }).catch(err=>{ - hideProgress("sticky"); + Progress.hide({sticky:true}); showToast("App Install failed, "+err,"error"); }); }); diff --git a/js/ui.js b/js/ui.js new file mode 100644 index 000000000..c88091872 --- /dev/null +++ b/js/ui.js @@ -0,0 +1,140 @@ +// General UI tools (progress bar, toast, prompt) + +/// Handle progress bars +var Progress = { + domElement : null, // the DOM element + sticky : false, // Progress.show({..., sticky:true}) don't remove until Progress.hide({sticky:true}) + interval : undefined, // the interval used if Progress.show({progress:"animate"}) + percent : undefined, // the current progress percentage + min : 0, // scaling for percentage + max : 1, // scaling for percentage + + /* Show a Progress message + Progress.show({ + sticky : bool // keep showing text even when Progress.hide is called (unless Progress.hide({sticky:true})) + percent : number | "animate" + min : // minimum scale for percentage (default 0) + max : // maximum scale for percentage (default 1) + }) */ + show : function(options) { + options = options||{}; + var text = options.title; + if (options.sticky) Progress.sticky = true; + if (options.min!==undefined) Progress.min = options.min; + if (options.max!==undefined) Progress.max = options.max; + var percent = options.percent; + if (percent!==undefined) + percent = Progress.min*100 + (Progress.max-Progress.min)*percent; + if (!Progress.domElement) { + if (Progress.interval) { + clearInterval(Progress.interval); + Progress.interval = undefined; + } + if (percent == "animate") { + Progress.interval = setInterval(function() { + Progress.percent += 2; + if (Progress.percent>100) Progress.percent=0; + Progress.show({percent:Progress.percent}); + }, 100); + percent = 0; + } + + var toastcontainer = document.getElementById("toastcontainer"); + Progress.domElement = htmlElement(`
+ ${text ? `
${text}
`:``} +
+
+
+
`); + toastcontainer.append(Progress.domElement); + } else { + var pt=document.getElementById("Progress.domElement"); + pt.setAttribute("aria-valuenow",percent); + pt.style.width = percent+"%"; + } + }, + // Progress.hide({sticky:true}) undoes Progress.show({title:"title", sticky:true}) + hide : function(options) { + options = options||{}; + if (Progress.sticky && !options.sticky) + return; + Progress.sticky = false; + Progress.min = 0; + Progress.max = 1; + if (Progress.interval) { + clearInterval(Progress.interval); + Progress.interval = undefined; + } + if (Progress.domElement) Progress.domElement.remove(); + Progress.domElement = undefined; + } +}; + +/// Add progress handler so we get nice uploads +Puck.writeProgress = function(charsSent, charsTotal) { + if (charsSent===undefined) { + Progress.hide(); + return; + } + var percent = Math.round(charsSent*100/charsTotal); + Progress.show({percent: percent}); +} + +/// Show a 'toast' message for status +function showToast(message, type) { + // toast-primary, toast-success, toast-warning or toast-error + var style = "toast-primary"; + if (type=="success") style = "toast-success"; + else if (type=="error") style = "toast-error"; + else if (type!==undefined) console.log("showToast: unknown toast "+type); + var toastcontainer = document.getElementById("toastcontainer"); + var msgDiv = htmlElement(`
`); + msgDiv.innerHTML = message; + toastcontainer.append(msgDiv); + setTimeout(function() { + msgDiv.remove(); + }, 5000); +} + +/// Show a yes/no prompt +function showPrompt(title, text, buttons) { + if (!buttons) buttons={yes:1,no:1}; + return new Promise((resolve,reject) => { + var modal = htmlElement(``); + document.body.append(modal); + modal.querySelector("a[href='#close']").addEventListener("click",event => { + event.preventDefault(); + reject("User cancelled"); + modal.remove(); + }); + htmlToArray(modal.getElementsByTagName("button")).forEach(button => { + button.addEventListener("click",event => { + event.preventDefault(); + var isYes = event.target.getAttribute("isyes")=="1"; + if (isYes) resolve(); + else reject("User cancelled"); + modal.remove(); + }); + }); + }); +} From f66aab5823c6b1974c38ebf729c223017740773b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 3 Apr 2020 15:15:06 +0100 Subject: [PATCH 0196/1189] Add page to export files from Stopwatch, save files in better format and with better filename --- apps.json | 3 +- apps/heart/interface.html | 12 +---- apps/swatch/ChangeLog | 1 + apps/swatch/interface.html | 90 ++++++++++++++++++++++++++++++++++++++ apps/swatch/stopwatch.js | 32 +++++++------- lib/interface.js | 18 +++++++- 6 files changed, 128 insertions(+), 28 deletions(-) create mode 100644 apps/swatch/interface.html diff --git a/apps.json b/apps.json index d502b37c4..18d20b9da 100644 --- a/apps.json +++ b/apps.json @@ -392,7 +392,8 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.03", + "version":"0.04", + "interface": "interface.html", "description": "Simple stopwatch with Lap Time logging to a JSON file", "tags": "health", "allow_emulator":true, diff --git a/apps/heart/interface.html b/apps/heart/interface.html index 177e2cdfb..4a21d2e27 100644 --- a/apps/heart/interface.html +++ b/apps/heart/interface.html @@ -11,17 +11,7 @@ var domRecords = document.getElementById("records"); function saveRecord(record,name) { var csv = `${record.map(rec=>[rec.time, rec.bpm, rec.confidence].join(",")).join("\n")}`; - var a = document.createElement("a"), - file = new Blob([csv], {type: "Comma-separated value file"}); - var url = URL.createObjectURL(file); - a.href = url; - a.download = name+".csv"; - document.body.appendChild(a); - a.click(); - setTimeout(function() { - document.body.removeChild(a); - window.URL.revokeObjectURL(url); - }, 0); + Util.saveCSV(name, csv); } diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index 86a782585..2900c9aa1 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -3,3 +3,4 @@ Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen 0.03: Added ability to save Lap log as a date named JSON file into memory Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running +0.04: Changed save file filename, add interface.html to allow laps to be loaded diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html new file mode 100644 index 000000000..928c5fe39 --- /dev/null +++ b/apps/swatch/interface.html @@ -0,0 +1,90 @@ + + + + + +
+ + + + + diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index d4136d8ed..2ebd8198b 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -4,7 +4,6 @@ var started = false; var timeY = 60; var hsXPos = 0; var lapTimes = []; -var saveTimes = []; var displayInterval; function timeToText(t) { @@ -25,7 +24,7 @@ function updateLabels() { for (var i in lapTimes) { if (i<18) {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 30 + i*8);} - else + else {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-18)*8);} } drawsecs(); @@ -51,10 +50,8 @@ function drawms() { g.clearRect(hsXPos,timeY,220,timeY+20); g.drawString("."+("0"+hs).substr(-2),hsXPos,timeY+10); } -function saveconvert() { - for (var v in lapTimes){ - saveTimes[v]=v+1+"-"+timeToText(lapTimes[(lapTimes.length-1)-v]); - } +function getLapTimesArray() { + return lapTimes.map(timeToText).reverse(); } setWatch(function() { // Start/stop @@ -80,16 +77,21 @@ setWatch(function() { // Start/stop }, BTN2, {repeat:true}); setWatch(function() { // Lap Bangle.beep(); - if (started) tCurrent = Date.now(); - lapTimes.unshift(tCurrent-tStart); - tStart = tCurrent; - if (!started) - { - var timenow= Date(); - saveconvert(); - require("Storage").writeJSON("StpWch-"+timenow.toString(), saveTimes); + if (started) { + tCurrent = Date.now(); + lapTimes.unshift(tCurrent-tStart); + } + tStart = tCurrent; + if (!started) { // save + var timenow= Date(); + var filename = "swatch-"+(new Date()).toISOString().substr(0,16).replace("T","_")+".json"; + // this maxes out the 28 char maximum + require("Storage").writeJSON(filename, getLapTimesArray()); + E.showMessage("Laps Saved","Stopwatch"); + setTimeout(updateLabels, 1000); + } else { + updateLabels(); } - updateLabels(); }, BTN1, {repeat:true}); setWatch(function() { // Reset if (!started) { diff --git a/lib/interface.js b/lib/interface.js index 414c9d7fb..7e8be4fd9 100644 --- a/lib/interface.js +++ b/lib/interface.js @@ -39,7 +39,10 @@ var Util = { window.postMessage({type:"readstoragefile",data:filename,id:__id}); }, eraseStorageFile : function(filename,callback) { - Puck.write(`\x10require("Storage").open(${JSON.stringify(filename)}","r").erase()\n`,callback); + Puck.write(`\x10require("Storage").open(${JSON.stringify(filename)},"r").erase()\n`,callback); + }, + eraseStorage : function(filename,callback) { + Puck.write(`\x10require("Storage").erase(${JSON.stringify(filename)})\n`,callback); }, showModal : function(title) { if (!Util.domModal) { @@ -66,6 +69,19 @@ var Util = { hideModal : function() { if (!Util.domModal) return; Util.domModal.classList.remove("active"); + }, + saveCSV : function(filename, csvData) { + var a = document.createElement("a"), + file = new Blob([csvData], {type: "Comma-separated value file"}); + var url = URL.createObjectURL(file); + a.href = url; + a.download = filename+".csv"; + document.body.appendChild(a); + a.click(); + setTimeout(function() { + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }, 0); } }; window.addEventListener("message", function(event) { From fbce9aaa7cd1bddaefa71ee8a9b15fb54912d7f1 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 3 Apr 2020 15:24:09 +0100 Subject: [PATCH 0197/1189] stopwatch - Added widgets --- apps.json | 2 +- apps/swatch/ChangeLog | 1 + apps/swatch/stopwatch.js | 14 +++++++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 18d20b9da..dcb27d1d1 100644 --- a/apps.json +++ b/apps.json @@ -392,7 +392,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.04", + "version":"0.05", "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 2900c9aa1..3246eeced 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -4,3 +4,4 @@ 0.03: Added ability to save Lap log as a date named JSON file into memory Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running 0.04: Changed save file filename, add interface.html to allow laps to be loaded +0.05: Added widgets diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 2ebd8198b..6f8ad9e34 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -13,24 +13,26 @@ function timeToText(t) { return mins+":"+("0"+secs).substr(-2)+"."+("0"+hs).substr(-2); } function updateLabels() { - g.clear(); + g.reset(1); + g.clearRect(0,23,g.getWidth()-1,g.getHeight()-24); g.setFont("6x8",2); g.setFontAlign(0,0,3); g.drawString(started?"STOP":"GO",230,120); - if (!started) g.drawString("RESET",230,190); + if (!started) g.drawString("RESET",230,180); g.drawString(started?"LAP":"SAVE",230,50); g.setFont("6x8",1); g.setFontAlign(-1,-1); for (var i in lapTimes) { - if (i<18) + if (i<16) {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 30 + i*8);} - else - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-18)*8);} + else if (i<32) + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-16)*8);} } drawsecs(); } function drawsecs() { var t = tCurrent-tStart; + g.reset(1); g.setFont("Vector",48); g.setFontAlign(0,0); var secs = Math.floor(t/1000)%60; @@ -103,3 +105,5 @@ setWatch(function() { // Reset }, BTN3, {repeat:true}); updateLabels(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); From c60be707d82f9a3de6d0073afd8ba2dade9ecaa7 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Fri, 3 Apr 2020 17:37:54 +0200 Subject: [PATCH 0198/1189] Added PWA and Browser Theme Support Add more favicon resolutions Add Progressive Web App Support Add Theme and Icon support for Safari Add Theme and Icon Support for Windows Metro Add Theme and Icon Support for Android Chrome Signed-off-by: OmegaRogue --- Bangle.js.svg | 478 +++++++++++++++++++++++++++++++++ browserconfig.xml | 9 + favicon.ico | Bin 1150 -> 0 bytes img/android-chrome-192x192.png | Bin 0 -> 4534 bytes img/android-chrome-512x512.png | Bin 0 -> 13713 bytes img/apple-touch-icon.png | Bin 0 -> 2905 bytes img/favicon-16x16.png | Bin 0 -> 586 bytes img/favicon-32x32.png | Bin 0 -> 860 bytes img/favicon.ico | Bin 0 -> 15086 bytes img/mstile-150x150.png | Bin 0 -> 3364 bytes img/safari-pinned-tab.svg | 100 +++++++ index.html | 13 +- site.webmanifest | 19 ++ 13 files changed, 618 insertions(+), 1 deletion(-) create mode 100644 Bangle.js.svg create mode 100644 browserconfig.xml delete mode 100644 favicon.ico create mode 100644 img/android-chrome-192x192.png create mode 100644 img/android-chrome-512x512.png create mode 100644 img/apple-touch-icon.png create mode 100644 img/favicon-16x16.png create mode 100644 img/favicon-32x32.png create mode 100644 img/favicon.ico create mode 100644 img/mstile-150x150.png create mode 100644 img/safari-pinned-tab.svg create mode 100644 site.webmanifest diff --git a/Bangle.js.svg b/Bangle.js.svg new file mode 100644 index 000000000..90c908c9b --- /dev/null +++ b/Bangle.js.svg @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browserconfig.xml b/browserconfig.xml new file mode 100644 index 000000000..0d56ca0d6 --- /dev/null +++ b/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #5755d9 + + + diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index 24ae659663f56ad85ce80aa656cd909b5977d7ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 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 COGRY> literal 0 HcmV?d00001 diff --git a/img/android-chrome-512x512.png b/img/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..6a147322241d7824b7d762c9e8d74c3c449c6769 GIT binary patch literal 13713 zcmZ|0Wk6KT8}NOor52>S8>Abg8x|xLSm|CG1Zh}8K)SnIK_pg66p(IMLQonc6r~ga z5#Gc7{GSichxg0wTxYJDIWu#1&-~_v!9z_V0y+W!0Eo1;)QkWC6D(o^c-Y{Vl@Egt z_=WAPtfveB&8dXfwm6{7Vy|VS2LQob0Dz1EfGhA4avuQvg#qB34FJgI0RXjkQJ0|{ zSb=E=(^La)<5DMjKnd4RTTdN#2OEo&nvgfrQxyQjCAHO*O#(mvC=Ng}K3cw243PTL z%K2_tZ#69@O-YM|1n)f$9vTOMRx=D|!^8U!k4L4XJWtIp#G@CSPK;@XK|zuRAkwU~ z)(<^f-XFd1Q6$Uh9QE|wU3+j=lpmyUrccGSd{iWJRxGn8w-;o`gWhRXto4=N=1t4V zP~LL4BaYY%%E?Hhs^n=inoMpei&NuCeZ00Iep*d$Zg}WGFg?e4lNTH^e~blzNukh+ z%Vn0sZJfIO}_L{1BXGDYll_P(E3JUo5P@Y; z6CxlP2ZbjAM9|V*76ZWZEFGAEWF=&STLzk)V}tXY4(bjXg=f@40JV2YU5;Q}?Z#)J zNmwQ)&-cL z;$thNUnT=J)%uYNj`4IzM$q4jSd6fQAxwA_9kLX<;L-Gir$QGVg?SgXzJ5Inx@e~K z0Bm8ZoaMit?ADo;pCjpz5iSb7(<4rKC~Ta&xMsue!yH6(&oDnD!MZvO=~+tB`*$|J zdU)S#>bNvpF(iQ7x_QB)G9%SUcO{};#aH6gjnS-E@(x&FKa|@lJ@j)!QG(g1r%Z)# z8&;JoNrHEZTE;{h)|3#MoQMJ)^zh6Om#Q_!VlIPGtoP4z9a>(ZS<~gfOhE@vjH}C) zPC*ZY2A1ca6E^9nSyMqZ=v;5^>pCb=)O z%PG*O1Nr_r9`q4zP)2C=FXPRoAsS3kxjDA`7mSI$np2HY0#M{x&|eLIA)-T#=?Kp3 zXg-}PPO~u=&<&W$y;wJjUI03mlYS?>lA!JdOupsVn9l><+=Z?ldl)>GMsO9>Y|4TB zWfC|X1#swCSrh4ye<+Lv1p45oH0%PbpX)FJ^`9?d)1~nbxsIA>gSO5woy9%f({k7u%{Dopd##UbmLKvP4kKi`9mKvr{4{DKp1Lf-@;Qhr|)Ibi#W8gEbX| zav{-%$A=LP-ddt;+45{m zcE4@ZI_OC?f45UR(nx@OOUe~kGpJ&2xm>zi-g~p7pgEgy3LJmz>l)m z3suRd6Jv;FkcC%i-&jY&U6SR?u0dsfHOlA@b`&e?dEvW*vP`D}m-2KjxJ!BVGui#J zFFsaOK|AUCtkJv`d7=rly1dVK(z$bZbsAUM66lap7o9~5st=MIYGZ#l*a}F@&nbxs z_|2#mS#5m@YHAr_D|GkeaS-N&mS=1x*-<=#)+Vr>hSKxw?u(YK?{nMi(tbR#81hSv zfJsd@IO8Omj}bgJhLIQhIqowS=rLVpi4}b&txsu(1P>=~4o6+?Y5e>xH+Xb8l2K12 z0_Mju&d5u9+ihl&{Dr9sg21 zWn!LzvDs@1NpyddU{FzKQF-f2JB(PFa)*m95#SdD#veqwU~pCph&@RaLM6LKo)twvFhg;xHrYF?cP3UApX$HUe2LAIL_ZRkC}zP8Y3dt_D> zDS<;Duzot~Y#bWk%P*`<#6tZ~Ay(T2HL)BdTpBobLu!2FMv+4ys(mi)0)LCo;VS2A|n6 zjP%UWTn3yG?}@2hi8in&u3k#G$u%Ks{REXpDV7jU?ONPNSR6P#Q zvyAahepn}a+lic}Yu`AdaMHM0T5~a$D~8Sx&xYM%?Gny5|Bk2tnWvg$$WvxL+P6rn zw*aR+cV3^gqRL#YljSb>uH*$*w>=?NF#|C9(Ma zK+YelRA3@wStp5EOt;dlmkE%+4oHz}FUVZOK>~6s%E(ja;N)lvQS&`GB9><>D#^j( z!cTC+P(#Z)gA7}zL!r9)mdkTiFvqY(y6BTwp4W*pU26GZJX<3SArUM?ZNwv>5Oesk zRJ6^}g%THLonj{yWRd=HL~JTTM#J=4zM_b^mLakEw@>RDr=yMUMZ|p9Pm|T|UMn%qdQBJ0CF59W6#76k{Y3X6WWIuW`XUX2gt=mh6= zBoxF_;?S?ef0@1(sdI->-s`&Qu;^Q+`yteeca!FOnkM}Tk(bjV5#5&`lNQBCDYmP~@Pv_$36M)}I7uc5aBuC`RP9bv7}_N%jo zy->>wSUzdDZj@|ze-%`4FnI$bw_I6BOrwjJf_^FbkEMT+UTB;JVm8u|7Qfk zhtnG$uAAkyU1>f|zTwI6BvvmVV0!lZqWzd%?^iaY6b5$-60JN5e0O@!^iNC48&_!q z6z#xm2Lb27juf3r0i-`@YPO(WhO7Vf2Acaa?6E7vopB^vFpa$UoFU3?qr8x+4w>v1QcSrW$?QyuTM z2X;gT;{|lW$wD8Gw`ru#HaaCe>C_?Dt{n{5HqTl6)ge6`Xd3#QgD z0dIB=gUeXZ#B7Ow(YH%4xwKSEvtG9IOi#8!ed0ZG>eX$D*W9^OA|HO#oqZYiP*5`( zkREofKErJtX9JjDGTo7z(VqCzvMrk^XB>*{=Eu zDPr>s2o04wA!>GPQwjGf;;YKM?=K@(8R&+H0Y6*$y*U^68!4Be;p6ndg`wHo!cgdAd~TfUp=Rbc z*@=Uh-nl1f&HseZA8j}7$y$>h^oCKu#)+hB4Zgcf5A)_yVKdki-RGGS8cENocgWxm z*J|JVVO{Z{AMGILCH?uS$X^&CrVYs_+6XK`Qsx#OT1V4enzbvz#yL_O_|DVB?X#Zb z`wh!55y{cKwp*g(`+EPFnCvXlia^XICn`CbakBP?W(XKPMw5eDg5&Oun# zIaCh1FMT3A{)W{#);Sc_L&bpZ${-tKu0)v254TY!PonvvOBr$c-)Wp(_gMm=Uyn4T z+T+|L2;IlP)}5a*mX3uxCCqj^&TDpcn89Cd<*;XD7!if?FNCf0ipAhE3YbslqoXV` z1{Y$jUrZyOkJzLSPDAbA|C~LsOmOhAHCmot#}&>BF0fUaafP7^cw?b^dX@BF$`)>o zoP>5|;l55R<8@Rtu?c^Cvr#64M4I%T7{Sq`Xd^5g{0JSszqIoO!L@W;_#x)wv5+`^ zPthWv`(b6b5!=uwhDTJ}E0jxW-zuSVgAJPi;$;GFKeV-{aj~#~%{Zflf6D0|LYX&n zFgaEz@qTqRUk!s3&Gzr4sUJ0Jq!HesH?W+46WDRa_DfI1txc3JB4?R;A6l;JrME8a zxD4ZBc~*YaelY=2$Z_jyvN3SY!*Jni%nHQ#I4 z+s=?0N*^F>3^$4mObm{0)mh@6`Of%&0}2t2Y=$@w1|@PKUPf-aO!=5xh2?ARXXj+G z?zZ-BH1MAjyZ2_2+6p5P8mxuCyYCB#dnaxC#{T|?O8Qa z%R>*76kq(rs%l7*+=o%+Fh&1U&9$7IEal*!T*>G&4IJO`Op!h*WVx=S>`|Dc7L15S z^H?J8?M?Dum9xv9e3=GG>3W`CFq&E-v{(TrK-A~Wi!C*$adoS_~X%qfVDWmVT>95LabxF&iW6|)&sr(xb z?| zw%(<@dF8({#*NO9W1o_%G((C&vva;t_DLd@b^UZ75lyfaV+eB;o=JBd)iV9uI|B6_ zMGB!)bl>tw@o7Odwjuf=N@oQ|a4LMf2_0|7x=~!wu0?U^o4frAGiJy;t!>0V-_gi7 zOzwGB>A_3@{pzb}`sVB792o3050WGOu^5*v?%>~$GKWj8r_^}P#7t;|^Wc{DBYTQu{hl8}S)rNvJ6aTpjjtfS zlIFy!T!KB})G$lp)H!RUk9y$);r{iHV$aYjD`$sXf_7;~Je#~)i2YHNJAk9{lCI0# zmg11q<9vr~xTO8wr6RnV^KzgD8YAN@CQuiRWT96ow}1Do7uBi*ult?lEA#HpzxiH| ziQJqW`X99TWQ2#Yo1o4M!>DhNMHu1RBAQxnoppWuk_~f&wgQ@QOG^_Aj6|uC4@eqv z3(Wi0c;~Y(h7tEvs>3rQ#D1sjOu4|HqyveCY6F>AtalHZfa3D7K4RF10JLv^`4b{ zk*u7DkeQcm00ea^Eu`*xGOg{UmV6Jd1!IR!0JBXqC~6qz1h3uLVh@PYB7P2W_E$T9 zUz3+n#_J0!4a5EfoHD$uht!CTDKjOo3Y7DQ*r|CFu?&v@pCt&CmRVf^431$Q;wFKv z_QxVM5?${(Ix>;bNn}w08h;kgVS-oAsOs{b(*t=enT40SxiX%tXK6{KfL7ZEK zo;PeeGT9fSSlsp#JW(!bM7?SuFh;rd-2O19tOxa!ma#U!J2Kif=qkQ zh%(nyp55iL4Fo6KUHgvaP`TpcTUEuLwP9nvAF(gE|1#A=0=Y4(+TLd#H2ePT7m~f6 z3ADjR_($Yk2Ovn}MSqq{C4@w&D=8!FD{i}Y>lV3)jyN$(px>N>_hXD|@QE}&Dyk#Q zY!u}N6l;tYo$;hoy)t|FEQ^Sx!@iVQlFrgP#;Z}&!B|Dcks@8S=y3s}D!r}OQ);Xn z-1%VWlK@(S1*7XSs9cFeh#fu&q#~%_G;=+Vu$BJnD;#1lNpc#Gv5GPn=AN+UdTLJH z%a9bk07PlapD+^Jw!CC}G8cuBHn<#`DNRxt*=k9zL|N<2HP@CeT5l&Ob|E^+zjGwl zFDF|qv_Q$3f_ae6J_0d-rS|bfPWFGp77 zav`$_xRevgO+THe&N&xIeU^kdR_COcVi&=8H8rv8Lf1Ls()>81$fZ_;s09N>SB)B} zg~MHtyqiXvvM1)(S*C3TMtU#GR~up` zc3SYc{}c(45X5i8_|>#jXaAF|Y{V}_Yi3odZ4w`$^jlEllFik4NtTfW4AwN@5+0ER z!Kzj&(hEDg=}gMa*~T!}mH3R?6yZL^ft+k@aNd?PcCB3EL7(C~lmAs$HC>kSUCilB@8+U${NF=DUl+M=MKS z^nZ-{$1SExFebX?qS~RsdQr~k6~TtUDXle;u52N-ZUdKZ5a67yv+;#i)-t>h}+7i@yXG&_0g9wXhcl_BSvQ41sk3SsbE`vdwuZl4Q(8q01j86!pFiWQ7-^6Pug*~894R$fJ5~( zs@fW()H&MFD@baB~+D%#u{)%Rerq_vJDVP2-{%6%<$t3h3@n;-=xaYiS zSEma66>~Bv@wdS7{cc+Z(gL@(7thwVxr_SVWRjr{`~C<(dznV}lBT}&MpRV?>zgsf zO247cE(ce$SXd$vul&R|w?(mu;znYT-Ky}0(laSpug4To$bLIOc-Y%`#zgZiJ?EU? zF^QtDd#S+AA#{FioZ~rzGm2(q{JRGIB-X<~XjyE8tx;)p-ZmCZClfQdnPus(%j>!$QlZk)&CY9hmmF`4mT#ane^h0OG7+)Hw z=mtUoCweNNez(KGvOTO}lT@>>K|aa%=x@JEid4eG{awm}s=+JeJf@i78`~^emPGqx zBW0eKXOPlg|AHt~tH1v8$+LCs(1+@j$3+R#0^P1=ea~F+j4i$lx>EiA*SSh zmp5^!S6T6tmBj)gTq>13b$?@?B&W0K#WPLia|^ev1L6&v%Cmw?!XIe6f20B>g@(525IbN`#4p#LkiQcD(Rnse;oaF z@pMFsE0d-Y&j`MQS*tHWZHRG>0ip6!T3DSo1V~u<2 z1DAO!I4EK!fvs)_6K;S{=03&pkN2#Js~0kVdCu#<7%s%}1DC~Du?J<@{$Ms)xhS_#P;XYidnEAuOT<~;5e#5)=?6e@}8KXBCT zQ6QQ>Yznf^m}@^5``lS*nG`-w;#pOFbhO~p^2^b9K>ojXODdOo49bF)bH_D3E_!9J zK6Qv8F&p*yFwy-_irS)&su|8V!-u!m$A3^wv@qD`35oU%>!wrHJH(!Jdj-xtxrjxX zm3kMFHx)f-Yne@!o0K{Hxbb=|Q{V)s^x4^g(mpenRy;^r|(J_5S(b%AY#mYvYROOYA_VCV$%xeI|aQ32qz-ruF|G3bQe+ zs@Hg)@gme^#gRFs*VpEiKSs-PT*yla_ff&MJxmz#b$PFX8 z=)S-n)RyDnROp-`@@#UJ4@w>GLiaw zPp*Y^z9?DDjp2rltU@ab3{4DmnDDz?Y#8g!v;~UMWQ>PXgG02;yQlF}w{e-IvHmvX z9Ce#&h|ZENM-QbhJX^%uFUE-l+Z%(^y_Q7aXDR+G9v17>3HM*;y?cz_gB2mJ4SM=B z)wnQ57GqX{jW^v6p+A)^8XiTf^inj6uk|eTG7~-3j>|ZvS7Hxn89QEapOToOuUyjM z%@v!xI5Z73hc|I-N&$g!nnY*VDx9VVv1v+~gQn7}7iSTa0UG7l`@L#?fNW>3`H-`I zz{zFZ(lAEor@-@`xVRt~ylD%Udd9t*Zf3%<+=40jBVR91iPVQ_{56RQpEB$c*6U^U zVY5E!Dx46d3!<{LC(lUg^BDdGm7r_}6^Whl2?;L(@YacJrI0jx#z$LB>t3TNID^y> z9|^{x;>z3*0Y2Aa+K-+sa43;Ln5f zJis(VIw4z7b~Jbj?@_!<9#L6Q$iBaiSE)EZ`Ky=&hDNb9mLitEVFoS%ndq2L0KtWi z5#}5tBjH;v6BF7|YYV?D>|3W6)J_uVW2}+g@7lZ*0e-0cy@)KCl?7L&qG6ENkWr0U z08)H{G?`nMhIfQ1BcX}9OJ+H54q^6NpF9djqzewDKiaNrkE##?;ODG zs?h5%oywW-d7qr&hTBaV_Jqma)QpauMRd*UqjU&WRmoE ztbQH7t&O9)HMy#edS@xf#c4K)v!g?p%CfMMyR}`)GL`C2W^j<&+`SL({&~NA$agt` zUEX52qe5No?_fO30rw$&rC)R+6t3~f`0>Ip0y&8wJ__G0 z170y%*(w%WoTjk}+C73W-D2NDN83CH*?l|b{Y{jju$g_k1qp-IIHj6I*uf^2;z-88 zPF`S!E7=oRx^d>xYtTqho?|62*wuf&;hQJ+vG7gzD^9k zzRzSZ60n?R_sMO~oOtmFpoVVRQB^VieE0iHM8hvfUS+OSuO`{A#2s1nw5(zHkt~J( zg7_rim@nvO-`YN&>*y0NLh+m?qZDsm9GX`nHE`FbwifT|`czW6vj4!!O_(C_kM|Rl65W0aKE)O_Q8@qJ35kJYV&ti>)(Sf z)}-Zm<8x-@T4^j(qMlAVRk^r{GLg>4&=%34Yl%b6lO%?RThZd5UWHu5mo`1&XeT1t zrC}13N7^8m27J(RH$A>$<;=w$`tmat?;#l6HCu9 zi#B_5sd6^gdCzKMLW{OGEMqFT{TcdMNiW>L(dOn&4;s3|J$tr{iAb^M6Qme!Ki zEm`{M1>6Rfe?Pq}zBNd(Qu(!ynx!R}HPmL$4rDtYGunsAu*`X9& z&^&xQ-5s{6spHsEX@C9=kDEz3*Zr&yBjIn}L8q+;@&}IsV>J#Ep&(b4 zUxBRbOu`x&Kkg|kOaD5tCE(PW5e!@GBBYrTJRHB#but-xL+ct;^u=6B}RKtp0CU(LJQj+kWS*4 z(cQC4shwzDpHXJKpFeCt)lww;S*|^b|CGlT`&|=#h-f-#R*<9^sk6wRQxZ4%4_uBQ zpqXErRM`>rPwqxwRlKz%JM^PUPE$&-xzs!-4vwFLg+6FYQ>R*X$W+A` z%o2{#i4{vQOtO>yN|CYmC3|Aef$HklI|`&yT+vce>C^LQo|-&TU7WH)Vp*5+7gThJ zisw}DgR;bj!TZ&@G--O0ojVzt82=AYhPqf{7i}d)fE=3g&vCvuhJ?S%G==+#6JHvH zG;*HbKfF@^CgutlvQovTu?;#OhT!rfY|*;{31qf+=$fDaOB#px>9iLplxqsG-~>xx z_Wmbidm`{Ls^l>*N$==gdOGn8c^uS2s3ur;Mdaj=C@s3Nr2R+JF-oAxFg2q%WxY@7 zB>=Cb5i$gRWTpC_+rJ>fDdl(kp%JUY0V}bJQ|+Dv@Fp;q2vi?pc&r19XL1Fsn$uFN zII$BvtrlJw--486f~?gduK+dwo&*Bl5Tq6#Sk3QH2?iQE0~}yyrwqz9t^=|BUr9ag zb4C8+~2BNZ9xP8wrDzJJ3sf7GW^rCcN4n= zjJL3IRlw_DSHzNdMbM{Y3kyLy3lf-ak_dz2X9qUv5MUexpe2g=b3r&#uOaRKz>!>2 zM)&Xk{j5Ut9Yi}pjQhx3yB>v|Xby`8=|vDQl>hGk!tFr=nqMgc1PrG&R;i^~d>*?{ zv1o%y*5*G#lQmQuw*%uK=qS(FaEEjLXh_c?@wltaeN@2c0&Wl7{}1TA=;O1*V?e?s z!Tym1`O+qoFj2psG_uy+;fsb_J}fo5@V31oQPth&;Fnwhbfzg3e3F?H?;*-5(7E+YKJId%cIZ(w-U)~Nt5)m$#D zOmJ8*%hsjm*f4(Pq5@gUd-8OrEkqt&cszF)Z^Ne|;K^*&8QUpnGzhUg{hRh{!qnx}r!Y}NB(2h1ap>)*y|0udb!%bgEY3)t{SzYHqXmA~Fq z5?lV#sd$oEwRDFQ`yrNKWQ=t52#`k(pY4bI+wm_`W&00ehU*b*m8o;9d)#r$u5Y0= z(GW|jw|7MIjF}SmTRO;p40E&gdJwVe0`Y%Z1>h#04XOYCs%9%7Gny9t$iq7avVMQv znC0mxZE-<-cvk&23fpa_17zW`j_*kzr(G5{)9#>b?c!KW50Kmb57u`6pjd65tM&sl z*Z=mGWQa=AHJsy)$;5hhCc-@6V zh3pWF|9r=I`ynm}0r>)=5i0ODRvAA~06hM$@Pr6JO0H7c-f`+iZ_1UF3a6egfi^w! zt~?|&Rfa$t=vt_79za6$aGmb7&~=u~5J5SOJ2$JJFAwG=n{YwE`e1PtK-FU`fitaV;AQHy#?rG%T$g)b zt11zF1&HjNvQQ9sU3X8q_C#_KVYPrZJ%}n}c$BanoNAs4Y==g4q!faoOdgD_XTKBh z@qj;G{jN+ni6&Fic6o?h2fg2h8#`Dqk8sbP`FhKq3YJgiu3@v`v^&mU`C5=mWI1B9UCLGA+q=J-Jyrs zHE8AkiXQ3V*l=;yIz2EA{eUXw$SJKik!EqABR{oZrfw1Rxicf!fpbio-AMTYvK2wF z6}8#mWE|LcNdDhJ4ZjwU#HZ0~_`e4=u+P}&p=aO`4$C?WE#Xpd?#1NQKZ!h4AySI^ zI+2sZqVm8?LzV!oG7oULY%-^>+-u4TsN&=qt-}~O=1Z*R#5)cEcUuiI46)K|@uxKe z**qomHBa9SyUqg+`1&lb% zKGM{XWm0Vs`dbXwquH`NKyQ`BLArK(cxFoEQfJ(&*beNjK!*DcmWG(ZPJpd^&&IhH zw{mlycYyrgm)m-u>uNZv=9*t$$1$IzDcrP?-AwEM9ksW9xObLBxR7NNrLlV~H+}NL z6KKo5y*C6?K+MAQIKV?ioPO$Neh#*NjDJm%pU(;uJE{%QnZu@ef~6Oyx&!!jwb$XV2o;{6U-?5!p&<4f}+0}}%b h1GwWztuh@!;2Slm->Hg3HW&iXR)470sA3cK{{hvaE!hA7 literal 0 HcmV?d00001 diff --git a/img/apple-touch-icon.png b/img/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9f5d62c1241c45e59abbca778b349fe648104d78 GIT binary patch literal 2905 zcmV-f3#RmmP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 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 JnJ45o{6FF@5n=!U literal 0 HcmV?d00001 diff --git a/img/mstile-150x150.png b/img/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..aae99969123d2a6c4fdfb081b2ff8ac17c6288cf GIT binary patch literal 3364 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 + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + + diff --git a/index.html b/index.html index efaf84a61..385e41a4b 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,17 @@ + + + + + + + + + + + Bangle.js App Loader + + +
+
+
+

Zoom in to the area you want as a map

+

Click

+ +
+ + + + + + + + + + From 8ff1ea0c0dfbc971a3de3e40d1737e12d6555329 Mon Sep 17 00:00:00 2001 From: Timo Kiefer Date: Tue, 7 Apr 2020 23:03:30 +0200 Subject: [PATCH 0284/1189] Added tabata app to control high-intensity interval training --- apps.json | 12 ++++ apps/tabata/tabata-icon.js | 1 + apps/tabata/tabata.js | 130 +++++++++++++++++++++++++++++++++++++ apps/tabata/tabata.png | Bin 0 -> 1946 bytes 4 files changed, 143 insertions(+) create mode 100644 apps/tabata/tabata-icon.js create mode 100644 apps/tabata/tabata.js create mode 100644 apps/tabata/tabata.png diff --git a/apps.json b/apps.json index ebc0d7fa7..4553eaab5 100644 --- a/apps.json +++ b/apps.json @@ -1090,5 +1090,17 @@ {"name":"minionclk.app.js","url":"app.js"}, {"name":"minionclk.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/tabata/tabata-icon.js b/apps/tabata/tabata-icon.js new file mode 100644 index 000000000..93783b607 --- /dev/null +++ b/apps/tabata/tabata-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwg96iOZzORgMZAYMQCxsBCwIAGDBsZyIDCCYQyBBAQuLEwWZCYYJBFx8BL4ITDjJILBgcJDYIGEyBCHFYQoGC4Y2BRBAJBC4wrDC4w9BiC6BC6Q6DAYIXpCIcJC/4X/C/4X/C50BjITCjOZD4IXOhOZCYMBAYIwEC52QC7QMDC/4XCzBH/C/4X/C5OQa6INBC4WRyIvQC5IOBC5YTBAYILByAECBAIXLA4IwBAYITBgMZDYIXGHgZICEAWRAYQfEAgIXIFAIIBiERCwYKCCQQOBBIQAvA")); \ No newline at end of file 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 0000000000000000000000000000000000000000..f0aaadedee90e22b64f7beaecaddb73e293596b1 GIT binary patch literal 1946 zcmV;L2W9w)P)2C~ zDZ6){4g^5!>mN4qB_S&mI1aO8Ap2o93*>_WR4Q-+KowL8k-q}yf|&uRgxMO16ad&R zIXTa8=g#Y27=Si3e8*H@26;$Co@Pr+=g4tuZVqcYeMEre0AOa1NizA?D9yTc`Bqr? zLo?e7vXhSUsJ#AqYNB=Ju9%O@|zU=8e>F z-@a>-Og>MMS|Pt;sx6iNsMe`?dgUH6H)gy#**O-5@|EJ@3bCYx8_Hz)zw2FB6Mfb_hCg+kj*buEBD`sEVXNnn@7Vqaog+a+I6-$gfXp5iq$Bx!aCWE0G) zp!x*N-t+3~|7^9jBf+a-b}Z{%2#3oBC6aY-5I-A57K!=BS z09bEknvklD9Q@pd3^u? z$C-M^0M^*JOn^-!pOR#9Hvt0xZr!SqNc@SwvjCpf`ue#50CK`tF+-t=U)2-jGaNPm zfNIvgIvzmv8>*UOclS=;jJ&+<00@ysCp7j2#drX+6y$lfx4XUxue_25&?D9YXAheiM!M33x$qT zN;0qe`t=JC8F#Qbn@U}BL>{<0JbV^FKg`By0t1LfA~me8K8Mw-({l<6YWy_wX3bjQ zZQOWaR&MSzkaPVsfdPDyPIq=4J-XcK=%}XI2YwnUDmv%9`DXM$Pfye}yWy+3w>Gm! zStPO?svStD+m&4IE4qAnwz}@ACDW#zbI2)vlE46RR1e)(R5aHUnNQ%5pT_37M>j!%)L%+E7tu7N~G71=a_J%Op= z@b#*^y#JV)Yh=bxW57&Lwc~*qGp5q4*H07NYxLT+R6#f#0m<%6#q6h*?y?5ML66nB4GjtvPywQ1wNEyvS;LVhkUoHuyBEz zRe=15Z!Y;S2UtEmC+8AH&fgh8OG~E$`_=6CT31)%mqgdy4!|Msf|~7PBGKh*ps_I~ zji+q)vNoZxcI?iSFiSq$aI=r#hA$2T+sUZ`wZACB1_clFwAcDz(npB;C=;; z(`=WSJqM8x%=Uvk4PXXT*FaQdw-NhDq#1zA^DVxiD)K&}GtZ+hM@ gB}*f5GJ=f%0+Ylc2Q#LaGXMYp07*qoM6N<$f{d$?yZ`_I literal 0 HcmV?d00001 From 35eaf82a78db867b56816ffd2d1df9b26d3b9bf2 Mon Sep 17 00:00:00 2001 From: Timo Kiefer Date: Tue, 7 Apr 2020 23:03:30 +0200 Subject: [PATCH 0285/1189] Added tabata app to control high-intensity interval training --- apps.json | 12 ++++ apps/tabata/tabata-icon.js | 1 + apps/tabata/tabata.js | 130 +++++++++++++++++++++++++++++++++++++ apps/tabata/tabata.png | Bin 0 -> 1946 bytes 4 files changed, 143 insertions(+) create mode 100644 apps/tabata/tabata-icon.js create mode 100644 apps/tabata/tabata.js create mode 100644 apps/tabata/tabata.png diff --git a/apps.json b/apps.json index 4939e7c74..3dbdbe3e2 100644 --- a/apps.json +++ b/apps.json @@ -1107,5 +1107,17 @@ {"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/tabata/tabata-icon.js b/apps/tabata/tabata-icon.js new file mode 100644 index 000000000..93783b607 --- /dev/null +++ b/apps/tabata/tabata-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwg96iOZzORgMZAYMQCxsBCwIAGDBsZyIDCCYQyBBAQuLEwWZCYYJBFx8BL4ITDjJILBgcJDYIGEyBCHFYQoGC4Y2BRBAJBC4wrDC4w9BiC6BC6Q6DAYIXpCIcJC/4X/C/4X/C50BjITCjOZD4IXOhOZCYMBAYIwEC52QC7QMDC/4XCzBH/C/4X/C5OQa6INBC4WRyIvQC5IOBC5YTBAYILByAECBAIXLA4IwBAYITBgMZDYIXGHgZICEAWRAYQfEAgIXIFAIIBiERCwYKCCQQOBBIQAvA")); \ No newline at end of file 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 0000000000000000000000000000000000000000..f0aaadedee90e22b64f7beaecaddb73e293596b1 GIT binary patch literal 1946 zcmV;L2W9w)P)2C~ zDZ6){4g^5!>mN4qB_S&mI1aO8Ap2o93*>_WR4Q-+KowL8k-q}yf|&uRgxMO16ad&R zIXTa8=g#Y27=Si3e8*H@26;$Co@Pr+=g4tuZVqcYeMEre0AOa1NizA?D9yTc`Bqr? zLo?e7vXhSUsJ#AqYNB=Ju9%O@|zU=8e>F z-@a>-Og>MMS|Pt;sx6iNsMe`?dgUH6H)gy#**O-5@|EJ@3bCYx8_Hz)zw2FB6Mfb_hCg+kj*buEBD`sEVXNnn@7Vqaog+a+I6-$gfXp5iq$Bx!aCWE0G) zp!x*N-t+3~|7^9jBf+a-b}Z{%2#3oBC6aY-5I-A57K!=BS z09bEknvklD9Q@pd3^u? z$C-M^0M^*JOn^-!pOR#9Hvt0xZr!SqNc@SwvjCpf`ue#50CK`tF+-t=U)2-jGaNPm zfNIvgIvzmv8>*UOclS=;jJ&+<00@ysCp7j2#drX+6y$lfx4XUxue_25&?D9YXAheiM!M33x$qT zN;0qe`t=JC8F#Qbn@U}BL>{<0JbV^FKg`By0t1LfA~me8K8Mw-({l<6YWy_wX3bjQ zZQOWaR&MSzkaPVsfdPDyPIq=4J-XcK=%}XI2YwnUDmv%9`DXM$Pfye}yWy+3w>Gm! zStPO?svStD+m&4IE4qAnwz}@ACDW#zbI2)vlE46RR1e)(R5aHUnNQ%5pT_37M>j!%)L%+E7tu7N~G71=a_J%Op= z@b#*^y#JV)Yh=bxW57&Lwc~*qGp5q4*H07NYxLT+R6#f#0m<%6#q6h*?y?5ML66nB4GjtvPywQ1wNEyvS;LVhkUoHuyBEz zRe=15Z!Y;S2UtEmC+8AH&fgh8OG~E$`_=6CT31)%mqgdy4!|Msf|~7PBGKh*ps_I~ zji+q)vNoZxcI?iSFiSq$aI=r#hA$2T+sUZ`wZACB1_clFwAcDz(npB;C=;; z(`=WSJqM8x%=Uvk4PXXT*FaQdw-NhDq#1zA^DVxiD)K&}GtZ+hM@ gB}*f5GJ=f%0+Ylc2Q#LaGXMYp07*qoM6N<$f{d$?yZ`_I literal 0 HcmV?d00001 From 50e1c3096d4dabdc25aa9897ad12a65822a3f227 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Wed, 8 Apr 2020 03:13:14 +0100 Subject: [PATCH 0286/1189] Center characters on the screen --- apps/marioclock/marioclock-app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index e1937fbe6..81f5616b9 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -33,7 +33,7 @@ const MARIO = "mario"; const characterSprite = { frameIdx: 0, - x: 35, + x: 33, y: 55, jumpCounter: 0, jumpIncrement: Math.PI / 6, From 195a7f53af209605096858945a64b35e5c0ccdb0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 08:09:02 +0100 Subject: [PATCH 0287/1189] minor icon tweak --- apps/tabata/tabata-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tabata/tabata-icon.js b/apps/tabata/tabata-icon.js index 93783b607..0a360fbbe 100644 --- a/apps/tabata/tabata-icon.js +++ b/apps/tabata/tabata-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwg96iOZzORgMZAYMQCxsBCwIAGDBsZyIDCCYQyBBAQuLEwWZCYYJBFx8BL4ITDjJILBgcJDYIGEyBCHFYQoGC4Y2BRBAJBC4wrDC4w9BiC6BC6Q6DAYIXpCIcJC/4X/C/4X/C50BjITCjOZD4IXOhOZCYMBAYIwEC52QC7QMDC/4XCzBH/C/4X/C5OQa6INBC4WRyIvQC5IOBC5YTBAYILByAECBAIXLA4IwBAYITBgMZDYIXGHgZICEAWRAYQfEAgIXIFAIIBiERCwYKCCQQOBBIQAvA")); \ No newline at end of file +require("heatshrink").decompress(atob("mEwwg96iOZzORgMZAYMQCxsBCwIAGDBsZyIDCCYQyBBAQuLEwWZCYYJBFx8BL4ITDjJILBgcJDYIGEyBCHFYQoGC4Y2BRBAJBC4wrDC4w9BiC6BC6Q6DAYIXpCIcJC/4X/C/4X/C50BjITCjOZD4IXOhOZCYMBAYIwEC52QC7QMDC/4XCzBH/C/4X/C5OQa6INBC4WRyIvQC5IOBC5YTBAYILByAECBAIXLA4IwBAYITBgMZDYIXGHgZICEAWRAYQfEAgIXIFAIIBiERCwYKCCQQOBBIQAvA")) From 36a89579421686c954f42cb9ac35000ac112c308 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 08:53:40 +0100 Subject: [PATCH 0288/1189] Remove 2v04 version warning, add links in About to official/developer versionsRemove --- CHANGELOG.md | 1 + index.html | 4 +--- js/index.js | 13 +++++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cfef69ac..213b65852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * `Remove All Apps` now doesn't perform a reset before erase - fixes inability to update firmware if settings are wrong * Added optional `README.md` file for apps +* Remove 2v04 version warning, add links in About to official/developer versions diff --git a/index.html b/index.html index 67f5a748b..0d5c17251 100644 --- a/index.html +++ b/index.html @@ -69,9 +69,6 @@ -

Note: If you have a version of Bangle.js firmware before 2v04, please update to the latest firmware or - use the legacy app loader. -

@@ -129,6 +126,7 @@
+

Check out the Source on GitHub, or find out how to add your own app

Using Espruino, Icons from icons8.com

diff --git a/js/index.js b/js/index.js index 3cdb1c30c..d2c6d698b 100644 --- a/js/index.js +++ b/js/index.js @@ -465,6 +465,19 @@ librarySearchInput.addEventListener('input', evt => { // =========================================== About +if (window.location.host=="banglejs.com") { + document.getElementById("apploaderlinks").innerHTML = + 'This is the official Bangle.js App Loader - you can also try the Development Version for the most recent apps.'; +} else if (window.location.host=="espruino.github.io") { + document.title += " [Development]"; + document.getElementById("apploaderlinks").innerHTML = + 'This is the development Bangle.js App Loader - you can also try the Official Version for stable apps.'; +} else { + document.title += " [Unofficial]"; + document.getElementById("apploaderlinks").innerHTML = + 'This is not the official Bangle.js App Loader - you can try the Official Version here.'; +} + document.getElementById("settime").addEventListener("click",event=>{ Comms.setTime().then(()=>{ showToast("Time set successfully","success"); From 3b7eec70e3e2fe49f5c64553f4355d1e3acd700c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 09:35:38 +0100 Subject: [PATCH 0289/1189] Alarm: Change 'New Alarm' to 'Save', allow Deletion of Alarms --- apps.json | 2 +- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 18 +++++++++--------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps.json b/apps.json index 2f9ab3b8e..b567ba14d 100644 --- a/apps.json +++ b/apps.json @@ -134,7 +134,7 @@ "name": "Default Alarm", "shortName":"Alarms", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "Set and respond to alarms", "tags": "tool,alarm,widget", "storage": [ diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index be3c1513c..2ff60e658 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -3,3 +3,4 @@ 0.03: More alarm scheduling issues 0.04: Tweaks for variable size widget system 0.05: Add alarm.boot.js and move code from the bootloader +0.06: Change 'New Alarm' to 'Save', allow Deletion of Alarms diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 6dd0debb1..745a7e797 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -84,15 +84,15 @@ function editAlarm(alarmIndex) { last : day, rp : repeat }; } - if (newAlarm) { - menu["> New Alarm"] = function() { - alarms.push(getAlarm()); - require("Storage").write("alarm.json",JSON.stringify(alarms)); - showMainMenu(); - }; - } else { - menu["> Save"] = function() { - alarms[alarmIndex] = getAlarm(); + menu["> Save"] = function() { + if (newAlarm) alarms.push(getAlarm()); + else alarms[alarmIndex] = getAlarm(); + require("Storage").write("alarm.json",JSON.stringify(alarms)); + showMainMenu(); + }; + if (!newAlarm) { + menu["> Delete"] = function() { + alarms.splice(alarmIndex,1); require("Storage").write("alarm.json",JSON.stringify(alarms)); showMainMenu(); }; From 50e61015eccaba80fae15fd8d20635ee27fe0401 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 10:16:32 +0100 Subject: [PATCH 0290/1189] Settings: Make LCD brightness work after leaving settings (fix #186) --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/boot.js | 8 ++++---- apps/setting/settings.js | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index b567ba14d..1187dd1bd 100644 --- a/apps.json +++ b/apps.json @@ -119,7 +119,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.10", + "version":"0.11", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 73bbc7bd1..51de64281 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -8,3 +8,4 @@ 0.09: Move Welcome into App/widget settings 0.10: Added LCD wake-up settings Adds LCD brightness setting +0.11: Make LCD brightness work after leaving settings diff --git a/apps/setting/boot.js b/apps/setting/boot.js index 8bf9df50d..b437cf744 100644 --- a/apps/setting/boot.js +++ b/apps/setting/boot.js @@ -1,6 +1,6 @@ (() => { - var settings = require('Storage').readJSON('setting.json', true); - if (settings != undefined) { - Bangle.setOptions(settings.options); - } + var settings = require('Storage').readJSON('setting.json', true); + if (!settings) return; + if (settings.options) Bangle.setOptions(settings.options); + if (settings.brightness && settings.brightness!=1) Bangle.setLCDBrightness(settings.brightness); })() diff --git a/apps/setting/settings.js b/apps/setting/settings.js index cbd856ec5..a93116bec 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -101,7 +101,7 @@ function showMainMenu() { }, 'LCD Brightness': { value: settings.brightness, - min: 0, + min: 0.1, max: 1, step: 0.1, onchange: v => { From 9edc3a659235f465cce77884f380020f079478cc Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 8 Apr 2020 12:12:25 +0200 Subject: [PATCH 0291/1189] GPS Info: Show number of satellites while waiting for fix --- apps.json | 2 +- apps/gpsinfo/ChangeLog | 1 + apps/gpsinfo/gps-info.js | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 1187dd1bd..8f123e079 100644 --- a/apps.json +++ b/apps.json @@ -722,7 +722,7 @@ "id": "gpsinfo", "name": "GPS Info", "icon": "gps-info.png", - "version":"0.02", + "version":"0.03", "description": "An application that displays information about altitude, lat/lon, satellites and time", "tags": "gps", "type": "app", diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 50d79e72d..90ace259c 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -1 +1,2 @@ 0.02: Ensure screen doesn't display garbage at startup +0.03: Show number of satellites while waiting for fix \ No newline at end of file diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index f7daf245a..836e3a71b 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -52,7 +52,11 @@ function onGPS(fix) { g.setFont("6x8", 2); g.drawString("Waiting for GPS", 120, 80); nofix = (nofix+1) % 4; - g.drawString(".".repeat(nofix) + " ".repeat(4-nofix), 120, 120) + g.drawString(".".repeat(nofix) + " ".repeat(4-nofix), 120, 120); + // Show number of satellites: + g.setFontAlign(0,0); + g.setFont("6x8"); + g.drawString(fix.satellites+" satellites", 120, 100); } g.flip(); } From 4301342292d4ae2a278bfff56d9d3cfac2aca2b6 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 8 Apr 2020 12:58:39 +0200 Subject: [PATCH 0292/1189] Reload apps after successful upload to get a fresh list of apps and files --- js/comms.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/comms.js b/js/comms.js index eb453871d..305dd26d3 100644 --- a/js/comms.js +++ b/js/comms.js @@ -23,6 +23,8 @@ uploadApp : (app,skipReset) => { // expects an apps.json structure (i.e. with `s Puck.write(`\x10E.showMessage('Hold BTN3\\nto reload')\n`,(result) => { Progress.hide({sticky:true}); if (result===null) return reject(""); + // Reload apps to get a fresh list of apps and files + this.getInstalledApps(); resolve(app); }); return; From dfad1218d630bf0acb684e91f879924b6a0763c5 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 8 Apr 2020 13:02:36 +0200 Subject: [PATCH 0293/1189] Force reload --- js/comms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/comms.js b/js/comms.js index 305dd26d3..7010660f4 100644 --- a/js/comms.js +++ b/js/comms.js @@ -24,7 +24,7 @@ uploadApp : (app,skipReset) => { // expects an apps.json structure (i.e. with `s Progress.hide({sticky:true}); if (result===null) return reject(""); // Reload apps to get a fresh list of apps and files - this.getInstalledApps(); + this.getInstalledApps(true); resolve(app); }); return; From c70ced75c1ad22a4b0971f63f0877d7d5661cd63 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 13:27:19 +0100 Subject: [PATCH 0294/1189] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f6c82c02..ca874ad2f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Check out: ## What filenames are used -Filenames in storage are limited to 8 characters. To +Filenames in storage are limited to 28 characters. To easily distinguish between file types, we use the following: * `stuff.info` is JSON that describes an app - this is auto-generated by the App Loader From 81dc5a1802dee84162f3286deacba292cd8ffcc4 Mon Sep 17 00:00:00 2001 From: MaBecker Date: Wed, 8 Apr 2020 15:26:38 +0200 Subject: [PATCH 0295/1189] new app custom --- apps.json | 12 ++++++++ apps/custom/custom.html | 64 ++++++++++++++++++++++++++++++++++++++++ apps/custom/custom.png | Bin 0 -> 3291 bytes 3 files changed, 76 insertions(+) create mode 100644 apps/custom/custom.html create mode 100644 apps/custom/custom.png diff --git a/apps.json b/apps.json index 8f123e079..9341f2be9 100644 --- a/apps.json +++ b/apps.json @@ -1118,6 +1118,18 @@ "storage": [ {"name":"tabata.app.js","url":"tabata.js"}, {"name":"tabata.img","url":"tabata-icon.js","evaluate":true} + ] + }, + { "id": "custom", + "name": "Custom Boot Code ", + "icon": "custom.png", + "version":"0.01", + "description": "Add code you want to run at boot time", + "tags": "tool,system", + "type": "bootloader", + "custom":"custom.html", + "storage": [ + {"name":"custom"} ] } ] diff --git a/apps/custom/custom.html b/apps/custom/custom.html new file mode 100644 index 000000000..5a5dbbecd --- /dev/null +++ b/apps/custom/custom.html @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + +

Type your javascript code here

+

+

Then click

+ + + + diff --git a/apps/custom/custom.png b/apps/custom/custom.png new file mode 100644 index 0000000000000000000000000000000000000000..722ceb9eedfcf37de343dc96fd9f4394e55295cf GIT binary patch literal 3291 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 C<=Q;} literal 0 HcmV?d00001 From 8dda7b59f2b920575a4d5691e9364587b15fe5d9 Mon Sep 17 00:00:00 2001 From: Alessandro Middei Date: Wed, 8 Apr 2020 16:01:06 +0200 Subject: [PATCH 0296/1189] Update locales.js Added it_IT copied by it_CH and modified for EUR as int_curr_symbol and \x80 as Euro symbol --- apps/locale/locales.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index 43e073cd1..f8eb262f0 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -320,6 +320,22 @@ var locales = { abday : "dom,lun,mar,mer,gio,ven,sab", day: "domenica,lunedì,martedì,mercoledì,giovedì,venerdì, sabato", trans : { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + "it_IT": { + lang: "it_IT", + decimal_point: ",", + thousands_sep: ".", + currency_symbol: "\x80", + int_curr_symbol: "EUR", + speed: 'kmh', + distance: { "0": "m", "1": "km" }, + temperature: '°C', + timePattern: { 0: "%HH.%MM.%SS ", 1: "%HH.%MM" }, // 17.00.00 // 17.00 + datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%Y" }, // sunnuntai 1. maaliskuuta 2020 // 1.3.2020 + abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic", + month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre", + abday : "dom,lun,mar,mer,gio,ven,sab", + day: "domenica,lunedì,martedì,mercoledì,giovedì,venerdì, sabato", + trans : { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, "wae_CH" : { lang: "wae_CH", decimal_point: ",", From b5fc41126c5d1f332309125129ae8974c6658b5d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Wed, 8 Apr 2020 16:48:28 +0200 Subject: [PATCH 0297/1189] 0.03 --- apps/pipboy/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/pipboy/ChangeLog b/apps/pipboy/ChangeLog index 134ba4e18..edbadd9b4 100644 --- a/apps/pipboy/ChangeLog +++ b/apps/pipboy/ChangeLog @@ -1,2 +1,3 @@ 0.01: New Watch! 0.02: Changed colors for better readability and added current date +0.03: Added Info to HP (day in year) and LEVEL (day of week / progress bar show day progress) From db06d9b7e7c6de63c034e63a35e213fe49df5377 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Wed, 8 Apr 2020 16:49:03 +0200 Subject: [PATCH 0298/1189] 0.03 --- apps/pipboy/app.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/pipboy/app.js b/apps/pipboy/app.js index 48a87fc5d..a8539c7db 100644 --- a/apps/pipboy/app.js +++ b/apps/pipboy/app.js @@ -6,6 +6,11 @@ const darkGreen = 0x0461; const darkerGreen = 0x0261; const pip = require("heatshrink").decompress(atob("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")); +function isLeapYear(year) +{ + return !((year % 4) && (year % 100) || !(year % 400)); +} + function topLine() { g.setColor(green); @@ -28,15 +33,29 @@ function topLine() { } function bottomLine() { + var today = new Date(); + var yy = today.getFullYear(); + var day = today.getDay(); //day of week as number + var h = today.getHours(); + + var startDate = new Date(yy, 0, 0); + var oneDay = 1000 * 60 * 60 * 24; + var daysInYear = 0; + var diff = today - startDate; + var currDayInYear = Math.floor(diff / oneDay); + + if (isLeapYear(yy)) daysInYear = 366; + else daysInYear = 365; + + g.setFont("6x8", tinyFont); //first line g.setColor(darkerGreen); g.fillRect(5, 175, 100, 185); //DATE g.fillRect(105, 175, 160, 185);//STIM g.fillRect(166, 175, 239, 185); // RADAWAY - g.setColor(green); - g.setFont("6x8", tinyFont); + g.drawString("DATE", 20, 177); g.drawString("STIM (3)", 135, 177); g.drawString("RADAWAY (8)", 205, 177); @@ -47,9 +66,10 @@ function bottomLine() { g.fillRect(75, 190, 239, 200); g.setColor(green); - g.drawString("HP 115/115", 38, 192); - g.drawString("LEVEL 6", 100, 192); - g.drawRect(127, 192, 235, 198); + g.drawString("HP "+ currDayInYear + "/"+ daysInYear, 38, 192); + g.drawString("LEVEL " + day, 100, 192); //show week day + g.drawRect(127, 192, 235, 198); //frame + g.fillRect(128, 193, 128 + ((107/24)*h), 197); //progress bar showing progress of day } function boy() { @@ -57,7 +77,6 @@ function boy() { } function drawClock() { - var t = new Date(); var h = t.getHours(); var m = t.getMinutes(); From 72290af0c1ba8afd803301c56c08aa6316b7231a Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Wed, 8 Apr 2020 16:50:35 +0200 Subject: [PATCH 0299/1189] Pipboy 0.03 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1187dd1bd..e9ba66804 100644 --- a/apps.json +++ b/apps.json @@ -849,7 +849,7 @@ "id": "pipboy", "name": "Pipboy", "icon": "app.png", - "version": "0.02", + "version": "0.03", "description": "Pipboy themed clock", "tags": "clock", "type":"clock", From a8af64d4fcb1e91055198dd11457d312b41e1446 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Wed, 8 Apr 2020 17:05:10 +0200 Subject: [PATCH 0300/1189] Added readme and screenshot --- apps/pipboy/README.md | 19 +++++++++++++++++++ apps/pipboy/pipboy-screenshot.png | Bin 0 -> 7499 bytes 2 files changed, 19 insertions(+) create mode 100644 apps/pipboy/README.md create mode 100644 apps/pipboy/pipboy-screenshot.png diff --git a/apps/pipboy/README.md b/apps/pipboy/README.md new file mode 100644 index 000000000..a8e03d638 --- /dev/null +++ b/apps/pipboy/README.md @@ -0,0 +1,19 @@ +# Pipboy themed clock +Have your own Pip-Boy (based on Java Script) + +![](pipboy-screenshot.png) + +## Features + +* High-end greenscreen design +* Shows all your stats +* Time +* Date +* STIMPAKS left +* RADAWAY left +* Health remaining (shows current day in year / days in year) +* Your Level (Shows day in week and progress bar for time passed in day) + +## Requests + +If you have any feature requests, please contact the original author https://twitter.com/simons_bird or co-author http://forum.espruino.com/profiles/155005/ \ No newline at end of file diff --git a/apps/pipboy/pipboy-screenshot.png b/apps/pipboy/pipboy-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..26d90ba3b3dc57aba4cbc3b29a7186878144637e GIT binary patch literal 7499 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 F{$FSm2U-9C literal 0 HcmV?d00001 From d46e78808e60e78e743d1613114dab197b2d09d4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 16:23:51 +0100 Subject: [PATCH 0301/1189] Fix issue removing an app that was just installed. Fix #253Fix issue removing an app that was just installed (Fix #253) --- CHANGELOG.md | 1 + js/comms.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 213b65852..a1cd3d803 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * `Remove All Apps` now doesn't perform a reset before erase - fixes inability to update firmware if settings are wrong * Added optional `README.md` file for apps * Remove 2v04 version warning, add links in About to official/developer versions +* Fix issue removing an app that was just installed (Fix #253) diff --git a/js/comms.js b/js/comms.js index eb453871d..12989e089 100644 --- a/js/comms.js +++ b/js/comms.js @@ -16,6 +16,11 @@ uploadApp : (app,skipReset) => { // expects an apps.json structure (i.e. with `s var maxBytes = fileContents.reduce((b,f)=>b+f.content.length, 0)||1; var currentBytes = 0; + var appInfoFileName = app.id+".info"; + var appInfoFile = fileContents.find(f=>f.name==appInfoFileName); + if (!appInfoFile) reject(`${appInfoFileName} not found`); + var appInfo = JSON.parse(appInfoFile.content); + // Upload each file one at a time function doUploadFiles() { // No files left - print 'reboot' message @@ -23,7 +28,7 @@ uploadApp : (app,skipReset) => { // expects an apps.json structure (i.e. with `s Puck.write(`\x10E.showMessage('Hold BTN3\\nto reload')\n`,(result) => { Progress.hide({sticky:true}); if (result===null) return reject(""); - resolve(app); + resolve(appInfo); }); return; } From b7d94f32441e384137763e455ae96a359396d3d8 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Wed, 8 Apr 2020 17:02:16 +0100 Subject: [PATCH 0302/1189] Integrate GadgetBridge --- apps.json | 2 +- apps/marioclock/ChangeLog | 3 +- apps/marioclock/README.md | 3 +- apps/marioclock/marioclock-app.js | 140 +++++++++++++++++++++++++++++- 4 files changed, 142 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 92df7fe93..0271c244d 100644 --- a/apps.json +++ b/apps.json @@ -914,7 +914,7 @@ { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.08", + "version":"0.09", "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", "tags": "clock,mario,retro", "type": "clock", diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index c95ce3d0d..acce6a7ed 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -5,4 +5,5 @@ 0.05: use 12/24 hour clock from settings 0.06: Performance refactor, and enhanced graphics! 0.07: Swipe right to change between Mario and Toad characters, swipe left to toggle night mode -0.08: Update date panel to be info panel toggling between Date, Battery and Temperature. Add Princes Daisy. +0.08: Update date panel to be info panel toggling between Date, Battery and Temperature. Add Princes Daisy +0.09: Add GadgetBridge functionality. Mario shows message type in speach bubble, while message scrolls in info panel \ No newline at end of file diff --git a/apps/marioclock/README.md b/apps/marioclock/README.md index 8b859e031..e6aeaa1bb 100644 --- a/apps/marioclock/README.md +++ b/apps/marioclock/README.md @@ -13,7 +13,8 @@ Enjoy watching Mario, or one of the other game characters run through a level wh * Awesome 8-bit style grey-scale graphics * Mario jumps to change the time, every minute * You can make Mario jump by pressing the bottom button (Button 3) on the watch -* Toggle the info pannel bettween `Date`, `Battery level`, and `Temperature` by pressing the top button (Button 1). +* Toggle the info pannel bettween `Date`, `Battery level`, and `Temperature` by pressing the top button (Button 1) +* If you have [GadgetBridge](https://f-droid.org/packages/nodomain.freeyourgadget.gadgetbridge/) installed on your phone, Mario will let you know when you get a new call or notification. You can clear a message by pressing either Button 1 or Button 3 ## Requests diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index 81f5616b9..529f1c95b 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -58,6 +58,7 @@ const ONE_SECOND = 1000; const DATE_MODE = "date"; const BATT_MODE = "batt"; const TEMP_MODE = "temp"; +const PHON_MODE = "gbri"; let timer = 0; let backgroundArr = []; @@ -68,6 +69,77 @@ let infoMode = DATE_MODE; let lastBatt = 0; let lastTemp = 0; +const phone = { + get status() { + return NRF.getSecurityStatus().connected ? "Yes" : "No"; + }, + message: null, + messageTimeout: null, + messageScrollX: null, + messageType: null, +}; + +function phoneOutbound(msg) { + Bluetooth.println(JSON.stringify(msg)); +} + +function phoneClearMessage() { + if (phone.message === null) return; + + if (phone.messageTimeout) { + clearTimeout(phone.messageTimeout); + phone.messageTimeout = null; + } + phone.message = null; + phone.messageScrollX = null; + phone.messageType = null; +} + +function phoneNewMessage(type, msg) { + Bangle.buzz(); + + phoneClearMessage(); + phone.messageTimeout = setTimeout(() => phone.message = null, ONE_SECOND * 30); + phone.message = msg; + phone.messageType = type; + + // Notify user and active screen + if (!Bangle.isLCDOn()) { + clearTimers(); + Bangle.setLCDPower(true); + } +} + +function truncStr(str, max) { + if (str.length > max) { + return str.substr(0, max) + '...'; + } + return str; +} + +function phoneInbound(evt) { + switch (evt.t) { + case 'notify': + const sender = truncStr(evt.sender, 10); + const subject = truncStr(evt.subject, 15); + phoneNewMessage("notify", `${sender} - '${subject}'`); + break; + case 'call': + if (evt.cmd === "accept") { + let nameOrNumber = "Unknown"; + if (evt.name !== null || evt.name !== "") { + nameOrNumber = evt.name; + } else if (evt.number !== null || evt.number !== "") { + nameOrNumber = evt.number; + } + phoneNewMessage("call", nameOrNumber); + } + break; + default: + return null; + } +} + function genRanNum(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } @@ -248,6 +320,22 @@ function drawToadFrame(idx, x, y) { } } +// Mario speach bubble +function drawNotice(x, y) { + if (phone.message === null) return; + + switch (phone.messageType) { + case "call": + const callImg = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INEw9cAAIPFBxAPEBw/WBxYACDrQ7QLI53OSpApDBoQAHB4INLByANNAwo=")); + g.drawImage(callImg, characterSprite.x, characterSprite.y - 16); + break; + case "notify": + const msgImg = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INCrgAHB4QOEDQgOIAIQFGBwovDA4gOGFooOVLJR3OSpApDBoQAHB4INLByANNAwoA=")); + g.drawImage(msgImg, characterSprite.x, characterSprite.y - 16); + break; + } +} + function drawCharacter(date, character) { // calculate jumping const seconds = date.getSeconds(), @@ -352,9 +440,33 @@ function buildTempStr() { return tempStr; } +function buildPhonStr() { + return `Phone: ${phone.status}`; +} + function drawInfo(date) { + let xPos; let str = ""; - switch(infoMode) { + + if (phone.message !== null) { + str = phone.message; + const strLen = g.stringWidth(str); + if (strLen > W) { + if (phone.messageScrollX === null || (phone.messageScrollX <= (strLen * -1))) { + phone.messageScrollX = W; + resetDisplayTimeout(); + } else { + phone.messageScrollX -= 2; + } + xPos = phone.messageScrollX; + } else { + xPos = (W - g.stringWidth(str)) / 2; + } + } else { + switch(infoMode) { + case PHON_MODE: + str = buildPhonStr(); + break; case TEMP_MODE: str = buildTempStr(); break; @@ -364,19 +476,26 @@ function drawInfo(date) { case DATE_MODE: default: str = buildDateStr(date); + } + xPos = (W - g.stringWidth(str)) / 2; } g.setFont("6x8"); g.setColor(LIGHTEST); - g.drawString(str, (W - g.stringWidth(str))/2, 1); + g.drawString(str, xPos, 1); } function changeInfoMode() { + phoneClearMessage(); + switch(infoMode) { case BATT_MODE: infoMode = TEMP_MODE; break; case TEMP_MODE: + infoMode = PHON_MODE; + break; + case PHON_MODE: infoMode = DATE_MODE; break; case DATE_MODE: @@ -399,6 +518,7 @@ function redraw() { drawTime(date); drawInfo(date); drawCharacter(date); + drawNotice(); drawCoin(); // Render new frame @@ -450,6 +570,7 @@ function init() { setWatch(() => { if (intervalRef && !characterSprite.isJumping) characterSprite.isJumping = true; resetDisplayTimeout(); + phoneClearMessage(); // Clear any phone messages and message timers }, BTN3, {repeat: true}); // Close watch and load launcher app @@ -487,8 +608,21 @@ function init() { } }); + // Phone connectivity + try { NRF.wake(); } catch (e) {} + + NRF.on('disconnect', () => Bangle.buzz()); + NRF.on('connect', () => { + setTimeout(() => { + phoneOutbound({ t: "status", bat: E.getBattery() }); + }, ONE_SECOND * 2); + Bangle.buzz(); + }); + + GB = (evt) => phoneInbound(evt); + startTimers(); } // Initialise! -init(); \ No newline at end of file +init() \ No newline at end of file From 006c4e6960e726daabfa3976023157ee9ec24836 Mon Sep 17 00:00:00 2001 From: Dimitri Gigot Date: Wed, 8 Apr 2020 16:42:47 +0000 Subject: [PATCH 0303/1189] Improve the perf --- apps.json | 2 +- apps/toucher/ChangeLog | 3 ++- apps/toucher/app.js | 19 ++++++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index e250da0f6..02c6364aa 100644 --- a/apps.json +++ b/apps.json @@ -1035,7 +1035,7 @@ "name": "Touch Launcher", "shortName":"Menu", "icon": "app.png", - "version":"0.04", + "version":"0.05", "description": "Touch enable left to right launcher.", "tags": "tool,system,launcher", "type":"launch", diff --git a/apps/toucher/ChangeLog b/apps/toucher/ChangeLog index c536d1a5b..a2a709ee3 100644 --- a/apps/toucher/ChangeLog +++ b/apps/toucher/ChangeLog @@ -1,4 +1,5 @@ 0.01: New App! 0.02: Add swipe support and doucle tap to run application 0.03: Close launcher when lcd turn off -0.04: Complete rewrite to add animation and loop ( issue #210 ) \ No newline at end of file +0.04: Complete rewrite to add animation and loop ( issue #210 ) +0.05: Improve perf \ No newline at end of file diff --git a/apps/toucher/app.js b/apps/toucher/app.js index 5c3703129..b67e5b26c 100644 --- a/apps/toucher/app.js +++ b/apps/toucher/app.js @@ -19,7 +19,7 @@ function getApps(){ const HEIGHT = g.getHeight(); const WIDTH = g.getWidth(); const HALF = WIDTH/2; -const ANIMATION_FRAME = 3; +const ANIMATION_FRAME = 4; const ANIMATION_STEP = HALF / ANIMATION_FRAME; function getPosition(index){ @@ -35,6 +35,8 @@ const back = { back: true }; +let icons = {}; + const apps = [back].concat(getApps()); apps.push(back); @@ -54,6 +56,12 @@ function drawIcons(offset){ const y = HALF - (HALF*0.3);//-(HALF*0.7); let diff = (x - HALF); if(diff < 0) diff *=-1; + + const dontRender = x+(HALF/2)<0 || x-(HALF/2)>120; + if(dontRender) { + delete icons[app.name]; + return; + } let size = 30; if((diff*0.5) < size) size -= (diff*0.5); else size = 0; @@ -72,8 +80,12 @@ function drawIcons(offset){ return; } // icon - const icon = app.icon ? Storage.read(app.icon) : null; + + 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){ @@ -100,7 +112,8 @@ function drawIcons(offset){ } function draw(ignoreLoop){ - g.clear(); + g.setColor(0,0,0); + g.fillRect(0,0,WIDTH,HEIGHT); drawIcons(slideOffset); g.flip(); if(slideOffset == target) return; From d2159b6ec4c00a6f3847380644a3df1a2f808cb4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 21:22:51 +0100 Subject: [PATCH 0304/1189] OpenStreetMap: Fix marker position, color, and map scaling --- apps.json | 4 ++-- apps/openstmap/ChangeLog | 1 + apps/openstmap/app.js | 30 ++++++++++++++++-------------- apps/openstmap/custom.html | 36 +++++++++++++++++++++++------------- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/apps.json b/apps.json index e250da0f6..1f6314f74 100644 --- a/apps.json +++ b/apps.json @@ -1099,7 +1099,7 @@ "name": "OpenStreetMap", "shortName":"OpenStMap", "icon": "app.png", - "version":"0.01", + "version":"0.02", "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", @@ -1118,7 +1118,7 @@ "storage": [ {"name":"tabata.app.js","url":"tabata.js"}, {"name":"tabata.img","url":"tabata-icon.js","evaluate":true} - ] + ] }, { "id": "custom", "name": "Custom Boot Code ", diff --git a/apps/openstmap/ChangeLog b/apps/openstmap/ChangeLog index 5560f00bc..2d60cb688 100644 --- a/apps/openstmap/ChangeLog +++ b/apps/openstmap/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Fix marker position, color, and map scaling diff --git a/apps/openstmap/app.js b/apps/openstmap/app.js index ec6dfdfd9..ae4817f16 100644 --- a/apps/openstmap/app.js +++ b/apps/openstmap/app.js @@ -28,14 +28,24 @@ function redraw() { } } } - g.setColor(1,0,0); - /*g.fillRect(cx-10,cy-1,cx+10,cy+1); - g.fillRect(cx-1,cy-10,cx+1,cy+10);*/ - if (fix.fix) - g.fillRect(cx-2,cy-2,cx+2,cy+2); + drawMarker(); } + +function drawMarker() { + if (!fix.fix) return; + var p = Bangle.project({lat:lat,lon:lon}); + var q = Bangle.project(fix); + var cx = g.getWidth()/2; + var cy = g.getHeight()/2; + var ix = (q.x-p.x)*4096/map.scale + cx; + var iy = cy - (q.y-p.y)*4096/map.scale; + g.setColor(1,0,0); + g.fillRect(ix-2,iy-2,ix+2,iy+2); +} + redraw(); + var fix; Bangle.on('GPS',function(f) { fix=f; @@ -47,15 +57,7 @@ Bangle.on('GPS',function(f) { if (!fix.fix) txt += " - NO FIX"; g.drawString(txt,120,4); - if (fix.fix) { - var p = Bangle.project({lat:lat,lon:lon}); - var q = Bangle.project(fix); - var cx = g.getWidth()/2; - var cy = g.getHeight()/2; - var ix = (q.x-p.x)*4096/map.scale + cx; - var iy = (q.y-p.y)*4096/map.scale + cy; - g.fillRect(ix-2,iy-2,ix+2,iy+2); - } + drawMarker(); }); Bangle.setGPSPower(1); redraw(); diff --git a/apps/openstmap/custom.html b/apps/openstmap/custom.html index cac95a94e..1b7cfada4 100644 --- a/apps/openstmap/custom.html +++ b/apps/openstmap/custom.html @@ -32,9 +32,10 @@
-

Zoom in to the area you want as a map

-

Click

- +
+ +
@@ -64,6 +65,7 @@ TODO: maxZoom: 18, attribution: 'Map data © OpenStreetMap contributors' }); + var mapFiles = []; tileLayer.addTo(map); function tilesLoaded(ctx, width, height) { @@ -93,7 +95,7 @@ TODO: return tiles; } - document.getElementById("upload").addEventListener("click", function() { + document.getElementById("getmap").addEventListener("click", function() { var bounds = map.getBounds(); var zoom = map.getZoom(); var centerlatlon = bounds.getCenter(); @@ -105,6 +107,7 @@ TODO: // Render everything to a canvas - 512 x 512 px var canvas = document.getElementById("maptiles"); + canvas.style.display=""; var ctx = canvas.getContext('2d'); canvas.width = OSMTILESIZE*2; canvas.height = OSMTILESIZE*2; @@ -128,25 +131,32 @@ TODO: Promise.all(tileGetters).then(() => { - var files = tilesLoaded(ctx, canvas.width, canvas.height); - files.unshift({name:"openstmap.json",content:JSON.stringify({ + document.getElementById("uploadbuttons").style.display=""; + mapFiles = tilesLoaded(ctx, canvas.width, canvas.height); + mapFiles.unshift({name:"openstmap.json",content:JSON.stringify({ imgx : canvas.width, imgy : canvas.height, tilesize : TILESIZE, - scale : 10000*Math.pow(2,zoom-16), // FIXME - this is probably wrong + scale : 10000*Math.pow(2,16-zoom), // FIXME - this is probably wrong lat : centerlatlon.lat, lon : centerlatlon.lng })}); - files.unshift({"name":"openstmap.app.js","url":"app.js"}); - files.unshift({"name":"openstmap.img","url":"app-icon.js","evaluate":true}); + mapFiles.unshift({"name":"openstmap.app.js","url":"app.js"}); + mapFiles.unshift({"name":"openstmap.img","url":"app-icon.js","evaluate":true}); - console.log(files); - sendCustomizedApp({ - storage:files - }); + console.log(mapFiles); }); + }); + document.getElementById("upload").addEventListener("click", function() { + sendCustomizedApp({ + storage:mapFiles + }); + }); + document.getElementById("cancel").addEventListener("click", function() { + document.getElementById("maptiles").style.display="none"; + document.getElementById("uploadbuttons").style.display="none"; }); From dbb558a5c87aa9755aac86b37b5240fee518798f Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 8 Apr 2020 22:28:24 +0200 Subject: [PATCH 0305/1189] Adds BatteryChart app and widget --- apps.json | 13 +++++++++++++ apps/batchart/ChangeLog | 1 + apps/batchart/app.js | 32 ++++++++++++++++++++++++++++++++ apps/batchart/app.png | Bin 0 -> 1620 bytes apps/batchart/widget.js | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 apps/batchart/ChangeLog create mode 100644 apps/batchart/app.js create mode 100644 apps/batchart/app.png create mode 100644 apps/batchart/widget.js diff --git a/apps.json b/apps.json index 6b9198f33..5ec359c16 100644 --- a/apps.json +++ b/apps.json @@ -1131,5 +1131,18 @@ "storage": [ {"name":"custom"} ] + }, + { "id": "batchart", + "name": "Battery Chart", + "shortName":"BatChart", + "icon": "widget.png", + "version":"0.01", + "description": "A widget and an app for recording and visualizing battery percentage over time.", + "tags": "app,widget,battery,time,record,chart,tool", + "storage": [ + {"name":"batchart.wid.js","url":"widget.js"}, + {"name":"batchart.app.js","url":"app.js"}, + {"name":"batchart.img.js","url":"app-icon.js"} + ] } ] diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/batchart/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/batchart/app.js b/apps/batchart/app.js new file mode 100644 index 000000000..c82b15737 --- /dev/null +++ b/apps/batchart/app.js @@ -0,0 +1,32 @@ +// place your const, vars, functions or classes here + +function renderBatteryChart(){ + g.drawString("t", 215, 175); + g.drawLine(40,190,40,80); + + g.drawString("%", 39, 70); + g.drawString("100", 15, 75); + g.drawLine(35,80,40,80); + + g.drawString("50", 20,125); + g.drawLine(35,130,40,130); + + g.drawString("0", 25, 175); + g.drawLine(35,180,210,180); + + g.drawString("Chart not yet functional", 60, 125); +} + +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + if (on) { + // call your app function here + // If you clear the screen, do Bangle.drawWidgets(); + renderBatteryChart(); + } +}); + +g.clear(); +// call your app function here + +renderBatteryChart(); diff --git a/apps/batchart/app.png b/apps/batchart/app.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 { + var settings = {}; + var batChartFile; // file for battery percentage recording + const recordingInterval10Min = 60*10*1000; + const recordingInterval10S = 10*1000; //For testing + var recordingInterval = null; + + // draw your widget + function draw() { + if (!settings.isRecording) return; + g.reset(); + g.drawString("BC", this.x, this.y); + } + + // Called by the heart app to reload settings and decide what's + function reload() { + WIDGETS["batchart"].width = 24; + batChartFile = require("Storage").open(".batchart","a"); + recordingInterval = setInterval(()=>{ + if (batChartFile) + console.log ([getTime().toFixed(0),E.getBattery()].join(",")); + //batChartfile.write([getTime().toFixed(0),E.getBattery].join(",")+"\n"); + }, recordingInterval10S) + } + + // add the widget + WIDGETS["batchart"]={area:"tl",width:24,draw:draw,reload:function() { + reload(); + Bangle.drawWidgets(); // relayout all widgets + }}; + // load settings, set correct widget width + reload(); +})() \ No newline at end of file From 8b2ea9f0c3148ac6b8ddf40a4b57205edcc628ae Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 8 Apr 2020 22:30:28 +0200 Subject: [PATCH 0306/1189] widpedom: Add goal setting Draws progress as part of a circle (default goal: 10.000 seems to be common-ish?) --- apps.json | 5 +-- apps/widpedom/ChangeLog | 1 + apps/widpedom/settings.js | 44 ++++++++++++++++++++++++ apps/widpedom/widget.js | 71 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 apps/widpedom/settings.js diff --git a/apps.json b/apps.json index e250da0f6..2a4cd7750 100644 --- a/apps.json +++ b/apps.json @@ -786,12 +786,13 @@ { "id": "widpedom", "name": "Pedometer widget", "icon": "widget.png", - "version":"0.08", + "version":"0.09", "description": "Daily pedometer widget", "tags": "widget", "type":"widget", "storage": [ - {"name":"widpedom.wid.js","url":"widget.js"} + {"name":"widpedom.wid.js","url":"widget.js"}, + {"name":"widpedom.settings.js","url":"settings.js"} ] }, { "id": "berlinc", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index 980494acb..d6fe28940 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -5,3 +5,4 @@ 0.06: Fix widget position increment 0.07: Tweaks for variable size widget system 0.08: Ensure redrawing works with variable size widget system +0.09: Add daily goal diff --git a/apps/widpedom/settings.js b/apps/widpedom/settings.js new file mode 100644 index 000000000..f6d30b830 --- /dev/null +++ b/apps/widpedom/settings.js @@ -0,0 +1,44 @@ +(function(back) { + const SETTINGS_FILE = 'widpedom.settings.json' + + // initialize with default settings... + let s = { + 'goal': 10000, + 'progress': false, + } + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage') + const saved = storage.readJSON(SETTINGS_FILE, 1) || {} + for (const key in saved) { + s[key] = saved[key] + } + + function save() { + storage.write(SETTINGS_FILE, s) + WIDGETS['wpedom'].reload() + } + + E.showMenu({ + '': { 'title': 'Pedometer widget' }, + 'Daily Goal': { + value: s.goal, + min: 0, step: 1000, + format: s => (s ? s / 1000 + ',000' : '0'), + onchange: (g) => { + s.goal = g + s.progress = !!g + save() + }, + }, + 'Show Progress': { + value: s.progress, + format: () => (s.progress ? 'Yes' : 'No'), + onchange: () => { + s.progress = !s.progress + save() + }, + }, + '< Back': back, + }) +}) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 1cc14fc2c..a9e5bf121 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -1,7 +1,57 @@ (() => { - const PEDOMFILE = "wpedom.json"; + const PEDOMFILE = "wpedom.json" + const SETTINGS_FILE = "widpedom.settings.json" + const DEFAULTS = { + 'goal': 10000, + 'progress': false, + } + const COLORS = { + 'white': -1, + 'progress': 0x001F, // Blue + 'done': 0x03E0, // DarkGreen + } + const TAU = Math.PI*2; let lastUpdate = new Date(); let stp_today = 0; + let settings; + + function loadSettings() { + settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; + } + + function setting(key) { + if (!settings) { loadSettings() } + return (key in settings) ? settings[key] : DEFAULTS[key]; + } + + function drawProgress(stps) { + if (setting('progress')) { + const width = 24, half = width/2; + const goal = setting('goal'), left = Math.max(goal-stps,0); + const c = left ? COLORS.progress : COLORS.done; + g.setColor(c).fillCircle(this.x + half, this.y + half, half); + if (left) { + const f = left/goal; // fraction to blank out + let p = []; + p.push(half,half); + p.push(half,0); + if(f>1/8) p.push(0,0); + if(f>2/8) p.push(0,half); + if(f>3/8) p.push(0,width); + if(f>4/8) p.push(half,width); + if(f>5/8) p.push(width,width); + if(f>6/8) p.push(width,half); + if(f>7/8) p.push(width,0); + p.push(half - Math.sin(f * TAU) * half); + p.push(half - Math.cos(f * TAU) * half); + for (let i = p.length; i; i -= 2) { + p[i - 2] += this.x; + p[i - 1] += this.y; + } + g.setColor(0).fillPoly(p); + } + } + } // draw your widget function draw() { @@ -11,6 +61,9 @@ } let stps = stp_today.toString(); g.reset(); + g.clearRect(this.x, this.y, this.x + width, this.y + 23); // erase background + drawProgress(stps); + g.setColor(COLORS.white); if (stps.length > 3){ stps = stps.slice(0,-3) + "," + stps.slice(-3); g.setFont("4x6", 1); // if big, shrink text to fix @@ -18,11 +71,15 @@ g.setFont("6x8", 1); } g.setFontAlign(0, 0); // align to x: center, y: center - g.clearRect(this.x,this.y+15,this.x+width,this.y+23); // erase background g.drawString(stps, this.x+width/2, this.y+19); g.drawImage(atob("CgoCLguH9f2/7+v6/79f56CtAAAD9fw/n8Hx9A=="),this.x+(width-10)/2,this.y+2); } + function reload() { + loadSettings() + draw() + } + Bangle.on('step', (up) => { let date = new Date(); if (lastUpdate.getDate() == date.getDate()){ @@ -31,7 +88,13 @@ // TODO: could save this to PEDOMFILE for lastUpdate's day? stp_today = 1; } - lastUpdate = date; + if (stp_today === setting('goal')) { + let b = 3, buzz = () => { + if (b--) Bangle.buzz().then(() => setTimeout(buzz, 100)) + } + buzz() + } + lastUpdate = date //console.log("up: " + up + " stp: " + stp_today + " " + date.toString()); if (Bangle.isLCDOn()) WIDGETS["wpedom"].draw(); }); @@ -49,7 +112,7 @@ }); // add your widget - WIDGETS["wpedom"]={area:"tl",width:26,draw:draw}; + WIDGETS["wpedom"]={area:"tl",width:26,draw:draw,reload:Reload}; // Load data at startup let pedomData = require("Storage").readJSON(PEDOMFILE,1); if (pedomData) { From 4bdc5813d365c1b3b7798939e562c9755ce78f97 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Apr 2020 21:34:40 +0100 Subject: [PATCH 0307/1189] change default map provider --- apps/openstmap/custom.html | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openstmap/custom.html b/apps/openstmap/custom.html index 1b7cfada4..50d6149cb 100644 --- a/apps/openstmap/custom.html +++ b/apps/openstmap/custom.html @@ -53,18 +53,23 @@ TODO: * Could potentially use a custom 16 color palette? * Allow user to choose size of map area to be uploaded (small/med/large) * What is faster? Storing as a compressed image and decompressing, or storing decompressed? -* Scaling for zoom levels */ var TILESIZE = 64; var OSMTILESIZE = 256; var OSMSUBTILES = OSMTILESIZE / TILESIZE; + /* Can see possible tiles on http://leaflet-extras.github.io/leaflet-providers/preview/ + However some don't allow cross-origin use */ + var TILELAYER = 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'; // simple, high contrast + //var TILELAYER = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; + //var TILELAYER = 'http://a.tile.stamen.com/toner/{z}/{x}/{y}.png'; // black and white var map = L.map('map').locate({setView: true, maxZoom: 16}); - var tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - //var tileLayer = L.tileLayer('http://a.tile.stamen.com/toner/{z}/{x}/{y}.png', { // black and white + var tileLayer = L.tileLayer(TILELAYER, { maxZoom: 18, attribution: 'Map data © OpenStreetMap contributors' }); + // Could optionally overlay trails: https://wiki.openstreetmap.org/wiki/Tiles + var mapFiles = []; tileLayer.addTo(map); From fa23aaf3f0094617c4b04bd9e957e0dc112306b4 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 9 Apr 2020 08:19:38 +0200 Subject: [PATCH 0308/1189] Widget stores data to file, icon added --- apps.json | 2 +- apps/batchart/ChangeLog | 3 ++- apps/batchart/app-icon.js | 1 + apps/batchart/app.png | Bin 1620 -> 1498 bytes apps/batchart/batchart.dat | 0 apps/batchart/widget.js | 52 +++++++++++++++++++++++++++++++------ 6 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 apps/batchart/app-icon.js create mode 100644 apps/batchart/batchart.dat diff --git a/apps.json b/apps.json index 5ec359c16..614befed2 100644 --- a/apps.json +++ b/apps.json @@ -1136,7 +1136,7 @@ "name": "Battery Chart", "shortName":"BatChart", "icon": "widget.png", - "version":"0.01", + "version":"0.02", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index 5560f00bc..d885f8fb0 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -1 +1,2 @@ -0.01: New App! +0.01: New app and widget +0.02: Widget stores data to file (1 dataset/min) diff --git a/apps/batchart/app-icon.js b/apps/batchart/app-icon.js new file mode 100644 index 000000000..0841ea920 --- /dev/null +++ b/apps/batchart/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AS64AIF/4pZABYuuGDIv/F/4v/F9+Gw0rAQIASF7YxTF7cxwAvtrdVF9qQTF/4vMYCQvcYCQvcSCQvdqpgQF7oEBYJ4veAoNbF9uGmMrrgvsw2AGILFKF8IACrYxJF8gxDSowvmBwWAF9oPGF9NbmIvtCAovqMAgvqCIgvrrdVF9oSDF9iPuF7crACxf/F++wFqmG2AvXGCouZAH4A/AGY")) \ No newline at end of file diff --git a/apps/batchart/app.png b/apps/batchart/app.png index 582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0..9a60d100432a8648784022c43dd397e72afb5ccc 100644 GIT binary patch literal 1498 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WMyDrW(e>JaRrI9F>&y)aPhP93bFBvatKRv$*A)y83?JG2&CS-=*Ko0#DIQ#y<@*e_hGNeN2AW)xO4f={VR9w-@O0i#)HQ|H;jVO5EzgU z&|F(M37Ah9N`m}?|Br0I5d5886&MMe1s;*b3=DjSL74G){)!Z!phSslL`iUdT1k0g zQ7S`0VrE{6US4X6f{C7io@r{UQ7SMHjXhl)Lp;3iPP!d*$UwwZdu@Z5c94FD#)YC4 zFaFoZ^IAvGHd(mvaQ7}br)Ame6L+|j`v3Fz5IK?G&fp{K9PJ+mj_`exiF%`H8us9B z_*HAu4NQD8D-Q1Gc2WB1$U8?tZ->zWHopSf=cgK^EDpYzrp=u7fTde7obAd1&QsmI z>AXNX<Q{8tX}s+|6^rctV*De1;Pkt+v;Pk2wtH~iBk^@AyL z>Ed=Fb6(RAY)YR^&Q04hU!-G?@8px(@2@<_PzbtrwEveIuNBk8qf7toTj7|la5|;5 zVj5smvdd|Uf~r7kw$dVFc}wUG3)f;T~l-_zC4Wt~$(695Pg B=TiUx delta 1614 zcmV-U2C@0t3)Bpd8Gi-<00374`G)`i00v@9M??Vs0RI60puMM)000IFNklVsi@IIDWLJF<-tS+MbQVNMvWngMiMVMF($}~PbV60 ziJqKGq6sl-z#5IgNDvG@D81m_8L(pU0#u>&LWh~o%w9f}(tqj9-n)CIwK<9WpZ2=# z@4xo`F6;X~IE~Zzb3>-k8akT^^OxcFx zcbN5=Q-4hR%xR(Og4IMqZ|csgd~Qy535+rOMa0?#Kz;OCgf+QCRm!I{`+3DGB8Q%K zb12A8MekO_`m$nMR~$gwqc;H$X+p4i#=p9GL1wziIzZOz?xtO`H1@Ww)h$#z=T~9{ zVnFT4`+q^wyMm*J0F*s8gp{jW_;jL|l)p)?`07}`!LAF9Ljz9%wK^oEKM9^v2d+uZ zBzb_ElWR@^923y?MQ5Sh3y}H359v|8R9g6#r~d$slVYvzX{^gvI{yK&9t6Sw)^Fo( z=6P9=8U6ZW2$40``%xcZ;5%V%3U4s;k`B zBhPV`-mc1q+yc;cGT(T8!xE53$1?&6D*mfe_?M*-n>DO|&}2{l-??t>KM^xP{PQp9 zJ>sMDt1wG0P7(^*|FxpxgxUNu=e>XY@94oXm34 z@_%b@CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu%1M71EC`5o2if_~ z7E&h??0jeQ1Y3N6p?}G72FSn>E+sATQ)Q)70!M+WViTAl9FdlI^_bw)g$_FC{~s`6^Y4_v-WecL8bso`qJL8Y zT{A$XG+1=ziuMVJ_2G<=DGAn&T*-bAD+V3WAAobF+T38@2nY8MbM(*&lEYc7tP(2s zF}E&6{RI_-Bd%NCJYpQ6B|bm5n6r%*!O{-dgz6Ke5>FZGo<5&Mq0i(4E(oP@&iXk z=-U1(Bgrgt{}SSg8|!FVQpN1*ApW3%X$qBd0$g%sHPPlXP=%gv2Ryu4{(qfM9wyt= zf4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+AnsNK1#>!x0o zbq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&ItO{WI-48rG zLwQb?#vgVvduyd9_6W)rFMqC8HKFMv5ASjy{+OGC=L-(~Zb6V^zSn`(Q>Nt&ZJd$0 zO%`^i+?+grDp}Z_q9=X}=<|3S6D2}Xo}(vz>ty7i#49G<-Lx9fe*rb6#JivumHVB} zLG4gdXO*R~xABLfz>ADt4^0(GkQeZWqQ#Jh>AK{zSO1DgHe=9$GLP~7^>KusvDgRF0oD#$_U@VLHS1}d#-AO(16^7(dI!@4R{#J2 M07*qoM6N<$f_kSNbpQYW diff --git a/apps/batchart/batchart.dat b/apps/batchart/batchart.dat new file mode 100644 index 000000000..e69de29bb diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 85cff4cf4..4335a3719 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -1,9 +1,18 @@ WIDGETS = {}; (() => { + var switchableConsumers = { + none: 0, + lcd: 1, + compass: 2, + bluetooth: 4, + gps: 8, + hrm: 16 + } var settings = {}; var batChartFile; // file for battery percentage recording - const recordingInterval10Min = 60*10*1000; + const recordingInterval10Min = 60 * 10 * 1000; + const recordingInterval1Min = 60*1000; //For testing const recordingInterval10S = 10*1000; //For testing var recordingInterval = null; @@ -16,13 +25,40 @@ WIDGETS = {}; // Called by the heart app to reload settings and decide what's function reload() { - WIDGETS["batchart"].width = 24; - batChartFile = require("Storage").open(".batchart","a"); - recordingInterval = setInterval(()=>{ - if (batChartFile) - console.log ([getTime().toFixed(0),E.getBattery()].join(",")); - //batChartfile.write([getTime().toFixed(0),E.getBattery].join(",")+"\n"); - }, recordingInterval10S) + WIDGETS["batchart"].width = 24; + + // Check if the data file exists, if not try to create it. + var batChartFileCheck = require("Storage").open("batchart.dat", "r"); + if (!batChartFileCheck) + if (!require("Storage").write("batchart.dat", "")) + //Only continue if the file was created + return; + + recordingInterval = setInterval(() => { + var batChartFileAppend = require("Storage").open("batchart.dat", "a"); + if (batChartFileAppend) { + console.log([getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")); + batChartFileAppend.write([getTime().toFixed(0),E.getBattery].join(",")+"\n"); + } + }, recordingInterval1Min) + } + + function getEnabledConsumersValue() { + var enabledConsumers = switchableConsumers.none; + + if (Bangle.isLCDOn()) + enabledConsumers = enabledConsumers | switchableConsumers.lcd; + // Already added in the hope they will be available soon to get more details + // if (Bangle.isCompassOn()) + // enabledConsumers = enabledConsumers | switchableConsumers.compass; + // if (Bangle.isBluetoothOn()) + // enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; + // if (Bangle.isGpsOn()) + // enabledConsumers = enabledConsumers | switchableConsumers.gps; + // if (Bangle.isHrmOn()) + // enabledConsumers = enabledConsumers | switchableConsumers.hrm; + + return enabledConsumers; } // add the widget From 98440c54c9dd4f9ba7b8326710692cfc94cc5e85 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 9 Apr 2020 08:25:27 +0200 Subject: [PATCH 0309/1189] Use correct batchart icon --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 614befed2..beddd2878 100644 --- a/apps.json +++ b/apps.json @@ -1135,14 +1135,14 @@ { "id": "batchart", "name": "Battery Chart", "shortName":"BatChart", - "icon": "widget.png", + "icon": "app.png", "version":"0.02", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ {"name":"batchart.wid.js","url":"widget.js"}, {"name":"batchart.app.js","url":"app.js"}, - {"name":"batchart.img.js","url":"app-icon.js"} + {"name":"batchart.img.js","url":"app-icon.js","evaluate":true} ] } ] From 248b0bbf96668d4e8c88d04c0adf8eaa585a9795 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 9 Apr 2020 08:30:15 +0200 Subject: [PATCH 0310/1189] Removes WIDGETS declaration --- apps/batchart/widget.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 4335a3719..48c54426b 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -1,5 +1,3 @@ -WIDGETS = {}; - (() => { var switchableConsumers = { none: 0, From 8d89334c4de6162de928d6ac304ec17f790663dd Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 9 Apr 2020 08:35:11 +0200 Subject: [PATCH 0311/1189] Small fixes --- apps/batchart/app.js | 2 ++ apps/batchart/widget.js | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/batchart/app.js b/apps/batchart/app.js index c82b15737..684f9a88d 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -27,6 +27,8 @@ Bangle.on('lcdPower', (on) => { }); g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); // call your app function here renderBatteryChart(); diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 48c54426b..b002da5d9 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -16,7 +16,6 @@ // draw your widget function draw() { - if (!settings.isRecording) return; g.reset(); g.drawString("BC", this.x, this.y); } From ea32401ba6fc944825c94dad69e27a5da61159c0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 9 Apr 2020 08:57:06 +0100 Subject: [PATCH 0312/1189] Locale 0.06: Remove translations if not required Ensure 'on' is always supplied for translations --- apps.json | 4 ++-- apps/locale/ChangeLog | 2 ++ apps/locale/locale.html | 3 ++- apps/locale/locales.js | 25 ++++++++++++++++--------- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/apps.json b/apps.json index 9341f2be9..51b33f54d 100644 --- a/apps.json +++ b/apps.json @@ -65,7 +65,7 @@ { "id": "locale", "name": "Languages", "icon": "locale.png", - "version":"0.05", + "version":"0.06", "description": "Translations for different countries", "tags": "tool,system,locale,translate", "type": "locale", @@ -1118,7 +1118,7 @@ "storage": [ {"name":"tabata.app.js","url":"tabata.js"}, {"name":"tabata.img","url":"tabata-icon.js","evaluate":true} - ] + ] }, { "id": "custom", "name": "Custom Boot Code ", diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index d46bbaea0..3d983150d 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -4,3 +4,5 @@ 0.04: Add function meridian 0.05: Inline locale details - faster, less memory overhead Add correct scaling for speed/distance/temperature +0.06: Remove translations if not required + Ensure 'on' is always supplied for translations diff --git a/apps/locale/locale.html b/apps/locale/locale.html index 5cb4b4598..21bf37f29 100644 --- a/apps/locale/locale.html +++ b/apps/locale/locale.html @@ -50,6 +50,7 @@ exports = { name : "en_GB", currencySym:"£", // do some sanity checks Object.keys(locales).forEach(function(localeName) { var locale = locales[localeName]; + if (locale.trans && !locale.trans.on) console.error(localeName+": If translations are provided, 'on' *must* be included"); if (distanceUnits[locale.distance[0]]===undefined) console.error(localeName+": Unknown distance unit "+locale.distance[0]); if (distanceUnits[locale.distance[1]]===undefined) console.error(localeName+": Unknown distance unit "+locale.distance[1]); if (speedUnits[locale.speed]===undefined) console.error(localeName+": Unknown speed unit "+locale.speed); @@ -131,7 +132,7 @@ exports = { distance: n => (n < ${distanceUnits[locale.distance[1]]}) ? Math.round(n/${distanceUnits[locale.distance[0]]}) + ${js(locale.distance[0])} : Math.round(n/${distanceUnits[locale.distance[1]]}) + ${js(locale.distance[1])}, speed: s => Math.round(s/${speedUnits[locale.speed]}) + ${js(locale.speed)}, temp: t => Math.round(${temperature}) + ${js(locale.temperature)}, - translate: s => {var t=${js(locale.trans)};s=""+s;return t[s]||t[s.toLowerCase()]||s;}, + translate: s => ${locale.trans?`{var t=${js(locale.trans)};s=""+s;return t[s]||t[s.toLowerCase()]||s;}`:`s`}, date: (d,short) => (short) ? \`${dateS}\`: \`${dateN}\`, time: (d,short) => (short) ? \`${timeS}\`: \`${timeN}\`, meridian: d => (d.getHours() <= 12) ? ${js(locale.ampm[0])}:${js(locale.ampm[1])}, diff --git a/apps/locale/locales.js b/apps/locale/locales.js index f8eb262f0..23468ebde 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -49,7 +49,8 @@ var locales = { month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - trans: { /*yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off"*/ }}, + // No translation for english... + }, "de_DE": { lang: "de_DE", decimal_point: ",", @@ -83,7 +84,8 @@ var locales = { month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - trans: { yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + // No translation for english... + }, "en_JP": { // we do not have the font, so it is not ja_JP lang: "en_JP", decimal_point: ".", @@ -100,7 +102,8 @@ var locales = { month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - trans: { yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + // No translation for english... + }, "nl_NL": { lang: "nl_NL", decimal_point: ",", @@ -117,7 +120,8 @@ var locales = { day: "zondag,maandag,dinsdag,woensdag,donderdag,vrijdag,zaterdag", abmonth: "jan,feb,mrt,apr,mei,jun,jul,aug,sep,okt,nov,dec", month: "januari,februari,maart,april,mei,juni,juli,augustus,september,oktober,november,december", - trans: { yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + // No translation for english... + }, "en_CA": { lang: "en_CA", decimal_point: ".", @@ -134,7 +138,8 @@ var locales = { month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - trans: { yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + // No translation for english... + }, "fr_FR": { lang: "fr_FR", decimal_point: ",", @@ -185,7 +190,8 @@ var locales = { month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - trans: { yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + // No translation for english... + }, "de_AT": { lang: "de_AT", decimal_point: ",", @@ -218,7 +224,8 @@ var locales = { month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - trans: { yes: "yes", Yes: "Yes", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + // No translation for english... + }, "es_ES": { lang: "es_ES", decimal_point: ",", @@ -403,7 +410,7 @@ var locales = { abday: "Dom,Seg,Ter,Qua,Qui,Sex,Sab", day: "Domingo,Segunda-feira,Terça-feira,Quarta-feira,Quinta-feira,Sexta-feira,Sábado", trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "certo", on: "ligado", off: "desligado" }}, - "cs_CZ": { + "cs_CZ": { lang: "cs_CZ", decimal_point: ",", thousands_sep: " ", @@ -419,5 +426,5 @@ var locales = { month: "leden,únor,bÅ™ezen,duben,kvÄ›ten,Äerven,Äervenec,srpen,září,říjen,listopad,prosinec", abday: "ne,po,út,st,Ät,pá,so", day: "nedÄ›le,pondÄ›lí,úterý,stÅ™eda,Ätvrtek,pátek,sobota", - trans: { yes: "tak", Yes: "Tak", no: "nie", No: "Nie", ok: "ok", on: "na", off: "poza" }} + trans: { yes: "tak", Yes: "Tak", no: "nie", No: "Nie", ok: "ok", on: "na", off: "poza" }} }; From 87904b31adc8d947ff4ceae370ea2eb80b54b650 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 9 Apr 2020 09:03:42 +0100 Subject: [PATCH 0313/1189] files 0.02: Fix deletion of apps - now use files list in app.info (fix #262) --- apps.json | 4 ++-- apps/files/files.js | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index fe2dded8e..eddd15cdd 100644 --- a/apps.json +++ b/apps.json @@ -318,9 +318,9 @@ { "id": "files", "name": "App Manager", "icon": "files.png", - "version":"0.01", + "version":"0.02", "description": "Show currently installed apps, free space, and allow their deletion from the watch", - "tags": "tool,system", + "tags": "tool,system,files", "storage": [ {"name":"files.app.js","url":"files.js"}, {"name":"files.img","url":"files-icon.js","evaluate":true} diff --git a/apps/files/files.js b/apps/files/files.js index 31353cf96..4775d35d0 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -32,9 +32,7 @@ function showMainMenu() { function eraseApp(app) { E.showMessage('Erasing\n' + app.name + '...'); - storage.erase(app['']); - storage.erase(app.icon); - storage.erase(app.src); + app.files.split(",").forEach(f=>storage.erase(f)); } function showAppMenu(app) { From 4f7cbbb1b57dbb884ee15cc2a34e479f99223f01 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 9 Apr 2020 09:43:16 +0100 Subject: [PATCH 0314/1189] quick fix for widget - #250 --- apps/widpedom/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index a9e5bf121..32886fc95 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -112,7 +112,7 @@ }); // add your widget - WIDGETS["wpedom"]={area:"tl",width:26,draw:draw,reload:Reload}; + WIDGETS["wpedom"]={area:"tl",width:26,draw:draw,reload:reload}; // Load data at startup let pedomData = require("Storage").readJSON(PEDOMFILE,1); if (pedomData) { From a0fa1040784b9307cc2c04edecfa02b7f6ea8979 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 9 Apr 2020 12:05:25 +0200 Subject: [PATCH 0315/1189] widpedom: Fix daily goal, don't store settings in separate file --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/settings.js | 8 +++--- apps/widpedom/widget.js | 56 +++++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/apps.json b/apps.json index eddd15cdd..035914609 100644 --- a/apps.json +++ b/apps.json @@ -786,7 +786,7 @@ { "id": "widpedom", "name": "Pedometer widget", "icon": "widget.png", - "version":"0.09", + "version":"0.10", "description": "Daily pedometer widget", "tags": "widget", "type":"widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index d6fe28940..43fcc8dc9 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -6,3 +6,4 @@ 0.07: Tweaks for variable size widget system 0.08: Ensure redrawing works with variable size widget system 0.09: Add daily goal +0.10: Fix daily goal, don't store settings in separate file diff --git a/apps/widpedom/settings.js b/apps/widpedom/settings.js index f6d30b830..d2db58593 100644 --- a/apps/widpedom/settings.js +++ b/apps/widpedom/settings.js @@ -1,5 +1,5 @@ (function(back) { - const SETTINGS_FILE = 'widpedom.settings.json' + const PEDOMFILE = "wpedom.json"; // initialize with default settings... let s = { @@ -9,13 +9,15 @@ // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings const storage = require('Storage') - const saved = storage.readJSON(SETTINGS_FILE, 1) || {} + const d = storage.readJSON(PEDOMFILE, 1) || {} + const saved = d.settings || {} for (const key in saved) { s[key] = saved[key] } function save() { - storage.write(SETTINGS_FILE, s) + d.settings = s + storage.write(PEDOMFILE, d) WIDGETS['wpedom'].reload() } diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 32886fc95..e7c3961b4 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -1,6 +1,5 @@ (() => { const PEDOMFILE = "wpedom.json" - const SETTINGS_FILE = "widpedom.settings.json" const DEFAULTS = { 'goal': 10000, 'progress': false, @@ -16,7 +15,8 @@ let settings; function loadSettings() { - settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; + const d = require('Storage').readJSON(PEDOMFILE, 1) || {}; + settings = d.settings || {}; } function setting(key) { @@ -25,31 +25,29 @@ } function drawProgress(stps) { - if (setting('progress')) { - const width = 24, half = width/2; - const goal = setting('goal'), left = Math.max(goal-stps,0); - const c = left ? COLORS.progress : COLORS.done; - g.setColor(c).fillCircle(this.x + half, this.y + half, half); - if (left) { - const f = left/goal; // fraction to blank out - let p = []; - p.push(half,half); - p.push(half,0); - if(f>1/8) p.push(0,0); - if(f>2/8) p.push(0,half); - if(f>3/8) p.push(0,width); - if(f>4/8) p.push(half,width); - if(f>5/8) p.push(width,width); - if(f>6/8) p.push(width,half); - if(f>7/8) p.push(width,0); - p.push(half - Math.sin(f * TAU) * half); - p.push(half - Math.cos(f * TAU) * half); - for (let i = p.length; i; i -= 2) { - p[i - 2] += this.x; - p[i - 1] += this.y; - } - g.setColor(0).fillPoly(p); + const width = 24, half = width/2; + const goal = setting('goal'), left = Math.max(goal-stps,0); + const c = left ? COLORS.progress : COLORS.done; + g.setColor(c).fillCircle(this.x + half, this.y + half, half); + if (left) { + const f = left/goal; // fraction to blank out + let p = []; + p.push(half,half); + p.push(half,0); + if(f>1/8) p.push(0,0); + if(f>2/8) p.push(0,half); + if(f>3/8) p.push(0,width); + if(f>4/8) p.push(half,width); + if(f>5/8) p.push(width,width); + if(f>6/8) p.push(width,half); + if(f>7/8) p.push(width,0); + p.push(half - Math.sin(f * TAU) * half); + p.push(half - Math.cos(f * TAU) * half); + for (let i = p.length; i; i -= 2) { + p[i - 2] += this.x; + p[i - 1] += this.y; } + g.setColor(0).fillPoly(p); } } @@ -62,7 +60,7 @@ let stps = stp_today.toString(); g.reset(); g.clearRect(this.x, this.y, this.x + width, this.y + 23); // erase background - drawProgress(stps); + if (setting('progress')){ drawProgress.call(this, stps); } g.setColor(COLORS.white); if (stps.length > 3){ stps = stps.slice(0,-3) + "," + stps.slice(-3); @@ -104,9 +102,11 @@ }); // When unloading, save state E.on('kill', () => { + if (!settings) { loadSettings() } let d = { lastUpdate : lastUpdate.toISOString(), - stepsToday : stp_today + stepsToday : stp_today, + settings : settings, }; require("Storage").write(PEDOMFILE,d); }); From 82d0d255c24b390173c4150beee03719ccb55f52 Mon Sep 17 00:00:00 2001 From: Fabio Date: Thu, 9 Apr 2020 14:05:06 +0200 Subject: [PATCH 0316/1189] Fixed missing ampm property for some locales --- apps/locale/locales.js | 193 ++++++++++++++++++++++------------------- 1 file changed, 106 insertions(+), 87 deletions(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index 23468ebde..ebf28e53d 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -1,15 +1,15 @@ /* jshint esversion: 6 */ const distanceUnits = { // how many meters per X? - "m" : 1, - "yd" : 0.9144, - "mi" : 1609.34, - "km" : 1000, - "kmi" : 1000 + "m": 1, + "yd": 0.9144, + "mi": 1609.34, + "km": 1000, + "kmi": 1000 }; const speedUnits = { // how many kph per X? - "kmh" : 1, - "kph" : 1, - "mph" : 1.60934 + "kmh": 1, + "kph": 1, + "mph": 1.60934 }; /* @@ -33,23 +33,23 @@ timePattern / datePattern: */ var locales = { - "en_GB": { // this is default - lang: "en_GB", - decimal_point: ".", - thousands_sep: ",", - currency_symbol: "£", currency_first:true, - int_curr_symbol: "GBP", - speed: 'mph', - distance: { "0": "yd", "1": "mi" }, - temperature: '°C', - ampm: {0:"am",1:"pm"}, - timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short) - abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", - month: "January,February,March,April,May,June,July,August,September,October,November,December", - abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", - day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", - // No translation for english... + "en_GB": { // this is default + lang: "en_GB", + decimal_point: ".", + thousands_sep: ",", + currency_symbol: "£", currency_first: true, + int_curr_symbol: "GBP", + speed: 'mph', + distance: { "0": "yd", "1": "mi" }, + temperature: '°C', + ampm: { 0: "am", 1: "pm" }, + timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, + datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short) + abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", + month: "January,February,March,April,May,June,July,August,September,October,November,December", + abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", + day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", + // No translation for english... }, "de_DE": { lang: "de_DE", @@ -60,24 +60,25 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"",1:""}, + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%Y" }, // Sonntag, 1. März 2020 // 01.01.20 abmonth: "Jan,Feb,Mär,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez", month: "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember", abday: "So,Mo,Di,Mi,Do,Fr,Sa", day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag", - trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" }}, + trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" } + }, "en_US": { lang: "en_US", decimal_point: ".", thousands_sep: ",", - currency_symbol: "$", currency_first:true, + currency_symbol: "$", currency_first: true, int_curr_symbol: "USD", speed: "mph", distance: { 0: "yd", 1: "mi" }, temperature: "°F", - ampm: {0:"am",1:"pm"}, + ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "", 1: "%m/%d/%y" }, abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", @@ -95,7 +96,7 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°F", - ampm: {0:"",1:""}, + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%y/%M/%d", 1: "%y/%m;/%d" }, abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", @@ -113,7 +114,7 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"",1:""}, + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %B %d %Y", 1: "%d.%m.%y" }, // zondag 1 maart 2020 // 01.01.20 abday: "zo,ma,di,wo,do,vr,za", @@ -131,7 +132,7 @@ var locales = { speed: "mph", distance: { 0: "mi", 1: "kmi" }, temperature: "°F", - ampm: {0:"am",1:"pm"}, + ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %B %d, %Y", "1": "%Y-%m-%d" }, // Sunday, March 1, 2020 // 2012-12-20 abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", @@ -149,14 +150,15 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"",1:""}, + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%Y" }, // dimanche 1 mars 2020 // 01/03/2020 abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", - trans : { yes : "oui", Yes: "Oui", no: "no", No: "No", ok : "ok", on: "on", off: "off" }}, + trans: { yes: "oui", Yes: "Oui", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "sv_SE": { lang: "sv_SE", decimal_point: ",", @@ -166,14 +168,15 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"fm",1:"em"}, + ampm: { 0: "fm", 1: "em" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // söndag 1 mars 2020 // 2020-03-01 - abmonth: "jan,feb,mars,apr,maj,juni,juli,aug,sep,okt,nov,dec", - month: "januari,februari,mars,april,maj,juni,juli,augusti,september,oktober,november,december", - abday: "sön,mÃ¥n,tis,ons,tors,fre,lör", - day: "söndag,mÃ¥ndag,tisdag,onsdag,torsdag,fredag,lördag", - trans : { yes : "ja", Yes: "Ja", no: "nej", No: "Nej", ok : "ok", on: "on", off: "off" }}, + abmonth: "jan,feb,mars,apr,maj,juni,juli,aug,sep,okt,nov,dec", + month: "januari,februari,mars,april,maj,juni,juli,augusti,september,oktober,november,december", + abday: "sön,mÃ¥n,tis,ons,tors,fre,lör", + day: "söndag,mÃ¥ndag,tisdag,onsdag,torsdag,fredag,lördag", + trans: { yes: "ja", Yes: "Ja", no: "nej", No: "Nej", ok: "ok", on: "on", off: "off" } + }, "en_AU": { lang: "en_AU", decimal_point: ".", @@ -183,7 +186,7 @@ var locales = { speed: "mph", distance: { 0: "mi", 1: "kmi" }, temperature: "°F", - ampm: {0:"am",1:"pm"}, + ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %B %d, %Y", "1": "%m/%d/%y" }, // Sunday, 1 March 2020 // 1/3/20 abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", @@ -201,13 +204,14 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, + timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20 abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez", month: "Jänner,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember", abday: "So,Mo,Di,Mi,Do,Fr,Sa", day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag", - trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" }}, + trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" } + }, "en_IL": { lang: "en_IL", decimal_point: ",", @@ -217,7 +221,7 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°F", - ampm: {0:"am",1:"pm"}, + ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020 abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", @@ -235,14 +239,15 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"",1:""}, + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %d de %B de %Y", "1": "%d/%m/%y" }, // domingo, 1 de marzo de 2020 // 01/03/20 abmonth: "ene,feb,mar,abr,may,jun,jul,ago,sept,oct,nov,dic", month: "enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre", abday: "dom,lun,mar,mié,jue,vie,sáb", day: "domingo,lunes,martes,miércoles,jueves,viernes,sábado", - trans: { yes : "sí", Yes: "Sí",no: "no", No: "No", ok : "ok", on: "on", off: "off" }}, + trans: { yes: "sí", Yes: "Sí", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "fr_BE": { lang: "fr_BE", decimal_point: ",", @@ -252,14 +257,15 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0: "",1: ""}, + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", - trans : { yes : "oui", Yes: "Oui", no: "no", No: "No", ok : "ok", on: "on", off: "off" }}, + trans: { yes: "oui", Yes: "Oui", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "fi_FI": { lang: "fi_FI", decimal_point: ",", @@ -269,48 +275,51 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0: "ap",1: "ip"}, + ampm: { 0: "ap", 1: "ip" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, // 17.00.00 // 17.00 datePattern: { 0: "%A %d. %B %Y", "1": "%-d/%-m/%Y" }, // sunnuntai 1. maaliskuuta 2020 // 1.3.2020 abmonth: "tammik,helmik,maalisk,huhtik,toukok,kesäk,heinäk,elok,syysk,lokak,marrask,jouluk", month: "tammikuuta,helmikuuta,maaliskuuta,huhtikuuta,toukokuuta,kesäkuuta,heinäkuuta,elokuuta,syyskuuta,lokakuuta,marraskuuta,joulukuuta", abday: "su,ma,ti,ke,to,pe,la", day: "sunnuntaina,maanantaina,tiistaina,keskiviikkona,torstaina,perjantaina,lauantaina", - trans : { yes : "oui", Yes: "Oui", no: "no", No: "No", ok : "ok", on: "on", off: "off" }}, + trans: { yes: "oui", Yes: "Oui", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "de_CH": { lang: "de_CH", - decimal_point: ",", + decimal_point: ",", thousands_sep: ".", currency_symbol: "CHF", int_curr_symbol: "CHF", speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"vorm",1:" nachm"}, + ampm: { 0: "vorm", 1: " nachm" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%Y" }, // Sonntag, 1. März 2020 // 1.3.2020 abmonth: "Jan,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez", month: "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember", abday: "So,Mo,Di,Mi,Do,Fr,Sa", day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag", - trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" }}, + trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" } + }, "fr_CH": { lang: "fr_CH", - decimal_point: ",", + decimal_point: ",", thousands_sep: ".", currency_symbol: "CHF", int_curr_symbol: "CHF", speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"AM",1:"PM"}, + ampm: { 0: "AM", 1: "PM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", - trans : { yes : "oui", Yes: "Oui", no: "no", No: "No", ok : "ok", on: "on", off: "off" }}, + trans: { yes: "oui", Yes: "Oui", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "it_CH": { lang: "it_CH", decimal_point: ",", @@ -320,13 +329,15 @@ var locales = { speed: 'kmh', distance: { "0": "m", "1": "km" }, temperature: '°C', + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH.%MM.%SS ", 1: "%HH.%MM" }, // 17.00.00 // 17.00 datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%Y" }, // sunnuntai 1. maaliskuuta 2020 // 1.3.2020 abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic", month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre", - abday : "dom,lun,mar,mer,gio,ven,sab", + abday: "dom,lun,mar,mer,gio,ven,sab", day: "domenica,lunedì,martedì,mercoledì,giovedì,venerdì, sabato", - trans : { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + trans: { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "it_IT": { lang: "it_IT", decimal_point: ",", @@ -336,29 +347,33 @@ var locales = { speed: 'kmh', distance: { "0": "m", "1": "km" }, temperature: '°C', + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH.%MM.%SS ", 1: "%HH.%MM" }, // 17.00.00 // 17.00 datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%Y" }, // sunnuntai 1. maaliskuuta 2020 // 1.3.2020 abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic", month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre", - abday : "dom,lun,mar,mer,gio,ven,sab", + abday: "dom,lun,mar,mer,gio,ven,sab", day: "domenica,lunedì,martedì,mercoledì,giovedì,venerdì, sabato", - trans : { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, - "wae_CH" : { + trans: { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, + "wae_CH": { lang: "wae_CH", - decimal_point: ",", + decimal_point: ",", thousands_sep: ".", currency_symbol: "CHF", int_curr_symbol: "CHF", speed: 'kmh', distance: { "0": "m", "1": "km" }, temperature: '°C', + ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH.%MM.%SS ", 1: "%HH.%MM" }, // 17.00.00 // 17.00 datePattern: { 0: "%A, %d. %B %Y", "1": "%Y-%m-%d" }, // Sunntag, 1. Märze 2020 // 2020-03-01 abmonth: "Jen,Hor,Mär,Abr,Mei,Brá,Hei,Öig,Her,Wím,Win,Chr", month: "Jenner,Hornig,Märze,Abrille,Meije,BráÄet,Heiwet,ÖigÅ¡te,HerbÅ¡tmánet,Wímánet,Wintermánet,ChriÅ¡tmánet", abday: "Sun,Män,ZiÅ¡,Mit,Fró,Fri,Sam", day: "Sunntag,Mäntag,ZiÅ¡tag,MittwuÄ,Fróntag,Fritag,SamÅ¡tag", - trans : { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" }}, + trans: { yes: "sì", Yes: "Sì", no: "no", No: "No", ok: "ok", on: "on", off: "off" } + }, "tr_TR": { // this is default lang: "tr_TR", decimal_point: ",", @@ -368,48 +383,51 @@ var locales = { speed: 'kmh', distance: { "0": "m", "1": "km" }, temperature: '°C', - ampm: {0:"öö",1:"ös"}, + ampm: { 0: "öö", 1: "ös" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%d %w %Y %A", 1: "%d/%m/%Y" }, // 1 Mart 2020 Pazar // "01/03/2020" abmonth: "Oca,Sub,Mar,Nis,May,Haz,Tem,Agu,Eyl,Eki,Kas,Ara", month: "Ocak,Subat,Mart,Nisan,Mayis,Haziran,Temmuz,Agustos,Eylul,Ekim,Kasim,Aralik", abday: "Paz,Pzt,Sal,Car,Per,Cum,Cmt", day: "Pazar,Pazartesi,Sali,Carsamba,Persembe,Cuma,Cumartesi", - trans: { yes: "evet", Yes: "Evet", no: "hayir", No: "Hayir", ok: "tamam", on: "acik", off: "kapali" }}, - "hu_HU": { - lang: "hu_HU", - decimal_point: ",", - thousands_sep: " ", - currency_symbol: "Ft", - int_curr_symbol: "HUF", - speed: 'kph', - distance: { "0": "m", "1": "km" }, - temperature: '°C', - ampm: {0:"de",1:"du"}, - timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%Y %b %d, %A", 1: "%Y.%m.%d" }, // 2020 Feb 28, Péntek" // "2020.03.01."(short) - abmonth: "Jan,Feb,Már,Ãpr,Máj,Jún,Júl,Aug,Szep,Okt,Nov,Dec", - month: "Január,Február,Március,Ãprilis,Május,Június,Július,Augusztus,Szeptember,Október,November,December", - abday: "Vas,Hét,Ke,Szer,Csüt,Pén,Szom", - day: "Vasárnap,HétfÅ‘,Kedd,Szerda,Csütörtök,Péntek,Szombat", - trans: { yes: "igen", Yes: "Igen", no: "nem", No: "Nem", ok: "ok", on: "be", off: "ki" }}, + trans: { yes: "evet", Yes: "Evet", no: "hayir", No: "Hayir", ok: "tamam", on: "acik", off: "kapali" } + }, + "hu_HU": { + lang: "hu_HU", + decimal_point: ",", + thousands_sep: " ", + currency_symbol: "Ft", + int_curr_symbol: "HUF", + speed: 'kph', + distance: { "0": "m", "1": "km" }, + temperature: '°C', + ampm: { 0: "de", 1: "du" }, + timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, + datePattern: { 0: "%Y %b %d, %A", 1: "%Y.%m.%d" }, // 2020 Feb 28, Péntek" // "2020.03.01."(short) + abmonth: "Jan,Feb,Már,Ãpr,Máj,Jún,Júl,Aug,Szep,Okt,Nov,Dec", + month: "Január,Február,Március,Ãprilis,Május,Június,Július,Augusztus,Szeptember,Október,November,December", + abday: "Vas,Hét,Ke,Szer,Csüt,Pén,Szom", + day: "Vasárnap,HétfÅ‘,Kedd,Szerda,Csütörtök,Péntek,Szombat", + trans: { yes: "igen", Yes: "Igen", no: "nem", No: "Nem", ok: "ok", on: "be", off: "ki" } + }, "pt_BR": { lang: "pt_BR", decimal_point: ",", thousands_sep: ".", - currency_symbol: "R$", currency_first:true, + currency_symbol: "R$", currency_first: true, int_curr_symbol: "BRL", speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: {0:"am",1:"pm"}, + ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "", 1: "%d/%m/%y" }, abmonth: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez", month: "Janeiro,Fevereiro,Março,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro", abday: "Dom,Seg,Ter,Qua,Qui,Sex,Sab", day: "Domingo,Segunda-feira,Terça-feira,Quarta-feira,Quinta-feira,Sexta-feira,Sábado", - trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "certo", on: "ligado", off: "desligado" }}, + trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "certo", on: "ligado", off: "desligado" } + }, "cs_CZ": { lang: "cs_CZ", decimal_point: ",", @@ -419,12 +437,13 @@ var locales = { speed: 'kmh', distance: { "0": "m", "1": "km" }, temperature: '°C', - ampm: {0:"dop",1:"odp"}, + ampm: { 0: "dop", 1: "odp" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%d. %b %Y", 1: "%d.%m.%Y" }, // "30. led 2020" // "30.01.2020"(short) abmonth: "led,úno,bÅ™e,dub,kvÄ›,Ävn,Ävc,srp,zář,říj,lis,pro", month: "leden,únor,bÅ™ezen,duben,kvÄ›ten,Äerven,Äervenec,srpen,září,říjen,listopad,prosinec", abday: "ne,po,út,st,Ät,pá,so", day: "nedÄ›le,pondÄ›lí,úterý,stÅ™eda,Ätvrtek,pátek,sobota", - trans: { yes: "tak", Yes: "Tak", no: "nie", No: "Nie", ok: "ok", on: "na", off: "poza" }} + trans: { yes: "tak", Yes: "Tak", no: "nie", No: "Nie", ok: "ok", on: "na", off: "poza" } + } }; From 9851328c69f3b8701fe25c8a2c4b3ca2a84aca86 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 9 Apr 2020 16:10:10 +0200 Subject: [PATCH 0317/1189] Rotate log files once a week --- apps.json | 2 +- apps/batchart/ChangeLog | 3 ++- apps/batchart/app-icon.js | 2 +- apps/batchart/widget.js | 55 +++++++++++++++++++++++---------------- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/apps.json b/apps.json index beddd2878..0347dd0c1 100644 --- a/apps.json +++ b/apps.json @@ -1136,7 +1136,7 @@ "name": "Battery Chart", "shortName":"BatChart", "icon": "app.png", - "version":"0.02", + "version":"0.03", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index d885f8fb0..1b77ff82f 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -1,2 +1,3 @@ 0.01: New app and widget -0.02: Widget stores data to file (1 dataset/min) +0.02: Widget stores data to file (1 dataset/10min) +0.03: Rotate log files once a week. diff --git a/apps/batchart/app-icon.js b/apps/batchart/app-icon.js index 0841ea920..b41629e01 100644 --- a/apps/batchart/app-icon.js +++ b/apps/batchart/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AS64AIF/4pZABYuuGDIv/F/4v/F9+Gw0rAQIASF7YxTF7cxwAvtrdVF9qQTF/4vMYCQvcYCQvcSCQvdqpgQF7oEBYJ4veAoNbF9uGmMrrgvsw2AGILFKF8IACrYxJF8gxDSowvmBwWAF9oPGF9NbmIvtCAovqMAgvqCIgvrrdVF9oSDF9iPuF7crACxf/F++wFqmG2AvXGCouZAH4A/AGY")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AS64AIF/4pZABYuuGDIv/F/4v/F9+Gw0rAQIASF7YxTF7cxwAvtrdVF9qQTF/4vMYCQvcYCQvcSCQvdqpgQF7oEBYJ4veAoNbF9uGmMrrgvsw2AGILFKF8IACrYxJF8gxDSowvmBwWAF9oPGF9NbmIvtCAovqMAgvqCIgvrrdVF9oSDF9iPuF7crACxf/F++wFqmG2AvXGCouZAH4A/AGY")) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index b002da5d9..2e2f43cdf 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -6,7 +6,8 @@ bluetooth: 4, gps: 8, hrm: 16 - } + }; + var settings = {}; var batChartFile; // file for battery percentage recording const recordingInterval10Min = 60 * 10 * 1000; @@ -20,26 +21,6 @@ g.drawString("BC", this.x, this.y); } - // Called by the heart app to reload settings and decide what's - function reload() { - WIDGETS["batchart"].width = 24; - - // Check if the data file exists, if not try to create it. - var batChartFileCheck = require("Storage").open("batchart.dat", "r"); - if (!batChartFileCheck) - if (!require("Storage").write("batchart.dat", "")) - //Only continue if the file was created - return; - - recordingInterval = setInterval(() => { - var batChartFileAppend = require("Storage").open("batchart.dat", "a"); - if (batChartFileAppend) { - console.log([getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")); - batChartFileAppend.write([getTime().toFixed(0),E.getBattery].join(",")+"\n"); - } - }, recordingInterval1Min) - } - function getEnabledConsumersValue() { var enabledConsumers = switchableConsumers.none; @@ -54,10 +35,40 @@ // enabledConsumers = enabledConsumers | switchableConsumers.gps; // if (Bangle.isHrmOn()) // enabledConsumers = enabledConsumers | switchableConsumers.hrm; - + return enabledConsumers; } + function logBatteryData() { + const previousWriteLogName = "bcprvday"; + const previousWriteDay = require("Storage").read(previousWriteLogName); + const currentWriteDay = new Date().getDay(); + + const logFileName = "bclog" + currentWriteDay; + + // Change log target on day change + if (previousWriteDay != currentWriteDay) { + //Remove a log file containing data from a week ago + require("Storage").erase(logFileName); + require("Storage").write(previousWriteLogName, currentWriteDay); + } + + var bcLogFileA = require("Storage").open(logFileName, "a"); + if (bcLogFileA) { + console.log([getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")); + bcLogFileA.write([[getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")].join(",")+"\n"); + } + } + + // Called by the heart app to reload settings and decide what's + function reload() { + WIDGETS["batchart"].width = 24; + + recordingInterval = setInterval(logBatteryData, recordingInterval10Min); + + logBatteryData(); + } + // add the widget WIDGETS["batchart"]={area:"tl",width:24,draw:draw,reload:function() { reload(); From 264c7c64cbb22a56e4d6e65e13ff91763120503a Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:12:36 +0200 Subject: [PATCH 0318/1189] Create app.js --- apps/stopwatch/app.js | 159 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 apps/stopwatch/app.js diff --git a/apps/stopwatch/app.js b/apps/stopwatch/app.js new file mode 100644 index 000000000..cf7186c98 --- /dev/null +++ b/apps/stopwatch/app.js @@ -0,0 +1,159 @@ +const EMPTY_LAP = '--:--:---'; +const EMPTY_H = '00:00:000'; +const MAX_LAPS = 6; +const XY_CENTER = g.getWidth() / 2; +const Y_CHRONO = 40; +const Y_HEADER = 80; +const Y_LAPS = 125; +const Y_BTN3 = 225; +const FONT = '6x8'; +const CHRONO = '/* C H R O N O */'; + +var laps = [EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP]; +var started = false; +var reset = false; +var whenStarted; +var whenStartedTotal; +var currentLapIndex = 1; +var currentLap = ''; +var chronoInterval; + +// Set laps. +setWatch(() => { + + reset = false; + + if (started) { + changeLap(); + } else { + if (!reset) { + chronoInterval = setInterval(chronometer, 10); + } + } +}, BTN1, { repeat: true, edge: 'rising' }); + +// Reset chronometre. +setWatch(() => { resetChrono(); }, BTN3, { repeat: true, edge: 'rising' }); + +// Show launcher when middle button pressed. +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: 'falling' }); + +function resetChrono() { + laps = [EMPTY_H, EMPTY_H, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP]; + started = false; + reset = true; + currentLapIndex = 1; + currentLap = ''; + + if (chronoInterval !== undefined) { + clearInterval(chronoInterval); + } + + printChrono(); +} + +function chronometer() { + + if (!started) { + var rightNow = Date.now(); + whenStarted = rightNow; + whenStartedTotal = rightNow; + started = true; + reset = false; + } + + currentLap = calculateLap(whenStarted); + total = calculateLap(whenStartedTotal); + + laps[0] = total; + laps[1] = currentLap; + printChrono(); +} + +function changeLap() { + + currentLapIndex++; + + if ((currentLapIndex) > MAX_LAPS) { + currentLapIndex = 2; + } + + laps[currentLapIndex] = currentLap; + whenStarted = Date.now(); +} + +function calculateLap(whenStarted) { + + var now = Date.now(); + var diffTime = now - whenStarted; + var dateDiffTime = new Date(diffTime); + + var millis = padStart(dateDiffTime.getMilliseconds().toString(), 3); + var seconds = padStart(dateDiffTime.getSeconds().toString(), 2); + var minutes = padStart(dateDiffTime.getMinutes().toString(), 2); + + return `${minutes}:${seconds}:${millis}`; +} + +function printChrono() { + + g.reset(); + g.setFontAlign(0, 0); + + var print = ''; + + g.setFont(FONT, 2); + print = CHRONO; + g.drawString(print, XY_CENTER, Y_CHRONO, true); + + g.setColor(0, 220, 0); + g.setFont(FONT, 3); + print = ` T ${laps[0]}\n`; + print += ` C ${laps[1]}\n`; + g.drawString(print, XY_CENTER, Y_HEADER, true); + + g.setColor(255, 255, 255); + g.setFont(FONT, 2); + + for (var i = 2; i < MAX_LAPS + 1; i++) { + + g.setColor(255, 255, 255); + let suffix = ' '; + if (currentLapIndex === i) { + let suffix = '*'; + g.setColor(255, 200, 0); + } + + const lapLine = `L${i - 1} ${laps[i]} ${suffix}\n`; + g.drawString(lapLine, XY_CENTER, Y_LAPS + (15 * (i - 1)), true); + } + + g.setColor(255, 255, 255); + g.setFont(FONT, 1); + print = 'Press 3 to reset'; + g.drawString(print, XY_CENTER, Y_BTN3, true); + + g.flip(); +} + +function padStart(value, size) { + + var result = ''; + var pads = size - value.length; + + if (pads > 0) { + for (var i = 0; i < pads; i++) { + result += '0'; + } + } + + result += value; + return result; +} + +// Clean app screen. +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +resetChrono(); From c5b184c94cb1dace89e5f2c3ec16456567ec07ba Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:18:35 +0200 Subject: [PATCH 0319/1189] Create app-icon.js --- apps/stopwatch/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/stopwatch/app-icon.js diff --git a/apps/stopwatch/app-icon.js b/apps/stopwatch/app-icon.js new file mode 100644 index 000000000..6a7f0798e --- /dev/null +++ b/apps/stopwatch/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("oFAxH+AH4A/AH4A/AH4A/ADc1AAw++IG43HH/4/5X/pAIH2y77H/7//HhRCNJsozIAgxBIR0gkKA5ISEAgZAgHhS7LSZp8cHhZCJHxA/bHpbPQX0M1rNZAoQEBrIkOCIwGCEAgAYHw4ZTDTA+jIBI+cDoQ+MBYNlsodZPyYgNH4YACIBi9fCRuJAAggYPyISOH4pAKH7CeFqY/VIAohDqZAXqY6CAYYTNH45AFEaY/mIAg/aCwIbRCYV9wetAAw/gHyZBDH5RAaDKINFAoOnAAw/uBg6ABH8wADH6YAHEqg/Qu4dHH7N3H6d3CoQDHCBAHLEpg/iBIwtNH8aAJAAglUH6aAQIIg+SH6jASEbIbcIDQ/dQBBAXDsZJHP168LICzdlIDDgIH7JALFJ4dKYLwiEIIgsKK44+afp4/LH0i8KC6A+jXho8LCo4/f/2bAAQHHABIRGHsAnMHhY+pG4wKHCSBBoF4YEGHtr+RHt5COHmQA/AH4A/AH4A/AE4A==")) From ab79963e70603a77a10908204ca35494203ab162 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:25:11 +0200 Subject: [PATCH 0320/1189] Update apps.json --- apps.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 035914609..ef049b346 100644 --- a/apps.json +++ b/apps.json @@ -1132,5 +1132,17 @@ "storage": [ {"name":"custom"} ] - } + }, + { "id": "stopwatch", + "name": "Stopwatch", + "shortName":"Stopwatch", + "icon": "app.png", + "version":"0.01", + "description": "Stopwatch with 5 laps supported (cyclically replaced)", + "tags": "stopwatch, chrono, timer, chronometer", + "storage": [ + {"name":"stopwatch.app.js","url":"app.js"}, + {"name":"stopwatch.img","url":"app-icon.js","evaluate":true} + ] +} ] From b847cb330132f682b9df2f6e6eec423de734130b Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:28:13 +0200 Subject: [PATCH 0321/1189] Add files via upload --- apps/stopwatch/app.png | Bin 0 -> 2483 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/stopwatch/app.png diff --git a/apps/stopwatch/app.png b/apps/stopwatch/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b0feeebc9cbc2971fe26709493593120336f0410 GIT binary patch literal 2483 zcmV;k2~75hP)+7_A%r0eB108KOst|p6F>+c z#YkkZf`Zi65#>=tZ5=Su;7|+@WDq2TKtZvXAYBY~s1k^b0xIf4MGZkPynA;42vNrO z0zChcZ>_sl);Z_f-~MvXu>Z=+qDpA8g0F(8!(n~plS2l^xk7S zEEfUWqplb2fB~PWD$D>LKd$Rrh3shS{j6v=Obgo$)54!qBkH?Qr%Y{V9ojn3NR_*f zG(Re^+l2UVZLaKzre0JGbRMED1cod00umw&FIHG)eO~zQEZKQMB`Q>SD>8Yl$&*|(||d~C*3H2GM28MCEf`! zF;XU{Z6G~e1KkHP!&sj1d{!DEsc^R3DgLQg8zNdsV&!r0~Wc)!O$#sd!{ ztOi~~c@$y6_n$MUs7OLlGtg^*=AsNn7_#^k$?Y{jZ$p^^>_rF$EYlY(5I!RCvMqN7gJMs{8`wt+y@p&Fe-qmjRy)Fitjpz%%Kl(boy{A_0`3qPJ~xk- z2KJ=@B?U|CdHLaYpeh>}+(&bOnow1C}?vgg&QA{s^xywjs&&`XAH$mahzd z>`K{MX=3{Z@=>k_I=M=jFKhx9zr08WM9MAVE|k$nn;A=n=kx5WC9>1_Og5Ii0iVI) zk_RvrVtj}T9rJXH_gVMkD(zNbK&&2Qu(5pQStifSmmRKUifg$sBULXtYXh-9!#s=Q zDcQq*uRT0VH)9!}Q-wM2S%|R^=b!Mz*9ejS{0dD3n7v#|jS@7Ll;J(~x@tmpz~Tnr z_OmwN`t&uHH7_oak3CC<@%iMtSY|}x!I3v`as$Nq#K*z3%CQYf$uX8aM#y+RUv?Q~ zz30;-l1A7yFeX(m(h$3WzZ^15jScaoLe7-sa%VVRFj>vl)yNQ-6jPmgO*_MdNfrC! z@ld!X^#)l9FuI3kqhz=>s2eI{w7_Eu7fe|$U!F=U>>KdPX=5xHrR2OrBpFNffX}jU zob+^cO9L$SEHAm1{q`U`x4Z$H^074!pRgW?JIs$uJm9m;SZZh~Ej^!2#v;bjA)H=V z1CCE)W5M;=W+2g62>9#>$GP}hGL6#1^BFn$b!qn0GHGIzQTuk{e6{JssZ`6-?Z-3aT0n{==gpLSvVq*D?4e=R(3iYWtp?~5)fm%`@ zNzswx3S}z5#AF>MmPCQf2a9CJsr1hGsBaYn#*52))@KXCcV}+EXBPq%5?x`NT0lv_ z@_{3O(Cv5whl|LG?M51q{dhOM3jj-^3QH5}GAo>(xStYZIbeKxKCoI!jAfhg>3=*Wh}e7IqL=G4%=0NRmjAhyTNCQiyMKgA)m3^L zOPLArp+GBRAyCeSaGZ#>P*xY+0emrLja-q{Mdt!tzX{MdzMRp(Q=%k~UMs62#fgMq zvYPmEb^%3W*2v(jF1i+|J!XwG566pm5_>)ijivKHx@aTMl4~pt>Kr0dYLRU$yIkd; z(>iPIvo%oX2ZkC;edCim<+s|{SS~Y4UL;;*1HyFAf)`@c$aS*Zv#j!bg6EYIFfh=w zG_*eXXJg`p4q7YV6Z9-^j#@7(VuewjMPm;~E?KHnPUm#cJcJ$yNmi-lz?&1mazd# zLt}Ztvy}KAr!2YWchFkR+fm?IMtMFHZ+=gv&%1;PUWJ*5hP*3bOO{Gh`I|V1I<4BW z2uKyk?6*N?E@-R6fNYen6@qnsMNUeQgkEiu4-!K#<2-Ftg z_I@8o&ipnyM1&la{C>ss6^;}!(J}zAq=QxumGc_VRbXPTVuFiW(H57M)(u!*pBQ#WK;y_Oo(gf-QZ#v4@w2c(!w_yS>PGNPZ2G{prD+jBZ(`jEVF6p4v zZ!>Poo}gN6VA002ovPDHLkV1kaKmL&iH literal 0 HcmV?d00001 From ce9cc7637f387d6057110f0359f4e195fdf387b6 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:32:58 +0200 Subject: [PATCH 0322/1189] Update app-icon.js --- apps/stopwatch/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/stopwatch/app-icon.js b/apps/stopwatch/app-icon.js index 6a7f0798e..c31177034 100644 --- a/apps/stopwatch/app-icon.js +++ b/apps/stopwatch/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFAxH+AH4A/AH4A/AH4A/ADc1AAw++IG43HH/4/5X/pAIH2y77H/7//HhRCNJsozIAgxBIR0gkKA5ISEAgZAgHhS7LSZp8cHhZCJHxA/bHpbPQX0M1rNZAoQEBrIkOCIwGCEAgAYHw4ZTDTA+jIBI+cDoQ+MBYNlsodZPyYgNH4YACIBi9fCRuJAAggYPyISOH4pAKH7CeFqY/VIAohDqZAXqY6CAYYTNH45AFEaY/mIAg/aCwIbRCYV9wetAAw/gHyZBDH5RAaDKINFAoOnAAw/uBg6ABH8wADH6YAHEqg/Qu4dHH7N3H6d3CoQDHCBAHLEpg/iBIwtNH8aAJAAglUH6aAQIIg+SH6jASEbIbcIDQ/dQBBAXDsZJHP168LICzdlIDDgIH7JALFJ4dKYLwiEIIgsKK44+afp4/LH0i8KC6A+jXho8LCo4/f/2bAAQHHABIRGHsAnMHhY+pG4wKHCSBBoF4YEGHtr+RHt5COHmQA/AH4A/AH4A/AE4A==")) +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AAc1AAwvpApIv/SDTCteV6MuSRY8bEowEGAxYuXKRYODBQYwWJ5KOINxTkVWxZaFMQoARrNZAg4SPCZgcJDSQQDFy4vEBhFlsoVRFzAvEGIowXPBoKBxIADDCJeMBxYvEGApgTqdTAQYOJF4wwDDRwgGC4gvKwetAAgvFDwYvRNhQACvunF4enDZ4vUAgmD04ADF64ACZZQFDvoAEDZwvNCwt3u4FFSwgvWEQQCFBgwLIDZAvbAAgvgAYIkIFpQLEF6IsFC6AaJCiBjGF6IWUMA55XMCgwSIiowMDpYuYPAwaDAoQhHBIYuWC4ocNCSQdMRwofGBIqeNABubAAIFFAAwSIGLwHDBxgwcKwoLJGMSQKAH4A/AH4A+")) From a37e096e431abd47b7fe7ce20771f209b6389621 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:34:42 +0200 Subject: [PATCH 0323/1189] Update apps.json --- apps.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index ef049b346..7ab80c723 100644 --- a/apps.json +++ b/apps.json @@ -1133,9 +1133,9 @@ {"name":"custom"} ] }, - { "id": "stopwatch", - "name": "Stopwatch", - "shortName":"Stopwatch", + { "id": "devstopwatch", + "name": "Dev Stopwatch", + "shortName":"Dev Stopwatch", "icon": "app.png", "version":"0.01", "description": "Stopwatch with 5 laps supported (cyclically replaced)", From b6567d99b6f6887a15afe93ada378d836f1f96d2 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:39:40 +0200 Subject: [PATCH 0324/1189] Update and rename apps/stopwatch/app-icon.js to apps/devstopwatch/app-icon.js --- apps/{stopwatch => devstopwatch}/app-icon.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/{stopwatch => devstopwatch}/app-icon.js (100%) diff --git a/apps/stopwatch/app-icon.js b/apps/devstopwatch/app-icon.js similarity index 100% rename from apps/stopwatch/app-icon.js rename to apps/devstopwatch/app-icon.js From 5c04e6e9816d26605a7c2ae59a08041f409f5667 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:42:41 +0200 Subject: [PATCH 0325/1189] Rename apps/stopwatch/app.js to apps/devstopwatch/app.js --- apps/{stopwatch => devstopwatch}/app.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/{stopwatch => devstopwatch}/app.js (100%) diff --git a/apps/stopwatch/app.js b/apps/devstopwatch/app.js similarity index 100% rename from apps/stopwatch/app.js rename to apps/devstopwatch/app.js From 96ce0cd480da13d7817eae4354c0302f4a382879 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:43:07 +0200 Subject: [PATCH 0326/1189] Delete app.png --- apps/stopwatch/app.png | Bin 2483 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/stopwatch/app.png diff --git a/apps/stopwatch/app.png b/apps/stopwatch/app.png deleted file mode 100644 index b0feeebc9cbc2971fe26709493593120336f0410..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2483 zcmV;k2~75hP)+7_A%r0eB108KOst|p6F>+c z#YkkZf`Zi65#>=tZ5=Su;7|+@WDq2TKtZvXAYBY~s1k^b0xIf4MGZkPynA;42vNrO z0zChcZ>_sl);Z_f-~MvXu>Z=+qDpA8g0F(8!(n~plS2l^xk7S zEEfUWqplb2fB~PWD$D>LKd$Rrh3shS{j6v=Obgo$)54!qBkH?Qr%Y{V9ojn3NR_*f zG(Re^+l2UVZLaKzre0JGbRMED1cod00umw&FIHG)eO~zQEZKQMB`Q>SD>8Yl$&*|(||d~C*3H2GM28MCEf`! zF;XU{Z6G~e1KkHP!&sj1d{!DEsc^R3DgLQg8zNdsV&!r0~Wc)!O$#sd!{ ztOi~~c@$y6_n$MUs7OLlGtg^*=AsNn7_#^k$?Y{jZ$p^^>_rF$EYlY(5I!RCvMqN7gJMs{8`wt+y@p&Fe-qmjRy)Fitjpz%%Kl(boy{A_0`3qPJ~xk- z2KJ=@B?U|CdHLaYpeh>}+(&bOnow1C}?vgg&QA{s^xywjs&&`XAH$mahzd z>`K{MX=3{Z@=>k_I=M=jFKhx9zr08WM9MAVE|k$nn;A=n=kx5WC9>1_Og5Ii0iVI) zk_RvrVtj}T9rJXH_gVMkD(zNbK&&2Qu(5pQStifSmmRKUifg$sBULXtYXh-9!#s=Q zDcQq*uRT0VH)9!}Q-wM2S%|R^=b!Mz*9ejS{0dD3n7v#|jS@7Ll;J(~x@tmpz~Tnr z_OmwN`t&uHH7_oak3CC<@%iMtSY|}x!I3v`as$Nq#K*z3%CQYf$uX8aM#y+RUv?Q~ zz30;-l1A7yFeX(m(h$3WzZ^15jScaoLe7-sa%VVRFj>vl)yNQ-6jPmgO*_MdNfrC! z@ld!X^#)l9FuI3kqhz=>s2eI{w7_Eu7fe|$U!F=U>>KdPX=5xHrR2OrBpFNffX}jU zob+^cO9L$SEHAm1{q`U`x4Z$H^074!pRgW?JIs$uJm9m;SZZh~Ej^!2#v;bjA)H=V z1CCE)W5M;=W+2g62>9#>$GP}hGL6#1^BFn$b!qn0GHGIzQTuk{e6{JssZ`6-?Z-3aT0n{==gpLSvVq*D?4e=R(3iYWtp?~5)fm%`@ zNzswx3S}z5#AF>MmPCQf2a9CJsr1hGsBaYn#*52))@KXCcV}+EXBPq%5?x`NT0lv_ z@_{3O(Cv5whl|LG?M51q{dhOM3jj-^3QH5}GAo>(xStYZIbeKxKCoI!jAfhg>3=*Wh}e7IqL=G4%=0NRmjAhyTNCQiyMKgA)m3^L zOPLArp+GBRAyCeSaGZ#>P*xY+0emrLja-q{Mdt!tzX{MdzMRp(Q=%k~UMs62#fgMq zvYPmEb^%3W*2v(jF1i+|J!XwG566pm5_>)ijivKHx@aTMl4~pt>Kr0dYLRU$yIkd; z(>iPIvo%oX2ZkC;edCim<+s|{SS~Y4UL;;*1HyFAf)`@c$aS*Zv#j!bg6EYIFfh=w zG_*eXXJg`p4q7YV6Z9-^j#@7(VuewjMPm;~E?KHnPUm#cJcJ$yNmi-lz?&1mazd# zLt}Ztvy}KAr!2YWchFkR+fm?IMtMFHZ+=gv&%1;PUWJ*5hP*3bOO{Gh`I|V1I<4BW z2uKyk?6*N?E@-R6fNYen6@qnsMNUeQgkEiu4-!K#<2-Ftg z_I@8o&ipnyM1&la{C>ss6^;}!(J}zAq=QxumGc_VRbXPTVuFiW(H57M)(u!*pBQ#WK;y_Oo(gf-QZ#v4@w2c(!w_yS>PGNPZ2G{prD+jBZ(`jEVF6p4v zZ!>Poo}gN6VA002ovPDHLkV1kaKmL&iH From fc963e89b3fd9bc1e378297392f0fa11e3479cd3 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:43:22 +0200 Subject: [PATCH 0327/1189] Add files via upload --- apps/devstopwatch/app.png | Bin 0 -> 2483 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/devstopwatch/app.png diff --git a/apps/devstopwatch/app.png b/apps/devstopwatch/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b0feeebc9cbc2971fe26709493593120336f0410 GIT binary patch literal 2483 zcmV;k2~75hP)+7_A%r0eB108KOst|p6F>+c z#YkkZf`Zi65#>=tZ5=Su;7|+@WDq2TKtZvXAYBY~s1k^b0xIf4MGZkPynA;42vNrO z0zChcZ>_sl);Z_f-~MvXu>Z=+qDpA8g0F(8!(n~plS2l^xk7S zEEfUWqplb2fB~PWD$D>LKd$Rrh3shS{j6v=Obgo$)54!qBkH?Qr%Y{V9ojn3NR_*f zG(Re^+l2UVZLaKzre0JGbRMED1cod00umw&FIHG)eO~zQEZKQMB`Q>SD>8Yl$&*|(||d~C*3H2GM28MCEf`! zF;XU{Z6G~e1KkHP!&sj1d{!DEsc^R3DgLQg8zNdsV&!r0~Wc)!O$#sd!{ ztOi~~c@$y6_n$MUs7OLlGtg^*=AsNn7_#^k$?Y{jZ$p^^>_rF$EYlY(5I!RCvMqN7gJMs{8`wt+y@p&Fe-qmjRy)Fitjpz%%Kl(boy{A_0`3qPJ~xk- z2KJ=@B?U|CdHLaYpeh>}+(&bOnow1C}?vgg&QA{s^xywjs&&`XAH$mahzd z>`K{MX=3{Z@=>k_I=M=jFKhx9zr08WM9MAVE|k$nn;A=n=kx5WC9>1_Og5Ii0iVI) zk_RvrVtj}T9rJXH_gVMkD(zNbK&&2Qu(5pQStifSmmRKUifg$sBULXtYXh-9!#s=Q zDcQq*uRT0VH)9!}Q-wM2S%|R^=b!Mz*9ejS{0dD3n7v#|jS@7Ll;J(~x@tmpz~Tnr z_OmwN`t&uHH7_oak3CC<@%iMtSY|}x!I3v`as$Nq#K*z3%CQYf$uX8aM#y+RUv?Q~ zz30;-l1A7yFeX(m(h$3WzZ^15jScaoLe7-sa%VVRFj>vl)yNQ-6jPmgO*_MdNfrC! z@ld!X^#)l9FuI3kqhz=>s2eI{w7_Eu7fe|$U!F=U>>KdPX=5xHrR2OrBpFNffX}jU zob+^cO9L$SEHAm1{q`U`x4Z$H^074!pRgW?JIs$uJm9m;SZZh~Ej^!2#v;bjA)H=V z1CCE)W5M;=W+2g62>9#>$GP}hGL6#1^BFn$b!qn0GHGIzQTuk{e6{JssZ`6-?Z-3aT0n{==gpLSvVq*D?4e=R(3iYWtp?~5)fm%`@ zNzswx3S}z5#AF>MmPCQf2a9CJsr1hGsBaYn#*52))@KXCcV}+EXBPq%5?x`NT0lv_ z@_{3O(Cv5whl|LG?M51q{dhOM3jj-^3QH5}GAo>(xStYZIbeKxKCoI!jAfhg>3=*Wh}e7IqL=G4%=0NRmjAhyTNCQiyMKgA)m3^L zOPLArp+GBRAyCeSaGZ#>P*xY+0emrLja-q{Mdt!tzX{MdzMRp(Q=%k~UMs62#fgMq zvYPmEb^%3W*2v(jF1i+|J!XwG566pm5_>)ijivKHx@aTMl4~pt>Kr0dYLRU$yIkd; z(>iPIvo%oX2ZkC;edCim<+s|{SS~Y4UL;;*1HyFAf)`@c$aS*Zv#j!bg6EYIFfh=w zG_*eXXJg`p4q7YV6Z9-^j#@7(VuewjMPm;~E?KHnPUm#cJcJ$yNmi-lz?&1mazd# zLt}Ztvy}KAr!2YWchFkR+fm?IMtMFHZ+=gv&%1;PUWJ*5hP*3bOO{Gh`I|V1I<4BW z2uKyk?6*N?E@-R6fNYen6@qnsMNUeQgkEiu4-!K#<2-Ftg z_I@8o&ipnyM1&la{C>ss6^;}!(J}zAq=QxumGc_VRbXPTVuFiW(H57M)(u!*pBQ#WK;y_Oo(gf-QZ#v4@w2c(!w_yS>PGNPZ2G{prD+jBZ(`jEVF6p4v zZ!>Poo}gN6VA002ovPDHLkV1kaKmL&iH literal 0 HcmV?d00001 From a9991da57d871406e6179e902ba2d4c70c57bea3 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:44:10 +0200 Subject: [PATCH 0328/1189] Create ChangeLog --- apps/devstopwatch/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/devstopwatch/ChangeLog diff --git a/apps/devstopwatch/ChangeLog b/apps/devstopwatch/ChangeLog new file mode 100644 index 000000000..e7c9e714a --- /dev/null +++ b/apps/devstopwatch/ChangeLog @@ -0,0 +1 @@ +0.01: App created From 3cfd41f5182e41352e75d08342393f1d854732e3 Mon Sep 17 00:00:00 2001 From: Simone Di Cicco Date: Thu, 9 Apr 2020 18:46:45 +0200 Subject: [PATCH 0329/1189] Update apps.json --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7ab80c723..63fa3a88a 100644 --- a/apps.json +++ b/apps.json @@ -1140,9 +1140,10 @@ "version":"0.01", "description": "Stopwatch with 5 laps supported (cyclically replaced)", "tags": "stopwatch, chrono, timer, chronometer", + "allow_emulator":true, "storage": [ - {"name":"stopwatch.app.js","url":"app.js"}, - {"name":"stopwatch.img","url":"app-icon.js","evaluate":true} + {"name":"devstopwatch.app.js","url":"app.js"}, + {"name":"devstopwatch.img","url":"app-icon.js","evaluate":true} ] } ] From 09a0854b080b91ff9600a2c4ace72d76be19842a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 9 Apr 2020 21:20:01 +0100 Subject: [PATCH 0330/1189] fix accidental changelog non-commit --- apps/files/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/files/ChangeLog diff --git a/apps/files/ChangeLog b/apps/files/ChangeLog new file mode 100644 index 000000000..8b7be7640 --- /dev/null +++ b/apps/files/ChangeLog @@ -0,0 +1 @@ +0.02: Fix deletion of apps - now use files list in app.info (fix #262) From f0cd45262262907299d8d24f83bd1ea91af64d13 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 9 Apr 2020 21:51:19 +0100 Subject: [PATCH 0331/1189] 0.12: Fix memory leak (#206) Bring App settings nearer the top Move LCD Timeout to wakeup menu --- apps.json | 2 +- apps/setting/ChangeLog | 3 +++ apps/setting/settings.js | 52 ++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/apps.json b/apps.json index cf7520de0..d85739aad 100644 --- a/apps.json +++ b/apps.json @@ -119,7 +119,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.11", + "version":"0.12", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 51de64281..22277968c 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -9,3 +9,6 @@ 0.10: Added LCD wake-up settings Adds LCD brightness setting 0.11: Make LCD brightness work after leaving settings +0.12: Fix memory leak (#206) + Bring App settings nearer the top + Move LCD Timeout to wakeup menu diff --git a/apps/setting/settings.js b/apps/setting/settings.js index a93116bec..ac7692610 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -63,7 +63,8 @@ function showMainMenu() { var beepN = ["Off", "Piezo", "Vibrate"]; const mainmenu = { '': { 'title': 'Settings' }, - 'Make Connectable': makeConnectable, + 'Make Connectable': ()=>makeConnectable(), + 'App/widget settings': ()=>showAppSettingsMenu(), 'BLE': { value: settings.ble, format: boolFormat, @@ -88,17 +89,6 @@ function showMainMenu() { updateSettings(); } }, - 'LCD Timeout': { - value: settings.timeout, - min: 0, - max: 60, - step: 5, - onchange: v => { - settings.timeout = 0 | v; - updateSettings(); - Bangle.setLCDTimeout(settings.timeout); - } - }, 'LCD Brightness': { value: settings.brightness, min: 0.1, @@ -133,8 +123,8 @@ function showMainMenu() { } } }, - 'Locale': showLocaleMenu, - 'Select Clock': showClockMenu, + 'Locale': ()=>showLocaleMenu(), + 'Select Clock': ()=>showClockMenu(), 'HID': { value: settings.HID, format: boolFormat, @@ -143,12 +133,11 @@ function showMainMenu() { updateSettings(); } }, - 'Set Time': showSetTimeMenu, - 'LCD Wake-Up': showWakeUpMenu, - 'App/widget settings': showAppSettingsMenu, - 'Reset Settings': showResetMenu, - 'Turn Off': Bangle.off, - '< Back': () => { load(); } + 'Set Time': ()=>showSetTimeMenu(), + 'LCD Wake-Up': ()=>showWakeUpMenu(), + 'Reset Settings': ()=>showResetMenu(), + 'Turn Off': ()=>Bangle.off(), + '< Back': ()=>load() }; return E.showMenu(mainmenu); } @@ -156,7 +145,18 @@ function showMainMenu() { function showWakeUpMenu() { const wakeUpMenu = { '': { 'title': 'LCD Wake-Up' }, - '< Back': showMainMenu, + '< Back': ()=>showMainMenu(), + 'LCD Timeout': { + value: settings.timeout, + min: 0, + max: 60, + step: 5, + onchange: v => { + settings.timeout = 0 | v; + updateSettings(); + Bangle.setLCDTimeout(settings.timeout); + } + }, 'Wake On BTN1': { value: settings.options.wakeOnBTN1, format: boolFormat, @@ -242,7 +242,7 @@ function showWakeUpMenu() { function showLocaleMenu() { const localemenu = { '': { 'title': 'Locale' }, - '< Back': showMainMenu, + '< Back': ()=>showMainMenu(), 'Time Zone': { value: settings.timezone, min: -11, @@ -268,7 +268,7 @@ function showLocaleMenu() { function showResetMenu() { const resetmenu = { '': { 'title': 'Reset' }, - '< Back': showMainMenu, + '< Back': ()=>showMainMenu(), 'Reset Settings': () => { E.showPrompt('Reset Settings?').then((v) => { if (v) { @@ -304,7 +304,7 @@ function showClockMenu() { '': { 'title': 'Select Clock', }, - '< Back': showMainMenu, + '< Back': ()=>showMainMenu(), }; clockApps.forEach((app, index) => { var label = app.name; @@ -342,7 +342,7 @@ function showSetTimeMenu() { timemenu.Year.value = d.getFullYear(); } }, - '< Back': showMainMenu, + '< Back': ()=>showMainMenu(), 'Hour': { value: d.getHours(), min: 0, @@ -416,7 +416,7 @@ function showSetTimeMenu() { function showAppSettingsMenu() { let appmenu = { '': { 'title': 'App Settings' }, - '< Back': showMainMenu, + '< Back': ()=>showMainMenu(), } const apps = storage.list(/\.info$/) .map(app => storage.readJSON(app, 1)) From 0aad2a3082f47554b2094bbd3f2c4f7fd486cab1 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Thu, 9 Apr 2020 18:29:49 -0500 Subject: [PATCH 0332/1189] Added NATO Alphabet app files --- apps/nato/appsManifestEntry.txt | 13 ++++ apps/nato/nato-icon.js | 1 + apps/nato/nato.js | 116 ++++++++++++++++++++++++++++++++ apps/nato/nato.png | Bin 0 -> 2023 bytes 4 files changed, 130 insertions(+) create mode 100644 apps/nato/appsManifestEntry.txt create mode 100644 apps/nato/nato-icon.js create mode 100644 apps/nato/nato.js create mode 100644 apps/nato/nato.png diff --git a/apps/nato/appsManifestEntry.txt b/apps/nato/appsManifestEntry.txt new file mode 100644 index 000000000..2e8d840e0 --- /dev/null +++ b/apps/nato/appsManifestEntry.txt @@ -0,0 +1,13 @@ + { "id": "nato", + "name": "NATO Alphabet", + "shortName" : "NATOAlphabet", + "icon": "nato.png", + "version":"0.01", + "type": "app", + "description": "Learn the NATO Phonetic alphabet plus some numbers.", + "tags": "app,learn,visual", + "storage": [ + {"name":"nato.app.js","url":"nato.js"}, + {"name":"nato.img","url":"nato-icon.js","evaluate":true} + ], + }, \ No newline at end of file diff --git a/apps/nato/nato-icon.js b/apps/nato/nato-icon.js new file mode 100644 index 000000000..b1a6e0947 --- /dev/null +++ b/apps/nato/nato-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwgFCiIABiAGFiINJAAUS///CAgGEgMT//zBoYXFmIiCC40fEooXF+QXJn4lCC5ARDC4oFC//xMAoXDJAQXFBgY9DC4wKCC4p2CPA4XDCQQXEOwXxPA4XBEQJICC4p2BmICCC44KBJAIXEiIJBkMvPAwXCWgYXFAgQMBPAoXCBwUxC4jtDeI4XDJAQXDFYXxHAoXGJAYXDLYPykUieIwXDJAYXDG4IAEPAgXCRgJICPYoAEPAgXDZ4TcDmYXGMAgXDUAZiEPwIABCALEBC5BZC+YQCRwRsEC45ID+S5BCAkBEYJ4DC4hID+IbCIAYjCCIYXGEgMxXoJwEgI3CA4JQDAAwaBmQGDFIQ3CC5UzkSLBdwIIDmYXCWY4jBCAJBCPYQ0EC5bXGkLuDC5QtEAAXzPoZMCmZwB+YFCbYkykQFCVoZMDWALnDQwRjDeoZIDZAgJCWwYeBFATWFC5LuHawgXKdwyJDD4YXIOAMzH4gICmIXKEwQXXkQXFKAKQFC85HNO64XDU44XMX48Sa5zvCmJICA4YXLE4fziIACJ4PyM4gXHCAQwBCwI2GC5JADAApGFC5ERmYWFFwwXHDARJCMgYWFB4MTmYiFLgMjCwMyiIuGE4QABNIyPDBQgA==")) \ No newline at end of file diff --git a/apps/nato/nato.js b/apps/nato/nato.js new file mode 100644 index 000000000..7e1e06db7 --- /dev/null +++ b/apps/nato/nato.js @@ -0,0 +1,116 @@ +/** + * Teach a user the NATO Phonetic Alphabet + numbers +*/ + +/** + * Constants +*/ +const FONT_NAME = 'Vector12'; +const FONT_SIZE = 80; +const SCREEN_PIXELS = 240; +const UNIT = 100; +const NATO_MAP = { + A: 'ALFA', + B: 'BRAVO', + C: 'CHARLIE', + D: 'DELTA', + E: 'ECHO', + F: 'FOXTROT', + G: 'GOLF', + H: 'HOTEL', + I: 'INDIA', + J: 'JULIETT', + K: 'KILO', + L: 'LIMA', + M: 'MIKE', + N: 'NOVEMBER', + O: 'OSCAR', + P: 'PAPA', + Q: 'QUEBEC', + R: 'ROMEO', + S: 'SIERRA', + T: 'TANGO', + U: 'UNIFORM', + V: 'VICTOR', + W: 'WHISKEY', + X: 'X-RAY', + Y: 'YANKEE', + Z: 'ZULU', + '0': 'ZE-RO', + '1': 'WUN', + '2': 'TOO', + '3': 'TREE', + '4': 'FOW-ER', + '5': 'FIFE', + '6': 'SIX', + '7': 'SEV-EN', + '8': 'AIT', + '9': 'NIN-ER', +}; + +/** + * Set the local state +*/ +let INDEX = 0; +let showLetter = true; + +/** + * Utility functions for writing text, changing state +*/ +const writeText = (txt) => { + g.clear(); + g.setFont(FONT_NAME, FONT_SIZE); + + var width = g.stringWidth(txt); + + var fontFix = FONT_SIZE; + while(width > SCREEN_PIXELS-10){ + fontFix--; + g.setFont(FONT_NAME, fontFix); + width = g.stringWidth(txt); + } + g.drawString(txt, (SCREEN_PIXELS / 2) - (width / 2), SCREEN_PIXELS / 2); +}; +const writeLetter = () => { + writeText(Object.keys(NATO_MAP)[INDEX]); +}; +const writeCode = () => { + writeText(NATO_MAP[Object.keys(NATO_MAP)[INDEX]]); +}; +const toggle = () => { + showLetter = !showLetter; + if(showLetter){ + writeLetter(); + }else { + writeCode(); + } +}; + +/** + * Bootstrapping +*/ +g.clear(); +g.setFont(FONT_NAME, FONT_SIZE); +g.setColor(0, 1, 0); +g.setFontAlign(-1, 0, 0); + + +const step = (positive) => () => { + if (positive) { + INDEX = INDEX + 1; + if (INDEX > Object.keys(NATO_MAP).length - 1) INDEX = 0; + } else { + INDEX = INDEX - 1; + if (INDEX < 0) INDEX = Object.keys(NATO_MAP).length - 1; + } + showLetter = true; + writeLetter(); +}; + +writeLetter(); + +// Press the middle button to see the NATO Phonetic wording +setWatch(toggle, BTN2, { repeat: true }); +// Allow user to switch between letters +setWatch(step(true), BTN1, { repeat: true }); +setWatch(step(false), BTN3, { repeat: true }); diff --git a/apps/nato/nato.png b/apps/nato/nato.png new file mode 100644 index 0000000000000000000000000000000000000000..bd4678c11f489649f765c47e73d04cd94cbe0a03 GIT binary patch literal 2023 zcmV^5HKn!Rq~;Y;-8uZY{ZHnw;Kf|H|4jzx6ID%-rbsu?R>i1*_nC2 zdB6AOy*DdJX^}|eH6g@r>NEAX5aQ!lEcUHezhM~CZ=95})3U73^!{)-ToDR|eonDo zNh}uo#jhXFg%^Ov#zxw)V~5imJOoSdA(M~@!;sZYuPZr!@&bltmmk5;c< zO@08P(P)d5vZ=4HkCrW4=8PK|8KI3EHA9AR)7iAtRyosyHY%O2U%yUORaLNq4$HFYvj)J6N|^#! zuwX&>@#Du9gn_q-L?X6amSs^;0x_Rz4R1Bs7L$R1wh+ zUQ|+rQ2_ufn(Bs?9reWE6)Wx8vxm-{IRh%aZdumvfi=JxStJta@S_q-bLrA0s;Q|V zFF`nTNVogCmX!#=Hs83S=c}_^>UgU+E+h6i6#^79cCb35@JdO=^+= zU@{N^!muXpd>r5iVH*pFZmM6nF@L%0X(5b$@o)dgKjKKR203_Qv zIXN$TNhGEG(5nc=0C1qFHv#-lQT zt9LpL)!YP;an=F&(G58*8Y*pm0h|heHL26+KLY^nqv81HWF(af^UDr7E91+L7p8%1 z0nl%K{;m2RNr*tQ*A)4D)`ZeZ*aVv0UQC}5@j6#FO2ZFqN2i) zPxV4Vh?ZC^)||=)xCpH0#C-L{b<(T@m^W`;0SdT!5`v(Ny-=dw?}P(75T=h;BEuy{ zzWmEN00@)n{!8KT)lew(iGB|Z;e`-i3L)OmcVDRsoit5ziz^mN zGp~FY{hX91);uAE7{_lZWib)Ghu=B{@hoj+E*r5B=1@ZczgpG z0HUD*7n9_ftfZnZE;q0N3BymiC!0|K34^w;R9Q$IOl#JxamD#w0FXBf4i0iEiB}r) z^76h)c}JGc2K00@kz648PPq|YU!}mnar0SNSm;`IY;4T_b^k^)6j%TN002ovPDHLk FV1jvc#zp`D literal 0 HcmV?d00001 From 866b6ca6355565ce51fcfb523a629064bdf88528 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Thu, 9 Apr 2020 18:46:32 -0500 Subject: [PATCH 0333/1189] Added NATO Alphabet to manifest --- apps.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps.json b/apps.json index d85739aad..d432b861b 100644 --- a/apps.json +++ b/apps.json @@ -1159,4 +1159,17 @@ {"name":"batchart.img","url":"app-icon.js","evaluate":true} ] } + { "id": "nato", + "name": "NATO Alphabet", + "shortName" : "NATOAlphabet", + "icon": "nato.png", + "version":"0.01", + "type": "app", + "description": "Learn the NATO Phonetic alphabet plus some numbers.", + "tags": "app,learn,visual", + "storage": [ + {"name":"nato.app.js","url":"nato.js"}, + {"name":"nato.img","url":"nato-icon.js","evaluate":true} + ], + }, ] From b833c39ac2d2fdfca70bdb41bb8d214e97b6bde4 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Thu, 9 Apr 2020 18:48:07 -0500 Subject: [PATCH 0334/1189] ...missed a comma --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index d432b861b..b18488bbc 100644 --- a/apps.json +++ b/apps.json @@ -1158,7 +1158,7 @@ {"name":"batchart.app.js","url":"app.js"}, {"name":"batchart.img","url":"app-icon.js","evaluate":true} ] - } + }, { "id": "nato", "name": "NATO Alphabet", "shortName" : "NATOAlphabet", From a9c5b7341715de222f901909844ab5fe54fcb9e3 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Thu, 9 Apr 2020 18:49:00 -0500 Subject: [PATCH 0335/1189] more commas --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index b18488bbc..c2377adcf 100644 --- a/apps.json +++ b/apps.json @@ -1171,5 +1171,5 @@ {"name":"nato.app.js","url":"nato.js"}, {"name":"nato.img","url":"nato-icon.js","evaluate":true} ], - }, + } ] From 6126a34bfa043fba7b1f606e2bc8346bb2b24a81 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Thu, 9 Apr 2020 18:50:19 -0500 Subject: [PATCH 0336/1189] , --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index c2377adcf..2216f6671 100644 --- a/apps.json +++ b/apps.json @@ -1170,6 +1170,6 @@ "storage": [ {"name":"nato.app.js","url":"nato.js"}, {"name":"nato.img","url":"nato-icon.js","evaluate":true} - ], + ] } ] From 6d31f60055211a3179d3a7e8841c667c5730b79d Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Fri, 10 Apr 2020 07:30:38 -0500 Subject: [PATCH 0337/1189] allow emulator for NATO --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 2216f6671..20ef55e38 100644 --- a/apps.json +++ b/apps.json @@ -1167,6 +1167,7 @@ "type": "app", "description": "Learn the NATO Phonetic alphabet plus some numbers.", "tags": "app,learn,visual", + "allow_emulator":true, "storage": [ {"name":"nato.app.js","url":"nato.js"}, {"name":"nato.img","url":"nato-icon.js","evaluate":true} From 4072bb68697923bf3a9a7e86bf5c8ced381e9919 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Fri, 10 Apr 2020 07:36:40 -0500 Subject: [PATCH 0338/1189] Removing app manifest txt This has been added to the main manifest. --- apps/nato/appsManifestEntry.txt | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 apps/nato/appsManifestEntry.txt diff --git a/apps/nato/appsManifestEntry.txt b/apps/nato/appsManifestEntry.txt deleted file mode 100644 index 2e8d840e0..000000000 --- a/apps/nato/appsManifestEntry.txt +++ /dev/null @@ -1,13 +0,0 @@ - { "id": "nato", - "name": "NATO Alphabet", - "shortName" : "NATOAlphabet", - "icon": "nato.png", - "version":"0.01", - "type": "app", - "description": "Learn the NATO Phonetic alphabet plus some numbers.", - "tags": "app,learn,visual", - "storage": [ - {"name":"nato.app.js","url":"nato.js"}, - {"name":"nato.img","url":"nato-icon.js","evaluate":true} - ], - }, \ No newline at end of file From 987be3201b580cf852aa8f9b86631689ef89d614 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Fri, 10 Apr 2020 07:40:29 -0500 Subject: [PATCH 0339/1189] Cleanup and comments --- apps/nato/nato.js | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/apps/nato/nato.js b/apps/nato/nato.js index 7e1e06db7..f4301b83f 100644 --- a/apps/nato/nato.js +++ b/apps/nato/nato.js @@ -1,10 +1,6 @@ -/** - * Teach a user the NATO Phonetic Alphabet + numbers -*/ +// Teach a user the NATO Phonetic Alphabet + numbers +// Based on the Morse Code app -/** - * Constants -*/ const FONT_NAME = 'Vector12'; const FONT_SIZE = 80; const SCREEN_PIXELS = 240; @@ -48,21 +44,16 @@ const NATO_MAP = { '9': 'NIN-ER', }; -/** - * Set the local state -*/ let INDEX = 0; let showLetter = true; -/** - * Utility functions for writing text, changing state -*/ const writeText = (txt) => { g.clear(); g.setFont(FONT_NAME, FONT_SIZE); var width = g.stringWidth(txt); + // Fit text to screen var fontFix = FONT_SIZE; while(width > SCREEN_PIXELS-10){ fontFix--; @@ -86,9 +77,8 @@ const toggle = () => { } }; -/** - * Bootstrapping -*/ +// Bootstrapping + g.clear(); g.setFont(FONT_NAME, FONT_SIZE); g.setColor(0, 1, 0); @@ -103,7 +93,7 @@ const step = (positive) => () => { INDEX = INDEX - 1; if (INDEX < 0) INDEX = Object.keys(NATO_MAP).length - 1; } - showLetter = true; + showLetter = true; // for toggle() writeLetter(); }; From ada96912f78107e00272e6897f75c78d6b160e9c Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Fri, 10 Apr 2020 07:46:44 -0500 Subject: [PATCH 0340/1189] Added newline to the end of apps/nato/nato-icon.js --- apps/nato/nato-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/nato/nato-icon.js b/apps/nato/nato-icon.js index b1a6e0947..ae38c0274 100644 --- a/apps/nato/nato-icon.js +++ b/apps/nato/nato-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwgFCiIABiAGFiINJAAUS///CAgGEgMT//zBoYXFmIiCC40fEooXF+QXJn4lCC5ARDC4oFC//xMAoXDJAQXFBgY9DC4wKCC4p2CPA4XDCQQXEOwXxPA4XBEQJICC4p2BmICCC44KBJAIXEiIJBkMvPAwXCWgYXFAgQMBPAoXCBwUxC4jtDeI4XDJAQXDFYXxHAoXGJAYXDLYPykUieIwXDJAYXDG4IAEPAgXCRgJICPYoAEPAgXDZ4TcDmYXGMAgXDUAZiEPwIABCALEBC5BZC+YQCRwRsEC45ID+S5BCAkBEYJ4DC4hID+IbCIAYjCCIYXGEgMxXoJwEgI3CA4JQDAAwaBmQGDFIQ3CC5UzkSLBdwIIDmYXCWY4jBCAJBCPYQ0EC5bXGkLuDC5QtEAAXzPoZMCmZwB+YFCbYkykQFCVoZMDWALnDQwRjDeoZIDZAgJCWwYeBFATWFC5LuHawgXKdwyJDD4YXIOAMzH4gICmIXKEwQXXkQXFKAKQFC85HNO64XDU44XMX48Sa5zvCmJICA4YXLE4fziIACJ4PyM4gXHCAQwBCwI2GC5JADAApGFC5ERmYWFFwwXHDARJCMgYWFB4MTmYiFLgMjCwMyiIuGE4QABNIyPDBQgA==")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwgFCiIABiAGFiINJAAUS///CAgGEgMT//zBoYXFmIiCC40fEooXF+QXJn4lCC5ARDC4oFC//xMAoXDJAQXFBgY9DC4wKCC4p2CPA4XDCQQXEOwXxPA4XBEQJICC4p2BmICCC44KBJAIXEiIJBkMvPAwXCWgYXFAgQMBPAoXCBwUxC4jtDeI4XDJAQXDFYXxHAoXGJAYXDLYPykUieIwXDJAYXDG4IAEPAgXCRgJICPYoAEPAgXDZ4TcDmYXGMAgXDUAZiEPwIABCALEBC5BZC+YQCRwRsEC45ID+S5BCAkBEYJ4DC4hID+IbCIAYjCCIYXGEgMxXoJwEgI3CA4JQDAAwaBmQGDFIQ3CC5UzkSLBdwIIDmYXCWY4jBCAJBCPYQ0EC5bXGkLuDC5QtEAAXzPoZMCmZwB+YFCbYkykQFCVoZMDWALnDQwRjDeoZIDZAgJCWwYeBFATWFC5LuHawgXKdwyJDD4YXIOAMzH4gICmIXKEwQXXkQXFKAKQFC85HNO64XDU44XMX48Sa5zvCmJICA4YXLE4fziIACJ4PyM4gXHCAQwBCwI2GC5JADAApGFC5ERmYWFFwwXHDARJCMgYWFB4MTmYiFLgMjCwMyiIuGE4QABNIyPDBQgA==")) From d9a9bae5eea9450acccae6f9a65b502311d478e9 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 10 Apr 2020 17:42:14 +0200 Subject: [PATCH 0341/1189] Move LCD Brightness menu into more general LCD menu & unify writings --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 40 ++++++++++++++++++++-------------------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/apps.json b/apps.json index d85739aad..a8390b927 100644 --- a/apps.json +++ b/apps.json @@ -119,7 +119,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.12", + "version":"0.13", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 22277968c..c3109dda6 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -12,3 +12,4 @@ 0.12: Fix memory leak (#206) Bring App settings nearer the top Move LCD Timeout to wakeup menu +0.13: Move LCD Brightness menu into more general LCD menu diff --git a/apps/setting/settings.js b/apps/setting/settings.js index ac7692610..c6be52191 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -89,17 +89,6 @@ function showMainMenu() { updateSettings(); } }, - 'LCD Brightness': { - value: settings.brightness, - min: 0.1, - max: 1, - step: 0.1, - onchange: v => { - settings.brightness = v || 1; - updateSettings(); - Bangle.setLCDBrightness(settings.brightness); - } - }, 'Beep': { value: 0 | beepV.indexOf(settings.beep), min: 0, max: 2, @@ -134,7 +123,7 @@ function showMainMenu() { } }, 'Set Time': ()=>showSetTimeMenu(), - 'LCD Wake-Up': ()=>showWakeUpMenu(), + 'LCD': ()=>showLCDMenu(), 'Reset Settings': ()=>showResetMenu(), 'Turn Off': ()=>Bangle.off(), '< Back': ()=>load() @@ -142,10 +131,21 @@ function showMainMenu() { return E.showMenu(mainmenu); } -function showWakeUpMenu() { - const wakeUpMenu = { - '': { 'title': 'LCD Wake-Up' }, +function showLCDMenu() { + const lcdMenu = { + '': { 'title': 'LCD' }, '< Back': ()=>showMainMenu(), + 'LCD Brightness': { + value: settings.brightness, + min: 0.1, + max: 1, + step: 0.1, + onchange: v => { + settings.brightness = v || 1; + updateSettings(); + Bangle.setLCDBrightness(settings.brightness); + } + }, 'LCD Timeout': { value: settings.timeout, min: 0, @@ -157,7 +157,7 @@ function showWakeUpMenu() { Bangle.setLCDTimeout(settings.timeout); } }, - 'Wake On BTN1': { + 'Wake on BTN1': { value: settings.options.wakeOnBTN1, format: boolFormat, onchange: () => { @@ -165,7 +165,7 @@ function showWakeUpMenu() { updateOptions(); } }, - 'Wake On BTN2': { + 'Wake on BTN2': { value: settings.options.wakeOnBTN2, format: boolFormat, onchange: () => { @@ -173,7 +173,7 @@ function showWakeUpMenu() { updateOptions(); } }, - 'Wake On BTN3': { + 'Wake on BTN3': { value: settings.options.wakeOnBTN3, format: boolFormat, onchange: () => { @@ -197,7 +197,7 @@ function showWakeUpMenu() { updateOptions(); } }, - 'Wake On Twist': { + 'Wake on Twist': { value: settings.options.wakeOnTwist, format: boolFormat, onchange: () => { @@ -236,7 +236,7 @@ function showWakeUpMenu() { } } } - return E.showMenu(wakeUpMenu) + return E.showMenu(lcdMenu) } function showLocaleMenu() { From 5e5fb570db0ff446275d45bfa658f6c59ad9c918 Mon Sep 17 00:00:00 2001 From: Fabio Date: Fri, 10 Apr 2020 19:20:49 +0200 Subject: [PATCH 0342/1189] New bledetect app --- apps.json | 12 ++++++ apps/bledetect/ChangeLog | 1 + apps/bledetect/bledetect-icon.js | 1 + apps/bledetect/bledetect.js | 67 +++++++++++++++++++++++++++++++ apps/bledetect/bledetect.png | Bin 0 -> 4163 bytes 5 files changed, 81 insertions(+) create mode 100644 apps/bledetect/ChangeLog create mode 100644 apps/bledetect/bledetect-icon.js create mode 100644 apps/bledetect/bledetect.js create mode 100644 apps/bledetect/bledetect.png diff --git a/apps.json b/apps.json index d85739aad..8e4e2555a 100644 --- a/apps.json +++ b/apps.json @@ -1158,5 +1158,17 @@ {"name":"batchart.app.js","url":"app.js"}, {"name":"batchart.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "bledetect", + "name": "BLE Detector", + "shortName":"BLEDetector", + "icon": "bledetect.png", + "version":"0.01", + "description": "Detect BLE devices and show some informations.", + "tags": "app,bluetooth,tool", + "storage": [ + {"name":"bledetect.app.js","url":"bledetect.js"}, + {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} + ] } ] diff --git a/apps/bledetect/ChangeLog b/apps/bledetect/ChangeLog new file mode 100644 index 000000000..9352c7b96 --- /dev/null +++ b/apps/bledetect/ChangeLog @@ -0,0 +1 @@ +0.01: Initial Release \ No newline at end of file diff --git a/apps/bledetect/bledetect-icon.js b/apps/bledetect/bledetect-icon.js new file mode 100644 index 000000000..a15e13307 --- /dev/null +++ b/apps/bledetect/bledetect-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("AAAAAAAACIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAiIgIiIiAAAAAAAAAAAAAAAAAAAAAAAAAiIgAiIiIAAAAAAAAAAAAAAAAAIAAAAAAiIgACIiIgAAAAAAAAAAAAAAAiIiAAAAAiIgAAAiIiIAAAAAAAAAAAAAAiIiIAAAAiIgAAACIiIgAAAAAAAAAAAAACIiIgAAAiIgAAAAIiIgAAAAAAAAAAAAAAIiIiAAAiIgAAAAIiIiAAAAAAAAAAAAAAAiIiIAAiIgAAACIiIgAAAAAAAAAAAAAAACIiIgAiIgAAAiIiIAAAAAAAAAAAAAAAAAIiIiIiIgACIiIiAAAAAAAAAAAAAAAAAAACIiIiIgAiIiIAAAAAAAAAAAAAAAAAAAAAIiIiIgIiIiAAAAAAAAAAAAAAAAAAAAAAAiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAACIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIiAAAAAAAAAIgAAAAAAAAAAAAAACIiIiIiIAAAAACIiIiIiAAAAAAAAAAAIiIiIiIiIgAAAAiIiIiIiIAAAAAAAAACIiIiIgIiIiAACIiIiIiIiIgAAAAAAAAiIiIiIgAiIiAACIiIiACIiIiAAAAAAAIiIiAiIgAAIgAAiIiAAAAAiIiIAAAAACIiIgAiIgAAAAAIiIgAAAAAAIiIAAAAAiIiIAAiIgAAAAAIiIAAAAAAAEiIgAAAIiIiAAAiIgAAAAAIiIAAAAAAAAiIgAAiIiIgAAAiIgAAAAAIiIAAAAAAAAiIgAAiIiAAAAAiIgAAAACIiAAAAAAAAAiIgAAiIgAAAAAiIgAAAACIiAAAAAAAAAiIgAAAAAAAAAAiIgAAAAAIiIAAAAAAAAiIgAAAAAAAAAAiIgAiIAAIiIAAAAAAAAiIgAAAAAAAAAAiIgIiIgAIiIgAAAAAAIiIgAAAAAAAAAAiIiIiIgAIiIgAAAAACIiIAAAAAAAAAAAiIiIiIAAAiIiIAAAAiIiIAAAAAAAAAAAiIiIgAAAACIiIiIiIiIiIAAAAAAAAAAAiIiIAAAAAAIiIiIiIiIiIgAAAAAAAAAAiIiAAAAAAAAiIiIiIiIiIiAAAAAAAAAAiIgAAAAAAAAAIiIiIgACIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIi")) \ No newline at end of file diff --git a/apps/bledetect/bledetect.js b/apps/bledetect/bledetect.js new file mode 100644 index 000000000..dde3ee9eb --- /dev/null +++ b/apps/bledetect/bledetect.js @@ -0,0 +1,67 @@ +let menu = { + "": { "title": "BLE Detector" }, + "RE-SCAN": () => scan() +}; + +function showMainMenu() { + menu["< Back"] = () => load(); + return E.showMenu(menu); +} + +function showDeviceInfo(device){ + console.log(device); + const deviceMenu = { + "": { "title": "Device Info" }, + "name": { + value: device.name + }, + "rssi": { + value: device.rssi + }, + "manufacturer": { + value: device.manufacturer + } + }; + + deviceMenu[device.id] = () => {}; + deviceMenu["< Back"] = () => scan(); + + /*for(let key in device){ + deviceMenu[key.substring(0,17)] = { + value: device[key.substring(0,17)] + }; + }*/ + + return E.showMenu(deviceMenu); +} + +function scan() { + menu = { + "": { "title": "BLE Detector" }, + "RE-SCAN": () => scan() + }; + + waitMessage(); + + NRF.findDevices(devices => { + for (let device of devices) { + let deviceName = device.id.substring(0,17); + + if (device.name) { + deviceName = device.name; + } + + menu[deviceName] = () => showDeviceInfo(device); + } + showMainMenu(menu); + }, { active: true }); +} + +function waitMessage() { + E.showMenu(); + E.showMessage("scanning"); +} + +scan(); +waitMessage(); + diff --git a/apps/bledetect/bledetect.png b/apps/bledetect/bledetect.png new file mode 100644 index 0000000000000000000000000000000000000000..59d6a26cee07bc61899bc7ec129c426784e5f716 GIT binary patch literal 4163 zcmaJ^c|276-=7H?YbY+GG{(M;nX!!}4KpGpLfHyqjNJ?~V<-EPr4$JfWzCvBA(FL( zM1)91+4po6^Njnu-QV-abD#4%=X{sf`~Ci`-`DG$>!ugZaj}Eh0RRA(p#jE>F)AHC zpreep<&i(*7=sWEYeh3BJJbB}6e0laM0O-X488C!L^C4ZDbS~ns09EpLES8@XjV95 z4FcIq5r2qL4Dj-1umJ!qod9n# zMDw5v7K9)V0?G-ha|WUnpurIEBGT}X054AxRU<$f`j@T-V}7^|gF^m-&^)xE|8dF+ zXA03HQ-}~1MWg~j2@Z#-sw%>jRa8~s@(_d)905~e+^Pz2WepWo4TKux?+ePXMsaf1 zFvIBoZHuwehPu*d-Wo8NzrVktKT?rQae={6DAb__0-?Y_C{P1QG<<*pi7NJ60Yjt` zC~n>~H!=xwsEBtY`_i_Cp1V-VU#STq*Yv@skcp8~vK_+|t&Z4O+nMS6%lD#2% z=Bf~BOE;1e*`F%&7aoVxFeFiFcoKnVh|z{J6cpXuoHW!BXgwtrePuOWWh@+yMWdC} zQD}8NxVjQX4GUL6{^nxH1Ya*AiT0c8^k1&Zzj6;-!ONRr8AGJF`4OG;DP%9mUm-6uwApeyMV>kmlEbRX(^zSW3_Z&|DXzXY6F7UhTVt1Nlz0jK9wPsj7WxkWfQI6kwXc=1NxDz7 z+P0&2=2zt-8g7O*zu>pY5k0rxR7bOxhn(Tk}kAv4s z03Ugh9zPM3^bW5=-tZM}S})N!^XRJ>;4I=j7r*(%$iA}yZ1*wyZXjoB!OwAtnIID* zFwo+8+cCh-M`lQVsD{BQ&aqJSMa?Lg&}^OuTG!dRCJp&`lI9&oQ@0KZ?aY<#iKu^_ z1+EAAG+)uCC-Of_Or^6S`)C$L%i;UXJh;)9rOBU-WE=XkWo@>Dc_T?j@Lw%R(L~$! zNRt^q;qRYb0Q10S=thmt&Brp6y88^QM(pSnD39wnO&?bN3A8BSL=tmCDexz*<{52k z9CaH@SBp-&&J7q)mWyZR@hlsy^(UKmw~Q$VIOhiU+a#gP#d6k2b#tC1wpAF0?9A|k3TRBsZl)3W$5kNdLn^g(XCX+fI z;i@G0O(PBdvwcf=dz-49 zdpBe=bnmK(hKeT!rpbPvBTTfL$>0sJBZRw~uyMOnEnMlSTpa8Np9DXLQ>o%tmNK0C zTj8ZM%-6c{ulj~W*L0J`$;Ql}kggNPSqJ?Mf8Mc|?^`tnDC|G-V@h)|$)tA>giX5% z&pK_+=JRG`<9UJ0Un;tFfF~Bdh6olfCR}z8V&6+Z{s5`J_h$8-1J_UzvKn#W{n z!^X_Htd?VZzFZ@tWNle~L{_xqV?;c?CZCLFU%Lc#d0{h;bBO!H+Mf0C(+(o=sH{LA zzm)-}^qaqFFtg{-`9F ze>#YID*|ut4LmrCkln~OG7(MVj2|uhDO+RavfytFODXS;tJI&oJD$%97&nZ4L>OBO zC+_sA(sHboE!)fwe3p+kC@0ce_kaZ-W-L4+dSYAp?jQYpjThb9d>rA6X$;+@rYBj5 zfOMN1XqLKrvrc;Z(c5}T4&@b#A%KD+9a9)CIbU$?wW&LET|F=C?x`w;ePYwxeleN7 zyHqs{VI|DvU5Ex6 zNojD(iJXi1a+;UYg9+vn*V7Q1J!c#Q*q7t>+JgM}i%eU&62X+l&h(_mrlaxYsNTZ- z#jUncKQS+#z~SgYhqjL`r$kUZLQ2r@{8<|zMm*{!hM3h^RyGH9ptOx&S^4^W2YJ^M z^;Q5>?lqw`z+A4?%A5M=vVouQuzr|BgL6(0_}KDi?m1nu6>KpkFGtKE*$)KWogg$( zMkXrOc-A`$gqGmhR}|J;I1PHW_rIlx@M#H64+NIBgns@NRsUzqSWP9n-_QME$1C&P zM_ksH7Ms5YIi?Ea~6dvQ(LS zFLjxvTs`M?G?$&&r?aGir%!BhYf6I*mN`N{w4{YKQd`RCqK3LIjn?)i9~!m091-sf z2dsrYVJ3An=3Dcone2=BSHr4nRfm1R*`p8HLEQTWh2KvFe)YRmJz7icb;!MYlQVT! zFiYOXcw#={y3C!-QJFHS+L*QxW_eADozlIa(L_{D<&Wf{`yswQnW=u_TCFarpmd;t z;pP>^-Zq%3^W{&9+-ZX}@9EjV+mJQs@rfsCUrgR67@fB*tP)Eh*k4f}gBdj6s<-)a zK_zkati3I2X$j}CJB<~MbKEvDPBxF`!bN21PeyYe$lP)981y`C9~>~sm6j&6%Kzh} z3!sr(a@@#I!n=Lo$jFCEtds8xVI~1A{2OlTrCzXKom&e5Js9-9{Tte@+#-lbIR*i^f9+*3#n3-4kYD=?09yIzOy zQg@}xINP^^IAcq-Sa-m-{NFkR-l|#X%hG|(6=vfjO#L}cFXoGS?uIElCpx$nOS)Y? zEq#ou;C?B7RT03(5@L?L2@sj{c@%XfyxF`$*#dV$*KC(Q+WDA1@8iQW0zFrD#-!!l zHLhbw4v$#7^`o0TJ$vp&D@iH>zue{beU^O0>A}KSD8E4Paed&q7uEx@b$1ibWH}_I zBk^W$m-{vzSF(g>zhJvDw#8-Hqu(5Psyi{RkGi*d?PU+a&uY>5qSNj{dzk5_@YAjj z(}Q~l+sW(r{J{H!jicmluDz{zl|OD2HY^1MWA_(i)J$L%qn_^NLy{+Z!d6-q>crQ9 zuLh0r(1+$Mt?-u@L$QMO7Ak7j)dbgvBO`O&GUXfJZ(le*EafhPo(}5}6hK9@-}u(Z z=PV`_bJDlH0JaC;?^L^!qi%O@O6ktb1?l-CSG6J>kN8UsI#QZkRfK#;=Okv-qcc-= zP0yQB8t+usI=?RFHwU{g`Bw}bTuhMqRCFr5{hVt4O>LcKx-+Q6oc=sQ({&`oCi$t{ z?z^1Hec)rE&V=E~JY_Wklf>O7{kvLetk<$ghGNA72ei(DuFzmCr?2+f2MLhY&aeJA zZ;nfzo<~hmUnj+(#rC}yw%;I+P2YOnh3R7bsj&A;yy1}-}KA@Ol((&`V zW{fT&dzgX}%ux!9ws+Y5tXh_-n_Yi2g6kv)XzD5%`F=CWS0!+WPss3N} zQvt=r@P1S4^x7|9ruSL1j6BN40KJu=S{V_kMd+q-629e%HU2d&*R~q&*X%G<|AQ!U z{^PH5IhJeBCxlJGI=~sZlY$svRPKgyBov5Xd3!HirUM^d`oISxtbJtV!Mo1A7+Tv^ znt~kD`4v_G&$!6|MqBghC-vM|eGza~Z{56IhRsGF(gkC*6s5-dy%#%HOZ^q8H*7I| zP5XgL#D&(C#fZ*WBlqnFJvBq=gzT6aTdp;_JB@?V_Q?(6^u;@zyxkUY03P?` z%5XS&cPEcq}VfuR~bvUcc#tt;(9ibRa1&B>4ClW!hWe3;xpy^6oUGV zPt3s2**vqvD9ifS7JiCqV)7ePmNON*3pS}s54gdwaa2EAXM7~Z^zzLu4sL~KcYIMy z3$7!GH%K_PbG>@VGJ2La3~yMMT17w9X*s71`o=%;LD4F>9l3r7(1FGkMX4TSU4s@5 z57fLa^wmmxr$q{|6e4PiX)E literal 0 HcmV?d00001 From 558952c5408833fe0efaa6adf3a2a909b672de94 Mon Sep 17 00:00:00 2001 From: Fabio Date: Fri, 10 Apr 2020 19:24:34 +0200 Subject: [PATCH 0343/1189] Fix bledetect icon --- apps/bledetect/bledetect-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bledetect/bledetect-icon.js b/apps/bledetect/bledetect-icon.js index a15e13307..70b90cd42 100644 --- a/apps/bledetect/bledetect-icon.js +++ b/apps/bledetect/bledetect-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("AAAAAAAACIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAiIgIiIiAAAAAAAAAAAAAAAAAAAAAAAAAiIgAiIiIAAAAAAAAAAAAAAAAAIAAAAAAiIgACIiIgAAAAAAAAAAAAAAAiIiAAAAAiIgAAAiIiIAAAAAAAAAAAAAAiIiIAAAAiIgAAACIiIgAAAAAAAAAAAAACIiIgAAAiIgAAAAIiIgAAAAAAAAAAAAAAIiIiAAAiIgAAAAIiIiAAAAAAAAAAAAAAAiIiIAAiIgAAACIiIgAAAAAAAAAAAAAAACIiIgAiIgAAAiIiIAAAAAAAAAAAAAAAAAIiIiIiIgACIiIiAAAAAAAAAAAAAAAAAAACIiIiIgAiIiIAAAAAAAAAAAAAAAAAAAAAIiIiIgIiIiAAAAAAAAAAAAAAAAAAAAAAAiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAACIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIiAAAAAAAAAIgAAAAAAAAAAAAAACIiIiIiIAAAAACIiIiIiAAAAAAAAAAAIiIiIiIiIgAAAAiIiIiIiIAAAAAAAAACIiIiIgIiIiAACIiIiIiIiIgAAAAAAAAiIiIiIgAiIiAACIiIiACIiIiAAAAAAAIiIiAiIgAAIgAAiIiAAAAAiIiIAAAAACIiIgAiIgAAAAAIiIgAAAAAAIiIAAAAAiIiIAAiIgAAAAAIiIAAAAAAAEiIgAAAIiIiAAAiIgAAAAAIiIAAAAAAAAiIgAAiIiIgAAAiIgAAAAAIiIAAAAAAAAiIgAAiIiAAAAAiIgAAAACIiAAAAAAAAAiIgAAiIgAAAAAiIgAAAACIiAAAAAAAAAiIgAAAAAAAAAAiIgAAAAAIiIAAAAAAAAiIgAAAAAAAAAAiIgAiIAAIiIAAAAAAAAiIgAAAAAAAAAAiIgIiIgAIiIgAAAAAAIiIgAAAAAAAAAAiIiIiIgAIiIgAAAAACIiIAAAAAAAAAAAiIiIiIAAAiIiIAAAAiIiIAAAAAAAAAAAiIiIgAAAACIiIiIiIiIiIAAAAAAAAAAAiIiIAAAAAAIiIiIiIiIiIgAAAAAAAAAAiIiAAAAAAAAiIiIiIiIiIiAAAAAAAAAAiIgAAAAAAAAAIiIiIgACIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIi")) \ No newline at end of file +require("heatshrink").decompress(atob("MDCEAAAAAAAAAAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAIiICIiIgAAAAAAAAAAAAAAAAAAAAAAAAIiIAIiIiAAAAAAAAAAAAAAAAACAAAAAAIiIAAiIiIAAAAAAAAAAAAAAAIiIgAAAAIiIAAAIiIiAAAAAAAAAAAAAAIiIiAAAAIiIAAAAiIiIAAAAAAAAAAAAAAiIiIAAAIiIAAAACIiIAAAAAAAAAAAAAACIiIgAAIiIAAAACIiIgAAAAAAAAAAAAAAIiIiAAIiIAAAAiIiIAAAAAAAAAAAAAAAAiIiIAIiIAAAIiIiAAAAAAAAAAAAAAAAACIiIiIiIAAiIiIgAAAAAAAAAAAAAAAAAAAiIiIiIAIiIiAAAAAAAAAAAAAAAAAAAAACIiIiICIiIgAAAAAAAAAAAAAAAAAAAAAAIiIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAACIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAACIiIiIgAAAAAAAACIAAAAAAAAAAAAAAAiIiIiIiAAAAAAiIiIiIgAAAAAAAAAACIiIiIiIiIAAAAIiIiIiIiAAAAAAAAAAiIiIiICIiIgAAiIiIiIiIiIAAAAAAAAIiIiIiIAIiIgAAiIiIgAiIiIgAAAAAACIiIgIiIAACIAAIiIgAAAAIiIiAAAAAAiIiIAIiIAAAAACIiIAAAAAACIiAAAAAIiIiAAIiIAAAAACIiAAAAAAABIiIAAACIiIgAAIiIAAAAACIiAAAAAAAAIiIAAIiIiIAAAIiIAAAAACIiAAAAAAAAIiIAAIiIgAAAAIiIAAAAAiIgAAAAAAAAIiIAAIiIAAAAAIiIAAAAAiIgAAAAAAAAIiIAAAAAAAAAAIiIAAAAACIiAAAAAAAAIiIAAAAAAAAAAIiIAIiAACIiAAAAAAAAIiIAAAAAAAAAAIiICIiIACIiIAAAAAACIiIAAAAAAAAAAIiIiIiIACIiIAAAAAAiIiAAAAAAAAAAAIiIiIiAAAIiIiAAAAIiIiAAAAAAAAAAAIiIiIAAAAAiIiIiIiIiIiAAAAAAAAAAAIiIiAAAAAACIiIiIiIiIiIAAAAAAAAAAIiIgAAAAAAAIiIiIiIiIiIgAAAAAAAAAIiIAAAAAAAAACIiIiIAAiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIg==")) From 8d8befd5ec33d95f5333232c098ddd96bca74999 Mon Sep 17 00:00:00 2001 From: Fabio Date: Fri, 10 Apr 2020 19:35:34 +0200 Subject: [PATCH 0344/1189] Finally fixed icon for bledetect --- apps.json | 2 +- apps/bledetect/bledetect-icon.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 8e4e2555a..9071c269f 100644 --- a/apps.json +++ b/apps.json @@ -1161,7 +1161,7 @@ }, { "id": "bledetect", "name": "BLE Detector", - "shortName":"BLEDetector", + "shortName":"BLE Detector", "icon": "bledetect.png", "version":"0.01", "description": "Detect BLE devices and show some informations.", diff --git a/apps/bledetect/bledetect-icon.js b/apps/bledetect/bledetect-icon.js index 70b90cd42..8c605889a 100644 --- a/apps/bledetect/bledetect-icon.js +++ b/apps/bledetect/bledetect-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("MDCEAAAAAAAAAAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAIiICIiIgAAAAAAAAAAAAAAAAAAAAAAAAIiIAIiIiAAAAAAAAAAAAAAAAACAAAAAAIiIAAiIiIAAAAAAAAAAAAAAAIiIgAAAAIiIAAAIiIiAAAAAAAAAAAAAAIiIiAAAAIiIAAAAiIiIAAAAAAAAAAAAAAiIiIAAAIiIAAAACIiIAAAAAAAAAAAAAACIiIgAAIiIAAAACIiIgAAAAAAAAAAAAAAIiIiAAIiIAAAAiIiIAAAAAAAAAAAAAAAAiIiIAIiIAAAIiIiAAAAAAAAAAAAAAAAACIiIiIiIAAiIiIgAAAAAAAAAAAAAAAAAAAiIiIiIAIiIiAAAAAAAAAAAAAAAAAAAAACIiIiICIiIgAAAAAAAAAAAAAAAAAAAAAAIiIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAACIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiIAAAAAAAAAAAAAAAAAAAAAAAAAACIiIiIgAAAAAAAACIAAAAAAAAAAAAAAAiIiIiIiAAAAAAiIiIiIgAAAAAAAAAACIiIiIiIiIAAAAIiIiIiIiAAAAAAAAAAiIiIiICIiIgAAiIiIiIiIiIAAAAAAAAIiIiIiIAIiIgAAiIiIgAiIiIgAAAAAACIiIgIiIAACIAAIiIgAAAAIiIiAAAAAAiIiIAIiIAAAAACIiIAAAAAACIiAAAAAIiIiAAIiIAAAAACIiAAAAAAABIiIAAACIiIgAAIiIAAAAACIiAAAAAAAAIiIAAIiIiIAAAIiIAAAAACIiAAAAAAAAIiIAAIiIgAAAAIiIAAAAAiIgAAAAAAAAIiIAAIiIAAAAAIiIAAAAAiIgAAAAAAAAIiIAAAAAAAAAAIiIAAAAACIiAAAAAAAAIiIAAAAAAAAAAIiIAIiAACIiAAAAAAAAIiIAAAAAAAAAAIiICIiIACIiIAAAAAACIiIAAAAAAAAAAIiIiIiIACIiIAAAAAAiIiAAAAAAAAAAAIiIiIiAAAIiIiAAAAIiIiAAAAAAAAAAAIiIiIAAAAAiIiIiIiIiIiAAAAAAAAAAAIiIiAAAAAACIiIiIiIiIiIAAAAAAAAAAIiIgAAAAAAAIiIiIiIiIiIgAAAAAAAAAIiIAAAAAAAAACIiIiIAAiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIg==")) +require("heatshrink").decompress(atob("oFAwgLIhGIFbuIxGAD7xAdD4RAcD4QgcD4ZhbD4hAaD4hAaD4pAZDYRAcD4UIEDZbDMKY0BD5IgES6IfJMIZAOCI4GFICIRHD4pARCI5GIICwfYIAxfXGQr7DT6ozFCgLfXKg4YDFIoARCwZjFHyZhGDIJdVIBJdWIBA+YIBIeWIA4eXEAxdXD44eZQAw+dMBEiAAUgX7IeDAAT/XDwxBLDYpAFgQfHIBI+FwAGDHxJAJThAICHwpFGLpQECPYQDCDAYUDA4ZAFHwYXBbg4WIEAQIFSwofKKwwJGHwofHGpAfIHwofSBQQ+JD5T1HBQoeGD6pKCLoofbW4ofXDAINFP64AHD4ZqCX6AfKZQT/SD5LKECpIfPAAYVKJJQfLCxAoCD6DCCD4QXEAwReLD4jhEDAYAGH553HABAfNHwhAXHw5AJA4b/MBQ4gFYJ0IDxAhEE47CLACDCOACBAjD7hACD7hABkAA=")) \ No newline at end of file From a95a396ac1cd20630848ef92baaa9db5a520a29a Mon Sep 17 00:00:00 2001 From: Fabio Date: Fri, 10 Apr 2020 19:43:10 +0200 Subject: [PATCH 0345/1189] Resized icon bledetect --- apps/bledetect/bledetect-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bledetect/bledetect-icon.js b/apps/bledetect/bledetect-icon.js index 8c605889a..2e49b3d0a 100644 --- a/apps/bledetect/bledetect-icon.js +++ b/apps/bledetect/bledetect-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFAwgLIhGIFbuIxGAD7xAdD4RAcD4QgcD4ZhbD4hAaD4hAaD4pAZDYRAcD4UIEDZbDMKY0BD5IgES6IfJMIZAOCI4GFICIRHD4pARCI5GIICwfYIAxfXGQr7DT6ozFCgLfXKg4YDFIoARCwZjFHyZhGDIJdVIBJdWIBA+YIBIeWIA4eXEAxdXD44eZQAw+dMBEiAAUgX7IeDAAT/XDwxBLDYpAFgQfHIBI+FwAGDHxJAJThAICHwpFGLpQECPYQDCDAYUDA4ZAFHwYXBbg4WIEAQIFSwofKKwwJGHwofHGpAfIHwofSBQQ+JD5T1HBQoeGD6pKCLoofbW4ofXDAINFP64AHD4ZqCX6AfKZQT/SD5LKECpIfPAAYVKJJQfLCxAoCD6DCCD4QXEAwReLD4jhEDAYAGH553HABAfNHwhAXHw5AJA4b/MBQ4gFYJ0IDxAhEE47CLACDCOACBAjD7hACD7hABkAA=")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwgJGhGAEKuIxAXXGCoXBGCoXCDCgXDJKYXDGCYUBhAwUFgQwPEogTCGBwNFFYYYNHwoEGJJQlFCIgKCdR4XHJBQNEI6IOFO6IPEDQYGDahoYEa6BJFxBFPJJIuQGAouRGAoWSGAgXTSIoAEgUgL6cCkQACDJCOFGAYWDAAJFLX4gWFGA4sFC40gJQYuHwBEDAQISCMYowEFgoJDCAwYBAwZYEC45AEgIHERAgXMA4i4FC6bPDC4hXFC5B7FC57CHI54XIawgXRVwS/JC5SuDC4wGGC45HBFAQRCAooXIVwYRBAAoXLLIwAFC5IuDGCIuFDAyQLABphKABgwaC6owB")) \ No newline at end of file From d843210ed09194875e64cc2c3b138f9b9ee5f1e2 Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Fri, 10 Apr 2020 22:32:09 +0200 Subject: [PATCH 0346/1189] add numerals clock --- apps.json | 15 +++++ apps/numerals/README.md | 17 ++++++ apps/numerals/numerals-icon.js | 1 + apps/numerals/numerals.app.js | 93 +++++++++++++++++++++++++++++ apps/numerals/numerals.png | Bin 0 -> 1173 bytes apps/numerals/numerals.settings.js | 33 ++++++++++ 6 files changed, 159 insertions(+) create mode 100644 apps/numerals/README.md create mode 100644 apps/numerals/numerals-icon.js create mode 100644 apps/numerals/numerals.app.js create mode 100644 apps/numerals/numerals.png create mode 100644 apps/numerals/numerals.settings.js diff --git a/apps.json b/apps.json index d85739aad..1f05142f5 100644 --- a/apps.json +++ b/apps.json @@ -1158,5 +1158,20 @@ {"name":"batchart.app.js","url":"app.js"}, {"name":"batchart.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "numerals", + "name": "Numerals Clock", + "shortName": "Numerals Clock", + "icon": "numerals.png", + "version":"0.01", + "description": "A simple big numerals clock", + "tags": "numerals,clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"numerals.app.js","url":"numerals.app.js"}, + {"name":"numerals.img","url":"numerals-icon.js","evaluate":true}, + {"name":"numerals.settings.js","url":"numerals.settings.js"} + ] } ] diff --git a/apps/numerals/README.md b/apps/numerals/README.md new file mode 100644 index 000000000..01d784ef8 --- /dev/null +++ b/apps/numerals/README.md @@ -0,0 +1,17 @@ +# Numerals Clock + +This is a simple big numerals clock. +Settings can be accessed through the app/widget settings menu of the Bangle.js + +## Settings available + +### color: +* rnd - shows numerals in different color combinations every time the watches wakes +* r/g - red/green +* y/w - yellow/white +* o/c - orange/cyan +* b/y - blue/yellow'ish + +### draw mode +* fill - fill numerals +* frame - only shows outline of numerals diff --git a/apps/numerals/numerals-icon.js b/apps/numerals/numerals-icon.js new file mode 100644 index 000000000..7e471fb0d --- /dev/null +++ b/apps/numerals/numerals-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/ABMBzIADyAJIAAkQBoMZBIoXCBIwADyIkIGAIuKGAQkIBJIwEEKQANC/4XWR58RiIHFWpAXFe4QRFcpAXFewQRFcxAXEFwQwGA4QXKiAXDGAgX/C/4X/C/4X/C7uQCwcBBwYXNBwYuEC54wCFwgXPzMRiIHFC54AHC/4XiCAoXRhIHDyK3GAAwOBJA0QG45VGC4YwCD4YwKFwgABcgIfEAwIAHBwgA/AAgA==")) \ No newline at end of file diff --git a/apps/numerals/numerals.app.js b/apps/numerals/numerals.app.js new file mode 100644 index 000000000..648a1005a --- /dev/null +++ b/apps/numerals/numerals.app.js @@ -0,0 +1,93 @@ +/** + * Bangle.js Numerals Clock + * + * + Original Author: Raik M. https://github.com/ps-igel + * + Created: April 2020 + * + see README.md for details + */ + +var numerals = { + 0:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,9,9,1],[30,21,61,21,69,29,69,61,61,69,30,69,22,61,22,29,30,21]], + 1:[[59,1,82,1,90,9,90,82,82,90,73,90,65,82,65,27,59,27,51,19,51,9,59,1]], + 2:[[9,1,82,1,90,9,90,47,82,55,21,55,21,64,82,64,90,72,90,82,82,90,9,90,1,82,1,43,9,35,70,35,70,25,9,25,1,17,1,9,9,1]], + 3:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,74,9,66,70,66,70,57,9,57,1,49,1,41,9,33,70,33,70,25,9,25,1,17,1,9,9,1]], + 4:[[9,1,14,1,22,9,22,34,69,34,69,9,77,1,82,1,90,9,90,82,82,90,78,90,70,82,70,55,9,55,1,47,1,9,9,1]], + 5:[[9,1,82,1,90,9,90,17,82,25,21,25,21,35,82,35,90,43,90,82,82,90,9,90,1,82,1,72,9,64,71,64,71,55,9,55,1,47,1,9,9,1]], + 6:[[9,1,82,1,90,9,90,14,82,22,22,22,22,36,82,36,90,44,90,82,82,90,9,90,1,82,1,9,9,1],[22,55,69,55,69,69,22,69,22,55]], + 7:[[9,1,82,1,90,9,90,15,15,90,9,90,1,82,1,76,54,23,9,23,1,15,1,9,9,1]], + 8:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,9,9,1],[22,22,69,22,69,36,22,36,22,22],[22,55,69,55,69,69,22,69,22,55]], + 9:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,77,9,69,69,69,69,55,9,55,1,47,1,9,9,1],[22,22,69,22,69,36,22,36,22,22]], +}; +var _hCol = ["#ff5555","#ffff00","#FF9901","#2F00FF"]; +var _mCol = ["#55ff55","#ffffff","#00EFEF","#FFBF00"]; +var _rCol = 0; +var interval = 0; +const REFRESH_RATE = 10E3; + +function translate(tx, ty, p) { + return p.map((x, i)=> x+((i%2)?ty:tx)); +} + +function fill(poly){ + return g.fillPoly(poly); +} + +function frame(poly){ + return g.drawPoly(poly); +} + +let settings = require('Storage').readJSON('numerals.json',1); +if (!settings) { + settings = { + color: 0, + drawMode: "fill" + }; +} + +function drawNum(num,col,x,y,func){ + g.setColor(col); + let tx = x*100+35; + let ty = y*100+35; + for (let i=0;i0) g.setColor((func==fill)?"#000000":col); + func(translate(tx, ty,numerals[num][i])); + } +} + +function draw(drawMode){ + let d = new Date(); + let h1 = Math.floor(d.getHours()/10); + let h2 = d.getHours()%10; + let m1 = Math.floor(d.getMinutes()/10); + let m2 = d.getMinutes()%10; + g.clearRect(0,24,240,240); + drawNum(h1,_hCol[_rCol],0,0,eval(drawMode)); + drawNum(h2,_hCol[_rCol],1,0,eval(drawMode)); + drawNum(m1,_mCol[_rCol],0,1,eval(drawMode)); + drawNum(m2,_mCol[_rCol],1,1,eval(drawMode)); +} + +Bangle.setLCDMode(); + +clearWatch(); +setWatch(Bangle.showLauncher, BTN1, {repeat:false,edge:"falling"}); + +g.clear(); +clearInterval(); +if (settings.color>0) _rCol=settings.color-1; +interval=setInterval(draw, REFRESH_RATE, settings.drawMode); +draw(settings.drawMode); + +Bangle.on('lcdPower', function(on) { + if (on) { + if (settings.color==0) _rCol = Math.floor(Math.random()*_hCol.length); + draw(settings.drawMode); + interval=setInterval(draw, REFRESH_RATE, settings.drawMode); + }else + { + clearInterval(interval); + } +}); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/numerals/numerals.png b/apps/numerals/numerals.png new file mode 100644 index 0000000000000000000000000000000000000000..c181e2e0dfc32596174d6c94480a6f92a101e20d GIT binary patch literal 1173 zcmV;G1Zw+EX>4Tx04R}tkv&MmKpe$i(@Iq;4t5Z6$WUFhAS&W0RV;#q(pG5I!Q|2}Xws0R zxHt-~1qVMCs}3&Cx;nTDg5U>;lcSTOi5bWxZD8-pLEHP9LY~pC=`JAGy0|+FmMa>uDQLn_Hp_EWT>m<8{ps& z7%fuvy2rb_JA3>0Osl^iO2u-QrwyT@00006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB600N~+L_t(&-tF1TYZO@+#^I;Rj;%XUaA*DnM_qYCM8{!7W-&}7 zZq!9gyrOFb2bDONC<@aHr-KW3O0PtM7jU5nf=X0GH|oL&qM&XyLptT6PfQy-rlQ@Q zIMfSGS5chryuYfi&iU#bGEJ?b+LNSEn0$b8dE9GX6K}G8Mq@hLhfWNqi1QE|#{&rQ zW}^@D8{|Dk2`66^%cB6Hv)%Y-k^%d$VJt+5m&Z*kYQjUO9GNd<$j&CpzKjS=pMJ1%o%_f_NQk0X#=xso-U$8bD?`VPf5%tCm z3|0yML#-S}W8b;{7Xa_SXMh}*hEZeI6!d=@SL(b=CCp6=a1YCIBMgD9Qc0p~@N9Jw ztW@~(D2E>v;5Pa(Z^9G`vuHn7v@o4Y+I3m!6Z1z7eXMf^uo$mXy~H&TD{%~e<9^f9 zCefvx!Chs;!*n01njcfF4PXi0Oq4>kjqc!1C=X+pX(k~VPp5`T2puQ-!JVE|ik zVcHI(QACn_v22dAi7W%i05X6KAOpw%GJp(VngUcR5urp4MXHe|EkoujRdzj}yc ziZ4H!zdMonsRV$7Vl(oa3YVxZWfwg^SWb{!hC2lv^XH^-a*PL)MzS_Ct{jd^FDpg+Y<{TeBj n$x|xAHL;ift}V-ysR8-`u%*0+fO-J!00000NkvXXu0mjfBikB4 literal 0 HcmV?d00001 diff --git a/apps/numerals/numerals.settings.js b/apps/numerals/numerals.settings.js new file mode 100644 index 000000000..f9c417da6 --- /dev/null +++ b/apps/numerals/numerals.settings.js @@ -0,0 +1,33 @@ +(function(back) { + function updateSettings() { + storage.write('numerals.json', numeralsSettings); + }; + function resetSettings() { + numeralsSettings = { + color: 0, + drawMode: "fill" + }; + updateSettings(); + } + let numeralsSettings = storage.readJSON('numerals.json',1); + if (!numeralsSettings) resetSettings(); + let dm = ["fill","frame"]; + let col = ["rnd","r/g","y/w","o/c","b/y"] + var menu={ + "" : { "title":"Numerals"}, + "Colors": { + value: 0|numeralsSettings.color, + min:0,max:4, + format: v=>col[v], + onchange: v=> { numeralsSettings.color=v; updateSettings();} + }, + "Draw mode": { + value: 0|dm.indexOf(numeralsSettings.drawMode), + min:0,max:1, + format: v=>dm[v], + onchange: v=> { numeralsSettings.drawMode=dm[v]; updateSettings();} + }, + "< back": back + }; + E.showMenu(menu); +}) \ No newline at end of file From 86ad563bc2f4d8ec23aa3e8e3c8ac25590f3bda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bov=C3=A9?= Date: Fri, 10 Apr 2020 23:03:59 +0200 Subject: [PATCH 0347/1189] Fixes jbmb8 apps entry --- apps.json | 47 +++--------------------------- apps/_example_app/add_to_apps.json | 1 - apps/jbm8b/Changelog | 3 +- apps/jbm8b/add_to_apps.json | 18 +++--------- 4 files changed, 10 insertions(+), 59 deletions(-) diff --git a/apps.json b/apps.json index c14fda261..a82da04d2 100644 --- a/apps.json +++ b/apps.json @@ -1434,54 +1434,15 @@ { "id": "jbm8b", "name": "Magic 8 Ball", + "shortName": "Magic 8 Ball", "icon": "app.png", "description": "A simple fortune telling app", "tags": "game", "storage": [ - { - "name": "+jbm8b", - "url": "app.json" - }, - { - "name": "-jbm8b", - "url": "app.js" - }, - { - "name": "*jbm8b", - "url": "app-icon.js", - "evaluate": true - } + { "name": "jbm8b.app.js", "url": "app.js" }, + { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } ], - "allow_emulator": true, - "type": "app", - "version": "0.02", - "sortorder": -9 - }, - { - "id": "jbb", - "name": "Battery Level", - "icon": "app.png", - "description": "Battery status and charging indicator", - "tags": "tool", - "storage": [ - { - "name": "+jbb", - "url": "app.json" - }, - { - "name": "-jbb", - "url": "app.js" - }, - { - "name": "*jbb", - "url": "app-icon.js", - "evaluate": true - } - ], - "allow_emulator": true, - "type": "app", - "version": "0.02", - "sortorder": -9 + "version": "0.03" }, { "id": "flagrse", diff --git a/apps/_example_app/add_to_apps.json b/apps/_example_app/add_to_apps.json index ca75a7bd8..dd66030b6 100644 --- a/apps/_example_app/add_to_apps.json +++ b/apps/_example_app/add_to_apps.json @@ -1,4 +1,3 @@ -// Create an entry in apps.json as follows: { "id": "7chname", "name": "My app's human readable name", "shortName":"Short Name", diff --git a/apps/jbm8b/Changelog b/apps/jbm8b/Changelog index bd71ffcd5..80d7de1d6 100644 --- a/apps/jbm8b/Changelog +++ b/apps/jbm8b/Changelog @@ -1,2 +1,3 @@ 0.01: First working version -0.02: Added delay in replying for dramatic effect \ No newline at end of file +0.02: Added delay in replying for dramatic effect +0.03: Fixed apps.json entry diff --git a/apps/jbm8b/add_to_apps.json b/apps/jbm8b/add_to_apps.json index 200ea5f65..8e28639e7 100644 --- a/apps/jbm8b/add_to_apps.json +++ b/apps/jbm8b/add_to_apps.json @@ -1,23 +1,13 @@ { "id": "jbm8b", "name": "Magic 8 Ball", + "shortName": "Magic 8 Ball", "icon": "app.png", "description": "A simple fortune telling app", "tags": "game", "storage": [ - { - "name": "+jbm8b", - "url": "app.json" - }, - { - "name": "-jbm8b", - "url": "app.js" - }, - { - "name": "*jbm8b", - "url": "app-icon.js", - "evaluate": true - } + { "name": "jbm8b.app.js", "url": "app.js" }, + { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } ], - "version": "0.02" + "version": "0.03" } \ No newline at end of file From 20ad2efbd4cf5b66b368e792826d0f7b631bf128 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 11 Apr 2020 01:52:27 +0100 Subject: [PATCH 0348/1189] In night mode, further left swipes reduce the screen brightness (3 levels) until returning to day-mode --- apps.json | 2 +- apps/marioclock/ChangeLog | 3 ++- apps/marioclock/README.md | 2 +- apps/marioclock/marioclock-app.js | 16 ++++++++++++++-- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 0271c244d..293a709c7 100644 --- a/apps.json +++ b/apps.json @@ -914,7 +914,7 @@ { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.09", + "version":"0.10", "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", "tags": "clock,mario,retro", "type": "clock", diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index acce6a7ed..b4a4c7af9 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -6,4 +6,5 @@ 0.06: Performance refactor, and enhanced graphics! 0.07: Swipe right to change between Mario and Toad characters, swipe left to toggle night mode 0.08: Update date panel to be info panel toggling between Date, Battery and Temperature. Add Princes Daisy -0.09: Add GadgetBridge functionality. Mario shows message type in speach bubble, while message scrolls in info panel \ No newline at end of file +0.09: Add GadgetBridge functionality. Mario shows message type in speach bubble, while message scrolls in info panel +0.10: Swiping left to enable night-mode now also reduces LCD brightness through 3 levels before returning to day-mode. \ No newline at end of file diff --git a/apps/marioclock/README.md b/apps/marioclock/README.md index e6aeaa1bb..25276a351 100644 --- a/apps/marioclock/README.md +++ b/apps/marioclock/README.md @@ -8,7 +8,7 @@ Enjoy watching Mario, or one of the other game characters run through a level wh ## Features * Multiple characters - swipe the screen right to change the character between `Mario`, `Toad`, and `Daisy` -* Night and Day modes - swipe left to toggle mode +* Night and Day modes - swipe left to enter night mode, with 3 levels of darkness before returning to day mode. * Smooth animation * Awesome 8-bit style grey-scale graphics * Mario jumps to change the time, every minute diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index 529f1c95b..e213c2498 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -16,6 +16,8 @@ const is12Hour = settings["12hour"] || false; // Screen dimensions let W, H; +// Screen brightness +let brightness = 1; let intervalRef, displayTimeoutRef = null; @@ -164,7 +166,17 @@ function switchCharacter() { } function toggleNightMode() { - nightMode = !nightMode; + if (!nightMode) { + nightMode = true; + return; + } + + brightness -= 0.30; + if (brightness <= 0) { + brightness = 1; + nightMode = false; + } + Bangle.setLCDBrightness(brightness); } function incrementTimer() { @@ -625,4 +637,4 @@ function init() { } // Initialise! -init() \ No newline at end of file +init(); \ No newline at end of file From cab228f47e79ec1872653dc6a29ac6ed5c4bbe8b Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 11 Apr 2020 10:47:01 +0100 Subject: [PATCH 0349/1189] Persist user settings --- apps.json | 2 +- apps/marioclock/ChangeLog | 3 ++- apps/marioclock/marioclock-app.js | 35 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 293a709c7..73a093a2c 100644 --- a/apps.json +++ b/apps.json @@ -914,7 +914,7 @@ { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.10", + "version":"0.11", "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", "tags": "clock,mario,retro", "type": "clock", diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index b4a4c7af9..6f3c79504 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -7,4 +7,5 @@ 0.07: Swipe right to change between Mario and Toad characters, swipe left to toggle night mode 0.08: Update date panel to be info panel toggling between Date, Battery and Temperature. Add Princes Daisy 0.09: Add GadgetBridge functionality. Mario shows message type in speach bubble, while message scrolls in info panel -0.10: Swiping left to enable night-mode now also reduces LCD brightness through 3 levels before returning to day-mode. \ No newline at end of file +0.10: Swiping left to enable night-mode now also reduces LCD brightness through 3 levels before returning to day-mode. +0.11: User settings persisted and read to file. \ No newline at end of file diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index e213c2498..eb9632c59 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -81,6 +81,16 @@ const phone = { messageType: null, }; +const SETTINGS_FILE = "marioclock.json"; + +function readSettings() { + return require('Storage').readJSON(SETTINGS_FILE, 1) || {}; +} + +function writeSettings(newSettings) { + require("Storage").writeJSON(SETTINGS_FILE, newSettings); +} + function phoneOutbound(msg) { Bluetooth.println(JSON.stringify(msg)); } @@ -567,8 +577,31 @@ function startTimers(){ redraw(); } +function loadSettings() { + const settings = readSettings(); + if (!settings) return; + + if (settings.character) characterSprite.character = settings.character; + if (settings.nightMode) nightMode = settings.nightMode; + if (settings.brightness) { + brightness = settings.brightness; + Bangle.setLCDBrightness(brightness); + } +} + +function updateSettings() { + const newSettings = { + character: characterSprite.character, + nightMode: nightMode, + brightness: brightness, + }; + writeSettings(newSettings); +} + // Main function init() { + loadSettings(); + clearInterval(); // Initialise display @@ -618,6 +651,8 @@ function init() { default: toggleNightMode(); } + + updateSettings(); }); // Phone connectivity From cf58c0eb5f93c27966a98e4c7cd97040e4ddf751 Mon Sep 17 00:00:00 2001 From: Fabio Date: Sat, 11 Apr 2020 13:03:45 +0200 Subject: [PATCH 0350/1189] bledetect fixed issue with wrong device informations --- apps/bledetect/ChangeLog | 3 ++- apps/bledetect/bledetect.js | 16 ++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/apps/bledetect/ChangeLog b/apps/bledetect/ChangeLog index 9352c7b96..cd5ce5845 100644 --- a/apps/bledetect/ChangeLog +++ b/apps/bledetect/ChangeLog @@ -1 +1,2 @@ -0.01: Initial Release \ No newline at end of file +0.01: Initial Release +0.02: Fixed issue with wrong device informations \ No newline at end of file diff --git a/apps/bledetect/bledetect.js b/apps/bledetect/bledetect.js index dde3ee9eb..6f5f5fa30 100644 --- a/apps/bledetect/bledetect.js +++ b/apps/bledetect/bledetect.js @@ -9,7 +9,6 @@ function showMainMenu() { } function showDeviceInfo(device){ - console.log(device); const deviceMenu = { "": { "title": "Device Info" }, "name": { @@ -24,13 +23,7 @@ function showDeviceInfo(device){ }; deviceMenu[device.id] = () => {}; - deviceMenu["< Back"] = () => scan(); - - /*for(let key in device){ - deviceMenu[key.substring(0,17)] = { - value: device[key.substring(0,17)] - }; - }*/ + deviceMenu["< Back"] = () => showMainMenu(); return E.showMenu(deviceMenu); } @@ -44,7 +37,7 @@ function scan() { waitMessage(); NRF.findDevices(devices => { - for (let device of devices) { + devices.forEach(device =>{ let deviceName = device.id.substring(0,17); if (device.name) { @@ -52,7 +45,7 @@ function scan() { } menu[deviceName] = () => showDeviceInfo(device); - } + }); showMainMenu(menu); }, { active: true }); } @@ -63,5 +56,4 @@ function waitMessage() { } scan(); -waitMessage(); - +waitMessage(); \ No newline at end of file From c368bcdb89f63925a85bb236c1c5f82152586e5f Mon Sep 17 00:00:00 2001 From: Fabio Di Stasio Date: Sat, 11 Apr 2020 13:26:02 +0200 Subject: [PATCH 0351/1189] Update app.json with bledetect new version. --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 9071c269f..fc60cb276 100644 --- a/apps.json +++ b/apps.json @@ -1163,7 +1163,7 @@ "name": "BLE Detector", "shortName":"BLE Detector", "icon": "bledetect.png", - "version":"0.01", + "version":"0.02", "description": "Detect BLE devices and show some informations.", "tags": "app,bluetooth,tool", "storage": [ From cffe04a54e41fce6be2fbcc11573769f2e03a2e9 Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Sat, 11 Apr 2020 15:37:40 +0200 Subject: [PATCH 0352/1189] add ChangeLog --- apps/numerals/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/numerals/ChangeLog diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog new file mode 100644 index 000000000..1dfcf61a6 --- /dev/null +++ b/apps/numerals/ChangeLog @@ -0,0 +1 @@ +0.01: new awesome clock \ No newline at end of file From fc801b29de7f1a0eb0d86cdc9d350f1b8841d38e Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Sat, 11 Apr 2020 18:22:48 +0200 Subject: [PATCH 0353/1189] update --- apps/numerals/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index 1dfcf61a6..5560f00bc 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -1 +1 @@ -0.01: new awesome clock \ No newline at end of file +0.01: New App! From 3f08eee070e36cdfcd8552f75ac55293d1700324 Mon Sep 17 00:00:00 2001 From: Fabio Date: Sat, 11 Apr 2020 21:04:16 +0200 Subject: [PATCH 0354/1189] Changelog update and README.md --- apps.json | 1 + apps/bledetect/ChangeLog | 2 +- apps/bledetect/README.md | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 apps/bledetect/README.md diff --git a/apps.json b/apps.json index fc60cb276..56a6b69d3 100644 --- a/apps.json +++ b/apps.json @@ -1166,6 +1166,7 @@ "version":"0.02", "description": "Detect BLE devices and show some informations.", "tags": "app,bluetooth,tool", + "readme": "README.md", "storage": [ {"name":"bledetect.app.js","url":"bledetect.js"}, {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} diff --git a/apps/bledetect/ChangeLog b/apps/bledetect/ChangeLog index cd5ce5845..520ccfa2f 100644 --- a/apps/bledetect/ChangeLog +++ b/apps/bledetect/ChangeLog @@ -1,2 +1,2 @@ -0.01: Initial Release +0.01: New App! 0.02: Fixed issue with wrong device informations \ No newline at end of file diff --git a/apps/bledetect/README.md b/apps/bledetect/README.md new file mode 100644 index 000000000..1f0c0a7a4 --- /dev/null +++ b/apps/bledetect/README.md @@ -0,0 +1,14 @@ +# BLE Detector + +BLE Detector it's an app born for testing purpose that aim to show as informations as possible about near BLE devices. + +## Features + +BLE Detector shows: + +- Device name (if available) +- Received Signal Strength Indication (RSSI) +- Manufacturer +- MAC Address + +More informations will coming with future versions. From 437b94d166c52a14e1cf748c4e3c0dbb0b888573 Mon Sep 17 00:00:00 2001 From: unmotivagedgene Date: Sat, 11 Apr 2020 14:53:52 -0500 Subject: [PATCH 0355/1189] Create changelog.txt --- apps/nato/changelog.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/nato/changelog.txt diff --git a/apps/nato/changelog.txt b/apps/nato/changelog.txt new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/nato/changelog.txt @@ -0,0 +1 @@ +0.01: New App! From da2c2dba593be534d3ef0c8c691746c02c99ae86 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 12 Apr 2020 01:11:47 +0200 Subject: [PATCH 0356/1189] Sanity check: fix warning about app without id, check for unknown keys --- bin/sanitycheck.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index a2c9dee9a..62b111ae0 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -37,7 +37,13 @@ try{ ERROR("apps.json not valid JSON"); } -apps.forEach((app,addIdx) => { +const APP_KEYS = [ + 'id', 'name', 'shortName', 'version', 'icon', 'description', 'tags', 'type', + 'sortorder', 'readme', 'custom', 'interface', 'storage', 'allow_emulator', +]; +const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate']; + +apps.forEach((app,appIdx) => { if (!app.id) ERROR(`App ${appIdx} has no id`); //console.log(`Checking ${app.id}...`); var appDir = APPSDIR+app.id+"/"; @@ -105,9 +111,15 @@ apps.forEach((app,addIdx) => { ERROR(`App ${app.id}'s ${file.name} is a JS file but isn't valid JS`); } } + for (const key in file) { + if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id}'s ${file.name} has unknown key ${key}`); + } }); //console.log(fileNames); if (isApp && !fileNames.includes(app.id+".app.js")) ERROR(`App ${app.id} has no entrypoint`); if (isApp && !fileNames.includes(app.id+".img")) ERROR(`App ${app.id} has no JS icon`); if (app.type=="widget" && !fileNames.includes(app.id+".wid.js")) ERROR(`Widget ${app.id} has no entrypoint`); + for (const key in app) { + if (!APP_KEYS.includes(key)) ERROR(`App ${app.id} has unknown key ${key}`); + } }); From f5246a4212dff6a7c18c640539ff261846ac2ca7 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 12 Apr 2020 01:29:57 +0200 Subject: [PATCH 0357/1189] Some minor settings fixes --- apps.json | 2 +- apps/setting/ChangeLog | 2 ++ apps/setting/settings.js | 14 +++++++------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index d85739aad..a8390b927 100644 --- a/apps.json +++ b/apps.json @@ -119,7 +119,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.12", + "version":"0.13", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 22277968c..3ca9dc3ec 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -12,3 +12,5 @@ 0.12: Fix memory leak (#206) Bring App settings nearer the top Move LCD Timeout to wakeup menu +0.13: Fix memory leak for App settings + Make capitalization more consistent diff --git a/apps/setting/settings.js b/apps/setting/settings.js index ac7692610..f1dc81ca9 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -64,7 +64,7 @@ function showMainMenu() { const mainmenu = { '': { 'title': 'Settings' }, 'Make Connectable': ()=>makeConnectable(), - 'App/widget settings': ()=>showAppSettingsMenu(), + 'App/Widget Settings': ()=>showAppSettingsMenu(), 'BLE': { value: settings.ble, format: boolFormat, @@ -81,7 +81,7 @@ function showMainMenu() { updateSettings(); } }, - 'Debug info': { + 'Debug Info': { value: settings.log, format: v => v ? "Show" : "Hide", onchange: () => { @@ -157,7 +157,7 @@ function showWakeUpMenu() { Bangle.setLCDTimeout(settings.timeout); } }, - 'Wake On BTN1': { + 'Wake on BTN1': { value: settings.options.wakeOnBTN1, format: boolFormat, onchange: () => { @@ -165,7 +165,7 @@ function showWakeUpMenu() { updateOptions(); } }, - 'Wake On BTN2': { + 'Wake on BTN2': { value: settings.options.wakeOnBTN2, format: boolFormat, onchange: () => { @@ -173,7 +173,7 @@ function showWakeUpMenu() { updateOptions(); } }, - 'Wake On BTN3': { + 'Wake on BTN3': { value: settings.options.wakeOnBTN3, format: boolFormat, onchange: () => { @@ -197,7 +197,7 @@ function showWakeUpMenu() { updateOptions(); } }, - 'Wake On Twist': { + 'Wake on Twist': { value: settings.options.wakeOnTwist, format: boolFormat, onchange: () => { @@ -450,7 +450,7 @@ function showAppSettings(app) { } try { // pass showAppSettingsMenu as "back" argument - appSettings(showAppSettingsMenu); + appSettings(()=>showAppSettingsMenu()); } catch (e) { console.log(`${app.name} settings error:`, e) return showError('Error in settings'); From eebc49470412d9cf93792df73156ee9ef12c4c3e Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 12 Apr 2020 13:32:25 +0200 Subject: [PATCH 0358/1189] Enables chart in the app --- apps/batchart/app.js | 107 ++++++++++++++++++++++++++++++++----- apps/batchart/batchart.dat | 0 apps/batchart/widget.js | 1 - 3 files changed, 95 insertions(+), 13 deletions(-) delete mode 100644 apps/batchart/batchart.dat diff --git a/apps/batchart/app.js b/apps/batchart/app.js index 684f9a88d..e8b30ba69 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -1,20 +1,100 @@ -// place your const, vars, functions or classes here +const GraphXZero = 40; +const GraphYZero = 180; +const GraphY100 = 80; +const GraphMarkerOffset = 5; +const MaxValueCount = 144; +const GraphXMax = GraphXZero + MaxValueCount; +var Storage = require("Storage"); -function renderBatteryChart(){ - g.drawString("t", 215, 175); - g.drawLine(40,190,40,80); +function renderCoordinateSystem() { + g.setFont("6x8", 1); + g.drawString("t", GraphXMax + GraphMarkerOffset, GraphYZero - GraphMarkerOffset); + g.drawLine(GraphXZero, GraphYZero + GraphMarkerOffset, GraphXZero, GraphY100); g.drawString("%", 39, 70); - g.drawString("100", 15, 75); - g.drawLine(35,80,40,80); - g.drawString("50", 20,125); - g.drawLine(35,130,40,130); + g.setFontAlign(1, -1, 0); + g.drawString("100", 30, GraphY100 - GraphMarkerOffset); + g.drawLine(GraphXZero - GraphMarkerOffset, GraphY100, GraphXZero, GraphY100); - g.drawString("0", 25, 175); - g.drawLine(35,180,210,180); + g.drawString("50", 30, GraphYZero - 50 - GraphMarkerOffset); + g.drawLine(GraphXZero - GraphMarkerOffset, 130, GraphXZero, 130); - g.drawString("Chart not yet functional", 60, 125); + g.drawString("0", 30, GraphYZero - GraphMarkerOffset); + g.drawLine(GraphXZero - GraphMarkerOffset, GraphYZero, GraphXMax, GraphYZero); +} + +function decrementDay(dayToDecrement) { + return dayToDecrement === 0 ? 6 : dayToDecrement-1; +} +function loadData() { + const MaxValueCount = 144; + const startingDay = new Date().getDay(); + + // Load data for the current day + var logFileName = "bclog" + startingDay; + + var dataLines = loadLinesFromFile(MaxValueCount, logFileName); + + // Top up to MaxValueCount from previous days as required + var previousDay = decrementDay(startingDay); + while (dataLines.length < MaxValueCount + && previousDay !== startingDay) { + + var topUpLogFileName = "bclog" + previousDay; + var remainingLines = MaxValueCount - dataLines.length; + var topUpLines = loadLinesFromFile(remainingLines, topUpLogFileName); + dataLines = topUpLines.concat(dataLines); + + previousDay = decrementDay(previousDay); + } + + return dataLines; +} + +function loadLinesFromFile(requestedLineCount, fileName) { + var allLines = []; + var returnLines = []; + + var readFile = Storage.open(fileName, "r"); + + while ((nextLine = readFile.readLine())) { + if(nextLine) { + allLines.push(nextLine); + } + } + + if (allLines.length <= 0) return; + + linesToReadCount = Math.min(requestedLineCount, allLines.length); + startingLineIndex = Math.max(0, allLines.length - requestedLineCount - 1); + + for (let i = startingLineIndex; i < linesToReadCount + startingLineIndex; i++) { + if(allLines[i]) { + returnLines.push(allLines[i]); + } + } + + allLines = null; + + return returnLines; +} + +function renderData(dataArray) { + g.setColor(1, 1, 0); + for (let i = 0; i < dataArray.length; i++) { + const element = dataArray[i]; + var dataInfo = element.split(","); + var batteryPercentage = parseInt(dataInfo[1]); + + g.setPixel(GraphXZero + i, GraphYZero - batteryPercentage); + } +} + +function renderBatteryChart() { + renderCoordinateSystem(); + var data = loadData(); + renderData(data); } // special function to handle display switch on @@ -22,7 +102,10 @@ Bangle.on('lcdPower', (on) => { if (on) { // call your app function here // If you clear the screen, do Bangle.drawWidgets(); - renderBatteryChart(); + //g.clear() + Bangle.loadWidgets(); + Bangle.drawWidgets(); + //renderBatteryChart(); } }); diff --git a/apps/batchart/batchart.dat b/apps/batchart/batchart.dat deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 2e2f43cdf..de7ce230d 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -60,7 +60,6 @@ } } - // Called by the heart app to reload settings and decide what's function reload() { WIDGETS["batchart"].width = 24; From 1a8a0d0a63b304fa0722447f73495d1ff6625731 Mon Sep 17 00:00:00 2001 From: Markus Date: Sun, 12 Apr 2020 14:06:12 +0200 Subject: [PATCH 0359/1189] Version for BatChart app updated --- apps.json | 2 +- apps/batchart/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index d85739aad..027abcb7c 100644 --- a/apps.json +++ b/apps.json @@ -1150,7 +1150,7 @@ "name": "Battery Chart", "shortName":"BatChart", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index 1b77ff82f..dcbd1687b 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -1,3 +1,4 @@ 0.01: New app and widget 0.02: Widget stores data to file (1 dataset/10min) 0.03: Rotate log files once a week. +0.04: chart in the app is now active. From 1c68ea0d1bbd6e16e12662e53876e7e723935190 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sun, 12 Apr 2020 14:43:52 +0100 Subject: [PATCH 0360/1189] Display info message when phone (dis)connectes and battery level <= 10% --- apps.json | 2 +- apps/marioclock/ChangeLog | 3 ++- apps/marioclock/marioclock-app.js | 30 +++++++++++++++++++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index 73a093a2c..6c7364a03 100644 --- a/apps.json +++ b/apps.json @@ -914,7 +914,7 @@ { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.11", + "version":"0.12", "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", "tags": "clock,mario,retro", "type": "clock", diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index 6f3c79504..69a3ccc7b 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -8,4 +8,5 @@ 0.08: Update date panel to be info panel toggling between Date, Battery and Temperature. Add Princes Daisy 0.09: Add GadgetBridge functionality. Mario shows message type in speach bubble, while message scrolls in info panel 0.10: Swiping left to enable night-mode now also reduces LCD brightness through 3 levels before returning to day-mode. -0.11: User settings persisted and read to file. \ No newline at end of file +0.11: User settings persisted and read to file. +0.12: Add info banner message when phone (dis)connects. Display low-battery warning (<=10%) \ No newline at end of file diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index eb9632c59..4acbf384b 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -346,16 +346,20 @@ function drawToadFrame(idx, x, y) { function drawNotice(x, y) { if (phone.message === null) return; + let img; switch (phone.messageType) { case "call": - const callImg = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INEw9cAAIPFBxAPEBw/WBxYACDrQ7QLI53OSpApDBoQAHB4INLByANNAwo=")); - g.drawImage(callImg, characterSprite.x, characterSprite.y - 16); + img = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INEw9cAAIPFBxAPEBw/WBxYACDrQ7QLI53OSpApDBoQAHB4INLByANNAwo=")); break; case "notify": - const msgImg = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INCrgAHB4QOEDQgOIAIQFGBwovDA4gOGFooOVLJR3OSpApDBoQAHB4INLByANNAwoA=")); - g.drawImage(msgImg, characterSprite.x, characterSprite.y - 16); + img = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INCrgAHB4QOEDQgOIAIQFGBwovDA4gOGFooOVLJR3OSpApDBoQAHB4INLByANNAwoA=")); + break; + case "lowBatt": + img = require("heatshrink").decompress(atob("h8PxH+AAMHABIND6wAJB4INFrgABB4oOEBoQPFBwwDGB0uHAAIOLJRB3OSpApDBoQAHB4INLByANNAwo")); break; } + + g.drawImage(img, characterSprite.x, characterSprite.y - 16); } function drawCharacter(date, character) { @@ -598,6 +602,14 @@ function updateSettings() { writeSettings(newSettings); } +function checkBatteryLevel() { + if (Bangle.isCharging()) return; + if (E.getBattery() > 10) return; + if (phone.message !== null) return; + + phoneNewMessage("lowBatt", "Warning, battery is low"); +} + // Main function init() { loadSettings(); @@ -658,17 +670,25 @@ function init() { // Phone connectivity try { NRF.wake(); } catch (e) {} - NRF.on('disconnect', () => Bangle.buzz()); + NRF.on('disconnect', () => { + Bangle.buzz(); + phoneNewMessage(null, "Phone disconnected"); + }); + NRF.on('connect', () => { setTimeout(() => { phoneOutbound({ t: "status", bat: E.getBattery() }); }, ONE_SECOND * 2); Bangle.buzz(); + phoneNewMessage(null, "Phone connected"); }); GB = (evt) => phoneInbound(evt); startTimers(); + + setInterval(checkBatteryLevel, ONE_SECOND * 60 * 10); + checkBatteryLevel(); } // Initialise! From 900b820474625dbd6437abed026203146e808a04 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Mon, 13 Apr 2020 11:14:50 +0200 Subject: [PATCH 0361/1189] Display temperature and LCD state in chart --- apps.json | 4 +- apps/batchart/ChangeLog | 1 + apps/batchart/app.js | 137 ++++++++++++++++++++++++++++++++++------ 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/apps.json b/apps.json index d85739aad..2fa94fa18 100644 --- a/apps.json +++ b/apps.json @@ -1148,9 +1148,9 @@ }, { "id": "batchart", "name": "Battery Chart", - "shortName":"BatChart", + "shortName":"Battery Chart", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index 1b77ff82f..8c1e8f995 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -1,3 +1,4 @@ 0.01: New app and widget 0.02: Widget stores data to file (1 dataset/10min) 0.03: Rotate log files once a week. +0.04: Display temperature and LCD state in chart diff --git a/apps/batchart/app.js b/apps/batchart/app.js index e8b30ba69..4fb919354 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -1,17 +1,26 @@ const GraphXZero = 40; const GraphYZero = 180; const GraphY100 = 80; + const GraphMarkerOffset = 5; const MaxValueCount = 144; const GraphXMax = GraphXZero + MaxValueCount; + +const GraphLcdY = GraphYZero + 10; +// const GraphCompassY = GraphYZero + 16; +// const GraphBluetoothY = GraphYZero + 22; +// const GraphGpsY = GraphYZero + 28; +// const GraphHrmY = GraphYZero + 34; + var Storage = require("Storage"); function renderCoordinateSystem() { g.setFont("6x8", 1); - g.drawString("t", GraphXMax + GraphMarkerOffset, GraphYZero - GraphMarkerOffset); - g.drawLine(GraphXZero, GraphYZero + GraphMarkerOffset, GraphXZero, GraphY100); - g.drawString("%", 39, 70); + // Left Y axis (Battery) + g.setColor(1, 1, 0); + g.drawLine(GraphXZero, GraphYZero + GraphMarkerOffset, GraphXZero, GraphY100); + g.drawString("%", 39, GraphY100 - 10); g.setFontAlign(1, -1, 0); g.drawString("100", 30, GraphY100 - GraphMarkerOffset); @@ -21,29 +30,47 @@ function renderCoordinateSystem() { g.drawLine(GraphXZero - GraphMarkerOffset, 130, GraphXZero, 130); g.drawString("0", 30, GraphYZero - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, GraphYZero, GraphXMax, GraphYZero); + + g.setColor(1,1,1); + g.setFontAlign(1, -1, 0); + g.drawLine(GraphXZero - GraphMarkerOffset, GraphYZero, GraphXMax + GraphMarkerOffset, GraphYZero); + + // Right Y axis (Temperature) + g.setColor(0.4, 0.4, 1); + g.drawLine(GraphXMax, GraphYZero + GraphMarkerOffset, GraphXMax, GraphY100); + g.drawString("°C", GraphXMax + GraphMarkerOffset, GraphY100 - 10); + g.setFontAlign(-1, -1, 0); + g.drawString("20", GraphXMax + 2 * GraphMarkerOffset, GraphYZero - GraphMarkerOffset); + + g.drawLine(GraphXMax + GraphMarkerOffset, 130, GraphXMax, 130); + g.drawString("30", GraphXMax + 2 * GraphMarkerOffset, GraphYZero - 50 - GraphMarkerOffset); + + g.drawLine(GraphXMax + GraphMarkerOffset, 80, GraphXMax, 80); + g.drawString("40", GraphXMax + 2 * GraphMarkerOffset, GraphY100 - GraphMarkerOffset); + + g.setColor(1,1,1); } function decrementDay(dayToDecrement) { return dayToDecrement === 0 ? 6 : dayToDecrement-1; } + function loadData() { - const MaxValueCount = 144; const startingDay = new Date().getDay(); // Load data for the current day - var logFileName = "bclog" + startingDay; + let logFileName = "bclog" + startingDay; - var dataLines = loadLinesFromFile(MaxValueCount, logFileName); + let dataLines = loadLinesFromFile(MaxValueCount, logFileName); // Top up to MaxValueCount from previous days as required - var previousDay = decrementDay(startingDay); + let previousDay = decrementDay(startingDay); while (dataLines.length < MaxValueCount && previousDay !== startingDay) { - var topUpLogFileName = "bclog" + previousDay; - var remainingLines = MaxValueCount - dataLines.length; - var topUpLines = loadLinesFromFile(remainingLines, topUpLogFileName); + let topUpLogFileName = "bclog" + previousDay; + let remainingLines = MaxValueCount - dataLines.length; + let topUpLines = loadLinesFromFile(remainingLines, topUpLogFileName); dataLines = topUpLines.concat(dataLines); previousDay = decrementDay(previousDay); @@ -53,8 +80,8 @@ function loadData() { } function loadLinesFromFile(requestedLineCount, fileName) { - var allLines = []; - var returnLines = []; + let allLines = []; + let returnLines = []; var readFile = Storage.open(fileName, "r"); @@ -63,11 +90,13 @@ function loadLinesFromFile(requestedLineCount, fileName) { allLines.push(nextLine); } } + + readFile = null; if (allLines.length <= 0) return; - linesToReadCount = Math.min(requestedLineCount, allLines.length); - startingLineIndex = Math.max(0, allLines.length - requestedLineCount - 1); + let linesToReadCount = Math.min(requestedLineCount, allLines.length); + let startingLineIndex = Math.max(0, allLines.length - requestedLineCount - 1); for (let i = startingLineIndex; i < linesToReadCount + startingLineIndex; i++) { if(allLines[i]) { @@ -81,20 +110,86 @@ function loadLinesFromFile(requestedLineCount, fileName) { } function renderData(dataArray) { - g.setColor(1, 1, 0); + const switchableConsumers = { + none: 0, + lcd: 1, + compass: 2, + bluetooth: 4, + gps: 8, + hrm: 16 + }; + + //const timestampIndex = 0; + const batteryIndex = 1; + const temperatureIndex = 2; + const switchabelsIndex = 3; + + var allConsumers = switchableConsumers.none | switchableConsumers.lcd | switchableConsumers.compass | switchableConsumers.bluetooth | switchableConsumers.gps | switchableConsumers.hrm; + for (let i = 0; i < dataArray.length; i++) { const element = dataArray[i]; + var dataInfo = element.split(","); - var batteryPercentage = parseInt(dataInfo[1]); - g.setPixel(GraphXZero + i, GraphYZero - batteryPercentage); + // Battery percentage + g.setColor(1, 1, 0); + g.setPixel(GraphXZero + i, GraphYZero - parseInt(dataInfo[batteryIndex])); + + // Temperature + g.setColor(0.4, 0.4, 1); + let scaledTemp = Math.floor(((parseFloat(dataInfo[temperatureIndex]) * 100) - 2000)/20) + ((((parseFloat(dataInfo[temperatureIndex]) * 100) - 2000) % 100)/25); + + g.setPixel(GraphXZero + i, GraphYZero - scaledTemp); + + // LCD state + if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.lcd == switchableConsumers.lcd) { + g.setColor(1, 1, 1); + g.setFontAlign(1, -1, 0); + g.drawString("LCD", GraphXZero - GraphMarkerOffset, GraphLcdY - 2, true); + g.drawLine(GraphXZero + i, GraphLcdY, GraphXZero + i, GraphLcdY + 1); + } + + // // Compass state + // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + // g.setColor(0, 1, 0); + // g.setFontAlign(-1, -1, 0); + // g.drawString("Compass", GraphXMax + GraphMarkerOffset, GraphCompassY - 2, true); + // g.drawLine(GraphXZero + i, GraphCompassY, GraphXZero + i, GraphCompassY + 1); + // } + + // // Bluetooth state + // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + // g.setColor(0, 0, 1); + // g.setFontAlign(1, -1, 0); + // g.drawString("BLE", GraphXZero - GraphMarkerOffset, GraphBluetoothY - 2, true); + // g.drawLine(GraphXZero + i, GraphBluetoothY, GraphXZero + i, GraphBluetoothY + 1); + // } + + // // Gps state + // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + // g.setColor(0.8, 0.5, 0.24); + // g.setFontAlign(-1, -1, 0); + // g.drawString("GPS", GraphXMax + GraphMarkerOffset, GraphGpsY - 2, true); + // g.drawLine(GraphXZero + i, GraphGpsY, GraphXZero + i, GraphGpsY + 1); + // } + + // // Hrm state + // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + // g.setColor(1, 0, 0); + // g.setFontAlign(1, -1, 0); + // g.drawString("HRM", GraphXZero - GraphMarkerOffset, GraphHrmY - 2, true); + // g.drawLine(GraphXZero + i, GraphHrmY, GraphXZero + i, GraphHrmY + 1); + // } } + + dataArray = null; } function renderBatteryChart() { renderCoordinateSystem(); - var data = loadData(); + let data = loadData(); renderData(data); + data = null; } // special function to handle display switch on @@ -102,10 +197,10 @@ Bangle.on('lcdPower', (on) => { if (on) { // call your app function here // If you clear the screen, do Bangle.drawWidgets(); - //g.clear() + g.clear() Bangle.loadWidgets(); Bangle.drawWidgets(); - //renderBatteryChart(); + renderBatteryChart(); } }); From 65f5a46dd95d5c63b27a0a8ee958d432f082ea84 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 13 Apr 2020 12:53:38 +0200 Subject: [PATCH 0362/1189] Create ChangeLog --- apps/activepedom/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/activepedom/ChangeLog diff --git a/apps/activepedom/ChangeLog b/apps/activepedom/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/activepedom/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! From 0cee31908614af8b8e02f7c9fd1f12073c95a2ab Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 13 Apr 2020 13:04:18 +0200 Subject: [PATCH 0363/1189] Initial transfer --- apps/activepedom/10600.png | Bin 0 -> 370 bytes apps/activepedom/1600.png | Bin 0 -> 374 bytes apps/activepedom/600.png | Bin 0 -> 338 bytes apps/activepedom/README.md | 38 ++++++++ apps/activepedom/app-icon.js | 1 + apps/activepedom/app.png | Bin 0 -> 836 bytes apps/activepedom/settings.js | 81 ++++++++++++++++ apps/activepedom/widget.js | 180 +++++++++++++++++++++++++++++++++++ 8 files changed, 300 insertions(+) create mode 100644 apps/activepedom/10600.png create mode 100644 apps/activepedom/1600.png create mode 100644 apps/activepedom/600.png create mode 100644 apps/activepedom/README.md create mode 100644 apps/activepedom/app-icon.js create mode 100644 apps/activepedom/app.png create mode 100644 apps/activepedom/settings.js create mode 100644 apps/activepedom/widget.js diff --git a/apps/activepedom/10600.png b/apps/activepedom/10600.png new file mode 100644 index 0000000000000000000000000000000000000000..36de436df0021f74082396aab83d959120af1fc5 GIT binary patch literal 370 zcmV-&0ge8NP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L0S8G$K~z{r?Um6E zgCGn=+2Vu$|Fu4tY}8Rx8ZJsPW;C9pK??|$J0qJFSh zwJEg-q^^!TJ6|J?E1{J|${}S@{81&0m2!AHkrHI2M57uT*7(kK9ah4qL^G^>X9XCC zm9WyPD34>~cq1+Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L0Sie)K~z{r?UmaO z!ypJi-O`7Cwx8XHCYvmhDGKUlt<|1{*uvx@mOYeGFC#~PSMJ9Pc#?w$3f$8@rAr5`=*eiI>q^;c6_G@ z`AqshRSKLece?)oopD8oGuiY@!QE-x&)E?!4&9gX7qL$|{VoVw)V6PGT~_<{1@wSx zLmiN#ZvhnLiAm-oF}Xc U&O83Y0{{R307*qoM6N<$f?Z6Z`Tzg` literal 0 HcmV?d00001 diff --git a/apps/activepedom/600.png b/apps/activepedom/600.png new file mode 100644 index 0000000000000000000000000000000000000000..4d2c625c709002faa5e3e5207e0caa12782fe1d9 GIT binary patch literal 338 zcmV-Y0j>UtP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L0Ov_WK~z{r-IdV} z!ypJn-O`7Cc0aohO*(13hEj2oY^`zBSl+OwdPlF{`^8AX;833oOi^Eb=Ix< z4Y=t@{U4EN>is*v0p}eVkm5nsZ9V)v&4(utBU<85KnKYd3p?#)jMms|@h9wbM`9t_ zW6hyhNp&rLCzs1k1;I*(>6PYJtLJVIm&?w(zzej-@5asZn@5Y3MF(QJU*xBe^AR;z`8dFFL zUsbR>Fo;!9EEKUY+GwFz*~Jh=379B|Xkj6W8t)RLCYKaGh{f!Zz1f-B$?ap3KYZk| z|M|Y(cQZRXdyu~JzyMJ8;xUlRpl%|%2+V4t$03)M^626HSkN;uKy(BB&gd*OMRWs` zaf{T(O%PMFaTBE3zzYk{aEkR~D@XJaI^c}XQa$M5FF53ymvV^RX3C3x7QrXK=v4Oj831Y|-y`(Ee+f6AiE4qTQt>jdQS#LQW9S>WA^klD>`fmZ&M06`DSVq0 zzF=$sN{asv0f$KO-9#=rs3~^b0RPGJ^cpD^$2Dk^Frv>r7kZGn$ zKu3}dv?I$NL4Kg zfMBeS7{3Pb3@IXJr8g~5lU|~4;Iw6qdSH1fbQU^{zJXuBdRJgJs`q{t&^K}437Mt( zfK}e_1@uj{xqypO9pY#)g1DJM-^546%g}<-4(0$~F*g(4sGGR!fYGQER07(}L}%ud z23;czxIJ*aptwE(G-OI?&@h#7PZS>2ayph3ph>$BFX=(BBO31=$@e@9K$BJ?j=({v zabT&&znkzZw5E@#*F6Q$(TFi4lK*O&fF^YjhQDbs?xZy4Ck}4rR>H^MHZ@bSDW;E(H;iWU*PcZo8_9K(;h&mO8`>M<}B<0EEX8tM_eM|K( zA01MzViJH+8VwYjA>JO|0DKSR8;wn8p*-*zF%wCg>)U{D2>5)pN&W+*T-arpW9jGs O0000 { + var stepTimeDiff = 9999; //Time difference between two steps + var startTimeStep = new Date(); //set start time + var stopTimeStep = 0; //Time after one step + var timerResetActive = 0; //timer to reset active + 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(); + var width = 45; + + var stepsTooShort = 0; + var stepsTooLong = 0; + var stepsOutsideTime = 0; + + //define default settings + const DEFAULTS = { + 'cMaxTime' : 1100, + 'cMinTime' : 240, + 'stepThreshold' : 30, + 'intervalResetActive' : 30000, + 'stepSensitivity' : 80, + 'stepGoal' : 10000, + }; + const SETTINGS_FILE = 'activepedom.settings.json'; + const PEDOMFILE = "activepedom.steps.json"; + + let settings; + //load settings + function loadSettings() { + settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; + } + //return setting + function setting(key) { + if (!settings) { loadSettings(); } + return (key in settings) ? settings[key] : DEFAULTS[key]; + } + + function setStepSensitivity(s) { + function sqr(x) { return x*x; } + var X=sqr(8192-s); + var Y=sqr(8192+s); + Bangle.setOptions({stepCounterThresholdLow:X,stepCounterThresholdHigh:Y}); + } + + //format number to make them shorter + function kFormatter(num) { + if (num <= 999) return num; //smaller 1.000, return 600 as 600 + if (num >= 1000 && num < 10000) { //between 1.000 and 10.000 + num = Math.floor(num/100)*100; + return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; //return 1600 as 1.6k + } + if (num >= 10000) { //greater 10.000 + num = Math.floor(num/1000)*1000; + return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; //return 10.600 as 10k + } + } + + //Set Active to 0 + function resetActive() { + active = 0; + steps = 0; + if (Bangle.isLCDOn()) WIDGETS["activepedom"].draw(); + } + + function calcSteps() { + stopTimeStep = new Date(); //stop time after each step + stepTimeDiff = stopTimeStep - startTimeStep; //time between steps in milliseconds + startTimeStep = new Date(); //start time again + + //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 + 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 + steps--; + } + + if (steps >= setting('stepThreshold')) { + if (active == 0) { + stepsCounted = stepsCounted + (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 + } + active = 1; + clearInterval(timerResetActive); //stop timer which resets active + timerResetActive = setInterval(resetActive, setting('intervalResetActive')); //reset active after timer runs out + steps = 0; + } + + if (active == 1) { + stepsCounted++; //count steps + } + else { + stepsOutsideTime++; + } + } + + function draw() { + var height = 23; //width is deined globally + var stepsDisplayLarge = kFormatter(stepsCounted); + + //Check if same day + let date = new Date(); + if (lastUpdate.getDate() == date.getDate()){ //if same day + } + else { + stepsCounted = 1; //set stepcount to 1 + } + lastUpdate = date; + + g.reset(); + g.clearRect(this.x, this.y, this.x+width, this.y+height); + + //draw numbers + if (active == 1) g.setColor(0x07E0); //green + else g.setColor(0xFFFF); //white + g.setFont("6x8", 2); + g.drawString(stepsDisplayLarge,this.x+1,this.y); //first line, big number + g.setFont("6x8", 1); + g.setColor(0xFFFF); //white + g.drawString(stepsCounted,this.x+1,this.y+14); //second line, small number + + //draw step goal bar + stepGoalPercent = (stepsCounted / setting('stepGoal')) * 100; + stepGoalBarLength = width / 100 * stepGoalPercent; + if (stepGoalBarLength > width) stepGoalBarLength = width; //do not draw across width of widget + g.setColor(0x7BEF); //grey + g.fillRect(this.x, this.y+height, this.x+width, this.y+height); // draw background bar + g.setColor(0xFFFF); //white + g.fillRect(this.x, this.y+height, this.x+1, this.y+height-1); //draw start of bar + g.fillRect(this.x+width, this.y+height, this.x+width-1, this.y+height-1); //draw end of bar + g.fillRect(this.x, this.y+height, this.x+stepGoalBarLength, this.y+height); // draw progress bar + } + + //This event is called just before the device shuts down for commands such as reset(), load(), save(), E.reboot() or Bangle.off() + E.on('kill', () => { + let d = { //define array to write to file + lastUpdate : lastUpdate.toISOString(), + stepsToday : stepsCounted, + stepsTooShort : stepsTooShort, + stepsTooLong : stepsTooLong, + stepsOutsideTime : stepsOutsideTime + }; + require("Storage").write(PEDOMFILE,d); //write array to file + }); + + //When Step is registered by firmware + Bangle.on('step', (up) => { + steps++; //increase step count + calcSteps(); + if (Bangle.isLCDOn()) WIDGETS["activepedom"].draw(); + }); + + // redraw when the LCD turns on + Bangle.on('lcdPower', function(on) { + if (on) WIDGETS["activepedom"].draw(); + }); + + //Read data from file and set variables + let pedomData = require("Storage").readJSON(PEDOMFILE,1); + if (pedomData) { + if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); + stepsCounted = pedomData.stepsToday|0; + stepsTooShort = pedomData.stepsTooShort; + stepsTooLong = pedomData.stepsTooLong; + stepsOutsideTime = pedomData.stepsOutsideTime; + } + + setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive) + + //Add widget + WIDGETS["activepedom"]={area:"tl",width:width,draw:draw}; + +})(); \ No newline at end of file From 43d0f455a7d730632f6b8b00cc464cd959fd7025 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 13 Apr 2020 13:09:30 +0200 Subject: [PATCH 0364/1189] Active Pedometer --- apps.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps.json b/apps.json index e9ba66804..49e2bad6a 100644 --- a/apps.json +++ b/apps.json @@ -1107,6 +1107,19 @@ {"name":"openstmap.app.js","url":"app.js"}, {"name":"openstmap.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "activepedom", + "name": "Active Pedometer", + "shortName":"activepedom", + "icon": "app.png", + "version":"0.01", + "description": "Pedometer that filters out arm movement and displays a step goal progress.", + "tags": "outdoors,widget", + "storage": [ + {"name":"activepedom.wid.js","url":"widget.js"}, + {"name":"activepedom.settings.js","url":"settings.js"}, + {"name":"activepedom.img","url":"app-icon.js","evaluate":true} + ] }, { "id": "tabata", "name": "Tabata", From 1bb6af5ad50833b8cd6a2ae29c34b3061e5911c8 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 13 Apr 2020 13:19:45 +0200 Subject: [PATCH 0365/1189] added type widget --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 49e2bad6a..a0b1a56aa 100644 --- a/apps.json +++ b/apps.json @@ -1115,6 +1115,7 @@ "version":"0.01", "description": "Pedometer that filters out arm movement and displays a step goal progress.", "tags": "outdoors,widget", + "type":"widget", "storage": [ {"name":"activepedom.wid.js","url":"widget.js"}, {"name":"activepedom.settings.js","url":"settings.js"}, From 477e6f07609a6a80a69cc9265732699d544a3c53 Mon Sep 17 00:00:00 2001 From: fredericrous Date: Mon, 13 Apr 2020 03:10:18 +0100 Subject: [PATCH 0366/1189] Add App Calculator --- apps.json | 12 + apps/calculator/ChangeLog | 1 + apps/calculator/app.js | 352 +++++++++++++++++++++++++++++ apps/calculator/calculator-icon.js | 1 + apps/calculator/calculator.info | 1 + apps/calculator/calculator.png | Bin 0 -> 10312 bytes 6 files changed, 367 insertions(+) create mode 100644 apps/calculator/ChangeLog create mode 100644 apps/calculator/app.js create mode 100644 apps/calculator/calculator-icon.js create mode 100644 apps/calculator/calculator.info create mode 100644 apps/calculator/calculator.png diff --git a/apps.json b/apps.json index d85739aad..77239e39e 100644 --- a/apps.json +++ b/apps.json @@ -1158,5 +1158,17 @@ {"name":"batchart.app.js","url":"app.js"}, {"name":"batchart.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "calculator", + "name": "Calculator", + "shortName":"Calculator", + "icon": "calculator.png", + "version":"0.01", + "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus. Push button1 and 3 to navigate up/down, tap right or left to navigate the sides, push button 2 to select.", + "tags": "app,tool", + "storage": [ + {"name":"calculator.app.js","url":"app.js"}, + {"name":"calculator.img","url":"calculator-icon.js","evaluate":true} + ] } ] diff --git a/apps/calculator/ChangeLog b/apps/calculator/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/calculator/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/calculator/app.js b/apps/calculator/app.js new file mode 100644 index 000000000..91dd7c49d --- /dev/null +++ b/apps/calculator/app.js @@ -0,0 +1,352 @@ +/** + * BangleJS Calculator + * + * Original Author: Frederic Rousseau https://github.com/fredericrous + * Created: April 2020 + */ + +g.clear(); +Graphics.prototype.setFont7x11Numeric7Seg = function() { + this.setFontCustom(atob("ACAB70AYAwBgC94AAAAAAAAAAB7wAAPQhhDCGELwAAAAhDCGEMIXvAAeACAEAIAQPeAA8CEMIYQwhA8AB70IYQwhhCB4AAAIAQAgBAB7wAHvQhhDCGEL3gAPAhDCGEMIXvAAe9CCEEIIQPeAA94EIIQQghA8AB70AYAwBgCAAAAHgQghBCCF7wAHvQhhDCGEIAAAPehBCCEEIAAAAA=="), 46, atob("AgAHBwcHBwcHBwcHAAAAAAAAAAcHBwcHBw=="), 11); +}; + +var DEFAULT_SELECTION = '5'; +var BOTTOM_MARGIN = 10; +var RIGHT_MARGIN = 20; +var COLORS = { + // [normal, selected] + DEFAULT: ['#7F8183', '#A6A6A7'], + OPERATOR: ['#F99D1C', '#CA7F2A'], + SPECIAL: ['#65686C', '#7F8183'] +}; + +var keys = { + '0': { + xy: [0, 200, 120, 240], + trbl: '2.00' + }, + '.': { + xy: [120, 200, 180, 240], + trbl: '3=.0' + }, + '=': { + xy: [181, 200, 240, 240], + trbl: '+==.', + color: COLORS.OPERATOR + }, + '1': { + xy: [0, 160, 60, 200], + trbl: '4201' + }, + '2': { + xy: [60, 160, 120, 200], + trbl: '5301' + }, + '3': { + xy: [120, 160, 180, 200], + trbl: '6+.2' + }, + '+': { + xy: [181, 160, 240, 200], + trbl: '-+=3', + color: COLORS.OPERATOR + }, + '4': { + xy: [0, 120, 60, 160], + trbl: '7514' + }, + '5': { + xy: [60, 120, 120, 160], + trbl: '8624' + }, + '6': { + xy: [120, 120, 180, 160], + trbl: '9-35' + }, + '-': { + xy: [181, 120, 240, 160], + trbl: '*-+6', + color: COLORS.OPERATOR + }, + '7': { + xy: [0, 80, 60, 120], + trbl: 'R847' + }, + '8': { + xy: [60, 80, 120, 120], + trbl: 'N957' + }, + '9': { + xy: [120, 80, 180, 120], + trbl: '%*68' + }, + '*': { + xy: [181, 80, 240, 120], + trbl: '/*-9', + color: COLORS.OPERATOR + }, + 'R': { + xy: [0, 40, 60, 79], + trbl: 'RN7R', + color: COLORS.SPECIAL, + val: 'AC' + }, + 'N': { + xy: [60, 40, 120, 79], + trbl: 'N%8R', + color: COLORS.SPECIAL, + val: '+/-' + }, + '%': { + xy: [120, 40, 180, 79], + trbl: '%/9N', + color: COLORS.SPECIAL + }, + '/': { + xy: [181, 40, 240, 79], + trbl: '//*%', + color: COLORS.OPERATOR + } +}; + +var selected = DEFAULT_SELECTION; +var prevSelected = DEFAULT_SELECTION; +var prevNumber = null; +var currNumber = null; +var operator = null; +var results = null; +var isDecimal = false; +var hasPressedEquals = false; + +function drawKey(name, k, selected) { + var rMargin = 0; + var bMargin = 0; + var color = k.color || COLORS.DEFAULT; + g.setColor(color[selected ? 1 : 0]); + g.setFont('Vector', 20); + g.fillRect(k.xy[0], k.xy[1], k.xy[2], k.xy[3]); + g.setColor(-1); + // correct margins to center the texts + if (name == '0') { + rMargin = (RIGHT_MARGIN * 2) - 7; + } else if (name === '/') { + rMargin = 5; + } else if (name === '*') { + bMargin = 5; + rMargin = 3; + } else if (name === '-') { + rMargin = 3; + } else if (name === 'R' || name === 'N') { + rMargin = k.val === 'C' ? 0 : -9; + } else if (name === '%') { + rMargin = -3; + } + g.drawString(k.val || name, k.xy[0] + RIGHT_MARGIN + rMargin, k.xy[1] + BOTTOM_MARGIN + bMargin); +} + +function doMath(x, y, operator) { + // might not be a number due to display of dot "." algo + x = Number(x); + y = Number(y); + switch (operator) { + case '/': + return x / y; + case '*': + return x * y; + case '+': + return x + y; + case '-': + return x - y; + } +} + +function displayOutput(num) { + var len; + var minusMarge = 0; + g.setColor(0); + g.fillRect(0, 0, 240, 39); + g.setColor(-1); + if (num === Infinity || num === -Infinity || isNaN(num)) { + // handle division by 0 + if (num === Infinity) { + num = 'INFINITY'; + } else if (num === -Infinity) { + num = '-INFINITY'; + } else { + num = 'NOT A NUMBER'; + minusMarge = -25; + } + len = (num + '').length; + currNumber = null; + results = null; + isDecimal = false; + hasPressedEquals = false; + prevNumber = null; + operator = null; + keys.R.val = 'AC'; + drawKey('R', keys.R); + g.setFont('Vector', 22); + } else { + // might not be a number due to display of dot "." + var numNumeric = Number(num); + + if (typeof num === 'string') { + if (num.indexOf('.') !== -1) { + // display a 0 before a lonely dot + if (numNumeric == 0) { + num = '0.'; + } + } else { + // remove preceding 0 + while (num.length > 1 && num[0] === '0') + num = num.substr(1); + } + } + + len = (num + '').length; + if (numNumeric < 0) { + // minus is not available in font 7x11Numeric7Seg, we use Vector + g.setFont('Vector', 20); + g.drawString('-', 220 - (len * 15), 10); + minusMarge = 15; + } + g.setFont('7x11Numeric7Seg', 2); + } + g.drawString(num, 220 - (len * 15) + minusMarge, 10); +} + +function calculatorLogic(x) { + if (hasPressedEquals) { + currNumber = results; + prevNumber = null; + operator = null; + results = null; + isDecimal = null; + displayOutput(currNumber); + hasPressedEquals = false; + } + if (prevNumber != null && currNumber != null && operator != null) { + // we execute the calculus only when there was a previous number entered before and an operator + results = doMath(prevNumber, currNumber, operator); + operator = x; + prevNumber = results; + currNumber = null; + displayOutput(results); + } else if (prevNumber == null && currNumber != null && operator == null) { + // no operator yet, save the current number for later use when an operator is pressed + operator = x; + prevNumber = currNumber; + currNumber = null; + displayOutput(prevNumber); + } else if (prevNumber == null && currNumber == null && operator == null) { + displayOutput(0); + } +} + +function buttonPress(val) { + switch (val) { + case 'R': + currNumber = null; + results = null; + isDecimal = false; + hasPressedEquals = false; + if (keys.R.val == 'AC') { + prevNumber = null; + operator = null; + } else { + keys.R.val = 'AC'; + drawKey('R', keys.R); + } + displayOutput(0); + break; + case '%': + if (results != null) { + displayOutput(results /= 100); + } else if (currNumber != null) { + displayOutput(currNumber /= 100); + } + break; + case 'N': + if (results != null) { + displayOutput(results *= -1); + } else if (currNumber != null) { + displayOutput(currNumber *= -1); + } + break; + case '/': + case '*': + case '-': + case '+': + calculatorLogic(val); + break; + case '.': + keys.R.val = 'C'; + drawKey('R', keys.R); + isDecimal = true; + displayOutput(currNumber == null ? 0 + '.' : currNumber + '.'); + break; + case '=': + if (prevNumber != null && currNumber != null && operator != null) { + results = doMath(prevNumber, currNumber, operator); + prevNumber = results; + displayOutput(results); + hasPressedEquals = true; + } + break; + default: + keys.R.val = 'C'; + drawKey('R', keys.R); + if (isDecimal) { + currNumber = currNumber == null ? 0 + '.' + val : currNumber + '.' + val; + isDecimal = false; + } else { + currNumber = currNumber == null ? val : currNumber + val; + } + displayOutput(currNumber); + break; + } +} + +for (var k in keys) { + if (keys.hasOwnProperty(k)) { + drawKey(k, keys[k], k == '5'); + } +} +g.setFont('7x11Numeric7Seg', 2.8); +g.drawString('0', 205, 10); + + +setWatch(function() { + drawKey(selected, keys[selected]); + // key 0 is 2 keys wide, go up to 1 if it was previously selected + if (selected == '0' && prevSelected === '1') { + prevSelected = selected; + selected = '1'; + } else { + prevSelected = selected; + selected = keys[selected].trbl[0]; + } + drawKey(selected, keys[selected], true); +}, BTN1, {repeat: true, debounce: 100}); + +setWatch(function() { + drawKey(selected, keys[selected]); + prevSelected = selected; + selected = keys[selected].trbl[2]; + drawKey(selected, keys[selected], true); +}, BTN3, {repeat: true, debounce: 100}); + +Bangle.on('touch', function(direction) { + drawKey(selected, keys[selected]); + prevSelected = selected; + if (direction == 1) { + selected = keys[selected].trbl[3]; + } else if (direction == 2) { + selected = keys[selected].trbl[1]; + } + drawKey(selected, keys[selected], true); +}); + +setWatch(function() { + buttonPress(selected); +}, BTN2, {repeat: true, debounce: 100}); diff --git a/apps/calculator/calculator-icon.js b/apps/calculator/calculator-icon.js new file mode 100644 index 000000000..94158e7d2 --- /dev/null +++ b/apps/calculator/calculator-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwhBC/AC8r6/XlYvr64CEF9UrMIIv/R/7vTMwIAmlUklQGDroAFqwHGBRgJBqwMDq+k5nNABAWDC4QZFERAvGBQOBF5I0FCYNW1mImWs6+sDoQsDAYIJEAAeB2eB1mBA4QvF43P6/GF4mB6+BAQYlEro3BAAI3FDAezBYgvE43O64DBF4hbCAAMrGAIiFBYRUEHogaBxA6CF4vXLwPHF4giEDIIkDDgI2BFoI6FBgYWCF5PPF4rSBKwVWI4bAFFgdcYAykBX5HX53NFwfNfwIkDAQYAGBBAKCIIYABd4y9DAAJ9CAD9dF4gAGCIi8BABLXBBRQLEF4vHRwgvEERQ6DHpgvH66PB65fUBpZfJ4/G6wxBMIaPbL5QvB6/WF6hqNF5KPDF6jkGd6JeBF5AAdF4oAGDBeH1mHAAwIBF8esABQvdWQonDX4YvIYAq/GXobvNF4hfKCwwvF43GF5AXGL44vJLwgvE453DMIYuFR5JiHI4yPHRoaREIwpIFF7TvbR5BJCX5IvMADgvcroABF6vG4wvIX46DKBZYvEFwPHGAgZHERALRF4YuBHYIwEFxxfPF5CDDF6ZfLDAyPFFwovFKRYvV47vDAgIvRR5aOFL4orCFwbvHADYvEAA4YLdRYvQ45eBR5C6UF5vHX4LvJF8PGZYXXGAYvnLYYvfZ4xfXd6AvKGAK/RDAKNTF4wAG44=")) diff --git a/apps/calculator/calculator.info b/apps/calculator/calculator.info new file mode 100644 index 000000000..e8a760024 --- /dev/null +++ b/apps/calculator/calculator.info @@ -0,0 +1 @@ +{"name":"Calculator","src":"calculator.app.js","icon":"calculator.img"} diff --git a/apps/calculator/calculator.png b/apps/calculator/calculator.png new file mode 100644 index 0000000000000000000000000000000000000000..8362c9200facdad594bf07376e12eaf6d0c3550c GIT binary patch literal 10312 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 Date: Mon, 13 Apr 2020 14:26:53 +0200 Subject: [PATCH 0367/1189] Active Pedometer rename --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a0b1a56aa..3dbccb9b1 100644 --- a/apps.json +++ b/apps.json @@ -1110,7 +1110,7 @@ }, { "id": "activepedom", "name": "Active Pedometer", - "shortName":"activepedom", + "shortName":"Active Pedometer", "icon": "app.png", "version":"0.01", "description": "Pedometer that filters out arm movement and displays a step goal progress.", From 5bbb6bfc894c88922719801426c93c6ec0509f2a Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 13 Apr 2020 14:57:47 +0200 Subject: [PATCH 0368/1189] Bugfix --- apps/activepedom/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activepedom/widget.js b/apps/activepedom/widget.js index ac07856fd..0c8b2438d 100644 --- a/apps/activepedom/widget.js +++ b/apps/activepedom/widget.js @@ -84,7 +84,7 @@ if (steps >= setting('stepThreshold')) { if (active == 0) { - stepsCounted = stepsCounted + (stepThreshold -1) ; //count steps needed to reach active status, last step is counted anyway, so treshold -1 + 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 } active = 1; From be10466ed14082f58923f80dfe1c55f2d6f3d6b2 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Mon, 13 Apr 2020 14:33:22 +0100 Subject: [PATCH 0369/1189] Don't double-buzz, it throws an error!, Also only call drawImage if we have an image to draw --- apps/marioclock/marioclock-app.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index 4acbf384b..7601b89ba 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -359,7 +359,7 @@ function drawNotice(x, y) { break; } - g.drawImage(img, characterSprite.x, characterSprite.y - 16); + if (img) g.drawImage(img, characterSprite.x, characterSprite.y - 16); } function drawCharacter(date, character) { @@ -671,7 +671,6 @@ function init() { try { NRF.wake(); } catch (e) {} NRF.on('disconnect', () => { - Bangle.buzz(); phoneNewMessage(null, "Phone disconnected"); }); @@ -679,7 +678,6 @@ function init() { setTimeout(() => { phoneOutbound({ t: "status", bat: E.getBattery() }); }, ONE_SECOND * 2); - Bangle.buzz(); phoneNewMessage(null, "Phone connected"); }); From c64d7bf57e04070b691b26a43a237c9e9ca9448a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 14 Apr 2020 07:48:07 +0200 Subject: [PATCH 0370/1189] Experimental changes for hrm, gps an compass --- apps/batchart/app.js | 50 +++++++++++++++++----------------- apps/batchart/widget.js | 60 ++++++++++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 37 deletions(-) diff --git a/apps/batchart/app.js b/apps/batchart/app.js index 4fb919354..569fecfd1 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -7,12 +7,12 @@ const MaxValueCount = 144; const GraphXMax = GraphXZero + MaxValueCount; const GraphLcdY = GraphYZero + 10; -// const GraphCompassY = GraphYZero + 16; +const GraphCompassY = GraphYZero + 16; // const GraphBluetoothY = GraphYZero + 22; -// const GraphGpsY = GraphYZero + 28; -// const GraphHrmY = GraphYZero + 34; +const GraphGpsY = GraphYZero + 28; +const GraphHrmY = GraphYZero + 34; -var Storage = require("Storage"); +const Storage = require("Storage"); function renderCoordinateSystem() { g.setFont("6x8", 1); @@ -149,13 +149,13 @@ function renderData(dataArray) { g.drawLine(GraphXZero + i, GraphLcdY, GraphXZero + i, GraphLcdY + 1); } - // // Compass state - // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { - // g.setColor(0, 1, 0); - // g.setFontAlign(-1, -1, 0); - // g.drawString("Compass", GraphXMax + GraphMarkerOffset, GraphCompassY - 2, true); - // g.drawLine(GraphXZero + i, GraphCompassY, GraphXZero + i, GraphCompassY + 1); - // } + // Compass state + if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + g.setColor(0, 1, 0); + g.setFontAlign(-1, -1, 0); + g.drawString("Compass", GraphXMax + GraphMarkerOffset, GraphCompassY - 2, true); + g.drawLine(GraphXZero + i, GraphCompassY, GraphXZero + i, GraphCompassY + 1); + } // // Bluetooth state // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { @@ -165,21 +165,21 @@ function renderData(dataArray) { // g.drawLine(GraphXZero + i, GraphBluetoothY, GraphXZero + i, GraphBluetoothY + 1); // } - // // Gps state - // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { - // g.setColor(0.8, 0.5, 0.24); - // g.setFontAlign(-1, -1, 0); - // g.drawString("GPS", GraphXMax + GraphMarkerOffset, GraphGpsY - 2, true); - // g.drawLine(GraphXZero + i, GraphGpsY, GraphXZero + i, GraphGpsY + 1); - // } + // Gps state + if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + g.setColor(0.8, 0.5, 0.24); + g.setFontAlign(-1, -1, 0); + g.drawString("GPS", GraphXMax + GraphMarkerOffset, GraphGpsY - 2, true); + g.drawLine(GraphXZero + i, GraphGpsY, GraphXZero + i, GraphGpsY + 1); + } - // // Hrm state - // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { - // g.setColor(1, 0, 0); - // g.setFontAlign(1, -1, 0); - // g.drawString("HRM", GraphXZero - GraphMarkerOffset, GraphHrmY - 2, true); - // g.drawLine(GraphXZero + i, GraphHrmY, GraphXZero + i, GraphHrmY + 1); - // } + // Hrm state + if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + g.setColor(1, 0, 0); + g.setFontAlign(1, -1, 0); + g.drawString("HRM", GraphXZero - GraphMarkerOffset, GraphHrmY - 2, true); + g.drawLine(GraphXZero + i, GraphHrmY, GraphXZero + i, GraphHrmY + 1); + } } dataArray = null; diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index de7ce230d..6ec330511 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -15,6 +15,12 @@ const recordingInterval10S = 10*1000; //For testing var recordingInterval = null; + var compassEventReceived = false; + var gpsEventReceived = false; + var hrmEventReceived = false; + + const Storage = require("Storage"); + // draw your widget function draw() { g.reset(); @@ -24,24 +30,54 @@ function getEnabledConsumersValue() { var enabledConsumers = switchableConsumers.none; + Bangle.on('mag', (() => { + console.log("mag received"); + compassEventReceived = true; + Bangle.on("mag", () => {}); + })); + + Bangle.on('GPS', (() => { + console.log("GPS received"); + gpsEventReceived = true; + })); + + Bangle.on('HRM', (() => { + console.log("HRM received"); + hrmEventReceived = true; + })); + + // Wait two seconds, that should be enough for each of the events to get raised once + setTimeout(() => { + Bangle.on('mag', () => {}); + Bangle.on('GPS', () => {}); + Bangle.on('HRM', () => {}); + }, 2000); + if (Bangle.isLCDOn()) enabledConsumers = enabledConsumers | switchableConsumers.lcd; // Already added in the hope they will be available soon to get more details - // if (Bangle.isCompassOn()) - // enabledConsumers = enabledConsumers | switchableConsumers.compass; - // if (Bangle.isBluetoothOn()) + if (compassEventReceived) + enabledConsumers = enabledConsumers | switchableConsumers.compass; + if (gpsEventReceived) + enabledConsumers = enabledConsumers | switchableConsumers.gps; + if (hrmEventReceived) + enabledConsumers = enabledConsumers | switchableConsumers.hrm; + //if (Bangle.isBluetoothOn()) // enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; - // if (Bangle.isGpsOn()) - // enabledConsumers = enabledConsumers | switchableConsumers.gps; - // if (Bangle.isHrmOn()) - // enabledConsumers = enabledConsumers | switchableConsumers.hrm; + + // Reset the event registration vars + compassEventReceived = false; + gpsEventReceived = false; + hrmEventReceived = false; + + console.log("Enabled: " + enabledConsumers); return enabledConsumers; } function logBatteryData() { const previousWriteLogName = "bcprvday"; - const previousWriteDay = require("Storage").read(previousWriteLogName); + const previousWriteDay = Storage.read(previousWriteLogName); const currentWriteDay = new Date().getDay(); const logFileName = "bclog" + currentWriteDay; @@ -49,11 +85,11 @@ // Change log target on day change if (previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago - require("Storage").erase(logFileName); - require("Storage").write(previousWriteLogName, currentWriteDay); + Storage.erase(logFileName); + Storage.write(previousWriteLogName, currentWriteDay); } - var bcLogFileA = require("Storage").open(logFileName, "a"); + var bcLogFileA = Storage.open(logFileName, "a"); if (bcLogFileA) { console.log([getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")); bcLogFileA.write([[getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")].join(",")+"\n"); @@ -63,7 +99,7 @@ function reload() { WIDGETS["batchart"].width = 24; - recordingInterval = setInterval(logBatteryData, recordingInterval10Min); + recordingInterval = setInterval(logBatteryData, recordingInterval10S); logBatteryData(); } From 0fa4b44990a9b8f63827b4185f318ced1ee2eb92 Mon Sep 17 00:00:00 2001 From: MaBecker Date: Tue, 14 Apr 2020 08:52:04 +0200 Subject: [PATCH 0371/1189] add favourite functionality * library select/unselect apps/widgets * as library section * as upload * deny unselect for boot and setting --- CHANGELOG.md | 1 + index.html | 4 +- js/index.js | 117 +++++++++++++++++++++++++++++++++++++++++---------- js/ui.js | 1 + js/utils.js | 13 ++++++ 5 files changed, 113 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1cd3d803..6368c2c46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,3 +7,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * Added optional `README.md` file for apps * Remove 2v04 version warning, add links in About to official/developer versions * Fix issue removing an app that was just installed (Fix #253) +* Add `Favourite` functionality diff --git a/index.html b/index.html index 0d5c17251..f016ffb49 100644 --- a/index.html +++ b/index.html @@ -96,6 +96,7 @@ +
@@ -134,7 +135,8 @@

Utilities

-

+ +

diff --git a/js/index.js b/js/index.js index d2c6d698b..ef9bcb4f1 100644 --- a/js/index.js +++ b/js/index.js @@ -1,6 +1,8 @@ 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=>{ try { @@ -18,7 +20,7 @@ httpGet("apps.json").then(apps=>{ function showChangeLog(appid) { var app = appNameToApp(appid); function show(contents) { - showPrompt(app.name+" Change Log",contents,{ok:true}).catch(()=>{});; + showPrompt(app.name+" Change Log",contents,{ok:true}).catch(()=>{}); } httpGet(`apps/${appid}/ChangeLog`). then(show).catch(()=>show("No Change Log available")); @@ -142,6 +144,20 @@ function handleAppInterface(app) { }); } +function handleAppFavourite(favourite, app){ + if (favourite) { + favourites = favourites.concat([app.id]); + } else { + if ([ "boot","setting"].includes(app.id)) { + showToast(app.name + ' is required, can\'t remove it' , 'warning'); + }else { + favourites = favourites.filter(e => e != app.id); + } + } + localStorage.setItem("favouriteapps.json", JSON.stringify(favourites)); + refreshLibrary(); +} + // =========================================== Top Navigation function showTab(tabname) { htmlToArray(document.querySelectorAll("#tab-navigate .tab-item")).forEach(tab => { @@ -156,7 +172,7 @@ function showTab(tabname) { // =========================================== Library -var chips = Array.from(document.querySelectorAll('.chip')).map(chip => chip.attributes.filterid.value) +var chips = Array.from(document.querySelectorAll('.chip')).map(chip => chip.attributes.filterid.value); var hash = window.location.hash ? window.location.hash.slice(1) : ''; var activeFilter = !!~chips.indexOf(hash) ? hash : ''; @@ -165,27 +181,34 @@ var currentSearch = ''; function refreshFilter(){ var filtersContainer = document.querySelector("#librarycontainer .filter-nav"); filtersContainer.querySelector('.active').classList.remove('active'); - if(activeFilter) filtersContainer.querySelector('.chip[filterid="'+activeFilter+'"]').classList.add('active') - else filtersContainer.querySelector('.chip[filterid]').classList.add('active') + if(activeFilter) filtersContainer.querySelector('.chip[filterid="'+activeFilter+'"]').classList.add('active'); + else filtersContainer.querySelector('.chip[filterid]').classList.add('active'); } function refreshLibrary() { var panelbody = document.querySelector("#librarycontainer .panel-body"); var visibleApps = appJSON; if (activeFilter) { - visibleApps = visibleApps.filter(app => app.tags && app.tags.split(',').includes(activeFilter)); + if ( activeFilter == "favourites" ) { + visibleApps = visibleApps.filter(app => app.id && (favourites.filter( e => e == app.id).length)); + }else{ + visibleApps = visibleApps.filter(app => app.tags && app.tags.split(',').includes(activeFilter)); + } } if (currentSearch) { 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); var versionInfo = version.text; if (versionInfo) versionInfo = " ("+versionInfo+")"; var readme = `
Read more...`; + var favourite = favourites.find(e => e == app.id); return `
${escapeHtml(app.name)}

@@ -195,7 +218,8 @@ function refreshLibrary() {

${escapeHtml(app.description)}${app.readme?`
${readme}`:""}

See the code on GitHub
-
+
+ @@ -232,7 +256,7 @@ function refreshLibrary() { // upload icon.classList.remove("icon-upload"); icon.classList.add("loading"); - uploadApp(app) + uploadApp(app); } else if (icon.classList.contains("icon-menu")) { // custom HTML update icon.classList.remove("icon-menu"); @@ -250,6 +274,10 @@ function refreshLibrary() { updateApp(app); } else if (icon.classList.contains("icon-download")) { handleAppInterface(app); + } else if ( button.innerText == String.fromCharCode(0x2661)) { + handleAppFavourite(true, app); + } else if ( button.innerText == String.fromCharCode(0x2665) ) { + handleAppFavourite(false, app); } }); }); @@ -262,17 +290,17 @@ refreshLibrary(); function uploadApp(app) { return getInstalledApps().then(()=>{ if (appsInstalled.some(i => i.id === app.id)) { - return updateApp(app) + return updateApp(app); } Comms.uploadApp(app).then((appJSON) => { - Progress.hide({ sticky: true }) + Progress.hide({ sticky: true }); if (appJSON) { - appsInstalled.push(appJSON) + appsInstalled.push(appJSON); } - showToast(app.name + ' Uploaded!', 'success') + showToast(app.name + ' Uploaded!', 'success'); }).catch(err => { - Progress.hide({ sticky: true }) - showToast('Upload failed, ' + err, 'error') + Progress.hide({ sticky: true }); + showToast('Upload failed, ' + err, 'error'); }).finally(()=>{ refreshMyApps(); refreshLibrary(); @@ -286,8 +314,8 @@ function removeApp(app) { return showPrompt("Delete","Really remove '"+app.name+"'?").then(() => { return getInstalledApps().then(()=>{ // a = from appid.info, app = from apps.json - return Comms.removeApp(appsInstalled.find(a => a.id === app.id)) - }) + return Comms.removeApp(appsInstalled.find(a => a.id === app.id)); + }); }).then(()=>{ appsInstalled = appsInstalled.filter(a=>a.id!=app.id); showToast(app.name+" removed successfully","success"); @@ -315,13 +343,13 @@ function updateApp(app) { if (app.custom) return customApp(app); return getInstalledApps().then(() => { // a = from appid.info, app = from apps.json - let remove = appsInstalled.find(a => a.id === app.id) + let remove = appsInstalled.find(a => a.id === app.id); // no need to remove files which will be overwritten anyway remove.files = remove.files.split(',') .filter(f => f !== app.id + '.info') .filter(f => !app.storage.some(s => s.name === f)) - .join(',') - return Comms.removeApp(remove) + .join(','); + return Comms.removeApp(remove); }).then(()=>{ showToast(`Updating ${app.name}...`); appsInstalled = appsInstalled.filter(a=>a.id!=app.id); @@ -397,7 +425,7 @@ return `
// check icon to figure out what we should do if (icon.classList.contains("icon-delete")) removeApp(app); if (icon.classList.contains("icon-refresh")) updateApp(app); - if (icon.classList.contains("icon-download")) handleAppInterface(app) + if (icon.classList.contains("icon-download")) handleAppInterface(app); }); }); } @@ -405,7 +433,7 @@ return `
let haveInstalledApps = false; function getInstalledApps(refresh) { if (haveInstalledApps && !refresh) { - return Promise.resolve(appsInstalled) + return Promise.resolve(appsInstalled); } showLoadingIndicator("myappscontainer"); // Get apps and files @@ -453,7 +481,7 @@ filtersContainer.addEventListener('click', ({ target }) => { activeFilter = target.getAttribute('filterid') || ''; refreshFilter(); refreshLibrary(); - window.location.hash = activeFilter + window.location.hash = activeFilter; }); var librarySearchInput = document.querySelector("#searchform input"); @@ -526,7 +554,7 @@ document.getElementById("installdefault").addEventListener("click",event=>{ upload(); }).catch(function() { Progress.hide({sticky:true}); - reject() + reject(); }); } upload(); @@ -541,3 +569,48 @@ document.getElementById("installdefault").addEventListener("click",event=>{ showToast("App Install failed, "+err,"error"); }); }); + +// 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=>{ + Progress.hide({sticky:true}); + showToast("App Install failed, "+err,"error"); + }); +}); + diff --git a/js/ui.js b/js/ui.js index 616a92555..ea6885eac 100644 --- a/js/ui.js +++ b/js/ui.js @@ -86,6 +86,7 @@ function showToast(message, type) { var style = "toast-primary"; if (type=="success") style = "toast-success"; else if (type=="error") style = "toast-error"; + else if (type=="warning") style = "toast-warning"; else if (type!==undefined) console.log("showToast: unknown toast "+type); var toastcontainer = document.getElementById("toastcontainer"); var msgDiv = htmlElement(`
`); diff --git a/js/utils.js b/js/utils.js index 85b6eb0a1..4913c7129 100644 --- a/js/utils.js +++ b/js/utils.js @@ -67,3 +67,16 @@ 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 b84d0446a87f86ffc2c1f7eee5a695a3b863f19d Mon Sep 17 00:00:00 2001 From: Fabio Date: Tue, 14 Apr 2020 09:08:26 +0200 Subject: [PATCH 0372/1189] New game Snake! --- apps.json | 13 ++++ apps/snake/ChangeLog | 1 + apps/snake/README.md | 13 ++++ apps/snake/snake-icon.js | 1 + apps/snake/snake.js | 144 +++++++++++++++++++++++++++++++++++++++ apps/snake/snake.png | Bin 0 -> 2337 bytes 6 files changed, 172 insertions(+) create mode 100644 apps/snake/ChangeLog create mode 100644 apps/snake/README.md create mode 100644 apps/snake/snake-icon.js create mode 100644 apps/snake/snake.js create mode 100644 apps/snake/snake.png diff --git a/apps.json b/apps.json index 56a6b69d3..dc9d47c2c 100644 --- a/apps.json +++ b/apps.json @@ -1171,5 +1171,18 @@ {"name":"bledetect.app.js","url":"bledetect.js"}, {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} ] + }, + { "id": "snake", + "name": "Snake", + "shortName":"Snake", + "icon": "snake.png", + "version":"0.01", + "description": "The classic snake game. Eat apples and don't bite your tail:", + "tags": "game,fun", + "readme": "README.md", + "storage": [ + {"name":"snake.app.js","url":"snake.js"}, + {"name":"snake.img","url":"snake-icon.js","evaluate":true} + ] } ] diff --git a/apps/snake/ChangeLog b/apps/snake/ChangeLog new file mode 100644 index 000000000..2286a7f70 --- /dev/null +++ b/apps/snake/ChangeLog @@ -0,0 +1 @@ +0.01: New App! \ No newline at end of file diff --git a/apps/snake/README.md b/apps/snake/README.md new file mode 100644 index 000000000..7860dbd88 --- /dev/null +++ b/apps/snake/README.md @@ -0,0 +1,13 @@ +# Snake + +![Screenshot](https://i.ibb.co/XzWrvPL/screenshot.png) + +The legentary classic game is now available on Bangle.js! +Eat apples and don't bite your tail. + +## Controls + +- UP: BTN1 +- DOWN: BTN3 +- LEFT: BTN4 +- RIGHT: BTN5 diff --git a/apps/snake/snake-icon.js b/apps/snake/snake-icon.js new file mode 100644 index 000000000..305061003 --- /dev/null +++ b/apps/snake/snake-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4A/ADE3m9hsIusrdhGIM3LtU3g0GAgQxlEwIqBmEAgEGF4QwkF4c3F4MxF4dbF8qLDrYHDre74IABF8QwBLoaPDF8wPKF96/jF/4v/F/4vrrc3AIQsnsIAKF94wiFxgv/R//+m4ABrYALBwIpYFwwAQLC4v/F7gXGF91hACovWFqwwUF4VbF7IwUFzSRVF1gwCF9wwZFyoA/AH4A/AH4A/AGg=")) \ No newline at end of file diff --git a/apps/snake/snake.js b/apps/snake/snake.js new file mode 100644 index 000000000..37b461596 --- /dev/null +++ b/apps/snake/snake.js @@ -0,0 +1,144 @@ +const H = g.getWidth(); +const W = g.getHeight(); +let running = true; +let score = 0; +let d; + +// game world +const gridSize = 40; +const tileSize = 6; +let nextX = 0; +let nextY = 0; + +// snake +const defaultTailSize = 3; +let tailSize = defaultTailSize; +const snakeTrail = []; +let snakeX = 10; +let snakeY = 10; + +// apple +let appleX = Math.floor(Math.random() * gridSize); +let appleY = Math.floor(Math.random() * gridSize); + +function gameStart() { + running = true; + score = 0; +} + +function gameStop() { + g.clear(); + g.setColor("#FFFFFF"); + g.setFont("6x8", 2); + g.drawString("GAME OVER!", W / 2, H / 2 - 20); + g.drawString("Tap to Restart", W / 2, H / 2 + 20); + running = false; + tailSize = defaultTailSize; +} + +function draw() { + if (!running) { + return; + } + + // move snake in next pos + snakeX += nextX; + snakeY += nextY; + + // snake over game world? + if (snakeX < 0) { + snakeX = gridSize - 1; + } + + if (snakeX > gridSize - 1) { + snakeX = 0; + } + + if (snakeY < 0) { + snakeY = gridSize - 1; + } + if (snakeY > gridSize - 1) { + snakeY = 0; + } + + //snake bite apple? + if (snakeX === appleX && snakeY === appleY) { + tailSize++; + score++; + + appleX = Math.floor(Math.random() * gridSize); + appleY = Math.floor(Math.random() * gridSize); + } + + //paint background + g.setColor("#000000"); + g.fillRect(0, 0, H, W); + + // paint snake + g.setColor("#008000"); + + for (let i = 0; i < snakeTrail.length; i++) { + g.fillRect(snakeTrail[i].x * tileSize, snakeTrail[i].y * tileSize, snakeTrail[i].x * tileSize + tileSize, snakeTrail[i].y * tileSize + tileSize); + + //snake bites it's tail? + if (snakeTrail[i].x === snakeX && snakeTrail[i].y === snakeY && tailSize > defaultTailSize) { + gameStop(); + } + } + + // paint apple + g.setColor("#FF0000"); + g.fillRect(appleX * tileSize, appleY * tileSize, appleX * tileSize + tileSize, appleY * tileSize + tileSize); + + // paint score + g.setColor("#FFFFFF"); + g.setFont("6x8"); + g.setFontAlign(0, 0); + g.drawString("Score:" + score, W / 2, 10); + + //set snake trail + snakeTrail.push({ x: snakeX, y: snakeY }); + while (snakeTrail.length > tailSize) { + snakeTrail.shift(); + } +} + +// input +setWatch(() => {// Up + if (d !== 'd') { + nextX = 0; + nextY = -1; + d = 'u'; + } +}, BTN1, { repeat: true }); +setWatch(() => {// Down + if (d !== 'u') { + nextX = 0; + nextY = 1; + d = 'd'; + } +}, BTN3, { repeat: true }); +setWatch(() => {// Left + if (d !== 'r') { + nextX = -1; + nextY = 0; + d = 'l'; + } +}, BTN4, { repeat: true }); +setWatch(() => {// Right + if (d !== 'l') { + nextX = 1; + nextY = 0; + d = 'r'; + } +}, BTN5, { repeat: true }); + +Bangle.on('touch', button => { + if (!running) { + gameStart(); + } +}); + +// render X times per second +var x = 5; +setInterval(draw, 1000 / x); \ No newline at end of file diff --git a/apps/snake/snake.png b/apps/snake/snake.png new file mode 100644 index 0000000000000000000000000000000000000000..04564a8f77dad377b2dd2dd0a50561ca582bc6fb GIT binary patch literal 2337 zcmaJ@dpuNWAD`rwUb~B2QaBxEcE)AKV1}6n;ml;b#$_m8DaOpfe3*-wgFzRhTq@Sa zOB-^J-dI`6t?W{5Yg1ApOBX4ds3;*~N2PuLcze%t&Ur4M@Avz={_&)Hd2Cl#(^o^G zQ0h!qh%KKjS3Xr``QJ}rK2<(#MCksAk0=z0;LFx_5a9FdK|d19k|lP5 z!}+f964)o+!gS*q7}hX{*o<-HdGRsYGn(2dO*1~2``k& zh8Ul0$#?c(ID&|&1VU_VEI!s6FOq~2h!hHCMZ?O z`#*)HzHwrhz=oxwXbD$dxKQI2Q(~%%1m++jiLXc$xtc|cVg#Su?C4Tgb_lNTfSaY)A~q$=TV)#@d-q zX4tNBArUuP01J^-F7IzH{fpd{RuG8gmLXWekAZm%iAVr^2${n<(toq4-4hpE|Ir2*+9Jsg;L68LQcN2!HIwE3J;{~ zEj=BInVkszDbI#qUW3_@u6xF}tpN}isj6-ci?>p%-uv#0~Qd2!is z*7siT5k{9y$1>8*DX6C9fx?};K6e(ikYzTKLdfA#R$Wa;(T`7M>f4G!T| zh1{1+b;43Hw_Fe}3YeOoda7!J+qF)m`DVflS-oho^W`wuC<%KZglNE%`hwU*l^=)5b&HH6?|!yCmjl4NoGp3Jrz zK3&=R|L*fBXnLjlBC2Pp4ysT*rLyLVl$N2S zcLqYoz03Q{AKebT@(8@K>v&?t&thaic^6IL(qrTM+1ncI-2@_x?T+j&Z7JP!Bdu$G z++4Hv3FzDvmQW9pG`!vBBCN1J)2AIvr#4r&Wj(@IXy}$`esi~!NoU!u2yX|Sp%0a`%MFS(NLxL2BkB#T__BFwmVICPxsE5 zZ=beodpv-J&SxswVk&lVH*kc=guZjDjZ|swM%CPS ztF#fSh)=E5bKIIa9saDNo*O_;F<3jQqaC31jCyvQt#Gd>vtZFK=sPC{=JoM>Kmlw` zvUtG=P3!X8?|;gH>b*cx8?v8oXT;~1ny0PV$W0x47l!yadQ65@o3;BZ#%S)z=Q=$= zPvoJKqABR4f#%#scQ~RNXL@sMdA5vnIQeXvPS3RSd~3==+9Cn-?e9lMA`ci}YQ&6p zjF%2OtBJ~O63WSr$wLJyTk2R?&pA5Qh^be8HlsH@{nmD9^h8NvVqj2Tss3Qg_w^gr zv1^pKh&?AM0LC3T|I78u*_*Cu|MO7wgS5+q9IU6*^Ok}UtLBEQad+eGAbe6^qo$o8 z)Lkz<4LkUii62JPZ#>wt{&``gs@Sk1_kBQLu9nBWxYQO2N24mWSLfX|o%%ak4R;n& zvM@iobzgMaegE9?y~?|O^BS?5@a~9@;^-%$TZnz7Y!Yb&TvS8FRdLpEsvaP*JALrMJqvYUZGj;WIy+%C0f9NL#dDXo@ z%*STaf8tK_FlOCXw4%b^#SBzj&Vxd#XgdczPTuVfCEtKZEvn0v2ADRqM{!a}`^ Date: Tue, 14 Apr 2020 10:47:39 +0100 Subject: [PATCH 0373/1189] remove un-needed file --- apps/calculator/calculator.info | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/calculator/calculator.info diff --git a/apps/calculator/calculator.info b/apps/calculator/calculator.info deleted file mode 100644 index e8a760024..000000000 --- a/apps/calculator/calculator.info +++ /dev/null @@ -1 +0,0 @@ -{"name":"Calculator","src":"calculator.app.js","icon":"calculator.img"} From bf1eed04ae4d423fef022189a93ac763b2fec0ca Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 14 Apr 2020 13:55:36 +0200 Subject: [PATCH 0374/1189] Remove unused settings variable --- apps/batchart/widget.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index de7ce230d..19cbd054c 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -1,5 +1,7 @@ (() => { - var switchableConsumers = { + const Storage = require("Storage"); + + const switchableConsumers = { none: 0, lcd: 1, compass: 2, @@ -8,7 +10,6 @@ hrm: 16 }; - var settings = {}; var batChartFile; // file for battery percentage recording const recordingInterval10Min = 60 * 10 * 1000; const recordingInterval1Min = 60*1000; //For testing @@ -49,11 +50,11 @@ // Change log target on day change if (previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago - require("Storage").erase(logFileName); - require("Storage").write(previousWriteLogName, currentWriteDay); + Storage.open(logFileName, "r")­.erase(); + Storage.write(previousWriteLogName, currentWriteDay); } - var bcLogFileA = require("Storage").open(logFileName, "a"); + var bcLogFileA = Storage.open(logFileName, "a"); if (bcLogFileA) { console.log([getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")); bcLogFileA.write([[getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")].join(",")+"\n"); From 4644fe4baf2005dacf792bfa9a56780f3748209d Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 14 Apr 2020 14:02:03 +0200 Subject: [PATCH 0375/1189] Fixes removal of listeners --- apps/batchart/widget.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 1fdbfe1c9..c45515fe5 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -20,8 +20,6 @@ var gpsEventReceived = false; var hrmEventReceived = false; - const Storage = require("Storage"); - // draw your widget function draw() { g.reset(); @@ -34,7 +32,6 @@ Bangle.on('mag', (() => { console.log("mag received"); compassEventReceived = true; - Bangle.on("mag", () => {}); })); Bangle.on('GPS', (() => { @@ -49,9 +46,7 @@ // Wait two seconds, that should be enough for each of the events to get raised once setTimeout(() => { - Bangle.on('mag', () => {}); - Bangle.on('GPS', () => {}); - Bangle.on('HRM', () => {}); + Bangle.removeAllListeners; }, 2000); if (Bangle.isLCDOn()) From 22a005203febe6c7d9bff8a10f06627360474598 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 14 Apr 2020 15:56:12 +0100 Subject: [PATCH 0376/1189] Use BTN2 for settings menu like other clocks --- apps.json | 6 +++--- apps/numerals/ChangeLog | 1 + apps/numerals/numerals.app.js | 14 +++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps.json b/apps.json index 47618e1a8..e278df965 100644 --- a/apps.json +++ b/apps.json @@ -1191,7 +1191,7 @@ "name": "Numerals Clock", "shortName": "Numerals Clock", "icon": "numerals.png", - "version":"0.01", + "version":"0.02", "description": "A simple big numerals clock", "tags": "numerals,clock", "type":"clock", @@ -1209,7 +1209,7 @@ "version":"0.02", "description": "Detect BLE devices and show some informations.", "tags": "app,bluetooth,tool", - "readme": "README.md", + "readme": "README.md", "storage": [ {"name":"bledetect.app.js","url":"bledetect.js"}, {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} @@ -1222,7 +1222,7 @@ "version":"0.01", "description": "The classic snake game. Eat apples and don't bite your tail:", "tags": "game,fun", - "readme": "README.md", + "readme": "README.md", "storage": [ {"name":"snake.app.js","url":"snake.js"}, {"name":"snake.img","url":"snake-icon.js","evaluate":true} diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index 5560f00bc..a8396e26b 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Use BTN2 for settings menu like other clocks diff --git a/apps/numerals/numerals.app.js b/apps/numerals/numerals.app.js index 648a1005a..fbfe5b9ed 100644 --- a/apps/numerals/numerals.app.js +++ b/apps/numerals/numerals.app.js @@ -11,7 +11,7 @@ var numerals = { 1:[[59,1,82,1,90,9,90,82,82,90,73,90,65,82,65,27,59,27,51,19,51,9,59,1]], 2:[[9,1,82,1,90,9,90,47,82,55,21,55,21,64,82,64,90,72,90,82,82,90,9,90,1,82,1,43,9,35,70,35,70,25,9,25,1,17,1,9,9,1]], 3:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,74,9,66,70,66,70,57,9,57,1,49,1,41,9,33,70,33,70,25,9,25,1,17,1,9,9,1]], - 4:[[9,1,14,1,22,9,22,34,69,34,69,9,77,1,82,1,90,9,90,82,82,90,78,90,70,82,70,55,9,55,1,47,1,9,9,1]], + 4:[[9,1,14,1,22,9,22,34,69,34,69,9,77,1,82,1,90,9,90,82,82,90,78,90,70,82,70,55,9,55,1,47,1,9,9,1]], 5:[[9,1,82,1,90,9,90,17,82,25,21,25,21,35,82,35,90,43,90,82,82,90,9,90,1,82,1,72,9,64,71,64,71,55,9,55,1,47,1,9,9,1]], 6:[[9,1,82,1,90,9,90,14,82,22,22,22,22,36,82,36,90,44,90,82,82,90,9,90,1,82,1,9,9,1],[22,55,69,55,69,69,22,69,22,55]], 7:[[9,1,82,1,90,9,90,15,15,90,9,90,1,82,1,76,54,23,9,23,1,15,1,9,9,1]], @@ -47,7 +47,7 @@ if (!settings) { function drawNum(num,col,x,y,func){ g.setColor(col); let tx = x*100+35; - let ty = y*100+35; + let ty = y*100+35; for (let i=0;i0) g.setColor((func==fill)?"#000000":col); func(translate(tx, ty,numerals[num][i])); @@ -57,7 +57,7 @@ function drawNum(num,col,x,y,func){ function draw(drawMode){ let d = new Date(); let h1 = Math.floor(d.getHours()/10); - let h2 = d.getHours()%10; + let h2 = d.getHours()%10; let m1 = Math.floor(d.getMinutes()/10); let m2 = d.getMinutes()%10; g.clearRect(0,24,240,240); @@ -70,9 +70,9 @@ function draw(drawMode){ Bangle.setLCDMode(); clearWatch(); -setWatch(Bangle.showLauncher, BTN1, {repeat:false,edge:"falling"}); +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); -g.clear(); +g.clear(); clearInterval(); if (settings.color>0) _rCol=settings.color-1; interval=setInterval(draw, REFRESH_RATE, settings.drawMode); @@ -80,7 +80,7 @@ draw(settings.drawMode); Bangle.on('lcdPower', function(on) { if (on) { - if (settings.color==0) _rCol = Math.floor(Math.random()*_hCol.length); + if (settings.color==0) _rCol = Math.floor(Math.random()*_hCol.length); draw(settings.drawMode); interval=setInterval(draw, REFRESH_RATE, settings.drawMode); }else @@ -90,4 +90,4 @@ Bangle.on('lcdPower', function(on) { }); Bangle.loadWidgets(); -Bangle.drawWidgets(); \ No newline at end of file +Bangle.drawWidgets(); From d54c0c7dea9dcf2d944f1ecd10a64fa7d50984f9 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 14 Apr 2020 16:11:29 +0100 Subject: [PATCH 0377/1189] 0.14: Reduce memory usage when running app settings page --- apps.json | 2 +- apps/setting/ChangeLog | 3 ++- apps/setting/settings.js | 6 ++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index e278df965..21fdf09b2 100644 --- a/apps.json +++ b/apps.json @@ -119,7 +119,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.13", + "version":"0.14", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 5c5a26c61..6c4c19230 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -14,4 +14,5 @@ Move LCD Timeout to wakeup menu 0.13: Fix memory leak for App settings Make capitalization more consistent - Move LCD Brightness menu into more general LCD menu \ No newline at end of file + Move LCD Brightness menu into more general LCD menu +0.14: Reduce memory usage when running app settings page diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 71a6a181e..d0d6578dc 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -325,8 +325,6 @@ function showClockMenu() { return E.showMenu(clockMenu); } - - function showSetTimeMenu() { d = new Date(); const timemenu = { @@ -419,8 +417,8 @@ function showAppSettingsMenu() { '< Back': ()=>showMainMenu(), } const apps = storage.list(/\.info$/) - .map(app => storage.readJSON(app, 1)) - .filter(app => app && app.settings) + .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?a:undefined}) + .filter(app => app) // filter out any undefined apps .sort((a, b) => a.sortorder - b.sortorder) if (apps.length === 0) { appmenu['No app has settings'] = () => { }; From 1d371db91622e6a29ab3d8e8b7c5b8f48bb3088e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 14 Apr 2020 16:11:43 +0100 Subject: [PATCH 0378/1189] Don't send double char code 16 when uploading --- js/comms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/comms.js b/js/comms.js index 12989e089..604ef19ed 100644 --- a/js/comms.js +++ b/js/comms.js @@ -40,7 +40,7 @@ uploadApp : (app,skipReset) => { // expects an apps.json structure (i.e. with `s currentBytes += f.content.length; // Chould check CRC here if needed instead of returning 'OK'... // E.CRC32(require("Storage").read(${JSON.stringify(app.name)})) - Puck.write(`\x10${f.cmd};Bluetooth.println("OK")\n`,(result) => { + Puck.write(`${f.cmd};Bluetooth.println("OK")\n`,(result) => { if (!result || result.trim()!="OK") { Progress.hide({sticky:true}); return reject("Unexpected response "+(result||"")); From 9f8747a797a07cc9002af8289d376e29a9250240 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 14 Apr 2020 16:15:43 +0100 Subject: [PATCH 0379/1189] Version number now clickable even when you're at the latest version (fix #291) --- CHANGELOG.md | 5 +++-- js/utils.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6368c2c46..9480f2ace 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,5 +6,6 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * `Remove All Apps` now doesn't perform a reset before erase - fixes inability to update firmware if settings are wrong * Added optional `README.md` file for apps * Remove 2v04 version warning, add links in About to official/developer versions -* Fix issue removing an app that was just installed (Fix #253) -* Add `Favourite` functionality +* Fix issue removing an app that was just installed (fix #253) +* Add `Favourite` functionality +* Version number now clickable even when you're at the latest version (fix #291) diff --git a/js/utils.js b/js/utils.js index 4913c7129..d8c1b8063 100644 --- a/js/utils.js +++ b/js/utils.js @@ -56,7 +56,7 @@ function getVersionInfo(appListing, appInstalled) { if (appListing.version) versionText = clicky("v"+appListing.version); } else { - versionText = (appInstalled.version ? ("v"+appInstalled.version) : "Unknown version"); + versionText = (appInstalled.version ? (clicky("v"+appInstalled.version)) : "Unknown version"); if (appListing.version != appInstalled.version) { if (appListing.version) versionText += ", latest "+clicky("v"+appListing.version); canUpdate = true; From f88f8756949b2b2742f2930dd6085989a8aeb394 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 17:29:24 +0200 Subject: [PATCH 0380/1189] Fixes eventhandlers for batchart widget --- apps/batchart/widget.js | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index c45515fe5..9b5a53c4e 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -26,23 +26,28 @@ g.drawString("BC", this.x, this.y); } + function onMag(){ + compassEventReceived = true; + // Stop handling events when no longer necessarry + Bangle.removeListener("mag", onMag); + } + + function onGps() { + gpsEventReceived = true; + Bangle.removeListener("GPS", onGps); + } + + function onHrm() { + gpsEventReceived = true; + Bangle.removeListener("HRM", onHrm); + } + function getEnabledConsumersValue() { var enabledConsumers = switchableConsumers.none; - Bangle.on('mag', (() => { - console.log("mag received"); - compassEventReceived = true; - })); - - Bangle.on('GPS', (() => { - console.log("GPS received"); - gpsEventReceived = true; - })); - - Bangle.on('HRM', (() => { - console.log("HRM received"); - hrmEventReceived = true; - })); + Bangle.on('mag', onMag); + Bangle.on('GPS', onGps); + Bangle.on('HRM', onHrm); // Wait two seconds, that should be enough for each of the events to get raised once setTimeout(() => { @@ -66,8 +71,6 @@ gpsEventReceived = false; hrmEventReceived = false; - console.log("Enabled: " + enabledConsumers); - return enabledConsumers; } From 9daf178fc1c5e95a99a3ae9c871e9848a54419c0 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 17:30:10 +0200 Subject: [PATCH 0381/1189] Fixes consumer indicators and adds home button --- apps/batchart/app.js | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/batchart/app.js b/apps/batchart/app.js index 569fecfd1..b81c38790 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -142,7 +142,7 @@ function renderData(dataArray) { g.setPixel(GraphXZero + i, GraphYZero - scaledTemp); // LCD state - if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.lcd == switchableConsumers.lcd) { + if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.lcd) { g.setColor(1, 1, 1); g.setFontAlign(1, -1, 0); g.drawString("LCD", GraphXZero - GraphMarkerOffset, GraphLcdY - 2, true); @@ -150,7 +150,7 @@ function renderData(dataArray) { } // Compass state - if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.compass) { g.setColor(0, 1, 0); g.setFontAlign(-1, -1, 0); g.drawString("Compass", GraphXMax + GraphMarkerOffset, GraphCompassY - 2, true); @@ -166,7 +166,7 @@ function renderData(dataArray) { // } // Gps state - if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.gps) { g.setColor(0.8, 0.5, 0.24); g.setFontAlign(-1, -1, 0); g.drawString("GPS", GraphXMax + GraphMarkerOffset, GraphGpsY - 2, true); @@ -174,7 +174,7 @@ function renderData(dataArray) { } // Hrm state - if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { + if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.hrm) { g.setColor(1, 0, 0); g.setFontAlign(1, -1, 0); g.drawString("HRM", GraphXZero - GraphMarkerOffset, GraphHrmY - 2, true); @@ -185,6 +185,16 @@ function renderData(dataArray) { dataArray = null; } +function renderHomeIcon() { + //Home for Btn2 + g.setColor(1, 1, 1); + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); + + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); +} + function renderBatteryChart() { renderCoordinateSystem(); let data = loadData(); @@ -192,21 +202,30 @@ function renderBatteryChart() { data = null; } +// Show launcher when middle button pressed +function switchOffApp(){ + Bangle.showLauncher(); +} + // special function to handle display switch on Bangle.on('lcdPower', (on) => { if (on) { // call your app function here // If you clear the screen, do Bangle.drawWidgets(); - g.clear() + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); renderBatteryChart(); } }); +setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true}); + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); // call your app function here +renderHomeIcon(); + renderBatteryChart(); From 63dbed0e3c11e9a52106bfe4ce675720f1a9feb0 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 17:31:37 +0200 Subject: [PATCH 0382/1189] Updates BatChart version --- apps.json | 2 +- apps/batchart/ChangeLog | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 47618e1a8..22a6f5500 100644 --- a/apps.json +++ b/apps.json @@ -1164,7 +1164,7 @@ "name": "Battery Chart", "shortName":"Battery Chart", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index f57805b6a..7a0ce429b 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -2,4 +2,5 @@ 0.02: Widget stores data to file (1 dataset/10min) 0.03: Rotate log files once a week. 0.04: chart in the app is now active. -0.05: Display temperature and LCD state in chart \ No newline at end of file +0.05: Display temperature and LCD state in chart +0.06: Fixes widget events and charting of component states \ No newline at end of file From 24cfc840e0f2d3d4fbed3d3b27b3eddda0eb2015 Mon Sep 17 00:00:00 2001 From: Fabio Date: Tue, 14 Apr 2020 17:43:12 +0200 Subject: [PATCH 0383/1189] Improvements of snake game --- apps.json | 2 +- apps/snake/ChangeLog | 3 +- apps/snake/README.md | 3 +- apps/snake/snake.js | 129 +++++++++++++++++++++++-------------------- 4 files changed, 75 insertions(+), 62 deletions(-) diff --git a/apps.json b/apps.json index 47618e1a8..1f168e771 100644 --- a/apps.json +++ b/apps.json @@ -1219,7 +1219,7 @@ "name": "Snake", "shortName":"Snake", "icon": "snake.png", - "version":"0.01", + "version":"0.02", "description": "The classic snake game. Eat apples and don't bite your tail:", "tags": "game,fun", "readme": "README.md", diff --git a/apps/snake/ChangeLog b/apps/snake/ChangeLog index 2286a7f70..428718739 100644 --- a/apps/snake/ChangeLog +++ b/apps/snake/ChangeLog @@ -1 +1,2 @@ -0.01: New App! \ No newline at end of file +0.01: New App! +0.02: Performance and graphic improvements, game pause, beep and buzz \ No newline at end of file diff --git a/apps/snake/README.md b/apps/snake/README.md index 7860dbd88..483eae7a9 100644 --- a/apps/snake/README.md +++ b/apps/snake/README.md @@ -1,6 +1,6 @@ # Snake -![Screenshot](https://i.ibb.co/XzWrvPL/screenshot.png) +![Screenshot](https://i.imgur.com/bXQjxhB.png) The legentary classic game is now available on Bangle.js! Eat apples and don't bite your tail. @@ -11,3 +11,4 @@ Eat apples and don't bite your tail. - DOWN: BTN3 - LEFT: BTN4 - RIGHT: BTN5 +- PAUSE: BTN2 diff --git a/apps/snake/snake.js b/apps/snake/snake.js index 37b461596..4532e0113 100644 --- a/apps/snake/snake.js +++ b/apps/snake/snake.js @@ -1,37 +1,61 @@ +Bangle.setLCDMode("120x120"); + const H = g.getWidth(); const W = g.getHeight(); let running = true; let score = 0; let d; - -// game world -const gridSize = 40; +const gridSize = 20; const tileSize = 6; let nextX = 0; let nextY = 0; - -// snake const defaultTailSize = 3; let tailSize = defaultTailSize; const snakeTrail = []; -let snakeX = 10; -let snakeY = 10; +const snake = { x: 10, y: 10 }; +const apple = { x: Math.floor(Math.random() * gridSize), y: Math.floor(Math.random() * gridSize) }; -// apple -let appleX = Math.floor(Math.random() * gridSize); -let appleY = Math.floor(Math.random() * gridSize); +function drawBackground(){ + g.setColor("#000000"); + g.fillRect(0, 0, H, W); +} + +function drawApple(){ + g.setColor("#FF0000"); + g.fillCircle((apple.x * tileSize) + tileSize/2, (apple.y * tileSize) + tileSize/2, tileSize/2); +} + +function drawSnake(){ + g.setColor("#008000"); + for (let i = 0; i < snakeTrail.length; i++) { + g.fillRect(snakeTrail[i].x * tileSize, snakeTrail[i].y * tileSize, snakeTrail[i].x * tileSize + tileSize, snakeTrail[i].y * tileSize + tileSize); + + //snake bites it's tail + if (snakeTrail[i].x === snake.x && snakeTrail[i].y === snake.y && tailSize > defaultTailSize) { + Bangle.buzz(1000); + gameOver(); + } + } +} + +function drawScore(){ + g.setColor("#FFFFFF"); + g.setFont("6x8"); + g.setFontAlign(0, 0); + g.drawString("Score:" + score, W / 2, 10); +} function gameStart() { running = true; score = 0; } -function gameStop() { +function gameOver() { g.clear(); g.setColor("#FFFFFF"); - g.setFont("6x8", 2); - g.drawString("GAME OVER!", W / 2, H / 2 - 20); - g.drawString("Tap to Restart", W / 2, H / 2 + 20); + g.setFont("6x8"); + g.drawString("GAME OVER!", W / 2, H / 2 - 10); + g.drawString("Tap to Restart", W / 2, H / 2 + 10); running = false; tailSize = defaultTailSize; } @@ -41,66 +65,50 @@ function draw() { return; } + g.clear(); + // move snake in next pos - snakeX += nextX; - snakeY += nextY; + snake.x += nextX; + snake.y += nextY; - // snake over game world? - if (snakeX < 0) { - snakeX = gridSize - 1; + // snake over game world + if (snake.x < 0) { + snake.x = gridSize - 1; + } + if (snake.x > gridSize - 1) { + snake.x = 0; } - if (snakeX > gridSize - 1) { - snakeX = 0; + if (snake.y < 0) { + snake.y = gridSize - 1; + } + if (snake.y > gridSize - 1) { + snake.y = 0; } - if (snakeY < 0) { - snakeY = gridSize - 1; - } - if (snakeY > gridSize - 1) { - snakeY = 0; - } - - //snake bite apple? - if (snakeX === appleX && snakeY === appleY) { + //snake bite apple + if (snake.x === apple.x && snake.y === apple.y) { + Bangle.beep(20); tailSize++; score++; - appleX = Math.floor(Math.random() * gridSize); - appleY = Math.floor(Math.random() * gridSize); + apple.x = Math.floor(Math.random() * gridSize); + apple.y = Math.floor(Math.random() * gridSize); + drawApple(); } - //paint background - g.setColor("#000000"); - g.fillRect(0, 0, H, W); - - // paint snake - g.setColor("#008000"); - - for (let i = 0; i < snakeTrail.length; i++) { - g.fillRect(snakeTrail[i].x * tileSize, snakeTrail[i].y * tileSize, snakeTrail[i].x * tileSize + tileSize, snakeTrail[i].y * tileSize + tileSize); - - //snake bites it's tail? - if (snakeTrail[i].x === snakeX && snakeTrail[i].y === snakeY && tailSize > defaultTailSize) { - gameStop(); - } - } - - // paint apple - g.setColor("#FF0000"); - g.fillRect(appleX * tileSize, appleY * tileSize, appleX * tileSize + tileSize, appleY * tileSize + tileSize); - - // paint score - g.setColor("#FFFFFF"); - g.setFont("6x8"); - g.setFontAlign(0, 0); - g.drawString("Score:" + score, W / 2, 10); + drawBackground(); + drawApple(); + drawSnake(); + drawScore(); //set snake trail - snakeTrail.push({ x: snakeX, y: snakeY }); + snakeTrail.push({ x: snake.x, y: snake.y }); while (snakeTrail.length > tailSize) { snakeTrail.shift(); } + + g.flip(); } // input @@ -132,6 +140,9 @@ setWatch(() => {// Right d = 'r'; } }, BTN5, { repeat: true }); +setWatch(() => {// Pause + running = !running; +}, BTN2, { repeat: true }); Bangle.on('touch', button => { if (!running) { @@ -140,5 +151,5 @@ Bangle.on('touch', button => { }); // render X times per second -var x = 5; +const x = 5; setInterval(draw, 1000 / x); \ No newline at end of file From e1342857284da2d6cc33b94c0fb8b22c4d9a9d9d Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 17:46:59 +0200 Subject: [PATCH 0384/1189] Fixes . error --- apps/batchart/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 9b5a53c4e..610da4017 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -84,7 +84,7 @@ // Change log target on day change if (previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago - Storage.open(logFileName, "r")­.erase(); + Storage.open(logFileName, "r").erase(); Storage.write(previousWriteLogName, currentWriteDay); } From 758b2e447e7e47b39bbf914a0f609d7adc6e0952 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 18:04:02 +0200 Subject: [PATCH 0385/1189] Fixes event registration --- apps/batchart/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 610da4017..7c4762649 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -38,7 +38,7 @@ } function onHrm() { - gpsEventReceived = true; + hrmEventReceived = true; Bangle.removeListener("HRM", onHrm); } From 3cc63e2a3e385cc32b4c12f6f114ef4bcb7f7a88 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 18:33:56 +0200 Subject: [PATCH 0386/1189] Fix data recording file retrieval --- apps/batchart/widget.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 7c4762649..0565f4160 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -1,3 +1,5 @@ +WIDGETS = {}; + (() => { const Storage = require("Storage"); @@ -76,7 +78,7 @@ function logBatteryData() { const previousWriteLogName = "bcprvday"; - const previousWriteDay = Storage.read(previousWriteLogName); + const previousWriteDay = parseInt(Storage.open(previousWriteLogName, "r").readLine()); const currentWriteDay = new Date().getDay(); const logFileName = "bclog" + currentWriteDay; @@ -85,7 +87,7 @@ if (previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago Storage.open(logFileName, "r").erase(); - Storage.write(previousWriteLogName, currentWriteDay); + Storage.open(previousWriteLogName, "w").write(parseInt(currentWriteDay)); } var bcLogFileA = Storage.open(logFileName, "a"); From f43b1e6ee394f5f49a21ae7261928d96c69ed8be Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 21:02:39 +0200 Subject: [PATCH 0387/1189] PrevDay lgging fixed --- apps/batchart/widget.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 0565f4160..2ef54e997 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -14,8 +14,8 @@ WIDGETS = {}; var batChartFile; // file for battery percentage recording const recordingInterval10Min = 60 * 10 * 1000; - const recordingInterval1Min = 60*1000; //For testing - const recordingInterval10S = 10*1000; //For testing + const recordingInterval1Min = 60*1000; //For testing + const recordingInterval10S = 10*1000; //For testing var recordingInterval = null; var compassEventReceived = false; @@ -67,7 +67,7 @@ WIDGETS = {}; enabledConsumers = enabledConsumers | switchableConsumers.hrm; //if (Bangle.isBluetoothOn()) // enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; - + // Reset the event registration vars compassEventReceived = false; gpsEventReceived = false; @@ -84,7 +84,8 @@ WIDGETS = {}; const logFileName = "bclog" + currentWriteDay; // Change log target on day change - if (previousWriteDay != currentWriteDay) { + if (previousWriteDay != NaN + && previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago Storage.open(logFileName, "r").erase(); Storage.open(previousWriteLogName, "w").write(parseInt(currentWriteDay)); @@ -110,6 +111,7 @@ WIDGETS = {}; reload(); Bangle.drawWidgets(); // relayout all widgets }}; + // load settings, set correct widget width reload(); })() \ No newline at end of file From 2299e283169f1668ebbaa179a721f194443a6310 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 21:11:52 +0200 Subject: [PATCH 0388/1189] Fix undefined topUpLines --- apps/batchart/app.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/batchart/app.js b/apps/batchart/app.js index b81c38790..deb406d8b 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -71,8 +71,11 @@ function loadData() { let topUpLogFileName = "bclog" + previousDay; let remainingLines = MaxValueCount - dataLines.length; let topUpLines = loadLinesFromFile(remainingLines, topUpLogFileName); - dataLines = topUpLines.concat(dataLines); - + + if(topUpLines) { + dataLines = topUpLines.concat(dataLines); + } + previousDay = decrementDay(previousDay); } From 935241d7c5aa5529d1211ba1cca2a3c5a480c199 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 21:20:09 +0200 Subject: [PATCH 0389/1189] Logstring changed --- apps/batchart/widget.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 2ef54e997..892c163fc 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -93,8 +93,10 @@ WIDGETS = {}; var bcLogFileA = Storage.open(logFileName, "a"); if (bcLogFileA) { - console.log([getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")); - bcLogFileA.write([[getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(",")].join(",")+"\n"); + let logString = [getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(","); + + console.log(logString); + bcLogFileA.write(logString + "\n"); } } From a798bb9dc664153243948f56ab9820ba8f007040 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Apr 2020 22:15:15 +0200 Subject: [PATCH 0390/1189] Improve logging and charting of component states and add widget icon --- apps.json | 2 +- apps/batchart/ChangeLog | 3 ++- apps/batchart/widget.js | 28 +++++++++++++++++++--------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index 22a6f5500..a191375cc 100644 --- a/apps.json +++ b/apps.json @@ -1164,7 +1164,7 @@ "name": "Battery Chart", "shortName":"Battery Chart", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index 7a0ce429b..ba9e4e847 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -3,4 +3,5 @@ 0.03: Rotate log files once a week. 0.04: chart in the app is now active. 0.05: Display temperature and LCD state in chart -0.06: Fixes widget events and charting of component states \ No newline at end of file +0.06: Fixes widget events and charting of component states +0.07: Improve logging and charting of component states and add widget icon \ No newline at end of file diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 892c163fc..53f8b3549 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -1,5 +1,3 @@ -WIDGETS = {}; - (() => { const Storage = require("Storage"); @@ -24,8 +22,16 @@ WIDGETS = {}; // draw your widget function draw() { + let x = this.x; + let y = this.y; + + g.setColor(0, 1, 0); + g.fillPoly([x+5, y, x+5, y+4, x+1, y+4, x+1, y+20, x+18, y+20, x+18, y+4, x+13, y+4, x+13, y], true); + + g.setColor(0,0,0); + g.drawPoly([x+5, y+6, x+8, y+12, x+13, y+12, x+16, y+18], false); + g.reset(); - g.drawString("BC", this.x, this.y); } function onMag(){ @@ -53,7 +59,7 @@ WIDGETS = {}; // Wait two seconds, that should be enough for each of the events to get raised once setTimeout(() => { - Bangle.removeAllListeners; + Bangle.removeAllListeners(); }, 2000); if (Bangle.isLCDOn()) @@ -73,7 +79,7 @@ WIDGETS = {}; gpsEventReceived = false; hrmEventReceived = false; - return enabledConsumers; + return enabledConsumers.toString(); } function logBatteryData() { @@ -84,7 +90,7 @@ WIDGETS = {}; const logFileName = "bclog" + currentWriteDay; // Change log target on day change - if (previousWriteDay != NaN + if (!isNaN(previousWriteDay) && previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago Storage.open(logFileName, "r").erase(); @@ -93,9 +99,13 @@ WIDGETS = {}; var bcLogFileA = Storage.open(logFileName, "a"); if (bcLogFileA) { - let logString = [getTime().toFixed(0), E.getBattery(), E.getTemperature(), getEnabledConsumersValue()].join(","); + let logTime = getTime().toFixed(0); + let logPercent = E.getBattery(); + let logTemperature = E.getTemperature(); + let logConsumers = getEnabledConsumersValue(); + + let logString = [logTime, logPercent, logTemperature, logConsumers].join(","); - console.log(logString); bcLogFileA.write(logString + "\n"); } } @@ -103,7 +113,7 @@ WIDGETS = {}; function reload() { WIDGETS["batchart"].width = 24; - recordingInterval = setInterval(logBatteryData, recordingInterval10S); + recordingInterval = setInterval(logBatteryData, recordingInterval10Min); logBatteryData(); } From 50d5ca7f7b70c892158335d3e26096a735898212 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 15 Apr 2020 01:04:45 +0200 Subject: [PATCH 0391/1189] welcome: don't run when settings are absent/updated Fixes #298 --- apps.json | 3 ++- apps/welcome/ChangeLog | 3 +++ apps/welcome/app.js | 7 +++++++ apps/welcome/boot.js | 6 ++++-- apps/welcome/settings-default.json | 3 +++ apps/welcome/settings.js | 13 ++++++------- 6 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 apps/welcome/settings-default.json diff --git a/apps.json b/apps.json index 21fdf09b2..a2ebea7b5 100644 --- a/apps.json +++ b/apps.json @@ -78,7 +78,7 @@ { "id": "welcome", "name": "Welcome", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "Appears at first boot and explains how to use Bangle.js", "tags": "start,welcome", "allow_emulator":true, @@ -86,6 +86,7 @@ {"name":"welcome.boot.js","url":"boot.js"}, {"name":"welcome.app.js","url":"app.js"}, {"name":"welcome.settings.js","url":"settings.js"}, + {"name":"welcome.settings.json","url":"settings-default.json","evaluate":true}, {"name":"welcome.img","url":"app-icon.js","evaluate":true} ] }, diff --git a/apps/welcome/ChangeLog b/apps/welcome/ChangeLog index 89f3ab2c9..b8786af6a 100644 --- a/apps/welcome/ChangeLog +++ b/apps/welcome/ChangeLog @@ -4,3 +4,6 @@ 0.04: Fix regression after tweaks to Storage.readJSON 0.05: Move configuration into App/widget settings 0.06: Move loader into welcome.boot.js +0.07: Run again when updated + Don't run again when settings app is updated (or absent) + Add "Run Now" option to settings diff --git a/apps/welcome/app.js b/apps/welcome/app.js index 93a4234d8..a32a6e56f 100644 --- a/apps/welcome/app.js +++ b/apps/welcome/app.js @@ -288,6 +288,13 @@ setWatch(()=>{ }, BTN2, {repeat:true,edge:"rising"}); setWatch(()=>move(-1), BTN1, {repeat:true}); +(function migrateSettings(){ + let global_settings = require('Storage').readJSON('setting.json', 1) + if (global_settings) { + delete global_settings.welcomed + require('Storage').write('setting.json', global_settings) + } +})() Bangle.setLCDTimeout(0); Bangle.setLCDPower(1); diff --git a/apps/welcome/boot.js b/apps/welcome/boot.js index ecf98b555..bc5afcc66 100644 --- a/apps/welcome/boot.js +++ b/apps/welcome/boot.js @@ -1,9 +1,11 @@ (function() { - let s = require('Storage').readJSON('setting.json', 1) || {} + let s = require('Storage').readJSON('welcome.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) + || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('welcome.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('setting.json', s) + require('Storage').write('welcome.settings.json', {welcomed: "yes"}) load('welcome.app.js') }) } diff --git a/apps/welcome/settings-default.json b/apps/welcome/settings-default.json new file mode 100644 index 000000000..d250efff5 --- /dev/null +++ b/apps/welcome/settings-default.json @@ -0,0 +1,3 @@ +{ + "welcomed": false +} diff --git a/apps/welcome/settings.js b/apps/welcome/settings.js index 2fbd585c6..b11921646 100644 --- a/apps/welcome/settings.js +++ b/apps/welcome/settings.js @@ -1,16 +1,15 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('setting.json', 1) || {} + let settings = require('Storage').readJSON('welcome.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'Welcome App' }, - 'Run again': { + 'Run on Next Boot': { value: !settings.welcomed, - format: v => v ? 'Yes' : 'No', - onchange: v => { - settings.welcomed = v ? undefined : true - require('Storage').write('setting.json', settings) - }, + format: v => v ? 'OK' : 'No', + onchange: v => require('Storage').write('welcome.settings.json', {welcomed: !v}), }, + 'Run Now': () => load('welcome.app.js'), '< Back': back, }) }) From 69a1e0038491a41e53a71892648f65fb3e88918a Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 15 Apr 2020 01:10:36 +0200 Subject: [PATCH 0392/1189] ncstart: don't run when settings are absent/updated Fixes #298 --- apps.json | 3 ++- apps/ncstart/ChangeLog | 3 +++ apps/ncstart/boot.js | 6 ++++-- apps/ncstart/settings-default.json | 3 +++ apps/ncstart/settings.js | 13 ++++++------- 5 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 apps/ncstart/settings-default.json diff --git a/apps.json b/apps.json index a2ebea7b5..6a4ce496f 100644 --- a/apps.json +++ b/apps.json @@ -505,13 +505,14 @@ "id": "ncstart", "name": "NCEU Startup", "icon": "start.png", - "version":"0.03", + "version":"0.04", "description": "NodeConfEU 2019 'First Start' Sequence", "tags": "start,welcome", "storage": [ {"name":"ncstart.app.js","url":"start.js"}, {"name":"ncstart.boot.js","url":"boot.js"}, {"name":"ncstart.settings.js","url":"settings.js"}, + {"name":"ncstart.settings.json","url":"settings-default.json","evaluate":true}, {"name":"ncstart.img","url":"start-icon.js","evaluate":true}, {"name":"nc-bangle.img","url":"start-bangle.js","evaluate":true}, {"name":"nc-nceu.img","url":"start-nceu.js","evaluate":true}, diff --git a/apps/ncstart/ChangeLog b/apps/ncstart/ChangeLog index 553f7388a..f4418827e 100644 --- a/apps/ncstart/ChangeLog +++ b/apps/ncstart/ChangeLog @@ -2,3 +2,6 @@ Renamed as nodeconf-specific 0.03: Move configuration into App/widget settings Move loader into welcome.boot.js +0.04: Run again when updated + Don't run again when settings app is updated (or absent) + Add "Run Now" option to settings diff --git a/apps/ncstart/boot.js b/apps/ncstart/boot.js index dbb70d213..e3f514f5b 100644 --- a/apps/ncstart/boot.js +++ b/apps/ncstart/boot.js @@ -1,9 +1,11 @@ (function() { - let s = require('Storage').readJSON('setting.json', 1) || {} + let s = require('Storage').readJSON('ncstart.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) + || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('ncstart.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('setting.json', s) + require('Storage').write('ncstart.settings.json', s) load('ncstart.app.js') }) } diff --git a/apps/ncstart/settings-default.json b/apps/ncstart/settings-default.json new file mode 100644 index 000000000..d250efff5 --- /dev/null +++ b/apps/ncstart/settings-default.json @@ -0,0 +1,3 @@ +{ + "welcomed": false +} diff --git a/apps/ncstart/settings.js b/apps/ncstart/settings.js index 284262634..2b24095cf 100644 --- a/apps/ncstart/settings.js +++ b/apps/ncstart/settings.js @@ -1,16 +1,15 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('setting.json', 1) || {} + let settings = require('Storage').readJSON('ncstart.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'NCEU Startup' }, - 'Run again': { + 'Run on Next Boot': { value: !settings.welcomed, - format: v => v ? 'Yes' : 'No', - onchange: v => { - settings.welcomed = v ? undefined : true - require('Storage').write('setting.json', settings) - }, + format: v => v ? 'OK' : 'No', + onchange: v => require('Storage').write('ncstart.settings.json', {welcomed: !v}), }, + 'Run Now': () => load('ncstart.app.js'), '< Back': back, }) }) From 6068eb078654d05011a63fe0d2c976ba358c6242 Mon Sep 17 00:00:00 2001 From: Fabio Date: Wed, 15 Apr 2020 09:16:19 +0200 Subject: [PATCH 0393/1189] Minor text fix in app.json description --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1f168e771..91bfe19af 100644 --- a/apps.json +++ b/apps.json @@ -1220,7 +1220,7 @@ "shortName":"Snake", "icon": "snake.png", "version":"0.02", - "description": "The classic snake game. Eat apples and don't bite your tail:", + "description": "The classic snake game. Eat apples and don't bite your tail.", "tags": "game,fun", "readme": "README.md", "storage": [ From 78214a267e6b68662b542deef2fd38314437b578 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 10:35:29 +0100 Subject: [PATCH 0394/1189] 0.15: Reduce memory usage when running default clock chooser (#294) --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 96e695237..60c9ca5f3 100644 --- a/apps.json +++ b/apps.json @@ -120,7 +120,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.14", + "version":"0.15", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 6c4c19230..3d82be9c0 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -16,3 +16,4 @@ Make capitalization more consistent Move LCD Brightness menu into more general LCD menu 0.14: Reduce memory usage when running app settings page +0.15: Reduce memory usage when running default clock chooser (#294) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index d0d6578dc..9e343a68e 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -296,10 +296,10 @@ function makeConnectable() { }); } function showClockMenu() { - var clockApps = require("Storage").list(/\.info$/).map(app => { - try { return require("Storage").readJSON(app); } - catch (e) { } - }).filter(app => app.type == "clock").sort((a, b) => a.sortorder - b.sortorder); + var clockApps = require("Storage").list(/\.info$/) + .map(app => {var a=storage.readJSON(app, 1);return (a&&a.type == "clock")?a:undefined}) + .filter(app => app) // filter out any undefined apps + .sort((a, b) => a.sortorder - b.sortorder); const clockMenu = { '': { 'title': 'Select Clock', From 02dcc1970960cd648ca0c42a48e428d6191f2946 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 10:50:07 +0100 Subject: [PATCH 0395/1189] widbt: Fix automatic update of Bluetooth connection status --- apps.json | 2 +- apps/widbt/ChangeLog | 1 + apps/widbt/widget.js | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 60c9ca5f3..69a41c52f 100644 --- a/apps.json +++ b/apps.json @@ -355,7 +355,7 @@ { "id": "widbt", "name": "Bluetooth Widget", "icon": "widget.png", - "version":"0.03", + "version":"0.04", "description": "Show the current Bluetooth connection status in the top right of the clock", "tags": "widget,bluetooth", "type":"widget", diff --git a/apps/widbt/ChangeLog b/apps/widbt/ChangeLog index c268d6df0..59dc603a9 100644 --- a/apps/widbt/ChangeLog +++ b/apps/widbt/ChangeLog @@ -1,2 +1,3 @@ 0.02: Tweaks for variable size widget system 0.03: Ensure redrawing works with variable size widget system +0.04: Fix automatic update of Bluetooth connection status diff --git a/apps/widbt/widget.js b/apps/widbt/widget.js index 8e96a395d..c3254c791 100644 --- a/apps/widbt/widget.js +++ b/apps/widbt/widget.js @@ -13,7 +13,7 @@ function changed() { WIDGETS["bluetooth"].draw(); g.flip();// turns screen on } -NRF.on('connected',changed); -NRF.on('disconnected',changed); +NRF.on('connect',changed); +NRF.on('disconnect',changed); WIDGETS["bluetooth"]={area:"tr",width:24,draw:draw}; })() From f890227b619c433047fc8784328002cc6f7da4de Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 10:53:03 +0100 Subject: [PATCH 0396/1189] gbridge: 0.09: Update Bluetooth connection state automatically --- apps.json | 2 +- apps/gbridge/ChangeLog | 1 + apps/gbridge/widget.js | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 69a41c52f..0643ad6de 100644 --- a/apps.json +++ b/apps.json @@ -93,7 +93,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.08", + "version":"0.09", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index d1f9c6a62..53f8a1b4c 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -7,3 +7,4 @@ 0.06: Gadgetbridge App 'Connected' state is no longer toggleable 0.07: Move configuration to settings menu 0.08: Don't turn on LCD at start of every song +0.09: Update Bluetooth connection state automatically diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index fa44757fc..03c622443 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -189,8 +189,8 @@ g.flip(); // turns screen on } - NRF.on("connected", changedConnectionState); - NRF.on("disconnected", changedConnectionState); + NRF.on("connect", changedConnectionState); + NRF.on("disconnect", changedConnectionState); WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: draw }; From 24d35eca2cf4e676832362803a378e453871e2db Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 18:54:29 +0800 Subject: [PATCH 0397/1189] Update stopwatch.js --- apps/swatch/stopwatch.js | 67 ++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 6f8ad9e34..478c22619 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -1,8 +1,11 @@ +var tTotal = Date.now(); var tStart = Date.now(); var tCurrent = Date.now(); var started = false; -var timeY = 60; +var timeY = 45; var hsXPos = 0; +var TtimeY = 75; +var ThsXPos = 0; var lapTimes = []; var displayInterval; @@ -12,6 +15,7 @@ function timeToText(t) { var hs = Math.floor(t/10)%100; return mins+":"+("0"+secs).substr(-2)+"."+("0"+hs).substr(-2); } + function updateLabels() { g.reset(1); g.clearRect(0,23,g.getWidth()-1,g.getHeight()-24); @@ -24,35 +28,53 @@ function updateLabels() { g.setFontAlign(-1,-1); for (var i in lapTimes) { if (i<16) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 30 + i*8);} + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 40 + i*8);} else if (i<32) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-16)*8);} + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 40 + (i-16)*8);} } drawsecs(); } + function drawsecs() { var t = tCurrent-tStart; - g.reset(1); - g.setFont("Vector",48); - g.setFontAlign(0,0); + var Tt = tCurrent-tTotal; var secs = Math.floor(t/1000)%60; var mins = Math.floor(t/60000); var txt = mins+":"+("0"+secs).substr(-2); + var Tsecs = Math.floor(Tt/1000)%60; + var Tmins = Math.floor(Tt/60000); + var Ttxt = Tmins+":"+("0"+Tsecs).substr(-2); var x = 100; - g.clearRect(0,timeY-26,200,timeY+26); - g.drawString(txt,x,timeY); + var Tx = 125; + g.reset(1); + g.setFont("Vector",38); + g.setFontAlign(0,0); + g.clearRect(0,timeY-21,200,timeY+21); + g.drawString(Ttxt,x,timeY); hsXPos = 5+x+g.stringWidth(txt)/2; + g.setFont("6x8",2); + g.clearRect(0,TtimeY-7,200,TtimeY+7); + g.drawString(txt,Tx,TtimeY); + ThsXPos = 5+Tx+g.stringWidth(Ttxt)/2; drawms(); } + function drawms() { var t = tCurrent-tStart; var hs = Math.floor(t/10)%100; + var Tt = tCurrent-tTotal; + var Ths = Math.floor(Tt/10)%100; g.setFontAlign(-1,0); g.setFont("6x8",2); g.clearRect(hsXPos,timeY,220,timeY+20); - g.drawString("."+("0"+hs).substr(-2),hsXPos,timeY+10); + g.drawString("."+("0"+Ths).substr(-2),hsXPos-5,timeY+14); + g.setFont("6x8",1); + g.clearRect(ThsXPos,TtimeY,220,TtimeY+5); + g.drawString("."+("0"+hs).substr(-2),ThsXPos-5,TtimeY+3); } + function getLapTimesArray() { + lapTimes.push(tCurrent-tTotal); return lapTimes.map(timeToText).reverse(); } @@ -61,7 +83,8 @@ setWatch(function() { // Start/stop Bangle.beep(); if (started) tStart = Date.now()+tStart-tCurrent; - tCurrent = Date.now(); + tTotal = Date.now()+tTotal-tCurrent; + tCurrent = Date.now(); if (displayInterval) { clearInterval(displayInterval); displayInterval = undefined; @@ -69,37 +92,41 @@ setWatch(function() { // Start/stop updateLabels(); if (started) displayInterval = setInterval(function() { - var last = tCurrent; - if (started) tCurrent = Date.now(); - if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) - drawsecs(); - else - drawms(); + var last = tCurrent; + if (started) tCurrent = Date.now(); + if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) + drawsecs(); + else + drawms(); }, 20); }, BTN2, {repeat:true}); + setWatch(function() { // Lap Bangle.beep(); if (started) { tCurrent = Date.now(); lapTimes.unshift(tCurrent-tStart); } - tStart = tCurrent; if (!started) { // save var timenow= Date(); var filename = "swatch-"+(new Date()).toISOString().substr(0,16).replace("T","_")+".json"; // this maxes out the 28 char maximum + lapTimes.unshift(tCurrent-tStart); require("Storage").writeJSON(filename, getLapTimesArray()); + tStart = tCurrent = tTotal = Date.now(); + lapTimes = []; E.showMessage("Laps Saved","Stopwatch"); setTimeout(updateLabels, 1000); } else { + tStart = tCurrent; updateLabels(); } }, BTN1, {repeat:true}); setWatch(function() { // Reset if (!started) { - Bangle.beep(); - tStart = tCurrent = Date.now(); - lapTimes = []; + Bangle.beep(); + tStart = tCurrent = tTotal = Date.now(); + lapTimes = []; } updateLabels(); }, BTN3, {repeat:true}); From 9a03c9bcce110c428d7334a11b01e4b48019ce81 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 18:57:52 +0800 Subject: [PATCH 0398/1189] Update ChangeLog --- apps/swatch/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index 3246eeced..9a037fa41 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -5,3 +5,4 @@ Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running 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 From 5d588d6d696d00133e28269e4d125595faa8d89e Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:11:54 +0800 Subject: [PATCH 0399/1189] Update interface.html --- apps/swatch/interface.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 928c5fe39..bfa7f8193 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -20,7 +20,7 @@ function getLapTimes() { html += `
-
${lap.date}
+
${lap.date} Elapsed Time: ${lap.d.1}
${lap.d.length} Laps
@@ -32,7 +32,7 @@ function getLapTimes() { - ${ lap.d.map((d,n)=>`${n+1}${d}`).join("\n") } + ${ lap.d.map((d+1,n)=>`${n+1}${d+1}`).join("\n") }
From 70e9c23c54f5898a83cdf1abb61b17e5304fa66d Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:17:03 +0800 Subject: [PATCH 0400/1189] Update interface.html --- apps/swatch/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index bfa7f8193..735f643a8 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -20,7 +20,7 @@ function getLapTimes() { html += `
-
${lap.date} Elapsed Time: ${lap.d.1}
+
${lap.date} Elapsed Time: ${lap[1]}
${lap.d.length} Laps
From 02aaf2dd166ba350019c3eb44eba757ba835dfef Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:22:07 +0800 Subject: [PATCH 0401/1189] Update interface.html --- apps/swatch/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 735f643a8..53f0dd503 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -20,7 +20,7 @@ function getLapTimes() { html += `
-
${lap.date} Elapsed Time: ${lap[1]}
+
${lap.date}
${lap.d.length} Laps
From 0f20176280e15875b8c9c3ef06619b887c3c28c3 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:22:51 +0800 Subject: [PATCH 0402/1189] Update interface.html --- apps/swatch/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 53f0dd503..928c5fe39 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -32,7 +32,7 @@ function getLapTimes() { - ${ lap.d.map((d+1,n)=>`${n+1}${d+1}`).join("\n") } + ${ lap.d.map((d,n)=>`${n+1}${d}`).join("\n") }
From 32e811b2312ab99bf7ba1bcf466621c0d0a30bc2 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:32:17 +0800 Subject: [PATCH 0404/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0643ad6de..5fae8f482 100644 --- a/apps.json +++ b/apps.json @@ -399,7 +399,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.05", + "version":"0.06", "interface": "interface.html", "description": "Simple stopwatch with Lap Time logging to a JSON file", "tags": "health", From b8226cce8fbfaa0a86c5f13a288a6d920be74bd1 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Wed, 15 Apr 2020 14:00:01 +0200 Subject: [PATCH 0405/1189] Added DANE Signed-off-by: OmegaRogue --- apps.json | 22 +++++ apps/dane/ChangeLog | 4 + apps/dane/add_to_apps.json | 22 +++++ apps/dane/app-icon.js | 1 + apps/dane/app.js | 163 +++++++++++++++++++++++++++++++++++++ apps/dane/app.png | Bin 0 -> 15535 bytes site.webmanifest | 4 +- 7 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 apps/dane/ChangeLog create mode 100644 apps/dane/add_to_apps.json create mode 100644 apps/dane/app-icon.js create mode 100644 apps/dane/app.js create mode 100644 apps/dane/app.png diff --git a/apps.json b/apps.json index 0643ad6de..91d2d249b 100644 --- a/apps.json +++ b/apps.json @@ -1241,5 +1241,27 @@ {"name":"calculator.app.js","url":"app.js"}, {"name":"calculator.img","url":"calculator-icon.js","evaluate":true} ] + }, + { + "id": "dane", + "name": "Digital Assistant, not EDITH", + "shortName": "DANE", + "icon": "app.png", + "version": "0.06", + "description": "A detailed description of my great app", + "tags": "clock", + "type": "clock", + "allow_emulator": true, + "storage": [ + { + "name": "dane.app.js", + "url": "app.js" + }, + { + "name": "dane.img", + "url": "app-icon.js", + "evaluate": true + } + ] } ] diff --git a/apps/dane/ChangeLog b/apps/dane/ChangeLog new file mode 100644 index 000000000..607d0adf5 --- /dev/null +++ b/apps/dane/ChangeLog @@ -0,0 +1,4 @@ +0.01: New App! +0.04: Added Icon to watchface +0.05: bugfix +0.06: moved and resized icon \ No newline at end of file diff --git a/apps/dane/add_to_apps.json b/apps/dane/add_to_apps.json new file mode 100644 index 000000000..6efb3ec85 --- /dev/null +++ b/apps/dane/add_to_apps.json @@ -0,0 +1,22 @@ +{ + "id": "dane", + "name": "Digital Assistant, not EDITH", + "shortName": "DANE", + "icon": "app.png", + "version": "0.06", + "description": "A detailed description of my great app", + "tags": "clock", + "type": "clock", + "allow_emulator": true, + "storage": [ + { + "name": "dane.app.js", + "url": "app.js" + }, + { + "name": "dane.img", + "url": "app-icon.js", + "evaluate": true + } + ] +} \ No newline at end of file diff --git a/apps/dane/app-icon.js b/apps/dane/app-icon.js new file mode 100644 index 000000000..4deb12640 --- /dev/null +++ b/apps/dane/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("l8wxH+AH4A/AH4A/AFUvl8Cu4AEgUCBQIrfFQMRAAe/Aw4xbDYIlBiUS7AjCAAY5BBYMSiJkBGC4sCicTiRQJHoUSCAIwBF6sv30SikUiRMMMIISD7AvTl/YiYtPF40TF6R4BicVFqAWDF4MViaPRIwQWTF4O/IwiKRCoMRUiZHEDJ5cXJAxeOOQuQhQuShWQJIe/JJkviIuC74tTFwORRqKLD+3cmVLpsLFZtNAANKhXeDYKNOu4uEmdlDwVNBoNlsoDDmoKBhYQChcyFycVFwOTFwJcBpomBhYjCmouBAwYMCmZdBa4d3FyonBKoIoCAwIECLooucEIIjCRIYuFms1Lqq7CFwS7DLQQsDhYrBHIZdHXZkCdQpQDXoIQDFwIDBeoQQCpYuSl8RFwMT70KCRYAIhUSFwMTiMvFxm/CQUSFyp5Did3Fxi8DOBwuLDSEv7ETfoRCNDI13DIMT34ZPIYSgOaxJ3SIgZeTC7COBdgMCC58vOoakWiQvQFoQTBFqgvEiURF5gRDOKIdIDwMRiO/axMCBoMRLQItXF4Z9B7F3BxF37BZBAAQnRIYobDMAKqIl5aDAA5zJFwaCBAA6PBFxQQEAAYKBFxjSCU4IECA4YuJCAoAEFx0UikTAAIEBAwQuKCIoADFxsCI5RdiUAoAEVgIVJABRDHAH4A/AH4A/ADAA=")) \ No newline at end of file diff --git a/apps/dane/app.js b/apps/dane/app.js new file mode 100644 index 000000000..dc6262c58 --- /dev/null +++ b/apps/dane/app.js @@ -0,0 +1,163 @@ +const font = "6x8"; +const timeFontSize = 4; +const dateFontSize = 3; +const smallFontSize = 2; +const yOffset = 23; +const xyCenter = g.getWidth()/2; +const cornerSize = 14; +const cornerOffset = 3; +const borderWidth = 1; +const yposTime = 27+yOffset; +const yposDate = 65+yOffset; + +const mainColor = "#26dafd"; +const mainColorDark = "#029dbb"; +const mainColorLight = "#8bebfe"; + +const secondaryColor = "#df9527"; +const secondaryColorDark = "#8b5c15"; +const secondaryColorLight = "#ecc180"; + +const success = "#00ff00"; +const successDark = "#000900"; +const successLight = "#060f06"; + +const alert = "#ff0000"; +const alertDark = "#090000"; +const alertLight = "#0f0606"; + +var img = { + width : 120, height : 120, bpp : 8, + transparent : 254, + buffer : require("heatshrink").decompress(atob("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")) +} + + +function drawTopLeftCorner(x,y) { + g.setColor(mainColor); + var x1 = x-cornerOffset; + var y1 = y-cornerOffset; + g.fillRect(x1,y1,x1+cornerSize,y1+cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x+cornerSize-cornerOffset,y+cornerSize-cornerOffset); +} +function drawTopRightCorner(x,y) { + g.setColor(mainColor); + var x1 = x+cornerOffset; + var y1 = y-cornerOffset; + g.fillRect(x1,y1,x1-cornerSize,y1+cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x-cornerSize-cornerOffset,y+cornerSize-cornerOffset); +} +function drawBottomLeftCorner(x,y) { + g.setColor(mainColor); + var x1 = x-cornerOffset; + var y1 = y+cornerOffset; + g.fillRect(x1,y1,x1+cornerSize,y1-cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x+cornerSize-cornerOffset,y-cornerSize+cornerOffset); +} +function drawBottomRightCorner(x,y) { + g.setColor(mainColor); + var x1 = x+cornerOffset; + var y1 = y+cornerOffset; + g.fillRect(x1,y1,x1-cornerSize,y1-cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x-cornerSize+cornerOffset,y-cornerSize+cornerOffset); +} + +function drawFrame(x1,y1,x2,y2) { + drawTopLeftCorner(x1,y1); + drawTopRightCorner(x2,y1); + drawBottomLeftCorner(x1,y2); + drawBottomRightCorner(x2,y2); + g.setColor(mainColorDark); + g.drawRect(x1,y1,x2,y2); + g.setColor("#000000"); + g.fillRect(x1+borderWidth,y1+borderWidth,x2-borderWidth,y2-borderWidth); +} +function drawTopFrame(x1,y1,x2,y2) { + + drawBottomLeftCorner(x1,y2); + drawBottomRightCorner(x2,y2); + g.setColor(mainColorDark); + g.drawRect(x1,y1,x2,y2); + g.setColor("#000000"); + g.fillRect(x1+borderWidth,y1+borderWidth,x2-borderWidth,y2-borderWidth); +} +function drawBottomFrame(x1,y1,x2,y2) { + drawTopLeftCorner(x1,y1); + drawTopRightCorner(x2,y1); + g.setColor(mainColorDark); + g.drawRect(x1,y1,x2,y2); + g.setColor("#000000"); + g.fillRect(x1+borderWidth,y1+borderWidth,x2-borderWidth,y2-borderWidth); +} + +function getUTCTime(d) { + return d.toUTCString().split(' ')[4].split(':').map(function(d){return Number(d);}); +} + + + + + +function drawTimeText() { + g.setFontAlign(0, 0); + var d = new Date(); + var da = d.toString().split(" "); + var dutc = getUTCTime(d); + + var time = da[4].split(":"); + var hours = time[0], + minutes = time[1], + seconds = time[2]; + g.setColor(mainColor); + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}:${seconds}`, xyCenter, yposTime, true); + g.setFont(font, smallFontSize); +} +function drawDateText() { + g.setFontAlign(0, 0); + var d = new Date(); + g.setFont(font, dateFontSize); + g.drawString(`${d.getDate()}.${d.getMonth()+1}.${d.getFullYear()}`, xyCenter, yposDate, true); +} + + + +function drawClock() { + // main frame + drawFrame(3,10+yOffset,g.getWidth()-3,g.getHeight()-3); + // time frame + drawTopFrame(20,10+yOffset,220,46+yOffset); + // date frame + drawTopFrame(28,46+yOffset,212,46+yOffset+35); + + // texts + drawTimeText(); + drawDateText(); + g.drawImage(img,g.getWidth()/2-(img.width/2),g.getHeight()/2); +} +function updateClock() { + drawTimeText(); + drawDateText(); +} + + +Bangle.on('lcdPower', function(on) { + if (on) drawClock(); +}); +g.clear(); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + + +drawClock(); + + +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + +// refesh every 100 milliseconds +setInterval(updateClock, 100); diff --git a/apps/dane/app.png b/apps/dane/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ee4f8403a82262e37b2750c9d7b245668e6cc46e GIT binary patch literal 15535 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 literal 0 HcmV?d00001 diff --git a/site.webmanifest b/site.webmanifest index 0d1fb4679..0565f159c 100644 --- a/site.webmanifest +++ b/site.webmanifest @@ -17,6 +17,6 @@ "theme_color": "#5755d9", "background_color": "#5755d9", "display": "standalone", - "start_url": "https://banglejs.com/apps/", - "scope": "https://banglejs.com/apps/" + "start_url": "https://omegavoid.codes/BangleApps", + "scope": "https://omegavoid.codes/BangleApps" } From 40f291730e8fbee478c6783008eb0ea620651143 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 13:39:50 +0100 Subject: [PATCH 0406/1189] 0.07: Added @jeffmer's awesome track viewer (fix #273) --- apps.json | 2 +- apps/gpsrec/ChangeLog | 1 + apps/gpsrec/app.js | 148 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 133 insertions(+), 18 deletions(-) diff --git a/apps.json b/apps.json index 0643ad6de..04061a71d 100644 --- a/apps.json +++ b/apps.json @@ -280,7 +280,7 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.06", + "version":"0.07", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 9a47bdd9a..8f1c575a1 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -4,3 +4,4 @@ 0.04: Properly Fix GPS time display in gpsrec app 0.05: Tweaks for variable size widget system 0.06: Ensure widget update itself (fix #118) and change to using icons +0.07: Added @jeffmer's awesome track viewer diff --git a/apps/gpsrec/app.js b/apps/gpsrec/app.js index 58b4295a6..63f3840ff 100644 --- a/apps/gpsrec/app.js +++ b/apps/gpsrec/app.js @@ -70,27 +70,65 @@ function viewTracks() { return E.showMenu(menu); } +function getTrackInfo(fn) { + var filename = getFN(fn); + var minLat = 90; + var maxLat = -90; + var minLong = 180; + var maxLong = -180; + var starttime, duration=0; + var f = require("Storage").open(filename,"r"); + if (f===undefined) return; + var l = f.readLine(f); + var nl = 0, c, n; + if (l!==undefined) { + c = l.split(","); + starttime = parseInt(c[0]); + } + // pushed this loop together to try and bump loading speed a little + while(l!==undefined) { + ++nl;c=l.split(","); + n = parseFloat(c[1]);if(n>maxLat)maxLat=n;if(nmaxLong)maxLong=n;if(nylen ? 200/xlen : 200/ylen; + return { + fn : fn, + filename : filename, + time : new Date(starttime), + records : nl, + minLat : minLat, maxLat : maxLat, + minLong : minLong, maxLong : maxLong, + lfactor : lfactor, + scale : scale, + duration : Math.round(duration/1000) + }; +} + +function asTime(v){ + var mins = Math.floor(v/60); + var secs = v-mins*60; + return ""+mins.toString()+"m "+secs.toString()+"s"; +} + function viewTrack(n) { + E.showMessage("Loading...","GPS Track "+n); + var info = getTrackInfo(n); const menu = { '': { 'title': 'GPS Track '+n } }; - var trackCount = 0; - var trackTime; - var f = require("Storage").open(getFN(n),"r"); - var l = f.readLine(); - if (l!==undefined) { - var c = l.split(","); - trackTime = new Date(parseInt(c[0])); - } - while (l!==undefined) { - trackCount++; - // TODO: min/max/length of track? - l = f.readLine(); - } - if (trackTime) - menu[" "+trackTime.toISOString().substr(0,16).replace("T"," ")] = function(){}; - menu[trackCount+" records"] = function(){}; - // TODO: option to draw it? Just scan through, project using min/max + if (info.time) + menu[info.time.toISOString().substr(0,16).replace("T"," ")] = function(){}; + menu["Duration"] = { value : asTime(info.duration)}; + menu["Records"] = { value : ""+info.records }; + menu['Plot'] = function() { + plotTrack(info); + }; menu['Erase'] = function() { E.showPrompt("Delete Track?").then(function(v) { if (v) { @@ -107,4 +145,80 @@ function viewTrack(n) { return E.showMenu(menu); } +function plotTrack(info) { + function xcoord(long){ + return 30 + Math.round((long-info.minLong)*info.lfactor*info.scale); + } + + function ycoord(lat){ + return 210 - Math.round((lat - info.minLat)*info.scale); + } + + function radians(a) { + return a*Math.PI/180; + } + + function distance(lat1,long1,lat2,long2){ + var x = radians(long1-long2) * Math.cos(radians((lat1+lat2)/2)); + var y = radians(lat2-lat1); + return Math.sqrt(x*x + y*y) * 6371000; + } + + E.showMenu(); // remove menu + g.setColor(1,0.5,0.5); + g.setFont("Vector",16); + g.fillRect(9,80,11,120); + g.fillPoly([9,60,19,80,0,80]); + g.setColor(1,1,1); + g.drawString("N",2,40); + g.drawString("Track"+info.fn.toString()+" - Loading",10,220); + g.setColor(0,0,0); + g.fillRect(0,220,239,239); + g.setColor(1,1,1); + g.drawString(asTime(info.duration),10,220); + var f = require("Storage").open(info.filename,"r"); + if (f===undefined) return; + var l = f.readLine(f); + var ox=0; + var oy=0; + var olat,olong,dist=0; + var first = true; + var i=0; + while(l!==undefined) { + var c = l.split(","); + var lat = parseFloat(c[1]); + var long = parseFloat(c[2]); + var x = xcoord(long); + var y = ycoord(lat); + if (first) { + g.moveTo(x,y); + g.setColor(0,1,0); + g.fillCircle(x,y,5); + g.setColor(1,1,1); + first = false; + } else if (x!=ox || y!=oy) { + g.lineTo(x,y); + } + if (!first) { + var d = distance(olat,olong,lat,long); + if (!isNaN(d)) dist+=d; + } + olat = lat; + olong = long; + ox = x; + oy = y; + l = f.readLine(f); + } + g.setColor(1,0,0); + g.fillCircle(ox,oy,5); + g.setColor(1,1,1); + g.drawString(require("locale").distance(dist),120,220); + g.setFont("6x8",2); + g.setFontAlign(0,0,3); + g.drawString("Back",230,200); + setWatch(function() { + viewTrack(info.fn); + }, BTN3); +} + showMainMenu(); From a56a9792f15499ed3ee6f74a1fe6c70a5f22ab3d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 13:58:05 +0100 Subject: [PATCH 0407/1189] Rewrite 'getInstalledApps' to minimize RAM usage --- CHANGELOG.md | 1 + js/comms.js | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9480f2ace..95e973e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,3 +9,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * Fix issue removing an app that was just installed (fix #253) * Add `Favourite` functionality * Version number now clickable even when you're at the latest version (fix #291) +* Rewrite 'getInstalledApps' to minimize RAM usage diff --git a/js/comms.js b/js/comms.js index 604ef19ed..1f840ada7 100644 --- a/js/comms.js +++ b/js/comms.js @@ -75,12 +75,21 @@ getInstalledApps : () => { Progress.hide({sticky:true}); return reject(""); } - Puck.eval('require("Storage").list(/\.info$/).map(f=>{var j=require("Storage").readJSON(f,1)||{};j.id=f.slice(0,-5);return j})', (appList,err) => { + Puck.write('\x10Bluetooth.print("[");require("Storage").list(/\.info$/).forEach(f=>{var j=require("Storage").readJSON(f,1)||{};j.id=f.slice(0,-5);Bluetooth.print(JSON.stringify(j)+",")});Bluetooth.println("0]")\n', (appList,err) => { Progress.hide({sticky:true}); + try { + appList = JSON.parse(appList); + // remove last element since we added a final '0' + // to make things easy on the Bangle.js side + appList = appList.slice(0,-1); + } catch (e) { + appList = null; + err = e.toString(); + } if (appList===null) return reject(err || ""); console.log("getInstalledApps", appList); resolve(appList); - }); + }, true /* callback on newline */); }); }); }, From a8f1aabbee9ac286d012b16fbfa63f7efa8632a1 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 14:30:51 +0100 Subject: [PATCH 0408/1189] Fix regression stopping correct widget updates --- apps.json | 6 +++--- apps/widbat/ChangeLog | 1 + apps/widbat/widget.js | 2 +- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/widget.js | 2 +- apps/widclk/ChangeLog | 1 + apps/widclk/widget.js | 4 ++-- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index 04061a71d..0a65897b5 100644 --- a/apps.json +++ b/apps.json @@ -330,7 +330,7 @@ { "id": "widbat", "name": "Battery Level Widget", "icon": "widget.png", - "version":"0.04", + "version":"0.05", "description": "Show the current battery level and charging status in the top right of the clock", "tags": "widget,battery", "type":"widget", @@ -342,7 +342,7 @@ "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.08", + "version":"0.09", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", @@ -777,7 +777,7 @@ { "id": "widclk", "name": "Digital clock widget", "icon": "widget.png", - "version":"0.03", + "version":"0.04", "description": "A simple digital clock widget", "tags": "widget,clock", "type":"widget", diff --git a/apps/widbat/ChangeLog b/apps/widbat/ChangeLog index cd9993c02..b9d50ab8b 100644 --- a/apps/widbat/ChangeLog +++ b/apps/widbat/ChangeLog @@ -1,3 +1,4 @@ 0.02: Now refresh battery monitor every minute if LCD on 0.03: Tweaks for variable size widget system 0.04: Ensure redrawing works with variable size widget system +0.05: Fix regression stopping correct widget updates diff --git a/apps/widbat/widget.js b/apps/widbat/widget.js index 2f1f29802..dd6774d4c 100644 --- a/apps/widbat/widget.js +++ b/apps/widbat/widget.js @@ -30,7 +30,7 @@ Bangle.on('lcdPower', function(on) { WIDGETS["bat"].draw(); // refresh once a minute if LCD on if (!batteryInterval) - batteryInterval = setInterval(draw, 60000); + batteryInterval = setInterval(()=>WIDGETS["bat"].draw(), 60000); } else { if (batteryInterval) { clearInterval(batteryInterval); diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 3627a86d3..129707320 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -5,3 +5,4 @@ 0.06: Show battery percentage as text 0.07: Add settings: percentage/color/charger icon 0.08: Draw percentage as inverted on monochrome battery +0.09: Fix regression stopping correct widget updates diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 9f88b5c49..aca690ce0 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -110,7 +110,7 @@ Bangle.on('lcdPower', function(on) { WIDGETS["batpc"].draw(); // refresh once a minute if LCD on if (!batteryInterval) - batteryInterval = setInterval(draw, 60000); + batteryInterval = setInterval(()=>WIDGETS["batpc"].draw(), 60000); } else { if (batteryInterval) { clearInterval(batteryInterval); diff --git a/apps/widclk/ChangeLog b/apps/widclk/ChangeLog index 5370129cc..6fda78a08 100644 --- a/apps/widclk/ChangeLog +++ b/apps/widclk/ChangeLog @@ -1,2 +1,3 @@ 0.02: Now refresh battery monitor every minute if LCD on 0.03: Ensure redrawing works with variable size widget system +0.04: Fix regression stopping correct widget updates diff --git a/apps/widclk/widget.js b/apps/widclk/widget.js index 1d5df36b2..ff22bb4d1 100644 --- a/apps/widclk/widget.js +++ b/apps/widclk/widget.js @@ -14,7 +14,7 @@ } } function startTimers(){ - intervalRef = setInterval(draw, 60*1000); + intervalRef = setInterval(()=>WIDGETS["wdclk"].draw(), 60*1000); WIDGETS["wdclk"].draw(); } Bangle.on('lcdPower', (on) => { @@ -23,5 +23,5 @@ }); WIDGETS["wdclk"]={area:"tr",width:width,draw:draw}; - if (Bangle.isLCDOn) intervalRef = setInterval(draw, 60*1000); + if (Bangle.isLCDOn) intervalRef = setInterval(()=>WIDGETS["wdclk"].draw(), 60*1000); })() From 9ccba226940906b154ac6c529d15912a6136dec4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 15 Apr 2020 14:31:45 +0100 Subject: [PATCH 0409/1189] RAM widget --- apps.json | 12 ++++++++++++ apps/widram/ChangeLog | 1 + apps/widram/widget.js | 23 +++++++++++++++++++++++ apps/widram/widget.png | Bin 0 -> 403 bytes 4 files changed, 36 insertions(+) create mode 100644 apps/widram/ChangeLog create mode 100644 apps/widram/widget.js create mode 100644 apps/widram/widget.png diff --git a/apps.json b/apps.json index 0a65897b5..7449a233b 100644 --- a/apps.json +++ b/apps.json @@ -363,6 +363,18 @@ {"name":"widbt.wid.js","url":"widget.js"} ] }, + { "id": "widram", + "name": "RAM Widget", + "shortName":"RAM Widget", + "icon": "widget.png", + "version":"0.01", + "description": "Display your Bangle's available RAM percentage in a widget", + "tags": "widget", + "type": "widget", + "storage": [ + {"name":"widram.wid.js","url":"widget.js"} + ] + }, { "id": "hrm", "name": "Heart Rate Monitor", "icon": "heartrate.png", diff --git a/apps/widram/ChangeLog b/apps/widram/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/widram/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/widram/widget.js b/apps/widram/widget.js new file mode 100644 index 000000000..08710b726 --- /dev/null +++ b/apps/widram/widget.js @@ -0,0 +1,23 @@ +(() => { + function draw() { + g.reset(); + var m = process.memory(); + var pc = Math.round(m.usage*100/m.total); + g.drawImage(atob("BwgBqgP////AVQ=="), this.x+(24-7)/2, this.y+4); + g.setColor(pc>70 ? "#ff0000" : (pc>50 ? "#ffff00" : "#ffffff")); + g.setFont("6x8").setFontAlign(0,0).drawString(pc+"%", this.x+12, this.y+20, true/*solid*/); + } + var ramInterval; + Bangle.on('lcdPower', function(on) { + if (on) { + WIDGETS["ram"].draw(); + if (!ramInterval) ramInterval = setInterval(()=>WIDGETS["ram"].draw(), 10000); + } else { + if (ramInterval) { + clearInterval(ramInterval); + ramInterval = undefined; + } + } + }); + WIDGETS["ram"]={area:"tl",width: 24,draw:draw}; +})() diff --git a/apps/widram/widget.png b/apps/widram/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..c1cbf2e1aea7e91968c357811e99f33cc62ffacb GIT binary patch literal 403 zcmV;E0c`$>P)1O4+bVCO4?^37mlMvtzIpiNAgg@-GVfPF0=OmtT$2E< zNdVWZUt-&r@W1CT^L_;+fNSO*u>BR*mG>)<8(`cSV%!-P?x&RQ5M#Hj`+diHjQ+*s z>S6)_t!TfpXJl7kR@qa^_of?}0CeM`l0pb0-82C>pdNr%Ck6e^R5AB-#{{^$96YGC x#WsUaQP1r(1K~`8TesKePp*p*LI@#B@d1JOVd<$MIgtPW002ovPDHLkV1j3etDpb? literal 0 HcmV?d00001 From af427a3105d54a30dd3921e43dbcf2c562e8870a Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Wed, 15 Apr 2020 21:36:29 +0200 Subject: [PATCH 0410/1189] update v0.03 --- apps/numerals/ChangeLog | 1 + apps/numerals/numerals-default.json | 5 +++ apps/numerals/numerals-icon.js | 2 +- apps/numerals/numerals.app.js | 50 +++++++++++++++-------------- apps/numerals/numerals.settings.js | 14 ++++++-- 5 files changed, 44 insertions(+), 28 deletions(-) create mode 100644 apps/numerals/numerals-default.json diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index a8396e26b..ec465a83f 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Use BTN2 for settings menu like other clocks +0.03: maximize numerals, make menu button configurable, change icon to mac palette, add default settings file, respect 12hour setting \ No newline at end of file diff --git a/apps/numerals/numerals-default.json b/apps/numerals/numerals-default.json new file mode 100644 index 000000000..aa6a25047 --- /dev/null +++ b/apps/numerals/numerals-default.json @@ -0,0 +1,5 @@ +{ + color:0, + drawMode:"fill", + menuButton:22 +} \ No newline at end of file diff --git a/apps/numerals/numerals-icon.js b/apps/numerals/numerals-icon.js index 7e471fb0d..7ef609874 100644 --- a/apps/numerals/numerals-icon.js +++ b/apps/numerals/numerals-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwhC/ABMBzIADyAJIAAkQBoMZBIoXCBIwADyIkIGAIuKGAQkIBJIwEEKQANC/4XWR58RiIHFWpAXFe4QRFcpAXFewQRFcxAXEFwQwGA4QXKiAXDGAgX/C/4X/C/4X/C7uQCwcBBwYXNBwYuEC54wCFwgXPzMRiIHFC54AHC/4XiCAoXRhIHDyK3GAAwOBJA0QG45VGC4YwCD4YwKFwgABcgIfEAwIAHBwgA/AAgA==")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwhC/ABXdAAfQBJAAEBgUNBJ4mGBKAmFEhAuLEwQhSABoX/C6yPPYw61IB4r3DHxoIFCwQIHC5YuDCIo3HC4oWEBI4X/C/4X/C/4X/C7XQC4gOEC5gwEBA4XLGAYOFC5oPCA44XNAA4X/C8SAGC6q4CCxb4EG5guICAgfIFxQA/ADg")) \ No newline at end of file diff --git a/apps/numerals/numerals.app.js b/apps/numerals/numerals.app.js index fbfe5b9ed..b24e8bc5e 100644 --- a/apps/numerals/numerals.app.js +++ b/apps/numerals/numerals.app.js @@ -7,57 +7,59 @@ */ var numerals = { - 0:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,9,9,1],[30,21,61,21,69,29,69,61,61,69,30,69,22,61,22,29,30,21]], - 1:[[59,1,82,1,90,9,90,82,82,90,73,90,65,82,65,27,59,27,51,19,51,9,59,1]], - 2:[[9,1,82,1,90,9,90,47,82,55,21,55,21,64,82,64,90,72,90,82,82,90,9,90,1,82,1,43,9,35,70,35,70,25,9,25,1,17,1,9,9,1]], - 3:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,74,9,66,70,66,70,57,9,57,1,49,1,41,9,33,70,33,70,25,9,25,1,17,1,9,9,1]], - 4:[[9,1,14,1,22,9,22,34,69,34,69,9,77,1,82,1,90,9,90,82,82,90,78,90,70,82,70,55,9,55,1,47,1,9,9,1]], - 5:[[9,1,82,1,90,9,90,17,82,25,21,25,21,35,82,35,90,43,90,82,82,90,9,90,1,82,1,72,9,64,71,64,71,55,9,55,1,47,1,9,9,1]], - 6:[[9,1,82,1,90,9,90,14,82,22,22,22,22,36,82,36,90,44,90,82,82,90,9,90,1,82,1,9,9,1],[22,55,69,55,69,69,22,69,22,55]], - 7:[[9,1,82,1,90,9,90,15,15,90,9,90,1,82,1,76,54,23,9,23,1,15,1,9,9,1]], - 8:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,9,9,1],[22,22,69,22,69,36,22,36,22,22],[22,55,69,55,69,69,22,69,22,55]], - 9:[[9,1,82,1,90,9,90,82,82,90,9,90,1,82,1,77,9,69,69,69,69,55,9,55,1,47,1,9,9,1],[22,22,69,22,69,36,22,36,22,22]], + 0:[[9,1,82,1,90,9,90,92,82,100,9,100,1,92,1,9],[30,25,61,25,69,33,69,67,61,75,30,75,22,67,22,33]], + 1:[[59,1,82,1,90,9,90,92,82,100,73,100,65,92,65,27,59,27,51,19,51,9]], + 2:[[9,1,82,1,90,9,90,53,82,61,21,61,21,74,82,74,90,82,90,92,82,100,9,100,1,92,1,48,9,40,70,40,70,27,9,27,1,19,1,9]], + 3:[[9,1,82,1,90,9,90,92,82,100,9,100,1,92,1,82,9,74,70,74,70,61,9,61,1,53,1,48,9,40,70,40,70,27,9,27,1,19,1,9]], + 4:[[9,1,14,1,22,9,22,36,69,36,69,9,77,1,82,1,90,9,90,92,82,100,78,100,70,92,70,61,9,61,1,53,1,9]], + 5:[[9,1,82,1,90,9,90,19,82,27,21,27,21,40,82,40,90,48,90,92,82,100,9,100,1,92,1,82,9,74,71,74,71,61,9,61,1,53,1,9]], + 6:[[9,1,82,1,90,9,90,19,82,27,22,27,22,40,82,40,90,48,90,92,82,100,9,100,1,92,1,9],[22,60,69,60,69,74,22,74]], + 7:[[9,1,82,1,90,9,90,15,20,98,9,98,1,90,1,86,56,22,9,22,1,14,1,9]], + 8:[[9,1,82,1,90,9,90,92,82,100,9,100,1,92,1,9],[22,27,69,27,69,43,22,43],[22,58,69,58,69,74,22,74]], + 9:[[9,1,82,1,90,9,90,92,82,100,9,100,1,92,1,82,9,74,69,74,69,61,9,61,1,53,1,9],[22,27,69,27,69,41,22,41]], }; +var _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||false; var _hCol = ["#ff5555","#ffff00","#FF9901","#2F00FF"]; var _mCol = ["#55ff55","#ffffff","#00EFEF","#FFBF00"]; var _rCol = 0; var interval = 0; const REFRESH_RATE = 10E3; -function translate(tx, ty, p) { +function translate(tx, ty, p){ return p.map((x, i)=> x+((i%2)?ty:tx)); } function fill(poly){ - return g.fillPoly(poly); + return g.fillPoly(poly,true); } function frame(poly){ - return g.drawPoly(poly); + return g.drawPoly(poly,true); } let settings = require('Storage').readJSON('numerals.json',1); if (!settings) { settings = { - color: 0, - drawMode: "fill" + color:0, + drawMode:"fill", + menuButton:24 }; } function drawNum(num,col,x,y,func){ g.setColor(col); - let tx = x*100+35; - let ty = y*100+35; + let tx = x*100+25; + let ty = y*104+32; for (let i=0;i0) g.setColor((func==fill)?"#000000":col); - func(translate(tx, ty,numerals[num][i])); + func(translate(tx,ty,numerals[num][i])); } } function draw(drawMode){ let d = new Date(); - let h1 = Math.floor(d.getHours()/10); - let h2 = d.getHours()%10; + let h1 = Math.floor((_12hour?d.getHours()%12:d.getHours())/10); + let h2 = (_12hour?d.getHours()%12:d.getHours())%10; let m1 = Math.floor(d.getMinutes()/10); let m2 = d.getMinutes()%10; g.clearRect(0,24,240,240); @@ -70,7 +72,7 @@ function draw(drawMode){ Bangle.setLCDMode(); clearWatch(); -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +setWatch(Bangle.showLauncher, settings.menuButton, {repeat:false,edge:"falling"}); g.clear(); clearInterval(); @@ -78,8 +80,8 @@ if (settings.color>0) _rCol=settings.color-1; interval=setInterval(draw, REFRESH_RATE, settings.drawMode); draw(settings.drawMode); -Bangle.on('lcdPower', function(on) { - if (on) { +Bangle.on('lcdPower', function(on){ + if (on){ if (settings.color==0) _rCol = Math.floor(Math.random()*_hCol.length); draw(settings.drawMode); interval=setInterval(draw, REFRESH_RATE, settings.drawMode); @@ -90,4 +92,4 @@ Bangle.on('lcdPower', function(on) { }); Bangle.loadWidgets(); -Bangle.drawWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/numerals/numerals.settings.js b/apps/numerals/numerals.settings.js index f9c417da6..2d388525c 100644 --- a/apps/numerals/numerals.settings.js +++ b/apps/numerals/numerals.settings.js @@ -4,15 +4,17 @@ }; function resetSettings() { numeralsSettings = { - color: 0, - drawMode: "fill" + color:0, + drawMode:"fill", + menuButton:22 }; updateSettings(); } let numeralsSettings = storage.readJSON('numerals.json',1); if (!numeralsSettings) resetSettings(); let dm = ["fill","frame"]; - let col = ["rnd","r/g","y/w","o/c","b/y"] + let col = ["rnd","r/g","y/w","o/c","b/y"]; + let btn = [[24,"BTN1"],[22,"BTN2"],[23,"BTN3"],[11,"BTN4"],[16,"BTN5"]]; var menu={ "" : { "title":"Numerals"}, "Colors": { @@ -27,6 +29,12 @@ format: v=>dm[v], onchange: v=> { numeralsSettings.drawMode=dm[v]; updateSettings();} }, + "Menu button": { + value: 1|btn[numeralsSettings.menuButton], + min:0,max:4, + format: v=>btn[v][1], + onchange: v=> { numeralsSettings.menuButton=btn[v][0]; updateSettings();} + }, "< back": back }; E.showMenu(menu); From b08715cad4ca3531b6d82344923685faa37bf20b Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Wed, 15 Apr 2020 21:39:29 +0200 Subject: [PATCH 0411/1189] update numerals app v0.03 --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7449a233b..6327a653c 100644 --- a/apps.json +++ b/apps.json @@ -1205,7 +1205,7 @@ "name": "Numerals Clock", "shortName": "Numerals Clock", "icon": "numerals.png", - "version":"0.02", + "version":"0.03", "description": "A simple big numerals clock", "tags": "numerals,clock", "type":"clock", @@ -1213,7 +1213,8 @@ "storage": [ {"name":"numerals.app.js","url":"numerals.app.js"}, {"name":"numerals.img","url":"numerals-icon.js","evaluate":true}, - {"name":"numerals.settings.js","url":"numerals.settings.js"} + {"name":"numerals.settings.js","url":"numerals.settings.js"}, + {"name":"numerals.json","url":"numerals-default.json","evaluate":true} ] }, { "id": "bledetect", From 7e300068b1598e8f8b7da702ba6e05de52c6887f Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Wed, 15 Apr 2020 21:43:03 +0200 Subject: [PATCH 0412/1189] update v0.03 --- apps/numerals/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/numerals/README.md b/apps/numerals/README.md index 01d784ef8..52e84c76d 100644 --- a/apps/numerals/README.md +++ b/apps/numerals/README.md @@ -5,13 +5,16 @@ Settings can be accessed through the app/widget settings menu of the Bangle.js ## Settings available -### color: +### Color: * rnd - shows numerals in different color combinations every time the watches wakes * r/g - red/green * y/w - yellow/white * o/c - orange/cyan * b/y - blue/yellow'ish -### draw mode +### Draw mode * fill - fill numerals * frame - only shows outline of numerals + +### Menu button +* choose button to start launcher menu with \ No newline at end of file From 0ef33e12dce47fe91106b7b03b5bc7880dc68c33 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 08:21:27 +0200 Subject: [PATCH 0413/1189] Distance calc and display --- apps/activepedom/ChangeLog | 3 +- apps/activepedom/README.md | 23 +++++++++++--- apps/activepedom/settings.js | 33 +++++++++++++++++++- apps/activepedom/widget.js | 58 +++++++++++++++++++++++++----------- 4 files changed, 93 insertions(+), 24 deletions(-) diff --git a/apps/activepedom/ChangeLog b/apps/activepedom/ChangeLog index 4c21f3ace..fb0bc78e5 100644 --- a/apps/activepedom/ChangeLog +++ b/apps/activepedom/ChangeLog @@ -1 +1,2 @@ -0.01: New Widget! +0.01: New Widget! +0.02: Distance calculation and display \ No newline at end of file diff --git a/apps/activepedom/README.md b/apps/activepedom/README.md index 8a10727cd..055a91f56 100644 --- a/apps/activepedom/README.md +++ b/apps/activepedom/README.md @@ -1,4 +1,4 @@ -# Improved pedometer +# Active Pedometer Pedometer that filters out arm movement and displays a step goal progress. I changed the step counting algorithm completely. @@ -19,8 +19,9 @@ When you reach the step threshold, the steps needed to reach the threshold are c ## Features * Two line display +* Can display distance (in km) or steps in each line * Large number for good readability -* Small number with the exact steps counted +* Small number with the exact steps counted or more exact distance * Large number is displayed in green when status is 'active' * Progress bar for step goal * Counts steps only if they are reached in a certain time @@ -29,9 +30,23 @@ 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 -## Development version +## Settings -* https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/pedometer +* Max time (ms): Maximum time between two steps in milliseconds, steps will not be counted if exceeded. Standard: 1100 +* Min time (ms): Minimum time between two steps in milliseconds, steps will not be counted if fallen below. Standard: 240 +* Step threshold: How many steps are needed to reach 'active' mode. If you do not reach the threshold in the 'Active Reset' time, the steps are not counted. Standard: 30 +* Act.Res. (ms): Active Reset. After how many miliseconds will the 'active mode' reset. You have to reach the step threshold in this time, otherwise the steps are not counted. Standard: 30000 +* Step sens.: Step Sensitivity. How sensitive should the sted detection be? This changes sensitivity in step detection in the firmware. Standard in firmware: 80 +* Step goal: This is your daily step goal. Standard: 10000 +* Step length: Length of one step in cm. Standard: 75 +* Line One: What to display in line one, steps or distance. Standard: steps +* Line Two: What to display in line two, steps or distance. Standard: distance + +## Releases + +* Offifical app loader: https://github.com/espruino/BangleApps/tree/master/apps/activepedom (https://banglejs.com/apps) +* Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/activepedom (https://purple-tentacle.github.io/BangleApps/#widget) +* Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/pedometer ## Requests diff --git a/apps/activepedom/settings.js b/apps/activepedom/settings.js index 43764a164..94ae435d2 100644 --- a/apps/activepedom/settings.js +++ b/apps/activepedom/settings.js @@ -4,6 +4,7 @@ */ (function(back) { const SETTINGS_FILE = 'activepedom.settings.json'; + const LINES = ['Steps', 'Distance']; // initialize with default settings... let s = { @@ -13,6 +14,9 @@ 'intervalResetActive' : 30000, 'stepSensitivity' : 80, 'stepGoal' : 10000, + 'stepLength' : 75, + 'lineOne': LINES[0], + 'lineTwo': LINES[1], }; // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -27,7 +31,7 @@ return function (value) { s[key] = value; storage.write(SETTINGS_FILE, s); - WIDGETS["activepedom"].draw(); + //WIDGETS["activepedom"].draw(); }; } @@ -76,6 +80,33 @@ step: 1000, onchange: save('stepGoal'), }, + 'Step length (cm)': { + value: s.stepLength, + min: 1, + max: 150, + step: 1, + onchange: save('stepLength'), + }, + 'Line One': { + format: () => s.lineOne, + onchange: function () { + // cycles through options + const oldIndex = LINES.indexOf(s.lineOne) + const newIndex = (oldIndex + 1) % LINES.length + s.lineOne = LINES[newIndex] + save('lineOne')(s.lineOne) + }, + }, + 'Line Two': { + format: () => s.lineTwo, + onchange: function () { + // cycles through options + const oldIndex = LINES.indexOf(s.lineTwo) + const newIndex = (oldIndex + 1) % LINES.length + s.lineTwo = LINES[newIndex] + save('lineTwo')(s.lineTwo) + }, + }, }; E.showMenu(menu); }); \ No newline at end of file diff --git a/apps/activepedom/widget.js b/apps/activepedom/widget.js index 0c8b2438d..d569716ec 100644 --- a/apps/activepedom/widget.js +++ b/apps/activepedom/widget.js @@ -8,22 +8,16 @@ 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(); - var width = 45; + var lastUpdate = new Date(); //used to reset counted steps on new day + var width = 45; //width of widget - var stepsTooShort = 0; + //used for statistics and debugging + var stepsTooShort = 0; var stepsTooLong = 0; var stepsOutsideTime = 0; - //define default settings - const DEFAULTS = { - 'cMaxTime' : 1100, - 'cMinTime' : 240, - 'stepThreshold' : 30, - 'intervalResetActive' : 30000, - 'stepSensitivity' : 80, - 'stepGoal' : 10000, - }; + var distance = 0; //distance travelled + const SETTINGS_FILE = 'activepedom.settings.json'; const PEDOMFILE = "activepedom.steps.json"; @@ -32,10 +26,21 @@ function loadSettings() { settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; } + //return setting function setting(key) { - if (!settings) { loadSettings(); } - return (key in settings) ? settings[key] : DEFAULTS[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]; } function setStepSensitivity(s) { @@ -46,7 +51,7 @@ } //format number to make them shorter - function kFormatter(num) { + function kFormatterSteps(num) { if (num <= 999) return num; //smaller 1.000, return 600 as 600 if (num >= 1000 && num < 10000) { //between 1.000 and 10.000 num = Math.floor(num/100)*100; @@ -99,11 +104,12 @@ else { stepsOutsideTime++; } + settings = 0; //reset settings to save memory } function draw() { var height = 23; //width is deined globally - var stepsDisplayLarge = kFormatter(stepsCounted); + distance = (stepsCounted * setting('stepLength')) / 100 /1000 //distance in km //Check if same day let date = new Date(); @@ -121,10 +127,21 @@ if (active == 1) g.setColor(0x07E0); //green else g.setColor(0xFFFF); //white g.setFont("6x8", 2); - g.drawString(stepsDisplayLarge,this.x+1,this.y); //first line, big number + + if (setting('lineOne') == 'Steps') { + g.drawString(kFormatterSteps(stepsCounted),this.x+1,this.y); //first line, big number, steps + } + if (setting('lineOne') == 'Distance') { + g.drawString(distance.toFixed(2),this.x+1,this.y); //first line, big number, distance + } g.setFont("6x8", 1); g.setColor(0xFFFF); //white - g.drawString(stepsCounted,this.x+1,this.y+14); //second line, small number + if (setting('lineTwo') == 'Steps') { + g.drawString(stepsCounted,this.x+1,this.y+14); //second line, small number, steps + } + if (setting('lineTwo') == 'Distance') { + g.drawString(distance.toFixed(3) + "km",this.x+1,this.y+14); //second line, small number, distance + } //draw step goal bar stepGoalPercent = (stepsCounted / setting('stepGoal')) * 100; @@ -136,6 +153,8 @@ g.fillRect(this.x, this.y+height, this.x+1, this.y+height-1); //draw start of bar g.fillRect(this.x+width, this.y+height, this.x+width-1, this.y+height-1); //draw end of bar g.fillRect(this.x, this.y+height, this.x+stepGoalBarLength, this.y+height); // draw progress bar + + settings = 0; //reset settings to save memory } //This event is called just before the device shuts down for commands such as reset(), load(), save(), E.reboot() or Bangle.off() @@ -164,6 +183,7 @@ //Read data from file and set variables let pedomData = require("Storage").readJSON(PEDOMFILE,1); + if (pedomData) { if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); stepsCounted = pedomData.stepsToday|0; @@ -172,6 +192,8 @@ stepsOutsideTime = pedomData.stepsOutsideTime; } + pedomdata = 0; //reset pedomdata to save memory + setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive) //Add widget From 505730cd50cb9ab08b2100bd6064399c907be3a3 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 08:23:38 +0200 Subject: [PATCH 0414/1189] active pedometer: added readme --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 3dbccb9b1..ec211f060 100644 --- a/apps.json +++ b/apps.json @@ -1116,6 +1116,7 @@ "description": "Pedometer that filters out arm movement and displays a step goal progress.", "tags": "outdoors,widget", "type":"widget", + "readme": "README.md", "storage": [ {"name":"activepedom.wid.js","url":"widget.js"}, {"name":"activepedom.settings.js","url":"settings.js"}, From d74eb43fb6477e5958dee98c623cb43dc3213e3d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 08:27:13 +0200 Subject: [PATCH 0415/1189] active pedometer: version 0.02 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ec211f060..ab8af0f37 100644 --- a/apps.json +++ b/apps.json @@ -1112,7 +1112,7 @@ "name": "Active Pedometer", "shortName":"Active Pedometer", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Pedometer that filters out arm movement and displays a step goal progress.", "tags": "outdoors,widget", "type":"widget", From 078a3e6d5f31363a7ab7042859870f02cf3a1126 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 08:16:27 +0100 Subject: [PATCH 0416/1189] change default temperature for israel as per #248 --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index ebf28e53d..508c92015 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -220,7 +220,7 @@ var locales = { int_curr_symbol: "ILS", speed: "kmh", distance: { 0: "m", 1: "km" }, - temperature: "°F", + temperature: "°C", ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020 From 944693eaf966fe4b54cbfeaef5148f5b1efc444d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:06:44 +0200 Subject: [PATCH 0417/1189] Chronowid initial --- apps/chronowid/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/chronowid/ChangeLog diff --git a/apps/chronowid/ChangeLog b/apps/chronowid/ChangeLog new file mode 100644 index 000000000..a6f342f01 --- /dev/null +++ b/apps/chronowid/ChangeLog @@ -0,0 +1 @@ +0.01: New widget and app! From 1a935951b03efdeca39d61da79302ff83c73ea18 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:07:39 +0200 Subject: [PATCH 0418/1189] Chronowid initial --- apps/chronowid/README.md | 35 ++++++++++++++ apps/chronowid/app-icon.js | 1 + apps/chronowid/app.js | 91 ++++++++++++++++++++++++++++++++++++ apps/chronowid/app.png | Bin 0 -> 1060 bytes apps/chronowid/widget.js | 93 +++++++++++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+) create mode 100644 apps/chronowid/README.md create mode 100644 apps/chronowid/app-icon.js create mode 100644 apps/chronowid/app.js create mode 100644 apps/chronowid/app.png create mode 100644 apps/chronowid/widget.js diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md new file mode 100644 index 000000000..b6325d94f --- /dev/null +++ b/apps/chronowid/README.md @@ -0,0 +1,35 @@ +# Chronometer Widget + +Chronometer (timer) that runs as a widget. +The advantage is, that you can still see your normal watchface and other widgets when the timer is running. +The widget is always active, but only shown when the timer is on. +Hours, minutes, seconds and timer status can be set with an app. + +## Screenshots + +TBD + +## Features + +* Using other apps does not interrupt the timer, no need to keep the widget open (BUT: there will be no buzz when the time is up, for that the widget has to be loaded) +* Target time is saved to a file and timer picks up again when widget is loaded again. + +## Settings + +There are no settings section in the settings app, timer can be set using an app. + +* Hours: Set the hours for the timer +* Minutes: Set the minutes for the timer +* Seconds: Set the seconds for the timer +* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app. The widget is always there, but only visible when timer is on. + + +## Releases + +* Offifical app loader: Not yet published. +* Forked app loader: Not yet published. +* Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid + +## Requests + +If you have any feature requests, please contact me on the Espruino forum: http://forum.espruino.com/profiles/155005/ \ No newline at end of file diff --git a/apps/chronowid/app-icon.js b/apps/chronowid/app-icon.js new file mode 100644 index 000000000..db2010218 --- /dev/null +++ b/apps/chronowid/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIFCn/8BYYFRABcD4AFFgIFCh/wgeAAoP//8HCYMDAoPD8EAg4FB8PwgEf+EP/H4HQOAgP8uEAvwfBv0ggBFCn4CB/EBwEfgEB+AFBh+AgfgAoI1BIoQJB4AHBAoXgg4uBAIIFCCYQFGh5rDJQJUBK4IFCNYIFVDoopDGoJiBHYYFKVYRZBWIYDBA4IFBNIQzBG4IbBToKkBAQKVFUIYICVoQUCXIQmCYoIsCaITqDAoLvDNYUAA=")) \ No newline at end of file diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js new file mode 100644 index 000000000..cb99268af --- /dev/null +++ b/apps/chronowid/app.js @@ -0,0 +1,91 @@ +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +const storage = require('Storage'); +const boolFormat = v => v ? "On" : "Off"; +let settingsChronowid; + +function updateSettings() { + var now = new Date(); + const goal = new Date(now.getFullYear(), now.getMonth(), now.getDate(), + now.getHours() + settingsChronowid.hours, now.getMinutes() + settingsChronowid.minutes, now.getSeconds() + settingsChronowid.seconds); + settingsChronowid.goal = goal.getTime(); + storage.writeJSON('chronowid.json', settingsChronowid); +} + +function resetSettings() { + settingsChronowid = { + hours : 0, + minutes : 0, + seconds : 0, + started : false, + counter : 0, + goal : 0, + }; + updateSettings(); +} + +settingsChronowid = storage.readJSON('chronowid.json',1); +if (!settingsChronowid.started) resetSettings(); + +E.on('kill', () => { + print("-KILL-"); + updateSettings(); +}); + +function showMenu() { + const timerMenu = { + '': { + 'title': 'Set timer', + 'predraw': function() { + timerMenu.hours.value = settingsChronowid.hours; + timerMenu.minutes.value = settingsChronowid.minutes; + timerMenu.seconds.value = settingsChronowid.seconds; + timerMenu.started.value = settingsChronowid.started; + } + }, + 'Hours': { + value: settingsChronowid.hours, + min: 0, + max: 24, + step: 1, + onchange: v => { + settingsChronowid.hours = v; + updateSettings(); + } + }, + 'Minutes': { + value: settingsChronowid.minutes, + min: 0, + max: 59, + step: 1, + onchange: v => { + settingsChronowid.minutes = v; + updateSettings(); + } + }, + 'Seconds': { + value: settingsChronowid.seconds, + min: 0, + max: 59, + step: 1, + onchange: v => { + settingsChronowid.seconds = v; + updateSettings(); + } + }, + 'Timer on': { + value: settingsChronowid.started, + format: boolFormat, + onchange: v => { + settingsChronowid.started = v; + updateSettings(); + } + }, + }; + timerMenu['-Exit-'] = ()=>{load();}; + return E.showMenu(timerMenu); +} + +showMenu(); \ No newline at end of file diff --git a/apps/chronowid/app.png b/apps/chronowid/app.png new file mode 100644 index 0000000000000000000000000000000000000000..5ac7a480c5d4533c9851ba6264b74aae48035eb0 GIT binary patch literal 1060 zcmV+<1l#+GP)*2?CL* z=jdIsdaVqLAjyY*ycLl}Syc2;L97)RfoN7x+ost=DzrV^$!5>oot--~TQ7d$;EsFG z_k7Qtx%ZxXXA1}qX~XsfVFXm;x<_9I=$uURJ1ZseBV6R)F#Xg92 zC;;k!X6tX2rp*iB9q=U=45ym<6tfq%{NOz;R#zF~ zJ#TM22egDKJPw=zW_$>jHUpdnVmAI3OLSh6Xa!Os2$%L1*ptsBqQH3<0V&k;dH^*J zV!%>h8S0MJS>N^N=zw!Tp-U3u_?VrR0C%$lOrU0pB8}e`%Or|`Hefgl=b%lbJ&8}K z0d9mSa7Pnl3h2bW9NBGIHbj6fi%XY;{Z5Sg5f5-dL;ez|^x%8cvRtS_-ANgz&(_A* zqSmeY`$fNzK2BYIbgjB!6`wIzK6`b8=ix@{cYKKzS;Nui}lHqvFZQ(WIb6|yu`hkz&m1I8mjlf19JVWAIYSZF1nYXRZFlZI3veZ?Zx{Zz- z8U)9%7bjUM#@w4ba1E#UKX%2CD=z$#UYuryQ`9i1TdC|xfDJ{$-!T?-V<2r9M8a*K z9dr-w(56e^hqzvD804PIcY}spvhJGp;v`o<(?MK={xM1d>kPT%AWp~zx;ro;uD2Qn z9RX@lgZaBNBK9n5lVt>Xh&6?IE#n8Z zsI|x*yVnoVDxC9q0(E+jFT`XVq)WAoT2$kM2z58s3?hyzbG@mhlt>&`<*F<;=^ zP>ZwY)2MUOz$gT6YsjZjrw2i1rwDKu=QE!MZt?eMF)&KeCy_?gPVK0L$193a^SqoY z?cz&A(mszu+>h5Mfy=-_)QTBL?Ioht=LYM$0h}wWd~8DNc^%r&ZyAGHk`M;0SHw|0 z71k@JUh*@uTUMOHnq3)qg@)Rd!MF@c(8CV;o7*RA(a euUUTu4g4F8cKpwc4bA8P0000 { + 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() { + //printDebug(); + now = new Date(); + diff = settingsChronowid.goal - now; //calculate difference + WIDGETS["chronowid"].draw(); + //time is up + if (settingsChronowid.started && diff <= 0) { + 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 + } + } + 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 6fc326bb49ae2e004c6c210e84f68c3c76906764 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:10:57 +0200 Subject: [PATCH 0419/1189] Chronowid initial --- apps.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ab8af0f37..0d6cdd214 100644 --- a/apps.json +++ b/apps.json @@ -1108,7 +1108,7 @@ {"name":"openstmap.img","url":"app-icon.js","evaluate":true} ] }, - { "id": "activepedom", + { "id": "activepedom", "name": "Active Pedometer", "shortName":"Active Pedometer", "icon": "app.png", @@ -1123,6 +1123,21 @@ {"name":"activepedom.img","url":"app-icon.js","evaluate":true} ] }, + { "id": "chronowidget", + "name": "Chrono Widget", + "shortName":"Chrono Widget", + "icon": "app.png", + "version":"0.01", + "description": "Chronometer (timer) which runs as widget.", + "tags": "tools,widget", + "type":"widget", + "readme": "README.md", + "storage": [ + {"name":"chronowidget.wid.js","url":"widget.js"}, + {"name":"chronowidget.app.js","url":"app.js"}, + {"name":"chronowidget.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "tabata", "name": "Tabata", "shortName": "Tabata - Control High-Intensity Interval Training", From e2657a62a592ab6e4b3018bfb8f8216d0ff3412b Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:13:23 +0200 Subject: [PATCH 0420/1189] chronowid typo --- apps.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 0d6cdd214..591ddad28 100644 --- a/apps.json +++ b/apps.json @@ -1123,7 +1123,7 @@ {"name":"activepedom.img","url":"app-icon.js","evaluate":true} ] }, - { "id": "chronowidget", + { "id": "chronowid", "name": "Chrono Widget", "shortName":"Chrono Widget", "icon": "app.png", @@ -1133,9 +1133,9 @@ "type":"widget", "readme": "README.md", "storage": [ - {"name":"chronowidget.wid.js","url":"widget.js"}, - {"name":"chronowidget.app.js","url":"app.js"}, - {"name":"chronowidget.img","url":"app-icon.js","evaluate":true} + {"name":"chronowid.wid.js","url":"widget.js"}, + {"name":"chronowid.app.js","url":"app.js"}, + {"name":"chronowid.img","url":"app-icon.js","evaluate":true} ] }, { "id": "tabata", From e0a3b9ae3e15274d77d1a4af5ad7c8c90b737316 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 09:16:37 +0100 Subject: [PATCH 0421/1189] Launchers: Only store relevant app data (saves RAM when many apps) --- apps.json | 4 ++-- apps/launch/ChangeLog | 2 ++ apps/launch/app.js | 2 +- apps/toucher/ChangeLog | 3 ++- apps/toucher/app.js | 8 ++++---- 5 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 apps/launch/ChangeLog diff --git a/apps.json b/apps.json index d3dd95b26..167df46f6 100644 --- a/apps.json +++ b/apps.json @@ -41,7 +41,7 @@ "name": "Default Launcher", "shortName":"Launcher", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", "tags": "tool,system,launcher", "type":"launch", @@ -1050,7 +1050,7 @@ "name": "Touch Launcher", "shortName":"Menu", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "Touch enable left to right launcher.", "tags": "tool,system,launcher", "type":"launch", diff --git a/apps/launch/ChangeLog b/apps/launch/ChangeLog new file mode 100644 index 000000000..9e4a1eaf3 --- /dev/null +++ b/apps/launch/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Only store relevant app data (saves RAM when many apps) diff --git a/apps/launch/app.js b/apps/launch/app.js index 682122f82..a256b6909 100644 --- a/apps/launch/app.js +++ b/apps/launch/app.js @@ -1,5 +1,5 @@ var s = require("Storage"); -var apps = s.list(/\.info$/).map(app=>s.readJSON(app,1)||{name:"DEAD: "+app.substr(1)}).filter(app=>app.type=="app" || app.type=="clock" || !app.type); +var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src}}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)); apps.sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first diff --git a/apps/toucher/ChangeLog b/apps/toucher/ChangeLog index a2a709ee3..0c97d9e13 100644 --- a/apps/toucher/ChangeLog +++ b/apps/toucher/ChangeLog @@ -2,4 +2,5 @@ 0.02: Add swipe support and doucle tap to run application 0.03: Close launcher when lcd turn off 0.04: Complete rewrite to add animation and loop ( issue #210 ) -0.05: Improve perf \ No newline at end of file +0.05: Improve perf +0.06: Only store relevant app data (saves RAM when many apps) diff --git a/apps/toucher/app.js b/apps/toucher/app.js index b67e5b26c..cf7d5333b 100644 --- a/apps/toucher/app.js +++ b/apps/toucher/app.js @@ -5,8 +5,8 @@ g.flip(); const Storage = require("Storage"); function getApps(){ - return 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) + 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 @@ -19,7 +19,7 @@ function getApps(){ const HEIGHT = g.getHeight(); const WIDTH = g.getWidth(); const HALF = WIDTH/2; -const ANIMATION_FRAME = 4; +const ANIMATION_FRAME = 4; const ANIMATION_STEP = HALF / ANIMATION_FRAME; function getPosition(index){ @@ -192,4 +192,4 @@ Bangle.on('swipe', dir => { // close launcher when lcd is off Bangle.on('lcdPower', on => { if(!on) return load(); -}); \ No newline at end of file +}); From 8c2decfa7b1d8a2d059129622207bbe810645d6a Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:17:14 +0200 Subject: [PATCH 0422/1189] readme update --- apps/chronowid/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md index b6325d94f..f31c24c7b 100644 --- a/apps/chronowid/README.md +++ b/apps/chronowid/README.md @@ -27,7 +27,7 @@ There are no settings section in the settings app, timer can be set using an app ## Releases * Offifical app loader: Not yet published. -* Forked app loader: Not yet published. +* Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/chronowid (https://purple-tentacle.github.io/BangleApps/index.html#) * Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid ## Requests From 9704522813daaf13354e63f79ba0f655546161b4 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:26:32 +0200 Subject: [PATCH 0423/1189] removed type widget --- apps.json | 1 - 1 file changed, 1 deletion(-) diff --git a/apps.json b/apps.json index 591ddad28..0a894353b 100644 --- a/apps.json +++ b/apps.json @@ -1130,7 +1130,6 @@ "version":"0.01", "description": "Chronometer (timer) which runs as widget.", "tags": "tools,widget", - "type":"widget", "readme": "README.md", "storage": [ {"name":"chronowid.wid.js","url":"widget.js"}, From 8c6b78ebe19b29e7513d708a8f9bfe34d1f51cdf Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:32:41 +0200 Subject: [PATCH 0424/1189] Bugfix json creation --- apps/chronowid/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js index cb99268af..48401a7bb 100644 --- a/apps/chronowid/app.js +++ b/apps/chronowid/app.js @@ -27,7 +27,7 @@ function resetSettings() { } settingsChronowid = storage.readJSON('chronowid.json',1); -if (!settingsChronowid.started) resetSettings(); +if (!settingsChronowid) resetSettings(); E.on('kill', () => { print("-KILL-"); @@ -88,4 +88,4 @@ function showMenu() { return E.showMenu(timerMenu); } -showMenu(); \ No newline at end of file +showMenu(); From 304e23f53ed8715d640b797e94b7d2c041f9c990 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 11:23:19 +0200 Subject: [PATCH 0425/1189] Fix home button and add min/max for chart --- apps/batchart/app.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/apps/batchart/app.js b/apps/batchart/app.js index deb406d8b..2d0d8e585 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -65,9 +65,7 @@ function loadData() { // Top up to MaxValueCount from previous days as required let previousDay = decrementDay(startingDay); - while (dataLines.length < MaxValueCount - && previousDay !== startingDay) { - + while (dataLines.length < MaxValueCount && previousDay !== startingDay) { let topUpLogFileName = "bclog" + previousDay; let remainingLines = MaxValueCount - dataLines.length; let topUpLines = loadLinesFromFile(remainingLines, topUpLogFileName); @@ -126,6 +124,12 @@ function renderData(dataArray) { const batteryIndex = 1; const temperatureIndex = 2; const switchabelsIndex = 3; + + const minTemperature = 20; + const maxTemparature = 40; + + const belowMinIndicatorValue = minTemperature - 1; + const aboveMaxIndicatorValue = maxTemparature + 1; var allConsumers = switchableConsumers.none | switchableConsumers.lcd | switchableConsumers.compass | switchableConsumers.bluetooth | switchableConsumers.gps | switchableConsumers.hrm; @@ -140,8 +144,19 @@ function renderData(dataArray) { // Temperature g.setColor(0.4, 0.4, 1); - let scaledTemp = Math.floor(((parseFloat(dataInfo[temperatureIndex]) * 100) - 2000)/20) + ((((parseFloat(dataInfo[temperatureIndex]) * 100) - 2000) % 100)/25); + + let datapointTemp = parseFloat(dataInfo[temperatureIndex]); + if (datapointTemp < minTemperature) { + datapointTemp = belowMinIndicatorValue; + } + if (datapointTemp > maxTemparature) { + datapointTemp = aboveMaxIndicatorValue; + } + + // Scale down the range of 20 - 40°C to a 100px y-axis, where 1px = .25° + let scaledTemp = Math.floor(((datapointTemp * 100) - 2000) / 20) + ((((datapointTemp * 100) - 2000) % 100) / 25); + g.setPixel(GraphXZero + i, GraphYZero - scaledTemp); // LCD state @@ -213,8 +228,6 @@ function switchOffApp(){ // special function to handle display switch on Bangle.on('lcdPower', (on) => { if (on) { - // call your app function here - // If you clear the screen, do Bangle.drawWidgets(); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -222,12 +235,11 @@ Bangle.on('lcdPower', (on) => { } }); -setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true}); +setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -// call your app function here renderHomeIcon(); From 24eb0f33fef2431bb589d59f95c342005b08a03a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 11:24:17 +0200 Subject: [PATCH 0426/1189] Minor changes based on JSLint hints --- apps/batchart/widget.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 53f8b3549..1b8ce79ba 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -12,8 +12,8 @@ var batChartFile; // file for battery percentage recording const recordingInterval10Min = 60 * 10 * 1000; - const recordingInterval1Min = 60*1000; //For testing - const recordingInterval10S = 10*1000; //For testing + const recordingInterval1Min = 60 * 1000; //For testing + const recordingInterval10S = 10 * 1000; //For testing var recordingInterval = null; var compassEventReceived = false; @@ -26,15 +26,15 @@ let y = this.y; g.setColor(0, 1, 0); - g.fillPoly([x+5, y, x+5, y+4, x+1, y+4, x+1, y+20, x+18, y+20, x+18, y+4, x+13, y+4, x+13, y], true); + g.fillPoly([x + 5, y, x + 5, y + 4, x + 1, y + 4, x + 1, y + 20, x + 18, y + 20, x + 18, y + 4, x + 13, y + 4, x + 13, y], true); - g.setColor(0,0,0); - g.drawPoly([x+5, y+6, x+8, y+12, x+13, y+12, x+16, y+18], false); + g.setColor(0, 0, 0); + g.drawPoly([x + 5, y + 6, x + 8, y + 12, x + 13, y + 12, x + 16, y + 18], false); g.reset(); } - function onMag(){ + function onMag() { compassEventReceived = true; // Stop handling events when no longer necessarry Bangle.removeListener("mag", onMag); @@ -51,6 +51,7 @@ } function getEnabledConsumersValue() { + // Wait for an event from each of the devices to see if they are switched on var enabledConsumers = switchableConsumers.none; Bangle.on('mag', onMag); @@ -58,13 +59,12 @@ Bangle.on('HRM', onHrm); // Wait two seconds, that should be enough for each of the events to get raised once - setTimeout(() => { + setTimeout(() => { Bangle.removeAllListeners(); }, 2000); if (Bangle.isLCDOn()) enabledConsumers = enabledConsumers | switchableConsumers.lcd; - // Already added in the hope they will be available soon to get more details if (compassEventReceived) enabledConsumers = enabledConsumers | switchableConsumers.compass; if (gpsEventReceived) @@ -90,8 +90,7 @@ const logFileName = "bclog" + currentWriteDay; // Change log target on day change - if (!isNaN(previousWriteDay) - && previousWriteDay != currentWriteDay) { + if (!isNaN(previousWriteDay) && previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago Storage.open(logFileName, "r").erase(); Storage.open(previousWriteLogName, "w").write(parseInt(currentWriteDay)); @@ -111,7 +110,7 @@ } function reload() { - WIDGETS["batchart"].width = 24; + WIDGETS.batchart.width = 24; recordingInterval = setInterval(logBatteryData, recordingInterval10Min); @@ -119,11 +118,12 @@ } // add the widget - WIDGETS["batchart"]={area:"tl",width:24,draw:draw,reload:function() { - reload(); - Bangle.drawWidgets(); // relayout all widgets - }}; + WIDGETS.batchart = { + area: "tl", width: 24, draw: draw, reload: function () { + reload(); + Bangle.drawWidgets(); + } + }; - // load settings, set correct widget width reload(); -})() \ No newline at end of file +})(); \ No newline at end of file From bb42044aa92f25f5375112194488c82ce76f0a37 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 10:25:13 +0100 Subject: [PATCH 0427/1189] Show elapsed time, and tweak stopwatch so lap times don't overlap the bottom widget area --- apps/swatch/interface.html | 3 ++- apps/swatch/stopwatch.js | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 928c5fe39..45391fb6e 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -17,11 +17,12 @@ function getLapTimes() {
\n`; lapData.forEach((lap,lapIndex) => { lap.date = lap.n.substr(7,16).replace("_"," "); + lap.elapsed = lap.d.shift(); // remove first item html += `
${lap.date}
-
${lap.d.length} Laps
+
${lap.d.length} Laps, total time ${lap.elapsed}
diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 478c22619..659f0606d 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -27,10 +27,10 @@ function updateLabels() { g.setFont("6x8",1); g.setFontAlign(-1,-1); for (var i in lapTimes) { - if (i<16) + if (i<15) {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 40 + i*8);} - else if (i<32) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 40 + (i-16)*8);} + else if (i<30) + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 40 + (i-15)*8);} } drawsecs(); } @@ -92,12 +92,12 @@ setWatch(function() { // Start/stop updateLabels(); if (started) displayInterval = setInterval(function() { - var last = tCurrent; - if (started) tCurrent = Date.now(); - if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) - drawsecs(); - else - drawms(); + var last = tCurrent; + if (started) tCurrent = Date.now(); + if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) + drawsecs(); + else + drawms(); }, 20); }, BTN2, {repeat:true}); @@ -108,10 +108,10 @@ setWatch(function() { // Lap lapTimes.unshift(tCurrent-tStart); } if (!started) { // save - var timenow= Date(); var filename = "swatch-"+(new Date()).toISOString().substr(0,16).replace("T","_")+".json"; + if (tCurrent!=tStart) + lapTimes.unshift(tCurrent-tStart); // this maxes out the 28 char maximum - lapTimes.unshift(tCurrent-tStart); require("Storage").writeJSON(filename, getLapTimesArray()); tStart = tCurrent = tTotal = Date.now(); lapTimes = []; From de2dc3a2cc23010af7d1cdb454048401ece9cf33 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 11:26:57 +0200 Subject: [PATCH 0428/1189] Add readme and increment version --- apps.json | 3 +- apps/batchart/ChangeLog | 3 +- apps/batchart/README.md | 67 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 apps/batchart/README.md diff --git a/apps.json b/apps.json index 7449a233b..7985c6776 100644 --- a/apps.json +++ b/apps.json @@ -1178,7 +1178,8 @@ "name": "Battery Chart", "shortName":"Battery Chart", "icon": "app.png", - "version":"0.07", + "version":"0.08", + "readme": "README.md", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index ba9e4e847..439d877be 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -4,4 +4,5 @@ 0.04: chart in the app is now active. 0.05: Display temperature and LCD state in chart 0.06: Fixes widget events and charting of component states -0.07: Improve logging and charting of component states and add widget icon \ No newline at end of file +0.07: Improve logging and charting of component states and add widget icon +0.08: Fix for Home button in the app and README added. \ No newline at end of file diff --git a/apps/batchart/README.md b/apps/batchart/README.md new file mode 100644 index 000000000..0ce2c646d --- /dev/null +++ b/apps/batchart/README.md @@ -0,0 +1,67 @@ +# Summary + +Battery Chart contains a widget that records the battery usage as well as information that might influence this usage. + +The app that comes with provides a graph that accumulates this information in a single screen. + +## How the widget works + +The widget records data in a fixed interval of ten minutes. + +When this timespan has passed, it saves the following information to a file called `bclogx` where `x` is + +the current day retrieved by `new Date().getDay()`: + +- Battery percentage +- Temperature (of the die) +- LCD state +- Compass state +- HRM state +- GPS state + +After seven days the logging rolls over and the previous data is overwritten. + +To properly handle the roll-over, the day of the previous logging operation is stored in `bcprvday`. + +The value is changed with the first recording operation of the new day. + +## How the App works + +### Events + +The app charts the last 144 (6/h * 24h) datapoints that have been recorded. + +If for the current day the 144 events have not been reached the list is padded with + +events from the previous `bclog` file(s). + +### Graph + +The graph then contains the battery percentage (left y-axis) and the temperature (right y-axis). + +In case the recorded temperature is outside the limits of the graph, the value is set to a minimum of 19 or a maximum of 41 and thus should be clearly visible outside of the graph's boundaries for the y-axis. + +The states of the various SoC devices are depicted below the graph. If at the time of recording the device was enabled a marker in the respective color is set, if not the pixels for this point in time stay black. + +If a device was not enabled during the 144 selected events, the name is not displayed. + +## File schema + +You can download the `bclog` files for your own analysis. They are `CSV` files without header rows and contain + +``` +timestamp,batteryPercentage,temperatureInDegreeC,deviceStates +``` + +with the `deviceStates` resembling a flag set consisting of + +``` +const switchableConsumers = { + none: 0, + lcd: 1, + compass: 2, + bluetooth: 4, + gps: 8, + hrm: 16 +}; +``` From a4ec9965ba5dae7768b20f25aadec9e6459411b4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 10:31:59 +0100 Subject: [PATCH 0429/1189] Make widget play well with other Gadgetbridge widgets/apps --- apps.json | 2 +- apps/gbridge/ChangeLog | 1 + apps/gbridge/widget.js | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e6fb7aaac..447d45154 100644 --- a/apps.json +++ b/apps.json @@ -93,7 +93,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.09", + "version":"0.10", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index 53f8a1b4c..f23a4eb6d 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -8,3 +8,4 @@ 0.07: Move configuration to settings menu 0.08: Don't turn on LCD at start of every song 0.09: Update Bluetooth connection state automatically +0.10: Make widget play well with other Gadgetbridge widgets/apps diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 03c622443..a87b9d1ec 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -145,6 +145,7 @@ } } + var _GB = global.GB; global.GB = (event) => { switch (event.t) { case "notify": @@ -160,6 +161,7 @@ handleCallEvent(event); break; } + if(_GB)setTimeout(_GB,0,event); }; // Touch control From eb4ac302ccd3464bd3d97b6f18b5fa635fcbe436 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 11:33:36 +0100 Subject: [PATCH 0430/1189] Reduce memory usage further when running app settings page --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 447d45154..0adf7de0b 100644 --- a/apps.json +++ b/apps.json @@ -120,7 +120,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.15", + "version":"0.16", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 3d82be9c0..3acfb5fb0 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -17,3 +17,4 @@ Move LCD Brightness menu into more general LCD menu 0.14: Reduce memory usage when running app settings page 0.15: Reduce memory usage when running default clock chooser (#294) +0.16: Reduce memory usage further when running app settings page diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 9e343a68e..d0d88ce20 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -417,7 +417,7 @@ function showAppSettingsMenu() { '< Back': ()=>showMainMenu(), } const apps = storage.list(/\.info$/) - .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?a:undefined}) + .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?{sortorder:a.sortorder,name:a.name,settings:a.settings}:undefined}) .filter(app => app) // filter out any undefined apps .sort((a, b) => a.sortorder - b.sortorder) if (apps.length === 0) { From 92c24e2cfc5f5d5f1b391b61a57674641c20becd Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Thu, 16 Apr 2020 12:35:43 +0200 Subject: [PATCH 0431/1189] Fix URLs in Webmanifest Signed-off-by: OmegaRogue --- site.webmanifest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site.webmanifest b/site.webmanifest index 0565f159c..0d1fb4679 100644 --- a/site.webmanifest +++ b/site.webmanifest @@ -17,6 +17,6 @@ "theme_color": "#5755d9", "background_color": "#5755d9", "display": "standalone", - "start_url": "https://omegavoid.codes/BangleApps", - "scope": "https://omegavoid.codes/BangleApps" + "start_url": "https://banglejs.com/apps/", + "scope": "https://banglejs.com/apps/" } From b02af77e514aa4bbcb41a8ab2039bb81762a1b03 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Thu, 16 Apr 2020 12:48:35 +0200 Subject: [PATCH 0432/1189] Add Description, Remove add_to_apps.json Add Description Remove add_to_apps.json Signed-off-by: OmegaRogue --- apps.json | 4 ++-- apps/dane/ChangeLog | 3 ++- apps/dane/add_to_apps.json | 22 ---------------------- 3 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 apps/dane/add_to_apps.json diff --git a/apps.json b/apps.json index 91d2d249b..c29bf8018 100644 --- a/apps.json +++ b/apps.json @@ -1247,8 +1247,8 @@ "name": "Digital Assistant, not EDITH", "shortName": "DANE", "icon": "app.png", - "version": "0.06", - "description": "A detailed description of my great app", + "version": "0.07", + "description": "A Watchface inspired by Tony Stark's EDITH", "tags": "clock", "type": "clock", "allow_emulator": true, diff --git a/apps/dane/ChangeLog b/apps/dane/ChangeLog index 607d0adf5..419109ec1 100644 --- a/apps/dane/ChangeLog +++ b/apps/dane/ChangeLog @@ -1,4 +1,5 @@ 0.01: New App! 0.04: Added Icon to watchface 0.05: bugfix -0.06: moved and resized icon \ No newline at end of file +0.06: moved and resized icon +0.07: Added Description \ No newline at end of file diff --git a/apps/dane/add_to_apps.json b/apps/dane/add_to_apps.json deleted file mode 100644 index 6efb3ec85..000000000 --- a/apps/dane/add_to_apps.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "id": "dane", - "name": "Digital Assistant, not EDITH", - "shortName": "DANE", - "icon": "app.png", - "version": "0.06", - "description": "A detailed description of my great app", - "tags": "clock", - "type": "clock", - "allow_emulator": true, - "storage": [ - { - "name": "dane.app.js", - "url": "app.js" - }, - { - "name": "dane.img", - "url": "app-icon.js", - "evaluate": true - } - ] -} \ No newline at end of file From 217d19815456966c0fd268e31153d6bf8ac57e63 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 12 Apr 2020 00:26:08 +0200 Subject: [PATCH 0433/1189] Add a "data" section to apps.json, with data files to clean on uninstall These are added to `appid.info` as "dataFiles" or "storageFiles", and can contain wildcards. --- README.md | 25 ++++++++++++++++++++----- bin/sanitycheck.js | 33 +++++++++++++++++++++++++++++++++ js/appinfo.js | 13 +++++++++++++ js/comms.js | 24 +++++++++++++++++++++--- js/index.js | 13 +++++++++++++ js/utils.js | 12 ++++++++++++ 6 files changed, 112 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ca874ad2f..7a96ad335 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,13 @@ and which gives information about the app for the Launcher. "files:"file1,file2,file3", // added by BangleApps loader on upload - lists all files // that belong to the app so it can be deleted + "dataFiles":"appid.data.json,appid.data?.json" + // added by BangleApps loader on upload - lists files that + // the app might write, so they can be deleted on uninstall + // typically these files are not uploaded, but created by the app + // these can include '*' or '?' wildcards + "storageFiles":" + // same as "dataFiles", except the app handles these as storageFile } ``` @@ -240,16 +247,27 @@ and which gives information about the app for the Launcher. "evaluate":true // if supplied, data isn't quoted into a String before upload // (eg it's evaluated as JS) }, + ] + "data": [ // list of files the app writes to + {"name":"appid.data.json", // filename used in storage + "storageFile":true // if supplied, file is treated as storageFile + }, + {"wildcard":"appid.data.*" // wildcard of filenames used in storage + }, // this is mutually exclusive with using "name" + ], "sortorder" : 0, // optional - choose where in the list this goes. // this should only really be used to put system // stuff at the top - ] } ``` * name, icon and description present the app in the app loader. * tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget`, `launcher` or empty. * storage is used to identify the app files and how to handle them +* data is used to clean up files when the app is uninstalled + (If the app has settings but no data section, it is assumed settings are + stored in `appid.settings.json`, so there is no need to add a data section + containing only that file) ### `apps.json`: `custom` element @@ -351,19 +369,16 @@ Example `settings.js` E.showMenu(appMenu) }) ``` -In this example the app needs to add both `app.settings.js` and -`app.settings.json` to `apps.json`: +In this example the app needs to add `app.settings.js` to `apps.json`: ```json { "id": "app", ... "storage": [ ... {"name":"app.settings.js","url":"settings.js"}, - {"name":"app.settings.json","content":"{}"} ] }, ``` -That way removing the app also cleans up `app.settings.json`. ## Coding hints diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 62b111ae0..fdf15a26b 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -74,6 +74,8 @@ apps.forEach((app,appIdx) => { var fileNames = []; app.storage.forEach((file) => { if (!file.name) ERROR(`App ${app.id} has a file with no name`); + if (file.name.includes('?') || file.name.includes('*')) + ERROR(`App ${app.id} storage file ${file.name} contains wildcards`); if (fileNames.includes(file.name)) ERROR(`App ${app.id} file ${file.name} is a duplicate`); fileNames.push(file.name); @@ -115,6 +117,37 @@ apps.forEach((app,appIdx) => { if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id}'s ${file.name} has unknown key ${key}`); } }); + let dataNames = []; + (app.data||[]).forEach((data)=>{ + if (!data.name && !data.wildcard) ERROR(`App ${app.id} has a data file with no name`); + if (dataNames.includes(data.name||data.wildcard)) + ERROR(`App ${app.id} data file ${data.name||data.wildcard} is a duplicate`); + dataNames.push(data.name||data.wildcard) + if ('name' in data && 'wildcard' in data) + ERROR(`App ${app.id} data file ${data.name} has both name and wildcard`); + if (data.name) { + if (data.name.includes('?') || data.name.includes('*')) + ERROR(`App ${app.id} data file name ${data.name} contains wildcards`); + } + if (data.wildcard) { + if (!data.wildcard.includes('?') && !data.wildcard.includes('*')) + ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not actually contains wildcard`); + if (data.wildcard.replace(/\?|\*/g,'') === '') + ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not contain regular characters`); + else if (data.wildcard.replace(/\?|\*/g,'').length < 3) + WARN(`App ${app.id} data file wildcard ${data.wildcard} is very broad`); + else if (!data.wildcard.includes(app.id)) + WARN(`App ${app.id} data file wildcard ${data.wildcard} does not include app ID`); + } + if ('storageFile' in data && typeof data.storageFile !== 'boolean') + ERROR(`App ${app.id} data file ${data.name||data.wildcard} has non-boolean value for "storageFile"`); + for (const key in data) { + if (!['name','wildcard','storageFile'].includes(key)) + ERROR(`App ${app.id} data file ${data.name||data.wildcard} has unknown property "${key}"`); + } + }); + if (fileNames.includes(app.id+".settings.js") && dataNames.length===1 && dataNames[0] === app.id+'.settings.json') + WARN(`App ${app.id} has settings, so does not need to declare data file ${app.id+'.settings.json'}`) //console.log(fileNames); if (isApp && !fileNames.includes(app.id+".app.js")) ERROR(`App ${app.id} has no entrypoint`); if (isApp && !fileNames.includes(app.id+".img")) ERROR(`App ${app.id} has no JS icon`); diff --git a/js/appinfo.js b/js/appinfo.js index f4ab498b1..04c5da893 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -69,6 +69,19 @@ var AppInfo = { var fileList = fileContents.map(storageFile=>storageFile.name); fileList.unshift(appJSONName); // do we want this? makes life easier! json.files = fileList.join(","); + let dataFileList = [], storageFileList = []; + if ('data' in app) { + // add "data" files to appropriate list + app.data.forEach(d=>{ + if (d.storageFile) storageFileList.push(d.name||d.wildcard) + else dataFileList.push(d.name||d.wildcard) + }) + } else if (json.settings) { + // settings but no data files: assume app uses .settings.json file + dataFileList.push(app.id + '.settings.json') + } + if (dataFileList.length) json.dataFiles = dataFileList.join(","); + if (storageFileList.length) json.storageFiles = storageFileList.join(","); fileContents.push({ name : appJSONName, content : JSON.stringify(json) diff --git a/js/comms.js b/js/comms.js index 1f840ada7..1e8250305 100644 --- a/js/comms.js +++ b/js/comms.js @@ -94,10 +94,28 @@ getInstalledApps : () => { }); }, removeApp : app => { // expects an appid.info structure (i.e. with `files`) - if (app.files === '') return Promise.resolve(); // nothing to erase + if (!app.files && !app.dataFiles && !app.storageFiles) return Promise.resolve(); // nothing to erase Progress.show({title:`Removing ${app.name}`,sticky:true}); - var cmds = app.files.split(',').map(file=>{ - return `\x10require("Storage").erase(${toJS(file)});\n`; + let cmds = '\x10const s=require("Storage");\n'; + // remove App files (regular files, exact names only) + cmds += app.files.split(',').map(file => `\x10s.erase(${toJS(file)});\n`).join(""); + // remove Data files (regular files, can use wildcards) + cmds += (app.dataFiles||[]).split(',').map(file => { + const isGlob = (file.includes('*') || file.includes('?')) + if (!isGlob) return `\x10s.erase(${toJS(file)});\n`; + const regex = new RegExp(globToRegex(file)) + return `\x10s.list(${regex}).forEach(f=>s.erase(f));\n`; + }).join(""); + // remove Storage files (storageFiles, can use wildcards) + cmds += (app.storageFiles||[]).split(',').map(file => { + const isGlob = (file.includes('*') || file.includes('?')) + if (!isGlob) return `\x10s.open(${toJS(file)},'r').erase();\n`; + // storageFiles have a chunk number appended to their real name + const regex = globToRegex(file+'\u0001') + // open() doesn't want the chunk number though + let cmd = `\x10s.list(${regex}).forEach(f=>s.open(f.substring(0,f.length-1),'r').erase());\n` + // using a literal \u0001 char fails (not sure why), so escape it + return cmd.replace('\u0001', '\\x01') }).join(""); console.log("removeApp", cmds); return Comms.reset().then(new Promise((resolve,reject) => { diff --git a/js/index.js b/js/index.js index ef9bcb4f1..c48920315 100644 --- a/js/index.js +++ b/js/index.js @@ -349,6 +349,19 @@ function updateApp(app) { .filter(f => f !== app.id + '.info') .filter(f => !app.storage.some(s => s.name === f)) .join(','); + let dataFiles = (remove.dataFiles||'').split(','), + storageFiles = (remove.storageFiles||'').split(',') + if ('data' in app) { + // keep declared (in new version) data files + dataFiles = dataFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) + storageFiles = storageFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) + } + else if (remove.settings || app.settings) { + // app with settings but no data files declared: keep .settings.json + dataFiles = dataFiles.filter(f => f !== (app.id + '.settings.json')) + } + if (dataFiles.length) remove.dataFiles = dataFiles.join(','); + if (storageFiles.length) remove.storageFiles = storageFiles.join(',') return Comms.removeApp(remove); }).then(()=>{ showToast(`Updating ${app.name}...`); diff --git a/js/utils.js b/js/utils.js index d8c1b8063..50d319338 100644 --- a/js/utils.js +++ b/js/utils.js @@ -8,6 +8,18 @@ function escapeHtml(text) { }; return text.replace(/[&<>"']/g, function(m) { return map[m]; }); } +// simple glob to regex conversion, only supports "*" and "?" wildcards +function globToRegex(pattern) { + const ESCAPE = '.*+-?^${}()|[]\\'; + const regex = pattern.replace(/./g, c => { + switch (c) { + case '?': return '.'; + case '*': return '.*'; + default: return ESCAPE.includes(c) ? ('\\' + c) : c; + } + }); + return new RegExp('^'+regex+'$'); +} function htmlToArray(collection) { return [].slice.call(collection); } From 9e0fd91339dc48acd38c4c0687000f199ddb5c23 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 15 Apr 2020 21:30:44 +0200 Subject: [PATCH 0434/1189] Data files: save all data files as a single string Separate regular and storage files by a semicolon --- README.md | 4 +--- bin/sanitycheck.js | 5 +++-- js/appinfo.js | 39 ++++++++++++++++++++++++++++++++------- js/comms.js | 14 ++++++++------ js/index.js | 18 ++++++++---------- 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7a96ad335..a04ee95b2 100644 --- a/README.md +++ b/README.md @@ -202,13 +202,11 @@ and which gives information about the app for the Launcher. "files:"file1,file2,file3", // added by BangleApps loader on upload - lists all files // that belong to the app so it can be deleted - "dataFiles":"appid.data.json,appid.data?.json" + "data":"appid.data.json,appid.data?.json;appidStorageFile,appidStorageFile*" // added by BangleApps loader on upload - lists files that // the app might write, so they can be deleted on uninstall // typically these files are not uploaded, but created by the app // these can include '*' or '?' wildcards - "storageFiles":" - // same as "dataFiles", except the app handles these as storageFile } ``` diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index fdf15a26b..197ebf57e 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -39,9 +39,10 @@ try{ const APP_KEYS = [ 'id', 'name', 'shortName', 'version', 'icon', 'description', 'tags', 'type', - 'sortorder', 'readme', 'custom', 'interface', 'storage', 'allow_emulator', + 'sortorder', 'readme', 'custom', 'interface', 'storage', 'data', 'allow_emulator', ]; const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate']; +const DATA_KEYS = ['name', 'wildcard', 'storageFile']; apps.forEach((app,appIdx) => { if (!app.id) ERROR(`App ${appIdx} has no id`); @@ -142,7 +143,7 @@ apps.forEach((app,appIdx) => { if ('storageFile' in data && typeof data.storageFile !== 'boolean') ERROR(`App ${app.id} data file ${data.name||data.wildcard} has non-boolean value for "storageFile"`); for (const key in data) { - if (!['name','wildcard','storageFile'].includes(key)) + if (!DATA_KEYS.includes(key)) ERROR(`App ${app.id} data file ${data.name||data.wildcard} has unknown property "${key}"`); } }); diff --git a/js/appinfo.js b/js/appinfo.js index 04c5da893..413098bc4 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -69,26 +69,51 @@ var AppInfo = { var fileList = fileContents.map(storageFile=>storageFile.name); fileList.unshift(appJSONName); // do we want this? makes life easier! json.files = fileList.join(","); - let dataFileList = [], storageFileList = []; + let data = {dataFiles: [], storageFiles: []}; if ('data' in app) { // add "data" files to appropriate list app.data.forEach(d=>{ - if (d.storageFile) storageFileList.push(d.name||d.wildcard) - else dataFileList.push(d.name||d.wildcard) + if (d.storageFile) data.storageFiles.push(d.name||d.wildcard) + else data.dataFiles.push(d.name||d.wildcard) }) } else if (json.settings) { // settings but no data files: assume app uses .settings.json file - dataFileList.push(app.id + '.settings.json') + data.dataFiles.push(app.id + '.settings.json') } - if (dataFileList.length) json.dataFiles = dataFileList.join(","); - if (storageFileList.length) json.storageFiles = storageFileList.join(","); + const dataString = AppInfo.makeDataString(data) + if (dataString) json.data = dataString fileContents.push({ name : appJSONName, content : JSON.stringify(json) }); resolve(fileContents); }); - } + }, + // (.info).data holds filenames of data: both regular and storageFiles + // These are stored as: (note comma vs semicolons) + // "fil1,file2", "file1,file2;storageFileA,storageFileB" or ";storageFileA" + /** + * Convert appid.info "data" to object with file names/patterns + * Passing in undefined works + * @param data "data" as stored in appid.info + * @returns {{storageFiles:[], dataFiles:[]}} + */ + parseDataString(data) { + data = data || ''; + let [files = [], storage = []] = data.split(';').map(d => d.split(',')) + return {dataFiles: files, storageFiles: storage} + }, + /** + * Convert object with file names/patterns to appid.info "data" string + * Passing in an incomplete object will not work + * @param data {{storageFiles:[], dataFiles:[]}} + * @returns {string} "data" to store in appid.info + */ + makeDataString(data) { + if (!data.dataFiles.length && !data.storageFiles.length) { return '' } + if (!data.storageFiles.length) { return data.dataFiles.join(',') } + return [data.dataFiles.join(','),data.storageFiles.join(',')].join(';') + }, }; if ("undefined"!=typeof module) diff --git a/js/comms.js b/js/comms.js index 1e8250305..736a2b7c7 100644 --- a/js/comms.js +++ b/js/comms.js @@ -94,20 +94,22 @@ getInstalledApps : () => { }); }, removeApp : app => { // expects an appid.info structure (i.e. with `files`) - if (!app.files && !app.dataFiles && !app.storageFiles) return Promise.resolve(); // nothing to erase + if (!app.files && !app.data) return Promise.resolve(); // nothing to erase Progress.show({title:`Removing ${app.name}`,sticky:true}); let cmds = '\x10const s=require("Storage");\n'; - // remove App files (regular files, exact names only) + // remove App files: regular files, exact names only cmds += app.files.split(',').map(file => `\x10s.erase(${toJS(file)});\n`).join(""); - // remove Data files (regular files, can use wildcards) - cmds += (app.dataFiles||[]).split(',').map(file => { + // remove app Data: (dataFiles and storageFiles) + const data = AppInfo.parseDataString(app.data) + // regular files, can use wildcards + cmds += data.dataFiles.map(file => { const isGlob = (file.includes('*') || file.includes('?')) if (!isGlob) return `\x10s.erase(${toJS(file)});\n`; const regex = new RegExp(globToRegex(file)) return `\x10s.list(${regex}).forEach(f=>s.erase(f));\n`; }).join(""); - // remove Storage files (storageFiles, can use wildcards) - cmds += (app.storageFiles||[]).split(',').map(file => { + // storageFiles, can use wildcards + cmds += data.storageFiles.map(file => { const isGlob = (file.includes('*') || file.includes('?')) if (!isGlob) return `\x10s.open(${toJS(file)},'r').erase();\n`; // storageFiles have a chunk number appended to their real name diff --git a/js/index.js b/js/index.js index c48920315..41a43730e 100644 --- a/js/index.js +++ b/js/index.js @@ -349,19 +349,17 @@ function updateApp(app) { .filter(f => f !== app.id + '.info') .filter(f => !app.storage.some(s => s.name === f)) .join(','); - let dataFiles = (remove.dataFiles||'').split(','), - storageFiles = (remove.storageFiles||'').split(',') + let data = AppInfo.parseDataString(remove.data) if ('data' in app) { - // keep declared (in new version) data files - dataFiles = dataFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) - storageFiles = storageFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) - } - else if (remove.settings || app.settings) { + // only remove data files which are no longer declared in new app version + const removeData = (f) => !app.data.some(d => (d.name || d.wildcard)===f) + data.dataFiles = data.dataFiles.filter(removeData) + data.storageFiles = data.storageFiles.filter(removeData) + } else if (remove.settings || app.settings) { // app with settings but no data files declared: keep .settings.json - dataFiles = dataFiles.filter(f => f !== (app.id + '.settings.json')) + data.dataFiles = data.dataFiles.filter(f => f!==(app.id+'.settings.json')) } - if (dataFiles.length) remove.dataFiles = dataFiles.join(','); - if (storageFiles.length) remove.storageFiles = storageFiles.join(',') + remove.data = AppInfo.makeDataString(data) return Comms.removeApp(remove); }).then(()=>{ showToast(`Updating ${app.name}...`); From 3e5cfcdc12cdaadbf5f761ea2883905ca8ad4583 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 14:32:42 +0200 Subject: [PATCH 0435/1189] Fixed home button and added readme for WOHRM --- apps.json | 1 + apps/wohrm/ChangeLog | 1 + apps/wohrm/README.md | 29 +++++++++++++++++++++++++++++ apps/wohrm/app.js | 7 ++----- 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 apps/wohrm/README.md diff --git a/apps.json b/apps.json index 899eed03e..459ecb3ab 100644 --- a/apps.json +++ b/apps.json @@ -891,6 +891,7 @@ "name": "Workout HRM", "icon": "app.png", "version":"0.06", + "readme": "README.md", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index f5c64dbee..53c451bcd 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -4,3 +4,4 @@ 0.04: Only buzz on high confidence (>85%) 0.05: Improved buzz timing and rendering 0.06: Removed debug outputs, fixed rendering for upper limit, improved rendering for +/- icons, changelog version order fixed +0.07: Home button fixed and README added \ No newline at end of file diff --git a/apps/wohrm/README.md b/apps/wohrm/README.md new file mode 100644 index 000000000..ad9e82525 --- /dev/null +++ b/apps/wohrm/README.md @@ -0,0 +1,29 @@ +# Summary +Workout heart rate monitor that buzzes when your heart rate hits the limits. + +This app is for the [Bangle.js watch](https://banglejs.com/). While active it monitors your heart rate +and will notify you with a buzz whenever your heart rate falls below or jumps above the set limits. + +# How it works +[Try it out](https://www.espruino.com/ide/emulator.html?codeurl=https://raw.githubusercontent.com/msdeibel/BangleApps/master/apps/wohrm/app.js&upload) using the [online Espruino emulator](https://www.espruino.com/ide/emulator.html). + +## Setting the limits +For setting the lower limit press button 4 (left part of the watch's touch screen). +Then adjust the value with the buttons 1 (top) and 3 (bottom) of the watch. + +For setting the upper limit act accordingly after pressing button 5 (the right part of the watch's screen). + +## Reading Reliability +As per the specs of the watch the HR monitor is not 100% reliable all the time. +That's why the WOHRM displays a confidence value for each reading of the current heart rate. + +To the left and right of the "Current" value two colored bars indicate the confidence in +the received value: For 85% and above the bars are green, between 84% and 50% the bars are yellow +and below 50% they turn red. + +## Closing the app +Pressing button 2 (middle) will switch off the HRM of the watch and return you to the launcher. + +# HRM usage +The HRM is switched on when the app is started. It stays switch on while the app is running, even +when the watch screen goes to stand-by. diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 7e0af4219..b3ce8acc8 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -287,13 +287,11 @@ function resetHighlightTimeout() { setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); } -// Show launcher when middle button pressed function switchOffApp(){ Bangle.setHRMPower(0); Bangle.showLauncher(); } -// special function to handle display switch on Bangle.on('lcdPower', (on) => { g.clear(); if (on) { @@ -312,19 +310,18 @@ Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true}); setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); +setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -//drawTrainingHeartRate(); renderHomeIcon(); renderLowerLimitBackground(); renderUpperLimitBackground(); -// refesh every sec setInterval(drawTrainingHeartRate, 1000); From 9f0adf190019b5dd0bcef5f713c34dabd8ca1c3d Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 16 Apr 2020 17:06:25 +0200 Subject: [PATCH 0436/1189] Data files: remove settings magic, some more sanitychecks --- README.md | 13 +++++---- bin/sanitycheck.js | 69 ++++++++++++++++++++++++++++++++++++++++------ js/appinfo.js | 9 ++---- js/comms.js | 7 ++--- js/index.js | 3 -- 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index a04ee95b2..a45647daf 100644 --- a/README.md +++ b/README.md @@ -263,9 +263,6 @@ and which gives information about the app for the Launcher. * tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget`, `launcher` or empty. * storage is used to identify the app files and how to handle them * data is used to clean up files when the app is uninstalled - (If the app has settings but no data section, it is assumed settings are - stored in `appid.settings.json`, so there is no need to add a data section - containing only that file) ### `apps.json`: `custom` element @@ -351,10 +348,10 @@ Example `settings.js` ```js // make sure to enclose the function in parentheses (function(back) { - let settings = require('Storage').readJSON('app.settings.json',1)||{}; + let settings = require('Storage').readJSON('app.json',1)||{}; function save(key, value) { settings[key] = value; - require('Storage').write('app.settings.json',settings); + require('Storage').write('app.json',settings); } const appMenu = { '': {'title': 'App Settings'}, @@ -367,13 +364,17 @@ Example `settings.js` E.showMenu(appMenu) }) ``` -In this example the app needs to add `app.settings.js` to `apps.json`: +In this example the app needs to add `app.settings.js` to `storage` in `apps.json`. +It should also add `app.json` to `data`, to make sure it is cleaned up when the app is uninstalled. ```json { "id": "app", ... "storage": [ ... {"name":"app.settings.js","url":"settings.js"}, + ], + "data": [ + {"name":"app.json"} ] }, ``` diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 197ebf57e..51230f6fa 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -43,7 +43,22 @@ const APP_KEYS = [ ]; const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate']; const DATA_KEYS = ['name', 'wildcard', 'storageFile']; +const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info +function globToRegex(pattern) { + const ESCAPE = '.*+-?^${}()|[]\\'; + const regex = pattern.replace(/./g, c => { + switch (c) { + case '?': return '.'; + case '*': return '.*'; + default: return ESCAPE.includes(c) ? ('\\' + c) : c; + } + }); + return new RegExp('^'+regex+'$'); +} +const isGlob = f => /[?*]/.test(f) +// All storage+data files in all apps: {app:,[file: | data:]} +let allFiles = []; apps.forEach((app,appIdx) => { if (!app.id) ERROR(`App ${appIdx} has no id`); //console.log(`Checking ${app.id}...`); @@ -75,11 +90,13 @@ apps.forEach((app,appIdx) => { var fileNames = []; app.storage.forEach((file) => { if (!file.name) ERROR(`App ${app.id} has a file with no name`); - if (file.name.includes('?') || file.name.includes('*')) - ERROR(`App ${app.id} storage file ${file.name} contains wildcards`); + if (isGlob(file.name)) ERROR(`App ${app.id} storage file ${file.name} contains wildcards`); + let char = file.name.match(FORBIDDEN_FILE_NAME_CHARS) + if (char) ERROR(`App ${app.id} storage file ${file.name} contains invalid character "${char[0]}"`) if (fileNames.includes(file.name)) ERROR(`App ${app.id} file ${file.name} is a duplicate`); fileNames.push(file.name); + allFiles.push({app: app.id, file: file.name}); if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`); if (!file.url && !file.content && !app.custom) ERROR(`App ${app.id} file ${file.name} has no contents`); var fileContents = ""; @@ -124,14 +141,13 @@ apps.forEach((app,appIdx) => { if (dataNames.includes(data.name||data.wildcard)) ERROR(`App ${app.id} data file ${data.name||data.wildcard} is a duplicate`); dataNames.push(data.name||data.wildcard) + allFiles.push({app: app.id, data: (data.name||data.wildcard)}); if ('name' in data && 'wildcard' in data) ERROR(`App ${app.id} data file ${data.name} has both name and wildcard`); - if (data.name) { - if (data.name.includes('?') || data.name.includes('*')) - ERROR(`App ${app.id} data file name ${data.name} contains wildcards`); - } + if (isGlob(data.name)) + ERROR(`App ${app.id} data file name ${data.name} contains wildcards`); if (data.wildcard) { - if (!data.wildcard.includes('?') && !data.wildcard.includes('*')) + if (!isGlob(data.wildcard)) ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not actually contains wildcard`); if (data.wildcard.replace(/\?|\*/g,'') === '') ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not contain regular characters`); @@ -140,6 +156,8 @@ apps.forEach((app,appIdx) => { else if (!data.wildcard.includes(app.id)) WARN(`App ${app.id} data file wildcard ${data.wildcard} does not include app ID`); } + let char = (data.name||data.wildcard).match(FORBIDDEN_FILE_NAME_CHARS) + if (char) ERROR(`App ${app.id} data file ${data.name||data.wildcard} contains invalid character "${char[0]}"`) if ('storageFile' in data && typeof data.storageFile !== 'boolean') ERROR(`App ${app.id} data file ${data.name||data.wildcard} has non-boolean value for "storageFile"`); for (const key in data) { @@ -147,8 +165,24 @@ apps.forEach((app,appIdx) => { ERROR(`App ${app.id} data file ${data.name||data.wildcard} has unknown property "${key}"`); } }); - if (fileNames.includes(app.id+".settings.js") && dataNames.length===1 && dataNames[0] === app.id+'.settings.json') - WARN(`App ${app.id} has settings, so does not need to declare data file ${app.id+'.settings.json'}`) + // prefer "appid.json" over "appid.settings.json" (TODO: change to ERROR once all apps comply?) + if (dataNames.includes(app.id+".settings.json") && !dataNames.includes(app.id+".json")) + WARN(`App ${app.id} uses data file ${app.id+'.settings.json'} instead of ${app.id+'.json'}`) + // settings files should be listed under data, not storage (TODO: change to ERROR once all apps comply?) + if (fileNames.includes(app.id+".settings.json")) + WARN(`App ${app.id} uses storage file ${app.id+'.settings.json'} instead of data file`) + if (fileNames.includes(app.id+".json")) + WARN(`App ${app.id} uses storage file ${app.id+'.json'} instead of data file`) + // warn if storage file matches data file of same app + dataNames.forEach(dataName=>{ + const glob = globToRegex(dataName) + fileNames.forEach(fileName=>{ + if (glob.test(fileName)) { + if (isGlob(dataName)) WARN(`App ${app.id} storage file ${fileName} matches data wildcard ${dataName}`) + else WARN(`App ${app.id} storage file ${fileName} is also listed in data`) + } + }) + }) //console.log(fileNames); if (isApp && !fileNames.includes(app.id+".app.js")) ERROR(`App ${app.id} has no entrypoint`); if (isApp && !fileNames.includes(app.id+".img")) ERROR(`App ${app.id} has no JS icon`); @@ -157,3 +191,20 @@ apps.forEach((app,appIdx) => { if (!APP_KEYS.includes(key)) ERROR(`App ${app.id} has unknown key ${key}`); } }); +// Do not allow files from different apps to collide +let fileA +while(fileA=allFiles.pop()) { + const nameA = (fileA.file||fileA.data), + globA = globToRegex(nameA), + typeA = fileA.file?'storage':'data' + allFiles.forEach(fileB => { + const nameB = (fileB.file||fileB.data), + globB = globToRegex(nameB), + typeB = fileB.file?'storage':'data' + if (globA.test(nameB)||globB.test(nameA)) { + if (isGlob(nameA)||isGlob(nameB)) + ERROR(`App ${fileB.app} ${typeB} file ${nameB} matches app ${fileA.app} ${typeB} file ${nameA}`) + else ERROR(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`) + } + }) +} diff --git a/js/appinfo.js b/js/appinfo.js index 413098bc4..56b6ff2f8 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -69,19 +69,16 @@ var AppInfo = { var fileList = fileContents.map(storageFile=>storageFile.name); fileList.unshift(appJSONName); // do we want this? makes life easier! json.files = fileList.join(","); - let data = {dataFiles: [], storageFiles: []}; if ('data' in app) { + let data = {dataFiles: [], storageFiles: []}; // add "data" files to appropriate list app.data.forEach(d=>{ if (d.storageFile) data.storageFiles.push(d.name||d.wildcard) else data.dataFiles.push(d.name||d.wildcard) }) - } else if (json.settings) { - // settings but no data files: assume app uses .settings.json file - data.dataFiles.push(app.id + '.settings.json') + const dataString = AppInfo.makeDataString(data) + if (dataString) json.data = dataString } - const dataString = AppInfo.makeDataString(data) - if (dataString) json.data = dataString fileContents.push({ name : appJSONName, content : JSON.stringify(json) diff --git a/js/comms.js b/js/comms.js index 736a2b7c7..b825a06ad 100644 --- a/js/comms.js +++ b/js/comms.js @@ -101,17 +101,16 @@ removeApp : app => { // expects an appid.info structure (i.e. with `files`) cmds += app.files.split(',').map(file => `\x10s.erase(${toJS(file)});\n`).join(""); // remove app Data: (dataFiles and storageFiles) const data = AppInfo.parseDataString(app.data) + const isGlob = f => /[?*]/.test(f) // regular files, can use wildcards cmds += data.dataFiles.map(file => { - const isGlob = (file.includes('*') || file.includes('?')) - if (!isGlob) return `\x10s.erase(${toJS(file)});\n`; + if (!isGlob(file)) return `\x10s.erase(${toJS(file)});\n`; const regex = new RegExp(globToRegex(file)) return `\x10s.list(${regex}).forEach(f=>s.erase(f));\n`; }).join(""); // storageFiles, can use wildcards cmds += data.storageFiles.map(file => { - const isGlob = (file.includes('*') || file.includes('?')) - if (!isGlob) return `\x10s.open(${toJS(file)},'r').erase();\n`; + if (!isGlob(file)) return `\x10s.open(${toJS(file)},'r').erase();\n`; // storageFiles have a chunk number appended to their real name const regex = globToRegex(file+'\u0001') // open() doesn't want the chunk number though diff --git a/js/index.js b/js/index.js index 41a43730e..483dc09c7 100644 --- a/js/index.js +++ b/js/index.js @@ -355,9 +355,6 @@ function updateApp(app) { const removeData = (f) => !app.data.some(d => (d.name || d.wildcard)===f) data.dataFiles = data.dataFiles.filter(removeData) data.storageFiles = data.storageFiles.filter(removeData) - } else if (remove.settings || app.settings) { - // app with settings but no data files declared: keep .settings.json - data.dataFiles = data.dataFiles.filter(f => f!==(app.id+'.settings.json')) } remove.data = AppInfo.makeDataString(data) return Comms.removeApp(remove); From 28d3a6eb1d8e5c19c489380eeae3f3310d9b11c6 Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 17 Apr 2020 12:29:40 +0200 Subject: [PATCH 0437/1189] Fix failing dismissal of Gadgetbridge messages --- apps/batchart/widget.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 1b8ce79ba..aa81c2c5b 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -71,8 +71,9 @@ enabledConsumers = enabledConsumers | switchableConsumers.gps; if (hrmEventReceived) enabledConsumers = enabledConsumers | switchableConsumers.hrm; - //if (Bangle.isBluetoothOn()) - // enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; + // First, coarse indication if the bluetooth device is enabled + if (NodeFilter.getSecuritystatus().connected) + enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; // Reset the event registration vars compassEventReceived = false; @@ -110,19 +111,14 @@ } function reload() { - WIDGETS.batchart.width = 24; + WIDGETS["batchart"].width = 24; recordingInterval = setInterval(logBatteryData, recordingInterval10Min); - - logBatteryData(); } // add the widget - WIDGETS.batchart = { - area: "tl", width: 24, draw: draw, reload: function () { - reload(); - Bangle.drawWidgets(); - } + WIDGETS["batchart"] = { + area: "tl", width: 24, draw: draw, reload: reload }; reload(); From 933ce770950524599a28fc5ce93009c697d3577a Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 17 Apr 2020 12:33:26 +0200 Subject: [PATCH 0438/1189] Enable graphing of the bluetooth state, update version info --- apps.json | 2 +- apps/batchart/ChangeLog | 3 ++- apps/batchart/app.js | 16 ++++++++-------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps.json b/apps.json index bbe0bbfcd..80c771c08 100644 --- a/apps.json +++ b/apps.json @@ -1194,7 +1194,7 @@ "name": "Battery Chart", "shortName":"Battery Chart", "icon": "app.png", - "version":"0.08", + "version":"0.09", "readme": "README.md", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index 439d877be..66b40fbbf 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -5,4 +5,5 @@ 0.05: Display temperature and LCD state in chart 0.06: Fixes widget events and charting of component states 0.07: Improve logging and charting of component states and add widget icon -0.08: Fix for Home button in the app and README added. \ No newline at end of file +0.08: Fix for Home button in the app and README added. +0.09: Fix failing dismissal of Gadgetbridge notifications, record (coarse) bluetooth state \ No newline at end of file diff --git a/apps/batchart/app.js b/apps/batchart/app.js index 2d0d8e585..472fb3a8a 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -8,7 +8,7 @@ const GraphXMax = GraphXZero + MaxValueCount; const GraphLcdY = GraphYZero + 10; const GraphCompassY = GraphYZero + 16; -// const GraphBluetoothY = GraphYZero + 22; +const GraphBluetoothY = GraphYZero + 22; const GraphGpsY = GraphYZero + 28; const GraphHrmY = GraphYZero + 34; @@ -175,13 +175,13 @@ function renderData(dataArray) { g.drawLine(GraphXZero + i, GraphCompassY, GraphXZero + i, GraphCompassY + 1); } - // // Bluetooth state - // if (switchables & switchableConsumers.lcd == switchableConsumers.lcd) { - // g.setColor(0, 0, 1); - // g.setFontAlign(1, -1, 0); - // g.drawString("BLE", GraphXZero - GraphMarkerOffset, GraphBluetoothY - 2, true); - // g.drawLine(GraphXZero + i, GraphBluetoothY, GraphXZero + i, GraphBluetoothY + 1); - // } + // Bluetooth state + if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.bluetooth) { + g.setColor(0, 0, 1); + g.setFontAlign(1, -1, 0); + g.drawString("BLE", GraphXZero - GraphMarkerOffset, GraphBluetoothY - 2, true); + g.drawLine(GraphXZero + i, GraphBluetoothY, GraphXZero + i, GraphBluetoothY + 1); + } // Gps state if (parseInt(dataInfo[switchabelsIndex]) & switchableConsumers.gps) { From 5782fa143957eee7714ca3212d1b2338b9d04b2b Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 17 Apr 2020 12:43:21 +0200 Subject: [PATCH 0439/1189] Use correct casing for getSecurityStatusMethod --- apps/batchart/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index aa81c2c5b..2b00a83e2 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -72,7 +72,7 @@ if (hrmEventReceived) enabledConsumers = enabledConsumers | switchableConsumers.hrm; // First, coarse indication if the bluetooth device is enabled - if (NodeFilter.getSecuritystatus().connected) + if (NRF.getSecurityStatus().connected)) enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; // Reset the event registration vars From 0c129bb10adc80db9d5cd791e0757356524360d0 Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 17 Apr 2020 12:45:13 +0200 Subject: [PATCH 0440/1189] Fix wrong ) --- apps/batchart/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 2b00a83e2..808c7781c 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -72,7 +72,7 @@ if (hrmEventReceived) enabledConsumers = enabledConsumers | switchableConsumers.hrm; // First, coarse indication if the bluetooth device is enabled - if (NRF.getSecurityStatus().connected)) + if (NRF.getSecurityStatus().connected) enabledConsumers = enabledConsumers | switchableConsumers.bluetooth; // Reset the event registration vars From 372f5123f4fe611284d0f6f5fc5a09d30a585ae8 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 15:55:41 +0200 Subject: [PATCH 0441/1189] chronowid 0.02 --- apps/chronowid/ChangeLog | 3 ++- apps/chronowid/README.md | 9 ++++++--- apps/chronowid/app.js | 11 +++++++++-- apps/chronowid/widget.js | 18 +++++++++--------- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/apps/chronowid/ChangeLog b/apps/chronowid/ChangeLog index a6f342f01..263145407 100644 --- a/apps/chronowid/ChangeLog +++ b/apps/chronowid/ChangeLog @@ -1 +1,2 @@ -0.01: New widget and app! +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 diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md index f31c24c7b..f422dd956 100644 --- a/apps/chronowid/README.md +++ b/apps/chronowid/README.md @@ -5,6 +5,8 @@ The advantage is, that you can still see your normal watchface and other widgets The widget is always active, but only shown when the timer is on. Hours, minutes, seconds and timer status can be set with an app. +Depending on when you start the timer, it may alert up to 0,999 seconds early. This is because it checks only for full seconds. When there is less than one seconds left, it buzzes. This cannot be avoided without checking more than every second, which I would like to avoid. + ## Screenshots TBD @@ -18,18 +20,19 @@ TBD There are no settings section in the settings app, timer can be set using an app. +* Reset values: Reset hours, minutes, seconds to 0; set timer on to false; write to settings file * Hours: Set the hours for the timer * Minutes: Set the minutes for the timer * Seconds: Set the seconds for the timer -* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app. The widget is always there, but only visible when timer is on. +* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app to load the widget which starts the timer. The widget is always there, but only visible when timer is on. ## Releases -* Offifical app loader: Not yet published. +* Offifical app loader: https://github.com/espruino/BangleApps/tree/master/apps/chronowid (https://banglejs.com/apps/) * Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/chronowid (https://purple-tentacle.github.io/BangleApps/index.html#) * Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid ## Requests -If you have any feature requests, please contact me on the Espruino forum: http://forum.espruino.com/profiles/155005/ \ No newline at end of file +If you have any feature requests, please write here: http://forum.espruino.com/conversations/345972/ \ No newline at end of file diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js index 48401a7bb..dd9531233 100644 --- a/apps/chronowid/app.js +++ b/apps/chronowid/app.js @@ -30,7 +30,6 @@ settingsChronowid = storage.readJSON('chronowid.json',1); if (!settingsChronowid) resetSettings(); E.on('kill', () => { - print("-KILL-"); updateSettings(); }); @@ -45,6 +44,14 @@ function showMenu() { timerMenu.started.value = settingsChronowid.started; } }, + 'Reset values': function() { + settingsChronowid.hours = 0; + settingsChronowid.minutes = 0; + settingsChronowid.seconds = 0; + settingsChronowid.started = false; + updateSettings(); + showMenu(); + }, 'Hours': { value: settingsChronowid.hours, min: 0, @@ -88,4 +95,4 @@ function showMenu() { return E.showMenu(timerMenu); } -showMenu(); +showMenu(); \ No newline at end of file diff --git a/apps/chronowid/widget.js b/apps/chronowid/widget.js index 708bc6345..557104d92 100644 --- a/apps/chronowid/widget.js +++ b/apps/chronowid/widget.js @@ -36,19 +36,18 @@ //counts down, calculates and displays function countDown() { - //printDebug(); now = new Date(); diff = settingsChronowid.goal - now; //calculate difference WIDGETS["chronowid"].draw(); //time is up - if (settingsChronowid.started && diff <= 0) { + 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(); } + //printDebug(); } // draw your widget @@ -72,12 +71,13 @@ g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00 } } - 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); - } + // 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 From dcb2a6c2d9b4f327796a3aaec53a43e33e4d715d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 15:56:55 +0200 Subject: [PATCH 0442/1189] chronowid 0.02 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 447d45154..e2b20cca4 100644 --- a/apps.json +++ b/apps.json @@ -1142,7 +1142,7 @@ "name": "Chrono Widget", "shortName":"Chrono Widget", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Chronometer (timer) which runs as widget.", "tags": "tools,widget", "readme": "README.md", From 9a664ecae4b9b64a7f9e773ff43adbd62c0ab3fa Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 16:38:33 +0200 Subject: [PATCH 0443/1189] Compass: 0.02 --- apps/compass/ChangeLog | 2 ++ apps/compass/compass.js | 77 +++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 apps/compass/ChangeLog diff --git a/apps/compass/ChangeLog b/apps/compass/ChangeLog new file mode 100644 index 000000000..efd778c72 --- /dev/null +++ b/apps/compass/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Show text if uncalibrated \ No newline at end of file diff --git a/apps/compass/compass.js b/apps/compass/compass.js index 10895e3cd..a014d79ff 100644 --- a/apps/compass/compass.js +++ b/apps/compass/compass.js @@ -1,34 +1,43 @@ -g.clear(); -g.setColor(0,0.5,1); -g.fillCircle(120,130,80,80); -g.setColor(0,0,0); -g.fillCircle(120,130,70,70); - -function arrow(r,c) { - r=r*Math.PI/180; - var p = Math.PI/2; - g.setColor(c); - g.fillPoly([ - 120+60*Math.sin(r), 130-60*Math.cos(r), - 120+10*Math.sin(r+p), 130-10*Math.cos(r+p), - 120+10*Math.sin(r+-p), 130-10*Math.cos(r-p), - ]); -} - -var oldHeading = 0; -Bangle.on('mag', function(m) { - if (!Bangle.isLCDOn()) return; - g.setFont("6x8",3); - g.setColor(0); - g.fillRect(70,0,170,24); - g.setColor(0xffff); - g.setFontAlign(0,0); - g.drawString(isNaN(m.heading)?"---":Math.round(m.heading),120,12); - g.setColor(0,0,0); - arrow(oldHeading,0); - arrow(oldHeading+180,0); - arrow(m.heading,0xF800); - arrow(m.heading+180,0x001F); - oldHeading = m.heading; -}); -Bangle.setCompassPower(1); +g.clear(); +g.setColor(0,0.5,1); +g.fillCircle(120,130,80,80); +g.setColor(0,0,0); +g.fillCircle(120,130,70,70); + +function arrow(r,c) { + r=r*Math.PI/180; + var p = Math.PI/2; + g.setColor(c); + g.fillPoly([ + 120+60*Math.sin(r), 130-60*Math.cos(r), + 120+10*Math.sin(r+p), 130-10*Math.cos(r+p), + 120+10*Math.sin(r+-p), 130-10*Math.cos(r-p), + ]); +} + +var oldHeading = 0; +Bangle.on('mag', function(m) { + if (!Bangle.isLCDOn()) return; + g.setFont("6x8",3); + g.setColor(0); + g.fillRect(0,0,230,40); + g.setColor(0xffff); + if (isNaN(m.heading)) { + g.setFontAlign(-1,-1); + g.setFont("6x8",2); + g.drawString("Uncalibrated",50,12); + g.drawString("turn 360° around",25,26); + } + else { + g.setFontAlign(0,0); + g.setFont("6x8",3); + g.drawString(Math.round(m.heading),120,12); + } + g.setColor(0,0,0); + arrow(oldHeading,0); + arrow(oldHeading+180,0); + arrow(m.heading,0xF800); + arrow(m.heading+180,0x001F); + oldHeading = m.heading; +}); +Bangle.setCompassPower(1); From 1017090cbe5fc6fb42101a0544fdd6e8ada983d0 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 16:40:25 +0200 Subject: [PATCH 0444/1189] compass 0.02 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e2b20cca4..d7bd6a7a1 100644 --- a/apps.json +++ b/apps.json @@ -235,7 +235,7 @@ { "id": "compass", "name": "Compass", "icon": "compass.png", - "version":"0.01", + "version":"0.02", "description": "Simple compass that points North", "tags": "tool,outdoors", "storage": [ From 1fff62e48da25d2455294643ac66321033088c76 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 17 Apr 2020 16:55:35 +0200 Subject: [PATCH 0445/1189] init hid camera app --- apps/hidcam/ChangeLog | 1 + apps/hidcam/add_to_apps.json | 13 +++++++++++++ apps/hidcam/app-icon.js | 1 + apps/hidcam/app.js | 12 ++++++++++++ apps/hidcam/app.png | Bin 0 -> 1620 bytes 5 files changed, 27 insertions(+) create mode 100644 apps/hidcam/ChangeLog create mode 100644 apps/hidcam/add_to_apps.json create mode 100644 apps/hidcam/app-icon.js create mode 100644 apps/hidcam/app.js create mode 100644 apps/hidcam/app.png diff --git a/apps/hidcam/ChangeLog b/apps/hidcam/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/hidcam/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/hidcam/add_to_apps.json b/apps/hidcam/add_to_apps.json new file mode 100644 index 000000000..ca75a7bd8 --- /dev/null +++ b/apps/hidcam/add_to_apps.json @@ -0,0 +1,13 @@ +// Create an entry in apps.json as follows: +{ "id": "7chname", + "name": "My app's human readable name", + "shortName":"Short Name", + "icon": "app.png", + "version":"0.01", + "description": "A detailed description of my great app", + "tags": "", + "storage": [ + {"name":"7chname.app.js","url":"app.js"}, + {"name":"7chname.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/hidcam/app-icon.js b/apps/hidcam/app-icon.js new file mode 100644 index 000000000..49232b838 --- /dev/null +++ b/apps/hidcam/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js new file mode 100644 index 000000000..af367779a --- /dev/null +++ b/apps/hidcam/app.js @@ -0,0 +1,12 @@ +// place your const, vars, functions or classes here + +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + if (on) { + // call your app function here + // If you clear the screen, do Bangle.drawWidgets(); + } +}); + +g.clear(); +// call your app function here diff --git a/apps/hidcam/app.png b/apps/hidcam/app.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 Date: Fri, 17 Apr 2020 18:56:38 +0200 Subject: [PATCH 0446/1189] app code and config --- apps/hidcam/ChangeLog | 2 +- apps/hidcam/add_to_apps.json | 13 ------------- apps/hidcam/app-icon.js | 2 +- apps/hidcam/app.js | 12 ------------ apps/hidcam/app.png | Bin 1620 -> 1425 bytes apps/hidcam/hidcam.app.js | 28 ++++++++++++++++++++++++++++ apps/hidcam/hidcam.app.json | 13 +++++++++++++ 7 files changed, 43 insertions(+), 27 deletions(-) delete mode 100644 apps/hidcam/add_to_apps.json delete mode 100644 apps/hidcam/app.js create mode 100644 apps/hidcam/hidcam.app.js create mode 100644 apps/hidcam/hidcam.app.json diff --git a/apps/hidcam/ChangeLog b/apps/hidcam/ChangeLog index 5560f00bc..665c0df6e 100644 --- a/apps/hidcam/ChangeLog +++ b/apps/hidcam/ChangeLog @@ -1 +1 @@ -0.01: New App! +0.01: Init diff --git a/apps/hidcam/add_to_apps.json b/apps/hidcam/add_to_apps.json deleted file mode 100644 index ca75a7bd8..000000000 --- a/apps/hidcam/add_to_apps.json +++ /dev/null @@ -1,13 +0,0 @@ -// Create an entry in apps.json as follows: -{ "id": "7chname", - "name": "My app's human readable name", - "shortName":"Short Name", - "icon": "app.png", - "version":"0.01", - "description": "A detailed description of my great app", - "tags": "", - "storage": [ - {"name":"7chname.app.js","url":"app.js"}, - {"name":"7chname.img","url":"app-icon.js","evaluate":true} - ] -} diff --git a/apps/hidcam/app-icon.js b/apps/hidcam/app-icon.js index 49232b838..aa9d5e194 100644 --- a/apps/hidcam/app-icon.js +++ b/apps/hidcam/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) +E.toArrayBuffer(atob("MDCEAzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMxERERERETMzMzMzMzMzMzMzMzMzMzMzMRERERERERMzMzMzMzMzMzMzMzMzMzMzMREREREREREzMzMzMzMzMzMzMzMAAAAzEREREREREREzMzMzMzMzMzMzMzMAAAAxERERERERERETMzMzMzMzMzMzMxERERERERERERERERERERERETMzMzMzMRERERERERERERERERERERERERMzMzMzEREREREREREAAAAAEREREREREREzMzMzEREREREREQAAAAAAABERESIiIREzMzMzEREREREREAAAAAAAAAERESIiIREzMzMzEREREREQAAAKqqqgAAABESIiIREzMzMzEREREREQAAqqqqqqoAABESIiIREzMzMzEREREREAAKqqqqqqqgAAEREREREzMzMzERERERAACqqqqqqqqqAAAREREREzMzMzERERERAAqqqiIiIqqqoAAREREREzMzMzqqqqqgAAqqoiIiIiKqoAAKqqqqozMzMzqqqqqgAKqqIiIiIiKqqgAKqqqqozMzMzqqqqqgAKqqIiqqqiKqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAAqqqqqqqqqqoAAKqqqqozMzMzqqqqqqAAqqqqqqqqqqoACqqqqqozMzMzqqqqqqAACqqqqqqqqqAACqqqqqozMzMzqqqqqqoAAKqqqqqqqgAAqqqqqqozMzMzqqqqqqoAAAqqqqqqoAAAqqqqqqozMzMzqqqqqqqgAAAKqqqgAAAKqqqqqqozMzMzqqqqqqqqAAAAAAAAAACqqqqqqqozMzMzqqqqqqqqqgAAAAAAAKqqqqqqqqozMzMzqqqqqqqqqqoAAAAAqqqqqqqqqqozMzMzOqqqqqqqqqqqqqqqqqqqqqqqqqMzMzMzM6qqqqqqqqqqqqqqqqqqqqqqqjMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw==")) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js deleted file mode 100644 index af367779a..000000000 --- a/apps/hidcam/app.js +++ /dev/null @@ -1,12 +0,0 @@ -// place your const, vars, functions or classes here - -// special function to handle display switch on -Bangle.on('lcdPower', (on) => { - if (on) { - // call your app function here - // If you clear the screen, do Bangle.drawWidgets(); - } -}); - -g.clear(); -// call your app function here diff --git a/apps/hidcam/app.png b/apps/hidcam/app.png index 582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0..3f631a0d8c2c9a2f82ad03564f6e503e97ec3b74 100644 GIT binary patch delta 1389 zcmV-z1(N#I43P_vHGc(0Nkl2XW^HHNnRPdH7YVh3 zAi4-C0tqZh0&gNIp^K!1F0{>?F8ZK?L=!~R#889`D}{vAtGp@*QYh5@80TYmE$3rD zXXnhv+r_N&?d+VhW?jr54xID6@AEwW|9PMDejI3`i6)w8Vt*MB_an&A!4sV_lRgYQ z(U60bA)%^oee%v5e=Ilm@&!mKhW3ATK_WL9^bF=wV%=wZcFZg%y|Nrf4_+Hu9Ce*+^R zc(KwX1zV6(7k9~?h!Hyfbl2<$#^#4n_>Pe{25aG9oee=sBAVos>< zeZK4Uo0W}K0(Kub;#YIxcL|;c!>=(2h$%VihL7Ie9x1h3sya$#pG2A>uj?sd(I~Ss z(fP@7oD9euxgs&*b+QBp??8vTYo};@fk(eQ-ni7;;|S=S+iZ& zQ%oh|M8YB59uK{}eKm#b*!n`1?bz81c@c`J;#MU9gEb$E-r?5R7`a@wF$XD$N25$9 z;`H^e#@*T3crrpoc}d^j=`$FZd*5QTQ}=G&k&it!R5#a z5~;sHN+RJ9nx^6DT=C!p=z5AY=&?+XoiY$ z0cl;&&o+yA*7s@|d7*&A4IY2~>ga(^KeTm$wPd}uTO2&!yS?xnk48!Bx?urTB{Y8O zp}Gz;soP|d`93RsYw&MaTMTA}HgEpTmqCEmlE3B>kete!eU3qVk*5icj{q=sO~q-e zpMSp+hDSipOcn0eKC-^7&AFmTK9h#|DVU2xY93ges2m+&u@!v=RuyBUGRAk-hCkwT zHd(mu>FzIU%Vt2;Ai4OKOP92ymMNh=r@|E=O@~DvjMJ4404)_dY^MYJZcj2U)uHs1y5MFf2e3*24Yl+_d3@l_-s& zD%LtZ@4?5YgGDLMg^}9mAF27tr*+VQKx5Z z7#3i+xVd`{3XYEuniw^l^e(~^VJCsEUR|D=s!a{d|_>g7N8ZA(iCfm4ELF z&rVwxsxW@gF|`+JYw@Fq{E9U_6X*QpQ!J#COL!HrkVtXhxX+mFkcUw@=#W~T_>4sc`SYWX)K1a5mj_QiwG0~G+^w0W_p zHez$bVew zFhhQ-(okyzE&*GOL{)@^c6%>Q%}X*JXCa*+BNxbK^Lrar)vzjd>=rk6t!Bg2Yy*Jc zVx_5CfXEIZ)s29G-vxQ7iiXqX#cA`JBUl$AmdnVYN^4aKef`VU8(5UbfNwBZPX7|7 v5qz7=%BN2Lwq^LgCeuU{O*GNO{|o;Bs>Z}7R{Rfy00000NkvXXu0mjfd2ysS delta 1586 zcmV-22F>}A3)BpdHGc*PNklVsi@IIDWLJF z<-tS+MbQVNMvWngMiMVMF($}~PbV60iJqKGq6sl-z#5IgNDvG@D81m_8L(pU0#u>& zLWh~o%w9f}(&^0JyL+a!If?wA_PXuwzxMtv>-#=9jnnvZLw~00MXDHdHZ-F~E6@xy zAk0IFoNQ?rJ?=L3M zHi1NI%W6w_1%Iftvl|hOhaVrR!sN{2xw@hkSSKyk8akT z^^R7(Pu73-SLjz9%wK^oEKM9^v2d+uZBzb_ElWR@^923y?MQ5Sh3y}H359v|8R9g6# zr~d$slVYvzX{^gvI{yK&9t6Sw)^Fo(=6P9=8U6ZW2$40`DO|&}2{l-??t>KM^xP{PQp9J>sMDt1wG0P7(^*|FxpxgxUNu=e>XY@94oX zm34@@sD<7z%UMsx_zdi4z8GAI!3iDJ{-uogg{9 zcYkp~PAMU^CCrIu%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FSn>E+sATQ)Q)70!M+WViTAl9FdlI^_bw) zg$_FC{~s`6^Y4_v-WecL8bso`qEiB0GeD&@Sajx!_6dmf;f#FXiqAg!jge#)(`PVmVSj|$`UsHZGo<5&Mq0i(4E(oP@&iXk=-U1(Bgrgt{}SSg8|!FVQpN1*ApW3%X$qBd z0$g%sHPPlXP=%gv2Ryu4{+&-ACfn41x}XBX7bma&a6)1z%_mzAlTKO8TYoT%Ma!#@ zNsf>EkEEDA*ST6fiC+AnsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6y zeLWqoYkSl4pzFQ(_Vp&ItO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmi zn45#=3l9BmL6Bp<*MZejrhnxPZJd$0O%`^i+?+grDp}Z_q9=X}=<|3S6D2}Xo}(vz z>ty7i#49G<-Lx9fe*rb6#JivumHVB}LG4gdXO*R~xABLfz>ADt4^0(GkQeZWqQ#Jh z>AK{zSO Date: Fri, 17 Apr 2020 19:00:45 +0200 Subject: [PATCH 0447/1189] adding the extra comma as mentioned on bangle js documentation --- apps/hidcam/hidcam.app.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/hidcam/hidcam.app.json b/apps/hidcam/hidcam.app.json index df35404e4..ad3ea89fe 100644 --- a/apps/hidcam/hidcam.app.json +++ b/apps/hidcam/hidcam.app.json @@ -1,4 +1,4 @@ -// Create an entry in apps.json as follows: +}, { "id": "hidcam", "name": "HID camera shutter", "shortName":"HID cam", @@ -11,3 +11,4 @@ {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ], } +] From 15535b0f19c232425c01311e1f1b5c33da50d78f Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 17 Apr 2020 19:06:09 +0200 Subject: [PATCH 0448/1189] move json info to the good place --- apps.json | 14 +++++++++++++- apps/hidcam/hidcam.app.json | 14 -------------- 2 files changed, 13 insertions(+), 15 deletions(-) delete mode 100644 apps/hidcam/hidcam.app.json diff --git a/apps.json b/apps.json index effa14aa4..d57f218be 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,17 @@ "evaluate": true } ] - } + }, +{ "id": "hidcam", + "name": "HID camera shutter", + "shortName":"HID cam", + "icon": "app.png", + "version":"0.01", + "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", + "tags": "tools", + "storage": [ + {"name":"hidcam.app.js","url":"hidcam.app.js"}, + {"name":"hidcam.img","url":"app-icon.js","evaluate":true} + ], +} ] diff --git a/apps/hidcam/hidcam.app.json b/apps/hidcam/hidcam.app.json deleted file mode 100644 index ad3ea89fe..000000000 --- a/apps/hidcam/hidcam.app.json +++ /dev/null @@ -1,14 +0,0 @@ -}, -{ "id": "hidcam", - "name": "HID camera shutter", - "shortName":"HID cam", - "icon": "app.png", - "version":"0.01", - "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", - "tags": "tools", - "storage": [ - {"name":"hidcam.app.js","url":"hidcam.app.js"}, - {"name":"hidcam.img","url":"app-icon.js","evaluate":true} - ], -} -] From 1dc2e3805d0cbbde633669b88c9f36465931ab69 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 17 Apr 2020 19:12:17 +0200 Subject: [PATCH 0449/1189] json format --- apps.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index d57f218be..d89fe95b0 100644 --- a/apps.json +++ b/apps.json @@ -1294,16 +1294,16 @@ } ] }, -{ "id": "hidcam", - "name": "HID camera shutter", - "shortName":"HID cam", - "icon": "app.png", - "version":"0.01", - "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", - "tags": "tools", - "storage": [ - {"name":"hidcam.app.js","url":"hidcam.app.js"}, - {"name":"hidcam.img","url":"app-icon.js","evaluate":true} - ], + { "id": "hidcam", + "name": "HID camera shutter", + "shortName":"HID cam", + "icon": "app.png", + "version":"0.01", + "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", + "tags": "tools", + "storage": [ + {"name":"hidcam.app.js","url":"hidcam.app.js"}, + {"name":"hidcam.img","url":"app-icon.js","evaluate":true} + ] } ] From c7f2a18caaff5a472db6f7f3765cd4234f936da1 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:08:07 +0200 Subject: [PATCH 0450/1189] Remove "settings" from appid.info --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 22 ++++++++++++++-------- js/appinfo.js | 2 -- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index 0c97b9e57..4b8b4a6b3 100644 --- a/apps.json +++ b/apps.json @@ -120,7 +120,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.16", + "version":"0.17", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 3acfb5fb0..81ac1fa81 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -18,3 +18,4 @@ 0.14: Reduce memory usage when running app settings page 0.15: Reduce memory usage when running default clock chooser (#294) 0.16: Reduce memory usage further when running app settings page +0.17: Remove need for "settings" in appid.info diff --git a/apps/setting/settings.js b/apps/setting/settings.js index d0d88ce20..97ce464ad 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -416,10 +416,19 @@ function showAppSettingsMenu() { '': { 'title': 'App Settings' }, '< Back': ()=>showMainMenu(), } - const apps = storage.list(/\.info$/) - .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?{sortorder:a.sortorder,name:a.name,settings:a.settings}:undefined}) - .filter(app => app) // filter out any undefined apps - .sort((a, b) => a.sortorder - b.sortorder) + const apps = storage.list(/\.settings\.js$/) + .map(s => s.substr(0, s.length-12)) + .map(id => { + const a=storage.readJSON(id+'.info',1); + return {id:id,name:a.name,sortorder:a.sortorder}; + }) + .sort((a, b) => { + const n = (0|a.sortorder)-(0|b.sortorder); + if (n) return n; // do sortorder first + if (a.nameb.name) return 1; + return 0; + }) if (apps.length === 0) { appmenu['No app has settings'] = () => { }; } @@ -433,10 +442,7 @@ function showAppSettings(app) { E.showMessage(`${app.name}:\n${msg}!\n\nBTN1 to go back`); setWatch(showAppSettingsMenu, BTN1, { repeat: false }); } - let appSettings = storage.read(app.settings); - if (!appSettings) { - return showError('Missing settings'); - } + let appSettings = storage.read(app.id+'.settings.js'); try { appSettings = eval(appSettings); } catch (e) { diff --git a/js/appinfo.js b/js/appinfo.js index 56b6ff2f8..9fff7c92a 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -60,8 +60,6 @@ var AppInfo = { if (app.type && app.type!="app") json.type = app.type; if (fileContents.find(f=>f.name==app.id+".app.js")) json.src = app.id+".app.js"; - if (fileContents.find(f=>f.name==app.id+".settings.js")) - json.settings = app.id+".settings.js"; if (fileContents.find(f=>f.name==app.id+".img")) json.icon = app.id+".img"; if (app.sortorder) json.sortorder = app.sortorder; From 43b0d8897e7a50556b93a58eff19d068d2f43544 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:25:56 +0200 Subject: [PATCH 0451/1189] widbatpc: Save settings in data file --- apps.json | 8 +++++--- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/settings.js | 2 +- apps/widbatpc/widget.js | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 0c97b9e57..315120cc7 100644 --- a/apps.json +++ b/apps.json @@ -342,14 +342,16 @@ "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.09", + "version":"0.10", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", "storage": [ {"name":"widbatpc.wid.js","url":"widget.js"}, - {"name":"widbatpc.settings.js","url":"settings.js"}, - {"name":"widbatpc.settings.json","content": "{}"} + {"name":"widbatpc.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"widbatpc.json"} ] }, { "id": "widbt", diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 129707320..138c1adc8 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -6,3 +6,4 @@ 0.07: Add settings: percentage/color/charger icon 0.08: Draw percentage as inverted on monochrome battery 0.09: Fix regression stopping correct widget updates +0.10: Don't overwrite existing settings on app update diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/settings.js index 5c0bdbcae..88988cf22 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/settings.js @@ -3,7 +3,7 @@ * @param {function} back Use back() to return to settings menu */ (function(back) { - const SETTINGS_FILE = 'widbatpc.settings.json' + const SETTINGS_FILE = 'widbatpc.json' const COLORS = ['By Level', 'Green', 'Monochrome'] // initialize with default settings... diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index aca690ce0..189ca215f 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -11,7 +11,7 @@ const COLORS = { 'ok': 0xFD20, // "Orange" 'low':0xF800, // "Red" } -const SETTINGS_FILE = 'widbatpc.settings.json' +const SETTINGS_FILE = 'widbatpc.json' let settings function loadSettings() { From b691f783aa7cb956c0644658907a93e27ce836c9 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:29:56 +0200 Subject: [PATCH 0452/1189] welcome: Save settings in data file fwelcom --- apps.json | 6 ++++-- apps/welcome/ChangeLog | 1 + apps/welcome/boot.js | 4 ++-- apps/welcome/settings-default.json | 3 --- apps/welcome/settings.js | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 apps/welcome/settings-default.json diff --git a/apps.json b/apps.json index 315120cc7..a8b29b685 100644 --- a/apps.json +++ b/apps.json @@ -78,7 +78,7 @@ { "id": "welcome", "name": "Welcome", "icon": "app.png", - "version":"0.07", + "version":"0.08", "description": "Appears at first boot and explains how to use Bangle.js", "tags": "start,welcome", "allow_emulator":true, @@ -86,8 +86,10 @@ {"name":"welcome.boot.js","url":"boot.js"}, {"name":"welcome.app.js","url":"app.js"}, {"name":"welcome.settings.js","url":"settings.js"}, - {"name":"welcome.settings.json","url":"settings-default.json","evaluate":true}, {"name":"welcome.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"welcome.json"} ] }, { "id": "gbridge", diff --git a/apps/welcome/ChangeLog b/apps/welcome/ChangeLog index b8786af6a..a377fc81e 100644 --- a/apps/welcome/ChangeLog +++ b/apps/welcome/ChangeLog @@ -7,3 +7,4 @@ 0.07: Run again when updated Don't run again when settings app is updated (or absent) Add "Run Now" option to settings +0.08: Don't overwrite existing settings on app update diff --git a/apps/welcome/boot.js b/apps/welcome/boot.js index bc5afcc66..f6ba6d2d6 100644 --- a/apps/welcome/boot.js +++ b/apps/welcome/boot.js @@ -1,11 +1,11 @@ (function() { - let s = require('Storage').readJSON('welcome.settings.json', 1) + let s = require('Storage').readJSON('welcome.json', 1) || require('Storage').readJSON('setting.json', 1) || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('welcome.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('welcome.settings.json', {welcomed: "yes"}) + require('Storage').write('welcome.json', {welcomed: "yes"}) load('welcome.app.js') }) } diff --git a/apps/welcome/settings-default.json b/apps/welcome/settings-default.json deleted file mode 100644 index d250efff5..000000000 --- a/apps/welcome/settings-default.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "welcomed": false -} diff --git a/apps/welcome/settings.js b/apps/welcome/settings.js index b11921646..e873c2785 100644 --- a/apps/welcome/settings.js +++ b/apps/welcome/settings.js @@ -1,13 +1,13 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('welcome.settings.json', 1) + let settings = require('Storage').readJSON('welcome.sjson', 1) || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'Welcome App' }, 'Run on Next Boot': { value: !settings.welcomed, format: v => v ? 'OK' : 'No', - onchange: v => require('Storage').write('welcome.settings.json', {welcomed: !v}), + onchange: v => require('Storage').write('welcome.json', {welcomed: !v}), }, 'Run Now': () => load('welcome.app.js'), '< Back': back, From b047f14d4ada97c510edc7a773a3e1f08982bc5d Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:35:59 +0200 Subject: [PATCH 0453/1189] setting: Save settings in data file --- apps.json | 6 ++++-- apps/setting/ChangeLog | 1 + apps/setting/settings-default.json | 25 ------------------------- 3 files changed, 5 insertions(+), 27 deletions(-) delete mode 100644 apps/setting/settings-default.json diff --git a/apps.json b/apps.json index a8b29b685..4d5493e49 100644 --- a/apps.json +++ b/apps.json @@ -122,15 +122,17 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.16", + "version":"0.17", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ {"name":"setting.app.js","url":"settings.js"}, {"name":"setting.boot.js","url":"boot.js"}, - {"name":"setting.json","url":"settings-default.json","evaluate":true}, {"name":"setting.img","url":"settings-icon.js","evaluate":true} ], + "data": [ + {"name":"setting.json"} + ], "sortorder" : -2 }, { "id": "alarm", diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 3acfb5fb0..773b510f0 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -18,3 +18,4 @@ 0.14: Reduce memory usage when running app settings page 0.15: Reduce memory usage when running default clock chooser (#294) 0.16: Reduce memory usage further when running app settings page +0.17: Don't overwrite existing settings on app update diff --git a/apps/setting/settings-default.json b/apps/setting/settings-default.json deleted file mode 100644 index c61fd6109..000000000 --- a/apps/setting/settings-default.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - ble: true, // Bluetooth enabled by default - blerepl: true, // Is REPL on Bluetooth - can Espruino IDE be used? - log: false, // Do log messages appear on screen? - timeout: 10, // Default LCD timeout in seconds - vibrate: true, // Vibration enabled by default. App must support - beep: "vib", // Beep enabled by default. App must support - timezone: 0, // Set the timezone for the device - HID : false, // BLE HID mode, off by default - clock: null, // a string for the default clock's name - "12hour" : false, // 12 or 24 hour clock? - // welcomed : undefined/true (whether welcome app should show) - brightness: 1, // LCD brightness from 0 to 1 - options: { - wakeOnBTN1: true, - wakeOnBTN2: true, - wakeOnBTN3: true, - wakeOnFaceUp: false, - wakeOnTouch: false, - wakeOnTwist: true, - twistThreshold: 819.2, - twistMaxY: -800, - twistTimeout: 1000 - } -} From 9358b4b5995e2efa6a49a1ca7865a0484f0c2c3f Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:39:27 +0200 Subject: [PATCH 0454/1189] alarm: Save settings in data file --- apps.json | 6 ++++-- apps/alarm/ChangeLog | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4d5493e49..30fb669d2 100644 --- a/apps.json +++ b/apps.json @@ -139,16 +139,18 @@ "name": "Default Alarm", "shortName":"Alarms", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "Set and respond to alarms", "tags": "tool,alarm,widget", "storage": [ {"name":"alarm.app.js","url":"app.js"}, {"name":"alarm.boot.js","url":"boot.js"}, {"name":"alarm.js","url":"alarm.js"}, - {"name":"alarm.json","content":"[]"}, {"name":"alarm.img","url":"app-icon.js","evaluate":true}, {"name":"alarm.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"alarm.json"} ] }, { "id": "wclock", diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 2ff60e658..ca92a0d97 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -4,3 +4,4 @@ 0.04: Tweaks for variable size widget system 0.05: Add alarm.boot.js and move code from the bootloader 0.06: Change 'New Alarm' to 'Save', allow Deletion of Alarms +0.07: Don't overwrite existing settings on app update From e4c0574ab77ad2b8064e3c50dd1e900f5a2fe7fb Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:45:48 +0200 Subject: [PATCH 0455/1189] heart: Save settings in data file, add recording files to data --- apps.json | 7 +++++-- apps/heart/ChangeLog | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 30fb669d2..6509458bf 100644 --- a/apps.json +++ b/apps.json @@ -300,15 +300,18 @@ { "id": "heart", "name": "Heart Rate Recorder", "icon": "app.png", - "version":"0.01", + "version":"0.02", "interface": "interface.html", "description": "Application that allows you to record your heart rate. Can run in background", "tags": "tool,health,widget", "storage": [ {"name":"heart.app.js","url":"app.js"}, - {"name":"heart.json","url":"app-settings.json","evaluate":true}, {"name":"heart.img","url":"app-icon.js","evaluate":true}, {"name":"heart.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"heart.json"}, + {"wildcard":".heart?","storageFile": true} ] }, { "id": "slevel", diff --git a/apps/heart/ChangeLog b/apps/heart/ChangeLog index 4c4db83bc..70134af27 100644 --- a/apps/heart/ChangeLog +++ b/apps/heart/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! - +0.02: Don't overwrite existing settings on app update + Clean up recordings on app removal From db35edede6527b4613ed147298be6497def457ee Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:49:57 +0200 Subject: [PATCH 0456/1189] ncstart: Save settings in data file --- apps.json | 6 ++++-- apps/ncstart/ChangeLog | 1 + apps/ncstart/boot.js | 4 ++-- apps/ncstart/settings-default.json | 3 --- apps/ncstart/settings.js | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 apps/ncstart/settings-default.json diff --git a/apps.json b/apps.json index 6509458bf..c3544abee 100644 --- a/apps.json +++ b/apps.json @@ -528,20 +528,22 @@ "id": "ncstart", "name": "NCEU Startup", "icon": "start.png", - "version":"0.04", + "version":"0.05", "description": "NodeConfEU 2019 'First Start' Sequence", "tags": "start,welcome", "storage": [ {"name":"ncstart.app.js","url":"start.js"}, {"name":"ncstart.boot.js","url":"boot.js"}, {"name":"ncstart.settings.js","url":"settings.js"}, - {"name":"ncstart.settings.json","url":"settings-default.json","evaluate":true}, {"name":"ncstart.img","url":"start-icon.js","evaluate":true}, {"name":"nc-bangle.img","url":"start-bangle.js","evaluate":true}, {"name":"nc-nceu.img","url":"start-nceu.js","evaluate":true}, {"name":"nc-nfr.img","url":"start-nfr.js","evaluate":true}, {"name":"nc-nodew.img","url":"start-nodew.js","evaluate":true}, {"name":"nc-tf.img","url":"start-tf.js","evaluate":true} + ], + "data": [ + {"name":"ncstart.json"} ] }, { "id": "ncfrun", diff --git a/apps/ncstart/ChangeLog b/apps/ncstart/ChangeLog index f4418827e..522633f7b 100644 --- a/apps/ncstart/ChangeLog +++ b/apps/ncstart/ChangeLog @@ -5,3 +5,4 @@ 0.04: Run again when updated Don't run again when settings app is updated (or absent) Add "Run Now" option to settings +0.05: Don't overwrite existing settings on app update diff --git a/apps/ncstart/boot.js b/apps/ncstart/boot.js index e3f514f5b..094033094 100644 --- a/apps/ncstart/boot.js +++ b/apps/ncstart/boot.js @@ -1,11 +1,11 @@ (function() { - let s = require('Storage').readJSON('ncstart.settings.json', 1) + let s = require('Storage').readJSON('ncstart.json', 1) || require('Storage').readJSON('setting.json', 1) || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('ncstart.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('ncstart.settings.json', s) + require('Storage').write('ncstart.json', s) load('ncstart.app.js') }) } diff --git a/apps/ncstart/settings-default.json b/apps/ncstart/settings-default.json deleted file mode 100644 index d250efff5..000000000 --- a/apps/ncstart/settings-default.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "welcomed": false -} diff --git a/apps/ncstart/settings.js b/apps/ncstart/settings.js index 2b24095cf..6780264a7 100644 --- a/apps/ncstart/settings.js +++ b/apps/ncstart/settings.js @@ -1,13 +1,13 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('ncstart.settings.json', 1) + let settings = require('Storage').readJSON('ncstart.json', 1) || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'NCEU Startup' }, 'Run on Next Boot': { value: !settings.welcomed, format: v => v ? 'OK' : 'No', - onchange: v => require('Storage').write('ncstart.settings.json', {welcomed: !v}), + onchange: v => require('Storage').write('ncstart.json', {welcomed: !v}), }, 'Run Now': () => load('ncstart.app.js'), '< Back': back, From 595de45e348799bb38d0728dd8a82aecc5c09287 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:52:42 +0200 Subject: [PATCH 0457/1189] numerals: Save settings in data file --- apps.json | 8 +++++--- apps/numerals/ChangeLog | 3 ++- apps/numerals/numerals-default.json | 5 ----- 3 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 apps/numerals/numerals-default.json diff --git a/apps.json b/apps.json index c3544abee..18fad4cfe 100644 --- a/apps.json +++ b/apps.json @@ -1235,7 +1235,7 @@ "name": "Numerals Clock", "shortName": "Numerals Clock", "icon": "numerals.png", - "version":"0.03", + "version":"0.04", "description": "A simple big numerals clock", "tags": "numerals,clock", "type":"clock", @@ -1243,8 +1243,10 @@ "storage": [ {"name":"numerals.app.js","url":"numerals.app.js"}, {"name":"numerals.img","url":"numerals-icon.js","evaluate":true}, - {"name":"numerals.settings.js","url":"numerals.settings.js"}, - {"name":"numerals.json","url":"numerals-default.json","evaluate":true} + {"name":"numerals.settings.js","url":"numerals.settings.js"} + ], + "data":[ + {"name":"numerals.json"} ] }, { "id": "bledetect", diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index ec465a83f..927c4ff5f 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Use BTN2 for settings menu like other clocks -0.03: maximize numerals, make menu button configurable, change icon to mac palette, add default settings file, respect 12hour setting \ No newline at end of file +0.03: maximize numerals, make menu button configurable, change icon to mac palette, add default settings file, respect 12hour setting +0.04: Don't overwrite existing settings on app update diff --git a/apps/numerals/numerals-default.json b/apps/numerals/numerals-default.json deleted file mode 100644 index aa6a25047..000000000 --- a/apps/numerals/numerals-default.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - color:0, - drawMode:"fill", - menuButton:22 -} \ No newline at end of file From a8d1ef3e53b35732bb8871956d1b2d1d13875d5e Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:42:29 +0200 Subject: [PATCH 0458/1189] gpsrec: Save settings in data file, add track files to data --- apps.json | 7 +++++-- apps/gpsrec/ChangeLog | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 18fad4cfe..a18029abc 100644 --- a/apps.json +++ b/apps.json @@ -286,15 +286,18 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.07", + "version":"0.08", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", "storage": [ {"name":"gpsrec.app.js","url":"app.js"}, - {"name":"gpsrec.json","url":"app-settings.json","evaluate":true}, {"name":"gpsrec.img","url":"app-icon.js","evaluate":true}, {"name":"gpsrec.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"gpsrec.json"}, + {"wildcard":".gpsrc?","storageFile": true} ] }, { "id": "heart", diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 8f1c575a1..17678bf3a 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -5,3 +5,5 @@ 0.05: Tweaks for variable size widget system 0.06: Ensure widget update itself (fix #118) and change to using icons 0.07: Added @jeffmer's awesome track viewer +0.08: Don't overwrite existing settings on app update + Clean up recorded tracks on app removal From e615b49cd027976ca9bceb869d18cab3e30d9d7f Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 22:17:36 +0200 Subject: [PATCH 0459/1189] wohrm: fix `apps.json` version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0c97b9e57..7499b352c 100644 --- a/apps.json +++ b/apps.json @@ -890,7 +890,7 @@ { "id": "wohrm", "name": "Workout HRM", "icon": "app.png", - "version":"0.06", + "version":"0.07", "readme": "README.md", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", From 2278947b3d4b7a2ff0cea136bfa16d7bbb0a9497 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 18 Apr 2020 00:51:22 +0200 Subject: [PATCH 0460/1189] App Manager: Add support for data files --- apps.json | 2 +- apps/files/ChangeLog | 1 + apps/files/files.js | 94 +++++++++++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/apps.json b/apps.json index 0c97b9e57..bac885598 100644 --- a/apps.json +++ b/apps.json @@ -319,7 +319,7 @@ { "id": "files", "name": "App Manager", "icon": "files.png", - "version":"0.02", + "version":"0.03", "description": "Show currently installed apps, free space, and allow their deletion from the watch", "tags": "tool,system,files", "storage": [ diff --git a/apps/files/ChangeLog b/apps/files/ChangeLog index 8b7be7640..1140000fe 100644 --- a/apps/files/ChangeLog +++ b/apps/files/ChangeLog @@ -1 +1,2 @@ 0.02: Fix deletion of apps - now use files list in app.info (fix #262) +0.03: Add support for data files diff --git a/apps/files/files.js b/apps/files/files.js index 4775d35d0..ef0481f0c 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -30,29 +30,80 @@ function showMainMenu() { return E.showMenu(mainmenu); } -function eraseApp(app) { - E.showMessage('Erasing\n' + app.name + '...'); +function isGlob(f) {return /[?*]/.test(f)} +function globToRegex(pattern) { + const ESCAPE = '.*+-?^${}()|[]\\'; + const regex = pattern.replace(/./g, c => { + switch (c) { + case '?': return '.'; + case '*': return '.*'; + default: return ESCAPE.includes(c) ? ('\\' + c) : c; + } + }); + return new RegExp('^'+regex+'$'); +} + +function eraseFiles(app) { app.files.split(",").forEach(f=>storage.erase(f)); } +function eraseData(app) { + if(!app.data) return; + const d=app.data.split(';'), + files=d[0].split(','), + sFiles=(d[1]||'').split(','); + let erase = f=>storage.erase(f); + files.forEach(f=>{ + if (!isGlob(f)) erase(f); + else storage.list(globToRegex(f)).forEach(erase); + }) + erase = sf=>storage.open(sf,'r').erase(); + sFiles.forEach(sf=>{ + if (!isGlob(sf)) erase(sf); + else storage.list(globToRegex(sf+'\u0001')) + .forEach(fs=>erase(fs.substring(0,fs.length-1))); + }) +} +function eraseApp(app, files,data) { + E.showMessage('Erasing\n' + app.name + '...'); + if (files) eraseFiles(app) + if (data) eraseData(app) +} +function eraseOne(app, files,data){ + E.showPrompt('Erase\n'+app.name+'?').then((v) => { + if (v) { + Bangle.buzz(100, 1); + eraseApp(app, files,data) + showApps(); + } else { + showAppMenu(app) + } + }) +} +function eraseAll(apps, files,data) { + E.showPrompt('Erase all?').then((v) => { + if (v) { + Bangle.buzz(100, 1); + for(var n = 0; n m = showApps(), - 'Erase': () => { - E.showPrompt('Erase\n' + app.name + '?').then((v) => { - if (v) { - Bangle.buzz(100, 1); - eraseApp(app); - m = showApps(); - } else { - m = showAppMenu(app) - } - }); - } - }; + } + if (app.data) { + appmenu['Erase Completely'] = () => eraseOne(app, true, true) + appmenu['Erase App,Keep Data'] = () => eraseOne(app,true, false) + appmenu['Only Erase Data'] = () => eraseOne(app,false, true) + } else { + appmenu['Erase'] = () => eraseOne(app,true, false) + } return E.showMenu(appmenu); } @@ -78,13 +129,12 @@ function showApps() { return menu; }, appsmenu); appsmenu['Erase All'] = () => { - E.showPrompt('Erase all?').then((v) => { - if (v) { - Bangle.buzz(100, 1); - for (var n = 0; n < list.length; n++) - eraseApp(list[n]); - } - m = showApps(); + E.showMenu({ + '': {'title': 'Erase All'}, + 'Erase Everything': () => eraseAll(list, true, true), + 'Erase Apps,Keep Data': () => eraseAll(list, true, false), + 'Only Erase Data': () => eraseAll(list, false, true), + '< Back': () => showApps(), }); }; } else { From c0f9c8b3e28b56680037a74f1666f0bac59c3cd9 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 18 Apr 2020 00:38:12 +0100 Subject: [PATCH 0461/1189] Store GPS coords, for use on next start if user desires --- apps.json | 2 +- apps/astrocalc/ChangeLog | 2 ++ apps/astrocalc/astrocalc-app.js | 51 +++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index bbe0bbfcd..60b47dbd8 100644 --- a/apps.json +++ b/apps.json @@ -1018,7 +1018,7 @@ { "id": "astrocalc", "name": "Astrocalc", "icon": "astrocalc.png", - "version":"0.01", + "version":"0.02", "description": "Calculates interesting information on the sun and moon cycles for the current day based on your location.", "tags": "app,sun,moon,cycles,tool,outdoors", "allow_emulator":true, diff --git a/apps/astrocalc/ChangeLog b/apps/astrocalc/ChangeLog index 0c8adeb61..188fc287b 100644 --- a/apps/astrocalc/ChangeLog +++ b/apps/astrocalc/ChangeLog @@ -1 +1,3 @@ 0.01: Create astrocalc app +0.02: Store last GPS lock, can be used instead of waiting for new GPS on +start. diff --git a/apps/astrocalc/astrocalc-app.js b/apps/astrocalc/astrocalc-app.js index 318147b13..0b0c63658 100644 --- a/apps/astrocalc/astrocalc-app.js +++ b/apps/astrocalc/astrocalc-app.js @@ -1,8 +1,18 @@ /** + * BangleJS ASTROCALC + * * Inspired by: https://www.timeanddate.com + * + * Original Author: Paul Cockrell https://github.com/paulcockrell + * Created: April 2020 + * + * Calculate the Sun and Moon positions based on watch GPS and display graphically */ const SunCalc = require("suncalc.js"); +const storage = require("Storage"); +const LAST_GPS_FILE = "astrocalc.gps.json"; +let lastGPS = (storage.readJSON(LAST_GPS_FILE, 1) || null); function drawMoon(phase, x, y) { const moonImgFiles = [ @@ -296,22 +306,50 @@ function indexPageMenu(gps) { return E.showMenu(menu); } +function getCenterStringX(str) { + return (g.getWidth() - g.stringWidth(str)) / 2; +} + /** * GPS wait page, shows GPS locating animation until it gets a lock, then moves to the Sun page */ function drawGPSWaitPage() { - const img = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AW43GF1wwsFwYwqFwowoFw4wmFxIwdE5YAPF/4vM5nN6YAE5vMF8YtHGIgvhFpQxKF7AuOGA4vXFyAwGF63MFyIABF6xeWMC4UDLwvNGpAJG5gwSdhIIDRBLyWCIgcJHAgJJDoouQF4vMQoICBBJoeGFx6GGACIfHL6YvaX6gvZeCIdFc4gAFXogvGFxgwFDwovQCAguOGAnMMBxeG5guTGAggGGAwNKFySREcA3N5vM5gDBdpQvXEY4AKXqovGGCKbFF7AwPZQwvZGJgtGF7vGdQItG5gSIF7gASF/44WEzgwRF0wwHF1AwFF1QwDF1gvwAH4A/AFAA==")) - + const img = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AW43GF1wwsFwYwqFwowoFw4wmFxIwdE5YAPF/4vM5nN6YAE5vMF8YtHGIgvhFpQxKF7AuOGA4vXFyAwGF63MFyIABF6xeWMC4UDLwvNGpAJG5gwSdhIIDRBLyWCIgcJHAgJJDoouQF4vMQoICBBJoeGFx6GGACIfHL6YvaX6gvZeCIdFc4gAFXogvGFxgwFDwovQCAguOGAnMMBxeG5guTGAggGGAwNKFySREcA3N5vM5gDBdpQvXEY4AKXqovGGCKbFF7AwPZQwvZGJgtGF7vGdQItG5gSIF7gASF/44WEzgwRF0wwHF1AwFF1QwDF1gvwAH4A/AFAA==")); + const str1 = "Astrocalc v0.02"; + const str2 = "Locating GPS"; + const str3 = "Please wait..."; + g.clear(); g.drawImage(img, 100, 50); g.setFont("6x8", 1); - g.drawString("Astrocalc v0.01", 80, 105); - g.drawString("Locating GPS", 85, 140); - g.drawString("Please wait...", 80, 155); + g.drawString(str1, getCenterStringX(str1), 105); + g.drawString(str2, getCenterStringX(str2), 140); + g.drawString(str3, getCenterStringX(str3), 155); + + if (lastGPS) { + lastGPS = JSON.parse(lastGPS); + lastGPS.time = new Date(); + + const str4 = "Press Button 3 to use last GPS"; + g.setColor("#d32e29"); + g.fillRect(0, 190, g.getWidth(), 215); + g.setColor("#ffffff"); + g.drawString(str4, getCenterStringX(str4), 200); + + setWatch(() => { + clearWatch(); + Bangle.setGPSPower(0); + lastGPS.time = new Date(); + m = indexPageMenu(lastGPS); + }, BTN3, {repeat: false}); + } + g.flip(); const DEBUG = false; if (DEBUG) { + clearWatch(); + const gps = { "lat": 56.45783133333, "lon": -3.02188583333, @@ -330,7 +368,10 @@ function drawGPSWaitPage() { Bangle.on('GPS', (gps) => { if (gps.fix === 0) return; + clearWatch(); + if (isNaN(gps.course)) gps.course = 0; + require("Storage").writeJSON(LAST_GPS_FILE, JSON.stringify(gps)); Bangle.setGPSPower(0); Bangle.buzz(); Bangle.setLCDPower(true); From 173969839e0a80e96b2d55065dc82382ce536cc7 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 18 Apr 2020 00:39:32 +0100 Subject: [PATCH 0462/1189] Fix Changelog --- apps/astrocalc/ChangeLog | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/astrocalc/ChangeLog b/apps/astrocalc/ChangeLog index 188fc287b..60ef5da0a 100644 --- a/apps/astrocalc/ChangeLog +++ b/apps/astrocalc/ChangeLog @@ -1,3 +1,2 @@ 0.01: Create astrocalc app -0.02: Store last GPS lock, can be used instead of waiting for new GPS on -start. +0.02: Store last GPS lock, can be used instead of waiting for new GPS on start From e052a6e65fdaad4c14c99798ea7dd316cadf7345 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 18 Apr 2020 00:41:15 +0100 Subject: [PATCH 0463/1189] Remove repeated assignment of date to gps object --- apps/astrocalc/astrocalc-app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/astrocalc/astrocalc-app.js b/apps/astrocalc/astrocalc-app.js index 0b0c63658..6b848abda 100644 --- a/apps/astrocalc/astrocalc-app.js +++ b/apps/astrocalc/astrocalc-app.js @@ -339,7 +339,6 @@ function drawGPSWaitPage() { setWatch(() => { clearWatch(); Bangle.setGPSPower(0); - lastGPS.time = new Date(); m = indexPageMenu(lastGPS); }, BTN3, {repeat: false}); } From bf4a3e0321abc7007a1fc1acede9616ff4a9cd49 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 09:01:15 +0200 Subject: [PATCH 0464/1189] Added rclock app --- apps.json | 12 +++ apps/rclock/ChangeLog | 1 + apps/rclock/app-icon.js | 1 + apps/rclock/app.png | Bin 0 -> 1620 bytes apps/rclock/rclock.app.js | 163 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 apps/rclock/ChangeLog create mode 100644 apps/rclock/app-icon.js create mode 100644 apps/rclock/app.png create mode 100644 apps/rclock/rclock.app.js diff --git a/apps.json b/apps.json index bbe0bbfcd..ac7181bb4 100644 --- a/apps.json +++ b/apps.json @@ -1291,6 +1291,18 @@ "name": "dane.img", "url": "app-icon.js", "evaluate": true + }, + { "id": "rclock", + "name": "Round clock with seconds, minutes and date", + "shortName":"Round Clock", + "icon": "app.png", + "version":"0.01", + "description": "Designed round clock with ticks for minutes and seconds", + "tags": "", + "storage": [ + {"name":"rclock.app.js","url":"app.js"}, + {"name":"rclock.img","url":"app-icon.js","evaluate":true} + ] } ] } diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/rclock/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/rclock/app-icon.js b/apps/rclock/app-icon.js new file mode 100644 index 000000000..49232b838 --- /dev/null +++ b/apps/rclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/rclock/app.png b/apps/rclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 Date: Sat, 18 Apr 2020 11:17:50 +0200 Subject: [PATCH 0465/1189] Fix error in app.json --- apps.json | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apps.json b/apps.json index ac7181bb4..89fd1a0a3 100644 --- a/apps.json +++ b/apps.json @@ -1291,19 +1291,18 @@ "name": "dane.img", "url": "app-icon.js", "evaluate": true - }, - { "id": "rclock", - "name": "Round clock with seconds, minutes and date", - "shortName":"Round Clock", - "icon": "app.png", - "version":"0.01", - "description": "Designed round clock with ticks for minutes and seconds", - "tags": "", - "storage": [ - {"name":"rclock.app.js","url":"app.js"}, - {"name":"rclock.img","url":"app-icon.js","evaluate":true} - ] } ] - } + }, + { "id": "rclock", + "name": "Round clock with seconds, minutes and date", + "shortName":"Round Clock", + "icon": "app.png", + "version":"0.01", + "description": "Designed round clock with ticks for minutes and seconds", + "tags": "", + "storage": [ + {"name":"rclock.app.js","url":"app.js"}, + {"name":"rclock.img","url":"app-icon.js","evaluate":true} + ] ] From 8f562d817782203bdf250c7d60803b9ac3102b40 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:21:14 +0200 Subject: [PATCH 0466/1189] Fix error in app.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 89fd1a0a3..d7e857066 100644 --- a/apps.json +++ b/apps.json @@ -1305,4 +1305,5 @@ {"name":"rclock.app.js","url":"app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} ] + } ] From 06705a6e5d0a3de5db7131c6a56684a917b6a710 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:28:08 +0200 Subject: [PATCH 0467/1189] Fixes --- apps.json | 6 ++++-- apps/rclock/ChangeLog | 2 +- apps/rclock/rclock.app.js | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index d7e857066..dc768218b 100644 --- a/apps.json +++ b/apps.json @@ -1294,13 +1294,15 @@ } ] }, - { "id": "rclock", + { + "id": "rclock", "name": "Round clock with seconds, minutes and date", "shortName":"Round Clock", "icon": "app.png", "version":"0.01", "description": "Designed round clock with ticks for minutes and seconds", - "tags": "", + "tags": "clock", + "type": "clock", "storage": [ {"name":"rclock.app.js","url":"app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog index 5560f00bc..a8f708a0a 100644 --- a/apps/rclock/ChangeLog +++ b/apps/rclock/ChangeLog @@ -1 +1 @@ -0.01: New App! +0.01: First published version of app diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 27fbda772..c681e0588 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -104,6 +104,7 @@ } first = false; } + // Reset seconds if (seconds == 59) { g.setColor('#000000'); From 7216b188672dfe4f5141c3a0470c38128f089cae Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:48:22 +0200 Subject: [PATCH 0468/1189] Fix error in reference to files --- apps.json | 2 +- package.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index dc768218b..bf771882a 100644 --- a/apps.json +++ b/apps.json @@ -1304,7 +1304,7 @@ "tags": "clock", "type": "clock", "storage": [ - {"name":"rclock.app.js","url":"app.js"}, + {"name":"rclock.app.js","url":"rclock.app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} ] } diff --git a/package.json b/package.json index 400385139..24793d86a 100644 --- a/package.json +++ b/package.json @@ -9,5 +9,8 @@ "scripts": { "test": "node bin/sanitycheck.js", "start": "npx http-server" + }, + "dependencies": { + "acorn": "^7.1.1" } } From a1f1da0341f4a8985e4f5baafcbdf1b1a1469f6a Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:52:30 +0200 Subject: [PATCH 0469/1189] Updated grey colors --- apps/rclock/rclock.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index c681e0588..405da7052 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -31,8 +31,8 @@ center: screen.center, }, circle: { - colormin: '#777777', - colorsec: '#444444', + colormin: '#999999', + colorsec: '#777777', width: 10, middle: screen.middle, center: screen.center, From afeff2c5761ed15d7164b1b3e338b7113ddee2b3 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:55:40 +0200 Subject: [PATCH 0470/1189] Updated grey colors --- apps/rclock/rclock.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 405da7052..25ca757cd 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -31,8 +31,8 @@ center: screen.center, }, circle: { - colormin: '#999999', - colorsec: '#777777', + colormin: '#bbbbbb', + colorsec: '#999999', width: 10, middle: screen.middle, center: screen.center, From 0a7a9e0b97652f96738c1a39e4bb6132c2aa9424 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 12:02:01 +0200 Subject: [PATCH 0471/1189] Align fonts --- apps/rclock/rclock.app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 25ca757cd..bd8395116 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -20,7 +20,7 @@ font: 'Vector', size: 60, middle: screen.middle - 30, - center: screen.center + 5 , + center: screen.center, }, date: { color: '#f0af00', @@ -31,8 +31,8 @@ center: screen.center, }, circle: { - colormin: '#bbbbbb', - colorsec: '#999999', + colormin: '#eeeeee', + colorsec: '#bbbbbb', width: 10, middle: screen.middle, center: screen.center, @@ -149,6 +149,7 @@ // clean app screen g.clear(); + g.setFontAlign( 0, 0, 0); Bangle.loadWidgets(); Bangle.drawWidgets(); From 6d1e87a765de9a48dee5939d66aeff0a97f3760b Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 12:39:13 +0200 Subject: [PATCH 0472/1189] Added icons --- .DS_Store | Bin 0 -> 6148 bytes apps/.DS_Store | Bin 0 -> 6148 bytes apps/rclock/.DS_Store | Bin 0 -> 6148 bytes apps/rclock/app-icon.js | 2 +- apps/rclock/app.png | Bin 1620 -> 0 bytes apps/rclock/appp.png | Bin 0 -> 10357 bytes 6 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 apps/.DS_Store create mode 100644 apps/rclock/.DS_Store delete mode 100644 apps/rclock/app.png create mode 100644 apps/rclock/appp.png diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e9892b6bcf444f36764922b8e4fcf88ecca916a8 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4I%_5-~#-K2??Z%JxAx+@j_rm6?#VYi=A4u-_X<| zqMPSsEi#Bm4>y&Sg~k+lCr5eUH(oE}`EJ);>!>lNF#jv{Xd}rZGKew5pFG zR`+&jitBP{sao4bWBAbcXSFE?rnOx(A%SUjVITn#Xb8+}KG^xcgMXX3Z5S>vG!N$@uSMUZw^aNf&RBRL$6#K0_mq+u>r%+ZqEtEGfdC6p6LSC`6 zBO*G#>}Dbp5gEY^}dS)lX)N&paQ?HfPEhd+^{CLf&S^h;4J`ffUq0p-b(H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T01gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 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 TkibuO00000NkvXXu0mjfp7a2c literal 0 HcmV?d00001 From cdba3a32c22bc330ba64fd3ba7088349b49ad78f Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 12:42:03 +0200 Subject: [PATCH 0473/1189] FIx name error --- apps/rclock/{appp.png => app.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/rclock/{appp.png => app.png} (100%) diff --git a/apps/rclock/appp.png b/apps/rclock/app.png similarity index 100% rename from apps/rclock/appp.png rename to apps/rclock/app.png From 2f834a585632acdd4f0ea5fc78effcb86a4e0fb2 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 13:00:59 +0200 Subject: [PATCH 0474/1189] Changes to permissions on file --- apps/rclock/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/rclock/.DS_Store diff --git a/apps/rclock/.DS_Store b/apps/rclock/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Sat, 18 Apr 2020 13:06:12 +0200 Subject: [PATCH 0475/1189] 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 3ed6448596080caa7ade69163e9482c8c45ad910 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 13:08:23 +0200 Subject: [PATCH 0476/1189] Delete .DS_Store --- apps/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/.DS_Store diff --git a/apps/.DS_Store b/apps/.DS_Store deleted file mode 100644 index f1e36c314ed1b52c7092fec1d7f2c0441196819d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKI|>3Z5S>vG!N$@uSMUZw^aNf&RBRL$6#K0_mq+u>r%+ZqEtEGfdC6p6LSC`6 zBO*G#>}Dbp5gEY^}dS)lX)N&paQ?HfPEhd+^{CLf&S^h;4J`ffUq0p-b( Date: Sat, 18 Apr 2020 13:09:31 +0200 Subject: [PATCH 0477/1189] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index e9892b6bcf444f36764922b8e4fcf88ecca916a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4I%_5-~#-K2??Z%JxAx+@j_rm6?#VYi=A4u-_X<| zqMPSsEi#Bm4>y&Sg~k+lCr5eUH(oE}`EJ);>!>lNF#jv{Xd}rZGKew5pFG zR`+&jitBP{sao4bWBAbcXSFE?rnOx(A%SUjVITn#Xb8+}KG^xcgMXX Date: Sat, 18 Apr 2020 15:34:35 +0200 Subject: [PATCH 0478/1189] shorter JS file name --- apps.json | 6 +++--- apps/hidcam/{hidcam.app.js => app.js} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename apps/hidcam/{hidcam.app.js => app.js} (100%) diff --git a/apps.json b/apps.json index 1e6b5e945..0546d6f65 100644 --- a/apps.json +++ b/apps.json @@ -1295,14 +1295,14 @@ ] }, { "id": "hidcam", - "name": "HID camera shutter", - "shortName":"HID cam", + "name": "Camera shutter", + "shortName":"Cam shutter", "icon": "app.png", "version":"0.01", "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", "tags": "tools", "storage": [ - {"name":"hidcam.app.js","url":"hidcam.app.js"}, + {"name":"hidcam.app.js","url":"app.js"}, {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ] } diff --git a/apps/hidcam/hidcam.app.js b/apps/hidcam/app.js similarity index 100% rename from apps/hidcam/hidcam.app.js rename to apps/hidcam/app.js From 37e26d6139782852411b61328006860a38034c47 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sat, 18 Apr 2020 14:38:32 +0100 Subject: [PATCH 0479/1189] Create ChangeLog --- apps/gpsnav/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/gpsnav/ChangeLog diff --git a/apps/gpsnav/ChangeLog b/apps/gpsnav/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/gpsnav/ChangeLog @@ -0,0 +1 @@ +0.01: New App! From ed51586dd0afdf9dd2df5c315e031c41ed62b162 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sat, 18 Apr 2020 14:39:36 +0100 Subject: [PATCH 0480/1189] Add files via upload --- apps/gpsnav/README.md | 66 ++++++++++ apps/gpsnav/app-icon.js | 1 + apps/gpsnav/app.js | 224 ++++++++++++++++++++++++++++++++ apps/gpsnav/first_screen.jpg | Bin 0 -> 65452 bytes apps/gpsnav/gpsnav.jpg | Bin 0 -> 47970 bytes apps/gpsnav/icon.png | Bin 0 -> 1887 bytes apps/gpsnav/marked_screen.jpg | Bin 0 -> 65895 bytes apps/gpsnav/select_screen.jpg | Bin 0 -> 64877 bytes apps/gpsnav/waypoint_screen.jpg | Bin 0 -> 67409 bytes apps/gpsnav/waypoints.json | 23 ++++ 10 files changed, 314 insertions(+) create mode 100644 apps/gpsnav/README.md create mode 100644 apps/gpsnav/app-icon.js create mode 100644 apps/gpsnav/app.js create mode 100644 apps/gpsnav/first_screen.jpg create mode 100644 apps/gpsnav/gpsnav.jpg create mode 100644 apps/gpsnav/icon.png create mode 100644 apps/gpsnav/marked_screen.jpg create mode 100644 apps/gpsnav/select_screen.jpg create mode 100644 apps/gpsnav/waypoint_screen.jpg create mode 100644 apps/gpsnav/waypoints.json diff --git a/apps/gpsnav/README.md b/apps/gpsnav/README.md new file mode 100644 index 000000000..80c6c1d00 --- /dev/null +++ b/apps/gpsnav/README.md @@ -0,0 +1,66 @@ +## gpsnav - navigate to waypoints + +The app is aimed at small boat navigation although it can also be used to mark the location of your car, bicycle etc and then get directions back to it. Please note that it would be foolish in the extreme to rely on this as your only boat navigation aid! + +The app displays direction of travel (course), speed, direction to waypoint (bearing) and distance to waypoint. The screen shot below is before the app has got a GPS fix. + +![](first_screen.jpg) + +The large digits are the course and speed. The top of the display is a linear compass which displays the direction of travel when a fix is received and you are moving. The blue text is the name of the current waypoint. NONE means that there is no waypoint set and so bearing and distance will remain at 0. To select a waypoint, press BTN2 (middle) and wait for the blue text to turn white. Then use BTN1 and BTN3 to select a waypoint. The waypoint choice is fixed by pressing BTN2 again. In the screen shot below a waypoint giving the location of Stone Henge has been selected. + +![](waypoint_screen.jpg) + +The display shows that Stone Henge is 108.75Km from the location where I made the screenshot and the direction is 255 degrees - approximately west. The display shows that I am currently moving approximately north - albeit slowly!. The position of the blue circle indicates that I need to turn left to get on course to Stone Henge. When the circle and red triangle line up you are on course and course will equal bearing. + +### Marking Waypoints + +The app lets you mark your current location as follows. There are vacant slots in the waypoint file which can be allocated a location. In the distributed waypoint file these are labelled WP0 to WP4. Select one of these - WP2 is shown below. + +![](select_screen.jpg) + +Bearing and distance are both zero as WP1 has currently no GPS location associated with it. To mark the location, press BTN2. + +![](marked_screen.jpg) + +The app indicates that WP2 is now marked by adding the prefix @ to it's name. The distance should be small as shown in the screen shot as you have just marked your current location. + +### Waypoint JSON file + +When the app is loaded from the app loader, a file named waypoints.json is loaded along with the javascript etc. The file has the following contents: + +~~~ +[ + { + "mark":0, + "name":"NONE" + }, + { + "mark":1, + "name":"No10", + "lat":51.5032, + "lon":-0.1269 + }, + { + "mark":1, + "name":"Stone", + "lat":51.1788, + "lon":-1.8260 + }, + { "name":"WP0" }, + { "name":"WP1" }, + { "name":"WP2" }, + { "name":"WP3" }, + { "name":"WP4" } +] +~~~ + +The file contains the initial NONE waypoint which is useful if you just want to display course and speed. The next two entries are waypoints to No 10 Downing Street and to Stone Henge - obtained from Google Maps. The last five entries are entries which can be *marked*. + +You add and delete entries using the Web IDE to load and then save the file from and to watch storage. The app itself does not limit the number of entries although it does load the entire file into RAM which will obviously limit this. + +I plan to release an accompanying watch app to edit waypoint files in the near future and a way to download your own waypoint file using the app loader. + + + + + diff --git a/apps/gpsnav/app-icon.js b/apps/gpsnav/app-icon.js new file mode 100644 index 000000000..890981d5a --- /dev/null +++ b/apps/gpsnav/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AFmACysDC9+IC6szC/8AgUgLwYXBPAgLDAA8kC5MyC5cyogXHmYiDURMkDAMzC4JgBmcyoAXMGANCC4YDBkgXMHwVEC4hQDC5kyF4kjJ4QAMOgMjC4eCohGNMARbCC4ODkilLAAQSBCYJ3EmYVLhAWCCgQaCAAUwCpowCFwYADIRAYHC4wZFRQIAGnAhJXgwAFxAYHwC9JFwiQCFhIZISAQwDX5sCoQTCDYUjUpAAFglElAXDmS9JAAtEoUyC4ckkbvMC4QQBC4YeBC5sEB4IXEkgfBJBkEH4QXCCYMkoQXMHwcIC4ZQCUpYMDC4oiBC5YEDC40AkCRNAAIXBCJ4X2URgAJhAXvCyoA/ACoA=")) \ No newline at end of file diff --git a/apps/gpsnav/app.js b/apps/gpsnav/app.js new file mode 100644 index 000000000..2a480410c --- /dev/null +++ b/apps/gpsnav/app.js @@ -0,0 +1,224 @@ +const Yoff = 40; +var pal2color = new Uint16Array([0x0000,0xffff,0x07ff,0xC618],0,2); +var buf = Graphics.createArrayBuffer(240,50,2,{msb:true}); + +function flip(b,y) { + g.drawImage({width:240,height:50,bpp:2,buffer:b.buffer, palette:pal2color},0,y); + b.clear(); +} + +var brg=0; +var wpindex=0; +const labels = ["N","NE","E","SE","S","SW","W","NW"]; + +function drawCompass(course) { + buf.setColor(1); + buf.setFont("Vector",16); + var start = course-90; + if (start<0) start+=360; + buf.fillRect(28,45,212,49); + var xpos = 30; + var frag = 15 - start%15; + if (frag<15) xpos+=frag; else frag = 0; + for (var i=frag;i<=180-frag;i+=15){ + var res = start + i; + if (res%90==0) { + buf.drawString(labels[Math.floor(res/45)%8],xpos-8,0); + buf.fillRect(xpos-2,25,xpos+2,45); + } else if (res%45==0) { + buf.drawString(labels[Math.floor(res/45)%8],xpos-12,0); + buf.fillRect(xpos-2,30,xpos+2,45); + } else if (res%15==0) { + buf.fillRect(xpos,35,xpos+1,45); + } + xpos+=15; + } + if (wpindex!=0) { + var bpos = brg - course; + if (bpos>180) bpos -=360; + if (bpos<-180) bpos +=360; + bpos+=120; + if (bpos<30) bpos = 14; + if (bpos>210) bpos = 226; + buf.setColor(2); + buf.fillCircle(bpos,40,8); + } + flip(buf,Yoff); +} + +//displayed heading +var heading = 0; +function newHeading(m,h){ + var s = Math.abs(m - h); + var delta = 1; + if (s<2) return h; + if (m > h){ + if (s >= 180) { delta = -1; s = 360 - s;} + } else if (m <= h){ + if (s < 180) delta = -1; + else s = 360 -s; + } + delta = delta * (1 + Math.round(s/15)); + heading+=delta; + if (heading<0) heading += 360; + if (heading>360) heading -= 360; + return heading; +} + +var course =0; +var speed = 0; +var satellites = 0; +var wp; +var dist=0; + +function radians(a) { + return a*Math.PI/180; +} + +function degrees(a) { + var d = a*180/Math.PI; + return (d+360)%360; +} + +function bearing(a,b){ + var delta = radians(b.lon-a.lon); + var alat = radians(a.lat); + var blat = radians(b.lat); + var y = Math.sin(delta) * Math.cos(blat); + var x = Math.cos(alat)*Math.sin(blat) - + Math.sin(alat)*Math.cos(blat)*Math.cos(delta); + return Math.round(degrees(Math.atan2(y, x))); +} + +function distance(a,b){ + var x = radians(a.lon-b.lon) * Math.cos(radians((a.lat+b.lat)/2)); + var y = radians(b.lat-a.lat); + return Math.round(Math.sqrt(x*x + y*y) * 6371000); +} + +var selected = false; + +function drawN(){ + buf.setColor(1); + buf.setFont("6x8",2); + buf.drawString("o",100,0); + buf.setFont("6x8",1); + buf.drawString("kph",220,40); + buf.setFont("Vector",40); + var cs = course.toString(); + cs = course<10?"00"+cs : course<100 ?"0"+cs : cs; + buf.drawString(cs,10,0); + var txt = (speed<10) ? speed.toFixed(1) : Math.round(speed); + buf.drawString(txt,140,4); + flip(buf,Yoff+70); + buf.setColor(1); + buf.setFont("Vector",20); + var bs = brg.toString(); + bs = brg<10?"00"+bs : brg<100 ?"0"+bs : bs; + buf.setColor(3); + buf.drawString("Brg: ",0,0); + buf.drawString("Dist: ",0,30); + buf.setColor(selected?1:2); + buf.drawString(wp.name,140,0); + buf.setColor(1); + buf.drawString(bs,60,0); + if (dist<1000) + buf.drawString(dist.toString()+"m",60,30); + else + buf.drawString((dist/1000).toFixed(2)+"Km",60,30); + flip(buf,Yoff+130); + g.setFont("6x8",1); + g.setColor(0,0,0); + g.fillRect(10,230,60,239); + g.setColor(1,1,1); + g.drawString("Sats " + satellites.toString(),10,230); +} + +var savedfix; + +function onGPS(fix) { + savedfix = fix; + if (fix!==undefined){ + course = isNaN(fix.course) ? course : Math.round(fix.course); + speed = isNaN(fix.speed) ? speed : fix.speed; + satellites = fix.satellites; + } + if (Bangle.isLCDOn()) { + if (fix!==undefined && fix.fix==1){ + dist = distance(fix,wp); + if (isNaN(dist)) dist = 0; + brg = bearing(fix,wp); + if (isNaN(brg)) brg = 0; + } + drawN(); + } +} + +var intervalRef; + +function clearTimers() { + if(intervalRef) {clearInterval(intervalRef);} +} + +function startTimers() { + intervalRefSec = setInterval(function() { + newHeading(course,heading); + if (course!=heading) drawCompass(heading); + },200); +} + +Bangle.on('lcdPower',function(on) { + if (on) { + g.clear(); + Bangle.drawWidgets(); + startTimers(); + drawAll(); + }else { + clearTimers(); + } +}); + +function drawAll(){ + g.setColor(1,0.5,0.5); + g.fillPoly([120,Yoff+50,110,Yoff+70,130,Yoff+70]); + g.setColor(1,1,1); + drawN(); + drawCompass(heading); +} + +var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}]; +wp=waypoints[0]; + +function nextwp(inc){ + if (!selected) return; + wpindex+=inc; + if (wpindex>=waypoints.length) wpindex=0; + if (wpindex<0) wpindex = waypoints.length-1; + wp = waypoints[wpindex]; + drawN(); +} + +function doselect(){ + if (selected && waypoints[wpindex].mark===undefined && savedfix.fix) { + waypoints[wpindex] ={mark:1, name:"@"+wp.name, lat:savedfix.lat, lon:savedfix.lon}; + wp = waypoints[wpindex]; + require("Storage").writeJSON("waypoints.json", waypoints); + } + selected=!selected; + drawN(); +} + +g.clear(); +Bangle.setLCDBrightness(1); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +// load widgets can turn off GPS +Bangle.setGPSPower(1); +drawAll(); +startTimers(); +Bangle.on('GPS', onGPS); +// Toggle selected +setWatch(nextwp.bind(null,-1), BTN1, {repeat:true,edge:"falling"}); +setWatch(doselect, BTN2, {repeat:true,edge:"falling"}); +setWatch(nextwp.bind(null,1), BTN3, {repeat:true,edge:"falling"}); + diff --git a/apps/gpsnav/first_screen.jpg b/apps/gpsnav/first_screen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34fbe1b506bf3b8951abadeac5589b11b202dc0f GIT binary patch literal 65452 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 AZvX%Q literal 0 HcmV?d00001 diff --git a/apps/gpsnav/gpsnav.jpg b/apps/gpsnav/gpsnav.jpg new file mode 100644 index 0000000000000000000000000000000000000000..975fe39032cb28fc755874e231842684fe3a73bb GIT binary patch literal 47970 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

M#X#R-X}cOVGl^%PqF>L!1JtcqDhm zdBLy7-w$}lTh?JWa<;=1OtJt-8<=p!bq5@A#ct`J5PU^rWj>h(=MU5zGo3k0<4I@1|hjEoZ}o0)p&eV&{}D% ze$Y}-{3M4VqwZH8g!Zq=tIrkqgG$nL>wPxxUrBur%^M7PMF=5%2yFDgti3nlFN!tY zay<)CMz^@O-x|7P`E18I1F81p;8jP&JQwn_8F*WmEpEQ^_3AH)I#srlJkZ@qaLI;M z;|MnuVh6bOtyuhNr_B|!OMFU9>>fg+DTFLHj)3H2K9%_!rg)RYFi9-`0B>bgY%nZ- zY-b>Y$G<&2>!G&zgRf}13l_dIWz1-tgStVSpYJX|D%L(AU^?8wei!B)8bANk{zvpl zPOE(bUI4`4amU^7^{qCzl5J{I+!Y`UdK_l4{3rhaAFzHkqMz~^pZ(?jV!Y;h1*jB@ zv0_<_WEa6FuOhW=blXdb=1CXstAIyd7b3G_{{WD(f4F~{u7^$k0FSGWqyGTt6|BJ3 z(HqOs;kIGEIY|r~oZxX>b^A$YZ!N8}6knL|eGe7a=^ydqYyR_pBV2y5)?fEu`O=7^ zvCi7uNp&P^HzI83wmy}a@fSeTMU+~CCfNcmNWjn6zw1{t-}TnNjb8YR{{SFJ{{Y-y z=T|L-J&z@`fg`pBayOhG%9_!xcCjoEud&5gw*LT+RQ~{b`c!TA$K(G1p-~l~o7oVU zm*v~WH)9^(=bE8~Wnw_V86&aAc=}eE?f(D+ti}6{{^_i)E`>QQAu)zwl1c0ADX+(kAb+hN@Gs_Tam(Q~Srs7+qn)9-=bn`7)s7oje6<|ppL4q(%85VJ z5BCT2rPROU)(^-307I#eLvl@ss*Ixr@ssrb0QFUgAPX2Fj|6_ap4Ah5$bS#yYUJPQ zht+C?_b`O>?0FT+pOo=|)YAErm6An~l!shn9B_TA75@NG{{Te(bs+x$Qz!fD{HnVd zK-aTRHX}TQmKYrO`MaLAy8D*SA(DTLGF;^s`lT1@in5~>X-hyN&KrQd6I5gK_1Y60HbPv z0LBkE$4d2EJ9w;gg}Ai=T6Sc90pkPISD0FV?8*GA)rb6mZT|r4tA8O{)7aW8L(+ax zWd*vZ92~Iw#3{mpeFbLQ*us28HkeC!M;-aW86!TKtt0-b52OD8=v583{Ekxn6aN4~ ztt3&dY~Zx=C4gb2kz;e*sa*b@tBuli8{H;(ZR}(ylOLFN`MUmOS9y2$Er09bKlB>& zX#W7?_wgUria!usmg4T?Qqm`B*oH=83i}*)$o(s^ourS#7B=d~W3+pRuI^26w*LU~ z2fF&V{)Ju5*Zhk5cl*(QDzyFMDQ?d1>{iLH+S;o8rqj$myNMm^GSf_tUAfe)Z{(22 z6YUBQ1P@$;Tdn^9BQ>Y}c(4A1DyN430OTX9f7eE>B-tx-nA5CaeKPXPkcbNmaB>O! z>k3(3Ee7Tx$WCKsNVHQ8(5de{EDC-SZ;@BTj1 O{<@#%S|_lrq5s*41p!O| literal 0 HcmV?d00001 diff --git a/apps/gpsnav/icon.png b/apps/gpsnav/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f899683d1d7e98b906c52bb0a5913de6f4dd2534 GIT binary patch literal 1887 zcmV-l2cY`(ry)@ zWg;nB2-><0R?!l+PBTp>?PycSfGwlYQ9@gxDi^5^Y!XysZ9`Hv!b-Z9ktKmZOG1;1 zCXVAvocMaqw;z!+C)oJ-up{jU&#!a&-tT!Hzu)Ekj)D8QkN;mB`Dd_r^P7X;l9Pjx zvvYyRCa<4=UQP~$oSjq9a;Gm;A}5Dz8F=jyHG+^e4tG$u`R$Hae0FUrS0IWbM zCMNh7<>Hae0420MdhPLrpOlM776XTGP!)j3qxZL6fv%nM{B=n=IV+3j}L&T$&Cy2NL|Z1ywhXg^}xUB_|UUE>&v^4ZV4e*T$c z6s_+xJvRAy_unUgh*(*o4OCWE^79H7A57O|{v>Vin)i>jHE|~6KF0_i~U{%gVDj4ZUBY__!88|{>mj)A_OwZjAb6Qdc%y{TwQc@h&! z_AV;2ps;i~JT9kU=(Fn$2X<{AJXZVS1^@t0HzkU7Pw+bc;M}REg{}66dO;Ab0H_$~ z>%r$;m!Z$i{Uyh7LP~m4H2?su_Qt;gcp^#+01RPZ$jiH`*m{Uig{nB(cK^w~>A0LM zrN6G|9E>5Rr_ zrRtEp6F*V8y`O--<>0kA<1I#mx*DJO7bK0#$>3@ar!=X60a&UV13EVc}j)QO~NW$2w~pc zy+YAJ2%$&;q71A*(XZC>?6a=%@Qz_u@F8Cy!rrZYtk9@|c;e&88KIQEM+t3FWUJoa zy_f_g8+f{YxG*62cX=iwPu+F~^MesSrEEn7??2ghM^;2)54iURXPNN16( z*pQV149!2raYX)NE{fm3@PqC# zpWmV`Tm{wFSE4hp039*nftdyX;9~D6h8-R(%bvvQ%r9Y5j33)jvF$mj8YJ(;$6l^k z=N!3h5qx8qymA)$tAB>W;Yk{|LVXM0^}L1htZT?&$3ZB5_}f*u?mbo3u)QLNX!JZPI3Z z#IRGeF$W^TgZ@T}mXr+~t=;p2*Ewp85l;cM2n?}2R$0B%pi^B+6ieB(mOZb&v1Vam zNttQxysNP$2=Ms(EsfSx^`v|ra65)yi4osQ1ZuNxt^PFnUZ2Sx2e3Y_0g%%Gu;Z2e z7Xg@${$kJ5KG)chfxeyx0HCmR`94bNs#Ge{l$OyWw&xG3)EPf3u#|QZ2rpSHx3|S> z_aN6B9-oXTfEml^V9mqIh4I9_{!-0Om(#J|IA^Y|pk&#W4bN1c601q{5aKvasnzM% z6+X1I(ppiqI+1t)n4?o&oBfP{oKE!1KDY1H`r6~o`UoGk4c)l<^Y-?3(IZ2&0W+Xn zxW-y$t*B~Amg1~*_MO?!C>72m8{bdZxSvkZ{buANgnzX+}uL(%f;Ug8Y8OUJO z2bigCnGch+vvTpsie>w*yAO2+&dbRm>%Wvnjq(BkK9rL~Rs&h->}!;uUrvtuxQ~0p Ze*jRY!kx=d0W$yq002ovPDHLkV1iy}i`f7G literal 0 HcmV?d00001 diff --git a/apps/gpsnav/marked_screen.jpg b/apps/gpsnav/marked_screen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..accd3b15fe5fa0996c51ada2f75ddd416dd17394 GIT binary patch literal 65895 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%0D85DN}Kju4Ys-^?RDWah8DK1Yt!XB1!a-x5(? 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

SKQuyodtT#X^!9_vAdcfo!M@gV% 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

\n"+e+"\n"},t.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},t.strong=function(e){return""+e+""},t.em=function(e){return""+e+""},t.codespan=function(e){return""+e+""},t.br=function(){return this.options.xhtml?"
":"
"},t.del=function(e){return""+e+""},t.link=function(e,t,n){if(null===(e=K(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"},t.image=function(e,t,n){if(null===(e=K(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},t.text=function(e){return e},e}(),ee=function(){function e(){}var t=e.prototype;return t.strong=function(e){return e},t.em=function(e){return e},t.codespan=function(e){return e},t.del=function(e){return e},t.html=function(e){return e},t.text=function(e){return e},t.link=function(e,t,n){return""+n},t.image=function(e,t,n){return""+n},t.br=function(){return""},e}(),te=function(){function e(){this.seen={}}return e.prototype.slug=function(e){var t=e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t))for(var n=t;this.seen[n]++,t=n+"-"+this.seen[n],this.seen.hasOwnProperty(t););return this.seen[t]=0,t},e}(),ne=t.defaults,re=_,ie=function(){function n(e){this.options=e||ne,this.options.renderer=this.options.renderer||new Y,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new ee,this.slugger=new te}n.parse=function(e,t){return new n(t).parse(e)};var e=n.prototype;return e.parse=function(e,t){void 0===t&&(t=!0);for(var n,r,i,s,a,l,o,c,h,u,p,g,f,d,k,b,m,x="",w=e.length,v=0;vAn error occurred:

"+le(e.message+"",!0)+"
";throw e}}return ue.options=ue.setOptions=function(e){return se(ue.defaults,e),ce(ue.defaults),ue},ue.getDefaults=oe,ue.defaults=he,ue.use=function(l){var t,n=se({},l);l.renderer&&function(){var a=ue.defaults.renderer||new Y;for(var e in l.renderer)!function(i){var s=a[i];a[i]=function(){for(var e=arguments.length,t=new Array(e),n=0;n Date: Mon, 1 Jun 2020 09:32:47 +0100 Subject: [PATCH 1034/1189] fix travis errors --- .eslintignore | 2 +- apps.json | 2 +- apps/verticalface/ChangeLog | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 apps/verticalface/ChangeLog diff --git a/.eslintignore b/.eslintignore index 544f416aa..550fbda3f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,5 +2,5 @@ lib/espruinotools.js lib/imageconverter.js lib/qrcode.min.js lib/heatshrink.js - +lib/marked.min.js apps/animclk/V29.LBM.js diff --git a/apps.json b/apps.json index 09c7f9390..5eb039b53 100644 --- a/apps.json +++ b/apps.json @@ -1831,7 +1831,7 @@ "name": "Vertical watch face", "shortName":"Vertical Face", "icon": "app.png", - "version":"0.4.1", + "version":"0.04", "description": "A simple vertical watch face with the date.", "tags": "clock", "type":"clock", diff --git a/apps/verticalface/ChangeLog b/apps/verticalface/ChangeLog new file mode 100644 index 000000000..19d763698 --- /dev/null +++ b/apps/verticalface/ChangeLog @@ -0,0 +1 @@ +0.04: Fixed day being displayed From 5bc70b474c0121bc26e7efdf4be07d6a3f876a4f Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 10:42:57 +0100 Subject: [PATCH 1035/1189] Merge didn't; t work --- apps.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 883a3cdf9..d266cd0c0 100644 --- a/apps.json +++ b/apps.json @@ -1768,11 +1768,10 @@ "storage": [ { "name": "jbm8b.app.js", "url": "app.js" }, { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } - ], + ] "version": "0.03" }, -{ - "id": "BLEcontroller", + { "id": "BLEcontroller", "name": "BLE Robot Controller with Joystick", "shortName": "BLE Controller", "icon": "BLEcontroller.png", @@ -1784,6 +1783,8 @@ "storage": [ { "name": "BLEcontroller.app.js", "url": "app.js" }, { "name": "BLEcontroller.img", "url": "app-icon.js", "evaluate": true } + ] + }, { "id": "widviz", "name": "Widget Visibility Widget", "shortName":"Viz Widget", From 6aad4d8f93413c30c3d6b579040920a2c87124b8 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 11:27:51 +0100 Subject: [PATCH 1036/1189] Fixing JSON --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index d266cd0c0..6c0f50eca 100644 --- a/apps.json +++ b/apps.json @@ -1765,11 +1765,11 @@ "icon": "app.png", "description": "A simple fortune telling app", "tags": "game", + "version": "0.03", "storage": [ { "name": "jbm8b.app.js", "url": "app.js" }, { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } - ] - "version": "0.03" + ] }, { "id": "BLEcontroller", "name": "BLE Robot Controller with Joystick", From 26d0fd32792b755c012223a982bf6b8b54b43dd1 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 11:40:59 +0100 Subject: [PATCH 1037/1189] Adding variable declarations and syntax error --- apps/BLEcontroller/app.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 6200600f1..7ba95589d 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -1,6 +1,6 @@ /* ========================================================== -Simple event based robot controller that enables robot +Simple event based robot controller that enables robot to switch into automatic or manual control modes. Behaviours are controlled via a simple finite state machine. In automatic mode the @@ -19,7 +19,7 @@ bottom_btn = false; msgNum = 0; // message number -/* +/* CONFIGURATION AREA - STATE VARIABLES declare global variables for the toggle button statuses; if you add an additional toggle button @@ -28,6 +28,12 @@ you should declare it and initiase it here */ var status_auto = {value: false}; var status_mic = {value: true}; var status_spk = {value: true}; +var status_face = {value: true}; +var status_chess = {value: false}; +var status_iris_light = {value: false}; +var status_iris = {value: false}; +var status_wake = {value: false}; +var status_hover = {value: false}; /* trsnsmit message where @@ -415,7 +421,7 @@ const speakScreen = { const irisScreen = { left: irisBtn, - right: irisBirisLightBtn, + right: irisLightBtn, btn3: "back" }; @@ -431,9 +437,9 @@ const chessScreen = { btn3: "back" }; -/* base state definition +/* base state definition Each of the screens correspond to a state; -this class provides a constuctor for each +this class provides a constuctor for each of the states */ class State { @@ -605,7 +611,7 @@ const Iris = new State({ } transmit(this.state, event.object, event.status); return this; - } + } }); const Lights = new State({ @@ -627,7 +633,7 @@ const Lights = new State({ } transmit(this.state, event.object, event.status); return this; - } + } }); @@ -676,7 +682,7 @@ const onOff= status => status ? "on" : "off"; /* create watching functions that will change the global -button status when pressed or released +button status when pressed or released This is actuslly the hesrt of the program. When a button is not being pressed, nothing is happening (no loops). This makes the progrsm more battery efficient. @@ -684,7 +690,7 @@ When a setWatch event is raised, the custom callbacks defined here will be called. These then fired as events to the current state/screen of the state mschine. Some events, will result in the stste of the state machine -chsnging, which is why the screen is redrswn after each +chsnging, which is why the screen is redrswn after each button press. */ const setMyWatch = (params) => { @@ -742,4 +748,4 @@ const drawScreen = (params) => { machine = Home; // instantiate the state machine at Home Bangle.drawWidgets(); // draw active widgets -drawScreen(machine.screen); // draw the screen \ No newline at end of file +drawScreen(machine.screen); // draw the screen From a5cc710ef84f053b598fad8eb0c2e3834140d1c9 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 11:44:27 +0100 Subject: [PATCH 1038/1189] Syntax error --- apps/BLEcontroller/app.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 7ba95589d..2ad91ba54 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -580,18 +580,6 @@ const Tail = new State({ } }); -const Speak = new State({ - state: "Speak", - screen: speakScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return DalekMenu; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - const Iris = new State({ state: "Iris", screen: irisScreen, From b929b5d0cbe903070f741510f4681e23333e3951 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 14:19:23 +0100 Subject: [PATCH 1039/1189] Splitting app into three variants --- apps/BLEcontroller/README.md | 32 +- apps/BLEcontroller/app-big.js | 739 ++++++++++++++++++++++++++++++++++ apps/BLEcontroller/app.js | 520 ++++-------------------- 3 files changed, 824 insertions(+), 467 deletions(-) create mode 100644 apps/BLEcontroller/app-big.js diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index 237392e1e..56f1a2658 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -1,14 +1,18 @@ -# BLE Robot Controller with Joystick +# BLE Generic Controller with Joystick -A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. Amaze your friends by controlling your robot from your watch! +A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. -To keep the messages small, commands are sent from the Controller to the BLE robot in a text string. This is made up of a comma delimited string of the following elements: +Amaze your friends by controlling your robot, your house or any other BLE device from your watch! + +To keep the messages small, commands are sent from the Controller to the BLE target in a text string. This is made up of a comma delimited string of the following elements: * message number (3 characters) * screen name (3 characters) * object name (3 characters) * value/status (3 characters) -The combination of these variables will uniquely identify the status change requested from the watch to the robot that can then be programmed to respond appropriately. +The combination of these variables will uniquely identify the status change requested from the watch to the target device that can then be programmed to respond appropriately. + +Gordon Williams' EspruinoHub is an excellent way to transform BLE advertisements into MQTT messages for further processing. ## Usage @@ -18,20 +22,12 @@ Most changes are possible via data, rather than code change. ## Features -In its default state, it has nine screens that provide the ability to: -* select which robot to interact with (dog or dalek) - * for the dog the following functions are available: - * control movement via a joystick (forwards, backwards, spin left, spin right) - * turn on/off follow mode - * start a game of chess - * wake or sleep the robot - * wag its tail in two directions - * for the dalek, the user can: - * turn on or off face recognition - * make it say random phrases - * control the dalek's iris light and servo - * turn the dalek hover lights on or off - * turn the speaker on or off +The default package contains three configurations: +* a simple home light and sockets controller UI (app.js) +* a robot controller UI with joystick (app-joy.js) +* a simple static assistant controller (app-ass.js) + +You can try out the other configurations by deleting app.js and renaming the file you want to app.js. ## Controls diff --git a/apps/BLEcontroller/app-big.js b/apps/BLEcontroller/app-big.js new file mode 100644 index 000000000..2ad91ba54 --- /dev/null +++ b/apps/BLEcontroller/app-big.js @@ -0,0 +1,739 @@ +/* +========================================================== +Simple event based robot controller that enables robot +to switch into automatic or manual control modes. Behaviours +are controlled via a simple finite state machine. +In automatic mode the +robot will look after itself. In manual mode, the watch +will provide simple forward, back, left and right commands. +The messages will be transmitted to a partner BLE Espruino +using BLE +Written by Richard Hopkins, May 2020 +========================================================== +declare global variables for watch button statuses */ +top_btn = false; +middle_btn = false; +left_btn= false; // the left side of the touch screen +right_btn = false; // the right side of the touch screen +bottom_btn = false; + +msgNum = 0; // message number + +/* +CONFIGURATION AREA - STATE VARIABLES +declare global variables for the toggle button +statuses; if you add an additional toggle button +you should declare it and initiase it here */ + +var status_auto = {value: false}; +var status_mic = {value: true}; +var status_spk = {value: true}; +var status_face = {value: true}; +var status_chess = {value: false}; +var status_iris_light = {value: false}; +var status_iris = {value: false}; +var status_wake = {value: false}; +var status_hover = {value: false}; + +/* trsnsmit message +where +s = first character of state, +o = first three character of object name +v = value of state.object +*/ + +const transmit = (state,object,status) => { + msgNum ++; + msg = { + n: msgNum.toString().slice(-4), + s: state.substr(0,4), + o: object.substr(0,4), + v: status.substr(0.4), + }; + message= msg.n + "," + msg.s + "," + msg.o + "," + msg.v; + NRF.setAdvertising({},{ + showName: false, + manufacturer: 0x0590, + manufacturerData: JSON.stringify(message)}); +}; + +/* +CONFIGURATION AREA - ICON DEFINITIONS +Retrieve 30px PNG icons from: +https://icons8.com/icon/set/speak/ios-glyphs +Create icons using: +https://www.espruino.com/Image+Converter +Use compression: true +Transparency: true +Diffusion: flat +Colours: 16bit RGB +Ouput as: Image Object +Add an additional element to the icons array +with a unique name and the data from the Image Object +*/ +const icons = [ + { + name: "walk", + data: "gEBAP4B/ALyh7b/YALHfY9tACY55HfYdNHto7pHpIbXbL5fXAD6VlHuYAjHf47/Hf47tHK47LDa45zHc4NHHeILJHeonTO9o9rHf47/eOoB/ANg=" + }, + { + name: "sit", + data: "gEBAP4B/AP4BacO4ANHPI/rACp1/Hf49rGtI5/He7n3ACY55HcYAZHf45/Hf45rHe4XHGbI7/Va47zZZrpbHfbtXD5Y/vHcYB/AP4BmA" + }, + { + name: "joystick", + data: "gEBAP4B/AP4BMavIALHPI9vHf47/eP45vHpY5xHo451Hf47/FuYAHHNItHABa33AP6xpAD455HqY7/Hf47/Hd49pHKIB/AP4B/AMwA==" + }, + { + name: "left", + data: "gEBAP4B/AP4BKa9ojHAC5pfHJKDTUsYdZHb6ZfO+I9dABabdLbIBdHf473PP47NJdY7/ePIB/RJop5Ys7t/AP6PvD7o7fP8Y1zTZoHPf/4B/AP4B+A==" + }, + { + name: "right", + data: "gEBAP4B/AP4BKa+oAXDo45hCaqFbUbLBfbbo7bHMojTR7Y5LHa51ZALo75Ov47/FeY77AP4B5WdbF3dv4B/R94fdHb5/jGuabNA57//AP4B/APw=" + }, + { + name: "forward", + data: "gEBAP4B/AKSX5avIALHPI9tACY55HsoAbHPI9fHfZFVGMo7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf49XHOIB/ALw=" + }, + { + name: "backward", + data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/HfIAfHf491W/L15HMo9THNI9PHNo9LHOI9HHOoB/ALg=" + }, + { + name: "back", + data: "gEBAP4B/AP4B/AKgADHPI71HP45/HP45/HP45/HP45/Hf49/Hv49/Hv49/Hv49/Hv497He4B/AP4B/AJAA==" + }, + { + name: "spk_on", + data: "gEBAP4B/AP4Bic/YAFPP4v1HrYZRVJo7ZDKp5jMJYvZHaYAHVL4LHACZrhADLBTJKI7dPLI7/Hf47/HeZBVFqZHZRJp1lAJ47LOtZTnHbIZDKLpHNAL69ZANp1tQbY5/AP4B/ANQ" + }, + { + name: "spk_off", + data: "gEBAPhB7P/o9rFKI9pFKY9tXNYZNHrZXfMaoAHPOZhNF7LdXHpKpZEJpvPDZK1ZAB49NPLo9jHdI9NHd49PHebvxEJY9NI6I7dHpaDXcKqfPHLKjZHcpTjHbIZDKa73JHa4BXGY45xe5Y7zV+o9/Hv49JHe4BEA=" + }, + { + name: "mic_on", + data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Hf47/Hf47/HdY9NCpp5lCb57fOdYvNeJo91HNrlvHf7tVIdY77AP4BiA=" + }, + { + name: "mic_off", + data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Wf47/HJZLjHZ45RHrI7NHJYhLHqoZJA54hNHr5lTXL6vPSra5jKbo9REZrLRHa5DTXp47jAA7TTF7INLRqY7fdKavhXKo5te6wA==" + }, + { + name: "comms", + data: "gEBAP4B+QvbF7ABo7/He49tACI7/Hf47zHtI7jJq47lRqoAVEqY7nHsoAZGJo71HrKxfQaY7bdKo7/Hdqz5B5Y7zHK47RD55FRHao3XHKo7JG7L1NHeJTbHboB/AP4BG" + }, + { + name: "dalek", + data: "gEBAP4B/AP4B/AJMQwQBBGucIoMAkADBhFhAoZBcAAQfJhEgB45BCHYMBjGiB4ZLCK5APDFpphBC5AbEJosY0YfCG4IAEJIYdGFYR5LHJYlEAI0Y4cY8YXMOpQBFlNFlMkOZA7MKII7JOAXkE4T1UERKtFHoxJBABY5QiGiD5kANYTnCiFiWIJVOgDZCOra3FoKxFDKI7hADQ7PkEIaoIHEaKYfJAoKPFAJcIGYIJHkI7UgMY8ZFHC5rVDKIZTCDIJhBA4ILBBoYFHC4QBEBogpBjHDdsJJEAoYAHKoTxWWb5tNWZOiHZRbBHbwtLF5ynBL7wtLjHjd6oAZkHkI5JJKAAZ3TkAjJhALBsJ5K0a/KkLvfkMEFpVhO8hrIU4QLGG4QAzkCdVAP4B/AP4Bb" + }, + { + name: "k9", + data: "gEBAP4B/AP4B/AP4B/AP4B/AKAADIf5N/IaIAJJv5LZLeIARffZNdD5JN/KLYATC65RbAGrHlJ/5P/JuYrRJfovNJf4BdAFJL/Jv5N/Jv5L1Jv5PvJv5L7Jv5PpAGpN/dv5HzAP4B/AP4B/AP4B/AP4B/ALg" + }, + { + name: "pawn", + data: "gEBAP4B/AP4B/AP4BEAA455HuY7/Hf47xAB47/PuI1xPZY7/Hf47/G9Y/zHfIATHPI9nHfYB/AOYAfHf4B/AP4B/APA=" + }, + { + name: "facerecog", + data: "gEBAP4BSLuozNH9YpTHsolXPsYfdDraZhELIZhHeLtJELY1VC4Y7HHqoXJABYdNHa5bJDrLvfHfbrPZJI7nGZpdVNJ4lRIpaznRqp1hCq55ZC6IRPd8oPjW8Y5jSr45dEJppNHcIjLHZY5ja6rrhFK45pVqI5rGI4AHHNpx3ANA=" + }, + { + name: "sleep", + data: "gEBAP4B/AP4B2ACY7/Quq95HP45/HP4APOdY7fACZfnHcaZZAL45/HP45/E7YAHCaZFZHfbh/HP45/HOoAHHf4B/AP4B/AP4BIA=" + }, + { + name: "awake", + data: "gEBAP4B/AKyb7HfIAFHPI77Ov451Hf453Hf453HdoAbHf45/Hf5HrHNY7NHNo7/HO47/HO47HHPJ1/Heo51HfoB/ALg=" + }, + { + name: "wag_h", + data: "gEBAP4B/AP4B/AP4B/AP4B/AMwADD+oAFHb4hTHMIlXHMopTHNItPAG47/WfY9tFKY9lEq49hELY7ja8YB/AP4B/AP4B/AP4B/AP4BCA" + }, + { + name: "wag_v", + data: "gEBAP4B/AP4BOafIAHHPI9xAB45vd449rFZIHLHsonJBKa7rGNo7/Hf47/Hf47/Hf47/Hf4xlBKY7hFIoHLQM4rHApK7rAB71xHOo9LHOI9HHOoB/AP4BYA=" + }, + { + name: "happy", + data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/HtInTCZrfZHa4vNABYlVKLI3PbLrzfD7qTXDLaphHMIpLAB45hIKY1pAP4B/AMA" + }, + { + name: "sad", + data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/CK4njCZ4APHcIVJBbbdTecYjZHr4fdSa4ZbEZ4lNCaY9dAB45hIKY1pAP4B/AMA" + }, + { + name: "hover", + data: "gEBAP4B/AP7NedL4fZK7ojNHeJ35DJI7vC5Y7tVMI7XHNYnNYro7hHKI7lAK47/HdoAhHPI7/Hf47/Hf4AtHPI7/Hf47/Hd45LAP4B/ANwA=" + }, + { + name: "light", + data: "gEBAP4B/APi/Na67lfACZ/nNaI9lE6o9jEbI9hD7Y7dDsJZ3D6YRJHdIJHHfaz7Hf5Z/Hf4hZHMIjFEqIVVHsY5hDpI7TEqL1jVsqlTdM55THOJvHOuY7/HfI9JHOI9HHOoBgA==" + }, + { + name: "speak", + data: "gEBAP4B/AP4BIbO4AXG+4/hAEY55HqoArHPI9PHfIAzHf47/Hf47/HeY9xHJI79Hto5NHtY5RHc45THco5VHcI3XHJpHRG7I7LEro5ZG+IB/AP4BwA==" + } + ]; + +/* finds icon data by name in the icon array and returns an image object*/ +const drawIcon = (name) => { + for (var icon of icons) { + if (icon.name == name) { + image = { + width : 30, height : 30, bpp : 16, + transparent : 1, + buffer: require("heatshrink").decompress(atob(icon.data)) + }; + return image;} + } +}; + +/* +CONFIGURATION AREA - BUTTON DEFINITIONS +for a simple button, just define a primary colour +and an icon name from the icon array and +the text to display beneath the button +for toggle buttons, additionally provide secondary +colours, icon name and text. Also provide a reference +to a global variable for the value of the button. +The global variable should be declared at the start of +the program and it may be adviable to use the 'status_name' +format to ensure it is clear. +*/ +var joystickBtn = { + primary_colour: 0x653E, + primary_icon: 'joystick', + primary_text: 'Joystick', + }; + +var turnLeftBtn = { + primary_colour: 0x653E, + primary_text: 'Left', + primary_icon: 'left', + }; + +var turnRightBtn = { + primary_colour: 0x33F9, + primary_text: 'Right', + primary_icon: 'right', + }; + +var k9Btn = { + primary_colour: 0x653E, + primary_text: 'K9', + primary_icon: 'k9', + }; + +var dalekBtn = { + primary_colour: 0x33F9, + primary_text: 'Dalek', + primary_icon: 'dalek', + }; + +var tailHBtn = { + primary_colour: 0x653E, + primary_text: 'Wag Tail', + primary_icon: 'wag_h', + }; + +var tailVBtn = { + primary_colour: 0x33F9, + primary_text: 'Wag Tail', + primary_icon: 'wag_v', + }; + +var happyBtn = { + primary_colour: 0x653E, + primary_text: 'Speak', + primary_icon: 'happy', + }; + +var sadBtn = { + primary_colour: 0x33F9, + primary_text: 'Speak', + primary_icon: 'sad', + }; + +var speakBtn = { + primary_colour: 0x33F9, + primary_text: 'Speak', + primary_icon: 'speak', + }; + +var faceBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'facerecog', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'facerecog', + value: status_face + }; + +var chessBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'pawn', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'pawn', + value: status_chess + }; + +var irisLightBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'light', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'light', + value: status_iris_light + }; + +var irisBtn = { + primary_colour: 0xE9C7, + primary_text: 'Closed', + primary_icon: 'sleep', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'Open', + secondary_icon : 'awake', + value: status_iris + }; + +var wakeBtn = { + primary_colour: 0xE9C7, + primary_text: 'Sleeping', + primary_icon: 'sleep', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'Awake', + secondary_icon : 'awake', + value: status_wake + }; + +var hoverBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'hover', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'hover', + value: status_hover + }; + +var autoBtn = { + primary_colour: 0xE9C7, + primary_text: 'Stop', + primary_icon: 'sit', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'Move', + secondary_icon : 'walk', + value: status_auto + }; + +var micBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'mic_off', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'mic_on', + value: status_mic + }; + +var spkBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'spk_off', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'spk_on', + value: status_spk + }; + +/* +CONFIGURATION AREA - SCREEN DEFINITIONS +a screen can have a button (as defined above) +on the left and/or the right of the screen. +in adddition a screen can optionally have +an icon for each of the three buttons on +the left hand side of the screen. These +are defined as btn1, bt2 and bt3. The +values are names from the icon array. +*/ +const menuScreen = { + left: k9Btn, + right: dalekBtn, +}; + +const k9MenuScreen = { + left: wakeBtn, + right: joystickBtn, + btn1: "pawn", + btn2: "wag_h", + btn3: "back" +}; + +const joystickScreen = { + left: turnLeftBtn, + right: turnRightBtn, + btn1: "forward", + btn2: "backward", + btn3: "back" +}; + +const tailScreen = { + left: tailHBtn, + right: tailVBtn, + btn3: "back" +}; + +const commsScreen = { + left: micBtn, + right: spkBtn, + btn3: "back" +}; + +const dalekMenuScreen = { + left: faceBtn, + right: speakBtn, + btn1: "hover", + btn2: "light", + btn3: "back" +}; + +const speakScreen = { + left: happyBtn, + right: sadBtn, + btn3: "back" +}; + +const irisScreen = { + left: irisBtn, + right: irisLightBtn, + btn3: "back" +}; + +const lightsScreen = { + left: hoverBtn, + right: spkBtn, + btn3: "back" +}; + +const chessScreen = { + left: chessBtn, + right: autoBtn, + btn3: "back" +}; + +/* base state definition +Each of the screens correspond to a state; +this class provides a constuctor for each +of the states +*/ +class State { + constructor(params) { + this.state = params.state; + this.events = params.events; + this.screen = params.screen; + } +} + +/* +CONFIGURATION AREA - BUTTON BEHAVIOURS/STATE TRANSITIONS +This area defines how each screen behaves. +Each screen corresponds to a different State of the +state machine. This makes it much easier to isolate +behaviours between screens. +The state value is transmitted whenever a button is pressed +to provide context (so the receiving device, knows which +button was pressed on which screen). +The screens are defined above. +The events section identifies if a particular button has been +pressed and released on the screen and an action can then be taken. +The events function receives a notification from a mySetWatch which +provides an event object that identifies which button and whether +it has been pressed down or released. Actions can then be taken. +The events function will always return a State object. +If the events function returns different State from the current +one, then the state machine will change to that new State and redrsw +the screen appropriately. +To add in additional capabilities for button presses, simply add +an additional 'if' statement. +For toggle buttons, the value of the sppropiate status object is +inversed and the new value transmitted. +*/ + +/* The Home State/Page is where the application beings */ +const Home = new State({ + state: "Home", + screen: menuScreen, + events: (event) => { + if ((event.object == "right") && (event.status == "end")) { + return DalekMenu; + } + if ((event.object == "left") && (event.status == "end")) { + //status_auto.value = !status_auto.value; + //transmit(this.state, "auto", onOff(status_auto.value)); + //return this; + return K9Menu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const K9Menu = new State({ + state: "K9Menu", + screen: k9MenuScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return Home; + } + if ((event.object == "right") && (event.status == "end")) { + return Joystick; + } + if ((event.object == "left") && (event.status == "end")) { + status_wake.value = !status_wake.value; + transmit(this.state, "auto", onOff(status_wake.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const DalekMenu = new State({ + state: "DalekMenu", + screen: dalekMenuScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return Home; + } + if ((event.object == "right") && (event.status == "end")) { + return Speak; + } + if ((event.object == "left") && (event.status == "end")) { + status_face.value = !status_face.value; + transmit(this.state, "face", onOff(status_face.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Speak = new State({ + state: "Speak", + screen: speakScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Chess = new State({ + state: "Chess", + screen: chessScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return K9Menu; + } + if ((event.object == "right") && (event.status == "end")) { + status_auto.value = !status_auto.value; + transmit(this.state, "follow", onOff(status_auto.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_chess.value = !status_chess.value; + transmit(this.state, "chess", onOff(status_chess.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Tail = new State({ + state: "Tail", + screen: tailScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return K9Menu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Iris = new State({ + state: "Iris", + screen: irisScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + if ((event.object == "right") && (event.status == "end")) { + status_iris_light.value = !status_iris_light.value; + transmit(this.state, "iris_light", onOff(status_iris_light.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_iris.value = !status_iris.value; + transmit(this.state, "iris_servo", onOff(status_iris.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Lights = new State({ + state: "Lights", + screen: lightsScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + if ((event.object == "right") && (event.status == "end")) { + status_spk.value = !status_spk.value; + transmit(this.state, "iris_light", onOff(status_spk.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_hover.value = !status_hover.value; + transmit(this.state, "hover", onOff(status_hover.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + + +/* Joystick page state */ +const Joystick = new State({ + state: "Joystick", + screen: joystickScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + transmit("Joystick", "joystick", "off"); + return Home; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +/* Comms page state */ +const Comms = new State({ + state: "Comms", + screen: commsScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return Home; + } + if ((event.object == "left") && (event.status == "end")) { + status_mic.value = !status_mic.value; + transmit(this.state, "mic", onOff(status_mic.value)); + return this; + } + if ((event.object == "right") && (event.status == "end")) { + status_spk.value = !status_spk.value; + transmit(this.state, "spk", onOff(status_spk.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +/* translate button status into english */ +const startEnd = status => status ? "start" : "end"; + +/* translate status into english */ +const onOff= status => status ? "on" : "off"; + + +/* create watching functions that will change the global +button status when pressed or released +This is actuslly the hesrt of the program. When a button +is not being pressed, nothing is happening (no loops). +This makes the progrsm more battery efficient. +When a setWatch event is raised, the custom callbacks defined +here will be called. These then fired as events to the current +state/screen of the state mschine. +Some events, will result in the stste of the state machine +chsnging, which is why the screen is redrswn after each +button press. +*/ +const setMyWatch = (params) => { + setWatch(() => { + params.bool=!params.bool; + machine = machine.events({object: params.label, status: startEnd(params.bool)}); + drawScreen(machine.screen); + }, params.btn, {repeat:true, edge:"both"}); +}; + +/* object array used to set up the watching functions +*/ +const buttons = [ + {bool : bottom_btn, label : "bottom",btn : BTN3}, + {bool : middle_btn, label : "middle",btn : BTN2}, + {bool : top_btn, label : "top",btn : BTN1}, + {bool : left_btn, label : "left",btn : BTN4}, + {bool : right_btn, label : "right",btn : BTN5} + ]; + +/* set up watchers for buttons */ +for (var button of buttons) + {setMyWatch(button);} + +/* Draw various kinds of buttons */ +const drawButton = (params,side) => { + g.setFontAlign(0,1); + icon = drawIcon(params.primary_icon); + text = params.primary_text; + g.setColor(params.primary_colour); + const x = (side == "left") ? 0 : 120; + if ((params.toggle) && (params.value.value)) { + g.setColor(params.secondary_colour); + text = params.secondary_text; + icon = drawIcon(params.secondary_icon); + } + g.fillRect(0+x,24,119+x, 239); + g.setColor(0x000); + g.setFont("Vector",15); + g.setFontAlign(0,0.0); + g.drawString(text,60+x,160); + options = {rotate: 0, scale:2}; + g.drawImage(icon,x+60,120,options); +}; + +/* Draw the pages corresponding to the states */ +const drawScreen = (params) => { + drawButton(params.left,'left'); + drawButton(params.right,'right'); + g.setColor(0x000); + if (params.btn1) {g.drawImage(drawIcon(params.btn1),210,40);} + if (params.btn2) {g.drawImage(drawIcon(params.btn2),210,125);} + if (params.btn3) {g.drawImage(drawIcon(params.btn3),210,195);} +}; + +machine = Home; // instantiate the state machine at Home +Bangle.drawWidgets(); // draw active widgets +drawScreen(machine.screen); // draw the screen diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 2ad91ba54..1b4775ef2 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -25,15 +25,10 @@ declare global variables for the toggle button statuses; if you add an additional toggle button you should declare it and initiase it here */ -var status_auto = {value: false}; -var status_mic = {value: true}; -var status_spk = {value: true}; -var status_face = {value: true}; -var status_chess = {value: false}; -var status_iris_light = {value: false}; -var status_iris = {value: false}; -var status_wake = {value: false}; -var status_hover = {value: false}; +var status_printer = {value: false}; +var status_tv = {value: false}; +var status_light_hall = {value: false}; +var status_light_study = {value: false}; /* trsnsmit message where @@ -73,108 +68,12 @@ with a unique name and the data from the Image Object */ const icons = [ { - name: "walk", - data: "gEBAP4B/ALyh7b/YALHfY9tACY55HfYdNHto7pHpIbXbL5fXAD6VlHuYAjHf47/Hf47tHK47LDa45zHc4NHHeILJHeonTO9o9rHf47/eOoB/ANg=" - }, - { - name: "sit", - data: "gEBAP4B/AP4BacO4ANHPI/rACp1/Hf49rGtI5/He7n3ACY55HcYAZHf45/Hf45rHe4XHGbI7/Va47zZZrpbHfbtXD5Y/vHcYB/AP4BmA" - }, - { - name: "joystick", - data: "gEBAP4B/AP4BMavIALHPI9vHf47/eP45vHpY5xHo451Hf47/FuYAHHNItHABa33AP6xpAD455HqY7/Hf47/Hd49pHKIB/AP4B/AMwA==" - }, - { - name: "left", - data: "gEBAP4B/AP4BKa9ojHAC5pfHJKDTUsYdZHb6ZfO+I9dABabdLbIBdHf473PP47NJdY7/ePIB/RJop5Ys7t/AP6PvD7o7fP8Y1zTZoHPf/4B/AP4B+A==" - }, - { - name: "right", - data: "gEBAP4B/AP4BKa+oAXDo45hCaqFbUbLBfbbo7bHMojTR7Y5LHa51ZALo75Ov47/FeY77AP4B5WdbF3dv4B/R94fdHb5/jGuabNA57//AP4B/APw=" - }, - { - name: "forward", - data: "gEBAP4B/AKSX5avIALHPI9tACY55HsoAbHPI9fHfZFVGMo7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf49XHOIB/ALw=" - }, - { - name: "backward", - data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/HfIAfHf491W/L15HMo9THNI9PHNo9LHOI9HHOoB/ALg=" - }, - { - name: "back", - data: "gEBAP4B/AP4B/AKgADHPI71HP45/HP45/HP45/HP45/Hf49/Hv49/Hv49/Hv49/Hv497He4B/AP4B/AJAA==" - }, - { - name: "spk_on", - data: "gEBAP4B/AP4Bic/YAFPP4v1HrYZRVJo7ZDKp5jMJYvZHaYAHVL4LHACZrhADLBTJKI7dPLI7/Hf47/HeZBVFqZHZRJp1lAJ47LOtZTnHbIZDKLpHNAL69ZANp1tQbY5/AP4B/ANQ" - }, - { - name: "spk_off", - data: "gEBAPhB7P/o9rFKI9pFKY9tXNYZNHrZXfMaoAHPOZhNF7LdXHpKpZEJpvPDZK1ZAB49NPLo9jHdI9NHd49PHebvxEJY9NI6I7dHpaDXcKqfPHLKjZHcpTjHbIZDKa73JHa4BXGY45xe5Y7zV+o9/Hv49JHe4BEA=" - }, - { - name: "mic_on", - data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Hf47/Hf47/HdY9NCpp5lCb57fOdYvNeJo91HNrlvHf7tVIdY77AP4BiA=" - }, - { - name: "mic_off", - data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Wf47/HJZLjHZ45RHrI7NHJYhLHqoZJA54hNHr5lTXL6vPSra5jKbo9REZrLRHa5DTXp47jAA7TTF7INLRqY7fdKavhXKo5te6wA==" - }, - { - name: "comms", - data: "gEBAP4B+QvbF7ABo7/He49tACI7/Hf47zHtI7jJq47lRqoAVEqY7nHsoAZGJo71HrKxfQaY7bdKo7/Hdqz5B5Y7zHK47RD55FRHao3XHKo7JG7L1NHeJTbHboB/AP4BG" - }, - { - name: "dalek", - data: "gEBAP4B/AP4B/AJMQwQBBGucIoMAkADBhFhAoZBcAAQfJhEgB45BCHYMBjGiB4ZLCK5APDFpphBC5AbEJosY0YfCG4IAEJIYdGFYR5LHJYlEAI0Y4cY8YXMOpQBFlNFlMkOZA7MKII7JOAXkE4T1UERKtFHoxJBABY5QiGiD5kANYTnCiFiWIJVOgDZCOra3FoKxFDKI7hADQ7PkEIaoIHEaKYfJAoKPFAJcIGYIJHkI7UgMY8ZFHC5rVDKIZTCDIJhBA4ILBBoYFHC4QBEBogpBjHDdsJJEAoYAHKoTxWWb5tNWZOiHZRbBHbwtLF5ynBL7wtLjHjd6oAZkHkI5JJKAAZ3TkAjJhALBsJ5K0a/KkLvfkMEFpVhO8hrIU4QLGG4QAzkCdVAP4B/AP4Bb" - }, - { - name: "k9", - data: "gEBAP4B/AP4B/AP4B/AP4B/AKAADIf5N/IaIAJJv5LZLeIARffZNdD5JN/KLYATC65RbAGrHlJ/5P/JuYrRJfovNJf4BdAFJL/Jv5N/Jv5L1Jv5PvJv5L7Jv5PpAGpN/dv5HzAP4B/AP4B/AP4B/AP4B/ALg" - }, - { - name: "pawn", - data: "gEBAP4B/AP4B/AP4BEAA455HuY7/Hf47xAB47/PuI1xPZY7/Hf47/G9Y/zHfIATHPI9nHfYB/AOYAfHf4B/AP4B/APA=" - }, - { - name: "facerecog", - data: "gEBAP4BSLuozNH9YpTHsolXPsYfdDraZhELIZhHeLtJELY1VC4Y7HHqoXJABYdNHa5bJDrLvfHfbrPZJI7nGZpdVNJ4lRIpaznRqp1hCq55ZC6IRPd8oPjW8Y5jSr45dEJppNHcIjLHZY5ja6rrhFK45pVqI5rGI4AHHNpx3ANA=" - }, - { - name: "sleep", - data: "gEBAP4B/AP4B2ACY7/Quq95HP45/HP4APOdY7fACZfnHcaZZAL45/HP45/E7YAHCaZFZHfbh/HP45/HOoAHHf4B/AP4B/AP4BIA=" - }, - { - name: "awake", - data: "gEBAP4B/AKyb7HfIAFHPI77Ov451Hf453Hf453HdoAbHf45/Hf5HrHNY7NHNo7/HO47/HO47HHPJ1/Heo51HfoB/ALg=" - }, - { - name: "wag_h", - data: "gEBAP4B/AP4B/AP4B/AP4B/AMwADD+oAFHb4hTHMIlXHMopTHNItPAG47/WfY9tFKY9lEq49hELY7ja8YB/AP4B/AP4B/AP4B/AP4BCA" - }, - { - name: "wag_v", - data: "gEBAP4B/AP4BOafIAHHPI9xAB45vd449rFZIHLHsonJBKa7rGNo7/Hf47/Hf47/Hf47/Hf4xlBKY7hFIoHLQM4rHApK7rAB71xHOo9LHOI9HHOoB/AP4BYA=" - }, - { - name: "happy", - data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/HtInTCZrfZHa4vNABYlVKLI3PbLrzfD7qTXDLaphHMIpLAB45hIKY1pAP4B/AMA" - }, - { - name: "sad", - data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/CK4njCZ4APHcIVJBbbdTecYjZHr4fdSa4ZbEZ4lNCaY9dAB45hIKY1pAP4B/AMA" - }, - { - name: "hover", - data: "gEBAP4B/AP7NedL4fZK7ojNHeJ35DJI7vC5Y7tVMI7XHNYnNYro7hHKI7lAK47/HdoAhHPI7/Hf47/Hf4AtHPI7/Hf47/Hd45LAP4B/ANwA=" + name: "switch", + data: "gEBAP4B/AP4B/AP4B/AMgA3HPJdlVvI7/Hf47/Hf47/Hf47/Hf47/Hf4AvIPKRXAP4B/AP4B/AP4B/AJgA==" }, { name: "light", data: "gEBAP4B/APi/Na67lfACZ/nNaI9lE6o9jEbI9hD7Y7dDsJZ3D6YRJHdIJHHfaz7Hf5Z/Hf4hZHMIjFEqIVVHsY5hDpI7TEqL1jVsqlTdM55THOJvHOuY7/HfI9JHOI9HHOoBgA==" - }, - { - name: "speak", - data: "gEBAP4B/AP4BIbO4AXG+4/hAEY55HqoArHPI9PHfIAzHf47/Hf47/HeY9xHJI79Hto5NHtY5RHc45THco5VHcI3XHJpHRG7I7LEro5ZG+IB/AP4BwA==" } ]; @@ -203,164 +102,62 @@ The global variable should be declared at the start of the program and it may be adviable to use the 'status_name' format to ensure it is clear. */ -var joystickBtn = { + +var lightBtn = { primary_colour: 0x653E, - primary_icon: 'joystick', - primary_text: 'Joystick', + primary_text: 'Lights', + primary_icon: 'light', }; -var turnLeftBtn = { - primary_colour: 0x653E, - primary_text: 'Left', - primary_icon: 'left', - }; - -var turnRightBtn = { +var socketsBtn = { primary_colour: 0x33F9, - primary_text: 'Right', - primary_icon: 'right', + primary_text: 'Sockets', + primary_icon: 'switch', }; -var k9Btn = { - primary_colour: 0x653E, - primary_text: 'K9', - primary_icon: 'k9', - }; - -var dalekBtn = { - primary_colour: 0x33F9, - primary_text: 'Dalek', - primary_icon: 'dalek', - }; - -var tailHBtn = { - primary_colour: 0x653E, - primary_text: 'Wag Tail', - primary_icon: 'wag_h', - }; - -var tailVBtn = { - primary_colour: 0x33F9, - primary_text: 'Wag Tail', - primary_icon: 'wag_v', - }; - -var happyBtn = { - primary_colour: 0x653E, - primary_text: 'Speak', - primary_icon: 'happy', - }; - -var sadBtn = { - primary_colour: 0x33F9, - primary_text: 'Speak', - primary_icon: 'sad', - }; - -var speakBtn = { - primary_colour: 0x33F9, - primary_text: 'Speak', - primary_icon: 'speak', - }; - -var faceBtn = { +var lightHallBtn = { primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'facerecog', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'facerecog', - value: status_face - }; - -var chessBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'pawn', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'pawn', - value: status_chess - }; - -var irisLightBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', + primary_text: 'Hall Off', primary_icon: 'light', toggle: true, secondary_colour: 0x3F48, - secondary_text: 'On', + secondary_text: 'Hall On', secondary_icon : 'light', - value: status_iris_light + value: status_light_hall }; -var irisBtn = { +var lightStudyBtn = { primary_colour: 0xE9C7, - primary_text: 'Closed', - primary_icon: 'sleep', + primary_text: 'Study Off', + primary_icon: 'light', toggle: true, secondary_colour: 0x3F48, - secondary_text: 'Open', - secondary_icon : 'awake', - value: status_iris + secondary_text: 'Study On', + secondary_icon : 'light', + value: status_light_study +}; + +var socketTVBtn = { + primary_colour: 0xE9C7, + primary_text: 'TV Off', + primary_icon: 'switch', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'TV On', + secondary_icon : 'switch', + value: status_tv }; -var wakeBtn = { +var socketPrinterBtn = { primary_colour: 0xE9C7, - primary_text: 'Sleeping', - primary_icon: 'sleep', + primary_text: 'Printer Off', + primary_icon: 'switch', toggle: true, secondary_colour: 0x3F48, - secondary_text: 'Awake', - secondary_icon : 'awake', - value: status_wake - }; - -var hoverBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'hover', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'hover', - value: status_hover - }; - -var autoBtn = { - primary_colour: 0xE9C7, - primary_text: 'Stop', - primary_icon: 'sit', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'Move', - secondary_icon : 'walk', - value: status_auto - }; - -var micBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'mic_off', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'mic_on', - value: status_mic - }; - -var spkBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'spk_off', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'spk_on', - value: status_spk - }; + secondary_text: 'Printer On', + secondary_icon : 'switch', + value: status_printer +}; /* CONFIGURATION AREA - SCREEN DEFINITIONS @@ -372,68 +169,20 @@ the left hand side of the screen. These are defined as btn1, bt2 and bt3. The values are names from the icon array. */ -const menuScreen = { - left: k9Btn, - right: dalekBtn, -}; - -const k9MenuScreen = { - left: wakeBtn, - right: joystickBtn, - btn1: "pawn", - btn2: "wag_h", - btn3: "back" -}; - -const joystickScreen = { - left: turnLeftBtn, - right: turnRightBtn, - btn1: "forward", - btn2: "backward", - btn3: "back" -}; - -const tailScreen = { - left: tailHBtn, - right: tailVBtn, - btn3: "back" -}; - -const commsScreen = { - left: micBtn, - right: spkBtn, - btn3: "back" -}; - -const dalekMenuScreen = { - left: faceBtn, - right: speakBtn, - btn1: "hover", - btn2: "light", - btn3: "back" -}; - -const speakScreen = { - left: happyBtn, - right: sadBtn, - btn3: "back" -}; - -const irisScreen = { - left: irisBtn, - right: irisLightBtn, - btn3: "back" +const homeScreen = { + left: lightsBtn, + right: socketsBtn, }; const lightsScreen = { - left: hoverBtn, - right: spkBtn, + left: lightHallBtn, + right: lightStudyBtn, btn3: "back" }; -const chessScreen = { - left: chessBtn, - right: autoBtn, +const socketsScreen = { + left: socketTVBtn, + right: socketPrinterBtn, btn3: "back" }; @@ -478,145 +227,34 @@ inversed and the new value transmitted. /* The Home State/Page is where the application beings */ const Home = new State({ state: "Home", - screen: menuScreen, + screen: homeScreen, events: (event) => { if ((event.object == "right") && (event.status == "end")) { - return DalekMenu; + return SocketsMenu; } if ((event.object == "left") && (event.status == "end")) { - //status_auto.value = !status_auto.value; - //transmit(this.state, "auto", onOff(status_auto.value)); - //return this; - return K9Menu; + return LightsMenu; } transmit(this.state, event.object, event.status); return this; } }); -const K9Menu = new State({ - state: "K9Menu", - screen: k9MenuScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - if ((event.object == "right") && (event.status == "end")) { - return Joystick; - } - if ((event.object == "left") && (event.status == "end")) { - status_wake.value = !status_wake.value; - transmit(this.state, "auto", onOff(status_wake.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const DalekMenu = new State({ - state: "DalekMenu", - screen: dalekMenuScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - if ((event.object == "right") && (event.status == "end")) { - return Speak; - } - if ((event.object == "left") && (event.status == "end")) { - status_face.value = !status_face.value; - transmit(this.state, "face", onOff(status_face.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Speak = new State({ - state: "Speak", - screen: speakScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return DalekMenu; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Chess = new State({ - state: "Chess", - screen: chessScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return K9Menu; - } - if ((event.object == "right") && (event.status == "end")) { - status_auto.value = !status_auto.value; - transmit(this.state, "follow", onOff(status_auto.value)); - return this; - } - if ((event.object == "left") && (event.status == "end")) { - status_chess.value = !status_chess.value; - transmit(this.state, "chess", onOff(status_chess.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Tail = new State({ - state: "Tail", - screen: tailScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return K9Menu; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Iris = new State({ - state: "Iris", - screen: irisScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return DalekMenu; - } - if ((event.object == "right") && (event.status == "end")) { - status_iris_light.value = !status_iris_light.value; - transmit(this.state, "iris_light", onOff(status_iris_light.value)); - return this; - } - if ((event.object == "left") && (event.status == "end")) { - status_iris.value = !status_iris.value; - transmit(this.state, "iris_servo", onOff(status_iris.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Lights = new State({ - state: "Lights", +const LightsMenu = new State({ + state: "LightsMenu", screen: lightsScreen, events: (event) => { if ((event.object == "bottom") && (event.status == "end")) { - return DalekMenu; + return Home; } if ((event.object == "right") && (event.status == "end")) { - status_spk.value = !status_spk.value; - transmit(this.state, "iris_light", onOff(status_spk.value)); + status_light_study.value = !status_light_study.value; + transmit(this.state, "auto", onOff(status_light_study.value)); return this; } if ((event.object == "left") && (event.status == "end")) { - status_hover.value = !status_hover.value; - transmit(this.state, "hover", onOff(status_hover.value)); + status_light_hall.value = !status_light_hall.value; + transmit(this.state, "auto", onOff(status_light_hall.value)); return this; } transmit(this.state, event.object, event.status); @@ -624,42 +262,26 @@ const Lights = new State({ } }); - -/* Joystick page state */ -const Joystick = new State({ - state: "Joystick", - screen: joystickScreen, +const SocketsMenu = new State({ + state: "SocketsMenu", + screen: lightsScreen, events: (event) => { if ((event.object == "bottom") && (event.status == "end")) { - transmit("Joystick", "joystick", "off"); - return Home; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -/* Comms page state */ -const Comms = new State({ - state: "Comms", - screen: commsScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - if ((event.object == "left") && (event.status == "end")) { - status_mic.value = !status_mic.value; - transmit(this.state, "mic", onOff(status_mic.value)); - return this; + return Home; } if ((event.object == "right") && (event.status == "end")) { - status_spk.value = !status_spk.value; - transmit(this.state, "spk", onOff(status_spk.value)); + status_printer.value = !status_printer.value; + transmit(this.state, "auto", onOff(status_printer.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_tv.value = !status_tv.value; + transmit(this.state, "auto", onOff(status_tv.value)); return this; } transmit(this.state, event.object, event.status); return this; - } + } }); /* translate button status into english */ From 0b7200eda7a444030ea02124486fc3a5214e34f6 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 14:20:46 +0100 Subject: [PATCH 1040/1189] Minor README change --- apps/BLEcontroller/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index 56f1a2658..0929a9fd7 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -1,4 +1,4 @@ -# BLE Generic Controller with Joystick +# BLE Customisable Controller with Joystick A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. From 60b0fee49d230554b5c09a0e870173b194ec0b61 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 14:22:38 +0100 Subject: [PATCH 1041/1189] Change to app description --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 9ba610101..79923cab2 100644 --- a/apps.json +++ b/apps.json @@ -1772,11 +1772,11 @@ ] }, { "id": "BLEcontroller", - "name": "BLE Robot Controller with Joystick", + "name": "BLE Customisable Controller with Joystick", "shortName": "BLE Controller", "icon": "BLEcontroller.png", "version": "0.01", - "description": "A configurable controller for BLE robots, with a basic four direction joystick. Easy to customise and add your own menus.", + "description": "A configurable controller for BLE devices and robots, with a basic four direction joystick. Designed to be easy to customise so you can add your own menus.", "tags": "tool,bluetooth", "readme": "README.md", "allow_emulator":true, From 03f4f1da8bca0474b371e8bb68728479faf4d09c Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 14:27:02 +0100 Subject: [PATCH 1042/1189] Bug fix --- apps/BLEcontroller/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 1b4775ef2..96f56efce 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -170,7 +170,7 @@ are defined as btn1, bt2 and bt3. The values are names from the icon array. */ const homeScreen = { - left: lightsBtn, + left: lightBtn, right: socketsBtn, }; From b9f0907e5a1a371038f56e5a57a5d69b015bbc02 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 14:36:03 +0100 Subject: [PATCH 1043/1189] Added back icon --- apps/BLEcontroller/README.md | 2 +- apps/BLEcontroller/app.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index 0929a9fd7..d66ea9557 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -1,4 +1,4 @@ -# BLE Customisable Controller with Joystick +# BLE Customisable Controller with Joystick A A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 96f56efce..0ae900b9b 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -74,6 +74,10 @@ const icons = [ { name: "light", data: "gEBAP4B/APi/Na67lfACZ/nNaI9lE6o9jEbI9hD7Y7dDsJZ3D6YRJHdIJHHfaz7Hf5Z/Hf4hZHMIjFEqIVVHsY5hDpI7TEqL1jVsqlTdM55THOJvHOuY7/HfI9JHOI9HHOoBgA==" + }, + { + name: "back", + data: "gEBAP4B/AP4B/AKgADHPI71HP45/HP45/HP45/HP45/Hf49/Hv49/Hv49/Hv49/Hv497He4B/AP4B/AJAA==" } ]; @@ -220,7 +224,7 @@ one, then the state machine will change to that new State and redrsw the screen appropriately. To add in additional capabilities for button presses, simply add an additional 'if' statement. -For toggle buttons, the value of the sppropiate status object is +For toggle buttons, the value of the appropiate status object is inversed and the new value transmitted. */ From 9f1b61d2d9211fed78e5e405023d46fbbfcee876 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 14:41:52 +0100 Subject: [PATCH 1044/1189] Minor bug fix --- apps/BLEcontroller/README.md | 2 +- apps/BLEcontroller/app.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index d66ea9557..0929a9fd7 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -1,4 +1,4 @@ -# BLE Customisable Controller with Joystick A +# BLE Customisable Controller with Joystick A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 0ae900b9b..fc7d7dbb7 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -268,7 +268,7 @@ const LightsMenu = new State({ const SocketsMenu = new State({ state: "SocketsMenu", - screen: lightsScreen, + screen: socketsScreen, events: (event) => { if ((event.object == "bottom") && (event.status == "end")) { return Home; From e9e9bf941aca623720b7aefcb68830e0f8981b66 Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Mon, 1 Jun 2020 15:53:28 +0200 Subject: [PATCH 1045/1189] correct string position --- apps.json | 2 +- apps/metronome/ChangeLog | 1 + apps/metronome/metronome.js | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index b478a8f69..00231a835 100644 --- a/apps.json +++ b/apps.json @@ -1403,7 +1403,7 @@ "id": "metronome", "name": "Metronome", "icon": "metronome_icon.png", - "version": "0.05", + "version": "0.06", "readme": "README.md", "description": "Makes the watch blinking and vibrating with a given rate", "tags": "tool", diff --git a/apps/metronome/ChangeLog b/apps/metronome/ChangeLog index 909d6b983..894d62940 100644 --- a/apps/metronome/ChangeLog +++ b/apps/metronome/ChangeLog @@ -3,3 +3,4 @@ 0.03: Uses mean of three time intervalls to calculate bmp 0.04: App shows instructions, Widgets remain visible, color changed 0.05: Buzz intensity and beats per bar can be changed via settings-app +0.06: Correct string position diff --git a/apps/metronome/metronome.js b/apps/metronome/metronome.js index add6fee16..19509f338 100644 --- a/apps/metronome/metronome.js +++ b/apps/metronome/metronome.js @@ -56,8 +56,8 @@ function updateScreen() { } catch(err) { } - g.setFont("Vector",48); - g.drawString(Math.floor(bpm)+"bpm", 5, 60); + g.setFont("Vector",40); + g.drawString(Math.floor(bpm)+"bpm", 100, 100); } @@ -105,7 +105,7 @@ setWatch(() => { interval = setInterval(updateScreen, 60000 / bpm); g.clear(); -g.drawString('Touch the screen to set tempo.\nUse BTN1 to increase, and\nBTN3 to decrease bpm value by 1.', 15, 150); +g.drawString('Touch the screen to set tempo.\nUse BTN1 to increase, and\nBTN3 to decrease bpm value by 1.', 25, 200); Bangle.loadWidgets(); Bangle.drawWidgets(); From 615f8c8fcefc3a1d71c5f63b3be1f0659fb16e56 Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 15:18:48 +0100 Subject: [PATCH 1046/1189] Update transmitted values --- apps/BLEcontroller/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index fc7d7dbb7..fd07d73f9 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -253,12 +253,12 @@ const LightsMenu = new State({ } if ((event.object == "right") && (event.status == "end")) { status_light_study.value = !status_light_study.value; - transmit(this.state, "auto", onOff(status_light_study.value)); + transmit(this.state, "study", onOff(status_light_study.value)); return this; } if ((event.object == "left") && (event.status == "end")) { status_light_hall.value = !status_light_hall.value; - transmit(this.state, "auto", onOff(status_light_hall.value)); + transmit(this.state, "hall", onOff(status_light_hall.value)); return this; } transmit(this.state, event.object, event.status); @@ -275,12 +275,12 @@ const SocketsMenu = new State({ } if ((event.object == "right") && (event.status == "end")) { status_printer.value = !status_printer.value; - transmit(this.state, "auto", onOff(status_printer.value)); + transmit(this.state, "printer", onOff(status_printer.value)); return this; } if ((event.object == "left") && (event.status == "end")) { status_tv.value = !status_tv.value; - transmit(this.state, "auto", onOff(status_tv.value)); + transmit(this.state, "tv", onOff(status_tv.value)); return this; } transmit(this.state, event.object, event.status); From 7cf0154259994b84a9dd5944b8bb8eb42d7c258d Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 15:21:08 +0100 Subject: [PATCH 1047/1189] Adding widgets back in --- apps/BLEcontroller/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index fd07d73f9..3f18ffa1c 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -313,6 +313,7 @@ const setMyWatch = (params) => { machine = machine.events({object: params.label, status: startEnd(params.bool)}); drawScreen(machine.screen); }, params.btn, {repeat:true, edge:"both"}); + drawWidgets(); }; /* object array used to set up the watching functions From 6962fd01d66b451c986c1a8b3eb43abfd2e9f18c Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 15:24:22 +0100 Subject: [PATCH 1048/1189] Syntax error --- apps/BLEcontroller/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 3f18ffa1c..01a2c78c8 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -313,7 +313,7 @@ const setMyWatch = (params) => { machine = machine.events({object: params.label, status: startEnd(params.bool)}); drawScreen(machine.screen); }, params.btn, {repeat:true, edge:"both"}); - drawWidgets(); + Bangle.drawWidgets(); }; /* object array used to set up the watching functions From fdbf4300ef20b9060ee4d1759d52c51936d73f7b Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 15:47:00 +0100 Subject: [PATCH 1049/1189] Change transmission frequency --- apps/BLEcontroller/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 01a2c78c8..8cb611273 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -19,6 +19,7 @@ bottom_btn = false; msgNum = 0; // message number +NRF.setConnectionInterval(100) /* CONFIGURATION AREA - STATE VARIABLES declare global variables for the toggle button From 39f62c1ab7c2c018e288c724ae69fbd5f0084dca Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 15:49:19 +0100 Subject: [PATCH 1050/1189] Try once at beginning of app --- apps/BLEcontroller/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 8cb611273..7fd908d59 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -20,6 +20,8 @@ bottom_btn = false; msgNum = 0; // message number NRF.setConnectionInterval(100) +Bangle.loadWidgets() +Bangle.drawWidgets() /* CONFIGURATION AREA - STATE VARIABLES declare global variables for the toggle button @@ -314,7 +316,6 @@ const setMyWatch = (params) => { machine = machine.events({object: params.label, status: startEnd(params.bool)}); drawScreen(machine.screen); }, params.btn, {repeat:true, edge:"both"}); - Bangle.drawWidgets(); }; /* object array used to set up the watching functions From 5ca81d9bfbcc0c8351c3bc4ed2f25c186cb4fbdc Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 16:01:50 +0100 Subject: [PATCH 1051/1189] Tidy up --- apps/BLEcontroller/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 7fd908d59..6f8b70e1b 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -19,9 +19,9 @@ bottom_btn = false; msgNum = 0; // message number -NRF.setConnectionInterval(100) -Bangle.loadWidgets() -Bangle.drawWidgets() +NRF.setConnectionInterval(100); +Bangle.loadWidgets(); +Bangle.drawWidgets(); /* CONFIGURATION AREA - STATE VARIABLES declare global variables for the toggle button From e8f8703b36cb4688e2b04cddd0480c73ace3bcff Mon Sep 17 00:00:00 2001 From: hopkira Date: Mon, 1 Jun 2020 16:06:10 +0100 Subject: [PATCH 1052/1189] Cosmetic change to give gap to widgets --- apps/BLEcontroller/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 6f8b70e1b..ba172b047 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -344,7 +344,7 @@ const drawButton = (params,side) => { text = params.secondary_text; icon = drawIcon(params.secondary_icon); } - g.fillRect(0+x,24,119+x, 239); + g.fillRect(0+x,28,119+x, 239); g.setColor(0x000); g.setFont("Vector",15); g.setFontAlign(0,0.0); From d9442f2fd077eba216abda3ccd41a8e766e1c3aa Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 1 Jun 2020 17:04:55 +0100 Subject: [PATCH 1053/1189] locale: Improve handling of non-ASCII characters (fix #469) --- apps.json | 2 +- apps/locale/ChangeLog | 1 + apps/locale/locale.html | 69 ++++++++++++++++++++++++++++++++++++----- apps/locale/locales.js | 52 ++++++++++++++++++++++++------- 4 files changed, 103 insertions(+), 21 deletions(-) diff --git a/apps.json b/apps.json index 5eb039b53..f098e1351 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..8338f9f84 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: Improve handling of non-ASCII characters (fix #469) diff --git a/apps/locale/locale.html b/apps/locale/locale.html index 21bf37f29..645d6b2db 100644 --- a/apps/locale/locale.html +++ b/apps/locale/locale.html @@ -1,5 +1,6 @@ + @@ -12,7 +13,7 @@

Then click

- + + + + From fa169c3bef6797980ef684dfa8704f0e0a40e840 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 11 Jun 2020 15:06:22 +0100 Subject: [PATCH 1137/1189] revert accidental commits --- .vscode/launch.json | 17 -- apps.json | 30 +- apps/dalekcontrol/README.md | 50 ---- apps/dalekcontrol/app-icon.js | 1 - apps/dalekcontrol/app.js | 450 ---------------------------- apps/dalekcontrol/dalek_icon_30.png | Bin 7042 -> 0 bytes apps/k9control/README.md | 50 ---- apps/k9control/app-icon.js | 1 - apps/k9control/app.js | 446 --------------------------- apps/k9control/k9_icon_30.png | Bin 4779 -> 0 bytes 10 files changed, 1 insertion(+), 1044 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 apps/dalekcontrol/README.md delete mode 100644 apps/dalekcontrol/app-icon.js delete mode 100644 apps/dalekcontrol/app.js delete mode 100644 apps/dalekcontrol/dalek_icon_30.png delete mode 100644 apps/k9control/README.md delete mode 100644 apps/k9control/app-icon.js delete mode 100644 apps/k9control/app.js delete mode 100644 apps/k9control/k9_icon_30.png diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 771354e66..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Launch Program", - "skipFiles": [ - "/**" - ], - "program": "${workspaceFolder}/http-server" - } - ] -} \ No newline at end of file diff --git a/apps.json b/apps.json index 5e4a2b4a5..7aaf66a13 100644 --- a/apps.json +++ b/apps.json @@ -1811,35 +1811,7 @@ { "name": "BLEcontroller.app.js", "url": "app.js" }, { "name": "BLEcontroller.img", "url": "app-icon.js", "evaluate": true } ] - }, - { "id": "k9control", - "name": "K9 BLE Controller with Joystick", - "shortName": "K9 Controller", - "icon": "k9_icon_30.png", - "version": "0.01", - "description": "My private K9 BLE controller", - "tags": "tool,bluetooth", - "readme": "README.md", - "allow_emulator":false, - "storage": [ - { "name": "k9control.app.js", "url": "app.js" }, - { "name": "k9control.img", "url": "app-icon.js", "evaluate": true } - ] - }, - { "id": "dalekcontrol", - "name": "Dalek BLE Controller with Joystick", - "shortName": "Dalek Controller", - "icon": "dalek_icon_30.png", - "version": "0.01", - "description": "My private Dalek BLE controller", - "tags": "tool,bluetooth", - "readme": "README.md", - "allow_emulator":false, - "storage": [ - { "name": "dalekcontrol.app.js", "url": "app.js" }, - { "name": "dalekcontrol.img", "url": "app-icon.js", "evaluate": true } - ] - }, + }, { "id": "widviz", "name": "Widget Visibility Widget", "shortName":"Viz Widget", diff --git a/apps/dalekcontrol/README.md b/apps/dalekcontrol/README.md deleted file mode 100644 index 3ffe7f514..000000000 --- a/apps/dalekcontrol/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Dalek Controller - -A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. - -Amaze your friends by controlling your robot, your house or any other BLE device from your watch! - - - -To keep the messages small, commands are sent from the Controller to the BLE target in a text string. This is made up of a comma delimited string of the following elements: -* message number (up to the least significant four digits) -* screen name (up to four characters) -* object name (up to four characters) -* value/status (up to four characters) - -The combination of these variables will uniquely identify the status change requested from the watch to the target device that can then be programmed to respond appropriately. - -Gordon Williams' EspruinoHub is an excellent way to transform thse BLE advertisements into MQTT messages for further processing. They can be subscribed to via the following MQTT topic (change the watchaddress, to the MAC address of your Bangle.js) -/ble/advertise/wa:tc:ha:dd:re:ss/espruino/# - -## Usage - -The application can be configured at will by changing the definitions of the screens, events, icons and buttons. - -Most changes are possible via data, rather than code change. - -## Features - -The default package contains three configurations: -* a simple home light and sockets controller UI (app.js) -* a robot controller UI with joystick (app-joy.js) -* a simple static assistant controller (app-ex2.js) - -You can try out the other configurations by deleting app.js and renaming the file you want to try as app.js. - -I have tested out the application to as many as eight screens without problems, but four screens are usually enough for most situations. - -## Controls - -The controls will vary by screen, but I suggest a convention of using BTN3 (the bottom button) for moving backwards up the menu stack. - -I have used the convention of red/green for buttons that are switches and blue buttons that provide single function operation (such as navigating a menu or executing a on-off activity) - -## Requests - -In the first instance, please consult my blog post on this application [here](https://k9-build.blogspot.com/2020/05/controlling-k9-using-bluetooth-ble-from.html) - -## Creator - -Richard Hopkins, FIET CEng -May 2020 diff --git a/apps/dalekcontrol/app-icon.js b/apps/dalekcontrol/app-icon.js deleted file mode 100644 index b228e290b..000000000 --- a/apps/dalekcontrol/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -E.toArrayBuffer(atob("Hh6EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIAAAAAAAAAAAAAAAACIiIiIAAAAAAAACIgAAIiICICIiAAAiIAACIiAiIiAgAgIiIgIiIAAAIgIiIiAAACIiIiAiAAAAAiIiIiAAACIiIiIgAAAAACIiIiAgAAIiIiIAAAAAAiIiIiICIgIiIiIgAAAAAiIiIiIgAiIiIiIgAAAAAiIiIiIiIiIiIiIgAAAAAiACIAAAAAACIAIgAAAAAgAAIAAAAAAAIAAgAAAAIiIiIiIiIiIiIiIiAAAAIiIiIiIiIiIiIiIiAAAAAAAAIAAAAAAAIAAAAAAAIAAAIAAAAAAAIAACAAAAIAAAIAAAAAAAIAACAAACIiIiIiIiIiIiIiIiIAACIAACIAAAAAACIAACIAAAIAAAIAAAAAAAIAACAAACIAACIAAAAAACIAACIAAiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) diff --git a/apps/dalekcontrol/app.js b/apps/dalekcontrol/app.js deleted file mode 100644 index 27e629d5d..000000000 --- a/apps/dalekcontrol/app.js +++ /dev/null @@ -1,450 +0,0 @@ -/* -========================================================== -Simple event based robot controller that enables robot -to switch into automatic or manual control modes. Behaviours -are controlled via a simple finite state machine. -In automatic mode the -robot will look after itself. In manual mode, the watch -will provide simple forward, back, left and right commands. -The messages will be transmitted to a partner BLE Espruino -using BLE -Written by Richard Hopkins, May 2020 -========================================================== -declare global variables for watch button statuses */ -top_btn = false; -middle_btn = false; -left_btn= false; // the left side of the touch screen -right_btn = false; // the right side of the touch screen -bottom_btn = false; - -msgNum = 0; // message number - -/* -CONFIGURATION AREA - STATE VARIABLES -declare global variables for the toggle button -statuses; if you add an additional toggle button -you should declare it and initiase it here */ - -var status_spk = {value: true}; -var status_face = {value: true}; -var status_iris_light = {value: false}; -var status_iris = {value: false}; -var status_hover = {value: false}; -var status_dome = {value: false}; - -/* trsnsmit message -where -s = first character of state, -o = first three character of object name -v = value of state.object -*/ - -const transmit = (state,object,status) => { - msgNum ++; - msg = { - n: msgNum.toString().slice(-4), - s: state.substr(0,4), - o: object.substr(0,4), - v: status.substr(0,4), - }; - message= msg.n + "," + msg.s + "," + msg.o + "," + msg.v; - NRF.setAdvertising({},{ - showName: false, - manufacturer: 0x0590, - manufacturerData: JSON.stringify(message)}); -}; - -/* -CONFIGURATION AREA - ICON DEFINITIONS -Retrieve 30px PNG icons from: -https://icons8.com/icon/set/speak/ios-glyphs -Create icons using: -https://www.espruino.com/Image+Converter -Use compression: true -Transparency: true -Diffusion: flat -Colours: 16bit RGB -Ouput as: Image Object -Add an additional element to the icons array -with a unique name and the data from the Image Object -*/ -const icons = [ - { - name: "back", - data: "gEBAP4B/AP4B/AKgADHPI71HP45/HP45/HP45/HP45/Hf49/Hv49/Hv49/Hv49/Hv497He4B/AP4B/AJAA==" - }, - { - name: "spk_on", - data: "gEBAP4B/AP4Bic/YAFPP4v1HrYZRVJo7ZDKp5jMJYvZHaYAHVL4LHACZrhADLBTJKI7dPLI7/Hf47/HeZBVFqZHZRJp1lAJ47LOtZTnHbIZDKLpHNAL69ZANp1tQbY5/AP4B/ANQ" - }, - { - name: "spk_off", - data: "gEBAPhB7P/o9rFKI9pFKY9tXNYZNHrZXfMaoAHPOZhNF7LdXHpKpZEJpvPDZK1ZAB49NPLo9jHdI9NHd49PHebvxEJY9NI6I7dHpaDXcKqfPHLKjZHcpTjHbIZDKa73JHa4BXGY45xe5Y7zV+o9/Hv49JHe4BEA=" - }, - { - name: "facerecog", - data: "gEBAP4BSLuozNH9YpTHsolXPsYfdDraZhELIZhHeLtJELY1VC4Y7HHqoXJABYdNHa5bJDrLvfHfbrPZJI7nGZpdVNJ4lRIpaznRqp1hCq55ZC6IRPd8oPjW8Y5jSr45dEJppNHcIjLHZY5ja6rrhFK45pVqI5rGI4AHHNpx3ANA=" - }, - { - name: "sleep", - data: "gEBAP4B/AP4B2ACY7/Quq95HP45/HP4APOdY7fACZfnHcaZZAL45/HP45/E7YAHCaZFZHfbh/HP45/HOoAHHf4B/AP4B/AP4BIA=" - }, - { - name: "awake", - data: "gEBAP4B/AKyb7HfIAFHPI77Ov451Hf453Hf453HdoAbHf45/Hf5HrHNY7NHNo7/HO47/HO47HHPJ1/Heo51HfoB/ALg=" - }, - { - name: "happy", - data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/HtInTCZrfZHa4vNABYlVKLI3PbLrzfD7qTXDLaphHMIpLAB45hIKY1pAP4B/AMA" - }, - { - name: "sad", - data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/CK4njCZ4APHcIVJBbbdTecYjZHr4fdSa4ZbEZ4lNCaY9dAB45hIKY1pAP4B/AMA" - }, - { - name: "hover", - data: "gEBAP4B/AP7NedL4fZK7ojNHeJ35DJI7vC5Y7tVMI7XHNYnNYro7hHKI7lAK47/HdoAhHPI7/Hf47/Hf4AtHPI7/Hf47/Hd45LAP4B/ANwA=" - }, - { - name: "light", - data: "gEBAP4B/APi/Na67lfACZ/nNaI9lE6o9jEbI9hD7Y7dDsJZ3D6YRJHdIJHHfaz7Hf5Z/Hf4hZHMIjFEqIVVHsY5hDpI7TEqL1jVsqlTdM55THOJvHOuY7/HfI9JHOI9HHOoBgA==" - }, - { - name: "speak", - data: "gEBAP4B/AP4BIbO4AXG+4/hAEY55HqoArHPI9PHfIAzHf47/Hf47/HeY9xHJI79Hto5NHtY5RHc45THco5VHcI3XHJpHRG7I7LEro5ZG+IB/AP4BwA==" - }, - { - name: "dalek", - data: "gEBAP4B/AP4B/AJMQwQBBGucIoMAkADBhFhAoZBcAAQfJhEgB45BCHYMBjGiB4ZLCK5APDFpphBC5AbEJosY0YfCG4IAEJIYdGFYR5LHJYlEAI0Y4cY8YXMOpQBFlNFlMkOZA7MKII7JOAXkE4T1UERKtFHoxJBABY5QiGiD5kANYTnCiFiWIJVOgDZCOra3FoKxFDKI7hADQ7PkEIaoIHEaKYfJAoKPFAJcIGYIJHkI7UgMY8ZFHC5rVDKIZTCDIJhBA4ILBBoYFHC4QBEBogpBjHDdsJJEAoYAHKoTxWWb5tNWZOiHZRbBHbwtLF5ynBL7wtLjHjd6oAZkHkI5JJKAAZ3TkAjJhALBsJ5K0a/KkLvfkMEFpVhO8hrIU4QLGG4QAzkCdVAP4B/AP4Bb" - } - ]; - -/* finds icon data by name in the icon array and returns an image object*/ -const drawIcon = (name) => { - for (var icon of icons) { - if (icon.name == name) { - image = { - width : 30, height : 30, bpp : 16, - transparent : 1, - buffer: require("heatshrink").decompress(atob(icon.data)) - }; - return image;} - } -}; - -/* -CONFIGURATION AREA - BUTTON DEFINITIONS -for a simple button, just define a primary colour -and an icon name from the icon array and -the text to display beneath the button -for toggle buttons, additionally provide secondary -colours, icon name and text. Also provide a reference -to a global variable for the value of the button. -The global variable should be declared at the start of -the program and it may be adviable to use the 'status_name' -format to ensure it is clear. -*/ - -var happyBtn = { - primary_colour: 0x653E, - primary_text: 'Speak', - primary_icon: 'happy', - }; - -var sadBtn = { - primary_colour: 0x33F9, - primary_text: 'Speak', - primary_icon: 'sad', - }; - -var speakBtn = { - primary_colour: 0x33F9, - primary_text: 'Speak', - primary_icon: 'speak', - }; - -var faceBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'facerecog', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'facerecog', - value: status_face - }; - -var irisLightBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'light', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'light', - value: status_iris_light - }; - -var irisBtn = { - primary_colour: 0xE9C7, - primary_text: 'Closed', - primary_icon: 'sleep', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'Open', - secondary_icon : 'awake', - value: status_iris - }; - -var hoverBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'hover', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'hover', - value: status_hover - }; - - var domeBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'dalek', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'dalek', - value: status_dome - }; - -/* -CONFIGURATION AREA - SCREEN DEFINITIONS -a screen can have a button (as defined above) -on the left and/or the right of the screen. -in adddition a screen can optionally have -an icon for each of the three buttons on -the left hand side of the screen. These -are defined as btn1, bt2 and bt3. The -values are names from the icon array. -*/ - -const menuScreen = { - left: faceBtn, - right: speakBtn, - btn1: "hover", - btn2: "light", -}; - -const speakScreen = { - left: happyBtn, - right: sadBtn, - btn3: "back" -}; - -const irisScreen = { - left: irisBtn, - right: irisLightBtn, - btn3: "back" -}; - -const lightsScreen = { - left: hoverBtn, - right: domeBtn, - btn3: "back" -}; - -/* base state definition -Each of the screens correspond to a state; -this class provides a constuctor for each -of the states -*/ -class State { - constructor(params) { - this.state = params.state; - this.events = params.events; - this.screen = params.screen; - } -} - -/* -CONFIGURATION AREA - BUTTON BEHAVIOURS/STATE TRANSITIONS -This area defines how each screen behaves. -Each screen corresponds to a different State of the -state machine. This makes it much easier to isolate -behaviours between screens. -The state value is transmitted whenever a button is pressed -to provide context (so the receiving device, knows which -button was pressed on which screen). -The screens are defined above. -The events section identifies if a particular button has been -pressed and released on the screen and an action can then be taken. -The events function receives a notification from a mySetWatch which -provides an event object that identifies which button and whether -it has been pressed down or released. Actions can then be taken. -The events function will always return a State object. -If the events function returns different State from the current -one, then the state machine will change to that new State and redrsw -the screen appropriately. -To add in additional capabilities for button presses, simply add -an additional 'if' statement. -For toggle buttons, the value of the sppropiate status object is -inversed and the new value transmitted. -*/ - -/* The Home State/Page is where the application beings */ - -const Home = new State({ - state: "DalekMenu", - screen: menuScreen, - events: (event) => { - if ((event.object == "top") && (event.status == "end")) { - return Lights; - } - if ((event.object == "middle") && (event.status == "end")) { - return Iris; - } - if ((event.object == "right") && (event.status == "end")) { - return Speak; - } - if ((event.object == "left") && (event.status == "end")) { - status_face.value = !status_face.value; - transmit(this.state, "face", onOff(status_face.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Speak = new State({ - state: "Speak", - screen: speakScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Iris = new State({ - state: "Iris", - screen: irisScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - if ((event.object == "right") && (event.status == "end")) { - status_iris_light.value = !status_iris_light.value; - transmit(this.state, "light", onOff(status_iris_light.value)); - return this; - } - if ((event.object == "left") && (event.status == "end")) { - status_iris.value = !status_iris.value; - transmit(this.state, "servo", onOff(status_iris.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Lights = new State({ - state: "Lights", - screen: lightsScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - if ((event.object == "right") && (event.status == "end")) { - status_dome.value = !status_dome.value; - transmit(this.state, "dome", onOff(status_dome.value)); - return this; - } - if ((event.object == "left") && (event.status == "end")) { - status_hover.value = !status_hover.value; - transmit(this.state, "hover", onOff(status_hover.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -/* translate button status into english */ -const startEnd = status => status ? "start" : "end"; - -/* translate status into english */ -const onOff= status => status ? "on" : "off"; - - -/* create watching functions that will change the global -button status when pressed or released -This is actuslly the hesrt of the program. When a button -is not being pressed, nothing is happening (no loops). -This makes the progrsm more battery efficient. -When a setWatch event is raised, the custom callbacks defined -here will be called. These then fired as events to the current -state/screen of the state mschine. -Some events, will result in the stste of the state machine -chsnging, which is why the screen is redrswn after each -button press. -*/ -const setMyWatch = (params) => { - setWatch(() => { - params.bool=!params.bool; - machine = machine.events({object: params.label, status: startEnd(params.bool)}); - drawScreen(machine.screen); - }, params.btn, {repeat:true, edge:"both"}); -}; - -/* object array used to set up the watching functions -*/ -const buttons = [ - {bool : bottom_btn, label : "bottom",btn : BTN3}, - {bool : middle_btn, label : "middle",btn : BTN2}, - {bool : top_btn, label : "top",btn : BTN1}, - {bool : left_btn, label : "left",btn : BTN4}, - {bool : right_btn, label : "right",btn : BTN5} - ]; - -/* set up watchers for buttons */ -for (var button of buttons) - {setMyWatch(button);} - -/* Draw various kinds of buttons */ -const drawButton = (params,side) => { - g.setFontAlign(0,1); - icon = drawIcon(params.primary_icon); - text = params.primary_text; - g.setColor(params.primary_colour); - const x = (side == "left") ? 0 : 120; - if ((params.toggle) && (params.value.value)) { - g.setColor(params.secondary_colour); - text = params.secondary_text; - icon = drawIcon(params.secondary_icon); - } - g.fillRect(0+x,24,119+x, 239); - g.setColor(0x000); - g.setFont("Vector",15); - g.setFontAlign(0,0.0); - g.drawString(text,60+x,160); - options = {rotate: 0, scale:2}; - g.drawImage(icon,x+60,120,options); -}; - -/* Draw the pages corresponding to the states */ -const drawScreen = (params) => { - drawButton(params.left,'left'); - drawButton(params.right,'right'); - g.setColor(0x000); - if (params.btn1) {g.drawImage(drawIcon(params.btn1),210,40);} - if (params.btn2) {g.drawImage(drawIcon(params.btn2),210,125);} - if (params.btn3) {g.drawImage(drawIcon(params.btn3),210,195);} -}; - -machine = Home; // instantiate the state machine at Home -Bangle.drawWidgets(); // draw active widgets -drawScreen(machine.screen); // draw the screen diff --git a/apps/dalekcontrol/dalek_icon_30.png b/apps/dalekcontrol/dalek_icon_30.png deleted file mode 100644 index b59750e9d716d2f67290004367bb3a746f9e6f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7042 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 - -To keep the messages small, commands are sent from the Controller to the BLE target in a text string. This is made up of a comma delimited string of the following elements: -* message number (up to the least significant four digits) -* screen name (up to four characters) -* object name (up to four characters) -* value/status (up to four characters) - -The combination of these variables will uniquely identify the status change requested from the watch to the target device that can then be programmed to respond appropriately. - -Gordon Williams' EspruinoHub is an excellent way to transform thse BLE advertisements into MQTT messages for further processing. They can be subscribed to via the following MQTT topic (change the watchaddress, to the MAC address of your Bangle.js) -/ble/advertise/wa:tc:ha:dd:re:ss/espruino/# - -## Usage - -The application can be configured at will by changing the definitions of the screens, events, icons and buttons. - -Most changes are possible via data, rather than code change. - -## Features - -The default package contains three configurations: -* a simple home light and sockets controller UI (app.js) -* a robot controller UI with joystick (app-joy.js) -* a simple static assistant controller (app-ex2.js) - -You can try out the other configurations by deleting app.js and renaming the file you want to try as app.js. - -I have tested out the application to as many as eight screens without problems, but four screens are usually enough for most situations. - -## Controls - -The controls will vary by screen, but I suggest a convention of using BTN3 (the bottom button) for moving backwards up the menu stack. - -I have used the convention of red/green for buttons that are switches and blue buttons that provide single function operation (such as navigating a menu or executing a on-off activity) - -## Requests - -In the first instance, please consult my blog post on this application [here](https://k9-build.blogspot.com/2020/05/controlling-k9-using-bluetooth-ble-from.html) - -## Creator - -Richard Hopkins, FIET CEng -May 2020 diff --git a/apps/k9control/app-icon.js b/apps/k9control/app-icon.js deleted file mode 100644 index 55d7fb3cc..000000000 --- a/apps/k9control/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -E.toArrayBuffer(atob("JyeEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiAAAAAAAAAAAAAAAAAAAAAAAAAiAAAAAAAAAAAAAAAAAAAAACIiIiAAAAAAAAAAAAAAAAAAAAACIiIgAAAAIAAAAAAAAAAAAAAAAiIiIiIAAAAiAAAAAAAAAAAAAAAiIiIiIAAAACIiAAAAAAAAAAAAAiIiIiIAAAAAAiIgAAAiIiIiIgAiIiIiIiAAAAAAIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIgAAAAAAIiIiIiIiIiIiIiIiIiIiAAAAAAIiIiIiIiIiIiIgAiIiIgAAAAACIiIiIiIiIiIiIAACIiIAAAAAAiIiIiIiIiIiIiAAAAAAAAAAAAIiIiIiIiIiIiIiAAAAAAAAAAACIiIiIiIiIiIiIiAAAAAAAAAAACIiIiIiIiIiIiIiAAAAAAAAAAACIiIiIiIiIiIiIiAAAAAAAAAAAiIiIiIiIiIiIiIiAAAAAAAAAAAiIiIiIiIiIiIiIiIAAAAAAAAAAiIiIiIiIiIiIiIiIAAAAAAAAAIiIiIiIiIiIiIiIiIAAAAAAAAAIiIiIiIiIiIiIiIiIgAAAAAAACIiIiIiIiIiIiIiIiIgAAAAAAACIiIiIiIiIiIiIiIiIiAAAAAAAAACIiIiIiIiIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) diff --git a/apps/k9control/app.js b/apps/k9control/app.js deleted file mode 100644 index 0735aeee6..000000000 --- a/apps/k9control/app.js +++ /dev/null @@ -1,446 +0,0 @@ -/* -========================================================== -Simple event based robot controller that enables robot -to switch into automatic or manual control modes. Behaviours -are controlled via a simple finite state machine. -In automatic mode the -robot will look after itself. In manual mode, the watch -will provide simple forward, back, left and right commands. -The messages will be transmitted to a partner BLE Espruino -using BLE -Written by Richard Hopkins, May 2020 -========================================================== -declare global variables for watch button statuses */ -top_btn = false; -middle_btn = false; -left_btn= false; // the left side of the touch screen -right_btn = false; // the right side of the touch screen -bottom_btn = false; - -msgNum = 0; // message number - -NRF.setConnectionInterval(100); -Bangle.loadWidgets(); -Bangle.drawWidgets(); -/* -CONFIGURATION AREA - STATE VARIABLES -declare global variables for the toggle button -statuses; if you add an additional toggle button -you should declare it and initiase it here */ - -var status_auto = {value: false}; -var status_chess = {value: false}; -var status_wake = {value: false}; - -/* trsnsmit message -where -s = first character of state, -o = first three character of object name -v = value of state.object -*/ - -const transmit = (state,object,status) => { - msgNum ++; - msg = { - n: msgNum.toString().slice(-4), - s: state.substr(0,4), - o: object.substr(0,4), - v: status.substr(0,4), - }; - message= msg.n + "," + msg.s + "," + msg.o + "," + msg.v; - NRF.setAdvertising({},{ - showName: false, - manufacturer: 0x0590, - manufacturerData: JSON.stringify(message)}); -}; - -/* -CONFIGURATION AREA - ICON DEFINITIONS -Retrieve 30px PNG icons from: -https://icons8.com/icon/set/speak/ios-glyphs -Create icons using: -https://www.espruino.com/Image+Converter -Use compression: true -Transparency: true -Diffusion: flat -Colours: 16bit RGB -Ouput as: Image Object -Add an additional element to the icons array -with a unique name and the data from the Image Object -*/ -const icons = [ - { - name: "walk", - data: "gEBAP4B/ALyh7b/YALHfY9tACY55HfYdNHto7pHpIbXbL5fXAD6VlHuYAjHf47/Hf47tHK47LDa45zHc4NHHeILJHeonTO9o9rHf47/eOoB/ANg=" - }, - { - name: "sit", - data: "gEBAP4B/AP4BacO4ANHPI/rACp1/Hf49rGtI5/He7n3ACY55HcYAZHf45/Hf45rHe4XHGbI7/Va47zZZrpbHfbtXD5Y/vHcYB/AP4BmA" - }, - { - name: "joystick", - data: "gEBAP4B/AP4BMavIALHPI9vHf47/eP45vHpY5xHo451Hf47/FuYAHHNItHABa33AP6xpAD455HqY7/Hf47/Hd49pHKIB/AP4B/AMwA==" - }, - { - name: "left", - data: "gEBAP4B/AP4BKa9ojHAC5pfHJKDTUsYdZHb6ZfO+I9dABabdLbIBdHf473PP47NJdY7/ePIB/RJop5Ys7t/AP6PvD7o7fP8Y1zTZoHPf/4B/AP4B+A==" - }, - { - name: "right", - data: "gEBAP4B/AP4BKa+oAXDo45hCaqFbUbLBfbbo7bHMojTR7Y5LHa51ZALo75Ov47/FeY77AP4B5WdbF3dv4B/R94fdHb5/jGuabNA57//AP4B/APw=" - }, - { - name: "forward", - data: "gEBAP4B/AKSX5avIALHPI9tACY55HsoAbHPI9fHfZFVGMo7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf49XHOIB/ALw=" - }, - { - name: "backward", - data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/HfIAfHf491W/L15HMo9THNI9PHNo9LHOI9HHOoB/ALg=" - }, - { - name: "back", - data: "gEBAP4B/AP4B/AKgADHPI71HP45/HP45/HP45/HP45/Hf49/Hv49/Hv49/Hv49/Hv497He4B/AP4B/AJAA==" - }, - { - name: "mic_on", - data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Hf47/Hf47/HdY9NCpp5lCb57fOdYvNeJo91HNrlvHf7tVIdY77AP4BiA=" - }, - { - name: "comms", - data: "gEBAP4B+QvbF7ABo7/He49tACI7/Hf47zHtI7jJq47lRqoAVEqY7nHsoAZGJo71HrKxfQaY7bdKo7/Hdqz5B5Y7zHK47RD55FRHao3XHKo7JG7L1NHeJTbHboB/AP4BG" - }, - { - name: "pawn", - data: "gEBAP4B/AP4B/AP4BEAA455HuY7/Hf47xAB47/PuI1xPZY7/Hf47/G9Y/zHfIATHPI9nHfYB/AOYAfHf4B/AP4B/APA=" - }, - { - name: "sleep", - data: "gEBAP4B/AP4B2ACY7/Quq95HP45/HP4APOdY7fACZfnHcaZZAL45/HP45/E7YAHCaZFZHfbh/HP45/HOoAHHf4B/AP4B/AP4BIA=" - }, - { - name: "awake", - data: "gEBAP4B/AKyb7HfIAFHPI77Ov451Hf453Hf453HdoAbHf45/Hf5HrHNY7NHNo7/HO47/HO47HHPJ1/Heo51HfoB/ALg=" - }, - { - name: "wag_h", - data: "gEBAP4B/AP4B/AP4B/AP4B/AMwADD+oAFHb4hTHMIlXHMopTHNItPAG47/WfY9tFKY9lEq49hELY7ja8YB/AP4B/AP4B/AP4B/AP4BCA" - }, - { - name: "wag_v", - data: "gEBAP4B/AP4BOafIAHHPI9xAB45vd449rFZIHLHsonJBKa7rGNo7/Hf47/Hf47/Hf47/Hf4xlBKY7hFIoHLQM4rHApK7rAB71xHOo9LHOI9HHOoB/AP4BYA=" - } - ]; - -/* finds icon data by name in the icon array and returns an image object*/ -const drawIcon = (name) => { - for (var icon of icons) { - if (icon.name == name) { - image = { - width : 30, height : 30, bpp : 16, - transparent : 1, - buffer: require("heatshrink").decompress(atob(icon.data)) - }; - return image;} - } -}; - -/* -CONFIGURATION AREA - BUTTON DEFINITIONS -for a simple button, just define a primary colour -and an icon name from the icon array and -the text to display beneath the button -for toggle buttons, additionally provide secondary -colours, icon name and text. Also provide a reference -to a global variable for the value of the button. -The global variable should be declared at the start of -the program and it may be adviable to use the 'status_name' -format to ensure it is clear. -*/ - -var joystickBtn = { - primary_colour: 0x653E, - primary_icon: 'joystick', - primary_text: 'Joystick', - }; - -var turnLeftBtn = { - primary_colour: 0x653E, - primary_text: 'Left', - primary_icon: 'left', - }; - -var turnRightBtn = { - primary_colour: 0x33F9, - primary_text: 'Right', - primary_icon: 'right', - }; - -var tailHBtn = { - primary_colour: 0x653E, - primary_text: 'Wag Tail', - primary_icon: 'wag_h', - }; - -var tailVBtn = { - primary_colour: 0x33F9, - primary_text: 'Wag Tail', - primary_icon: 'wag_v', - }; - -var chessBtn = { - primary_colour: 0xE9C7, - primary_text: 'Off', - primary_icon: 'pawn', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'On', - secondary_icon : 'pawn', - value: status_chess - }; - -var wakeBtn = { - primary_colour: 0xE9C7, - primary_text: 'Sleeping', - primary_icon: 'sleep', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'Awake', - secondary_icon : 'awake', - value: status_wake - }; - -var autoBtn = { - primary_colour: 0xE9C7, - primary_text: 'Stop', - primary_icon: 'sit', - toggle: true, - secondary_colour: 0x3F48, - secondary_text: 'Move', - secondary_icon : 'walk', - value: status_auto - }; - -/* -CONFIGURATION AREA - SCREEN DEFINITIONS -a screen can have a button (as defined above) -on the left and/or the right of the screen. -in adddition a screen can optionally have -an icon for each of the three buttons on -the left hand side of the screen. These -are defined as btn1, bt2 and bt3. The -values are names from the icon array. -*/ -const menuScreen = { - left: wakeBtn, - right: joystickBtn, - btn1: "pawn", - btn2: "wag_v", -}; - -const joystickScreen = { - left: turnLeftBtn, - right: turnRightBtn, - btn1: "forward", - btn2: "backward", - btn3: "back" -}; - -const tailScreen = { - left: tailHBtn, - right: tailVBtn, - btn3: "back" -}; - -const chessScreen = { - left: chessBtn, - right: autoBtn, - btn3: "back" -}; - - -/* base state definition -Each of the screens correspond to a state; -this class provides a constuctor for each -of the states -*/ -class State { - constructor(params) { - this.state = params.state; - this.events = params.events; - this.screen = params.screen; - } -} - -/* -CONFIGURATION AREA - BUTTON BEHAVIOURS/STATE TRANSITIONS -This area defines how each screen behaves. -Each screen corresponds to a different State of the -state machine. This makes it much easier to isolate -behaviours between screens. -The state value is transmitted whenever a button is pressed -to provide context (so the receiving device, knows which -button was pressed on which screen). -The screens are defined above. -The events section identifies if a particular button has been -pressed and released on the screen and an action can then be taken. -The events function receives a notification from a mySetWatch which -provides an event object that identifies which button and whether -it has been pressed down or released. Actions can then be taken. -The events function will always return a State object. -If the events function returns different State from the current -one, then the state machine will change to that new State and redrsw -the screen appropriately. -To add in additional capabilities for button presses, simply add -an additional 'if' statement. -For toggle buttons, the value of the appropiate status object is -inversed and the new value transmitted. -*/ - -/* The Home State/Page is where the application beings */ - -const Home = new State({ - state: "K9Menu", - screen: menuScreen, - events: (event) => { - if ((event.object == "top") && (event.status == "end")) { - return Chess; - } - if ((event.object == "middle") && (event.status == "end")) { - return Tail; - } - if ((event.object == "right") && (event.status == "end")) { - return Joystick; - } - if ((event.object == "left") && (event.status == "end")) { - status_wake.value = !status_wake.value; - transmit(this.state, "wake", onOff(status_wake.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Chess = new State({ - state: "Chess", - screen: chessScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - if ((event.object == "right") && (event.status == "end")) { - status_auto.value = !status_auto.value; - transmit(this.state, "follow", onOff(status_auto.value)); - return this; - } - if ((event.object == "left") && (event.status == "end")) { - status_chess.value = !status_chess.value; - transmit(this.state, "chess", onOff(status_chess.value)); - return this; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -const Tail = new State({ - state: "Tail", - screen: tailScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - return Home; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -/* Joystick page state */ -const Joystick = new State({ - state: "Joystick", - screen: joystickScreen, - events: (event) => { - if ((event.object == "bottom") && (event.status == "end")) { - transmit("Joystick", "joystick", "off"); - return Home; - } - transmit(this.state, event.object, event.status); - return this; - } -}); - -/* translate button status into english */ -const startEnd = status => status ? "start" : "end"; - -/* translate status into english */ -const onOff= status => status ? "on" : "off"; - - -/* create watching functions that will change the global -button status when pressed or released -This is actuslly the hesrt of the program. When a button -is not being pressed, nothing is happening (no loops). -This makes the progrsm more battery efficient. -When a setWatch event is raised, the custom callbacks defined -here will be called. These then fired as events to the current -state/screen of the state mschine. -Some events, will result in the stste of the state machine -chsnging, which is why the screen is redrswn after each -button press. -*/ -const setMyWatch = (params) => { - setWatch(() => { - params.bool=!params.bool; - machine = machine.events({object: params.label, status: startEnd(params.bool)}); - drawScreen(machine.screen); - }, params.btn, {repeat:true, edge:"both"}); -}; - -/* object array used to set up the watching functions -*/ -const buttons = [ - {bool : bottom_btn, label : "bottom",btn : BTN3}, - {bool : middle_btn, label : "middle",btn : BTN2}, - {bool : top_btn, label : "top",btn : BTN1}, - {bool : left_btn, label : "left",btn : BTN4}, - {bool : right_btn, label : "right",btn : BTN5} - ]; - -/* set up watchers for buttons */ -for (var button of buttons) - {setMyWatch(button);} - -/* Draw various kinds of buttons */ -const drawButton = (params,side) => { - g.setFontAlign(0,1); - icon = drawIcon(params.primary_icon); - text = params.primary_text; - g.setColor(params.primary_colour); - const x = (side == "left") ? 0 : 120; - if ((params.toggle) && (params.value.value)) { - g.setColor(params.secondary_colour); - text = params.secondary_text; - icon = drawIcon(params.secondary_icon); - } - g.fillRect(0+x,28,119+x, 239); - g.setColor(0x000); - g.setFont("Vector",15); - g.setFontAlign(0,0.0); - g.drawString(text,60+x,160); - options = {rotate: 0, scale:2}; - g.drawImage(icon,x+60,120,options); -}; - -/* Draw the pages corresponding to the states */ -const drawScreen = (params) => { - drawButton(params.left,'left'); - drawButton(params.right,'right'); - g.setColor(0x000); - if (params.btn1) {g.drawImage(drawIcon(params.btn1),210,40);} - if (params.btn2) {g.drawImage(drawIcon(params.btn2),210,125);} - if (params.btn3) {g.drawImage(drawIcon(params.btn3),210,195);} -}; - -machine = Home; // instantiate the state machine at Home -Bangle.drawWidgets(); // draw active widgets -drawScreen(machine.screen); // draw the screen diff --git a/apps/k9control/k9_icon_30.png b/apps/k9control/k9_icon_30.png deleted file mode 100644 index f8ecae2b85dc24a11aaa4cb4e0dedba20c92e5cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4779 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 Z9FxZ=hg`FO|9t`gll|tDyZT2@{R^8<=kNdk From 1658b5f035f9141d0a226b6763e900c5404c1589 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 12 Jun 2020 15:10:08 +0100 Subject: [PATCH 1138/1189] new pixels --- apps.json | 2 +- apps/about/ChangeLog | 1 + apps/about/app.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7aaf66a13..a09aa6c6b 100644 --- a/apps.json +++ b/apps.json @@ -53,7 +53,7 @@ { "id": "about", "name": "About", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers", "tags": "tool,system", "allow_emulator":true, diff --git a/apps/about/ChangeLog b/apps/about/ChangeLog index 16aea0610..2a050c91e 100644 --- a/apps/about/ChangeLog +++ b/apps/about/ChangeLog @@ -3,3 +3,4 @@ 0.03: Actual pixels as of 5 Mar 2020 0.04: Actual pixels as of 9 Mar 2020 0.05: Actual pixels as of 27 Apr 2020 +0.06: Actual pixels as of 12 Jun 2020 diff --git a/apps/about/app.js b/apps/about/app.js index 57c85563d..4b4589262 100644 --- a/apps/about/app.js +++ b/apps/about/app.js @@ -29,5 +29,5 @@ g.drawString(NRF.getAddress(),120,232); g.flip(); // Pixel chooser image -g.drawImage(require("heatshrink").decompress(atob("+FQgl+xnu8AIBwGQgHuAoN3gF/hcLgEHu943G3gHdhvdDwIBCAAV3uEAhoBBhsO90OgHgoACBh0IhP5AAQZD8Hw+GwAwXn4AECxGAh0MEAOeJAMP3+/huIDocMg1mMog8BhnsAQIBC///J4MN6HcBIOIAAPs8Hl9nM5gcB0Hg852BAIMAI4YAD6BoBIIMAKAcAvA6D7vd7xVBTYJ3B9e+hAgEMAIBBAA29BIePwCGBYILECO4Y+BCIXMsEAAIOZyGZzx3Dh/A57nCRgUA5vA5p3CFAPuAAOQd4J3BewR2DPAzvCh//d4j/Bd4xVCgFFAYPuO4sAiBHCeAMAhBvBtOAhi5Bd4J3Dd4f7/7vDh4TBOoKeDgGdO4n8JoIvB+cQh/w/kNd4fodoXJhLvCKYJ4Dhe7AYJXFwBHBUAhBCAIMN6DvDeAPgqFQd453DAAcI/APC5ns4AKCdgQAD//wUwMMhhgBO4Nmd4xED57vD+EwFgKTCYoON/+v////OZwGXgF55vQCATaBEQRxB6Hw7EILwZIEO4YACKYlFoB3CHIZ2CAIJHBEAToCMwLvBAArvCAAnA4HP/8MOoIBBB4OQHIIiChn8/h3CeYQACFoMN7v6/jvDDAN+BwJ3DYIoKBh/YewfACQhdB/7vBDYwAJgMRBpavDAAfpeQp3D+B1CO4bvCYYfP4BKDmAcDh3ud4Wt7vdDgONwF8O4Q8Bh5jCEoOPgHf/53CGgMAoAFBbgP/CgJZEAIYAB5HIbxRCBAYULhZfBAAMA/GA/47Bd44ABh4CBg1mg8A3YAB3vtO4cMWxvG5vdZYWIw8AvPQA4SOCmADBEoMNho1CO4VQBYRABPAIoC44BEH4SIBAYJEFo4xCO4e7MITLC+GANYRwC5/M/nPMhp3BwAJGWIQ7Dgczt1pzIHCa4IABhpkBOgQACD4ZRCs1m4AyEJgJOEAA8MXYYZDgEEvoRFd4TwBO5IAJ5nAFAMNTYZEBGgRiD7p0CO4nM43JmZABAIICBAAOAHIMCkEgkQgD3cOAgVsAQOwGQLeBhPpz2QJZEO8AoCd4R5CdwcNAQkAqtVWgP/+H//5iCxDbBMgoABEYIlCO4YVBwHgG4TAB18P+AnBd4hVBd4VAgn/eIYAGX4Ww30GGwZqGz3pGgYMGJAOIwC0CWoYAD7vdLAnQNYK2COAZ1BbgpqBwHMbYTvEAAR3B0AEBg93DQIdEhUAxDPBdoNEAAIMC+HA+EM5fMuAiC8DvCu4IBb4zvBO4/uIAfQKAJ3Gh7sC6/X7ogBUIL0BCwJ3HDwR3DA4K4CAQJ3GKAJrBCoZuBAIMK1Wg4eAhwRB91AdpA/BdwQAB2BhCO4cHc5D8DPoIrBQ4LvM6BWBAQILCwB9BO4P//7vI5nMd4fAeILvB6A2BAIQ5BgDwCAAkKBAXAxDdCAAIPET4K3DLwQAB3wmBOQJqCu1gd4QAGHQYADRYocB+APEhoxChPJG4TlFAA53BzOZBY/wAAIsDhTwDXwbvFO5LvHxbvEdwUM5l2egZqCAAIIBhxnCNQdwuDHBCgg1JeAPgcYPwAQIXEhOQAgXu92QAAIdGJYPg+ArCcoIBBhgpBMoiCBO4IVBDAIcChYRFLISHDAwN3NIMM/93CgmIOwJtBh3uAIPuNQZ3BLwgiBSYuIAIOA5MO72Ox/vxOM7jIBLgMJhJ3EzJ3DsC7CJ4SyCGYvAAAKJEI4PMAAQLB7yQDgGJwADBAQTuBWgSDD7n5HQJrDwB2BABQMBhiBBA4Xgh///4FBcgMA/HwBgTvF1GKxGoO4gAByGZAYNmAQLhGAAwNFh0PboUNxoDC95fBB4UIzEAh/wE4otGO4Pt9p3Bd4I3Hf4TlD5x9DAAKxBGYTvDbAQPBuEGAoLvBAIMJGgMPXATuBA4LuBJALoFXYIkCeAYEDWIICBhMN7oIBdwIIBCAbwBh8P4AaBEQUNLwYIDd4bIBh/PAARlBLgVgDAXM5yvBy7kCAAbvCAAdng9gu0GqCWCAAnwDgyJBcIf/LgYnGSQYEDg2AzuNV4bvENoIRBh/MUAwAG73u6DQBMwIAC/4/BcgaQDhwtBy8A3ewEAjvBAAdQgoCEhfu9cOY4RcCJAIWDeAQMCQoJ1Bd4OAhkHS4IMBC4Z3CxMNxo6GRwvwd4QAJBYPt7qsCAAPgOQLvJAAeXhYdCZYIBBKYOAAIIwI3yMB6CoBd4UDgbvDO44gBPIQ+BW4YADD4TvBOoI2FKA0A0AABAwfu9oOFOwPgAQLgBDoqwBAQIJFO5QACJIP/JQIDC+AVCO4LrBdgjuE24uB/7uFd4nwQob0DxEN7uIVxJ3E1R3Bh0ONoZ+E93gAIIPCVQ7fDgENAwRhC8AWBE4LvNAAXdaQsAmAHEO4QABhOZyB6BxB3BIg3QH4PQ/GIEIIAGQIMPTQMAhTuB1DaE9xNCAQTvCLgQACyDcDAAWIFARbD3ew9ycEKILvCABkMAAMAgZKCAAYlBHog8BAArqDO4mPx5bBuCTDCYWfh/P6AeFNgVwg7FEaITvC4BIB4B3HMgXdEwP/VwyCBO4QpB8A4GABiUCACB2COoIBCxH4wEM28A5hYCgEGszvC6F3NojKBuF3O4g+DPQPAAAWQ/7GB5nMH48D+AsCAAZDBF4YFCP4OAwD4GJgQCBhkJBYg8BBQJeBCgoABBAQCBNgIABd4UL5dwBASZQxGAKQcNAgPuQgJuBhnAz8A/kM553GFwMwO4PPhYfFTYjvBhAwBfAQABuA/GVAKKCTgxdR/GI+EM3gXCSIZeBg8Au7vEO4vQJgIAB+BTB8DvI//8FQLzBFYPL5YDBKQvQd5Z3FYoUPO4ZUBCQOf/5YDVoIFDIwNw+CUHBgQADEAOIUQnHg9wg+8714zUQCYbvBO4pDFXwRPBd4UOfwIzB5e7U4gAMO4R4BA4S4HhgiBO452DRQcP54ECyEJzJ3DkYXDGIIABRQTvCVoI0EhvcZghFCu4QBhswJQ7rBBAp3E3cL2AxBCIr0EABJjCKASKDO4q7ChwTC8DvDhMJPIIJBh0AnpUDxGAd4kAdwJ3DzIYBhu9OwbvDAAXfEoKTCcI8LAYU83gEC2B4BCoP85ns4Z6BO5UP/5lCAAz+DF4kPOoIBBC4rtCLwMO8EAgchd4w6JzwYBhHdYoibBaoO72He7qbCJwxKEgcAQgZ3D5//53Onk8O4YiBAIO62DvIKQMJKIMIZoa8D+AABR4X/O4jvDO4PHyEQu0GcYT0EAAPN82A1bvDAAaTBg2WywID6ENJ4TvEIYYAIOwIWBd4PO9x3BhvQUwMBgIRB1WgCwXuEZYABg4EDHYI9CXAK6FLQcOO4IFBsACBGoMRgGHO4mJO4IAChkKyENYgTvCAAWN77GHhh5BhnMPoQEDBAnM5jvB4YIBFQUQ+EQd4vgV4LuDAAI0F6DUDO44aDzOZCwZ3Cd4YzBAILvBw+HO4OKO4nA1WQ4GwFYMGBIML3YDBJwYAC/53CgEOZxoAFO4MPgPxSwIAE93gSIQACqsFqEMF4MLeAqPDW4QAJxyWFO4YJBhAUGhZoBhOQhANCd4W/l51DyGQzILBG4LgBAAp/CO5wcBSoJcDEIJfBhn8gH5bgNA+FAQAo0DboMO/zwCAANwg7/DTobcCAIPBH4uwhbeCAIIGBBgYgDboOy+WwcQR0BPAJ3F6BGD5gyBLoPM5nPNYhbFHAQAC953DhGIgGZNAMPFwJ3FJgYOBC4X/PAMHAAQOCg/ud4UMAAYMCzOIwB3CEwWwO4oABJQbvFAAg3BHAPgFIKpDO4TgB//5RYIABjUAhUQeAYABxAeC7qWDAALvCAAfAK4Z2DAAIIFg93d4gGBAgSVBO4sJQQLvH2EIBwPYAQOqVoYOBXAICDbI5YDO4cJzOZzjPEKYXQO4PMCQI/BLYorIABGQhp3ChwbDdwRRCd4PPCYLvHO4rvHhp6CZwSnD/7aBh6/EZYoAIhx9CAAQoCO4UHgzvBOCIbCAAaiBI4Xg8AUG2DvC4HwO4bzB34MBhI3BhZxBd4YGBDoTvCu7UCIRHdhoABNgYCBhhvFBQPMd4gAChqRBg9gMgUPdoYBDfwIaExAABZgLvDAIUOhIBBQAMJAYJ3D93Ah7RDAAO7+ARBEQgADBAbvBAoPuO48OW4R2FAAZ2GCoPOEAMLX4gDCNYS3B+Hw/8AuAIBAQScBDQQBBG4SoBF4OQAALvDO4ZQCd4eZOwbDCd4WZwEPGwQAL7p3BhOQDALMBQQPgNY/bO4R4DCAXx/DOGAAZnBAAMPd4JCBg4ABTgo4BAIPuEwXteAhlDJgOQd4UL3YMC/PwAgW52EJ/grDh//O4IpDeQ0A5iLBGIOwc4ZBB5hsChM3eoJFCO4cOVYX/iAkDEQN3OgKJDuCmBd4IAFO4buDEoImCW4QARd4x3D5nMO4QKBFIcAhGIAodVDwQfB7sN6CLBwH/JgUJMIML7zaCMoYACiMfF4PwX4OQuFwdgZ3B6BgBeAMAd4oRB3cLVgLFFhoEBha7Ch8PhAABAgJ4G+xPCd4vHvjBBVIZ5Ed4gABSoQxChsICQKgDhOnVw4iCT4hQBO4TvDMYR3DdQVwBIR3ChcLPALvDHwXAFQQSCABXwPoP/sBCHO4SMCwBxEhAFB5ncDYIsMAA5CD8DCBAQOZ5nMRYTvHAoPdH4UPdgIBDSAQACJgMIGYzvDdoQADBweZzMAsx3CYAZIBIofAZgoMBwBKB6AMELAQCBIIJ3OAAmZ/6YDIQNwg7vBO4buBABewAAK+DGh4AEz3pegZtBGwLyC4C1DOwj/DO5BYBhOQ3JCBh7LBgHuAAMA5vgvI9HVAKpCABDkBO4ztDgEEdwYAJd4TqDgwFEO4sP95ABO4TiBbYp4EKoncgEKAIPdRoMJCoJCDbYQjBDQPA8Fw0BQLAYyYBQJT5DCAISE+DVBAQTvHsFgZQ2Zd45TCAAeIBAXg9wCBBobvC0Gg6HMfAOQDQg9Cd4p3B2BlFzEzmEP/4BBBQbEDAAcPO4kHboMGNAoQCwATEdAcIdwMGAwYWDhvLD4sOeoMHAwWJwDvIO4JxBeALvB5jJKABf4RAOImCNBKoVQAQOOG4YACQgjvBHYIGCHCTvFh8fRwRaBAA53DhA/COwJ4GAAULhy7BhkDBo8NJwYAHxAqBO4hqBMwMI9HoeYZBC5kM4DvEZ4XAEIMHu+Zh5iB3ew2HP5nAdAbwBAocP+J3ChItCOIYtCAoYOBgHgOwUMdYIADBIOw8Fw6GQLwIAG6GZzLvKFYJ6Bd4arC7qRCO4cM5gABd4XQ8DvDCARKC+C8BAgP//4GBABEBiJ3BqAcCuF3O4l3AwgAF4AABIQJ3Ch7wDyYIB1MK7gOCYwOQDgcMNYP/NwQMCyDtBBAQHBhv9/p3FOwTZBXQcJx3ugF3uEHvKnDO4LvDdQYADL4kP81wdA14KQmwcoq3CAQP8BYfweATvCyGQ6EMI4J3Bd5UAhQEDxEIdoOgO4MPDQJ3GMIZEF8BXCJQR3EGpIAFh/g8AtCLwQlBHoIgCAQbwFPQcAggLEd4SUB6ARBuF96EAhML3YABDYMJCwQwCNYWAAQJVB7vw/oaBO4Y0B5iuD4+Qhx3Kh4DCWoIGBh7tCAgIUE+HuAYJ3D/8A7iTDhgeCegQAEBIdEoBoB9IIDO4PcDQNwuDvD2CaC4HACALuEd4iRB7vzO4JTBg5JCeATJBhl5d4wEBgf/+RwBaoIMBAYQAHhwLBd4YACqHwAILlFAILyHPAUEAAIkBTISDEAAJ3CC4Z3GABLqBhvd7ruBxEHu65C5kOKILuBLgQ3CNoILB+Hw/7iChnsFIkNhsMHoUOCAJ3BegQABgtVNQwnBAYMLWYIADNgVAOwNAd4UN5pfFKwR3GgEJgBkBLIX/VoKoCXQgAHB4QAFOAPwLYIBBO4QDBAIIjBSIPMDYxyDhaCBb4zvJ9wAE2C4CO4KlEO4IqBXQUAtvM5wdBO4O7fggTBCgJJCM5ByEhjjEAA4KBBg4XCh//UoRsBNoXdJwWw2HQ2G9BAIYBhcJYYIFBD4TRCAAiWDO4sAyEA93gAIJ3FAA94vEO70AzOQCoLtMhkN7o2ChOQDALkCAAe72BTBKosHu93VYIAENwKOBd4R6CVYXA2GQgyLCfhTvHLYJ3P997SoNwhBgCEgXuCIn/MwYCCO4MNCwQvBAIIAG1WgSxbvCGggABCpjqCAwsIDojvGaYR3EbBEPh33uELg94cAoRF/7dFgHMd4mIwABBQoISEBAJkCCQPgcYIAJ5jvCfQvdeIQANh7vLGRbvEvOQW4KbBwGA5nACwv/xB3GAA2Qd4r1INAMAMIRrBuEHu8IxEA4HARAMHCwibDoAeDagQXBAIIRCC4h3EgxQKhi6CBIsIaIICCO4cIQYP/d44AFzJxDCIMM/IMDd4sNDIsHg6uBO4QJCeAl3AoJiBRIUO9wLBYoJOBAAOwJBPgWxA8BVIJEC7oPHwBBEAAMwaQoAQd5I+FdwLvCA4PMQIg2GbQRvBhgSCd4u/FQsOQYR3BhP8gGO2AIB/kN6HMOwR9B6AZC9ns8GIwEMO4cLeAQlCO4hNCAA64CO4QaBhgACd4sOuHnd4RdDdwYBBO4i+DRIOIJALuBSQUPIQV3DIIABhGZwB3EP4UGOIJ4BOwJfC6ENAwL6BMJA/E9x4BDIPgEwUA3YABNwQAC4GQPAOwV4QAUUI0HgxWBd4WMd4ysCuCbBDAYMBDALvDO4TvBOIJwBeAfdpxjCG4igBhLwCBQnuUoVQHARqBAARCDhn5DQIABDIUEYAZIBsABCABFwgcwmEzJ4IZFhnMR5R3FoEAyBhDd4gABhwACdwQICd4UHu9wO4JoCAAkOd4cwbogEBdwgABdwLvJIAOAs8HO5LuFhCxBuATFxBgCAASACu4ABIIQ9DO4gKCd4Pd6DnCh0NUobvCOoJ3C/53HAoj8Bd4h3BNw6BCFALvDO4d3MYMPh7uGAYUwYIPgJQgeDD4QHDZoKSGAAcKSwIAVO4QFCT4JFC9wVJd4/M/LwCSAKRFxDRBh95AwMP+AnJO4LvCMoRdDxAKBxB3R1AJHeILsBAQMNbotwEIX/AAIHBAAIdFs3M5kAK4ML3cA3buCVY/gAALQEAIMHUAIAI0AGFdwjrCAYQFC/g8BO4QAETwjvBRYetFYwADYYoACh//EIJ/BO4nP/lm9x3BABGAPYQqEFYp3CFAI2HTQOqFBLpBUQJuCO4XA4EMIAJLEh/vD5PbTgXuAATJC8BABYgwAHeoI1Bhh3DVAdAJocLeBBoDO4g0FKgMPhcz9zEKOIMMHYMMBAX8AYUHg8AxApCIwIHBAAzvEOIUAu9wO40IO5EJzIoBd4XMO4dAp8EcgPdgGwDgQ7Eh6TCuDFEhxRDd4uu3QFBokEUAPqI4SgBOoLoCNgT2CuGAvCwDF4JlBH4V3GYOOAwO7hewOIIoBJoJ3F+/3+CoByBLBJoUJ/LnFgcAmEAwmAO4Pu6BNCg5tBAQS7DfYLwBAAbDF4HO93u9TwCoAABKwOuCIbvGAAlghA5Bg1ms13AAI6CAQMI5AFB2AABd4YFBG4PuO4V/v4WB5+QxvQAILvEO49NJwMOd4RlCOwICBWIJ3Cd4xGCAAfM4Hg8Hu12qFwQBBeAjvDO48Gg0AxEAOwJ3Du1mHwLvE2ABBO4oiFSITvHh//yB3EgEiAoVEYwSKBboY2BOAQbBKYLuLMoMAOwIA=")),0,135); +g.drawImage(require("heatshrink").decompress(atob("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")),0,135); g.flip(); From a1820b7e7ec5f60002567e74ff49c1b4fe7ca66e Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sat, 13 Jun 2020 08:15:43 +0200 Subject: [PATCH 1139/1189] Added Mixed Clock 2 fork of original mixed clock Differences to original Mixed Clock: - Color is all white for better readability in the bright sunlight - Thicker clock hands for better readability in the bright sunlight - Extra space under the clock for widgets - Seconds in the digital clock --- apps.json | 13 ++++ apps/miclock2/clock-mixed-icon.js | 1 + apps/miclock2/clock-mixed.js | 113 ++++++++++++++++++++++++++++++ apps/miclock2/clock-mixed.png | Bin 0 -> 707 bytes 4 files changed, 127 insertions(+) create mode 100644 apps/miclock2/clock-mixed-icon.js create mode 100644 apps/miclock2/clock-mixed.js create mode 100755 apps/miclock2/clock-mixed.png diff --git a/apps.json b/apps.json index a09aa6c6b..55d70fe34 100644 --- a/apps.json +++ b/apps.json @@ -1945,5 +1945,18 @@ {"name":"gpspoilog.app.js","url":"app.js"}, {"name":"gpspoilog.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "miclock2", + "name": "Mixed Clock 2", + "icon": "clock-mixed.png", + "version":"0.01", + "description": "White color variant of the Mixed Clock with thicker clock hands for better readability in the bright sunlight, extra space under the clock for widgets and seconds in the digital clock.", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"miclock.app.js","url":"clock-mixed.js"}, + {"name":"miclock.img","url":"clock-mixed-icon.js","evaluate":true} + ] } ] diff --git a/apps/miclock2/clock-mixed-icon.js b/apps/miclock2/clock-mixed-icon.js new file mode 100644 index 000000000..3ca3b0612 --- /dev/null +++ b/apps/miclock2/clock-mixed-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATiwAGFdYzlFp4xeFyYwZD49kxGs2fX6+z1mIsgxcDQtAxArCAA+zxFAGDAYFxAsJAAuIGCxcF1omHgEABI+sGCouERRIvJSgKTEFzovLGAJgRCIiMIF5ySGF57qMF5nXsgvORoggLF5yRPLyAvO6+IF6LsKF6JgEF5lkD5gvPYIiOaF6CQMBYesD5oAP1gvPXxpfDAQIAFYCILDJ5wvP64veACCPeAB6PQd4p9EQQ4MLd6GIF7uIF5YwDsgiNAY4vHsguLYBJfXXxiQKL66ONF4lAL7dAF5pgIF6y9DFxYvEi2sF6+sDwgvLGAryEACLsEFxrCGGCmzXh5gJSQYAPRgovQGA1kMR7qEFyQwHi2IGJWzxCLEFygwIMYOI1gzC2esxBbGFywxKABotXGCwuaGKQtdGZorjAH4A/AF4=")) diff --git a/apps/miclock2/clock-mixed.js b/apps/miclock2/clock-mixed.js new file mode 100644 index 000000000..d928a5185 --- /dev/null +++ b/apps/miclock2/clock-mixed.js @@ -0,0 +1,113 @@ +// Code based on the original Mixed Clock + +/* jshint esversion: 6 */ +var locale = require("locale"); +const Radius = { "center": 7, "hour": 60, "min": 80, "dots": 88 }; +const Center = { "x": 120, "y": 96 }; +const Widths = { hour: 2, minute: 2 }; +var buf = Graphics.createArrayBuffer(240,192,1,{msb:true}); + +function rotatePoint(x, y, d) { + rad = -1 * d / 180 * Math.PI; + var sin = Math.sin(rad); + var cos = Math.cos(rad); + xn = ((Center.x + x * cos - y * sin) + 0.5) | 0; + yn = ((Center.y + x * sin - y * cos) + 0.5) | 0; + p = [xn, yn]; + return p; +} + + +// from https://github.com/espruino/Espruino/issues/1702 +function setLineWidth(x1, y1, x2, y2, lw) { + var dx = x2 - x1; + var dy = y2 - y1; + var d = Math.sqrt(dx * dx + dy * dy); + dx = dx * lw / d; + dy = dy * lw / d; + + return [ + // rounding + x1 - (dx + dy) / 2, y1 - (dy - dx) / 2, + x1 - dx, y1 -dy, + x1 + (dy - dx) / 2, y1 - (dx + dy) / 2, + + x1 + dy, y1 - dx, + x2 + dy, y2 - dx, + + // rounding + x2 + (dx + dy) / 2, y2 + (dy - dx) / 2, + x2 + dx, y2 + dy, + x2 - (dy - dx) / 2, y2 + (dx + dy) / 2, + + x2 - dy, y2 + dx, + x1 - dy, y1 + dx + ]; +} + + +function drawMixedClock(force) { + if ((force || Bangle.isLCDOn()) && buf.buffer) { + var date = new Date(); + var dateArray = date.toString().split(" "); + var isEn = locale.name.startsWith("en"); + var point = []; + var minute = date.getMinutes(); + var hour = date.getHours(); + var radius; + + g.reset(); + buf.clear(); + + // draw date + buf.setFont("6x8", 2); + buf.setFontAlign(-1, 0); + buf.drawString(locale.dow(date,true) + ' ', 4, 16, true); + buf.drawString(isEn?(' ' + dateArray[2]):locale.month(date,true), 4, 176, true); + buf.setFontAlign(1, 0); + buf.drawString(isEn?locale.month(date,true):(' ' + dateArray[2]), 237, 16, true); + buf.drawString(dateArray[3], 237, 176, true); + + // draw hour and minute dots + for (i = 0; i < 60; i++) { + radius = (i % 5) ? 2 : 4; + point = rotatePoint(0, Radius.dots, i * 6); + buf.fillCircle(point[0], point[1], radius); + } + + // draw digital time + buf.setFont("6x8", 3); + buf.setFontAlign(0, 0); + buf.drawString(dateArray[4], 120, 120, true); + + // draw new minute hand + point = rotatePoint(0, Radius.min, minute * 6); + buf.drawLine(Center.x, Center.y, point[0], point[1]); + buf.fillPoly(setLineWidth(Center.x, Center.y, point[0], point[1], Widths.minute)); + // draw new hour hand + point = rotatePoint(0, Radius.hour, hour % 12 * 30 + date.getMinutes() / 2 | 0); + buf.fillPoly(setLineWidth(Center.x, Center.y, point[0], point[1], Widths.hour)); + + // draw center + buf.fillCircle(Center.x, Center.y, Radius.center); + + g.drawImage({width:buf.getWidth(),height:buf.getHeight(),bpp:1,buffer:buf.buffer},0,24); + } +} + +Bangle.on('lcdPower', function(on) { + if (on) + drawMixedClock(true); + Bangle.drawWidgets(); +}); + +setInterval(() => drawMixedClock(true), 30000); // force an update every 30s even screen is off + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawMixedClock(); // immediately draw +setInterval(drawMixedClock, 500); // update twice a second + +// Show launcher when middle button pressed after freeing memory first +setWatch(() => {delete buf.buffer; Bangle.showLauncher()}, BTN2, {repeat:false,edge:"falling"}); diff --git a/apps/miclock2/clock-mixed.png b/apps/miclock2/clock-mixed.png new file mode 100755 index 0000000000000000000000000000000000000000..f02ad5e9ee3a0bf215beed0d8cf9d8765015b314 GIT binary patch literal 707 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sa{_!qT!A#h<|7Pi4ua5HFbQJp zXIKqmL!}Nu)d0C0Pcy7Jz_11^0@Skh5J>T=0}N|{f(PHddk0d?KpYl@w4E=7yS=i zxccJNmV1x&cAi=$dl2LS>5?G7UISE7D(w3b_%UOgE( z!JUDDakr<7V~EG`yP-FyH5u@PGO{{49xq+BhH24`GiUz)zdd0UuRzrOz0Y4P%*~r^ z^3wOc^2PfW$F^^ch$ue%@mKy?_tOv8wJo#`nl<}Y!u3NA#!tV+Ut7og%jMagZw4Ro zD+SXcBV3mLpK;O3d1mj=M~eJ2945&Bcv5j~qy6^p{*u`W)<5Ssp1<(p+x6)W>;C`p z3VJ8nDW3M<$&K?(MdQ}6C(HPLH`@wLU`&6ZR(N8+k=Fwa1-{)A<4;`gJjwBfM{>>c z8cx2{A}0pFom;hAf1Q+6R8U%>z2_FMi@*vFMwf@2O~Ji+KCTI=sgF3C8s!3+ex-06 z+9M_U_34bQ6GPO39UE5ho#gzj{==f>4kuHJVwiB!2^Pf@jV!N(Sa-QJv#~!|Z+c+C z$0%h{#`U7Y;n#AH_zS$7dNNADCQfRTuuEo+=SNS!1CN9YDl1R>cR1RFJz@0Zc*HnS zebxyM&iX|mESHpDAK~wE@J`d4(r9#9Gv%fJEz{OB%YrfsR@$(yU1ZI@a!N;`)YYRF zPKIG8Y9&<@W!gPU>QC*}eH|kldpAJCXZALo+aczz+i!}5FaDl;y|`zksYFC@^4_=K b?F9c{ecS$I?dMmTpw#H;>gTe~DWM4f>^e@f literal 0 HcmV?d00001 From 687db8904f37410462d22b23fc12ce4d942a87fa Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sat, 13 Jun 2020 08:25:48 +0200 Subject: [PATCH 1140/1189] Mixed Clock 2: Fix apps.json entry --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 55d70fe34..6c7ede88f 100644 --- a/apps.json +++ b/apps.json @@ -1955,8 +1955,8 @@ "type":"clock", "allow_emulator":true, "storage": [ - {"name":"miclock.app.js","url":"clock-mixed.js"}, - {"name":"miclock.img","url":"clock-mixed-icon.js","evaluate":true} + {"name":"miclock2.app.js","url":"clock-mixed.js"}, + {"name":"miclock2.img","url":"clock-mixed-icon.js","evaluate":true} ] } ] From 3404d244b66735cecfeaa91ea8d6be4289744d1b Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sat, 13 Jun 2020 16:29:17 -0400 Subject: [PATCH 1141/1189] App Manager: reduce memory usage --- apps.json | 2 +- apps/files/ChangeLog | 1 + apps/files/files.js | 29 ++++++++++++++--------------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps.json b/apps.json index a09aa6c6b..2cddea678 100644 --- a/apps.json +++ b/apps.json @@ -403,7 +403,7 @@ { "id": "files", "name": "App Manager", "icon": "files.png", - "version":"0.05", + "version":"0.06", "description": "Show currently installed apps, free space, and allow their deletion from the watch", "tags": "tool,system,files", "storage": [ diff --git a/apps/files/ChangeLog b/apps/files/ChangeLog index f2e5f64f5..b4037a733 100644 --- a/apps/files/ChangeLog +++ b/apps/files/ChangeLog @@ -2,3 +2,4 @@ 0.03: Add support for data files 0.04: Add functionality to sort apps manually or alphabetically ascending/descending. 0.05: Tweaks to help with memory usage +0.06: Reduce memory usage \ No newline at end of file diff --git a/apps/files/files.js b/apps/files/files.js index ab259d6df..e240a8e68 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -45,13 +45,13 @@ function globToRegex(pattern) { return new RegExp('^'+regex+'$'); } -function eraseFiles(app) { - app.files.split(",").forEach(f=>store.erase(f)); +function eraseFiles(info) { + info.files.split(",").forEach(f=>store.erase(f)); } -function eraseData(app) { - if(!app.data) return; - const d=app.data.split(';'), +function eraseData(info) { + if(!info.data) return; + const d=info.data.split(';'), files=d[0].split(','), sFiles=(d[1]||'').split(','); let erase = f=>store.erase(f); @@ -68,8 +68,9 @@ function eraseData(app) { } function eraseApp(app, files,data) { E.showMessage('Erasing\n' + app.name + '...'); - if (files) eraseFiles(app); - if (data) eraseData(app); + var info = store.readJSON(app.id + ".info", 1)||{}; + if (files) eraseFiles(info); + if (data) eraseData(info); } function eraseOne(app, files,data){ E.showPrompt('Erase\n'+app.name+'?').then((v) => { @@ -86,8 +87,7 @@ function eraseAll(apps, files,data) { E.showPrompt('Erase all?').then((v) => { if (v) { Bangle.buzz(100, 1); - for(var n = 0; n eraseApp(app, files, data)); } showApps(); }); @@ -100,7 +100,7 @@ function showAppMenu(app) { }, '< Back': () => showApps(), }; - if (app.data) { + if (app.hasData) { appmenu['Erase Completely'] = () => eraseOne(app, true, true); appmenu['Erase App,Keep Data'] = () => eraseOne(app, true, false); appmenu['Only Erase Data'] = () => eraseOne(app, false, true); @@ -120,11 +120,10 @@ function showApps() { var list = store.list(/\.info$/).filter((a)=> { return a !== 'setting.info'; - }).sort().map((app) => { - var ret = store.readJSON(app,1)||{}; - ret[''] = app; - return ret; - }); + }).map((a)=> { + let app = store.readJSON(a, 1) || {}; + return {id: app.id, name: app.name, hasData: !!app.data}; + }).sort(sortHelper());; if (list.length > 0) { list.reduce((menu, app) => { From 30864632a626dc66c7f41bd0d6993f640f6055a2 Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sat, 13 Jun 2020 17:10:42 -0400 Subject: [PATCH 1142/1189] largeclock: Adjust layout to account for new font --- apps.json | 2 +- apps/largeclock/ChangeLog | 1 + apps/largeclock/largeclock.js | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index a09aa6c6b..563e7fd70 100644 --- a/apps.json +++ b/apps.json @@ -1605,7 +1605,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.03", + "version": "0.04", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", diff --git a/apps/largeclock/ChangeLog b/apps/largeclock/ChangeLog index fe44e5078..15dcd269e 100644 --- a/apps/largeclock/ChangeLog +++ b/apps/largeclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: Init 0.02: fix 3/4 moon orientation 0.03: Change `largeclock.json` to 'data' file to allow settings to be preserved +0.04: Adjust layout to account for new vector font diff --git a/apps/largeclock/largeclock.js b/apps/largeclock/largeclock.js index 9975775fb..913040557 100644 --- a/apps/largeclock/largeclock.js +++ b/apps/largeclock/largeclock.js @@ -8,7 +8,7 @@ const moonR = 12; const moonX = 215; const moonY = 50; -const settings = require("Storage").readJSON("largeclock.json", 1); +const settings = require("Storage").readJSON("largeclock.json", 1)||{}; const BTN1app = settings.BTN1 || ""; const BTN3app = settings.BTN3 || ""; @@ -131,12 +131,12 @@ function drawTime(d) { g.setColor(1, 1, 1); g.setFontAlign(-1, -1); g.setFont("Vector", 100); - g.drawString(hours, 50, 24, true); + g.drawString(hours, 40, 24, true); g.setColor(1, 50, 1); - g.drawString(minutes, 50, 135, true); + g.drawString(minutes, 40, 135, true); g.setFont("Vector", 20); g.setRotation(3); - g.drawString(`${dow} ${day} ${month}`, 50, 15, true); + g.drawString(`${dow} ${day} ${month}`, 50, 10, true); g.drawString(year, 75, 205, true); lastMinutes = minutes; } @@ -144,7 +144,7 @@ function drawTime(d) { g.setFont("Vector", 20); g.setColor(1, 1, 1); g.setFontAlign(0, -1); - g.clearRect(200, 210, 240, 240); + g.clearRect(195, 210, 240, 240); g.drawString(seconds, 215, 215); } From 86bb7da3524a3266fe86f1d2a88387f3978bda43 Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sat, 13 Jun 2020 17:49:45 -0400 Subject: [PATCH 1143/1189] largeclock: Support 12 hour time --- apps.json | 2 +- apps/largeclock/ChangeLog | 1 + apps/largeclock/largeclock.js | 20 +++++++++++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 563e7fd70..ec757c96e 100644 --- a/apps.json +++ b/apps.json @@ -1605,7 +1605,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.04", + "version": "0.05", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", diff --git a/apps/largeclock/ChangeLog b/apps/largeclock/ChangeLog index 15dcd269e..494002e0e 100644 --- a/apps/largeclock/ChangeLog +++ b/apps/largeclock/ChangeLog @@ -2,3 +2,4 @@ 0.02: fix 3/4 moon orientation 0.03: Change `largeclock.json` to 'data' file to allow settings to be preserved 0.04: Adjust layout to account for new vector font +0.05: Add support for 12 hour time \ No newline at end of file diff --git a/apps/largeclock/largeclock.js b/apps/largeclock/largeclock.js index 913040557..6f3d638fa 100644 --- a/apps/largeclock/largeclock.js +++ b/apps/largeclock/largeclock.js @@ -4,9 +4,11 @@ let interval; let lastMoonPhase; let lastMinutes; +const is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; + const moonR = 12; const moonX = 215; -const moonY = 50; +const moonY = is12Hour ? 90 : 50; const settings = require("Storage").readJSON("largeclock.json", 1)||{}; const BTN1app = settings.BTN1 || ""; @@ -118,15 +120,23 @@ function drawMoon(d) { function drawTime(d) { const da = d.toString().split(" "); - const time = da[4].substr(0, 5).split(":"); + const time = da[4].split(":"); const dow = da[0]; const month = da[1]; const day = da[2]; const year = da[3]; - const hours = time[0]; + const hours = is12Hour ? ("0" + (((d.getHours() + 11) % 12) + 1)).substr(-2) : time[0]; + const meridian = d.getHours() < 12 ? "AM" : "PM"; const minutes = time[1]; - const seconds = d.getSeconds(); + const seconds = time[2]; if (minutes != lastMinutes) { + if (is12Hour) { + g.setFont("Vector", 18); + g.setColor(1, 1, 1); + g.setFontAlign(0, -1); + g.clearRect(195, 34, 240, 44); + g.drawString(meridian, 217, 34); + } g.clearRect(0, 24, moonX - moonR - 10, 239); g.setColor(1, 1, 1); g.setFontAlign(-1, -1); @@ -137,7 +147,7 @@ function drawTime(d) { g.setFont("Vector", 20); g.setRotation(3); g.drawString(`${dow} ${day} ${month}`, 50, 10, true); - g.drawString(year, 75, 205, true); + g.drawString(year, is12Hour ? 46 : 75, 205, true); lastMinutes = minutes; } g.setRotation(0); From 5805329248b80518f01f4272c0285102f16018ed Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sat, 13 Jun 2020 21:20:47 -0400 Subject: [PATCH 1144/1189] blobclk: Adapt to fillPoly changes --- apps.json | 2 +- apps/blobclk/ChangeLog | 1 + apps/blobclk/clock-blob.js | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index a09aa6c6b..ab08ea051 100644 --- a/apps.json +++ b/apps.json @@ -869,7 +869,7 @@ "name": "Large Digit Blob Clock", "shortName" : "Blob Clock", "icon": "clock-blob.png", - "version":"0.03", + "version":"0.04", "description": "A clock with big digits", "tags": "clock", "type":"clock", diff --git a/apps/blobclk/ChangeLog b/apps/blobclk/ChangeLog index 1cfc59015..9715fc4ab 100644 --- a/apps/blobclk/ChangeLog +++ b/apps/blobclk/ChangeLog @@ -2,3 +2,4 @@ Only draw widgets after clearing screen - they update automatically Remove 'faceUp' check as it's automatic 0.03: Modified for use with new bootloader and firmware +0.04: Modified to account for changes in the behavior of Graphics.fillPoly diff --git a/apps/blobclk/clock-blob.js b/apps/blobclk/clock-blob.js index 1d85bc65e..76f10865f 100644 --- a/apps/blobclk/clock-blob.js +++ b/apps/blobclk/clock-blob.js @@ -18,8 +18,8 @@ function flip() { g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},55,26); } function drawPixel(ox,oy,x,y,r,p) { - let x1 = ox+x*(r*2+1); - let y1 = oy+y*(r*2+1); + let x1 = ox+x*(r*2); + let y1 = oy+y*(r*2); let xmid = x1+r; let ymid = y1+r; let x2 = xmid+r; @@ -27,14 +27,14 @@ function drawPixel(ox,oy,x,y,r,p) { if (p > 0) { if (p > 1) { buf.setColor(0,0,0); - buf.fillRect(x1,y1,x2,y2); + buf.fillPoly([x1,y1,x2,y1,x2,y2,x1,y2]); } buf.setColor(1,1,1); } else { buf.setColor(0,0,0); } if (p < 2) { - buf.fillRect(x1,y1,x2,y2); + buf.fillPoly([x1,y1,x2,y1,x2,y2,x1,y2]); } else if (p === 2) { buf.fillPoly([xmid,y1,x2,y1,x2,y2,x1,y2,x1,ymid]); } else if (p === 3) { From 36e1b6b61e02789bf33722bb4d7233a5e6022829 Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sat, 13 Jun 2020 21:27:54 -0400 Subject: [PATCH 1145/1189] App Manager: remove extra semicolon --- apps/files/files.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files/files.js b/apps/files/files.js index e240a8e68..9e6c97702 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -123,7 +123,7 @@ function showApps() { }).map((a)=> { let app = store.readJSON(a, 1) || {}; return {id: app.id, name: app.name, hasData: !!app.data}; - }).sort(sortHelper());; + }).sort(sortHelper()); if (list.length > 0) { list.reduce((menu, app) => { From 2ffdd2d2829417572b102280b2ee3d7570dba418 Mon Sep 17 00:00:00 2001 From: Francesco Bedussi Date: Sun, 14 Jun 2020 16:15:59 +0200 Subject: [PATCH 1146/1189] feat: allow to disable BTN1 and BTN3 buttons --- apps.json | 2 +- apps/largeclock/ChangeLog | 1 + apps/largeclock/README.md | 2 +- apps/largeclock/largeclock.js | 4 ++-- apps/largeclock/largeclock.json | 4 ++-- apps/largeclock/settings.js | 4 ++++ 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index a09aa6c6b..563e7fd70 100644 --- a/apps.json +++ b/apps.json @@ -1605,7 +1605,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.03", + "version": "0.04", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", diff --git a/apps/largeclock/ChangeLog b/apps/largeclock/ChangeLog index fe44e5078..39ab5d629 100644 --- a/apps/largeclock/ChangeLog +++ b/apps/largeclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: Init 0.02: fix 3/4 moon orientation 0.03: Change `largeclock.json` to 'data' file to allow settings to be preserved +0.04: Allow to disable BTN1 and BTN3 buttons diff --git a/apps/largeclock/README.md b/apps/largeclock/README.md index c9a325823..5c2ad42c2 100644 --- a/apps/largeclock/README.md +++ b/apps/largeclock/README.md @@ -11,7 +11,7 @@ A readable and informational digital watch, with date, seconds and moon phase an ## How to use it - The clock can be used as any other one, if you like it just set it as the default clock app in settings > select clock -- In setting > large clock you can select which app is to be open by BTN1 and BTN3 +- In setting > large clock you can select which app, if any, is to be open by BTN1 and BTN3 ## Credits diff --git a/apps/largeclock/largeclock.js b/apps/largeclock/largeclock.js index 9975775fb..fb4835146 100644 --- a/apps/largeclock/largeclock.js +++ b/apps/largeclock/largeclock.js @@ -9,8 +9,8 @@ const moonX = 215; const moonY = 50; const settings = require("Storage").readJSON("largeclock.json", 1); -const BTN1app = settings.BTN1 || ""; -const BTN3app = settings.BTN3 || ""; +const BTN1app = settings && settings.BTN1 || ""; +const BTN3app = settings && settings.BTN3 || ""; function drawMoon(d) { const BLACK = 0, diff --git a/apps/largeclock/largeclock.json b/apps/largeclock/largeclock.json index 7c38d59de..58c981197 100644 --- a/apps/largeclock/largeclock.json +++ b/apps/largeclock/largeclock.json @@ -1,4 +1,4 @@ { - "BTN1": "timer.app.js", - "BTN3": "calendar.app.js" + "BTN1": "", + "BTN3": "" } diff --git a/apps/largeclock/settings.js b/apps/largeclock/settings.js index a33f3c438..293f66677 100644 --- a/apps/largeclock/settings.js +++ b/apps/largeclock/settings.js @@ -21,6 +21,10 @@ if (a.n > b.n) return 1; return 0; }); + apps.push({ + n: "NONE", + src: "" + }); const settings = s.readJSON("largeclock.json", 1) || { BTN1: "", From 4635cd92bc8c2a612103e2774bbf059ded1795c0 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 14 Jun 2020 19:00:02 +0200 Subject: [PATCH 1147/1189] Pong: Keep display on during game --- apps.json | 2 +- apps/pong/ChangeLog | 1 + apps/pong/app.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 94c13ef9e..48b2fa4fc 100644 --- a/apps.json +++ b/apps.json @@ -1541,7 +1541,7 @@ "name": "Pong", "shortName": "Pong", "icon": "pong.png", - "version": "0.02", + "version": "0.03", "description": "A clone of the Atari game Pong", "tags": "game", "type": "app", diff --git a/apps/pong/ChangeLog b/apps/pong/ChangeLog index 6433ebce4..198d7bbde 100644 --- a/apps/pong/ChangeLog +++ b/apps/pong/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: 2 players local + improve ai +0.03: Keep display on during gameplay diff --git a/apps/pong/app.js b/apps/pong/app.js index ba34d60b5..012cd8f81 100644 --- a/apps/pong/app.js +++ b/apps/pong/app.js @@ -337,6 +337,7 @@ function onFrame() { ai.show(); net(); ball.show(); + g.flip() } else if (state === 3) { g.clear(); g.setColor(0); From 223668faa069bd3eb8a0500183e8c11ff657073b Mon Sep 17 00:00:00 2001 From: Bastian Greshake Tzovaras Date: Wed, 17 Jun 2020 12:07:47 +0200 Subject: [PATCH 1148/1189] first add of 1button --- apps.json | 16 ++++++ apps/1button/ChangeLog | 1 + apps/1button/README.md | 25 +++++++++ apps/1button/interface.html | 107 ++++++++++++++++++++++++++++++++++++ apps/1button/widget.js | 36 ++++++++++++ apps/1button/widget.png | Bin 0 -> 4433 bytes 6 files changed, 185 insertions(+) create mode 100644 apps/1button/ChangeLog create mode 100644 apps/1button/README.md create mode 100644 apps/1button/interface.html create mode 100644 apps/1button/widget.js create mode 100644 apps/1button/widget.png diff --git a/apps.json b/apps.json index 94c13ef9e..a228723cd 100644 --- a/apps.json +++ b/apps.json @@ -1958,5 +1958,21 @@ {"name":"miclock2.app.js","url":"clock-mixed.js"}, {"name":"miclock2.img","url":"clock-mixed-icon.js","evaluate":true} ] + }, + { "id": "1button", + "name": "One-Button-Tracker", + "icon": "widget.png", + "version":"0.01", + "interface": "interface.html", + "description": "A widget that turns BTN1 into a tracker, records time of button press/release.", + "tags": "tool,quantifiedself,widget", + "type": "widget", + "readme": "README.md", + "storage": [ + {"name":"1button.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"one_button_presses.csv","storageFile": true} + ] } ] diff --git a/apps/1button/ChangeLog b/apps/1button/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/1button/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/1button/README.md b/apps/1button/README.md new file mode 100644 index 000000000..a909e9e7e --- /dev/null +++ b/apps/1button/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/1button/interface.html b/apps/1button/interface.html new file mode 100644 index 000000000..42e8dcb1a --- /dev/null +++ b/apps/1button/interface.html @@ -0,0 +1,107 @@ + + + + + +
+ + + + + diff --git a/apps/1button/widget.js b/apps/1button/widget.js new file mode 100644 index 000000000..e0542137e --- /dev/null +++ b/apps/1button/widget.js @@ -0,0 +1,36 @@ +(() => { + var press_time = new Date(); + recFile = require("Storage").open("one_button_presses.csv","a"); + + // set widget text + function draw() { + g.reset(); // reset the graphics context to defaults (color/font/etc) + // add your code + g.fillCircle(this.x+6,this.y+6,4); + g.drawString("1BUTTON", this.x+13, this.y+4); + } + + // listen to button press to get start time + setWatch(function(e) { + console.log("Button pressed"); + digitalWrite(LED2,1); + press_time = new Date(); + Bangle.buzz(); + }, BTN1, { repeat: true, edge: 'rising', debounce: 50 }); + + // listen to button go to get end time & write data + setWatch(function(e) { + console.log("Button let go"); + digitalWrite(LED2,0); + var unpress_time = new Date(); + recFile.write([press_time.getTime(),unpress_time.getTime()].join(",")+"\n"); + }, BTN1, { repeat: true, edge: 'falling', debounce: 50 }); + + + // add your widget + WIDGETS["1button"]={ + area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right) + width: 100, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout + draw:draw // called to draw the widget + }; +})() diff --git a/apps/1button/widget.png b/apps/1button/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..6a827c392eb485bfb870d1cdbb06dbb26bba9f5a GIT binary patch literal 4433 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 Q`OiOxnvyoOQo$ztKO4MhlK=n! literal 0 HcmV?d00001 From b6afd43b326c032254eed2911b46c7b4d7d4c19c Mon Sep 17 00:00:00 2001 From: Bastian Greshake Tzovaras Date: Wed, 17 Jun 2020 12:27:39 +0200 Subject: [PATCH 1149/1189] tweak interface --- apps/1button/interface.html | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/apps/1button/interface.html b/apps/1button/interface.html index 42e8dcb1a..56020bb12 100644 --- a/apps/1button/interface.html +++ b/apps/1button/interface.html @@ -10,28 +10,25 @@ var domRecords = document.getElementById("records"); function saveRecord(record,name) { - var csv = `${record.map(rec=>[rec.time, rec.bpm, rec.confidence].join(",")).join("\n")}`; + var csv = `${record.map(rec=>[rec.start_time, rec.end_time].join(",")).join("\n")}`; Util.saveCSV(name, csv); } -function recordLineToObject(l, hasRecordNbr) { +function recordLineToObject(l) { var t = l.trim().split(","); - var n = hasRecordNbr?1:0; var o = { - start_time: parseFloat(t[n+0]), - end_time: parseFloat(t[n+1]), + start_time: parseFloat(t[0]), + end_time: parseFloat(t[1]), }; - if (hasRecordNbr) - o.number = t[0]; return o; } -function downloadRecord(recordNbr, callback) { +function downloadRecord(callback) { Util.showModal("Downloading one-button tracker data..."); Util.readStorageFile(`one_button_presses.csv`,data=>{ Util.hideModal(); - var record = data.trim().split("\n").map(l=>recordLineToObject(l,false)); + var record = data.trim().split("\n").map(l=>recordLineToObject(l)); callback(record); }); } @@ -40,24 +37,24 @@ function getRecordList() { Util.showModal("Loading one button tracker records..."); domRecords.innerHTML = ""; Puck.write(`\x10(function() { - var f = require("Storage").open("one_button_presses.csv,"r"); - var l = f.readLine(); + var f = require("Storage").open("one_button_presses.csv,"r"); + var l = f.readLine(); })()\n`,recordList=>{ var recordLines = recordList.trim().split("\n"); var html = `
\n`; recordLines.forEach(l => { - var record = recordLineToObject(l, true /*has record number*/); + var record = recordLineToObject(l); html += `
-
Heart Rate Record ${record.number}
-
${(new Date(record.time*1000)).toString().substr(0,24)}
+
One-Button Presses
+
${(new Date(record.start_time*1000)).toString().substr(0,24)}
`; @@ -85,13 +82,13 @@ function getRecordList() { var task = button.getAttribute("task"); if (task=="delete") { Util.showModal("Deleting record..."); - Util.eraseStorageFile(`.heart${recordNbr.toString(36)}`,()=>{ + Util.eraseStorageFile(`one_button_presses.csv`,()=>{ Util.hideModal(); getRecordList(); }); } if (task=="download") { - downloadRecord(recordNbr, record => saveRecord(record, `HeartRateRecord${recordNbr}`)); + downloadRecord(record => saveRecord(record, `one_button_presses`)); } }); } From e8f09cb61d593276baa42fbb23dcedfeeef219c1 Mon Sep 17 00:00:00 2001 From: Bastian Greshake Tzovaras Date: Wed, 17 Jun 2020 12:36:41 +0200 Subject: [PATCH 1150/1189] remove looping in interface --- apps/1button/interface.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/1button/interface.html b/apps/1button/interface.html index 56020bb12..47ed9bd2c 100644 --- a/apps/1button/interface.html +++ b/apps/1button/interface.html @@ -43,8 +43,6 @@ function getRecordList() { var recordLines = recordList.trim().split("\n"); var html = `
\n`; - recordLines.forEach(l => { - var record = recordLineToObject(l); html += `
@@ -58,7 +56,6 @@ function getRecordList() {
`; - }); if (recordLines.length==0) { html += `
From df44962aeb1e7bcb76206ee4a175e347a98f648f Mon Sep 17 00:00:00 2001 From: Bastian Greshake Tzovaras Date: Wed, 17 Jun 2020 12:44:31 +0200 Subject: [PATCH 1151/1189] whops, undefined error --- apps/1button/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/1button/interface.html b/apps/1button/interface.html index 47ed9bd2c..081e0bf2a 100644 --- a/apps/1button/interface.html +++ b/apps/1button/interface.html @@ -47,7 +47,7 @@ function getRecordList() {
One-Button Presses
-
${(new Date(record.start_time*1000)).toString().substr(0,24)}
+
Get all of your button presses
2$hmvlvTQ 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 literal 0 HcmV?d00001 diff --git a/apps/gpsnav/waypoints.json b/apps/gpsnav/waypoints.json new file mode 100644 index 000000000..143316b19 --- /dev/null +++ b/apps/gpsnav/waypoints.json @@ -0,0 +1,23 @@ +[ + { + "mark":0, + "name":"NONE" + }, + { + "mark":1, + "name":"No10", + "lat":51.5032, + "lon":-0.1269 + }, + { + "mark":1, + "name":"Stone", + "lat":51.1788, + "lon":-1.8260 + }, + { "name":"WP0" }, + { "name":"WP1" }, + { "name":"WP2" }, + { "name":"WP3" }, + { "name":"WP4" } +] \ No newline at end of file From 73366a600cdf52d0f108f2aacd7542ee502bb583 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sat, 18 Apr 2020 14:44:00 +0100 Subject: [PATCH 0481/1189] Update apps.json --- apps.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps.json b/apps.json index 0c97b9e57..0b7001a5e 100644 --- a/apps.json +++ b/apps.json @@ -291,6 +291,18 @@ {"name":"gpsrec.wid.js","url":"widget.js"} ] }, + { "id": "gpsnav", + "name": "GPS Navigation", + "icon": "icon.png", + "version":"0.01", + "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording", + "tags": "tool,outdoors,gps", + "storage": [ + {"name":"gpsnav.app.js","url":"app.js"}, + {"name":"waypoints.json","url":"waypoints.json","evaluate":false}, + {"name":"gpsnav.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "heart", "name": "Heart Rate Recorder", "icon": "app.png", From 696afd7f6bae48410d27df696298b239b31c1f3f Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:08:33 +0200 Subject: [PATCH 0482/1189] ble hid control is removed from require and is now hard written in app --- apps/hidcam/app.js | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 6a4150673..f529deff2 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -1,16 +1,46 @@ -var controls = require("ble_hid_controls"); var storage = require('Storage'); const settings = storage.readJSON('setting.json',1) || { HID: false }; +// hidcontrol module selective and manual import : +report = new Uint8Array([ + 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) + 0x09, 0x01, // USAGE (Consumer Control) + 0xa1, 0x01, // COLLECTION (Application) + // -------------------- common global items + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit + // -------------------- misc bits + 0x95, 0x05, // REPORT_COUNT (5) + 0x09, 0xb5, // USAGE (Scan Next Track) + 0x09, 0xb6, // USAGE (Scan Previous Track) + 0x09, 0xb7, // USAGE (Stop) + 0x09, 0xcd, // USAGE (Play/Pause) + 0x09, 0xe2, // USAGE (Mute) + 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs + // -------------------- volume up/down bits + 0x95, 0x02, // REPORT_COUNT (2) + 0x09, 0xe9, // USAGE (Volume Up) + 0x09, 0xea, // USAGE (Volume Down) + 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs + // -------------------- padding bit + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Cnst,Ary,Abs) + 0xc0 // END_COLLECTION +]); +function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }); } +volumeUp = function(cb) { p(0x20,cb) }; +//end of manual selective import + g.clear(); E.showMessage('BTN2 to trigger','camTrigger'); Bangle.loadWidgets(); Bangle.drawWidgets(); if (settings.HID) { - NRF.setServices(undefined, { hid : controls.report }); - shotTrigger = function() {controls.volumeUp();}; + NRF.setServices(undefined, { hid : report }); + shotTrigger = function() {volumeUp();}; } else { E.showMessage('HID disabled'); setTimeout(load, 1000); From 41d206cdbe03461808b54f71149f6598b7ac0a24 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:24:33 +0200 Subject: [PATCH 0483/1189] typos in code and no more useless timeout --- apps/hidcam/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index f529deff2..9117d94f5 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -33,6 +33,8 @@ function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }) volumeUp = function(cb) { p(0x20,cb) }; //end of manual selective import +NRF.setServices(undefined, { hid : report }); + g.clear(); E.showMessage('BTN2 to trigger','camTrigger'); Bangle.loadWidgets(); @@ -50,7 +52,6 @@ setWatch(function(e){ E.showMessage('capture'); Bangle.beep(); shotTrigger(); - set.Timeout(load,1000); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From fc6d6aa4bbe1fdfefade4a0e85ab96460d1feda2 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:41:43 +0200 Subject: [PATCH 0484/1189] hid code correction --- apps/hidcam/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 9117d94f5..e114863cc 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -30,7 +30,7 @@ report = new Uint8Array([ 0xc0 // END_COLLECTION ]); function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }); } -volumeUp = function(cb) { p(0x20,cb) }; +volumeUp = function(cb) { p(0x80,cb) }; //end of manual selective import NRF.setServices(undefined, { hid : report }); From b58069fba13b50bba26dadf667dc55616d64bdc2 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:52:30 +0200 Subject: [PATCH 0485/1189] massive rewrite with really heavy inspiration from music control app --- apps/hidcam/app.js | 89 +++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index e114863cc..57d4a6f05 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -2,58 +2,51 @@ var storage = require('Storage'); const settings = storage.readJSON('setting.json',1) || { HID: false }; -// hidcontrol module selective and manual import : -report = new Uint8Array([ - 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) - 0x09, 0x01, // USAGE (Consumer Control) - 0xa1, 0x01, // COLLECTION (Application) - // -------------------- common global items - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit - // -------------------- misc bits - 0x95, 0x05, // REPORT_COUNT (5) - 0x09, 0xb5, // USAGE (Scan Next Track) - 0x09, 0xb6, // USAGE (Scan Previous Track) - 0x09, 0xb7, // USAGE (Stop) - 0x09, 0xcd, // USAGE (Play/Pause) - 0x09, 0xe2, // USAGE (Mute) - 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs - // -------------------- volume up/down bits - 0x95, 0x02, // REPORT_COUNT (2) - 0x09, 0xe9, // USAGE (Volume Up) - 0x09, 0xea, // USAGE (Volume Down) - 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs - // -------------------- padding bit - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x01, // INPUT (Cnst,Ary,Abs) - 0xc0 // END_COLLECTION -]); -function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }); } -volumeUp = function(cb) { p(0x80,cb) }; -//end of manual selective import - -NRF.setServices(undefined, { hid : report }); - -g.clear(); -E.showMessage('BTN2 to trigger','camTrigger'); -Bangle.loadWidgets(); -Bangle.drawWidgets(); +var sendHid, camShot, profile; if (settings.HID) { - NRF.setServices(undefined, { hid : report }); - shotTrigger = function() {volumeUp();}; + profile = 'camShutter'; + sendHid = function (code, cb) { + try { + NRF.sendHIDReport([1,code], () => { + NRF.sendHIDReport([1,0], () => { + if (cb) cb(); + }); + }); + } catch(e) { + print(e); + } + }; + camShot = function (cb) { sendHid(0x80, cb); }; } else { E.showMessage('HID disabled'); setTimeout(load, 1000); } - -setWatch(function(e){ - E.showMessage('capture'); - Bangle.beep(); - shotTrigger(); +function drawApp() { g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - E.showMessage('BTN2 to trigger','camTrigger'); -},BTN2,{ repeat:true, edge:'falling' }); + g.setFont("6x8",2); + g.setFontAlign(0,0); + g.drawString(profile, 120, 120); + const d = g.getWidth() - 18; + + function c(a) { + return { + width: 8, + height: a.length, + bpp: 1, + buffer: (new Uint8Array(a)).buffer + }; + } + + g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); +} + +if (camShot) { + setWatch(function(e) { + E.showMessage('camShot !'); + setTimeout(drawApp, 1000); + camShot(() => {}); + }, BTN2, { edge:"falling",repeat:true,debounce:50}); + + drawApp(); +} From 58e826accc018bbc638721f822b105959a19df52 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:01:01 +0200 Subject: [PATCH 0486/1189] adding widgets --- apps/hidcam/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 57d4a6f05..c3c672d4c 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -24,6 +24,8 @@ if (settings.HID) { } function drawApp() { g.clear(); + Bangle.loadWidgets() + Bangle.drawWidgets() g.setFont("6x8",2); g.setFontAlign(0,0); g.drawString(profile, 120, 120); From 63526c49e227a423eea5eaab25226c029d3e37b9 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:08:01 +0200 Subject: [PATCH 0487/1189] using app icon instead of text --- apps/hidcam/app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index c3c672d4c..6e599959c 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -26,9 +26,10 @@ function drawApp() { g.clear(); Bangle.loadWidgets() Bangle.drawWidgets() - g.setFont("6x8",2); - g.setFontAlign(0,0); - g.drawString(profile, 120, 120); +// g.setFont("6x8",2); +// g.setFontAlign(0,0); +// g.drawString(profile, 120, 120); + g.drawImage(storage.read("hidcam.img"),120,120) const d = g.getWidth() - 18; function c(a) { From aa168c3d5c5dce983dc4f3a52a24bd5e1d435868 Mon Sep 17 00:00:00 2001 From: fredericrous Date: Sat, 18 Apr 2020 16:30:05 +0100 Subject: [PATCH 0488/1189] Fix App Calculator issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Javascript rounded float issues - Reset after equals wasn't done properly - Introduce unit tests 🤗 --- apps.json | 4 +- apps/calculator/ChangeLog | 1 + apps/calculator/app.js | 146 +++++++++++++------- apps/calculator/tests.html | 273 +++++++++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+), 55 deletions(-) create mode 100644 apps/calculator/tests.html diff --git a/apps.json b/apps.json index 0c97b9e57..9bd4ee6fb 100644 --- a/apps.json +++ b/apps.json @@ -1264,8 +1264,8 @@ "name": "Calculator", "shortName":"Calculator", "icon": "calculator.png", - "version":"0.01", - "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus. Push button1 and 3 to navigate up/down, tap right or left to navigate the sides, push button 2 to select.", + "version":"0.02", + "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", "tags": "app,tool", "storage": [ {"name":"calculator.app.js","url":"app.js"}, diff --git a/apps/calculator/ChangeLog b/apps/calculator/ChangeLog index 5560f00bc..3b9b23270 100644 --- a/apps/calculator/ChangeLog +++ b/apps/calculator/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: fix precision rounding issue + no reset when equals pressed diff --git a/apps/calculator/app.js b/apps/calculator/app.js index 91dd7c49d..ad26d2d22 100644 --- a/apps/calculator/app.js +++ b/apps/calculator/app.js @@ -144,19 +144,57 @@ function drawKey(name, k, selected) { g.drawString(k.val || name, k.xy[0] + RIGHT_MARGIN + rMargin, k.xy[1] + BOTTOM_MARGIN + bMargin); } +function getIntWithPrecision(x) { + var xStr = x.toString(); + var xRadix = xStr.indexOf('.'); + var xPrecision = xRadix === -1 ? 0 : xStr.length - xRadix - 1; + return { + num: Number(xStr.replace('.', '')), + p: xPrecision + }; +} + +function multiply(x, y) { + var xNum = getIntWithPrecision(x); + var yNum = getIntWithPrecision(y); + return xNum.num * yNum.num / Math.pow(10, xNum.p + yNum.p); +} + +function divide(x, y) { + var xNum = getIntWithPrecision(x); + var yNum = getIntWithPrecision(y); + return xNum.num / yNum.num / Math.pow(10, xNum.p - yNum.p); +} + +function sum(x, y) { + let xNum = getIntWithPrecision(x); + let yNum = getIntWithPrecision(y); + + let diffPrecision = Math.abs(xNum.p - yNum.p); + if (diffPrecision > 0) { + if (xNum.p > yNum.p) { + yNum.num = yNum.num * Math.pow(10, diffPrecision); + } else { + xNum.num = xNum.num * Math.pow(10, diffPrecision); + } + } + return (xNum.num + yNum.num) / Math.pow(10, Math.max(xNum.p, yNum.p)); +} + +function subtract(x, y) { + return sum(x, -y); +} + function doMath(x, y, operator) { - // might not be a number due to display of dot "." algo - x = Number(x); - y = Number(y); switch (operator) { case '/': - return x / y; + return divide(x, y); case '*': - return x * y; + return multiply(x, y); case '+': - return x + y; + return sum(x, y); case '-': - return x - y; + return subtract(x, y); } } @@ -204,7 +242,7 @@ function displayOutput(num) { } len = (num + '').length; - if (numNumeric < 0) { + if (numNumeric < 0 || (numNumeric === 0 && 1/numNumeric === -Infinity)) { // minus is not available in font 7x11Numeric7Seg, we use Vector g.setFont('Vector', 20); g.drawString('-', 220 - (len * 15), 10); @@ -214,18 +252,33 @@ function displayOutput(num) { } g.drawString(num, 220 - (len * 15) + minusMarge, 10); } - +var wasPressedEquals = false; +var hasPressedNumber = false; function calculatorLogic(x) { - if (hasPressedEquals) { - currNumber = results; + if (wasPressedEquals && hasPressedNumber !== false) { prevNumber = null; - operator = null; - results = null; - isDecimal = null; - displayOutput(currNumber); - hasPressedEquals = false; + currNumber = hasPressedNumber; + wasPressedEquals = false; + hasPressedNumber = false; + return; } - if (prevNumber != null && currNumber != null && operator != null) { + if (hasPressedEquals) { + if (hasPressedNumber) { + prevNumber = null; + hasPressedNumber = false; + operator = null; + } else { + currNumber = null; + prevNumber = results; + } + hasPressedEquals = false; + wasPressedEquals = true; + } + + if (currNumber == null && operator != null && '/*-+'.indexOf(x) !== -1) { + operator = x; + displayOutput(prevNumber); + } else if (prevNumber != null && currNumber != null && operator != null) { // we execute the calculus only when there was a previous number entered before and an operator results = doMath(prevNumber, currNumber, operator); operator = x; @@ -255,8 +308,10 @@ function buttonPress(val) { operator = null; } else { keys.R.val = 'AC'; - drawKey('R', keys.R); + drawKey('R', keys.R, true); } + wasPressedEquals = false; + hasPressedNumber = false; displayOutput(0); break; case '%': @@ -265,11 +320,12 @@ function buttonPress(val) { } else if (currNumber != null) { displayOutput(currNumber /= 100); } + hasPressedNumber = false; break; case 'N': if (results != null) { displayOutput(results *= -1); - } else if (currNumber != null) { + } else { displayOutput(currNumber *= -1); } break; @@ -278,6 +334,7 @@ function buttonPress(val) { case '-': case '+': calculatorLogic(val); + hasPressedNumber = false; break; case '.': keys.R.val = 'C'; @@ -290,18 +347,24 @@ function buttonPress(val) { results = doMath(prevNumber, currNumber, operator); prevNumber = results; displayOutput(results); - hasPressedEquals = true; + hasPressedEquals = 1; } + hasPressedNumber = false; break; default: keys.R.val = 'C'; drawKey('R', keys.R); + const is0Negative = (currNumber === 0 && 1/currNumber === -Infinity); if (isDecimal) { - currNumber = currNumber == null ? 0 + '.' + val : currNumber + '.' + val; + currNumber = currNumber == null || hasPressedEquals === 1 ? 0 + '.' + val : currNumber + '.' + val; isDecimal = false; } else { - currNumber = currNumber == null ? val : currNumber + val; + currNumber = currNumber == null || hasPressedEquals === 1 ? val : (is0Negative ? '-' + val : currNumber + val); } + if (hasPressedEquals === 1) { + hasPressedEquals = 2; + } + hasPressedNumber = currNumber; displayOutput(currNumber); break; } @@ -315,38 +378,15 @@ for (var k in keys) { g.setFont('7x11Numeric7Seg', 2.8); g.drawString('0', 205, 10); - -setWatch(function() { - drawKey(selected, keys[selected]); - // key 0 is 2 keys wide, go up to 1 if it was previously selected - if (selected == '0' && prevSelected === '1') { - prevSelected = selected; - selected = '1'; - } else { - prevSelected = selected; - selected = keys[selected].trbl[0]; - } - drawKey(selected, keys[selected], true); -}, BTN1, {repeat: true, debounce: 100}); - -setWatch(function() { +function moveDirection(d) { drawKey(selected, keys[selected]); prevSelected = selected; - selected = keys[selected].trbl[2]; + selected = (d === 0 && selected == '0' && prevSelected === '1') ? '1' : keys[selected].trbl[d]; drawKey(selected, keys[selected], true); -}, BTN3, {repeat: true, debounce: 100}); +} -Bangle.on('touch', function(direction) { - drawKey(selected, keys[selected]); - prevSelected = selected; - if (direction == 1) { - selected = keys[selected].trbl[3]; - } else if (direction == 2) { - selected = keys[selected].trbl[1]; - } - drawKey(selected, keys[selected], true); -}); - -setWatch(function() { - buttonPress(selected); -}, BTN2, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(0), BTN1, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(2), BTN3, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(3), BTN4, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(1), BTN5, {repeat: true, debounce: 100}); +setWatch(_ => buttonPress(selected), BTN2, {repeat: true, debounce: 100}); diff --git a/apps/calculator/tests.html b/apps/calculator/tests.html new file mode 100644 index 000000000..1cbfdf617 --- /dev/null +++ b/apps/calculator/tests.html @@ -0,0 +1,273 @@ + + + + + + Calculator tests + + + + + + +
+ + + + + + + From 20f7c80462ce905288a987eda8455d9016771041 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:30:28 +0200 Subject: [PATCH 0489/1189] graphical adjustments --- apps/hidcam/app.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 6e599959c..89b8ac4a1 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -24,12 +24,10 @@ if (settings.HID) { } function drawApp() { g.clear(); - Bangle.loadWidgets() - Bangle.drawWidgets() -// g.setFont("6x8",2); -// g.setFontAlign(0,0); -// g.drawString(profile, 120, 120); - g.drawImage(storage.read("hidcam.img"),120,120) + Bangle.loadWidgets(); + Bangle.drawWidgets(); + g.fillCircle(122,127,60); + g.drawImage(storage.read("hidcam.img"),100,105); const d = g.getWidth() - 18; function c(a) { @@ -40,8 +38,7 @@ function drawApp() { buffer: (new Uint8Array(a)).buffer }; } - - g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); + g.fillRect(180,130, 240, 124); } if (camShot) { From d545a7a87d8a73270f90263e337a232339355360 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:36:47 +0200 Subject: [PATCH 0490/1189] changelog update --- apps/hidcam/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hidcam/ChangeLog b/apps/hidcam/ChangeLog index 665c0df6e..73b3268b7 100644 --- a/apps/hidcam/ChangeLog +++ b/apps/hidcam/ChangeLog @@ -1 +1 @@ -0.01: Init +0.01: Core functionnality From 406deafadd762bd45c427362a40a210c61fb8bbf Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 21:22:04 +0300 Subject: [PATCH 0491/1189] BlackJack game --- apps/blackjack/ChangeLog | 1 + apps/blackjack/blackjack.app.js | 191 ++++++++++++++++++++++++++++++++ apps/blackjack/blackjack.img | Bin 0 -> 706 bytes apps/blackjack/blackjack.info | 1 + 4 files changed, 193 insertions(+) create mode 100644 apps/blackjack/ChangeLog create mode 100644 apps/blackjack/blackjack.app.js create mode 100644 apps/blackjack/blackjack.img create mode 100644 apps/blackjack/blackjack.info diff --git a/apps/blackjack/ChangeLog b/apps/blackjack/ChangeLog new file mode 100644 index 000000000..c941d90e5 --- /dev/null +++ b/apps/blackjack/ChangeLog @@ -0,0 +1 @@ +0.01: New game! BTN4- Hit card, BTN5- Stand \ No newline at end of file diff --git a/apps/blackjack/blackjack.app.js b/apps/blackjack/blackjack.app.js new file mode 100644 index 000000000..dc5d35494 --- /dev/null +++ b/apps/blackjack/blackjack.app.js @@ -0,0 +1,191 @@ +const Clubs = { width : 48, height : 48, bpp : 1, + buffer : require("heatshrink").decompress(atob("ACcP+AFDn/8Aod//wFD///AgUBAoOAApsDAoPAAr4vLI4pTEgP8L4M/wEH/5rB//gh//x/x//wj//9/3//4n4iBAAIZBAol/Aof+Apv5z4FP+OPAo41BAoX8I4Pj45HBAoPD4YFBLIOD4JZBRAMD4CKC/AFBj59Cg/gQYYFXAB4=")) +}; + +const Spades = { width : 48, height : 48, bpp : 1, + buffer : require("heatshrink").decompress(atob("ABsBwAFDgfAAocH8AFDh/wAocf/AFDn/8Aod//wFD///FwYFBGAUDAoIwCg4FBGAUPAoIwCj4FBGAU/AoIwCv4FBGAQEBGAQuCGAQuCGAQFLHQQ8CAupHLL4prB+fPTgU/8fHVwbLLApbXFbpYFLdIoADA==")) +}; + +const Hearts = { width : 48, height : 48, bpp : 4, + buffer : require("heatshrink").decompress(atob("ADlVqtQBQ8FBYIKIrnMAAINGqoKC4okGCwYAB4AKDhgKE4oWKAAILDBQwYEBYwwDFwojFgoLHEgQ6H5hhCBZAkCBRAjLEgI6IC4YLIC5Y7BBZXBjgjVABYX/C8CnKABbXLABTvMC8sMC6fAC4KQURwIABRypgULwRgULwRIUCwhIRIwiRSRoZITCwx5POoowRCxAwNFxIwNCxQwLFxYwLCxgwJFxowJCxwwHFx4wHCyAwFFyIwFCyQwDFycAgoXBqAXTgFc4oWUJAJGUJARGVAEo")) + }; + +const Diamonds = { width : 48, height : 48, bpp : 4, + buffer : require("heatshrink").decompress(atob("AHUFC60M4AXV5nFIyvM5hGVC4JIUCwJIUIwRIUIwRIUCwZISIwgABqBGUJCQWFPKBGGJCFcC455OCw4wOOox5QIxB5NOpBIOFxZ5LCxYwKOpQwMIxh5KOxipLL6xgNR5QwMX5TvXPJZ1JJBpGLPJR1LJBZGNPJIWOJA5GOPJB1NJBIWQPIpGRJApGRPIoWSJAa8PJA5GTJAYWUJAJGVAAJGVAHo=")) + }; + + +var deck = []; +var player = {Hand:[]}; +var computer = {Hand:[]}; + +function createDeck() { + var suits = ["Spades", "Hearts", "Diamonds", "Clubs"]; + var values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]; + + var dck = []; + for (var i = 0 ; i < values.length; i++) { + for(var x = 0; x < suits.length; x++) { + dck.push({ Value: values[i], Suit: suits[x] }); + } + } + return dck; +} + +function shuffle(a) { + var j, x, i; + for (i = a.length - 1; i > 0; i--) { + j = Math.floor(Math.random() * (i + 1)); + x = a[i]; + a[i] = a[j]; + a[j] = x; + } + return a; +} + +function EndGameMessdage(msg){ + g.drawString(msg, 155, 200); + setTimeout(function(){ + startGame(); + }, 2500); + +} + +function hitMe() { + player.Hand.push(deck.pop()); + renderOnScreen(1); + var playerWeight = calcWeight(player.Hand, 0); + + if(playerWeight == 21) + EndGameMessdage('WINNER'); + else if(playerWeight > 21) + EndGameMessdage('LOOSER'); +} + +function calcWeight(hand, hideCard) { + + if(hideCard === 1) { + if (hand[0].Value == "J" || hand[0].Value == "Q" || hand[0].Value == "K") + return "10 +"; + else if (hand[0].Value == "A") + return "11 +"; + else + return parseInt(hand[0].Value) +" +"; + } + else { + var weight = 0; + for(i=0; i 21 || bangleWeight < playerWeight) + EndGameMessdage('WINNER'); + else if(bangleWeight > playerWeight) + EndGameMessdage('LOOSER'); +} + +function renderOnScreen(HideCard) { + const fontName = "6x8"; + + g.clear(); // clear screen + g.reset(); // default draw styles + g.setFont(fontName, 1); + + g.drawString('RST', 220, 35); + g.drawString('Hit', 60, 230); + g.drawString('Stand', 165, 230); + + g.setFont(fontName, 3); + for(i=0; i9WgH5ul2)7_0>|Km^WM! ktsjd-R^R}YcOcfVu~7y4Cx08IkIR{#J2 literal 0 HcmV?d00001 diff --git a/apps/blackjack/blackjack.info b/apps/blackjack/blackjack.info new file mode 100644 index 000000000..b30333f2e --- /dev/null +++ b/apps/blackjack/blackjack.info @@ -0,0 +1 @@ +{"id":"blackjack","name":"Black Jack","src":"blackjack.app.js","icon":"blackjack.img","version":"0.1","files":"blackjack.info,blackjack.app.js,blackjack.img"} \ No newline at end of file From 58d640a2e2dc08e79423ce984f9c1c0156e23a80 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:11:50 +0300 Subject: [PATCH 0492/1189] added blackjack game to apps.json --- apps.json | 12 ++++++++++++ apps/blackjack/blackjack.png | Bin 0 -> 646 bytes 2 files changed, 12 insertions(+) create mode 100644 apps/blackjack/blackjack.png diff --git a/apps.json b/apps.json index 0c97b9e57..0a6281c37 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,17 @@ "evaluate": true } ] + }, + { "id": "blackjack", + "name": "Black Jack game", + "shortName":"BlackJack game", + "icon": "blackjack.png", + "version":"0.01", + "description": "Simplle implementation of card game Black Jack", + "tags": "", + "storage": [ + {"name":"blackjack.app.js","url":"blackjack.app.js"}, + {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} + ] } ] diff --git a/apps/blackjack/blackjack.png b/apps/blackjack/blackjack.png new file mode 100644 index 0000000000000000000000000000000000000000..53715b5e44226d70a129a36fc2f663e4e6157f0e GIT binary patch literal 646 zcmV;10(t$3P)Px#1ZP1_K>z@;j|==^1poj5Fi=cXMF0Q*78VvLC@3~IHc3fIR8&-GXlQnJc87+Amh{@>F7O#lD@32;bRa{vGi!vFvd!vV){sAK>D0pCeP zK~y-)rIWu;6hRcnzXx|W!-?iPS{f2UNu$=DlaT_>83S%9tk^I!6*|as>t=o1 zrJvG>k!LXqxx|Z4A74gs{_PI%Akg(TfJI{Cugo!h<(+25uNnN{ERuBfM1wo3)LJn|XA$T-T{l3VA%^j=gFO901_m@WD5=}vb6`NG zp~0hQy+xe_M*_^V$jA-SJqspuhUDwPhYMI>u2sI{R&{~_ zO#|9M{X0KJ$pE7kvV(yxZ{BVjVAMjiQUAui9s?Oa?~ Date: Sat, 18 Apr 2020 22:20:09 +0300 Subject: [PATCH 0493/1189] adde icon for game --- apps/blackjack/blackjack-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/blackjack/blackjack-icon.js diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js new file mode 100644 index 000000000..5c184fe4a --- /dev/null +++ b/apps/blackjack/blackjack-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("ABsD4AECn//2AEBg/4gEQAoMIAQIFFjACHBYoFIh+AgEMGQXwAokfAoMP8EHwPghk//AXBmEMnl8n+AjEMvl8/4FCvE9AoMQAoM894XBgkYvgdCgkAAocGgF4AoNgAoPwAongAocB4AFDgeAAoPAg0HL4QFBhwFEjkGh+BwEGnEOAoUCv/+Apd//a3BAorBDAohLBgf+AocB/gFDgFMAogCCUoUH8AFDDASxDn/AYYQrB/DMCAAN/zAFDg7LBAAYlBAAoA==")) \ No newline at end of file From 98795281a190d9dd5ba9e6ff2217ba919d9f331e Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:20:57 +0300 Subject: [PATCH 0494/1189] fix typo in description --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0a6281c37..3b7ac0def 100644 --- a/apps.json +++ b/apps.json @@ -1299,7 +1299,7 @@ "shortName":"BlackJack game", "icon": "blackjack.png", "version":"0.01", - "description": "Simplle implementation of card game Black Jack", + "description": "Simple implementation of card game Black Jack", "tags": "", "storage": [ {"name":"blackjack.app.js","url":"blackjack.app.js"}, From 34e3748ee6ee01eddbf09e47b08ecc1c7dbc5303 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:27:58 +0300 Subject: [PATCH 0495/1189] add game tag and change icon --- apps.json | 5 +++-- apps/blackjack/blackjack-icon.js | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 apps/blackjack/blackjack-icon.js diff --git a/apps.json b/apps.json index 3b7ac0def..a62fa9ece 100644 --- a/apps.json +++ b/apps.json @@ -1300,10 +1300,11 @@ "icon": "blackjack.png", "version":"0.01", "description": "Simple implementation of card game Black Jack", - "tags": "", + "tags": "game", + "allow_emulator":true, "storage": [ {"name":"blackjack.app.js","url":"blackjack.app.js"}, - {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} + {"name":"blackjack.img","url":"blackjack.img"} ] } ] diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js deleted file mode 100644 index 5c184fe4a..000000000 --- a/apps/blackjack/blackjack-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("ABsD4AECn//2AEBg/4gEQAoMIAQIFFjACHBYoFIh+AgEMGQXwAokfAoMP8EHwPghk//AXBmEMnl8n+AjEMvl8/4FCvE9AoMQAoM894XBgkYvgdCgkAAocGgF4AoNgAoPwAongAocB4AFDgeAAoPAg0HL4QFBhwFEjkGh+BwEGnEOAoUCv/+Apd//a3BAorBDAohLBgf+AocB/gFDgFMAogCCUoUH8AFDDASxDn/AYYQrB/DMCAAN/zAFDg7LBAAYlBAAoA==")) \ No newline at end of file From aee60d97c0476dd7fd694a78e73e85d45ce4badf Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:43:29 +0300 Subject: [PATCH 0496/1189] Fix icon --- apps.json | 4 ++-- apps/blackjack/blackjack-icon.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 apps/blackjack/blackjack-icon.js diff --git a/apps.json b/apps.json index a62fa9ece..6e221c778 100644 --- a/apps.json +++ b/apps.json @@ -1296,7 +1296,7 @@ }, { "id": "blackjack", "name": "Black Jack game", - "shortName":"BlackJack game", + "shortName":"Black Jack game", "icon": "blackjack.png", "version":"0.01", "description": "Simple implementation of card game Black Jack", @@ -1304,7 +1304,7 @@ "allow_emulator":true, "storage": [ {"name":"blackjack.app.js","url":"blackjack.app.js"}, - {"name":"blackjack.img","url":"blackjack.img"} + {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} ] } ] diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js new file mode 100644 index 000000000..f0976a5be --- /dev/null +++ b/apps/blackjack/blackjack-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIQNgfAAgU/+UQAgMHmEAAoUIAQIFFjACHBYoFIgeAAocA+EAhgFCg4FBg/ggeB8EMj/4h+AmEMnl4j+AjEMvF8v4FDnv3wEQhk4nnnC4MEjE8g4FCgF4Ao8gAoNwAoNgg0A8AFDgPAAoZXBAoPAgxQBAocOAokcBoOAwEGnEOg+BwECv/+AosPAol//MAAoP8v/7RgLBDAokCAoO8AoJRBgHMAolMAogCCNIJLBcQKrCgP8WIk7wC9Dgf4ZgQABu4FEYIIFDRYIFEAAI")) \ No newline at end of file From 0c03bce926a8cac1282001c885dfa9d28eafde33 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:45:33 +0300 Subject: [PATCH 0497/1189] icon brightness --- apps/blackjack/blackjack-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js index f0976a5be..cb4d00cdd 100644 --- a/apps/blackjack/blackjack-icon.js +++ b/apps/blackjack/blackjack-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwgIQNgfAAgU/+UQAgMHmEAAoUIAQIFFjACHBYoFIgeAAocA+EAhgFCg4FBg/ggeB8EMj/4h+AmEMnl4j+AjEMvF8v4FDnv3wEQhk4nnnC4MEjE8g4FCgF4Ao8gAoNwAoNgg0A8AFDgPAAoZXBAoPAgxQBAocOAokcBoOAwEGnEOg+BwECv/+AosPAol//MAAoP8v/7RgLBDAokCAoO8AoJRBgHMAolMAogCCNIJLBcQKrCgP8WIk7wC9Dgf4ZgQABu4FEYIIFDRYIFEAAI")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwgIQNgfAAgU///wAgMH/4dBAoMMAQMQAQMIAQMYAQ4RCApcPwAFDgIwBAoQ4BAoMP8EHwfghk//AXBuEMv38n+AjEMvl8/4FDvoFBmEMvF994FBg04vgdBAoMAAot4AoNgAoPwAoZFBAongAoPggyIBAoPAg0HwAFDh4BBAoUeh0PwOAg08AocDv/+Ao3DAod//a3BAorBDAohRBgf+AocBAokApgCBhzSCWIkHVYgYCWIngYwQrB/gFDgF//AFDD4QAD8AFEAAIA=")) \ No newline at end of file From 79f18015ef8ae54f9ff24eb1573fb2acb6f9bb8a Mon Sep 17 00:00:00 2001 From: fredericrous Date: Sat, 18 Apr 2020 22:05:36 +0100 Subject: [PATCH 0498/1189] Add Calculator App Readme --- apps/calculator/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 apps/calculator/README.md diff --git a/apps/calculator/README.md b/apps/calculator/README.md new file mode 100644 index 000000000..78848908a --- /dev/null +++ b/apps/calculator/README.md @@ -0,0 +1,23 @@ +# Calculator + +Basic calculator reminiscent of MacOs's one. Handy for small calculus. + + + +## Features + +- add / substract / divide / multiply +- handles floats +- basic memory button + +## Controls + +- UP: BTN1 +- DOWN: BTN3 +- LEFT: BTN4 +- RIGHT: BTN5 +- SELECT: BTN2 + +## Creator + + From 0df1fb19e3d45f92ed5e490c11a59017df9d27eb Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Sun, 19 Apr 2020 13:55:20 +0200 Subject: [PATCH 0499/1189] initial commit adding metronome app --- apps.json | 20 +++++++ apps/metronome/README.md | 10 ++++ apps/metronome/metronome-icon.js | 1 + apps/metronome/metronome.info | 1 + apps/metronome/metronome.js | 93 ++++++++++++++++++++++++++++++ apps/metronome/metronome_icon.png | Bin 0 -> 7575 bytes 6 files changed, 125 insertions(+) create mode 100644 apps/metronome/README.md create mode 100644 apps/metronome/metronome-icon.js create mode 100644 apps/metronome/metronome.info create mode 100644 apps/metronome/metronome.js create mode 100644 apps/metronome/metronome_icon.png diff --git a/apps.json b/apps.json index 0c97b9e57..590a85e38 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,25 @@ "evaluate": true } ] + }, + { + "id": "Metronome", + "name": "Metronome", + "icon": "metronome_icon.png", + "version": "0.03", + "description": "Makes the watch blinking and vibrating with a given rate", + "tags": "tool", + "allow_emulator": true, + "storage": [ + { + "name": "metronome.app.js", + "url": "metronome.js" + }, + { + "name": "metronome.img", + "url": "metronome-icon.js", + "evaluate": true + } + ] } ] diff --git a/apps/metronome/README.md b/apps/metronome/README.md new file mode 100644 index 000000000..19d489327 --- /dev/null +++ b/apps/metronome/README.md @@ -0,0 +1,10 @@ +# Metronome + +This metronome makes your watch blink and vibrate with a given rate. + +## Usage + +* Tap the screen at least three times. The app calculates the mean rate of your tapping. This rate is displayed in bmp while the text blinks and the watch softly vibrates with every beat. +* 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`. diff --git a/apps/metronome/metronome-icon.js b/apps/metronome/metronome-icon.js new file mode 100644 index 000000000..8b45f233b --- /dev/null +++ b/apps/metronome/metronome-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+ABt4AB4fOFyFOABtUGDotOAAYvcp4ARqovbq0rACAvbqwABF98yGCAvdGAcHgAAEF8tWmIuGGA6QaF4lWFw4vgFwovPmIvuYDIvd0ejF59cF6qQFFwIvnMAguSqxfaFyQvYvOi0QuTF64uCAAQuRXwIvUqouEF6guFF5+cAAiOZF6iOaF5sxv+iF6xfRmVWFwWjv8rp4tSL6YvBqwuDMgQvnFwovURwIvQRggAELygvPgwuIF8ouEBwIvnFwwwXF54uBvwuFq0yF6buCF5guClQuFGAgvfFwcAF49WmIvRFwQvKFwkAmQvHYQMxF7l+FwgvKGAIvalQuGF5dWFx1VABVUvF4p0qAAdPCZNPF51OAD4vOKQIACF/4waF9wuEqgv/F/gwMF97vvAAUqADYtQAAMAADYuRGDgmLA=")) diff --git a/apps/metronome/metronome.info b/apps/metronome/metronome.info new file mode 100644 index 000000000..74dcbd2c7 --- /dev/null +++ b/apps/metronome/metronome.info @@ -0,0 +1 @@ +{"id":"metronome","name":"Metronome","src":"metronome.app.js", "icon": "metronome_icon.png", "sortorder":-2,"version":"0.03","files":"metronome.info,metronome.app.js, metronome_icon.png"} diff --git a/apps/metronome/metronome.js b/apps/metronome/metronome.js new file mode 100644 index 000000000..acd4b70b8 --- /dev/null +++ b/apps/metronome/metronome.js @@ -0,0 +1,93 @@ +var tStart = Date.now(); +var cindex=0; // index to iterate through colous +var bpm=60; // ininital bpm value +var time_diffs = [1000, 1000, 1000]; //array to calculate mean bpm +var tindex=0; //index to iterate through time_diffs + +Bangle.setLCDTimeout(undefined); //do not deaktivate display while running this app + +function changecolor() { + const maxColors = 2; + const colors = { + 0: { value: 0xFFFF, name: "White" }, + 1: { value: 0x000F, name: "Navy" }, + // 2: { value: 0x03E0, name: "DarkGreen" }, + // 3: { value: 0x03EF, name: "DarkCyan" }, + // 4: { value: 0x7800, name: "Maroon" }, + // 5: { value: 0x780F, name: "Purple" }, + // 6: { value: 0x7BE0, name: "Olive" }, + // 7: { value: 0xC618, name: "LightGray" }, + // 8: { value: 0x7BEF, name: "DarkGrey" }, + // 9: { value: 0x001F, name: "Blue" }, + // 10: { value: 0x07E0, name: "Green" }, + // 11: { value: 0x07FF, name: "Cyan" }, + // 12: { value: 0xF800, name: "Red" }, + // 13: { value: 0xF81F, name: "Magenta" }, + // 14: { value: 0xFFE0, name: "Yellow" }, + // 15: { value: 0xFFFF, name: "White" }, + // 16: { value: 0xFD20, name: "Orange" }, + // 17: { value: 0xAFE5, name: "GreenYellow" }, + // 18: { value: 0xF81F, name: "Pink" }, + }; + g.setColor(colors[cindex].value); + if (cindex == maxColors-1) { + cindex = 0; + } + else { + cindex += 1; + } + return cindex; +} + +function updateScreen() { + g.clear(); + changecolor(); + Bangle.buzz(50, 0.75); + g.setFont("Vector",48); + g.drawString(Math.floor(bpm)+"bpm", -1, 70); +} + +Bangle.on('touch', function(button) { +// setting bpm by tapping the screen. Uses the mean time difference between several tappings. + if (tindex < time_diffs.length) { + if (Date.now()-tStart < 5000) { + time_diffs[tindex] = Date.now()-tStart; + } + } else { + tindex=0; + time_diffs[tindex] = Date.now()-tStart; + } + tindex += 1; + mean_time = 0.0; + for(count = 0; count < time_diffs.length; count++) { + mean_time += time_diffs[count]; + } + time_diff = mean_time/count; + + tStart = Date.now(); + clearInterval(time_diff); + g.clear(); + g.setFont("Vector",48); + bpm = (60 * 1000/(time_diff)); + g.drawString(Math.floor(bpm)+"bpm", -1, 70); + clearInterval(interval); + interval = setInterval(updateScreen, 60000 / bpm); + return bpm; +}); + +// enable bpm finetuning via buttons. +setWatch(() => { + bpm += 1; + clearInterval(interval); + interval = setInterval(updateScreen, 60000 / bpm); +}, BTN1, {repeat:true}); + +setWatch(() => { + if (bpm > 1) { + bpm -= 1; + clearInterval(interval); + interval = setInterval(updateScreen, 60000 / bpm); + } +}, BTN3, {repeat:true}); + +interval = setInterval(updateScreen, 60000 / bpm); diff --git a/apps/metronome/metronome_icon.png b/apps/metronome/metronome_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4dac7117f9e91221b0cfec54538e339c81df1939 GIT binary patch literal 7575 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 literal 0 HcmV?d00001 From 28dc51c377cb8b1c692df97f5f0bbc741b16ed7d Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Sun, 19 Apr 2020 14:03:11 +0200 Subject: [PATCH 0500/1189] correct app path --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 590a85e38..83c0ba88f 100644 --- a/apps.json +++ b/apps.json @@ -1295,7 +1295,7 @@ ] }, { - "id": "Metronome", + "id": "metronome", "name": "Metronome", "icon": "metronome_icon.png", "version": "0.03", From 0bdf476ea6fe78aafaaf5318d92ac7f0fe8b5b60 Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Sun, 19 Apr 2020 14:13:26 +0200 Subject: [PATCH 0501/1189] remove metronome.info --- apps/metronome/metronome.info | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/metronome/metronome.info diff --git a/apps/metronome/metronome.info b/apps/metronome/metronome.info deleted file mode 100644 index 74dcbd2c7..000000000 --- a/apps/metronome/metronome.info +++ /dev/null @@ -1 +0,0 @@ -{"id":"metronome","name":"Metronome","src":"metronome.app.js", "icon": "metronome_icon.png", "sortorder":-2,"version":"0.03","files":"metronome.info,metronome.app.js, metronome_icon.png"} From 1596b0246b9693bdf7fd26a04417e49aa61dfb9d Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sun, 19 Apr 2020 16:18:13 +0200 Subject: [PATCH 0502/1189] Add setting to hide widget when battery is over 20%. --- apps/widbatpc/{settings.js => widbatpc.settings.js} | 12 +++++++++--- apps/widbatpc/widbatpc.settings.json | 1 + apps/widbatpc/{widget.js => widbatpc.wid.js} | 13 ++++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) rename apps/widbatpc/{settings.js => widbatpc.settings.js} (88%) create mode 100644 apps/widbatpc/widbatpc.settings.json rename apps/widbatpc/{widget.js => widbatpc.wid.js} (95%) diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/widbatpc.settings.js similarity index 88% rename from apps/widbatpc/settings.js rename to apps/widbatpc/widbatpc.settings.js index 5c0bdbcae..9f39b5d07 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/widbatpc.settings.js @@ -11,6 +11,7 @@ 'color': COLORS[0], 'percentage': true, 'charger': true, + 'hideifmorethan20pct': false, } // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -51,8 +52,13 @@ const newIndex = (oldIndex + 1) % COLORS.length s.color = COLORS[newIndex] save('color')(s.color) - }, - }, - } + } + }, + 'Hide when \> 20\%': { + value: s.hideifmorethan20pct, + format: onOffFormat, + onchange: save('hideifmorethan20pct'), + }, + } E.showMenu(menu) }) diff --git a/apps/widbatpc/widbatpc.settings.json b/apps/widbatpc/widbatpc.settings.json new file mode 100644 index 000000000..7a22adfc0 --- /dev/null +++ b/apps/widbatpc/widbatpc.settings.json @@ -0,0 +1 @@ +{"color":"By Level","percentage":true,"charger":true,"hideifmorethan20pct":false} diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widbatpc.wid.js similarity index 95% rename from apps/widbatpc/widget.js rename to apps/widbatpc/widbatpc.wid.js index aca690ce0..959ec211f 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widbatpc.wid.js @@ -3,6 +3,7 @@ const DEFAULTS = { 'color': 'By Level', 'percentage': true, 'charger': true, + 'hideifmorethan20pct': false, } const COLORS = { 'white': -1, @@ -53,8 +54,16 @@ function setWidth() { } } function draw() { + var s = 39; var x = this.x, y = this.y; + const l = E.getBattery(), + c = levelColor(l); + const xl = x+4+l*(s-12)/100 + + if(!Bangle.isCharging() && setting('hideifmorethan20pct') && l > 20){ + return;} + if (Bangle.isCharging() && setting('charger')) { g.setColor(chargerColor()).drawImage(atob( "DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y); @@ -64,9 +73,7 @@ function draw() { g.fillRect(x,y+2,x+s-4,y+21); g.clearRect(x+2,y+4,x+s-6,y+19); g.fillRect(x+s-3,y+10,x+s,y+14); - const l = E.getBattery(), - c = levelColor(l); - const xl = x+4+l*(s-12)/100 + g.setColor(c).fillRect(x+4,y+6,xl,y+17); g.setColor(-1); if (!setting('percentage')) { From d2270eaae6565a322895e25afb3c638a26c2b186 Mon Sep 17 00:00:00 2001 From: Frederic R Date: Sun, 19 Apr 2020 16:48:33 +0100 Subject: [PATCH 0503/1189] Update App Calculator's Readme. Larger image --- apps/calculator/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/calculator/README.md b/apps/calculator/README.md index 78848908a..b25d355bf 100644 --- a/apps/calculator/README.md +++ b/apps/calculator/README.md @@ -2,7 +2,7 @@ Basic calculator reminiscent of MacOs's one. Handy for small calculus. - + ## Features From 4d52de224ceddc49aabc107bf246374da8393106 Mon Sep 17 00:00:00 2001 From: Stefano Baldan Date: Sun, 19 Apr 2020 18:03:14 +0200 Subject: [PATCH 0504/1189] Added app for running --- apps.json | 21 +++ apps/banglerun/ChangeLog | 1 + apps/banglerun/app-icon.js | 1 + apps/banglerun/app.js | 314 +++++++++++++++++++++++++++++++++++ apps/banglerun/banglerun.png | Bin 0 -> 10456 bytes 5 files changed, 337 insertions(+) create mode 100755 apps/banglerun/ChangeLog create mode 100644 apps/banglerun/app-icon.js create mode 100644 apps/banglerun/app.js create mode 100644 apps/banglerun/banglerun.png diff --git a/apps.json b/apps.json index 0c97b9e57..143b02bd3 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,26 @@ "evaluate": true } ] + }, + { + "id": "banglerun", + "name": "BangleRun", + "shortName": "BangleRun", + "icon": "banglerun.png", + "version": "0.01", + "description": "An app for running sessions.", + "tags": "run,running,fitness,outdoors", + "allow_emulator": false, + "storage": [ + { + "name": "banglerun.app.js", + "url": "app.js" + }, + { + "name": "banglerun.img", + "url": "app-icon.js", + "evaluate": true + } + ] } ] diff --git a/apps/banglerun/ChangeLog b/apps/banglerun/ChangeLog new file mode 100755 index 000000000..7b83706bf --- /dev/null +++ b/apps/banglerun/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/banglerun/app-icon.js b/apps/banglerun/app-icon.js new file mode 100644 index 000000000..0ccbedab4 --- /dev/null +++ b/apps/banglerun/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwMB/4ACx4ED/0DApP8AqAXB84GDg/DAgXj/+DCAUABgIFB4EAv4FCwEAj0PAoJPBgwFEgEfDgMOAoM/AoMegFAAoP8jkA8F/AoM8gP4DgP4nBvD/F4KQfwuAFE+A/CAoPgAofx8A/CKYRwELIIFDLII6BAoZSBLIYeC/0BwAFDgfAGAQFBHgf8g4BBIIUH/wFBSYMPAoXwAog/Bj4FEv4FDDQQCBQoQFCZYYFi/6KE/+P/4A=")) diff --git a/apps/banglerun/app.js b/apps/banglerun/app.js new file mode 100644 index 000000000..fc21e3627 --- /dev/null +++ b/apps/banglerun/app.js @@ -0,0 +1,314 @@ +/** Global constants */ +const DEG_TO_RAD = Math.PI / 180; +const EARTH_RADIUS = 6371008.8; + +/** Utilities for handling vectors */ +class Vector { + static magnitude(a) { + let sum = 0; + for (const key of Object.keys(a)) { + sum += a[key] * a[key]; + } + return Math.sqrt(sum); + } + + static add(a, b) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] + b[key]; + } + return result; + } + + static sub(a, b) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] - b[key]; + } + return result; + } + + static multiplyScalar(a, x) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] * x; + } + return result; + } + + static divideScalar(a, x) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] / x; + } + return result; + } +} + +/** Interquartile range filter, to detect outliers */ +class IqrFilter { + constructor(size, threshold) { + const q = Math.floor(size / 4); + this._buffer = []; + this._size = 4 * q + 2; + this._i1 = q; + this._i3 = 3 * q + 1; + this._threshold = threshold; + } + + isReady() { + return this._buffer.length === this._size; + } + + isOutlier(point) { + let result = true; + if (this._buffer.length === this._size) { + result = false; + for (const key of Object.keys(point)) { + const data = this._buffer.map(item => item[key]); + data.sort((a, b) => (a - b) / Math.abs(a - b)); + const q1 = data[this._i1]; + const q3 = data[this._i3]; + const iqr = q3 - q1; + const lower = q1 - this._threshold * iqr; + const upper = q3 + this._threshold * iqr; + if (point[key] < lower || point[key] > upper) { + result = true; + break; + } + } + } + this._buffer.push(point); + this._buffer = this._buffer.slice(-this._size); + return result; + } +} + +/** Process GPS data */ +class Gps { + constructor() { + this._lastCall = Date.now(); + this._lastValid = 0; + this._coords = null; + this._filter = new IqrFilter(10, 1.5); + this._shift = { x: 0, y: 0, z: 0 }; + } + + isReady() { + return this._filter.isReady(); + } + + getDistance(gps) { + const time = Date.now(); + const interval = (time - this._lastCall) / 1000; + this._lastCall = time; + + if (!gps.fix) { + return { t: interval, d: 0 }; + } + + const p = gps.lat * DEG_TO_RAD; + const q = gps.lon * DEG_TO_RAD; + const coords = { + x: EARTH_RADIUS * Math.sin(p) * Math.cos(q), + y: EARTH_RADIUS * Math.sin(p) * Math.sin(q), + z: EARTH_RADIUS * Math.cos(p), + }; + + if (!this._coords) { + this._coords = coords; + this._lastValid = time; + return { t: interval, d: 0 }; + } + + const ds = Vector.sub(coords, this._coords); + const dt = (time - this._lastValid) / 1000; + const v = Vector.divideScalar(ds, dt); + + if (this._filter.isOutlier(v)) { + return { t: interval, d: 0 }; + } + + this._shift = Vector.add(this._shift, ds); + const length = Vector.magnitude(this._shift); + const remainder = length % 10; + const distance = length - remainder; + + this._coords = coords; + this._lastValid = time; + if (distance > 0) { + this._shift = Vector.multiplyScalar(this._shift, remainder / length); + } + + return { t: interval, d: distance }; + } +} + +/** Process step counter data */ +class Step { + constructor(size) { + this._buffer = []; + this._size = size; + } + + getCadence() { + this._buffer.push(Date.now() / 1000); + this._buffer = this._buffer.slice(-this._size); + const interval = this._buffer[this._buffer.length - 1] - this._buffer[0]; + return interval ? Math.round(60 * (this._buffer.length - 1) / interval) : 0; + } +} + +const gps = new Gps(); +const step = new Step(10); + +let totDist = 0; +let totTime = 0; +let totSteps = 0; + +let speed = 0; +let cadence = 0; +let heartRate = 0; + +let gpsReady = false; +let hrmReady = false; +let running = false; + +function formatClock(date) { + return ('0' + date.getHours()).substr(-2) + ':' + ('0' + date.getMinutes()).substr(-2); +} + +function formatDistance(m) { + return ('0' + (m / 1000).toFixed(2) + ' km').substr(-7); +} + +function formatTime(s) { + const hrs = Math.floor(s / 3600); + const min = Math.floor(s / 60); + const sec = Math.floor(s % 60); + return (hrs ? hrs + ':' : '') + ('0' + min).substr(-2) + `:` + ('0' + sec).substr(-2); +} + +function formatSpeed(kmh) { + if (kmh <= 0.6) { + return `__'__"`; + } + const skm = 3600 / kmh; + const min = Math.floor(skm / 60); + const sec = Math.floor(skm % 60); + return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; +} + +function drawBackground() { + g.setColor(running ? 0x00E0 : 0x0000); + g.fillRect(0, 30, 240, 240); + + g.setColor(0xFFFF); + g.setFontAlign(0, -1, 0); + g.setFont('6x8', 2); + + g.drawString('DISTANCE', 120, 50); + g.drawString('TIME', 60, 100); + g.drawString('PACE', 180, 100); + g.drawString('STEPS', 60, 150); + g.drawString('STP/m', 180, 150); + g.drawString('SPEED', 40, 200); + g.drawString('HEART', 120, 200); + g.drawString('CADENCE', 200, 200); +} + +function draw() { + const totSpeed = totTime ? 3.6 * totDist / totTime : 0; + const totCadence = totTime ? Math.round(60 * totSteps / totTime) : 0; + + g.setColor(running ? 0x00E0 : 0x0000); + g.fillRect(0, 30, 240, 50); + g.fillRect(0, 70, 240, 100); + g.fillRect(0, 120, 240, 150); + g.fillRect(0, 170, 240, 200); + g.fillRect(0, 220, 240, 240); + + g.setFont('6x8', 2); + + g.setFontAlign(-1, -1, 0); + g.setColor(gpsReady ? 0x07E0 : 0xF800); + g.drawString(' GPS', 6, 30); + + g.setFontAlign(1, -1, 0); + g.setColor(0xFFFF); + g.drawString(formatClock(new Date()), 234, 30); + + g.setFontAlign(0, -1, 0); + g.setFontVector(20); + g.drawString(formatDistance(totDist), 120, 70); + g.drawString(formatTime(totTime), 60, 120); + g.drawString(formatSpeed(totSpeed), 180, 120); + g.drawString(totSteps, 60, 170); + g.drawString(totCadence, 180, 170); + + g.setFont('6x8', 2); + g.drawString(formatSpeed(speed), 40, 220); + + g.setColor(hrmReady ? 0x07E0 : 0xF800); + g.drawString(heartRate, 120, 220); + + g.setColor(0xFFFF); + g.drawString(cadence, 200, 220); +} + +function handleGps(coords) { + const step = gps.getDistance(coords); + gpsReady = coords.fix > 0 && gps.isReady(); + speed = isFinite(gps.speed) ? gps.speed : 0; + if (running) { + totDist += step.d; + totTime += step.t; + } +} + +function handleHrm(hrm) { + hrmReady = hrm.confidence > 50; + heartRate = hrm.bpm; +} + +function handleStep() { + cadence = step.getCadence(); + if (running) { + totSteps += 1; + } +} + +function start() { + running = true; + drawBackground(); + draw(); +} + +function stop() { + if (!running) { + totDist = 0; + totTime = 0; + totSteps = 0; + } + running = false; + drawBackground(); + draw(); +} + +Bangle.on('GPS', handleGps); +Bangle.on('HRM', handleHrm); +Bangle.on('step', handleStep); + +Bangle.setGPSPower(1); +Bangle.setHRMPower(1); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawBackground(); +draw(); + +setInterval(draw, 500); + +setWatch(start, BTN1, { repeat: true }); +setWatch(stop, BTN3, { repeat: true }); diff --git a/apps/banglerun/banglerun.png b/apps/banglerun/banglerun.png new file mode 100644 index 0000000000000000000000000000000000000000..bf2cd8af3ef5f9711d18df1656a03a98283bcc67 GIT binary patch literal 10456 zcmV;}C@0s6P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3>tk{!8{rT=3Uvjk|d97wa-K`(#4gNU1gRj;~h ztjQuXc{2n8a6iHwQD*V0O-!Zcmb2woY_a*yH`PAB+Wp(vc>lh?!uuos z{p)k{^#jjG;rqza-{U)yexd!hLrc!%=-iC@EdzUbfP*9V1JT8SG4?{{#)-oNWJg7Ez5{E7VSLgP4o zdOu-~^rgNRV?usC-sh{eKPTwdB!9j$f6o5bcYjR2@9*c~kGah69P!QH{=lU_J`Z2F z@qdKFJ0k!42giEe>Z+t z+wEk@mz{R-d%EU4t8$EsZn^G`+xP2qlOaaGec`M3(}(+64aGM!Rs78a}K z!}QyPz{mb;EbiX7-TO^fx$|-y>Kzwzobn%kn}7P@zxi#>nVKSJ>(^W{t~=ojLo27h zIf?~w=UumSC;0RGU4Hu`eh5`oFx_dcJYcuuxx`5BJGR1I=fH7^uTKg&Q`UO{rignd z2IB%NV6zL!WoL``#X07&vOt}Y`w;zL1zbvgF-RXn$lerRz3$C9#oc3l^4aTSu!)68 zA&0`+w9r|s7!&bRVkL%p3MrLyX zwboX9^DTgZspVE$ZLRh0P3K0PYjuwAd@}q9BaSrkD5H)x`Xqd2oN4A+W}R*J~|vuaB`H}8r)S*SU+f$Zbwdu-F@S#7TB z&kTDUTh6Y2czt1bW9QIMPvc~s&=1g&V**L6tHl=1Vaie@*Y;Sp9=~P_yVdP`IU$jN zD<*KyH#q2|xkKwU#=f|VU}EON0g)x+R9hJW1nGM`o^#_O`}jedzMsgUji;%czBbc1 zqc3wrZ%^N)a=RACW?Eh2+4CkKIp+kTYPYgW6zQMRiKd-M^|H!HKE^U<(KRyHi0`RC z&g6s3{U>ccjEUugy1@@-rg4!FW{P!p7q|3+k1W~z+^dE;!d~3Q>o&&Q`xq?ym_41u zEx_mfIb-vH)xM9HYCOzibc|shmqK}-k69~b&U64B8wr$&j3@*r=bpLpAx$6%K94@$ z8L!M*+$oeA;O zD#zrtQfi|(Lte}?=d?N4UdAdg7$Z1t5&N9F3Kuy8ggu@Sg^_r`+7{r;gfj;tI08Bw zIKI@yy&VxvkS~~W=+rViVO95bS)?0_U4u}yd(Xlu)m7|>c2Baq<=TxfeIF97%-oLM zX(U!-EHbx87d>IXI1V$g8D00MGH=-tNOgudT1l2+I0CYES6Ob>s@UGUZrex6S%=p| ziV}<|?x=7lwE_U)w(VnX(rMP1lrAS4CN?thDQK$mW~w8>5g2<=o)qN?jOF&=cHNRc z3>UxbmU3U^taP!b z^tMh;F>n=zS2h78P-o8c@F^=G_Zl1z3^EXoJzOD=;YJC=DR^-w%Jx5;7>he=5lTRMaBUKhV2D5|1y?I!0Lm33^h$&IO&OenS-RBT zs9cqa;#s{OD&K*EBzwG}0he^F7R#>?tgJ_;cBV!kg#?WDjc%(H@Ya z5nS+I%kbVH;PW^JD5)&isSFAg86N6O74&2!=S>iD@=1`Q1mPltQoiZIMPD*CmrcE{ z8aS#T<8;xZQ2F9h;`d%uewVMK>>O`~uq1s00jrfCDH7ilIZaUzktu*NGaD3(Vb5O6 z7~;MKSn-TMQiK&WOVIt}Xf(un4*iu)9$*(kB0|O?zWEMm^rnZh!#wG+2>d9*x;$M( zBkrb0QhFRvc-INo|9yJs979NKa)R;n)yVPhp#Q{t@K4M;k}^JdRNY^WG(QiGi^+qd zW`xpOgusYgKzTB)0{NIT5P}g&VQ&Uc_{9VAT8Rh}W|I*55cvZ`p2K2;y(47g!Rf^N zMZ_I0GO{i}?x}l`aLo;$AroR0o$ZKKevkwsyN}}#1>Uhn#QY2+6F<2zwFAWz3zHiN z#F}$Tt2?&<8P5{oMW#j~YKF5B0mtUthvVE{5de#P_0f9xF>e@oATEQ%Voqp{6hY{M z89m0g0-9qhNu^O2^UE;ua$_=-Ho@4;qlCf_plJ_>r@T60rt!2!To>uvX?UEe_W zxaCAoNb;`<{iBNSyrhaiB=fKVbuq;B9^l~xQsw^G^!sx(-dcBo(_l@vgX4}H8G*Y| z$9Vz^cStOdYY<9nNs>IJY0sb-REI+9g3VgN%y^I@fGlDZb%Qg_*=I5Z5wd1N zz5oy#;f3ZwE}f3h!@@4c>}Kw$y(`Y3O@}I-OUQ0)53Kc;5{O_o`H9*=BrTZ;%m}zn zUI3$oLmaNDqbIaXK=$K4 z+La8FO;<9QF{j1>bDUddxjH1GSAWQcJrIK}t=cf@66q5jWa`K#a%atgn=w$tex{Rv z!lx|(G!78K5Be+!3OP;qcEOi`bi7!J=R-)2rpqJV&0_*|UXfQ!Je(r3)$jA>i<;#@ z&5Vh8yaSP4IkyNA4fq{(Q~P~WG^Dh`$}boaFn@Ci(bhV^55R~|Gn~cH(3P&|KQ2H# z5;_f^OFA70x)LcTqD)BJc||+W(w0)jnI+j?gwnG=sy$p>g>pggiTv3J ziOj4fGzzDY8?dv1=@D5+)NnZ!06cBNNQ@Ue3cU)KS%etKKCH6eTW}DDUnx4f8WzOY zW7b{rQPNI}yP(MxnyarF$`E)hg1M3Y&N-EIw%j3lc}vOqW7p*W9+N7*F7q^+nQF4X2=gbgIX2gCpHH|WO9lX8{$&H%e(h5(rBktX4r zV~rDo3TXmwx<}I03d(6)}fp z&JtE2?8X&-E|8ljqaFgcDjn-pl4>juIDPA_{^%{F0Sb{-H9$TDK72~5vGo>nx$#1f z30i=#U>OWl0OLmFpk}S733T9^Gn!Bu*U1={iA6;#5s=$X-%Q=k^MQ7?a?o_XM_O!3@Q zZRs>I7v8*I|1+0+OObtlg1VorK5J0x$$!7}JBO7PIeTeJG$^0X?M3%TO!@>1(9s%1D(4 zoAUfbF4^l`G{n=s;s?#pQNvi-fjbr$Vb^)C9r9N|DVcF!7!&+I;TjM;kM2pPR|zp- zRE~0B37upHR4*>A7-zB_nTX%Uy@teq$=l#%br@=8nl2jyBO*xn4w+x@)Od`bXLeTs z21l%0p*B|NkvC-N3?7z7P!lB6y-;ngzOg(;X$isk_J1%eG4?(t?U31EaAM?Py6@a^s zHJpfjWE0^FG-Y>Hld4GAhbe@#?IPqWY|(DRVj*^tVo-UJTS~$d)nh^{s=1$#I;L*| z%}d38fM0scL8s|LB4J9_klH2+mtlTfXKAo9P(4|7$OG13Z5`;^Z!M{?M7x3RvndXn zyCwudfl67hNYAN-TNQcLh%%DZhV&4=@`&kmbG1f$GZ!N}-y^>YEvC$QV2)pq@ZTfC zUyCi~Q*HUwT=$T_+yrDq;>mVp%Yy)d$ex6ZLdxw8psH+I(4pipD#jVOY__kfY) zxLAX1J!`86$l>@kDVyK2C1pA7b)B}6)fOA%epCMuJET6+bY=nxbA-@muAupvm{r(T z%ZPSW4UfzMq&?st#!wkY5(_;`mUNjwbi~-CW>qeyCcKS=q9(R^K_b9?V~&JK1l9OOh^h9d7l;a>fc0mtJd0c{vdQ<0e}n)M z3u+Vov5*GnhPzoGMnOuW-7Iu>N&6}Isr=Gk40(|9srbktL>~V1%gyGiO1d-Z5Nd68 zS}-HLz)PGoya@I@wjr>102F6@$nxB5WtMf%^fz2ahx)Es$KpTgQ5md!PeM$AREX+yJx- z1WD=uAvsGNNfeTM3x(MDRkR%;O~t`=(MSGrZIvXY|5!aDm1%{K0&_#OR-kD`lNA{V zGNcNtA`HaQk!=B`Re+EnO!kr|MPA6A?Ut68$v&e2A&+g%@L(a7uWjYh zueS%qRD)JlsRsa-%0*%o2)o?_RJ)Ra)+`~|Zj7jR@f5TfO^QBfwLpNblH_EJX)~sh z%W%5+ev0=DqB^5&$`f0`tlZ*#NUEz;t(RC0j8-oIy`mE%76%enAB?CN83j-Q%%Vy} z6`K))hz_U1PY2Pl$Vi!MIN+v>Il=`X4Lc9MRLQZ9+=@?a4$LxNdhGnvV+V@jPY52l6=h@Y~Em3M0u? z2vA`%j0RA{oTPa1A;hjw>xI4@k&D2ocd3#7v%KPt8clD3h1jY@je@rSMR4uv#SX^~5Dv;#E0}Sp%!s8% zWo$ z1(;kG$wu%Z7IdBwd~J_qn{mD;LW|n#(p;QhL8*odN#VPComE8olv}WX5C;osR1JP> z^F#eYF3*FKzT^1EHneZs(8q1z0838`2Pk7F9a~T_HtW7Fn)xRQzgt8x3yBDBRwJQ{}P`RjNh!OA(O3@B(Y8S)JczHG?1O zvNAhcu6a7cL#tYp%WcbQcMr}U$2{GqFZ-UMuJ9;`G4-J{SE$k=o+y$SvBvqT=)39_ zdL<|K=K8NT^E^$p(wUA? z=N8(7TGkznUAPpOE@uP+qtRv#8PbJ;^ur0LKuaN=ay;h^VPjkXe|Qf8*Rg7<;8!38 z%96D$3#*&<->V~)zDdBTU1p0JJ_do$)V#uq`2)j1IPZl8s?sFng@hvah&JF*5hk*Z z08C6-DWkH`=%xyqrs`pPL!whX#yW{AG^)og00jIr=wNquQHWe!g$;6R9_!WW-9lmR z9*P*$5nF=W0dOAgmAuTDBcMsSPh>Y3h$w?a?jD3^Lj+-|-cjiQx+;#W>vP`UXM``G zJCS=?bOi$D;8~=stD0wPgMYU+tex#q`3cO~cb9^;U4(Fp8H9sFNxLkX6Me`51of}U zQlqlmurDzD>|S>X7l8+Ctvd8|J?FJ(m#m*|__K)K2pfofbQ&7$oEJT;eeoj+Ka%j{ z_V#WI)W@&3c@6a~SDRb2N#Epi8@b79Q_gn}tdvE9N|Mk0c4)I&zqdncnWI@u{@Z45 zQCI5=*w2WAM_yrJ#HU^Ry30FB1So5ny;d!uI-~Dfa}Yt^7KuEyfo?|;$57kMYD&Is zV1l!}ZFnA3VBWo}%urukukchA^$YMWPDRE~slC?TnEDFCIrp!X13py!$%B zTpf8%yj@r*#V)}@ePKaT$pzW0yQPD$c{Ma9R-G96L=T*!q5Go$$0(?;_?2dd zG#f{8lCkURmX9CZa`&l(z`O`j_4|;sZ3&hcdaBQqce@t@KxS+!3VB&L1WU=MvohgJ$kjTGg9Feaw;!`7Dk3vbTsNBmAPn|}4Lvb(F zs8R!f_1?6Tzbx$;d3Haf+jwtYdn6IA;JCXL^VQP6ee;={MMx8U33L4TViJ$*x~}JX zH(03RaV|*{;RRNMa-UqT&sL-FuA+5*8^}gm5O!*+%H917aKeWY+OI&GO^TWXAW{cx zd$e!pJmh5};y$>y+ZtnJ8j6~&+6?k(wxT{Sdx;TMwG<=1WG7U*WM^#T%9ra(eOo=s zSeb`6V^J&Z>12FmthPyfZ~j8cj%i}XtWni^T@_$x8hCx#%O#+DDa>+a5bVg=a&o@|)*E_3vQ0kzAd)USqfQWL2T zG8+iHTMMe%^AS6T>QM!-5?KaZl_kz1$t%|tR`8G83~LT~v~qp%A@~njq5UyATkV^j zcRzByqQj8v$aRt46W~92Q9-C(&{@DDS^9QN@@Tig-X&O~S9SXs?fi;m-jcFK?PTp# zWTvzcIV)?CK&bMjV$y$-?%L5{pv-mQ&qk&Xt&QZsA9nRuj~W-`Pf1T%5+K0a4lAPW z+MM!im$)SZBPp(~Q?O5EQWak{4IX~_-HMm`6vnI1E!06ABc$%8)L@bwO+_ZxygV?H zr993$wILk6&RV-;F?);>U{6^B!rlvL4co?4R0A2;iwoM<`sqXVw-1T_KMD;%b#0a% z3_}FTd)<8txA%>YFZ|m8nEh89nmLAou~jONkFmi#^1?m6ttE{Lro8(MQ2E*qK}0xI zEm%3N6sX5BJwh~3tt*0{G4~0jkL2jW?XBwPS3yRtM^k)(k|1dniTOS?g!`hxA)P#&u{OeTJxn3 z!Yw^LEfqz&j_&G|Ax6+L{+k@ZRu5~^FJl~RS1YP{N;Cp zqTFJ|Q#eDR235rIBHMelR1+2!IZXstb-KLv%^Xy@*37XUwMnTVpl`luQxA5-sSOC- zwu8;Ok{7Con?%Y?0#fBI@MB(YTi#yLh^hVMXUPX`z)%~Mh$fEi4vg{V4vd`$Uw0X9 z;(8CLgG9kKL+AdM=VpSf(m<)^xOk3(3**-AT;{O+pT)RM;JvvrCUtiP{!-(F-}?%`I^|8I7lvpdN<(^f0z}+SLc3Y4ho`bL2J>?OcdUt6#LV;@XyUp2xZ6TQ2@4SO!nen~^5 zCxIf1Q=gKoQcvCU0kz@@x+3bH^t8^2DZ)vi>qLS?c#ZG2YOyN3uHp+zE`!S?YJ(jL zT&@$kQi?G|%Vd9Au!twgi7o%K)-k9UQFe~ko{F-Elz{u{^PdK{tA(Gn_WL0plIj-D z9=y>W7;}9(c(eb+oAtq)Si;U;=&ao-pSKpA6$`PNeW^yA4DkrX^OQoQgK3n*&x#^- z_;6c~?{KpB&JNJ-_E+1xh0N900T|6skS8xkJ11Ly+X4F?_>>AiHYMKR<9PrGBsh_J zUw2XK=V;I9wUXsl%*%W?<=W+n{{zi`e9hz^IvoQ{BqtSj4dA{L$b(C)!8OIDvteAx zx3%SmQ=<0ik!0FpY8-m~?hBW|$qT$yK;elu2z76F7Ac?-(^tCz<21dOKa zSAkpGkJ5YSSLxaGyPG-ur~N88BfYDEswzKP+y1X9ZPeSA?f`!ulP*0ylyglv=k{N7 zPNihv-#y#0B4*9sHvRauXQc(b2>P9w=yjX!Hjx6=KecDqUQ64bR0Bbpxw>k@q!k!c zUs@&Efx46Lo>w!3pbBsX$R(Bb%XK3gIDZ5I)*W-*d?%R+F!So_(qP}gU}LU!-lA@zCrC0+L+Po)jQrl>k!n@RT>v1B60sEb=LO*zhecaUc7 zfM~>;joKB!$}w?X6BR){qrL4=K0nv=!^FUj$}}BgJv^2(3&NQyqEL=(c6aNxC>_1B zPGp~^Js{dLd^MmVz(q&qYJ=>IQru*PHpMj zPY8ytW=>GA(0XWmNkCfW8|U2X#NQSNX$2pmfT=ERVw2d}T^0fj9*bUC!OX;`uav!> z?Q5-LsEr`d`x*~B{?UhG>daEHktb;Px^xnwKS1d>#(+`sQ+Xjd`3 z$IQYrrpb_jS`c9NIezWr4fqPx$%fioN8L_!%Bn-k-#e(J8N|JN-l~U*y8LtTQQjt$ z{K!`i>NgZPwV=v(3(9^Zw^2dz=WaE!(0#vhbRigKc{p0Q|AVEk&iv4{d3pNQkHITh z@TaO(?siE3b8AJrl`$|h7DOGItiXSJ0^h~mUUpjdjS*j76@mmJLI`263N}zh(w(f` z)Y=l`1V^6bCyrIYc=isP_C?SSL_Tj8-I7MS)h#XhD}$zAHD6wq^&U)v@OsN^409XE zWS@!${@tlnm(49!>3@X`9~c?H#~XmPipoOhqoSIyl$o5?{| zl0*B#EV=+M@_DiB6?yPw5q!sH^%iQ%0S089p{pJBMX|3)K-az7BcXKoK(8<9i-uK z1=aq?tO$EH=cxy(m!a)Ia2z-L~kA`+iL=SF(_h49yoP-r_X><~7cL zdW+Nio7Xu1=`Bw4Z(ig4r?)uGzj=-GpWfm$|K>H$e|n44{Pi`?c!@jSLz&x)Nh%YZ z?^iP^aPu zK+`(_Bx-@WRKwFgGyOjv7^_rJEX>4Tx04R}tkv&MmKpe$i(~2UM4(%Y~5TrU;5Eao)t5Adr zp;lsqRLwF{iMW`_u8Q5S2q26QW-uf(Q=gNhBs|C0J$!tn3pDGt{e5iP%@e@? z3|wh#f3*Qjf0ABrYtbVhv<+Nbw>4!CxZDBypLE%f9m!8qC=`JAGy0}15WWR^*WBJ( z`#607($rP*1~@nbMv9cZ?(y!P&ffk#)9UXBtXy)w2GfNL00006VoOIv00000008+z zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru~7;^ zr935GpR;r3%*+O14^}X72><{PVYY~n^DMRv9B~^$e=vZLpFcIiX0-+W-J7@XW#9n- zuGj0v`?N;j_iFW_R2GQ)Pk@Mw?9&>7IF1jS!1?NeZ6H(EBQJNXeQ+TFfERv1Ns<5} z0s%n0UQ5YMUGE<7Ftgj85*R%_qTz4|hzMV!IdV>3%%9nE@$dx3$0O?Z``Zb;K>=x+ zLiFtnxqF0#V%ISR_T=ap4F&_)mlvPx&t>&`G z*Qw`I(QakG(RLwk>=-e0M1)}Cl5;$wvRYwTmib;Na6Ljn-~j818uyS6JOY*Cd?TijYdH1OSs>gUhD{natWD3xau?JBvg=xB}k>o>6@Cw)Cm*- zd||Z2xoyr2Y2Wxj!_hu>9@x8)l87LfxYWdMcM<`ecDk%d+bIDP)@dQKbIJ$-lfJJK z4Xqq_{qhx6fe9B8ZaU39DrCj=S9Uo?n@{m1XUhoVI0i`T-HAKlb@UtnrJ|G-tM6H- z={plb#L|B0>go!1LZC|fRXU!ZEwReEY~}>VmXP~=Oo4E{$L&OOlCs}&?YJ@m`Au3e zF{@rsH$63yB{KpYnKa6P)`5>1e@x{2iTR=&0cUhV-ELQDle>}d*NXR`B-t(12#7Oo z)51eUcZtbBLX@P3ITPpW=JrPW+ND(jKO~i#dt1@23uV@wpE@bDF#iC2b#dMc4qXBO O0000 Date: Mon, 20 Apr 2020 09:27:57 +0200 Subject: [PATCH 0505/1189] Removed href="#" that scrolls page on top --- js/index.js | 2 +- js/utils.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/index.js b/js/index.js index ef9bcb4f1..d8c7a4473 100644 --- a/js/index.js +++ b/js/index.js @@ -207,7 +207,7 @@ function refreshLibrary() { var version = getVersionInfo(app, appInstalled); var versionInfo = version.text; if (versionInfo) versionInfo = " ("+versionInfo+")"; - var readme = `Read more...`; + var readme = `Read more...`; var favourite = favourites.find(e => e == app.id); return `
diff --git a/js/utils.js b/js/utils.js index 4913c7129..406e3a0a1 100644 --- a/js/utils.js +++ b/js/utils.js @@ -49,7 +49,7 @@ function getVersionInfo(appListing, appInstalled) { var versionText = ""; var canUpdate = false; function clicky(v) { - return `${v}`; + return `${v}`; } if (!appInstalled) { From 9cc58597cd5d0934f34da6a935b2187cb1b3df36 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Apr 2020 09:21:27 +0100 Subject: [PATCH 0506/1189] merge with new namings --- apps/widbatpc/{widbatpc.settings.js => settings.js} | 0 apps/widbatpc/{widbatpc.wid.js => widget.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename apps/widbatpc/{widbatpc.settings.js => settings.js} (100%) rename apps/widbatpc/{widbatpc.wid.js => widget.js} (100%) diff --git a/apps/widbatpc/widbatpc.settings.js b/apps/widbatpc/settings.js similarity index 100% rename from apps/widbatpc/widbatpc.settings.js rename to apps/widbatpc/settings.js diff --git a/apps/widbatpc/widbatpc.wid.js b/apps/widbatpc/widget.js similarity index 100% rename from apps/widbatpc/widbatpc.wid.js rename to apps/widbatpc/widget.js From 20bb1aed8456dcfc6028d77400970e45ebf6c2db Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Apr 2020 10:06:23 +0100 Subject: [PATCH 0507/1189] Add 'hide if charge greater than' Move 'DEFAULTS' to try and reduce memory usage a little --- apps.json | 4 +-- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/settings.js | 23 +++++++------ apps/widbatpc/widbatpc.settings.json | 1 - apps/widbatpc/widget.js | 50 +++++++++++++++++----------- 5 files changed, 46 insertions(+), 33 deletions(-) delete mode 100644 apps/widbatpc/widbatpc.settings.json diff --git a/apps.json b/apps.json index fe3d5f3eb..5b024eb97 100644 --- a/apps.json +++ b/apps.json @@ -354,7 +354,7 @@ "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.09", + "version":"0.10", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", @@ -1372,7 +1372,7 @@ {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ] }, - { + { "id": "rclock", "name": "Round clock with seconds, minutes and date", "shortName":"Round Clock", diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 129707320..4c5f16a04 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -6,3 +6,4 @@ 0.07: Add settings: percentage/color/charger icon 0.08: Draw percentage as inverted on monochrome battery 0.09: Fix regression stopping correct widget updates +0.10: Add 'hide if charge greater than' diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/settings.js index 9f39b5d07..bfed48f09 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/settings.js @@ -11,22 +11,22 @@ 'color': COLORS[0], 'percentage': true, 'charger': true, - 'hideifmorethan20pct': false, + 'hideifmorethan': 100, } // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings const storage = require('Storage') const saved = storage.readJSON(SETTINGS_FILE, 1) || {} for (const key in saved) { - s[key] = saved[key] + s[key] = saved[key]; } // creates a function to safe a specific setting, e.g. save('color')(1) function save(key) { return function (value) { - s[key] = value - storage.write(SETTINGS_FILE, s) - WIDGETS["batpc"].reload() + s[key] = value; + storage.write(SETTINGS_FILE, s); + WIDGETS["batpc"].reload(); } } @@ -54,11 +54,14 @@ save('color')(s.color) } }, - 'Hide when \> 20\%': { - value: s.hideifmorethan20pct, - format: onOffFormat, - onchange: save('hideifmorethan20pct'), + 'Hide if >': { + value: s.hideifmorethan||100, + min: 10, + max : 100, + step: 10, + format: x => x+"%", + onchange: save('hideifmorethan'), }, - } + } E.showMenu(menu) }) diff --git a/apps/widbatpc/widbatpc.settings.json b/apps/widbatpc/widbatpc.settings.json deleted file mode 100644 index 7a22adfc0..000000000 --- a/apps/widbatpc/widbatpc.settings.json +++ /dev/null @@ -1 +0,0 @@ -{"color":"By Level","percentage":true,"charger":true,"hideifmorethan20pct":false} diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 959ec211f..fe6f8550c 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -1,10 +1,4 @@ (function(){ -const DEFAULTS = { - 'color': 'By Level', - 'percentage': true, - 'charger': true, - 'hideifmorethan20pct': false, -} const COLORS = { 'white': -1, 'charging': 0x07E0, // "Green" @@ -17,10 +11,19 @@ const SETTINGS_FILE = 'widbatpc.settings.json' let settings function loadSettings() { settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {} + const DEFAULTS = { + 'color': 'By Level', + 'percentage': true, + 'charger': true, + 'hideifmorethan': 100, + }; + Object.keys(DEFAULTS).forEach(k=>{ + if (settings[k]===undefined) settings[k]=DEFAULTS[k] + }); } function setting(key) { if (!settings) { loadSettings() } - return (key in settings) ? settings[key] : DEFAULTS[key] + return settings[key]; } const levelColor = (l) => { @@ -46,24 +49,27 @@ const levelColor = (l) => { const chargerColor = () => { return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging } - +// sets width, returns true if it changed function setWidth() { - WIDGETS["batpc"].width = 40; - if (Bangle.isCharging() && setting('charger')) { - WIDGETS["batpc"].width += 16; - } + var w = 40; + if (Bangle.isCharging() && setting('charger')) + w += 16; + if (E.getBattery() > setting('hideifmorethan')) + w = 0; + var changed = WIDGETS["batpc"].width != w; + WIDGETS["batpc"].width = w; + return changed; } function draw() { - + // if hidden, don't draw + if (!WIDGETS["batpc"].width) return; + // else... var s = 39; var x = this.x, y = this.y; const l = E.getBattery(), c = levelColor(l); const xl = x+4+l*(s-12)/100 - if(!Bangle.isCharging() && setting('hideifmorethan20pct') && l > 20){ - return;} - if (Bangle.isCharging() && setting('charger')) { g.setColor(chargerColor()).drawImage(atob( "DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y); @@ -104,20 +110,24 @@ function reload() { g.clear(); Bangle.drawWidgets(); } +// update widget - redraw just widget, or all widgets if size changed +function update() { + if (setWidth()) Bangle.drawWidgets(); + else WIDGETS["batpc"].draw(); +} Bangle.on('charging',function(charging) { if(charging) Bangle.buzz(); - setWidth(); - Bangle.drawWidgets(); // relayout widgets + update(); g.flip(); }); var batteryInterval; Bangle.on('lcdPower', function(on) { if (on) { - WIDGETS["batpc"].draw(); + update(); // refresh once a minute if LCD on if (!batteryInterval) - batteryInterval = setInterval(()=>WIDGETS["batpc"].draw(), 60000); + batteryInterval = setInterval(update, 60000); } else { if (batteryInterval) { clearInterval(batteryInterval); From 5fe7f48477818c1bb31b7650e9d93f45d594f7e0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Apr 2020 10:07:55 +0100 Subject: [PATCH 0508/1189] Add 'update all' button (fix #237) --- index.html | 1 + js/index.js | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index f016ffb49..3c8b440e4 100644 --- a/index.html +++ b/index.html @@ -113,6 +113,7 @@
+
diff --git a/js/index.js b/js/index.js index 2b1fb1cfc..51b1d71c3 100644 --- a/js/index.js +++ b/js/index.js @@ -218,7 +218,7 @@ function refreshLibrary() {

${escapeHtml(app.description)}${app.readme?`
${readme}`:""}

See the code on GitHub
-
+
@@ -401,10 +401,18 @@ function showLoadingIndicator(id) { panelbody.innerHTML = '
'; } +function getAppsToUpdate() { + var appsToUpdate = []; + appsInstalled.forEach(appInstalled => { + var app = appNameToApp(appInstalled.id); + if (app.version != appInstalled.version) + appsToUpdate.push(app); + }); + return appsToUpdate; +} + function refreshMyApps() { var panelbody = document.querySelector("#myappscontainer .panel-body"); - var tab = document.querySelector("#tab-myappscontainer a"); - tab.setAttribute("data-badge", appsInstalled.length); panelbody.innerHTML = appsInstalled.map(appInstalled => { var app = appNameToApp(appInstalled.id); var version = getVersionInfo(app, appInstalled); @@ -436,6 +444,17 @@ return `
if (icon.classList.contains("icon-download")) handleAppInterface(app); }); }); + var appsToUpdate = getAppsToUpdate(); + var tab = document.querySelector("#tab-myappscontainer a"); + var updateApps = document.querySelector("#myappscontainer .updateapps"); + if (appsToUpdate.length) { + updateApps.innerHTML = `Update ${appsToUpdate.length} apps`; + updateApps.classList.remove("hidden"); + tab.setAttribute("data-badge", `${appsInstalled.length} ⬆${appsToUpdate.length}`); + } else { + updateApps.classList.add("hidden"); + tab.setAttribute("data-badge", appsInstalled.length); + } } let haveInstalledApps = false; @@ -471,6 +490,22 @@ htmlToArray(document.querySelectorAll(".btn.refresh")).map(button => button.addE showToast("Getting app list failed, "+err,"error"); }); })); +htmlToArray(document.querySelectorAll(".btn.updateapps")).map(button => button.addEventListener("click", () => { + var appsToUpdate = getAppsToUpdate(); + var count = appsToUpdate.length; + function updater() { + if (!appsToUpdate.length) return; + var app = appsToUpdate.pop(); + return updateApp(app).then(function() { + return updater(); + }); + } + updater().then(err => { + showToast(`Updated ${count} apps`,"success"); + }).catch(err => { + showToast("Update failed, "+err,"error"); + }); +})); connectMyDeviceBtn.addEventListener("click", () => { if (connectMyDeviceBtn.classList.contains('is-connected')) { Comms.disconnectDevice(); @@ -621,4 +656,3 @@ document.getElementById("installfavourite").addEventListener("click",event=>{ showToast("App Install failed, "+err,"error"); }); }); - From 0f8247e7e49f3b976e96dea0626a3369ea2a9456 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Mon, 20 Apr 2020 11:52:19 +0200 Subject: [PATCH 0509/1189] Data file fixes for settings/welcome/ncstart settings: never delete settings file welcome: fix typo, remove outdated comment ncstart: remove outdated comment --- apps.json | 3 --- apps/ncstart/settings.js | 1 - apps/welcome/settings.js | 3 +-- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apps.json b/apps.json index a18029abc..32a7e7dff 100644 --- a/apps.json +++ b/apps.json @@ -130,9 +130,6 @@ {"name":"setting.boot.js","url":"boot.js"}, {"name":"setting.img","url":"settings-icon.js","evaluate":true} ], - "data": [ - {"name":"setting.json"} - ], "sortorder" : -2 }, { "id": "alarm", diff --git a/apps/ncstart/settings.js b/apps/ncstart/settings.js index 6780264a7..560fad8ba 100644 --- a/apps/ncstart/settings.js +++ b/apps/ncstart/settings.js @@ -1,4 +1,3 @@ -// The welcome app is special, and gets to use global settings (function(back) { let settings = require('Storage').readJSON('ncstart.json', 1) || require('Storage').readJSON('setting.json', 1) || {} diff --git a/apps/welcome/settings.js b/apps/welcome/settings.js index e873c2785..20c2e9b13 100644 --- a/apps/welcome/settings.js +++ b/apps/welcome/settings.js @@ -1,6 +1,5 @@ -// The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('welcome.sjson', 1) + let settings = require('Storage').readJSON('welcome.json', 1) || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'Welcome App' }, 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 0510/1189] 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 0511/1189] 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 0512/1189] 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 0513/1189] 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 0514/1189] 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 0515/1189] 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 0516/1189] 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 0517/1189] 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 0518/1189] 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 0519/1189] 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 0520/1189] 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 0521/1189] 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 0522/1189] 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 0523/1189] 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 0524/1189] 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 0525/1189] 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 0526/1189] 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 0527/1189] 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 0528/1189] 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 0529/1189] 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 0530/1189] 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 0531/1189] 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 0532/1189] 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 0533/1189] 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 0534/1189] 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 0535/1189] 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 0536/1189] 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 0537/1189] 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 0538/1189] =?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 0539/1189] 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 0540/1189] 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 0541/1189] 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 0542/1189] 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 0543/1189] 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 0544/1189] 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 0545/1189] 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 0546/1189] 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 0547/1189] 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 0548/1189] 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 0549/1189] 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 0550/1189] 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 0551/1189] 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 zcmV;J9cSW+P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+NGQ6bsV{ph5y5fF#-Ex4%TzVgE4=;i>xB4me`Ws z6PskQmIM+JahCwv?Em}UWB!MKxu$AjDmAy9E&pPR&37JD`~2(or?c_?y#K=MCI0^5 zdGqmt=c(}d&YEA(Z=UzO-@l%puj_Q4PhT$7_Unc5;|u+DAzxnuyqwO3H^-O)fjef*Xd`{Vw$j|6)DY@~udK(MtwlvW*ebeXC zc&_u$zs>uto;mp)T(I|NeP$V+@6LDRrw=R@uQncskocLxv%c04GN!=H+iPvN{aDQ( z*5>{Dn}6m{ZtIl}KZN_^(JKwiPcQr<4f1|HAN~=&{PFufZ~pm$OTP~Hjp>&emH08R z|6xYyW0gL_`|*9ws^{$I?t0AJa(>;^`%av>p*(9S3GT--Uxn|)<8r?mUzKv1)K`(^&*P5<_Fj%vv{^Qsy51lX$#nT8^#pS+ETxbs@n zbQk#j^mwFVnY!ywBa+w-S_(BpXWhIB9TH4h1gJ_1S`fw z{*+kBp`JpDDW#lBs;Q-(Lym?D%eiF1Z7-q3l1eV6)Y3|?p+?|1*HUY3wKv}aXq+15 z*lKI7cgE~oxo6XPf9ILuM;LLWkw+PIw9zN&GviD%&ob+5voF8GqK;QyW!2SI-)@si zJMLt5-euR_c0c6W2`8R(@+qgDcKS!uUQzw&>o20_UQzQmQhHzch#Jq9^87Y8U$}^3 zM#Ow{M7$^hB(zt|Y;`euMNToZ%?lholT3=ua<;qdqX}_4pN{*8-Dl+fDsCpne~p{} z)5sZx?!S!Ojhor&OWb}DwI$k~H)2l}YE5mR`gncU?rRr|cJqGl%ipUUyH7276T{V6 z9@Zfd5I1Xcj$3T4R!}Eev!`Vm!S>z8*^V+9>l}?)dS*grwxGXj?I+e_>zUy!KLEzm z)95Tj9jg>ms+~E;zQJNUeA}~!WmAc(H0#%xR4E~6pwh@$-*;|j?2~y1FkVKZu6Hjc z@6-p;2cdH2wY951fZ4N`g-YsuQ8Ozu zd#HvDOWjOFs^=I>GnD`~j`pw%3ZpUWPjXKqHab z94$u|6aN)}@OdPHd>;I_zkj|^S=sem4yioK8MPb=gStCP(R2=!Nibq=?Fe`XouZLR z$Q6|*qow*GhCw%j+GkJ_@8qQ4WtQV# z12f&t>TVSU1i)o>wtPSD^t-lvjJJ8z8sQKr*~yabl>R(@KC%Zfx~QLC?zqQOCi@OH z@*F|T(-w$aNet#Th+N}7$p13iQTEwVcbRq>?y-{YvF4Mx_!!McFeC|mxJI1-;n&maUyc&1bbx89IJ z+3uQv5j*Mz@XAkb&7CZ;+q1Zx3=a)dAQ=D-sJyM^D5J@rpfTfF!?oR7+&j>>Sb+uK z^K$8=A!-3w=2iIMc@@b2CRxpwY)v3F(O+TTB!mITnFJqQgXJ61FD^ zpX<$0c~4;e_S88XaG>M`vBnMu$~rcl%9P01wCzbR4H**{Mn!-%GZq&M0YgA$%F_+v0TE3{%4H(F1;fWONi#G}D3=(*MSI7( zb_x)D2pyJ3<%*z)D3DRG1Jjfz^tl@DwKYBVw!+)gfV_fvFHq0?~bqD>fl zlTF!bS)3hRHZQ<1&6k?=l-GFZBl5pi??}hUgV=1mTo`iS!XYG0V|3;{d>^j)!TM#Q z&f1}!kWR>g)y%_P5GW!d`xaeBAQjLC@loQP3}9!Y2#G4Jr29mA)ooXf$F2lchXJsi z8YVuPvC7^=6a9SLJVZ6l!_C&laNMmcMarRw)&p8j(xJ})__5&GAx6vj8y@_Y1`TN1 z1*iqRulWoF39_t18x5dTG9s!<_+7r5zpR8WzbVdxR5_Hf-^T!FSiZ|$ow8G9ccjs& zK=&b@b4;qKX+YmfycW@{d+tf<)wvca5D7R*@nFg4 zu;!QJhC6QaKaTrI$8Ux;q-V~ka>&VpZy=$@D-}_WJg2T7hyumiPkJM-Q`49pp}dXX zFlm$nZ{&SwTr^IkHQ3;!;*}JyoZFNgBKP^=%{Hp|qQscZ+-ws}Scn`1mJ=xyAmzSD z&Wt!F7R<0DYEvQJ{&aLQUSj$f_miX9q|YSXaF*Bt6}lW!AM(-NX3`-vci?a?jG%S$ z7u$Zli_wjk3jtZVMO$|mHUN#&lP*^ax!72Bk_{S*#AzJ(@lw)Ix)D?Gjr&iSnlv}E zChtwD-s&M8Swx?I$GCXpJK_gPj8pPhC44l3 zo&Zi;+`Vn+DB)_zBq*x8P{E}jTlPo~XZ~J$9Pot*fEVHM6f77lg6SmLcJt`5-MV@; zfZjk7d&}KE;VUeo1IcCA29Ci6NC0QoS;*ADasg_$-u>Vt2OErb0 z!32gfO@um*#fU6%3-Sd{lG{Oq5Wvj57c_DEmwqRB0dWE0H|mcMmFf>n045nnG2GjM z^titse8g_D2#ILTkpp4`O^``13;V(?H%Y>qq z6%ReDJ1sUu_6d<@L^>WrUiM54!uAMcZVbyhZ&t>ltn8hvoDXN`k}?bB1~lAJWRUMd zZ6gx zzug$*`ba#B00DGetK${#$ZE`SuRHZ(a8f`swqOuCb>M{}%HAXRSwPf60(NU4N&T%s ziUHGDR`rM__mILc4p4D0eu;J`m@=3zOJkTr)G-Y%1}hkM%(F4KI~UWIfg z_f_ADUU0gab4>tC$}e;@5Sv-#yj1f@3pLAF;!q8oui^qjdnX;`vtxCr5EfS0p_gT3 z7HZjoWw{1YrKBQe)#WR&2QwKp`GAqNh^6b(eWdDbB!FMU>c)@K0}1!o>#|$qs)rPT zo99QXgh_J{32;2!x6fX<%xsjean2D3Gj}#^Vq6&`;A%s#{S$YXVrj7}q#L>IW>crewTF!Srtr8I(!i?4WG==9;&gx*L0qODDT%M5 zqpE8vg8P&?8<~U6dvs2~PMDX{St(qbEWNYPn^vjV_Dk;U{*pWUmJ8x~Z5fz$!fno+ z6^+^z2^GRLn))e8DMB*C&&>M3j}4XtXNeDUM1A-u1L1rPpjLCZA5GPK%=LG3833P? zNPZa_!0v5m@GRPdy8VOOlvXs=lXk2};*L)dd-}wktc9C+sIO0MOA&Vg6{{3ZEi8kN z7GU!Uk3=KdtzunZKHwJ}m+`vCl0q8M4`td4|4Mx*#6p`0X@sptUbHdLOwLvwLQ zWegUD&tv;x6XxPX(wJrpMZ^)4q+U}SEGVhIHqyZ0Bgb7b5E^FJ6-hl{smiUPHPW?9 zNirMoEICk5TlR7y#7Ram3mJ7AQQe{*1)mgh-W~SC0-*cjSjmCM*~+xzE4VxZ3eQIk z2pr_DfCGty%Vxsrk*;nxDV_QPGCTPqc5IDOA(LB$v2F*S6nA8Y_5!4xF0c-DWewh; z%rw;IT(@XXsOm&r=?6l>J*NRA5=gCsnI7!Fy$Zk*Twsx|+7M;WFLI+46*Mm({%*9J z1Gx~2c|8;W|D9{hpY|BAESc4hku!gA$NQX`Hi!~ zfbP8@^F*8vx#KpU$=W3h5imI}7_t`NO5P<&BCT(+H`l;SHDxM;qGYVH8RS(DvmKBa zKE%dvl;t8vQZbWh-^uQv9F^6NA@=Y>3Z(nJ%_OBugvL^9zF{~gX-QdNn7UL1bd)hy zK3PdYm?8UH~dbGNc>I?vjRs;=B5v)j5ccecV z6v|NWpx54{O#=usWn?c%U=dG@pN$}s?LhA%A{H5jUPYj%6AWwe7b53-imT%byt(L`|-I9oupGGR11r^ExG2GBgQ(xVR}b16XqC^WNLpNmThUGmQ<~|aIG;RAQsg|P8HvTr zSG~Td~W9wP!Nvt zLWQOV{On3D{Nkf51%Wb^asIW|a^%oma z62Opq*vPL2S%u3+FndBnnY-`&JxVeHjF4Cz94QVE23@k6C4i7eT}xnv+h;}rp`>$L zzy{>+Ed_*YMmi1M9UQ5x#~KfRt6kYFD-x+7NjOn*%@GT0&Esv5!j&gmvqJ|;Zcl%B z8CPwAgA+&nZPwir+s6ih5?}rJzi-pe^l)4I{cf#!`kf@#j`8P~vy)96-?d)26_yY* z!1Nd-8m{6&QdT0)_iPT{`M1yjb89H)_gP)1FJW5I00HAb;xNYL&|0S{U;zI5QuL!-ItO5xoE#L+r$6^fToOIR&tDYyUvviPFNp;B+ z(1gy-JTSOU72rN(L6kdW;zAYoke--RmA_3l^N0EN+jKL(%RfaWXzNp*RGl}}8Ha|V zkc4>lH9*N$&6SURFJFrlcU*91u!W*>4S_YH^W*EGOlg4_nxmAfMp>Mp%hab4!KAYjMmv6p@cfJEgEENi+ z>cC3Z2~8XT)g^3dIwkksNc!M=hu#mNdz%m@43hI}2L@rP-F^92uiglh0?T-n1AYagbYh)!+zal)dA&Ae zUL}*{)9Y(9YKngXmb}Jlu;?@7ZPA7rJY0rv>VgN?0_EF-+VjH7TxP#Vo~j%=VDGF$TkXEmvT^cfj#&KM|j0tCmio&uu&Y~;`I@~i6qXnQZJ9Y~_GM!r$jO=n$T z;&LUw)+2=uZY2x{i42u$kDEK0XEdJ6&4x>*P6x2m^S}13>ZAs>hw41Q#&|>fUu@o* zzuM(>=i6*Cf0-`dW{denx?qs*$&f{cfabX_9ZK5KF^jvw{_L*?s||J?5R#lTz+6Q# zv9u#>ZNxw#AZ62W0g!6E4uEJ^!t0T}3fo~s66OHYl}A8@dIL06!iUnagy-o;$4`z% z#LXWY5m6!kaAPF;-R_#^Cd>gJbnxZ2BMGi03fxsr%Mz;715OkpM_S{*bg+m4MUWe! zPM`B!R~+nne(*jmvuTYK~fzUp%o*D;F;3OlEP1Saohn^Z*gFC78A4DE=kjWV|9WK4p<#G zS$KV@Jt*B9xs5Zf^>a^`Ki_8n%0kWZNeuVV>8qyxM?c=6sFs#V1wqlZusUlEwQqH& zhxQmleRMmbi4c9$iZJ#+JCUc~5+6up*^ZVjix90uqy}D=^3?wlff-EQxhSyI5kzGf z*lc-+&dul;)9rlVUUbmd>Utw70{j6CAG{j_Vh3pHW$Mbc}&`4fO)V!D`hP zNl}cfGfi6a-MddZf+dTn)_vQJ?3)qwaPfcTQTDSp9AxA@Ugd;$1(-iA0ivw(6ZdzA zzS!#D=pT++c7WT@es+g#hj}R? zybD7nZTO?9mGe7ag`GReniIJEWb}KnNgNw7S4z7YA_yOYN=%nZ(CH^ldw21NGxF7HCJ?`EC z-bRHfhJON3R8vpIV?s8!Dg<8P#~}JKg0RR8Es^~_vh%9^9BPv z0`VNvbdz|4cxKboIPVjOSV@$L&xyx%x*+i**CmJFI2Ud9^30H)NzD_7h=pPYOC8Kg zxghPypV~=$mrDz%9_T=JeLu z$LRx*p{|y1fP+I|tVr4GF7NK{?Csw(t^R%he010qNS#tmYE+YT{E+YYWr9XB6000McNlirueSad^g zZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00NvzL_t(&-qlzuY#TukeY=e%!`3xe zWQAEpQDK9O%Oe>T6qHl}g&_qdDJuvwFetJVZXD!7%cu&A4jqWol1i4MYK!(Xx7qvb z-R#CU(&_%Q@4cCw**k#A_Loz=znp4BHo*ZL0D6-x0O0ZF1pSMph($oQ1#f^G@V&_v z|9-yFogh#rGMy#Rn{1wzl zL{-Q@9Nz>fk z0wu~sb&);d0(N`pL1{y5o8nf4?+3d9H{$IQAEUdK5!NR zuM}$X*B~VL%09qdl|qzX(ey*xCQ?NpRPSiy)J3pt-5;{?wQ@{}eE$0(>)0^~9C15z ztzMI}ez2uPt40>0KSU*9NSO37wmj>L&JeIICU|xN6g)ll`HS)F5#X$HQ3z0V9ZKua uQE04?tMj_*eck7xM!*3|_z1=MHTNHk3W=6?yz3_b0000tlxq zC9)f@Omu&Na^VuQ3o*OkLX&0x0b91aC7LC3CR;|G&UwKyoPP>)C@?@qQJ{sk6xyD% z=l4Jh)I!fW1~D0* z;<FiSH3Y&R!hSP)O!EM^qB9S{ZPxdCNqq>+N%{VX0i+kf2a3kz~{zxV@bYqQG5oH!NB|6Hd{lUV)z^y&}M+3 zY=5_#<7uJuaS;v7ol@c{1NA&9VD&4B3iooLQyfU9IAT(K-S-zbY%m%Or~5yA!-tJ9 zfSKSZqel&78BikP)W`p zzI3Z)knW0%i}dirvv(SJ)f zTTQ^kGnzzKFl@TSGDoSS-YQ$q_X zStXt~30!=tPYtT;z`;H5V0>y6Mt{kO@}eE-Hg={#RoR=cnjP4=WI+G$pD1t@AGnoDDLd-t<`6KobcAM^dKuT|+%Z2+wbomVp3YQ6hbwUH5CHjYHCMD1Ly zXg>?7d1;3DYz&U|Auu`0cgn*q+BMpxOrvss7j!Zjc+5_X6DaYNquBF0`+po@Z3AnL z-_3-rG;Agktn9YaRTGi2sK_2*3rEl`N17m;jI&g6ByU>De1Nw*W@k~U1Px+gC`ELJj&yD-w z@X0mbQC{R_2GsD+B>r!fO0}Zf0QxOUt54OHzlaH-XDuWWalZOQ>VK{k-3HXM(oa{4 z%%IK%Ex`EHFzC+|RLpt@yWwJmOe>of#Mu@=51VEH#S6s{9o#%D1JN_>#7hfe`U6y8 zYJ?wyDGkFoERDt!OF!~i5Yltbc`Jfd zVhJF1ywFnv_&cBz%5vY72I(M1P`*E)V*6bys&(q@M006J)tq88(QSY;BV*7CYFWk1 z1*l#6L8FyT3*u}Gpa Date: Tue, 21 Apr 2020 20:10:56 +0100 Subject: [PATCH 0552/1189] 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 zcmc&%X;c$w77axKg&-u*K+|ji#ULVrVzVX$St2fMO+W!5t|+_ghP6}_1&N9y*s|E5 zAhIh;*lV;$KtV)Vg@hm?m>@(#z$PqH{IP#bpEEskrqBF%Rp-3#y?g4NbHDp;U2<`v ztY7!TIt&K0-f_2`8~Wz21tf_+Nz_l*(LB@9&c;2~_j9gI_^=rk{H)b!BW2z0JewK$ z+Q$0bm8uvWkD5D%$r4p+9ZkWq1BcoiuJ1THxVW+yyCnF0c2#p5L#F7jZqiDl{vc6Ans80G1pK0Wa9{Oj^B3%C zr!<$2Umz4sBIw^eSxb{N5EXqLULT4%J75Hv@3ABlS1n?PAEXyo3Zw`_3X8G2nr(#Wg5 z4#c)DnK=2N8j`|?GJdyrUmvf$tG?+>Z=Fun9`1rgb4s4>v5h&4_4K2cLa+fX%8cCu z>=l1Oq=q0WEiNBn)b@{zvi%ZeQ|xHq$`WU8T^f>PH?>6hjE$Xa7Pi|rNma!xe{ndS z{#v9+xkl5^>LxUnw$Q~j#>>Nv%5728~V1SV&Ox5x`kS;-L@NP~a?Y+v==34_$$LVD9VF2=pjkUXo0U{*v zF4-7BMN_j|I~mClgT6y4k#dm|2@N~Y9M+3LIfSsmeDQpSlLSP@z~<-PQ#6|&mQP9-rz#&})V}+@~F!${HBp`+{cU=Y>Ydl|Q_Fy+RiW^PmeYxqa+Yqe* zRE{t2S0Z?+NGkwC=NL%z2X7@iPWf~5q#ch!^aPnR zgJSSP4zK2rHs7SiHU$?8sj1lDrNqEj#!_x%S}F#RKRl)beZVIp<{!!HAXyxlqaEY} z!s;N_tW|xt7_5yBa{fvh{^~glFp(|38E<5VfiG5_#)08jGDkfEF9BYF@O5Jpz33k@wh0nCKX>>bnQyA7KR<)R8g zIy_&y6IBp;V^By8IsY7+O)H*A@=OtN<(Du zA}@RuV_frZSZ0qpj@iRhK5x&FxSFsPJJ1@=*aP_lWT4?A^Hhfqv^6V3Q%CD4x}f1s z3K|uPhpEOaYuvqgYVF5Y#q;~?<={-Y=bC$!+P9{@^JG<7=D#!jWC1!^d>>~(-B^nc z@QZpj9Um}qmxnd`M4PI1zczgKenRj120=+eW`!;1?z!q#H~Vmzf_bXx)c*mHdUZ-T zg^5tMopJNJYU+A^wy4Dq@~F4FXlz$FF2AuW)(V!AiduZQR+TI1QHTNhv)}%9V-4EUxy()i zG&J61+qQP9dX=gNBT7Xd+9uJDCQ3a5cIv>4{3wdGXjb(r_u17$W--mBXSQ(}sMPzh zpKskgPtOwfQ$z*x*8AT+B&@V7PBgb3;%}Y%xo(A}yEdukY2RTLSVg?0EO%{EL-D33 z)%sOil$>cQ?QDy|l!yu5_)n2UKt;nRCWwlCT(ubLUn1;@pKcCl{ze9yp64Og)^gm$ zZ)A{gRco+!6V!GbdH!alC{-ncWrp|bvWcK!8$bp|)}uUq1e z$l>f!p-}TXkKDVEhTMDp7;gYd1PqXV(61YtG%OMPD^@rTILuG9Y9`iUt2kyFeC-iyjt zyf$Z|JhwWs|0hv>-@Q11A-9i+ofc;)l$$yS-hq~`rF)yj5VNuaa)ZH;V5a9l-{NHZ zQasTDTi##D>w%wyBzIpqVUl#CA%L!P!mk8+Ymax*JRKx0RqvmHEgM$MX$yb1 z>a*u`QMt<}O}yLKi$hSET!H6}lL>R@Jx6|^B+#WS=|@w|G($nx=}8UBJi)i7rMr%a zs$lXl6Ee86DCL43xW}D{dLd(_e_$rdwmZ{tS+*q6BjyV6{oBQT_h((}?u#zXI#iY> z^u*{*CpP_7AcWL$i!)KeI~j8EbM<n-ojZrswdCG6qX@iBar*)DKJ{W~B{>g1d4U>XIpt1ja3Bnde4!G_yQ7gU*+!KqXgE z13743(Bl53BdT8w1hkxrc=!&B*OY4>LK{vhva@o;iPJ4!NvbX+To6eb^Q3PaZz&Yi zI}{5K;SL^0Xm*ah zzuhDUq&cImSbQB?mS73TwWMV9)sn<1{X#ajfZlp^rM&IyXQNByMMHybL1nAU)H zSkn&j`)}^kR4fk(Dd;(e>_W{4_Q!HO2Q{^SWnvX*d3zp0W&=U=R}SN7?_^i8i+1*( 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 0553/1189] 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 0554/1189] 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 0555/1189] 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 0556/1189] 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 0557/1189] 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 0558/1189] 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 0559/1189] 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 0560/1189] 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 0561/1189] 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 0562/1189] 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 0563/1189] 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 0564/1189] 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 0565/1189] 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 0566/1189] 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 0567/1189] 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 0568/1189] 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 0569/1189] 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 0570/1189] 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 0571/1189] 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 0572/1189] 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 0573/1189] 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 0574/1189] 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 0575/1189] 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 0576/1189] 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 0577/1189] 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 0578/1189] 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 0579/1189] 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 0580/1189] 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 0581/1189] 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 0582/1189] 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 0583/1189] 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 0584/1189] 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 0585/1189] 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(); From a7305dc947ecebd275874941c35d3510667290c8 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Thu, 23 Apr 2020 21:31:12 +0200 Subject: [PATCH 0586/1189] First atempt to HR indication --- apps/rclock/rclock.app.js | 96 +++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index bd8395116..bbb74205d 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -4,6 +4,14 @@ var hours; var date; var first = true; + var locale = require('locale'); + var _12hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"] || false; + + //HR variables + var color="#FF0000"; + var id=0; + var size=10; + var grow=true; const screen = { width: g.getWidth(), @@ -41,17 +49,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) { @@ -72,7 +70,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) { @@ -84,7 +82,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 () { @@ -104,7 +102,7 @@ } first = false; } - + // Reset seconds if (seconds == 59) { g.setColor('#000000'); @@ -128,14 +126,34 @@ //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; + } + + var meridian; + + if (typeof locale.meridian === "function") { + meridian = locale.meridian(new Date()); + } else { + meridian = ""; + } + + var timestr; + + if (meridian.length > 0 && _12hour) { + timestr = hours + " " + meridian; + } else { + timestr = hours; + } + 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); @@ -147,19 +165,61 @@ if (on) drawClock(); }); + +//setInterval for HR visualisation + const newBeats = function (hr) { + if (id != 0) { + changeInterval(id, 6e3 / hr.bpm); + } else { + id = setInterval(drawHR, 6e3 / hr.bpm); + } + }; + +//visualize HR with circles pulsating + const drawHR = function (hr) { + if (grow && size < 12) { + size++; + } + + if (!grow && size > 3) { + size--; + } + + if (size == 12 || size == 3) { + grow = !grow; + } + + if (grow) { + color = "#f0af00"; + g.setColor(color); + g.fillCircle(settings.circle.center, settings.circle.middle, size); + } else { + color = "#000000"; + g.setColor(color); + g.drawCircle(settings.circle.center, settings.circle.middle, size); + } + print(size); + }; + // clean app screen g.clear(); - g.setFontAlign( 0, 0, 0); + g.setFontAlign(0, 0, 0); Bangle.loadWidgets(); Bangle.drawWidgets(); // refesh every 30 sec setInterval(drawClock, 1E3); + //start HR monitor and draw heart rate + Bangle.setHRMPower(1); + Bangle.on('HRM', function (d) { + newBeats(d); + }); + // draw now drawClock(); // Show launcher when middle button pressed setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); -} \ No newline at end of file +} \ No newline at end of file From e9509ca74fbda81e9df819fe2a2b4e417f81ca92 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Fri, 24 Apr 2020 07:33:16 +0200 Subject: [PATCH 0587/1189] Updated change log --- apps/rclock/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog index a8f708a0a..d3c24cd8e 100644 --- a/apps/rclock/ChangeLog +++ b/apps/rclock/ChangeLog @@ -1 +1,3 @@ 0.01: First published version of app +0.02: Added support for locale and 12H clock +0.03: Added HR indication to clock \ No newline at end of file From 1223184ee027e66aad9be82976d89e6eb1f3658c Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 25 Apr 2020 12:11:07 +0200 Subject: [PATCH 0588/1189] Add imprecise word clock. --- apps.json | 13 +++ apps/impwclock/clock-impword-icon.js | 1 + apps/impwclock/clock-impword.js | 160 +++++++++++++++++++++++++++ apps/impwclock/clock-impword.png | Bin 0 -> 10763 bytes 4 files changed, 174 insertions(+) create mode 100644 apps/impwclock/clock-impword-icon.js create mode 100644 apps/impwclock/clock-impword.js create mode 100644 apps/impwclock/clock-impword.png diff --git a/apps.json b/apps.json index 6d67d8b40..65f321a91 100644 --- a/apps.json +++ b/apps.json @@ -163,6 +163,19 @@ {"name":"wclock.img","url":"clock-word-icon.js","evaluate":true} ] }, + { "id": "impwclock", + "name": "Imprecise Word Clock", + "icon": "clock-impword.png", + "version":"0.01", + "description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"impwclock.app.js","url":"clock-impword.js"}, + {"name":"impwclock.img","url":"clock-impword-icon.js","evaluate":true} + ] + }, { "id": "aclock", "name": "Analog Clock", "icon": "clock-analog.png", diff --git a/apps/impwclock/clock-impword-icon.js b/apps/impwclock/clock-impword-icon.js new file mode 100644 index 000000000..f5ed47f1f --- /dev/null +++ b/apps/impwclock/clock-impword-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkEIf4A3iIBEn8ggP//8wgX/+cQl8Agc/BQPyCokQgHzmEB+ET+EfmMj+AXCmABBF4MBiIABiEC+PxC4Uwn4NB+QXMBAMzI4UxmYOBC5sfCgIvBgPzF4cfC5BgCFAMPkPwiXzL4cPmMvkAXDPAnzEgMxR4wDCGITl/AH4ApgUQbIICBAgXwBYMD+UAYoP/l4CBiUhd4QXFgIXCh73BfQUfAgIPBC4cQiIACC4cvj4PBC5AuCC48zgcwC4ZHBC5sBCAIEBF5EAC4RgDCQItCPAIXLCoQBBFgM/IoZHER4QA/AH4Anj8wgXzgX/+cQWoPyYQK9Bn/zj/wb4MTCAMf+MDAYMxkfwj8BmYXBmEzCYMf+cDmPzkMvj8zAIM/eoPyC4fy+IXDl8TmfwI4UvmYABAwIXB//xgPwBIIXCgYFBmEP/8fh/yF4sDC4QjBC4RvBF4UPB4JUBL4kAn8ROIJbBC4IIBL4hDBmaPEgBuB+EB+aPCUQUjCALn/AH4A/A")) \ No newline at end of file diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js new file mode 100644 index 000000000..dafbbfcf5 --- /dev/null +++ b/apps/impwclock/clock-impword.js @@ -0,0 +1,160 @@ +/* Imprecise Word Clock - A. Blanton +A remix of word clock +by Gordon Williams https://github.com/gfwilliams +- Changes the representation of time to be more general +- Shows accurate digital time when button 1 is pressed +*/ +/* jshint esversion: 6 */ + +const allWords = [ + "AEARLYDN", + "LATEYRZO", + "MORNINGO", + "KMIDDLEN", + "AFTERDAY", + "OFDZTHEC", + "EVENINGR", + "ORMNIGHT" +]; + + +const timeOfDay = { + 0: ["", 0, 0], + 1: ["EARLYMORNING", 10, 11, 12, 13, 14, 02, 12, 22, 32, 42, 52, 62], + 2: ["MORNING", 02, 12, 22, 32, 42, 52, 62], + 3: ["LATEMORNING", 01, 11, 21, 31, 02, 12, 22, 32, 42, 52, 62], + 4: ["MIDDAY", 13, 23, 33, 54, 64, 74], + 5: ["EARLYAFTERNOON", 10, 20, 30, 40, 50, 04, 14, 24, 34, 44, 70, 71, 72, 73], + 6: ["AFTERNOON", 04, 14, 24, 34, 44, 70, 71, 72, 73], + 7: ["LATEAFTERNOON", 01, 11, 21, 31, 04, 14, 24, 34, 44, 70, 71, 72, 73], + 8: ["EARLYEVENING", 10, 20, 30, 40, 50, 06, 16, 26, 36, 46, 56, 66], + 9: ["EVENING", 06, 16, 26, 36, 46, 56, 66], + 10: ["NIGHT", 37, 47, 57, 67, 77], + 11: ["MIDDLEOFTHENIGHT", 32, 33, 34, 35, 36, 37, 50, 51, 54, 55, 56, 73,74,75,76,77 ], +}; + + +// offsets and increments +const xs = 35; +const ys = 31; +const dy = 22; +const dx = 25; + +// font size and color +const fontSize = 3; // "6x8" +const passivColor = 0x3186 /*grey*/ ; +const activeColorNight = 0xF800 /*red*/ ; +const activeColorDay = 0xFFFF /* white */; + +function drawWordClock() { + + + // get time + var t = new Date(); + var h = t.getHours(); + var m = t.getMinutes(); + var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); + var day = t.getDay(); + + var hidx; + + var activeColor = activeColorDay; + if(h < 7 || h > 19) {activeColor = activeColorNight;} + + g.setFont("6x8",fontSize); + g.setColor(passivColor); + g.setFontAlign(0, -1, 0); + + // draw allWords + var c; + var y = ys; + var x = xs; + allWords.forEach((line) => { + x = xs; + for (c in line) { + g.drawString(line[c], x, y); + x += dx; + } + y += dy; + }); + + + // Switch case isn't good for this in Js apparently so... + if(h < 3){ + // Middle of the Night + hidx = 11; + } + else if (h < 7){ + // Early Morning + hidx = 1; + } + else if (h < 10){ + // Morning + hidx = 2; + } + else if (h < 12){ + // Late Morning + hidx = 3; + } + else if (h < 13){ + // Midday + hidx = 4; + } + else if (h < 14){ + // Early afternoon + hidx = 5; + } + else if (h < 16){ + // Afternoon + hidx = 6; + } + else if (h < 17){ + // Late Afternoon + hidx = 7; + } + else if (h < 19){ + // Early evening + hidx = 8; + } + else if (h < 21){ + // evening + hidx = 9; + } + else if (h < 24){ + // Night + hidx = 10; + } + + // write hour in active color + g.setColor(activeColor); + timeOfDay[hidx][0].split('').forEach((c, pos) => { + x = xs + (timeOfDay[hidx][pos + 1] / 10 | 0) * dx; + y = ys + (timeOfDay[hidx][pos + 1] % 10) * dy; + g.drawString(c, x, y); + }); + + + // Display digital time while button 1 is pressed + if (BTN1.read()){ + g.setColor(activeColor); + g.clearRect(0, 215, 240, 240); + g.drawString(time, 120, 215); + } else { g.clearRect(0, 215, 240, 240); } + +} + +Bangle.on('lcdPower', function(on) { + if (on) drawWordClock(); +}); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +setInterval(drawWordClock, 1E4); +drawWordClock(); + +// Show digital time while top button is pressed +setWatch(drawWordClock, BTN1, {repeat:true,edge:"both"}); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); diff --git a/apps/impwclock/clock-impword.png b/apps/impwclock/clock-impword.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ed0e8282583a96e7bbd8bc444813af273260f7 GIT binary patch literal 10763 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 JPDHLkV1n2bV Date: Sat, 25 Apr 2020 18:25:13 +0200 Subject: [PATCH 0589/1189] Add readme. --- apps/impwclock/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 apps/impwclock/README.md diff --git a/apps/impwclock/README.md b/apps/impwclock/README.md new file mode 100644 index 000000000..30e42c95e --- /dev/null +++ b/apps/impwclock/README.md @@ -0,0 +1,4 @@ +# Imprecise Word Clock + +This clock tells time in very rough approximation, as in "Late morning" or "Early afternoon." Good for vacations and weekends. Press button 1 to see the time in accurate, digital form. But do you really need to know the exact time? + From 152b0e617b9b852058aee788726da41fb7a0abe3 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 25 Apr 2020 23:02:10 +0300 Subject: [PATCH 0590/1189] locale.meridian function does not exists if languages app is not installed --- apps/barclock/clock-bar.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/barclock/clock-bar.js b/apps/barclock/clock-bar.js index da436daee..0f2609298 100644 --- a/apps/barclock/clock-bar.js +++ b/apps/barclock/clock-bar.js @@ -12,7 +12,12 @@ date.setMonth(1, 3) // februari: months are zero-indexed const localized = locale.date(date, true) locale.dayFirst = /3.*2/.test(localized) - locale.hasMeridian = (locale.meridian(date) !== '') + + locale.hasMeridian = false + if(typeof locale.meridian === 'function') { // function does not exists if languages app is not installed + locale.hasMeridian = (locale.meridian(date) !== '') + } + } const screen = { width: g.getWidth(), From cff313e89db2141d060d484cc73d1eba3b125e4b Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 25 Apr 2020 23:05:36 +0300 Subject: [PATCH 0591/1189] version update --- apps.json | 2 +- apps/barclock/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6d67d8b40..e39756b84 100644 --- a/apps.json +++ b/apps.json @@ -1012,7 +1012,7 @@ { "id": "barclock", "name": "Bar Clock", "icon": "clock-bar.png", - "version":"0.04", + "version":"0.05", "description": "A simple digital clock showing seconds as a bar", "tags": "clock", "type":"clock", diff --git a/apps/barclock/ChangeLog b/apps/barclock/ChangeLog index 2e0fd088c..616ee66e9 100644 --- a/apps/barclock/ChangeLog +++ b/apps/barclock/ChangeLog @@ -2,3 +2,4 @@ 0.02: Apply locale, 12-hour setting 0.03: Fix dates drawing over each other at midnight 0.04: Small bugfix +0.05: Clock does not start if app Languages is not installed \ No newline at end of file From 66264ea61c300564f433a87515b6d982e2b9f79c Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 26 Apr 2020 03:29:45 +0200 Subject: [PATCH 0592/1189] ballmaze game: Navigate a ball through a maze using the accelerometer --- apps.json | 16 ++ apps/ballmaze/README.md | 15 + apps/ballmaze/app.js | 514 ++++++++++++++++++++++++++++++++++ apps/ballmaze/icon.js | 1 + apps/ballmaze/icon.png | Bin 0 -> 444 bytes apps/ballmaze/maze.png | Bin 0 -> 2850 bytes apps/ballmaze/size_select.png | Bin 0 -> 4409 bytes 7 files changed, 546 insertions(+) create mode 100644 apps/ballmaze/README.md create mode 100644 apps/ballmaze/app.js create mode 100644 apps/ballmaze/icon.js create mode 100644 apps/ballmaze/icon.png create mode 100644 apps/ballmaze/maze.png create mode 100644 apps/ballmaze/size_select.png diff --git a/apps.json b/apps.json index 6d67d8b40..9652b3e19 100644 --- a/apps.json +++ b/apps.json @@ -1482,5 +1482,21 @@ {"name":"pong.app.js","url":"app.js"}, {"name":"pong.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "ballmaze", + "name": "Ball Maze", + "icon": "icon.png", + "version": "0.01", + "description": "Navigate a ball through a maze by tilting your watch.", + "readme": "README.md", + "tags": "game", + "type": "app", + "storage": [ + {"name": "ballmaze.app.js","url":"app.js"}, + {"name": "ballmaze.img","url":"icon.js","evaluate": true} + ], + "data": [ + {"name": "ballmaze.json"} + ] } ] diff --git a/apps/ballmaze/README.md b/apps/ballmaze/README.md new file mode 100644 index 000000000..22a295686 --- /dev/null +++ b/apps/ballmaze/README.md @@ -0,0 +1,15 @@ +# Ball Maze + +Navigate a ball through a maze by tilting your watch. + +![Screenshot](size_select.png) +![Screenshot](maze.png) + +## Usage + +Select a maze size to begin the game. +Tilt your watch to steer the ball towards the target and advance to the next level. + +## Creator + +Richard de Boer diff --git a/apps/ballmaze/app.js b/apps/ballmaze/app.js new file mode 100644 index 000000000..b249d6494 --- /dev/null +++ b/apps/ballmaze/app.js @@ -0,0 +1,514 @@ +(() => { + let intervalID; + let settings = require("Storage").readJSON("ballmaze.json") || {}; + + // density, elasticity of bounces, "drag coefficient" + const rho = 100, e = 0.3, C = 0.01; + // screen width & height in pixels + const sW = 240, sH = 160; + // gravity constant (lowercase was already taken) + const G = 9.80665; + + // wall bit flags + const TOP = 1<<0, LEFT = 1<<1, BOTTOM = 1<<2, RIGHT = 1<<3, + LINKED = 1<<4; // used in maze generation + + // The play area is 240x160, sizes are the ball radius, so we can use common + // denominators of 120x80 to get square rooms + // Reverse the order to show the easiest on top of the menu + const sizes = [1, 2, 4, 5, 8, 10, 16, 20, 40].reverse(), + // even size 1 actually works, but larger mazes take forever to generate + minSize = 4, defaultSize = 10; + const sizeNames = { + 1: "Insane", 2: "Gigantic", 4: "Enormous", 5: "Huge", 8: "Large", + 10: "Medium", 16: "Small", 20: "Tiny", 40: "Trivial", + }; + + /** + * Draw something to all screen buffers + * @param draw {function} Callback which performs the drawing + */ + function drawAll(draw) { + draw(); + g.flip(); + draw(); + g.flip(); + } + + /** + * Clear all buffers + */ + function clearAll() { + drawAll(() => g.clear()); + } + + // use unbuffered graphics for UI stuff + function showMessage(message, title) { + Bangle.setLCDMode(); + return E.showMessage(message, title); + } + + function showPrompt(prompt, options) { + Bangle.setLCDMode(); + return E.showPrompt(prompt, options); + } + + function showMenu(menu) { + Bangle.setLCDMode(); + return E.showMenu(menu); + } + + const sign = (n) => n<0?-1:1; // we don't really care about zero + + /** + * Play the game, using a ball with radius size + * @param size {number} + */ + function playMaze(size) { + const r = size; + // ball mass, weight, "drag" + // Yes, larger maze = larger ball = heavier ball + // (atm our physics is so oversimplified that mass cancels out though) + const m = rho*(r*r*r), w = G*m, d = C*w; + + // number of columns/rows + const cols = Math.round(sW/(r*2.5)), + rows = Math.round(sH/(r*2.5)); + // width & height of one column/row in pixels + const cW = sW/cols, rH = sH/rows; + + // list of rooms, every room can have one or more wall bits set + // actual layout: 0 1 2 + // 3 4 5 + // this means that for room with index "i": (except edge cases!) + // i-1 = room to the left + // i+1 = room to the right + // i-cols = room above + // i+cols = room below + let rooms = new Uint8Array(rows*cols); + // shortest route from start to finish + let route; + + let x, y, // current position + px, py, ppx, ppy, // previous positions (for erasing old image) + vx, vy; // velocity + + function start() { + // start in top left corner + x = cW/2; + y = rH/2; + vx = vy = 0; + ppx = px = x; + ppy = py = y + + clearWatch(); + generateMaze(); // this shows unbuffered progress messages + if (settings.cheat && r>1) findRoute(); // not enough memory for r==1 :-( + + Bangle.setLCDMode("doublebuffered"); + clearAll(); + drawAll(drawMaze); + intervalID = setInterval(tick, 100); + } + + // Position conversions + // index: index of room in rooms[] + // rowcol: position measured in roomsizes + // xy: position measured in pixels + /** + * Index from RowCol + * @param row {number} + * @param col {number} + * @returns {number} rooms[] index + */ + function iFromRC(row, col) { + return row*cols+col; + } + + /** + * RowCol from index + * @param index {number} + * @returns {(number)[]} [row,column] + */ + function rcFromI(index) { + return [ + Math.floor(index/cols), + index%cols, + ]; + } + + /** + * RowCol from Xy + * @param x {number} + * @param y {number} + * @returns {(number)[]} [row,column] + */ + function rcFromXy(x, y) { + return [ + Math.floor(y/sH*rows), + Math.floor(x/sW*cols), + ]; + } + + /** + * Link another room up + * @param index {number} Dig from already linked room with this index + * @param dir {number} in this direction + * @return {number} index of room we just linked up + */ + function dig(index, dir) { + rooms[index] &= ~dir; + let neighbour; + switch(dir) { + case LEFT: + neighbour = index-1; + rooms[neighbour] &= ~RIGHT; + break; + case RIGHT: + neighbour = index+1; + rooms[neighbour] &= ~LEFT; + break; + case TOP: + neighbour = index-cols; + rooms[neighbour] &= ~BOTTOM; + break; + case BOTTOM: + neighbour = index+cols; + rooms[neighbour] &= ~TOP; + break; + } + rooms[neighbour] |= LINKED; + return neighbour; + } + + /** + * Generate the maze + */ + function generateMaze() { + // Maze generation basically works like this: + // 1. Start with all rooms set to completely walled off and "unlinked" + // 2. Then mark a room as "linked", and add it to the "to do" list + // 3. When the "to do" list is empty, we're done + // 4. pick a random room from the list + // 5. if all adjacent rooms are linked -> remove room from list, goto 3 + // 6. pick a random unlinked adjacent room + // 7. remove the walls between the rooms + // 8. mark the adjacent room as linked and add it to the "to do" list + // 9. go to 4 + let pdotnum = 0; + const title = "Please wait", + message = "Generating maze\n", + showProgress = (done, total) => { + const dotnum = Math.floor(done/total*10); + if (dotnum>pdotnum) { + const dots = ".".repeat(dotnum)+" ".repeat(10-dotnum); + showMessage(message+dots, title); + pdotnum = dotnum; + } + }; + showProgress(0, 100); + // start with all rooms completely walled off + rooms.fill(TOP|LEFT|BOTTOM|RIGHT); + const + // is room at row,col already linked? + linked = (row, col) => !!(rooms[iFromRC(row, col)]&LINKED), + // pick random array element + pickRandom = (arr) => arr[Math.floor(Math.random()*arr.length)]; + // starting with top-right room seems to generate more interesting mazes + rooms[cols] |= LINKED; + let todo = [cols], done = 1; + while(todo.length) { + const index = pickRandom(todo); + const rc = rcFromI(index), + row = rc[0], col = rc[1]; + let sides = []; + if ((col>0) && !linked(row, col-1)) sides.push(LEFT); + if ((col0) && !linked(row-1, col)) sides.push(TOP); + if ((row0 && !(walls&LEFT) && dist[i-1]>d+1) { + dist[i-1] = d+1; + todo.push(i-1); + } + if (row>0 && !(walls&TOP) && dist[i-cols]>d+1) { + dist[i-cols] = d+1; + todo.push(i-cols); + } + if (cold+1) { + dist[i+1] = d+1; + todo.push(i+1); + } + if (rowd+1) { + dist[i+cols] = d+1; + todo.push(i+cols); + } + } + + route = [rooms.length-1]; + while(true) { + const i = route[0], d = dist[i], walls = rooms[i], + rc = rcFromI(i), + row = rc[0], col = rc[1]; + if (i===0) { break; } + if (col0 && !(walls&TOP) && dist[i-cols]0 && !(walls&LEFT) && dist[i-1] { + const rc = rcFromI(i), + row = rc[0], col = rc[1], + x = (col+0.5)*cW, y = (row+0.5)*rH; + g.lineTo(x, y); + }); + } + + /** + * Move the ball + */ + function move() { + const a = Bangle.getAccel(); + const fx = (-a.x*w)-(sign(vx)*d*a.z), fy = (-a.y*w)-(sign(vy)*d*a.z); + vx += fx/m; + vy += fy/m; + const s = Math.ceil(Math.max(Math.abs(vx), Math.abs(vy))); + for(let n = s; n>0; n--) { + x += vx/s; + y += vy/s; + bounce(); + } + if (x>sW-cW+r && y>sH-rH+r) win(); + } + + /** + * Check whether we hit any walls, and if so: Bounce. + * + * Bounce = reverse velocity in bounce direction, multiply with elasticity + * Also apply drag in perpendicular direction ("friction with the wall") + */ + function bounce() { + const row = Math.floor(y/sH*rows), col = Math.floor(x/sW*cols), + i = row*cols+col, walls = rooms[i]; + if (vx<0) { + const left = col*cW+r; + if ((walls&LEFT) && x<=left) { + x += (1+e)*(left-x); + const fy = sign(vy)*d*Math.abs(vx); + vy -= fy/m; + vx = -vx*e; + } + } else { + const right = (col+1)*cW-r; + if ((walls&RIGHT) && x>=right) { + x -= (1+e)*(x-right); + const fy = sign(vy)*d*Math.abs(vx); + vy -= fy/m; + vx = -vx*e; + } + } + if (vy<0) { + const top = row*rH+r; + if ((walls&TOP) && y<=top) { + y += (1+e)*(top-y); + const fx = sign(vx)*d*Math.abs(vy); + vx -= fx/m; + vy = -vy*e; + } + } else { + const bottom = (row+1)*rH-r; + if ((walls&BOTTOM) && y>=bottom) { + y -= (1+e)*(y-bottom); + const fx = sign(vx)*d*Math.abs(vy); + vx -= fx/m; + vy = -vy*e; + } + } + } + + /** + * You reached the bottom-right corner, you win! + */ + function win() { + clearInterval(intervalID); + Bangle.buzz().then(askAgain); + } + + /** + * You solved the maze, try the next one? + */ + function askAgain() { + const nextLevel = (size>minSize)?"next level":"again"; + const nextSize = (size>minSize)?sizes[sizes.indexOf(size)+1]:size; + showPrompt(`Well done!\n\nPlay ${nextLevel}?`, + {"title": "Congratulations!"}) + .then(function(again) { + if (again) { + playMaze(nextSize); + } else { + startGame(); + } + }); + } + + function tick() { + ppx = px; + ppy = py; + px = x; + py = y; + move(); + drawUpdate(); + } + + start(); + } + + /** + * Ask player what size maze they would like to play + */ + function startGame() { + let menu = { + "": { + title: "Select Maze Size", + selected: sizes.indexOf(settings.size || defaultSize), + }, + }; + sizes.filter(s => s>=minSize).forEach(size => { + let name = sizeNames[size]; + if (size { + // remember chosen size + settings.size = size; + require("Storage").write("ballmaze.json", settings); + playMaze(size); + }; + }); + menu["< Exit"] = () => load(); + showMenu(menu); + } + + startGame(); +})(); diff --git a/apps/ballmaze/icon.js b/apps/ballmaze/icon.js new file mode 100644 index 000000000..10b5a502e --- /dev/null +++ b/apps/ballmaze/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4AU9wAOCw0OC5/gFyowHC+Hs5gACC7HhiMRjwXSCoIADC5wCB4MSkIXDGIoXKiUikQwJC5PhCwIXFGAgXJFwRHEGAnOC5HhC5IwC5gXJIw4XF4AXKFwwXEGAoXCiKlFMAzNCgDpDC4QAKcgZJBC6wADF6kAhgXP5xfEC58SC4iNCC4nhC5McC4S/DC6a9DC4IACC5MhC4XOC5HuLxPMC4PuC5IwHkUeC44ABA4IACFw5cBC5owEkUhjwXPGAyMCC5wxDLgIACC54ADC94AGC7sOCx/gC4owQCwwA/AH4AMA")) diff --git a/apps/ballmaze/icon.png b/apps/ballmaze/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..44697db4b75e49c76f668a4da1275b040f1d6fd7 GIT binary patch literal 444 zcmV;t0Ym4UUAPlroCJC$1Svpf^DXX-r@I8EuYDFP7;1rO2 zQeP^R-1+hGBB5-u_oCr624NNa!kt}*6zh+GX3n<0y z77qV^KI8A&C@o@%1NRV$UR)|ht%%q3{q4zz5FiMJ=Xyj_;3`>vEr zAOGRLg@Rs%ygP%_Ou0Mekl)-Ium z2h$Y%LDzIM<$KYAM%vCa(uZruYsycoDhIUEh?38x4|i0pPN7y2v~XLV)qF2hvoocU z-^k|L2s$mUcVn(3EKzbwYXoEN$y)sby6#WCcip|#ep&mo_x?Wn z`@`PPrvZF#UF}`k6beO`=i_;l?1^_3)+AfbvAGhmgHk+rfiPJ_aLfe?MSGOz=^iKy zUzl`DKJm}(e?Mn!j-shJMNWs2lh5ezPSDi!5E=uY-?}>sHpX>~^yrt7=I2YywPEGT zT$(Iwq57*6uac`C$U3INs|7vx2Zw`#f}C19MW}>piY0&seE%L;WX6s7h+9)m!3qoN z(ja)B2E2`lCjCM*U7}#8C|DE-y=Q!Vh=De4K?D3Gc-P~BgCKMTfG#5RM?ztUw*+^P zaQ6eC0ZlLu(}OkXR+e1F^uOYF17HsY?1JDEZ1&gY+=!ij7LiArZ!*;1VgLXgL?)1p z6;;6xi;2=)<+vbdO8sl--_*Oj6@g&OVmM5Gm7~+@T6H<|F&e5RMKOL=87vH1@P4j^D5GF~tn1oWt_< z*{QVymPwIIO``2!AvJe-p^~MQyD{}Nt`a4V$KHZLZ-l*FJ;b_+ClnPasWy;bY8>QZ4(XgO~11;04$bDW8p$UBM?J#`9L#G4kAY zwX+YoT4c*bk3^K=1^fy8r%bC$xDDt{4-MtB)Ii$FQ zXV_J`saRW2YRO}*`0f$bfSQ?LZ9PvPF~z#ThPj-(4QjdaWsgt7m(dFr3}Vvfs-wSb zsf$6V@RJkITnP&X>7Pnt{Zpf>j#;u~1o{ioHmtScLWHw!H8=ub9dfsrdzpgeCzW}j z{t--!W_NDDq}$}@TtwBf%$sF}xpj$|*g(?Qe4Sf?U|6s`tnN9FT;osWt<6ckoVOD` zxnZ%!A_64+l>>nPaN_L1M5m#%YdiI~fxO$l;|vWN)vDcP_m8QnbWWd2iVX~e2DsS< zw{GTn8-?5yJNLLIuP0cte4U?>FmhMNBN*4KlZPEErE_Tp_`2CZ-g>+zSUGNVH&TIX!e)2tTwz_)< z-IdMQ8>VSc%b*`9!}*z#%$f<+!?un2SvH6w>+Lm%(SZF;IJGRq#{6iD#=_+YaoodlTuOrAbP6FuC* zX3a6aMMMYIPM$S&BHBioznin{#ZzSdY&R1F$_!t{VYAJO7>Inel5(VPV{0YtFlt{+ z!Dhe7Z~z}eFuN!KfMysd!Cv8eMUd%J0mDXuvq92xc{jX;i4yi6RC+m?9xac2xD$&6 zA!DyQ6mXfmmvJ`B+@4IO9>e|Dl2ZB&jK*Tw7Baet8lU@q%FyHf@M?~Jg0gi3qu>b%7 literal 0 HcmV?d00001 diff --git a/apps/ballmaze/size_select.png b/apps/ballmaze/size_select.png new file mode 100644 index 0000000000000000000000000000000000000000..cac278820c92c15dce2a7897279c0299fe50b84a GIT binary patch literal 4409 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 Pg+ToG1^HHalhXbJ%Igu= literal 0 HcmV?d00001 From 615aeef4cdd0b226a432c4b50b1c9f0f916d74b5 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 26 Apr 2020 05:35:50 +0200 Subject: [PATCH 0593/1189] ballmaze: also bounce off corners --- apps/ballmaze/app.js | 68 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/apps/ballmaze/app.js b/apps/ballmaze/app.js index b249d6494..cce296f2c 100644 --- a/apps/ballmaze/app.js +++ b/apps/ballmaze/app.js @@ -99,9 +99,8 @@ y = rH/2; vx = vy = 0; ppx = px = x; - ppy = py = y + ppy = py = y; - clearWatch(); generateMaze(); // this shows unbuffered progress messages if (settings.cheat && r>1) findRoute(); // not enough memory for r==1 :-( @@ -395,7 +394,7 @@ y += vy/s; bounce(); } - if (x>sW-cW+r && y>sH-rH+r) win(); + if (x>sW-cW && y>sH-rH) win(); } /** @@ -407,40 +406,79 @@ function bounce() { const row = Math.floor(y/sH*rows), col = Math.floor(x/sW*cols), i = row*cols+col, walls = rooms[i]; + const left = col*cW, + right = (col+1)*cW, + top = row*rH, + bottom = (row+1)*rH; + let bounced = false; if (vx<0) { - const left = col*cW+r; - if ((walls&LEFT) && x<=left) { - x += (1+e)*(left-x); + if ((walls&LEFT) && x<=left+r) { + x += (1+e)*(left+r-x); const fy = sign(vy)*d*Math.abs(vx); vy -= fy/m; vx = -vx*e; + bounced = true; } } else { - const right = (col+1)*cW-r; - if ((walls&RIGHT) && x>=right) { - x -= (1+e)*(x-right); + if ((walls&RIGHT) && x>=right-r) { + x -= (1+e)*(x+r-right); const fy = sign(vy)*d*Math.abs(vx); vy -= fy/m; vx = -vx*e; + bounced = true; } } if (vy<0) { - const top = row*rH+r; - if ((walls&TOP) && y<=top) { - y += (1+e)*(top-y); + if ((walls&TOP) && y<=top+r) { + y += (1+e)*(top+r-y); const fx = sign(vx)*d*Math.abs(vy); vx -= fx/m; vy = -vy*e; + bounced = true; } } else { - const bottom = (row+1)*rH-r; - if ((walls&BOTTOM) && y>=bottom) { - y -= (1+e)*(y-bottom); + if ((walls&BOTTOM) && y>=bottom-r) { + y -= (1+e)*(y+r-bottom); const fx = sign(vx)*d*Math.abs(vy); vx -= fx/m; vy = -vy*e; + bounced = true; } } + if (bounced) return; + let cx, cy; + if ((rooms[i-1]&TOP) || rooms[i-cols]&LEFT) { + if ((x-left)*(x-left)+(y-top)*(y-top)<=r*r) { + cx = left; + cy = top; + } + } + else if ((rooms[i-1]&BOTTOM) || rooms[i+cols]&LEFT) { + if ((x-left)*(x-left)+(bottom-y)*(bottom-y)<=r*r) { + cx = left; + cy = bottom; + } + } + else if ((rooms[i+1]&TOP) || rooms[i-cols]&RIGHT) { + if ((right-x)*(right-x)+(y-top)*(y-top)<=r*r) { + cx = right; + cy = top; + } + } + else if ((rooms[i+1]&BOTTOM) || rooms[i+cols]&RIGHT) { + if ((right-x)*(right-x)+(bottom-y)*(bottom-y)<=r*r) { + cx = right; + cy = bottom; + } + } + if (!cx) return; + let nx = x-cx, ny = y-cy; + const l = Math.sqrt(nx*nx+ny*ny); + nx /= l; + ny /= l; + const p = vx*nx+vy*ny; + vx -= 2*p*nx*e; + vy -= 2*p*ny*e; } /** From a08c0383b4d7dcd2ea61c608385527d03a19268f Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sun, 26 Apr 2020 08:45:35 +0200 Subject: [PATCH 0594/1189] Bug fix for hours in early morning. --- apps/impwclock/clock-impword.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js index dafbbfcf5..c54fa7976 100644 --- a/apps/impwclock/clock-impword.js +++ b/apps/impwclock/clock-impword.js @@ -20,7 +20,7 @@ const allWords = [ const timeOfDay = { 0: ["", 0, 0], - 1: ["EARLYMORNING", 10, 11, 12, 13, 14, 02, 12, 22, 32, 42, 52, 62], + 1: ["EARLYMORNING", 10, 20, 30, 40, 50, 02, 12, 22, 32, 42, 52, 62], 2: ["MORNING", 02, 12, 22, 32, 42, 52, 62], 3: ["LATEMORNING", 01, 11, 21, 31, 02, 12, 22, 32, 42, 52, 62], 4: ["MIDDAY", 13, 23, 33, 54, 64, 74], @@ -30,7 +30,7 @@ const timeOfDay = { 8: ["EARLYEVENING", 10, 20, 30, 40, 50, 06, 16, 26, 36, 46, 56, 66], 9: ["EVENING", 06, 16, 26, 36, 46, 56, 66], 10: ["NIGHT", 37, 47, 57, 67, 77], - 11: ["MIDDLEOFTHENIGHT", 32, 33, 34, 35, 36, 37, 50, 51, 54, 55, 56, 73,74,75,76,77 ], + 11: ["MIDDLEOFTHENIGHT", 13, 23, 33, 43, 53, 63, 05, 15, 45, 55, 65, 37,47,57,67,77 ], }; From 02eb4d5c407cdce9a9519b8823499f749e62aa5f Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 26 Apr 2020 14:59:41 +0200 Subject: [PATCH 0595/1189] ballmaze: handle broken settings JSON --- apps/ballmaze/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ballmaze/app.js b/apps/ballmaze/app.js index cce296f2c..3e26277b7 100644 --- a/apps/ballmaze/app.js +++ b/apps/ballmaze/app.js @@ -1,6 +1,6 @@ (() => { let intervalID; - let settings = require("Storage").readJSON("ballmaze.json") || {}; + let settings = require("Storage").readJSON("ballmaze.json",true) || {}; // density, elasticity of bounces, "drag coefficient" const rho = 100, e = 0.3, C = 0.01; From dd014d5a268ef3fcbce70e1e51ffd618058ba35c Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 27 Apr 2020 10:35:11 +0200 Subject: [PATCH 0596/1189] Active Pedometer 0.04 --- apps/activepedom/ChangeLog | 3 ++- apps/activepedom/README.md | 19 ++++++++++--------- apps/activepedom/app.js | 2 +- apps/activepedom/widget.js | 21 +++++++++++---------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/apps/activepedom/ChangeLog b/apps/activepedom/ChangeLog index c1b9ec011..ca26a648a 100644 --- a/apps/activepedom/ChangeLog +++ b/apps/activepedom/ChangeLog @@ -1,3 +1,4 @@ 0.01: New Widget! 0.02: Distance calculation and display -0.03: Data logging and display \ No newline at end of file +0.03: Data logging and display +0.04: Steps are set to 0 in log on new day \ No newline at end of file diff --git a/apps/activepedom/README.md b/apps/activepedom/README.md index f45297e57..a2a351a12 100644 --- a/apps/activepedom/README.md +++ b/apps/activepedom/README.md @@ -18,7 +18,7 @@ Steps are saved to a datafile every 5 minutes. You can watch a graph using the a * 10600 steps ![](10600.png) -## Features +## Features Widget * Two line display * Can display distance (in km) or steps in each line @@ -32,22 +32,23 @@ Steps are saved to a datafile every 5 minutes. You can watch a graph using the a * 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 +## Features 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 + ## Data storage -* Data is stored to a file +* Data is stored to a file named activepedomYYYYMMDD.data (activepedom20200427.data) +* One file is created for each day * Format: now,stepsCounted,active,stepsTooShort,stepsTooLong,stepsOutsideTime -* now is UNIX timestamp in ms -* You can chose the app to watch a steps graph +* 'now' is UNIX timestamp in ms +* You can use 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 index 0a9b3b93f..cc875f371 100644 --- a/apps/activepedom/app.js +++ b/apps/activepedom/app.js @@ -162,4 +162,4 @@ 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 c6bd410ce..2ae1b9b62 100644 --- a/apps/activepedom/widget.js +++ b/apps/activepedom/widget.js @@ -33,27 +33,28 @@ function storeData() { now = new Date(); - month = now.getMonth() + 1; - if (month < 10) month = "0" + month; - filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data"; + month = now.getMonth() + 1; //month is 0-based + if (month < 10) month = "0" + month; //leading 0 + filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data"; //new file for each day dataFile = s.open(filename,"a"); - if (dataFile) { + if (dataFile) { //check if filen already exists if (dataFile.getLength() == 0) { - stepsToWrite = 0; - } - else { - stepsToWrite = stepsCounted; + //new day, set steps to 0 + stepsCounted = 0; + stepsTooShort = 0; + stepsTooLong = 0; + stepsOutsideTime = 0; } dataFile.write([ now.getTime(), - stepsToWrite, + stepsCounted, active, stepsTooShort, stepsTooLong, stepsOutsideTime, ].join(",")+"\n"); } - dataFile = undefined; + dataFile = undefined; //save memory } //return setting From 7630f1f23e8580735d8b278789cc8b1d7b26dcfe Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Mon, 27 Apr 2020 10:35:59 +0200 Subject: [PATCH 0597/1189] Active Pedometer 0.04 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 36498423e..f405e14ab 100644 --- a/apps.json +++ b/apps.json @@ -1127,7 +1127,7 @@ "name": "Active Pedometer", "shortName":"Active Pedometer", "icon": "app.png", - "version":"0.03", + "version":"0.04", "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", "readme": "README.md", From e3e57267b48cf927d405deba64e70698c1a1f17a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 27 Apr 2020 11:43:35 +0100 Subject: [PATCH 0598/1189] new about page pixels --- apps.json | 2 +- apps/about/ChangeLog | 1 + apps/about/app.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 43e7e4b9d..57ceac04d 100644 --- a/apps.json +++ b/apps.json @@ -53,7 +53,7 @@ { "id": "about", "name": "About", "icon": "app.png", - "version":"0.04", + "version":"0.05", "description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers", "tags": "tool,system", "allow_emulator":true, diff --git a/apps/about/ChangeLog b/apps/about/ChangeLog index 2c81c0537..16aea0610 100644 --- a/apps/about/ChangeLog +++ b/apps/about/ChangeLog @@ -2,3 +2,4 @@ 0.02: Update version checker for new filename type 0.03: Actual pixels as of 5 Mar 2020 0.04: Actual pixels as of 9 Mar 2020 +0.05: Actual pixels as of 27 Apr 2020 diff --git a/apps/about/app.js b/apps/about/app.js index dc7b0cad8..57c85563d 100644 --- a/apps/about/app.js +++ b/apps/about/app.js @@ -29,5 +29,5 @@ g.drawString(NRF.getAddress(),120,232); g.flip(); // Pixel chooser image -g.drawImage(require("heatshrink").decompress(atob("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")),0,135); +g.drawImage(require("heatshrink").decompress(atob("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")),0,135); g.flip(); From 35470a151e99f851360a216290a615bad151211e Mon Sep 17 00:00:00 2001 From: fredericrous Date: Mon, 27 Apr 2020 12:15:30 +0100 Subject: [PATCH 0599/1189] improve ui, add 2 player local prepare the ground for 2 players bluetooth --- apps.json | 3 +- apps/pong/ChangeLog | 1 + apps/pong/app.js | 288 +++++++++++++++++++++++++++++++++----------- 3 files changed, 218 insertions(+), 74 deletions(-) diff --git a/apps.json b/apps.json index f167acf5d..5708e6d62 100644 --- a/apps.json +++ b/apps.json @@ -1486,11 +1486,12 @@ "name": "Pong", "shortName": "Pong", "icon": "pong.png", - "version": "0.01", + "version": "0.02", "description": "A clone of the Atari game Pong", "tags": "game", "type": "app", "allow_emulator": true, + "readme": "README.md", "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 index 5560f00bc..6433ebce4 100644 --- a/apps/pong/ChangeLog +++ b/apps/pong/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: 2 players local + improve ai diff --git a/apps/pong/app.js b/apps/pong/app.js index 4531b3af8..272eaf2e7 100644 --- a/apps/pong/app.js +++ b/apps/pong/app.js @@ -8,6 +8,7 @@ * - Let's make pong, One Man Army Studios, Youtube * - Pong.js, KanoComputing, Github * - Coding Challenge #67: Pong!, The Coding Train, Youtube + * - Pixl.js Multiplayer Pong, espruino website */ const SCREEN_WIDTH = 240; @@ -15,6 +16,13 @@ const FPS = 16; const MAX_SCORE = 11; let scores = [0, 0]; let aiSpeedRandom = 0; +let winnerMessage = ''; + +const sound = { + ping: () => Bangle.beep(8, 466), + pong: () => Bangle.beep(8, 220), + fall: () => Bangle.beep(16*3, 494).then(_ => Bangle.beep(32*3, 3322)) +}; function Vector(x, y) { this.x = x; @@ -28,12 +36,18 @@ Vector.prototype.add = function (x) { 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); -}; +const intersects = (circ, rect, right) => { + var c = circ.pos; + c.r = circ.r; + if (c.y - c.r < rect.pos.y + rect.height && c.y + c.r > rect.pos.y) { + if (right) { + return c.x + c.r > rect.pos.x - rect.width*2 && c.x < rect.pos.x + rect.width + } else { + return c.x - c.r < rect.pos.x + rect.width*2 && c.x > rect.pos.x - rect.width + } + } + return false; +} ///////////////////////////// Ball ////////////////////////////////////////// @@ -45,12 +59,26 @@ function Ball() { this.reset(); } -Ball.prototype.show = function () { +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)); + this.ballReturn = 0; +}; +Ball.prototype.restart = function() { + this.reset(); + 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); +}; +Ball.prototype.show = function (invert) { if (this.prevPos != null) { - g.setColor(0); + g.setColor(invert ? -1 : 0); g.fillCircle(this.prevPos.x, this.prevPos.y, this.prevPos.r); } - g.setColor(-1); + g.setColor(invert ? 0 : -1); g.fillCircle(this.pos.x, this.pos.y, this.r); this.prevPos = { x: this.pos.x, @@ -58,55 +86,62 @@ Ball.prototype.show = function () { r: this.r }; }; -Ball.prototype.bouncePlayer = function (multiplyX, multiplyY, player) { +function bounceAngle(playerY, ballY, playerHeight, maxHangle) { + let relativeIntersectY = (playerY + (playerHeight/2)) - ballY; + let normalizedRelativeIntersectionY = relativeIntersectY / (playerHeight/2); + let bounceAngle = normalizedRelativeIntersectionY * maxHangle; + return { x: Math.cos(bounceAngle), y: -Math.sin(bounceAngle) }; +} +Ball.prototype.bouncePlayer = function (directionX, directionY, player) { + this.ballReturn++; 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; + var angle = bounceAngle(player.pos.y, this.pos.y, player.height, MAX_BOUNCE_ANGLE) + this.velocity.x = this.speed * angle.x * directionX; + this.velocity.y = this.speed * angle.y * directionY; + this.ballReturn % 2 === 0 ? sound.ping() : sound.pong(); }; -Ball.prototype.bounce = function (multiplyX, multiplyY, player) { +Ball.prototype.bounce = function (directionX, directionY, player) { if (player) - return this.bouncePlayer(multiplyX, multiplyY, player); + return this.bouncePlayer(directionX, directionY, player); - if (multiplyX) { - this.velocity.x = Math.abs(this.velocity.x) * multiplyX; + if (directionX) { + this.velocity.x = Math.abs(this.velocity.x) * directionX; } - if (multiplyY) { - this.velocity.y = Math.abs(this.velocity.y) * multiplyY; + if (directionY) { + this.velocity.y = Math.abs(this.velocity.y) * directionY; } }; -Ball.prototype.checkWallsCollision = function () { +Ball.prototype.fall = function (playerId) { + scores[playerId]++; + if (scores[playerId] >= MAX_SCORE) { + this.restart(); + state = 3; + if (playerId === 1) { + winnerMessage = startOption === 0 ? "AI Wins!" : "Player 2 Wins!"; + } else { + winnerMessage = startOption === 0 ? "You Win!" : "Player 1 Wins!"; + } + } else { + sound.fall(); + this.reset(); + } +}; +Ball.prototype.wallCollision = 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(); - } + this.fall(1); } else if (this.pos.x > SCREEN_WIDTH) { - scores[0]++; - if (scores[0] >= MAX_SCORE) { - this.restart(); - state = 3; - winnerMessage = "You Win!"; - } else { - this.reset(); - } + this.fall(0); } else { return false; } return true; }; -Ball.prototype.checkPlayerCollision = function (player) { +Ball.prototype.playerCollision = function (player) { if (intersects(this, player)) { if (this.pos.x < SCREEN_WIDTH/2) { this.bounce(1, 1, player); @@ -120,8 +155,8 @@ Ball.prototype.checkPlayerCollision = function (player) { } return false; }; -Ball.prototype.checkCollisions = function () { - return this.checkWallsCollision() || this.checkPlayerCollision(player) || this.checkPlayerCollision(ai); +Ball.prototype.collisions = function () { + return this.wallCollision() || this.playerCollision(player) || this.playerCollision(ai); }; Ball.prototype.updatePosition = function () { var elapsed = new Date().getTime() - this.lastUpdate; @@ -132,31 +167,20 @@ Ball.prototype.updatePosition = function () { 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); + this.collisions(); }; //////////////////////////// Player ///////////////////////////////////////// -function Player() { +function Player(right) { this.width = 4; this.height = 30; - this.pos = new Vector(this.width*2, SCREEN_WIDTH/2 - this.height/2); + this.pos = new Vector(right ? SCREEN_WIDTH-this.width : this.width, SCREEN_WIDTH/2 - this.height/2); this.acc = new Vector(0, 0); this.speed = 15; this.maxSpeed = 25; this.prevPos = null; + this.right = right; } Player.prototype.show = function () { if (this.prevPos != null) { @@ -196,11 +220,14 @@ function AI() { 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); + var y = ball.pos.y - this.height/2; + var randomizedY = ball.ballReturn < 3 ? y : y + (aiSpeedRandom * this.height/2); + var yConstrained = constrain(randomizedY, 0, SCREEN_WIDTH-this.height); this.pos = new Vector(this.pos.x, yConstrained); }; +/////////////////////////////// Scenes //////////////////////////////////////// + function net() { var dashSize = 5; for (let y = dashSize/2; y < SCREEN_WIDTH; y += dashSize*2) { @@ -210,12 +237,6 @@ function net() { } } -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; @@ -233,10 +254,80 @@ function drawScores() { function drawGameOver() { g.setFont("Vector", 20); - g.drawString(winnerMessage, 75, SCREEN_WIDTH/2 - 10); + g.drawString(winnerMessage, startOption === 0 ? 55 : 75, SCREEN_WIDTH/2 - 10); } -function draw() { +function showControls(hide) { + g.setColor(hide ? 0 : -1); + g.setFont("Vector", 8); + var topArrowString = ` + ######## + ## + ## ## + ### ## + ### ## + ### +## +`; + + var arrows = [Graphics.createImage(topArrowString), Graphics.createImage(` + ## + ## +#################### + ## + ## +`), Graphics.createImage(topArrowString.split('\n').reverse().join('\n')) + ]; + + g.drawString('UP', 170, 50); + g.drawImage(arrows[0], 200, 40); + g.drawString('DOWN', 156, 120); + g.drawImage(arrows[1], 200, 120); + g.drawString('START', 152, 190); + g.drawImage(arrows[2], 200, 200); +} + +function drawStartScreen(hide) { + g.setColor(hide ? 0 : -1); + g.setFont("Vector", 10); + g.drawString("1 PLAYER", 95, 80); + g.drawString("2 PLAYERS", 95, 110); + + const ball1 = new Ball(); + ball1.prevPos = null; + ball1.pos = new Vector(87, 86); + ball1.show(hide || !(startOption === 0)); + + const ball2 = new Ball(); + ball2.prevPos = null; + ball2.pos = new Vector(87, 116); + ball2.show(hide || !(startOption === 1)); +} + +function drawStartTimer(count, callback) { + setTimeout(_ => { + player.show(); + ai.show(); + net(); + g.setColor(0); + g.fillRect(117-7, 115-7, 117+14, 115+14); + if (count >= 0) { + g.setFont("Vector", 10); + g.drawString(count+1, 115, 115); + g.setColor(-1); + g.drawString(count === 0 ? 'Go!' : count, 115 - (count === 0 ? 4: 0), 115); + drawStartTimer(count - 1, callback); + } else { + g.setColor(0); + g.fillRect(117-7, 115-7, 117+14, 115+14); + callback(); + } + }, 800); +} + +//////////////////////////////// Main ///////////////////////////////////////// + +function onFrame() { if (state === 1) { ball.update(); player.update(); @@ -261,22 +352,73 @@ function draw() { drawScores(); } +function startThatGame() { + player.show(); + ai.show(); + net(); + drawScores(); + drawStartTimer(3, () => setInterval(onFrame, 1000 / FPS)); +} + +var player = new Player(); +var ai; +var ball = new Ball(); +var state = 0; +var prevScores = [0, 0]; +var playerBle = null; +var startOption = 0; + g.clear(); g.setColor(0); g.fillRect(0,0,240,240); +showControls(); +setTimeout(() => { + showControls(true); + drawStartScreen(); +}, 2000); -setInterval(draw, 1000 / FPS); +////////////////////////////// Controls /////////////////////////////////////// -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 => { + if (state === 0) { + if (o.state) { + startOption = startOption === 0 ? startOption : startOption - 1; + drawStartScreen(); + } + } else o.state ? player.up() : player.stop(); +}, BTN1, {repeat: true, edge: 'both'}); +setWatch(o => { + if (state === 0) { + if (o.state) { + startOption = startOption === 1 ? startOption : startOption + 1; + drawStartScreen(); + } + } else o.state ? player.down() : player.stop(); +}, BTN2, {repeat: true, edge: 'both'}); setWatch(o => { state++; + clearInterval(); if (state >= 2) { - ball.restart(); g.setColor(0); - g.fillRect(0,0,240,240); + g.fillRect(0, 0, 240, 240); + ball.show(true); scores = [0, 0]; + playerBle = null; + ball = new Ball(); state = 1; + startThatGame(); + } else { + drawStartScreen(true); + showControls(true); + if (startOption === 1) { + ai = new Player(true); + startThatGame(); + } else { + ai = new AI(); + startThatGame(); + } } -}, BTN2, {repeat: true}); +}, BTN3, {repeat: true}); + +setWatch(o => startOption === 1 && (o.state ? ai.up() : ai.stop()), BTN4, {repeat: true, edge: 'both'}); +setWatch(o => startOption === 1 && (o.state ? ai.down() : ai.stop()), BTN5, {repeat: true, edge: 'both'}); From e03d33edc10fef8a720e0f51744d8608f0a4d8e7 Mon Sep 17 00:00:00 2001 From: fredericrous Date: Mon, 27 Apr 2020 14:13:26 +0100 Subject: [PATCH 0600/1189] add readme, remove impurity --- apps/pong/README.md | 28 ++++++++++++++++++++++++++++ apps/pong/app.js | 8 ++++---- 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 apps/pong/README.md diff --git a/apps/pong/README.md b/apps/pong/README.md new file mode 100644 index 000000000..ea4939539 --- /dev/null +++ b/apps/pong/README.md @@ -0,0 +1,28 @@ +# Pong + +A clone of the Atari game Pong + + + +## Features + +- Play against a dumb AI +- Play local Multiplayer against your friends + +## Controls + +Player's controls: +- UP: BTN1 +- DOWN: BTN2 +long press to move faster + +Restart a game: +- RESET: BTN3 + +Buttons for player 2: +- UP: BTN4 +- DOWN: BTN5 + +## Creator + + diff --git a/apps/pong/app.js b/apps/pong/app.js index 272eaf2e7..ba34d60b5 100644 --- a/apps/pong/app.js +++ b/apps/pong/app.js @@ -38,12 +38,12 @@ 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, right) => { var c = circ.pos; - c.r = circ.r; - if (c.y - c.r < rect.pos.y + rect.height && c.y + c.r > rect.pos.y) { + var r = circ.r; + if (c.y - r < rect.pos.y + rect.height && c.y + r > rect.pos.y) { if (right) { - return c.x + c.r > rect.pos.x - rect.width*2 && c.x < rect.pos.x + rect.width + return c.x + r > rect.pos.x - rect.width*2 && c.x < rect.pos.x + rect.width } else { - return c.x - c.r < rect.pos.x + rect.width*2 && c.x > rect.pos.x - rect.width + return c.x - r < rect.pos.x + rect.width*2 && c.x > rect.pos.x - rect.width } } return false; From 727d7a1452f4ed87952e7b4293cbca4275bca553 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 27 Apr 2020 16:12:13 +0100 Subject: [PATCH 0601/1189] Online minification test --- index.html | 1 + js/appinfo.js | 10 + js/espruinotools.js | 33208 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 33219 insertions(+) create mode 100644 js/espruinotools.js diff --git a/index.html b/index.html index 3c8b440e4..c13bc0b36 100644 --- a/index.html +++ b/index.html @@ -156,6 +156,7 @@ + diff --git a/js/appinfo.js b/js/appinfo.js index 9fff7c92a..e5e50aa5c 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -11,6 +11,16 @@ var AppInfo = { return Promise.resolve(storageFile); else if (storageFile.url) return fileGetter(`apps/${app.id}/${storageFile.url}`).then(content => { + if (storageFile.url.endsWith(".js") && !storageFile.url.endsWith(".min.js")) { // if original file ends in '.js'... + return Espruino.transform(content, { + SET_TIME_ON_WRITE : false, + //PRETOKENISE : true, // pretokenise still has an issue with number passing + MINIFICATION_LEVEL : "ESPRIMA", + builtinModules : "Flash,Storage,heatshrink,tensorflow,locale" + }); + } else + return content; + }).then(content => { return { name : storageFile.name, content : content, diff --git a/js/espruinotools.js b/js/espruinotools.js new file mode 100644 index 000000000..d40ab7c77 --- /dev/null +++ b/js/espruinotools.js @@ -0,0 +1,33208 @@ +// EspruinoTools (https://github.com/espruino/EspruinoTools) + +if (typeof $ === "undefined") { + var jqReady = []; + var jqShim = { + ready : function(cb) { jqReady.push(cb); }, + css : function() {}, + html : function() {}, + width : function() {}, + height : function() {}, + addClass : function() {}, + removeClass : function() {}, + appendTo : function() { return jqShim; }, + show : function() {}, + hide : function() {}, + }; + var $ = function() { return jqShim; }; +} +/** + Copyright 2014 Gordon Williams (gw@pur3.co.uk) + + This Source Code is subject to the terms of the Mozilla Public + License, v2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + ------------------------------------------------------------------ + Initialisation code + ------------------------------------------------------------------ +**/ +"use strict"; + +var Espruino; + +(function() { + + /** List of processors. These are functions that are called one + * after the other with the data received from the last one. + * + * Common processors are: + * + * sending - sending code to Espruino (no data) + * transformForEspruino - transform code ready to be sent to Espruino + * transformModuleForEspruino({code,name}) + * - transform module code before it's sent to Espruino with Modules.addCached (we only do this if we don't think it's been minified before) + * connected - connected to Espruino (no data) + * disconnected - disconnected from Espruino (no data) + * environmentVar - Board's process.env loaded (object to be saved into Espruino.Env.environmentData) + * boardJSONLoaded - Board's JSON was loaded into environmentVar + * getModule - Called with data={moduleName:"foo", moduleCode:undefined} - moduleCode should be filled in if the module can be found + * getURL - Called with data={url:"http://....", data:undefined) - data should be filled in if the URL is handled (See Espruino.Core.Utils.getURL to use this) + * terminalClear - terminal has been cleared + * terminalPrompt - we've received a '>' character (eg, `>` or `debug>`). The argument is the current line's contents. + * terminalNewLine - When we get a new line on the terminal, this gets called with the last line's contents + * debugMode - called with true or false when debug mode is entered or left + * editorHover - called with { node : htmlNode, showTooltip : function(htmlNode) } when something is hovered over + * notification - called with { mdg, type:"success","error"/"warning"/"info" } + **/ + var processors = {}; + + function init() { + + Espruino.Core.Config.loadConfiguration(function() { + // Initialise all modules + function initModule(modName, mod) { + console.log("Initialising "+modName); + if (mod.init !== undefined) + mod.init(); + } + + var module; + for (module in Espruino.Core) initModule(module, Espruino.Core[module]); + for (module in Espruino.Plugins) initModule(module, Espruino.Plugins[module]); + + callProcessor("initialised", undefined, function() { + // We need the delay because of background.js's url_handler... + setTimeout(function() { + Espruino.initialised = true; + }, 1000); + }); + }); + } + + // workaround for broken chrome on Mac + if (navigator.userAgent.indexOf("Mac OS X")>=0 && + navigator.userAgent.indexOf("Chrome/33.0.1750")>=0) { + $(document).ready(function() { window.setTimeout(init,100); }); + } else { + $(document).ready(init); + } + + /** Add a processor function of type function(data,callback) */ + function addProcessor(eventType, processor) { + if (processors[eventType]===undefined) + processors[eventType] = []; + processors[eventType].push(processor); + } + + /** Call a processor function */ + function callProcessor(eventType, data, callback) { + var p = processors[eventType]; + // no processors + if (p===undefined || p.length==0) { + if (callback!==undefined) callback(data); + return; + } + // now go through all processors + var n = 0; + var cbCalled = false; + var cb = function(inData) { + if (cbCalled) throw new Error("Internal error in "+eventType+" processor. Callback is called TWICE."); + cbCalled = true; + if (n < p.length) { + cbCalled = false; + p[n++](inData, cb); + } else { + if (callback!==undefined) callback(inData); + } + }; + cb(data); + } + + // ----------------------------------- + Espruino = { + Core : { }, + Plugins : { }, + addProcessor : addProcessor, + callProcessor : callProcessor, + initialised : false, + init : init, // just in case we need to initialise this by hand + }; + + return Espruino; +})(); +Espruino.Core.Notifications = { + success : function(e) { console.log(e); }, + error : function(e) { console.error(e); }, + warning : function(e) { console.warn(e); }, + info : function(e) { console.log(e); }, +}; +Espruino.Core.Status = { + setStatus : function(e,len) { console.log(e); }, + hasProgress : function() { return false; }, + incrementProgress : function(amt) {} +}; +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.acorn = {}))); +}(this, (function (exports) { 'use strict'; + +// Reserved word lists for various dialects of the language + +var reservedWords = { + 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" +}; + +// And the keywords + +var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + +var keywords = { + 5: ecma5AndLessKeywords, + 6: ecma5AndLessKeywords + " const class extends export import super" +}; + +var keywordRelationalOperator = /^in(stanceof)?$/; + +// ## Character categories + +// Big ugly regular expressions that match characters in the +// whitespace, identifier, and identifier-start categories. These +// are only applied when a character is found to actually have a +// code point above 128. +// Generated by `bin/generate-identifier-regex.js`. + +var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; +var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + +var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); +var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + +nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; + +// These are a run-length and offset encoded representation of the +// >0xffff code points that are a valid part of identifiers. The +// offset starts at 0x10000, and each pair of numbers represents an +// offset to the next range, and then a size of the range. They were +// generated by bin/generate-identifier-regex.js + +// eslint-disable-next-line comma-spacing +var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541]; + +// eslint-disable-next-line comma-spacing +var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239]; + +// This has a complexity linear to the value of the code. The +// assumption is that looking up astral identifier characters is +// rare. +function isInAstralSet(code, set) { + var pos = 0x10000; + for (var i = 0; i < set.length; i += 2) { + pos += set[i]; + if (pos > code) { return false } + pos += set[i + 1]; + if (pos >= code) { return true } + } +} + +// Test whether a given character code starts an identifier. + +function isIdentifierStart(code, astral) { + if (code < 65) { return code === 36 } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) +} + +// Test whether a given character is part of an identifier. + +function isIdentifierChar(code, astral) { + if (code < 48) { return code === 36 } + if (code < 58) { return true } + if (code < 65) { return false } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) +} + +// ## Token types + +// The assignment of fine-grained, information-carrying type objects +// allows the tokenizer to store the information it has about a +// token in a way that is very cheap for the parser to look up. + +// All token type variables start with an underscore, to make them +// easy to recognize. + +// The `beforeExpr` property is used to disambiguate between regular +// expressions and divisions. It is set on all token types that can +// be followed by an expression (thus, a slash after them would be a +// regular expression). +// +// The `startsExpr` property is used to check if the token ends a +// `yield` expression. It is set on all token types that either can +// directly start an expression (like a quotation mark) or can +// continue an expression (like the body of a string). +// +// `isLoop` marks a keyword as starting a loop, which is important +// to know when parsing a label, in order to allow or disallow +// continue jumps to that label. + +var TokenType = function TokenType(label, conf) { + if ( conf === void 0 ) conf = {}; + + this.label = label; + this.keyword = conf.keyword; + this.beforeExpr = !!conf.beforeExpr; + this.startsExpr = !!conf.startsExpr; + this.isLoop = !!conf.isLoop; + this.isAssign = !!conf.isAssign; + this.prefix = !!conf.prefix; + this.postfix = !!conf.postfix; + this.binop = conf.binop || null; + this.updateContext = null; +}; + +function binop(name, prec) { + return new TokenType(name, {beforeExpr: true, binop: prec}) +} +var beforeExpr = {beforeExpr: true}; +var startsExpr = {startsExpr: true}; + +// Map keyword names to token types. + +var keywords$1 = {}; + +// Succinct definitions of keyword token types +function kw(name, options) { + if ( options === void 0 ) options = {}; + + options.keyword = name; + return keywords$1[name] = new TokenType(name, options) +} + +var types = { + num: new TokenType("num", startsExpr), + regexp: new TokenType("regexp", startsExpr), + string: new TokenType("string", startsExpr), + name: new TokenType("name", startsExpr), + eof: new TokenType("eof"), + + // Punctuation token types. + bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), + bracketR: new TokenType("]"), + braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), + braceR: new TokenType("}"), + parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), + parenR: new TokenType(")"), + comma: new TokenType(",", beforeExpr), + semi: new TokenType(";", beforeExpr), + colon: new TokenType(":", beforeExpr), + dot: new TokenType("."), + question: new TokenType("?", beforeExpr), + arrow: new TokenType("=>", beforeExpr), + template: new TokenType("template"), + invalidTemplate: new TokenType("invalidTemplate"), + ellipsis: new TokenType("...", beforeExpr), + backQuote: new TokenType("`", startsExpr), + dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + eq: new TokenType("=", {beforeExpr: true, isAssign: true}), + assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), + incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), + prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), + logicalOR: binop("||", 1), + logicalAND: binop("&&", 2), + bitwiseOR: binop("|", 3), + bitwiseXOR: binop("^", 4), + bitwiseAND: binop("&", 5), + equality: binop("==/!=/===/!==", 6), + relational: binop("/<=/>=", 7), + bitShift: binop("<>/>>>", 8), + plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), + modulo: binop("%", 10), + star: binop("*", 10), + slash: binop("/", 10), + starstar: new TokenType("**", {beforeExpr: true}), + + // Keyword token types. + _break: kw("break"), + _case: kw("case", beforeExpr), + _catch: kw("catch"), + _continue: kw("continue"), + _debugger: kw("debugger"), + _default: kw("default", beforeExpr), + _do: kw("do", {isLoop: true, beforeExpr: true}), + _else: kw("else", beforeExpr), + _finally: kw("finally"), + _for: kw("for", {isLoop: true}), + _function: kw("function", startsExpr), + _if: kw("if"), + _return: kw("return", beforeExpr), + _switch: kw("switch"), + _throw: kw("throw", beforeExpr), + _try: kw("try"), + _var: kw("var"), + _const: kw("const"), + _while: kw("while", {isLoop: true}), + _with: kw("with"), + _new: kw("new", {beforeExpr: true, startsExpr: true}), + _this: kw("this", startsExpr), + _super: kw("super", startsExpr), + _class: kw("class", startsExpr), + _extends: kw("extends", beforeExpr), + _export: kw("export"), + _import: kw("import"), + _null: kw("null", startsExpr), + _true: kw("true", startsExpr), + _false: kw("false", startsExpr), + _in: kw("in", {beforeExpr: true, binop: 7}), + _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), + _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), + _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), + _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) +}; + +// Matches a whole line break (where CRLF is considered a single +// line break). Used to count lines. + +var lineBreak = /\r\n?|\n|\u2028|\u2029/; +var lineBreakG = new RegExp(lineBreak.source, "g"); + +function isNewLine(code) { + return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 +} + +var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + +var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + +var ref = Object.prototype; +var hasOwnProperty = ref.hasOwnProperty; +var toString = ref.toString; + +// Checks if an object has a property. + +function has(obj, propName) { + return hasOwnProperty.call(obj, propName) +} + +var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" +); }); + +// These are used when `options.locations` is on, for the +// `startLoc` and `endLoc` properties. + +var Position = function Position(line, col) { + this.line = line; + this.column = col; +}; + +Position.prototype.offset = function offset (n) { + return new Position(this.line, this.column + n) +}; + +var SourceLocation = function SourceLocation(p, start, end) { + this.start = start; + this.end = end; + if (p.sourceFile !== null) { this.source = p.sourceFile; } +}; + +// The `getLineInfo` function is mostly useful when the +// `locations` option is off (for performance reasons) and you +// want to find the line/column position for a given character +// offset. `input` should be the code string that the offset refers +// into. + +function getLineInfo(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreakG.lastIndex = cur; + var match = lineBreakG.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else { + return new Position(line, offset - cur) + } + } +} + +// A second optional argument can be given to further configure +// the parser process. These options are recognized: + +var defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must + // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support + // for strict mode, the set of reserved words, and support for + // new syntax features. The default is 7. + ecmaVersion: 7, + // `sourceType` indicates the mode the code should be parsed in. + // Can be either `"script"` or `"module"`. This influences global + // strict mode and parsing of `import` and `export` declarations. + sourceType: "script", + // `onInsertedSemicolon` can be a callback that will be called + // when a semicolon is automatically inserted. It will be passed + // th position of the comma as an offset, and if `locations` is + // enabled, it is given the location as a `{line, column}` object + // as second argument. + onInsertedSemicolon: null, + // `onTrailingComma` is similar to `onInsertedSemicolon`, but for + // trailing commas. + onTrailingComma: null, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When enabled, hashbang directive in the beginning of file + // is allowed and treated as a line comment. + allowHashBang: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false, + plugins: {} +}; + +// Interpret and default an options object + +function getOptions(opts) { + var options = {}; + + for (var opt in defaultOptions) + { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } + + if (options.ecmaVersion >= 2015) + { options.ecmaVersion -= 2009; } + + if (options.allowReserved == null) + { options.allowReserved = options.ecmaVersion < 5; } + + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { return tokens.push(token); }; + } + if (isArray(options.onComment)) + { options.onComment = pushComment(options, options.onComment); } + + return options +} + +function pushComment(options, array) { + return function(block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? "Block" : "Line", + value: text, + start: start, + end: end + }; + if (options.locations) + { comment.loc = new SourceLocation(this, startLoc, endLoc); } + if (options.ranges) + { comment.range = [start, end]; } + array.push(comment); + } +} + +// Registered plugins +var plugins = {}; + +function keywordRegexp(words) { + return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") +} + +var Parser = function Parser(options, input, startPos) { + this.options = options = getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); + var reserved = ""; + if (!options.allowReserved) { + for (var v = options.ecmaVersion;; v--) + { if (reserved = reservedWords[v]) { break } } + if (options.sourceType == "module") { reserved += " await"; } + } + this.reservedWords = keywordRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; + this.reservedWordsStrict = keywordRegexp(reservedStrict); + this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); + this.input = String(input); + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + + // Load plugins + this.loadPlugins(options.plugins); + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos; + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; + } else { + this.pos = this.lineStart = 0; + this.curLine = 1; + } + + // Properties of the current token: + // Its type + this.type = types.eof; + // For tokens that include more information than their type, the value + this.value = null; + // Its start and end offset + this.start = this.end = this.pos; + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition(); + + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext(); + this.exprAllowed = true; + + // Figure out if it's a module code. + this.inModule = options.sourceType === "module"; + this.strict = this.inModule || this.strictDirective(this.pos); + + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1; + + // Flags to track whether we are in a function, a generator, an async function. + this.inFunction = this.inGenerator = this.inAsync = false; + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = 0; + // Labels in scope. + this.labels = []; + + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") + { this.skipLineComment(2); } + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = []; + this.enterFunctionScope(); +}; + +// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them +Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; +Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) }; + +Parser.prototype.extend = function extend (name, f) { + this[name] = f(this[name]); +}; + +Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { + var this$1 = this; + + for (var name in pluginConfigs) { + var plugin = plugins[name]; + if (!plugin) { throw new Error("Plugin '" + name + "' not found") } + plugin(this$1, pluginConfigs[name]); + } +}; + +Parser.prototype.parse = function parse () { + var node = this.options.program || this.startNode(); + this.nextToken(); + return this.parseTopLevel(node) +}; + +var pp = Parser.prototype; + +// ## Parser utilities + +var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; +pp.strictDirective = function(start) { + var this$1 = this; + + for (;;) { + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this$1.input)[0].length; + var match = literal.exec(this$1.input.slice(start)); + if (!match) { return false } + if ((match[1] || match[2]) == "use strict") { return true } + start += match[0].length; + } +}; + +// Predicate that tests whether the next token is of the given +// type, and if yes, consumes it as a side effect. + +pp.eat = function(type) { + if (this.type === type) { + this.next(); + return true + } else { + return false + } +}; + +// Tests whether parsed token is a contextual keyword. + +pp.isContextual = function(name) { + return this.type === types.name && this.value === name && !this.containsEsc +}; + +// Consumes contextual keyword if possible. + +pp.eatContextual = function(name) { + if (!this.isContextual(name)) { return false } + this.next(); + return true +}; + +// Asserts that following token is given contextual keyword. + +pp.expectContextual = function(name) { + if (!this.eatContextual(name)) { this.unexpected(); } +}; + +// Test whether a semicolon can be inserted at the current position. + +pp.canInsertSemicolon = function() { + return this.type === types.eof || + this.type === types.braceR || + lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) +}; + +pp.insertSemicolon = function() { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) + { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } + return true + } +}; + +// Consume a semicolon, or, failing that, see if we are allowed to +// pretend that there is a semicolon at this position. + +pp.semicolon = function() { + if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } +}; + +pp.afterTrailingComma = function(tokType, notNext) { + if (this.type == tokType) { + if (this.options.onTrailingComma) + { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } + if (!notNext) + { this.next(); } + return true + } +}; + +// Expect a token of a given type. If found, consume it, otherwise, +// raise an unexpected token error. + +pp.expect = function(type) { + this.eat(type) || this.unexpected(); +}; + +// Raise an unexpected token error. + +pp.unexpected = function(pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token"); +}; + +function DestructuringErrors() { + this.shorthandAssign = + this.trailingComma = + this.parenthesizedAssign = + this.parenthesizedBind = + this.doubleProto = + -1; +} + +pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) { return } + if (refDestructuringErrors.trailingComma > -1) + { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; + if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } +}; + +pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { + if (!refDestructuringErrors) { return false } + var shorthandAssign = refDestructuringErrors.shorthandAssign; + var doubleProto = refDestructuringErrors.doubleProto; + if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } + if (shorthandAssign >= 0) + { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } + if (doubleProto >= 0) + { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } +}; + +pp.checkYieldAwaitInDefaultParams = function() { + if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) + { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } + if (this.awaitPos) + { this.raise(this.awaitPos, "Await expression cannot be a default value"); } +}; + +pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + { return this.isSimpleAssignTarget(expr.expression) } + return expr.type === "Identifier" || expr.type === "MemberExpression" +}; + +var pp$1 = Parser.prototype; + +// ### Statement parsing + +// Parse a program. Initializes the parser, reads any number of +// statements, and wraps them in a Program node. Optionally takes a +// `program` argument. If present, the statements will be appended +// to its body instead of creating a new node. + +pp$1.parseTopLevel = function(node) { + var this$1 = this; + + var exports = {}; + if (!node.body) { node.body = []; } + while (this.type !== types.eof) { + var stmt = this$1.parseStatement(true, true, exports); + node.body.push(stmt); + } + this.adaptDirectivePrologue(node.body); + this.next(); + if (this.options.ecmaVersion >= 6) { + node.sourceType = this.options.sourceType; + } + return this.finishNode(node, "Program") +}; + +var loopLabel = {kind: "loop"}; +var switchLabel = {kind: "switch"}; + +pp$1.isLet = function() { + if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + if (nextCh === 91 || nextCh == 123) { return true } // '{' and '[' + if (isIdentifierStart(nextCh, true)) { + var pos = next + 1; + while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } + var ident = this.input.slice(next, pos); + if (!keywordRelationalOperator.test(ident)) { return true } + } + return false +}; + +// check 'async [no LineTerminator here] function' +// - 'async /*foo*/ function' is OK. +// - 'async /*\n*/ function' is invalid. +pp$1.isAsyncFunction = function() { + if (this.options.ecmaVersion < 8 || !this.isContextual("async")) + { return false } + + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length; + return !lineBreak.test(this.input.slice(this.pos, next)) && + this.input.slice(next, next + 8) === "function" && + (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) +}; + +// Parse a single statement. +// +// If expecting a statement and finding a slash operator, parse a +// regular expression literal. This is to handle cases like +// `if (foo) /blah/.exec(foo)`, where looking at the previous token +// does not help. + +pp$1.parseStatement = function(declaration, topLevel, exports) { + var starttype = this.type, node = this.startNode(), kind; + + if (this.isLet()) { + starttype = types._var; + kind = "let"; + } + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) + case types._debugger: return this.parseDebuggerStatement(node) + case types._do: return this.parseDoStatement(node) + case types._for: return this.parseForStatement(node) + case types._function: + if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); } + return this.parseFunctionStatement(node, false) + case types._class: + if (!declaration) { this.unexpected(); } + return this.parseClass(node, true) + case types._if: return this.parseIfStatement(node) + case types._return: return this.parseReturnStatement(node) + case types._switch: return this.parseSwitchStatement(node) + case types._throw: return this.parseThrowStatement(node) + case types._try: return this.parseTryStatement(node) + case types._const: case types._var: + kind = kind || this.value; + if (!declaration && kind != "var") { this.unexpected(); } + return this.parseVarStatement(node, kind) + case types._while: return this.parseWhileStatement(node) + case types._with: return this.parseWithStatement(node) + case types.braceL: return this.parseBlock() + case types.semi: return this.parseEmptyStatement(node) + case types._export: + case types._import: + if (!this.options.allowImportExportEverywhere) { + if (!topLevel) + { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } + if (!this.inModule) + { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } + } + return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + if (this.isAsyncFunction()) { + if (!declaration) { this.unexpected(); } + this.next(); + return this.parseFunctionStatement(node, true) + } + + var maybeName = this.value, expr = this.parseExpression(); + if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) + { return this.parseLabeledStatement(node, maybeName, expr) } + else { return this.parseExpressionStatement(node, expr) } + } +}; + +pp$1.parseBreakContinueStatement = function(node, keyword) { + var this$1 = this; + + var isBreak = keyword == "break"; + this.next(); + if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } + else if (this.type !== types.name) { this.unexpected(); } + else { + node.label = this.parseIdent(); + this.semicolon(); + } + + // Verify that there is an actual destination to break or + // continue to. + var i = 0; + for (; i < this.labels.length; ++i) { + var lab = this$1.labels[i]; + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } + if (node.label && isBreak) { break } + } + } + if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") +}; + +pp$1.parseDebuggerStatement = function(node) { + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") +}; + +pp$1.parseDoStatement = function(node) { + this.next(); + this.labels.push(loopLabel); + node.body = this.parseStatement(false); + this.labels.pop(); + this.expect(types._while); + node.test = this.parseParenExpression(); + if (this.options.ecmaVersion >= 6) + { this.eat(types.semi); } + else + { this.semicolon(); } + return this.finishNode(node, "DoWhileStatement") +}; + +// Disambiguating between a `for` and a `for`/`in` or `for`/`of` +// loop is non-trivial. Basically, we have to parse the init `var` +// statement or expression, disallowing the `in` operator (see +// the second parameter to `parseExpression`), and then check +// whether the next token is `in` or `of`. When there is no init +// part (semicolon immediately after the opening parenthesis), it +// is a regular `for` loop. + +pp$1.parseForStatement = function(node) { + this.next(); + var awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1; + this.labels.push(loopLabel); + this.enterLexicalScope(); + this.expect(types.parenL); + if (this.type === types.semi) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, null) + } + var isLet = this.isLet(); + if (this.type === types._var || this.type === types._const || isLet) { + var init$1 = this.startNode(), kind = isLet ? "let" : this.value; + this.next(); + this.parseVar(init$1, true, kind); + this.finishNode(init$1, "VariableDeclaration"); + if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && + !(kind !== "var" && init$1.declarations[0].init)) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + } else { node.await = awaitAt > -1; } + } + return this.parseForIn(node, init$1) + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init$1) + } + var refDestructuringErrors = new DestructuringErrors; + var init = this.parseExpression(true, refDestructuringErrors); + if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + } else { node.await = awaitAt > -1; } + } + this.toAssignable(init, false, refDestructuringErrors); + this.checkLVal(init); + return this.parseForIn(node, init) + } else { + this.checkExpressionErrors(refDestructuringErrors, true); + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init) +}; + +pp$1.parseFunctionStatement = function(node, isAsync) { + this.next(); + return this.parseFunction(node, true, false, isAsync) +}; + +pp$1.parseIfStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + // allow function declarations in branches, but only in non-strict mode + node.consequent = this.parseStatement(!this.strict && this.type == types._function); + node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type == types._function) : null; + return this.finishNode(node, "IfStatement") +}; + +pp$1.parseReturnStatement = function(node) { + if (!this.inFunction && !this.options.allowReturnOutsideFunction) + { this.raise(this.start, "'return' outside of function"); } + this.next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") +}; + +pp$1.parseSwitchStatement = function(node) { + var this$1 = this; + + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.expect(types.braceL); + this.labels.push(switchLabel); + this.enterLexicalScope(); + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + var cur; + for (var sawDefault = false; this.type != types.braceR;) { + if (this$1.type === types._case || this$1.type === types._default) { + var isCase = this$1.type === types._case; + if (cur) { this$1.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this$1.startNode()); + cur.consequent = []; + this$1.next(); + if (isCase) { + cur.test = this$1.parseExpression(); + } else { + if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } + sawDefault = true; + cur.test = null; + } + this$1.expect(types.colon); + } else { + if (!cur) { this$1.unexpected(); } + cur.consequent.push(this$1.parseStatement(true)); + } + } + this.exitLexicalScope(); + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.next(); // Closing brace + this.labels.pop(); + return this.finishNode(node, "SwitchStatement") +}; + +pp$1.parseThrowStatement = function(node) { + this.next(); + if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) + { this.raise(this.lastTokEnd, "Illegal newline after throw"); } + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement") +}; + +// Reused empty array added for node fields that are always empty. + +var empty = []; + +pp$1.parseTryStatement = function(node) { + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.type === types._catch) { + var clause = this.startNode(); + this.next(); + this.expect(types.parenL); + clause.param = this.parseBindingAtom(); + this.enterLexicalScope(); + this.checkLVal(clause.param, "let"); + this.expect(types.parenR); + clause.body = this.parseBlock(false); + this.exitLexicalScope(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) + { this.raise(node.start, "Missing catch or finally clause"); } + return this.finishNode(node, "TryStatement") +}; + +pp$1.parseVarStatement = function(node, kind) { + this.next(); + this.parseVar(node, false, kind); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration") +}; + +pp$1.parseWhileStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + this.labels.push(loopLabel); + node.body = this.parseStatement(false); + this.labels.pop(); + return this.finishNode(node, "WhileStatement") +}; + +pp$1.parseWithStatement = function(node) { + if (this.strict) { this.raise(this.start, "'with' in strict mode"); } + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement(false); + return this.finishNode(node, "WithStatement") +}; + +pp$1.parseEmptyStatement = function(node) { + this.next(); + return this.finishNode(node, "EmptyStatement") +}; + +pp$1.parseLabeledStatement = function(node, maybeName, expr) { + var this$1 = this; + + for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) + { + var label = list[i$1]; + + if (label.name === maybeName) + { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); + } } + var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; + for (var i = this.labels.length - 1; i >= 0; i--) { + var label$1 = this$1.labels[i]; + if (label$1.statementStart == node.start) { + // Update information about previous labels on this node + label$1.statementStart = this$1.start; + label$1.kind = kind; + } else { break } + } + this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); + node.body = this.parseStatement(true); + if (node.body.type == "ClassDeclaration" || + node.body.type == "VariableDeclaration" && node.body.kind != "var" || + node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) + { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } + this.labels.pop(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") +}; + +pp$1.parseExpressionStatement = function(node, expr) { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") +}; + +// Parse a semicolon-enclosed block of statements, handling `"use +// strict"` declarations when `allowStrict` is true (used for +// function bodies). + +pp$1.parseBlock = function(createNewLexicalScope) { + var this$1 = this; + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; + + var node = this.startNode(); + node.body = []; + this.expect(types.braceL); + if (createNewLexicalScope) { + this.enterLexicalScope(); + } + while (!this.eat(types.braceR)) { + var stmt = this$1.parseStatement(true); + node.body.push(stmt); + } + if (createNewLexicalScope) { + this.exitLexicalScope(); + } + return this.finishNode(node, "BlockStatement") +}; + +// Parse a regular `for` loop. The disambiguation code in +// `parseStatement` will already have parsed the init statement or +// expression. + +pp$1.parseFor = function(node, init) { + node.init = init; + this.expect(types.semi); + node.test = this.type === types.semi ? null : this.parseExpression(); + this.expect(types.semi); + node.update = this.type === types.parenR ? null : this.parseExpression(); + this.expect(types.parenR); + this.exitLexicalScope(); + node.body = this.parseStatement(false); + this.labels.pop(); + return this.finishNode(node, "ForStatement") +}; + +// Parse a `for`/`in` and `for`/`of` loop, which are almost +// same from parser's perspective. + +pp$1.parseForIn = function(node, init) { + var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; + this.next(); + if (type == "ForInStatement") { + if (init.type === "AssignmentPattern" || + (init.type === "VariableDeclaration" && init.declarations[0].init != null && + (this.strict || init.declarations[0].id.type !== "Identifier"))) + { this.raise(init.start, "Invalid assignment in for-in loop head"); } + } + node.left = init; + node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign(); + this.expect(types.parenR); + this.exitLexicalScope(); + node.body = this.parseStatement(false); + this.labels.pop(); + return this.finishNode(node, type) +}; + +// Parse a list of variable declarations. + +pp$1.parseVar = function(node, isFor, kind) { + var this$1 = this; + + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = this$1.startNode(); + this$1.parseVarId(decl, kind); + if (this$1.eat(types.eq)) { + decl.init = this$1.parseMaybeAssign(isFor); + } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { + this$1.unexpected(); + } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { + this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); + } else { + decl.init = null; + } + node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); + if (!this$1.eat(types.comma)) { break } + } + return node +}; + +pp$1.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(kind); + this.checkLVal(decl.id, kind, false); +}; + +// Parse a function declaration or literal (depending on the +// `isStatement` parameter). + +pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { + this.initFunction(node); + if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) + { node.generator = this.eat(types.star); } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + if (isStatement) { + node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent(); + if (node.id) { + this.checkLVal(node.id, "var"); + } + } + + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; + this.inGenerator = node.generator; + this.inAsync = node.async; + this.yieldPos = 0; + this.awaitPos = 0; + this.inFunction = true; + this.enterFunctionScope(); + + if (!isStatement) + { node.id = this.type == types.name ? this.parseIdent() : null; } + + this.parseFunctionParams(node); + this.parseFunctionBody(node, allowExpressionBody); + + this.inGenerator = oldInGen; + this.inAsync = oldInAsync; + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.inFunction = oldInFunc; + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") +}; + +pp$1.parseFunctionParams = function(node) { + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); +}; + +// Parse a class declaration or literal (depending on the +// `isStatement` parameter). + +pp$1.parseClass = function(node, isStatement) { + var this$1 = this; + + this.next(); + + this.parseClassId(node, isStatement); + this.parseClassSuper(node); + var classBody = this.startNode(); + var hadConstructor = false; + classBody.body = []; + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + var member = this$1.parseClassMember(classBody); + if (member && member.type === "MethodDefinition" && member.kind === "constructor") { + if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); } + hadConstructor = true; + } + } + node.body = this.finishNode(classBody, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") +}; + +pp$1.parseClassMember = function(classBody) { + var this$1 = this; + + if (this.eat(types.semi)) { return null } + + var method = this.startNode(); + var tryContextual = function (k, noLineBreak) { + if ( noLineBreak === void 0 ) noLineBreak = false; + + var start = this$1.start, startLoc = this$1.startLoc; + if (!this$1.eatContextual(k)) { return false } + if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } + if (method.key) { this$1.unexpected(); } + method.computed = false; + method.key = this$1.startNodeAt(start, startLoc); + method.key.name = k; + this$1.finishNode(method.key, "Identifier"); + return false + }; + + method.kind = "method"; + method.static = tryContextual("static"); + var isGenerator = this.eat(types.star); + var isAsync = false; + if (!isGenerator) { + if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + } else if (tryContextual("get")) { + method.kind = "get"; + } else if (tryContextual("set")) { + method.kind = "set"; + } + } + if (!method.key) { this.parsePropertyName(method); } + var key = method.key; + if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || + key.type === "Literal" && key.value === "constructor")) { + if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } + if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } + if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } + method.kind = "constructor"; + } else if (method.static && key.type === "Identifier" && key.name === "prototype") { + this.raise(key.start, "Classes may not have a static property named prototype"); + } + this.parseClassMethod(classBody, method, isGenerator, isAsync); + if (method.kind === "get" && method.value.params.length !== 0) + { this.raiseRecoverable(method.value.start, "getter should have no params"); } + if (method.kind === "set" && method.value.params.length !== 1) + { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } + if (method.kind === "set" && method.value.params[0].type === "RestElement") + { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } + return method +}; + +pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { + method.value = this.parseMethod(isGenerator, isAsync); + classBody.body.push(this.finishNode(method, "MethodDefinition")); +}; + +pp$1.parseClassId = function(node, isStatement) { + node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; +}; + +pp$1.parseClassSuper = function(node) { + node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; +}; + +// Parses module export declaration. + +pp$1.parseExport = function(node, exports) { + var this$1 = this; + + this.next(); + // export * from '...' + if (this.eat(types.star)) { + this.expectContextual("from"); + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(types._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === types._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync); + } else if (this.type === types._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(true); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } + node.specifiers = []; + node.source = null; + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + } else { + // check for keywords used as local names + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + var spec = list[i]; + + this$1.checkUnreserved(spec.local); + } + + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") +}; + +pp$1.checkExport = function(exports, name, pos) { + if (!exports) { return } + if (has(exports, name)) + { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } + exports[name] = true; +}; + +pp$1.checkPatternExport = function(exports, pat) { + var this$1 = this; + + var type = pat.type; + if (type == "Identifier") + { this.checkExport(exports, pat.name, pat.start); } + else if (type == "ObjectPattern") + { for (var i = 0, list = pat.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this$1.checkPatternExport(exports, prop); + } } + else if (type == "ArrayPattern") + { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { + var elt = list$1[i$1]; + + if (elt) { this$1.checkPatternExport(exports, elt); } + } } + else if (type == "Property") + { this.checkPatternExport(exports, pat.value); } + else if (type == "AssignmentPattern") + { this.checkPatternExport(exports, pat.left); } + else if (type == "RestElement") + { this.checkPatternExport(exports, pat.argument); } + else if (type == "ParenthesizedExpression") + { this.checkPatternExport(exports, pat.expression); } +}; + +pp$1.checkVariableExport = function(exports, decls) { + var this$1 = this; + + if (!exports) { return } + for (var i = 0, list = decls; i < list.length; i += 1) + { + var decl = list[i]; + + this$1.checkPatternExport(exports, decl.id); + } +}; + +pp$1.shouldParseExportStatement = function() { + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() +}; + +// Parses a comma-separated list of module exports. + +pp$1.parseExportSpecifiers = function(exports) { + var this$1 = this; + + var nodes = [], first = true; + // export { x, y as z } [from '...'] + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var node = this$1.startNode(); + node.local = this$1.parseIdent(true); + node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; + this$1.checkExport(exports, node.exported.name, node.exported.start); + nodes.push(this$1.finishNode(node, "ExportSpecifier")); + } + return nodes +}; + +// Parses import declaration. + +pp$1.parseImport = function(node) { + this.next(); + // import '...' + if (this.type === types.string) { + node.specifiers = empty; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") +}; + +// Parses a comma-separated list of module imports. + +pp$1.parseImportSpecifiers = function() { + var this$1 = this; + + var nodes = [], first = true; + if (this.type === types.name) { + // import defaultObj, { x, y as z } from '...' + var node = this.startNode(); + node.local = this.parseIdent(); + this.checkLVal(node.local, "let"); + nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); + if (!this.eat(types.comma)) { return nodes } + } + if (this.type === types.star) { + var node$1 = this.startNode(); + this.next(); + this.expectContextual("as"); + node$1.local = this.parseIdent(); + this.checkLVal(node$1.local, "let"); + nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); + return nodes + } + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var node$2 = this$1.startNode(); + node$2.imported = this$1.parseIdent(true); + if (this$1.eatContextual("as")) { + node$2.local = this$1.parseIdent(); + } else { + this$1.checkUnreserved(node$2.imported); + node$2.local = node$2.imported; + } + this$1.checkLVal(node$2.local, "let"); + nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); + } + return nodes +}; + +// Set `ExpressionStatement#directive` property for directive prologues. +pp$1.adaptDirectivePrologue = function(statements) { + for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { + statements[i].directive = statements[i].expression.raw.slice(1, -1); + } +}; +pp$1.isDirectiveCandidate = function(statement) { + return ( + statement.type === "ExpressionStatement" && + statement.expression.type === "Literal" && + typeof statement.expression.value === "string" && + // Reject parenthesized strings. + (this.input[statement.start] === "\"" || this.input[statement.start] === "'") + ) +}; + +var pp$2 = Parser.prototype; + +// Convert existing expression atom to assignable pattern +// if possible. + +pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { + var this$1 = this; + + if (this.options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + if (this.inAsync && node.name === "await") + { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } + break + + case "ObjectPattern": + case "ArrayPattern": + case "RestElement": + break + + case "ObjectExpression": + node.type = "ObjectPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + for (var i = 0, list = node.properties; i < list.length; i += 1) { + var prop = list[i]; + + this$1.toAssignable(prop, isBinding); + // Early error: + // AssignmentRestProperty[Yield, Await] : + // `...` DestructuringAssignmentTarget[Yield, Await] + // + // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. + if ( + prop.type === "RestElement" && + (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") + ) { + this$1.raise(prop.argument.start, "Unexpected token"); + } + } + break + + case "Property": + // AssignmentProperty has type == "Property" + if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } + this.toAssignable(node.value, isBinding); + break + + case "ArrayExpression": + node.type = "ArrayPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + this.toAssignableList(node.elements, isBinding); + break + + case "SpreadElement": + node.type = "RestElement"; + this.toAssignable(node.argument, isBinding); + if (node.argument.type === "AssignmentPattern") + { this.raise(node.argument.start, "Rest elements cannot have a default value"); } + break + + case "AssignmentExpression": + if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } + node.type = "AssignmentPattern"; + delete node.operator; + this.toAssignable(node.left, isBinding); + // falls through to AssignmentPattern + + case "AssignmentPattern": + break + + case "ParenthesizedExpression": + this.toAssignable(node.expression, isBinding); + break + + case "MemberExpression": + if (!isBinding) { break } + + default: + this.raise(node.start, "Assigning to rvalue"); + } + } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + return node +}; + +// Convert list of expression atoms to binding list. + +pp$2.toAssignableList = function(exprList, isBinding) { + var this$1 = this; + + var end = exprList.length; + for (var i = 0; i < end; i++) { + var elt = exprList[i]; + if (elt) { this$1.toAssignable(elt, isBinding); } + } + if (end) { + var last = exprList[end - 1]; + if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") + { this.unexpected(last.argument.start); } + } + return exprList +}; + +// Parses spread element. + +pp$2.parseSpread = function(refDestructuringErrors) { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeAssign(false, refDestructuringErrors); + return this.finishNode(node, "SpreadElement") +}; + +pp$2.parseRestBinding = function() { + var node = this.startNode(); + this.next(); + + // RestElement inside of a function parameter must be an identifier + if (this.options.ecmaVersion === 6 && this.type !== types.name) + { this.unexpected(); } + + node.argument = this.parseBindingAtom(); + + return this.finishNode(node, "RestElement") +}; + +// Parses lvalue (assignable) atom. + +pp$2.parseBindingAtom = function() { + if (this.options.ecmaVersion >= 6) { + switch (this.type) { + case types.bracketL: + var node = this.startNode(); + this.next(); + node.elements = this.parseBindingList(types.bracketR, true, true); + return this.finishNode(node, "ArrayPattern") + + case types.braceL: + return this.parseObj(true) + } + } + return this.parseIdent() +}; + +pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { + var this$1 = this; + + var elts = [], first = true; + while (!this.eat(close)) { + if (first) { first = false; } + else { this$1.expect(types.comma); } + if (allowEmpty && this$1.type === types.comma) { + elts.push(null); + } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { + break + } else if (this$1.type === types.ellipsis) { + var rest = this$1.parseRestBinding(); + this$1.parseBindingListItem(rest); + elts.push(rest); + if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } + this$1.expect(close); + break + } else { + var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); + this$1.parseBindingListItem(elem); + elts.push(elem); + } + } + return elts +}; + +pp$2.parseBindingListItem = function(param) { + return param +}; + +// Parses assignment pattern around given atom if possible. + +pp$2.parseMaybeDefault = function(startPos, startLoc, left) { + left = left || this.parseBindingAtom(); + if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.right = this.parseMaybeAssign(); + return this.finishNode(node, "AssignmentPattern") +}; + +// Verify that a node is an lval — something that can be assigned +// to. +// bindingType can be either: +// 'var' indicating that the lval creates a 'var' binding +// 'let' indicating that the lval creates a lexical ('let' or 'const') binding +// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references + +pp$2.checkLVal = function(expr, bindingType, checkClashes) { + var this$1 = this; + + switch (expr.type) { + case "Identifier": + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) + { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } + if (checkClashes) { + if (has(checkClashes, expr.name)) + { this.raiseRecoverable(expr.start, "Argument name clash"); } + checkClashes[expr.name] = true; + } + if (bindingType && bindingType !== "none") { + if ( + bindingType === "var" && !this.canDeclareVarName(expr.name) || + bindingType !== "var" && !this.canDeclareLexicalName(expr.name) + ) { + this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")); + } + if (bindingType === "var") { + this.declareVarName(expr.name); + } else { + this.declareLexicalName(expr.name); + } + } + break + + case "MemberExpression": + if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } + break + + case "ObjectPattern": + for (var i = 0, list = expr.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this$1.checkLVal(prop, bindingType, checkClashes); + } + break + + case "Property": + // AssignmentProperty has type == "Property" + this.checkLVal(expr.value, bindingType, checkClashes); + break + + case "ArrayPattern": + for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { + var elem = list$1[i$1]; + + if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } + } + break + + case "AssignmentPattern": + this.checkLVal(expr.left, bindingType, checkClashes); + break + + case "RestElement": + this.checkLVal(expr.argument, bindingType, checkClashes); + break + + case "ParenthesizedExpression": + this.checkLVal(expr.expression, bindingType, checkClashes); + break + + default: + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); + } +}; + +// A recursive descent parser operates by defining functions for all +// syntactic elements, and recursively calling those, each function +// advancing the input stream and returning an AST node. Precedence +// of constructs (for example, the fact that `!x[1]` means `!(x[1])` +// instead of `(!x)[1]` is handled by the fact that the parser +// function that parses unary prefix operators is called first, and +// in turn calls the function that parses `[]` subscripts — that +// way, it'll receive the node for `x[1]` already parsed, and wraps +// *that* in the unary operator node. +// +// Acorn uses an [operator precedence parser][opp] to handle binary +// operator precedence, because it is much more compact than using +// the technique outlined above, which uses different, nesting +// functions to specify precedence, for all of the ten binary +// precedence levels that JavaScript defines. +// +// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser + +var pp$3 = Parser.prototype; + +// Check if property name clashes with already added. +// Object/class getters and setters are not allowed to clash — +// either with each other or with an init property — and in +// strict mode, init properties are also not allowed to be repeated. + +pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { + if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") + { return } + if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) + { return } + var key = prop.key; + var name; + switch (key.type) { + case "Identifier": name = key.name; break + case "Literal": name = String(key.value); break + default: return + } + var kind = prop.kind; + if (this.options.ecmaVersion >= 6) { + if (name === "__proto__" && kind === "init") { + if (propHash.proto) { + if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; } + // Backwards-compat kludge. Can be removed in version 6.0 + else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } + } + propHash.proto = true; + } + return + } + name = "$" + name; + var other = propHash[name]; + if (other) { + var redefinition; + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set; + } else { + redefinition = other.init || other[kind]; + } + if (redefinition) + { this.raiseRecoverable(key.start, "Redefinition of property"); } + } else { + other = propHash[name] = { + init: false, + get: false, + set: false + }; + } + other[kind] = true; +}; + +// ### Expression parsing + +// These nest, from the most general expression type at the top to +// 'atomic', nondivisible expression types at the bottom. Most of +// the functions will simply let the function(s) below them parse, +// and, *if* the syntactic construct they handle is present, wrap +// the AST node that the inner parser gave them in another node. + +// Parse a full expression. The optional arguments are used to +// forbid the `in` operator (in for loops initalization expressions) +// and provide reference for storing '=' operator inside shorthand +// property assignment in contexts where both object expression +// and object pattern might appear (so it's possible to raise +// delayed syntax error at correct position). + +pp$3.parseExpression = function(noIn, refDestructuringErrors) { + var this$1 = this; + + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); + if (this.type === types.comma) { + var node = this.startNodeAt(startPos, startLoc); + node.expressions = [expr]; + while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } + return this.finishNode(node, "SequenceExpression") + } + return expr +}; + +// Parse an assignment expression. This includes applications of +// operators like `+=`. + +pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { + if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() } + + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign; + oldTrailingComma = refDestructuringErrors.trailingComma; + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; + } else { + refDestructuringErrors = new DestructuringErrors; + ownDestructuringErrors = true; + } + + var startPos = this.start, startLoc = this.startLoc; + if (this.type == types.parenL || this.type == types.name) + { this.potentialArrowAt = this.start; } + var left = this.parseMaybeConditional(noIn, refDestructuringErrors); + if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } + if (this.type.isAssign) { + var node = this.startNodeAt(startPos, startLoc); + node.operator = this.value; + node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; + if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } + refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly + this.checkLVal(left); + this.next(); + node.right = this.parseMaybeAssign(noIn); + return this.finishNode(node, "AssignmentExpression") + } else { + if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } + } + if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } + if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } + return left +}; + +// Parse a ternary conditional (`?:`) operator. + +pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprOps(noIn, refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + if (this.eat(types.question)) { + var node = this.startNodeAt(startPos, startLoc); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + this.expect(types.colon); + node.alternate = this.parseMaybeAssign(noIn); + return this.finishNode(node, "ConditionalExpression") + } + return expr +}; + +// Start the precedence parser. + +pp$3.parseExprOps = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeUnary(refDestructuringErrors, false); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) +}; + +// Parse binary operators with the operator precedence parsing +// algorithm. `left` is the left-hand side of the operator. +// `minPrec` provides context that allows the function to stop and +// defer further parser to one of its callers when it encounters an +// operator that has a lower precedence than the set it is parsing. + +pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { + var prec = this.type.binop; + if (prec != null && (!noIn || this.type !== types._in)) { + if (prec > minPrec) { + var logical = this.type === types.logicalOR || this.type === types.logicalAND; + var op = this.value; + this.next(); + var startPos = this.start, startLoc = this.startLoc; + var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); + var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) + } + } + return left +}; + +pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.operator = op; + node.right = right; + return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") +}; + +// Parse unary operators, both prefix and postfix. + +pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { + var this$1 = this; + + var startPos = this.start, startLoc = this.startLoc, expr; + if (this.inAsync && this.isContextual("await")) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.type.prefix) { + var node = this.startNode(), update = this.type === types.incDec; + node.operator = this.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(null, true); + this.checkExpressionErrors(refDestructuringErrors, true); + if (update) { this.checkLVal(node.argument); } + else if (this.strict && node.operator === "delete" && + node.argument.type === "Identifier") + { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } + else { sawUnary = true; } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else { + expr = this.parseExprSubscripts(refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + while (this.type.postfix && !this.canInsertSemicolon()) { + var node$1 = this$1.startNodeAt(startPos, startLoc); + node$1.operator = this$1.value; + node$1.prefix = false; + node$1.argument = expr; + this$1.checkLVal(expr); + this$1.next(); + expr = this$1.finishNode(node$1, "UpdateExpression"); + } + } + + if (!sawUnary && this.eat(types.starstar)) + { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } + else + { return expr } +}; + +// Parse call, dot, and `[]`-subscript expressions. + +pp$3.parseExprSubscripts = function(refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprAtom(refDestructuringErrors); + var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; + if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } + var result = this.parseSubscripts(expr, startPos, startLoc); + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } + if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } + } + return result +}; + +pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { + var this$1 = this; + + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd == base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async"; + for (var computed = (void 0);;) { + if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { + var node = this$1.startNodeAt(startPos, startLoc); + node.object = base; + node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); + node.computed = !!computed; + if (computed) { this$1.expect(types.bracketR); } + base = this$1.finishNode(node, "MemberExpression"); + } else if (!noCalls && this$1.eat(types.parenL)) { + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; + this$1.yieldPos = 0; + this$1.awaitPos = 0; + var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); + if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { + this$1.checkPatternErrors(refDestructuringErrors, false); + this$1.checkYieldAwaitInDefaultParams(); + this$1.yieldPos = oldYieldPos; + this$1.awaitPos = oldAwaitPos; + return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) + } + this$1.checkExpressionErrors(refDestructuringErrors, true); + this$1.yieldPos = oldYieldPos || this$1.yieldPos; + this$1.awaitPos = oldAwaitPos || this$1.awaitPos; + var node$1 = this$1.startNodeAt(startPos, startLoc); + node$1.callee = base; + node$1.arguments = exprList; + base = this$1.finishNode(node$1, "CallExpression"); + } else if (this$1.type === types.backQuote) { + var node$2 = this$1.startNodeAt(startPos, startLoc); + node$2.tag = base; + node$2.quasi = this$1.parseTemplate({isTagged: true}); + base = this$1.finishNode(node$2, "TaggedTemplateExpression"); + } else { + return base + } + } +}; + +// Parse an atomic expression — either a single token that is an +// expression, an expression started by a keyword like `function` or +// `new`, or an expression wrapped in punctuation like `()`, `[]`, +// or `{}`. + +pp$3.parseExprAtom = function(refDestructuringErrors) { + var node, canBeArrow = this.potentialArrowAt == this.start; + switch (this.type) { + case types._super: + if (!this.inFunction) + { this.raise(this.start, "'super' outside of function or class"); } + node = this.startNode(); + this.next(); + // The `super` keyword can appear at below: + // SuperProperty: + // super [ Expression ] + // super . IdentifierName + // SuperCall: + // super Arguments + if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) + { this.unexpected(); } + return this.finishNode(node, "Super") + + case types._this: + node = this.startNode(); + this.next(); + return this.finishNode(node, "ThisExpression") + + case types.name: + var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; + var id = this.parseIdent(this.type !== types.name); + if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) + { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) } + if (canBeArrow && !this.canInsertSemicolon()) { + if (this.eat(types.arrow)) + { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } + if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { + id = this.parseIdent(); + if (this.canInsertSemicolon() || !this.eat(types.arrow)) + { this.unexpected(); } + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) + } + } + return id + + case types.regexp: + var value = this.value; + node = this.parseLiteral(value.value); + node.regex = {pattern: value.pattern, flags: value.flags}; + return node + + case types.num: case types.string: + return this.parseLiteral(this.value) + + case types._null: case types._true: case types._false: + node = this.startNode(); + node.value = this.type === types._null ? null : this.type === types._true; + node.raw = this.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case types.parenL: + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + { refDestructuringErrors.parenthesizedAssign = start; } + if (refDestructuringErrors.parenthesizedBind < 0) + { refDestructuringErrors.parenthesizedBind = start; } + } + return expr + + case types.bracketL: + node = this.startNode(); + this.next(); + node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); + return this.finishNode(node, "ArrayExpression") + + case types.braceL: + return this.parseObj(false, refDestructuringErrors) + + case types._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, false) + + case types._class: + return this.parseClass(this.startNode(), false) + + case types._new: + return this.parseNew() + + case types.backQuote: + return this.parseTemplate() + + default: + this.unexpected(); + } +}; + +pp$3.parseLiteral = function(value) { + var node = this.startNode(); + node.value = value; + node.raw = this.input.slice(this.start, this.end); + this.next(); + return this.finishNode(node, "Literal") +}; + +pp$3.parseParenExpression = function() { + this.expect(types.parenL); + var val = this.parseExpression(); + this.expect(types.parenR); + return val +}; + +pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { + var this$1 = this; + + var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; + if (this.options.ecmaVersion >= 6) { + this.next(); + + var innerStartPos = this.start, innerStartLoc = this.startLoc; + var exprList = [], first = true, lastIsComma = false; + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; + this.yieldPos = 0; + this.awaitPos = 0; + while (this.type !== types.parenR) { + first ? first = false : this$1.expect(types.comma); + if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { + lastIsComma = true; + break + } else if (this$1.type === types.ellipsis) { + spreadStart = this$1.start; + exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); + if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } + break + } else { + exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); + } + } + var innerEndPos = this.start, innerEndLoc = this.startLoc; + this.expect(types.parenR); + + if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return this.parseParenArrowList(startPos, startLoc, exprList) + } + + if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } + if (spreadStart) { this.unexpected(spreadStart); } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc); + val.expressions = exprList; + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); + } else { + val = exprList[0]; + } + } else { + val = this.parseParenExpression(); + } + + if (this.options.preserveParens) { + var par = this.startNodeAt(startPos, startLoc); + par.expression = val; + return this.finishNode(par, "ParenthesizedExpression") + } else { + return val + } +}; + +pp$3.parseParenItem = function(item) { + return item +}; + +pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) +}; + +// New's precedence is slightly tricky. It must allow its argument to +// be a `[]` or dot subscript expression, but not a call — at least, +// not without wrapping it in parentheses. Thus, it uses the noCalls +// argument to parseSubscripts to prevent it from consuming the +// argument list. + +var empty$1 = []; + +pp$3.parseNew = function() { + var node = this.startNode(); + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { + node.meta = meta; + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + if (node.property.name !== "target" || containsEsc) + { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } + if (!this.inFunction) + { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } + return this.finishNode(node, "MetaProperty") + } + var startPos = this.start, startLoc = this.startLoc; + node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); + if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } + else { node.arguments = empty$1; } + return this.finishNode(node, "NewExpression") +}; + +// Parse template expression. + +pp$3.parseTemplateElement = function(ref) { + var isTagged = ref.isTagged; + + var elem = this.startNode(); + if (this.type === types.invalidTemplate) { + if (!isTagged) { + this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); + } + elem.value = { + raw: this.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), + cooked: this.value + }; + } + this.next(); + elem.tail = this.type === types.backQuote; + return this.finishNode(elem, "TemplateElement") +}; + +pp$3.parseTemplate = function(ref) { + var this$1 = this; + if ( ref === void 0 ) ref = {}; + var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; + + var node = this.startNode(); + this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement({isTagged: isTagged}); + node.quasis = [curElt]; + while (!curElt.tail) { + this$1.expect(types.dollarBraceL); + node.expressions.push(this$1.parseExpression()); + this$1.expect(types.braceR); + node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); + } + this.next(); + return this.finishNode(node, "TemplateLiteral") +}; + +pp$3.isAsyncProp = function(prop) { + return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && + (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && + !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) +}; + +// Parse an object literal or binding pattern. + +pp$3.parseObj = function(isPattern, refDestructuringErrors) { + var this$1 = this; + + var node = this.startNode(), first = true, propHash = {}; + node.properties = []; + this.next(); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var prop = this$1.parseProperty(isPattern, refDestructuringErrors); + if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); } + node.properties.push(prop); + } + return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") +}; + +pp$3.parseProperty = function(isPattern, refDestructuringErrors) { + var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; + if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) { + if (isPattern) { + prop.argument = this.parseIdent(false); + if (this.type === types.comma) { + this.raise(this.start, "Comma is not permitted after the rest element"); + } + return this.finishNode(prop, "RestElement") + } + // To disallow parenthesized identifier via `this.toAssignable()`. + if (this.type === types.parenL && refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0) { + refDestructuringErrors.parenthesizedAssign = this.start; + } + if (refDestructuringErrors.parenthesizedBind < 0) { + refDestructuringErrors.parenthesizedBind = this.start; + } + } + // Parse argument. + prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); + // To disallow trailing comma via `this.toAssignable()`. + if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { + refDestructuringErrors.trailingComma = this.start; + } + // Finish + return this.finishNode(prop, "SpreadElement") + } + if (this.options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + if (isPattern || refDestructuringErrors) { + startPos = this.start; + startLoc = this.startLoc; + } + if (!isPattern) + { isGenerator = this.eat(types.star); } + } + var containsEsc = this.containsEsc; + this.parsePropertyName(prop); + if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + this.parsePropertyName(prop, refDestructuringErrors); + } else { + isAsync = false; + } + this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); + return this.finishNode(prop, "Property") +}; + +pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { + if ((isGenerator || isAsync) && this.type === types.colon) + { this.unexpected(); } + + if (this.eat(types.colon)) { + prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); + prop.kind = "init"; + } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { + if (isPattern) { this.unexpected(); } + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (!isPattern && !containsEsc && + this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set") && + (this.type != types.comma && this.type != types.braceR)) { + if (isGenerator || isAsync) { this.unexpected(); } + prop.kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + var paramCount = prop.kind === "get" ? 0 : 1; + if (prop.value.params.length !== paramCount) { + var start = prop.value.start; + if (prop.kind === "get") + { this.raiseRecoverable(start, "getter should have no params"); } + else + { this.raiseRecoverable(start, "setter should have exactly one param"); } + } else { + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") + { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } + } + } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + this.checkUnreserved(prop.key); + prop.kind = "init"; + if (isPattern) { + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else if (this.type === types.eq && refDestructuringErrors) { + if (refDestructuringErrors.shorthandAssign < 0) + { refDestructuringErrors.shorthandAssign = this.start; } + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else { + prop.value = prop.key; + } + prop.shorthand = true; + } else { this.unexpected(); } +}; + +pp$3.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(types.bracketL)) { + prop.computed = true; + prop.key = this.parseMaybeAssign(); + this.expect(types.bracketR); + return prop.key + } else { + prop.computed = false; + } + } + return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) +}; + +// Initialize empty function node. + +pp$3.initFunction = function(node) { + node.id = null; + if (this.options.ecmaVersion >= 6) { + node.generator = false; + node.expression = false; + } + if (this.options.ecmaVersion >= 8) + { node.async = false; } +}; + +// Parse object or class method. + +pp$3.parseMethod = function(isGenerator, isAsync) { + var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; + + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + this.inGenerator = node.generator; + this.inAsync = node.async; + this.yieldPos = 0; + this.awaitPos = 0; + this.inFunction = true; + this.enterFunctionScope(); + + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + this.parseFunctionBody(node, false); + + this.inGenerator = oldInGen; + this.inAsync = oldInAsync; + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.inFunction = oldInFunc; + return this.finishNode(node, "FunctionExpression") +}; + +// Parse arrow function expression with given parameters. + +pp$3.parseArrowExpression = function(node, params, isAsync) { + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; + + this.enterFunctionScope(); + this.initFunction(node); + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + this.inGenerator = false; + this.inAsync = node.async; + this.yieldPos = 0; + this.awaitPos = 0; + this.inFunction = true; + + node.params = this.toAssignableList(params, true); + this.parseFunctionBody(node, true); + + this.inGenerator = oldInGen; + this.inAsync = oldInAsync; + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.inFunction = oldInFunc; + return this.finishNode(node, "ArrowFunctionExpression") +}; + +// Parse function body and check parameters. + +pp$3.parseFunctionBody = function(node, isArrowFunction) { + var isExpression = isArrowFunction && this.type !== types.braceL; + var oldStrict = this.strict, useStrict = false; + + if (isExpression) { + node.body = this.parseMaybeAssign(); + node.expression = true; + this.checkParams(node, false); + } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end); + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } + } + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + var oldLabels = this.labels; + this.labels = []; + if (useStrict) { this.strict = true; } + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); + node.body = this.parseBlock(false); + node.expression = false; + this.adaptDirectivePrologue(node.body.body); + this.labels = oldLabels; + } + this.exitFunctionScope(); + + if (this.strict && node.id) { + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + this.checkLVal(node.id, "none"); + } + this.strict = oldStrict; +}; + +pp$3.isSimpleParamList = function(params) { + for (var i = 0, list = params; i < list.length; i += 1) + { + var param = list[i]; + + if (param.type !== "Identifier") { return false + } } + return true +}; + +// Checks function params for various disallowed patterns such as using "eval" +// or "arguments" and duplicate parameters. + +pp$3.checkParams = function(node, allowDuplicates) { + var this$1 = this; + + var nameHash = {}; + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; + + this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash); + } +}; + +// Parses a comma-separated list of expressions, and returns them as +// an array. `close` is the token type that ends the list, and +// `allowEmpty` can be turned on to allow subsequent commas with +// nothing in between them to be parsed as `null` (which is needed +// for array literals). + +pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { + var this$1 = this; + + var elts = [], first = true; + while (!this.eat(close)) { + if (!first) { + this$1.expect(types.comma); + if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } + } else { first = false; } + + var elt = (void 0); + if (allowEmpty && this$1.type === types.comma) + { elt = null; } + else if (this$1.type === types.ellipsis) { + elt = this$1.parseSpread(refDestructuringErrors); + if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) + { refDestructuringErrors.trailingComma = this$1.start; } + } else { + elt = this$1.parseMaybeAssign(false, refDestructuringErrors); + } + elts.push(elt); + } + return elts +}; + +pp$3.checkUnreserved = function(ref) { + var start = ref.start; + var end = ref.end; + var name = ref.name; + + if (this.inGenerator && name === "yield") + { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } + if (this.inAsync && name === "await") + { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } + if (this.isKeyword(name)) + { this.raise(start, ("Unexpected keyword '" + name + "'")); } + if (this.options.ecmaVersion < 6 && + this.input.slice(start, end).indexOf("\\") != -1) { return } + var re = this.strict ? this.reservedWordsStrict : this.reservedWords; + if (re.test(name)) { + if (!this.inAsync && name === "await") + { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); } + this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); + } +}; + +// Parse the next token as an identifier. If `liberal` is true (used +// when parsing properties), it will also convert keywords into +// identifiers. + +pp$3.parseIdent = function(liberal, isBinding) { + var node = this.startNode(); + if (liberal && this.options.allowReserved == "never") { liberal = false; } + if (this.type === types.name) { + node.name = this.value; + } else if (this.type.keyword) { + node.name = this.type.keyword; + + // To fix https://github.com/acornjs/acorn/issues/575 + // `class` and `function` keywords push new context into this.context. + // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. + // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword + if ((node.name === "class" || node.name === "function") && + (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { + this.context.pop(); + } + } else { + this.unexpected(); + } + this.next(); + this.finishNode(node, "Identifier"); + if (!liberal) { this.checkUnreserved(node); } + return node +}; + +// Parses yield expression inside generator. + +pp$3.parseYield = function() { + if (!this.yieldPos) { this.yieldPos = this.start; } + + var node = this.startNode(); + this.next(); + if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(types.star); + node.argument = this.parseMaybeAssign(); + } + return this.finishNode(node, "YieldExpression") +}; + +pp$3.parseAwait = function() { + if (!this.awaitPos) { this.awaitPos = this.start; } + + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(null, true); + return this.finishNode(node, "AwaitExpression") +}; + +var pp$4 = Parser.prototype; + +// This function is used to raise exceptions on parse errors. It +// takes an offset integer (into the current `input`) to indicate +// the location of the error, attaches the position to the end +// of the error message, and then raises a `SyntaxError` with that +// message. + +pp$4.raise = function(pos, message) { + var loc = getLineInfo(this.input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = this.pos; + throw err +}; + +pp$4.raiseRecoverable = pp$4.raise; + +pp$4.curPosition = function() { + if (this.options.locations) { + return new Position(this.curLine, this.pos - this.lineStart) + } +}; + +var pp$5 = Parser.prototype; + +// Object.assign polyfill +var assign = Object.assign || function(target) { + var sources = [], len = arguments.length - 1; + while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; + + for (var i = 0, list = sources; i < list.length; i += 1) { + var source = list[i]; + + for (var key in source) { + if (has(source, key)) { + target[key] = source[key]; + } + } + } + return target +}; + +// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + +pp$5.enterFunctionScope = function() { + // var: a hash of var-declared names in the current lexical scope + // lexical: a hash of lexically-declared names in the current lexical scope + // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) + // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) + this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}); +}; + +pp$5.exitFunctionScope = function() { + this.scopeStack.pop(); +}; + +pp$5.enterLexicalScope = function() { + var parentScope = this.scopeStack[this.scopeStack.length - 1]; + var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}; + + this.scopeStack.push(childScope); + assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical); +}; + +pp$5.exitLexicalScope = function() { + var childScope = this.scopeStack.pop(); + var parentScope = this.scopeStack[this.scopeStack.length - 1]; + + assign(parentScope.childVar, childScope.var, childScope.childVar); +}; + +/** + * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` + * in the current lexical scope or any of the parent lexical scopes in this function. + */ +pp$5.canDeclareVarName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1]; + + return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) +}; + +/** + * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` + * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in + * any child lexical scopes in this function. + */ +pp$5.canDeclareLexicalName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1]; + + return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) +}; + +pp$5.declareVarName = function(name) { + this.scopeStack[this.scopeStack.length - 1].var[name] = true; +}; + +pp$5.declareLexicalName = function(name) { + this.scopeStack[this.scopeStack.length - 1].lexical[name] = true; +}; + +var Node = function Node(parser, pos, loc) { + this.type = ""; + this.start = pos; + this.end = 0; + if (parser.options.locations) + { this.loc = new SourceLocation(parser, loc); } + if (parser.options.directSourceFile) + { this.sourceFile = parser.options.directSourceFile; } + if (parser.options.ranges) + { this.range = [pos, 0]; } +}; + +// Start an AST node, attaching a start offset. + +var pp$6 = Parser.prototype; + +pp$6.startNode = function() { + return new Node(this, this.start, this.startLoc) +}; + +pp$6.startNodeAt = function(pos, loc) { + return new Node(this, pos, loc) +}; + +// Finish an AST node, adding `type` and `end` properties. + +function finishNodeAt(node, type, pos, loc) { + node.type = type; + node.end = pos; + if (this.options.locations) + { node.loc.end = loc; } + if (this.options.ranges) + { node.range[1] = pos; } + return node +} + +pp$6.finishNode = function(node, type) { + return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) +}; + +// Finish node at given position + +pp$6.finishNodeAt = function(node, type, pos, loc) { + return finishNodeAt.call(this, node, type, pos, loc) +}; + +// The algorithm used to determine whether a regexp can appear at a +// given point in the program is loosely based on sweet.js' approach. +// See https://github.com/mozilla/sweet.js/wiki/design + +var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { + this.token = token; + this.isExpr = !!isExpr; + this.preserveSpace = !!preserveSpace; + this.override = override; + this.generator = !!generator; +}; + +var types$1 = { + b_stat: new TokContext("{", false), + b_expr: new TokContext("{", true), + b_tmpl: new TokContext("${", false), + p_stat: new TokContext("(", false), + p_expr: new TokContext("(", true), + q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), + f_stat: new TokContext("function", false), + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) +}; + +var pp$7 = Parser.prototype; + +pp$7.initialContext = function() { + return [types$1.b_stat] +}; + +pp$7.braceIsBlock = function(prevType) { + var parent = this.curContext(); + if (parent === types$1.f_expr || parent === types$1.f_stat) + { return true } + if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) + { return !parent.isExpr } + + // The check for `tt.name && exprAllowed` detects whether we are + // after a `yield` or `of` construct. See the `updateContext` for + // `tt.name`. + if (prevType === types._return || prevType == types.name && this.exprAllowed) + { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } + if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow) + { return true } + if (prevType == types.braceL) + { return parent === types$1.b_stat } + if (prevType == types._var || prevType == types.name) + { return false } + return !this.exprAllowed +}; + +pp$7.inGeneratorContext = function() { + var this$1 = this; + + for (var i = this.context.length - 1; i >= 1; i--) { + var context = this$1.context[i]; + if (context.token === "function") + { return context.generator } + } + return false +}; + +pp$7.updateContext = function(prevType) { + var update, type = this.type; + if (type.keyword && prevType == types.dot) + { this.exprAllowed = false; } + else if (update = type.updateContext) + { update.call(this, prevType); } + else + { this.exprAllowed = type.beforeExpr; } +}; + +// Token-specific context update code + +types.parenR.updateContext = types.braceR.updateContext = function() { + if (this.context.length == 1) { + this.exprAllowed = true; + return + } + var out = this.context.pop(); + if (out === types$1.b_stat && this.curContext().token === "function") { + out = this.context.pop(); + } + this.exprAllowed = !out.isExpr; +}; + +types.braceL.updateContext = function(prevType) { + this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); + this.exprAllowed = true; +}; + +types.dollarBraceL.updateContext = function() { + this.context.push(types$1.b_tmpl); + this.exprAllowed = true; +}; + +types.parenL.updateContext = function(prevType) { + var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; + this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); + this.exprAllowed = true; +}; + +types.incDec.updateContext = function() { + // tokExprAllowed stays unchanged +}; + +types._function.updateContext = types._class.updateContext = function(prevType) { + if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && + !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) + { this.context.push(types$1.f_expr); } + else + { this.context.push(types$1.f_stat); } + this.exprAllowed = false; +}; + +types.backQuote.updateContext = function() { + if (this.curContext() === types$1.q_tmpl) + { this.context.pop(); } + else + { this.context.push(types$1.q_tmpl); } + this.exprAllowed = false; +}; + +types.star.updateContext = function(prevType) { + if (prevType == types._function) { + var index = this.context.length - 1; + if (this.context[index] === types$1.f_expr) + { this.context[index] = types$1.f_expr_gen; } + else + { this.context[index] = types$1.f_gen; } + } + this.exprAllowed = true; +}; + +types.name.updateContext = function(prevType) { + var allowed = false; + if (this.options.ecmaVersion >= 6) { + if (this.value == "of" && !this.exprAllowed || + this.value == "yield" && this.inGeneratorContext()) + { allowed = true; } + } + this.exprAllowed = allowed; +}; + +// Object type used to represent tokens. Note that normally, tokens +// simply exist as properties on the parser object. This is only +// used for the onToken callback and the external tokenizer. + +var Token = function Token(p) { + this.type = p.type; + this.value = p.value; + this.start = p.start; + this.end = p.end; + if (p.options.locations) + { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } + if (p.options.ranges) + { this.range = [p.start, p.end]; } +}; + +// ## Tokenizer + +var pp$8 = Parser.prototype; + +// Are we running under Rhino? +var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; + +// Move to the next token + +pp$8.next = function() { + if (this.options.onToken) + { this.options.onToken(new Token(this)); } + + this.lastTokEnd = this.end; + this.lastTokStart = this.start; + this.lastTokEndLoc = this.endLoc; + this.lastTokStartLoc = this.startLoc; + this.nextToken(); +}; + +pp$8.getToken = function() { + this.next(); + return new Token(this) +}; + +// If we're in an ES6 environment, make parsers iterable +if (typeof Symbol !== "undefined") + { pp$8[Symbol.iterator] = function() { + var this$1 = this; + + return { + next: function () { + var token = this$1.getToken(); + return { + done: token.type === types.eof, + value: token + } + } + } + }; } + +// Toggle strict mode. Re-reads the next number or string to please +// pedantic tests (`"use strict"; 010;` should fail). + +pp$8.curContext = function() { + return this.context[this.context.length - 1] +}; + +// Read a single token, updating the parser object's token-related +// properties. + +pp$8.nextToken = function() { + var curContext = this.curContext(); + if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } + + this.start = this.pos; + if (this.options.locations) { this.startLoc = this.curPosition(); } + if (this.pos >= this.input.length) { return this.finishToken(types.eof) } + + if (curContext.override) { return curContext.override(this) } + else { this.readToken(this.fullCharCodeAtPos()); } +}; + +pp$8.readToken = function(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) + { return this.readWord() } + + return this.getTokenFromCode(code) +}; + +pp$8.fullCharCodeAtPos = function() { + var code = this.input.charCodeAt(this.pos); + if (code <= 0xd7ff || code >= 0xe000) { return code } + var next = this.input.charCodeAt(this.pos + 1); + return (code << 10) + next - 0x35fdc00 +}; + +pp$8.skipBlockComment = function() { + var this$1 = this; + + var startLoc = this.options.onComment && this.curPosition(); + var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); + if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } + this.pos = end + 2; + if (this.options.locations) { + lineBreakG.lastIndex = start; + var match; + while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { + ++this$1.curLine; + this$1.lineStart = match.index + match[0].length; + } + } + if (this.options.onComment) + { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, + startLoc, this.curPosition()); } +}; + +pp$8.skipLineComment = function(startSkip) { + var this$1 = this; + + var start = this.pos; + var startLoc = this.options.onComment && this.curPosition(); + var ch = this.input.charCodeAt(this.pos += startSkip); + while (this.pos < this.input.length && !isNewLine(ch)) { + ch = this$1.input.charCodeAt(++this$1.pos); + } + if (this.options.onComment) + { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, + startLoc, this.curPosition()); } +}; + +// Called at the start of the parse and after every token. Skips +// whitespace and comments, and. + +pp$8.skipSpace = function() { + var this$1 = this; + + loop: while (this.pos < this.input.length) { + var ch = this$1.input.charCodeAt(this$1.pos); + switch (ch) { + case 32: case 160: // ' ' + ++this$1.pos; + break + case 13: + if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { + ++this$1.pos; + } + case 10: case 8232: case 8233: + ++this$1.pos; + if (this$1.options.locations) { + ++this$1.curLine; + this$1.lineStart = this$1.pos; + } + break + case 47: // '/' + switch (this$1.input.charCodeAt(this$1.pos + 1)) { + case 42: // '*' + this$1.skipBlockComment(); + break + case 47: + this$1.skipLineComment(2); + break + default: + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this$1.pos; + } else { + break loop + } + } + } +}; + +// Called at the end of every token. Sets `end`, `val`, and +// maintains `context` and `exprAllowed`, and skips the space after +// the token, so that the next one's `start` will point at the +// right position. + +pp$8.finishToken = function(type, val) { + this.end = this.pos; + if (this.options.locations) { this.endLoc = this.curPosition(); } + var prevType = this.type; + this.type = type; + this.value = val; + + this.updateContext(prevType); +}; + +// ### Token reading + +// This is the function that is called to fetch the next token. It +// is somewhat obscure, because it works in character codes rather +// than characters, and because operator parsing has been inlined +// into it. +// +// All in the name of speed. +// +pp$8.readToken_dot = function() { + var next = this.input.charCodeAt(this.pos + 1); + if (next >= 48 && next <= 57) { return this.readNumber(true) } + var next2 = this.input.charCodeAt(this.pos + 2); + if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + this.pos += 3; + return this.finishToken(types.ellipsis) + } else { + ++this.pos; + return this.finishToken(types.dot) + } +}; + +pp$8.readToken_slash = function() { // '/' + var next = this.input.charCodeAt(this.pos + 1); + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.slash, 1) +}; + +pp$8.readToken_mult_modulo_exp = function(code) { // '%*' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + var tokentype = code === 42 ? types.star : types.modulo; + + // exponentiation operator ** and **= + if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) { + ++size; + tokentype = types.starstar; + next = this.input.charCodeAt(this.pos + 2); + } + + if (next === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(tokentype, size) +}; + +pp$8.readToken_pipe_amp = function(code) { // '|&' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) +}; + +pp$8.readToken_caret = function() { // '^' + var next = this.input.charCodeAt(this.pos + 1); + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.bitwiseXOR, 1) +}; + +pp$8.readToken_plus_min = function(code) { // '+-' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && + (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { + // A `-->` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types.incDec, 2) + } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.plusMin, 1) +}; + +pp$8.readToken_lt_gt = function(code) { // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(types.bitShift, size) + } + if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && + this.input.charCodeAt(this.pos + 3) == 45) { + // `",device.name); + device.getPorts(function(devicePorts, instantPorts) { + //console.log("getPorts <--",device.name); + if (instantPorts===false) shouldCallAgain = true; + if (devicePorts) { + devicePorts.forEach(function(port) { + var ignored = false; + if (Espruino.Config.SERIAL_IGNORE) + Espruino.Config.SERIAL_IGNORE.split("|").forEach(function(wildcard) { + var regexp = "^"+wildcard.replace(/\./g,"\\.").replace(/\*/g,".*")+"$"; + if (port.path.match(new RegExp(regexp))) + ignored = true; + }); + + if (!ignored) { + if (port.usb && port.usb[0]==0x0483 && port.usb[1]==0x5740) + port.description = "Espruino board"; + ports.push(port); + newPortToDevice[port.path] = device; + } + }); + } + responses++; + if (responses == devices.length) { + portToDevice = newPortToDevice; + ports.sort(function(a,b) { + if (a.unimportant && !b.unimportant) return 1; + if (b.unimportant && !a.unimportant) return -1; + return 0; + }); + callback(ports, shouldCallAgain); + } + }); + }); + }; + + var openSerial=function(serialPort, connectCallback, disconnectCallback) { + return openSerialInternal(serialPort, connectCallback, disconnectCallback, 2); + } + + var openSerialInternal=function(serialPort, connectCallback, disconnectCallback, attempts) { + /* If openSerial is called, we need to have called getPorts first + in order to figure out which one of the serial_ implementations + we must call into. */ + if (portToDevice === undefined) { + portToDevice = []; // stop recursive calls if something errors + return getPorts(function() { + openSerialInternal(serialPort, connectCallback, disconnectCallback, attempts); + }); + } + + if (!(serialPort in portToDevice)) { + if (serialPort.toLowerCase() in portToDevice) { + serialPort = serialPort.toLowerCase(); + } else { + if (attempts>0) { + console.log("Port "+JSON.stringify(serialPort)+" not found - checking ports again ("+attempts+" attempts left)"); + return getPorts(function() { + openSerialInternal(serialPort, connectCallback, disconnectCallback, attempts-1); + }); + } else { + console.error("Port "+JSON.stringify(serialPort)+" not found"); + return connectCallback(undefined); + } + } + } + + connectionInfo = undefined; + flowControlXOFF = false; + currentDevice = portToDevice[serialPort]; + currentDevice.open(serialPort, function(cInfo) { // CONNECT + if (!cInfo) { +// Espruino.Core.Notifications.error("Unable to connect"); + console.error("Unable to open device (connectionInfo="+cInfo+")"); + connectCallback(undefined); + } else { + connectionInfo = cInfo; + connectedPort = serialPort; + console.log("Connected", cInfo); + var portInfo = { port:serialPort }; + if (connectionInfo.portName) + portInfo.portName = connectionInfo.portName; + Espruino.callProcessor("connected", portInfo, function() { + connectCallback(cInfo); + }); + } + }, function(data) { // RECEIEVE DATA + if (!(data instanceof ArrayBuffer)) console.warn("Serial port implementation is not returning ArrayBuffers"); + if (Espruino.Config.SERIAL_FLOW_CONTROL) { + var u = new Uint8Array(data); + for (var i=0;i resume upload"); + flowControlXOFF = false; + } + if (u[i]==19) { // XOFF + console.log("XOFF received => pause upload"); + flowControlXOFF = true; + } + } + } + if (readListener) readListener(data); + }, function() { // DISCONNECT + currentDevice = undefined; + if (!connectionInfo) { + // we got a disconnect when we hadn't connected... + // Just call connectCallback(undefined), don't bother sending disconnect + connectCallback(undefined); + return; + } + connectionInfo = undefined; + if (writeTimeout!==undefined) + clearTimeout(writeTimeout); + writeTimeout = undefined; + writeData = []; + sendingBinary = false; + flowControlXOFF = false; + + Espruino.callProcessor("disconnected", undefined, function() { + disconnectCallback(); + }); + }); + }; + + var str2ab=function(str) { + var buf=new ArrayBuffer(str.length); + var bufView=new Uint8Array(buf); + for (var i=0; i=256) { + console.warn("Attempted to send non-8 bit character - code "+ch); + ch = "?".charCodeAt(0); + } + bufView[i] = ch; + } + return buf; + }; + + var closeSerial=function() { + if (currentDevice) { + currentDevice.close(); + currentDevice = undefined; + } else + console.error("Close called, but serial port not open"); + }; + + var isConnected = function() { + return currentDevice!==undefined; + }; + + var writeSerialWorker = function(isStarting) { + writeTimeout = undefined; // we've been called + // check flow control + if (flowControlXOFF) { + /* flow control was enabled - bit hacky (we could use a callback) + but safe - just check again in a bit to see if we should send */ + writeTimeout = setTimeout(function() { + writeSerialWorker(); + }, 50); + return; + } + + // if we disconnected while sending, empty queue + if (currentDevice === undefined) { + if (writeData[0].callback) + writeData[0].callback(); + writeData.shift(); + if (writeData.length) setTimeout(function() { + writeSerialWorker(false); + }, 1); + return; + } + + if (writeData[0].data === "") { + if (writeData[0].showStatus) + Espruino.Core.Status.setStatus("Sent"); + if (writeData[0].callback) + writeData[0].callback(); + writeData.shift(); // remove this empty first element + if (!writeData.length) return; // anything left to do? + isStarting = true; + } + + if (isStarting) { + var blockSize = 512; + if (currentDevice.maxWriteLength) + blockSize = currentDevice.maxWriteLength; + /* if we're throttling our writes we want to send small + * blocks of data at once. We still limit the size of + * sent blocks to 512 because on Mac we seem to lose + * data otherwise (not on any other platforms!) */ + if (slowWrite) blockSize=19; + writeData[0].blockSize = blockSize; + + writeData[0].showStatus &= writeData[0].data.length>writeData[0].blockSize; + if (writeData[0].showStatus) { + Espruino.Core.Status.setStatus("Sending...", writeData[0].data.length); + console.log("---> "+JSON.stringify(writeData[0].data)); + } + } + + // Initial split use previous, or don't + var d = undefined; + var split = writeData[0].nextSplit || { start:0, end:writeData[0].data.length, delay:0 }; + // if we get something like Ctrl-C or `reset`, wait a bit for it to complete + if (!sendingBinary) { + function findSplitIdx(prev, substr, delay, reason) { + var match = writeData[0].data.match(substr); + // not found + if (match===null) return prev; + // or previous find was earlier in str + var end = match.index + match[0].length; + if (end > prev.end) return prev; + // found, and earlier + prev.start = match.index; + prev.end = end; + prev.delay = delay; + prev.match = match[0]; + prev.reason = reason; + return prev; + } + split = findSplitIdx(split, /\x03/, 250, "Ctrl-C"); // Ctrl-C + split = findSplitIdx(split, /reset\(\);\n/, 250, "reset()"); // Reset + split = findSplitIdx(split, /load\(\);\n/, 250, "load()"); // Load + split = findSplitIdx(split, /Modules.addCached\("[^\n]*"\);\n/, 250, "Modules.addCached"); // Adding a module + split = findSplitIdx(split, /\x10require\("Storage"\).write\([^\n]*\);\n/, 500, "Storage.write"); // Write chunk of data + } + // Otherwise split based on block size + if (!split.match || split.end >= writeData[0].blockSize) { + if (split.match) writeData[0].nextSplit = split; + split = { start:0, end:writeData[0].blockSize, delay:0 }; + } + if (split.match) console.log("Splitting for "+split.reason+", delay "+split.delay); + // Only send some of the data + if (writeData[0].data.length>split.end) { + if (slowWrite && split.delay==0) split.delay=50; + d = writeData[0].data.substr(0,split.end); + writeData[0].data = writeData[0].data.substr(split.end); + if (writeData[0].nextSplit) { + writeData[0].nextSplit.start -= split.end; + writeData[0].nextSplit.end -= split.end; + if (writeData[0].nextSplit.end<=0) + writeData[0].nextSplit = undefined; + } + } else { + d = writeData[0].data; + writeData[0].data = ""; + writeData[0].nextSplit = undefined; + } + // update status + if (writeData[0].showStatus) + Espruino.Core.Status.incrementProgress(d.length); + // actually write data + //console.log("Sending block "+JSON.stringify(d)+", wait "+split.delay+"ms"); + currentDevice.write(d, function() { + // Once written, start timeout + writeTimeout = setTimeout(function() { + writeSerialWorker(); + }, split.delay); + }); + } + + // Throttled serial write + var writeSerial = function(data, showStatus, callback) { + if (showStatus===undefined) showStatus=true; + + /* Queue our data to write. If there was previous data and no callback to + invoke on this data or the previous then just append data. This would happen + if typing in the terminal for example. */ + if (!callback && writeData.length && !writeData[writeData.length-1].callback) { + writeData[writeData.length-1].data += data; + } else { + writeData.push({data:data,callback:callback,showStatus:showStatus}); + /* if this is our first data, start sending now. Otherwise we're already + busy sending and will pull data off writeData when ready */ + if (writeData.length==1) + writeSerialWorker(true); + } + }; + + + // ---------------------------------------------------------- + Espruino.Core.Serial = { + "devices" : [], // List of devices that can provide a serial API + "init" : init, + "getPorts": getPorts, + "open": openSerial, + "isConnected": isConnected, + "startListening": startListening, + "write": writeSerial, + "close": closeSerial, + "isSlowWrite": function() { return slowWrite; }, + "setSlowWrite": function(isOn, force) { + if ((!force) && Espruino.Config.SERIAL_THROTTLE_SEND) { + console.log("ForceThrottle option is set - set Slow Write = true"); + isOn = true; + } else + console.log("Set Slow Write = "+isOn); + slowWrite = isOn; + }, + "setBinary": function(isOn) { + sendingBinary = isOn; + } + }; +})(); +/** + Copyright 2014 Gordon Williams (gw@pur3.co.uk) + + This Source Code is subject to the terms of the Mozilla Public + License, v2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + ------------------------------------------------------------------ + The plugin that actually writes code out to Espruino + ------------------------------------------------------------------ +**/ +"use strict"; +(function(){ + + function init() { + Espruino.Core.Config.add("RESET_BEFORE_SEND", { + section : "Communications", + name : "Reset before Send", + description : "Reset Espruino before sending code from the editor pane?", + type : "boolean", + defaultValue : true + }); + Espruino.Core.Config.add("STORE_LINE_NUMBERS", { + section : "Communications", + name : "Store line numbers", + description : "Should Espruino store line numbers for each function? This uses one extra variable per function, but allows you to get source code debugging in the Web IDE", + type : "boolean", + defaultValue : true + }); + + } + + function writeToEspruino(code, callback) { + /* hack around non-K&R code formatting that would have + broken Espruino CLI's bracket counting */ + code = reformatCode(code); + if (code === undefined) return; // it should already have errored + + // We want to make sure we've got a prompt before sending. If not, + // this will issue a Ctrl+C + Espruino.Core.Utils.getEspruinoPrompt(function() { + // Make sure code ends in 2 newlines + while (code[code.length-2]!="\n" || code[code.length-1]!="\n") + code += "\n"; + + // If we're supposed to reset Espruino before sending... + if (Espruino.Config.RESET_BEFORE_SEND) { + code = "\x10reset();\n"+code; + } + + //console.log("Sending... "+data); + Espruino.Core.Serial.write(code, true, function() { + // give 5 seconds for sending with save and 2 seconds without save + var count = Espruino.Config.SAVE_ON_SEND ? 50 : 20; + setTimeout(function cb() { + if (Espruino.Core.Terminal!==undefined && + Espruino.Core.Terminal.getTerminalLine()!=">") { + count--; + if (count>0) { + setTimeout(cb, 100); + } else { + Espruino.Core.Notifications.error("Prompt not detected - upload failed. Trying to recover..."); + Espruino.Core.Serial.write("\x03\x03echo(1)\n", false, callback); + } + } else { + if (callback) callback(); + } + }, 100); + }); + }); + }; + + /// Parse and fix issues like `if (false)\n foo` in the root scope + function reformatCode(code) { + var APPLY_LINE_NUMBERS = false; + var lineNumberOffset = 0; + var ENV = Espruino.Core.Env.getData(); + if (ENV && ENV.VERSION_MAJOR && ENV.VERSION_MINOR) { + if (ENV.VERSION_MAJOR>1 || + ENV.VERSION_MINOR>=81.086) { + if (Espruino.Config.STORE_LINE_NUMBERS) + APPLY_LINE_NUMBERS = true; + } + } + // Turn cr/lf into just lf (eg. windows -> unix) + code = code.replace(/\r\n/g,"\n"); + // First off, try and fix funky characters + for (var i=0;i255) && ch!=9/*Tab*/ && ch!=10/*LF*/ && ch!=13/*CR*/) { + console.warn("Funky character code "+ch+" at position "+i+". Replacing with ?"); + code = code.substr(0,i)+"?"+code.substr(i+1); + } + } + + /* Search for lines added to the start of the code by the module handler. + Ideally there would be a better way of doing this so line numbers stayed correct, + but this hack works for now. Fixes EspruinoWebIDE#140 */ + if (APPLY_LINE_NUMBERS) { + var l = code.split("\n"); + var i = 0; + while (l[i] && (l[i].substr(0,8)=="Modules." || + l[i].substr(0,8)=="setTime(")) i++; + lineNumberOffset = -i; + } + + var resultCode = "\x10"; // 0x10 = echo off for line + /** we're looking for: + * `a = \n b` + * `for (.....) \n X` + * `if (.....) \n X` + * `if (.....) { } \n else foo` + * `while (.....) \n X` + * `do \n X` + * `function (.....) \n X` + * `function N(.....) \n X` + * `var a \n , b` `var a = 0 \n, b` + * `var a, \n b` `var a = 0, \n b` + * `a \n . b` + * `foo() \n . b` + * `try { } \n catch \n () \n {}` + * + * These are divided into two groups - where there are brackets + * after the keyword (statementBeforeBrackets) and where there aren't + * (statement) + * + * We fix them by replacing \n with what you get when you press + * Alt+Enter (Ctrl + LF). This tells Espruino that it's a newline + * but NOT to execute. + */ + var lex = Espruino.Core.Utils.getLexer(code); + var brackets = 0; + var curlyBrackets = 0; + var statementBeforeBrackets = false; + var statement = false; + var varDeclaration = false; + var lastIdx = 0; + var lastTok = {str:""}; + var tok = lex.next(); + while (tok!==undefined) { + var previousString = code.substring(lastIdx, tok.startIdx); + var tokenString = code.substring(tok.startIdx, tok.endIdx); + //console.log("prev "+JSON.stringify(previousString)+" next "+tokenString); + + /* Inserting Alt-Enter newline, which adds newline without trying + to execute */ + if (brackets>0 || // we have brackets - sending the alt-enter special newline means Espruino doesn't have to do a search itself - faster. + statement || // statement was before brackets - expecting something else + statementBeforeBrackets || // we have an 'if'/etc + varDeclaration || // variable declaration then newline + tok.str=="," || // comma on newline - there was probably something before + tok.str=="." || // dot on newline - there was probably something before + tok.str=="+" || tok.str=="-" || // +/- on newline - there was probably something before + tok.str=="=" || // equals on newline - there was probably something before + tok.str=="else" || // else on newline + lastTok.str=="else" || // else befgore newline + tok.str=="catch" || // catch on newline - part of try..catch + lastTok.str=="catch" + ) { + //console.log("Possible"+JSON.stringify(previousString)); + previousString = previousString.replace(/\n/g, "\x1B\x0A"); + } + + var previousBrackets = brackets; + if (tok.str=="(" || tok.str=="{" || tok.str=="[") brackets++; + if (tok.str=="{") curlyBrackets++; + if (tok.str==")" || tok.str=="}" || tok.str=="]") brackets--; + if (tok.str=="}") curlyBrackets--; + + if (brackets==0) { + if (tok.str=="for" || tok.str=="if" || tok.str=="while" || tok.str=="function" || tok.str=="throw") { + statementBeforeBrackets = true; + varDeclaration = false; + } else if (tok.str=="var") { + varDeclaration = true; + } else if (tok.type=="ID" && lastTok.str=="function") { + statementBeforeBrackets = true; + } else if (tok.str=="try" || tok.str=="catch") { + statementBeforeBrackets = true; + } else if (tok.str==")" && statementBeforeBrackets) { + statementBeforeBrackets = false; + statement = true; + } else if (["=","^","&&","||","+","+=","-","-=","*","*=","/","/=","%","%=","&","&=","|","|="].indexOf(tok.str)>=0) { + statement = true; + } else { + if (tok.str==";") varDeclaration = false; + statement = false; + statementBeforeBrackets = false; + } + } + /* If we're at root scope and had whitespace/comments between code, + remove it all and replace it with a single newline and a + 0x10 (echo off for line) character. However DON'T do this if we had + an alt-enter in the line, as it was there to stop us executing + prematurely */ + if (previousBrackets==0 && + previousString.indexOf("\n")>=0 && + previousString.indexOf("\x1B\x0A")<0) { + previousString = "\n\x10"; + // Apply line numbers to each new line sent, to aid debugger + if (APPLY_LINE_NUMBERS && tok.lineNumber && (tok.lineNumber+lineNumberOffset)>0) { + // Esc [ 1234 d + // This is the 'set line number' command that we're abusing :) + previousString += "\x1B\x5B"+(tok.lineNumber+lineNumberOffset)+"d"; + } + } + + // add our stuff back together + resultCode += previousString+tokenString; + // next + lastIdx = tok.endIdx; + lastTok = tok; + tok = lex.next(); + } + //console.log(resultCode); + if (brackets>0) { + Espruino.Core.Notifications.error("You have more open brackets than close brackets. Please see the hints in the Editor window."); + return undefined; + } + if (brackets<0) { + Espruino.Core.Notifications.error("You have more close brackets than open brackets. Please see the hints in the Editor window."); + return undefined; + } + return resultCode; + }; + + Espruino.Core.CodeWriter = { + init : init, + writeToEspruino : writeToEspruino, + }; +}()); +/** + Copyright 2014 Gordon Williams (gw@pur3.co.uk) + + This Source Code is subject to the terms of the Mozilla Public + License, v2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + ------------------------------------------------------------------ + Automatically load any referenced modules + ------------------------------------------------------------------ +**/ +"use strict"; +(function(){ + + function init() { + Espruino.Core.Config.add("MODULE_URL", { + section : "Communications", + name : "Module URL", + description : "Where to search online for modules when `require()` is used", + type : "string", + defaultValue : "https://www.espruino.com/modules" + }); + Espruino.Core.Config.add("MODULE_EXTENSIONS", { + section : "Communications", + name : "Module Extensions", + description : "The file extensions to use for each module. These are checked in order and the first that exists is used. One or more file extensions (including the dot) separated by `|`", + type : "string", + defaultValue : ".min.js|.js" + }); + Espruino.Core.Config.add("MODULE_AS_FUNCTION", { + section : "Communications", + name : "Modules uploaded as functions", + description : "Espruino 1v90 and later ONLY. Upload modules as Functions, allowing any functions inside them to be loaded directly from flash when 'Save on Send' is enabled.", + type : "boolean", + defaultValue : true + }); + + Espruino.Core.Config.add("MODULE_PROXY_ENABLED", { + section : "Communications", + name : "Enable Proxy", + description : "Enable Proxy for loading the modules when `require()` is used (only in native IDE)", + type : "boolean", + defaultValue : false + }); + + Espruino.Core.Config.add("MODULE_PROXY_URL", { + section : "Communications", + name : "Proxy URL", + description : "Proxy URL for loading the modules when `require()` is used (only in native IDE)", + type : "string", + defaultValue : "" + }); + + Espruino.Core.Config.add("MODULE_PROXY_PORT", { + section : "Communications", + name : "Proxy Port", + description : "Proxy Port for loading the modules when `require()` is used (only in native IDE)", + type : "string", + defaultValue : "" + }); + + // When code is sent to Espruino, search it for modules and add extra code required to load them + Espruino.addProcessor("transformForEspruino", function(code, callback) { + loadModules(code, callback); + }); + + // Append the 'getModule' processor as the last (plugins get initialized after Espruino.Core modules) + Espruino.Plugins.CoreModules = { + init: function() { + Espruino.addProcessor("getModule", function(data, callback) { + if (data.moduleCode!==undefined) { // already provided be previous getModule processor + return callback(data); + } + + fetchGetModule(data, callback); + }); + } + }; + } + + function isBuiltIn(module) { + var d = Espruino.Core.Env.getData(); + // If we got data from the device itself, use that as the + // definitive answer + if ("string" == typeof d.MODULES) + return d.MODULES.split(",").indexOf(module)>=0; + // Otherwise try and figure it out from JSON + if ("info" in d && + "builtin_modules" in d.info && + d.info.builtin_modules.indexOf(module)>=0) + return true; + // Otherwise assume we don't have it + return false; + } + + /** Find any instances of require(...) in the code string and return a list */ + var getModulesRequired = function(code) { + var modules = []; + + var lex = Espruino.Core.Utils.getLexer(code); + var tok = lex.next(); + var state = 0; + while (tok!==undefined) { + if (state==0 && tok.str=="require") { + state=1; + } else if (state==1 && tok.str=="(") { + state=2; + } else if (state==2 && (tok.type=="STRING")) { + state=0; + var module = tok.value; + if (!isBuiltIn(module) && modules.indexOf(module)<0) + modules.push(module); + } else + state = 0; + tok = lex.next(); + } + + return modules; + }; + + /** Download modules from MODULE_URL/.. */ + function fetchGetModule(data, callback) { + var fullModuleName = data.moduleName; + + // try and load the module the old way... + console.log("loadModule("+fullModuleName+")"); + + var urls = []; // Array of where to look for this module + var modName; // Simple name of the module + if(Espruino.Core.Utils.isURL(fullModuleName)) { + modName = fullModuleName.substr(fullModuleName.lastIndexOf("/") + 1).split(".")[0]; + urls = [ fullModuleName ]; + } else { + modName = fullModuleName; + Espruino.Config.MODULE_URL.split("|").forEach(function (url) { + url = url.trim(); + if (url.length!=0) + Espruino.Config.MODULE_EXTENSIONS.split("|").forEach(function (extension) { + urls.push(url + "/" + fullModuleName + extension); + }) + }); + }; + + // Recursively go through all the urls + (function download(urls) { + if (urls.length==0) { + return callback(data); + } + var dlUrl = urls[0]; + Espruino.Core.Utils.getURL(dlUrl, function (code) { + if (code!==undefined) { + // we got it! + data.moduleCode = code; + data.isMinified = dlUrl.substr(-7)==".min.js"; + return callback(data); + } else { + // else try next + download(urls.slice(1)); + } + }); + })(urls); + } + + + /** Called from loadModule when a module is loaded. Parse it for other modules it might use + * and resolve dfd after all submodules have been loaded */ + function moduleLoaded(resolve, requires, modName, data, loadedModuleData, alreadyMinified){ + // Check for any modules used from this module that we don't already have + var newRequires = getModulesRequired(data); + console.log(" - "+modName+" requires "+JSON.stringify(newRequires)); + // if we need new modules, set them to load and get their promises + var newPromises = []; + for (var i in newRequires) { + if (requires.indexOf(newRequires[i])<0) { + console.log(" Queueing "+newRequires[i]); + requires.push(newRequires[i]); + newPromises.push(loadModule(requires, newRequires[i], loadedModuleData)); + } else { + console.log(" Already loading "+newRequires[i]); + } + } + + var loadProcessedModule = function (module) { + // if we needed to load something, wait until it's loaded before resolving this + Promise.all(newPromises).then(function(){ + // add the module to end of our array + if (Espruino.Config.MODULE_AS_FUNCTION) + loadedModuleData.push("Modules.addCached(" + JSON.stringify(module.name) + ",function(){" + module.code + "});"); + else + loadedModuleData.push("Modules.addCached(" + JSON.stringify(module.name) + "," + JSON.stringify(module.code) + ");"); + // We're done + resolve(); + }); + } + if (alreadyMinified) + loadProcessedModule({code:data,name:modName}); + else + Espruino.callProcessor("transformModuleForEspruino", {code:data,name:modName}, loadProcessedModule); + } + + /** Given a module name (which could be a URL), try and find it. Return + * a deferred thingybob which signals when we're done. */ + function loadModule(requires, fullModuleName, loadedModuleData) { + return new Promise(function(resolve, reject) { + // First off, try and find this module using callProcessor + Espruino.callProcessor("getModule", + { moduleName:fullModuleName, moduleCode:undefined, isMinified:false }, + function(data) { + if (data.moduleCode===undefined) { + Espruino.Core.Notifications.warning("Module "+fullModuleName+" not found"); + return resolve(); + } + + // great! it found something. Use it. + moduleLoaded(resolve, requires, fullModuleName, data.moduleCode, loadedModuleData, data.isMinified); + }); + }); + } + + /** Finds instances of 'require' and then ensures that + those modules are loaded into the module cache beforehand + (by inserting the relevant 'addCached' commands into 'code' */ + function loadModules(code, callback){ + var loadedModuleData = []; + var requires = getModulesRequired(code); + if (requires.length == 0) { + // no modules needed - just return + callback(code); + } else { + Espruino.Core.Status.setStatus("Loading modules"); + // Kick off the module loading (each returns a promise) + var promises = requires.map(function (moduleName) { + return loadModule(requires, moduleName, loadedModuleData); + }); + // When all promises are complete + Promise.all(promises).then(function(){ + callback(loadedModuleData.join("\n") + "\n" + code); + }); + } + }; + + + Espruino.Core.Modules = { + init : init + }; +}()); +/** + Copyright 2014 Gordon Williams (gw@pur3.co.uk) + + This Source Code is subject to the terms of the Mozilla Public + License, v2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + ------------------------------------------------------------------ + Board Environment variables (process.env) - queried when board connects + ------------------------------------------------------------------ +**/ +"use strict"; +(function(){ + + var environmentData = {}; + var boardData = {}; + + function init() { + Espruino.Core.Config.add("ENV_ON_CONNECT", { + section : "Communications", + name : "Request board details on connect", + description : 'Just after the board is connected, should we query `process.env` to find out which board we\'re connected to? '+ + 'This enables the Web IDE\'s code completion, compiler features, and firmware update notice.', + type : "boolean", + defaultValue : true, + }); + + Espruino.addProcessor("connected", function(data, callback) { + // Give us some time for any stored data to come in + setTimeout(queryBoardProcess, 200, data, callback); + }); + } + + function queryBoardProcess(data, callback) { + if ((!Espruino.Config.ENV_ON_CONNECT) || + (Espruino.Core.MenuFlasher && Espruino.Core.MenuFlasher.isFlashing())) { + return callback(data); + } + + Espruino.Core.Utils.executeExpression("process.env", function(result) { + var json = {}; + if (result!==undefined) { + try { + json = JSON.parse(result); + } catch (e) { + console.log("JSON parse failed - " + e + " in " + JSON.stringify(result)); + } + } + if (Object.keys(json).length==0) { + Espruino.Core.Notifications.error("Unable to retrieve board information.\nConnection Error?"); + // make sure we don't remember a previous board's info + json = { + VERSION : undefined, + BOARD : undefined, + MODULES : undefined, + EXPTR : undefined + }; + } else { + if (json.BOARD && json.VERSION) + Espruino.Core.Notifications.info("Found " +json.BOARD+", "+json.VERSION); + } + // now process the enviroment variables + for (var k in json) { + boardData[k] = json[k]; + environmentData[k] = json[k]; + } + if (environmentData.VERSION) { + var v = environmentData.VERSION; + var vIdx = v.indexOf("v"); + if (vIdx>=0) { + environmentData.VERSION_MAJOR = parseInt(v.substr(0,vIdx)); + var minor = v.substr(vIdx+1); + var dot = minor.indexOf("."); + if (dot>=0) + environmentData.VERSION_MINOR = parseInt(minor.substr(0,dot)) + parseInt(minor.substr(dot+1))*0.001; + else + environmentData.VERSION_MINOR = parseFloat(minor); + } + } + + Espruino.callProcessor("environmentVar", environmentData, function(envData) { + environmentData = envData; + callback(data); + }); + }); + } + + /** Get all data merged in from the board */ + function getData() { + return environmentData; + } + + /** Get just the board's environment data */ + function getBoardData() { + return boardData; + } + + /** Get a list of boards that we know about */ + function getBoardList(callback) { + var jsonDir = Espruino.Config.BOARD_JSON_URL; + + // ensure jsonDir ends with slash + if (jsonDir.indexOf('/', jsonDir.length - 1) === -1) { + jsonDir += '/'; + } + + Espruino.Core.Utils.getJSONURL(jsonDir + "boards.json", function(boards){ + // now load all the individual JSON files + var promises = []; + for (var boardId in boards) { + promises.push((function() { + var id = boardId; + return new Promise(function(resolve, reject) { + Espruino.Core.Utils.getJSONURL(jsonDir + boards[boardId].json, function (data) { + boards[id]["json"] = data; + resolve(); + }); + }); + })()); + } + + // When all are loaded, load the callback + Promise.all(promises).then(function() { + callback(boards); + }); + }); + } + + Espruino.Core.Env = { + init : init, + getData : getData, + getBoardData : getBoardData, + getBoardList : getBoardList, + }; +}()); +/** + Copyright 2014 Gordon Williams (gw@pur3.co.uk) + + This Source Code is subject to the terms of the Mozilla Public + License, v2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + ------------------------------------------------------------------ + Try and get any URLS that are from GitHub + ------------------------------------------------------------------ +**/ +"use strict"; +(function(){ + + function init() { + Espruino.addProcessor("getURL", getGitHub); + } + + function getGitHub(data, callback) { + var match = data.url.match(/^https?:\/\/github.com\/([^\/]+)\/([^\/]+)\/blob\/([^\/]+)\/(.*)$/); + if (match) { + var git = { + owner : match[1], + repo : match[2], + branch : match[3], + path : match[4] + }; + + var url = "https://raw.githubusercontent.com/"+git.owner+"/"+git.repo+"/"+git.branch+"/"+git.path; + console.log("Found GitHub", JSON.stringify(git)); + callback({url: url}); + } else + callback(data); // no match - continue as normal + } + + Espruino.Plugins.GetGitHub = { + init : init, + }; +}()); +/*! https://mths.be/utf8js v2.0.0 by @mathias */ +;(function(root) { + + // Detect free variables `exports` + var freeExports = typeof exports == 'object' && exports; + + // Detect free variable `module` + var freeModule = typeof module == 'object' && module && + module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, + // and use it as `root` + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var stringFromCharCode = String.fromCharCode; + + // Taken from https://mths.be/punycode + function ucs2decode(string) { + var output = []; + var counter = 0; + var length = string.length; + var value; + var extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + // Taken from https://mths.be/punycode + function ucs2encode(array) { + var length = array.length; + var index = -1; + var value; + var output = ''; + while (++index < length) { + value = array[index]; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + } + return output; + } + + function checkScalarValue(codePoint) { + if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { + throw Error( + 'Lone surrogate U+' + codePoint.toString(16).toUpperCase() + + ' is not a scalar value' + ); + } + } + /*--------------------------------------------------------------------------*/ + + function createByte(codePoint, shift) { + return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80); + } + + function encodeCodePoint(codePoint) { + if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence + return stringFromCharCode(codePoint); + } + var symbol = ''; + if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence + symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0); + } + else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence + checkScalarValue(codePoint); + symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0); + symbol += createByte(codePoint, 6); + } + else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence + symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0); + symbol += createByte(codePoint, 12); + symbol += createByte(codePoint, 6); + } + symbol += stringFromCharCode((codePoint & 0x3F) | 0x80); + return symbol; + } + + function utf8encode(string) { + var codePoints = ucs2decode(string); + var length = codePoints.length; + var index = -1; + var codePoint; + var byteString = ''; + while (++index < length) { + codePoint = codePoints[index]; + byteString += encodeCodePoint(codePoint); + } + return byteString; + } + + /*--------------------------------------------------------------------------*/ + + function readContinuationByte() { + if (byteIndex >= byteCount) { + throw Error('Invalid byte index'); + } + + var continuationByte = byteArray[byteIndex] & 0xFF; + byteIndex++; + + if ((continuationByte & 0xC0) == 0x80) { + return continuationByte & 0x3F; + } + + // If we end up here, it’s not a continuation byte + throw Error('Invalid continuation byte'); + } + + function decodeSymbol() { + var byte1; + var byte2; + var byte3; + var byte4; + var codePoint; + + if (byteIndex > byteCount) { + throw Error('Invalid byte index'); + } + + if (byteIndex == byteCount) { + return false; + } + + // Read first byte + byte1 = byteArray[byteIndex] & 0xFF; + byteIndex++; + + // 1-byte sequence (no continuation bytes) + if ((byte1 & 0x80) == 0) { + return byte1; + } + + // 2-byte sequence + if ((byte1 & 0xE0) == 0xC0) { + var byte2 = readContinuationByte(); + codePoint = ((byte1 & 0x1F) << 6) | byte2; + if (codePoint >= 0x80) { + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 3-byte sequence (may include unpaired surrogates) + if ((byte1 & 0xF0) == 0xE0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3; + if (codePoint >= 0x0800) { + checkScalarValue(codePoint); + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 4-byte sequence + if ((byte1 & 0xF8) == 0xF0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + byte4 = readContinuationByte(); + codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) | + (byte3 << 0x06) | byte4; + if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { + return codePoint; + } + } + + throw Error('Invalid UTF-8 detected'); + } + + var byteArray; + var byteCount; + var byteIndex; + function utf8decode(byteString) { + byteArray = ucs2decode(byteString); + byteCount = byteArray.length; + byteIndex = 0; + var codePoints = []; + var tmp; + while ((tmp = decodeSymbol()) !== false) { + codePoints.push(tmp); + } + return ucs2encode(codePoints); + } + + /*--------------------------------------------------------------------------*/ + + var utf8 = { + 'version': '2.0.0', + 'encode': utf8encode, + 'decode': utf8decode + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define(function() { + return utf8; + }); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = utf8; + } else { // in Narwhal or RingoJS v0.7.0- + var object = {}; + var hasOwnProperty = object.hasOwnProperty; + for (var key in utf8) { + hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]); + } + } + } else { // in Rhino or a web browser + root.utf8 = utf8; + } + +}(this)); +/** + Copyright 2015 Gordon Williams (gw@pur3.co.uk), + Victor Nakoryakov (victor@amperka.ru) + + This Source Code is subject to the terms of the Mozilla Public + License, v2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + ------------------------------------------------------------------ + Escape non-ASCII characters into \xHH UTF-8 sequences before send + ------------------------------------------------------------------ +**/ +"use strict"; +(function(){ + + // Node.js doesn't have utf8 installed + var utf8lib; + if ("undefined"==typeof utf8) { + if ("undefined"!=typeof require) { + console.log("Loading UTF8 with require"); + utf8lib = require('utf8'); + } else { + console.log("WARNING: Loading placeholder UTF8"); + utf8lib = { encode : function(c){return c} }; + } + } else { + console.log("UTF8 Library loaded successfully"); + utf8lib = utf8; + } + + function init() { + Espruino.addProcessor("transformForEspruino", function(code, callback) { + escapeUnicode(code, callback); + }); + } + + function escapeUnicode(code, callback) { + // Only correct unicode inside strings + var newCode = ""; + var lex = Espruino.Core.Utils.getLexer(code); + var lastIdx = 0; + var tok = lex.next(); + while (tok!==undefined) { + var previousString = code.substring(lastIdx, tok.startIdx); + var tokenString = code.substring(tok.startIdx, tok.endIdx); + if (tok.type=="STRING") { + var newTokenString = ""; + for (var i=0;i= 255) + newTokenString += escapeChar(tokenString[i]); + else + newTokenString += tokenString[i]; + } + tokenString = newTokenString; + } + newCode += previousString+tokenString; + // next + lastIdx = tok.endIdx; + tok = lex.next(); + } + newCode += code.substring(lastIdx); + callback(newCode); + } + + function escapeChar(c) { + // encode char into UTF-8 sequence in form of \xHH codes + var result = ''; + utf8lib.encode(c).split('').forEach(function(c) { + var code = c.charCodeAt(0) & 0xFF; + result += "\\x"; + if (code < 0x10) result += '0'; + result += code.toString(16).toUpperCase(); + }); + + return result; + } + + Espruino.Plugins.Unicode = { + init : init, + }; +}()); +(function webpackUniversalModuleDefinition(root, factory) { +/* istanbul ignore next */ + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); +/* istanbul ignore next */ + else if(typeof exports === 'object') + exports["esprima"] = factory(); + else + root["esprima"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/* istanbul ignore if */ +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /* + Copyright JS Foundation and other contributors, https://js.foundation/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + Object.defineProperty(exports, "__esModule", { value: true }); + var comment_handler_1 = __webpack_require__(1); + var jsx_parser_1 = __webpack_require__(3); + var parser_1 = __webpack_require__(8); + var tokenizer_1 = __webpack_require__(15); + function parse(code, options, delegate) { + var commentHandler = null; + var proxyDelegate = function (node, metadata) { + if (delegate) { + delegate(node, metadata); + } + if (commentHandler) { + commentHandler.visit(node, metadata); + } + }; + var parserDelegate = (typeof delegate === 'function') ? proxyDelegate : null; + var collectComment = false; + if (options) { + collectComment = (typeof options.comment === 'boolean' && options.comment); + var attachComment = (typeof options.attachComment === 'boolean' && options.attachComment); + if (collectComment || attachComment) { + commentHandler = new comment_handler_1.CommentHandler(); + commentHandler.attach = attachComment; + options.comment = true; + parserDelegate = proxyDelegate; + } + } + var isModule = false; + if (options && typeof options.sourceType === 'string') { + isModule = (options.sourceType === 'module'); + } + var parser; + if (options && typeof options.jsx === 'boolean' && options.jsx) { + parser = new jsx_parser_1.JSXParser(code, options, parserDelegate); + } + else { + parser = new parser_1.Parser(code, options, parserDelegate); + } + var program = isModule ? parser.parseModule() : parser.parseScript(); + var ast = program; + if (collectComment && commentHandler) { + ast.comments = commentHandler.comments; + } + if (parser.config.tokens) { + ast.tokens = parser.tokens; + } + if (parser.config.tolerant) { + ast.errors = parser.errorHandler.errors; + } + return ast; + } + exports.parse = parse; + function parseModule(code, options, delegate) { + var parsingOptions = options || {}; + parsingOptions.sourceType = 'module'; + return parse(code, parsingOptions, delegate); + } + exports.parseModule = parseModule; + function parseScript(code, options, delegate) { + var parsingOptions = options || {}; + parsingOptions.sourceType = 'script'; + return parse(code, parsingOptions, delegate); + } + exports.parseScript = parseScript; + function tokenize(code, options, delegate) { + var tokenizer = new tokenizer_1.Tokenizer(code, options); + var tokens; + tokens = []; + try { + while (true) { + var token = tokenizer.getNextToken(); + if (!token) { + break; + } + if (delegate) { + token = delegate(token); + } + tokens.push(token); + } + } + catch (e) { + tokenizer.errorHandler.tolerate(e); + } + if (tokenizer.errorHandler.tolerant) { + tokens.errors = tokenizer.errors(); + } + return tokens; + } + exports.tokenize = tokenize; + var syntax_1 = __webpack_require__(2); + exports.Syntax = syntax_1.Syntax; + // Sync with *.json manifests. + exports.version = '4.0.1'; + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var syntax_1 = __webpack_require__(2); + var CommentHandler = (function () { + function CommentHandler() { + this.attach = false; + this.comments = []; + this.stack = []; + this.leading = []; + this.trailing = []; + } + CommentHandler.prototype.insertInnerComments = function (node, metadata) { + // innnerComments for properties empty block + // `function a() {/** comments **\/}` + if (node.type === syntax_1.Syntax.BlockStatement && node.body.length === 0) { + var innerComments = []; + for (var i = this.leading.length - 1; i >= 0; --i) { + var entry = this.leading[i]; + if (metadata.end.offset >= entry.start) { + innerComments.unshift(entry.comment); + this.leading.splice(i, 1); + this.trailing.splice(i, 1); + } + } + if (innerComments.length) { + node.innerComments = innerComments; + } + } + }; + CommentHandler.prototype.findTrailingComments = function (metadata) { + var trailingComments = []; + if (this.trailing.length > 0) { + for (var i = this.trailing.length - 1; i >= 0; --i) { + var entry_1 = this.trailing[i]; + if (entry_1.start >= metadata.end.offset) { + trailingComments.unshift(entry_1.comment); + } + } + this.trailing.length = 0; + return trailingComments; + } + var entry = this.stack[this.stack.length - 1]; + if (entry && entry.node.trailingComments) { + var firstComment = entry.node.trailingComments[0]; + if (firstComment && firstComment.range[0] >= metadata.end.offset) { + trailingComments = entry.node.trailingComments; + delete entry.node.trailingComments; + } + } + return trailingComments; + }; + CommentHandler.prototype.findLeadingComments = function (metadata) { + var leadingComments = []; + var target; + while (this.stack.length > 0) { + var entry = this.stack[this.stack.length - 1]; + if (entry && entry.start >= metadata.start.offset) { + target = entry.node; + this.stack.pop(); + } + else { + break; + } + } + if (target) { + var count = target.leadingComments ? target.leadingComments.length : 0; + for (var i = count - 1; i >= 0; --i) { + var comment = target.leadingComments[i]; + if (comment.range[1] <= metadata.start.offset) { + leadingComments.unshift(comment); + target.leadingComments.splice(i, 1); + } + } + if (target.leadingComments && target.leadingComments.length === 0) { + delete target.leadingComments; + } + return leadingComments; + } + for (var i = this.leading.length - 1; i >= 0; --i) { + var entry = this.leading[i]; + if (entry.start <= metadata.start.offset) { + leadingComments.unshift(entry.comment); + this.leading.splice(i, 1); + } + } + return leadingComments; + }; + CommentHandler.prototype.visitNode = function (node, metadata) { + if (node.type === syntax_1.Syntax.Program && node.body.length > 0) { + return; + } + this.insertInnerComments(node, metadata); + var trailingComments = this.findTrailingComments(metadata); + var leadingComments = this.findLeadingComments(metadata); + if (leadingComments.length > 0) { + node.leadingComments = leadingComments; + } + if (trailingComments.length > 0) { + node.trailingComments = trailingComments; + } + this.stack.push({ + node: node, + start: metadata.start.offset + }); + }; + CommentHandler.prototype.visitComment = function (node, metadata) { + var type = (node.type[0] === 'L') ? 'Line' : 'Block'; + var comment = { + type: type, + value: node.value + }; + if (node.range) { + comment.range = node.range; + } + if (node.loc) { + comment.loc = node.loc; + } + this.comments.push(comment); + if (this.attach) { + var entry = { + comment: { + type: type, + value: node.value, + range: [metadata.start.offset, metadata.end.offset] + }, + start: metadata.start.offset + }; + if (node.loc) { + entry.comment.loc = node.loc; + } + node.type = type; + this.leading.push(entry); + this.trailing.push(entry); + } + }; + CommentHandler.prototype.visit = function (node, metadata) { + if (node.type === 'LineComment') { + this.visitComment(node, metadata); + } + else if (node.type === 'BlockComment') { + this.visitComment(node, metadata); + } + else if (this.attach) { + this.visitNode(node, metadata); + } + }; + return CommentHandler; + }()); + exports.CommentHandler = CommentHandler; + + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.Syntax = { + AssignmentExpression: 'AssignmentExpression', + AssignmentPattern: 'AssignmentPattern', + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + AwaitExpression: 'AwaitExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExportAllDeclaration: 'ExportAllDeclaration', + ExportDefaultDeclaration: 'ExportDefaultDeclaration', + ExportNamedDeclaration: 'ExportNamedDeclaration', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForOfStatement: 'ForOfStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', + ImportSpecifier: 'ImportSpecifier', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MetaProperty: 'MetaProperty', + MethodDefinition: 'MethodDefinition', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + RestElement: 'RestElement', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + Super: 'Super', + SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + YieldExpression: 'YieldExpression' + }; + + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; +/* istanbul ignore next */ + var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + Object.defineProperty(exports, "__esModule", { value: true }); + var character_1 = __webpack_require__(4); + var JSXNode = __webpack_require__(5); + var jsx_syntax_1 = __webpack_require__(6); + var Node = __webpack_require__(7); + var parser_1 = __webpack_require__(8); + var token_1 = __webpack_require__(13); + var xhtml_entities_1 = __webpack_require__(14); + token_1.TokenName[100 /* Identifier */] = 'JSXIdentifier'; + token_1.TokenName[101 /* Text */] = 'JSXText'; + // Fully qualified element name, e.g. returns "svg:path" + function getQualifiedElementName(elementName) { + var qualifiedName; + switch (elementName.type) { + case jsx_syntax_1.JSXSyntax.JSXIdentifier: + var id = elementName; + qualifiedName = id.name; + break; + case jsx_syntax_1.JSXSyntax.JSXNamespacedName: + var ns = elementName; + qualifiedName = getQualifiedElementName(ns.namespace) + ':' + + getQualifiedElementName(ns.name); + break; + case jsx_syntax_1.JSXSyntax.JSXMemberExpression: + var expr = elementName; + qualifiedName = getQualifiedElementName(expr.object) + '.' + + getQualifiedElementName(expr.property); + break; + /* istanbul ignore next */ + default: + break; + } + return qualifiedName; + } + var JSXParser = (function (_super) { + __extends(JSXParser, _super); + function JSXParser(code, options, delegate) { + return _super.call(this, code, options, delegate) || this; + } + JSXParser.prototype.parsePrimaryExpression = function () { + return this.match('<') ? this.parseJSXRoot() : _super.prototype.parsePrimaryExpression.call(this); + }; + JSXParser.prototype.startJSX = function () { + // Unwind the scanner before the lookahead token. + this.scanner.index = this.startMarker.index; + this.scanner.lineNumber = this.startMarker.line; + this.scanner.lineStart = this.startMarker.index - this.startMarker.column; + }; + JSXParser.prototype.finishJSX = function () { + // Prime the next lookahead. + this.nextToken(); + }; + JSXParser.prototype.reenterJSX = function () { + this.startJSX(); + this.expectJSX('}'); + // Pop the closing '}' added from the lookahead. + if (this.config.tokens) { + this.tokens.pop(); + } + }; + JSXParser.prototype.createJSXNode = function () { + this.collectComments(); + return { + index: this.scanner.index, + line: this.scanner.lineNumber, + column: this.scanner.index - this.scanner.lineStart + }; + }; + JSXParser.prototype.createJSXChildNode = function () { + return { + index: this.scanner.index, + line: this.scanner.lineNumber, + column: this.scanner.index - this.scanner.lineStart + }; + }; + JSXParser.prototype.scanXHTMLEntity = function (quote) { + var result = '&'; + var valid = true; + var terminated = false; + var numeric = false; + var hex = false; + while (!this.scanner.eof() && valid && !terminated) { + var ch = this.scanner.source[this.scanner.index]; + if (ch === quote) { + break; + } + terminated = (ch === ';'); + result += ch; + ++this.scanner.index; + if (!terminated) { + switch (result.length) { + case 2: + // e.g. '{' + numeric = (ch === '#'); + break; + case 3: + if (numeric) { + // e.g. 'A' + hex = (ch === 'x'); + valid = hex || character_1.Character.isDecimalDigit(ch.charCodeAt(0)); + numeric = numeric && !hex; + } + break; + default: + valid = valid && !(numeric && !character_1.Character.isDecimalDigit(ch.charCodeAt(0))); + valid = valid && !(hex && !character_1.Character.isHexDigit(ch.charCodeAt(0))); + break; + } + } + } + if (valid && terminated && result.length > 2) { + // e.g. 'A' becomes just '#x41' + var str = result.substr(1, result.length - 2); + if (numeric && str.length > 1) { + result = String.fromCharCode(parseInt(str.substr(1), 10)); + } + else if (hex && str.length > 2) { + result = String.fromCharCode(parseInt('0' + str.substr(1), 16)); + } + else if (!numeric && !hex && xhtml_entities_1.XHTMLEntities[str]) { + result = xhtml_entities_1.XHTMLEntities[str]; + } + } + return result; + }; + // Scan the next JSX token. This replaces Scanner#lex when in JSX mode. + JSXParser.prototype.lexJSX = function () { + var cp = this.scanner.source.charCodeAt(this.scanner.index); + // < > / : = { } + if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) { + var value = this.scanner.source[this.scanner.index++]; + return { + type: 7 /* Punctuator */, + value: value, + lineNumber: this.scanner.lineNumber, + lineStart: this.scanner.lineStart, + start: this.scanner.index - 1, + end: this.scanner.index + }; + } + // " ' + if (cp === 34 || cp === 39) { + var start = this.scanner.index; + var quote = this.scanner.source[this.scanner.index++]; + var str = ''; + while (!this.scanner.eof()) { + var ch = this.scanner.source[this.scanner.index++]; + if (ch === quote) { + break; + } + else if (ch === '&') { + str += this.scanXHTMLEntity(quote); + } + else { + str += ch; + } + } + return { + type: 8 /* StringLiteral */, + value: str, + lineNumber: this.scanner.lineNumber, + lineStart: this.scanner.lineStart, + start: start, + end: this.scanner.index + }; + } + // ... or . + if (cp === 46) { + var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1); + var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2); + var value = (n1 === 46 && n2 === 46) ? '...' : '.'; + var start = this.scanner.index; + this.scanner.index += value.length; + return { + type: 7 /* Punctuator */, + value: value, + lineNumber: this.scanner.lineNumber, + lineStart: this.scanner.lineStart, + start: start, + end: this.scanner.index + }; + } + // ` + if (cp === 96) { + // Only placeholder, since it will be rescanned as a real assignment expression. + return { + type: 10 /* Template */, + value: '', + lineNumber: this.scanner.lineNumber, + lineStart: this.scanner.lineStart, + start: this.scanner.index, + end: this.scanner.index + }; + } + // Identifer can not contain backslash (char code 92). + if (character_1.Character.isIdentifierStart(cp) && (cp !== 92)) { + var start = this.scanner.index; + ++this.scanner.index; + while (!this.scanner.eof()) { + var ch = this.scanner.source.charCodeAt(this.scanner.index); + if (character_1.Character.isIdentifierPart(ch) && (ch !== 92)) { + ++this.scanner.index; + } + else if (ch === 45) { + // Hyphen (char code 45) can be part of an identifier. + ++this.scanner.index; + } + else { + break; + } + } + var id = this.scanner.source.slice(start, this.scanner.index); + return { + type: 100 /* Identifier */, + value: id, + lineNumber: this.scanner.lineNumber, + lineStart: this.scanner.lineStart, + start: start, + end: this.scanner.index + }; + } + return this.scanner.lex(); + }; + JSXParser.prototype.nextJSXToken = function () { + this.collectComments(); + this.startMarker.index = this.scanner.index; + this.startMarker.line = this.scanner.lineNumber; + this.startMarker.column = this.scanner.index - this.scanner.lineStart; + var token = this.lexJSX(); + this.lastMarker.index = this.scanner.index; + this.lastMarker.line = this.scanner.lineNumber; + this.lastMarker.column = this.scanner.index - this.scanner.lineStart; + if (this.config.tokens) { + this.tokens.push(this.convertToken(token)); + } + return token; + }; + JSXParser.prototype.nextJSXText = function () { + this.startMarker.index = this.scanner.index; + this.startMarker.line = this.scanner.lineNumber; + this.startMarker.column = this.scanner.index - this.scanner.lineStart; + var start = this.scanner.index; + var text = ''; + while (!this.scanner.eof()) { + var ch = this.scanner.source[this.scanner.index]; + if (ch === '{' || ch === '<') { + break; + } + ++this.scanner.index; + text += ch; + if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { + ++this.scanner.lineNumber; + if (ch === '\r' && this.scanner.source[this.scanner.index] === '\n') { + ++this.scanner.index; + } + this.scanner.lineStart = this.scanner.index; + } + } + this.lastMarker.index = this.scanner.index; + this.lastMarker.line = this.scanner.lineNumber; + this.lastMarker.column = this.scanner.index - this.scanner.lineStart; + var token = { + type: 101 /* Text */, + value: text, + lineNumber: this.scanner.lineNumber, + lineStart: this.scanner.lineStart, + start: start, + end: this.scanner.index + }; + if ((text.length > 0) && this.config.tokens) { + this.tokens.push(this.convertToken(token)); + } + return token; + }; + JSXParser.prototype.peekJSXToken = function () { + var state = this.scanner.saveState(); + this.scanner.scanComments(); + var next = this.lexJSX(); + this.scanner.restoreState(state); + return next; + }; + // Expect the next JSX token to match the specified punctuator. + // If not, an exception will be thrown. + JSXParser.prototype.expectJSX = function (value) { + var token = this.nextJSXToken(); + if (token.type !== 7 /* Punctuator */ || token.value !== value) { + this.throwUnexpectedToken(token); + } + }; + // Return true if the next JSX token matches the specified punctuator. + JSXParser.prototype.matchJSX = function (value) { + var next = this.peekJSXToken(); + return next.type === 7 /* Punctuator */ && next.value === value; + }; + JSXParser.prototype.parseJSXIdentifier = function () { + var node = this.createJSXNode(); + var token = this.nextJSXToken(); + if (token.type !== 100 /* Identifier */) { + this.throwUnexpectedToken(token); + } + return this.finalize(node, new JSXNode.JSXIdentifier(token.value)); + }; + JSXParser.prototype.parseJSXElementName = function () { + var node = this.createJSXNode(); + var elementName = this.parseJSXIdentifier(); + if (this.matchJSX(':')) { + var namespace = elementName; + this.expectJSX(':'); + var name_1 = this.parseJSXIdentifier(); + elementName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_1)); + } + else if (this.matchJSX('.')) { + while (this.matchJSX('.')) { + var object = elementName; + this.expectJSX('.'); + var property = this.parseJSXIdentifier(); + elementName = this.finalize(node, new JSXNode.JSXMemberExpression(object, property)); + } + } + return elementName; + }; + JSXParser.prototype.parseJSXAttributeName = function () { + var node = this.createJSXNode(); + var attributeName; + var identifier = this.parseJSXIdentifier(); + if (this.matchJSX(':')) { + var namespace = identifier; + this.expectJSX(':'); + var name_2 = this.parseJSXIdentifier(); + attributeName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_2)); + } + else { + attributeName = identifier; + } + return attributeName; + }; + JSXParser.prototype.parseJSXStringLiteralAttribute = function () { + var node = this.createJSXNode(); + var token = this.nextJSXToken(); + if (token.type !== 8 /* StringLiteral */) { + this.throwUnexpectedToken(token); + } + var raw = this.getTokenRaw(token); + return this.finalize(node, new Node.Literal(token.value, raw)); + }; + JSXParser.prototype.parseJSXExpressionAttribute = function () { + var node = this.createJSXNode(); + this.expectJSX('{'); + this.finishJSX(); + if (this.match('}')) { + this.tolerateError('JSX attributes must only be assigned a non-empty expression'); + } + var expression = this.parseAssignmentExpression(); + this.reenterJSX(); + return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); + }; + JSXParser.prototype.parseJSXAttributeValue = function () { + return this.matchJSX('{') ? this.parseJSXExpressionAttribute() : + this.matchJSX('<') ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute(); + }; + JSXParser.prototype.parseJSXNameValueAttribute = function () { + var node = this.createJSXNode(); + var name = this.parseJSXAttributeName(); + var value = null; + if (this.matchJSX('=')) { + this.expectJSX('='); + value = this.parseJSXAttributeValue(); + } + return this.finalize(node, new JSXNode.JSXAttribute(name, value)); + }; + JSXParser.prototype.parseJSXSpreadAttribute = function () { + var node = this.createJSXNode(); + this.expectJSX('{'); + this.expectJSX('...'); + this.finishJSX(); + var argument = this.parseAssignmentExpression(); + this.reenterJSX(); + return this.finalize(node, new JSXNode.JSXSpreadAttribute(argument)); + }; + JSXParser.prototype.parseJSXAttributes = function () { + var attributes = []; + while (!this.matchJSX('/') && !this.matchJSX('>')) { + var attribute = this.matchJSX('{') ? this.parseJSXSpreadAttribute() : + this.parseJSXNameValueAttribute(); + attributes.push(attribute); + } + return attributes; + }; + JSXParser.prototype.parseJSXOpeningElement = function () { + var node = this.createJSXNode(); + this.expectJSX('<'); + var name = this.parseJSXElementName(); + var attributes = this.parseJSXAttributes(); + var selfClosing = this.matchJSX('/'); + if (selfClosing) { + this.expectJSX('/'); + } + this.expectJSX('>'); + return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); + }; + JSXParser.prototype.parseJSXBoundaryElement = function () { + var node = this.createJSXNode(); + this.expectJSX('<'); + if (this.matchJSX('/')) { + this.expectJSX('/'); + var name_3 = this.parseJSXElementName(); + this.expectJSX('>'); + return this.finalize(node, new JSXNode.JSXClosingElement(name_3)); + } + var name = this.parseJSXElementName(); + var attributes = this.parseJSXAttributes(); + var selfClosing = this.matchJSX('/'); + if (selfClosing) { + this.expectJSX('/'); + } + this.expectJSX('>'); + return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); + }; + JSXParser.prototype.parseJSXEmptyExpression = function () { + var node = this.createJSXChildNode(); + this.collectComments(); + this.lastMarker.index = this.scanner.index; + this.lastMarker.line = this.scanner.lineNumber; + this.lastMarker.column = this.scanner.index - this.scanner.lineStart; + return this.finalize(node, new JSXNode.JSXEmptyExpression()); + }; + JSXParser.prototype.parseJSXExpressionContainer = function () { + var node = this.createJSXNode(); + this.expectJSX('{'); + var expression; + if (this.matchJSX('}')) { + expression = this.parseJSXEmptyExpression(); + this.expectJSX('}'); + } + else { + this.finishJSX(); + expression = this.parseAssignmentExpression(); + this.reenterJSX(); + } + return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); + }; + JSXParser.prototype.parseJSXChildren = function () { + var children = []; + while (!this.scanner.eof()) { + var node = this.createJSXChildNode(); + var token = this.nextJSXText(); + if (token.start < token.end) { + var raw = this.getTokenRaw(token); + var child = this.finalize(node, new JSXNode.JSXText(token.value, raw)); + children.push(child); + } + if (this.scanner.source[this.scanner.index] === '{') { + var container = this.parseJSXExpressionContainer(); + children.push(container); + } + else { + break; + } + } + return children; + }; + JSXParser.prototype.parseComplexJSXElement = function (el) { + var stack = []; + while (!this.scanner.eof()) { + el.children = el.children.concat(this.parseJSXChildren()); + var node = this.createJSXChildNode(); + var element = this.parseJSXBoundaryElement(); + if (element.type === jsx_syntax_1.JSXSyntax.JSXOpeningElement) { + var opening = element; + if (opening.selfClosing) { + var child = this.finalize(node, new JSXNode.JSXElement(opening, [], null)); + el.children.push(child); + } + else { + stack.push(el); + el = { node: node, opening: opening, closing: null, children: [] }; + } + } + if (element.type === jsx_syntax_1.JSXSyntax.JSXClosingElement) { + el.closing = element; + var open_1 = getQualifiedElementName(el.opening.name); + var close_1 = getQualifiedElementName(el.closing.name); + if (open_1 !== close_1) { + this.tolerateError('Expected corresponding JSX closing tag for %0', open_1); + } + if (stack.length > 0) { + var child = this.finalize(el.node, new JSXNode.JSXElement(el.opening, el.children, el.closing)); + el = stack[stack.length - 1]; + el.children.push(child); + stack.pop(); + } + else { + break; + } + } + } + return el; + }; + JSXParser.prototype.parseJSXElement = function () { + var node = this.createJSXNode(); + var opening = this.parseJSXOpeningElement(); + var children = []; + var closing = null; + if (!opening.selfClosing) { + var el = this.parseComplexJSXElement({ node: node, opening: opening, closing: closing, children: children }); + children = el.children; + closing = el.closing; + } + return this.finalize(node, new JSXNode.JSXElement(opening, children, closing)); + }; + JSXParser.prototype.parseJSXRoot = function () { + // Pop the opening '<' added from the lookahead. + if (this.config.tokens) { + this.tokens.pop(); + } + this.startJSX(); + var element = this.parseJSXElement(); + this.finishJSX(); + return element; + }; + JSXParser.prototype.isStartOfExpression = function () { + return _super.prototype.isStartOfExpression.call(this) || this.match('<'); + }; + return JSXParser; + }(parser_1.Parser)); + exports.JSXParser = JSXParser; + + +/***/ }, +/* 4 */ +/***/ function(module, exports) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + // See also tools/generate-unicode-regex.js. + var Regex = { + // Unicode v8.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/, + // Unicode v8.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ + }; + exports.Character = { + /* tslint:disable:no-bitwise */ + fromCodePoint: function (cp) { + return (cp < 0x10000) ? String.fromCharCode(cp) : + String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + + String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); + }, + // https://tc39.github.io/ecma262/#sec-white-space + isWhiteSpace: function (cp) { + return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) || + (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0); + }, + // https://tc39.github.io/ecma262/#sec-line-terminators + isLineTerminator: function (cp) { + return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029); + }, + // https://tc39.github.io/ecma262/#sec-names-and-keywords + isIdentifierStart: function (cp) { + return (cp === 0x24) || (cp === 0x5F) || + (cp >= 0x41 && cp <= 0x5A) || + (cp >= 0x61 && cp <= 0x7A) || + (cp === 0x5C) || + ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(exports.Character.fromCodePoint(cp))); + }, + isIdentifierPart: function (cp) { + return (cp === 0x24) || (cp === 0x5F) || + (cp >= 0x41 && cp <= 0x5A) || + (cp >= 0x61 && cp <= 0x7A) || + (cp >= 0x30 && cp <= 0x39) || + (cp === 0x5C) || + ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(exports.Character.fromCodePoint(cp))); + }, + // https://tc39.github.io/ecma262/#sec-literals-numeric-literals + isDecimalDigit: function (cp) { + return (cp >= 0x30 && cp <= 0x39); // 0..9 + }, + isHexDigit: function (cp) { + return (cp >= 0x30 && cp <= 0x39) || + (cp >= 0x41 && cp <= 0x46) || + (cp >= 0x61 && cp <= 0x66); // a..f + }, + isOctalDigit: function (cp) { + return (cp >= 0x30 && cp <= 0x37); // 0..7 + } + }; + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var jsx_syntax_1 = __webpack_require__(6); + /* tslint:disable:max-classes-per-file */ + var JSXClosingElement = (function () { + function JSXClosingElement(name) { + this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement; + this.name = name; + } + return JSXClosingElement; + }()); + exports.JSXClosingElement = JSXClosingElement; + var JSXElement = (function () { + function JSXElement(openingElement, children, closingElement) { + this.type = jsx_syntax_1.JSXSyntax.JSXElement; + this.openingElement = openingElement; + this.children = children; + this.closingElement = closingElement; + } + return JSXElement; + }()); + exports.JSXElement = JSXElement; + var JSXEmptyExpression = (function () { + function JSXEmptyExpression() { + this.type = jsx_syntax_1.JSXSyntax.JSXEmptyExpression; + } + return JSXEmptyExpression; + }()); + exports.JSXEmptyExpression = JSXEmptyExpression; + var JSXExpressionContainer = (function () { + function JSXExpressionContainer(expression) { + this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer; + this.expression = expression; + } + return JSXExpressionContainer; + }()); + exports.JSXExpressionContainer = JSXExpressionContainer; + var JSXIdentifier = (function () { + function JSXIdentifier(name) { + this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier; + this.name = name; + } + return JSXIdentifier; + }()); + exports.JSXIdentifier = JSXIdentifier; + var JSXMemberExpression = (function () { + function JSXMemberExpression(object, property) { + this.type = jsx_syntax_1.JSXSyntax.JSXMemberExpression; + this.object = object; + this.property = property; + } + return JSXMemberExpression; + }()); + exports.JSXMemberExpression = JSXMemberExpression; + var JSXAttribute = (function () { + function JSXAttribute(name, value) { + this.type = jsx_syntax_1.JSXSyntax.JSXAttribute; + this.name = name; + this.value = value; + } + return JSXAttribute; + }()); + exports.JSXAttribute = JSXAttribute; + var JSXNamespacedName = (function () { + function JSXNamespacedName(namespace, name) { + this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName; + this.namespace = namespace; + this.name = name; + } + return JSXNamespacedName; + }()); + exports.JSXNamespacedName = JSXNamespacedName; + var JSXOpeningElement = (function () { + function JSXOpeningElement(name, selfClosing, attributes) { + this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement; + this.name = name; + this.selfClosing = selfClosing; + this.attributes = attributes; + } + return JSXOpeningElement; + }()); + exports.JSXOpeningElement = JSXOpeningElement; + var JSXSpreadAttribute = (function () { + function JSXSpreadAttribute(argument) { + this.type = jsx_syntax_1.JSXSyntax.JSXSpreadAttribute; + this.argument = argument; + } + return JSXSpreadAttribute; + }()); + exports.JSXSpreadAttribute = JSXSpreadAttribute; + var JSXText = (function () { + function JSXText(value, raw) { + this.type = jsx_syntax_1.JSXSyntax.JSXText; + this.value = value; + this.raw = raw; + } + return JSXText; + }()); + exports.JSXText = JSXText; + + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.JSXSyntax = { + JSXAttribute: 'JSXAttribute', + JSXClosingElement: 'JSXClosingElement', + JSXElement: 'JSXElement', + JSXEmptyExpression: 'JSXEmptyExpression', + JSXExpressionContainer: 'JSXExpressionContainer', + JSXIdentifier: 'JSXIdentifier', + JSXMemberExpression: 'JSXMemberExpression', + JSXNamespacedName: 'JSXNamespacedName', + JSXOpeningElement: 'JSXOpeningElement', + JSXSpreadAttribute: 'JSXSpreadAttribute', + JSXText: 'JSXText' + }; + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var syntax_1 = __webpack_require__(2); + /* tslint:disable:max-classes-per-file */ + var ArrayExpression = (function () { + function ArrayExpression(elements) { + this.type = syntax_1.Syntax.ArrayExpression; + this.elements = elements; + } + return ArrayExpression; + }()); + exports.ArrayExpression = ArrayExpression; + var ArrayPattern = (function () { + function ArrayPattern(elements) { + this.type = syntax_1.Syntax.ArrayPattern; + this.elements = elements; + } + return ArrayPattern; + }()); + exports.ArrayPattern = ArrayPattern; + var ArrowFunctionExpression = (function () { + function ArrowFunctionExpression(params, body, expression) { + this.type = syntax_1.Syntax.ArrowFunctionExpression; + this.id = null; + this.params = params; + this.body = body; + this.generator = false; + this.expression = expression; + this.async = false; + } + return ArrowFunctionExpression; + }()); + exports.ArrowFunctionExpression = ArrowFunctionExpression; + var AssignmentExpression = (function () { + function AssignmentExpression(operator, left, right) { + this.type = syntax_1.Syntax.AssignmentExpression; + this.operator = operator; + this.left = left; + this.right = right; + } + return AssignmentExpression; + }()); + exports.AssignmentExpression = AssignmentExpression; + var AssignmentPattern = (function () { + function AssignmentPattern(left, right) { + this.type = syntax_1.Syntax.AssignmentPattern; + this.left = left; + this.right = right; + } + return AssignmentPattern; + }()); + exports.AssignmentPattern = AssignmentPattern; + var AsyncArrowFunctionExpression = (function () { + function AsyncArrowFunctionExpression(params, body, expression) { + this.type = syntax_1.Syntax.ArrowFunctionExpression; + this.id = null; + this.params = params; + this.body = body; + this.generator = false; + this.expression = expression; + this.async = true; + } + return AsyncArrowFunctionExpression; + }()); + exports.AsyncArrowFunctionExpression = AsyncArrowFunctionExpression; + var AsyncFunctionDeclaration = (function () { + function AsyncFunctionDeclaration(id, params, body) { + this.type = syntax_1.Syntax.FunctionDeclaration; + this.id = id; + this.params = params; + this.body = body; + this.generator = false; + this.expression = false; + this.async = true; + } + return AsyncFunctionDeclaration; + }()); + exports.AsyncFunctionDeclaration = AsyncFunctionDeclaration; + var AsyncFunctionExpression = (function () { + function AsyncFunctionExpression(id, params, body) { + this.type = syntax_1.Syntax.FunctionExpression; + this.id = id; + this.params = params; + this.body = body; + this.generator = false; + this.expression = false; + this.async = true; + } + return AsyncFunctionExpression; + }()); + exports.AsyncFunctionExpression = AsyncFunctionExpression; + var AwaitExpression = (function () { + function AwaitExpression(argument) { + this.type = syntax_1.Syntax.AwaitExpression; + this.argument = argument; + } + return AwaitExpression; + }()); + exports.AwaitExpression = AwaitExpression; + var BinaryExpression = (function () { + function BinaryExpression(operator, left, right) { + var logical = (operator === '||' || operator === '&&'); + this.type = logical ? syntax_1.Syntax.LogicalExpression : syntax_1.Syntax.BinaryExpression; + this.operator = operator; + this.left = left; + this.right = right; + } + return BinaryExpression; + }()); + exports.BinaryExpression = BinaryExpression; + var BlockStatement = (function () { + function BlockStatement(body) { + this.type = syntax_1.Syntax.BlockStatement; + this.body = body; + } + return BlockStatement; + }()); + exports.BlockStatement = BlockStatement; + var BreakStatement = (function () { + function BreakStatement(label) { + this.type = syntax_1.Syntax.BreakStatement; + this.label = label; + } + return BreakStatement; + }()); + exports.BreakStatement = BreakStatement; + var CallExpression = (function () { + function CallExpression(callee, args) { + this.type = syntax_1.Syntax.CallExpression; + this.callee = callee; + this.arguments = args; + } + return CallExpression; + }()); + exports.CallExpression = CallExpression; + var CatchClause = (function () { + function CatchClause(param, body) { + this.type = syntax_1.Syntax.CatchClause; + this.param = param; + this.body = body; + } + return CatchClause; + }()); + exports.CatchClause = CatchClause; + var ClassBody = (function () { + function ClassBody(body) { + this.type = syntax_1.Syntax.ClassBody; + this.body = body; + } + return ClassBody; + }()); + exports.ClassBody = ClassBody; + var ClassDeclaration = (function () { + function ClassDeclaration(id, superClass, body) { + this.type = syntax_1.Syntax.ClassDeclaration; + this.id = id; + this.superClass = superClass; + this.body = body; + } + return ClassDeclaration; + }()); + exports.ClassDeclaration = ClassDeclaration; + var ClassExpression = (function () { + function ClassExpression(id, superClass, body) { + this.type = syntax_1.Syntax.ClassExpression; + this.id = id; + this.superClass = superClass; + this.body = body; + } + return ClassExpression; + }()); + exports.ClassExpression = ClassExpression; + var ComputedMemberExpression = (function () { + function ComputedMemberExpression(object, property) { + this.type = syntax_1.Syntax.MemberExpression; + this.computed = true; + this.object = object; + this.property = property; + } + return ComputedMemberExpression; + }()); + exports.ComputedMemberExpression = ComputedMemberExpression; + var ConditionalExpression = (function () { + function ConditionalExpression(test, consequent, alternate) { + this.type = syntax_1.Syntax.ConditionalExpression; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + } + return ConditionalExpression; + }()); + exports.ConditionalExpression = ConditionalExpression; + var ContinueStatement = (function () { + function ContinueStatement(label) { + this.type = syntax_1.Syntax.ContinueStatement; + this.label = label; + } + return ContinueStatement; + }()); + exports.ContinueStatement = ContinueStatement; + var DebuggerStatement = (function () { + function DebuggerStatement() { + this.type = syntax_1.Syntax.DebuggerStatement; + } + return DebuggerStatement; + }()); + exports.DebuggerStatement = DebuggerStatement; + var Directive = (function () { + function Directive(expression, directive) { + this.type = syntax_1.Syntax.ExpressionStatement; + this.expression = expression; + this.directive = directive; + } + return Directive; + }()); + exports.Directive = Directive; + var DoWhileStatement = (function () { + function DoWhileStatement(body, test) { + this.type = syntax_1.Syntax.DoWhileStatement; + this.body = body; + this.test = test; + } + return DoWhileStatement; + }()); + exports.DoWhileStatement = DoWhileStatement; + var EmptyStatement = (function () { + function EmptyStatement() { + this.type = syntax_1.Syntax.EmptyStatement; + } + return EmptyStatement; + }()); + exports.EmptyStatement = EmptyStatement; + var ExportAllDeclaration = (function () { + function ExportAllDeclaration(source) { + this.type = syntax_1.Syntax.ExportAllDeclaration; + this.source = source; + } + return ExportAllDeclaration; + }()); + exports.ExportAllDeclaration = ExportAllDeclaration; + var ExportDefaultDeclaration = (function () { + function ExportDefaultDeclaration(declaration) { + this.type = syntax_1.Syntax.ExportDefaultDeclaration; + this.declaration = declaration; + } + return ExportDefaultDeclaration; + }()); + exports.ExportDefaultDeclaration = ExportDefaultDeclaration; + var ExportNamedDeclaration = (function () { + function ExportNamedDeclaration(declaration, specifiers, source) { + this.type = syntax_1.Syntax.ExportNamedDeclaration; + this.declaration = declaration; + this.specifiers = specifiers; + this.source = source; + } + return ExportNamedDeclaration; + }()); + exports.ExportNamedDeclaration = ExportNamedDeclaration; + var ExportSpecifier = (function () { + function ExportSpecifier(local, exported) { + this.type = syntax_1.Syntax.ExportSpecifier; + this.exported = exported; + this.local = local; + } + return ExportSpecifier; + }()); + exports.ExportSpecifier = ExportSpecifier; + var ExpressionStatement = (function () { + function ExpressionStatement(expression) { + this.type = syntax_1.Syntax.ExpressionStatement; + this.expression = expression; + } + return ExpressionStatement; + }()); + exports.ExpressionStatement = ExpressionStatement; + var ForInStatement = (function () { + function ForInStatement(left, right, body) { + this.type = syntax_1.Syntax.ForInStatement; + this.left = left; + this.right = right; + this.body = body; + this.each = false; + } + return ForInStatement; + }()); + exports.ForInStatement = ForInStatement; + var ForOfStatement = (function () { + function ForOfStatement(left, right, body) { + this.type = syntax_1.Syntax.ForOfStatement; + this.left = left; + this.right = right; + this.body = body; + } + return ForOfStatement; + }()); + exports.ForOfStatement = ForOfStatement; + var ForStatement = (function () { + function ForStatement(init, test, update, body) { + this.type = syntax_1.Syntax.ForStatement; + this.init = init; + this.test = test; + this.update = update; + this.body = body; + } + return ForStatement; + }()); + exports.ForStatement = ForStatement; + var FunctionDeclaration = (function () { + function FunctionDeclaration(id, params, body, generator) { + this.type = syntax_1.Syntax.FunctionDeclaration; + this.id = id; + this.params = params; + this.body = body; + this.generator = generator; + this.expression = false; + this.async = false; + } + return FunctionDeclaration; + }()); + exports.FunctionDeclaration = FunctionDeclaration; + var FunctionExpression = (function () { + function FunctionExpression(id, params, body, generator) { + this.type = syntax_1.Syntax.FunctionExpression; + this.id = id; + this.params = params; + this.body = body; + this.generator = generator; + this.expression = false; + this.async = false; + } + return FunctionExpression; + }()); + exports.FunctionExpression = FunctionExpression; + var Identifier = (function () { + function Identifier(name) { + this.type = syntax_1.Syntax.Identifier; + this.name = name; + } + return Identifier; + }()); + exports.Identifier = Identifier; + var IfStatement = (function () { + function IfStatement(test, consequent, alternate) { + this.type = syntax_1.Syntax.IfStatement; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + } + return IfStatement; + }()); + exports.IfStatement = IfStatement; + var ImportDeclaration = (function () { + function ImportDeclaration(specifiers, source) { + this.type = syntax_1.Syntax.ImportDeclaration; + this.specifiers = specifiers; + this.source = source; + } + return ImportDeclaration; + }()); + exports.ImportDeclaration = ImportDeclaration; + var ImportDefaultSpecifier = (function () { + function ImportDefaultSpecifier(local) { + this.type = syntax_1.Syntax.ImportDefaultSpecifier; + this.local = local; + } + return ImportDefaultSpecifier; + }()); + exports.ImportDefaultSpecifier = ImportDefaultSpecifier; + var ImportNamespaceSpecifier = (function () { + function ImportNamespaceSpecifier(local) { + this.type = syntax_1.Syntax.ImportNamespaceSpecifier; + this.local = local; + } + return ImportNamespaceSpecifier; + }()); + exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier; + var ImportSpecifier = (function () { + function ImportSpecifier(local, imported) { + this.type = syntax_1.Syntax.ImportSpecifier; + this.local = local; + this.imported = imported; + } + return ImportSpecifier; + }()); + exports.ImportSpecifier = ImportSpecifier; + var LabeledStatement = (function () { + function LabeledStatement(label, body) { + this.type = syntax_1.Syntax.LabeledStatement; + this.label = label; + this.body = body; + } + return LabeledStatement; + }()); + exports.LabeledStatement = LabeledStatement; + var Literal = (function () { + function Literal(value, raw) { + this.type = syntax_1.Syntax.Literal; + this.value = value; + this.raw = raw; + } + return Literal; + }()); + exports.Literal = Literal; + var MetaProperty = (function () { + function MetaProperty(meta, property) { + this.type = syntax_1.Syntax.MetaProperty; + this.meta = meta; + this.property = property; + } + return MetaProperty; + }()); + exports.MetaProperty = MetaProperty; + var MethodDefinition = (function () { + function MethodDefinition(key, computed, value, kind, isStatic) { + this.type = syntax_1.Syntax.MethodDefinition; + this.key = key; + this.computed = computed; + this.value = value; + this.kind = kind; + this.static = isStatic; + } + return MethodDefinition; + }()); + exports.MethodDefinition = MethodDefinition; + var Module = (function () { + function Module(body) { + this.type = syntax_1.Syntax.Program; + this.body = body; + this.sourceType = 'module'; + } + return Module; + }()); + exports.Module = Module; + var NewExpression = (function () { + function NewExpression(callee, args) { + this.type = syntax_1.Syntax.NewExpression; + this.callee = callee; + this.arguments = args; + } + return NewExpression; + }()); + exports.NewExpression = NewExpression; + var ObjectExpression = (function () { + function ObjectExpression(properties) { + this.type = syntax_1.Syntax.ObjectExpression; + this.properties = properties; + } + return ObjectExpression; + }()); + exports.ObjectExpression = ObjectExpression; + var ObjectPattern = (function () { + function ObjectPattern(properties) { + this.type = syntax_1.Syntax.ObjectPattern; + this.properties = properties; + } + return ObjectPattern; + }()); + exports.ObjectPattern = ObjectPattern; + var Property = (function () { + function Property(kind, key, computed, value, method, shorthand) { + this.type = syntax_1.Syntax.Property; + this.key = key; + this.computed = computed; + this.value = value; + this.kind = kind; + this.method = method; + this.shorthand = shorthand; + } + return Property; + }()); + exports.Property = Property; + var RegexLiteral = (function () { + function RegexLiteral(value, raw, pattern, flags) { + this.type = syntax_1.Syntax.Literal; + this.value = value; + this.raw = raw; + this.regex = { pattern: pattern, flags: flags }; + } + return RegexLiteral; + }()); + exports.RegexLiteral = RegexLiteral; + var RestElement = (function () { + function RestElement(argument) { + this.type = syntax_1.Syntax.RestElement; + this.argument = argument; + } + return RestElement; + }()); + exports.RestElement = RestElement; + var ReturnStatement = (function () { + function ReturnStatement(argument) { + this.type = syntax_1.Syntax.ReturnStatement; + this.argument = argument; + } + return ReturnStatement; + }()); + exports.ReturnStatement = ReturnStatement; + var Script = (function () { + function Script(body) { + this.type = syntax_1.Syntax.Program; + this.body = body; + this.sourceType = 'script'; + } + return Script; + }()); + exports.Script = Script; + var SequenceExpression = (function () { + function SequenceExpression(expressions) { + this.type = syntax_1.Syntax.SequenceExpression; + this.expressions = expressions; + } + return SequenceExpression; + }()); + exports.SequenceExpression = SequenceExpression; + var SpreadElement = (function () { + function SpreadElement(argument) { + this.type = syntax_1.Syntax.SpreadElement; + this.argument = argument; + } + return SpreadElement; + }()); + exports.SpreadElement = SpreadElement; + var StaticMemberExpression = (function () { + function StaticMemberExpression(object, property) { + this.type = syntax_1.Syntax.MemberExpression; + this.computed = false; + this.object = object; + this.property = property; + } + return StaticMemberExpression; + }()); + exports.StaticMemberExpression = StaticMemberExpression; + var Super = (function () { + function Super() { + this.type = syntax_1.Syntax.Super; + } + return Super; + }()); + exports.Super = Super; + var SwitchCase = (function () { + function SwitchCase(test, consequent) { + this.type = syntax_1.Syntax.SwitchCase; + this.test = test; + this.consequent = consequent; + } + return SwitchCase; + }()); + exports.SwitchCase = SwitchCase; + var SwitchStatement = (function () { + function SwitchStatement(discriminant, cases) { + this.type = syntax_1.Syntax.SwitchStatement; + this.discriminant = discriminant; + this.cases = cases; + } + return SwitchStatement; + }()); + exports.SwitchStatement = SwitchStatement; + var TaggedTemplateExpression = (function () { + function TaggedTemplateExpression(tag, quasi) { + this.type = syntax_1.Syntax.TaggedTemplateExpression; + this.tag = tag; + this.quasi = quasi; + } + return TaggedTemplateExpression; + }()); + exports.TaggedTemplateExpression = TaggedTemplateExpression; + var TemplateElement = (function () { + function TemplateElement(value, tail) { + this.type = syntax_1.Syntax.TemplateElement; + this.value = value; + this.tail = tail; + } + return TemplateElement; + }()); + exports.TemplateElement = TemplateElement; + var TemplateLiteral = (function () { + function TemplateLiteral(quasis, expressions) { + this.type = syntax_1.Syntax.TemplateLiteral; + this.quasis = quasis; + this.expressions = expressions; + } + return TemplateLiteral; + }()); + exports.TemplateLiteral = TemplateLiteral; + var ThisExpression = (function () { + function ThisExpression() { + this.type = syntax_1.Syntax.ThisExpression; + } + return ThisExpression; + }()); + exports.ThisExpression = ThisExpression; + var ThrowStatement = (function () { + function ThrowStatement(argument) { + this.type = syntax_1.Syntax.ThrowStatement; + this.argument = argument; + } + return ThrowStatement; + }()); + exports.ThrowStatement = ThrowStatement; + var TryStatement = (function () { + function TryStatement(block, handler, finalizer) { + this.type = syntax_1.Syntax.TryStatement; + this.block = block; + this.handler = handler; + this.finalizer = finalizer; + } + return TryStatement; + }()); + exports.TryStatement = TryStatement; + var UnaryExpression = (function () { + function UnaryExpression(operator, argument) { + this.type = syntax_1.Syntax.UnaryExpression; + this.operator = operator; + this.argument = argument; + this.prefix = true; + } + return UnaryExpression; + }()); + exports.UnaryExpression = UnaryExpression; + var UpdateExpression = (function () { + function UpdateExpression(operator, argument, prefix) { + this.type = syntax_1.Syntax.UpdateExpression; + this.operator = operator; + this.argument = argument; + this.prefix = prefix; + } + return UpdateExpression; + }()); + exports.UpdateExpression = UpdateExpression; + var VariableDeclaration = (function () { + function VariableDeclaration(declarations, kind) { + this.type = syntax_1.Syntax.VariableDeclaration; + this.declarations = declarations; + this.kind = kind; + } + return VariableDeclaration; + }()); + exports.VariableDeclaration = VariableDeclaration; + var VariableDeclarator = (function () { + function VariableDeclarator(id, init) { + this.type = syntax_1.Syntax.VariableDeclarator; + this.id = id; + this.init = init; + } + return VariableDeclarator; + }()); + exports.VariableDeclarator = VariableDeclarator; + var WhileStatement = (function () { + function WhileStatement(test, body) { + this.type = syntax_1.Syntax.WhileStatement; + this.test = test; + this.body = body; + } + return WhileStatement; + }()); + exports.WhileStatement = WhileStatement; + var WithStatement = (function () { + function WithStatement(object, body) { + this.type = syntax_1.Syntax.WithStatement; + this.object = object; + this.body = body; + } + return WithStatement; + }()); + exports.WithStatement = WithStatement; + var YieldExpression = (function () { + function YieldExpression(argument, delegate) { + this.type = syntax_1.Syntax.YieldExpression; + this.argument = argument; + this.delegate = delegate; + } + return YieldExpression; + }()); + exports.YieldExpression = YieldExpression; + + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var assert_1 = __webpack_require__(9); + var error_handler_1 = __webpack_require__(10); + var messages_1 = __webpack_require__(11); + var Node = __webpack_require__(7); + var scanner_1 = __webpack_require__(12); + var syntax_1 = __webpack_require__(2); + var token_1 = __webpack_require__(13); + var ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder'; + var Parser = (function () { + function Parser(code, options, delegate) { + if (options === void 0) { options = {}; } + this.config = { + range: (typeof options.range === 'boolean') && options.range, + loc: (typeof options.loc === 'boolean') && options.loc, + source: null, + tokens: (typeof options.tokens === 'boolean') && options.tokens, + comment: (typeof options.comment === 'boolean') && options.comment, + tolerant: (typeof options.tolerant === 'boolean') && options.tolerant + }; + if (this.config.loc && options.source && options.source !== null) { + this.config.source = String(options.source); + } + this.delegate = delegate; + this.errorHandler = new error_handler_1.ErrorHandler(); + this.errorHandler.tolerant = this.config.tolerant; + this.scanner = new scanner_1.Scanner(code, this.errorHandler); + this.scanner.trackComment = this.config.comment; + this.operatorPrecedence = { + ')': 0, + ';': 0, + ',': 0, + '=': 0, + ']': 0, + '||': 1, + '&&': 2, + '|': 3, + '^': 4, + '&': 5, + '==': 6, + '!=': 6, + '===': 6, + '!==': 6, + '<': 7, + '>': 7, + '<=': 7, + '>=': 7, + '<<': 8, + '>>': 8, + '>>>': 8, + '+': 9, + '-': 9, + '*': 11, + '/': 11, + '%': 11 + }; + this.lookahead = { + type: 2 /* EOF */, + value: '', + lineNumber: this.scanner.lineNumber, + lineStart: 0, + start: 0, + end: 0 + }; + this.hasLineTerminator = false; + this.context = { + isModule: false, + await: false, + allowIn: true, + allowStrictDirective: true, + allowYield: true, + firstCoverInitializedNameError: null, + isAssignmentTarget: false, + isBindingElement: false, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + labelSet: {}, + strict: false + }; + this.tokens = []; + this.startMarker = { + index: 0, + line: this.scanner.lineNumber, + column: 0 + }; + this.lastMarker = { + index: 0, + line: this.scanner.lineNumber, + column: 0 + }; + this.nextToken(); + this.lastMarker = { + index: this.scanner.index, + line: this.scanner.lineNumber, + column: this.scanner.index - this.scanner.lineStart + }; + } + Parser.prototype.throwError = function (messageFormat) { + var values = []; + for (var _i = 1; _i < arguments.length; _i++) { + values[_i - 1] = arguments[_i]; + } + var args = Array.prototype.slice.call(arguments, 1); + var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { + assert_1.assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + }); + var index = this.lastMarker.index; + var line = this.lastMarker.line; + var column = this.lastMarker.column + 1; + throw this.errorHandler.createError(index, line, column, msg); + }; + Parser.prototype.tolerateError = function (messageFormat) { + var values = []; + for (var _i = 1; _i < arguments.length; _i++) { + values[_i - 1] = arguments[_i]; + } + var args = Array.prototype.slice.call(arguments, 1); + var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { + assert_1.assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + }); + var index = this.lastMarker.index; + var line = this.scanner.lineNumber; + var column = this.lastMarker.column + 1; + this.errorHandler.tolerateError(index, line, column, msg); + }; + // Throw an exception because of the token. + Parser.prototype.unexpectedTokenError = function (token, message) { + var msg = message || messages_1.Messages.UnexpectedToken; + var value; + if (token) { + if (!message) { + msg = (token.type === 2 /* EOF */) ? messages_1.Messages.UnexpectedEOS : + (token.type === 3 /* Identifier */) ? messages_1.Messages.UnexpectedIdentifier : + (token.type === 6 /* NumericLiteral */) ? messages_1.Messages.UnexpectedNumber : + (token.type === 8 /* StringLiteral */) ? messages_1.Messages.UnexpectedString : + (token.type === 10 /* Template */) ? messages_1.Messages.UnexpectedTemplate : + messages_1.Messages.UnexpectedToken; + if (token.type === 4 /* Keyword */) { + if (this.scanner.isFutureReservedWord(token.value)) { + msg = messages_1.Messages.UnexpectedReserved; + } + else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) { + msg = messages_1.Messages.StrictReservedWord; + } + } + } + value = token.value; + } + else { + value = 'ILLEGAL'; + } + msg = msg.replace('%0', value); + if (token && typeof token.lineNumber === 'number') { + var index = token.start; + var line = token.lineNumber; + var lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column; + var column = token.start - lastMarkerLineStart + 1; + return this.errorHandler.createError(index, line, column, msg); + } + else { + var index = this.lastMarker.index; + var line = this.lastMarker.line; + var column = this.lastMarker.column + 1; + return this.errorHandler.createError(index, line, column, msg); + } + }; + Parser.prototype.throwUnexpectedToken = function (token, message) { + throw this.unexpectedTokenError(token, message); + }; + Parser.prototype.tolerateUnexpectedToken = function (token, message) { + this.errorHandler.tolerate(this.unexpectedTokenError(token, message)); + }; + Parser.prototype.collectComments = function () { + if (!this.config.comment) { + this.scanner.scanComments(); + } + else { + var comments = this.scanner.scanComments(); + if (comments.length > 0 && this.delegate) { + for (var i = 0; i < comments.length; ++i) { + var e = comments[i]; + var node = void 0; + node = { + type: e.multiLine ? 'BlockComment' : 'LineComment', + value: this.scanner.source.slice(e.slice[0], e.slice[1]) + }; + if (this.config.range) { + node.range = e.range; + } + if (this.config.loc) { + node.loc = e.loc; + } + var metadata = { + start: { + line: e.loc.start.line, + column: e.loc.start.column, + offset: e.range[0] + }, + end: { + line: e.loc.end.line, + column: e.loc.end.column, + offset: e.range[1] + } + }; + this.delegate(node, metadata); + } + } + } + }; + // From internal representation to an external structure + Parser.prototype.getTokenRaw = function (token) { + return this.scanner.source.slice(token.start, token.end); + }; + Parser.prototype.convertToken = function (token) { + var t = { + type: token_1.TokenName[token.type], + value: this.getTokenRaw(token) + }; + if (this.config.range) { + t.range = [token.start, token.end]; + } + if (this.config.loc) { + t.loc = { + start: { + line: this.startMarker.line, + column: this.startMarker.column + }, + end: { + line: this.scanner.lineNumber, + column: this.scanner.index - this.scanner.lineStart + } + }; + } + if (token.type === 9 /* RegularExpression */) { + var pattern = token.pattern; + var flags = token.flags; + t.regex = { pattern: pattern, flags: flags }; + } + return t; + }; + Parser.prototype.nextToken = function () { + var token = this.lookahead; + this.lastMarker.index = this.scanner.index; + this.lastMarker.line = this.scanner.lineNumber; + this.lastMarker.column = this.scanner.index - this.scanner.lineStart; + this.collectComments(); + if (this.scanner.index !== this.startMarker.index) { + this.startMarker.index = this.scanner.index; + this.startMarker.line = this.scanner.lineNumber; + this.startMarker.column = this.scanner.index - this.scanner.lineStart; + } + var next = this.scanner.lex(); + this.hasLineTerminator = (token.lineNumber !== next.lineNumber); + if (next && this.context.strict && next.type === 3 /* Identifier */) { + if (this.scanner.isStrictModeReservedWord(next.value)) { + next.type = 4 /* Keyword */; + } + } + this.lookahead = next; + if (this.config.tokens && next.type !== 2 /* EOF */) { + this.tokens.push(this.convertToken(next)); + } + return token; + }; + Parser.prototype.nextRegexToken = function () { + this.collectComments(); + var token = this.scanner.scanRegExp(); + if (this.config.tokens) { + // Pop the previous token, '/' or '/=' + // This is added from the lookahead token. + this.tokens.pop(); + this.tokens.push(this.convertToken(token)); + } + // Prime the next lookahead. + this.lookahead = token; + this.nextToken(); + return token; + }; + Parser.prototype.createNode = function () { + return { + index: this.startMarker.index, + line: this.startMarker.line, + column: this.startMarker.column + }; + }; + Parser.prototype.startNode = function (token, lastLineStart) { + if (lastLineStart === void 0) { lastLineStart = 0; } + var column = token.start - token.lineStart; + var line = token.lineNumber; + if (column < 0) { + column += lastLineStart; + line--; + } + return { + index: token.start, + line: line, + column: column + }; + }; + Parser.prototype.finalize = function (marker, node) { + if (this.config.range) { + node.range = [marker.index, this.lastMarker.index]; + } + if (this.config.loc) { + node.loc = { + start: { + line: marker.line, + column: marker.column, + }, + end: { + line: this.lastMarker.line, + column: this.lastMarker.column + } + }; + if (this.config.source) { + node.loc.source = this.config.source; + } + } + if (this.delegate) { + var metadata = { + start: { + line: marker.line, + column: marker.column, + offset: marker.index + }, + end: { + line: this.lastMarker.line, + column: this.lastMarker.column, + offset: this.lastMarker.index + } + }; + this.delegate(node, metadata); + } + return node; + }; + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + Parser.prototype.expect = function (value) { + var token = this.nextToken(); + if (token.type !== 7 /* Punctuator */ || token.value !== value) { + this.throwUnexpectedToken(token); + } + }; + // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). + Parser.prototype.expectCommaSeparator = function () { + if (this.config.tolerant) { + var token = this.lookahead; + if (token.type === 7 /* Punctuator */ && token.value === ',') { + this.nextToken(); + } + else if (token.type === 7 /* Punctuator */ && token.value === ';') { + this.nextToken(); + this.tolerateUnexpectedToken(token); + } + else { + this.tolerateUnexpectedToken(token, messages_1.Messages.UnexpectedToken); + } + } + else { + this.expect(','); + } + }; + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + Parser.prototype.expectKeyword = function (keyword) { + var token = this.nextToken(); + if (token.type !== 4 /* Keyword */ || token.value !== keyword) { + this.throwUnexpectedToken(token); + } + }; + // Return true if the next token matches the specified punctuator. + Parser.prototype.match = function (value) { + return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value; + }; + // Return true if the next token matches the specified keyword + Parser.prototype.matchKeyword = function (keyword) { + return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword; + }; + // Return true if the next token matches the specified contextual keyword + // (where an identifier is sometimes a keyword depending on the context) + Parser.prototype.matchContextualKeyword = function (keyword) { + return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword; + }; + // Return true if the next token is an assignment operator + Parser.prototype.matchAssign = function () { + if (this.lookahead.type !== 7 /* Punctuator */) { + return false; + } + var op = this.lookahead.value; + return op === '=' || + op === '*=' || + op === '**=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + }; + // Cover grammar support. + // + // When an assignment expression position starts with an left parenthesis, the determination of the type + // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) + // or the first comma. This situation also defers the determination of all the expressions nested in the pair. + // + // There are three productions that can be parsed in a parentheses pair that needs to be determined + // after the outermost pair is closed. They are: + // + // 1. AssignmentExpression + // 2. BindingElements + // 3. AssignmentTargets + // + // In order to avoid exponential backtracking, we use two flags to denote if the production can be + // binding element or assignment target. + // + // The three productions have the relationship: + // + // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression + // + // with a single exception that CoverInitializedName when used directly in an Expression, generates + // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the + // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. + // + // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not + // effect the current flags. This means the production the parser parses is only used as an expression. Therefore + // the CoverInitializedName check is conducted. + // + // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates + // the flags outside of the parser. This means the production the parser parses is used as a part of a potential + // pattern. The CoverInitializedName check is deferred. + Parser.prototype.isolateCoverGrammar = function (parseFunction) { + var previousIsBindingElement = this.context.isBindingElement; + var previousIsAssignmentTarget = this.context.isAssignmentTarget; + var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; + this.context.isBindingElement = true; + this.context.isAssignmentTarget = true; + this.context.firstCoverInitializedNameError = null; + var result = parseFunction.call(this); + if (this.context.firstCoverInitializedNameError !== null) { + this.throwUnexpectedToken(this.context.firstCoverInitializedNameError); + } + this.context.isBindingElement = previousIsBindingElement; + this.context.isAssignmentTarget = previousIsAssignmentTarget; + this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError; + return result; + }; + Parser.prototype.inheritCoverGrammar = function (parseFunction) { + var previousIsBindingElement = this.context.isBindingElement; + var previousIsAssignmentTarget = this.context.isAssignmentTarget; + var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; + this.context.isBindingElement = true; + this.context.isAssignmentTarget = true; + this.context.firstCoverInitializedNameError = null; + var result = parseFunction.call(this); + this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement; + this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget; + this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError; + return result; + }; + Parser.prototype.consumeSemicolon = function () { + if (this.match(';')) { + this.nextToken(); + } + else if (!this.hasLineTerminator) { + if (this.lookahead.type !== 2 /* EOF */ && !this.match('}')) { + this.throwUnexpectedToken(this.lookahead); + } + this.lastMarker.index = this.startMarker.index; + this.lastMarker.line = this.startMarker.line; + this.lastMarker.column = this.startMarker.column; + } + }; + // https://tc39.github.io/ecma262/#sec-primary-expression + Parser.prototype.parsePrimaryExpression = function () { + var node = this.createNode(); + var expr; + var token, raw; + switch (this.lookahead.type) { + case 3 /* Identifier */: + if ((this.context.isModule || this.context.await) && this.lookahead.value === 'await') { + this.tolerateUnexpectedToken(this.lookahead); + } + expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Node.Identifier(this.nextToken().value)); + break; + case 6 /* NumericLiteral */: + case 8 /* StringLiteral */: + if (this.context.strict && this.lookahead.octal) { + this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.StrictOctalLiteral); + } + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + token = this.nextToken(); + raw = this.getTokenRaw(token); + expr = this.finalize(node, new Node.Literal(token.value, raw)); + break; + case 1 /* BooleanLiteral */: + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + token = this.nextToken(); + raw = this.getTokenRaw(token); + expr = this.finalize(node, new Node.Literal(token.value === 'true', raw)); + break; + case 5 /* NullLiteral */: + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + token = this.nextToken(); + raw = this.getTokenRaw(token); + expr = this.finalize(node, new Node.Literal(null, raw)); + break; + case 10 /* Template */: + expr = this.parseTemplateLiteral(); + break; + case 7 /* Punctuator */: + switch (this.lookahead.value) { + case '(': + this.context.isBindingElement = false; + expr = this.inheritCoverGrammar(this.parseGroupExpression); + break; + case '[': + expr = this.inheritCoverGrammar(this.parseArrayInitializer); + break; + case '{': + expr = this.inheritCoverGrammar(this.parseObjectInitializer); + break; + case '/': + case '/=': + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + this.scanner.index = this.startMarker.index; + token = this.nextRegexToken(); + raw = this.getTokenRaw(token); + expr = this.finalize(node, new Node.RegexLiteral(token.regex, raw, token.pattern, token.flags)); + break; + default: + expr = this.throwUnexpectedToken(this.nextToken()); + } + break; + case 4 /* Keyword */: + if (!this.context.strict && this.context.allowYield && this.matchKeyword('yield')) { + expr = this.parseIdentifierName(); + } + else if (!this.context.strict && this.matchKeyword('let')) { + expr = this.finalize(node, new Node.Identifier(this.nextToken().value)); + } + else { + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + if (this.matchKeyword('function')) { + expr = this.parseFunctionExpression(); + } + else if (this.matchKeyword('this')) { + this.nextToken(); + expr = this.finalize(node, new Node.ThisExpression()); + } + else if (this.matchKeyword('class')) { + expr = this.parseClassExpression(); + } + else { + expr = this.throwUnexpectedToken(this.nextToken()); + } + } + break; + default: + expr = this.throwUnexpectedToken(this.nextToken()); + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-array-initializer + Parser.prototype.parseSpreadElement = function () { + var node = this.createNode(); + this.expect('...'); + var arg = this.inheritCoverGrammar(this.parseAssignmentExpression); + return this.finalize(node, new Node.SpreadElement(arg)); + }; + Parser.prototype.parseArrayInitializer = function () { + var node = this.createNode(); + var elements = []; + this.expect('['); + while (!this.match(']')) { + if (this.match(',')) { + this.nextToken(); + elements.push(null); + } + else if (this.match('...')) { + var element = this.parseSpreadElement(); + if (!this.match(']')) { + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + this.expect(','); + } + elements.push(element); + } + else { + elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); + if (!this.match(']')) { + this.expect(','); + } + } + } + this.expect(']'); + return this.finalize(node, new Node.ArrayExpression(elements)); + }; + // https://tc39.github.io/ecma262/#sec-object-initializer + Parser.prototype.parsePropertyMethod = function (params) { + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + var previousStrict = this.context.strict; + var previousAllowStrictDirective = this.context.allowStrictDirective; + this.context.allowStrictDirective = params.simple; + var body = this.isolateCoverGrammar(this.parseFunctionSourceElements); + if (this.context.strict && params.firstRestricted) { + this.tolerateUnexpectedToken(params.firstRestricted, params.message); + } + if (this.context.strict && params.stricted) { + this.tolerateUnexpectedToken(params.stricted, params.message); + } + this.context.strict = previousStrict; + this.context.allowStrictDirective = previousAllowStrictDirective; + return body; + }; + Parser.prototype.parsePropertyMethodFunction = function () { + var isGenerator = false; + var node = this.createNode(); + var previousAllowYield = this.context.allowYield; + this.context.allowYield = true; + var params = this.parseFormalParameters(); + var method = this.parsePropertyMethod(params); + this.context.allowYield = previousAllowYield; + return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); + }; + Parser.prototype.parsePropertyMethodAsyncFunction = function () { + var node = this.createNode(); + var previousAllowYield = this.context.allowYield; + var previousAwait = this.context.await; + this.context.allowYield = false; + this.context.await = true; + var params = this.parseFormalParameters(); + var method = this.parsePropertyMethod(params); + this.context.allowYield = previousAllowYield; + this.context.await = previousAwait; + return this.finalize(node, new Node.AsyncFunctionExpression(null, params.params, method)); + }; + Parser.prototype.parseObjectPropertyKey = function () { + var node = this.createNode(); + var token = this.nextToken(); + var key; + switch (token.type) { + case 8 /* StringLiteral */: + case 6 /* NumericLiteral */: + if (this.context.strict && token.octal) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictOctalLiteral); + } + var raw = this.getTokenRaw(token); + key = this.finalize(node, new Node.Literal(token.value, raw)); + break; + case 3 /* Identifier */: + case 1 /* BooleanLiteral */: + case 5 /* NullLiteral */: + case 4 /* Keyword */: + key = this.finalize(node, new Node.Identifier(token.value)); + break; + case 7 /* Punctuator */: + if (token.value === '[') { + key = this.isolateCoverGrammar(this.parseAssignmentExpression); + this.expect(']'); + } + else { + key = this.throwUnexpectedToken(token); + } + break; + default: + key = this.throwUnexpectedToken(token); + } + return key; + }; + Parser.prototype.isPropertyKey = function (key, value) { + return (key.type === syntax_1.Syntax.Identifier && key.name === value) || + (key.type === syntax_1.Syntax.Literal && key.value === value); + }; + Parser.prototype.parseObjectProperty = function (hasProto) { + var node = this.createNode(); + var token = this.lookahead; + var kind; + var key = null; + var value = null; + var computed = false; + var method = false; + var shorthand = false; + var isAsync = false; + if (token.type === 3 /* Identifier */) { + var id = token.value; + this.nextToken(); + computed = this.match('['); + isAsync = !this.hasLineTerminator && (id === 'async') && + !this.match(':') && !this.match('(') && !this.match('*') && !this.match(','); + key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Node.Identifier(id)); + } + else if (this.match('*')) { + this.nextToken(); + } + else { + computed = this.match('['); + key = this.parseObjectPropertyKey(); + } + var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); + if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'get' && lookaheadPropertyKey) { + kind = 'get'; + computed = this.match('['); + key = this.parseObjectPropertyKey(); + this.context.allowYield = false; + value = this.parseGetterMethod(); + } + else if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'set' && lookaheadPropertyKey) { + kind = 'set'; + computed = this.match('['); + key = this.parseObjectPropertyKey(); + value = this.parseSetterMethod(); + } + else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { + kind = 'init'; + computed = this.match('['); + key = this.parseObjectPropertyKey(); + value = this.parseGeneratorMethod(); + method = true; + } + else { + if (!key) { + this.throwUnexpectedToken(this.lookahead); + } + kind = 'init'; + if (this.match(':') && !isAsync) { + if (!computed && this.isPropertyKey(key, '__proto__')) { + if (hasProto.value) { + this.tolerateError(messages_1.Messages.DuplicateProtoProperty); + } + hasProto.value = true; + } + this.nextToken(); + value = this.inheritCoverGrammar(this.parseAssignmentExpression); + } + else if (this.match('(')) { + value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); + method = true; + } + else if (token.type === 3 /* Identifier */) { + var id = this.finalize(node, new Node.Identifier(token.value)); + if (this.match('=')) { + this.context.firstCoverInitializedNameError = this.lookahead; + this.nextToken(); + shorthand = true; + var init = this.isolateCoverGrammar(this.parseAssignmentExpression); + value = this.finalize(node, new Node.AssignmentPattern(id, init)); + } + else { + shorthand = true; + value = id; + } + } + else { + this.throwUnexpectedToken(this.nextToken()); + } + } + return this.finalize(node, new Node.Property(kind, key, computed, value, method, shorthand)); + }; + Parser.prototype.parseObjectInitializer = function () { + var node = this.createNode(); + this.expect('{'); + var properties = []; + var hasProto = { value: false }; + while (!this.match('}')) { + properties.push(this.parseObjectProperty(hasProto)); + if (!this.match('}')) { + this.expectCommaSeparator(); + } + } + this.expect('}'); + return this.finalize(node, new Node.ObjectExpression(properties)); + }; + // https://tc39.github.io/ecma262/#sec-template-literals + Parser.prototype.parseTemplateHead = function () { + assert_1.assert(this.lookahead.head, 'Template literal must start with a template head'); + var node = this.createNode(); + var token = this.nextToken(); + var raw = token.value; + var cooked = token.cooked; + return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); + }; + Parser.prototype.parseTemplateElement = function () { + if (this.lookahead.type !== 10 /* Template */) { + this.throwUnexpectedToken(); + } + var node = this.createNode(); + var token = this.nextToken(); + var raw = token.value; + var cooked = token.cooked; + return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); + }; + Parser.prototype.parseTemplateLiteral = function () { + var node = this.createNode(); + var expressions = []; + var quasis = []; + var quasi = this.parseTemplateHead(); + quasis.push(quasi); + while (!quasi.tail) { + expressions.push(this.parseExpression()); + quasi = this.parseTemplateElement(); + quasis.push(quasi); + } + return this.finalize(node, new Node.TemplateLiteral(quasis, expressions)); + }; + // https://tc39.github.io/ecma262/#sec-grouping-operator + Parser.prototype.reinterpretExpressionAsPattern = function (expr) { + switch (expr.type) { + case syntax_1.Syntax.Identifier: + case syntax_1.Syntax.MemberExpression: + case syntax_1.Syntax.RestElement: + case syntax_1.Syntax.AssignmentPattern: + break; + case syntax_1.Syntax.SpreadElement: + expr.type = syntax_1.Syntax.RestElement; + this.reinterpretExpressionAsPattern(expr.argument); + break; + case syntax_1.Syntax.ArrayExpression: + expr.type = syntax_1.Syntax.ArrayPattern; + for (var i = 0; i < expr.elements.length; i++) { + if (expr.elements[i] !== null) { + this.reinterpretExpressionAsPattern(expr.elements[i]); + } + } + break; + case syntax_1.Syntax.ObjectExpression: + expr.type = syntax_1.Syntax.ObjectPattern; + for (var i = 0; i < expr.properties.length; i++) { + this.reinterpretExpressionAsPattern(expr.properties[i].value); + } + break; + case syntax_1.Syntax.AssignmentExpression: + expr.type = syntax_1.Syntax.AssignmentPattern; + delete expr.operator; + this.reinterpretExpressionAsPattern(expr.left); + break; + default: + // Allow other node type for tolerant parsing. + break; + } + }; + Parser.prototype.parseGroupExpression = function () { + var expr; + this.expect('('); + if (this.match(')')) { + this.nextToken(); + if (!this.match('=>')) { + this.expect('=>'); + } + expr = { + type: ArrowParameterPlaceHolder, + params: [], + async: false + }; + } + else { + var startToken = this.lookahead; + var params = []; + if (this.match('...')) { + expr = this.parseRestElement(params); + this.expect(')'); + if (!this.match('=>')) { + this.expect('=>'); + } + expr = { + type: ArrowParameterPlaceHolder, + params: [expr], + async: false + }; + } + else { + var arrow = false; + this.context.isBindingElement = true; + expr = this.inheritCoverGrammar(this.parseAssignmentExpression); + if (this.match(',')) { + var expressions = []; + this.context.isAssignmentTarget = false; + expressions.push(expr); + while (this.lookahead.type !== 2 /* EOF */) { + if (!this.match(',')) { + break; + } + this.nextToken(); + if (this.match(')')) { + this.nextToken(); + for (var i = 0; i < expressions.length; i++) { + this.reinterpretExpressionAsPattern(expressions[i]); + } + arrow = true; + expr = { + type: ArrowParameterPlaceHolder, + params: expressions, + async: false + }; + } + else if (this.match('...')) { + if (!this.context.isBindingElement) { + this.throwUnexpectedToken(this.lookahead); + } + expressions.push(this.parseRestElement(params)); + this.expect(')'); + if (!this.match('=>')) { + this.expect('=>'); + } + this.context.isBindingElement = false; + for (var i = 0; i < expressions.length; i++) { + this.reinterpretExpressionAsPattern(expressions[i]); + } + arrow = true; + expr = { + type: ArrowParameterPlaceHolder, + params: expressions, + async: false + }; + } + else { + expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); + } + if (arrow) { + break; + } + } + if (!arrow) { + expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); + } + } + if (!arrow) { + this.expect(')'); + if (this.match('=>')) { + if (expr.type === syntax_1.Syntax.Identifier && expr.name === 'yield') { + arrow = true; + expr = { + type: ArrowParameterPlaceHolder, + params: [expr], + async: false + }; + } + if (!arrow) { + if (!this.context.isBindingElement) { + this.throwUnexpectedToken(this.lookahead); + } + if (expr.type === syntax_1.Syntax.SequenceExpression) { + for (var i = 0; i < expr.expressions.length; i++) { + this.reinterpretExpressionAsPattern(expr.expressions[i]); + } + } + else { + this.reinterpretExpressionAsPattern(expr); + } + var parameters = (expr.type === syntax_1.Syntax.SequenceExpression ? expr.expressions : [expr]); + expr = { + type: ArrowParameterPlaceHolder, + params: parameters, + async: false + }; + } + } + this.context.isBindingElement = false; + } + } + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions + Parser.prototype.parseArguments = function () { + this.expect('('); + var args = []; + if (!this.match(')')) { + while (true) { + var expr = this.match('...') ? this.parseSpreadElement() : + this.isolateCoverGrammar(this.parseAssignmentExpression); + args.push(expr); + if (this.match(')')) { + break; + } + this.expectCommaSeparator(); + if (this.match(')')) { + break; + } + } + } + this.expect(')'); + return args; + }; + Parser.prototype.isIdentifierName = function (token) { + return token.type === 3 /* Identifier */ || + token.type === 4 /* Keyword */ || + token.type === 1 /* BooleanLiteral */ || + token.type === 5 /* NullLiteral */; + }; + Parser.prototype.parseIdentifierName = function () { + var node = this.createNode(); + var token = this.nextToken(); + if (!this.isIdentifierName(token)) { + this.throwUnexpectedToken(token); + } + return this.finalize(node, new Node.Identifier(token.value)); + }; + Parser.prototype.parseNewExpression = function () { + var node = this.createNode(); + var id = this.parseIdentifierName(); + assert_1.assert(id.name === 'new', 'New expression must start with `new`'); + var expr; + if (this.match('.')) { + this.nextToken(); + if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === 'target') { + var property = this.parseIdentifierName(); + expr = new Node.MetaProperty(id, property); + } + else { + this.throwUnexpectedToken(this.lookahead); + } + } + else { + var callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression); + var args = this.match('(') ? this.parseArguments() : []; + expr = new Node.NewExpression(callee, args); + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + } + return this.finalize(node, expr); + }; + Parser.prototype.parseAsyncArgument = function () { + var arg = this.parseAssignmentExpression(); + this.context.firstCoverInitializedNameError = null; + return arg; + }; + Parser.prototype.parseAsyncArguments = function () { + this.expect('('); + var args = []; + if (!this.match(')')) { + while (true) { + var expr = this.match('...') ? this.parseSpreadElement() : + this.isolateCoverGrammar(this.parseAsyncArgument); + args.push(expr); + if (this.match(')')) { + break; + } + this.expectCommaSeparator(); + if (this.match(')')) { + break; + } + } + } + this.expect(')'); + return args; + }; + Parser.prototype.parseLeftHandSideExpressionAllowCall = function () { + var startToken = this.lookahead; + var maybeAsync = this.matchContextualKeyword('async'); + var previousAllowIn = this.context.allowIn; + this.context.allowIn = true; + var expr; + if (this.matchKeyword('super') && this.context.inFunctionBody) { + expr = this.createNode(); + this.nextToken(); + expr = this.finalize(expr, new Node.Super()); + if (!this.match('(') && !this.match('.') && !this.match('[')) { + this.throwUnexpectedToken(this.lookahead); + } + } + else { + expr = this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); + } + while (true) { + if (this.match('.')) { + this.context.isBindingElement = false; + this.context.isAssignmentTarget = true; + this.expect('.'); + var property = this.parseIdentifierName(); + expr = this.finalize(this.startNode(startToken), new Node.StaticMemberExpression(expr, property)); + } + else if (this.match('(')) { + var asyncArrow = maybeAsync && (startToken.lineNumber === this.lookahead.lineNumber); + this.context.isBindingElement = false; + this.context.isAssignmentTarget = false; + var args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments(); + expr = this.finalize(this.startNode(startToken), new Node.CallExpression(expr, args)); + if (asyncArrow && this.match('=>')) { + for (var i = 0; i < args.length; ++i) { + this.reinterpretExpressionAsPattern(args[i]); + } + expr = { + type: ArrowParameterPlaceHolder, + params: args, + async: true + }; + } + } + else if (this.match('[')) { + this.context.isBindingElement = false; + this.context.isAssignmentTarget = true; + this.expect('['); + var property = this.isolateCoverGrammar(this.parseExpression); + this.expect(']'); + expr = this.finalize(this.startNode(startToken), new Node.ComputedMemberExpression(expr, property)); + } + else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { + var quasi = this.parseTemplateLiteral(); + expr = this.finalize(this.startNode(startToken), new Node.TaggedTemplateExpression(expr, quasi)); + } + else { + break; + } + } + this.context.allowIn = previousAllowIn; + return expr; + }; + Parser.prototype.parseSuper = function () { + var node = this.createNode(); + this.expectKeyword('super'); + if (!this.match('[') && !this.match('.')) { + this.throwUnexpectedToken(this.lookahead); + } + return this.finalize(node, new Node.Super()); + }; + Parser.prototype.parseLeftHandSideExpression = function () { + assert_1.assert(this.context.allowIn, 'callee of new expression always allow in keyword.'); + var node = this.startNode(this.lookahead); + var expr = (this.matchKeyword('super') && this.context.inFunctionBody) ? this.parseSuper() : + this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); + while (true) { + if (this.match('[')) { + this.context.isBindingElement = false; + this.context.isAssignmentTarget = true; + this.expect('['); + var property = this.isolateCoverGrammar(this.parseExpression); + this.expect(']'); + expr = this.finalize(node, new Node.ComputedMemberExpression(expr, property)); + } + else if (this.match('.')) { + this.context.isBindingElement = false; + this.context.isAssignmentTarget = true; + this.expect('.'); + var property = this.parseIdentifierName(); + expr = this.finalize(node, new Node.StaticMemberExpression(expr, property)); + } + else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { + var quasi = this.parseTemplateLiteral(); + expr = this.finalize(node, new Node.TaggedTemplateExpression(expr, quasi)); + } + else { + break; + } + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-update-expressions + Parser.prototype.parseUpdateExpression = function () { + var expr; + var startToken = this.lookahead; + if (this.match('++') || this.match('--')) { + var node = this.startNode(startToken); + var token = this.nextToken(); + expr = this.inheritCoverGrammar(this.parseUnaryExpression); + if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { + this.tolerateError(messages_1.Messages.StrictLHSPrefix); + } + if (!this.context.isAssignmentTarget) { + this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); + } + var prefix = true; + expr = this.finalize(node, new Node.UpdateExpression(token.value, expr, prefix)); + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + } + else { + expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall); + if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) { + if (this.match('++') || this.match('--')) { + if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { + this.tolerateError(messages_1.Messages.StrictLHSPostfix); + } + if (!this.context.isAssignmentTarget) { + this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); + } + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + var operator = this.nextToken().value; + var prefix = false; + expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix)); + } + } + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-unary-operators + Parser.prototype.parseAwaitExpression = function () { + var node = this.createNode(); + this.nextToken(); + var argument = this.parseUnaryExpression(); + return this.finalize(node, new Node.AwaitExpression(argument)); + }; + Parser.prototype.parseUnaryExpression = function () { + var expr; + if (this.match('+') || this.match('-') || this.match('~') || this.match('!') || + this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) { + var node = this.startNode(this.lookahead); + var token = this.nextToken(); + expr = this.inheritCoverGrammar(this.parseUnaryExpression); + expr = this.finalize(node, new Node.UnaryExpression(token.value, expr)); + if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) { + this.tolerateError(messages_1.Messages.StrictDelete); + } + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + } + else if (this.context.await && this.matchContextualKeyword('await')) { + expr = this.parseAwaitExpression(); + } + else { + expr = this.parseUpdateExpression(); + } + return expr; + }; + Parser.prototype.parseExponentiationExpression = function () { + var startToken = this.lookahead; + var expr = this.inheritCoverGrammar(this.parseUnaryExpression); + if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) { + this.nextToken(); + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + var left = expr; + var right = this.isolateCoverGrammar(this.parseExponentiationExpression); + expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right)); + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-exp-operator + // https://tc39.github.io/ecma262/#sec-multiplicative-operators + // https://tc39.github.io/ecma262/#sec-additive-operators + // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators + // https://tc39.github.io/ecma262/#sec-relational-operators + // https://tc39.github.io/ecma262/#sec-equality-operators + // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators + // https://tc39.github.io/ecma262/#sec-binary-logical-operators + Parser.prototype.binaryPrecedence = function (token) { + var op = token.value; + var precedence; + if (token.type === 7 /* Punctuator */) { + precedence = this.operatorPrecedence[op] || 0; + } + else if (token.type === 4 /* Keyword */) { + precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0; + } + else { + precedence = 0; + } + return precedence; + }; + Parser.prototype.parseBinaryExpression = function () { + var startToken = this.lookahead; + var expr = this.inheritCoverGrammar(this.parseExponentiationExpression); + var token = this.lookahead; + var prec = this.binaryPrecedence(token); + if (prec > 0) { + this.nextToken(); + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + var markers = [startToken, this.lookahead]; + var left = expr; + var right = this.isolateCoverGrammar(this.parseExponentiationExpression); + var stack = [left, token.value, right]; + var precedences = [prec]; + while (true) { + prec = this.binaryPrecedence(this.lookahead); + if (prec <= 0) { + break; + } + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) { + right = stack.pop(); + var operator = stack.pop(); + precedences.pop(); + left = stack.pop(); + markers.pop(); + var node = this.startNode(markers[markers.length - 1]); + stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right))); + } + // Shift. + stack.push(this.nextToken().value); + precedences.push(prec); + markers.push(this.lookahead); + stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression)); + } + // Final reduce to clean-up the stack. + var i = stack.length - 1; + expr = stack[i]; + var lastMarker = markers.pop(); + while (i > 1) { + var marker = markers.pop(); + var lastLineStart = lastMarker && lastMarker.lineStart; + var node = this.startNode(marker, lastLineStart); + var operator = stack[i - 1]; + expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr)); + i -= 2; + lastMarker = marker; + } + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-conditional-operator + Parser.prototype.parseConditionalExpression = function () { + var startToken = this.lookahead; + var expr = this.inheritCoverGrammar(this.parseBinaryExpression); + if (this.match('?')) { + this.nextToken(); + var previousAllowIn = this.context.allowIn; + this.context.allowIn = true; + var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression); + this.context.allowIn = previousAllowIn; + this.expect(':'); + var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression); + expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate)); + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-assignment-operators + Parser.prototype.checkPatternParam = function (options, param) { + switch (param.type) { + case syntax_1.Syntax.Identifier: + this.validateParam(options, param, param.name); + break; + case syntax_1.Syntax.RestElement: + this.checkPatternParam(options, param.argument); + break; + case syntax_1.Syntax.AssignmentPattern: + this.checkPatternParam(options, param.left); + break; + case syntax_1.Syntax.ArrayPattern: + for (var i = 0; i < param.elements.length; i++) { + if (param.elements[i] !== null) { + this.checkPatternParam(options, param.elements[i]); + } + } + break; + case syntax_1.Syntax.ObjectPattern: + for (var i = 0; i < param.properties.length; i++) { + this.checkPatternParam(options, param.properties[i].value); + } + break; + default: + break; + } + options.simple = options.simple && (param instanceof Node.Identifier); + }; + Parser.prototype.reinterpretAsCoverFormalsList = function (expr) { + var params = [expr]; + var options; + var asyncArrow = false; + switch (expr.type) { + case syntax_1.Syntax.Identifier: + break; + case ArrowParameterPlaceHolder: + params = expr.params; + asyncArrow = expr.async; + break; + default: + return null; + } + options = { + simple: true, + paramSet: {} + }; + for (var i = 0; i < params.length; ++i) { + var param = params[i]; + if (param.type === syntax_1.Syntax.AssignmentPattern) { + if (param.right.type === syntax_1.Syntax.YieldExpression) { + if (param.right.argument) { + this.throwUnexpectedToken(this.lookahead); + } + param.right.type = syntax_1.Syntax.Identifier; + param.right.name = 'yield'; + delete param.right.argument; + delete param.right.delegate; + } + } + else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') { + this.throwUnexpectedToken(this.lookahead); + } + this.checkPatternParam(options, param); + params[i] = param; + } + if (this.context.strict || !this.context.allowYield) { + for (var i = 0; i < params.length; ++i) { + var param = params[i]; + if (param.type === syntax_1.Syntax.YieldExpression) { + this.throwUnexpectedToken(this.lookahead); + } + } + } + if (options.message === messages_1.Messages.StrictParamDupe) { + var token = this.context.strict ? options.stricted : options.firstRestricted; + this.throwUnexpectedToken(token, options.message); + } + return { + simple: options.simple, + params: params, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + }; + Parser.prototype.parseAssignmentExpression = function () { + var expr; + if (!this.context.allowYield && this.matchKeyword('yield')) { + expr = this.parseYieldExpression(); + } + else { + var startToken = this.lookahead; + var token = startToken; + expr = this.parseConditionalExpression(); + if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') { + if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) { + var arg = this.parsePrimaryExpression(); + this.reinterpretExpressionAsPattern(arg); + expr = { + type: ArrowParameterPlaceHolder, + params: [arg], + async: true + }; + } + } + if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) { + // https://tc39.github.io/ecma262/#sec-arrow-function-definitions + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + var isAsync = expr.async; + var list = this.reinterpretAsCoverFormalsList(expr); + if (list) { + if (this.hasLineTerminator) { + this.tolerateUnexpectedToken(this.lookahead); + } + this.context.firstCoverInitializedNameError = null; + var previousStrict = this.context.strict; + var previousAllowStrictDirective = this.context.allowStrictDirective; + this.context.allowStrictDirective = list.simple; + var previousAllowYield = this.context.allowYield; + var previousAwait = this.context.await; + this.context.allowYield = true; + this.context.await = isAsync; + var node = this.startNode(startToken); + this.expect('=>'); + var body = void 0; + if (this.match('{')) { + var previousAllowIn = this.context.allowIn; + this.context.allowIn = true; + body = this.parseFunctionSourceElements(); + this.context.allowIn = previousAllowIn; + } + else { + body = this.isolateCoverGrammar(this.parseAssignmentExpression); + } + var expression = body.type !== syntax_1.Syntax.BlockStatement; + if (this.context.strict && list.firstRestricted) { + this.throwUnexpectedToken(list.firstRestricted, list.message); + } + if (this.context.strict && list.stricted) { + this.tolerateUnexpectedToken(list.stricted, list.message); + } + expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) : + this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression)); + this.context.strict = previousStrict; + this.context.allowStrictDirective = previousAllowStrictDirective; + this.context.allowYield = previousAllowYield; + this.context.await = previousAwait; + } + } + else { + if (this.matchAssign()) { + if (!this.context.isAssignmentTarget) { + this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); + } + if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) { + var id = expr; + if (this.scanner.isRestrictedWord(id.name)) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment); + } + if (this.scanner.isStrictModeReservedWord(id.name)) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); + } + } + if (!this.match('=')) { + this.context.isAssignmentTarget = false; + this.context.isBindingElement = false; + } + else { + this.reinterpretExpressionAsPattern(expr); + } + token = this.nextToken(); + var operator = token.value; + var right = this.isolateCoverGrammar(this.parseAssignmentExpression); + expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right)); + this.context.firstCoverInitializedNameError = null; + } + } + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-comma-operator + Parser.prototype.parseExpression = function () { + var startToken = this.lookahead; + var expr = this.isolateCoverGrammar(this.parseAssignmentExpression); + if (this.match(',')) { + var expressions = []; + expressions.push(expr); + while (this.lookahead.type !== 2 /* EOF */) { + if (!this.match(',')) { + break; + } + this.nextToken(); + expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); + } + expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); + } + return expr; + }; + // https://tc39.github.io/ecma262/#sec-block + Parser.prototype.parseStatementListItem = function () { + var statement; + this.context.isAssignmentTarget = true; + this.context.isBindingElement = true; + if (this.lookahead.type === 4 /* Keyword */) { + switch (this.lookahead.value) { + case 'export': + if (!this.context.isModule) { + this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration); + } + statement = this.parseExportDeclaration(); + break; + case 'import': + if (!this.context.isModule) { + this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration); + } + statement = this.parseImportDeclaration(); + break; + case 'const': + statement = this.parseLexicalDeclaration({ inFor: false }); + break; + case 'function': + statement = this.parseFunctionDeclaration(); + break; + case 'class': + statement = this.parseClassDeclaration(); + break; + case 'let': + statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement(); + break; + default: + statement = this.parseStatement(); + break; + } + } + else { + statement = this.parseStatement(); + } + return statement; + }; + Parser.prototype.parseBlock = function () { + var node = this.createNode(); + this.expect('{'); + var block = []; + while (true) { + if (this.match('}')) { + break; + } + block.push(this.parseStatementListItem()); + } + this.expect('}'); + return this.finalize(node, new Node.BlockStatement(block)); + }; + // https://tc39.github.io/ecma262/#sec-let-and-const-declarations + Parser.prototype.parseLexicalBinding = function (kind, options) { + var node = this.createNode(); + var params = []; + var id = this.parsePattern(params, kind); + if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { + if (this.scanner.isRestrictedWord(id.name)) { + this.tolerateError(messages_1.Messages.StrictVarName); + } + } + var init = null; + if (kind === 'const') { + if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) { + if (this.match('=')) { + this.nextToken(); + init = this.isolateCoverGrammar(this.parseAssignmentExpression); + } + else { + this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const'); + } + } + } + else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) { + this.expect('='); + init = this.isolateCoverGrammar(this.parseAssignmentExpression); + } + return this.finalize(node, new Node.VariableDeclarator(id, init)); + }; + Parser.prototype.parseBindingList = function (kind, options) { + var list = [this.parseLexicalBinding(kind, options)]; + while (this.match(',')) { + this.nextToken(); + list.push(this.parseLexicalBinding(kind, options)); + } + return list; + }; + Parser.prototype.isLexicalDeclaration = function () { + var state = this.scanner.saveState(); + this.scanner.scanComments(); + var next = this.scanner.lex(); + this.scanner.restoreState(state); + return (next.type === 3 /* Identifier */) || + (next.type === 7 /* Punctuator */ && next.value === '[') || + (next.type === 7 /* Punctuator */ && next.value === '{') || + (next.type === 4 /* Keyword */ && next.value === 'let') || + (next.type === 4 /* Keyword */ && next.value === 'yield'); + }; + Parser.prototype.parseLexicalDeclaration = function (options) { + var node = this.createNode(); + var kind = this.nextToken().value; + assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); + var declarations = this.parseBindingList(kind, options); + this.consumeSemicolon(); + return this.finalize(node, new Node.VariableDeclaration(declarations, kind)); + }; + // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns + Parser.prototype.parseBindingRestElement = function (params, kind) { + var node = this.createNode(); + this.expect('...'); + var arg = this.parsePattern(params, kind); + return this.finalize(node, new Node.RestElement(arg)); + }; + Parser.prototype.parseArrayPattern = function (params, kind) { + var node = this.createNode(); + this.expect('['); + var elements = []; + while (!this.match(']')) { + if (this.match(',')) { + this.nextToken(); + elements.push(null); + } + else { + if (this.match('...')) { + elements.push(this.parseBindingRestElement(params, kind)); + break; + } + else { + elements.push(this.parsePatternWithDefault(params, kind)); + } + if (!this.match(']')) { + this.expect(','); + } + } + } + this.expect(']'); + return this.finalize(node, new Node.ArrayPattern(elements)); + }; + Parser.prototype.parsePropertyPattern = function (params, kind) { + var node = this.createNode(); + var computed = false; + var shorthand = false; + var method = false; + var key; + var value; + if (this.lookahead.type === 3 /* Identifier */) { + var keyToken = this.lookahead; + key = this.parseVariableIdentifier(); + var init = this.finalize(node, new Node.Identifier(keyToken.value)); + if (this.match('=')) { + params.push(keyToken); + shorthand = true; + this.nextToken(); + var expr = this.parseAssignmentExpression(); + value = this.finalize(this.startNode(keyToken), new Node.AssignmentPattern(init, expr)); + } + else if (!this.match(':')) { + params.push(keyToken); + shorthand = true; + value = init; + } + else { + this.expect(':'); + value = this.parsePatternWithDefault(params, kind); + } + } + else { + computed = this.match('['); + key = this.parseObjectPropertyKey(); + this.expect(':'); + value = this.parsePatternWithDefault(params, kind); + } + return this.finalize(node, new Node.Property('init', key, computed, value, method, shorthand)); + }; + Parser.prototype.parseObjectPattern = function (params, kind) { + var node = this.createNode(); + var properties = []; + this.expect('{'); + while (!this.match('}')) { + properties.push(this.parsePropertyPattern(params, kind)); + if (!this.match('}')) { + this.expect(','); + } + } + this.expect('}'); + return this.finalize(node, new Node.ObjectPattern(properties)); + }; + Parser.prototype.parsePattern = function (params, kind) { + var pattern; + if (this.match('[')) { + pattern = this.parseArrayPattern(params, kind); + } + else if (this.match('{')) { + pattern = this.parseObjectPattern(params, kind); + } + else { + if (this.matchKeyword('let') && (kind === 'const' || kind === 'let')) { + this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.LetInLexicalBinding); + } + params.push(this.lookahead); + pattern = this.parseVariableIdentifier(kind); + } + return pattern; + }; + Parser.prototype.parsePatternWithDefault = function (params, kind) { + var startToken = this.lookahead; + var pattern = this.parsePattern(params, kind); + if (this.match('=')) { + this.nextToken(); + var previousAllowYield = this.context.allowYield; + this.context.allowYield = true; + var right = this.isolateCoverGrammar(this.parseAssignmentExpression); + this.context.allowYield = previousAllowYield; + pattern = this.finalize(this.startNode(startToken), new Node.AssignmentPattern(pattern, right)); + } + return pattern; + }; + // https://tc39.github.io/ecma262/#sec-variable-statement + Parser.prototype.parseVariableIdentifier = function (kind) { + var node = this.createNode(); + var token = this.nextToken(); + if (token.type === 4 /* Keyword */ && token.value === 'yield') { + if (this.context.strict) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); + } + else if (!this.context.allowYield) { + this.throwUnexpectedToken(token); + } + } + else if (token.type !== 3 /* Identifier */) { + if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); + } + else { + if (this.context.strict || token.value !== 'let' || kind !== 'var') { + this.throwUnexpectedToken(token); + } + } + } + else if ((this.context.isModule || this.context.await) && token.type === 3 /* Identifier */ && token.value === 'await') { + this.tolerateUnexpectedToken(token); + } + return this.finalize(node, new Node.Identifier(token.value)); + }; + Parser.prototype.parseVariableDeclaration = function (options) { + var node = this.createNode(); + var params = []; + var id = this.parsePattern(params, 'var'); + if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { + if (this.scanner.isRestrictedWord(id.name)) { + this.tolerateError(messages_1.Messages.StrictVarName); + } + } + var init = null; + if (this.match('=')) { + this.nextToken(); + init = this.isolateCoverGrammar(this.parseAssignmentExpression); + } + else if (id.type !== syntax_1.Syntax.Identifier && !options.inFor) { + this.expect('='); + } + return this.finalize(node, new Node.VariableDeclarator(id, init)); + }; + Parser.prototype.parseVariableDeclarationList = function (options) { + var opt = { inFor: options.inFor }; + var list = []; + list.push(this.parseVariableDeclaration(opt)); + while (this.match(',')) { + this.nextToken(); + list.push(this.parseVariableDeclaration(opt)); + } + return list; + }; + Parser.prototype.parseVariableStatement = function () { + var node = this.createNode(); + this.expectKeyword('var'); + var declarations = this.parseVariableDeclarationList({ inFor: false }); + this.consumeSemicolon(); + return this.finalize(node, new Node.VariableDeclaration(declarations, 'var')); + }; + // https://tc39.github.io/ecma262/#sec-empty-statement + Parser.prototype.parseEmptyStatement = function () { + var node = this.createNode(); + this.expect(';'); + return this.finalize(node, new Node.EmptyStatement()); + }; + // https://tc39.github.io/ecma262/#sec-expression-statement + Parser.prototype.parseExpressionStatement = function () { + var node = this.createNode(); + var expr = this.parseExpression(); + this.consumeSemicolon(); + return this.finalize(node, new Node.ExpressionStatement(expr)); + }; + // https://tc39.github.io/ecma262/#sec-if-statement + Parser.prototype.parseIfClause = function () { + if (this.context.strict && this.matchKeyword('function')) { + this.tolerateError(messages_1.Messages.StrictFunction); + } + return this.parseStatement(); + }; + Parser.prototype.parseIfStatement = function () { + var node = this.createNode(); + var consequent; + var alternate = null; + this.expectKeyword('if'); + this.expect('('); + var test = this.parseExpression(); + if (!this.match(')') && this.config.tolerant) { + this.tolerateUnexpectedToken(this.nextToken()); + consequent = this.finalize(this.createNode(), new Node.EmptyStatement()); + } + else { + this.expect(')'); + consequent = this.parseIfClause(); + if (this.matchKeyword('else')) { + this.nextToken(); + alternate = this.parseIfClause(); + } + } + return this.finalize(node, new Node.IfStatement(test, consequent, alternate)); + }; + // https://tc39.github.io/ecma262/#sec-do-while-statement + Parser.prototype.parseDoWhileStatement = function () { + var node = this.createNode(); + this.expectKeyword('do'); + var previousInIteration = this.context.inIteration; + this.context.inIteration = true; + var body = this.parseStatement(); + this.context.inIteration = previousInIteration; + this.expectKeyword('while'); + this.expect('('); + var test = this.parseExpression(); + if (!this.match(')') && this.config.tolerant) { + this.tolerateUnexpectedToken(this.nextToken()); + } + else { + this.expect(')'); + if (this.match(';')) { + this.nextToken(); + } + } + return this.finalize(node, new Node.DoWhileStatement(body, test)); + }; + // https://tc39.github.io/ecma262/#sec-while-statement + Parser.prototype.parseWhileStatement = function () { + var node = this.createNode(); + var body; + this.expectKeyword('while'); + this.expect('('); + var test = this.parseExpression(); + if (!this.match(')') && this.config.tolerant) { + this.tolerateUnexpectedToken(this.nextToken()); + body = this.finalize(this.createNode(), new Node.EmptyStatement()); + } + else { + this.expect(')'); + var previousInIteration = this.context.inIteration; + this.context.inIteration = true; + body = this.parseStatement(); + this.context.inIteration = previousInIteration; + } + return this.finalize(node, new Node.WhileStatement(test, body)); + }; + // https://tc39.github.io/ecma262/#sec-for-statement + // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements + Parser.prototype.parseForStatement = function () { + var init = null; + var test = null; + var update = null; + var forIn = true; + var left, right; + var node = this.createNode(); + this.expectKeyword('for'); + this.expect('('); + if (this.match(';')) { + this.nextToken(); + } + else { + if (this.matchKeyword('var')) { + init = this.createNode(); + this.nextToken(); + var previousAllowIn = this.context.allowIn; + this.context.allowIn = false; + var declarations = this.parseVariableDeclarationList({ inFor: true }); + this.context.allowIn = previousAllowIn; + if (declarations.length === 1 && this.matchKeyword('in')) { + var decl = declarations[0]; + if (decl.init && (decl.id.type === syntax_1.Syntax.ArrayPattern || decl.id.type === syntax_1.Syntax.ObjectPattern || this.context.strict)) { + this.tolerateError(messages_1.Messages.ForInOfLoopInitializer, 'for-in'); + } + init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); + this.nextToken(); + left = init; + right = this.parseExpression(); + init = null; + } + else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { + init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); + this.nextToken(); + left = init; + right = this.parseAssignmentExpression(); + init = null; + forIn = false; + } + else { + init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); + this.expect(';'); + } + } + else if (this.matchKeyword('const') || this.matchKeyword('let')) { + init = this.createNode(); + var kind = this.nextToken().value; + if (!this.context.strict && this.lookahead.value === 'in') { + init = this.finalize(init, new Node.Identifier(kind)); + this.nextToken(); + left = init; + right = this.parseExpression(); + init = null; + } + else { + var previousAllowIn = this.context.allowIn; + this.context.allowIn = false; + var declarations = this.parseBindingList(kind, { inFor: true }); + this.context.allowIn = previousAllowIn; + if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword('in')) { + init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); + this.nextToken(); + left = init; + right = this.parseExpression(); + init = null; + } + else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { + init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); + this.nextToken(); + left = init; + right = this.parseAssignmentExpression(); + init = null; + forIn = false; + } + else { + this.consumeSemicolon(); + init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); + } + } + } + else { + var initStartToken = this.lookahead; + var previousAllowIn = this.context.allowIn; + this.context.allowIn = false; + init = this.inheritCoverGrammar(this.parseAssignmentExpression); + this.context.allowIn = previousAllowIn; + if (this.matchKeyword('in')) { + if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { + this.tolerateError(messages_1.Messages.InvalidLHSInForIn); + } + this.nextToken(); + this.reinterpretExpressionAsPattern(init); + left = init; + right = this.parseExpression(); + init = null; + } + else if (this.matchContextualKeyword('of')) { + if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { + this.tolerateError(messages_1.Messages.InvalidLHSInForLoop); + } + this.nextToken(); + this.reinterpretExpressionAsPattern(init); + left = init; + right = this.parseAssignmentExpression(); + init = null; + forIn = false; + } + else { + if (this.match(',')) { + var initSeq = [init]; + while (this.match(',')) { + this.nextToken(); + initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); + } + init = this.finalize(this.startNode(initStartToken), new Node.SequenceExpression(initSeq)); + } + this.expect(';'); + } + } + } + if (typeof left === 'undefined') { + if (!this.match(';')) { + test = this.parseExpression(); + } + this.expect(';'); + if (!this.match(')')) { + update = this.parseExpression(); + } + } + var body; + if (!this.match(')') && this.config.tolerant) { + this.tolerateUnexpectedToken(this.nextToken()); + body = this.finalize(this.createNode(), new Node.EmptyStatement()); + } + else { + this.expect(')'); + var previousInIteration = this.context.inIteration; + this.context.inIteration = true; + body = this.isolateCoverGrammar(this.parseStatement); + this.context.inIteration = previousInIteration; + } + return (typeof left === 'undefined') ? + this.finalize(node, new Node.ForStatement(init, test, update, body)) : + forIn ? this.finalize(node, new Node.ForInStatement(left, right, body)) : + this.finalize(node, new Node.ForOfStatement(left, right, body)); + }; + // https://tc39.github.io/ecma262/#sec-continue-statement + Parser.prototype.parseContinueStatement = function () { + var node = this.createNode(); + this.expectKeyword('continue'); + var label = null; + if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { + var id = this.parseVariableIdentifier(); + label = id; + var key = '$' + id.name; + if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { + this.throwError(messages_1.Messages.UnknownLabel, id.name); + } + } + this.consumeSemicolon(); + if (label === null && !this.context.inIteration) { + this.throwError(messages_1.Messages.IllegalContinue); + } + return this.finalize(node, new Node.ContinueStatement(label)); + }; + // https://tc39.github.io/ecma262/#sec-break-statement + Parser.prototype.parseBreakStatement = function () { + var node = this.createNode(); + this.expectKeyword('break'); + var label = null; + if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { + var id = this.parseVariableIdentifier(); + var key = '$' + id.name; + if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { + this.throwError(messages_1.Messages.UnknownLabel, id.name); + } + label = id; + } + this.consumeSemicolon(); + if (label === null && !this.context.inIteration && !this.context.inSwitch) { + this.throwError(messages_1.Messages.IllegalBreak); + } + return this.finalize(node, new Node.BreakStatement(label)); + }; + // https://tc39.github.io/ecma262/#sec-return-statement + Parser.prototype.parseReturnStatement = function () { + if (!this.context.inFunctionBody) { + this.tolerateError(messages_1.Messages.IllegalReturn); + } + var node = this.createNode(); + this.expectKeyword('return'); + var hasArgument = (!this.match(';') && !this.match('}') && + !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */) || + this.lookahead.type === 8 /* StringLiteral */ || + this.lookahead.type === 10 /* Template */; + var argument = hasArgument ? this.parseExpression() : null; + this.consumeSemicolon(); + return this.finalize(node, new Node.ReturnStatement(argument)); + }; + // https://tc39.github.io/ecma262/#sec-with-statement + Parser.prototype.parseWithStatement = function () { + if (this.context.strict) { + this.tolerateError(messages_1.Messages.StrictModeWith); + } + var node = this.createNode(); + var body; + this.expectKeyword('with'); + this.expect('('); + var object = this.parseExpression(); + if (!this.match(')') && this.config.tolerant) { + this.tolerateUnexpectedToken(this.nextToken()); + body = this.finalize(this.createNode(), new Node.EmptyStatement()); + } + else { + this.expect(')'); + body = this.parseStatement(); + } + return this.finalize(node, new Node.WithStatement(object, body)); + }; + // https://tc39.github.io/ecma262/#sec-switch-statement + Parser.prototype.parseSwitchCase = function () { + var node = this.createNode(); + var test; + if (this.matchKeyword('default')) { + this.nextToken(); + test = null; + } + else { + this.expectKeyword('case'); + test = this.parseExpression(); + } + this.expect(':'); + var consequent = []; + while (true) { + if (this.match('}') || this.matchKeyword('default') || this.matchKeyword('case')) { + break; + } + consequent.push(this.parseStatementListItem()); + } + return this.finalize(node, new Node.SwitchCase(test, consequent)); + }; + Parser.prototype.parseSwitchStatement = function () { + var node = this.createNode(); + this.expectKeyword('switch'); + this.expect('('); + var discriminant = this.parseExpression(); + this.expect(')'); + var previousInSwitch = this.context.inSwitch; + this.context.inSwitch = true; + var cases = []; + var defaultFound = false; + this.expect('{'); + while (true) { + if (this.match('}')) { + break; + } + var clause = this.parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + this.throwError(messages_1.Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + this.expect('}'); + this.context.inSwitch = previousInSwitch; + return this.finalize(node, new Node.SwitchStatement(discriminant, cases)); + }; + // https://tc39.github.io/ecma262/#sec-labelled-statements + Parser.prototype.parseLabelledStatement = function () { + var node = this.createNode(); + var expr = this.parseExpression(); + var statement; + if ((expr.type === syntax_1.Syntax.Identifier) && this.match(':')) { + this.nextToken(); + var id = expr; + var key = '$' + id.name; + if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { + this.throwError(messages_1.Messages.Redeclaration, 'Label', id.name); + } + this.context.labelSet[key] = true; + var body = void 0; + if (this.matchKeyword('class')) { + this.tolerateUnexpectedToken(this.lookahead); + body = this.parseClassDeclaration(); + } + else if (this.matchKeyword('function')) { + var token = this.lookahead; + var declaration = this.parseFunctionDeclaration(); + if (this.context.strict) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunction); + } + else if (declaration.generator) { + this.tolerateUnexpectedToken(token, messages_1.Messages.GeneratorInLegacyContext); + } + body = declaration; + } + else { + body = this.parseStatement(); + } + delete this.context.labelSet[key]; + statement = new Node.LabeledStatement(id, body); + } + else { + this.consumeSemicolon(); + statement = new Node.ExpressionStatement(expr); + } + return this.finalize(node, statement); + }; + // https://tc39.github.io/ecma262/#sec-throw-statement + Parser.prototype.parseThrowStatement = function () { + var node = this.createNode(); + this.expectKeyword('throw'); + if (this.hasLineTerminator) { + this.throwError(messages_1.Messages.NewlineAfterThrow); + } + var argument = this.parseExpression(); + this.consumeSemicolon(); + return this.finalize(node, new Node.ThrowStatement(argument)); + }; + // https://tc39.github.io/ecma262/#sec-try-statement + Parser.prototype.parseCatchClause = function () { + var node = this.createNode(); + this.expectKeyword('catch'); + this.expect('('); + if (this.match(')')) { + this.throwUnexpectedToken(this.lookahead); + } + var params = []; + var param = this.parsePattern(params); + var paramMap = {}; + for (var i = 0; i < params.length; i++) { + var key = '$' + params[i].value; + if (Object.prototype.hasOwnProperty.call(paramMap, key)) { + this.tolerateError(messages_1.Messages.DuplicateBinding, params[i].value); + } + paramMap[key] = true; + } + if (this.context.strict && param.type === syntax_1.Syntax.Identifier) { + if (this.scanner.isRestrictedWord(param.name)) { + this.tolerateError(messages_1.Messages.StrictCatchVariable); + } + } + this.expect(')'); + var body = this.parseBlock(); + return this.finalize(node, new Node.CatchClause(param, body)); + }; + Parser.prototype.parseFinallyClause = function () { + this.expectKeyword('finally'); + return this.parseBlock(); + }; + Parser.prototype.parseTryStatement = function () { + var node = this.createNode(); + this.expectKeyword('try'); + var block = this.parseBlock(); + var handler = this.matchKeyword('catch') ? this.parseCatchClause() : null; + var finalizer = this.matchKeyword('finally') ? this.parseFinallyClause() : null; + if (!handler && !finalizer) { + this.throwError(messages_1.Messages.NoCatchOrFinally); + } + return this.finalize(node, new Node.TryStatement(block, handler, finalizer)); + }; + // https://tc39.github.io/ecma262/#sec-debugger-statement + Parser.prototype.parseDebuggerStatement = function () { + var node = this.createNode(); + this.expectKeyword('debugger'); + this.consumeSemicolon(); + return this.finalize(node, new Node.DebuggerStatement()); + }; + // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations + Parser.prototype.parseStatement = function () { + var statement; + switch (this.lookahead.type) { + case 1 /* BooleanLiteral */: + case 5 /* NullLiteral */: + case 6 /* NumericLiteral */: + case 8 /* StringLiteral */: + case 10 /* Template */: + case 9 /* RegularExpression */: + statement = this.parseExpressionStatement(); + break; + case 7 /* Punctuator */: + var value = this.lookahead.value; + if (value === '{') { + statement = this.parseBlock(); + } + else if (value === '(') { + statement = this.parseExpressionStatement(); + } + else if (value === ';') { + statement = this.parseEmptyStatement(); + } + else { + statement = this.parseExpressionStatement(); + } + break; + case 3 /* Identifier */: + statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement(); + break; + case 4 /* Keyword */: + switch (this.lookahead.value) { + case 'break': + statement = this.parseBreakStatement(); + break; + case 'continue': + statement = this.parseContinueStatement(); + break; + case 'debugger': + statement = this.parseDebuggerStatement(); + break; + case 'do': + statement = this.parseDoWhileStatement(); + break; + case 'for': + statement = this.parseForStatement(); + break; + case 'function': + statement = this.parseFunctionDeclaration(); + break; + case 'if': + statement = this.parseIfStatement(); + break; + case 'return': + statement = this.parseReturnStatement(); + break; + case 'switch': + statement = this.parseSwitchStatement(); + break; + case 'throw': + statement = this.parseThrowStatement(); + break; + case 'try': + statement = this.parseTryStatement(); + break; + case 'var': + statement = this.parseVariableStatement(); + break; + case 'while': + statement = this.parseWhileStatement(); + break; + case 'with': + statement = this.parseWithStatement(); + break; + default: + statement = this.parseExpressionStatement(); + break; + } + break; + default: + statement = this.throwUnexpectedToken(this.lookahead); + } + return statement; + }; + // https://tc39.github.io/ecma262/#sec-function-definitions + Parser.prototype.parseFunctionSourceElements = function () { + var node = this.createNode(); + this.expect('{'); + var body = this.parseDirectivePrologues(); + var previousLabelSet = this.context.labelSet; + var previousInIteration = this.context.inIteration; + var previousInSwitch = this.context.inSwitch; + var previousInFunctionBody = this.context.inFunctionBody; + this.context.labelSet = {}; + this.context.inIteration = false; + this.context.inSwitch = false; + this.context.inFunctionBody = true; + while (this.lookahead.type !== 2 /* EOF */) { + if (this.match('}')) { + break; + } + body.push(this.parseStatementListItem()); + } + this.expect('}'); + this.context.labelSet = previousLabelSet; + this.context.inIteration = previousInIteration; + this.context.inSwitch = previousInSwitch; + this.context.inFunctionBody = previousInFunctionBody; + return this.finalize(node, new Node.BlockStatement(body)); + }; + Parser.prototype.validateParam = function (options, param, name) { + var key = '$' + name; + if (this.context.strict) { + if (this.scanner.isRestrictedWord(name)) { + options.stricted = param; + options.message = messages_1.Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = messages_1.Messages.StrictParamDupe; + } + } + else if (!options.firstRestricted) { + if (this.scanner.isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = messages_1.Messages.StrictParamName; + } + else if (this.scanner.isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = messages_1.Messages.StrictReservedWord; + } + else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = messages_1.Messages.StrictParamDupe; + } + } + /* istanbul ignore next */ + if (typeof Object.defineProperty === 'function') { + Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true }); + } + else { + options.paramSet[key] = true; + } + }; + Parser.prototype.parseRestElement = function (params) { + var node = this.createNode(); + this.expect('...'); + var arg = this.parsePattern(params); + if (this.match('=')) { + this.throwError(messages_1.Messages.DefaultRestParameter); + } + if (!this.match(')')) { + this.throwError(messages_1.Messages.ParameterAfterRestParameter); + } + return this.finalize(node, new Node.RestElement(arg)); + }; + Parser.prototype.parseFormalParameter = function (options) { + var params = []; + var param = this.match('...') ? this.parseRestElement(params) : this.parsePatternWithDefault(params); + for (var i = 0; i < params.length; i++) { + this.validateParam(options, params[i], params[i].value); + } + options.simple = options.simple && (param instanceof Node.Identifier); + options.params.push(param); + }; + Parser.prototype.parseFormalParameters = function (firstRestricted) { + var options; + options = { + simple: true, + params: [], + firstRestricted: firstRestricted + }; + this.expect('('); + if (!this.match(')')) { + options.paramSet = {}; + while (this.lookahead.type !== 2 /* EOF */) { + this.parseFormalParameter(options); + if (this.match(')')) { + break; + } + this.expect(','); + if (this.match(')')) { + break; + } + } + } + this.expect(')'); + return { + simple: options.simple, + params: options.params, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + }; + Parser.prototype.matchAsyncFunction = function () { + var match = this.matchContextualKeyword('async'); + if (match) { + var state = this.scanner.saveState(); + this.scanner.scanComments(); + var next = this.scanner.lex(); + this.scanner.restoreState(state); + match = (state.lineNumber === next.lineNumber) && (next.type === 4 /* Keyword */) && (next.value === 'function'); + } + return match; + }; + Parser.prototype.parseFunctionDeclaration = function (identifierIsOptional) { + var node = this.createNode(); + var isAsync = this.matchContextualKeyword('async'); + if (isAsync) { + this.nextToken(); + } + this.expectKeyword('function'); + var isGenerator = isAsync ? false : this.match('*'); + if (isGenerator) { + this.nextToken(); + } + var message; + var id = null; + var firstRestricted = null; + if (!identifierIsOptional || !this.match('(')) { + var token = this.lookahead; + id = this.parseVariableIdentifier(); + if (this.context.strict) { + if (this.scanner.isRestrictedWord(token.value)) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); + } + } + else { + if (this.scanner.isRestrictedWord(token.value)) { + firstRestricted = token; + message = messages_1.Messages.StrictFunctionName; + } + else if (this.scanner.isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = messages_1.Messages.StrictReservedWord; + } + } + } + var previousAllowAwait = this.context.await; + var previousAllowYield = this.context.allowYield; + this.context.await = isAsync; + this.context.allowYield = !isGenerator; + var formalParameters = this.parseFormalParameters(firstRestricted); + var params = formalParameters.params; + var stricted = formalParameters.stricted; + firstRestricted = formalParameters.firstRestricted; + if (formalParameters.message) { + message = formalParameters.message; + } + var previousStrict = this.context.strict; + var previousAllowStrictDirective = this.context.allowStrictDirective; + this.context.allowStrictDirective = formalParameters.simple; + var body = this.parseFunctionSourceElements(); + if (this.context.strict && firstRestricted) { + this.throwUnexpectedToken(firstRestricted, message); + } + if (this.context.strict && stricted) { + this.tolerateUnexpectedToken(stricted, message); + } + this.context.strict = previousStrict; + this.context.allowStrictDirective = previousAllowStrictDirective; + this.context.await = previousAllowAwait; + this.context.allowYield = previousAllowYield; + return isAsync ? this.finalize(node, new Node.AsyncFunctionDeclaration(id, params, body)) : + this.finalize(node, new Node.FunctionDeclaration(id, params, body, isGenerator)); + }; + Parser.prototype.parseFunctionExpression = function () { + var node = this.createNode(); + var isAsync = this.matchContextualKeyword('async'); + if (isAsync) { + this.nextToken(); + } + this.expectKeyword('function'); + var isGenerator = isAsync ? false : this.match('*'); + if (isGenerator) { + this.nextToken(); + } + var message; + var id = null; + var firstRestricted; + var previousAllowAwait = this.context.await; + var previousAllowYield = this.context.allowYield; + this.context.await = isAsync; + this.context.allowYield = !isGenerator; + if (!this.match('(')) { + var token = this.lookahead; + id = (!this.context.strict && !isGenerator && this.matchKeyword('yield')) ? this.parseIdentifierName() : this.parseVariableIdentifier(); + if (this.context.strict) { + if (this.scanner.isRestrictedWord(token.value)) { + this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); + } + } + else { + if (this.scanner.isRestrictedWord(token.value)) { + firstRestricted = token; + message = messages_1.Messages.StrictFunctionName; + } + else if (this.scanner.isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = messages_1.Messages.StrictReservedWord; + } + } + } + var formalParameters = this.parseFormalParameters(firstRestricted); + var params = formalParameters.params; + var stricted = formalParameters.stricted; + firstRestricted = formalParameters.firstRestricted; + if (formalParameters.message) { + message = formalParameters.message; + } + var previousStrict = this.context.strict; + var previousAllowStrictDirective = this.context.allowStrictDirective; + this.context.allowStrictDirective = formalParameters.simple; + var body = this.parseFunctionSourceElements(); + if (this.context.strict && firstRestricted) { + this.throwUnexpectedToken(firstRestricted, message); + } + if (this.context.strict && stricted) { + this.tolerateUnexpectedToken(stricted, message); + } + this.context.strict = previousStrict; + this.context.allowStrictDirective = previousAllowStrictDirective; + this.context.await = previousAllowAwait; + this.context.allowYield = previousAllowYield; + return isAsync ? this.finalize(node, new Node.AsyncFunctionExpression(id, params, body)) : + this.finalize(node, new Node.FunctionExpression(id, params, body, isGenerator)); + }; + // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive + Parser.prototype.parseDirective = function () { + var token = this.lookahead; + var node = this.createNode(); + var expr = this.parseExpression(); + var directive = (expr.type === syntax_1.Syntax.Literal) ? this.getTokenRaw(token).slice(1, -1) : null; + this.consumeSemicolon(); + return this.finalize(node, directive ? new Node.Directive(expr, directive) : new Node.ExpressionStatement(expr)); + }; + Parser.prototype.parseDirectivePrologues = function () { + var firstRestricted = null; + var body = []; + while (true) { + var token = this.lookahead; + if (token.type !== 8 /* StringLiteral */) { + break; + } + var statement = this.parseDirective(); + body.push(statement); + var directive = statement.directive; + if (typeof directive !== 'string') { + break; + } + if (directive === 'use strict') { + this.context.strict = true; + if (firstRestricted) { + this.tolerateUnexpectedToken(firstRestricted, messages_1.Messages.StrictOctalLiteral); + } + if (!this.context.allowStrictDirective) { + this.tolerateUnexpectedToken(token, messages_1.Messages.IllegalLanguageModeDirective); + } + } + else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + return body; + }; + // https://tc39.github.io/ecma262/#sec-method-definitions + Parser.prototype.qualifiedPropertyName = function (token) { + switch (token.type) { + case 3 /* Identifier */: + case 8 /* StringLiteral */: + case 1 /* BooleanLiteral */: + case 5 /* NullLiteral */: + case 6 /* NumericLiteral */: + case 4 /* Keyword */: + return true; + case 7 /* Punctuator */: + return token.value === '['; + default: + break; + } + return false; + }; + Parser.prototype.parseGetterMethod = function () { + var node = this.createNode(); + var isGenerator = false; + var previousAllowYield = this.context.allowYield; + this.context.allowYield = !isGenerator; + var formalParameters = this.parseFormalParameters(); + if (formalParameters.params.length > 0) { + this.tolerateError(messages_1.Messages.BadGetterArity); + } + var method = this.parsePropertyMethod(formalParameters); + this.context.allowYield = previousAllowYield; + return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); + }; + Parser.prototype.parseSetterMethod = function () { + var node = this.createNode(); + var isGenerator = false; + var previousAllowYield = this.context.allowYield; + this.context.allowYield = !isGenerator; + var formalParameters = this.parseFormalParameters(); + if (formalParameters.params.length !== 1) { + this.tolerateError(messages_1.Messages.BadSetterArity); + } + else if (formalParameters.params[0] instanceof Node.RestElement) { + this.tolerateError(messages_1.Messages.BadSetterRestParameter); + } + var method = this.parsePropertyMethod(formalParameters); + this.context.allowYield = previousAllowYield; + return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); + }; + Parser.prototype.parseGeneratorMethod = function () { + var node = this.createNode(); + var isGenerator = true; + var previousAllowYield = this.context.allowYield; + this.context.allowYield = true; + var params = this.parseFormalParameters(); + this.context.allowYield = false; + var method = this.parsePropertyMethod(params); + this.context.allowYield = previousAllowYield; + return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); + }; + // https://tc39.github.io/ecma262/#sec-generator-function-definitions + Parser.prototype.isStartOfExpression = function () { + var start = true; + var value = this.lookahead.value; + switch (this.lookahead.type) { + case 7 /* Punctuator */: + start = (value === '[') || (value === '(') || (value === '{') || + (value === '+') || (value === '-') || + (value === '!') || (value === '~') || + (value === '++') || (value === '--') || + (value === '/') || (value === '/='); // regular expression literal + break; + case 4 /* Keyword */: + start = (value === 'class') || (value === 'delete') || + (value === 'function') || (value === 'let') || (value === 'new') || + (value === 'super') || (value === 'this') || (value === 'typeof') || + (value === 'void') || (value === 'yield'); + break; + default: + break; + } + return start; + }; + Parser.prototype.parseYieldExpression = function () { + var node = this.createNode(); + this.expectKeyword('yield'); + var argument = null; + var delegate = false; + if (!this.hasLineTerminator) { + var previousAllowYield = this.context.allowYield; + this.context.allowYield = false; + delegate = this.match('*'); + if (delegate) { + this.nextToken(); + argument = this.parseAssignmentExpression(); + } + else if (this.isStartOfExpression()) { + argument = this.parseAssignmentExpression(); + } + this.context.allowYield = previousAllowYield; + } + return this.finalize(node, new Node.YieldExpression(argument, delegate)); + }; + // https://tc39.github.io/ecma262/#sec-class-definitions + Parser.prototype.parseClassElement = function (hasConstructor) { + var token = this.lookahead; + var node = this.createNode(); + var kind = ''; + var key = null; + var value = null; + var computed = false; + var method = false; + var isStatic = false; + var isAsync = false; + if (this.match('*')) { + this.nextToken(); + } + else { + computed = this.match('['); + key = this.parseObjectPropertyKey(); + var id = key; + if (id.name === 'static' && (this.qualifiedPropertyName(this.lookahead) || this.match('*'))) { + token = this.lookahead; + isStatic = true; + computed = this.match('['); + if (this.match('*')) { + this.nextToken(); + } + else { + key = this.parseObjectPropertyKey(); + } + } + if ((token.type === 3 /* Identifier */) && !this.hasLineTerminator && (token.value === 'async')) { + var punctuator = this.lookahead.value; + if (punctuator !== ':' && punctuator !== '(' && punctuator !== '*') { + isAsync = true; + token = this.lookahead; + key = this.parseObjectPropertyKey(); + if (token.type === 3 /* Identifier */ && token.value === 'constructor') { + this.tolerateUnexpectedToken(token, messages_1.Messages.ConstructorIsAsync); + } + } + } + } + var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); + if (token.type === 3 /* Identifier */) { + if (token.value === 'get' && lookaheadPropertyKey) { + kind = 'get'; + computed = this.match('['); + key = this.parseObjectPropertyKey(); + this.context.allowYield = false; + value = this.parseGetterMethod(); + } + else if (token.value === 'set' && lookaheadPropertyKey) { + kind = 'set'; + computed = this.match('['); + key = this.parseObjectPropertyKey(); + value = this.parseSetterMethod(); + } + } + else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { + kind = 'init'; + computed = this.match('['); + key = this.parseObjectPropertyKey(); + value = this.parseGeneratorMethod(); + method = true; + } + if (!kind && key && this.match('(')) { + kind = 'init'; + value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); + method = true; + } + if (!kind) { + this.throwUnexpectedToken(this.lookahead); + } + if (kind === 'init') { + kind = 'method'; + } + if (!computed) { + if (isStatic && this.isPropertyKey(key, 'prototype')) { + this.throwUnexpectedToken(token, messages_1.Messages.StaticPrototype); + } + if (!isStatic && this.isPropertyKey(key, 'constructor')) { + if (kind !== 'method' || !method || (value && value.generator)) { + this.throwUnexpectedToken(token, messages_1.Messages.ConstructorSpecialMethod); + } + if (hasConstructor.value) { + this.throwUnexpectedToken(token, messages_1.Messages.DuplicateConstructor); + } + else { + hasConstructor.value = true; + } + kind = 'constructor'; + } + } + return this.finalize(node, new Node.MethodDefinition(key, computed, value, kind, isStatic)); + }; + Parser.prototype.parseClassElementList = function () { + var body = []; + var hasConstructor = { value: false }; + this.expect('{'); + while (!this.match('}')) { + if (this.match(';')) { + this.nextToken(); + } + else { + body.push(this.parseClassElement(hasConstructor)); + } + } + this.expect('}'); + return body; + }; + Parser.prototype.parseClassBody = function () { + var node = this.createNode(); + var elementList = this.parseClassElementList(); + return this.finalize(node, new Node.ClassBody(elementList)); + }; + Parser.prototype.parseClassDeclaration = function (identifierIsOptional) { + var node = this.createNode(); + var previousStrict = this.context.strict; + this.context.strict = true; + this.expectKeyword('class'); + var id = (identifierIsOptional && (this.lookahead.type !== 3 /* Identifier */)) ? null : this.parseVariableIdentifier(); + var superClass = null; + if (this.matchKeyword('extends')) { + this.nextToken(); + superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); + } + var classBody = this.parseClassBody(); + this.context.strict = previousStrict; + return this.finalize(node, new Node.ClassDeclaration(id, superClass, classBody)); + }; + Parser.prototype.parseClassExpression = function () { + var node = this.createNode(); + var previousStrict = this.context.strict; + this.context.strict = true; + this.expectKeyword('class'); + var id = (this.lookahead.type === 3 /* Identifier */) ? this.parseVariableIdentifier() : null; + var superClass = null; + if (this.matchKeyword('extends')) { + this.nextToken(); + superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); + } + var classBody = this.parseClassBody(); + this.context.strict = previousStrict; + return this.finalize(node, new Node.ClassExpression(id, superClass, classBody)); + }; + // https://tc39.github.io/ecma262/#sec-scripts + // https://tc39.github.io/ecma262/#sec-modules + Parser.prototype.parseModule = function () { + this.context.strict = true; + this.context.isModule = true; + this.scanner.isModule = true; + var node = this.createNode(); + var body = this.parseDirectivePrologues(); + while (this.lookahead.type !== 2 /* EOF */) { + body.push(this.parseStatementListItem()); + } + return this.finalize(node, new Node.Module(body)); + }; + Parser.prototype.parseScript = function () { + var node = this.createNode(); + var body = this.parseDirectivePrologues(); + while (this.lookahead.type !== 2 /* EOF */) { + body.push(this.parseStatementListItem()); + } + return this.finalize(node, new Node.Script(body)); + }; + // https://tc39.github.io/ecma262/#sec-imports + Parser.prototype.parseModuleSpecifier = function () { + var node = this.createNode(); + if (this.lookahead.type !== 8 /* StringLiteral */) { + this.throwError(messages_1.Messages.InvalidModuleSpecifier); + } + var token = this.nextToken(); + var raw = this.getTokenRaw(token); + return this.finalize(node, new Node.Literal(token.value, raw)); + }; + // import {} ...; + Parser.prototype.parseImportSpecifier = function () { + var node = this.createNode(); + var imported; + var local; + if (this.lookahead.type === 3 /* Identifier */) { + imported = this.parseVariableIdentifier(); + local = imported; + if (this.matchContextualKeyword('as')) { + this.nextToken(); + local = this.parseVariableIdentifier(); + } + } + else { + imported = this.parseIdentifierName(); + local = imported; + if (this.matchContextualKeyword('as')) { + this.nextToken(); + local = this.parseVariableIdentifier(); + } + else { + this.throwUnexpectedToken(this.nextToken()); + } + } + return this.finalize(node, new Node.ImportSpecifier(local, imported)); + }; + // {foo, bar as bas} + Parser.prototype.parseNamedImports = function () { + this.expect('{'); + var specifiers = []; + while (!this.match('}')) { + specifiers.push(this.parseImportSpecifier()); + if (!this.match('}')) { + this.expect(','); + } + } + this.expect('}'); + return specifiers; + }; + // import ...; + Parser.prototype.parseImportDefaultSpecifier = function () { + var node = this.createNode(); + var local = this.parseIdentifierName(); + return this.finalize(node, new Node.ImportDefaultSpecifier(local)); + }; + // import <* as foo> ...; + Parser.prototype.parseImportNamespaceSpecifier = function () { + var node = this.createNode(); + this.expect('*'); + if (!this.matchContextualKeyword('as')) { + this.throwError(messages_1.Messages.NoAsAfterImportNamespace); + } + this.nextToken(); + var local = this.parseIdentifierName(); + return this.finalize(node, new Node.ImportNamespaceSpecifier(local)); + }; + Parser.prototype.parseImportDeclaration = function () { + if (this.context.inFunctionBody) { + this.throwError(messages_1.Messages.IllegalImportDeclaration); + } + var node = this.createNode(); + this.expectKeyword('import'); + var src; + var specifiers = []; + if (this.lookahead.type === 8 /* StringLiteral */) { + // import 'foo'; + src = this.parseModuleSpecifier(); + } + else { + if (this.match('{')) { + // import {bar} + specifiers = specifiers.concat(this.parseNamedImports()); + } + else if (this.match('*')) { + // import * as foo + specifiers.push(this.parseImportNamespaceSpecifier()); + } + else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword('default')) { + // import foo + specifiers.push(this.parseImportDefaultSpecifier()); + if (this.match(',')) { + this.nextToken(); + if (this.match('*')) { + // import foo, * as foo + specifiers.push(this.parseImportNamespaceSpecifier()); + } + else if (this.match('{')) { + // import foo, {bar} + specifiers = specifiers.concat(this.parseNamedImports()); + } + else { + this.throwUnexpectedToken(this.lookahead); + } + } + } + else { + this.throwUnexpectedToken(this.nextToken()); + } + if (!this.matchContextualKeyword('from')) { + var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; + this.throwError(message, this.lookahead.value); + } + this.nextToken(); + src = this.parseModuleSpecifier(); + } + this.consumeSemicolon(); + return this.finalize(node, new Node.ImportDeclaration(specifiers, src)); + }; + // https://tc39.github.io/ecma262/#sec-exports + Parser.prototype.parseExportSpecifier = function () { + var node = this.createNode(); + var local = this.parseIdentifierName(); + var exported = local; + if (this.matchContextualKeyword('as')) { + this.nextToken(); + exported = this.parseIdentifierName(); + } + return this.finalize(node, new Node.ExportSpecifier(local, exported)); + }; + Parser.prototype.parseExportDeclaration = function () { + if (this.context.inFunctionBody) { + this.throwError(messages_1.Messages.IllegalExportDeclaration); + } + var node = this.createNode(); + this.expectKeyword('export'); + var exportDeclaration; + if (this.matchKeyword('default')) { + // export default ... + this.nextToken(); + if (this.matchKeyword('function')) { + // export default function foo () {} + // export default function () {} + var declaration = this.parseFunctionDeclaration(true); + exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); + } + else if (this.matchKeyword('class')) { + // export default class foo {} + var declaration = this.parseClassDeclaration(true); + exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); + } + else if (this.matchContextualKeyword('async')) { + // export default async function f () {} + // export default async function () {} + // export default async x => x + var declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression(); + exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); + } + else { + if (this.matchContextualKeyword('from')) { + this.throwError(messages_1.Messages.UnexpectedToken, this.lookahead.value); + } + // export default {}; + // export default []; + // export default (1 + 2); + var declaration = this.match('{') ? this.parseObjectInitializer() : + this.match('[') ? this.parseArrayInitializer() : this.parseAssignmentExpression(); + this.consumeSemicolon(); + exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); + } + } + else if (this.match('*')) { + // export * from 'foo'; + this.nextToken(); + if (!this.matchContextualKeyword('from')) { + var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; + this.throwError(message, this.lookahead.value); + } + this.nextToken(); + var src = this.parseModuleSpecifier(); + this.consumeSemicolon(); + exportDeclaration = this.finalize(node, new Node.ExportAllDeclaration(src)); + } + else if (this.lookahead.type === 4 /* Keyword */) { + // export var f = 1; + var declaration = void 0; + switch (this.lookahead.value) { + case 'let': + case 'const': + declaration = this.parseLexicalDeclaration({ inFor: false }); + break; + case 'var': + case 'class': + case 'function': + declaration = this.parseStatementListItem(); + break; + default: + this.throwUnexpectedToken(this.lookahead); + } + exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); + } + else if (this.matchAsyncFunction()) { + var declaration = this.parseFunctionDeclaration(); + exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); + } + else { + var specifiers = []; + var source = null; + var isExportFromIdentifier = false; + this.expect('{'); + while (!this.match('}')) { + isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword('default'); + specifiers.push(this.parseExportSpecifier()); + if (!this.match('}')) { + this.expect(','); + } + } + this.expect('}'); + if (this.matchContextualKeyword('from')) { + // export {default} from 'foo'; + // export {foo} from 'foo'; + this.nextToken(); + source = this.parseModuleSpecifier(); + this.consumeSemicolon(); + } + else if (isExportFromIdentifier) { + // export {default}; // missing fromClause + var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; + this.throwError(message, this.lookahead.value); + } + else { + // export {foo}; + this.consumeSemicolon(); + } + exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(null, specifiers, source)); + } + return exportDeclaration; + }; + return Parser; + }()); + exports.Parser = Parser; + + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + "use strict"; + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + Object.defineProperty(exports, "__esModule", { value: true }); + function assert(condition, message) { + /* istanbul ignore if */ + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + exports.assert = assert; + + +/***/ }, +/* 10 */ +/***/ function(module, exports) { + + "use strict"; + /* tslint:disable:max-classes-per-file */ + Object.defineProperty(exports, "__esModule", { value: true }); + var ErrorHandler = (function () { + function ErrorHandler() { + this.errors = []; + this.tolerant = false; + } + ErrorHandler.prototype.recordError = function (error) { + this.errors.push(error); + }; + ErrorHandler.prototype.tolerate = function (error) { + if (this.tolerant) { + this.recordError(error); + } + else { + throw error; + } + }; + ErrorHandler.prototype.constructError = function (msg, column) { + var error = new Error(msg); + try { + throw error; + } + catch (base) { + /* istanbul ignore else */ + if (Object.create && Object.defineProperty) { + error = Object.create(base); + Object.defineProperty(error, 'column', { value: column }); + } + } + /* istanbul ignore next */ + return error; + }; + ErrorHandler.prototype.createError = function (index, line, col, description) { + var msg = 'Line ' + line + ': ' + description; + var error = this.constructError(msg, col); + error.index = index; + error.lineNumber = line; + error.description = description; + return error; + }; + ErrorHandler.prototype.throwError = function (index, line, col, description) { + throw this.createError(index, line, col, description); + }; + ErrorHandler.prototype.tolerateError = function (index, line, col, description) { + var error = this.createError(index, line, col, description); + if (this.tolerant) { + this.recordError(error); + } + else { + throw error; + } + }; + return ErrorHandler; + }()); + exports.ErrorHandler = ErrorHandler; + + +/***/ }, +/* 11 */ +/***/ function(module, exports) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + // Error messages should be identical to V8. + exports.Messages = { + BadGetterArity: 'Getter must not have any formal parameters', + BadSetterArity: 'Setter must have exactly one formal parameter', + BadSetterRestParameter: 'Setter function argument must not be a rest parameter', + ConstructorIsAsync: 'Class constructor may not be an async method', + ConstructorSpecialMethod: 'Class constructor may not be an accessor', + DeclarationMissingInitializer: 'Missing initializer in %0 declaration', + DefaultRestParameter: 'Unexpected token =', + DuplicateBinding: 'Duplicate binding %0', + DuplicateConstructor: 'A class may only have one constructor', + DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', + ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer', + GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts', + IllegalBreak: 'Illegal break statement', + IllegalContinue: 'Illegal continue statement', + IllegalExportDeclaration: 'Unexpected token', + IllegalImportDeclaration: 'Unexpected token', + IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list', + IllegalReturn: 'Illegal return statement', + InvalidEscapedReservedWord: 'Keyword must not contain escaped characters', + InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', + InvalidModuleSpecifier: 'Unexpected token', + InvalidRegExp: 'Invalid regular expression', + LetInLexicalBinding: 'let is disallowed as a lexically bound name', + MissingFromClause: 'Unexpected token', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NewlineAfterThrow: 'Illegal newline after throw', + NoAsAfterImportNamespace: 'Unexpected token', + NoCatchOrFinally: 'Missing catch or finally after try', + ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', + Redeclaration: '%0 \'%1\' has already been declared', + StaticPrototype: 'Classes may not have static property named prototype', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', + UnexpectedEOS: 'Unexpected end of input', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedNumber: 'Unexpected number', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedString: 'Unexpected string', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedToken: 'Unexpected token %0', + UnexpectedTokenIllegal: 'Unexpected token ILLEGAL', + UnknownLabel: 'Undefined label \'%0\'', + UnterminatedRegExp: 'Invalid regular expression: missing /' + }; + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var assert_1 = __webpack_require__(9); + var character_1 = __webpack_require__(4); + var messages_1 = __webpack_require__(11); + function hexValue(ch) { + return '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + function octalValue(ch) { + return '01234567'.indexOf(ch); + } + var Scanner = (function () { + function Scanner(code, handler) { + this.source = code; + this.errorHandler = handler; + this.trackComment = false; + this.isModule = false; + this.length = code.length; + this.index = 0; + this.lineNumber = (code.length > 0) ? 1 : 0; + this.lineStart = 0; + this.curlyStack = []; + } + Scanner.prototype.saveState = function () { + return { + index: this.index, + lineNumber: this.lineNumber, + lineStart: this.lineStart + }; + }; + Scanner.prototype.restoreState = function (state) { + this.index = state.index; + this.lineNumber = state.lineNumber; + this.lineStart = state.lineStart; + }; + Scanner.prototype.eof = function () { + return this.index >= this.length; + }; + Scanner.prototype.throwUnexpectedToken = function (message) { + if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } + return this.errorHandler.throwError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); + }; + Scanner.prototype.tolerateUnexpectedToken = function (message) { + if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } + this.errorHandler.tolerateError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); + }; + // https://tc39.github.io/ecma262/#sec-comments + Scanner.prototype.skipSingleLineComment = function (offset) { + var comments = []; + var start, loc; + if (this.trackComment) { + comments = []; + start = this.index - offset; + loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart - offset + }, + end: {} + }; + } + while (!this.eof()) { + var ch = this.source.charCodeAt(this.index); + ++this.index; + if (character_1.Character.isLineTerminator(ch)) { + if (this.trackComment) { + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart - 1 + }; + var entry = { + multiLine: false, + slice: [start + offset, this.index - 1], + range: [start, this.index - 1], + loc: loc + }; + comments.push(entry); + } + if (ch === 13 && this.source.charCodeAt(this.index) === 10) { + ++this.index; + } + ++this.lineNumber; + this.lineStart = this.index; + return comments; + } + } + if (this.trackComment) { + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + var entry = { + multiLine: false, + slice: [start + offset, this.index], + range: [start, this.index], + loc: loc + }; + comments.push(entry); + } + return comments; + }; + Scanner.prototype.skipMultiLineComment = function () { + var comments = []; + var start, loc; + if (this.trackComment) { + comments = []; + start = this.index - 2; + loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart - 2 + }, + end: {} + }; + } + while (!this.eof()) { + var ch = this.source.charCodeAt(this.index); + if (character_1.Character.isLineTerminator(ch)) { + if (ch === 0x0D && this.source.charCodeAt(this.index + 1) === 0x0A) { + ++this.index; + } + ++this.lineNumber; + ++this.index; + this.lineStart = this.index; + } + else if (ch === 0x2A) { + // Block comment ends with '*/'. + if (this.source.charCodeAt(this.index + 1) === 0x2F) { + this.index += 2; + if (this.trackComment) { + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + var entry = { + multiLine: true, + slice: [start + 2, this.index - 2], + range: [start, this.index], + loc: loc + }; + comments.push(entry); + } + return comments; + } + ++this.index; + } + else { + ++this.index; + } + } + // Ran off the end of the file - the whole thing is a comment + if (this.trackComment) { + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + var entry = { + multiLine: true, + slice: [start + 2, this.index], + range: [start, this.index], + loc: loc + }; + comments.push(entry); + } + this.tolerateUnexpectedToken(); + return comments; + }; + Scanner.prototype.scanComments = function () { + var comments; + if (this.trackComment) { + comments = []; + } + var start = (this.index === 0); + while (!this.eof()) { + var ch = this.source.charCodeAt(this.index); + if (character_1.Character.isWhiteSpace(ch)) { + ++this.index; + } + else if (character_1.Character.isLineTerminator(ch)) { + ++this.index; + if (ch === 0x0D && this.source.charCodeAt(this.index) === 0x0A) { + ++this.index; + } + ++this.lineNumber; + this.lineStart = this.index; + start = true; + } + else if (ch === 0x2F) { + ch = this.source.charCodeAt(this.index + 1); + if (ch === 0x2F) { + this.index += 2; + var comment = this.skipSingleLineComment(2); + if (this.trackComment) { + comments = comments.concat(comment); + } + start = true; + } + else if (ch === 0x2A) { + this.index += 2; + var comment = this.skipMultiLineComment(); + if (this.trackComment) { + comments = comments.concat(comment); + } + } + else { + break; + } + } + else if (start && ch === 0x2D) { + // U+003E is '>' + if ((this.source.charCodeAt(this.index + 1) === 0x2D) && (this.source.charCodeAt(this.index + 2) === 0x3E)) { + // '-->' is a single-line comment + this.index += 3; + var comment = this.skipSingleLineComment(3); + if (this.trackComment) { + comments = comments.concat(comment); + } + } + else { + break; + } + } + else if (ch === 0x3C && !this.isModule) { + if (this.source.slice(this.index + 1, this.index + 4) === '!--') { + this.index += 4; // `' is a single-line comment - this.index += 3; - var comment = this.skipSingleLineComment(3); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (ch === 0x3C && !this.isModule) { - if (this.source.slice(this.index + 1, this.index + 4) === '!--') { - this.index += 4; // ` - - + + + diff --git a/js/appinfo.js b/js/appinfo.js index 776142bcd..6a91dce2d 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -1,7 +1,23 @@ +// Converts a string into most efficient way to send to Espruino (either json, base64, or compressed base64) function toJS(txt) { var json = JSON.stringify(txt); var b64 = "atob("+JSON.stringify(btoa(json))+")"; - return b64.length < json.length ? b64 : json; + var js = b64.length < json.length ? b64 : json; + + if (heatshrink) { + var ua = new Uint8Array(txt.length); + for (var i=0;i { // Load all files Promise.all(app.storage.map(storageFile => { - if (storageFile.content) + if (storageFile.content!==undefined) return Promise.resolve(storageFile); else if (storageFile.url) return options.fileGetter(`apps/${app.id}/${storageFile.url}`).then(content => { @@ -52,14 +68,14 @@ var AppInfo = { let js = storageFile.content.trim(); if (js.endsWith(";")) js = js.slice(0,-1); - storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${js});`; + storageFile.cmd = `\x10require('Storage').write(${JSON.stringify(storageFile.name)},${js});`; } else { let code = storageFile.content; // write code in chunks, in case it is too big to fit in RAM (fix #157) - var CHUNKSIZE = 4096; - storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${toJS(code.substr(0,CHUNKSIZE))},0,${code.length});`; + var CHUNKSIZE = 8192; + storageFile.cmd = `\x10require('Storage').write(${JSON.stringify(storageFile.name)},${toJS(code.substr(0,CHUNKSIZE))},0,${code.length});`; for (var i=CHUNKSIZE;i { // expects an apps.json structure (i.e. with `s }).then(fileContents => { return new Promise((resolve,reject) => { console.log("uploadApp",fileContents.map(f=>f.name).join(", ")); - var maxBytes = fileContents.reduce((b,f)=>b+f.content.length, 0)||1; + var maxBytes = fileContents.reduce((b,f)=>b+f.cmd.length, 0)||1; var currentBytes = 0; var appInfoFileName = app.id+".info"; @@ -37,19 +37,25 @@ uploadApp : (app,skipReset) => { // expects an apps.json structure (i.e. with `s } var f = fileContents.shift(); console.log(`Upload ${f.name} => ${JSON.stringify(f.content)}`); - Progress.show({ - min:currentBytes / maxBytes, - max:(currentBytes+f.content.length) / maxBytes}); - currentBytes += f.content.length; // Chould check CRC here if needed instead of returning 'OK'... // E.CRC32(require("Storage").read(${JSON.stringify(app.name)})) - Puck.write(`${f.cmd};Bluetooth.println("OK")\n`,(result) => { - if (!result || result.trim()!="OK") { - Progress.hide({sticky:true}); - return reject("Unexpected response "+(result||"")); - } - doUploadFiles(); - }, true); // wait for a newline + var cmds = f.cmd.split("\n"); + function uploadCmd() { + if (!cmds.length) return doUploadFiles(); + var cmd = cmds.shift(); + Progress.show({ + min:currentBytes / maxBytes, + max:(currentBytes+cmd.length) / maxBytes}); + currentBytes += cmd.length; + Puck.write(`${cmd};Bluetooth.println("OK")\n`,(result) => { + if (!result || result.trim()!="OK") { + Progress.hide({sticky:true}); + return reject("Unexpected response "+(result||"")); + } + uploadCmd(); + }, true); // wait for a newline + } + uploadCmd(); } // Start the upload function doUpload() { diff --git a/lib/heatshrink.js b/lib/heatshrink.js new file mode 100644 index 000000000..8e4e9a8df --- /dev/null +++ b/lib/heatshrink.js @@ -0,0 +1,100 @@ +/* + Compiled to JS with Emscripten by Gordon Williams + heatshrink_config.h matches that of Espruino. + Source for conversion at http://github.com/gfwilliams/heatshrink-js +*/ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.heatshrink = factory(); + } +}(typeof self !== 'undefined' ? self : this, function () { +/* +Copyright (c) 2013-2015, Scott Vokes +All rights reserved. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=2928,DYNAMIC_BASE=5245808,DYNAMICTOP_PTR=2896;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAARAAoAERERAAAAAAUAAAAAAAAJAAAAAAsAAAAAAAAAABEADwoREREDCgcAARMJCwsAAAkGCwAACwAGEQAAABEREQAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAARAAoKERERAAoAAAIACQsAAAAJAAsAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAMAAAAAAkMAAAAAAAMAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAA0AAAAEDQAAAAAJDgAAAAAADgAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAPAAAAAA8AAAAACRAAAAAAABAAABAAABIAAAASEhIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAABISEgAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAoAAAAACgAAAAAJCwAAAAAACwAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAwAAAAACQwAAAAAAAwAAAwAADAxMjM0NTY3ODlBQkNERUYFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAEgEAAAABAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAK/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApeXiBDT01QUkVTU0lORyAlZCBieXRlcwoAQXNzZXJ0IGF0IGhlYXRzaHJpbmtfd3JhcHBlci5jOiVkCgBeXiBzdW5rICV6ZAoAXl4gcG9sbGVkICV6ZAoAaW46ICV1IGNvbXByZXNzZWQ6ICV1CgAKXl4gREVDT01QUkVTU0lORyAlZCBieXRlcwoALSsgICAwWDB4AChudWxsKQAtMFgrMFggMFgtMHgrMHggMHgAaW5mAElORgBuYW4ATkFOAC4=";var tempDoublePtr=2912;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function flush_NO_FILESYSTEM(){var fflush=Module["_fflush"];if(fflush)fflush(0);var buffers=SYSCALLS.buffers;if(buffers[1].length)SYSCALLS.printChar(1,10);if(buffers[2].length)SYSCALLS.printChar(2,10)}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:0,get:function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(){var ret=UTF8ToString(SYSCALLS.get());return ret},get64:function(){var low=SYSCALLS.get(),high=SYSCALLS.get();return low},getZero:function(){SYSCALLS.get()}};function _fd_write(stream,iov,iovcnt,pnum){try{var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___wasi_fd_write(){return _fd_write.apply(null,arguments)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){abortOnCannotGrowMemory(requestedSize)}var ASSERTIONS=false;function intArrayToString(array){var ret=[];for(var i=0;i255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]=0;n=(f|0)>1;if(n){c[g>>2]=b;ab(888,g)|0}l=(d|0)==0;g=0;h=0;a:while(1){if(h>>>0>=b>>>0){h=26;break}if((X(p,a+h|0,b-h|0,o)|0)<=-1){h=6;break}i=c[o>>2]|0;h=i+h|0;if(n){c[r>>2]=i;ab(949,r)|0}k=(h|0)==(b|0);if(k?(ma(p)|0)!=1:0){h=12;break}b:while(1){if(l)j=Z(p,m,64,o)|0;else j=Z(p,d+g|0,e-g|0,o)|0;if((j|0)<=-1){h=17;break a}i=c[o>>2]|0;g=i+g|0;if(n){c[q>>2]=i;ab(962,q)|0}switch(j|0){case 1:break;case 0:break b;default:{h=21;break a}}}if(k?ma(p)|0:0){h=25;break}}if((h|0)==6){c[s>>2]=21;ab(914,s)|0;g=0}else if((h|0)==12){c[x>>2]=25;ab(914,x)|0;g=0}else if((h|0)==17){c[t>>2]=36;ab(914,t)|0;g=0}else if((h|0)==21){c[u>>2]=40;ab(914,u)|0;g=0}else if((h|0)==25){c[v>>2]=42;ab(914,v)|0;g=0}else if((h|0)==26)if((f|0)>0){c[w>>2]=b;c[w+4>>2]=g;ab(977,w)|0}I=y;return g|0}function V(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;y=I;I=I+448|0;w=y+128|0;v=y+120|0;u=y+112|0;q=y+104|0;t=y+96|0;x=y+88|0;r=y+80|0;s=y+72|0;g=y+64|0;p=y+140|0;o=y+136|0;m=y;na(p);c[o>>2]=0;n=(f|0)>1;if(n){c[g>>2]=b;ab(1e3,g)|0}l=(d|0)==0;g=0;h=0;a:while(1){if(h>>>0>=b>>>0){h=27;break}if((oa(p,a+h|0,b-h|0,o)|0)<=-1){h=6;break}i=c[o>>2]|0;h=i+h|0;if(n){c[r>>2]=i;ab(949,r)|0}k=(h|0)==(b|0);if(k?(za(p)|0)!=1:0){h=12;break}do{if(l)j=pa(p,m,64,o)|0;else j=pa(p,d+g|0,e-g|0,o)|0;if((j|0)<=-1){h=17;break a}i=c[o>>2]|0;g=i+g|0;if(n){c[q>>2]=i;ab(962,q)|0;i=c[o>>2]|0}}while((j|0)==1&(i|0)!=0);if(j|0){h=22;break}if(k?za(p)|0:0){h=26;break}}if((h|0)==6){c[s>>2]=63;ab(914,s)|0;g=0}else if((h|0)==12){c[x>>2]=67;ab(914,x)|0;g=0}else if((h|0)==17){c[t>>2]=78;ab(914,t)|0;g=0}else if((h|0)==22){c[u>>2]=82;ab(914,u)|0;g=0}else if((h|0)==26){c[v>>2]=84;ab(914,v)|0;g=0}else if((h|0)==27)if((f|0)>0){c[w>>2]=b;c[w+4>>2]=g;ab(977,w)|0}I=y;return g|0}function W(c){c=c|0;ob(c+15|0,0,512)|0;b[c>>1]=0;a[c+12>>0]=0;b[c+2>>1]=0;a[c+11>>0]=0;a[c+14>>0]=-128;a[c+13>>0]=0;b[c+4>>1]=0;b[c+8>>1]=0;a[c+10>>0]=0;return}function X(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;if(!((d|0)==0|(e|0)==0|(g|0)==0))if((Y(d)|0)==0?(h=d+12|0,(a[h>>0]|0)==0):0){j=b[d>>1]|0;i=256-j&65535;k=i>>>0>>0?i:f;mb((j+256&65535)+(d+15)|0,e|0,k|0)|0;c[g>>2]=k;b[d>>1]=k+(j&65535);if(i>>>0>f>>>0)d=0;else{a[h>>0]=1;d=0}}else d=-2;else d=-1;return d|0}function Y(b){b=b|0;return a[b+11>>0]&1|0}function Z(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;k=I;I=I+16|0;i=k;if(!((b|0)==0|(d|0)==0|(f|0)==0))if(!e)d=-2;else{c[f>>2]=0;c[i>>2]=d;c[i+4>>2]=e;c[i+8>>2]=f;h=b+12|0;g=a[h>>0]|0;a:while(1){switch(g<<24>>24){case 9:case 0:{d=0;j=15;break a}case 8:{j=11;break a}case 1:{d=2;break}case 2:{d=(_(b)|0)&255;break}case 3:{d=($(b,i)|0)&255;break}case 4:{d=(aa(b,i)|0)&255;break}case 5:{d=(ba(b,i)|0)&255;break}case 6:{d=(ca(b,i)|0)&255;break}case 7:{da(b);d=0;break}default:{d=-2;break a}}a[h>>0]=d;if(d<<24>>24==g<<24>>24?(c[f>>2]|0)==(e|0):0){d=1;j=15;break}g=d}if((j|0)==11){a[h>>0]=ea(b,i)|0;d=0}}else d=-1;I=k;return d|0}function _(a){a=a|0;var c=0,d=0,f=0,g=0,h=0,i=0,j=0;j=I;I=I+16|0;h=j;i=a+2|0;c=b[i>>1]|0;g=(Y(a)|0)!=0;d=c&65535;f=e[a>>1]|0;if((f-(g?1:64)|0)<(d|0))c=g?8:7;else{g=f-d|0;b[h>>1]=0;c=la(a,(c+256&65535)+65280&65535,d+256&65535,((g|0)<64?g:64)&65535,h)|0;if(c<<16>>16==-1){b[i>>1]=(b[i>>1]|0)+1<<16>>16;c=0}else{b[a+6>>1]=c;c=b[h>>1]|0}b[a+4>>1]=c;c=3}I=j;return c|0}function $(c,d){c=c|0;d=d|0;do if(fa(d)|0)if(!(b[c+4>>1]|0)){ka(c,d,1);c=4;break}else{ka(c,d,0);b[c+8>>1]=(e[c+6>>1]|0)+65535;a[c+10>>0]=8;c=5;break}else c=3;while(0);return c|0}function aa(a,b){a=a|0;b=b|0;if(!(fa(b)|0))a=4;else{ja(a,b);a=2}return a|0}function ba(c,d){c=c|0;d=d|0;if((fa(d)|0)!=0?(ha(c,d)|0)<<24>>24==0:0){b[c+8>>1]=(e[c+4>>1]|0)+65535;a[c+10>>0]=6;c=6}else c=5;return c|0}function ca(a,c){a=a|0;c=c|0;if((fa(c)|0)!=0?(ha(a,c)|0)<<24>>24==0:0){c=a+4|0;a=a+2|0;b[a>>1]=(e[a>>1]|0)+(e[c>>1]|0);b[c>>1]=0;a=2}else a=6;return a|0}function da(a){a=a|0;ga(a);return}function ea(b,d){b=b|0;d=d|0;var e=0,f=0;if((a[b+14>>0]|0)!=-128)if(!(fa(d)|0))b=8;else{f=a[b+13>>0]|0;e=c[d>>2]|0;d=c[d+8>>2]|0;b=c[d>>2]|0;c[d>>2]=b+1;a[e+b>>0]=f;b=9}else b=9;return b|0}function fa(a){a=a|0;return (c[c[a+8>>2]>>2]|0)>>>0<(c[a+4>>2]|0)>>>0|0}function ga(a){a=a|0;var c=0,d=0,f=0;d=a+2|0;f=256-(b[d>>1]|0)<<16>>16;c=256-(f&65535)|0;nb(a+15|0,a+15+c|0,f+256&65535|0)|0;b[d>>1]=0;b[a>>1]=(e[a>>1]|0)-c;return}function ha(c,f){c=c|0;f=f|0;var g=0,h=0,i=0,j=0;i=c+10|0;g=a[i>>0]|0;if((g&255)<=8)if(!(g<<24>>24))g=0;else{h=b[c+8>>1]&255;j=4}else{h=(e[c+8>>1]|0)>>>((g&255)+-8|0)&255;g=8;j=4}if((j|0)==4){ia(c,g,h,f);a[i>>0]=(d[i>>0]|0)-(g&255)}return g|0}function ia(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0;h=d&255;j=b+14|0;if(d<<24>>24==8?(a[j>>0]|0)==-128:0){j=c[f>>2]|0;i=c[f+8>>2]|0;f=c[i>>2]|0;c[i>>2]=f+1;a[j+f>>0]=e}else g=4;a:do if((g|0)==4){i=e&255;g=b+13|0;b=f+8|0;e=h;while(1){d=e+-1|0;if((e|0)<=0)break a;e=a[j>>0]|0;if(1<>0]=a[g>>0]|e;h=(e&255)>>>1;a[j>>0]=h;if(!(h<<24>>24)){a[j>>0]=-128;k=a[g>>0]|0;e=c[f>>2]|0;l=c[b>>2]|0;h=c[l>>2]|0;c[l>>2]=h+1;a[e+h>>0]=k;a[g>>0]=0}e=d}}while(0);return}function ja(c,d){c=c|0;d=d|0;ia(c,8,a[((b[c+2>>1]|0)+255&65535)+(c+15)>>0]|0,d);return}function ka(a,b,c){a=a|0;b=b|0;c=c|0;ia(a,1,c,b);return}function la(c,d,e,f,g){c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0;n=e&65535;l=c+15+n|0;h=-1;e=0;m=n+65535&65535;while(1){if(m<<16>>16>16)break;i=(m<<16>>16)+(c+15)|0;k=e&65535;if((a[i+k>>0]|0)==(a[l+k>>0]|0)?(a[i>>0]|0)==(a[l>>0]|0):0){k=1;while(1){j=k&65535;if((k&65535)>=(f&65535))break;if((a[i+j>>0]|0)!=(a[l+j>>0]|0))break;k=k+1<<16>>16}if((k&65535)>(e&65535))if(k<<16>>16==f<<16>>16){h=m;e=f;break}else{h=m;e=k}}m=m+-1<<16>>16}if((e&65535)>1){b[g>>1]=e;e=n-(h&65535)&65535}else e=-1;return e|0}function ma(b){b=b|0;var c=0;if(!b)b=-1;else{c=b+11|0;a[c>>0]=a[c>>0]|1;c=b+12|0;b=a[c>>0]|0;if(!(b<<24>>24)){a[c>>0]=1;b=1}b=b<<24>>24!=9&1}return b|0}function na(a){a=a|0;ob(a|0,0,301)|0;return}function oa(a,d,f,g){a=a|0;d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0;if((a|0)==0|(d|0)==0|(g|0)==0)f=-1;else{i=e[a>>1]|0;j=32-i|0;h=j>>>0>>0?j:f;if(!j){f=1;h=0}else{mb(a+13+i|0,d|0,h|0)|0;b[a>>1]=h+i;f=0}c[g>>2]=h}return f|0}function pa(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0;k=I;I=I+16|0;i=k;if((b|0)==0|(d|0)==0|(f|0)==0)d=-1;else{c[f>>2]=0;c[i>>2]=d;c[i+4>>2]=e;c[i+8>>2]=f;h=b+10|0;d=a[h>>0]|0;a:while(1){switch(d<<24>>24){case 0:{g=qa(b)|0;break}case 1:{g=ra(b,i)|0;break}case 2:{g=sa(b)|0;break}case 3:{g=ta(b)|0;break}case 4:{g=ua(b)|0;break}case 5:{g=va(b)|0;break}case 6:{g=wa(b,i)|0;break}default:{d=-2;break a}}l=d;d=g&255;a[h>>0]=d;if(l<<24>>24==d<<24>>24){j=12;break}}if((j|0)==12)d=(c[f>>2]|0)==(e|0)&1}I=k;return d|0}function qa(a){a=a|0;switch((ya(a,1)|0)<<16>>16){case -1:{a=0;break}case 0:{b[a+6>>1]=0;a=3;break}default:a=1}return a|0}function ra(d,e){d=d|0;e=e|0;var f=0,g=0,h=0;if((c[c[e+8>>2]>>2]|0)>>>0<(c[e+4>>2]|0)>>>0?(f=ya(d,8)|0,f<<16>>16!=-1):0){f=f&255;h=d+8|0;g=b[h>>1]|0;b[h>>1]=g+1<<16>>16;a[d+45+(g&255)>>0]=f;xa(e,f);f=0}else f=1;return f|0}function sa(a){a=a|0;var c=0;c=ya(a,0)|0;if(c<<16>>16==-1)c=2;else{b[a+6>>1]=(c&65535)<<8;c=3}return c|0}function ta(a){a=a|0;var c=0,d=0;c=ya(a,8)|0;if(c<<16>>16==-1)c=3;else{d=a+6|0;b[d>>1]=(b[d>>1]|c)+1<<16>>16;b[a+4>>1]=0;c=5}return c|0}function ua(a){a=a|0;var c=0;c=ya(a,-2)|0;if(c<<16>>16==-1)c=4;else{b[a+4>>1]=(c&65535)<<8;c=5}return c|0}function va(a){a=a|0;var c=0;c=ya(a,6)|0;if(c<<16>>16==-1)c=5;else{a=a+4|0;b[a>>1]=(b[a>>1]|c)+1<<16>>16;c=6}return c|0}function wa(d,f){d=d|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;g=(c[f+4>>2]|0)-(c[c[f+8>>2]>>2]|0)|0;if(g){k=d+4|0;j=e[k>>1]|0;j=g>>>0>j>>>0?j:g;h=d+45|0;i=d+8|0;g=e[d+6>>1]|0;d=0;while(1){if(d>>>0>=j>>>0)break;n=a[h+((e[i>>1]|0)-g&255)>>0]|0;xa(f,n);m=b[i>>1]|0;a[h+(m&255)>>0]=n;b[i>>1]=m+1<<16>>16;d=d+1|0}n=(e[k>>1]|0)-j|0;b[k>>1]=n;if(!(n&65535))g=0;else l=6}else l=6;if((l|0)==6)g=6;return g|0}function xa(b,d){b=b|0;d=d|0;var e=0,f=0;e=c[b>>2]|0;f=c[b+8>>2]|0;b=c[f>>2]|0;c[f>>2]=b+1;a[e+b>>0]=d;return}function ya(c,e){c=c|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=e&255;a:do if((e&255)>15)e=-1;else{e=b[c>>1]|0;j=c+12|0;if(e<<16>>16==0?(1<(d[j>>0]|0|0):0){e=-1;break}k=c+11|0;l=c+2|0;g=e;e=0;i=0;while(1){if(i>>>0>=m>>>0)break a;f=a[j>>0]|0;if(!(f<<24>>24)){if(!(g<<16>>16)){e=-1;break a}h=b[l>>1]|0;f=h+1<<16>>16;b[l>>1]=f;h=a[(h&65535)+(c+13)>>0]|0;a[k>>0]=h;if(f<<16>>16==g<<16>>16){b[l>>1]=0;b[c>>1]=0;g=0}a[j>>0]=-128;f=-128}else h=a[k>>0]|0;a[j>>0]=(f&255)>>>1;e=((e&65535)<<1|(f&h)<<24>>24!=0)&65535;i=i+1|0}}while(0);return e|0}function za(c){c=c|0;a:do if(!c)c=-1;else switch(a[c+10>>0]|0){case 0:{c=(b[c>>1]|0)!=0&1;break a}case 4:case 5:case 2:case 3:{c=(b[c>>1]|0)!=0&1;break a}case 1:{c=(b[c>>1]|0)!=0&1;break a}default:{c=1;break a}}while(0);return c|0}function Aa(a){a=a|0;return 0}function Ba(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;l=I;I=I+32|0;g=l;i=l+16|0;j=a+28|0;f=c[j>>2]|0;c[g>>2]=f;k=a+20|0;f=(c[k>>2]|0)-f|0;c[g+4>>2]=f;c[g+8>>2]=b;c[g+12>>2]=d;e=a+60|0;h=2;f=f+d|0;while(1){if(!((x(c[e>>2]|0,g|0,h|0,i|0)|0)<<16>>16))b=c[i>>2]|0;else{c[i>>2]=-1;b=-1}if((f|0)==(b|0)){b=6;break}if((b|0)<0){b=8;break}p=c[g+4>>2]|0;m=b>>>0>p>>>0;n=m?g+8|0:g;p=b-(m?p:0)|0;c[n>>2]=(c[n>>2]|0)+p;o=n+4|0;c[o>>2]=(c[o>>2]|0)-p;g=n;h=h+(m<<31>>31)|0;f=f-b|0}if((b|0)==6){p=c[a+44>>2]|0;c[a+16>>2]=p+(c[a+48>>2]|0);c[j>>2]=p;c[k>>2]=p}else if((b|0)==8){c[a+16>>2]=0;c[j>>2]=0;c[k>>2]=0;c[a>>2]=c[a>>2]|32;if((h|0)==2)d=0;else d=d-(c[g+4>>2]|0)|0}I=l;return d|0}function Ca(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;u(0);return 0}function Da(){return 2128}function Ea(a,b,c){a=a|0;b=b|0;c=c|0;return Ha(a,b,c,1,1)|0}function Fa(b,e,f,g,h,i){b=b|0;e=+e;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0.0,t=0,u=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;H=I;I=I+560|0;m=H+32|0;u=H+536|0;G=H;F=G;l=H+540|0;c[u>>2]=0;E=l+12|0;_a(e)|0;j=v()|0;if((j|0)<0){e=-e;_a(e)|0;j=v()|0;D=1;B=1045}else{D=(h&2049|0)!=0&1;B=(h&2048|0)==0?((h&1|0)==0?1046:1051):1048}do if(0==0&(j&2146435072|0)==2146435072){G=(i&32|0)!=0;j=D+3|0;Ta(b,32,f,j,h&-65537);La(b,B,D);La(b,e!=e|0.0!=0.0?(G?1072:1076):G?1064:1068,3);Ta(b,32,f,j,h^8192)}else{s=+$a(e,u)*2.0;j=s!=0.0;if(j)c[u>>2]=(c[u>>2]|0)+-1;x=i|32;if((x|0)==97){o=i&32;q=(o|0)==0?B:B+9|0;p=D|2;j=12-g|0;do if(!(g>>>0>11|(j|0)==0)){e=8.0;do{j=j+-1|0;e=e*16.0}while((j|0)!=0);if((a[q>>0]|0)==45){e=-(e+(-s-e));break}else{e=s+e-e;break}}else e=s;while(0);k=c[u>>2]|0;j=(k|0)<0?0-k|0:k;j=Ra(j,((j|0)<0)<<31>>31,E)|0;if((j|0)==(E|0)){j=l+11|0;a[j>>0]=48}a[j+-1>>0]=(k>>31&2)+43;n=j+-2|0;a[n>>0]=i+15;k=(g|0)<1;l=(h&8|0)==0;j=G;while(1){D=~~e;m=j+1|0;a[j>>0]=o|d[480+D>>0];e=(e-+(D|0))*16.0;if((m-F|0)==1?!(l&(k&e==0.0)):0){a[m>>0]=46;m=j+2|0}if(!(e!=0.0))break;else j=m}if((g|0)!=0?(-2-F+m|0)<(g|0):0){k=E;l=n;j=g+2+k-l|0}else{k=E;l=n;j=k-F-l+m|0}E=j+p|0;Ta(b,32,f,E,h);La(b,q,p);Ta(b,48,f,E,h^65536);F=m-F|0;La(b,G,F);G=k-l|0;Ta(b,48,j-(F+G)|0,0,0);La(b,n,G);Ta(b,32,f,E,h^8192);j=E;break}k=(g|0)<0?6:g;if(j){l=(c[u>>2]|0)+-28|0;c[u>>2]=l;e=s*268435456.0}else{l=c[u>>2]|0;e=s}C=(l|0)<0?m:m+288|0;m=C;do{z=~~e>>>0;c[m>>2]=z;m=m+4|0;e=(e-+(z>>>0))*1.0e9}while(e!=0.0);z=C;if((l|0)>0){j=C;do{o=(l|0)<29?l:29;l=m+-4|0;if(l>>>0>=j>>>0){n=0;do{t=lb(c[l>>2]|0,0,o|0)|0;t=fb(t|0,v()|0,n|0,0)|0;w=v()|0;n=jb(t|0,w|0,1e9,0)|0;y=eb(n|0,v()|0,1e9,0)|0;y=gb(t|0,w|0,y|0,v()|0)|0;v()|0;c[l>>2]=y;l=l+-4|0}while(l>>>0>=j>>>0);if(n){j=j+-4|0;c[j>>2]=n}}a:do if(m>>>0>j>>>0)while(1){l=m+-4|0;if(c[l>>2]|0)break a;if(l>>>0>j>>>0)m=l;else{m=l;break}}while(0);l=(c[u>>2]|0)-o|0;c[u>>2]=l}while((l|0)>0)}else j=C;if((l|0)<0){g=((k+25|0)/9|0)+1|0;t=(x|0)==102;do{q=0-l|0;q=(q|0)<9?q:9;if(j>>>0>>0){o=(1<>>q;p=0;l=j;do{y=c[l>>2]|0;c[l>>2]=(y>>>q)+p;p=r(y&o,n)|0;l=l+4|0}while(l>>>0>>0);j=(c[j>>2]|0)==0?j+4|0:j;if(p){c[m>>2]=p;m=m+4|0}}else j=(c[j>>2]|0)==0?j+4|0:j;l=t?C:j;m=(m-l>>2|0)>(g|0)?l+(g<<2)|0:m;l=(c[u>>2]|0)+q|0;c[u>>2]=l}while((l|0)<0);t=m}else t=m;if(j>>>0>>0){l=(z-j>>2)*9|0;n=c[j>>2]|0;if(n>>>0>=10){m=10;do{m=m*10|0;l=l+1|0}while(n>>>0>=m>>>0)}}else l=0;u=(x|0)==103;w=(k|0)!=0;m=k-((x|0)==102?0:l)+((w&u)<<31>>31)|0;if((m|0)<(((t-z>>2)*9|0)+-9|0)){y=m+9216|0;m=(y|0)/9|0;g=C+4+(m+-1024<<2)|0;m=y-(m*9|0)|0;if((m|0)<8){n=10;while(1){n=n*10|0;if((m|0)<7)m=m+1|0;else break}}else n=10;p=c[g>>2]|0;m=(p>>>0)/(n>>>0)|0;q=p-(r(m,n)|0)|0;o=(g+4|0)==(t|0);if(!(o&(q|0)==0)){s=(m&1|0)==0?9007199254740992.0:9007199254740994.0;y=n>>>1;e=q>>>0>>0?.5:o&(q|0)==(y|0)?1.0:1.5;if(D){y=(a[B>>0]|0)==45;s=y?-s:s;e=y?-e:e}m=p-q|0;c[g>>2]=m;if(s+e!=s){y=m+n|0;c[g>>2]=y;if(y>>>0>999999999){l=g;while(1){m=l+-4|0;c[l>>2]=0;if(m>>>0>>0){j=j+-4|0;c[j>>2]=0}y=(c[m>>2]|0)+1|0;c[m>>2]=y;if(y>>>0>999999999)l=m;else break}}else m=g;l=(z-j>>2)*9|0;o=c[j>>2]|0;if(o>>>0>=10){n=10;do{n=n*10|0;l=l+1|0}while(o>>>0>=n>>>0)}}else m=g}else m=g;x=m+4|0;y=j;j=t>>>0>x>>>0?x:t}else{y=j;j=t}q=0-l|0;b:do if(j>>>0>y>>>0)while(1){m=j+-4|0;if(c[m>>2]|0){t=1;x=j;break b}if(m>>>0>y>>>0)j=m;else{t=0;x=m;break}}else{t=0;x=j}while(0);do if(u){j=k+((w^1)&1)|0;if((j|0)>(l|0)&(l|0)>-5){k=j+-1-l|0;n=i+-1|0}else{k=j+-1|0;n=i+-2|0}if(!(h&8)){if(t?(A=c[x+-4>>2]|0,(A|0)!=0):0)if(!((A>>>0)%10|0)){j=10;m=0;do{j=j*10|0;m=m+1|0}while(!((A>>>0)%(j>>>0)|0|0))}else m=0;else m=9;j=((x-z>>2)*9|0)+-9|0;if((n|32|0)==102){i=j-m|0;i=(i|0)>0?i:0;k=(k|0)<(i|0)?k:i;break}else{i=j+l-m|0;i=(i|0)>0?i:0;k=(k|0)<(i|0)?k:i;break}}}else n=i;while(0);g=(k|0)!=0;o=g?1:h>>>3&1;p=(n|32|0)==102;if(p){w=0;j=(l|0)>0?l:0}else{j=(l|0)<0?q:l;j=Ra(j,((j|0)<0)<<31>>31,E)|0;m=E;if((m-j|0)<2)do{j=j+-1|0;a[j>>0]=48}while((m-j|0)<2);a[j+-1>>0]=(l>>31&2)+43;j=j+-2|0;a[j>>0]=n;w=j;j=m-j|0}j=D+1+k+o+j|0;Ta(b,32,f,j,h);La(b,B,D);Ta(b,48,f,j,h^65536);if(p){o=y>>>0>C>>>0?C:y;q=G+9|0;p=q;n=G+8|0;m=o;do{l=Ra(c[m>>2]|0,0,q)|0;if((m|0)==(o|0)){if((l|0)==(q|0)){a[n>>0]=48;l=n}}else if(l>>>0>G>>>0){ob(G|0,48,l-F|0)|0;do l=l+-1|0;while(l>>>0>G>>>0)}La(b,l,p-l|0);m=m+4|0}while(m>>>0<=C>>>0);if(!((h&8|0)==0&(g^1)))La(b,1080,1);if(m>>>0>>0&(k|0)>0)while(1){l=Ra(c[m>>2]|0,0,q)|0;if(l>>>0>G>>>0){ob(G|0,48,l-F|0)|0;do l=l+-1|0;while(l>>>0>G>>>0)}La(b,l,(k|0)<9?k:9);m=m+4|0;l=k+-9|0;if(!(m>>>0>>0&(k|0)>9)){k=l;break}else k=l}Ta(b,48,k+9|0,9,0)}else{g=t?x:y+4|0;if(y>>>0>>0&(k|0)>-1){q=G+9|0;u=(h&8|0)==0;t=q;n=0-F|0;p=G+8|0;o=y;do{l=Ra(c[o>>2]|0,0,q)|0;if((l|0)==(q|0)){a[p>>0]=48;l=p}do if((o|0)==(y|0)){m=l+1|0;La(b,l,1);if(u&(k|0)<1){l=m;break}La(b,1080,1);l=m}else{if(l>>>0<=G>>>0)break;ob(G|0,48,l+n|0)|0;do l=l+-1|0;while(l>>>0>G>>>0)}while(0);F=t-l|0;La(b,l,(k|0)>(F|0)?F:k);k=k-F|0;o=o+4|0}while(o>>>0>>0&(k|0)>-1)}Ta(b,48,k+18|0,18,0);La(b,w,E-w|0)}Ta(b,32,f,j,h^8192)}while(0);I=H;return ((j|0)<(f|0)?f:j)|0}function Ga(a,b){a=a|0;b=b|0;var d=0.0,e=0;e=(c[b>>2]|0)+(8-1)&~(8-1);d=+g[e>>3];c[b>>2]=e+8;g[a>>3]=d;return}function Ha(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=I;I=I+224|0;o=t+208|0;s=t+160|0;r=t+80|0;q=t;h=s;i=h+40|0;do{c[h>>2]=0;h=h+4|0}while((h|0)<(i|0));c[o>>2]=c[e>>2];if((Ia(0,d,o,r,s,f,g)|0)<0)e=-1;else{if((c[b+76>>2]|0)>-1)p=Ja(b)|0;else p=0;e=c[b>>2]|0;n=e&32;if((a[b+74>>0]|0)<1)c[b>>2]=e&-33;j=b+48|0;if(!(c[j>>2]|0)){i=b+44|0;e=c[i>>2]|0;c[i>>2]=q;k=b+28|0;c[k>>2]=q;m=b+20|0;c[m>>2]=q;c[j>>2]=80;l=b+16|0;c[l>>2]=q+80;h=Ia(b,d,o,r,s,f,g)|0;if(e){N[c[b+36>>2]&1](b,0,0)|0;h=(c[m>>2]|0)==0?-1:h;c[i>>2]=e;c[j>>2]=0;c[l>>2]=0;c[k>>2]=0;c[m>>2]=0}}else h=Ia(b,d,o,r,s,f,g)|0;e=c[b>>2]|0;c[b>>2]=e|n;if(p|0)Ka(b);e=(e&32|0)==0?h:-1}I=t;return e|0}function Ia(d,e,f,h,i,j,k){d=d|0;e=e|0;f=f|0;h=h|0;i=i|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,J=0,K=0,L=0;K=I;I=I+64|0;H=K+56|0;F=K+40|0;z=K;J=K+48|0;G=K+60|0;c[H>>2]=e;C=(d|0)!=0;y=z+40|0;B=y;z=z+39|0;A=J+4|0;e=0;l=0;o=0;a:while(1){do{do if((e|0)>-1)if((l|0)>(2147483647-e|0)){c[(Da()|0)>>2]=75;e=-1;break}else{e=l+e|0;break}while(0);s=c[H>>2]|0;l=a[s>>0]|0;if(!(l<<24>>24)){x=92;break a}m=s;b:while(1){switch(l<<24>>24){case 37:{x=10;break b}case 0:{l=m;break b}default:{}}w=m+1|0;c[H>>2]=w;l=a[w>>0]|0;m=w}c:do if((x|0)==10){x=0;n=m;l=m;do{if((a[n+1>>0]|0)!=37)break c;l=l+1|0;n=n+2|0;c[H>>2]=n}while((a[n>>0]|0)==37)}while(0);l=l-s|0;if(C)La(d,s,l)}while((l|0)!=0);w=(Ma(a[(c[H>>2]|0)+1>>0]|0)|0)==0;l=c[H>>2]|0;if(!w?(a[l+2>>0]|0)==36:0){m=3;q=(a[l+1>>0]|0)+-48|0;p=1}else{m=1;q=-1;p=o}m=l+m|0;c[H>>2]=m;l=a[m>>0]|0;n=(l<<24>>24)+-32|0;if(n>>>0>31|(1<>2]=m;l=a[m>>0]|0;n=(l<<24>>24)+-32|0;if(n>>>0>31|(1<>24==42){if((Ma(a[m+1>>0]|0)|0)!=0?(D=c[H>>2]|0,(a[D+2>>0]|0)==36):0){l=D+1|0;c[i+((a[l>>0]|0)+-48<<2)>>2]=10;n=1;m=D+3|0;l=c[h+((a[l>>0]|0)+-48<<3)>>2]|0}else{if(p|0){e=-1;break}if(C){w=(c[f>>2]|0)+(4-1)&~(4-1);l=c[w>>2]|0;c[f>>2]=w+4}else l=0;n=0;m=(c[H>>2]|0)+1|0}c[H>>2]=m;u=(l|0)<0;o=u?o|8192:o;w=n;u=u?0-l|0:l}else{l=Na(H)|0;if((l|0)<0){e=-1;break}m=c[H>>2]|0;w=p;u=l}do if((a[m>>0]|0)==46){l=m+1|0;if((a[l>>0]|0)!=42){c[H>>2]=l;t=Na(H)|0;l=c[H>>2]|0;break}if(Ma(a[m+2>>0]|0)|0?(E=c[H>>2]|0,(a[E+3>>0]|0)==36):0){t=E+2|0;c[i+((a[t>>0]|0)+-48<<2)>>2]=10;t=c[h+((a[t>>0]|0)+-48<<3)>>2]|0;l=E+4|0;c[H>>2]=l;break}if(w|0){e=-1;break a}if(C){t=(c[f>>2]|0)+(4-1)&~(4-1);m=c[t>>2]|0;c[f>>2]=t+4}else m=0;l=(c[H>>2]|0)+2|0;c[H>>2]=l;t=m}else{l=m;t=-1}while(0);r=0;while(1){if(((a[l>>0]|0)+-65|0)>>>0>57){e=-1;break a}m=l;l=l+1|0;c[H>>2]=l;m=a[(a[m>>0]|0)+-65+(16+(r*58|0))>>0]|0;p=m&255;if((p+-1|0)>>>0>=8)break;else r=p}if(!(m<<24>>24)){e=-1;break}n=(q|0)>-1;do if(m<<24>>24==19)if(n){e=-1;break a}else x=54;else{if(n){c[i+(q<<2)>>2]=p;p=h+(q<<3)|0;q=c[p+4>>2]|0;x=F;c[x>>2]=c[p>>2];c[x+4>>2]=q;x=54;break}if(!C){e=0;break a}Oa(F,p,f,k);l=c[H>>2]|0;x=55}while(0);if((x|0)==54){x=0;if(C)x=55;else l=0}d:do if((x|0)==55){x=0;n=a[l+-1>>0]|0;n=(r|0)!=0&(n&15|0)==3?n&-33:n;l=o&-65537;q=(o&8192|0)==0?o:l;e:do switch(n|0){case 110:switch((r&255)<<24>>24){case 0:{c[c[F>>2]>>2]=e;l=0;break d}case 1:{c[c[F>>2]>>2]=e;l=0;break d}case 2:{l=c[F>>2]|0;c[l>>2]=e;c[l+4>>2]=((e|0)<0)<<31>>31;l=0;break d}case 3:{b[c[F>>2]>>1]=e;l=0;break d}case 4:{a[c[F>>2]>>0]=e;l=0;break d}case 6:{c[c[F>>2]>>2]=e;l=0;break d}case 7:{l=c[F>>2]|0;c[l>>2]=e;c[l+4>>2]=((e|0)<0)<<31>>31;l=0;break d}default:{l=0;break d}}case 112:{l=q|8;m=t>>>0>8?t:8;n=120;x=67;break}case 88:case 120:{l=q;m=t;x=67;break}case 111:{o=F;o=Qa(c[o>>2]|0,c[o+4>>2]|0,y)|0;m=B-o|0;l=q;m=(q&8|0)==0|(t|0)>(m|0)?t:m+1|0;r=0;p=1028;x=73;break}case 105:case 100:{m=F;l=c[m>>2]|0;m=c[m+4>>2]|0;if((m|0)<0){l=gb(0,0,l|0,m|0)|0;m=v()|0;n=F;c[n>>2]=l;c[n+4>>2]=m;n=1;p=1028;x=72;break e}else{n=(q&2049|0)!=0&1;p=(q&2048|0)==0?((q&1|0)==0?1028:1030):1029;x=72;break e}}case 117:{m=F;l=c[m>>2]|0;m=c[m+4>>2]|0;n=0;p=1028;x=72;break}case 99:{a[z>>0]=c[F>>2];s=z;q=l;o=1;n=0;m=1028;l=B;break}case 115:{p=c[F>>2]|0;p=(p|0)==0?1038:p;r=Sa(p,0,t)|0;L=(r|0)==0;s=p;q=l;o=L?t:r-p|0;n=0;m=1028;l=L?p+t|0:r;break}case 67:{c[J>>2]=c[F>>2];c[A>>2]=0;c[F>>2]=J;o=-1;x=79;break}case 83:{if(!t){Ta(d,32,u,0,q);l=0;x=89}else{o=t;x=79}break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{l=M[j&1](d,+g[F>>3],u,t,q,n)|0;break d}default:{o=t;n=0;m=1028;l=B}}while(0);f:do if((x|0)==67){o=F;o=Pa(c[o>>2]|0,c[o+4>>2]|0,y,n&32)|0;p=F;p=(l&8|0)==0|(c[p>>2]|0)==0&(c[p+4>>2]|0)==0;r=p?0:2;p=p?1028:1028+(n>>>4)|0;x=73}else if((x|0)==72){o=Ra(l,m,y)|0;l=q;m=t;r=n;x=73}else if((x|0)==79){x=0;l=0;p=c[F>>2]|0;while(1){m=c[p>>2]|0;if(!m)break;m=Ua(G,m)|0;n=(m|0)<0;if(n|m>>>0>(o-l|0)>>>0){x=83;break}l=m+l|0;if(o>>>0>l>>>0)p=p+4|0;else break}if((x|0)==83){x=0;if(n){e=-1;break a}}Ta(d,32,u,l,q);if(!l){l=0;x=89}else{n=0;o=c[F>>2]|0;while(1){m=c[o>>2]|0;if(!m){x=89;break f}m=Ua(G,m)|0;n=m+n|0;if((n|0)>(l|0)){x=89;break f}La(d,G,m);if(n>>>0>=l>>>0){x=89;break}else o=o+4|0}}}while(0);if((x|0)==73){x=0;n=F;n=(c[n>>2]|0)!=0|(c[n+4>>2]|0)!=0;L=(m|0)!=0|n;n=B-o+((n^1)&1)|0;s=L?o:y;q=(m|0)>-1?l&-65537:l;o=L?((m|0)>(n|0)?m:n):0;n=r;m=p;l=B}else if((x|0)==89){x=0;Ta(d,32,u,l,q^8192);l=(u|0)>(l|0)?u:l;break}t=l-s|0;r=(o|0)<(t|0)?t:o;L=r+n|0;l=(u|0)<(L|0)?L:u;Ta(d,32,l,L,q);La(d,m,n);Ta(d,48,l,L,q^65536);Ta(d,48,r,t,0);La(d,s,t);Ta(d,32,l,L,q^8192)}while(0);o=w}g:do if((x|0)==92)if(!d)if(!o)e=0;else{e=1;while(1){l=c[i+(e<<2)>>2]|0;if(!l)break;Oa(h+(e<<3)|0,l,f,k);e=e+1|0;if(e>>>0>=10){e=1;break g}}while(1){if(c[i+(e<<2)>>2]|0){e=-1;break g}e=e+1|0;if(e>>>0>=10){e=1;break}}}while(0);I=K;return e|0}function Ja(a){a=a|0;return 1}function Ka(a){a=a|0;return}function La(a,b,d){a=a|0;b=b|0;d=d|0;if(!(c[a>>2]&32))Ya(b,d,a)|0;return}function Ma(a){a=a|0;return (a+-48|0)>>>0<10|0}function Na(b){b=b|0;var d=0,e=0;if(!(Ma(a[c[b>>2]>>0]|0)|0))d=0;else{d=0;do{e=c[b>>2]|0;d=(d*10|0)+-48+(a[e>>0]|0)|0;e=e+1|0;c[b>>2]=e}while((Ma(a[e>>0]|0)|0)!=0)}return d|0}function Oa(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0.0;a:do if(b>>>0<=20)do switch(b|0){case 9:{e=(c[d>>2]|0)+(4-1)&~(4-1);b=c[e>>2]|0;c[d>>2]=e+4;c[a>>2]=b;break a}case 10:{b=(c[d>>2]|0)+(4-1)&~(4-1);e=c[b>>2]|0;c[d>>2]=b+4;b=a;c[b>>2]=e;c[b+4>>2]=((e|0)<0)<<31>>31;break a}case 11:{b=(c[d>>2]|0)+(4-1)&~(4-1);e=c[b>>2]|0;c[d>>2]=b+4;b=a;c[b>>2]=e;c[b+4>>2]=0;break a}case 12:{b=(c[d>>2]|0)+(8-1)&~(8-1);e=b;f=c[e>>2]|0;e=c[e+4>>2]|0;c[d>>2]=b+8;b=a;c[b>>2]=f;c[b+4>>2]=e;break a}case 13:{f=(c[d>>2]|0)+(4-1)&~(4-1);b=c[f>>2]|0;c[d>>2]=f+4;b=(b&65535)<<16>>16;f=a;c[f>>2]=b;c[f+4>>2]=((b|0)<0)<<31>>31;break a}case 14:{f=(c[d>>2]|0)+(4-1)&~(4-1);b=c[f>>2]|0;c[d>>2]=f+4;f=a;c[f>>2]=b&65535;c[f+4>>2]=0;break a}case 15:{f=(c[d>>2]|0)+(4-1)&~(4-1);b=c[f>>2]|0;c[d>>2]=f+4;b=(b&255)<<24>>24;f=a;c[f>>2]=b;c[f+4>>2]=((b|0)<0)<<31>>31;break a}case 16:{f=(c[d>>2]|0)+(4-1)&~(4-1);b=c[f>>2]|0;c[d>>2]=f+4;f=a;c[f>>2]=b&255;c[f+4>>2]=0;break a}case 17:{f=(c[d>>2]|0)+(8-1)&~(8-1);h=+g[f>>3];c[d>>2]=f+8;g[a>>3]=h;break a}case 18:{P[e&1](a,d);break a}default:break a}while(0);while(0);return}function Pa(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;if(!((b|0)==0&(c|0)==0))do{e=e+-1|0;a[e>>0]=d[480+(b&15)>>0]|0|f;b=kb(b|0,c|0,4)|0;c=v()|0}while(!((b|0)==0&(c|0)==0));return e|0}function Qa(b,c,d){b=b|0;c=c|0;d=d|0;if(!((b|0)==0&(c|0)==0))do{d=d+-1|0;a[d>>0]=b&7|48;b=kb(b|0,c|0,3)|0;c=v()|0}while(!((b|0)==0&(c|0)==0));return d|0}function Ra(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;if(c>>>0>0|(c|0)==0&b>>>0>4294967295)do{e=b;b=jb(b|0,c|0,10,0)|0;f=c;c=v()|0;g=eb(b|0,c|0,10,0)|0;g=gb(e|0,f|0,g|0,v()|0)|0;v()|0;d=d+-1|0;a[d>>0]=g&255|48}while(f>>>0>9|(f|0)==9&e>>>0>4294967295);if(b)do{g=b;b=(b>>>0)/10|0;d=d+-1|0;a[d>>0]=g-(b*10|0)|48}while(g>>>0>=10);return d|0}function Sa(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=d&255;f=(e|0)!=0;a:do if(f&(b&3|0)!=0){g=d&255;while(1){if((a[b>>0]|0)==g<<24>>24){i=6;break a}b=b+1|0;e=e+-1|0;f=(e|0)!=0;if(!(f&(b&3|0)!=0)){i=5;break}}}else i=5;while(0);if((i|0)==5)if(f)i=6;else i=16;b:do if((i|0)==6){g=d&255;if((a[b>>0]|0)==g<<24>>24)if(!e){i=16;break}else break;f=r(h,16843009)|0;c:do if(e>>>0>3)while(1){h=c[b>>2]^f;if((h&-2139062144^-2139062144)&h+-16843009|0)break c;b=b+4|0;e=e+-4|0;if(e>>>0<=3){i=11;break}}else i=11;while(0);if((i|0)==11)if(!e){i=16;break}while(1){if((a[b>>0]|0)==g<<24>>24)break b;e=e+-1|0;if(!e){i=16;break}else b=b+1|0}}while(0);if((i|0)==16)b=0;return b|0}function Ta(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=I;I=I+256|0;f=g;if((c|0)>(d|0)&(e&73728|0)==0){e=c-d|0;ob(f|0,b<<24>>24|0,(e>>>0<256?e:256)|0)|0;if(e>>>0>255){b=c-d|0;do{La(a,f,256);e=e+-256|0}while(e>>>0>255);e=b&255}La(a,f,e)}I=g;return}function Ua(a,b){a=a|0;b=b|0;if(!a)a=0;else a=Va(a,b,0)|0;return a|0}function Va(b,d,e){b=b|0;d=d|0;e=e|0;do if(b){if(d>>>0<128){a[b>>0]=d;b=1;break}if(!(c[c[(Wa()|0)+188>>2]>>2]|0))if((d&-128|0)==57216){a[b>>0]=d;b=1;break}else{c[(Da()|0)>>2]=84;b=-1;break}if(d>>>0<2048){a[b>>0]=d>>>6|192;a[b+1>>0]=d&63|128;b=2;break}if(d>>>0<55296|(d&-8192|0)==57344){a[b>>0]=d>>>12|224;a[b+1>>0]=d>>>6&63|128;a[b+2>>0]=d&63|128;b=3;break}if((d+-65536|0)>>>0<1048576){a[b>>0]=d>>>18|240;a[b+1>>0]=d>>>12&63|128;a[b+2>>0]=d>>>6&63|128;a[b+3>>0]=d&63|128;b=4;break}else{c[(Da()|0)>>2]=84;b=-1;break}}else b=1;while(0);return b|0}function Wa(){return Xa()|0}function Xa(){return 644}function Ya(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;g=e+16|0;f=c[g>>2]|0;if(!f)if(!(Za(e)|0)){f=c[g>>2]|0;h=5}else f=0;else h=5;a:do if((h|0)==5){j=e+20|0;i=c[j>>2]|0;g=i;if((f-i|0)>>>0>>0){f=N[c[e+36>>2]&1](e,b,d)|0;break}b:do if((a[e+75>>0]|0)<0|(d|0)==0){h=g;e=0;g=d;f=b}else{i=d;while(1){f=i+-1|0;if((a[b+f>>0]|0)==10)break;if(!f){h=g;e=0;g=d;f=b;break b}else i=f}f=N[c[e+36>>2]&1](e,b,i)|0;if(f>>>0>>0)break a;h=c[j>>2]|0;e=i;g=d-i|0;f=b+i|0}while(0);mb(h|0,f|0,g|0)|0;c[j>>2]=(c[j>>2]|0)+g;f=e+g|0}while(0);return f|0}function Za(b){b=b|0;var d=0,e=0;d=b+74|0;e=a[d>>0]|0;a[d>>0]=e+255|e;d=c[b>>2]|0;if(!(d&8)){c[b+8>>2]=0;c[b+4>>2]=0;d=c[b+44>>2]|0;c[b+28>>2]=d;c[b+20>>2]=d;c[b+16>>2]=d+(c[b+48>>2]|0);d=0}else{c[b>>2]=d|32;d=-1}return d|0}function _a(a){a=+a;var b=0;g[h>>3]=a;b=c[h>>2]|0;u(c[h+4>>2]|0);return b|0}function $a(a,b){a=+a;b=b|0;var d=0,e=0,f=0;g[h>>3]=a;d=c[h>>2]|0;e=c[h+4>>2]|0;f=kb(d|0,e|0,52)|0;v()|0;switch(f&2047){case 0:{if(a!=0.0){a=+$a(a*18446744073709551616.0,b);d=(c[b>>2]|0)+-64|0}else d=0;c[b>>2]=d;break}case 2047:break;default:{c[b>>2]=(f&2047)+-1022;c[h>>2]=d;c[h+4>>2]=e&-2146435073|1071644672;a=+g[h>>3]}}return +a}function ab(a,b){a=a|0;b=b|0;var d=0,e=0;d=I;I=I+16|0;e=d;c[e>>2]=b;b=Ea(c[160]|0,a,e)|0;I=d;return b|0}function bb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=I;I=I+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=c[549]|0;d=m>>>a;if(d&3|0){e=(d&1^1)+a|0;f=2236+(e<<1<<2)|0;b=f+8|0;a=c[b>>2]|0;g=a+8|0;d=c[g>>2]|0;if((d|0)==(f|0))c[549]=m&~(1<>2]=f;c[b>>2]=d}v=e<<3;c[a+4>>2]=v|3;v=a+v+4|0;c[v>>2]=c[v>>2]|1;v=g;I=w;return v|0}l=c[551]|0;if(k>>>0>l>>>0){if(d|0){i=2<>>12&16;d=d>>>i;a=d>>>5&8;d=d>>>a;g=d>>>2&4;d=d>>>g;b=d>>>1&2;d=d>>>b;e=d>>>1&1;e=(a|i|g|b|e)+(d>>>e)|0;d=2236+(e<<1<<2)|0;b=d+8|0;g=c[b>>2]|0;i=g+8|0;a=c[i>>2]|0;if((a|0)==(d|0)){a=m&~(1<>2]=d;c[b>>2]=a;a=m}v=e<<3;h=v-k|0;c[g+4>>2]=k|3;f=g+k|0;c[f+4>>2]=h|1;c[g+v>>2]=h;if(l|0){e=c[554]|0;b=l>>>3;d=2236+(b<<1<<2)|0;b=1<>2]|0}c[b>>2]=e;c[a+12>>2]=e;c[e+8>>2]=a;c[e+12>>2]=d}c[551]=h;c[554]=f;v=i;I=w;return v|0}g=c[550]|0;if(g){i=(g&0-g)+-1|0;f=i>>>12&16;i=i>>>f;e=i>>>5&8;i=i>>>e;h=i>>>2&4;i=i>>>h;d=i>>>1&2;i=i>>>d;j=i>>>1&1;j=c[2500+((e|f|h|d|j)+(i>>>j)<<2)>>2]|0;i=(c[j+4>>2]&-8)-k|0;d=j;while(1){a=c[d+16>>2]|0;if(!a){a=c[d+20>>2]|0;if(!a)break}d=(c[a+4>>2]&-8)-k|0;h=d>>>0>>0;i=h?d:i;d=a;j=h?a:j}h=j+k|0;if(h>>>0>j>>>0){f=c[j+24>>2]|0;b=c[j+12>>2]|0;do if((b|0)==(j|0)){a=j+20|0;b=c[a>>2]|0;if(!b){a=j+16|0;b=c[a>>2]|0;if(!b){d=0;break}}while(1){e=b+20|0;d=c[e>>2]|0;if(!d){e=b+16|0;d=c[e>>2]|0;if(!d)break;else{b=d;a=e}}else{b=d;a=e}}c[a>>2]=0;d=b}else{d=c[j+8>>2]|0;c[d+12>>2]=b;c[b+8>>2]=d;d=b}while(0);do if(f|0){b=c[j+28>>2]|0;a=2500+(b<<2)|0;if((j|0)==(c[a>>2]|0)){c[a>>2]=d;if(!d){c[550]=g&~(1<>2]|0)==(j|0)?v:f+20|0)>>2]=d;if(!d)break}c[d+24>>2]=f;b=c[j+16>>2]|0;if(b|0){c[d+16>>2]=b;c[b+24>>2]=d}b=c[j+20>>2]|0;if(b|0){c[d+20>>2]=b;c[b+24>>2]=d}}while(0);if(i>>>0<16){v=i+k|0;c[j+4>>2]=v|3;v=j+v+4|0;c[v>>2]=c[v>>2]|1}else{c[j+4>>2]=k|3;c[h+4>>2]=i|1;c[h+i>>2]=i;if(l|0){e=c[554]|0;b=l>>>3;d=2236+(b<<1<<2)|0;b=1<>2]|0}c[b>>2]=e;c[a+12>>2]=e;c[e+8>>2]=a;c[e+12>>2]=d}c[551]=i;c[554]=h}v=j+8|0;I=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=c[550]|0;if(e){d=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;a=c[2500+(j<<2)>>2]|0;a:do if(!a){f=0;a=0;q=61}else{f=0;h=k<<((j|0)==31?0:25-(j>>>1)|0);i=a;a=0;while(1){g=(c[i+4>>2]&-8)-k|0;if(g>>>0>>0)if(!g){d=0;f=i;a=i;q=65;break a}else{d=g;a=i}q=c[i+20>>2]|0;i=c[i+16+(h>>>31<<2)>>2]|0;f=(q|0)==0|(q|0)==(i|0)?f:q;if(!i){q=61;break}else h=h<<1}}while(0);if((q|0)==61){if((f|0)==0&(a|0)==0){a=2<>>12&16;a=a>>>i;h=a>>>5&8;a=a>>>h;j=a>>>2&4;a=a>>>j;m=a>>>1&2;a=a>>>m;f=a>>>1&1;f=c[2500+((h|i|j|m|f)+(a>>>f)<<2)>>2]|0;a=0}if(!f){i=d;g=a}else q=65}if((q|0)==65)while(1){m=(c[f+4>>2]&-8)-k|0;g=m>>>0>>0;d=g?m:d;g=g?f:a;a=c[f+16>>2]|0;if(!a)a=c[f+20>>2]|0;if(!a){i=d;break}else{f=a;a=g}}if(((g|0)!=0?i>>>0<((c[551]|0)-k|0)>>>0:0)?(l=g+k|0,l>>>0>g>>>0):0){h=c[g+24>>2]|0;b=c[g+12>>2]|0;do if((b|0)==(g|0)){a=g+20|0;b=c[a>>2]|0;if(!b){a=g+16|0;b=c[a>>2]|0;if(!b){b=0;break}}while(1){f=b+20|0;d=c[f>>2]|0;if(!d){f=b+16|0;d=c[f>>2]|0;if(!d)break;else{b=d;a=f}}else{b=d;a=f}}c[a>>2]=0}else{v=c[g+8>>2]|0;c[v+12>>2]=b;c[b+8>>2]=v}while(0);do if(h){a=c[g+28>>2]|0;d=2500+(a<<2)|0;if((g|0)==(c[d>>2]|0)){c[d>>2]=b;if(!b){e=e&~(1<>2]|0)==(g|0)?v:h+20|0)>>2]=b;if(!b)break}c[b+24>>2]=h;a=c[g+16>>2]|0;if(a|0){c[b+16>>2]=a;c[a+24>>2]=b}a=c[g+20>>2]|0;if(a){c[b+20>>2]=a;c[a+24>>2]=b}}while(0);b:do if(i>>>0<16){v=i+k|0;c[g+4>>2]=v|3;v=g+v+4|0;c[v>>2]=c[v>>2]|1}else{c[g+4>>2]=k|3;c[l+4>>2]=i|1;c[l+i>>2]=i;b=i>>>3;if(i>>>0<256){d=2236+(b<<1<<2)|0;a=c[549]|0;b=1<>2]|0}c[b>>2]=l;c[a+12>>2]=l;c[l+8>>2]=a;c[l+12>>2]=d;break}b=i>>>8;if(b)if(i>>>0>16777215)d=31;else{u=(b+1048320|0)>>>16&8;v=b<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=i>>>(d+7|0)&1|d<<1}else d=0;b=2500+(d<<2)|0;c[l+28>>2]=d;a=l+16|0;c[a+4>>2]=0;c[a>>2]=0;a=1<>2]=l;c[l+24>>2]=b;c[l+12>>2]=l;c[l+8>>2]=l;break}b=c[b>>2]|0;c:do if((c[b+4>>2]&-8|0)!=(i|0)){e=i<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=b+16+(e>>>31<<2)|0;a=c[d>>2]|0;if(!a)break;if((c[a+4>>2]&-8|0)==(i|0)){b=a;break c}else{e=e<<1;b=a}}c[d>>2]=l;c[l+24>>2]=b;c[l+12>>2]=l;c[l+8>>2]=l;break b}while(0);u=b+8|0;v=c[u>>2]|0;c[v+12>>2]=l;c[u>>2]=l;c[l+8>>2]=v;c[l+12>>2]=b;c[l+24>>2]=0}while(0);v=g+8|0;I=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=c[551]|0;if(d>>>0>=m>>>0){a=d-m|0;b=c[554]|0;if(a>>>0>15){v=b+m|0;c[554]=v;c[551]=a;c[v+4>>2]=a|1;c[b+d>>2]=a;c[b+4>>2]=m|3}else{c[551]=0;c[554]=0;c[b+4>>2]=d|3;v=b+d+4|0;c[v>>2]=c[v>>2]|1}v=b+8|0;I=w;return v|0}h=c[552]|0;if(h>>>0>m>>>0){t=h-m|0;c[552]=t;v=c[555]|0;u=v+m|0;c[555]=u;c[u+4>>2]=t|1;c[v+4>>2]=m|3;v=v+8|0;I=w;return v|0}if(!(c[667]|0)){c[669]=4096;c[668]=4096;c[670]=-1;c[671]=-1;c[672]=0;c[660]=0;c[667]=n&-16^1431655768;a=4096}else a=c[669]|0;i=m+48|0;j=m+47|0;g=a+j|0;e=0-a|0;k=g&e;if(k>>>0<=m>>>0){v=0;I=w;return v|0}a=c[659]|0;if(a|0?(l=c[657]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;I=w;return v|0}d:do if(!(c[660]&4)){d=c[555]|0;e:do if(d){f=2644;while(1){n=c[f>>2]|0;if(n>>>0<=d>>>0?(n+(c[f+4>>2]|0)|0)>>>0>d>>>0:0)break;a=c[f+8>>2]|0;if(!a){q=128;break e}else f=a}b=g-h&e;if(b>>>0<2147483647){a=pb(b|0)|0;if((a|0)==((c[f>>2]|0)+(c[f+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=a;g=b;q=145;break d}}else{e=a;q=136}}else b=0}else q=128;while(0);do if((q|0)==128){d=pb(0)|0;if((d|0)!=(-1|0)?(b=d,o=c[668]|0,p=o+-1|0,b=((p&b|0)==0?0:(p+b&0-o)-b|0)+k|0,o=c[657]|0,p=b+o|0,b>>>0>m>>>0&b>>>0<2147483647):0){n=c[659]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){b=0;break}a=pb(b|0)|0;if((a|0)==(d|0)){h=d;g=b;q=145;break d}else{e=a;q=136}}else b=0}while(0);do if((q|0)==136){d=0-b|0;if(!(i>>>0>b>>>0&(b>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){b=0;break}else{h=e;g=b;q=145;break d}a=c[669]|0;a=j-b+a&0-a;if(a>>>0>=2147483647){h=e;g=b;q=145;break d}if((pb(a|0)|0)==(-1|0)){pb(d|0)|0;b=0;break}else{h=e;g=a+b|0;q=145;break d}}while(0);c[660]=c[660]|4;q=143}else{b=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(r=pb(k|0)|0,p=pb(0)|0,t=p-r|0,s=t>>>0>(m+40|0)>>>0,!((r|0)==(-1|0)|s^1|r>>>0

>>0&((r|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=r;g=s?t:b;q=145}if((q|0)==145){b=(c[657]|0)+g|0;c[657]=b;if(b>>>0>(c[658]|0)>>>0)c[658]=b;j=c[555]|0;f:do if(j){e=2644;while(1){b=c[e>>2]|0;a=c[e+4>>2]|0;if((h|0)==(b+a|0)){q=154;break}d=c[e+8>>2]|0;if(!d)break;else e=d}if(((q|0)==154?(u=e+4|0,(c[e+12>>2]&8|0)==0):0)?h>>>0>j>>>0&b>>>0<=j>>>0:0){c[u>>2]=a+g;v=(c[552]|0)+g|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;c[555]=u;c[552]=t;c[u+4>>2]=t|1;c[j+v+4>>2]=40;c[556]=c[671];break}if(h>>>0<(c[553]|0)>>>0)c[553]=h;d=h+g|0;a=2644;while(1){if((c[a>>2]|0)==(d|0)){q=162;break}b=c[a+8>>2]|0;if(!b)break;else a=b}if((q|0)==162?(c[a+12>>2]&8|0)==0:0){c[a>>2]=h;l=a+4|0;c[l>>2]=(c[l>>2]|0)+g;l=h+8|0;l=h+((l&7|0)==0?0:0-l&7)|0;b=d+8|0;b=d+((b&7|0)==0?0:0-b&7)|0;k=l+m|0;i=b-l-m|0;c[l+4>>2]=m|3;g:do if((j|0)==(b|0)){v=(c[552]|0)+i|0;c[552]=v;c[555]=k;c[k+4>>2]=v|1}else{if((c[554]|0)==(b|0)){v=(c[551]|0)+i|0;c[551]=v;c[554]=k;c[k+4>>2]=v|1;c[k+v>>2]=v;break}a=c[b+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=c[b+8>>2]|0;d=c[b+12>>2]|0;if((d|0)==(a|0)){c[549]=c[549]&~(1<>2]=d;c[d+8>>2]=a;break}}else{g=c[b+24>>2]|0;a=c[b+12>>2]|0;do if((a|0)==(b|0)){e=b+16|0;d=e+4|0;a=c[d>>2]|0;if(!a){a=c[e>>2]|0;if(!a){a=0;break}else d=e}while(1){f=a+20|0;e=c[f>>2]|0;if(!e){f=a+16|0;e=c[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}c[d>>2]=0}else{v=c[b+8>>2]|0;c[v+12>>2]=a;c[a+8>>2]=v}while(0);if(!g)break;d=c[b+28>>2]|0;e=2500+(d<<2)|0;do if((c[e>>2]|0)!=(b|0)){v=g+16|0;c[((c[v>>2]|0)==(b|0)?v:g+20|0)>>2]=a;if(!a)break h}else{c[e>>2]=a;if(a|0)break;c[550]=c[550]&~(1<>2]=g;e=b+16|0;d=c[e>>2]|0;if(d|0){c[a+16>>2]=d;c[d+24>>2]=a}d=c[e+4>>2]|0;if(!d)break;c[a+20>>2]=d;c[d+24>>2]=a}while(0);b=b+h|0;f=h+i|0}else f=i;b=b+4|0;c[b>>2]=c[b>>2]&-2;c[k+4>>2]=f|1;c[k+f>>2]=f;b=f>>>3;if(f>>>0<256){d=2236+(b<<1<<2)|0;a=c[549]|0;b=1<>2]|0}c[b>>2]=k;c[a+12>>2]=k;c[k+8>>2]=a;c[k+12>>2]=d;break}b=f>>>8;do if(!b)e=0;else{if(f>>>0>16777215){e=31;break}u=(b+1048320|0)>>>16&8;v=b<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);a=2500+(e<<2)|0;c[k+28>>2]=e;b=k+16|0;c[b+4>>2]=0;c[b>>2]=0;b=c[550]|0;d=1<>2]=k;c[k+24>>2]=a;c[k+12>>2]=k;c[k+8>>2]=k;break}b=c[a>>2]|0;i:do if((c[b+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=b+16+(e>>>31<<2)|0;a=c[d>>2]|0;if(!a)break;if((c[a+4>>2]&-8|0)==(f|0)){b=a;break i}else{e=e<<1;b=a}}c[d>>2]=k;c[k+24>>2]=b;c[k+12>>2]=k;c[k+8>>2]=k;break g}while(0);u=b+8|0;v=c[u>>2]|0;c[v+12>>2]=k;c[u>>2]=k;c[k+8>>2]=v;c[k+12>>2]=b;c[k+24>>2]=0}while(0);v=l+8|0;I=w;return v|0}a=2644;while(1){b=c[a>>2]|0;if(b>>>0<=j>>>0?(v=b+(c[a+4>>2]|0)|0,v>>>0>j>>>0):0)break;a=c[a+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;b=a+8|0;d=g+-40|0;t=h+8|0;t=(t&7|0)==0?0:0-t&7;u=h+t|0;t=d-t|0;c[555]=u;c[552]=t;c[u+4>>2]=t|1;c[h+d+4>>2]=40;c[556]=c[671];d=a+4|0;c[d>>2]=27;c[b>>2]=c[661];c[b+4>>2]=c[662];c[b+8>>2]=c[663];c[b+12>>2]=c[664];c[661]=h;c[662]=g;c[664]=0;c[663]=b;b=a+24|0;do{u=b;b=b+4|0;c[b>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;c[d>>2]=c[d>>2]&-2;c[j+4>>2]=g|1;c[a>>2]=g;b=g>>>3;if(g>>>0<256){d=2236+(b<<1<<2)|0;a=c[549]|0;b=1<>2]|0}c[b>>2]=j;c[a+12>>2]=j;c[j+8>>2]=a;c[j+12>>2]=d;break}b=g>>>8;if(b)if(g>>>0>16777215)e=31;else{u=(b+1048320|0)>>>16&8;v=b<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=2500+(e<<2)|0;c[j+28>>2]=e;c[j+20>>2]=0;c[f>>2]=0;b=c[550]|0;a=1<>2]=j;c[j+24>>2]=d;c[j+12>>2]=j;c[j+8>>2]=j;break}b=c[d>>2]|0;j:do if((c[b+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=b+16+(e>>>31<<2)|0;a=c[d>>2]|0;if(!a)break;if((c[a+4>>2]&-8|0)==(g|0)){b=a;break j}else{e=e<<1;b=a}}c[d>>2]=j;c[j+24>>2]=b;c[j+12>>2]=j;c[j+8>>2]=j;break f}while(0);u=b+8|0;v=c[u>>2]|0;c[v+12>>2]=j;c[u>>2]=j;c[j+8>>2]=v;c[j+12>>2]=b;c[j+24>>2]=0}}else{v=c[553]|0;if((v|0)==0|h>>>0>>0)c[553]=h;c[661]=h;c[662]=g;c[664]=0;c[558]=c[667];c[557]=-1;c[562]=2236;c[561]=2236;c[564]=2244;c[563]=2244;c[566]=2252;c[565]=2252;c[568]=2260;c[567]=2260;c[570]=2268;c[569]=2268;c[572]=2276;c[571]=2276;c[574]=2284;c[573]=2284;c[576]=2292;c[575]=2292;c[578]=2300;c[577]=2300;c[580]=2308;c[579]=2308;c[582]=2316;c[581]=2316;c[584]=2324;c[583]=2324;c[586]=2332;c[585]=2332;c[588]=2340;c[587]=2340;c[590]=2348;c[589]=2348;c[592]=2356;c[591]=2356;c[594]=2364;c[593]=2364;c[596]=2372;c[595]=2372;c[598]=2380;c[597]=2380;c[600]=2388;c[599]=2388;c[602]=2396;c[601]=2396;c[604]=2404;c[603]=2404;c[606]=2412;c[605]=2412;c[608]=2420;c[607]=2420;c[610]=2428;c[609]=2428;c[612]=2436;c[611]=2436;c[614]=2444;c[613]=2444;c[616]=2452;c[615]=2452;c[618]=2460;c[617]=2460;c[620]=2468;c[619]=2468;c[622]=2476;c[621]=2476;c[624]=2484;c[623]=2484;v=g+-40|0;t=h+8|0;t=(t&7|0)==0?0:0-t&7;u=h+t|0;t=v-t|0;c[555]=u;c[552]=t;c[u+4>>2]=t|1;c[h+v+4>>2]=40;c[556]=c[671]}while(0);b=c[552]|0;if(b>>>0>m>>>0){t=b-m|0;c[552]=t;v=c[555]|0;u=v+m|0;c[555]=u;c[u+4>>2]=t|1;c[v+4>>2]=m|3;v=v+8|0;I=w;return v|0}}c[(Da()|0)>>2]=12;v=0;I=w;return v|0}function cb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(!a)return;d=a+-8|0;e=c[553]|0;a=c[a+-4>>2]|0;b=a&-8;k=d+b|0;do if(!(a&1)){f=c[d>>2]|0;if(!(a&3))return;g=d+(0-f)|0;h=f+b|0;if(g>>>0>>0)return;if((c[554]|0)==(g|0)){b=k+4|0;a=c[b>>2]|0;if((a&3|0)!=3){i=g;j=g;b=h;break}c[551]=h;c[b>>2]=a&-2;c[g+4>>2]=h|1;c[g+h>>2]=h;return}d=f>>>3;if(f>>>0<256){a=c[g+8>>2]|0;b=c[g+12>>2]|0;if((b|0)==(a|0)){c[549]=c[549]&~(1<>2]=b;c[b+8>>2]=a;i=g;j=g;b=h;break}}f=c[g+24>>2]|0;a=c[g+12>>2]|0;do if((a|0)==(g|0)){d=g+16|0;b=d+4|0;a=c[b>>2]|0;if(!a){a=c[d>>2]|0;if(!a){d=0;break}else b=d}while(1){e=a+20|0;d=c[e>>2]|0;if(!d){e=a+16|0;d=c[e>>2]|0;if(!d)break;else{a=d;b=e}}else{a=d;b=e}}c[b>>2]=0;d=a}else{d=c[g+8>>2]|0;c[d+12>>2]=a;c[a+8>>2]=d;d=a}while(0);if(f){a=c[g+28>>2]|0;b=2500+(a<<2)|0;if((c[b>>2]|0)==(g|0)){c[b>>2]=d;if(!d){c[550]=c[550]&~(1<>2]|0)==(g|0)?j:f+20|0)>>2]=d;if(!d){i=g;j=g;b=h;break}}c[d+24>>2]=f;b=g+16|0;a=c[b>>2]|0;if(a|0){c[d+16>>2]=a;c[a+24>>2]=d}a=c[b+4>>2]|0;if(a){c[d+20>>2]=a;c[a+24>>2]=d;i=g;j=g;b=h}else{i=g;j=g;b=h}}else{i=g;j=g;b=h}}else{i=d;j=d}while(0);if(i>>>0>=k>>>0)return;a=k+4|0;d=c[a>>2]|0;if(!(d&1))return;if(!(d&2)){if((c[555]|0)==(k|0)){k=(c[552]|0)+b|0;c[552]=k;c[555]=j;c[j+4>>2]=k|1;if((j|0)!=(c[554]|0))return;c[554]=0;c[551]=0;return}if((c[554]|0)==(k|0)){k=(c[551]|0)+b|0;c[551]=k;c[554]=i;c[j+4>>2]=k|1;c[i+k>>2]=k;return}f=(d&-8)+b|0;e=d>>>3;do if(d>>>0<256){b=c[k+8>>2]|0;a=c[k+12>>2]|0;if((a|0)==(b|0)){c[549]=c[549]&~(1<>2]=a;c[a+8>>2]=b;break}}else{g=c[k+24>>2]|0;a=c[k+12>>2]|0;do if((a|0)==(k|0)){d=k+16|0;b=d+4|0;a=c[b>>2]|0;if(!a){a=c[d>>2]|0;if(!a){d=0;break}else b=d}while(1){e=a+20|0;d=c[e>>2]|0;if(!d){e=a+16|0;d=c[e>>2]|0;if(!d)break;else{a=d;b=e}}else{a=d;b=e}}c[b>>2]=0;d=a}else{d=c[k+8>>2]|0;c[d+12>>2]=a;c[a+8>>2]=d;d=a}while(0);if(g|0){a=c[k+28>>2]|0;b=2500+(a<<2)|0;if((c[b>>2]|0)==(k|0)){c[b>>2]=d;if(!d){c[550]=c[550]&~(1<>2]|0)==(k|0)?h:g+20|0)>>2]=d;if(!d)break}c[d+24>>2]=g;b=k+16|0;a=c[b>>2]|0;if(a|0){c[d+16>>2]=a;c[a+24>>2]=d}a=c[b+4>>2]|0;if(a|0){c[d+20>>2]=a;c[a+24>>2]=d}}}while(0);c[j+4>>2]=f|1;c[i+f>>2]=f;if((j|0)==(c[554]|0)){c[551]=f;return}}else{c[a>>2]=d&-2;c[j+4>>2]=b|1;c[i+b>>2]=b;f=b}a=f>>>3;if(f>>>0<256){d=2236+(a<<1<<2)|0;b=c[549]|0;a=1<>2]|0}c[a>>2]=j;c[b+12>>2]=j;c[j+8>>2]=b;c[j+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{i=(a+1048320|0)>>>16&8;k=a<>>16&4;k=k<>>16&2;e=14-(h|i|e)+(k<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;b=2500+(e<<2)|0;c[j+28>>2]=e;c[j+20>>2]=0;c[j+16>>2]=0;a=c[550]|0;d=1<>2]=j;c[j+24>>2]=b;c[j+12>>2]=j;c[j+8>>2]=j}else{a=c[b>>2]|0;b:do if((c[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;b=c[d>>2]|0;if(!b)break;if((c[b+4>>2]&-8|0)==(f|0)){a=b;break b}else{e=e<<1;a=b}}c[d>>2]=j;c[j+24>>2]=a;c[j+12>>2]=j;c[j+8>>2]=j;break a}while(0);i=a+8|0;k=c[i>>2]|0;c[k+12>>2]=j;c[i>>2]=j;c[j+8>>2]=k;c[j+12>>2]=a;c[j+24>>2]=0}while(0);k=(c[557]|0)+-1|0;c[557]=k;if(k|0)return;a=2652;while(1){a=c[a>>2]|0;if(!a)break;else a=a+8|0}c[557]=-1;return}function db(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;f=a&65535;e=b&65535;c=r(e,f)|0;d=a>>>16;a=(c>>>16)+(r(e,d)|0)|0;e=b>>>16;b=r(e,f)|0;return (u((a>>>16)+(r(e,d)|0)+(((a&65535)+b|0)>>>16)|0),a+b<<16|c&65535|0)|0}function eb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;f=c;c=db(e,f)|0;a=v()|0;return (u((r(b,f)|0)+(r(d,e)|0)+a|a&0|0),c|0|0)|0}function fb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (u(b+d+(c>>>0>>0|0)>>>0|0),c|0)|0}function gb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (u(d|0),a-c>>>0|0)|0}function hb(a){a=a|0;return (a?31-(s(a^a-1)|0)|0:32)|0}function ib(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;l=a;j=b;k=j;h=d;n=e;i=n;if(!k){g=(f|0)!=0;if(!i){if(g){c[f>>2]=(l>>>0)%(h>>>0);c[f+4>>2]=0}n=0;f=(l>>>0)/(h>>>0)>>>0;return (u(n|0),f)|0}else{if(!g){n=0;f=0;return (u(n|0),f)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;f=0;return (u(n|0),f)|0}}g=(i|0)==0;do if(h){if(!g){g=(s(i|0)|0)-(s(k|0)|0)|0;if(g>>>0<=31){m=g+1|0;i=31-g|0;b=g-31>>31;h=m;a=l>>>(m>>>0)&b|k<>>(m>>>0)&b;g=0;i=l<>2]=a|0;c[f+4>>2]=j|b&0;n=0;f=0;return (u(n|0),f)|0}g=h-1|0;if(g&h|0){i=(s(h|0)|0)+33-(s(k|0)|0)|0;p=64-i|0;m=32-i|0;j=m>>31;o=i-32|0;b=o>>31;h=i;a=m-1>>31&k>>>(o>>>0)|(k<>>(i>>>0))&b;b=b&k>>>(i>>>0);g=l<>>(o>>>0))&j|l<>31;break}if(f|0){c[f>>2]=g&l;c[f+4>>2]=0}if((h|0)==1){o=j|b&0;p=a|0|0;return (u(o|0),p)|0}else{p=hb(h|0)|0;o=k>>>(p>>>0)|0;p=k<<32-p|l>>>(p>>>0)|0;return (u(o|0),p)|0}}else{if(g){if(f|0){c[f>>2]=(k>>>0)%(h>>>0);c[f+4>>2]=0}o=0;p=(k>>>0)/(h>>>0)>>>0;return (u(o|0),p)|0}if(!l){if(f|0){c[f>>2]=0;c[f+4>>2]=(k>>>0)%(i>>>0)}o=0;p=(k>>>0)/(i>>>0)>>>0;return (u(o|0),p)|0}g=i-1|0;if(!(g&i)){if(f|0){c[f>>2]=a|0;c[f+4>>2]=g&k|b&0}o=0;p=k>>>((hb(i|0)|0)>>>0);return (u(o|0),p)|0}g=(s(i|0)|0)-(s(k|0)|0)|0;if(g>>>0<=30){b=g+1|0;i=31-g|0;h=b;a=k<>>(b>>>0);b=k>>>(b>>>0);g=0;i=l<>2]=a|0;c[f+4>>2]=j|b&0;o=0;p=0;return (u(o|0),p)|0}while(0);if(!h){k=i;j=0;i=0}else{m=d|0|0;l=n|e&0;k=fb(m|0,l|0,-1,-1)|0;d=v()|0;j=i;i=0;do{e=j;j=g>>>31|j<<1;g=i|g<<1;e=a<<1|e>>>31|0;n=a>>>31|b<<1|0;gb(k|0,d|0,e|0,n|0)|0;p=v()|0;o=p>>31|((p|0)<0?-1:0)<<1;i=o&1;a=gb(e|0,n|0,o&m|0,(((p|0)<0?-1:0)>>31|((p|0)<0?-1:0)<<1)&l|0)|0;b=v()|0;h=h-1|0}while((h|0)!=0);k=j;j=0}h=0;if(f|0){c[f>>2]=a;c[f+4>>2]=b}o=(g|0)>>>31|(k|h)<<1|(h<<1|g>>>31)&0|j;p=(g<<1|0>>>31)&-2|i;return (u(o|0),p)|0}function jb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return ib(a,b,c,d,0)|0}function kb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){u(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function lb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){u(b<>>32-c|0);return a<=8192){z(b|0,d|0,e|0)|0;return b|0}h=b|0;g=b+e|0;if((b&3)==(d&3)){while(b&3){if(!e)return h|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((b|0)<=(f|0)){c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];c[b+16>>2]=c[d+16>>2];c[b+20>>2]=c[d+20>>2];c[b+24>>2]=c[d+24>>2];c[b+28>>2]=c[d+28>>2];c[b+32>>2]=c[d+32>>2];c[b+36>>2]=c[d+36>>2];c[b+40>>2]=c[d+40>>2];c[b+44>>2]=c[d+44>>2];c[b+48>>2]=c[d+48>>2];c[b+52>>2]=c[d+52>>2];c[b+56>>2]=c[d+56>>2];c[b+60>>2]=c[d+60>>2];b=b+64|0;d=d+64|0}while((b|0)<(e|0)){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}}else{e=g-4|0;while((b|0)<(e|0)){a[b>>0]=a[d>>0]|0;a[b+1>>0]=a[d+1>>0]|0;a[b+2>>0]=a[d+2>>0]|0;a[b+3>>0]=a[d+3>>0]|0;b=b+4|0;d=d+4|0}}while((b|0)<(g|0)){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0}return h|0}function nb(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if((c|0)<(b|0)&(b|0)<(c+d|0)){e=b;c=c+d|0;b=b+d|0;while((d|0)>0){b=b-1|0;c=c-1|0;d=d-1|0;a[b>>0]=a[c>>0]|0}b=e}else mb(b,c,d)|0;return b|0}function ob(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=b+e|0;d=d&255;if((e|0)>=67){while(b&3){a[b>>0]=d;b=b+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((b|0)<=(g|0)){c[b>>2]=i;c[b+4>>2]=i;c[b+8>>2]=i;c[b+12>>2]=i;c[b+16>>2]=i;c[b+20>>2]=i;c[b+24>>2]=i;c[b+28>>2]=i;c[b+32>>2]=i;c[b+36>>2]=i;c[b+40>>2]=i;c[b+44>>2]=i;c[b+48>>2]=i;c[b+52>>2]=i;c[b+56>>2]=i;c[b+60>>2]=i;b=b+64|0}while((b|0)<(f|0)){c[b>>2]=i;b=b+4|0}}while((b|0)<(h|0)){a[b>>0]=d;b=b+1|0}return h-e|0}function pb(a){a=a|0;var b=0,d=0,e=0;e=y()|0;d=c[i>>2]|0;b=d+a|0;if((a|0)>0&(b|0)<(d|0)|(b|0)<0){C(b|0)|0;w(12);return -1}if((b|0)>(e|0))if(!(A(b|0)|0)){w(12);return -1}c[i>>2]=b;return d|0}function qb(a,b){a=a|0;b=b|0;return L[a&1](b|0)|0}function rb(a,b,c,d,e,f,g){a=a|0;b=b|0;c=+c;d=d|0;e=e|0;f=f|0;g=g|0;return M[a&1](b|0,+c,d|0,e|0,f|0,g|0)|0}function sb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return N[a&1](b|0,c|0,d|0)|0}function tb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return O[a&1](b|0,c|0,d|0,e|0)|0}function ub(a,b,c){a=a|0;b=b|0;c=c|0;P[a&1](b|0,c|0)}function vb(a){a=a|0;t(0);return 0}function wb(a,b,c,d,e,f){a=a|0;b=+b;c=c|0;d=d|0;e=e|0;f=f|0;t(1);return 0}function xb(a,b,c){a=a|0;b=b|0;c=c|0;t(2);return 0}function yb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;t(3);return 0}function zb(a,b){a=a|0;b=b|0;t(4)} + +// EMSCRIPTEN_END_FUNCS +var L=[vb,Aa];var M=[wb,Fa];var N=[xb,Ba];var O=[yb,Ca];var P=[zb,Ga];return{___errno_location:Da,___muldi3:eb,___udivdi3:jb,_bitshift64Lshr:kb,_bitshift64Shl:lb,_compress:U,_decompress:V,_free:cb,_i64Add:fb,_i64Subtract:gb,_malloc:bb,_memcpy:mb,_memmove:nb,_memset:ob,_sbrk:pb,dynCall_ii:qb,dynCall_iidiiii:rb,dynCall_iiii:sb,dynCall_iiiii:tb,dynCall_vii:ub,establishStackSpace:T,stackAlloc:Q,stackRestore:S,stackSave:R}}) + + +// EMSCRIPTEN_END_ASM +(asmGlobalArg,asmLibraryArg,buffer);var ___errno_location=Module["___errno_location"]=asm["___errno_location"];var ___muldi3=Module["___muldi3"]=asm["___muldi3"];var ___udivdi3=Module["___udivdi3"]=asm["___udivdi3"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _compress=Module["_compress"]=asm["_compress"];var _decompress=Module["_decompress"]=asm["_decompress"];var _free=Module["_free"]=asm["_free"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memmove=Module["_memmove"]=asm["_memmove"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];var dynCall_ii=Module["dynCall_ii"]=asm["dynCall_ii"];var dynCall_iidiiii=Module["dynCall_iidiiii"]=asm["dynCall_iidiiii"];var dynCall_iiii=Module["dynCall_iiii"]=asm["dynCall_iiii"];var dynCall_iiiii=Module["dynCall_iiiii"]=asm["dynCall_iiiii"];var dynCall_vii=Module["dynCall_vii"]=asm["dynCall_vii"];Module["asm"]=asm;Module["ccall"]=ccall;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); + +var HS_LOG_LEVEL = 0; + +function heatshrink_compress(inputBuffer) { + if (inputBuffer.BYTES_PER_ELEMENT!=1) throw new Error("Expecting Byte Array"); + var input_size = inputBuffer.length; + var output_size = input_size + (input_size/2) + 4; + + var bufIn = Module._malloc(input_size); + Module.HEAPU8.set(inputBuffer, bufIn); + // int compress(uint8_t *input, uint32_t input_size, uint8_t *output, uint32_t output_size, int log_lvl) + output_size = Module.ccall('compress', 'number', ['number','number','number','number','number'], [bufIn,input_size,0,0,HS_LOG_LEVEL/*log level*/])+1; + var bufOut = Module._malloc(output_size); + output_size = Module.ccall('compress', 'number', ['number','number','number','number','number'], [bufIn,input_size,bufOut,output_size,HS_LOG_LEVEL/*log level*/]); + // console.log("Compressed to "+output_size); + + var outputBuffer = new Uint8Array(output_size); + for (var i=0;i>16; + var pg=(p>>8)&255; + var pb=p&255; + var dr = r-pr; + var dg = g-pg; + var db = b-pb; + var d = dr*dr + dg*dg + db*db; + if (dthresh; + }, + "2bitbw":function(r,g,b) { + var c = (r+g+b) / 3; + c += 31; // rounding + if (c>255)c=255; + return c>>6; + }, + "4bit":function(r,g,b,a) { + var thresh = 128; + return ( + ((r>thresh)?1:0) | + ((g>thresh)?2:0) | + ((b>thresh)?4:0) | + ((a>thresh)?8:0)); + }, + "4bitmac":function(r,g,b,a) { + return PALETTE.lookup(PALETTE.MAC16,r,g,b,a, true /* no transparency */); + }, + "vga":function(r,g,b,a) { + return PALETTE.lookup(PALETTE.VGA,r,g,b,a); + }, + "web":function(r,g,b,a) { + return PALETTE.lookup(PALETTE.WEB,r,g,b,a); + }, + "rgb565":function(r,g,b,a) { + return ( + ((r&0xF8)<<8) | + ((g&0xFC)<<3) | + ((b&0xF8)>>3)); + }, + }; + var COL_TO_RGB = { + "1bit":function(c) { + return c ? 0xFFFFFFFF : 0xFF000000; + }, + "2bitbw":function(c) { + c = c&3; + c = c | (c<<2) | (c<<4) | (c<<6); + return 0xFF000000|(c<<16)|(c<<8)|c; + }, + "4bit":function(c) { + if (!(c&8)) return 0; + return ((c&1 ? 0xFF0000 : 0xFF000000) | + (c&2 ? 0x00FF00 : 0xFF000000) | + (c&4 ? 0x0000FF : 0xFF000000)); + }, + "4bitmac":function(c) { + return 0xFF000000|PALETTE.MAC16[c]; + }, + "vga":function(c) { + if (c==TRANSPARENT_8BIT) return 0; + return 0xFF000000|PALETTE.VGA[c]; + }, + "web":function(c) { + if (c==TRANSPARENT_8BIT) return 0; + return 0xFF000000|PALETTE.WEB[c]; + }, + "rgb565":function(c) { + var r = (c>>8)&0xF8; + var g = (c>>3)&0xFC; + var b = (c<<3)&0xF8; + return 0xFF000000|(r<<16)|(g<<8)|b; + }, + }; + // What Espruino uses by default + var BPP_TO_COLOR_FORMAT = { + 1 : "1bit", + 2 : "2bitbw", + 4 : "4bitmac", + 8 : "web", + 16 : "rgb565" + }; + + function clip(x) { + if (x<0) return 0; + if (x>255) return 255; + return x; + } + + + /* + See 'getOptions' for possible options + */ + function RGBAtoString(rgba, options) { + options = options||{}; + if (!rgba) throw new Error("No dataIn specified"); + if (!options.width) throw new Error("No Width specified"); + if (!options.height) throw new Error("No Height specified"); + if ("string"!=typeof options.diffusion) + options.diffusion = "none"; + options.compression = options.compression || false; + options.brightness = options.brightness | 0; + options.mode = options.mode || "1bit"; + options.output = options.output || "object"; + options.inverted = options.inverted || false; + options.transparent = !!options.transparent; + var transparentCol = undefined; + if (options.transparent) { + if (options.mode=="4bit") + transparentCol=0; + if (options.mode=="vga" || options.mode=="web") + transparentCol=TRANSPARENT_8BIT; + } + var bpp = COL_BPP[options.mode]; + var bitData = new Uint8Array(((options.width*options.height)*bpp+7)/8); + + function readImage() { + var pixels = new Int32Array(options.width*options.height); + var n = 0; + var er=0,eg=0,eb=0; + for (var y=0; y>>24; + var or = (cr>>16)&255; + var og = (cr>>8)&255; + var ob = cr&255; + if (options.diffusion.startsWith("error") && a>128) { + er = r-or; + eg = g-og; + eb = b-ob; + } else { + er = 0; + eg = 0; + eb = 0; + } + + n++; + } + } + return pixels; + } + function writeImage(pixels) { + var n = 0; + for (var y=0; y>3] |= c ? 128>>(n&7) : 0; + else if (bpp==2) bitData[n>>2] |= c<<((3-(n&3))*2); + else if (bpp==4) bitData[n>>1] |= c<<((n&1)?0:4); + else if (bpp==8) bitData[n] = c; + else if (bpp==16) { bitData[n<<1] = c>>8; bitData[1+(n<<1)] = c&0xFF; } + else throw new Error("Unhandled BPP"); + // Write preview + var cr = COL_TO_RGB[options.mode](c); + if (c===transparentCol) + cr = ((((x>>2)^(y>>2))&1)?0xFFFFFF:0); // pixel pattern + var oa = cr>>>24; + var or = (cr>>16)&255; + var og = (cr>>8)&255; + var ob = cr&255; + if (options.rgbaOut) { + options.rgbaOut[n*4] = or; + options.rgbaOut[n*4+1]= og; + options.rgbaOut[n*4+2]= ob; + options.rgbaOut[n*4+3]=255; + } + n++; + } + } + } + + var pixels = readImage(); + if (options.transparent && transparentCol===undefined && bpp<=16) { + // we have no fixed transparent colour - pick one that's unused + var colors = new Uint32Array(1<=0) + colors[pixels[i]]++; + // find an empty one + for (var i=0;i>2)^(y>>2))&1)?0xFFFFFF:0); + rgba[n*4] = rgba[n*4]*na + chequerboard*a; + rgba[n*4+1] = rgba[n*4+1]*na + chequerboard*a; + rgba[n*4+2] = rgba[n*4+2]*na + chequerboard*a; + rgba[n*4+3] = 255; + n++; + } + } + } + + /* RGBAtoString options, PLUS: + + updateCanvas: update canvas with the quantized image + */ + function canvastoString(canvas, options) { + options = options||{}; + options.width = canvas.width; + options.height = canvas.height; + var ctx = canvas.getContext("2d"); + var imageData = ctx.getImageData(0, 0, options.width, options.height); + var rgba = imageData.data; + if (options.updateCanvas) + options.rgbaOut = rgba; + var str = RGBAtoString(rgba, options); + if (options.updateCanvas) + ctx.putImageData(imageData,0,0); + return str; + } + + /* RGBAtoString options, PLUS: + + */ + function imagetoString(img, options) { + options = options||{}; + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext("2d"); + ctx.drawImage(img,0,0); + return canvastoString(canvas, options); + } + + function getOptions() { + return { + width : "int", + height : "int", + rgbaOut : "Uint8Array", // to store quantised data + diffusion : ["none"], + compression : "bool", + transparent : "bool", + brightness : "int", + mode : Object.keys(COL_BPP), + output : ["object","string","raw"], + inverted : "bool", + } + } + + /* Decode an Espruino image string into a URL, return undefined if it's not valid. + options = { + transparent : bool // should the image be transparent, or just chequered where transparent? + } */ + function stringToImageURL(data, options) { + options = options||{}; + var p = 0; + var width = 0|data.charCodeAt(p++); + var height = 0|data.charCodeAt(p++); + var bpp = 0|data.charCodeAt(p++); + var transparentCol = -1; + if (bpp&128) { + bpp &= 127; + transparentCol = 0|data.charCodeAt(p++); + } + var mode = BPP_TO_COLOR_FORMAT[bpp]; + if (!mode) return undefined; // unknown format + var bitmapSize = ((width*height*bpp)+7) >> 3; + // If it's the wrong length, it's not a bitmap or it's corrupt! + if (data.length != p+bitmapSize) + return undefined; + // Ok, build the picture + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext("2d"); + var imageData = ctx.getImageData(0, 0, width, height); + var rgba = imageData.data; + var no = 0; + var nibits = 0; + var nidata = 0; + for (var i=0;i>(nibits-bpp)) & ((1<>16)&255; // r + rgba[no++] = (cr>>8)&255; // g + rgba[no++] = cr&255; // b + rgba[no++] = cr>>>24; // a + } + if (!options.transparent) + RGBAtoCheckerboard(rgba, {width:width, height:height}); + ctx.putImageData(imageData,0,0); + return canvas.toDataURL(); + } + +// decode an Espruino image string into an HTML string, return undefined if it's not valid. See stringToImageURL + function stringToImageHTML(data, options) { + var url = stringToImageURL(data, options); + if (!url) return undefined; + return ''; + } + + // ======================================================= + return { + RGBAtoString : RGBAtoString, + RGBAtoCheckerboard : RGBAtoCheckerboard, + canvastoString : canvastoString, + imagetoString : imagetoString, + getOptions : getOptions, + + stringToImageHTML : stringToImageHTML, + stringToImageURL : stringToImageURL + }; +})); From 20ddb0cb44f87c6f567d7c7f16c3b0597db3964e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 7 May 2020 10:19:57 +0100 Subject: [PATCH 0705/1189] drop chunk size again - too tight --- js/appinfo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/appinfo.js b/js/appinfo.js index 6a91dce2d..b4d0b5426 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -72,7 +72,7 @@ var AppInfo = { } else { let code = storageFile.content; // write code in chunks, in case it is too big to fit in RAM (fix #157) - var CHUNKSIZE = 8192; + var CHUNKSIZE = 4096; storageFile.cmd = `\x10require('Storage').write(${JSON.stringify(storageFile.name)},${toJS(code.substr(0,CHUNKSIZE))},0,${code.length});`; for (var i=CHUNKSIZE;i Date: Thu, 7 May 2020 10:20:09 +0100 Subject: [PATCH 0706/1189] Add option for 16 bit images --- apps/imgclock/custom.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/imgclock/custom.html b/apps/imgclock/custom.html index 1506aa7d4..8c920571a 100644 --- a/apps/imgclock/custom.html +++ b/apps/imgclock/custom.html @@ -52,6 +52,12 @@

+
+ +

+

or Enter Wifi name:

+

and Wifi password:

+
+ +
+ +
+
+
+ + +

Try your QR Code:

Click

@@ -14,19 +30,54 @@ + + + + \ No newline at end of file From 05e3a1f51f273d1f736343b5650009fad590abc1 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sun, 17 May 2020 12:01:52 +0100 Subject: [PATCH 0869/1189] gpsnav 0.03 --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 04c2f637d..a0421c2ed 100644 --- a/apps.json +++ b/apps.json @@ -331,10 +331,11 @@ { "id": "gpsnav", "name": "GPS Navigation", "icon": "icon.png", - "version":"0.01", - "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording", + "version":"0.03", + "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording, now with waypoint editor", "tags": "tool,outdoors,gps", "readme": "README.md", + "interface":"waypoints.html", "storage": [ {"name":"gpsnav.app.js","url":"app.js"}, {"name":"waypoints.json","url":"waypoints.json","evaluate":false}, From ca65ff6be6591b90798f2df510c5cad27f88b44e Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 17:50:07 +0100 Subject: [PATCH 0870/1189] Create app.js --- apps/BLEcontroller/app.js | 424 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 apps/BLEcontroller/app.js diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js new file mode 100644 index 000000000..a486917cf --- /dev/null +++ b/apps/BLEcontroller/app.js @@ -0,0 +1,424 @@ +/* + +========================================================== + +Simple event based robot controller that enables robot +to switch into automatic or manual control modes. Behaviours +are controlled via a simple finite state machine. + +In automatic mode the +robot will look after itself. In manual mode, the watch +will provide simple forward, back, left and right commands. +The messages will be transmitted to a partner BLE Espruino +using BLE + +Written by Richard Hopkins, May 2020 + +========================================================== + +declare global variables for watch button statuses */ +top_btn = false; +middle_btn = false; +left_btn= false; // the left side of the touch screen +right_btn = false; // the right side of the touch screen +bottom_btn = false; + +/* + +CONFIGURATION AREA - STATE VARIABLES + +declare global variables for the toggle button +statuses; if you add an additional toggle button +you should declare it and initiase it here */ + +var status_auto = {value: false}; +var status_mic = {value: true}; +var status_spk = {value: true}; + +/* trsnsmit message */ +const transmit = (state,object,status) => { + message = { + state: state, + obj: object, + val: status, + }; + print(message); + return JSON.stringify(message); +}; + +/* + +CONFIGURATION AREA - ICON DEFINITIONS + +Retrieve 30px PNG icons from: +https://icons8.com/icon/set/speak/ios-glyphs + +Create icons using: +https://www.espruino.com/Image+Converter +Use compression: true +Transparency: true +Diffusion: flat +Colours: 16bit RGB +Ouput as: Image Object + +Add an additional element to the icons array +with a unique name and the data from the Image Object +*/ +const icons = [ + { + name: "walk", + data: "gEBAP4B/ALyh7b/YALHfY9tACY55HfYdNHto7pHpIbXbL5fXAD6VlHuYAjHf47/Hf47tHK47LDa45zHc4NHHeILJHeonTO9o9rHf47/eOoB/ANg=" + }, + { + name: "sit", + data: "gEBAP4B/AP4BacO4ANHPI/rACp1/Hf49rGtI5/He7n3ACY55HcYAZHf45/Hf45rHe4XHGbI7/Va47zZZrpbHfbtXD5Y/vHcYB/AP4BmA" + }, + { + name: "joystick", + data: "gEBAP4B/AP4BMavIALHPI9vHf47/eP45vHpY5xHo451Hf47/FuYAHHNItHABa33AP6xpAD455HqY7/Hf47/Hd49pHKIB/AP4B/AMwA==" + }, + { + name: "left", + data: "gEBAP4B/AP4BKa9ojHAC5pfHJKDTUsYdZHb6ZfO+I9dABabdLbIBdHf473PP47NJdY7/ePIB/RJop5Ys7t/AP6PvD7o7fP8Y1zTZoHPf/4B/AP4B+A==" + }, + { + name: "right", + data: "gEBAP4B/AP4BKa+oAXDo45hCaqFbUbLBfbbo7bHMojTR7Y5LHa51ZALo75Ov47/FeY77AP4B5WdbF3dv4B/R94fdHb5/jGuabNA57//AP4B/APw=" + }, + { + name: "forward", + data: "gEBAP4B/AKSX5avIALHPI9tACY55HsoAbHPI9fHfZFVGMo7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf49XHOIB/ALw=" + }, + { + name: "backward", + data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/HfIAfHf491W/L15HMo9THNI9PHNo9LHOI9HHOoB/ALg=" + }, + { + name: "back", + data: "gEBAP4B/AP4B/AKgADHPI71HP45/HP45/HP45/HP45/Hf49/Hv49/Hv49/Hv49/Hv497He4B/AP4B/AJAA==" + }, + { + name: "spk_on", + data: "gEBAP4B/AP4Bic/YAFPP4v1HrYZRVJo7ZDKp5jMJYvZHaYAHVL4LHACZrhADLBTJKI7dPLI7/Hf47/HeZBVFqZHZRJp1lAJ47LOtZTnHbIZDKLpHNAL69ZANp1tQbY5/AP4B/ANQ" + }, + { + name: "spk_off", + data: "gEBAPhB7P/o9rFKI9pFKY9tXNYZNHrZXfMaoAHPOZhNF7LdXHpKpZEJpvPDZK1ZAB49NPLo9jHdI9NHd49PHebvxEJY9NI6I7dHpaDXcKqfPHLKjZHcpTjHbIZDKa73JHa4BXGY45xe5Y7zV+o9/Hv49JHe4BEA=" + }, + { + name: "mic_on", + data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Hf47/Hf47/HdY9NCpp5lCb57fOdYvNeJo91HNrlvHf7tVIdY77AP4BiA=" + }, + { + name: "mic_off", + data: "gEBAP4B/AKCZ5a/Y7/Hf47/Hf47/Hf47/GbY7TIcY7/Wf47/HJZLjHZ45RHrI7NHJYhLHqoZJA54hNHr5lTXL6vPSra5jKbo9REZrLRHa5DTXp47jAA7TTF7INLRqY7fdKavhXKo5te6wA==" + }, + { + name: "comms", + data: "gEBAP4B+QvbF7ABo7/He49tACI7/Hf47zHtI7jJq47lRqoAVEqY7nHsoAZGJo71HrKxfQaY7bdKo7/Hdqz5B5Y7zHK47RD55FRHao3XHKo7JG7L1NHeJTbHboB/AP4BG" + } +]; + +/* finds icon data by name in the icon array and returns an image object*/ +const drawIcon = (name) => { + for (var icon of icons) { + if (icon.name == name) { + image = { + width : 30, height : 30, bpp : 16, + transparent : 1, + buffer: require("heatshrink").decompress(atob(icon.data)) + }; + return image;} + } +}; + +/* + +CONFIGURATION AREA - BUTTON DEFINITIONS + +for a simple button, just define a primary colour +and an icon name from the icon array and +the text to display beneath the button + +for toggle buttons, additionally provide secondary +colours, icon name and text. Also provide a reference +to a global variable for the value of the button. +The global variable should be declared at the start of +the program and it may be adviable to use the 'status_name' +format to ensure it is clear. + +*/ +var joystickBtn = { + primary_colour: 0x653E, + primary_icon: 'joystick', + primary_text: 'Joystick', + }; + +var turnLeftBtn = { + primary_colour: 0x653E, + primary_text: 'Left', + primary_icon: 'left', + }; + +var turnRightBtn = { + primary_colour: 0x33F9, + primary_text: 'Right', + primary_icon: 'right', + }; + +var autoBtn = { + primary_colour: 0xE9C7, + primary_text: 'Stop', + primary_icon: 'sit', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'Move', + secondary_icon : 'walk', + value: status_auto + }; + +var micBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'mic_off', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'mic_on', + value: status_mic + }; + +var spkBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'spk_off', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'spk_on', + value: status_spk + }; + +/* + +CONFIGURATION AREA - SCREEN DEFINITIONS + +a screen can have a button (as defined above) +on the left and/or the right of the screen. + +in adddition a screen can optionally have +an icon for each of the three buttons on +the left hand side of the screen. These +are defined as btn1, bt2 and bt3. The +values are names from the icon array. + +*/ +const menuScreen = { + left: autoBtn, + right: joystickBtn, + btn1: "comms" +}; + +const joystickScreen = { + left: turnLeftBtn, + right: turnRightBtn, + btn1: "forward", + btn2: "backward", + btn3: "back" +}; + +const commsScreen = { + left: micBtn, + right: spkBtn, + btn3: "back" +}; + +/* base state definition + +Each of the screens correspond to a state; +this class provides a constuctor for each +of the states + +*/ +class State { + constructor(params) { + this.state = params.state; + this.events = params.events; + this.screen = params.screen; + } +} + +/* + +CONFIGURATION AREA - BUTTON BEHAVIOURS/STATE TRANSITIONS + +This area defines how each screen behaves. + +Each screen corresponds to a different State of the +state machine. This makes it much easier to isolate +behaviours between screens. + +The state value is transmitted whenever a button is pressed +to provide context (so the receiving device, knows which +button was pressed on which screen). + +The screens are defined above. + +The events section identifies if a particular button has been +pressed and released on the screen and an action can then be taken. + +The events function receives a notification from a mySetWatch which +provides an event object that identifies which button and whether +it has been pressed down or released. Actions can then be taken. +The events function will always return a State object. + +If the events function returns different State from the current +one, then the state machine will change to that new State and redrsw +the screen appropriately. + +To add in additional capabilities for button presses, simply add +an additional 'if' statement. + +For toggle buttons, the value of the sppropiate status object is +inversed and the new value transmitted. + +*/ + +/* The Home State/Page is where the application beings */ +const Home = new State({ + state: "Home", + screen: menuScreen, + events: (event) => { + if ((event.object == "right") && (event.status == "end")) { + transmit("Joystick", "joystick", "on"); + return Joystick; + } + if ((event.object == "top") && (event.status == "end")) { + return Comms; + } + if ((event.object == "left") && (event.status == "end")) { + status_auto.value = !status_auto.value; + transmit(this.state, "auto", onOff(status_auto.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +/* Joystick page state */ +const Joystick = new State({ + state: "Joystick", + screen: joystickScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + transmit("Joystick", "joystick", "off"); + return Home; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +/* Comms page state */ +const Comms = new State({ + state: "Comms", + screen: commsScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return Home; + } + if ((event.object == "left") && (event.status == "end")) { + status_mic.value = !status_mic.value; + transmit(this.state, "mic", onOff(status_mic.value)); + return this; + } + if ((event.object == "right") && (event.status == "end")) { + status_spk.value = !status_spk.value; + transmit(this.state, "spk", onOff(status_spk.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +/* translate button status into english */ +const startEnd = status => status ? "start" : "end"; + +/* translate status into english */ +const onOff= status => status ? "on" : "off"; + + +/* create watching functions that will change the global +button status when pressed or released + +This is actuslly the hesrt of the program. When a button +is not being pressed, nothing is happening (no loops). +This makes the progrsm more battery efficient. + +When a setWatch event is raised, the custom callbacks defined +here will be called. These then fired as events to the current +state/screen of the state mschine. + +Some events, will result in the stste of the state machine +chsnging, which is why the screen is redrswn after each +button press. + +*/ +const setMyWatch = (params) => { + setWatch(() => { + params.bool=!params.bool; + machine = machine.events({object: params.label, status: startEnd(params.bool)}); + drawScreen(machine.screen); + }, params.btn, {repeat:true, edge:"both"}); +}; + +/* object array used to set up the watching functions +*/ +const buttons = [ + {bool : bottom_btn, label : "bottom",btn : BTN3}, + {bool : middle_btn, label : "mdiddle",btn : BTN2}, + {bool : top_btn, label : "top",btn : BTN1}, + {bool : left_btn, label : "left",btn : BTN4}, + {bool : right_btn, label : "right",btn : BTN5} + ]; + +/* set up watchers for buttons */ +for (var button of buttons) + {setMyWatch(button);} + +/* Draw various kinds of buttons */ +const drawButton = (params,side) => { + g.setFontAlign(0,1); + icon = drawIcon(params.primary_icon); + text = params.primary_text; + g.setColor(params.primary_colour); + const x = (side == "left") ? 0 : 120; + if ((params.toggle) && (params.value.value)) { + g.setColor(params.secondary_colour); + text = params.secondary_text; + icon = drawIcon(params.secondary_icon); + } + g.fillRect(0+x,24,119+x, 239); + g.setColor(0x000); + g.setFont("Vector",15); + g.setFontAlign(0,0.0); + g.drawString(text,60+x,160); + options = {rotate: 0, scale:2}; + g.drawImage(icon,x+60,120,options); +}; + +/* Draw the pages corresponding to the states */ +const drawScreen = (params) => { + drawButton(params.left,'left'); + drawButton(params.right,'right'); + g.setColor(0x000); + if (params.btn1) {g.drawImage(drawIcon(params.btn1),210,40);} + if (params.btn2) {g.drawImage(drawIcon(params.btn2),210,125);} + if (params.btn3) {g.drawImage(drawIcon(params.btn3),210,195);} +}; + +machine = Home; // instantiate the state machine at Home +Bangle.drawWidgets(); // draw active widgets +drawScreen(machine.screen); // draw the screen From 033b227e674a50e55a1bdc356bedc90045c18dd9 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 17:56:05 +0100 Subject: [PATCH 0871/1189] Create app-icon.js --- apps/BLEcontroller/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/BLEcontroller/app-icon.js diff --git a/apps/BLEcontroller/app-icon.js b/apps/BLEcontroller/app-icon.js new file mode 100644 index 000000000..da959f36a --- /dev/null +++ b/apps/BLEcontroller/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("nk8wkBiIA/AH4A/AA8QaIYdYd4gOLG5odMBhYcHCBAuEgJVVDqQLHCA0BNpA6QSYgd5LLYaFSq4dQLR4wJLyQdKQJBbOJZwdYBxypRS6AdZJZ4drPH54/PH541DjIdCDjRaBDjYAhTITUeDy4cEDzAdXCwoANGh4ANIRASKFBQdRBZodtLLq0TDv4dZAH4A/AH4ArA==")) From 0e67901c39932c90cf93d9529f50d13f959a7042 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 17:59:52 +0100 Subject: [PATCH 0872/1189] Update app-icon.js --- apps/BLEcontroller/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app-icon.js b/apps/BLEcontroller/app-icon.js index da959f36a..db64a917d 100644 --- a/apps/BLEcontroller/app-icon.js +++ b/apps/BLEcontroller/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("nk8wkBiIA/AH4A/AA8QaIYdYd4gOLG5odMBhYcHCBAuEgJVVDqQLHCA0BNpA6QSYgd5LLYaFSq4dQLR4wJLyQdKQJBbOJZwdYBxypRS6AdZJZ4drPH54/PH541DjIdCDjRaBDjYAhTITUeDy4cEDzAdXCwoANGh4ANIRASKFBQdRBZodtLLq0TDv4dZAH4A/AH4ArA==")) +E.toArrayBuffer(atob("PDyEARERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERAAAAAAEREREREREREREREREREREREREREREREREQAAAAAAEREREREREREREQAAEREREREREREREAAAAAAAAAAAERERERERERERAAAAABERERERERERAAAAAAAAAAAAEREREREREREQAAAAAAERERERERERAAAAAAAREREREREREREREREQAAAAAAERERERERERAAAAAAEREREREREREREREREAAAEQAAAAAAAAAAAAAAAAABEREREREREREREREREAABERAAAAAAAAAAAAAAAAABEREREREREREREREREAABERAAAAAAAAAAAAAAAAABEREREREREREREREREAAAEQAAAAAAAAAAAAAAAAABEREREREREREREREREQAAAAAAARERERERERAAAAAAEREREREREREREREREQAAAAAAARERERERERAAAAAAARERERERERERERERERAAAAAAABERERERERAAAAAAAAAAAAEREREREREREREQAAAAABEREREREREAAAAAAAAAAAERERERERERERERAAAAAAEREREREREREREQAAAAAAERERERERERERERAAAAAAERERERERERERERAAAAAAEREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREQAAAAABEREREREREREREREREREREREREREREREREQAAAAABERERERERERERERERERERERERERERERERERAAAAAAERERERERERERERERERERERERERERERERERAAAAAAEREREREREREREREREREREREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREQAAAAABEREREREREREREREREREREREREREREREREQAAAAABERERERERERERERERERERERERERERERERERAAAAAAERERERERERERERERERERERERERERERERERAAAAAAEREREREREREREREREREREREREREREREREREAAAAREREREREREREREREREREREREREREREREREREAABEREREREREREREREREREREREREREREREREREREQEREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREQAAABERERERERERERERERERERERERERERERERERAAAAAAAREREREREREREREREREREREREREREREREAAAAAAAAAEREREREREREREREREREREREREREREREAAAAAAAAAERERERERERERERERERERERAAAAAAAAAAAAAAAAAAAAAAAAAAAREREREREREREQAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREREREREAAAAAAAAAAAAAARAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAEREAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAEREAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAARAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREQ==")) From ed20c802da0f7b577754d37c4e439be01cc54290 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:01:52 +0100 Subject: [PATCH 0873/1189] Add files via upload --- apps/BLEcontroller/BLEcontroller.png | Bin 0 -> 579 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/BLEcontroller/BLEcontroller.png diff --git a/apps/BLEcontroller/BLEcontroller.png b/apps/BLEcontroller/BLEcontroller.png new file mode 100644 index 0000000000000000000000000000000000000000..df529e982df191f6cd16e13b91503880546e3b05 GIT binary patch literal 579 zcmV-J0=)f+P)0&l=6uncr60#<-4LD4u}oUzxLt0>JPsZnf=H(GxN=RY=~QshW#_o)vQwR6Y53F~sJV_j|%*5y{mx(s~cZ7WuRX_Eh7pF8SZ{s6XtF}HHkrwH5v6Rw41 zNv~@GuIa$r4sHRLz>^=B{%f=THUEMs;D+eweGN>yk*LQe-jt3q8=UAHE`(~Zj@)Qt ztU1v8g9121lQz+evKsB_gZkjyq`k;P$V1t$Rs%<)Kikb8MP#4*f0#kFbpFtz5!vGy!T@R R(GCCr002ovPDHLkV1mbo0=NJG literal 0 HcmV?d00001 From 89a49189f4c4694a971e332b69a0a62a569e6900 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:07:04 +0100 Subject: [PATCH 0874/1189] Update apps.json --- apps.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps.json b/apps.json index 04c2f637d..6385082f6 100644 --- a/apps.json +++ b/apps.json @@ -1760,5 +1760,20 @@ { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } ], "version": "0.03" + }, +{ + "id": "BLEcontroller", + "name": "BLE Robot Controller with Joystick", + "shortName": "BLE Controller", + "icon": "BLEcontroller.png", + "version": "0.01", + "description": "A configurable controller for BLE robots, including a basic joystick.", + "tags": "tools", + "readme": "README.md", + "allow_emulator":true, + "storage": [ + { "name": "BLEcontroller.app.js", "url": "app.js" }, + { "name": "BLEcontroller.img", "url": "app-icon.js", "evaluate": true } + ] } ] From 6bf2b7d9691d224b8fdf33b557a378fa6f06e9fd Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:09:54 +0100 Subject: [PATCH 0875/1189] Create README.md --- apps/BLEcontroller/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 apps/BLEcontroller/README.md diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md new file mode 100644 index 000000000..172bb1758 --- /dev/null +++ b/apps/BLEcontroller/README.md @@ -0,0 +1,3 @@ +=== BLE Controller +==Some text += More text From 0d013efb8e1c342a187c54027a75f88fe2acbcd2 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:13:23 +0100 Subject: [PATCH 0876/1189] Update app-icon.js --- apps/BLEcontroller/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app-icon.js b/apps/BLEcontroller/app-icon.js index db64a917d..0f5e1aff6 100644 --- a/apps/BLEcontroller/app-icon.js +++ b/apps/BLEcontroller/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("PDyEARERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERAAAAAAEREREREREREREREREREREREREREREREREQAAAAAAEREREREREREREQAAEREREREREREREAAAAAAAAAAAERERERERERERAAAAABERERERERERAAAAAAAAAAAAEREREREREREQAAAAAAERERERERERAAAAAAAREREREREREREREREQAAAAAAERERERERERAAAAAAEREREREREREREREREAAAEQAAAAAAAAAAAAAAAAABEREREREREREREREREAABERAAAAAAAAAAAAAAAAABEREREREREREREREREAABERAAAAAAAAAAAAAAAAABEREREREREREREREREAAAEQAAAAAAAAAAAAAAAAABEREREREREREREREREQAAAAAAARERERERERAAAAAAEREREREREREREREREQAAAAAAARERERERERAAAAAAARERERERERERERERERAAAAAAABERERERERAAAAAAAAAAAAEREREREREREREQAAAAABEREREREREAAAAAAAAAAAERERERERERERERAAAAAAEREREREREREREQAAAAAAERERERERERERERAAAAAAERERERERERERERAAAAAAEREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREQAAAAABEREREREREREREREREREREREREREREREREQAAAAABERERERERERERERERERERERERERERERERERAAAAAAERERERERERERERERERERERERERERERERERAAAAAAEREREREREREREREREREREREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREAAAAAAREREREREREREREREREREREREREREREREREQAAAAABEREREREREREREREREREREREREREREREREQAAAAABERERERERERERERERERERERERERERERERERAAAAAAERERERERERERERERERERERERERERERERERAAAAAAEREREREREREREREREREREREREREREREREREAAAAREREREREREREREREREREREREREREREREREREAABEREREREREREREREREREREREREREREREREREREQEREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREQAAABERERERERERERERERERERERERERERERERERAAAAAAAREREREREREREREREREREREREREREREREAAAAAAAAAEREREREREREREREREREREREREREREREAAAAAAAAAERERERERERERERERERERERAAAAAAAAAAAAAAAAAAAAAAAAAAAREREREREREREQAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREREREREAAAAAAAAAAAAAARAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAEREAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAEREAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAARAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREQ==")) +E.toArrayBuffer(atob("QECEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREhEhEREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREj////MzIREREAAAAAAAAAAAAAAAAAAAAAAAAAARERP//////zMzIRERAAAAAAAAAAAAAAAAAAAAAAAAARES/////////zMzIREQAAAAAAAAAAAAAAAAAAAAAAARET//////////8zMzEREAAAAAAAAAAAAAAAAAAAAAARET////////////MzMxERAAAAAAAAAAAAAAAAAAAAABET/////////////zMzMREAAAAAAAAAAAAAAAAAAAABES//////////////8zMyERAAAAAAAAAAAAAAAAAAABES///////////////zMzMREQAAAAAAAAAAAAAAAAAAERP//////zMzMzP///8zMzERAAAAAAAAAAAAAAAAAAARL//////zMzMzMz///zMzMhEAAAAAAAAAAAAAAAAAARE//////zM///MzM///8zMyERAAAAAAAAAAAAAAAAABEf/////zM///8zMzP//zMzMREAAAAAAAAAAAAAAAAAES//////M////zMzM///MzMxEQAAAAAAAAAAAAAAAAARL/////8z//MzMzMz///zMzIRAAAAAAAAAAAAAAAAARE//////zP/8zMzMzP///MzMhEQAAAAAAAAAAAAAAABET//////M//zMzMzM///8zMyERAAAAAAAAAAAAAAAAERP/////8zPzMzMzMz///zMzMREAAAAAAAAAAAAAAAARE//////zMzMzMzMzP///MzMxEQAAAAAAAAAAAAAAABET//////MzMzMzMzM///8zMzERAAAAAAAAAAAAAAAAERP//////zMzMzMzM////zMzMREAAAAAAAAAAAAAAAARE///////8zMzMzM/////MzMxEQAAAAAAAAAAAAAAABET////////MzMzM/////8zMyERAAAAAAAAAAAAAAABERE/////////8z///////zMyEREQAAAAAAAAAAAAAAERERP/////////////////MzERERAAAAAAAAAAAAAAERIhEv////////////////8zIRIhEQAAAAAAAAAAAAARH/ER/////////////////zMRH/ERAAAAAAAAAAAAABESIRL/////////////////MyESIREAAAAAAAAAAAAAERERE/////////////////8zMREREQAAAAAAAAAAAAAREREv/////////////////zMyERERAAAAAAAAAAAAARERE///////////////////MzMhEREQAAAAAAAAAAARERET//////////////////8zMzEREREAAAAAAAAAABEQERP//////////////////zMzMREBEQAAAAAAAAABERARE///////////////////MzMxEQEREAAAAAAAABERABET//////////////////8zMzERABERAAAAAAERERAAERP//////////////////zMzMREAAREREAAAEREREAARE///////////////////MzMxEQABERERAAEREREQABET//////////////////8zMzERAAEREREQAREzERAAERP//////////////////zMzMREAAREAERABEf8REAARE///////////////////MzMxEQABEQAREAEREREQABET//////////////////8zMzERAAEREREQABEREQAAERP/8///P/8z//P/8z//PzMzMREAABEREQAAARERAAARE//zP/M//zP/Mz/zP/MzMzMxEQAAEREQAAAAAREAABET//P//z//M//z//M//z8zMzERAAAREAAAAAABEQAAERP//////////////////zMzMREAABEQAAAAAAEREAAREv//////////////////MzMhEQABERAAAAAAABEQAAEREREREREREREREREREREREREQAAERAAAAAAAAEREAABEREREREREREREREREREREREQAAEREAAAAAAAARERAAAREREREREREREREREREREREQAAEREQAAAAAAAREREQAAAAAAAAEREREREREREQAAAAAAEREREAAAAAAREREREAAAAAAAAREREREREREREAAAAAERERERAAAAABEQABEQAAAAAAABERERERERERERAAAAAREAAREAAAAAEQAAERAAAAAREREREREREREREREAAAABEAABEQAAAAARAAABEAAAARERERERERERERERERAAAAEQAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) From 0bb93839e65d107a5a56d105199ac80a55740e64 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:14:17 +0100 Subject: [PATCH 0877/1189] Add files via upload --- apps/BLEcontroller/BLEcontroller.png | Bin 579 -> 3473 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/BLEcontroller/BLEcontroller.png b/apps/BLEcontroller/BLEcontroller.png index df529e982df191f6cd16e13b91503880546e3b05..e42fe5dae5a7bc3cfc4aa20380f5a036df9d081f 100644 GIT binary patch literal 3473 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 delta 572 zcmV-C0>k~08^Z)4iBL{Q4GJ0x0000DNk~Le0000y0000y2nGNE06P5Ha*-hve*ySO zL_t(&f$f?-OT%yw#(%zppx`Ll!AZYDK}5ktT@@$6$+4>-4uYRW2PwEnt>EqpBH}1I zh^~rOaS>mJq!5cu&g7DRD))n1+Hm(gy?>6TS1=62FboYAfOp_4BK`$Zv#N%BfD&*F zyaI2)DXkX?r}JJNp{T89bhe@1S;c+}|v zR)8x((Kub6LC3T@MM2THU2eua4jvwYNT&0+a!sk}RB+K{=eX#yQ>@EP!n)k*SeJhZ z>vF4OU2YQAA>3# zZUL9TlOLDyk*LQe-jt3q8=UAHE`(~Zj@)QttU1v8g9121lQz+ zevKsB_gZkjyq`k;P$V1t$Rs%<)Kikb8MP#4*f0#kFbpFtz5!vG61?|g1JMou0000< KMNUMnLSTYaZ~#sK From 673e1c3c7bb326b62c9f352713deb63259f43d11 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:18:08 +0100 Subject: [PATCH 0878/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6385082f6..afac26dba 100644 --- a/apps.json +++ b/apps.json @@ -1767,7 +1767,7 @@ "shortName": "BLE Controller", "icon": "BLEcontroller.png", "version": "0.01", - "description": "A configurable controller for BLE robots, including a basic joystick.", + "description": "A configurable controller for BLE robots, with a basic four direction joystick.", "tags": "tools", "readme": "README.md", "allow_emulator":true, From 077728de67e620ef4dc9f71c4e62642759406429 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:18:56 +0100 Subject: [PATCH 0879/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index afac26dba..c3780cfeb 100644 --- a/apps.json +++ b/apps.json @@ -1768,7 +1768,7 @@ "icon": "BLEcontroller.png", "version": "0.01", "description": "A configurable controller for BLE robots, with a basic four direction joystick.", - "tags": "tools", + "tags": "tool,bluetooth", "readme": "README.md", "allow_emulator":true, "storage": [ From ba68904acf2e6a436794d40e4236d28d697c1dea Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:23:51 +0100 Subject: [PATCH 0880/1189] Update app-icon.js --- apps/BLEcontroller/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/app-icon.js b/apps/BLEcontroller/app-icon.js index 0f5e1aff6..662f43c5c 100644 --- a/apps/BLEcontroller/app-icon.js +++ b/apps/BLEcontroller/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("QECEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREREREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREhEhEREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREj////MzIREREAAAAAAAAAAAAAAAAAAAAAAAAAARERP//////zMzIRERAAAAAAAAAAAAAAAAAAAAAAAAARES/////////zMzIREQAAAAAAAAAAAAAAAAAAAAAAARET//////////8zMzEREAAAAAAAAAAAAAAAAAAAAAARET////////////MzMxERAAAAAAAAAAAAAAAAAAAAABET/////////////zMzMREAAAAAAAAAAAAAAAAAAAABES//////////////8zMyERAAAAAAAAAAAAAAAAAAABES///////////////zMzMREQAAAAAAAAAAAAAAAAAAERP//////zMzMzP///8zMzERAAAAAAAAAAAAAAAAAAARL//////zMzMzMz///zMzMhEAAAAAAAAAAAAAAAAAARE//////zM///MzM///8zMyERAAAAAAAAAAAAAAAAABEf/////zM///8zMzP//zMzMREAAAAAAAAAAAAAAAAAES//////M////zMzM///MzMxEQAAAAAAAAAAAAAAAAARL/////8z//MzMzMz///zMzIRAAAAAAAAAAAAAAAAARE//////zP/8zMzMzP///MzMhEQAAAAAAAAAAAAAAABET//////M//zMzMzM///8zMyERAAAAAAAAAAAAAAAAERP/////8zPzMzMzMz///zMzMREAAAAAAAAAAAAAAAARE//////zMzMzMzMzP///MzMxEQAAAAAAAAAAAAAAABET//////MzMzMzMzM///8zMzERAAAAAAAAAAAAAAAAERP//////zMzMzMzM////zMzMREAAAAAAAAAAAAAAAARE///////8zMzMzM/////MzMxEQAAAAAAAAAAAAAAABET////////MzMzM/////8zMyERAAAAAAAAAAAAAAABERE/////////8z///////zMyEREQAAAAAAAAAAAAAAERERP/////////////////MzERERAAAAAAAAAAAAAAERIhEv////////////////8zIRIhEQAAAAAAAAAAAAARH/ER/////////////////zMRH/ERAAAAAAAAAAAAABESIRL/////////////////MyESIREAAAAAAAAAAAAAERERE/////////////////8zMREREQAAAAAAAAAAAAAREREv/////////////////zMyERERAAAAAAAAAAAAARERE///////////////////MzMhEREQAAAAAAAAAAARERET//////////////////8zMzEREREAAAAAAAAAABEQERP//////////////////zMzMREBEQAAAAAAAAABERARE///////////////////MzMxEQEREAAAAAAAABERABET//////////////////8zMzERABERAAAAAAERERAAERP//////////////////zMzMREAAREREAAAEREREAARE///////////////////MzMxEQABERERAAEREREQABET//////////////////8zMzERAAEREREQAREzERAAERP//////////////////zMzMREAAREAERABEf8REAARE///////////////////MzMxEQABEQAREAEREREQABET//////////////////8zMzERAAEREREQABEREQAAERP/8///P/8z//P/8z//PzMzMREAABEREQAAARERAAARE//zP/M//zP/Mz/zP/MzMzMxEQAAEREQAAAAAREAABET//P//z//M//z//M//z8zMzERAAAREAAAAAABEQAAERP//////////////////zMzMREAABEQAAAAAAEREAAREv//////////////////MzMhEQABERAAAAAAABEQAAEREREREREREREREREREREREREQAAERAAAAAAAAEREAABEREREREREREREREREREREREQAAEREAAAAAAAARERAAAREREREREREREREREREREREQAAEREQAAAAAAAREREQAAAAAAAAEREREREREREQAAAAAAEREREAAAAAAREREREAAAAAAAAREREREREREREAAAAAERERERAAAAABEQABEQAAAAAAABERERERERERERAAAAAREAAREAAAAAEQAAERAAAAAREREREREREREREREAAAABEAABEQAAAAARAAABEAAAARERERERERERERERERAAAAEQAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) +E.toArrayBuffer(atob("MDCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAABERIQAAAAAAAAAAAAAAAAAAAAAAAAABERIRpiEQAAAAAAAAAAAAAAAAAAAAAAEREhOiImEqYAAAAAAAAAAAAAAAAAAAABESP///8zOFEQAAAAAAAAAAAAAAAAAAARI//////z8zp6AAAAAAAAAAAAAAAAAAES////////PzOFEAAAAAAAAAAAAAAAABEv////////8/MyGgAAAAAAAAAAAAAAARI//////////z8zIRAAAAAAAAAAAAAAARP/////8/P///M/IRAAAAAAAAAAAAAAES/////zgzM///M/OFEAAAAAAAAAAAAAET////84/zMzP/8z8hEAAAAAAAAAAAAAEf////M///gzP/8/MyEAAAAAAAAAAAABEv///zP/8zjzM/8/M4UQAAAAAAAAAAABEv///zP/M48zj//zPyEQAAAAAAAAAAABE////zP/ODMzj//zPyEQAAAAAAAAAAABE////zMzjyM48//zPyEQAAAAAAAAAAABE/////ODMzOPP/8/M4QQAAAAAAAAAAABE/////MzjzOD///zPyEQAAAAAAAAAAABE/////8zOPMz///zMzEQAAAAAAAAAAABEj//////PzP///8/MxhQAAAAAAAAAAARES////////////8/MRpyAAAAAAAAAAASMRP////////////zMRMhAAAAAAAAAAARMR////////////8/IRMhAAAAAAAAAAARES/////////////zMhp6AAAAAAAAAAEREv////////////8/MyEacAAAAAAAABERIv/////////////zPyERGAAAAAAAABEBE//////////////zPyEQEQAAAAAAAREBE//////////////zPyEQERAAAAABERABE//////////////zPyEQAREQAAEREgABE//////////////zPyEQABERIAESESABE//////////////zPyEQARESEAEfIRABE//////////////zPyEQAREBEAEREgABE//////z//////8/MzEQABERIAAREQABE/8/8z/zPz/z8/M/MzGAABERAAABEQABE/8/8/8/Pz/z8/PzPyEQABEQAAAAEQABE//////////////zPyEQABEAAAAAERAAETMzMzMzMjMzMzODIxEAAREAAAAAARAAEREhGmIRGhESaiYRKmEAARAAAAAAEREgABERIaYhEaERJqEmEQABERIAAAABERIaAAAAAAEREhGmIREAAAARESGgAAABEAARAAAAAAEREhGmIRGgAAARAAEQAAABEAARAAABERIRpiERoREgAAARAAEQAAAAAAAAAAABERIRpiERoREgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) From dfc54d8d73703eb816ed2c37817c0a61a09e9edf Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:24:17 +0100 Subject: [PATCH 0881/1189] Add files via upload --- apps/BLEcontroller/BLEcontroller.png | Bin 3473 -> 2642 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/BLEcontroller/BLEcontroller.png b/apps/BLEcontroller/BLEcontroller.png index e42fe5dae5a7bc3cfc4aa20380f5a036df9d081f..3fa8575f30c5b25c3b1b21708de7281fed85de1c 100644 GIT binary patch literal 2642 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 A$p8QV literal 3473 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 From 0d8501f2d64e221ff80512cb819cdf4123c05141 Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:26:13 +0100 Subject: [PATCH 0882/1189] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index c3780cfeb..ef6f68d11 100644 --- a/apps.json +++ b/apps.json @@ -1767,7 +1767,7 @@ "shortName": "BLE Controller", "icon": "BLEcontroller.png", "version": "0.01", - "description": "A configurable controller for BLE robots, with a basic four direction joystick.", + "description": "A configurable controller for BLE robots, with a basic four direction joystick. Easy to customise and add your own menus.", "tags": "tool,bluetooth", "readme": "README.md", "allow_emulator":true, From a38371d8d4e208552470718cf082c78e6e40f5df Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:36:54 +0100 Subject: [PATCH 0883/1189] Update README.md --- apps/BLEcontroller/README.md | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index 172bb1758..a21db6240 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -1,3 +1,31 @@ -=== BLE Controller -==Some text -= More text +# BLE Robot Controller with Joystic + +A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. Amaze your friends by controlling your robot from your watch! + +Commands are sent from the Controller to the BLE robot in a JSON format. + +## Usage + +The application can be configured at will by chaning the definitions of the screens, events, icons and buttons. + +Most changes are possible via data, rather than code change. + +## Features + +In its default state, it has three screens that provide the ability to: +turn the robot on or off +turn on and off its voice and microphone +make the robot move by spinning left or right and moving forward and backwards + +## Controls + +The controls will vary by screen, but I suggest a convention of using BTN3 (the bottom button) for moving backwards up the menu stack. + +## Requests + +In the first instance, please consult my blog post on this application here. + +## Creator + +Richard Hopkins, FIET CEng +May 2020 From ce066c2a3852895a293df19fdaa3a2ca13bff37a Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Sun, 17 May 2020 18:37:10 +0100 Subject: [PATCH 0884/1189] Update README.md --- apps/BLEcontroller/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index a21db6240..049a5f824 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -1,4 +1,4 @@ -# BLE Robot Controller with Joystic +# BLE Robot Controller with Joystick A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. Amaze your friends by controlling your robot from your watch! From 31e56b23eddfd7f6c2e37d0f8fa983019bfc25bb Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sun, 17 May 2020 18:46:44 -0400 Subject: [PATCH 0885/1189] Stop Gadgetbridge from ignoring initial message. Gadgetbridge seems to ignore the first line sent to it after connecting. This commit works around this by prepending each message with a blank line. --- apps/gbridge/widget.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index a87b9d1ec..0d0f2468d 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -13,6 +13,7 @@ }; function gbSend(message) { + Bluetooth.println(""); Bluetooth.println(JSON.stringify(message)); } From 9ebb718cc259475efe88b6a585ddb9d44165212d Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Sun, 17 May 2020 13:37:08 -0400 Subject: [PATCH 0886/1189] gbridge: report battery status more often Make the gbridge widget report battery status - every 10 minutes - 2 seconds after a new bluetooth connection is initiated --- apps.json | 2 +- apps/gbridge/ChangeLog | 1 + apps/gbridge/widget.js | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 04c2f637d..ff13cdff6 100644 --- a/apps.json +++ b/apps.json @@ -95,7 +95,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.10", + "version":"0.11", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index f23a4eb6d..f66040388 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -9,3 +9,4 @@ 0.08: Don't turn on LCD at start of every song 0.09: Update Bluetooth connection state automatically 0.10: Make widget play well with other Gadgetbridge widgets/apps +0.11: Report battery status on connect and at regular intervals diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 0d0f2468d..ae7d0f8fa 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -197,5 +197,11 @@ WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: draw }; - gbSend({ t: "status", bat: E.getBattery() }); + function sendBattery() { + gbSend({ t: "status", bat: E.getBattery() }); + } + + NRF.on("connect", () => setTimeout(sendBattery, 2000)); + setInterval(sendBattery, 10*60*1000); + sendBattery(); })(); From 89bd6532255bbbc50ac03624c1844b2f08ad6293 Mon Sep 17 00:00:00 2001 From: Francesco Bedussi Date: Mon, 18 May 2020 22:46:45 +0200 Subject: [PATCH 0887/1189] chore: ignore .vscode folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index be33fbc90..757619ec5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ package-lock.json .DS_Store *.js.bak appdates.csv +.vscode From 3148a59dc6ccaa6646c262375e96c59ba821619f Mon Sep 17 00:00:00 2001 From: Francesco Bedussi Date: Mon, 18 May 2020 22:57:08 +0200 Subject: [PATCH 0888/1189] fix: simpletimer - BTN2 to open launcher --- apps.json | 2 +- apps/simpletimer/ChangeLog | 1 + apps/simpletimer/app.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index adc1cf907..a34dcf3a4 100644 --- a/apps.json +++ b/apps.json @@ -1633,7 +1633,7 @@ "id": "simpletimer", "name": "Timer", "icon": "app.png", - "version": "0.02", + "version": "0.03", "description": "Simple timer, useful when playing board games or cooking", "tags": "timer", "readme": "README.md", diff --git a/apps/simpletimer/ChangeLog b/apps/simpletimer/ChangeLog index f9f79cd47..3f8d98248 100644 --- a/apps/simpletimer/ChangeLog +++ b/apps/simpletimer/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial version 0.02: Reset with gesture +0.03: BTN2 to open launcher diff --git a/apps/simpletimer/app.js b/apps/simpletimer/app.js index b8e07d107..0bd7992e2 100644 --- a/apps/simpletimer/app.js +++ b/apps/simpletimer/app.js @@ -111,6 +111,7 @@ function reset(value) { state = value === 0 ? "unset" : "set"; } +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); function addWatch() { clearWatch(); setWatch(changeState, BTN1, { From d98fca9f01c4d6e2a864c2e49a06154d178f51c0 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 19 May 2020 15:22:41 +0100 Subject: [PATCH 0889/1189] Create ChangeLog --- apps/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/ChangeLog diff --git a/apps/ChangeLog b/apps/ChangeLog new file mode 100644 index 000000000..1a4baf536 --- /dev/null +++ b/apps/ChangeLog @@ -0,0 +1 @@ + From 17fb9e795f861841400221059996c67122b42d8f Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 19 May 2020 15:23:43 +0100 Subject: [PATCH 0890/1189] Delete ChangeLog --- apps/ChangeLog | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/ChangeLog diff --git a/apps/ChangeLog b/apps/ChangeLog deleted file mode 100644 index 1a4baf536..000000000 --- a/apps/ChangeLog +++ /dev/null @@ -1 +0,0 @@ - From b45fb06ec1ba35536dd4a76ef5f2ef0270f55c4e Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 19 May 2020 15:25:21 +0100 Subject: [PATCH 0891/1189] Create ChangeLog --- apps/widviz/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/widviz/ChangeLog diff --git a/apps/widviz/ChangeLog b/apps/widviz/ChangeLog new file mode 100644 index 000000000..1a4baf536 --- /dev/null +++ b/apps/widviz/ChangeLog @@ -0,0 +1 @@ + From b602188abe3974d8d5c363c3765b05b19043a401 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 19 May 2020 15:28:34 +0100 Subject: [PATCH 0892/1189] Widget files --- apps/widviz/eye.png | Bin 0 -> 1519 bytes apps/widviz/widget.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 apps/widviz/eye.png create mode 100644 apps/widviz/widget.js diff --git a/apps/widviz/eye.png b/apps/widviz/eye.png new file mode 100644 index 0000000000000000000000000000000000000000..414ad33f582b9e69e51269d45fe309b333d808c7 GIT binary patch literal 1519 zcmVOEpmkE19Hr3VSFItI*?O0g~z9Ncw>>2GDK`Ua)#w z`vaj!>bJxKq;g(Ptx;++;OTRv3)Flk@X0mjEh3!u$h4NIux%@pYl?F2574kLa=69* zOMh?%C`?t&%h_9%r^`*@Bq@NJ?*!htGU^RSS^Wl?&}_iVwAn>+p++LWg(v_7C!!<% z$X)kD*T{IAE!gjwV7(>9(EZh#>6dCcpwpeMlN|)>adlD7<}$@njd+?tjWau+Un<{Ism=iC zBMb4_br;n{5qNo-a_e#>n(-+H0Ehv6bHm-xPDG;gTrZU?UaL^01$5EsJ=kognlf=# zeT{ZSK{og0UMJbu4*Mbipvx6h=+wW6>x&|=p;)%NQZ3}HXRnjo{@tKE zlwiUH$f;UAYw#o>KN;P8&SslB9TE}x@l%Bls(EO3{W!#O3zk+EW;d)W;4jLdz@r*24FJ5~IyOBG0Q@>Q{z2Oqw||KWJFr$m zaoRi+$J&$3XrOL;sL|@BnlF|qR`UgnUMG3J$3rzW62ajbZFAki=DLONKB1d0r@iNF zx2MlVaz}V%e$JM1CDm-Sdb{l*Hc$-UNQ;AVh{a0LD=U@2r$(!nGSf%|Up;GByHJ7) zQCx^t7v-F))oUb)SR9Q3^B*#`b-7}RN<^6*X>m|~lK^V71#dbMc?tn|YfV0P`{S|< z&^cs}SuMq~m`|k``np-oYs{1YMfR=ErzW`R2)EgSNkFH6cT(1mEs~Vx-!uA+`XkhD zlL6-%nDumLJRI<LEid6RrGIRUg~8SODY_4=4z#uDWs z0MIeWbJp5z^fpbC+q*_Wmv8&2CIyfHG8^#Xyu=BQ0UWyOh;Tz50069F?8tEo!72ni zp~<6+)6O(zikyrcx@xB;D9*#oQ@fu4LICzw1BCGrIdo}|{)=l}8#x{g?Hl$J2gP?A&c zG^q_TVf=SA2Kz6M^46@oE7dCtd2%gN6@~aNGfy(_wucU0p*PDQ6Yex6)gehh5)oQo zqs6AK3O+LW>i0vvPIj~vqDaHKf{mpz-cW@i@LZ|9VVzFEdEDa&@AzRTIFWEWOn}ta zXqkx&(kVZb*;(~9+HxJwlJvRAMyuB{K$jmTJ-*&3<=rXEKyY8vs5hKp`4JbZK+8gr zx^l(8DbUVbcb(`Um}y~CuMCW!N@b9nqi3vpvKDX?W+!p6ld@)3aQ z1(FvYmZz+&V*p(vq0g_oTJ8pt=9_VmAJ@IEL3*jsWWdX`;v%_7D-qx#6aa!`bl4xc z<0iX?L#?*pknet9gW{T97ez|5=qgQVc71GMYPNii`ENAqzM#zkrP3TwD$N0<(m&`h Vo=7w-CD;G}002ovPDHLkV1nTx;!6Mk literal 0 HcmV?d00001 diff --git a/apps/widviz/widget.js b/apps/widviz/widget.js new file mode 100644 index 000000000..36d695c60 --- /dev/null +++ b/apps/widviz/widget.js @@ -0,0 +1,37 @@ +(() => { + + var saved = null; + + function hide(){ + if (!Bangle.isLCDOn() || saved) return; + saved = []; + for (var wd of WIDGETS) { + saved.push(wd.draw); + wd.draw=()=>{}; + } + g.setColor(0,0,0); + g.fillRect(0,0,239,23); + } + + function reveal(){ + if (!Bangle.isLCDOn() || !saved) return; + for (var wd of WIDGETS) wd.draw = saved.shift(); + Bangle.drawWidgets(); + saved=null; + } + + function setup(){ + setWatch(hide, BTN4, {repeat:true,edge:"rising"}); + setWatch(reveal, BTN5, {repeat:true,edge:"rising"}); + } + + function draw(){ + var img = E.toArrayBuffer(atob("GBgBAAAAAAAAAAAAAAAAAH4AAf+AB4HgDgBwHDw4OH4cMOcMYMMGYMMGMOcMOH4cHDw4DgBwB4HgAf+AAH4AAAAAAAAAAAAAAAAA")); + g.setColor(0x07ff); + g.drawImage(img,this.x,this.y); + } + + WIDGETS["viz"] ={area:"tl", width:24,draw:draw,setup:setup}; + setup(); + +})(); From fe0387b3bb6d7465790134dfee50be3d700baa16 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 19 May 2020 15:29:50 +0100 Subject: [PATCH 0893/1189] Update ChangeLog --- apps/widviz/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/widviz/ChangeLog b/apps/widviz/ChangeLog index 1a4baf536..ac6257425 100644 --- a/apps/widviz/ChangeLog +++ b/apps/widviz/ChangeLog @@ -1 +1 @@ - + 0.01: New Widget From 19ed596a16250ea6ede6646e317eeb4575ed4ada Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 19 May 2020 15:33:01 +0100 Subject: [PATCH 0894/1189] Update apps.json --- apps.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps.json b/apps.json index a34dcf3a4..f351bee16 100644 --- a/apps.json +++ b/apps.json @@ -1761,5 +1761,17 @@ { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } ], "version": "0.03" + }, + { "id": "widviz", + "name": "Widget Visibility Widget", + "shortName":"Viz Widget", + "icon": "eye.png", + "version":"0.01", + "description": "Touch left screen to hide top bar widgets, right screen to redisplay. Will not work with apps that use BTN4 & BTN5.", + "tags": "widget", + "type": "widget", + "storage": [ + {"name":"widviz.wid.js","url":"widget.js"} + ] } ] From 7e39d8f1b5881dbd21b06db873fad699f45b4869 Mon Sep 17 00:00:00 2001 From: GRISHENK0 Date: Wed, 20 May 2020 14:45:25 +0200 Subject: [PATCH 0895/1189] Update French locales Change thousands separator and modify the speed unit --- apps/locale/locales.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index cbc56b85c..3becc760b 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -145,10 +145,10 @@ var locales = { "fr_FR": { lang: "fr_FR", decimal_point: ",", - thousands_sep: ".", + thousands_sep: " ", currency_symbol: "\x80", int_curr_symbol: "EUR", - speed: "kmh", + speed: "km/h", distance: { 0: "m", 1: "km" }, temperature: "°C", ampm: { 0: "", 1: "" }, From 5f8e424f5fd0d640f5688d960f33edaf1194e193 Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Mon, 11 May 2020 20:58:31 -0400 Subject: [PATCH 0896/1189] imgclock: Make imgclock text area wider This prevents imgclock from cutting off the date in locales with long date formats such as "Wednesday, September 10, 2020". Also adjusts the position and alignment of the date when necessary to prevent it from flowing off the edge of the screen. --- apps.json | 2 +- apps/imgclock/ChangeLog | 3 ++- apps/imgclock/app.js | 14 ++++++++++---- apps/imgclock/custom.html | 16 +++++++++------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/apps.json b/apps.json index a34dcf3a4..07cedf21a 100644 --- a/apps.json +++ b/apps.json @@ -168,7 +168,7 @@ "name": "Image background clock", "shortName":"Image Clock", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "A clock with an image as a background", "tags": "clock", "type" : "clock", diff --git a/apps/imgclock/ChangeLog b/apps/imgclock/ChangeLog index ae978f9f9..20906fb87 100644 --- a/apps/imgclock/ChangeLog +++ b/apps/imgclock/ChangeLog @@ -4,4 +4,5 @@ 0.04: Fix hour alignment for single digits Scaling for background images <240px wide 0.05: Fix memory/interval leak when LCD turns on -0.06: Support 12 hour time \ No newline at end of file +0.06: Support 12 hour time +0.07: Don't cut off wide date formats \ No newline at end of file diff --git a/apps/imgclock/app.js b/apps/imgclock/app.js index dc961f58b..becf0a1fb 100644 --- a/apps/imgclock/app.js +++ b/apps/imgclock/app.js @@ -7,7 +7,7 @@ var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; var inf = require("Storage").readJSON("imgclock.face.json"); var img = require("Storage").read("imgclock.face.img"); var IX = inf.x, IY = inf.y, IBPP = inf.bpp; -var IW = 110, IH = 45, OY = 24; +var IW = 174, IH = 45, OY = 24; var bgwidth = img.charCodeAt(0); var bgoptions; if (bgwidth<240) @@ -40,7 +40,7 @@ function draw() { new Uint8Array(cg.buffer).set(bgimg); // draw time cg.setColor(inf.col); - var x = 40; + var x = 74 + 32 * inf.align; cg.setFont("7x11Numeric7Seg",3); cg.setFontAlign(1,-1); cg.drawString(hours, x, 0); @@ -54,8 +54,14 @@ function draw() { cg.drawString(("0"+t.getSeconds()).substr(-2), x, 20); cg.setFont("6x8",1); cg.drawString(meridian, x+2, 0); - cg.setFontAlign(0,-1); - cg.drawString(locale.date(t),IW/2,IH-8); + let date = locale.date(t); + if (cg.stringWidth(date) < IW-64) { + cg.setFontAlign(0, -1); + cg.drawString(date,IW/2+32*inf.align,IH-8); + } else { + cg.setFontAlign(inf.align, -1); + cg.drawString(date,IW*(inf.align+1)/2,IH-8); + } // draw to screen g.drawImage(cgimg,IX,IY+OY); } diff --git a/apps/imgclock/custom.html b/apps/imgclock/custom.html index 8c920571a..8428725af 100644 --- a/apps/imgclock/custom.html +++ b/apps/imgclock/custom.html @@ -13,9 +13,9 @@ - + diff --git a/js/espruinotools.js b/lib/espruinotools.js similarity index 100% rename from js/espruinotools.js rename to lib/espruinotools.js From 572a468cab6cd1e72f0f0a86e4f0817aa379c739 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 28 May 2020 14:20:56 +0100 Subject: [PATCH 1014/1189] Set page scaling better for mobile --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index af68a6d45..480fdd2e1 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + From 0c0fc9ac8f223c496d50855c04c001550173bee5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 28 May 2020 14:33:37 +0100 Subject: [PATCH 1015/1189] Improve upload of binary files --- CHANGELOG.md | 1 + js/appinfo.js | 9 +++++++-- js/utils.js | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5cd6aef5..29b6aa6e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,3 +18,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * Adding '#search' after the URL (when not the name of a 'filter' chip) will set up search for that term * If `bin/pre-publish.sh` has been run and recent.csv created, add 'Sort By' chip * New 'espruinotools' which fixes pretokenise issue when ID follows ID (fix #416) +* Improve upload of binary files diff --git a/js/appinfo.js b/js/appinfo.js index 54f1458db..b0b4e05ca 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -7,9 +7,14 @@ if (typeof btoa==="undefined") { // Converts a string into most efficient way to send to Espruino (either json, base64, or compressed base64) function toJS(txt) { + let isBinary = false; + for (let i=0;i127) isBinary=true; + } let json = JSON.stringify(txt); - let b64 = "atob("+JSON.stringify(btoa(json))+")"; - let js = b64.length < json.length ? b64 : json; + let b64 = "atob("+JSON.stringify(btoa(txt))+")"; + let js = (isBinary || (b64.length < json.length)) ? b64 : json; if (typeof heatshrink !== "undefined") { let ua = new Uint8Array(txt.length); diff --git a/js/utils.js b/js/utils.js index 859c5b10d..69dcda93b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -32,8 +32,18 @@ function httpGet(url) { return new Promise((resolve,reject) => { let oReq = new XMLHttpRequest(); oReq.addEventListener("load", () => { - if (oReq.status==200) resolve(oReq.responseText) - else reject(oReq.status+" - "+oReq.statusText); + // ensure we actually load the data as a raw 8 bit string (not utf-8/etc) + if (oReq.status==200) { + let a = new FileReader(); + a.onloadend = function() { + let bytes = new Uint8Array(a.result); + let str = ""; + for (let i=0;i reject()); oReq.addEventListener("abort", () => reject()); @@ -41,6 +51,7 @@ function httpGet(url) { oReq.onerror = function () { reject("HTTP Request failed"); }; + oReq.responseType = 'blob'; oReq.send(); }); } From ab5861126ca5042637700a06c69d38fac15a819b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 28 May 2020 14:34:40 +0100 Subject: [PATCH 1016/1189] App description can now be markdown --- CHANGELOG.md | 1 + README.md | 2 +- js/index.js | 9 +++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b6aa6e5..48bfe74ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,3 +19,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * If `bin/pre-publish.sh` has been run and recent.csv created, add 'Sort By' chip * New 'espruinotools' which fixes pretokenise issue when ID follows ID (fix #416) * Improve upload of binary files +* App description can now be markdown diff --git a/README.md b/README.md index 04854c99e..ac4fc716d 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,7 @@ and which gives information about the app for the Launcher. "name": "Readable name", // readable name "shortName": "Short name", // short name for launcher "icon": "icon.png", // icon in apps/ - "description": "...", // long description + "description": "...", // long description (can contain markdown) "type":"...", // optional(if app) - 'app'/'widget'/'launch'/'bootloader' "tags": "", // comma separated tag list for searching diff --git a/js/index.js b/js/index.js index 34975f3a1..363081a15 100644 --- a/js/index.js +++ b/js/index.js @@ -52,6 +52,11 @@ function showReadme(appid) { } httpGet(appPath+app.readme).then(show).catch(()=>show("Failed to load README.")); } +function getAppDescription(app) { + let appPath = `apps/${app.id}/`; + let markedOptions = { baseUrl : appPath }; + return marked(app.description, markedOptions); +} function handleCustomApp(appTemplate) { // Pops up an IFRAME that allows an app to be customised if (!appTemplate.custom) throw new Error("App doesn't have custom HTML"); @@ -259,7 +264,7 @@ function refreshLibrary() {
@@ -470,7 +475,7 @@ function refreshMyApps() {

${escapeHtml(app.name)} (${version.text})

-

${escapeHtml(app.description)}

+

${getAppDescription(app)}

See the code on GitHub
From ed47314f02d36420d187df9e62ea5adeef1f5121 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 28 May 2020 14:36:54 +0100 Subject: [PATCH 1017/1189] Added animated clock using palette cycling --- .eslintignore | 1 + apps.json | 18 +- apps/animclk/ChangeLog | 1 + apps/animclk/V29.LBM.js | 482 ++++++++++++++++++++++++++++++++++ apps/animclk/animclk.pal | Bin 0 -> 512 bytes apps/animclk/animclk.pixels1 | 1 + apps/animclk/animclk.pixels2 | 1 + apps/animclk/app-icon.js | 1 + apps/animclk/app.js | 116 ++++++++ apps/animclk/app.png | Bin 0 -> 4797 bytes apps/animclk/create_images.js | 57 ++++ 11 files changed, 677 insertions(+), 1 deletion(-) create mode 100644 apps/animclk/ChangeLog create mode 100644 apps/animclk/V29.LBM.js create mode 100644 apps/animclk/animclk.pal create mode 100644 apps/animclk/animclk.pixels1 create mode 100644 apps/animclk/animclk.pixels2 create mode 100644 apps/animclk/app-icon.js create mode 100644 apps/animclk/app.js create mode 100644 apps/animclk/app.png create mode 100644 apps/animclk/create_images.js diff --git a/.eslintignore b/.eslintignore index 40173021d..544f416aa 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,3 +3,4 @@ lib/imageconverter.js lib/qrcode.min.js lib/heatshrink.js +apps/animclk/V29.LBM.js diff --git a/apps.json b/apps.json index b888a9934..6093d82df 100644 --- a/apps.json +++ b/apps.json @@ -1787,7 +1787,7 @@ {"name":"binclock.app.js","url":"app.js"}, {"name":"binclock.img","url":"app-icon.js","evaluate":true} ] - } , + }, { "id": "pizzatimer", "name": "Pizza Timer", @@ -1801,5 +1801,21 @@ {"name":"pizzatimer.app.js","url":"app.js"}, {"name":"pizzatimer.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "animclk", + "name": "Animated Clock", + "shortName":"Anim Clock", + "icon": "app.png", + "version":"0.01", + "description": "An animated clock face using Mark Ferrari's amazing 8 bit game art and palette cycling: http://www.markferrari.com/art/8bit-game-art", + "tags": "clock,animated", + "type": "clock", + "storage": [ + {"name":"animclk.app.js","url":"app.js"}, + {"name":"animclk.pixels1","url":"animclk.pixels1"}, + {"name":"animclk.pixels2","url":"animclk.pixels2"}, + {"name":"animclk.pal","url":"animclk.pal"}, + {"name":"animclk.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/animclk/ChangeLog b/apps/animclk/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/animclk/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/animclk/V29.LBM.js b/apps/animclk/V29.LBM.js new file mode 100644 index 000000000..5b986d77d --- /dev/null +++ b/apps/animclk/V29.LBM.js @@ -0,0 +1,482 @@ +CanvasCycle.processImage({filename:'V29.LBM',width:640,height:480,colors:[[0,0,0],[219,247,255],[203,243,255],[175,235,255],[155,231,255],[131,223,255],[95,223,255],[95,215,255],[63,215,255],[47,207,255],[0,199,255],[23,191,255],[11,183,255],[31,175,255],[47,163,247],[47,151,239],[59,139,231],[63,127,219],[71,115,203],[147,203,255],[103,171,223],[67,123,143],[199,171,159],[179,215,171],[191,215,223],[183,223,239],[175,235,255],[155,211,231],[135,187,207],[151,207,167],[195,207,171],[199,171,159],[95,151,179],[95,151,179],[83,135,159],[71,119,139],[63,107,123],[59,103,115],[31,91,115],[47,99,119],[63,107,123],[67,123,143],[67,123,143],[67,127,147],[71,127,151],[71,131,151],[71,131,155],[75,135,159],[159,199,215],[31,103,123],[7,75,95],[0,71,87],[0,67,83],[0,67,83],[0,67,83],[0,71,91],[15,91,111],[31,103,127],[51,123,143],[63,131,151],[75,139,159],[87,151,167],[123,175,187],[163,199,207],[255,255,255],[255,255,255],[131,175,191],[111,155,175],[119,167,183],[139,179,195],[163,199,207],[191,215,223],[167,203,215],[191,215,223],[207,227,235],[215,231,239],[191,215,227],[231,243,247],[215,231,239],[231,243,247],[179,203,219],[167,191,207],[155,183,199],[143,175,191],[135,167,183],[123,159,175],[115,151,167],[119,155,171],[123,159,175],[127,163,179],[131,167,183],[139,171,187],[155,187,203],[179,203,219],[199,219,235],[223,239,255],[79,147,171],[59,131,155],[43,119,143],[31,107,131],[43,119,143],[59,131,159],[79,147,171],[99,163,187],[119,83,79],[211,159,135],[87,55,55],[55,31,31],[23,15,11],[115,71,63],[175,127,115],[231,179,155],[115,107,135],[159,139,155],[143,127,151],[191,167,187],[143,127,151],[115,107,135],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[247,247,251],[231,227,247],[207,215,243],[187,219,243],[195,211,231],[187,207,203],[91,91,91],[75,59,51],[75,59,51],[75,59,51],[79,71,71],[79,91,103],[99,107,123],[119,131,143],[143,151,163],[171,175,183],[179,191,195],[187,207,203],[187,207,203],[187,207,203],[187,207,203],[147,143,171],[183,151,175],[131,127,159],[131,127,159],[131,127,159],[159,147,179],[195,175,191],[111,95,115],[111,95,115],[123,103,123],[151,127,151],[111,95,115],[151,123,135],[203,167,175],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,239,231],[243,223,239],[231,199,223],[207,179,219],[187,171,211],[171,159,211],[155,151,215],[151,151,215],[155,159,219],[163,171,227],[175,191,247],[255,255,255],[255,255,255],[207,167,143],[147,103,95],[91,63,63],[71,51,51],[139,119,103],[91,71,63],[23,15,11],[215,171,155],[143,111,103],[119,91,83],[219,175,155],[143,111,103],[103,79,79],[79,59,59],[95,71,83],[111,91,111],[59,47,47],[99,75,67],[135,119,107],[63,51,51],[51,43,51],[95,71,83],[111,91,111],[79,59,59],[143,111,103],[203,175,163],[183,155,147],[255,239,227],[243,227,215],[235,215,203],[207,183,171],[179,155,143],[255,227,199],[243,211,183],[231,195,167],[219,179,151],[211,163,135],[199,147,123],[187,131,111],[179,119,99],[107,103,131],[215,171,155],[143,111,103],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[255,255,255],[11,11,11],[107,103,131],[219,219,235],[255,255,255]],cycles:[{reverse:0,rate:0,low:59,high:63},{reverse:0,rate:0,low:7,high:13},{reverse:0,rate:0,low:13,high:17},{reverse:0,rate:1227,low:32,high:47},{reverse:0,rate:1689,low:48,high:63},{reverse:0,rate:1689,low:64,high:79},{reverse:0,rate:1227,low:80,high:95},{reverse:0,rate:921,low:96,high:103},{reverse:0,rate:1689,low:128,high:143},{reverse:0,rate:1536,low:22,high:31},{reverse:0,rate:0,low:138,high:142},{reverse:0,rate:0,low:0,high:0},{reverse:0,rate:0,low:0,high:0},{reverse:0,rate:0,low:0,high:0},{reverse:0,rate:0,low:0,high:0},{reverse:0,rate:0,low:0,high:0}],pixels:[ +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,108,108,108,252,252,109,109,109,109,109,109,252,252,252,252,252,252,252,252,252,108,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,252,110,109,110,252,110,252,110,252,110,252,110,252,252,252,109,252,252,252,252,252,252,252,109,252,109,109,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,107,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,108,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,108,252,108,252,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,108,108,108,108,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,252,110,109,110,252,110,252,110,109,110,252,110,252,110,252,110,252,110,252,110,252,110,252,110,252,109,252,109,252,109,252,252,252,109,252,109,252,109,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,109,252,252,252,107,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,108,109,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,108,108,109,109,109,109,252,109,109,109,109,109,109,109,109,109,252,109,252,252,252,108,108,108,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,252,252,252,110,109,110,109,110,109,110,109,110,109,110,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,109,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,109,108,108,109,109,252,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,252,110,252,110,252,110,252,110,109,110,252,110,252,110,252,110,252,110,252,110,252,110,252,252,252,252,252,109,252,109,252,109,252,110,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,110,252,110,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,108,109,109,109,108,109,252,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,109,109,252,109,109,109,109,109,109,109,252,109,252,109,252,108,108,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,252,110,109,110,109,110,109,110,252,110,109,110,252,110,252,110,252,252,252,110,252,252,252,252,252,252,252,109,252,109,252,110,252,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,252,252,110,252,252,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,110,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,109,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,108,109,108,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,252,110,252,110,252,110,109,110,252,110,252,110,252,110,252,110,252,110,252,110,252,109,252,252,252,109,252,109,252,109,252,110,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,108,109,109,108,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,110,109,110,109,110,109,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,109,252,110,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,109,252,110,252,110,252,110,252,110,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,109,109,109,109,109,252,109,109,109,252,109,252,109,252,109,252,109,109,109,109,109,108,109,108,108,108,109,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,252,110,252,110,109,110,252,110,252,110,252,110,252,110,252,110,252,252,252,110,252,110,252,109,252,109,252,110,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,110,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,108,109,108,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,109,109,109,109,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,252,109,109,109,109,109,108,109,108,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,252,110,109,110,109,110,252,110,109,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,109,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,109,252,109,252,109,252,110,252,110,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,108,109,252,109,252,109,252,109,252,252,252,109,252,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,109,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,109,109,252,109,109,109,252,109,109,109,252,109,252,108,108,108,108,108,108,109,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,18,110,252,110,109,110,109,110,109,110,252,110,252,110,252,252,252,252,252,110,252,109,252,109,252,109,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,109,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,109,108,109,109,109,109,108,108,108,108,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,252,110,109,110,109,110,109,110,109,110,252,110,252,110,252,252,252,252,252,252,252,109,252,109,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,109,252,109,252,109,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,109,252,109,252,109,252,109,252,109,252,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,108,108,108,109,109,252,108,108,108,108,108,108,109,108,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,109,110,252,110,252,110,252,252,252,110,252,110,252,109,252,109,252,109,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,109,108,109,109,109,108,109,252,109,109,109,109,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,108,109,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,109,109,109,109,109,109,109,108,108,108,108,109,108,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,109,110,109,110,109,252,252,252,252,110,252,110,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,109,109,109,252,109,252,109,252,109,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,109,109,109,252,109,252,109,108,108,108,108,108,109,108,109,108,109,109,109,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,252,110,109,110,109,110,252,110,252,110,252,110,109,110,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,109,108,109,108,252,108,252,109,109,109,109,109,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,109,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,252,108,108,108,108,109,109,109,109,108,109,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,252,110,252,110,252,252,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,108,109,252,109,252,109,252,109,252,109,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,108,109,108,252,108,108,109,108,109,108,108,108,109,108,108,108,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,252,110,109,110,109,110,109,110,252,110,252,110,109,110,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,109,110,109,110,109,110,110,110,110,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,109,252,109,252,109,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,108,109,108,109,108,109,108,109,108,109,252,252,108,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,252,252,108,252,108,108,108,108,108,109,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,252,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,109,107,109,107,252,252,252,107,252,107,252,107,109,252,109,252,109,252,109,110,109,109,109,109,109,110,110,110,109,252,252,252,252,252,252,252,252,252,109,252,109,252,110,252,110,252,110,252,252,252,110,252,252,252,252,109,252,109,109,109,109,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,107,252,109,109,108,109,252,109,252,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,108,109,108,108,108,252,108,252,108,252,108,108,108,108,108,108,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,252,110,109,110,109,109,109,109,109,110,109,109,109,110,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,252,109,107,107,252,107,252,107,252,107,252,107,252,107,252,107,107,106,106,106,18,18,18,252,109,110,109,110,109,110,109,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,108,252,108,109,108,109,108,109,108,109,108,109,252,109,108,109,109,109,109,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,252,252,109,108,108,108,108,108,108,108,108,108,108,252,108,252,108,252,252,108,252,18,18,18,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,110,109,110,109,110,109,109,109,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,107,107,107,107,107,107,252,107,252,107,252,252,252,107,107,106,106,106,18,18,17,18,18,18,17,18,18,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,252,252,252,110,252,252,109,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,109,252,109,109,109,109,109,109,110,109,110,252,252,252,252,252,252,252,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,107,252,108,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,108,109,108,109,252,109,109,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,252,110,109,110,109,109,109,109,109,109,109,110,109,110,252,252,252,252,252,252,252,252,252,252,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,107,252,107,252,107,252,107,252,107,109,107,109,107,106,106,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,110,109,110,109,110,109,110,252,110,109,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,108,109,108,109,108,109,108,109,108,109,108,109,252,109,108,109,109,109,108,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,108,108,108,108,108,108,108,108,252,108,108,108,252,109,252,108,252,252,252,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,109,109,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,107,107,107,107,107,107,252,107,252,107,109,252,106,106,106,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,252,110,252,109,252,109,252,252,252,252,252,109,252,252,252,252,109,252,109,109,109,109,109,110,110,110,110,252,252,252,252,109,252,252,252,109,252,109,252,110,252,110,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,108,109,108,109,252,109,108,109,252,109,108,109,252,109,108,109,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,107,109,107,252,107,109,107,252,107,252,109,252,107,252,109,252,107,252,252,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,109,110,109,109,109,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,107,252,107,252,107,252,107,109,106,106,106,106,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,110,109,110,109,110,109,110,109,110,109,110,252,110,110,110,252,110,109,252,109,252,252,252,252,252,109,252,252,252,252,109,252,109,252,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,107,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,107,252,252,109,109,109,109,109,109,109,109,109,109,109,109,109,109,252,109,252,252,252,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,109,109,109,109,110,109,110,109,110,109,252,252,252,252,252,252,252,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,109,107,107,107,107,107,107,252,107,106,106,106,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,110,109,110,109,110,109,109,109,110,109,252,109,252,252,252,252,252,109,252,252,252,252,109,252,109,109,109,109,109,109,110,110,110,109,252,252,252,109,252,109,252,109,252,110,252,110,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,108,109,108,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,108,252,108,252,107,252,107,252,107,109,107,109,107,252,107,109,107,252,107,252,107,252,107,109,109,109,252,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,110,109,109,109,109,109,110,109,110,109,110,109,252,252,252,252,252,252,252,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,252,107,252,107,252,106,106,106,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,110,109,110,109,110,109,110,109,110,252,110,109,252,252,252,252,252,252,252,109,252,252,109,252,109,252,109,109,109,109,110,109,110,109,110,252,252,109,252,252,252,252,109,252,109,252,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,252,108,252,252,252,108,252,252,252,108,108,252,108,252,108,252,108,252,108,252,109,109,107,252,252,252,107,252,252,109,107,109,109,109,107,109,109,109,109,109,109,109,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,109,109,109,109,110,109,110,109,110,109,252,252,252,252,252,252,252,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,107,107,107,107,106,106,106,107,106,106,106,106,106,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,109,252,109,252,109,109,109,109,109,109,109,109,110,110,110,110,109,252,109,252,109,252,252,252,252,109,109,109,109,252,109,110,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,107,109,108,109,108,109,252,109,108,109,252,109,108,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,252,252,252,108,252,108,252,108,252,108,252,108,252,108,252,108,109,108,252,107,252,107,252,107,252,107,109,107,109,107,252,107,109,107,252,107,109,109,109,109,109,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,107,107,252,107,252,252,107,106,106,106,107,106,107,106,106,106,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,109,109,252,109,252,109,109,109,109,110,109,110,110,110,252,252,252,252,109,109,252,109,252,109,252,109,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,108,109,108,109,108,109,107,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,252,108,252,108,108,252,108,108,108,252,108,252,108,252,108,109,108,109,108,109,107,252,109,109,107,252,109,109,109,109,109,109,109,109,109,109,109,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,107,107,107,252,252,252,252,252,252,252,106,106,106,106,106,106,106,106,106,106,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,110,252,252,252,252,252,252,109,252,109,109,109,109,109,109,109,110,109,110,110,110,109,110,252,252,109,252,109,252,109,109,109,109,109,109,109,110,109,110,252,252,252,252,252,252,252,252,252,252,109,252,109,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,107,109,108,109,108,109,108,109,252,109,108,109,252,109,252,109,252,109,109,109,252,109,252,109,252,109,252,252,252,108,252,108,252,108,109,108,109,108,109,108,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,107,252,109,109,109,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,110,109,110,109,110,109,110,252,252,252,252,252,252,252,110,109,110,109,110,109,110,109,107,109,107,252,107,107,107,252,107,252,107,252,107,252,107,252,252,252,106,107,106,106,106,106,106,106,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,18,18,18,17,18,17,18,17,109,110,109,110,109,110,252,252,252,252,252,109,252,109,252,109,109,109,109,110,109,110,109,110,110,110,109,252,252,252,252,109,252,109,252,109,109,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,107,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,109,108,252,252,252,108,108,252,108,108,108,109,108,109,108,109,108,109,107,109,109,109,107,252,109,109,107,252,109,109,107,109,109,109,107,109,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,110,109,252,252,252,252,252,252,252,109,107,109,107,109,107,109,107,109,107,109,107,107,107,252,107,252,107,252,252,252,252,252,252,252,106,106,106,106,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,110,110,110,110,110,109,252,252,252,252,252,109,109,109,109,109,109,109,110,109,110,109,110,252,252,252,252,109,252,252,252,109,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,107,109,252,109,108,109,252,109,108,109,252,109,108,109,252,109,252,109,109,109,252,109,252,109,252,252,252,108,252,108,109,108,109,108,252,108,109,108,252,107,109,107,252,107,252,107,252,107,252,107,109,107,109,107,252,109,109,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,110,109,110,109,110,109,252,252,252,252,252,252,110,109,107,109,107,107,107,107,107,107,107,252,107,252,107,252,107,252,107,252,107,252,252,252,107,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,109,110,109,110,252,110,252,252,252,109,252,109,252,109,109,110,109,110,109,110,109,110,109,110,252,252,252,109,252,109,252,109,252,109,109,109,110,110,109,110,109,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,108,109,107,109,108,109,108,109,107,109,108,109,108,252,108,252,108,252,108,252,108,252,108,108,252,108,108,108,109,108,109,108,109,108,109,107,109,107,109,107,109,109,109,107,109,109,109,109,109,109,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,110,109,110,109,110,109,110,252,252,252,252,252,107,107,107,107,107,107,107,107,107,107,107,252,107,252,107,252,252,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,109,110,109,110,109,252,252,252,252,109,109,109,109,109,109,110,109,110,109,110,109,110,109,252,252,252,252,252,252,109,252,109,109,109,109,109,110,110,109,110,109,252,252,252,252,252,109,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,108,109,108,109,252,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,108,252,108,109,108,109,108,109,108,109,108,252,108,109,107,252,107,252,107,252,107,252,107,106,107,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,109,110,109,110,109,110,109,252,107,107,107,107,107,107,252,107,252,107,252,107,252,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,110,109,110,109,252,252,109,252,109,252,109,109,110,109,110,109,110,110,110,109,110,109,252,252,109,252,109,252,109,252,109,252,109,252,109,109,109,109,110,252,252,252,252,252,252,252,252,252,252,109,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,107,109,108,109,108,109,108,109,108,109,108,109,108,109,108,252,108,252,108,252,108,252,252,252,108,108,252,107,108,108,109,108,109,108,109,108,109,107,109,109,109,107,109,109,109,107,109,106,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,110,109,110,109,110,110,107,107,107,107,107,107,107,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,18,18,17,18,110,109,110,109,252,109,109,252,109,109,109,109,109,109,110,109,110,109,110,109,110,252,252,252,252,252,109,252,109,109,109,252,109,109,109,109,109,109,110,252,252,109,252,109,252,109,252,109,252,109,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,252,109,107,109,252,109,108,109,252,109,108,109,252,109,108,109,252,109,252,252,252,109,252,252,252,107,252,108,109,108,109,108,109,108,252,107,252,107,252,107,252,107,252,107,252,106,106,106,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,109,110,109,110,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,110,110,110,109,252,109,109,252,109,109,109,109,110,109,110,109,110,109,110,109,252,252,252,252,109,252,109,252,109,252,109,252,109,109,109,109,110,109,252,252,252,252,252,252,252,109,252,252,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,107,109,107,109,107,109,108,109,108,109,252,252,252,252,252,252,108,252,252,252,108,252,252,108,252,108,109,108,109,108,109,109,109,107,252,109,252,252,252,107,107,107,106,106,106,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,110,110,109,110,109,252,109,109,109,109,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,109,252,109,109,109,109,109,109,109,109,110,252,252,252,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,108,109,252,109,108,109,108,109,252,109,252,109,252,109,252,109,252,252,252,109,252,107,252,107,252,252,252,108,109,108,109,108,252,108,252,107,252,107,252,107,107,107,107,107,107,106,106,106,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,110,109,110,109,110,252,109,109,110,109,110,110,110,109,110,109,110,252,252,252,252,252,109,252,109,252,109,252,109,252,109,109,109,109,110,252,252,252,252,252,252,252,252,252,252,252,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,108,252,108,107,108,107,252,252,252,109,109,109,109,108,109,109,109,109,252,109,109,106,107,107,107,107,107,107,106,106,106,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,109,110,109,110,109,109,109,110,109,110,110,110,109,110,109,252,252,252,252,252,252,252,252,109,252,109,109,109,109,109,109,109,109,110,109,252,252,252,109,252,109,252,109,252,109,252,109,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,107,109,108,109,252,109,252,109,252,109,252,252,252,252,252,109,109,109,108,107,252,107,252,252,109,108,109,108,252,108,109,109,252,108,252,109,107,106,107,106,107,106,107,107,107,106,106,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,110,109,110,109,110,109,110,110,110,109,110,109,110,252,252,252,109,252,252,252,109,252,109,252,109,252,109,252,109,109,109,109,110,109,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,108,109,108,109,252,109,252,252,252,252,252,109,252,252,252,109,109,107,252,252,109,109,109,109,109,109,109,109,109,109,109,109,108,106,107,106,107,107,107,107,107,107,107,107,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,109,110,109,109,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,109,252,109,252,109,109,109,109,109,109,110,109,110,109,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,109,107,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,107,252,107,252,107,109,109,109,109,109,109,252,109,252,109,252,106,108,106,107,106,107,106,107,106,107,107,107,107,107,106,106,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,18,17,109,110,109,110,109,110,109,110,109,110,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,109,109,109,109,110,109,110,252,252,252,252,252,252,252,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,109,107,109,108,109,108,109,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,109,109,109,109,109,109,109,109,109,109,109,106,106,108,106,106,106,107,107,107,106,107,107,107,107,107,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,109,252,109,109,109,109,109,109,109,109,109,109,110,109,252,109,252,252,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,109,107,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,109,109,109,109,109,109,252,109,106,106,107,106,107,106,107,106,107,106,107,106,107,107,107,106,107,107,106,106,106,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,17,18,17,17,110,109,110,109,110,252,110,109,110,252,252,252,252,252,109,252,109,252,109,252,109,252,109,109,109,109,109,109,110,109,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,107,109,108,109,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,109,109,109,109,109,109,109,108,106,106,106,106,106,106,106,106,107,106,107,106,107,107,107,107,107,107,106,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,110,109,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,107,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,109,109,109,109,109,109,107,107,109,106,106,106,106,106,107,106,107,106,107,106,107,106,107,106,107,107,107,106,106,106,106,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,17,18,17,17,17,17,17,17,110,110,110,109,110,109,110,109,252,252,252,109,252,252,109,252,109,252,109,252,109,252,109,109,109,109,110,109,110,109,252,252,252,252,252,252,252,252,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,108,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,107,109,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,109,109,109,109,107,107,107,107,107,106,106,106,106,106,106,107,106,107,106,107,107,107,107,107,107,107,106,106,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,110,110,109,110,109,110,252,252,252,252,109,252,252,252,252,109,252,109,109,109,109,109,109,109,109,110,109,110,109,252,109,252,252,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,107,109,252,109,252,109,252,109,252,109,252,109,252,109,252,107,252,109,252,109,252,252,109,107,107,107,252,107,107,107,252,106,106,106,107,106,107,106,107,106,107,106,107,106,107,107,107,106,106,106,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,110,110,109,110,252,110,109,252,252,110,252,252,252,109,252,109,252,109,109,109,252,109,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,107,109,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,109,107,107,107,252,107,109,109,107,107,106,106,106,106,106,106,107,106,107,107,107,107,107,107,107,106,106,106,106,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,110,110,110,109,110,109,252,109,110,109,252,252,252,252,109,109,109,252,109,109,109,110,110,109,110,109,110,252,252,109,252,109,252,109,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,252,109,252,109,252,109,252,109,252,109,252,109,252,107,252,109,252,109,252,252,107,107,109,107,252,107,252,107,252,107,252,106,106,106,107,106,107,106,107,106,107,106,107,107,107,106,106,106,106,106,106,106,106,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,17,16,17,17,17,17,17,17,110,110,110,110,110,110,109,110,109,110,109,110,252,109,252,109,252,109,109,109,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,107,109,252,109,107,109,252,109,252,109,252,252,252,109,252,252,252,252,107,107,107,107,109,109,109,109,252,109,252,107,109,252,106,106,106,106,106,106,107,107,107,107,107,107,107,106,107,106,106,106,106,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,110,110,109,110,109,110,109,110,109,110,109,252,252,109,109,109,109,110,110,110,109,110,109,110,252,252,252,252,252,252,252,252,109,252,109,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,107,109,252,109,252,109,252,109,252,109,252,109,252,109,252,107,252,252,252,109,107,107,252,107,252,107,252,107,109,109,252,109,109,107,252,107,106,106,107,106,107,106,107,106,107,107,107,106,107,106,106,106,106,106,106,106,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,110,110,110,109,110,109,110,109,110,109,110,109,252,109,252,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,107,109,107,109,107,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,252,107,252,107,252,252,252,252,252,252,109,109,252,106,106,106,106,106,107,107,107,107,107,106,107,106,107,106,106,106,106,106,106,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,110,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,252,109,110,109,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,107,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,252,252,107,109,107,106,106,107,106,107,106,107,107,107,106,107,106,107,106,106,106,107,106,106,106,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,110,110,110,109,110,109,110,252,110,109,110,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,109,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,109,109,109,109,109,109,107,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,252,107,107,107,252,252,252,252,252,252,252,252,252,252,109,109,106,106,106,106,107,107,107,106,107,106,107,106,107,106,106,106,106,106,106,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,17,16,17,17,110,110,109,110,109,110,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,110,252,110,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,252,107,109,109,106,106,107,107,107,106,107,106,107,106,107,106,106,106,106,106,106,106,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,109,110,109,110,109,110,109,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,109,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,108,109,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,109,106,252,106,107,106,107,106,107,106,107,106,107,106,106,106,106,106,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,109,110,109,110,109,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,109,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,109,252,252,107,252,107,252,109,107,106,107,106,106,107,107,106,107,106,106,106,106,106,106,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,110,109,110,109,110,109,110,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,252,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,107,107,107,107,107,107,107,107,252,107,252,107,252,252,252,252,252,109,109,109,252,252,252,252,252,252,252,107,107,106,107,106,107,107,107,106,106,106,106,106,106,106,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,109,110,109,110,109,110,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,109,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,110,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,109,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,107,107,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,109,252,107,252,252,252,107,252,252,252,252,252,106,107,106,106,107,107,106,107,106,107,106,106,106,106,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,109,110,109,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,252,107,109,107,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,252,107,252,107,252,107,252,252,109,109,109,109,252,252,252,252,252,252,252,252,252,107,107,106,107,106,107,106,107,106,106,106,106,106,106,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,110,109,110,109,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,107,107,107,107,252,107,252,107,252,107,252,107,252,107,107,107,252,107,252,109,252,109,252,107,252,107,252,252,252,107,107,106,107,106,107,106,106,106,106,106,107,106,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,109,110,109,110,109,110,109,110,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,109,109,107,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,107,107,107,107,107,107,107,107,107,107,252,107,107,107,109,109,109,109,252,109,252,109,252,252,107,107,252,252,252,107,107,107,107,106,107,106,107,106,106,106,106,106,106,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,109,110,109,110,109,110,109,110,109,109,109,109,252,110,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,107,107,107,107,252,107,252,107,252,107,107,107,252,107,109,107,252,107,252,109,252,107,252,109,252,107,252,107,252,252,252,107,107,252,107,106,107,106,106,106,107,106,106,106,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,16,17,110,109,110,109,110,109,110,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,107,109,109,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,107,107,107,252,107,109,109,109,109,109,109,252,109,252,252,252,252,107,107,252,107,252,252,252,107,107,107,107,106,107,106,106,106,106,106,106,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,110,109,110,109,110,109,110,109,109,109,109,109,109,109,109,252,252,252,252,252,252,110,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,109,109,252,109,107,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,107,107,252,107,107,252,252,252,252,252,109,109,109,109,252,109,107,107,252,107,252,109,252,109,252,252,107,107,252,107,252,252,252,107,252,107,107,106,106,106,106,106,106,106,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,16,17,16,17,16,16,16,17,110,109,110,109,110,109,110,252,110,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,107,252,252,252,252,252,252,252,109,109,109,109,109,109,107,109,252,109,252,252,252,252,252,252,252,252,252,252,107,252,107,252,107,252,252,109,109,109,109,109,109,109,252,109,107,107,252,252,252,109,252,252,252,107,107,107,107,107,252,252,252,107,252,107,107,106,106,106,106,106,106,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,110,109,110,109,110,109,110,109,110,109,110,252,109,109,109,252,109,109,252,252,252,109,252,252,252,252,252,252,252,110,252,109,252,109,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,108,109,252,252,252,252,252,252,252,107,252,252,252,252,252,252,252,252,109,109,252,109,109,109,252,109,252,109,252,109,252,107,252,109,252,252,252,109,252,107,252,107,252,107,252,107,109,109,109,107,107,106,106,106,106,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,16,16,17,16,109,110,109,110,109,110,252,110,252,110,252,110,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,109,252,252,252,252,252,252,107,252,252,252,107,252,107,252,107,109,109,109,109,109,109,109,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,107,109,109,107,106,107,106,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,252,110,110,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,107,252,252,252,252,109,252,109,108,109,252,252,252,252,107,252,252,252,107,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,107,107,109,107,109,107,109,107,109,109,107,106,107,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,109,110,109,110,109,110,252,110,252,110,252,110,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,107,252,107,109,107,109,109,109,109,109,109,109,109,109,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,109,109,109,109,106,107,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,109,110,109,110,109,110,109,110,109,110,109,110,252,110,109,110,252,110,110,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,252,109,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,109,109,109,109,109,109,109,109,109,109,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,110,109,110,109,110,109,110,252,110,252,110,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,109,109,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,109,109,109,109,109,109,109,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,110,252,110,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,109,109,109,109,109,109,109,109,109,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,109,110,109,110,109,110,252,110,252,110,252,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,108,252,252,252,252,252,252,252,252,252,109,109,108,109,252,109,109,109,252,252,252,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,109,110,109,110,109,110,109,110,109,110,252,110,109,110,252,252,109,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,109,252,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,109,109,109,109,109,109,109,109,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,110,109,110,109,110,109,110,109,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,15,16,16,16,16,16,16,16,110,109,110,109,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,109,109,109,109,109,109,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,110,109,110,109,110,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,252,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,109,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,16,15,16,16,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,109,109,109,109,109,109,109,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,109,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,110,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,109,109,109,109,109,109,109,109,109,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,252,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,108,109,109,109,109,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,109,252,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,109,108,109,108,109,109,109,109,109,109,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,109,110,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,109,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,109,109,109,109,109,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,109,110,109,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,108,107,107,109,107,109,107,109,109,109,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,15,16,110,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,252,109,252,252,252,252,252,252,252,108,108,107,107,107,109,109,109,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,110,109,110,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,109,252,252,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,108,108,108,109,107,109,107,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,109,110,109,110,109,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,252,252,252,252,252,252,108,108,108,108,108,109,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,107,107,109,107,109,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,110,109,110,109,110,109,110,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,252,252,252,252,252,108,108,107,107,107,107,107,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,110,109,110,109,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,108,252,108,252,107,109,107,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,15,15,15,14,15,15,15,15,109,110,109,110,252,110,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,252,252,252,107,107,107,107,107,107,107,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,107,107,107,252,107,252,107,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,14,15,15,15,14,15,14,15,110,109,110,109,109,252,109,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,252,107,107,107,107,107,107,107,252,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,107,107,107,107,107,107,107,252,106,107,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,109,110,252,109,252,109,252,252,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,107,107,107,107,107,107,107,106,107,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,252,252,109,109,109,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,106,107,106,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,110,110,109,109,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,106,107,107,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,15,15,15,14,110,110,109,109,109,109,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,252,107,252,107,106,106,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,15,252,110,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,107,107,107,107,107,107,106,106,107,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,110,109,110,109,109,109,109,252,110,252,109,110,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,252,109,107,107,107,107,109,107,107,109,252,106,107,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,109,110,252,110,252,109,252,109,109,110,252,110,110,110,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,109,109,107,107,107,107,107,107,109,107,109,106,106,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,15,14,14,14,14,110,109,110,109,110,109,109,252,252,109,109,109,110,110,110,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,109,107,107,109,107,107,107,109,107,109,107,106,106,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,252,110,109,110,252,109,252,109,252,109,109,110,109,110,110,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,109,109,109,109,107,107,107,107,107,107,107,107,107,106,106,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,110,110,109,110,109,110,109,252,252,109,109,109,110,110,110,110,252,109,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,109,109,107,107,107,107,107,109,107,109,107,109,106,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,110,109,110,252,110,252,252,252,109,252,109,109,110,110,110,252,109,109,109,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,109,107,107,107,107,107,107,107,107,107,107,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,110,109,110,109,252,252,252,252,109,109,109,109,110,110,109,252,109,109,109,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,109,109,107,107,107,109,107,107,107,109,107,106,106,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,14,14,15,14,15,14,15,14,110,110,252,110,252,110,252,109,252,109,252,109,109,109,109,110,252,109,252,109,252,109,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,109,109,107,107,107,107,107,107,107,107,107,109,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,109,110,109,110,109,252,252,252,252,109,109,109,109,110,110,110,252,109,109,109,109,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,109,109,109,107,107,109,107,107,107,109,107,109,107,106,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,15,14,14,14,110,110,252,110,252,110,252,109,252,109,252,109,252,109,110,110,252,109,252,109,109,109,109,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,107,107,107,107,107,107,107,109,106,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,109,110,109,110,252,252,252,109,252,109,109,109,109,110,252,110,252,109,109,109,109,109,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,109,109,109,109,109,107,107,107,107,109,107,109,106,106,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,110,252,110,252,110,252,252,252,109,252,109,252,109,109,110,252,110,252,109,109,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,109,107,107,107,107,107,107,107,106,106,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,109,110,109,110,109,110,252,252,252,109,252,109,109,109,110,110,109,110,109,109,109,109,109,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,107,109,109,109,109,109,107,107,107,109,107,109,106,107,106,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,252,110,252,110,252,110,252,252,252,109,252,109,252,109,109,110,110,110,252,110,252,109,109,109,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,109,109,109,107,107,107,107,107,106,106,106,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,110,109,110,109,110,252,110,109,252,252,109,252,109,109,109,109,110,252,110,109,110,109,109,109,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,107,109,109,109,109,109,109,109,107,109,107,107,106,107,106,106,106,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,110,109,110,252,110,252,110,252,252,252,109,109,109,252,109,252,109,110,110,252,110,252,110,252,109,109 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,109,108,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,109,109,109,109,109,107,107,107,106,106,106,106,106,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,110,109,110,109,110,109,110,109,252,109,109,109,109,252,252,252,109,109,109,252,110,252,252,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,107,109,109,109,109,109,109,109,109,109,107,107,106,107,106,107,106,106,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,109,110,109,110,109,110,252,110,252,109,252,109,109,110,109,252,252,109,109,252,252,252,252,252,109,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,109,109,109,109,109,109,109,109,109,109,109,107,107,106,106,106,106,106,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,14,14,13,14,110,109,110,109,110,109,110,109,252,109,109,109,109,110,110,109,110,110,252,252,252,252,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,109,107,109,107,109,109,109,109,109,109,109,109,109,109,106,106,106,106,106,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,109,110,109,110,252,110,109,252,252,109,252,109,109,110,110,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,108,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,109,109,109,109,109,109,109,109,109,109,109,109,109,109,107,106,106,106,106,106,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,13,14,14,14,13,14,13,14,110,109,110,109,110,109,252,109,252,109,109,109,109,110,110,110,252,252,252,252,252,109,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,108,252,108,252,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,107,107,252,107,109,107,109,107,109,107,109,109,109,109,109,109,107,107,109,109,109,107,106,106,106,106,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,110,109,110,109,110,252,109,252,109,252,109,109,109,110,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,252,108,252,108,108,108,108,108,252,108,108,108,252,252,252,107,252,252,107,107,107,107,107,107,109,109,109,109,109,109,109,109,107,107,107,107,109,107,107,107,106,106,106,106,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,110,109,110,109,252,109,252,109,252,109,110,110,252,252,252,252,252,252,252,109,252,109,252,109,252 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,108,252,108,252,108,108,108,252,108,108,108,252,107,252,107,252,107,252,107,107,107,107,107,109,107,109,107,109,107,109,109,109,109,107,107,109,107,109,107,109,107,109,106,106,106,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,110,252,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,252,252,108,108,108,108,108,108,108,108,107,107,252,107,252,107,252,107,107,107,107,107,107,107,109,107,109,109,109,109,109,109,109,107,107,107,109,107,107,107,107,106,106,106,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,13,14,13,13,13,14,13,14,110,109,110,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,108,108,108,108,108,252,108,252,108,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,109,107,106,106,106,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,108,108,108,108,108,108,108,108,108,107,107,252,107,107,107,252,107,252,107,252,252,107,107,107,107,107,107,109,109,109,109,109,109,107,107,109,107,107,107,107,107,106,106,106,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252 +,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,108,108,108,252,107,252,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,109,109,109,109,109,107,109,107,107,107,106,106,106,106,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109 +,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,108,108,108,108,108,107,107,107,107,107,252,107,252,107,252,107,252,107,252,109,109,109,109,109,107,107,109,109,109,109,109,109,107,107,107,107,107,106,106,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,110,109,110,109,110,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252 +,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,108,108,108,108,252,108,252,108,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,107,109,109,109,109,109,109,109,106,109,106,106,106,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,13,14,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,252,109,252,108,108,108,108,108,108,108,108,108,107,107,107,107,252,107,107,107,252,107,252,107,252,252,252,109,109,109,109,109,109,109,109,109,109,109,109,109,108,106,108,106,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,109,252,252,252 +,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,252,108,252,252,108,108,108,108,108,108,252,108,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,109,109,107,109,109,109,109,107,106,107,106,106,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,14,13,13,13,109,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,108,108,252,252,252,108,108,108,108,108,108,108,108,107,107,107,107,107,252,107,252,107,252,107,252,252,252,109,109,109,109,109,109,109,109,109,109,109,109,107,107,107,107,106,106,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,109,108,252,108,252,108,252,252,108,108,108,108,252,108,252,108,252,107,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,109,109,109,109,109,107,107,107,107,107,106,107,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,110,109,110,252,110,252,252,252,252,252,252,252,252,252,252,109,252,252 +,252,252,252,252,108,252,109,252,252,252,252,252,109,252,109,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,108,108,109,108,252,252,252,108,108,108,108,108,108,108,107,107,252,107,107,107,252,107,252,107,252,252,109,107,109,109,109,109,109,109,109,109,109,109,109,107,107,107,107,107,106,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,109,110,109,110,109,110,252,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,108,108,252,108,252,108,252,109,252,252,108,108,252,108,108,108,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,109,109,109,109,109,107,107,107,107,107,107,106,106,106,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,109,110,252,110,252,110,252,252,252,252,252,252,252,252,252,252,252 +,252,252,252,252,108,252,252,252,252,252,252,252,109,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,108,109,109,252,252,252,108,108,108,108,108,107,107,107,107,107,107,252,107,109,107,109,107,109,109,109,109,109,109,109,109,109,109,109,109,109,109,107,107,107,107,107,106,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,110,109,110,252,110,252,110,252,252,252,252,252,252,109,252,252,252 +,252,252,252,108,252,252,252,252,252,252,252,109,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,108,108,252,108,252,108,109,108,252,109,252,252,108,108,108,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,107,109,107,109,109,109,109,109,109,109,109,107,107,107,106,107,106,106,106,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,110,109,110,252,110,252,110,252,252,252,252,252,252,252,252,252 +,252,252,108,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,108,108,108,109,109,109,109,252,252,252,108,108,108,107,107,107,107,107,107,252,107,107,107,109,109,109,107,109,109,109,109,109,109,109,109,109,109,109,109,109,107,107,106,107,106,106,106,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,110,109,110,252,110,252,110,252,252,252,252,252,252,252,252 +,252,252,252,108,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,108,108,252,108,109,108,252,108,252,252,252,252,108,108,252,107,107,107,252,107,252,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,109,109,109,109,109,107,107,106,107,106,106,106,106,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,110,252,110,252,110,252,110,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,108,109,109,109,109,252,252,252,252,252,108,108,108,107,107,107,107,107,107,107,107,109,107,109,107,109,109,109,109,109,109,109,109,109,109,109,109,109,107,107,106,107,106,106,106,106,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,12,13,13,13,13,13,109,252,110,252,110,252,252,252,252,252,252,252,252 +,252,252,252,108,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,252,252,252,108,252,108,252,109,252,252,252,252,108,108,108,107,252,107,252,107,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,109,109,109,109,107,107,106,107,106,107,106,106,106,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,109,252,110,252,110,252,109,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,109,252,109,109,108,252,252,252,252,252,252,252,108,108,108,107,107,107,107,107,107,109,107,109,107,109,109,109,107,109,109,109,109,109,109,109,109,109,107,107,106,107,106,107,106,106,106,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,13,13,12,13,109,252,110,252,252,252,252,252,252,252,252 +,252,252,252,108,252,252,252,252,252,252,252,109,252,252,252,108,252,252,252,252,252,252,109,252,252,252,109,252,252,252,252,252,252,108,252,108,252,109,109,252,109,252,108,252,108,252,108,252,252,252,252,252,108,252,107,107,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,109,106,107,109,106,107,106,107,106,106,106,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,252,110,252,110,252,110,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,109,252,252,109,108,252,109,252,252,252,252,252,252,252,252,108,108,107,107,107,107,107,107,107,107,109,107,109,107,109,109,109,109,109,109,109,107,109,107,107,106,107,106,107,106,106,106,106,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,252,110,252,252,252,252,252,252,252,252 +,252,252,252,108,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,108,108,107,252,107,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,109,107,107,106,107,106,107,106,106,106,106,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,252,110,252,109,252,109,252,252,109 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,108,107,107,107,107,107,107,107,109,107,109,107,106,107,106,107,109,107,109,107,109,107,109,107,107,106,107,106,106,106,106,106,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,110,252,252,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,109,109,252,109,252,109,252,108,252,252,252,108,252,252,252,252,252,107,107,107,107,107,109,107,109,107,107,107,107,107,109,107,109,107,109,107,109,107,109,107,107,106,107,106,106,106,106,106,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,109,110,252,110,252,252,252,109,252 +,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,109,109,107,109,107,107,107,107,107,106,107,109,107,109,107,109,107,107,109,107,106,107,106,106,106,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,109,110,252,252,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,252,109,252,109,252,109,252,109,252,109,252,107,252,252,252,252,252,252,107,107,252,107,109,109,109,107,107,107,109,107,109,107,109,107,109,107,109,107,107,107,107,106,107,106,106,106,106,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,252,110,252,109,252,252,252 +,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,107,107,107,107,107,107,107,109,107,109,107,109,107,106,106,107,107,107,106,106,106,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,252,110,252,252,252,252 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,252,107,109,109,107,107,107,107,109,107,109,107,109,107,109,107,107,106,107,107,107,107,107,106,106,106,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,12,12,13,12,252,110,252,109,252 +,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,107,107,107,107,107,109,107,109,107,109,107,106,106,107,107,107,107,107,106,106,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,110,252,252,252,252 +,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,252,107,109,107,109,109,107,107,109,107,109,107,109,107,109,107,107,106,107,106,107,107,107,107,106,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,214,214,201,201,216,12,12,12,12,12,12,12,12,12,12,110,252,252,252 +,252,252,108,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,107,107,107,109,107,109,107,109,107,106,106,107,106,107,106,107,107,107,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,202,202,202,214,201,201,216,216,216,216,216,216,216,12,12,12,12,12,252,252,252 +,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,107,107,107,252,107,107,107,109,107,109,107,109,107,109,107,109,107,109,107,109,106,107,106,107,106,107,107,107,107,106,106,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,202,202,202,202,203,214,201,201,201,216,216,216,216,216,216,216,216,216,12,252,110,252 +,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,107,107,109,107,106,107,109,107,109,107,109,107,109,106,107,106,107,107,107,107,107,106,107,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,202,202,202,202,202,203,202,202,214,214,201,201,216,216,216,216,216,216,216,216,216,216,252,252 +,252,108,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,252,107,109,107,107,107,109,107,106,107,109,107,109,107,109,107,109,106,107,106,107,106,107,106,107,107,107,106,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,202,202,202,202,202,203,202,202,202,203,202,214,201,201,216,216,216,216,216,216,216,216,216,216,252 +,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,108,109,108,109,252,252,252,109,252,252,252,252,252,252,252,252,252,107,252,107,109,109,109,109,109,107,106,107,106,107,109,107,109,107,109,106,107,106,107,106,107,107,107,107,107,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,202,202,202,202,202,203,202,202,202,203,202,203,203,214,201,216,216,216,216,216,216,216,216,216,216,252 +,252,108,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,252,107,109,107,109,109,106,107,109,107,109,107,109,107,109,106,107,106,107,106,107,107,107,107,107,106,106,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,202,202,202,202,202,202,203,202,202,202,203,202,203,203,203,214,201,201,216,201,216,216,216,216,216,216,216,216 +,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,108,252,252,252,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,252,109,109,109,109,109,106,107,106,107,109,107,109,107,109,106,106,106,107,106,107,107,107,107,106,106,106,106,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,202,202,202,202,203,203,203,203,202,202,202,202,203,202,203,202,214,201,201,216,214,201,216,201,216,216,216,216,216 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,108,252,252,252,252,252,108,109,108,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,252,252,252,109,109,107,109,109,109,107,109,107,109,107,109,107,107,106,107,106,107,106,107,107,107,107,106,106,106,106,106,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,202,202,202,202,203,203,202,202,203,202,202,202,202,203,203,203,203,202,202,214,201,216,214,214,201,216,201,216,216,216,216 +,108,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,108,252,252,252,252,252,252,252,108,109,108,109,109,109,109,109,252,252,252,252,252,252,252,252,252,252,107,107,106,107,109,107,109,106,106,106,106,107,109,107,109,106,106,106,107,106,107,106,107,107,107,107,106,106,106,106,106,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,202,203,203,203,202,202,202,202,203,203,203,202,202,202,203,203,203,202,202,202,214,201,214,214,214,214,201,216,201,216,216,216 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,109,107,109,107,107,106,107,107,109,107,109,106,106,106,107,106,107,106,107,107,107,107,107,106,106,106,106,106,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,202,202,202,203,202,202,202,203,202,203,202,203,202,202,202,203,202,203,202,203,202,203,214,201,214,204,203,214,201,201,216,201,216,216 +,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,108,252,252,252,252,252,252,252,108,109,109,109,109,109,252,109,252,252,252,252,252,252,252,252,107,107,252,107,109,107,109,107,109,106,107,106,107,106,107,107,107,107,107,106,106,106,107,107,107,106,107,106,106,106,106,106,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,203,202,203,203,202,202,202,202,202,202,203,203,202,202,202,202,203,202,203,203,202,202,203,202,203,214,214,203,204,204,214,201,201,216,201,216 +,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,107,107,252,107,109,107,109,107,109,107,107,106,107,106,107,106,107,106,107,106,107,106,107,106,107,106,107,106,106,106,106,106,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,203,202,203,202,202,202,202,202,203,202,203,202,203,202,202,204,203,202,203,202,203,203,203,202,203,202,203,202,214,203,204,203,204,214,201,216,201,216,201 +,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,252,109,252,109,252,252,252,252,252,252,107,107,107,107,107,107,109,107,109,107,109,106,106,106,107,107,107,106,107,107,107,107,106,107,107,106,107,106,106,106,106,106,106,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,12,11,12,12,202,202,203,202,202,202,202,202,202,202,203,202,203,202,203,203,202,202,202,202,203,202,203,203,203,202,202,202,202,202,203,203,203,203,204,204,214,201,201,216,201,216 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,252,252,252,252,107,107,107,109,107,109,107,109,107,109,107,107,106,107,106,107,106,107,106,107,106,107,107,107,107,107,106,107,106,106,106,106,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,203,202,202,202,203,202,203,202,203,202,203,202,203,202,203,202,203,203,202,202,202,202,203,202,203,203,203,203,202,202,203,202,203,202,203,203,204,203,204,214,201,201,201,216,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,108,252,252,109,109,109,252,252,252,252,252,252,252,107,252,107,107,107,107,107,109,107,109,107,109,106,107,106,107,106,107,107,107,107,107,107,107,107,107,106,107,106,106,106,106,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,202,202,202,202,202,202,202,202,202,203,202,203,202,203,203,203,203,203,203,202,202,202,202,202,202,203,203,203,204,204,202,202,202,203,203,203,203,204,204,204,204,204,214,214,201,201,216 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,252,252,252,252,107,107,107,109,107,109,107,109,107,109,107,107,106,107,106,107,106,107,106,107,107,107,107,107,106,107,106,106,106,106,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,202,203,202,203,202,202,202,202,202,203,202,203,202,203,202,203,202,203,203,202,202,202,214,214,214,201,202,203,203,203,214,214,214,202,202,203,202,203,203,204,203,204,203,204,204,214,214,214,201,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,107,109,107,107,107,107,107,107,107,107,106,107,106,107,106,107,106,106,106,106,106,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,203,203,203,203,203,203,202,202,202,202,203,214,214,214,214,214,203,203,214,201,201,201,214,202,202,202,203,203,203,204,203,203,204,204,204,204,214,214,201,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,108,252,252,109,252,109,252,252,252,252,252,252,252,107,107,107,109,107,109,107,109,107,109,107,107,106,107,107,107,106,107,106,107,106,107,106,107,106,106,106,106,106,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,202,202,203,202,202,202,203,202,203,202,203,202,203,202,203,202,202,202,203,202,202,202,203,202,204,203,204,203,204,203,204,214,214,201,216,201,214,202,203,202,203,204,204,203,204,203,204,204,204,204,214,214,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,252,252,252,252,252,252,109,252,252,107,107,107,109,107,109,107,109,107,109,107,107,107,107,106,107,106,107,106,107,106,107,106,107,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,203,202,202,202,202,202,202,202,202,202,203,203,203,204,204,203,204,204,204,202,214,201,214,216,201,214,202,202,203,204,204,204,203,203,204,204,204,204,204,214,214,214 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,107,107,107,109,107,109,107,109,107,109,107,107,106,107,106,107,106,107,106,107,106,107,106,107,106,106,106,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,12,11,202,202,203,202,202,202,202,202,203,202,203,202,203,202,202,202,203,202,203,202,203,202,203,202,203,203,204,204,204,203,204,202,203,202,214,214,201,216,201,202,204,203,204,203,204,203,204,203,204,203,204,204,204,214,214 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,107,106,107,106,107,109,107,109,107,107,106,107,106,107,106,107,106,106,106,107,106,107,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,203,202,202,202,203,203,203,202,203,203,202,202,203,203,203,203,204,204,204,203,202,202,203,203,214,214,214,201,214,203,203,203,204,204,203,203,204,204,204,204,204,204,204,214 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,252,109,252,107,106,107,252,107,109,107,109,107,109,106,107,106,107,106,107,106,107,106,107,106,106,106,107,106,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,11,12,11,11,202,203,202,202,202,203,202,202,202,203,202,203,202,203,202,202,203,204,202,203,202,202,202,203,203,204,203,204,204,204,203,202,202,203,202,203,203,214,214,214,201,214,203,204,203,204,204,203,204,204,203,204,203,204,204,214 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,109,252,109,106,107,106,107,109,107,109,107,109,106,107,106,107,106,107,106,106,106,106,106,107,107,107,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,202,202,203,203,204,204,202,202,202,202,203,203,203,203,204,204,204,203,203,202,202,202,203,203,203,203,203,214,214,201,214,203,203,204,204,204,204,204,204,204,204,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,107,252,107,252,107,252,107,252,107,109,107,109,106,107,106,107,106,107,106,106,106,107,106,107,106,107,106,106,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,202,202,202,202,203,202,202,202,203,202,202,202,203,202,203,203,204,204,202,202,202,202,203,203,204,203,204,204,204,203,204,202,203,202,203,202,203,203,203,203,204,203,214,214,214,203,204,204,204,204,204,203,204,203,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,109,252,252,252,107,106,107,109,107,109,107,107,106,107,106,107,106,106,106,106,106,107,107,107,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,202,203,203,202,202,204,204,203,202,202,203,203,203,204,204,204,204,203,203,202,202,203,202,203,203,203,203,203,203,204,204,204,214,214,203,204,204,204,203,204,204,204,201,201,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,252,107,252,107,252,107,252,107,106,107,252,107,109,107,107,106,107,106,107,106,106,106,107,106,107,106,107,106,106,106,106,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,202,202,202,203,202,203,202,203,202,202,202,202,202,203,202,202,202,203,203,204,204,203,202,203,203,204,204,204,203,204,202,202,202,203,202,203,202,203,203,203,203,204,203,204,203,204,204,204,204,204,214,214,201,201,201,201,216,216 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,109,107,109,109,109,109,252,252,106,107,252,107,109,106,107,106,107,106,107,106,106,106,106,106,107,107,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,202,202,203,202,203,203,203,203,204,203,202,202,203,203,204,204,204,202,202,202,202,202,203,202,203,203,203,203,203,203,204,203,204,204,204,204,203,214,201,201,201,216,216,216,216,216 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,252,107,109,107,252,107,252,107,252,109,252,107,252,107,252,106,107,107,107,106,107,106,106,106,107,106,107,106,106,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,203,202,202,202,203,202,202,202,203,202,202,202,203,202,203,202,203,203,204,204,204,203,204,203,202,204,204,204,202,202,202,202,203,202,203,202,203,203,203,204,204,203,204,204,204,203,202,214,201,201,201,216,201,216,216,216,216 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,107,107,109,107,109,107,109,109,109,109,252,109,252,109,106,107,106,106,107,107,107,107,107,106,106,106,107,106,107,107,106,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,202,202,202,202,202,202,204,202,202,202,202,203,203,204,204,204,202,204,204,204,204,204,204,204,202,202,202,202,202,203,202,203,203,203,203,204,204,204,204,204,204,204,214,214,214,214,201,201,216,201,216,216,216 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,107,252,107,109,107,252,107,252,109,252,109,252,107,252,106,107,106,107,106,107,106,107,106,107,106,107,106,106,106,106,106,106,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,202,202,202,203,202,203,202,203,202,203,202,203,202,202,202,204,202,202,202,203,202,203,203,204,202,204,203,204,203,204,204,204,204,202,202,203,202,203,202,204,203,203,203,204,203,204,204,204,203,204,203,202,202,203,214,214,201,201,216,201,216,216 +,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,109,107,109,107,252,109,109,109,109,109,109,109,252,252,106,106,106,106,107,106,107,107,107,107,107,107,106,107,107,106,106,106,106,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,202,202,202,202,202,202,202,202,203,202,202,202,202,202,203,204,202,202,203,203,203,203,204,204,202,203,204,204,204,204,204,204,204,202,202,202,203,202,203,204,203,203,203,203,204,204,204,204,204,203,202,202,203,203,203,203,214,201,201,216,201,216 +,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,108,108,108,108,108,252,107,109,107,252,107,252,107,109,107,109,107,252,107,252,109,252,109,107,106,107,106,107,106,107,106,107,107,107,106,107,106,106,106,106,106,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,202,202,202,203,202,203,202,203,202,202,202,202,202,202,203,204,202,203,202,203,203,204,203,204,202,203,204,204,204,204,204,204,202,202,202,202,202,203,203,204,203,203,203,204,203,204,204,204,203,202,202,203,202,203,203,204,214,201,201,216,216,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,109,107,107,107,109,107,109,107,109,109,109,109,252,109,252,109,109,106,107,106,107,107,107,107,107,106,107,106,107,106,106,106,106,106,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,202,202,202,202,202,202,203,202,202,202,202,202,202,202,204,204,202,202,203,203,203,203,204,204,202,203,204,204,204,204,204,204,202,202,203,202,203,203,204,204,202,203,203,203,204,204,204,204,203,202,202,202,203,203,203,203,203,214,201,201,201,216 +,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,108,108,108,252,108,107,107,252,107,109,107,252,107,109,107,252,107,252,109,252,107,109,109,252,106,107,107,107,106,107,106,107,106,107,106,106,106,106,106,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,203,202,202,202,203,202,203,202,203,202,202,202,203,202,203,203,204,202,203,202,203,203,204,204,204,202,204,203,204,203,204,204,203,202,202,202,202,202,203,203,204,203,204,203,204,203,204,204,204,202,203,203,204,202,203,203,204,203,214,214,201,201,201 +,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,108,108,108,108,108,107,107,107,109,107,109,107,109,107,109,109,109,109,109,109,109,109,109,109,107,106,107,106,107,106,107,106,107,106,106,106,106,106,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,10,11,11,11,202,202,202,202,202,203,203,202,202,202,202,202,202,202,203,203,204,203,203,203,203,203,203,204,202,203,204,204,204,204,204,204,202,202,202,202,202,203,202,204,204,203,203,203,203,204,204,204,203,202,202,203,202,203,204,204,204,204,214,214,214,201,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,109,107,109,107,252,107,252,107,109,107,252,107,252,107,109,109,252,109,252,109,107,106,107,106,107,106,106,106,106,106,106,106,106,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,202,202,203,202,202,202,203,202,202,202,202,202,203,202,203,203,204,202,203,202,203,203,204,203,202,203,204,203,204,204,204,204,202,202,202,202,202,202,204,202,203,203,204,203,204,204,204,204,204,202,203,202,202,202,203,203,204,204,204,204,214,214,201 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,107,107,107,107,107,107,109,107,109,107,109,109,109,107,109,109,109,109,109,109,109,109,107,106,107,106,106,106,106,106,106,106,106,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,11,11,10,11,202,202,202,202,202,203,203,203,202,202,202,202,202,203,203,204,202,203,203,203,203,203,203,202,203,203,204,204,204,204,204,204,202,202,202,203,202,203,204,203,203,203,203,204,204,204,204,204,203,202,202,203,202,203,203,204,204,204,204,204,204,214,214 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,107,107,107,252,107,109,107,252,107,252,107,252,107,252,107,252,107,109,109,252,109,252,106,107,106,106,106,107,106,106,106,106,106,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,203,202,202,202,203,202,203,202,202,202,202,202,202,202,203,203,204,202,203,203,204,203,202,202,203,203,204,203,204,203,204,204,202,202,203,202,203,203,204,203,203,203,204,203,204,204,204,204,204,202,202,202,202,202,203,203,204,203,204,204,204,204,204 +,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,107,107,107,107,107,107,107,109,107,109,107,109,109,109,109,109,109,109,109,109,106,107,106,106,106,106,106,106,106,106,106,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,202,202,202,202,202,203,203,202,202,202,202,202,202,203,203,204,202,203,203,203,203,204,202,203,203,204,204,204,204,204,204,202,202,202,202,203,203,203,203,204,203,204,203,204,204,204,204,204,202,203,203,204,202,203,203,204,204,204,204,204,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,107,109,107,252,107,252,107,252,107,109,107,109,107,109,109,252,109,252,106,107,106,106,106,107,106,106,106,106,106,106,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,202,202,202,202,203,202,203,202,202,202,202,202,203,203,204,204,203,202,203,203,204,202,202,202,204,204,204,203,204,204,204,202,202,202,203,202,203,203,204,203,204,203,204,203,204,203,204,202,203,202,204,203,204,202,204,204,204,203,204,204,204,204,204 +,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,107,107,252,108,108,108,107,107,107,107,109,107,107,107,252,109,109,109,109,109,109,109,109,109,107,106,106,106,106,106,106,106,106,106,106,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,202,202,202,202,202,202,203,203,203,202,202,202,202,202,203,203,204,204,202,202,204,202,203,204,202,204,204,203,204,204,204,204,202,202,202,202,203,203,203,203,203,203,204,204,204,202,202,202,203,203,203,203,204,204,204,203,204,204,204,204,203,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,252,108,108,107,109,107,109,107,252,107,252,107,252,107,109,107,252,107,109,109,252,106,106,106,107,106,106,106,106,106,106,106,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,202,203,202,203,202,203,202,203,202,202,202,202,202,203,203,204,203,204,204,202,202,203,203,204,202,204,203,204,203,204,203,204,202,203,202,203,203,203,203,203,203,204,203,204,204,202,202,203,202,203,203,204,203,204,204,204,204,204,203,204,204,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,107,252,252,252,252,109,108,107,107,107,107,107,107,109,107,252,107,109,109,109,109,109,109,109,109,106,106,106,106,106,106,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,202,202,203,203,202,202,202,202,202,202,204,203,203,203,202,202,203,203,204,203,202,203,204,204,204,204,204,204,202,202,203,203,203,203,203,203,204,203,204,204,204,202,202,202,203,203,203,203,204,204,204,204,204,204,204,204,203,204,204,204 +,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,108,108,252,107,252,252,109,109,107,108,107,107,252,107,252,107,252,107,252,107,109,107,109,109,252,109,107,106,106,106,106,106,106,106,106,106,106,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,202,202,202,203,202,203,203,203,202,202,202,203,202,203,202,203,203,202,202,203,203,204,204,204,202,204,203,204,203,204,204,202,202,203,202,203,203,204,203,204,203,204,204,204,202,203,202,202,202,204,204,204,203,204,204,204,203,204,203,204,204,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,107,252,252,109,109,252,252,107,107,107,107,109,107,107,107,252,109,109,109,109,109,109,109,107,106,106,106,106,106,106,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,203,203,203,202,202,202,202,202,202,202,203,203,203,202,202,203,203,204,204,203,204,203,204,203,204,204,202,202,203,202,203,203,203,203,203,203,204,204,204,204,202,202,202,203,203,204,204,204,204,204,204,204,204,204,204,204,203,204,204,204 +,252,252,252,252,252,108,252,252,252,252,252,252,252,252,108,108,108,252,107,109,109,252,109,252,107,252,107,107,107,252,107,252,107,109,107,109,109,252,109,107,106,107,106,106,106,106,106,106,106,106,106,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,202,203,202,203,202,203,203,203,202,202,202,202,202,203,202,203,203,202,202,203,203,204,204,204,203,204,203,204,203,204,203,202,202,203,202,203,203,203,203,204,203,204,203,204,202,202,202,203,203,204,204,204,203,204,204,204,203,204,203,204,204,203,204,204 +,252,252,252,252,108,252,252,252,252,252,252,252,252,252,108,107,108,107,109,109,109,109,252,252,252,107,107,107,107,107,252,107,252,109,109,109,109,109,109,106,106,106,106,106,106,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,203,203,203,202,202,202,202,202,202,202,203,203,204,202,203,203,204,204,203,203,204,203,204,204,204,204,202,202,203,203,203,203,204,203,203,203,204,204,204,204,202,202,203,203,203,204,204,204,204,204,204,204,204,199,199,199,203,204,204,204 +,252,252,252,252,252,252,252,252,252,252,252,252,252,108,107,252,108,109,109,252,109,252,109,252,252,252,107,107,107,252,107,252,107,109,107,109,109,252,109,106,106,106,106,106,106,106,106,106,106,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,11,10,10,10,202,202,202,202,203,202,203,203,203,202,202,202,202,202,203,203,204,203,202,202,203,203,204,203,204,203,204,203,204,203,204,202,203,202,203,203,203,203,204,203,204,203,204,204,204,202,203,203,204,203,204,204,204,203,204,204,199,199,233,233,201,201,201,201,201 +,252,252,252,252,108,252,252,252,252,252,252,252,252,107,108,108,252,109,109,109,252,109,252,252,252,252,107,107,107,107,107,107,252,109,109,109,109,109,109,106,106,106,106,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,202,203,203,203,202,202,202,202,203,203,203,203,203,202,202,203,203,204,204,203,203,204,204,204,204,204,202,202,202,203,203,203,203,204,203,203,203,204,204,204,204,202,203,203,203,204,204,204,204,204,199,199,233,233,233,200,200,200,200,200,200 +,252,252,252,252,252,252,252,252,252,252,252,252,107,252,108,252,108,252,109,252,109,252,109,252,252,107,107,252,107,252,107,252,107,252,107,109,109,252,106,106,106,107,106,106,106,106,106,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,11,10,10,10,10,10,202,202,202,202,203,202,203,203,203,202,202,202,203,202,203,202,203,202,203,202,204,203,204,203,204,203,204,203,204,202,203,203,203,203,203,203,204,203,204,203,204,204,204,204,204,202,203,203,204,203,204,204,199,199,233,233,200,200,200,200,200,201,201,201,201 +,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,109,109,109,109,252,109,252,252,107,107,107,107,107,107,252,252,109,109,109,109,109,109,107,106,106,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,202,203,203,203,202,202,202,203,203,202,202,203,203,202,202,203,203,204,204,203,203,204,203,204,204,204,202,203,203,203,203,204,204,204,204,204,204,204,204,204,204,203,203,203,203,204,199,199,233,233,233,233,200,200,200,194,194,234,234,234,234 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,252,109,252,109,252,109,252,107,107,107,252,107,252,107,252,107,109,109,252,109,107,106,106,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,203,202,203,202,202,202,202,202,203,203,204,202,204,202,203,203,204,204,204,203,204,203,204,203,204,202,203,203,203,203,204,203,204,203,204,203,204,203,204,204,203,202,203,203,199,199,199,233,233,233,200,200,200,233,234,234,233,201,201,201,201 +,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,109,109,109,109,252,252,252,252,107,107,107,107,252,252,252,252,109,109,109,109,109,106,107,106,106,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,202,203,203,202,202,202,202,203,203,203,203,202,204,204,202,203,203,204,204,203,203,204,204,204,204,202,203,203,203,203,203,203,203,204,204,204,204,204,204,204,202,203,199,199,199,233,233,233,233,200,200,200,233,234,234,233,200,200,200,200,233 +,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,109,252,109,252,109,252,109,252,107,252,107,252,107,252,107,109,109,252,109,109,106,107,106,107,106,106,106,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,202,202,202,202,203,203,203,202,202,202,202,202,203,202,202,203,204,203,202,202,204,204,204,203,204,203,204,203,202,203,204,203,203,203,204,203,204,203,204,204,204,204,204,199,199,199,234,234,233,233,234,233,200,200,200,233,234,234,233,200,200,233,234,233,233 +,252,252,252,252,252,252,252,252,252,252,252,108,108,108,109,109,109,109,252,109,252,252,252,252,107,107,107,107,109,109,109,109,109,109,109,109,107,106,252,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,202,202,203,203,202,202,202,202,203,202,202,202,203,203,204,203,202,204,204,204,204,203,204,203,204,204,203,203,203,203,203,203,204,203,204,204,204,204,199,199,234,234,234,233,233,233,234,233,200,233,233,233,234,233,233,200,200,234,234,234,233,233 +,252,252,252,252,252,252,252,252,252,252,252,108,108,109,108,252,108,252,109,252,109,252,252,252,107,252,107,109,107,109,109,109,109,109,109,252,106,252,106,106,106,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,202,202,202,202,202,203,202,203,202,202,202,202,203,202,202,203,203,204,204,203,203,204,203,204,204,204,203,204,203,203,203,203,203,204,204,204,203,204,203,204,204,199,234,234,234,233,233,234,233,234,233,200,233,234,192,234,233,200,200,200,200,200,233,233,234,234 +,252,252,252,252,252,252,252,252,252,252,108,108,108,108,109,109,252,109,252,109,252,252,252,107,107,107,252,107,109,109,109,109,109,109,109,107,107,106,106,106,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,202,202,202,202,202,202,203,202,202,202,202,202,202,202,203,203,203,203,204,203,203,203,204,204,204,203,204,204,204,203,203,203,203,203,204,203,204,203,204,199,234,234,234,199,234,234,234,234,234,234,234,234,234,234,234,233,200,233,200,200,200,234,233,234,234,234 +,252,252,252,252,252,252,252,252,252,108,108,109,108,252,108,252,109,252,109,252,109,252,109,107,107,252,107,109,109,252,109,107,109,107,107,107,106,107,106,106,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,202,202,202,202,202,203,203,202,202,202,202,202,202,202,202,203,203,204,203,204,203,204,203,204,204,204,203,204,203,203,203,204,203,204,204,204,203,204,199,192,199,192,192,199,192,193,192,192,193,193,234,234,234,234,234,234,234,200,234,233,234,233,234,234,234,233 +,252,252,252,252,252,252,252,252,108,108,108,108,109,108,109,109,252,109,252,252,252,252,107,107,107,107,252,109,109,107,107,106,107,106,107,106,107,106,106,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,202,202,202,202,203,203,203,202,202,202,202,202,202,202,202,202,203,203,204,204,204,204,204,204,204,203,204,204,204,203,203,203,204,204,204,203,204,199,192,199,192,192,199,199,192,192,193,192,193,193,193,234,200,192,234,234,234,234,234,234,233,234,234,194,234,233 +,252,252,252,252,252,252,252,108,108,109,108,252,108,252,109,252,109,252,109,252,252,252,107,252,107,252,252,109,107,109,106,107,107,107,106,107,106,106,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,202,202,203,202,202,203,202,202,202,202,202,203,202,202,202,203,203,204,203,204,203,204,203,204,203,204,203,204,203,203,203,204,203,204,204,204,203,199,192,192,192,193,199,192,192,193,192,193,193,193,192,234,234,200,233,234,234,234,234,234,234,234,194,234,233,233 +,252,252,252,252,252,252,108,108,108,108,108,108,252,109,252,109,252,252,252,252,252,252,107,107,252,252,252,107,106,106,107,107,107,106,107,106,107,106,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,10,202,202,203,202,203,203,202,202,202,202,202,202,202,202,203,203,203,203,204,204,204,203,204,204,203,203,204,204,204,203,203,203,204,204,204,203,199,192,199,192,192,192,199,192,192,192,193,193,193,192,192,192,234,234,234,234,234,234,234,234,234,194,194,234,233,233 +,252,252,252,252,252,252,108,108,108,252,108,252,109,252,109,252,109,252,109,252,252,252,252,107,107,252,107,106,107,106,107,107,107,107,106,107,106,107,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,202,202,203,202,203,202,203,202,203,202,202,202,203,202,203,202,203,203,204,203,204,203,204,204,204,203,204,203,204,203,203,203,204,203,204,204,204,199,192,192,193,192,192,199,193,192,193,193,193,192,192,192,192,192,192,192,234,192,193,193,234,193,194,194,234,234,233 +,252,252,252,252,252,252,108,108,108,108,109,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,106,107,106,107,109,109,107,106,107,106,106,106,106,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,202,202,202,203,203,203,203,202,202,202,202,202,202,202,202,203,203,203,203,204,204,204,204,202,203,204,203,204,204,203,203,203,203,204,204,204,199,192,199,192,192,193,199,199,192,193,193,193,193,192,192,192,192,192,192,193,192,193,193,193,193,194,194,194,194,194,234 +,252,252,252,252,252,252,108,252,108,252,108,252,108,252,109,252,252,252,252,252,252,252,109,252,252,106,107,106,107,107,107,252,107,107,106,107,106,106,106,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,202,202,203,202,203,202,203,202,202,202,202,202,202,202,203,202,203,203,204,204,204,203,202,204,204,203,204,203,204,203,204,203,204,203,204,199,192,199,193,192,192,199,193,192,192,192,193,192,193,192,193,192,192,192,193,192,193,192,193,193,194,193,194,194,194,194,194 +,252,252,252,252,252,108,108,108,109,108,109,109,252,252,252,252,252,252,252,252,252,107,107,107,106,109,109,107,106,107,252,109,107,107,107,106,106,106,106,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,202,202,202,203,203,203,202,202,202,202,202,202,202,202,202,203,203,203,204,204,204,202,203,204,203,203,203,204,204,203,203,204,203,204,204,199,192,192,192,199,199,199,192,193,193,193,192,192,192,193,192,192,193,192,192,192,192,192,192,193,193,194,194,194,194,194,194 +,252,252,252,252,252,108,108,109,108,252,108,252,109,252,109,252,252,252,107,107,107,106,106,252,107,109,107,107,107,107,107,252,107,107,106,106,106,106,106,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,202,202,203,202,203,203,202,202,203,202,202,202,202,202,203,203,204,203,204,204,202,202,204,204,204,203,204,203,204,203,203,203,204,203,199,192,199,199,193,199,193,192,193,192,193,192,192,192,193,192,192,192,193,192,193,192,193,193,194,193,194,194,194,194,194,194,194 +,252,252,252,252,252,108,252,108,108,108,109,252,252,252,252,252,108,107,107,107,107,107,252,107,109,109,252,106,107,107,252,252,107,107,106,106,106,106,106,106,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,202,202,202,203,203,203,202,202,202,202,202,202,202,203,203,203,203,204,204,204,202,203,203,204,203,204,203,204,204,203,203,203,203,204,199,192,192,193,192,192,192,193,192,193,193,192,192,192,192,193,192,192,192,192,192,193,193,193,193,194,194,194,194,194,194,194,194 +,252,108,108,252,108,252,108,252,108,109,108,252,109,108,108,252,108,252,107,252,107,252,107,109,107,252,109,107,107,252,107,109,107,107,106,106,106,106,106,106,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,10,9,202,202,203,202,203,203,202,202,202,202,202,202,203,202,203,203,204,203,204,202,203,203,204,204,204,203,204,203,204,203,204,203,204,199,192,192,199,192,193,192,193,192,193,193,193,192,192,192,193,192,193,192,192,192,193,193,194,193,194,193,194,194,194,194,194,194,194 +,108,108,108,108,252,252,108,108,252,108,109,109,252,108,108,108,252,107,107,107,252,252,252,109,109,109,109,106,107,106,252,109,107,107,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,202,202,202,203,203,203,202,202,202,202,202,202,204,203,203,203,203,204,204,202,202,203,203,204,203,203,203,204,204,203,203,204,199,192,199,192,192,192,192,193,192,193,194,193,193,192,192,192,192,192,192,193,192,192,192,193,193,194,193,194,194,194,194,194,194,194,194 +,108,252,108,252,252,252,108,108,108,252,108,252,108,252,108,252,108,252,107,109,107,252,107,109,109,252,107,107,106,252,107,109,107,107,106,106,106,106,106,106,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,202,202,202,203,202,203,203,202,202,203,202,202,202,204,202,203,203,204,203,202,202,203,203,204,204,204,203,204,203,204,203,204,203,199,192,192,192,192,192,193,192,193,193,194,193,192,192,193,192,193,192,193,192,193,192,193,193,194,193,194,194,194,194,194,194,194,194,194 +,108,108,252,252,108,108,252,252,109,108,108,108,108,108,108,108,108,107,109,107,109,109,109,109,109,109,252,106,107,106,252,109,107,106,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,202,203,203,203,202,202,202,202,202,202,202,202,204,203,203,203,203,204,202,202,203,203,204,204,203,204,203,204,204,203,203,199,192,199,192,192,192,193,194,193,193,193,193,194,192,192,192,192,193,193,192,192,192,193,193,193,193,194,194,194,194,194,194,194,194,194,194 +,108,252,108,252,108,252,108,109,109,108,108,252,108,252,108,252,108,109,107,252,107,109,107,252,107,252,109,107,106,252,107,252,106,107,106,106,106,106,106,106,106,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,9,9,9,10,202,202,202,203,203,202,202,203,202,203,202,203,202,203,204,204,203,204,202,203,202,203,203,204,204,204,203,204,203,204,203,204,199,192,192,192,192,193,193,194,193,194,194,194,192,192,192,192,192,193,192,193,192,193,192,193,193,194,193,194,194,194,194,194,194,194,194,194 +,108,108,252,108,252,108,252,109,109,108,108,108,108,108,108,108,252,107,109,107,252,109,109,109,252,109,252,107,107,106,252,106,107,106,107,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,202,203,203,203,202,202,203,202,202,202,202,202,203,204,203,204,204,202,202,203,203,204,204,203,203,203,203,204,204,203,199,192,199,192,192,193,193,193,193,193,193,194,194,194,192,192,192,192,192,193,193,192,192,193,193,193,193,194,194,194,194,194,194,194,193,194,194 +,252,108,108,252,108,252,108,252,109,108,108,108,108,252,108,252,108,109,107,252,107,109,107,109,109,252,109,107,106,107,106,107,106,107,106,106,106,106,106,106,106,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,9,9,9,9,9,10,9,9,202,203,203,202,202,202,202,203,202,203,202,202,202,203,204,203,203,204,202,203,203,204,203,204,203,204,203,204,203,204,203,199,192,192,192,192,192,193,192,193,193,194,193,194,194,192,192,192,192,193,192,192,192,193,192,193,193,194,193,194,194,194,193,194,194,194,194,194 +,252,108,108,108,252,108,252,252,109,109,108,108,108,108,108,108,109,107,109,109,252,109,109,109,109,109,252,107,107,106,107,106,107,106,107,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,203,202,202,202,202,202,202,203,202,202,202,202,203,204,204,203,203,202,202,203,203,204,204,203,203,204,203,204,204,203,199,192,192,192,192,192,192,193,193,193,193,194,194,192,192,192,192,192,192,193,192,192,192,193,193,193,194,194,194,194,194,194,193,194,194,194,194 +,252,108,108,252,108,252,108,252,252,109,108,108,108,252,108,252,108,109,107,252,107,109,107,252,109,252,109,252,106,107,106,107,106,107,106,107,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,202,203,202,203,202,202,202,203,203,202,202,203,202,203,203,204,203,202,202,203,203,204,203,204,203,204,203,204,203,204,203,199,192,193,193,194,193,194,192,193,193,194,193,194,192,193,192,193,192,193,192,192,192,193,192,193,193,194,193,194,193,194,194,193,194,194,194,194 +,252,108,108,108,252,252,252,252,252,252,109,108,108,108,108,108,109,107,107,107,252,109,109,109,252,109,252,109,107,252,252,109,107,106,107,106,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,203,203,202,202,202,202,202,203,202,204,202,202,203,203,204,204,204,202,202,202,203,203,204,204,204,203,204,203,204,204,199,192,192,192,193,193,193,193,194,194,193,193,194,193,192,192,192,192,193,193,192,192,192,192,193,193,193,193,194,194,194,194,194,193,194,193,194,194 +,108,252,108,252,108,252,108,252,252,252,252,109,108,252,108,108,108,252,107,252,107,109,107,252,107,252,107,107,107,252,252,109,109,107,106,107,106,106,106,106,106,106,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,202,202,203,202,202,202,202,202,202,203,204,202,202,202,203,203,204,203,202,202,203,203,204,204,204,203,204,203,204,204,204,199,192,192,193,192,194,193,194,193,194,193,194,194,194,192,192,192,193,192,193,193,192,193,194,192,193,193,194,193,194,193,194,193,194,194,194,194,194 +,108,108,108,108,252,252,252,252,252,252,252,252,109,108,108,108,108,107,107,107,252,107,109,109,109,109,252,107,107,252,252,109,109,109,107,106,107,106,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,202,202,202,202,202,202,202,202,203,204,202,202,203,203,204,204,204,202,203,203,203,203,204,203,204,203,204,204,204,204,199,192,192,192,192,193,192,194,193,194,194,194,194,194,192,192,192,192,193,193,192,192,193,194,194,193,193,193,194,194,194,193,194,194,194,193,194,194 +,108,108,108,252,108,252,108,252,252,252,108,252,252,109,108,108,108,109,107,252,107,252,107,252,107,252,109,107,107,252,252,109,109,107,109,107,106,107,106,106,106,106,106,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,202,202,202,202,202,203,202,202,202,202,203,204,202,202,202,203,203,204,202,202,202,203,203,204,204,204,203,204,203,204,204,204,199,193,192,193,192,192,193,193,193,193,194,194,194,193,192,193,192,193,192,193,192,193,193,194,193,194,193,194,194,194,193,194,193,194,193,194,194,194 +,108,108,108,108,252,252,252,252,252,108,252,252,252,108,109,109,108,107,107,107,252,107,252,107,109,109,252,109,107,252,109,109,107,107,109,109,107,106,107,106,106,106,106,106,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,202,202,202,202,202,202,203,202,202,202,203,204,202,202,203,203,204,203,203,202,202,203,203,204,204,203,204,204,204,204,204,203,199,192,193,192,192,193,192,193,193,194,193,194,194,193,192,192,192,192,193,193,192,192,193,193,194,194,194,194,194,194,194,194,194,194,194,193,194,194 +,108,252,108,252,108,252,108,252,252,252,108,252,108,252,252,109,109,107,107,107,107,252,107,252,107,252,107,252,107,252,109,109,107,252,107,109,107,107,106,107,106,107,106,106,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,202,202,202,202,203,202,202,202,202,202,202,203,204,202,202,202,204,204,203,202,203,202,203,203,204,203,204,203,204,203,204,203,204,199,192,192,192,192,192,193,193,193,193,194,194,194,193,192,193,192,193,192,193,192,193,192,193,193,194,194,194,194,194,193,194,193,194,193,194,195,194 +,108,108,108,108,252,108,252,252,252,108,252,108,108,252,252,252,109,107,107,107,109,109,252,252,109,109,252,107,107,109,109,109,107,107,109,109,109,109,107,106,107,106,106,106,106,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,9,9,202,202,202,203,202,202,202,202,202,202,202,203,204,202,202,203,203,204,203,202,202,203,203,204,204,204,204,204,204,204,204,203,199,199,192,193,192,192,193,192,193,193,194,194,194,194,192,192,192,192,192,193,193,192,192,193,193,194,194,194,194,194,194,193,193,194,193,194,194,194,194 +,108,108,108,252,108,252,108,252,252,108,108,252,108,252,108,252,252,109,107,252,107,252,107,252,109,252,107,252,107,109,109,109,109,107,107,252,107,109,109,107,106,107,106,106,106,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,202,202,202,202,203,203,202,203,202,202,202,202,204,202,202,203,203,204,202,203,202,203,203,204,204,204,203,204,203,204,204,204,203,199,199,193,192,192,193,193,193,193,194,193,194,194,193,192,192,193,192,193,193,193,192,193,193,194,193,194,194,194,194,194,193,194,193,194,193,194,195,194 +,108,108,108,108,252,252,252,252,252,108,108,108,108,108,252,252,252,252,107,107,252,109,252,252,252,252,107,107,107,107,109,107,109,109,107,107,109,109,109,107,107,106,107,106,106,106,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,9,9,9,8,202,202,202,202,203,202,202,202,203,202,202,202,204,204,202,202,204,204,203,202,203,203,203,203,204,204,204,204,204,204,204,204,204,199,192,192,192,193,192,193,192,193,193,194,193,194,192,192,192,192,193,193,193,193,192,192,193,193,194,194,194,194,194,193,193,194,194,194,194,194,194,194 +,108,252,108,252,108,252,108,252,252,252,108,108,108,252,252,252,252,252,107,107,107,252,107,252,252,107,107,109,107,109,107,109,107,252,107,109,107,109,107,109,109,107,106,107,106,106,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,202,202,203,202,203,203,203,202,203,202,203,202,202,204,204,202,203,203,204,202,202,202,203,203,204,204,204,203,204,204,204,203,204,203,199,192,193,192,192,192,192,193,193,193,193,194,194,192,192,192,193,192,193,192,193,192,193,192,194,193,194,194,194,194,194,193,195,194,194,193,194,195,194 +,108,108,108,108,252,252,252,252,252,252,252,108,108,107,252,252,252,252,107,107,107,107,252,252,252,107,107,107,107,109,109,109,109,109,107,109,107,107,109,109,109,109,107,106,107,106,106,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,202,202,202,202,202,202,203,202,202,202,202,202,202,204,204,202,202,203,203,204,202,202,203,203,204,204,204,204,204,204,204,204,204,204,204,199,192,192,192,193,192,193,193,194,193,194,194,194,192,192,192,192,193,192,193,193,192,192,193,194,194,194,194,194,194,194,194,194,195,194,194,195,195,194 +,108,108,108,252,108,252,108,252,252,252,252,252,108,252,252,252,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,109,107,109,107,107,109,107,109,109,107,106,107,106,106,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,202,202,202,202,202,203,203,203,202,203,202,202,202,204,204,202,202,202,203,204,202,202,202,203,203,204,203,204,203,204,204,204,204,204,199,199,192,192,192,192,193,193,193,193,194,194,194,194,192,192,192,193,192,193,193,194,193,192,193,194,193,194,193,194,195,195,194,195,194,194,194,195,194,194 +,108,108,108,108,252,252,109,252,252,252,252,252,252,252,108,107,252,252,252,107,107,107,252,107,252,109,109,107,109,109,107,107,109,109,109,109,109,107,107,107,109,109,109,109,109,106,107,106,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,153,154,154,154,154,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,202,202,202,202,202,202,202,203,203,202,202,202,202,203,203,204,202,203,202,204,203,203,202,203,203,204,204,204,204,204,204,204,204,204,203,199,192,192,193,192,193,192,193,193,194,193,194,193,194,194,192,192,192,193,193,193,193,193,193,194,194,194,194,194,194,194,194,194,194,195,194,194,194,195,194 +,252,108,108,252,108,252,108,252,252,252,109,252,252,252,109,252,107,252,252,108,107,109,107,252,107,252,107,252,109,109,107,109,107,252,107,109,109,109,107,107,107,109,107,109,109,107,106,106,106,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,153,153,153,153,153,153,154,154,154,153,154,154,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,202,202,202,202,203,202,203,203,203,202,202,202,203,203,204,204,202,203,203,203,203,203,202,202,203,203,204,203,204,203,204,204,204,204,204,199,192,192,192,193,193,193,193,193,193,193,193,194,194,194,193,192,193,192,193,193,193,193,194,193,194,194,194,194,194,195,194,194,195,193,194,194,195,195,194 +,109,108,108,108,109,108,252,252,252,252,252,252,252,252,252,252,108,107,252,107,108,107,252,107,109,109,109,109,252,109,107,107,109,107,109,109,109,109,109,107,107,109,109,109,109,107,107,106,106,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,153,153,153,153,152,152,152,152,152,153,153,154,153,154,154,154,154,154,154,153,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,202,202,202,202,202,202,203,203,203,203,203,202,203,203,204,204,202,203,204,203,203,203,202,202,203,203,204,204,204,204,204,204,204,204,204,203,199,192,192,193,192,193,192,193,192,194,193,194,193,194,194,192,193,192,193,193,193,193,193,193,194,194,194,194,194,193,194,194,194,194,195,194,195,194,195,194 +,252,108,108,252,108,252,252,252,252,252,109,252,109,252,252,252,107,252,107,108,107,252,107,109,107,252,107,252,109,252,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,107,106,106,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,8,9,153,153,152,152,152,157,157,155,156,157,157,152,153,153,153,153,153,153,154,154,154,154,154,154,154,154,8,9,8,9,8,9,8,9,8,9,8,9,202,202,202,202,202,203,202,203,202,203,202,202,202,204,204,202,202,204,204,203,203,204,202,203,203,204,204,204,203,204,204,204,204,204,204,204,199,192,192,192,193,192,193,192,193,194,194,193,194,192,193,194,192,192,192,193,193,194,193,194,193,194,194,194,194,193,194,195,194,195,194,194,195,195,195,194 +,109,252,108,108,252,252,109,252,252,252,252,252,252,252,252,252,108,107,108,252,107,107,107,107,109,109,109,109,252,252,107,107,109,107,109,107,109,109,109,107,107,107,109,109,109,109,109,107,107,106,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,152,157,156,156,155,155,157,157,156,155,156,156,157,152,153,153,152,152,153,153,153,153,153,154,154,154,154,154,154,154,154,8,8,8,8,8,8,8,8,202,202,202,202,203,203,203,202,203,202,204,202,202,202,202,202,203,203,204,204,203,202,202,203,203,204,204,204,204,203,204,204,204,204,204,199,192,192,192,193,192,193,192,193,193,194,193,194,193,192,193,194,192,194,193,193,193,193,193,193,194,194,194,194,194,193,194,194,195,195,195,194,195,195,195,194 +,252,252,108,108,108,252,108,252,252,252,109,252,252,252,252,252,108,252,107,252,107,252,107,109,107,252,107,252,109,252,107,109,107,252,107,109,107,252,107,107,107,109,107,109,107,109,109,107,107,106,106,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,152,157,157,157,156,156,155,157,156,156,155,157,156,157,156,152,153,157,156,152,152,153,153,154,153,153,154,153,154,154,154,154,154,154,154,154,8,9,8,8,202,202,203,204,202,203,202,202,202,203,204,203,202,202,202,203,203,204,203,204,203,204,202,203,203,204,204,204,203,204,203,204,204,204,204,199,192,192,192,192,193,192,192,193,193,194,194,193,192,193,193,194,193,194,192,193,193,194,193,194,193,194,194,194,195,194,194,195,194,195,194,195,194,195,195,195 +,109,252,109,108,108,252,252,252,252,252,252,252,252,252,252,252,108,107,108,109,107,107,107,107,109,107,109,109,252,109,107,107,107,107,109,107,109,107,109,107,107,107,109,107,109,109,109,107,107,106,106,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,157,157,157,157,156,156,155,155,157,157,156,156,155,156,156,156,156,152,157,157,156,156,152,153,153,153,154,154,154,154,153,154,154,154,154,154,154,154,154,154,202,202,203,204,202,202,202,202,202,203,203,204,202,202,202,203,203,203,203,204,204,204,203,203,204,204,204,204,204,204,204,204,204,204,204,204,199,192,192,192,193,192,193,192,193,193,194,194,194,192,193,194,194,193,194,193,193,193,193,194,194,194,193,194,194,195,194,194,194,195,195,195,195,195,195,195,195 +,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,108,107,108,109,252,252,107,107,109,107,252,107,252,107,252,109,252,107,109,107,252,107,252,107,107,107,109,107,109,107,109,109,109,107,107,106,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,9,8,8,8,157,157,157,156,157,155,156,155,157,156,156,155,155,156,157,156,156,155,157,156,157,155,152,153,153,153,153,153,153,154,154,154,154,154,154,154,154,154,154,154,202,202,204,202,202,202,202,202,203,203,204,204,203,202,203,202,203,203,204,203,204,204,203,203,202,204,204,204,204,204,204,203,204,203,204,204,199,192,192,192,192,192,192,193,193,193,193,194,192,192,193,193,194,194,193,194,193,193,194,193,194,193,194,194,195,194,195,195,195,195,195,194,195,195,195,194,192 +,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,107,108,107,109,109,252,107,107,107,109,109,109,109,252,109,252,107,252,107,107,107,109,107,109,107,107,107,107,107,109,109,109,109,107,106,106,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,157,157,157,157,156,156,155,155,157,157,156,156,155,155,157,156,155,157,157,156,156,156,156,152,153,153,153,153,153,153,153,153,153,154,153,154,154,154,154,154,202,202,202,202,202,203,202,202,203,203,204,204,202,202,202,203,203,203,203,204,204,204,203,202,203,204,204,204,204,204,204,204,204,204,204,204,192,192,192,192,193,192,193,192,193,193,194,192,192,193,193,193,193,194,194,194,194,194,194,194,194,193,193,194,194,195,195,195,195,195,195,195,194,195,194,192,199 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,108,107,252,109,252,252,252,107,109,107,252,107,252,109,252,109,107,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,109,107,107,106,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,8,8,8,8,8,8,9,8,157,157,157,156,156,155,156,155,157,156,156,155,156,155,157,157,157,156,157,156,156,155,156,152,153,153,152,152,152,152,152,152,153,153,153,153,154,153,154,153,202,202,203,202,203,202,202,202,203,203,204,203,204,202,203,202,203,203,204,203,204,204,202,202,204,204,204,203,204,204,204,203,204,204,204,199,192,192,192,192,192,192,192,193,193,193,193,192,193,192,193,193,194,194,194,194,194,193,194,193,194,194,194,193,195,194,195,193,195,194,195,194,194,195,192,199,192 +,109,252,109,252,109,252,252,252,252,252,252,252,252,252,108,107,108,107,252,252,252,107,107,107,107,107,109,109,252,109,252,107,107,107,252,107,252,107,109,107,107,107,107,107,109,107,109,109,107,106,106,106,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,157,157,157,156,156,156,155,155,157,157,156,156,156,155,155,155,157,157,157,156,156,156,202,202,202,152,152,202,202,203,202,202,203,152,152,152,152,153,153,153,154,202,202,202,202,202,202,202,203,203,203,203,204,204,202,202,203,203,203,203,203,203,204,202,203,203,204,204,204,204,204,204,204,204,204,204,199,192,192,192,192,192,192,193,192,193,193,194,192,192,193,193,193,194,194,194,194,193,194,194,194,194,193,193,195,194,195,195,195,195,194,194,195,195,192,199,192,193 +,252,109,252,252,252,252,252,252,252,252,252,252,252,108,107,109,107,252,107,252,109,107,107,252,107,252,107,252,107,252,109,107,109,252,107,252,107,252,107,109,107,107,107,109,107,109,107,109,106,107,106,106,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,157,157,157,157,156,156,155,155,157,157,156,156,155,156,155,155,156,202,202,202,202,202,202,202,202,202,202,202,202,203,202,203,202,203,203,204,152,153,153,154,202,203,202,203,202,202,202,203,202,203,203,204,203,204,202,203,202,203,202,203,203,204,202,203,203,204,204,204,204,204,204,204,204,204,204,204,199,193,192,192,192,192,192,192,193,193,194,192,192,193,192,193,193,194,195,194,194,194,193,194,194,194,195,193,193,195,194,195,195,194,195,195,195,192,199,192,192,192 +,109,252,109,252,252,252,252,252,252,252,252,252,252,107,108,107,109,109,252,109,252,252,107,107,109,107,109,109,252,107,252,109,107,107,107,107,252,107,109,107,109,107,107,107,109,109,109,109,107,106,107,106,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,157,157,157,157,156,156,156,155,157,156,157,156,156,155,202,202,202,202,202,202,202,202,202,202,202,202,202,202,203,203,204,204,203,203,203,204,204,152,153,153,202,202,203,202,202,202,202,202,203,203,203,203,204,204,202,202,202,202,203,203,203,202,203,203,203,203,204,204,204,204,204,204,204,204,204,204,192,192,193,192,192,192,192,193,193,194,192,192,193,193,193,193,194,195,195,195,194,194,194,195,195,195,193,193,195,195,195,195,195,194,194,195,192,199,192,192,193,192 +,252,252,252,252,252,252,252,109,252,252,252,252,252,108,107,109,107,252,107,252,252,252,109,107,107,252,107,107,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,107,107,109,107,109,106,107,106,106,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,157,157,157,157,156,156,155,155,157,157,156,157,155,156,202,202,202,202,202,202,202,202,203,202,202,203,202,203,203,204,204,203,202,203,203,204,203,204,152,153,202,203,202,202,202,202,202,203,202,203,203,204,203,204,202,203,202,203,203,202,202,203,203,204,203,204,204,204,203,204,204,204,203,204,204,204,192,192,192,192,192,192,193,193,193,192,192,193,192,193,193,194,194,195,195,194,195,195,194,195,193,195,193,195,195,195,195,195,195,194,195,192,199,192,192,192,192,192 +,109,252,109,252,252,252,109,252,252,252,252,252,252,107,108,107,109,107,252,252,252,252,252,252,107,107,107,107,109,252,252,107,107,107,107,107,107,107,252,107,109,107,107,107,109,107,109,109,107,106,107,106,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,7,8,8,8,157,157,157,157,156,156,156,155,155,157,157,156,156,156,155,202,202,202,202,202,202,203,203,202,202,202,202,203,203,204,204,204,203,203,203,203,203,204,204,155,152,203,202,202,202,202,202,202,202,203,203,203,203,204,204,202,202,203,202,202,202,203,203,203,203,204,204,204,204,204,204,204,204,204,204,204,204,192,193,192,193,192,193,192,193,192,192,192,192,193,193,193,194,195,195,195,195,194,195,195,195,195,195,194,195,195,195,195,195,194,195,192,199,192,192,192,192,193,192 +,252,109,252,252,252,252,252,252,252,252,252,252,107,108,107,252,108,252,107,252,109,252,109,252,107,107,107,252,107,252,109,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,107,109,106,107,106,106,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,157,157,157,157,157,156,156,155,155,156,157,156,156,155,156,202,203,202,203,202,203,202,202,202,203,202,203,203,204,203,204,204,203,203,204,203,204,203,204,155,155,202,202,202,202,202,202,202,203,202,203,203,204,203,204,202,203,202,202,202,203,202,203,203,204,203,204,203,204,204,204,204,204,204,204,204,199,192,193,192,192,192,192,193,192,192,193,192,193,193,194,194,195,194,195,195,194,195,195,195,195,195,195,195,195,194,195,195,195,195,192,199,199,192,193,192,193,192,193 +,252,252,109,252,252,252,109,252,252,252,252,252,108,107,108,107,109,109,252,109,252,252,252,109,252,107,107,107,252,252,252,107,107,107,107,107,252,107,107,107,109,109,107,107,109,109,109,109,107,106,107,106,106,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,7,7,7,8,157,157,157,157,156,156,155,155,157,157,156,156,156,156,202,202,202,202,202,203,202,202,202,203,203,203,203,203,203,204,204,204,203,203,203,204,204,204,204,203,155,202,202,202,202,202,202,202,202,203,203,203,203,204,204,202,202,203,202,202,203,203,203,204,204,204,204,204,204,204,204,204,204,204,204,204,192,199,192,192,192,192,193,192,192,192,192,193,193,193,193,195,195,195,195,194,195,195,195,195,195,195,194,195,194,195,195,195,195,192,199,192,192,192,192,192,192,193,192 +,252,109,252,252,252,109,252,252,252,252,252,252,108,252,107,109,108,252,107,252,109,252,252,252,109,107,107,252,107,252,107,107,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,106,107,106,106,106,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,157,157,157,156,156,155,155,156,157,156,157,156,156,155,202,202,203,202,202,202,203,202,203,203,204,203,204,203,204,203,204,203,204,203,204,203,204,203,202,202,155,202,202,202,202,202,202,202,203,202,203,203,204,204,202,202,203,202,202,202,203,203,204,203,204,203,204,204,204,203,204,204,204,204,204,204,192,192,192,192,192,192,192,193,192,192,192,192,193,192,193,194,195,194,195,195,195,195,195,195,195,195,195,194,195,194,195,195,192,199,192,192,193,192,193,192,193,192,193 +,252,252,109,252,109,252,252,252,252,252,252,252,108,108,108,108,109,109,252,252,252,252,252,109,252,107,107,107,252,252,107,107,107,107,107,107,107,107,252,107,109,109,109,107,107,107,109,109,107,106,107,106,106,106,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,157,157,157,157,156,155,155,156,157,157,157,156,156,155,155,202,202,202,203,202,202,203,204,203,203,203,203,203,204,204,204,204,203,203,203,203,204,204,202,202,202,202,202,202,203,203,202,202,202,202,203,203,204,204,204,202,202,204,202,202,203,203,204,204,204,203,204,204,204,204,204,204,204,204,204,204,204,192,192,192,192,193,192,193,192,192,192,192,192,192,193,194,195,195,195,195,194,195,194,195,195,195,195,194,195,195,195,195,195,199,192,192,192,192,192,192,192,192,193,192 +,252,109,252,252,252,252,252,252,252,252,252,252,108,108,108,252,108,252,109,252,109,252,252,252,109,252,107,252,252,107,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,109,107,107,106,107,106,106,106,106,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,202,206,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,157,157,157,157,156,156,155,157,156,157,156,157,156,156,155,202,202,203,202,203,202,202,202,204,204,203,203,204,203,204,204,204,203,203,203,204,202,202,202,202,202,202,202,203,202,203,202,202,202,203,203,204,203,204,202,202,203,204,202,204,202,203,203,204,203,204,203,204,203,204,203,204,204,204,204,204,199,192,192,193,192,192,192,192,193,192,192,192,192,193,193,195,195,194,195,194,195,195,195,195,195,195,195,195,194,195,195,195,199,192,192,192,192,192,192,193,192,193,192,193 +,252,252,109,252,109,252,252,252,252,252,252,252,108,108,108,108,252,109,252,109,252,252,252,252,252,252,107,107,252,252,107,107,107,107,107,107,252,107,109,107,109,109,109,109,109,107,109,106,107,106,106,106,106,106,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,202,203,203,206,207,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,157,157,157,157,156,155,157,156,157,157,156,156,156,156,202,202,202,202,202,202,202,202,203,203,204,203,203,203,204,204,204,204,203,203,202,202,202,202,202,202,202,202,203,203,203,203,202,202,203,203,204,204,203,203,202,202,203,203,204,202,203,203,203,203,204,203,204,204,204,204,204,204,204,204,204,204,192,192,192,192,193,192,192,193,192,192,192,193,192,192,193,195,194,194,194,194,194,195,194,195,195,195,195,194,195,195,195,199,199,192,192,192,192,192,192,192,192,192,193,192 +,252,252,252,109,252,252,252,252,252,252,252,252,108,109,108,109,252,252,109,252,109,252,109,252,109,252,107,252,107,252,107,107,107,252,107,252,107,109,107,109,107,252,107,109,109,107,107,107,106,107,106,106,106,106,106,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,202,203,202,203,203,204,206,207,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,7,7,6,7,157,157,157,157,155,157,156,157,157,157,156,156,156,156,202,202,202,202,202,202,202,203,203,204,204,204,203,204,203,204,204,203,202,203,202,203,202,203,202,203,203,203,202,203,203,203,202,202,203,204,202,203,202,203,202,203,203,204,202,203,202,203,202,203,203,204,203,204,203,204,204,204,204,204,204,204,192,192,192,193,192,192,192,192,192,192,192,192,193,193,192,194,194,194,194,194,195,194,194,195,195,195,195,195,195,195,199,199,192,193,192,192,192,193,192,193,192,193,192,193 +,252,252,109,252,109,252,252,252,252,252,252,252,108,108,109,252,109,109,252,252,252,252,252,252,252,252,107,107,252,252,107,107,107,107,107,107,252,107,109,107,109,109,109,109,109,107,109,106,107,106,106,106,106,106,106,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,202,202,203,203,202,202,203,203,206,207,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,157,157,157,157,156,155,156,157,157,157,156,156,156,156,155,202,202,202,202,202,202,203,203,203,204,204,203,204,204,204,204,202,202,202,202,203,202,202,202,203,203,203,203,203,203,203,203,202,202,204,202,202,202,202,202,203,203,204,204,203,202,203,203,203,203,203,203,204,204,204,204,204,204,204,204,204,199,192,192,192,192,192,192,193,192,192,193,192,193,193,194,194,194,194,194,194,192,193,194,195,195,195,195,195,195,195,199,199,192,192,192,192,192,192,192,193,193,193,192,193,193 +,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,252,108,252,109,252,109,252,252,252,109,252,252,107,107,252,109,252,107,252,107,252,107,109,107,252,107,252,107,109,107,107,107,109,106,106,106,106,106,106,106,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,202,203,202,203,202,202,202,203,203,204,206,207,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,157,157,157,157,155,156,157,156,157,156,157,156,156,155,156,202,203,202,203,202,203,202,203,203,204,204,204,203,204,203,202,202,203,202,203,202,203,202,203,203,203,202,203,203,203,202,202,202,203,203,204,203,204,202,203,202,204,203,204,202,203,202,203,203,204,203,204,203,204,203,204,204,204,204,204,204,199,192,192,192,192,192,193,192,192,192,192,193,193,193,193,194,194,194,194,192,194,194,195,195,195,194,195,195,195,199,199,192,192,192,192,192,193,192,193,192,193,192,193,192,193 +,252,252,109,252,109,252,252,252,252,252,252,252,108,108,108,108,252,109,252,109,252,252,252,252,252,252,252,107,107,107,109,109,107,107,107,107,109,107,109,107,109,109,109,109,107,107,107,109,107,106,106,106,106,106,106,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,202,202,202,202,202,202,203,202,204,202,202,203,203,206,207,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,6,7,6,7,6,7,6,6,157,157,157,157,157,157,156,155,156,157,156,156,156,156,202,202,202,202,202,202,202,203,203,203,204,204,202,203,203,202,202,202,202,203,202,203,202,203,203,203,203,204,204,204,202,202,202,203,203,203,203,204,202,203,203,203,203,204,202,202,202,203,203,203,203,203,203,203,199,199,204,204,204,204,204,204,192,192,192,192,192,193,193,193,193,192,193,192,193,193,194,193,194,194,192,193,194,195,195,195,195,195,195,195,199,192,192,192,192,192,192,192,192,193,192,193,192,193,193,193,193 +,252,109,252,252,252,252,252,252,252,252,252,252,107,252,108,252,252,252,109,252,109,252,109,252,252,252,109,107,107,252,107,252,107,252,107,252,107,109,107,109,107,252,107,107,107,109,107,109,106,106,106,106,106,106,106,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,202,202,202,202,203,203,204,202,204,202,203,203,204,206,207,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,157,157,157,156,156,155,155,157,157,156,157,156,156,155,202,202,202,202,203,202,203,203,204,203,204,202,203,202,202,202,203,202,203,202,203,202,203,203,203,203,204,204,204,202,203,202,203,202,203,203,204,202,203,203,204,203,204,202,203,202,203,202,203,202,203,203,199,199,192,193,204,203,204,204,192,199,192,192,193,192,192,192,193,193,194,192,192,193,193,194,194,194,192,192,193,192,194,193,195,195,195,195,195,195,199,192,192,192,192,192,193,192,193,192,193,192,193,192,193,192,193 +,252,252,109,252,109,252,252,252,252,252,252,252,108,108,109,252,109,109,252,252,252,252,252,252,252,252,252,107,107,107,109,109,252,107,252,107,107,107,109,107,109,109,109,107,107,107,107,109,107,106,106,106,106,106,106,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,202,202,202,202,203,203,204,204,202,204,202,202,203,203,206,207,207,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,157,157,157,156,156,156,155,155,157,157,157,156,156,155,155,202,202,202,202,202,203,203,203,203,204,204,202,202,202,202,203,203,203,203,203,203,203,203,203,203,204,204,202,202,202,202,203,203,203,203,204,204,202,202,203,203,204,204,202,202,203,202,203,203,203,199,199,193,192,194,194,204,204,204,199,199,199,192,193,193,192,192,193,193,193,193,192,193,192,194,193,194,192,192,193,193,193,193,195,195,195,195,195,194,195,199,192,192,193,192,192,192,192,192,192,192,193,193,193,193,193,193 +,252,109,252,252,252,252,252,252,252,252,252,109,107,109,108,252,108,252,109,252,109,252,252,252,252,252,252,107,107,109,107,252,109,252,107,109,107,109,107,252,107,252,107,252,107,109,107,107,106,106,106,106,106,106,106,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,202,203,202,202,202,203,203,204,202,204,202,203,203,204,206,207,207,207,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,6,7,6,6,157,157,157,157,156,156,155,155,156,157,156,156,155,156,155,202,202,203,202,203,202,203,203,204,203,204,202,202,202,203,202,203,203,203,202,203,203,203,204,204,204,204,202,202,202,203,202,203,203,204,203,204,202,202,202,203,203,204,199,199,199,203,202,199,199,192,192,193,193,194,194,194,193,199,199,193,193,194,193,192,192,193,192,193,193,194,192,192,193,193,194,192,192,193,192,193,194,195,194,195,194,195,195,195,195,199,199,192,192,192,192,193,192,192,192,193,193,194,193,193,193,193 +,109,252,109,252,252,252,252,252,252,252,252,252,108,108,108,108,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,252,109,107,107,109,107,109,107,109,109,107,107,109,109,107,106,107,106,106,106,106,106,106,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,202,202,202,202,202,203,203,204,203,202,202,203,204,203,206,207,207,207,206,207,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,157,157,157,156,156,155,156,155,157,156,156,156,156,155,202,202,202,202,202,202,203,203,203,204,204,204,203,203,203,203,203,203,204,203,204,204,204,204,204,204,204,202,202,202,202,202,203,203,203,203,204,204,202,202,203,203,204,199,199,192,193,192,192,192,192,192,192,193,194,193,194,194,192,192,193,193,193,193,194,192,192,192,193,193,193,193,192,193,194,192,192,192,192,192,193,194,194,195,195,195,195,195,195,195,199,199,192,199,192,192,192,192,192,192,193,192,193,193,193,192,193,193 +,252,252,252,252,252,252,252,252,252,252,252,252,107,252,108,252,252,252,109,252,109,252,109,252,252,252,109,107,107,109,107,109,107,252,109,109,107,252,107,109,107,252,106,107,107,107,106,107,106,106,106,106,106,106,106,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,202,202,203,202,203,202,203,202,203,204,204,203,202,202,203,204,204,206,207,207,207,207,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,145,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,5,6,6,6,157,157,156,157,155,156,155,155,156,157,156,156,155,156,202,203,202,202,202,203,202,203,203,204,204,202,202,203,202,203,203,204,203,204,204,204,203,204,204,204,204,202,202,203,202,203,203,204,203,204,204,204,202,202,202,204,204,199,192,193,192,193,193,194,194,192,192,193,193,194,194,192,193,194,192,193,193,194,193,192,192,193,193,194,193,194,192,194,193,192,192,193,192,193,193,194,194,195,195,195,194,195,195,195,199,192,199,193,192,192,192,193,192,193,192,193,193,194,193,193,193,193 +,109,252,109,252,252,252,252,252,252,252,252,252,108,107,109,252,109,109,252,109,252,252,252,252,252,252,252,107,107,107,109,107,109,109,109,107,109,107,109,107,109,109,106,107,107,106,107,106,107,106,106,106,106,106,106,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,202,202,202,202,202,203,202,203,204,202,203,204,204,202,202,203,204,204,206,207,206,207,207,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,145,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,157,157,157,156,156,156,155,155,157,157,156,156,156,156,155,202,202,202,202,203,203,203,203,204,204,202,202,202,202,203,203,203,203,204,204,204,204,204,204,204,204,202,202,203,203,203,203,203,203,204,204,202,202,203,202,203,204,199,199,192,192,193,193,193,193,194,194,192,192,193,193,192,193,194,194,193,193,193,193,194,192,192,192,193,193,194,194,192,193,193,192,192,192,193,193,194,194,193,194,194,194,195,195,195,195,199,192,199,192,193,192,192,192,192,192,192,193,193,193,193,193,194,193 +,252,109,252,252,252,252,252,252,252,252,252,252,107,109,108,252,108,252,109,252,109,252,109,252,252,252,252,107,107,107,107,252,107,252,109,109,107,109,107,252,107,252,107,107,106,107,106,107,106,107,106,106,106,106,106,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,202,202,203,202,202,202,203,202,203,203,204,202,204,204,203,202,203,204,204,206,207,206,207,207,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,145,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,157,157,157,156,156,155,156,155,157,156,157,156,156,155,156,202,202,202,203,202,203,203,204,204,202,202,204,202,203,203,204,203,204,203,204,204,204,204,204,203,204,202,203,202,203,203,204,203,204,204,203,202,203,202,203,202,204,199,193,192,193,192,193,193,193,192,194,193,194,193,192,192,193,193,195,195,193,193,194,193,192,192,193,192,194,193,194,194,193,192,192,192,193,193,194,194,193,194,195,194,195,195,195,195,195,199,192,192,193,192,192,192,192,192,192,193,194,193,194,193,194,193,193 +,109,252,109,252,252,252,252,252,252,252,252,252,108,107,108,108,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,109,109,109,107,109,107,109,107,109,109,107,107,107,106,107,106,107,106,106,106,106,106,106,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,202,202,202,202,203,202,202,203,204,202,204,203,204,202,204,202,202,203,204,206,207,205,206,206,207,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,145,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,5,6,5,6,6,6,5,6,157,157,156,157,156,156,155,155,157,156,156,156,156,156,202,202,202,202,202,203,203,204,204,202,203,203,204,203,203,203,203,203,203,204,204,204,204,204,204,204,204,202,202,203,203,203,203,204,204,204,202,203,203,203,203,203,199,199,192,192,192,193,193,193,193,192,193,194,194,192,192,193,193,194,193,195,195,193,193,194,192,192,192,193,193,193,194,194,192,193,192,192,192,192,193,193,193,194,194,195,195,195,195,195,195,199,192,192,192,193,193,192,192,192,192,193,194,194,193,193,193,193,194 +,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,109,252,252,109,252,109,252,109,252,252,252,108,107,107,252,107,107,107,252,107,109,107,109,107,109,107,252,107,107,106,107,106,107,106,107,106,106,106,106,106,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,202,203,202,203,202,203,202,203,204,202,202,203,203,204,204,202,204,203,204,206,207,205,205,207,207,207,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,145,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,157,157,157,156,156,155,156,155,157,156,156,156,156,155,202,202,203,202,203,203,204,202,202,202,203,203,204,202,203,203,204,203,204,203,204,204,204,204,204,204,204,202,203,202,203,203,204,203,204,202,203,202,203,202,203,203,199,192,192,192,193,192,193,192,193,193,194,194,192,192,193,192,194,194,194,195,195,193,194,192,192,192,193,193,194,193,194,192,193,192,192,192,193,192,193,193,194,193,195,194,195,195,195,194,195,192,192,192,193,192,193,193,192,192,193,193,194,193,194,193,194,193,192 +,252,252,109,252,109,252,252,252,252,252,252,252,109,108,108,252,109,109,252,109,252,109,252,252,252,252,108,107,107,107,107,107,109,107,109,109,107,107,109,107,109,109,109,107,106,106,107,106,107,106,107,106,106,106,106,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,202,202,202,202,202,203,204,203,202,204,202,203,202,203,203,204,202,204,203,204,206,207,205,206,206,207,207,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,145,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,157,157,157,157,156,156,156,155,155,157,157,156,156,155,155,202,202,202,202,204,203,202,202,202,203,203,204,204,203,203,204,204,204,204,203,204,204,204,204,204,204,204,202,202,203,203,204,204,204,202,202,202,203,203,203,203,199,199,192,192,192,192,192,192,193,193,194,194,192,192,193,194,194,193,194,193,195,195,195,192,193,192,192,193,193,193,194,194,194,192,192,192,192,192,193,193,193,193,194,195,195,195,195,195,194,199,192,192,192,192,193,193,193,192,192,193,193,193,194,194,194,193,193,192 +,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,252,109,252,109,252,109,252,252,252,108,107,107,107,107,252,107,109,109,109,107,109,107,252,107,252,107,107,106,106,106,107,106,107,106,106,106,106,106,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,108,252,108,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,202,202,203,202,202,203,204,203,204,204,202,202,204,203,204,202,203,203,204,204,206,207,205,205,207,207,207,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,145,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,6,157,157,157,157,156,156,155,156,155,157,156,156,155,156,202,203,202,204,204,203,202,202,202,203,202,203,203,204,204,204,203,204,204,203,203,204,203,204,204,204,204,155,155,203,202,204,203,204,202,202,202,203,202,203,203,204,199,192,192,193,192,192,192,193,193,194,193,192,192,193,192,194,192,194,194,195,193,194,194,193,192,192,192,193,193,194,193,194,193,192,192,193,192,193,192,193,193,194,193,194,194,195,194,195,195,199,192,192,192,193,192,193,193,192,192,193,193,194,193,194,193,193,192,192 +,252,252,252,252,109,252,109,252,252,252,252,252,109,108,108,108,252,109,109,109,252,252,252,252,252,252,108,107,107,107,107,107,252,109,109,109,109,107,109,107,109,109,109,106,107,106,106,106,107,106,107,106,107,106,106,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,108,108,108,109,109,109,107,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,202,202,202,202,202,204,204,204,203,202,202,203,204,204,204,202,202,203,203,204,206,207,205,206,206,207,207,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,150,144,144,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,157,157,157,157,157,156,157,156,156,155,155,157,156,156,202,202,202,202,203,203,204,203,202,202,202,202,203,203,203,204,204,203,204,204,204,204,204,204,204,204,204,155,155,155,155,202,203,203,204,202,202,202,203,203,203,203,203,199,199,192,192,192,192,192,193,193,194,194,192,192,193,193,194,194,194,194,195,192,193,193,193,193,194,193,192,192,193,194,194,194,192,192,192,193,193,194,194,193,194,194,194,194,195,195,195,195,195,199,192,192,193,193,193,193,193,192,192,192,193,193,194,194,193,192,192,192 +,252,252,252,109,252,252,252,252,252,252,252,252,252,109,108,109,252,252,109,252,109,252,109,252,252,252,108,107,107,252,107,107,107,109,107,109,107,109,107,109,107,252,107,106,107,107,106,106,106,107,106,107,106,107,106,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,108,252,108,252,108,109,109,109,107,109,107,109,107,109,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,202,202,202,202,203,203,204,204,204,202,203,203,204,203,204,202,203,202,204,204,205,206,205,206,207,206,207,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,150,144,144,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,157,157,157,155,156,157,157,157,156,156,155,155,157,203,202,202,202,203,202,203,203,204,204,203,202,202,202,203,203,204,203,204,204,204,203,204,203,204,203,204,204,204,204,156,155,155,155,202,203,204,202,202,202,203,202,203,203,204,203,199,192,192,192,193,192,193,193,194,193,192,192,193,192,193,192,194,194,194,194,192,192,193,193,193,194,194,192,193,193,194,193,194,192,192,192,193,193,194,193,194,194,194,193,194,195,195,195,195,195,199,192,192,192,193,192,193,192,193,192,193,193,194,194,192,192,192,192,192 +,252,252,252,252,109,252,252,252,252,252,252,252,252,107,108,252,109,109,109,109,252,109,252,252,252,252,108,107,107,107,107,107,107,107,109,109,109,107,109,109,109,109,106,107,107,106,107,106,106,106,107,106,107,106,106,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,108,108,252,108,252,109,109,109,107,107,109,107,109,107,109,109,107,107,107,107,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,202,202,202,202,203,203,204,204,204,202,203,203,204,204,202,202,203,203,204,204,205,205,206,205,206,207,207,207,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,150,150,144,146,144,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,157,157,157,157,157,156,156,155,155,157,157,156,156,155,157,202,202,202,202,202,203,203,204,204,204,202,202,202,203,203,203,203,204,204,204,204,204,203,203,204,204,204,204,204,204,155,155,155,155,202,202,202,202,202,202,202,203,203,203,203,199,199,192,192,192,192,193,193,193,193,194,192,192,192,194,194,194,194,194,194,192,192,193,193,193,193,195,194,192,192,194,193,193,193,192,192,192,192,193,193,194,194,194,193,194,194,195,195,195,195,195,199,199,192,193,193,193,193,192,192,193,193,193,194,194,192,192,193,192,193 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,252,252,109,252,109,252,109,252,109,252,108,252,107,107,107,107,107,109,109,109,107,109,107,109,107,252,107,107,107,107,107,107,106,107,106,107,106,107,106,106,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,108,108,252,252,252,108,252,252,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,202,202,202,202,202,203,203,204,203,204,203,204,204,202,202,203,203,204,203,204,204,205,206,205,206,207,206,207,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,150,150,149,146,144,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,157,156,157,157,157,157,157,156,157,155,156,155,155,156,156,155,155,157,202,202,203,202,203,203,204,203,204,204,202,202,203,202,203,203,204,203,204,204,204,203,204,203,204,204,204,203,204,204,156,155,155,202,203,202,202,202,203,202,203,203,204,203,204,199,192,192,193,192,193,192,193,193,192,192,193,192,193,192,194,194,193,194,192,192,193,193,193,194,195,193,194,192,192,194,193,193,192,192,193,192,193,192,193,193,194,193,194,193,194,194,195,195,195,195,199,192,199,192,193,193,194,192,193,192,193,193,194,192,193,192,193,193,193 +,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,252,108,252,107,107,107,107,252,109,109,107,109,107,109,107,109,106,106,107,107,107,107,107,107,106,106,106,107,106,107,106,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,108,108,252,108,252,252,252,252,109,109,107,107,107,107,107,107,107,109,107,107,107,109,107,107,107,107,107,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,202,202,203,202,203,203,204,204,203,203,204,203,204,202,203,203,203,203,204,204,205,205,207,205,206,207,206,207,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,150,150,150,149,146,147,144,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,5,5,4,5,157,157,156,157,156,156,157,157,157,156,156,156,155,155,155,157,156,156,155,202,202,202,202,203,203,203,203,204,204,204,202,202,202,203,203,203,203,203,203,204,204,204,204,204,204,204,204,204,204,204,155,155,155,202,202,202,202,202,202,203,203,203,203,204,199,199,192,192,192,192,192,193,193,192,192,193,193,193,193,195,195,194,194,192,192,193,193,193,194,194,193,195,194,192,192,193,193,192,192,193,193,193,193,193,193,194,194,194,193,193,194,195,195,195,195,195,199,192,192,193,193,193,193,192,192,193,193,194,194,192,192,193,193,194,192 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,252,252,109,252,109,252,109,252,252,252,108,252,107,107,107,107,107,109,109,109,107,109,107,109,106,106,107,107,107,107,107,107,106,107,106,106,106,107,106,106,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,108,108,252,252,252,252,252,252,252,109,252,109,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,202,202,202,202,202,204,204,204,203,204,204,204,204,203,203,204,203,204,203,204,204,205,206,205,205,206,206,207,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,150,150,150,150,149,146,147,144,144,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,157,157,157,156,157,156,156,156,157,157,157,156,156,156,156,155,155,156,156,155,155,202,202,202,203,202,203,203,204,203,204,204,202,203,203,202,203,203,204,203,204,204,204,203,204,203,204,204,204,204,204,155,156,155,155,202,202,202,203,202,203,202,203,203,204,203,199,192,192,192,193,192,193,193,194,192,193,192,193,193,195,195,194,194,192,192,193,193,193,193,194,195,195,195,194,192,193,192,193,192,193,193,194,193,194,194,194,193,193,193,194,193,195,194,195,194,195,195,199,192,192,192,193,193,194,192,193,192,193,193,192,192,194,193,193,193,192 +,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,107,109,109,109,109,109,109,252,252,252,252,108,252,107,107,107,107,107,107,109,107,109,107,109,107,106,107,107,107,107,106,107,106,106,107,107,106,107,106,107,106,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,108,108,252,108,252,252,252,252,252,252,252,109,109,107,109,107,107,107,107,109,107,107,107,109,107,107,107,107,107,107,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,202,202,202,202,202,203,204,204,203,203,204,204,203,204,202,203,203,204,204,204,204,205,205,206,205,205,206,206,207,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,150,148,148,148,146,146,147,147,147,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,5,4,4,4,157,157,157,157,157,156,156,156,157,157,156,155,157,156,156,155,155,155,156,156,155,156,202,202,202,202,203,203,203,203,204,204,204,202,202,203,203,203,203,203,204,204,204,204,204,204,204,204,204,204,204,204,156,155,155,155,202,202,202,202,203,203,203,203,203,203,199,199,192,192,192,192,193,193,193,199,193,194,194,194,195,195,194,194,192,192,194,193,193,193,194,195,195,193,195,195,194,192,193,193,194,192,192,192,193,193,193,193,193,193,193,193,194,195,195,195,195,194,195,199,192,199,193,193,193,192,192,192,193,193,192,192,193,193,193,194,194,192 +,252,252,252,252,252,252,252,109,252,252,252,252,252,252,107,109,107,252,109,252,109,252,109,252,109,252,252,107,107,107,107,252,107,107,107,109,107,109,107,106,107,106,107,252,107,107,106,106,106,107,107,107,106,107,106,106,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,252,108,108,252,252,252,252,252,252,252,252,109,109,109,107,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,202,202,202,202,203,202,204,204,203,203,204,204,204,204,203,202,204,203,204,204,205,204,205,206,207,205,205,206,207,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,150,150,149,149,149,149,149,144,147,4,5,4,5,4,5,4,5,4,5,4,5,4,5,150,145,145,145,145,145,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,157,157,157,157,156,157,156,157,156,156,155,157,156,157,155,156,155,155,156,156,155,202,202,202,202,203,202,203,203,204,203,204,204,202,202,203,203,204,203,204,203,204,204,204,204,204,203,204,204,204,204,204,155,156,155,155,202,202,202,203,202,203,202,203,203,204,199,192,192,192,192,193,192,193,199,193,193,194,193,195,194,195,195,192,193,192,193,194,193,194,193,195,195,195,193,195,194,192,194,193,192,193,192,193,192,193,192,193,193,194,193,194,194,195,195,195,195,194,195,199,192,192,192,193,193,192,192,193,193,194,192,193,193,194,193,194,192,192 +,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,107,109,107,109,109,252,109,252,109,252,252,252,107,107,107,107,107,107,107,107,107,109,107,109,106,107,106,107,107,107,107,106,106,107,107,107,107,107,106,107,106,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,108,108,108,252,108,252,252,252,252,252,252,252,252,109,109,109,107,109,109,109,107,109,109,107,107,107,109,107,107,107,107,107,107,107,107,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,202,202,202,203,203,202,204,204,203,203,203,204,204,202,202,203,202,204,204,204,204,205,205,206,205,205,205,206,206,207,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,150,150,150,150,150,150,150,145,144,147,144,144,4,4,4,4,4,4,4,4,4,4,4,4,4,150,149,144,146,147,147,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,157,157,157,157,157,156,157,156,156,155,155,156,156,156,156,155,155,155,156,155,156,202,202,202,202,202,203,203,203,203,204,204,204,202,203,203,204,203,204,203,204,204,204,204,204,204,204,204,204,204,204,204,155,155,155,155,202,202,202,202,203,203,203,203,204,199,199,192,192,192,193,193,193,192,193,193,193,193,195,195,195,195,195,192,192,193,194,194,193,193,195,195,195,195,195,195,194,192,193,192,192,192,193,193,193,193,194,193,194,194,194,194,194,195,195,194,195,194,195,199,192,199,193,193,193,192,193,193,193,193,192,192,193,193,193,192,192,192 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,252,109,252,109,252,109,252,109,107,107,252,107,107,107,107,107,109,107,109,106,107,107,109,107,252,107,107,107,107,106,107,106,107,107,107,106,106,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,109,109,109,109,109,107,109,107,109,107,109,107,107,107,107,107,107,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,202,202,202,202,202,203,204,204,203,203,204,202,203,204,203,203,202,203,204,204,205,205,213,205,207,205,213,206,214,207,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,150,232,150,232,149,149,232,149,144,232,147,232,144,232,4,4,4,4,4,4,4,4,4,4,4,4,150,148,148,148,148,148,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,157,157,157,157,157,156,157,157,157,156,156,155,157,156,156,155,156,155,155,156,155,202,202,202,203,202,203,203,203,203,204,203,204,204,202,202,203,203,204,203,204,203,204,204,204,203,204,203,204,204,204,204,204,155,155,155,203,202,202,202,203,202,203,203,204,203,199,192,192,192,193,192,193,192,199,192,193,193,194,195,195,194,195,192,192,192,194,193,194,193,195,193,195,193,195,193,195,194,193,193,192,192,193,193,194,194,193,192,193,193,194,193,194,194,195,195,195,194,195,195,199,192,192,192,193,193,192,192,193,192,192,192,193,193,194,192,192,192,192 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,109,109,109,252,109,252,252,252,107,107,107,107,107,107,107,107,107,109,107,106,106,107,107,252,107,252,107,107,107,106,106,107,107,107,107,107,106,106,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,107,109,109,107,107,107,109,107,109,107,107,107,107,107,107,107,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,202,202,202,202,203,202,203,204,203,203,203,202,203,204,204,204,202,202,204,204,204,204,205,205,206,205,205,205,206,206,206,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,150,150,145,145,145,145,145,145,145,4,4,4,4,150,150,150,150,149,150,149,149,144,144,144,144,147,147,144,144,4,4,4,4,150,145,145,145,145,145,4,4,150,149,146,147,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,157,157,157,157,156,156,157,157,156,156,155,155,156,156,156,156,155,155,155,156,155,202,202,202,202,203,203,203,203,203,203,204,204,204,202,203,203,204,203,204,204,204,204,204,203,204,204,204,204,204,204,204,204,155,155,155,202,202,202,203,203,203,203,203,203,199,199,192,192,192,192,193,193,192,199,193,193,194,195,195,195,195,195,192,192,193,193,194,194,193,193,193,193,195,195,195,195,194,192,193,193,194,193,193,192,192,192,193,193,193,193,194,194,194,194,195,195,195,195,195,199,192,199,193,193,193,192,192,192,193,192,193,193,194,192,192,192,193,193 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,109,252,109,252,109,252,109,252,109,107,107,107,107,252,107,252,107,252,107,107,106,107,107,109,107,252,107,107,107,107,106,107,106,107,107,107,106,106,106,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,108,252,108,108,252,108,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,107,109,109,109,107,109,107,109,107,107,107,107,107,107,107,107,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,202,202,202,202,202,202,202,204,204,203,202,203,203,204,204,204,203,204,203,204,204,205,205,205,205,213,206,205,205,206,206,207,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,150,150,150,149,144,146,146,147,147,4,3,4,150,150,150,150,150,150,145,145,145,146,146,146,146,146,146,147,147,147,3,4,3,150,149,232,146,232,147,4,3,150,149,146,150,150,150,145,145,145,145,145,145,4,3,4,3,4,3,4,3,4,3,4,3,157,157,157,157,156,156,157,156,156,155,155,156,157,156,156,155,156,155,155,156,155,202,203,202,203,202,203,202,203,202,204,203,204,202,203,202,203,204,204,203,204,204,204,203,204,203,204,203,204,204,204,204,204,155,155,155,202,202,203,202,203,203,204,203,204,199,192,192,192,192,193,192,199,199,193,193,194,193,195,194,195,195,193,192,193,193,194,194,195,195,195,193,195,193,195,195,195,195,194,194,193,193,193,192,193,192,193,192,193,193,194,193,194,193,194,194,195,195,195,195,199,192,193,192,193,193,194,192,193,192,192,192,192,192,193,192,193,192,193 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,109,252,109,109,109,252,252,252,107,107,107,107,107,107,107,107,107,107,107,107,106,107,107,109,107,252,107,107,107,107,106,107,107,107,107,107,106,106,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,108,108,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,107,107,109,109,107,109,109,107,107,107,107,107,107,107,107,107,107,107,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,202,202,202,202,203,202,203,203,204,202,203,203,204,202,204,204,204,204,204,204,204,204,205,205,205,205,213,205,213,206,206,206,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,4,4,4,3,150,150,150,149,144,146,146,147,147,4,4,3,150,150,232,149,232,149,232,149,232,144,232,146,232,146,232,147,232,147,150,145,145,145,145,145,145,145,145,3,4,150,149,146,150,149,149,149,144,146,146,147,147,4,4,3,4,4,4,3,4,4,4,3,4,157,157,157,157,156,157,157,157,156,155,155,157,156,156,156,156,155,155,155,155,202,202,202,202,202,203,203,203,202,204,203,204,204,202,202,203,203,204,203,204,204,204,203,204,204,204,204,204,204,204,204,204,155,155,155,155,202,202,202,203,203,203,203,204,199,199,192,192,199,199,199,199,192,193,193,193,193,194,195,195,195,195,192,193,193,193,193,195,195,193,193,195,195,195,195,195,195,195,194,194,193,193,192,192,192,192,192,193,193,193,193,194,194,194,194,195,195,195,195,195,199,192,192,193,193,193,193,192,192,192,192,192,192,192,192,193,192,193,192 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,252,109,252,109,252,109,252,109,107,107,107,107,107,107,252,107,252,107,107,106,107,107,109,107,252,107,107,107,107,106,107,106,107,106,107,106,107,106,106,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,108,108,252,108,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,109,252,109,109,109,109,107,107,107,109,107,109,109,109,107,109,107,107,107,107,107,107,107,107,107,107,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,202,203,202,202,202,202,202,203,203,202,202,204,204,204,203,204,203,204,203,204,204,215,205,205,205,215,205,213,205,213,206,214,206,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,149,149,148,148,148,148,148,3,4,3,4,150,150,232,149,232,149,232,149,232,144,232,146,232,146,232,147,232,147,149,144,144,144,149,149,149,149,149,145,145,150,149,146,150,149,149,149,144,146,146,147,147,4,3,4,3,4,3,4,3,4,3,4,157,157,157,157,157,157,156,157,156,156,155,155,156,157,156,156,155,156,155,157,155,203,202,202,202,203,202,203,202,204,203,204,204,204,202,203,203,204,204,204,203,204,204,204,203,204,204,204,203,204,203,204,155,155,155,155,155,202,202,203,203,204,203,204,203,199,199,193,199,192,192,192,192,193,192,193,193,194,193,195,195,195,192,193,193,195,193,195,195,193,192,193,193,195,193,195,195,195,193,194,193,193,192,192,192,192,192,193,193,194,193,194,193,194,194,195,195,195,195,195,199,199,192,199,192,193,193,194,192,193,192,193,192,193,192,193,192,193,193,193 +,108,252,252,252,252,252,252,252,109,252,252,252,252,252,252,107,109,107,109,109,109,109,252,109,252,252,252,107,107,107,107,107,107,107,252,107,107,107,107,107,107,107,252,107,252,107,107,106,106,106,107,106,107,107,107,107,106,106,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,108,252,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,107,107,107,107,109,109,109,107,109,107,109,107,107,107,107,107,107,107,107,107,107,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,202,202,202,202,202,202,202,202,203,203,202,203,203,204,203,204,204,204,204,204,204,205,204,205,205,205,205,205,213,205,205,213,206,206,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,3,4,3,4,3,4,3,3,150,150,149,144,146,146,147,148,148,150,150,150,150,150,150,150,150,150,149,149,144,144,144,146,146,146,147,147,147,149,146,146,144,146,144,144,144,149,149,149,150,149,146,232,150,148,148,148,148,148,148,4,3,4,3,3,3,4,3,4,3,4,157,157,157,157,157,157,157,157,157,157,156,156,155,157,156,156,156,156,155,155,157,155,202,202,202,202,202,203,202,203,204,204,204,203,203,202,202,203,204,204,204,204,204,203,203,204,204,204,204,204,204,156,156,155,155,155,155,155,202,202,202,203,203,204,204,199,199,199,199,192,192,193,192,192,192,193,193,193,193,195,195,195,195,192,193,193,193,195,195,193,193,193,193,195,195,195,195,195,195,194,194,193,192,192,192,192,192,192,192,193,193,194,194,194,194,195,195,195,195,195,199,199,192,192,192,192,192,193,193,194,192,192,192,192,192,193,193,193,193,193,193 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,109,252,109,252,109,252,109,252,109,107,107,107,107,252,107,252,107,252,107,107,106,107,107,252,107,252,107,107,107,106,106,107,106,107,106,107,107,107,106,106,106,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,108,108,252,108,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,107,109,107,109,107,109,109,109,107,109,107,107,107,107,107,107,107,107,107,107,107,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,202,202,203,202,203,202,202,202,203,203,202,202,204,204,204,203,204,203,204,203,204,204,215,205,215,205,215,205,213,206,215,206,214,206,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,150,150,149,144,146,146,147,144,144,144,144,144,144,144,144,144,144,144,147,149,144,144,144,146,146,146,147,147,147,149,146,232,146,232,146,232,146,232,144,144,150,149,146,147,150,149,149,144,146,146,147,3,4,3,4,3,4,3,4,3,4,157,157,157,157,157,157,157,156,157,157,156,156,155,155,156,157,156,156,155,156,155,157,202,202,202,203,202,203,202,203,204,204,204,203,202,203,202,203,203,204,203,204,204,204,203,204,203,204,204,204,203,157,155,156,155,155,155,155,155,202,202,203,203,204,203,199,199,199,199,193,192,193,192,192,192,193,193,194,193,194,195,195,195,195,192,193,193,195,193,195,195,193,192,193,193,195,193,195,195,195,194,193,192,193,192,193,192,193,192,193,192,193,193,194,195,195,195,195,195,195,199,199,192,193,199,193,192,193,193,194,193,194,194,192,192,193,192,193,192,193,193,193 +,108,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,109,107,109,109,252,109,252,109,252,252,252,107,107,107,107,107,107,107,107,107,107,107,107,106,107,107,252,107,107,107,106,106,106,106,107,106,107,107,107,106,106,106,106,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,108,108,108,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,107,107,107,107,109,109,109,107,109,107,107,107,107,107,107,107,107,107,107,107,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,202,202,202,202,202,202,202,202,203,202,203,203,204,204,204,203,203,204,204,204,204,205,205,205,205,213,205,205,205,214,206,205,205,214,206,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,150,150,145,145,145,145,145,146,150,150,149,144,146,232,147,144,144,144,144,144,144,144,144,144,144,144,144,147,149,144,144,144,146,146,147,147,147,149,147,147,147,147,147,147,147,147,147,147,150,149,146,147,150,149,149,144,146,232,147,3,3,3,3,3,3,3,3,3,3,157,157,157,157,157,157,157,156,157,156,156,156,155,155,157,156,156,156,156,155,155,156,202,202,202,202,202,202,203,203,204,202,202,202,203,203,202,203,204,203,204,204,203,203,203,203,204,204,204,204,204,156,156,155,155,155,155,155,155,202,203,203,204,204,204,199,199,192,192,192,193,193,192,192,193,193,193,193,194,194,195,195,195,195,192,193,193,195,195,192,192,192,193,193,193,193,195,195,195,194,193,192,192,192,192,192,193,193,192,192,193,193,194,195,195,195,195,195,199,199,192,192,193,193,193,193,193,192,193,193,194,194,192,192,193,192,193,193,193,193,193,193 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,252,109,252,109,252,109,252,109,107,107,252,107,107,107,252,107,252,107,107,106,107,107,107,107,107,107,107,106,106,106,107,106,107,107,107,106,107,106,106,106,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,108,108,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,252,107,109,107,252,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,107,107,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,202,202,202,203,202,203,202,202,202,203,202,203,203,204,204,204,203,204,203,204,203,215,204,215,205,215,205,215,205,213,213,214,206,214,206,206,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,4,3,3,3,150,150,150,149,144,144,146,147,150,150,149,144,146,146,147,144,144,232,144,232,144,232,144,232,144,144,144,144,147,147,144,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,150,150,149,149,144,146,146,147,3,4,3,3,3,4,4,4,4,4,157,157,157,157,157,157,156,156,156,157,156,156,155,155,156,157,156,156,155,156,155,157,202,203,202,202,202,203,203,204,202,202,202,203,203,204,203,204,204,204,204,203,203,204,203,204,203,204,203,204,156,157,155,156,155,155,155,155,202,203,202,203,203,204,199,199,199,193,192,193,192,193,192,193,192,193,193,194,193,194,195,195,195,192,192,193,193,195,195,192,192,193,192,193,193,195,195,195,194,193,192,192,192,193,192,193,192,193,193,192,194,194,193,195,195,195,195,199,199,192,199,193,199,193,192,193,192,193,194,194,192,193,192,193,192,193,192,193,193,194,193,193 +,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,252,252,252,107,107,107,107,107,107,107,107,107,107,107,107,106,107,107,252,107,107,107,106,106,107,106,107,107,107,106,107,106,106,106,106,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,108,252,108,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,107,107,109,109,109,107,109,107,109,107,107,107,107,107,107,107,107,107,107,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,202,202,202,202,203,202,202,202,203,203,202,203,203,204,203,203,204,203,204,204,204,204,205,205,215,205,205,205,213,205,213,213,213,213,214,206,206,206,3,3,215,206,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,150,150,150,149,149,144,146,147,150,150,232,144,146,146,147,144,144,144,144,232,144,232,144,144,144,144,144,144,144,144,147,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,149,232,144,146,152,152,153,153,153,153,153,153,154,153,154,154,157,157,157,157,157,156,156,157,157,156,156,155,155,155,157,156,156,156,156,155,155,202,202,202,202,202,203,203,204,202,202,202,202,202,203,203,204,204,204,204,204,203,204,203,204,204,204,204,204,204,157,156,156,155,155,155,155,155,202,202,203,203,204,199,199,199,192,192,193,192,193,193,192,192,193,193,193,193,194,194,195,194,195,192,192,193,193,193,195,195,192,193,193,193,195,195,195,194,193,192,192,192,192,192,193,193,193,194,194,193,194,195,195,195,195,195,199,192,192,192,193,193,193,193,193,192,193,193,192,192,192,192,193,193,193,193,193,193,193,193,193,193 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,108,252,107,107,107,252,107,252,107,252,107,107,107,107,107,107,107,107,107,107,106,106,106,107,107,107,106,106,106,106,106,106,106,106,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,108,108,108,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,107,107,252,109,109,107,109,107,109,107,109,107,107,107,107,107,107,107,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,202,202,202,203,202,204,202,202,202,203,202,203,204,204,203,204,203,204,203,204,204,215,204,215,205,215,205,215,205,215,205,213,206,214,206,206,206,215,205,213,206,214,206,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,148,148,148,148,148,148,148,150,150,149,144,146,146,147,144,144,144,144,144,144,144,144,144,144,144,232,144,144,144,144,147,146,146,232,146,146,146,232,146,146,146,232,146,146,146,146,146,232,146,146,146,146,149,149,152,152,157,156,157,157,156,152,152,153,153,153,153,154,157,157,157,157,157,157,156,157,156,157,156,156,155,157,155,157,156,156,155,156,155,202,202,203,202,203,203,204,204,203,202,202,202,203,203,204,204,204,203,204,204,204,203,204,203,204,203,204,204,204,156,156,155,156,155,155,155,155,202,203,203,204,204,199,199,193,192,193,192,193,192,192,192,193,192,193,193,194,193,194,195,195,192,192,192,193,192,193,193,195,195,193,193,195,195,195,195,194,192,193,192,192,192,193,192,193,194,194,194,194,193,195,195,195,195,199,199,192,192,193,192,193,192,193,192,193,192,192,192,193,192,193,192,193,192,193,193,194,193,194,194,193 +,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,252,252,108,252,107,107,107,107,107,107,107,107,107,107,107,106,107,106,107,107,107,106,106,106,107,107,107,106,106,106,107,106,106,106,106,106,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,108,108,108,108,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,107,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,202,202,202,202,202,204,202,203,202,202,203,203,204,202,203,203,203,203,204,204,204,204,215,205,205,205,213,205,205,205,215,205,205,205,213,205,205,205,213,213,214,206,206,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,3,2,3,3,150,150,149,149,149,149,149,150,150,149,144,146,232,147,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,147,147,147,147,147,147,147,147,147,147,147,146,146,146,232,146,232,146,232,146,146,149,157,157,156,156,157,157,157,156,155,156,155,155,152,152,157,157,157,157,157,157,156,156,157,156,156,156,155,157,156,155,156,156,156,156,155,202,202,202,202,202,202,204,204,203,202,203,203,204,204,204,204,203,203,204,204,204,203,204,204,204,204,204,204,204,204,157,156,156,155,155,155,155,155,203,203,204,204,199,199,192,192,192,192,192,192,193,192,192,192,193,193,193,193,194,194,195,195,192,192,192,192,193,193,193,193,195,195,193,193,195,195,194,194,192,192,192,192,192,192,193,193,194,194,194,195,195,195,195,195,199,199,192,192,193,192,193,193,193,193,192,192,192,192,192,192,193,193,193,193,193,193,193,193,193,193,193,193 +,252,252,108,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,109,109,109,252,109,252,252,252,108,252,107,107,107,107,107,252,107,252,107,107,107,107,106,107,107,107,107,106,106,107,106,107,107,106,106,107,106,106,106,106,106,106,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,108,252,108,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,107,109,252,107,109,107,109,107,109,107,109,107,109,107,107,107,107,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,202,202,202,203,202,203,202,202,202,202,203,204,204,204,203,204,203,204,203,204,203,215,204,215,205,215,205,215,205,215,205,213,205,213,205,215,205,213,205,213,205,214,206,206,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,150,232,149,149,149,149,149,150,150,149,144,146,146,147,144,144,113,114,114,114,114,114,114,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,147,147,146,146,146,146,146,146,146,146,157,157,156,156,155,157,157,157,156,155,156,156,155,156,156,157,157,157,157,157,156,156,157,157,156,156,155,156,157,156,155,157,156,156,155,156,202,202,202,203,202,203,203,202,202,203,203,204,203,204,203,204,203,204,204,204,203,204,203,204,203,204,204,204,204,204,156,157,155,156,155,155,155,155,203,203,203,204,199,199,192,193,192,193,192,193,193,192,192,193,192,193,193,194,194,194,194,195,192,192,192,193,193,195,193,195,193,195,193,195,193,194,194,192,192,193,192,192,192,193,192,194,194,194,194,195,194,195,194,195,199,199,192,193,192,193,192,193,193,193,192,193,192,193,192,193,192,193,192,193,193,194,193,194,193,194,193,194 +,252,252,108,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,109,109,109,252,252,252,252,108,252,107,107,107,107,107,107,252,107,107,107,107,107,107,106,107,107,107,106,106,106,107,107,106,106,107,106,107,106,106,106,106,106,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,108,108,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,109,107,109,107,109,107,109,109,109,109,109,107,107,107,107,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,202,202,202,202,202,204,203,202,202,202,203,203,204,203,203,203,204,204,204,204,215,204,215,205,215,205,213,205,215,205,215,205,215,205,215,205,215,205,213,206,215,214,206,206,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,150,150,149,149,149,149,149,150,150,232,144,146,146,147,144,113,113,113,113,113,113,113,114,114,114,114,114,114,114,114,113,113,114,114,114,114,114,144,144,144,144,144,144,144,147,146,146,146,146,146,157,157,157,157,156,156,155,157,157,157,156,155,156,155,155,156,156,157,157,157,157,157,157,156,157,157,156,156,156,155,157,156,156,155,156,156,156,155,202,202,203,203,204,204,203,202,202,203,203,203,204,204,203,203,204,204,204,203,204,203,204,204,204,204,204,204,204,157,157,156,156,155,155,155,155,202,203,203,204,199,199,192,192,192,192,192,193,193,193,192,192,192,193,193,193,193,194,194,195,195,192,192,192,192,193,193,195,195,195,193,195,193,195,194,194,192,192,192,192,193,192,192,193,193,194,194,195,195,195,194,195,195,199,192,192,192,193,192,193,193,193,193,192,192,192,192,192,192,193,192,193,193,193,193,193,193,193,193,193,193 +,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,108,109,252,109,252,108,252,107,107,107,252,107,252,107,252,107,252,107,106,107,107,107,107,107,106,106,107,106,107,106,106,106,107,106,106,106,106,106,106,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,107,109,107,109,252,107,109,107,252,107,109,107,109,107,109,107,107,107,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,202,202,202,203,202,203,204,202,202,203,203,204,204,204,203,204,204,204,205,215,205,215,205,215,205,213,205,215,205,215,205,213,205,213,205,213,205,213,205,213,206,214,214,206,206,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,150,150,149,232,149,149,149,150,150,149,144,146,146,147,144,115,115,115,115,116,115,115,115,116,115,113,113,113,113,113,113,113,113,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,157,157,157,157,156,156,155,157,157,157,156,155,155,156,155,156,156,157,157,157,157,157,156,156,157,157,156,156,155,157,156,156,155,155,156,156,155,202,202,203,202,203,203,204,202,202,202,203,203,204,204,203,203,204,203,204,199,192,193,194,203,204,203,204,203,204,204,157,156,156,155,156,155,155,202,203,203,204,202,199,199,192,192,193,192,193,192,193,192,192,192,193,192,193,193,194,193,194,195,195,192,192,192,193,192,195,193,195,195,195,193,195,194,194,192,192,192,193,192,193,192,193,192,193,194,195,194,195,195,195,193,195,199,192,192,193,192,193,192,193,193,193,192,193,192,192,192,193,192,193,192,193,193,194,193,192,193,194,194,193 +,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,109,252,107,252,252,252,252,108,252,107,107,107,107,107,107,107,107,252,107,252,107,106,107,106,107,106,106,107,106,107,107,106,106,107,106,107,106,106,106,106,106,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,107,107,107,109,109,107,107,107,109,109,109,107,109,107,107,107,107,107,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,202,202,202,202,203,202,203,202,204,202,203,203,204,203,204,204,215,205,215,215,215,205,213,215,215,205,215,215,215,205,215,215,215,205,215,215,215,205,213,213,213,205,206,214,206,206,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,150,145,147,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,150,150,149,149,149,149,149,150,150,113,113,113,113,113,116,115,116,115,116,116,116,116,116,116,116,116,117,117,117,117,117,117,116,116,113,113,113,113,113,114,114,114,114,114,114,114,114,114,114,114,157,156,157,156,156,156,155,157,155,157,156,155,156,156,155,156,156,157,157,157,157,157,156,155,155,157,156,156,156,157,157,156,156,155,156,155,156,202,202,202,203,203,203,203,202,202,203,203,204,204,204,204,204,204,203,199,192,192,193,193,194,204,204,204,204,204,204,157,157,156,156,155,155,203,203,203,204,202,199,199,192,192,192,192,193,193,193,193,192,192,192,192,193,193,193,193,194,194,195,195,192,192,192,192,193,193,193,195,195,193,195,195,194,194,192,192,192,192,192,193,192,192,192,192,193,194,195,195,195,195,195,199,199,192,192,192,193,193,193,193,193,193,192,192,192,192,192,192,193,193,193,192,193,193,193,193,194,194,194,193 +,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,252,252,252,108,252,107,252,107,107,107,252,107,252,107,252,107,252,107,106,107,106,106,106,106,107,107,107,106,107,106,107,106,106,106,106,106,106,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,252,109,107,107,252,109,109,109,252,109,252,107,109,107,109,107,109,107,107,107,107,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,202,202,203,202,203,202,203,203,202,202,202,202,204,204,204,204,215,204,215,205,215,205,215,205,213,205,215,205,215,205,215,214,214,205,2,205,213,205,215,205,213,206,214,205,206,214,206,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,150,144,147,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,113,113,113,113,113,113,113,113,115,116,115,116,115,116,116,116,116,116,116,117,116,117,116,117,116,117,117,117,116,117,116,117,116,117,116,117,116,117,116,113,113,113,113,113,113,113,113,113,113,157,157,156,157,157,156,156,155,157,157,157,155,155,156,156,155,155,156,157,157,157,157,157,156,156,155,157,156,156,155,157,156,156,155,156,155,202,202,202,202,203,203,204,203,202,202,203,202,203,203,204,204,204,204,199,199,192,192,193,193,194,193,194,203,204,204,204,204,204,156,157,155,156,192,194,194,204,204,203,199,192,199,193,192,193,192,193,192,193,192,193,192,193,193,194,193,194,194,194,195,192,192,193,192,193,193,195,193,195,195,195,193,194,194,192,192,192,192,192,192,192,192,193,192,193,193,195,195,195,194,195,195,199,192,193,192,193,192,193,192,193,193,194,192,193,192,193,192,193,192,192,192,193,193,194,193,194,193,194,193,193 +,252,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,109,109,109,108,252,252,252,252,252,252,107,107,107,107,107,107,252,107,252,107,252,107,252,107,106,107,106,106,107,106,107,107,106,106,107,106,107,106,106,106,106,106,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,252,108,252,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,252,109,252,107,107,252,107,109,107,109,252,109,252,107,252,252,109,109,107,107,107,107,107,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,202,202,202,202,202,203,202,202,204,202,203,202,204,204,204,215,204,215,215,215,205,213,215,213,215,215,215,215,213,215,213,214,214,215,2,2,205,215,215,215,215,213,213,215,213,206,214,206,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,150,144,147,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,113,113,115,115,115,115,115,115,115,115,115,116,115,116,116,116,116,116,116,116,116,116,116,117,117,117,117,117,117,116,116,116,116,116,116,117,116,117,116,117,117,117,117,117,117,117,117,117,117,117,117,117,157,157,156,157,156,156,156,157,157,156,155,155,156,156,155,155,155,157,157,157,157,157,156,156,155,155,156,157,155,156,157,157,156,156,155,202,202,202,202,202,202,203,203,204,202,202,202,203,203,203,204,204,199,199,192,192,192,193,193,193,193,194,194,204,204,204,204,204,204,157,156,192,192,193,193,194,194,194,199,199,192,192,192,193,193,194,192,193,193,192,192,193,193,193,193,194,194,194,195,195,192,192,192,193,193,193,193,195,195,195,193,194,194,194,192,192,192,192,192,193,192,192,193,193,195,195,194,195,195,195,195,195,199,192,192,193,192,193,193,193,193,193,193,192,192,192,192,192,192,192,192,193,193,193,193,194,194,194,193,194,194 +,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,109,252,252,252,252,107,107,252,107,252,107,252,107,252,107,252,107,252,107,106,107,106,107,107,107,107,106,106,106,107,106,106,106,106,106,106,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,107,107,252,109,252,109,107,109,252,109,252,252,252,252,252,107,109,107,107,107,107,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,202,202,203,202,203,202,202,203,204,203,204,203,204,203,204,204,215,215,215,205,215,205,213,205,215,205,215,205,213,213,214,214,2,2,2,205,213,205,213,205,213,205,213,213,215,214,206,206,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2,150,144,147,2,1,2,2,2,1,2,1,2,1,2,2,2,1,2,1,2,113,113,113,116,113,113,113,115,115,117,117,117,117,117,116,117,116,117,117,116,115,116,116,117,116,117,116,117,116,117,116,116,116,117,116,117,116,117,116,117,116,117,116,117,116,117,116,117,116,117,116,117,116,117,117,117,117,117,117,157,157,156,157,157,156,156,157,157,156,156,155,156,155,156,155,155,157,157,157,157,157,157,156,156,155,157,156,155,157,157,156,156,155,202,202,202,202,202,202,203,202,203,202,202,202,203,202,203,203,204,199,199,192,192,192,193,193,193,193,194,193,194,194,204,204,204,204,204,192,192,192,193,193,194,193,194,193,199,192,199,192,193,192,194,194,193,192,193,192,193,192,193,193,194,193,194,194,195,195,193,192,193,192,193,193,195,195,195,193,195,193,194,192,193,192,192,192,193,192,192,192,193,193,195,195,195,194,195,194,195,193,199,192,193,192,193,192,193,193,194,193,194,192,193,192,192,192,192,192,193,192,193,193,194,193,194,194,194,194,194 +,252,252,252,252,252,252,108,108,252,252,252,252,252,252,252,252,252,252,109,109,108,108,252,109,252,252,252,252,252,107,107,107,107,107,107,107,252,107,252,107,252,107,252,107,106,107,252,107,107,107,106,106,107,106,107,106,106,106,106,106,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,252,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,252,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,107,107,107,107,107,107,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,202,202,202,202,203,203,203,202,202,204,203,202,204,204,204,204,215,204,215,215,215,215,213,215,215,215,213,205,213,213,213,213,2,2,2,1,215,215,215,215,213,213,213,205,213,213,214,214,206,214,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,150,144,147,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,115,115,116,117,115,115,115,115,116,116,117,117,117,116,117,117,117,117,116,116,117,117,117,116,117,117,116,116,117,117,117,116,116,116,116,116,117,116,116,116,117,116,116,116,117,117,117,116,117,117,117,117,117,117,117,117,117,117,117,157,157,156,157,156,156,155,157,156,156,155,155,156,156,155,156,155,157,157,157,157,157,156,156,155,155,156,156,155,157,157,156,156,156,202,202,202,202,202,202,202,203,202,202,202,203,203,203,203,204,199,192,192,192,192,193,193,193,193,193,193,194,194,194,194,204,204,192,192,193,193,193,193,193,194,194,194,199,199,192,192,193,192,193,193,194,193,193,192,192,192,193,193,193,193,194,194,194,194,195,192,192,192,193,193,195,195,193,193,195,194,194,192,192,192,193,192,192,192,192,192,193,194,193,194,195,194,195,195,195,195,199,199,192,192,192,192,193,193,193,193,194,194,192,192,192,192,192,192,192,192,193,193,194,194,194,194,193,194,194,193 +,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,109,109,108,252,108,252,252,252,252,252,252,107,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,106,107,252,107,252,106,106,106,107,106,107,106,106,106,106,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,108,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,107,107,107,252,109,252,109,252,109,252,109,252,109,252,252,252,107,107,107,109,107,107,107,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,202,203,202,203,202,203,202,202,202,203,204,204,203,204,203,204,204,215,215,215,215,215,205,215,205,215,205,213,213,214,213,214,1,2,1,2,215,215,205,215,205,213,205,213,213,214,205,206,214,206,214,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,150,149,149,144,147,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,115,115,116,117,115,115,115,116,116,117,117,117,116,117,116,117,117,117,116,116,116,117,116,117,117,117,116,117,117,116,117,116,116,117,116,117,116,117,116,117,113,113,113,114,113,114,114,114,114,114,114,114,114,114,114,114,114,114,157,157,156,156,157,157,156,156,157,157,156,156,155,156,156,156,156,155,157,157,157,157,157,157,155,155,156,156,155,155,156,157,156,156,155,203,202,202,202,203,202,202,202,202,202,202,202,203,203,204,199,192,192,192,192,193,192,193,193,194,193,194,193,194,194,194,192,192,192,193,193,193,193,194,193,194,193,194,199,192,192,192,192,193,193,194,194,193,192,192,192,193,192,193,193,194,193,194,194,194,195,193,193,192,193,195,192,195,193,195,193,194,194,192,192,193,192,192,192,193,192,193,192,195,193,195,195,195,194,195,195,195,192,192,192,193,192,193,193,194,193,194,192,194,192,193,192,193,192,193,192,193,192,193,193,194,193,194,194,194,193,193 +,252,252,252,252,252,252,108,108,109,252,252,252,252,252,252,252,252,252,109,109,108,108,252,109,252,252,252,252,252,252,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,107,107,106,106,106,106,107,106,106,106,106,106,1,2,1,2,1,2,1,2,1,2,1,2,1,2,108,252,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,107,252,109,109,109,109,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,107,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,202,202,202,202,203,203,202,203,204,202,204,203,204,204,204,204,204,215,215,215,215,215,213,215,215,215,215,213,213,213,214,214,2,1,2,1,2,215,215,215,215,215,215,215,213,213,215,214,214,206,214,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,150,149,149,149,144,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,115,115,115,116,117,115,115,116,115,116,116,117,117,116,116,117,117,117,116,116,116,116,116,117,117,117,117,117,117,117,115,116,117,113,113,113,113,113,113,113,113,113,116,116,116,116,116,116,116,116,116,116,116,116,116,117,117,117,117,157,157,156,156,157,156,156,157,157,156,156,155,155,156,156,155,156,157,157,157,157,157,157,156,155,156,156,156,156,155,157,156,156,156,156,202,202,202,202,202,202,202,202,202,203,202,202,202,203,203,199,192,192,192,193,193,193,193,193,193,194,194,194,194,194,192,192,192,193,193,193,193,193,193,194,194,194,199,192,199,192,192,193,193,193,194,194,193,192,192,193,192,193,193,193,193,194,194,194,194,195,192,193,192,195,193,193,193,195,195,194,194,192,192,192,192,192,192,192,192,193,193,194,194,195,195,194,194,195,195,195,195,192,192,192,192,193,193,193,193,194,192,193,193,194,192,192,192,192,192,193,193,193,193,193,193,194,194,194,193,194,193 +,252,252,252,252,252,108,108,252,108,252,252,252,252,252,252,252,252,252,109,252,107,252,108,252,108,252,252,252,252,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,106,107,106,106,107,106,106,106,106,2,1,2,1,2,1,2,1,2,1,2,1,2,1,252,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,107,107,107,107,252,109,252,109,252,109,252,252,252,252,252,107,107,107,109,107,109,107,107,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,202,202,203,202,203,202,203,203,202,204,202,203,204,203,204,203,204,204,204,215,215,215,213,215,215,215,213,215,213,213,214,213,214,1,2,1,2,1,215,215,215,215,213,215,213,215,213,205,214,213,214,206,214,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,115,115,112,113,113,113,2,1,2,1,2,1,2,1,2,1,2,1,2,1,115,115,115,117,115,115,115,115,116,116,117,117,116,116,117,117,117,117,116,116,117,116,117,117,117,116,117,117,115,115,116,116,115,117,115,115,116,115,116,116,117,116,117,116,117,157,151,152,152,115,116,115,116,116,116,116,117,116,117,157,157,156,155,157,157,156,157,156,156,155,156,155,156,156,157,157,157,157,157,157,157,156,155,156,157,156,156,155,156,155,157,156,156,202,202,202,202,202,202,202,202,202,203,202,202,202,204,204,199,192,193,192,193,192,193,193,193,193,194,193,194,193,194,194,192,192,193,192,193,192,193,193,194,193,194,194,199,192,192,192,193,192,193,193,194,194,193,192,193,192,193,193,194,193,194,193,194,194,194,194,193,192,193,192,193,193,195,193,194,193,194,192,193,192,193,192,192,192,193,192,194,194,195,194,195,194,195,194,195,195,193,192,193,192,193,192,193,193,192,192,193,193,194,193,194,192,192,192,193,192,193,193,193,193,194,193,194,193,194,193,193 +,252,252,252,252,252,108,108,108,252,252,252,252,252,252,252,252,252,252,109,109,108,108,108,108,252,252,252,252,252,252,252,107,252,107,107,107,252,252,252,252,109,107,252,107,252,107,252,107,252,107,107,106,107,107,106,106,107,106,106,106,1,1,1,1,1,1,1,1,1,1,1,1,1,1,108,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,107,107,107,109,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,109,107,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,202,202,202,202,202,203,203,204,204,203,202,203,203,204,203,204,203,204,204,204,215,215,215,215,215,215,215,213,213,214,214,214,214,1,1,1,1,1,215,215,215,215,213,213,213,215,213,214,214,214,214,214,214,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,115,115,115,117,112,113,113,1,1,1,1,1,1,1,1,1,1,1,1,1,1,115,115,115,117,115,116,115,116,116,116,117,117,116,117,117,116,116,117,116,117,116,117,117,117,117,117,117,117,115,115,116,116,117,116,116,116,116,117,117,115,115,116,116,117,157,157,156,151,152,115,115,115,115,116,116,116,116,117,117,157,156,156,155,157,157,157,157,156,155,156,155,155,157,157,157,157,157,157,157,157,156,156,155,157,156,156,156,156,155,155,156,156,155,202,202,202,202,202,202,203,202,202,203,202,204,203,203,199,192,192,192,192,192,193,193,193,193,193,193,193,193,194,194,194,192,193,192,193,193,193,193,193,193,194,194,199,192,192,192,193,192,193,193,193,193,194,193,192,192,193,193,193,193,194,192,193,193,194,194,194,192,193,193,193,193,195,193,195,194,194,192,192,192,193,193,192,192,193,194,194,194,194,195,195,194,195,195,195,195,195,192,199,192,193,193,193,193,192,192,193,193,193,193,194,194,194,192,192,192,193,193,193,193,194,194,197,193,193,193,194,193 +,252,252,252,252,252,108,108,252,108,252,252,252,252,252,252,252,252,252,109,252,107,252,108,252,108,252,108,252,252,252,252,252,107,252,107,252,107,252,107,109,109,252,107,252,107,252,107,252,107,252,107,107,107,107,106,106,106,106,106,106,1,1,2,1,1,1,2,1,1,1,2,1,1,1,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,107,107,107,252,107,252,109,252,109,252,109,252,109,252,252,252,107,252,107,109,107,107,107,107,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,202,202,203,202,202,202,203,203,204,203,202,203,204,203,204,203,204,203,204,203,204,215,215,215,215,215,213,215,213,213,214,214,214,1,2,1,1,1,215,215,215,215,213,215,213,215,213,214,213,214,214,213,214,214,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,115,116,115,116,112,112,113,113,1,1,1,2,1,1,1,2,149,112,112,112,1,115,115,116,115,116,115,116,115,116,116,117,117,116,116,117,116,117,117,117,116,117,116,117,116,117,117,117,115,116,116,117,116,117,116,115,116,117,116,117,116,117,117,115,157,157,157,156,151,151,152,115,115,117,117,116,115,116,116,117,157,157,155,155,157,157,157,157,156,155,155,155,157,157,157,157,157,157,157,157,157,157,155,155,156,157,156,156,155,155,155,156,155,156,202,203,202,202,202,203,202,203,202,203,202,203,203,199,199,192,192,193,192,193,192,193,192,193,193,194,193,194,193,194,194,192,192,193,192,193,193,194,193,194,194,194,199,192,192,192,192,193,192,193,193,194,194,193,192,193,192,193,192,193,192,193,192,194,193,194,193,195,192,193,192,193,193,195,193,194,192,193,192,193,192,192,192,193,192,194,194,194,194,195,195,195,194,195,195,195,195,192,192,193,192,193,193,192,192,193,192,193,193,194,193,194,194,194,192,193,192,193,193,194,196,193,196,193,193,193,193,194 +,252,252,252,252,109,108,108,108,252,252,252,252,252,252,252,252,252,109,109,252,252,107,108,108,252,108,252,252,252,252,252,107,252,107,252,107,107,107,109,109,109,109,252,107,252,107,252,107,109,107,252,107,107,107,107,106,106,106,106,106,1,1,1,1,1,1,1,1,1,1,1,1,1,1,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,109,109,109,109,252,109,252,109,252,252,252,252,252,107,107,107,107,107,107,107,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,202,202,202,202,202,203,203,204,204,203,202,203,203,203,203,204,203,204,204,204,215,204,215,215,215,215,215,213,213,213,214,214,1,1,1,1,1,1,215,215,215,215,215,213,213,215,213,214,215,213,214,214,214,214,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,115,115,115,115,116,112,116,112,113,1,1,1,1,1,1,149,149,149,149,149,112,115,115,115,115,115,115,116,116,116,116,116,116,117,116,117,116,116,116,117,116,117,117,117,117,117,117,115,115,116,116,116,117,117,116,115,116,117,117,117,116,117,117,117,157,157,157,157,156,156,151,152,115,116,115,116,116,116,116,116,157,157,156,156,157,157,157,157,157,156,155,155,157,157,157,157,156,157,157,157,157,156,156,155,157,157,156,156,156,156,155,155,156,156,155,202,202,202,202,202,202,202,202,203,202,203,203,199,199,192,192,192,192,193,192,193,193,193,193,193,193,194,194,194,194,194,192,192,192,193,193,193,193,194,194,194,199,192,192,192,192,193,192,193,193,194,194,194,193,193,192,192,192,193,193,192,192,193,193,194,194,195,195,193,192,193,193,193,193,194,192,192,192,193,192,192,192,193,193,193,193,194,194,195,195,195,195,195,195,195,195,194,192,192,192,193,193,192,192,192,192,193,193,193,193,194,194,194,194,193,193,193,193,196,196,193,193,193,193,194,193,194,194 +,252,252,252,252,252,108,108,252,108,252,252,252,252,252,252,252,252,109,109,252,252,108,107,252,108,252,108,252,108,252,252,252,107,252,107,252,252,109,109,252,109,107,107,252,107,252,107,109,107,107,107,252,107,107,107,107,106,107,106,106,19,19,19,19,19,19,19,19,19,19,19,19,19,19,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,252,252,107,107,107,109,107,109,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,202,202,202,203,202,202,202,203,203,204,203,202,202,203,202,203,203,204,203,204,204,204,215,215,215,215,215,213,215,214,213,214,213,19,19,19,19,19,215,215,215,212,215,215,215,213,215,213,213,214,213,214,213,215,214,214,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,115,115,117,117,112,117,116,112,112,19,19,19,19,149,149,149,149,115,115,112,112,112,115,115,115,116,115,116,116,116,116,117,116,117,117,117,116,117,116,117,116,117,117,117,115,115,115,116,116,117,116,117,115,116,115,116,116,117,116,115,117,117,157,157,157,157,157,156,155,151,152,116,115,116,115,116,115,116,115,157,156,156,157,155,157,157,157,156,155,155,157,157,157,157,156,156,157,157,156,157,155,157,157,157,156,157,156,156,155,156,155,156,155,202,202,203,202,203,202,203,202,203,202,202,203,204,199,192,192,192,192,192,192,193,192,193,192,194,192,194,193,194,193,194,192,193,192,193,193,192,192,193,193,194,194,192,192,192,192,193,192,193,192,193,193,194,194,194,193,194,192,193,193,193,192,193,192,194,193,194,195,195,192,193,193,195,193,194,193,192,192,193,192,192,192,193,192,193,193,193,194,194,194,195,195,195,194,195,194,195,194,192,192,193,192,192,192,193,192,193,192,193,193,194,193,194,193,194,192,193,192,193,196,193,196,193,193,194,193,194,194,194 +,252,252,252,252,109,108,108,108,252,252,252,252,252,252,252,252,252,252,109,109,109,107,108,108,252,108,252,107,252,252,252,252,252,107,252,107,109,107,109,109,252,109,252,107,252,107,252,107,109,107,107,107,252,109,109,107,107,106,107,106,106,20,20,20,20,20,20,20,20,20,20,20,20,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,109,107,109,109,252,109,109,109,252,252,252,252,252,252,252,107,252,107,107,107,107,107,107,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,202,202,202,202,202,202,203,203,204,204,202,202,202,202,203,203,203,203,204,204,204,215,204,215,215,215,215,215,213,213,214,214,214,20,20,20,20,215,215,215,215,215,215,215,213,213,215,213,213,215,213,213,214,205,214,214,214,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,115,115,115,115,117,115,117,112,117,112,112,112,112,112,116,115,116,116,117,116,115,115,116,116,115,115,115,115,116,116,116,116,117,116,117,117,117,117,117,117,117,117,117,117,115,115,115,115,116,116,116,116,117,115,116,117,116,116,116,116,115,117,117,157,157,157,157,157,157,156,156,151,151,155,115,115,116,116,116,116,117,157,156,157,157,156,155,157,157,155,155,157,157,157,157,157,157,156,157,156,157,155,157,157,157,157,157,156,156,156,156,155,155,155,155,202,202,202,202,202,203,203,202,202,203,202,204,199,192,192,192,192,192,192,192,192,192,192,192,192,194,194,194,194,194,192,192,192,192,192,193,193,193,193,194,194,199,192,192,192,192,192,193,192,193,193,194,194,194,192,193,192,193,192,193,192,193,192,194,193,194,194,195,195,193,193,193,193,194,194,192,192,193,192,193,192,192,192,193,193,193,193,194,194,195,195,195,195,195,195,195,195,199,192,192,192,193,192,192,192,193,193,193,193,193,193,194,193,194,194,192,192,193,192,193,193,193,193,194,193,194,193,194,194 +,252,252,252,252,252,108,108,252,108,252,252,252,252,252,109,252,252,252,109,109,109,252,107,108,108,252,108,252,107,252,109,252,252,252,107,252,107,109,107,109,109,252,109,107,107,252,107,252,107,107,107,252,109,109,107,109,107,107,106,106,106,106,20,20,20,20,20,20,20,20,20,20,20,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,107,107,107,107,107,109,107,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,202,202,202,203,202,203,202,203,203,204,202,203,202,203,203,204,203,204,204,204,204,204,215,204,215,215,213,215,214,215,215,214,214,20,20,20,215,215,215,212,215,213,215,215,215,215,215,215,215,215,214,214,214,215,213,214,214,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,115,115,116,115,116,117,115,116,112,116,117,112,116,115,115,115,116,116,117,115,117,115,116,115,117,115,116,115,116,116,117,116,117,116,117,116,117,115,117,115,116,116,117,115,115,115,115,115,116,115,115,115,117,115,116,116,117,115,116,116,117,115,117,157,157,157,157,155,151,157,156,155,156,151,152,116,117,116,117,116,117,117,157,155,157,156,156,155,157,156,155,155,157,157,157,157,157,156,157,156,157,155,157,156,157,157,157,156,157,156,156,155,156,155,155,155,202,202,203,202,203,202,203,202,203,202,202,199,199,192,192,192,193,193,192,192,194,192,193,192,193,193,194,193,194,193,192,192,192,192,193,192,193,193,194,193,194,192,192,192,192,192,193,192,193,193,194,194,194,192,192,192,193,192,193,192,193,192,194,193,194,194,194,195,195,192,193,193,194,193,192,192,193,192,193,192,192,192,193,192,193,193,194,193,194,194,195,194,195,195,195,195,194,193,193,192,193,192,197,192,193,192,193,192,193,193,198,193,194,194,198,192,193,193,197,192,193,193,194,193,194,193,194,193,194 +,252,252,252,252,109,108,108,108,109,252,252,252,252,252,252,252,252,252,109,109,109,109,109,107,108,108,252,252,252,252,252,252,252,107,252,107,252,107,109,109,109,109,109,107,107,107,252,107,109,109,107,107,107,109,109,107,107,107,107,106,106,106,106,20,20,20,20,20,20,20,20,20,20,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,107,107,107,107,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,202,202,202,203,203,204,203,204,203,202,204,202,202,203,203,203,203,204,204,204,204,204,204,204,215,215,215,215,215,213,214,215,213,214,20,20,20,215,215,215,215,212,215,215,215,215,215,213,215,213,215,214,213,214,215,213,213,214,213,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,115,115,115,115,115,115,116,116,115,117,112,117,112,116,115,115,115,116,116,116,115,117,117,116,116,117,115,115,115,116,116,116,117,117,117,116,116,117,115,116,116,117,115,115,115,115,115,116,115,115,115,115,115,116,115,117,116,117,117,117,116,116,115,116,157,157,157,157,156,156,155,151,156,156,156,155,151,155,116,117,117,117,157,156,156,157,156,156,155,155,157,155,156,157,157,157,157,157,156,157,157,156,156,155,156,157,157,157,157,157,156,155,156,157,156,156,155,155,202,202,202,202,202,203,203,202,202,203,199,199,192,192,192,192,192,193,193,193,192,192,192,193,193,192,193,194,194,194,192,192,192,193,193,193,193,193,193,194,192,192,192,193,192,193,193,193,193,193,194,194,192,192,192,192,192,193,192,194,193,193,193,194,194,194,195,195,195,195,193,193,194,192,192,193,192,192,192,193,192,193,193,193,193,193,194,194,194,195,195,195,195,195,195,195,194,192,192,193,192,192,192,193,192,193,193,193,193,193,193,194,194,192,192,192,193,193,193,193,193,193,193,194,193,194,194,194,194 +,252,252,252,252,252,108,108,252,108,252,252,252,252,252,109,252,252,252,252,109,109,109,109,252,107,252,109,252,109,252,252,252,109,252,252,252,107,252,107,109,109,252,109,108,107,252,107,252,109,252,107,107,107,252,107,107,107,107,107,107,106,106,106,20,21,20,20,20,21,20,21,20,21,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,109,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,107,109,107,107,107,107,107,107,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,202,202,202,203,202,203,203,204,204,202,203,202,202,203,202,203,203,204,204,204,203,204,204,204,204,204,215,215,202,215,213,214,215,215,214,21,20,215,215,212,215,212,215,215,215,213,213,213,213,212,205,213,211,213,213,215,205,214,213,214,211,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,115,115,115,115,116,115,115,115,116,116,117,116,112,117,116,115,116,115,116,116,117,115,116,117,117,116,117,115,116,115,115,115,116,116,117,117,116,115,117,115,115,115,116,115,116,115,116,115,116,115,115,115,117,115,116,115,116,116,117,116,117,117,117,117,117,117,157,157,157,156,156,157,155,151,156,155,156,155,155,151,117,117,117,156,157,156,157,156,157,155,156,155,157,156,157,157,157,156,157,157,157,156,157,156,156,155,157,157,157,156,156,155,156,155,155,156,156,155,155,202,202,202,203,202,203,203,204,203,202,196,199,192,192,192,192,192,193,192,193,193,192,192,193,192,192,194,194,193,194,192,192,192,193,192,193,193,194,193,194,193,192,192,193,192,193,193,193,193,193,194,194,192,192,192,192,193,192,192,193,193,194,194,194,194,194,195,195,195,195,195,193,193,192,192,193,192,193,192,192,192,193,193,193,193,193,194,195,194,195,194,195,194,195,197,195,194,194,192,197,192,197,192,193,192,196,192,197,193,197,193,194,193,198,192,197,192,197,193,193,193,197,193,197,193,194,193,197,194,194 +,252,252,252,252,109,108,108,108,252,252,109,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,108,108,252,107,109,109,109,109,107,107,109,109,252,109,252,107,107,109,107,107,107,107,107,107,107,107,106,106,20,20,20,20,20,20,20,20,20,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,109,107,252,109,109,109,252,252,252,109,252,252,252,252,252,107,109,107,107,107,107,107,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,202,202,202,202,202,203,203,203,203,204,204,203,202,202,204,203,202,203,203,203,203,204,204,204,204,204,204,202,204,204,204,215,214,214,215,215,20,20,215,215,215,215,215,215,215,215,215,215,215,213,212,215,215,211,214,213,215,212,213,213,213,213,211,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,80,83,86,89,92,95,115,115,115,116,116,117,116,117,112,116,115,115,115,116,116,116,116,117,117,116,116,117,115,115,116,116,115,116,117,116,116,117,115,116,115,115,115,115,115,115,115,116,116,116,115,115,115,115,115,116,115,115,116,116,117,117,116,117,117,117,117,157,157,156,155,155,157,156,151,155,151,156,155,155,151,151,155,157,157,156,156,156,157,157,156,156,155,155,157,157,157,157,157,157,157,157,155,157,157,156,155,155,157,157,156,156,156,156,155,155,155,156,155,156,155,202,202,202,202,202,203,203,204,204,203,199,192,192,192,192,192,192,192,193,193,193,192,192,192,192,194,193,193,193,192,192,192,193,192,193,193,193,193,194,194,192,192,193,192,193,192,193,193,193,194,194,193,192,192,193,192,193,192,193,192,194,193,194,194,194,195,195,195,195,193,195,193,192,192,193,192,193,192,192,192,193,192,193,193,193,194,195,194,195,195,195,195,195,193,195,195,194,196,193,193,193,192,193,192,193,192,193,193,193,193,194,193,194,194,192,192,193,192,193,193,193,193,193,193,194,193,194,194,193,194 +,252,252,252,252,252,109,108,108,108,252,108,252,252,252,109,252,252,252,252,252,109,252,109,109,109,252,109,252,109,252,109,252,252,252,252,252,107,108,108,109,109,252,109,108,107,252,107,252,107,252,109,109,109,252,107,107,107,107,107,107,107,107,107,106,106,20,21,20,21,20,21,20,21,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,252,109,107,107,107,107,107,107,107,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,202,203,202,203,202,203,203,204,203,204,204,202,202,204,204,203,202,203,203,204,209,202,203,204,209,204,202,202,203,203,203,204,203,213,214,204,215,215,20,215,215,215,215,212,215,212,215,215,215,215,215,213,212,215,212,211,213,215,205,212,212,213,211,213,211,21,20,20,20,20,20,20,35,38,41,44,46,32,34,37,38,41,42,45,46,32,33,48,51,54,57,60,62,44,45,47,32,33,34,36,48,50,51,54,55,58,59,62,62,48,53,58,62,37,38,41,41,44,48,50,51,53,54,57,57,60,61,63,115,115,115,116,115,116,115,116,115,115,115,115,115,116,115,116,115,116,116,117,117,117,117,117,157,157,157,157,156,156,157,157,156,156,155,151,155,156,155,155,155,151,156,157,199,199,199,193,156,156,155,156,157,157,157,157,156,157,157,157,156,155,157,157,156,156,155,157,156,157,156,156,155,156,155,155,155,156,155,155,202,202,202,203,202,203,203,204,202,199,192,193,192,193,192,193,192,193,193,193,193,192,192,192,193,194,193,194,192,192,192,193,192,193,193,194,194,194,193,192,192,193,192,193,192,193,192,194,194,194,194,192,192,193,192,193,192,193,193,193,193,194,194,194,194,195,195,195,195,195,194,194,192,192,193,192,192,192,193,192,193,193,193,193,194,195,194,195,194,192,192,195,193,195,194,195,193,196,192,197,192,197,193,197,192,197,193,197,193,197,194,198,194,198,192,197,193,197,193,197,193,197,193,197,193,197,194,193,194,194 +,252,252,252,252,252,252,108,108,108,108,109,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,108,107,109,109,109,109,107,107,109,107,109,109,252,109,109,109,109,107,107,107,107,107,107,107,107,106,106,20,20,21,20,20,20,20,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,109,107,109,109,252,109,252,109,252,252,252,252,252,252,109,107,109,107,107,107,107,107,107,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,20,21,20,20,20,20,20,20,202,202,202,202,202,203,203,210,208,208,208,208,210,209,209,203,209,203,203,203,203,209,204,209,209,204,203,202,203,203,203,204,204,208,204,211,214,204,215,20,215,215,212,212,215,212,215,215,215,215,215,215,215,213,211,212,215,211,213,215,215,212,212,213,211,213,211,211,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,33,34,35,37,38,39,40,41,42,44,45,46,47,32,34,35,37,39,40,42,44,45,47,32,33,33,34,35,35,36,37,38,38,39,39,40,41,42,42,43,44,44,45,46,48,50,52,55,56,59,61,63,157,157,157,157,157,157,156,156,157,155,156,156,156,151,151,151,151,156,155,155,151,157,192,199,193,197,193,198,156,156,155,157,157,157,157,156,156,155,157,156,155,157,156,155,157,155,156,157,156,156,156,156,155,155,155,156,155,155,155,203,202,203,202,203,203,204,202,199,192,196,192,193,192,196,192,193,192,193,193,192,192,192,193,194,193,193,193,193,192,193,193,193,192,193,194,194,194,192,192,193,192,193,192,193,193,196,193,194,194,197,192,193,192,193,192,193,193,197,193,194,193,194,194,195,195,195,195,197,194,193,192,192,193,192,193,192,192,192,193,193,193,193,194,198,194,195,194,192,192,193,193,193,193,195,194,197,196,193,193,193,193,192,193,193,193,193,193,193,194,194,193,194,192,192,193,193,193,193,193,193,193,193,193,194,194,193,194,198,194 +,252,252,252,252,252,252,107,109,108,252,108,252,108,252,252,252,109,252,252,252,252,109,109,252,109,252,109,252,109,252,109,108,109,252,252,252,252,252,252,108,252,109,109,109,109,108,107,252,107,252,109,252,109,109,109,109,109,107,107,107,107,107,107,107,107,107,21,20,21,20,21,20,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,252,107,252,107,252,109,252,109,252,109,252,109,252,252,252,107,109,107,109,107,107,107,107,107,107,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,202,202,208,202,202,202,209,210,208,203,208,203,208,208,209,202,209,203,203,203,208,208,211,209,208,209,202,210,203,209,203,209,208,209,208,208,211,214,215,20,212,212,212,212,212,215,212,215,215,212,215,215,215,205,213,205,211,212,211,213,215,205,212,212,213,211,213,212,211,211,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,21,36,37,40,32,34,35,37,38,40,41,43,44,46,47,45,45,46,46,47,46,47,157,157,157,157,156,157,156,156,157,157,156,156,155,156,155,156,155,155,151,151,155,155,151,199,193,196,193,193,198,198,198,198,156,156,155,156,155,155,155,157,156,156,155,155,157,156,155,157,156,156,155,156,155,156,155,155,155,156,155,203,202,203,202,203,203,204,202,199,192,196,192,196,193,193,196,196,193,194,193,194,192,193,193,194,192,193,192,193,192,193,192,193,193,193,193,194,194,195,192,192,192,193,192,193,193,194,194,194,194,194,192,192,192,192,193,193,193,193,193,193,193,194,194,194,195,195,195,198,194,193,192,192,193,192,193,192,192,192,193,192,193,193,194,198,194,195,194,192,192,193,192,193,193,195,194,195,195,196,193,197,192,197,193,196,192,197,193,197,194,198,194,198,193,198,192,197,193,197,193,197,193,197,193,197,193,198,194,198,194,194 +,252,252,252,252,252,252,108,108,108,108,109,108,252,252,252,109,252,252,252,252,108,107,108,107,109,107,109,107,252,109,252,109,252,252,252,252,252,252,252,109,108,252,252,252,109,107,108,107,107,107,107,107,107,107,107,107,109,109,107,107,107,107,107,107,107,107,107,20,20,21,20,21,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,252,109,109,109,252,252,252,252,252,252,252,107,109,107,109,107,109,107,107,107,107,107,107,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,21,20,20,20,21,20,21,20,202,210,210,210,208,210,210,209,209,208,208,203,203,203,208,208,208,203,203,209,208,208,208,208,211,209,210,209,210,208,203,209,208,208,209,209,208,208,211,214,215,212,212,212,215,212,215,212,212,212,215,212,212,215,212,215,215,212,211,211,211,213,212,215,212,212,211,211,211,211,211,211,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,41,42,43,44,45,46,47,43,43,45,45,46,47,156,156,156,156,156,156,156,155,155,156,156,155,155,156,155,155,155,155,155,151,151,155,155,155,155,199,196,193,196,193,193,198,198,198,156,156,156,156,156,155,155,155,156,155,155,156,156,155,155,156,156,156,156,156,156,155,155,155,155,155,155,202,203,202,203,203,204,202,199,192,196,192,196,193,196,193,196,193,193,194,194,192,193,193,194,194,193,192,193,192,193,193,193,193,194,194,194,194,194,192,192,192,193,192,193,193,196,194,197,193,196,193,192,192,193,192,193,193,197,193,197,193,197,193,194,195,195,195,198,198,193,194,192,193,193,194,194,192,192,193,193,193,193,193,198,198,197,194,192,192,192,192,193,193,193,194,195,194,196,196,197,193,193,193,196,193,193,193,197,194,194,194,198,194,194,192,197,192,193,193,197,193,193,193,197,194,194,194,194,194,194,194 +,252,252,252,252,252,252,107,108,108,252,108,252,108,252,252,252,252,252,252,108,107,252,107,108,107,252,107,252,107,252,107,252,109,252,107,252,252,252,109,252,109,252,109,252,107,252,107,108,107,252,107,107,107,252,107,109,107,252,107,252,107,107,107,107,107,107,107,106,107,20,21,20,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,252,107,252,107,252,107,252,109,252,109,252,252,252,109,109,107,109,107,109,107,107,107,107,107,107,107,107,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,210,210,209,209,208,209,210,210,209,209,208,210,203,203,208,209,208,208,203,203,208,209,208,209,208,211,208,209,209,209,210,210,208,209,208,209,208,209,208,215,211,214,212,212,212,212,212,212,212,212,212,212,212,212,212,212,215,215,212,212,211,211,211,212,211,215,215,205,211,211,211,211,211,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,21,21,45,46,46,47,32,38,37,38,38,39,38,39,40,156,156,156,156,156,156,156,155,156,155,156,156,156,155,155,155,155,155,155,155,155,155,155,155,151,151,151,192,196,193,196,197,193,193,198,198,198,198,156,155,156,155,156,155,156,155,156,155,156,155,156,155,157,156,156,155,156,155,156,155,155,155,155,155,203,203,203,202,203,203,203,199,196,193,196,193,196,196,196,196,193,193,194,193,193,193,194,194,192,192,193,196,193,193,193,193,194,193,194,194,195,192,192,192,193,192,193,193,193,194,197,193,196,194,192,192,192,192,193,193,193,193,197,193,193,193,194,194,195,195,198,195,193,193,192,193,192,193,193,194,192,193,192,193,193,193,194,194,193,194,192,192,193,192,193,193,195,193,195,194,197,196,196,193,197,193,196,193,197,193,197,194,198,194,198,194,198,193,197,193,197,193,197,193,197,193,197,193,197,193,198,194,198,194,198 +,252,252,252,252,252,252,108,107,108,108,109,252,109,252,252,252,252,252,108,107,108,107,108,107,108,107,109,108,109,107,109,109,109,109,252,252,252,252,252,252,252,109,252,107,252,107,252,107,252,107,107,107,107,107,107,107,107,107,109,107,252,107,107,107,107,107,107,107,106,107,21,21,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,252,109,252,252,252,252,252,252,109,107,109,107,109,107,109,107,107,107,107,107,107,107,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,202,202,209,209,209,209,208,210,209,209,208,210,210,210,209,209,208,208,208,203,209,209,208,209,208,208,211,208,209,209,208,210,209,209,208,208,209,209,208,208,208,215,211,211,212,212,212,212,212,212,212,212,212,215,212,215,215,212,212,212,212,212,211,211,212,212,211,212,212,212,212,211,211,211,211,20,21,20,21,20,21,21,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,20,21,20,44,20,45,20,32,34,36,37,40,41,43,45,32,33,34,35,37,38,39,40,41,47,47,53,54,56,57,59,60,62,63,48,49,51,52,54,55,57,58,60,61,63,48,50,52,58,60,61,63,48,50,52,54,55,199,193,196,193,193,193,197,198,198,197,198,198,155,155,155,155,155,155,155,155,155,155,155,155,155,156,156,156,156,155,155,155,155,155,155,155,155,202,203,202,203,203,203,199,196,193,196,196,196,197,196,196,197,197,194,194,193,193,193,193,196,192,193,196,193,193,193,193,193,193,194,195,195,193,192,192,193,192,193,193,196,196,197,194,197,196,193,194,192,193,193,193,192,193,197,193,197,193,196,194,195,194,198,195,197,193,193,192,192,192,192,193,192,193,193,193,193,193,194,194,198,194,192,192,193,192,193,193,193,193,195,195,197,197,196,196,196,193,196,193,193,193,197,193,197,194,198,194,194,194,197,193,197,192,197,193,193,193,197,193,197,193,198,194,198,194,198,194 +,252,252,252,252,252,252,252,108,107,109,108,252,108,252,252,252,252,252,108,108,107,108,107,109,107,252,107,109,108,109,108,252,107,109,109,252,109,252,252,252,252,252,252,252,107,252,107,252,252,252,109,252,107,107,107,252,107,252,107,109,107,252,107,107,107,107,107,107,107,106,107,107,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,252,107,252,107,252,109,252,109,252,109,252,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,21,20,21,20,21,21,21,20,21,20,21,20,210,210,209,210,209,209,208,208,208,208,209,210,209,209,208,208,209,210,203,203,209,209,209,209,208,209,208,209,211,209,208,209,208,209,209,208,208,209,208,209,208,208,208,215,211,212,212,212,212,212,212,212,212,212,212,215,211,215,215,212,212,212,212,212,211,211,211,212,212,212,212,212,211,212,211,212,211,211,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,47,32,34,35,38,39,42,43,45,32,35,37,40,42,45,47,62,63,48,49,52,53,56,57,60,61,63,48,50,51,54,55,58,59,61,63,48,49,52,53,56,57,60,61,63,199,196,193,196,193,197,197,198,197,198,197,198,198,156,155,155,155,155,155,156,156,156,155,155,155,156,155,155,155,155,155,155,155,155,155,155,203,203,203,203,203,203,196,192,196,196,196,196,196,196,196,197,196,193,197,194,194,193,193,192,192,193,196,193,196,193,193,194,193,194,194,195,195,192,192,193,192,193,193,197,193,196,194,197,196,196,194,192,193,192,193,194,194,196,193,197,193,197,194,194,194,195,195,197,193,193,192,193,193,192,193,193,193,193,193,193,194,194,194,198,194,193,194,193,192,193,193,195,193,195,194,195,194,197,196,197,193,197,193,197,193,198,193,196,194,197,194,198,194,198,193,197,193,197,193,197,193,197,193,197,193,198,193,198,194,198,194,198 +,252,252,252,252,252,252,252,252,108,107,108,108,109,252,109,252,252,252,252,108,108,107,108,107,108,107,108,108,109,108,109,108,252,109,109,109,252,252,252,252,252,252,252,252,252,252,252,107,252,107,252,109,252,107,107,107,107,107,107,107,252,107,252,107,252,252,107,107,108,107,106,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,252,109,252,109,252,252,252,252,252,252,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,210,210,209,209,209,209,208,208,209,209,208,210,209,209,208,210,209,209,209,209,209,209,209,209,209,209,209,209,208,208,208,209,208,208,211,209,208,209,209,209,208,208,208,211,211,208,211,212,212,212,212,212,212,212,212,212,212,212,212,211,212,212,212,212,212,212,211,211,212,212,212,212,211,211,211,211,211,211,211,211,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,41,20,42,43,20,44,45,45,47,47,32,33,34,35,36,37,38,32,33,34,35,36,37,38,40,41,21,42,44,45,46,47,58,58,59,59,60,60,61,61,62,62,63,63,196,196,196,196,197,197,197,197,198,198,198,198,198,198,75,75,76,77,78,78,79,53,53,53,54,156,156,155,156,155,155,155,155,155,155,155,203,202,203,203,203,196,192,196,196,196,196,196,198,198,193,193,193,193,198,194,194,197,192,196,193,196,193,196,193,193,193,193,194,195,195,195,192,192,193,192,193,193,197,193,196,193,196,193,196,193,192,193,194,193,196,193,197,193,197,193,194,193,194,195,195,198,198,193,193,192,193,192,192,193,193,193,193,193,193,198,193,198,198,194,193,192,192,194,193,193,193,193,195,195,195,194,197,196,196,193,197,193,197,193,197,193,197,194,198,194,198,194,197,194,197,193,197,193,197,193,197,193,196,193,197,194,198,194,198,194,198,194 +,252,252,252,252,252,252,252,252,252,108,107,109,108,252,108,252,252,252,252,108,108,109,107,108,107,109,107,109,108,252,108,252,108,252,108,252,109,252,107,252,109,252,109,252,252,252,252,252,107,252,107,252,109,252,107,107,107,252,107,252,107,252,107,252,107,252,107,107,252,108,107,107,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,252,107,252,107,252,107,252,109,252,109,252,252,252,107,109,107,109,107,109,107,107,107,109,107,107,107,107,107,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,210,209,210,209,209,208,208,210,210,208,209,208,210,209,210,209,210,210,210,210,210,210,210,209,209,208,209,208,209,208,208,209,209,208,209,211,209,208,209,208,209,208,209,208,211,211,208,211,212,212,212,212,212,212,212,212,212,212,212,211,211,212,212,212,212,211,212,211,211,211,212,212,212,211,211,211,211,211,212,211,211,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,21,20,33,20,34,20,35,35,37,37,38,38,39,39,40,40,42,42,43,43,44,44,45,45,47,47,32,33,35,35,37,37,39,40,42,42,44,44,46,47,63,48,50,51,54,55,58,59,62,62,59,199,196,196,196,196,197,197,198,197,198,197,198,198,198,198,198,69,71,71,72,73,74,74,76,76,78,78,79,52,53,52,54,53,55,54,55,203,203,203,203,196,199,196,196,196,196,196,196,197,198,198,197,193,198,197,194,194,196,196,193,196,193,196,193,196,194,193,194,193,195,195,196,192,193,193,193,193,197,193,196,196,196,194,196,196,197,193,197,193,196,193,197,197,197,193,197,194,194,194,194,195,198,197,193,192,193,193,193,193,193,193,193,193,193,198,194,198,198,194,193,194,196,194,193,196,193,197,195,193,195,194,197,196,196,193,197,193,197,193,197,193,198,193,198,194,198,194,198,194,197,193,197,193,197,193,197,193,197,193,197,193,198,193,198,194,198,194,194 +,252,252,252,252,109,252,252,252,252,252,108,107,109,108,109,252,109,252,252,108,108,107,108,107,108,107,108,108,109,108,109,108,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,252,107,252,109,109,109,108,107,107,107,107,107,252,107,252,252,107,107,252,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,109,107,252,252,252,252,252,252,252,252,109,109,109,107,109,107,109,107,107,107,107,107,107,107,107,107,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,140,141,209,209,209,208,208,208,210,208,209,208,208,209,210,210,210,210,210,209,210,209,209,208,208,208,209,209,209,209,209,208,209,209,209,208,211,209,209,208,208,208,209,208,208,211,211,208,208,211,212,212,212,212,212,212,212,212,212,212,212,211,211,212,212,212,212,212,212,211,211,212,212,212,212,212,211,211,211,211,211,211,211,21,21,21,21,21,21,21,21,32,34,37,39,42,44,47,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,32,34,36,38,41,42,45,47,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,42,42,43,43,44,44,45,46,46,47,47,32,33,35,36,37,38,40,41,42,43,45,46,47,53,54,54,196,196,196,196,197,197,197,197,198,198,198,198,198,198,198,198,198,62,63,63,64,65,67,68,69,70,72,73,74,75,77,78,79,51,52,52,203,203,203,203,199,196,196,196,196,196,197,193,193,193,198,198,193,197,195,198,194,196,196,196,196,196,193,196,193,197,194,195,195,195,195,192,193,196,193,196,193,193,197,193,198,194,197,196,197,193,197,193,196,193,197,194,197,193,194,193,194,194,195,195,198,197,193,196,193,193,193,193,193,193,193,193,193,198,194,198,198,198,198,193,193,196,192,196,193,197,193,193,195,195,196,196,196,193,197,193,197,193,197,193,197,193,198,193,198,194,198,194,197,194,197,193,197,193,197,193,196,193,197,193,197,193,198,194,198,194,198,194 +,252,252,252,252,252,252,252,252,252,252,107,108,108,109,252,252,108,252,108,252,108,252,109,252,107,109,108,109,108,252,108,252,108,252,108,252,108,252,107,252,108,252,109,252,252,252,252,252,109,252,107,252,107,252,107,252,108,252,252,252,108,252,108,252,108,252,108,252,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,107,252,109,252,252,252,252,109,109,109,107,109,107,107,107,109,107,109,107,107,107,107,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,21,21,20,21,21,21,20,21,20,21,21,21,20,21,21,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,21,21,21,21,20,21,20,21,21,21,21,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,21,21,20,21,21,21,20,21,20,21,21,21,20,21,21,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,20,21,20,21,21,21,21,21,20,21,21,21,20,21,21,21,21,21,20,21,139,203,140,209,209,208,208,209,209,208,209,208,208,209,210,210,210,209,210,209,210,209,209,208,209,208,209,211,208,211,209,208,209,209,209,208,209,211,209,211,209,208,208,208,209,208,208,211,211,211,211,211,211,48,49,50,51,52,53,54,55,56,57,32,34,37,38,41,42,45,47,211,211,211,32,34,34,36,37,39,40,42,42,45,45,47,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,21,21,21,20,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,196,196,196,196,197,196,197,197,198,197,198,198,198,198,198,198,198,198,198,60,199,192,196,62,63,64,65,65,67,67,69,69,71,199,196,72,203,203,203,203,199,196,196,196,196,196,193,193,198,197,198,197,198,197,195,197,198,194,196,196,196,196,193,196,194,197,194,197,195,195,195,192,193,196,193,193,193,193,197,197,196,194,198,196,196,193,197,197,196,193,197,194,197,193,197,197,194,194,195,195,198,198,194,197,196,197,193,197,193,197,193,197,193,198,194,198,198,194,198,198,193,194,193,196,193,197,193,197,195,197,195,196,197,193,197,193,197,193,197,193,197,193,198,193,198,194,198,194,198,193,197,193,197,193,197,193,197,193,197,193,198,193,198,193,198,194,198,198,198 +,252,252,252,252,109,252,252,252,252,252,252,108,108,108,109,108,252,252,252,252,252,252,252,252,108,107,108,108,108,108,108,108,252,108,109,108,252,252,252,107,252,252,252,252,252,252,252,252,252,252,252,107,252,107,108,107,252,252,252,252,252,252,108,108,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,109,107,109,107,252,252,252,252,252,252,252,252,109,107,109,107,109,107,107,107,107,107,109,107,107,107,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,21,20,21,21,21,40,20,48,50,51,54,55,57,59,61,63,63,139,61,62,208,48,209,209,208,208,209,50,51,210,210,210,210,210,209,209,209,209,208,208,208,209,208,208,208,211,211,209,209,209,209,208,208,208,208,211,211,209,208,208,208,208,208,208,208,211,211,205,211,205,32,34,36,37,40,41,43,45,47,32,33,34,35,36,37,38,40,41,42,42,211,211,211,211,211,211,211,211,21,21,21,21,21,21,21,32,37,42,47,21,21,21,21,21,21,21,32,35,38,41,44,47,21,21,21,21,32,46,21,21,21,21,21,21,32,34,37,39,42,44,47,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,48,49,49,49,196,196,196,196,196,197,197,197,197,198,197,198,198,197,198,198,198,198,198,192,196,196,197,197,61,62,63,63,64,65,66,66,199,196,196,196,196,196,196,196,196,196,196,198,198,197,193,193,197,198,198,198,198,198,197,195,195,196,196,196,196,197,197,197,197,195,195,195,197,195,195,193,196,193,196,193,196,193,193,196,193,197,198,196,196,197,193,196,193,197,193,197,197,197,193,198,194,195,195,194,195,194,197,196,196,193,197,193,197,193,197,197,197,194,198,194,197,198,198,198,193,196,196,193,197,197,197,195,195,195,196,196,193,197,196,197,193,197,197,197,193,197,197,197,193,198,198,198,194,197,197,197,193,197,196,196,193,197,197,197,193,198,198,198,194,198,198,194,198 +,252,252,252,252,252,252,252,252,252,108,252,108,108,109,108,109,108,252,108,252,252,252,108,252,107,109,107,109,108,252,108,109,108,252,108,252,108,252,108,252,108,252,108,252,252,252,107,252,107,252,109,108,107,252,107,252,107,252,108,252,108,252,108,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,252,107,252,107,252,107,252,107,252,252,252,109,252,252,109,107,109,107,109,107,107,107,109,107,109,107,109,107,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,21,32,21,34,21,36,20,38,21,41,43,43,20,36,47,36,57,58,59,60,62,63,63,63,209,49,130,130,130,48,210,210,210,210,209,210,209,210,209,209,208,209,208,209,208,208,211,211,208,209,211,209,208,209,208,209,208,209,208,209,209,209,208,208,208,209,208,209,208,211,211,208,211,211,21,215,215,215,215,213,212,215,215,211,214,213,215,212,213,213,213,213,211,211,211,211,212,211,211,211,21,211,21,39,47,21,21,20,21,21,21,21,21,21,21,20,21,21,21,21,21,21,21,20,21,21,21,21,21,21,21,20,21,21,21,21,21,21,21,20,21,21,21,21,21,21,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,196,196,196,196,196,197,197,197,196,197,197,198,197,198,197,198,198,198,196,196,196,197,197,198,60,62,61,62,62,199,199,196,192,198,197,198,198,196,196,196,197,196,197,198,193,198,193,198,197,198,198,197,197,195,197,195,196,197,196,197,196,194,196,194,197,195,197,195,195,193,196,193,196,193,196,193,193,196,193,197,197,198,196,197,197,197,193,196,196,197,194,197,197,197,194,198,198,198,195,195,197,194,197,196,197,193,197,193,197,193,198,194,198,194,198,198,197,198,194,197,196,193,196,197,197,198,197,195,197,196,193,197,193,197,193,197,193,197,193,197,193,198,194,198,194,198,194,198,194,197,193,197,193,197,193,197,193,197,193,198,193,198,193,198,198,194,198,198 +,109,252,109,252,252,252,252,252,252,252,108,252,108,108,108,108,109,108,109,252,252,252,252,252,252,108,108,108,108,107,108,107,108,107,252,108,252,107,252,252,252,252,252,252,252,252,252,107,252,107,252,107,108,107,108,107,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,109,107,252,109,252,252,252,252,252,252,252,252,109,107,109,107,109,107,107,107,109,107,109,107,107,21,21,21,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,20,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,21,21,21,20,21,21,20,21,21,20,21,21,21,21,21,21,21,21,45,21,36,20,37,21,38,38,59,60,62,63,62,32,36,40,43,47,210,210,54,210,210,209,210,209,209,209,209,208,208,208,208,208,208,211,211,211,211,208,211,211,32,33,34,35,35,37,37,38,39,40,41,42,42,44,44,45,46,47,212,215,215,215,213,21,212,21,32,39,46,21,213,213,215,205,214,213,214,21,211,211,213,32,211,39,43,47,47,21,21,21,21,21,21,21,21,21,32,35,38,41,44,47,21,32,37,42,47,44,44,44,44,44,44,44,44,44,44,44,32,36,39,43,47,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,32,32,32,32,33,33,33,34,34,34,35,35,36,36,37,37,37,38,38,39,39,39,40,40,41,41,42,42,43,43,43,44,44,44,45,45,46,46,47,47,48,48,49,49,196,196,196,196,197,196,196,197,197,198,197,197,198,198,198,197,198,198,197,196,196,196,197,197,198,60,61,61,199,192,196,192,197,197,197,197,198,198,198,198,196,197,198,198,198,197,197,197,198,198,198,197,195,197,195,195,194,197,198,198,197,197,197,197,195,197,195,195,195,196,193,196,193,193,193,196,193,196,197,194,198,196,197,196,197,193,196,193,197,194,197,197,198,194,198,194,198,195,195,195,197,196,193,197,196,197,193,197,197,197,194,198,198,198,198,198,198,198,198,197,196,196,193,197,197,198,198,197,196,196,196,196,196,196,197,197,197,197,197,197,197,197,198,197,198,196,198,198,198,197,197,196,196,196,197,197,197,197,197,197,198,198,198,194,198,198,198,194 +,252,109,252,252,252,252,252,252,252,252,252,108,252,252,252,109,108,252,108,252,108,252,109,252,109,108,108,109,108,109,108,252,108,252,108,252,108,252,108,252,108,252,108,109,108,252,252,252,252,252,108,108,108,108,107,252,107,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,252,107,252,107,252,107,252,109,252,109,252,252,252,252,252,252,109,107,109,107,107,107,109,107,109,107,109,107,107,21,40,21,41,21,21,21,43,21,44,21,45,21,21,21,32,21,34,21,36,21,21,21,39,21,32,21,35,21,21,21,39,21,41,21,43,21,21,21,47,21,46,21,34,21,21,21,35,21,38,21,41,21,21,21,46,21,32,21,20,21,21,21,32,21,35,21,38,21,21,21,44,21,47,21,36,21,21,21,37,21,38,21,38,21,21,21,39,21,40,21,41,21,21,21,47,21,42,21,34,21,21,21,38,21,40,21,43,21,21,21,47,21,33,21,35,21,21,21,39,21,41,21,43,21,21,21,46,21,37,21,37,21,21,21,38,21,38,21,20,21,21,21,39,21,42,21,45,32,34,35,37,38,40,41,43,44,46,47,210,210,52,52,209,55,57,210,209,210,209,209,208,209,208,208,208,208,208,208,211,211,211,211,208,211,208,208,21,209,215,208,215,213,214,215,21,214,215,212,211,211,211,211,211,37,40,41,44,45,47,213,215,213,215,32,34,35,37,38,40,41,213,211,211,213,211,211,21,211,21,21,21,21,21,32,37,41,47,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,45,45,45,45,45,45,45,45,45,32,35,40,43,47,32,33,32,33,32,32,32,33,33,34,33,34,34,35,35,36,35,36,36,37,37,38,37,39,38,39,39,40,39,41,40,41,41,42,42,43,42,43,43,44,44,45,44,45,45,46,46,47,46,47,48,49,48,49,49,50,50,196,196,196,196,196,196,197,197,198,198,198,197,198,198,198,197,198,198,197,196,197,197,198,197,198,60,192,192,196,192,197,196,197,197,198,197,198,198,198,196,197,197,198,198,198,197,198,197,198,197,198,197,195,195,195,196,198,197,198,196,197,197,195,197,195,195,195,193,193,196,193,197,193,197,193,196,197,197,198,198,196,196,198,197,198,196,196,196,197,197,197,197,198,198,198,198,195,195,194,196,194,197,193,197,193,197,197,198,197,198,194,198,198,197,198,197,198,198,197,196,193,196,197,197,198,198,197,196,196,193,197,193,197,193,197,193,197,193,198,194,198,194,198,193,198,194,198,198,197,193,196,193,197,193,197,193,197,193,198,193,198,194,198,198,198,198,198 +,109,252,109,252,252,252,252,252,252,252,108,252,108,252,108,108,109,108,109,108,252,252,252,252,252,108,108,108,108,108,108,108,109,108,108,108,252,108,252,108,252,252,108,108,252,109,252,252,252,252,109,108,108,108,108,108,252,252,252,252,252,252,108,108,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,252,109,252,109,252,252,252,252,252,252,252,252,109,107,109,107,109,107,107,107,109,109,109,109,109,107,21,21,41,20,21,21,43,21,21,20,45,21,21,21,35,20,21,21,39,21,21,21,34,21,21,21,42,21,21,21,45,21,21,21,39,21,21,21,32,20,21,21,41,21,21,20,33,21,21,21,36,21,21,21,39,21,21,21,33,21,21,21,33,20,21,21,36,21,21,20,38,21,21,21,41,21,21,21,44,21,21,20,47,21,21,21,47,21,21,21,46,21,20,21,45,21,21,21,43,20,21,21,43,21,21,20,44,21,21,21,34,20,21,21,38,21,21,21,41,21,21,21,45,20,21,21,32,21,21,20,32,21,21,21,36,21,21,21,40,21,21,20,33,21,21,34,36,36,37,38,39,39,40,41,42,43,44,44,48,49,50,51,53,54,55,56,57,58,60,60,62,63,48,49,51,51,53,54,55,56,32,33,34,35,215,215,215,215,211,211,215,215,215,215,215,215,215,215,215,215,215,212,215,213,46,46,46,46,46,46,46,46,32,212,21,215,213,214,46,46,46,46,46,46,46,46,46,46,47,21,21,21,21,21,21,47,47,47,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,32,32,32,32,32,33,33,33,33,33,33,33,32,33,33,33,33,34,34,34,34,35,35,35,35,36,36,36,36,37,37,38,38,38,38,39,39,40,40,40,40,41,41,41,41,42,42,42,42,43,43,44,44,44,44,45,45,45,46,46,46,47,47,47,48,49,49,49,49,50,50,51,51,52,196,196,196,197,196,196,196,197,197,198,197,198,198,197,197,198,197,198,193,197,197,197,197,198,198,198,192,196,192,196,196,197,197,197,197,198,198,198,196,197,197,198,198,198,197,197,197,195,195,197,197,196,197,197,197,198,198,198,198,197,197,197,197,195,197,195,197,196,196,196,193,197,197,196,196,197,194,198,197,198,196,196,197,198,193,197,194,197,196,197,197,198,197,198,195,198,198,198,197,196,196,196,197,196,197,197,197,197,198,197,198,198,197,198,197,198,198,198,197,193,196,193,197,198,198,197,196,196,196,196,196,197,197,197,197,197,197,197,197,197,197,197,197,196,198,198,198,198,197,196,196,197,196,197,197,197,197,197,197,198,198,198,194,198,194,198,198 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,108,109,108,109,108,252,108,252,252,108,108,108,108,109,108,109,108,252,108,252,108,252,108,252,108,108,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,107,107,107,252,107,252,107,252,107,252,109,252,109,252,252,252,252,252,252,109,107,109,107,109,107,107,107,109,107,109,107,109,107,37,21,41,21,44,21,32,21,42,21,46,21,32,21,37,21,42,21,32,21,33,21,35,21,35,21,37,21,37,21,39,21,40,21,41,21,42,21,43,21,44,21,45,21,46,21,47,21,39,21,41,21,42,21,44,21,45,21,32,21,42,21,43,21,33,21,32,21,32,21,47,21,36,21,38,21,39,21,41,21,42,21,43,21,45,21,46,21,47,21,32,21,33,21,34,21,35,21,36,21,37,21,38,21,38,21,39,21,40,21,41,21,42,21,47,21,43,21,44,21,32,21,35,21,37,21,47,21,41,21,40,21,45,21,47,21,41,21,42,21,44,21,45,21,47,21,40,21,32,21,41,203,203,202,42,39,40,40,41,41,42,42,43,42,44,44,45,44,45,45,47,209,41,209,21,209,32,46,21,209,21,208,21,209,215,215,215,215,47,208,32,34,37,39,42,44,47,212,21,211,21,47,21,215,215,213,213,215,47,47,47,47,47,47,47,47,47,47,45,46,21,211,21,211,21,21,47,47,47,47,47,47,47,47,33,32,33,32,33,32,33,32,33,32,33,33,34,33,34,33,34,33,34,34,34,32,33,32,33,33,34,33,35,34,35,35,36,35,36,36,37,36,37,37,38,37,38,38,39,39,40,39,40,40,41,41,42,41,42,42,43,42,43,43,44,43,44,44,45,45,46,45,46,46,47,46,47,100,101,101,102,102,48,48,49,49,50,49,51,50,51,51,199,196,53,52,53,196,196,196,197,196,197,197,198,198,198,198,197,196,197,197,198,197,198,197,198,196,197,197,198,198,197,193,192,196,197,196,197,196,197,197,198,197,198,196,197,197,198,195,195,197,195,195,197,197,197,197,198,197,198,197,198,197,198,197,198,197,198,195,197,195,197,196,196,196,197,197,196,196,197,197,197,197,198,196,196,198,198,198,196,196,197,197,197,197,197,197,198,198,198,195,195,195,198,196,196,197,193,197,196,197,197,198,194,198,194,197,198,197,198,198,198,198,197,197,196,196,197,197,198,196,196,196,197,193,197,196,197,193,197,197,197,194,197,197,198,194,196,197,198,197,196,198,197,193,196,196,197,193,197,197,197,193,198,197,198,193,198,194,198,197,197 +,252,252,109,252,252,252,252,252,252,252,108,252,108,252,108,252,252,108,109,252,109,252,252,252,252,252,108,108,108,108,108,108,108,108,108,108,109,108,252,108,108,108,108,108,108,108,252,108,252,108,252,252,108,108,252,108,252,108,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,252,109,252,252,252,252,252,252,252,252,252,252,109,107,109,107,109,107,107,109,109,107,109,107,107,36,37,37,39,39,32,21,34,34,35,36,37,38,39,21,40,41,42,43,44,44,45,21,35,37,40,42,45,32,33,21,36,37,38,39,41,42,43,21,46,47,40,32,34,35,37,21,40,41,32,34,36,38,41,21,45,47,40,41,41,41,42,21,43,43,43,43,44,44,45,21,32,34,41,37,45,40,44,21,32,47,36,37,40,38,43,21,47,41,38,32,40,33,43,21,46,34,38,35,40,36,42,21,44,38,45,39,47,40,37,21,39,41,40,33,41,32,43,21,44,44,45,32,47,37,33,21,34,47,35,34,36,32,37,21,38,42,39,47,32,47,33,21,35,39,36,40,37,40,38,21,39,210,34,203,202,203,202,203,203,210,202,203,202,203,202,203,36,203,37,204,203,202,203,203,21,203,203,204,203,204,204,204,215,215,21,209,21,213,215,214,21,215,213,215,215,212,215,215,215,32,32,32,32,32,32,32,33,32,33,214,33,33,33,215,214,214,213,214,33,33,33,33,34,33,34,34,34,34,34,34,34,34,34,34,34,34,35,34,35,35,35,35,35,35,35,35,32,32,33,33,33,33,34,34,34,34,35,196,197,197,36,36,37,37,37,37,38,38,38,38,39,39,40,40,40,40,41,41,41,41,42,42,43,43,43,43,44,44,44,44,45,45,45,45,46,46,47,47,47,97,98,98,99,99,100,100,101,48,48,49,49,49,50,50,51,51,51,52,52,52,53,192,196,196,196,198,196,196,197,196,196,196,197,197,198,198,197,197,198,198,196,198,197,197,197,197,198,198,198,198,198,198,192,196,192,196,196,196,196,197,198,197,197,197,198,197,198,195,195,197,195,195,197,197,197,197,197,197,197,197,198,198,198,198,198,198,198,196,196,196,197,196,196,196,196,196,196,196,197,196,198,197,198,198,197,196,198,198,196,196,197,196,197,196,197,197,198,197,198,198,198,198,198,198,197,196,196,197,197,197,197,197,197,198,197,197,197,197,198,197,198,198,198,198,197,196,197,197,198,196,196,196,196,196,197,196,197,197,197,197,197,197,197,197,197,197,198,196,197,197,198,196,198,197,196,196,196,196,197,197,197,197,197,197,198,197,198,194,198,198,198,197 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,108,109,108,252,108,252,109,252,109,108,109,108,108,109,108,252,108,109,108,252,108,108,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,108,107,109,107,252,107,252,107,252,107,252,109,252,109,252,252,252,252,252,252,109,107,109,107,109,107,109,107,109,107,109,107,36,21,37,21,39,21,40,21,42,21,43,21,45,21,32,21,36,21,39,21,42,21,46,21,38,21,32,21,34,21,36,21,39,21,42,21,32,21,34,21,36,21,38,21,33,21,35,21,36,21,43,21,40,21,42,21,44,21,46,21,47,21,42,21,43,21,32,21,37,21,42,21,47,21,32,21,34,21,35,21,36,21,37,21,38,21,40,21,46,21,35,21,32,21,33,21,36,21,43,21,36,21,37,21,38,21,39,21,40,21,41,21,42,21,42,21,43,21,44,21,45,21,46,21,47,21,32,21,32,21,32,21,34,21,35,21,37,21,38,21,40,21,41,21,43,21,44,21,46,21,47,21,32,21,32,21,32,38,32,39,32,40,32,42,32,43,32,44,32,45,32,46,32,38,32,34,32,37,32,41,32,45,32,46,32,40,32,41,32,41,32,42,32,35,36,35,36,35,36,35,36,35,36,36,36,36,36,36,36,36,36,36,37,36,37,36,37,36,37,36,37,36,37,36,37,36,37,36,37,36,37,36,37,32,33,32,33,33,34,33,34,34,35,34,35,35,36,35,36,36,37,36,37,37,38,37,196,196,197,197,198,197,197,197,198,40,41,40,41,41,42,41,42,42,43,42,43,43,44,43,44,44,45,44,45,45,46,45,46,46,47,46,47,47,101,101,102,102,96,96,97,97,48,48,49,49,50,50,51,51,52,51,199,199,196,196,196,196,198,198,56,199,196,196,197,197,198,196,197,196,197,196,197,197,198,198,197,197,198,198,198,193,199,199,197,196,197,197,198,197,198,198,198,196,196,196,196,196,196,197,198,197,197,197,198,197,198,197,195,195,195,197,197,197,197,197,198,197,198,197,198,197,198,198,198,197,198,196,196,196,197,197,198,197,198,197,198,196,196,197,197,197,198,198,196,196,196,198,198,197,196,196,196,196,197,197,197,197,198,198,198,198,198,197,198,197,196,196,197,196,197,197,197,196,197,197,198,197,198,197,198,197,198,198,198,197,196,196,198,198,196,196,197,193,197,196,197,193,197,196,197,193,197,197,198,194,198,196,197,194,198,198,196,198,197,196,197,193,197,196,197,193,197,197,198,193,198,197,198,197,198,197,197 +,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,108,109,252,109,108,252,252,252,252,108,252,108,109,108,108,108,108,252,108,108,108,108,108,108,108,108,108,108,108,252,108,252,108,252,252,108,108,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,107,109,107,252,109,252,109,252,252,252,252,252,252,252,107,109,107,109,107,109,107,109,107,109,107,107,35,33,36,35,37,37,39,39,40,41,41,43,42,45,44,47,45,32,33,34,34,35,36,37,37,38,39,40,40,41,42,43,43,44,45,46,46,47,34,40,35,41,41,42,47,44,36,45,37,46,37,47,32,39,36,41,39,43,43,45,47,47,32,38,33,32,35,34,36,37,38,40,34,42,39,44,44,47,34,36,35,37,33,39,36,40,39,41,41,43,44,44,47,45,44,46,45,34,46,35,36,36,32,37,38,38,44,39,34,41,38,42,41,43,45,44,44,45,45,46,46,47,32,35,40,36,41,36,32,36,39,40,38,40,39,42,40,32,41,37,32,42,44,47,33,44,36,42,39,42,42,47,45,46,44,46,44,46,45,46,32,46,33,46,33,32,34,32,34,32,35,32,32,32,35,32,204,203,41,32,209,203,204,215,215,40,35,35,213,36,213,36,35,214,214,215,215,36,212,215,212,36,36,36,36,36,212,36,213,214,213,214,214,37,36,36,36,37,32,32,211,33,211,33,214,34,34,34,34,35,35,35,35,36,36,36,36,37,37,37,37,37,37,38,38,38,38,39,39,39,39,40,40,40,197,197,197,197,197,198,198,198,198,198,198,198,198,198,43,44,44,44,44,45,45,45,45,46,46,46,46,47,47,47,47,97,97,98,98,99,99,100,100,101,48,48,49,49,50,50,50,51,51,52,52,53,53,54,54,55,199,192,196,196,196,196,197,198,198,198,199,196,196,196,196,198,198,198,196,197,196,196,197,197,198,198,197,198,198,198,197,199,199,196,196,198,198,197,197,198,198,198,197,196,196,196,196,196,197,198,198,198,197,197,197,198,198,198,198,197,197,197,197,197,198,197,197,198,197,198,197,198,198,198,198,198,196,196,196,197,197,197,197,198,198,198,197,196,196,197,198,197,197,196,196,197,196,198,198,198,196,197,196,197,196,197,197,198,197,198,198,198,198,198,198,197,196,196,196,197,196,197,196,197,197,197,197,197,197,198,197,198,198,198,198,198,197,197,197,196,196,196,196,197,196,197,196,197,197,197,197,197,197,197,197,198,196,196,197,197,198,198,197,198,197,196,196,197,196,197,197,197,197,197,197,198,198,198,198,198,198,197,197 +,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,108,109,108,109,252,252,252,252,252,108,109,108,109,252,108,252,108,252,108,108,108,109,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,109,252,252,252,252,252,252,252,252,252,109,107,107,107,107,252,107,252,107,252,107,252,109,252,109,252,252,252,252,252,107,109,107,109,107,109,107,109,107,107,107,107,21,41,21,41,21,41,21,33,21,35,21,36,21,38,21,39,21,41,21,43,21,44,21,46,21,47,21,34,21,37,21,39,21,42,21,45,21,47,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,41,21,36,21,43,21,41,21,41,21,33,21,34,21,35,21,36,21,37,21,38,21,39,21,40,21,41,21,41,21,43,21,43,21,45,21,45,21,47,21,47,21,47,21,32,21,37,21,41,21,45,21,47,21,36,21,36,21,36,21,36,21,37,21,37,21,37,21,42,21,47,21,47,21,35,21,41,21,47,21,47,21,47,21,47,42,32,43,32,44,32,44,32,45,32,45,32,46,32,47,32,47,40,37,40,38,47,39,47,32,47,33,32,34,47,35,32,36,32,37,32,38,35,35,35,34,35,34,35,34,35,35,35,36,37,36,36,36,37,36,32,32,33,32,33,33,34,33,34,34,35,34,35,34,35,35,36,35,36,36,37,36,37,36,37,37,38,37,38,38,39,38,39,39,40,39,40,40,41,40,41,41,42,41,42,41,42,42,197,196,197,196,197,197,198,197,198,197,198,197,198,198,198,197,198,46,47,46,47,47,47,102,103,96,97,98,99,100,101,102,96,96,48,48,49,49,50,50,51,51,52,52,53,53,54,53,55,55,56,55,56,56,58,196,192,196,196,196,196,197,198,197,198,198,198,192,196,196,196,196,197,197,198,197,198,196,196,196,197,197,198,198,198,197,198,198,199,196,196,196,197,197,198,198,198,197,197,198,197,196,197,196,196,197,197,197,198,197,198,197,197,197,198,197,198,197,197,197,197,198,198,197,198,197,198,197,198,198,198,198,198,198,196,196,197,197,198,197,198,197,198,197,196,196,197,198,198,197,196,196,197,197,198,197,198,198,198,196,197,197,197,197,198,198,198,198,198,198,198,197,198,196,197,196,197,196,197,196,197,197,197,197,197,197,198,197,198,197,198,197,198,198,198,197,196,196,197,196,197,196,197,196,197,196,197,193,197,197,198,197,198,197,196,193,197,197,198,198,197,198,197,193,196,196,197,196,197,197,198,193,198,197,198,197,198,197,197,197,197 +,252,252,109,252,252,252,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,109,252,252,109,252,252,108,252,108,252,108,252,108,108,108,108,108,108,108,108,108,108,108,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,109,252,109,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,107,109,107,107,107,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,32,21,36,21,40,21,43,21,47,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,32,21,42,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,44,21,32,33,34,21,36,21,37,21,39,21,41,21,43,21,44,21,46,21,47,21,32,21,32,21,32,21,32,21,32,21,32,21,32,44,32,46,36,44,36,45,36,45,36,46,36,47,34,203,46,46,47,47,47,40,47,203,47,203,47,34,34,34,35,34,35,34,35,34,35,34,35,32,32,32,33,33,33,33,33,33,34,34,34,34,35,35,35,35,35,35,36,36,36,36,36,36,37,37,37,37,38,38,38,38,38,38,39,39,39,39,39,39,40,40,40,40,41,41,41,41,41,41,42,42,42,42,43,42,43,43,43,43,44,44,44,196,197,197,197,197,197,197,197,197,198,197,198,198,198,198,198,197,198,198,198,101,101,102,102,102,103,103,96,48,49,49,50,50,51,51,52,52,53,53,53,54,54,55,55,56,56,57,57,58,58,59,59,59,196,196,196,192,196,196,197,197,197,197,197,197,198,198,196,196,196,196,196,197,198,198,197,197,198,198,198,198,197,197,197,198,198,198,198,198,196,196,196,196,197,197,197,198,198,197,198,197,196,196,197,197,198,197,197,198,198,198,198,198,197,197,197,198,198,197,198,197,197,197,198,198,197,197,197,197,198,198,198,198,198,198,196,196,197,197,197,198,198,196,196,196,196,197,198,198,198,197,196,196,197,197,197,197,198,197,198,197,198,198,197,197,197,197,198,197,198,198,198,198,198,197,196,196,196,196,197,196,197,197,197,197,197,197,197,197,198,198,198,198,198,197,197,197,198,196,196,196,196,196,197,196,197,197,197,197,197,197,197,197,197,197,197,196,197,197,197,197,198,197,198,197,196,196,196,196,197,197,197,197,197,197,198,198,198,198,197,197,197,198 +,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,108,252,108,252,252,252,108,108,108,108,252,108,109,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,107,252,107,252,109,252,109,252,252,252,252,109,107,109,107,109,107,109,107,109,107,107,34,32,35,32,37,32,38,32,39,32,41,32,42,32,32,32,33,32,34,32,36,32,37,32,38,32,39,32,40,32,41,32,32,32,34,32,35,32,37,32,38,32,40,32,41,32,43,32,44,32,46,32,36,32,38,32,40,32,42,32,44,32,47,32,39,32,42,32,45,32,32,32,46,32,35,32,36,32,37,32,38,32,39,32,35,32,41,32,46,32,35,32,36,32,32,32,33,32,34,32,32,32,32,32,33,34,34,36,35,39,35,42,36,45,37,47,38,32,38,32,21,32,21,32,21,32,21,32,21,32,21,32,21,47,21,46,21,47,21,46,21,40,21,40,21,40,46,40,37,42,38,40,39,40,32,40,32,40,39,40,46,35,35,35,35,35,35,35,35,35,35,35,35,32,32,33,32,33,33,34,33,34,33,34,34,35,34,35,34,35,35,36,35,36,36,37,36,37,36,37,215,38,37,38,37,38,38,212,38,39,39,215,39,212,39,40,211,41,40,41,40,41,42,42,42,42,42,43,42,43,42,43,43,44,43,44,43,44,44,45,44,45,45,46,45,46,45,197,196,197,196,197,197,197,197,198,197,198,197,198,197,198,198,198,197,198,197,198,198,198,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,196,196,196,196,196,196,196,196,196,197,196,198,197,198,198,196,196,196,196,196,196,198,197,198,197,198,197,198,197,198,197,198,198,197,197,198,198,198,198,196,196,197,196,196,196,197,197,198,197,198,197,198,197,198,196,197,197,198,198,198,197,198,197,198,197,197,197,198,198,198,197,197,197,197,198,198,197,198,197,198,197,198,197,198,198,196,196,197,197,198,197,196,196,196,196,197,197,198,197,198,197,196,196,197,196,197,197,197,197,198,197,198,198,197,196,197,197,198,197,198,197,198,198,198,197,196,196,197,196,197,196,196,196,197,197,198,198,198,197,198,198,198,197,198,197,198,196,196,196,197,196,197,196,197,196,197,196,197,196,197,197,197,197,198,197,198,197,196,196,197,197,198,198,198,198,197,196,197,196,197,196,197,197,198,197,198,197,198,198,197,198,197,197,197 +,109,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,252,108,252,108,109,108,108,108,108,108,108,108,108,108,108,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,252,109,252,109,252,252,252,252,252,252,252,252,252,252,109,107,109,107,109,107,109,107,107,107,107,34,35,34,35,35,35,36,35,36,35,37,35,38,35,38,35,39,35,40,35,40,35,41,35,42,35,42,35,43,35,44,35,45,35,45,35,46,35,46,35,41,36,41,36,42,36,42,36,43,36,43,36,44,36,44,36,32,36,36,36,40,36,45,36,40,36,43,36,46,36,36,36,37,36,37,36,38,36,39,36,40,36,46,36,32,36,32,36,33,36,33,36,34,36,34,36,35,36,35,36,32,36,34,36,37,36,32,36,33,36,34,36,35,45,36,40,37,40,38,40,39,40,32,40,34,40,35,40,21,40,21,32,39,32,41,32,42,32,43,47,45,47,46,47,33,47,34,47,35,43,37,43,33,43,35,43,37,43,39,33,35,32,32,33,33,33,33,33,33,34,33,34,34,34,34,35,35,35,35,36,36,36,203,36,36,37,36,204,37,37,37,38,215,38,215,39,39,39,39,39,39,40,39,40,40,40,40,41,41,41,41,42,42,42,42,42,42,43,43,43,43,43,43,44,44,44,44,45,45,45,197,45,45,46,46,46,46,46,46,47,47,47,99,197,196,197,196,197,197,197,197,197,197,197,197,198,197,198,197,198,198,198,198,198,198,198,198,198,198,198,53,54,54,55,55,56,57,57,57,58,59,59,60,61,61,61,62,63,63,64,64,66,66,196,196,196,196,196,196,196,196,196,197,198,196,197,197,198,198,197,197,196,196,196,196,197,196,197,197,198,197,198,198,198,197,197,197,198,198,198,198,198,198,198,198,198,196,196,196,197,197,197,197,198,197,198,198,198,198,198,198,198,196,197,198,198,197,197,197,199,196,197,197,198,197,197,197,198,198,198,198,198,197,197,197,198,198,198,198,198,198,198,196,196,197,197,197,196,196,197,196,197,197,198,198,198,197,197,196,196,196,197,197,197,197,197,197,198,198,198,197,197,197,197,197,198,198,198,198,198,198,196,196,197,197,197,197,197,197,198,197,198,198,198,197,198,197,197,196,196,196,196,196,196,198,196,196,196,196,196,196,197,197,197,197,197,197,197,197,197,197,197,197,198,196,196,197,197,198,198,197,198,197,196,196,197,196,197,197,197,197,197,197,198,198,198,198,196,197,198,197 +,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,109,108,108,252,108,108,108,252,108,109,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,252,252,109,252,252,252,107,109,107,109,107,109,107,109,107,107,107,38,34,38,35,38,35,38,36,38,37,38,38,38,38,38,39,38,40,38,40,38,41,38,42,38,42,38,43,38,44,38,45,38,45,38,46,38,47,38,39,40,39,40,39,40,39,40,40,40,40,40,41,40,32,40,33,40,34,40,36,40,37,40,38,40,39,40,41,40,42,40,43,40,45,40,46,40,44,40,46,40,43,40,45,40,32,40,33,40,33,40,34,40,35,40,32,40,32,40,33,40,34,40,35,40,32,40,33,40,34,40,36,40,32,40,33,44,35,44,37,44,33,44,36,45,39,45,42,45,45,40,37,40,38,40,40,40,41,40,42,32,43,32,44,32,45,32,47,32,32,47,34,47,35,47,36,47,37,47,39,34,34,35,36,38,38,40,40,42,42,44,45,46,47,35,35,32,35,38,41,44,46,37,37,37,37,38,37,38,38,39,38,39,39,40,39,40,39,40,40,41,40,41,41,42,41,42,42,43,42,43,43,44,43,44,44,45,44,45,45,46,45,46,46,47,46,47,47,197,197,198,198,97,96,98,97,98,98,99,197,198,197,198,198,198,196,197,197,197,197,197,197,198,197,198,197,198,197,198,198,198,198,198,197,198,197,198,198,198,198,59,59,60,60,61,61,62,62,63,89,90,89,90,90,91,64,66,66,69,69,196,196,196,196,196,196,196,196,198,197,198,197,198,197,196,197,198,197,198,197,196,196,197,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,197,198,198,198,198,198,196,196,196,197,196,197,197,197,198,197,197,198,198,198,197,198,198,198,197,198,197,198,199,199,196,193,197,197,197,198,197,197,197,198,197,198,198,198,197,198,197,198,197,198,198,198,196,196,196,197,197,196,196,197,196,197,197,198,197,198,198,198,196,196,196,197,196,197,197,198,197,198,198,198,196,197,197,198,197,198,197,198,197,198,198,198,196,197,196,197,197,198,197,198,197,198,197,198,196,196,196,196,196,196,196,196,196,198,198,196,196,197,197,198,196,197,196,197,196,197,196,197,196,197,197,198,197,198,197,196,196,197,197,198,198,198,198,198,196,196,196,197,196,197,197,198,197,198,197,198,198,196,197,198,197,198 +,109,252,108,252,108,252,108,252,108,252,108,252,252,252,252,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,108,108,108,108,108,108,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,252,109,252,109,252,252,252,252,252,252,252,252,107,107,109,107,109,107,109,107,109,107,107,107,41,35,41,35,41,36,41,37,41,38,41,39,41,39,41,40,41,41,41,42,41,43,41,43,41,44,41,45,41,46,41,46,41,39,41,40,41,42,41,43,43,45,43,46,43,39,43,39,43,39,43,32,43,33,43,33,43,34,43,35,43,36,43,37,43,38,43,38,43,39,43,40,43,41,43,42,43,42,43,43,43,44,43,45,43,46,43,46,43,45,43,45,43,45,43,45,43,46,43,46,43,46,43,47,43,47,43,32,43,34,43,35,43,36,32,32,34,33,35,34,37,35,39,36,40,37,42,37,44,38,45,39,47,40,47,41,47,32,46,35,46,38,32,41,32,44,32,47,32,34,32,35,32,36,32,37,32,38,32,38,32,39,32,40,32,41,32,42,32,43,32,32,33,33,33,33,34,34,35,32,33,34,35,35,37,37,38,39,40,41,42,42,44,44,45,46,47,42,43,213,44,44,44,44,45,45,46,46,47,47,98,98,99,99,214,99,100,214,100,100,101,101,101,101,101,196,197,197,197,197,198,198,103,103,197,197,197,197,197,197,197,197,197,197,198,197,198,197,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,128,128,129,130,130,88,88,89,89,89,89,89,89,90,64,66,68,70,72,75,77,79,50,196,196,196,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,197,198,198,198,198,198,197,198,198,198,198,198,198,198,198,196,196,197,198,196,197,197,197,197,198,197,198,197,198,198,198,198,196,196,196,199,199,196,196,197,196,197,197,198,194,198,198,197,197,198,198,198,197,197,197,198,198,198,198,198,196,196,196,197,197,197,196,196,196,196,197,197,197,198,198,198,196,196,196,197,197,197,197,197,197,198,198,198,197,197,197,197,197,198,197,198,198,198,198,198,198,197,197,197,197,198,197,198,198,198,196,196,196,196,196,196,196,196,196,197,197,198,196,196,197,197,197,198,198,196,196,196,196,197,197,197,197,197,197,197,197,197,197,196,196,197,197,197,198,198,197,198,197,196,196,196,196,197,197,197,197,198,198,198,198,196,197,197,197,198,198 +,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,108,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,252,107,252,107,252,107,252,109,252,252,252,252,252,107,109,107,109,107,109,107,107,107,107,107,107,32,44,33,44,34,44,35,44,36,44,37,44,38,44,39,44,41,44,42,44,43,44,44,44,45,44,46,44,44,44,46,44,37,44,38,44,39,44,40,47,41,47,42,47,43,47,44,47,45,47,46,47,32,47,32,47,33,47,34,47,35,47,35,47,36,47,37,47,37,47,38,47,39,47,39,47,40,47,41,47,42,47,42,47,43,47,44,47,45,47,45,47,46,47,47,47,36,47,37,47,38,47,38,47,39,47,40,47,34,47,39,47,44,47,32,47,33,47,34,47,35,47,35,32,36,32,37,32,38,32,39,32,40,32,41,32,32,32,33,32,35,36,36,36,38,36,39,36,41,36,42,36,44,36,45,36,47,36,37,36,38,36,38,36,39,36,40,36,41,36,41,32,42,32,43,32,44,32,45,32,32,33,33,34,34,35,34,36,35,37,36,38,37,39,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,99,99,100,99,100,100,101,100,101,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,197,197,198,197,198,197,198,197,198,197,198,197,198,197,198,197,198,198,198,198,134,134,136,136,138,139,141,143,143,198,128,129,129,130,64,66,68,69,72,73,76,77,79,64,67,69,72,74,77,79,79,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,198,198,198,198,198,198,198,198,198,198,198,198,198,197,198,197,198,198,196,198,198,198,198,198,197,196,197,197,197,198,197,197,197,197,197,197,198,197,198,198,198,198,197,197,199,196,196,196,196,196,197,197,198,197,198,197,198,197,198,197,198,198,197,197,198,197,198,198,198,198,196,196,197,196,197,196,197,196,196,197,198,197,198,197,198,197,196,196,197,196,197,197,198,197,198,197,198,196,197,197,197,197,198,197,198,197,198,198,198,197,198,196,197,197,198,197,198,198,198,196,196,196,196,196,196,196,197,196,197,197,198,196,197,196,197,197,198,197,198,196,197,196,197,196,197,196,197,196,197,197,197,197,198,196,197,196,197,197,198,198,198,198,196,196,197,196,197,196,197,197,198,197,198,197,196,197,197,197,198,198,198 +,109,252,108,252,108,252,108,252,252,252,108,252,252,252,252,252,108,108,108,108,109,252,109,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,107,107,252,252,252,252,252,252,252,252,252,107,107,107,109,107,109,107,109,107,109,107,107,107,107,32,47,33,47,33,47,33,47,33,47,34,47,32,47,34,47,35,47,36,47,37,47,39,47,40,47,41,47,42,47,44,47,45,47,46,47,39,47,40,32,40,32,41,32,42,32,43,32,43,32,44,32,45,32,46,32,32,32,33,32,34,32,35,32,36,32,37,32,37,32,39,32,39,32,40,32,41,32,42,32,43,32,44,32,45,32,46,32,47,32,32,32,34,32,35,32,37,32,39,32,41,32,43,32,44,32,46,32,43,32,45,32,46,32,33,32,33,32,35,32,35,36,37,36,37,36,39,36,40,36,41,36,42,37,43,37,32,37,33,37,34,40,35,40,36,40,37,39,38,40,39,40,40,40,42,39,43,40,44,40,45,40,46,39,47,40,39,40,39,40,40,37,41,37,42,37,42,37,43,32,44,32,45,32,45,32,46,32,38,32,32,33,33,34,35,35,36,36,37,37,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,197,196,196,196,196,197,196,134,135,136,136,138,138,32,33,35,36,37,38,40,41,42,43,45,46,47,136,40,139,140,141,142,143,128,129,130,131,132,133,135,135,137,138,139,140,142,143,143,143,128,129,129,128,64,64,65,65,66,66,67,67,67,68,68,69,69,69,70,70,71,71,72,72,72,73,73,74,74,74,75,75,76,76,77,77,77,78,78,79,79,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,197,196,196,197,197,197,197,198,197,197,197,197,198,197,198,198,196,192,196,196,197,196,196,196,197,197,197,197,198,198,198,198,198,198,198,198,197,197,197,197,198,198,198,198,196,196,196,196,197,197,196,196,197,196,197,197,198,198,198,198,198,196,196,196,197,197,197,197,198,198,198,197,197,197,197,197,198,197,198,197,198,198,198,198,198,197,197,197,198,198,198,197,198,198,196,196,196,196,196,196,197,197,197,197,196,196,196,196,197,197,198,198,198,197,197,196,197,197,197,196,198,198,197,197,197,197,197,196,196,197,197,197,198,198,198,197,198,196,196,196,197,197,197,197,198,198,198,198,196,196,197,197,198,197,198,198 +,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,109,108,252,108,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,108,108,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,107,252,107,252,107,252,107,252,109,252,107,252,252,107,107,109,107,109,107,109,107,109,107,107,107,107,107,32,32,32,32,32,33,32,33,32,33,32,33,32,33,32,33,32,32,32,32,32,33,32,33,32,36,32,38,32,41,32,44,32,47,32,38,32,39,35,39,35,40,35,41,35,41,35,42,35,43,35,43,35,44,35,45,35,46,35,32,35,33,35,33,35,34,35,35,35,36,35,37,35,38,35,38,35,39,35,40,35,41,35,42,35,43,35,44,35,45,36,45,36,46,36,41,36,42,36,42,36,42,36,42,36,42,36,42,36,43,36,43,37,43,37,43,37,32,37,33,37,35,40,36,40,38,40,39,40,40,40,41,40,43,42,44,42,45,42,47,44,32,43,33,44,34,43,35,44,36,43,33,44,37,43,41,44,45,43,41,44,42,43,43,44,44,43,45,44,46,42,47,32,46,34,46,35,32,37,34,38,37,40,40,41,43,43,45,44,32,46,46,47,38,39,38,39,38,39,38,39,38,39,32,33,33,35,35,36,36,38,38,39,39,41,41,42,42,44,44,44,32,33,33,34,34,35,35,37,36,38,38,39,39,40,40,41,41,43,42,44,44,45,45,46,46,47,59,60,61,63,63,48,49,50,50,52,52,54,54,55,56,57,57,59,59,61,61,62,63,64,64,64,65,65,66,66,66,67,67,67,68,68,68,69,69,70,70,70,70,71,71,72,72,70,69,70,70,71,70,72,71,72,72,73,72,74,73,74,74,75,74,75,75,76,75,76,76,77,76,77,77,78,78,79,78,79,219,219,219,196,196,196,196,196,196,196,196,196,197,197,198,198,197,198,198,198,198,196,198,197,196,197,196,196,196,197,196,197,197,198,198,198,197,198,198,198,197,198,198,197,197,198,197,198,197,198,196,196,196,197,197,198,196,196,196,197,196,197,197,198,197,198,196,197,196,197,197,197,197,198,197,198,198,197,197,197,197,197,197,198,197,198,198,198,198,198,198,197,196,197,197,198,198,198,197,196,196,196,196,197,196,197,197,198,197,198,196,197,196,197,197,198,197,198,198,198,197,198,197,198,197,196,197,198,197,198,196,197,198,196,196,197,197,198,197,198,198,198,198,196,196,197,196,197,197,198,197,198,198,196,196,197,197,198,197,198,198,198 +,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,108,108,108,108,109,252,109,108,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,108,108,108,108,108,108,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,109,107,252,107,252,252,252,252,252,252,252,107,107,107,109,109,109,109,109,107,109,107,109,107,107,107,35,33,35,34,35,39,35,44,35,33,35,34,35,34,35,34,35,34,35,32,35,33,35,34,35,34,35,35,35,36,35,37,35,37,35,38,35,39,37,40,37,41,37,41,37,32,37,35,37,37,37,40,37,43,37,45,37,47,38,32,38,33,38,34,38,34,38,35,38,36,38,37,38,37,38,38,38,39,38,40,38,41,38,41,38,42,38,43,39,44,40,44,39,45,40,46,39,47,40,42,39,42,40,43,39,43,40,43,39,43,42,43,42,44,42,44,42,44,42,44,43,44,43,33,43,35,43,37,43,39,43,42,47,44,47,46,47,46,47,46,47,32,47,33,47,34,47,35,47,35,47,36,47,37,47,38,47,38,47,39,47,40,47,41,47,41,47,42,47,43,47,44,47,45,47,45,47,46,47,47,47,45,47,40,40,40,41,40,32,32,33,33,34,34,34,35,35,35,36,36,37,37,37,38,38,38,39,35,36,39,40,40,41,41,42,42,43,43,43,44,43,44,44,44,45,44,45,46,44,45,46,46,46,46,46,47,102,47,103,96,103,98,96,98,98,97,97,54,98,55,99,56,57,58,58,58,102,100,54,55,55,56,56,57,57,58,58,58,62,62,62,62,63,63,65,64,63,66,63,65,65,64,65,66,65,66,67,67,68,66,68,69,70,70,71,71,72,72,70,70,70,70,71,71,72,72,72,72,73,73,74,74,74,74,75,75,76,76,76,77,77,77,78,78,78,79,79,196,196,196,196,196,197,197,197,197,197,197,198,198,198,198,198,197,198,196,196,196,196,196,196,196,197,196,197,196,197,197,198,197,198,197,198,198,198,198,219,219,219,219,219,219,219,219,219,196,196,196,197,197,197,196,196,196,196,197,197,197,197,197,198,198,196,196,197,197,197,197,197,197,198,198,197,197,197,197,197,197,198,197,198,198,198,198,198,198,198,197,197,197,198,198,198,198,196,196,196,196,197,197,197,197,198,198,198,196,196,196,197,197,197,197,198,198,198,197,197,197,197,197,196,197,197,198,197,196,197,197,197,198,198,197,197,197,198,198,198,198,198,196,196,196,197,197,197,197,198,198,196,196,197,197,198,197,198,198,198,198 +,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,109,108,252,108,252,252,252,108,252,108,252,252,252,252,252,252,252,252,108,252,252,108,252,252,108,108,252,108,109,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,252,107,109,107,109,107,109,109,109,107,109,107,107,107,107,34,37,35,37,37,37,38,37,40,37,41,37,43,37,44,37,46,37,34,37,34,38,35,38,35,38,32,38,33,38,35,38,36,38,37,38,38,40,39,40,40,40,41,40,32,40,33,40,34,40,35,40,36,40,36,40,37,40,38,41,39,41,40,41,41,41,42,41,43,41,44,41,44,41,45,41,46,41,38,41,39,41,40,41,40,41,41,41,42,44,43,43,43,44,44,43,45,44,45,43,46,44,47,43,43,44,44,43,44,44,44,47,44,47,44,47,45,47,45,47,45,47,45,47,45,47,46,47,46,47,46,47,39,39,39,39,39,39,39,47,42,47,32,47,33,47,34,47,34,47,35,47,36,47,37,47,37,47,38,47,39,33,32,33,32,33,33,34,33,34,34,35,34,35,35,36,35,36,35,36,36,37,36,37,37,38,37,38,37,38,38,39,38,39,39,40,39,40,40,41,40,41,40,41,41,42,38,39,41,42,36,42,43,40,42,41,43,43,44,43,44,45,44,45,44,46,46,45,45,45,46,45,47,46,45,47,45,96,46,46,46,47,98,99,101,99,100,101,50,52,50,53,53,53,54,55,55,57,102,100,54,55,55,56,56,57,57,58,58,58,58,58,61,62,61,61,62,62,62,62,62,64,62,63,65,66,65,65,66,67,67,67,68,67,68,70,70,70,70,71,71,72,72,69,69,70,70,71,71,72,72,73,73,74,74,75,75,76,76,77,77,78,78,79,79,79,196,196,196,197,196,197,196,197,197,198,197,198,197,198,198,198,197,198,198,196,196,197,196,197,196,197,197,197,197,197,197,197,197,197,197,198,197,198,198,198,198,197,219,219,219,219,219,219,196,196,196,196,196,197,197,196,196,196,196,197,197,198,197,198,198,198,196,197,196,197,196,197,197,198,197,198,196,197,197,197,197,198,197,198,197,198,198,198,197,198,198,197,197,198,198,198,196,197,196,196,197,198,197,196,196,197,197,198,198,196,196,197,196,197,197,198,197,198,198,198,197,198,197,196,196,198,198,198,196,197,196,197,197,198,198,197,197,198,197,198,198,198,197,198,196,197,196,197,197,198,197,198,196,197,196,198,197,198,198,198,198,198 +,252,252,109,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,108,108,108,108,109,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,252,252,108,108,108,108,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,107,252,107,252,107,252,252,252,252,252,252,107,107,109,109,109,109,109,107,109,107,109,107,107,107,40,34,40,35,40,36,40,36,40,37,40,38,40,39,40,39,40,40,40,41,41,42,41,42,41,43,41,44,41,45,41,46,41,47,41,37,41,32,42,33,42,33,42,34,42,35,42,35,42,32,42,33,42,34,42,34,42,35,44,36,44,37,44,38,44,39,44,39,44,40,44,41,44,42,44,42,44,43,44,44,44,45,44,45,44,46,44,47,47,43,47,43,47,44,47,44,47,45,47,46,47,47,47,46,47,46,47,46,47,47,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,33,33,33,33,34,33,34,34,34,34,34,34,35,35,35,35,36,35,36,36,36,36,36,36,37,37,37,37,37,37,38,38,38,38,38,38,39,39,39,39,39,39,40,40,40,40,40,40,41,41,41,41,41,41,42,42,42,42,42,41,42,39,42,43,40,43,40,43,43,43,42,44,44,44,44,44,45,44,45,45,45,45,45,45,45,45,46,45,46,46,46,47,99,99,100,101,100,101,101,101,47,100,101,101,101,101,101,101,101,102,100,54,55,102,100,54,55,55,56,55,56,57,57,58,58,58,58,58,61,61,61,61,61,62,62,62,63,63,63,63,63,63,64,63,65,63,65,66,68,68,69,69,70,64,70,70,71,71,72,72,64,65,66,67,68,69,70,70,72,72,73,74,75,76,77,78,79,196,196,196,197,197,197,197,197,197,197,197,198,198,198,198,198,198,198,198,198,198,198,198,196,196,196,197,197,197,197,197,198,197,198,198,198,198,198,198,198,198,198,198,198,196,196,196,196,219,219,219,219,198,198,198,196,196,196,196,197,197,197,197,198,198,198,198,196,196,196,196,197,197,197,197,198,198,197,197,197,197,197,197,198,198,198,198,198,198,198,196,197,197,198,198,198,198,196,196,196,196,198,197,196,196,197,197,198,198,198,196,196,196,197,197,197,197,198,198,198,197,197,197,196,197,198,197,198,197,196,196,197,197,197,197,198,197,197,197,198,198,198,197,198,198,196,196,197,197,197,198,198,196,196,196,197,197,198,197,198,197,198,198 +,252,252,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,108,252,252,109,108,252,108,252,252,252,108,252,252,252,252,252,252,252,108,252,252,252,252,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,109,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,252,252,107,107,107,109,107,109,109,109,107,109,107,109,107,109,33,42,34,42,34,42,35,42,36,42,36,42,37,42,38,42,38,42,39,42,40,44,40,44,41,44,42,44,42,44,43,44,44,44,44,44,45,45,32,45,33,45,33,45,34,45,35,45,35,45,36,45,37,45,37,45,38,45,39,47,39,47,32,47,34,47,35,47,37,47,39,47,41,47,43,47,45,47,47,47,46,47,47,47,41,47,42,47,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,34,33,34,33,34,33,34,33,34,33,34,34,34,34,34,34,34,33,34,34,34,34,33,34,33,34,33,34,33,34,34,35,34,35,35,35,35,35,35,36,35,36,36,36,36,37,36,37,36,37,37,37,37,38,37,38,37,38,38,39,38,39,38,39,38,39,39,40,39,40,39,40,39,40,40,41,40,41,40,41,40,41,41,42,41,42,41,42,41,42,42,43,42,42,43,42,42,42,43,42,43,43,42,44,43,43,43,44,43,44,44,43,44,45,44,45,44,45,45,45,46,45,45,46,45,46,46,46,46,46,47,100,101,101,47,101,100,47,100,100,101,47,101,100,47,100,100,100,101,100,102,101,47,102,102,101,101,99,99,54,102,99,56,56,102,56,102,57,57,61,58,58,58,61,61,61,61,61,61,61,63,63,63,63,63,63,64,61,64,61,65,67,68,67,68,69,69,70,70,70,70,71,71,72,72,75,73,72,76,64,78,76,77,196,196,196,196,197,196,197,196,197,197,198,197,198,197,198,197,198,198,198,197,198,196,197,196,197,196,197,196,197,197,197,197,198,197,197,197,197,198,198,198,198,198,198,197,198,198,198,197,197,197,196,219,219,219,219,219,219,219,219,219,198,196,197,197,198,198,198,197,198,196,197,196,197,197,198,197,198,196,197,196,197,197,198,197,198,197,198,197,198,198,198,196,197,197,198,198,198,198,196,196,196,196,196,197,196,196,197,197,198,197,198,196,196,196,197,196,197,197,198,197,198,197,198,197,196,197,198,197,198,196,197,196,197,197,198,197,198,198,198,197,198,197,198,198,198,198,198,196,197,197,198,197,198,197,196,196,197,196,198,197,197,197,198,198,198 +,252,252,252,252,108,252,108,252,108,252,108,108,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,108,109,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,252,252,107,107,109,252,107,252,107,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,252,107,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,107,109,107,107,107,44,33,45,34,44,35,45,35,44,36,45,37,44,37,45,38,44,39,45,39,47,40,47,41,47,41,47,42,47,43,47,44,47,44,47,45,47,46,47,46,47,32,47,33,47,34,47,35,47,35,47,36,47,37,47,38,47,39,32,32,32,32,32,32,32,32,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,33,34,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,37,42,47,35,36,35,36,35,36,35,36,36,36,36,37,36,37,37,37,37,37,37,37,37,38,37,38,38,38,38,38,38,38,38,39,39,39,39,39,39,39,39,40,39,40,40,40,40,40,40,40,40,41,40,41,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,43,42,43,43,43,43,43,43,43,43,43,42,43,42,43,43,43,44,44,44,43,44,44,44,45,44,45,45,45,45,45,45,45,46,46,45,46,46,46,46,46,47,47,47,47,46,100,100,100,46,100,47,47,101,47,101,101,47,101,100,47,100,100,100,101,100,102,101,47,102,102,101,101,99,99,54,102,99,56,56,102,56,56,57,58,57,58,58,60,60,60,61,61,61,61,61,61,61,61,62,63,63,63,63,61,65,61,68,61,69,69,70,70,70,70,71,71,72,72,69,74,68,70,196,196,196,196,196,197,197,197,197,197,197,198,197,198,198,198,198,198,198,198,198,196,196,196,196,197,196,197,197,197,197,197,197,197,197,198,197,198,198,197,197,197,197,196,198,198,198,198,197,198,197,197,197,196,196,196,196,196,196,219,219,219,219,219,219,219,219,219,219,219,219,219,219,197,197,198,198,198,198,196,196,197,196,197,197,197,197,198,198,198,198,198,198,198,196,197,198,198,198,198,196,196,196,196,197,198,196,196,197,197,197,198,198,198,196,196,196,197,197,197,197,198,198,198,197,196,197,198,197,196,196,197,196,197,197,197,197,198,198,198,197,198,197,198,198,198,197,198,198,196,197,197,197,198,198,198,196,196,196,197,197,197,197,198,198,198,198 +,252,252,252,108,252,109,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,252,107,109,107,109,107,107,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,109,109,107,107,107,107,252,107,252,107,252,107,252,107,252,107,252,252,109,107,109,107,109,107,109,107,109,107,109,107,109,107,47,38,47,32,47,33,47,34,47,35,47,36,47,37,47,38,47,39,47,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,41,43,41,42,41,42,42,44,45,47,32,32,32,32,32,32,32,32,34,33,34,33,34,32,33,36,37,39,40,42,43,46,47,33,34,33,34,33,34,33,34,33,34,33,34,33,34,34,35,35,35,32,37,42,47,35,35,35,35,35,35,35,36,35,36,35,36,35,32,35,37,40,42,45,47,36,37,36,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37,38,38,38,38,39,38,39,38,39,38,39,38,39,39,40,39,40,39,40,39,40,39,40,40,40,40,41,40,41,40,41,40,41,41,41,41,41,41,42,41,42,41,42,41,42,42,42,42,43,42,43,42,43,42,43,42,43,43,44,43,44,44,43,43,44,43,43,44,43,43,43,43,42,43,44,44,44,44,44,45,45,44,45,44,45,45,45,46,45,46,45,46,45,46,46,46,46,47,46,47,46,47,46,100,47,99,99,99,47,100,100,100,100,100,100,101,47,101,100,47,100,100,100,101,100,102,101,47,102,102,101,101,99,99,54,102,99,56,56,102,102,56,56,56,58,58,57,58,57,62,57,57,101,58,61,61,62,61,61,62,62,62,62,63,62,63,63,64,64,64,94,93,64,95,66,92,65,72,196,196,196,196,197,196,197,197,197,197,198,197,198,197,198,197,198,198,198,197,198,130,196,196,197,196,196,196,197,196,197,197,198,197,198,197,198,197,198,198,198,196,197,198,197,197,197,197,197,197,197,197,198,197,198,197,198,197,198,197,198,196,196,196,196,196,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,198,198,198,196,196,197,197,198,198,198,198,198,196,196,196,196,196,196,196,196,196,197,197,198,198,198,197,196,196,197,196,197,197,198,197,198,196,197,197,198,197,196,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,198,198,197,198,196,197,197,198,198,196,196,197,196,197,197,197,197,198,198,198,198,198 +,252,252,252,252,108,252,109,252,252,252,108,252,108,252,108,252,252,252,252,252,108,252,108,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,107,107,107,107,109,252,107,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,107,107,252,107,252,107,252,252,252,252,252,252,252,107,107,107,109,109,109,109,109,107,109,107,109,107,109,32,32,32,32,32,47,44,42,39,37,34,32,32,33,33,35,35,36,37,38,38,39,40,41,41,42,43,44,45,45,46,47,33,33,33,33,34,33,33,34,35,37,38,40,41,42,44,46,47,33,33,33,34,33,34,33,34,34,35,34,35,34,35,34,35,34,35,34,35,35,35,35,35,35,35,35,35,35,35,35,35,32,39,47,35,35,35,36,37,36,37,36,37,36,37,36,47,32,35,38,41,44,47,37,37,37,37,37,37,38,38,38,38,38,38,38,38,38,39,38,47,45,42,40,37,34,32,38,39,38,39,39,39,39,38,39,38,39,38,39,39,39,39,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,40,41,40,41,40,41,41,41,41,41,41,41,41,42,41,42,41,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,44,44,44,44,43,44,44,44,45,43,43,44,44,44,45,44,45,45,45,45,46,45,46,45,45,46,46,46,46,46,46,46,46,47,46,47,46,47,47,47,46,99,47,47,47,47,99,99,99,100,100,100,101,101,101,101,47,101,100,47,100,100,100,101,100,102,101,47,102,102,101,101,99,99,54,102,99,56,56,102,55,55,56,56,57,57,58,58,58,60,61,58,61,61,61,62,62,62,63,63,62,63,61,62,62,63,62,90,62,94,91,90,94,91,94,92,93,93,196,196,196,196,197,197,197,197,197,197,198,198,198,198,198,198,198,198,198,198,128,129,196,196,196,196,197,197,197,197,197,197,197,197,198,198,198,198,198,196,196,197,197,197,197,197,197,196,196,197,197,198,198,197,198,197,198,197,198,198,198,198,198,198,198,198,198,197,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,196,197,197,198,198,198,196,197,197,198,198,198,198,198,196,196,197,197,197,198,198,198,196,197,197,198,198,196,196,196,196,197,197,197,197,198,198,198,198,198,197,198,197,198,198,198,197,198,198,198,196,198,198,198,196,196,196,197,196,197,197,198,197,198,198,198,198 +,252,252,252,108,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,109,107,109,107,109,252,252,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,252,107,252,107,109,107,252,107,252,107,252,109,252,109,109,107,109,107,109,109,109,109,109,107,109,107,109,107,33,34,33,34,33,46,45,42,47,42,47,47,33,34,33,34,33,34,33,35,34,35,34,32,35,36,39,40,43,44,47,35,34,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,36,36,37,36,36,36,37,36,36,36,37,36,32,34,35,38,39,42,43,46,46,36,37,36,37,36,37,36,37,37,38,38,38,47,32,35,36,39,40,43,44,47,38,38,39,38,39,39,39,38,39,39,40,39,40,39,40,39,40,39,38,32,35,40,43,47,39,38,39,38,39,38,39,38,39,39,39,39,38,39,38,39,47,43,46,47,47,40,39,40,47,40,32,40,40,41,40,37,42,47,40,41,41,41,35,40,43,47,41,42,41,42,41,42,42,32,34,38,41,44,47,43,42,43,42,43,43,44,43,44,43,44,43,44,44,46,46,46,44,45,45,45,45,46,47,47,44,46,47,44,46,44,45,45,45,45,46,45,46,45,46,45,46,47,47,46,47,47,103,47,96,47,96,97,47,96,97,97,98,97,97,98,98,98,98,99,99,99,99,99,99,99,99,100,100,101,47,101,100,47,100,100,100,101,100,102,101,47,102,102,101,101,99,99,54,102,99,56,56,102,55,55,56,56,57,55,58,57,58,61,58,60,61,62,61,61,62,62,63,63,62,62,62,62,62,63,62,91,91,92,90,92,92,91,92,93,93,94,128,130,130,131,132,134,134,136,136,138,138,140,141,142,143,128,143,142,135,138,140,143,136,196,196,196,196,197,196,197,197,197,197,198,197,198,197,198,196,197,197,197,197,197,197,196,196,197,196,197,196,198,196,197,197,198,197,198,197,198,197,198,197,198,198,198,197,198,198,198,197,220,220,220,220,220,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,197,196,197,197,198,197,198,196,197,198,198,197,198,197,196,196,198,198,198,196,197,196,197,197,198,197,198,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,198,198,198,198,198,197,198,197,198,197,198,196,198,196,197,196,197,197,198,197,198,198,198,198,198 +,252,252,252,252,108,252,108,252,109,252,108,252,252,252,252,252,108,252,109,252,109,252,108,252,108,108,252,108,108,252,252,252,252,252,252,252,252,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,252,252,107,107,109,252,109,252,107,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,109,107,109,107,109,109,252,109,252,109,107,107,109,109,109,109,109,107,109,107,109,107,109,107,34,34,34,34,34,35,34,35,34,35,34,34,34,35,34,35,32,34,35,37,39,40,42,44,46,47,35,36,35,36,35,36,35,36,36,36,36,36,36,36,36,36,36,34,36,37,38,39,41,42,43,44,46,47,36,37,33,34,36,36,38,39,40,41,43,43,45,46,47,38,38,38,38,38,37,38,38,38,38,38,38,38,37,38,38,39,39,40,39,40,39,39,39,40,39,40,39,40,39,39,40,40,40,40,40,40,32,34,36,38,41,43,45,47,40,41,39,41,40,41,40,41,40,41,40,41,40,32,34,36,38,40,43,45,47,40,41,40,40,40,40,40,40,40,41,40,41,41,41,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,43,42,43,43,43,43,43,43,43,43,44,44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,96,96,99,99,99,46,46,99,47,100,46,100,99,99,100,100,47,100,46,100,100,101,101,101,102,45,102,46,102,102,102,102,102,103,103,103,103,96,96,96,97,97,97,97,98,98,97,97,98,98,98,53,99,101,47,101,100,47,100,100,100,101,100,102,101,47,102,102,101,101,99,99,54,102,99,56,56,102,102,100,54,55,55,56,56,57,57,58,58,58,60,60,60,61,61,61,61,61,62,62,62,196,196,196,196,196,63,60,61,61,62,62,92,62,92,92,93,92,94,94,94,94,128,129,130,130,131,132,133,134,135,135,136,137,138,139,140,141,142,70,71,71,72,72,73,136,196,136,197,196,197,197,197,197,197,197,198,197,198,198,197,197,197,196,197,197,197,197,196,196,196,196,196,196,197,197,197,197,198,198,198,198,198,197,198,197,198,198,198,198,198,198,198,198,198,198,198,222,221,221,221,221,221,221,220,220,220,220,220,220,220,220,220,220,220,220,220,219,219,219,219,219,219,219,219,196,196,196,197,197,197,197,197,197,198,198,198,197,198,197,198,197,198,198,198,197,198,197,198,196,197,197,197,197,198,196,196,196,197,197,197,197,197,197,198,198,198,197,197,197,198,198,198,198,198,197,198,198,198,197,198,197,196,198,196,196,197,197,197,197,198,197,198,198,198,198 +,252,252,252,109,252,108,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,107,107,109,107,252,107,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,107,252,107,252,107,109,107,252,107,252,252,109,107,109,107,109,107,109,109,109,107,109,107,109,107,107,36,35,36,35,36,36,36,36,36,36,36,35,36,36,36,36,36,36,37,37,37,37,37,37,37,37,34,36,37,39,39,41,42,44,44,46,47,37,38,37,38,37,38,37,38,37,38,37,38,37,38,38,38,38,38,38,39,39,39,39,39,39,39,39,39,39,39,39,40,39,40,39,40,39,40,39,40,39,40,39,32,34,34,36,36,38,39,40,41,43,43,45,45,47,41,41,41,41,41,41,42,42,42,42,42,42,42,42,43,42,43,42,43,42,43,42,41,42,42,42,34,37,38,41,42,45,47,42,42,42,42,42,42,42,42,42,42,42,40,41,41,42,41,42,41,42,41,42,42,43,32,36,39,44,47,43,43,44,43,45,46,46,43,44,44,45,44,45,44,45,44,45,45,45,45,45,46,45,45,46,46,45,44,46,44,46,47,44,46,47,103,103,97,97,98,98,99,99,97,98,99,100,100,97,98,49,100,101,101,101,102,100,101,102,101,103,101,103,102,103,102,103,51,52,96,96,97,97,52,53,97,98,53,98,98,97,97,98,54,98,98,99,98,56,98,56,55,56,55,56,56,57,56,57,57,99,57,58,57,58,57,58,58,59,58,59,58,59,59,59,59,60,59,60,60,61,60,61,60,61,61,61,60,61,61,63,63,63,196,196,196,196,196,196,197,198,198,198,61,62,62,63,63,63,93,92,93,93,94,94,93,94,94,94,95,95,94,95,64,65,65,66,66,67,67,68,68,69,69,70,70,71,71,72,136,136,136,197,196,136,196,198,197,198,197,198,197,198,197,198,196,196,196,197,196,197,197,197,197,196,197,198,196,197,196,197,197,198,197,198,197,198,197,198,198,198,197,198,197,198,197,198,197,198,198,198,198,198,198,198,222,222,222,222,222,222,221,222,221,221,221,221,220,221,220,221,220,220,220,220,220,220,220,220,219,196,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,197,198,197,198,197,198,197,196,196,197,197,198,198,197,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,197,198,198,198,197,198,198,198,197,196,197,198,196,197,196,197,197,198,197,198,198,198,198,198 +,252,252,108,252,108,252,108,252,252,252,108,252,108,252,109,252,252,252,109,252,109,252,108,252,252,252,108,108,108,252,108,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,107,107,107,107,109,252,107,107,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,107,107,252,109,109,109,252,252,252,252,107,107,107,107,109,109,109,107,109,107,109,107,109,107,107,37,37,33,35,36,37,38,40,41,42,43,45,46,47,39,41,43,45,47,38,38,38,38,38,38,38,38,38,38,38,38,38,39,39,39,38,34,36,37,38,39,40,41,42,43,45,46,47,39,39,40,39,40,39,40,40,40,40,40,40,40,40,40,40,40,40,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,42,42,42,43,42,43,42,43,42,43,42,43,42,43,47,44,41,38,35,32,40,47,43,44,44,44,44,44,44,44,44,44,42,44,44,44,43,44,44,44,47,45,43,41,40,37,36,34,32,43,44,43,44,43,42,42,32,33,35,36,37,38,40,41,42,43,45,46,47,44,45,45,45,45,97,98,98,98,98,98,46,32,35,38,41,44,47,47,47,99,99,100,100,100,100,100,100,45,101,46,101,101,46,101,46,102,102,102,96,97,97,96,98,99,50,50,99,99,98,50,51,99,100,51,52,51,101,102,102,102,102,52,53,53,53,53,53,53,53,53,54,54,54,54,54,54,55,55,55,55,55,55,56,56,98,56,56,56,56,98,57,57,57,57,57,57,58,57,58,58,58,58,59,100,59,59,59,59,59,59,60,60,60,60,60,60,61,60,61,61,61,61,61,61,62,62,62,62,62,63,63,63,196,196,196,197,197,198,197,197,198,198,198,198,198,198,92,62,63,92,93,92,93,93,94,94,94,94,64,94,65,64,66,65,67,66,67,67,68,68,68,68,69,69,69,70,71,71,71,135,136,136,136,136,136,198,197,198,198,198,198,198,198,196,196,196,196,196,196,196,197,197,197,197,197,197,198,198,198,197,197,197,198,197,198,198,198,198,198,197,198,197,198,197,198,198,198,197,198,198,198,198,198,198,198,198,198,198,198,222,222,222,222,222,222,222,222,221,221,221,221,221,221,221,221,220,221,220,220,220,196,196,196,196,197,197,197,197,198,198,198,198,198,198,198,197,198,198,198,197,198,198,198,197,198,198,196,196,197,197,198,196,197,197,197,197,197,197,197,197,198,198,198,197,198,197,198,197,198,198,198,197,198,198,198,197,198,196,197,198,196,196,197,197,197,197,198,198,198,198,198,198 +,252,252,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,252,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,107,107,109,107,109,107,252,107,252,107,252,107,252,109,252,109,252,107,109,107,109,107,109,109,109,107,109,107,109,107,107,107,38,39,38,39,34,34,37,37,39,40,42,42,45,45,47,39,39,40,39,40,39,40,39,40,39,40,39,40,39,40,39,40,40,41,40,40,40,41,40,41,40,41,40,40,40,41,40,41,40,41,41,41,41,41,41,42,41,42,42,42,41,42,41,42,41,42,42,43,42,43,42,43,42,43,42,43,42,43,42,43,42,43,42,44,43,44,44,44,44,44,44,44,44,44,44,44,44,44,44,46,45,46,45,46,45,46,45,46,45,46,45,47,45,42,40,37,35,32,47,45,45,45,45,46,45,45,45,45,45,45,45,45,46,45,46,46,46,44,45,44,45,45,42,43,43,43,43,43,43,46,47,46,47,47,47,96,97,97,97,98,99,99,99,99,99,99,100,100,99,100,100,100,100,100,101,100,101,101,100,101,100,100,100,101,102,101,102,102,102,102,103,103,51,103,97,97,96,51,52,98,52,99,53,52,53,52,53,53,101,101,54,53,54,53,54,54,55,54,55,54,55,54,55,55,56,55,56,55,56,55,56,56,57,56,57,56,57,57,57,57,58,57,58,57,58,58,58,58,59,58,59,58,59,59,60,59,60,59,60,60,60,60,61,60,61,60,61,61,61,61,61,62,61,62,62,62,63,63,62,62,63,63,63,63,143,143,196,197,198,198,198,198,198,197,198,198,198,198,198,198,198,92,93,93,92,94,94,64,66,65,66,64,66,65,66,67,67,67,68,68,67,67,68,68,68,68,69,69,70,70,70,71,71,71,135,137,138,140,140,141,142,142,143,128,129,196,140,140,140,141,141,142,142,143,198,197,198,198,198,197,198,198,198,197,198,197,198,197,198,198,198,198,197,197,198,197,198,197,198,197,198,198,198,197,198,197,198,197,198,198,198,197,198,198,65,65,66,217,222,222,222,222,222,221,221,221,221,220,221,220,221,220,196,196,197,196,197,196,197,196,197,197,198,197,198,198,198,197,198,197,198,197,198,197,198,197,198,197,198,196,197,197,198,196,197,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,198,198,198,198,197,198,198,198,197,196,197,198,196,197,196,197,197,198,197,198,198,198,198,198 +,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,252,109,107,107,107,107,107,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,109,107,252,109,252,109,252,252,252,252,107,107,109,107,109,109,109,109,109,107,109,107,109,107,107,107,39,40,47,39,32,34,37,39,42,44,47,40,39,40,40,40,96,34,36,38,41,43,45,47,40,41,40,41,40,41,40,42,41,42,41,42,41,42,41,42,41,42,41,42,41,42,41,42,42,43,42,43,42,42,43,43,42,43,32,33,34,34,36,36,37,38,39,40,41,42,43,43,44,45,46,47,43,44,44,44,44,47,46,44,43,41,40,38,37,35,34,32,45,45,45,46,45,46,47,47,46,33,35,36,37,38,40,47,42,43,45,46,47,47,96,96,34,36,38,39,41,43,45,47,97,97,97,33,35,36,37,38,40,41,42,43,45,46,47,99,100,45,45,45,45,45,44,45,45,46,102,103,96,96,97,96,97,41,43,41,44,47,99,99,100,100,100,100,100,100,100,101,50,50,101,50,101,101,51,101,101,101,51,51,101,102,101,103,101,103,103,103,53,53,96,96,53,53,53,53,54,54,54,54,54,54,54,54,55,55,55,55,55,55,55,55,56,56,56,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,58,59,59,59,59,59,59,59,59,60,60,60,60,60,60,60,60,61,61,61,61,61,61,61,61,62,62,62,62,62,61,62,62,62,62,62,62,63,48,63,63,63,53,63,197,128,128,143,143,198,143,198,198,198,198,198,198,198,198,198,198,132,132,93,94,94,92,93,64,65,93,68,66,66,68,67,67,68,68,68,68,70,68,68,69,69,69,70,70,70,70,71,71,72,72,73,73,73,73,138,138,138,138,139,139,139,139,140,140,140,140,141,141,141,141,141,142,142,142,143,143,143,143,143,198,198,198,198,198,198,198,198,198,198,198,198,197,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,66,66,217,78,217,217,222,222,222,221,221,221,221,220,221,220,220,198,196,196,196,196,197,197,197,197,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,196,196,197,198,197,197,197,197,197,197,197,197,198,198,198,198,197,197,197,197,198,198,198,198,198,197,198,198,198,198,196,197,197,198,196,196,197,197,197,197,198,197,198,198,198,198 +,252,108,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,107,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,252,107,252,107,252,107,109,107,252,109,252,109,107,107,109,107,109,109,109,107,109,107,109,107,107,107,107,41,41,41,41,41,41,41,41,41,41,41,41,41,41,42,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,32,35,38,41,44,47,43,43,43,43,43,43,103,101,100,101,100,101,100,101,101,103,103,44,45,44,45,44,45,44,45,44,45,44,45,45,46,45,46,45,46,45,46,45,46,45,46,45,46,45,46,45,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,96,97,96,98,97,98,98,99,99,101,100,102,101,102,101,103,102,103,96,96,96,96,96,96,96,96,97,96,97,48,48,97,48,46,97,57,48,57,97,48,98,52,98,99,99,100,100,46,100,45,100,100,46,102,101,103,103,97,103,97,97,98,98,98,50,99,50,99,51,99,100,100,101,100,51,52,51,52,52,53,52,53,52,53,102,53,53,102,53,54,53,103,53,96,54,55,54,55,54,55,54,55,55,56,55,56,55,56,55,56,56,57,56,57,56,57,56,57,57,58,57,58,57,58,57,58,58,58,58,59,58,59,58,59,59,59,59,59,59,60,59,60,60,60,60,60,60,61,60,61,60,61,61,61,61,62,61,62,61,62,61,62,62,62,62,63,62,62,62,62,62,62,63,62,63,62,61,62,60,61,63,88,63,63,63,143,143,143,128,128,143,128,131,129,131,129,132,132,132,132,133,133,133,92,65,65,93,66,64,66,92,64,67,64,69,67,69,70,70,70,70,70,69,70,70,69,69,70,70,71,70,72,71,72,72,73,73,74,73,74,74,75,75,76,75,76,76,77,77,78,77,78,78,79,79,79,64,79,64,64,64,65,64,66,65,66,66,67,67,68,132,132,132,132,133,133,134,134,135,135,198,136,198,198,198,198,197,198,198,198,198,198,198,198,198,198,198,198,198,198,77,217,77,217,77,217,222,222,222,221,221,221,220,220,219,219,219,198,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,198,197,198,197,198,197,196,196,196,197,198,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,197,198,197,198,198,198,197,198,198,198,196,197,197,198,196,197,196,197,197,198,197,197,198,197,198,198 +,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,107,107,107,107,107,107,107,107,107,107,252,107,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,107,252,109,109,109,252,252,252,252,252,109,107,107,109,109,109,109,109,107,109,107,107,107,107,107,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,44,34,36,38,40,43,45,47,34,36,37,38,39,41,42,43,44,46,47,45,46,45,46,45,46,45,46,45,46,45,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,96,96,47,44,41,38,35,32,98,98,47,43,40,36,32,99,99,99,100,100,100,47,43,39,36,32,35,38,41,44,47,102,103,102,102,102,102,102,102,57,97,41,43,41,42,41,42,44,45,47,46,61,46,49,99,61,99,49,102,98,100,98,100,100,100,43,100,46,102,101,102,102,102,102,103,96,96,96,97,98,52,97,52,52,53,53,53,53,53,53,53,53,54,53,54,54,101,54,54,54,54,54,55,54,55,55,55,55,55,55,56,55,56,56,56,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,58,59,58,59,59,59,59,59,59,60,59,60,60,59,60,60,60,59,60,60,60,61,61,61,61,61,61,62,61,62,62,62,62,62,62,62,62,63,63,63,63,63,63,60,60,61,61,61,63,61,61,62,62,62,63,62,62,62,61,62,62,59,61,88,88,88,88,89,59,62,89,63,89,89,67,91,65,65,66,92,68,92,65,66,68,65,67,66,68,67,68,65,68,67,68,68,68,70,70,71,70,71,70,70,71,71,70,71,71,71,71,72,72,72,72,73,73,74,74,74,74,75,75,76,76,76,76,77,77,77,77,78,78,78,78,79,79,79,64,79,64,64,64,65,65,65,65,66,66,67,67,68,68,68,68,69,70,70,70,71,71,72,72,73,73,73,73,74,74,75,75,76,76,76,76,76,76,76,77,77,77,217,77,217,217,217,222,222,221,221,221,221,220,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,198,198,198,198,198,198,198,198,196,196,196,196,196,196,198,197,197,197,197,197,197,198,198,198,198,198,198,197,197,198,197,198,197,198,198,198,197,198,198,198,198,196,197,197,198,196,196,197,197,198,198,198,198,198,198,198,198 +,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,252,107,109,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,107,107,252,107,109,107,252,107,252,107,252,107,252,109,252,109,252,109,109,109,107,107,109,109,109,109,109,107,109,107,107,107,107,107,47,39,32,34,37,38,41,42,45,46,32,33,35,35,37,38,40,40,42,43,45,45,47,45,44,45,44,45,44,45,45,46,46,46,45,46,46,46,45,46,46,46,45,46,46,46,45,47,47,47,47,47,47,47,47,47,47,44,43,40,39,36,34,32,96,97,32,34,37,39,42,44,47,96,97,96,47,39,32,39,47,97,98,97,98,98,99,98,98,99,99,47,44,41,38,35,32,34,37,39,42,44,47,101,102,101,52,102,102,102,34,35,38,39,42,43,46,47,102,102,102,102,97,96,57,97,102,102,102,97,102,102,49,51,49,102,99,49,50,100,100,50,100,45,100,45,43,101,101,101,100,102,102,103,52,96,52,96,53,96,97,52,98,52,53,53,54,53,54,53,54,53,54,100,55,54,55,54,55,54,55,55,55,55,56,55,56,55,56,56,56,56,57,56,57,56,57,57,57,57,58,57,58,57,58,57,58,58,58,58,59,58,59,58,59,59,59,59,60,59,60,59,60,60,60,60,61,60,60,61,60,58,60,61,61,60,59,60,61,61,61,61,63,62,63,62,62,63,62,62,63,62,63,62,62,62,61,63,60,63,63,62,61,61,61,63,61,62,61,63,61,63,63,62,62,61,62,61,61,62,88,63,63,89,62,89,61,90,90,65,64,90,66,67,64,67,67,67,66,68,67,68,69,66,68,69,69,67,68,70,68,69,70,69,71,71,72,72,71,72,72,71,72,71,72,72,73,72,73,73,74,73,74,75,74,74,75,75,76,75,76,76,77,76,77,77,78,78,79,78,79,79,79,79,79,64,79,64,64,64,65,65,66,66,67,66,67,67,68,68,69,69,70,69,70,70,71,71,72,72,73,72,73,73,74,74,75,75,76,76,76,217,217,217,217,217,217,217,217,222,222,221,221,221,221,220,221,220,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,197,196,198,196,197,197,198,197,198,197,198,197,198,198,198,197,198,197,198,197,198,198,198,197,198,198,198,198,196,196,193,196,193,196,197,197,198,199,199,199,193,193,198,198,198 +,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,252,107,107,107,107,107,107,107,107,107,252,107,109,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,109,107,109,109,252,109,252,109,252,252,252,252,252,252,107,107,109,107,109,107,109,107,109,107,107,107,107,44,44,45,44,45,44,45,44,44,44,45,97,97,99,99,100,100,102,102,103,96,45,45,45,97,98,99,101,102,103,46,46,47,47,47,47,47,103,100,101,100,101,101,101,47,32,34,37,39,42,44,47,97,98,98,98,98,99,99,99,100,100,100,101,101,101,101,102,102,102,102,103,103,96,96,96,96,97,97,97,32,35,37,40,42,45,47,47,47,44,47,42,47,47,101,52,100,100,100,100,100,102,101,100,100,102,101,102,102,50,102,102,102,102,102,102,102,102,50,50,102,102,102,57,102,102,102,97,102,57,103,98,98,98,50,99,50,50,50,99,50,50,99,100,51,45,51,45,51,101,100,52,102,102,102,102,52,52,52,53,53,53,53,53,53,53,53,54,54,54,54,54,54,54,54,55,55,55,55,55,55,55,55,56,56,56,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,58,59,59,59,59,59,59,59,59,60,60,60,60,60,60,61,60,61,61,61,61,61,60,61,60,61,58,61,61,60,60,59,59,61,61,61,62,62,63,61,61,61,63,63,62,62,63,62,62,62,61,61,60,61,61,61,61,61,62,61,63,61,61,63,63,63,62,58,62,58,61,62,89,88,87,62,86,88,64,90,90,64,66,65,66,67,68,68,67,66,67,68,68,68,68,69,69,70,69,68,69,70,69,70,69,69,70,70,71,73,74,72,72,74,72,73,72,73,73,73,73,73,73,74,75,75,74,75,75,75,75,76,76,76,76,77,77,77,77,78,78,78,78,79,79,79,79,79,79,79,64,64,64,64,64,65,27,31,30,29,28,27,26,26,25,24,23,22,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,221,221,221,221,221,221,221,220,220,220,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,197,197,197,197,197,197,197,197,198,198,198,198,198,198,197,197,197,197,197,197,198,198,198,198,197,197,198,198,199,199,199,199,199,193,199,196,193,199,193,193,193,193,199,199,199,199 +,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,107,109,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,252,107,109,109,109,109,107,109,107,109,107,107,107,45,46,46,46,46,46,47,32,34,36,39,40,43,45,47,102,103,47,47,47,98,98,100,100,102,103,47,47,47,47,96,96,97,96,97,96,97,32,98,97,98,97,100,100,100,98,99,98,99,99,100,99,100,99,100,100,101,100,47,45,44,41,40,37,36,33,32,102,103,102,103,47,32,34,37,39,42,44,47,97,97,98,98,99,101,51,51,33,47,43,40,35,32,47,47,51,103,100,102,102,102,101,101,102,101,100,45,99,50,103,103,102,102,50,50,57,50,50,50,50,50,57,103,102,102,57,54,57,58,50,54,50,53,50,50,50,49,50,51,50,50,50,100,100,51,100,51,100,52,45,52,52,101,102,101,52,53,52,96,53,54,53,54,53,54,53,54,54,55,54,55,54,55,54,55,55,56,55,56,55,56,56,56,56,57,56,57,57,57,57,58,57,58,57,58,58,59,58,59,58,59,58,59,58,59,60,60,60,59,59,59,60,61,61,60,61,60,61,61,61,62,61,62,62,62,62,62,63,61,61,61,62,61,60,60,61,60,61,59,94,59,62,63,62,63,83,83,82,61,62,63,82,62,63,63,63,61,83,84,84,62,62,62,62,62,62,62,63,62,62,62,63,63,62,62,62,62,62,85,62,61,62,86,87,88,89,65,66,67,68,67,67,69,68,69,68,69,70,69,70,69,70,70,70,71,71,70,71,71,71,71,72,72,71,73,72,73,72,74,74,74,74,74,74,74,74,75,74,75,75,74,76,75,75,75,76,76,76,77,76,77,76,77,77,78,77,78,78,79,78,79,78,79,79,79,64,79,31,64,28,65,26,31,29,28,25,24,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,217,217,217,221,217,221,217,221,217,221,221,221,221,220,221,220,221,220,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,197,196,197,197,198,197,198,198,198,198,198,197,198,198,196,196,197,196,197,197,198,197,198,198,198,198,198,198,199,199,193,196,193,193,193,193,193,193,194,193,199,199,199,193,193,193,193 +,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,252,107,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,109,107,107,107,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,109,109,109,109,107,109,107,107,107,107,47,32,35,38,41,44,47,47,47,47,47,47,47,103,102,103,103,32,33,34,35,36,37,39,39,41,41,43,44,45,46,47,98,98,47,45,43,41,38,37,34,32,47,99,99,99,99,32,34,37,39,42,44,47,100,101,101,101,101,101,101,101,101,102,102,102,102,102,47,40,32,47,103,103,96,96,96,97,96,97,97,98,102,98,100,101,99,98,100,99,50,98,103,99,49,100,49,100,102,100,49,101,101,101,102,51,102,102,102,102,50,51,51,50,100,100,100,100,52,102,57,54,50,58,102,54,50,50,61,63,50,56,51,50,49,103,50,50,50,50,50,51,51,100,100,100,51,99,52,46,52,52,101,53,102,53,53,53,53,53,53,54,54,54,54,54,54,55,55,55,55,55,55,56,55,56,56,56,56,56,56,57,57,57,57,57,57,58,58,58,58,58,58,59,58,59,59,59,59,59,59,59,58,60,60,58,60,60,60,60,59,60,61,61,62,60,61,61,62,61,62,62,63,63,63,62,62,63,61,61,61,62,60,60,61,61,61,62,61,60,94,60,61,81,81,64,63,63,82,82,62,82,82,64,62,82,83,82,60,60,84,84,62,62,83,61,62,64,62,63,66,62,64,61,62,85,62,86,63,86,85,86,87,87,64,65,67,68,67,69,68,68,69,69,69,70,70,70,72,70,71,71,71,71,72,72,73,72,73,72,73,72,73,72,74,73,74,74,73,75,75,75,75,74,75,74,74,75,74,76,76,75,76,76,75,76,76,76,76,77,77,77,77,78,78,78,78,79,78,79,79,79,79,79,64,79,29,64,26,65,23,65,29,66,27,31,29,28,26,25,23,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,220,220,220,220,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,198,196,196,198,198,198,198,198,198,198,199,196,196,196,196,193,193,193,194,193,194,196,199,199,193,193,193,193,193,193,193 +,252,108,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,107,107,107,252,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,109,107,252,107,109,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,107,109,107,252,107,107,107,102,101,32,33,36,37,39,40,42,43,46,47,103,102,103,103,103,102,96,96,96,96,97,96,97,96,97,97,97,97,98,98,98,97,98,98,99,98,99,98,99,98,98,99,99,100,99,101,100,99,100,100,101,100,101,100,101,34,37,38,41,42,45,47,102,101,102,102,103,102,103,102,102,96,103,96,97,97,97,97,99,51,99,100,51,99,50,51,103,51,97,96,96,96,96,52,103,102,49,100,101,49,45,51,100,51,100,50,102,50,102,52,53,100,45,52,103,50,50,50,50,49,50,54,55,50,50,55,54,59,52,50,50,50,50,53,50,50,51,50,51,51,51,51,52,51,100,52,52,100,53,52,53,53,53,53,54,53,54,53,54,54,55,54,55,55,55,55,56,55,56,55,56,56,57,56,57,56,57,57,58,57,58,57,58,58,59,58,59,58,59,59,60,59,60,59,60,60,60,61,59,60,59,61,59,60,60,60,88,59,60,61,61,61,61,62,62,63,61,62,62,62,62,61,63,63,63,61,63,62,63,62,61,94,61,61,59,62,93,60,60,62,63,64,81,64,81,65,82,82,65,82,64,83,63,65,83,83,66,83,83,83,62,64,84,83,67,65,67,66,63,67,64,64,85,65,86,65,87,65,69,86,69,66,67,69,69,70,70,70,71,70,70,70,71,71,72,71,72,73,72,74,73,74,74,73,73,73,74,73,74,73,74,75,74,74,74,75,75,74,76,75,76,75,76,75,74,75,75,76,77,75,76,76,76,76,77,76,77,77,78,77,78,78,78,78,79,78,79,78,79,79,79,64,79,64,64,64,65,25,65,24,66,22,67,26,67,25,25,23,31,29,28,25,24,22,218,218,218,218,218,218,218,218,218,217,218,217,218,217,217,217,217,221,217,221,217,221,221,221,221,221,221,220,221,220,221,220,221,220,220,220,220,219,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,198,199,196,196,193,196,193,196,193,194,193,194,199,199,196,196,193,193,193,193,194,193,194 +,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,107,109,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,109,107,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,107,107,107,107,102,101,102,102,102,102,102,102,102,102,34,35,37,38,40,41,43,44,46,47,96,96,32,34,36,38,41,43,45,47,99,99,98,98,98,98,98,98,98,98,99,98,99,99,99,102,49,99,100,100,100,100,46,101,101,100,102,101,101,101,101,101,102,101,100,102,102,102,103,103,103,98,101,103,51,97,97,51,52,101,100,51,102,53,102,51,97,51,97,49,98,49,52,102,50,102,50,101,50,50,101,49,102,51,100,100,51,51,100,103,51,51,51,51,97,51,51,51,52,51,51,49,48,48,48,50,55,52,50,50,50,50,50,50,50,50,51,50,51,51,51,51,52,52,52,52,53,52,53,53,53,53,53,53,54,54,54,54,55,55,55,55,55,55,56,56,56,56,56,56,57,57,57,57,58,57,58,58,58,58,58,58,59,59,59,59,60,60,60,60,60,60,61,60,61,61,61,61,61,61,62,60,59,60,62,59,60,58,88,59,60,59,60,63,62,62,62,63,63,63,62,62,61,90,91,92,63,92,63,92,62,93,61,61,95,60,94,94,62,63,62,80,65,65,65,82,65,65,82,82,66,66,67,67,83,68,84,67,66,65,84,83,64,65,69,69,67,68,68,68,68,68,69,70,66,69,67,67,71,70,71,71,71,71,71,72,72,71,71,71,71,71,71,72,73,72,74,75,74,74,74,74,74,75,74,75,74,74,74,74,74,75,75,74,75,74,75,76,75,75,76,75,75,76,75,75,76,75,76,77,76,76,77,77,77,77,77,77,78,77,78,78,78,78,79,78,79,79,79,79,79,64,79,64,64,64,64,64,65,65,65,26,66,25,67,24,67,23,68,22,31,29,27,24,22,31,23,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,220,220,220,220,220,219,220,220,220,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,199,196,196,196,196,193,193,193,193,194,194,199,196,196,196,193,193,194,193,194,193,194,193 +,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,109,107,107,107,107,101,32,34,37,38,41,42,45,47,102,102,103,103,103,103,103,96,103,103,96,97,96,96,96,97,97,97,97,99,98,99,98,98,97,103,99,98,99,99,99,100,99,99,99,47,99,103,100,102,101,100,103,101,100,100,51,101,102,101,101,102,102,103,102,102,102,102,101,49,49,101,51,101,101,50,102,102,102,100,51,51,98,52,97,52,52,52,52,52,49,49,98,50,51,50,50,102,50,49,50,46,50,50,100,50,51,50,50,50,51,51,102,51,51,51,51,51,102,102,51,102,51,50,51,51,51,50,48,48,54,51,51,50,51,50,50,50,53,51,52,51,52,52,53,52,53,53,54,53,54,53,54,54,54,54,55,54,55,55,56,55,56,56,57,56,57,57,57,57,58,57,58,58,59,58,59,58,59,59,60,59,60,60,61,60,61,61,61,62,61,60,62,60,61,60,62,62,62,61,62,60,59,59,61,59,60,62,60,58,88,59,61,64,62,61,62,63,62,89,89,90,63,91,91,62,91,92,92,92,93,93,94,63,94,62,94,80,80,95,62,95,65,66,65,64,66,66,65,64,65,65,66,68,68,69,68,69,68,68,69,68,67,67,69,71,67,70,70,69,71,70,70,71,72,71,70,69,73,70,71,72,71,72,72,72,72,72,72,72,73,73,73,73,73,74,74,74,74,75,74,74,75,74,75,75,74,75,75,75,75,75,74,75,75,75,75,75,75,75,76,76,75,76,77,76,77,76,76,76,76,76,77,76,77,77,78,77,78,77,78,78,79,78,79,78,79,78,79,79,79,64,79,29,79,64,64,27,65,27,66,30,66,29,67,28,67,27,68,27,69,26,218,25,30,24,27,23,24,22,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,221,221,221,221,221,220,221,220,221,220,220,220,220,219,220,219,220,219,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,199,196,196,196,196,193,196,193,194,194,194,199,196,196,196,193,196,194,193,194,193,194,194,194 +,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,107,107,107,252,107,109,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,107,107,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,107,109,107,252,107,107,107,107,101,102,102,102,102,102,102,102,102,103,103,102,102,103,103,47,32,36,39,43,47,99,97,98,97,98,97,98,98,100,98,100,99,101,96,100,96,99,101,51,97,96,51,99,47,102,100,103,101,102,102,102,102,51,52,99,51,102,103,103,102,102,103,102,102,52,52,102,101,102,101,51,51,102,50,51,51,102,52,52,52,53,52,53,52,52,97,51,50,51,96,50,50,51,102,50,101,50,50,100,50,50,50,50,50,51,51,51,51,51,52,102,52,53,52,52,52,52,52,52,52,52,51,51,52,51,51,51,51,51,51,54,51,51,52,51,54,52,52,52,52,53,53,53,53,53,53,54,54,54,54,55,55,55,55,56,56,56,56,57,57,57,57,58,58,58,58,58,58,59,59,59,59,60,60,60,60,61,61,61,61,61,62,62,62,62,62,62,62,63,61,63,62,62,62,62,84,62,84,62,63,61,61,62,60,60,60,60,60,59,60,89,69,61,88,63,69,62,90,90,88,90,90,63,91,63,91,92,93,94,63,94,94,94,64,94,95,81,64,66,65,65,66,65,66,66,67,67,68,67,67,68,69,68,68,68,69,68,69,70,71,72,71,71,70,72,70,72,71,73,71,70,71,71,71,72,72,73,72,73,72,72,72,73,72,73,73,73,74,72,73,73,73,74,75,73,74,74,75,75,75,75,75,76,75,75,76,75,75,75,75,75,75,76,76,75,76,75,76,75,76,76,76,77,76,76,77,77,76,77,77,77,77,78,78,78,78,78,78,78,78,79,79,79,30,79,79,79,64,79,64,64,28,64,28,65,27,65,27,66,30,67,29,67,28,68,27,68,26,31,25,27,23,25,22,22,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,221,221,221,221,221,221,221,221,220,221,220,220,220,220,220,220,220,220,220,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,193,196,196,196,193,194,193,194,196,196,196,196,193,193,194,193,194,194,194,194,193,194 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,109,109,107,109,107,252,107,107,107,102,101,102,101,102,102,102,102,102,103,103,102,103,102,103,96,97,97,97,97,97,97,97,97,98,96,100,99,98,51,102,100,51,100,103,97,97,51,97,96,47,97,96,101,103,51,101,50,51,50,99,98,102,99,99,52,51,51,102,103,101,53,103,52,103,102,54,102,53,102,102,52,102,54,102,52,52,52,52,52,53,52,52,52,52,52,52,52,52,52,52,52,52,52,52,51,50,50,50,51,50,50,51,50,49,51,52,51,52,52,53,52,53,53,54,53,53,53,53,53,53,53,54,54,54,52,52,51,52,54,51,51,54,51,52,51,51,52,52,53,52,53,53,54,53,54,55,54,55,55,56,56,55,56,56,56,57,57,58,57,58,58,59,58,58,59,58,59,58,60,59,61,61,61,62,61,62,62,62,63,62,61,63,61,61,60,60,62,62,62,63,63,63,63,61,82,62,82,63,59,84,62,85,62,61,60,62,62,62,88,88,62,60,64,88,89,64,64,90,69,91,65,91,91,67,92,91,92,93,64,64,65,64,94,64,64,64,65,65,65,66,67,67,66,67,67,67,67,67,67,68,68,68,69,68,69,69,70,69,69,70,72,71,72,72,72,71,72,71,73,72,71,72,72,73,73,74,73,71,74,73,73,73,73,73,73,73,74,73,74,73,74,75,74,74,74,74,74,74,74,75,75,75,75,75,76,75,75,76,76,75,75,76,75,77,76,76,75,76,77,76,76,76,76,77,77,76,77,77,77,78,77,78,78,78,78,78,78,79,78,79,79,79,79,79,64,79,64,79,64,64,64,65,31,65,30,66,29,66,27,67,27,68,26,68,25,69,23,30,23,31,22,31,23,29,30,26,28,24,26,218,25,218,23,218,22,218,218,218,218,218,218,218,218,218,217,218,217,217,221,217,221,217,221,221,221,221,220,221,220,221,220,221,220,221,220,220,220,220,219,220,219,220,219,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,193,196,194,196,194,194,193,194,194,199,196,196,193,196,194,193,194,193,194,193,194,194,194 +,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,107,107,107,107,107,107,107,107,107,109,107,252,252,252,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,107,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,109,107,107,107,109,107,107,107,107,107,102,101,102,102,102,102,103,103,103,102,96,103,96,103,97,96,97,98,103,97,99,100,98,53,98,99,98,97,97,99,97,100,99,97,102,52,97,102,51,101,51,101,51,51,103,50,50,98,99,99,51,98,51,102,96,52,53,53,102,53,53,52,102,102,102,102,53,52,53,52,52,52,52,53,52,52,53,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,53,53,53,53,53,53,54,55,55,54,56,55,56,51,58,52,56,56,54,58,51,54,54,52,51,53,52,52,53,53,55,54,55,55,55,56,56,57,57,57,57,55,57,56,58,58,59,59,60,60,60,61,61,59,61,59,61,62,58,62,60,60,60,61,61,62,62,63,63,62,62,63,62,62,62,62,62,62,62,95,63,80,62,82,63,83,84,84,61,59,85,59,60,60,62,59,63,90,60,62,64,61,66,67,65,68,71,68,68,69,65,65,66,69,67,65,65,65,66,66,66,66,66,66,66,65,66,66,66,67,67,67,67,67,67,68,67,67,68,68,68,69,69,69,69,71,69,70,71,70,71,72,71,72,72,72,73,73,72,73,73,73,72,74,72,73,72,73,74,74,74,74,73,73,73,74,74,73,75,74,74,74,74,74,74,74,74,74,75,75,75,75,75,75,75,75,76,76,76,76,76,77,77,76,77,76,76,77,76,78,77,76,77,76,77,78,77,78,78,78,78,78,78,79,79,79,79,79,79,79,79,79,64,64,64,64,64,64,64,65,28,65,28,66,27,66,27,67,26,67,26,68,26,68,25,69,25,79,31,31,29,26,26,24,31,23,29,22,26,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,221,221,221,221,221,221,221,221,221,221,220,220,220,220,220,220,220,220,220,220,219,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,193,196,194,196,194,193,194,194,194,196,193,196,196,196,194,193,194,194,194,194,194,197,194,194 +,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,108,107,107,107,252,107,252,107,252,107,252,107,252,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,109,107,109,109,107,109,107,107,107,109,101,102,101,102,101,102,103,103,103,103,96,103,103,96,97,97,97,52,97,98,97,103,53,52,47,101,52,99,97,52,99,52,46,52,46,52,52,52,52,54,53,54,54,51,51,50,51,102,52,53,53,49,52,52,53,53,53,50,103,102,52,102,102,53,102,52,102,52,53,53,52,53,53,53,53,53,53,53,53,53,52,53,52,53,52,53,52,53,52,53,52,53,52,53,52,53,52,53,52,53,52,53,52,53,53,53,52,53,53,53,53,53,53,53,54,54,54,54,54,55,56,55,56,57,56,54,57,54,56,58,56,57,53,56,58,53,52,55,53,54,55,53,55,55,57,58,57,58,58,58,58,57,58,57,59,59,57,60,58,61,59,62,63,63,61,61,61,59,60,63,59,60,63,63,63,60,60,60,63,63,92,62,93,63,63,61,63,81,62,63,95,81,63,63,80,83,82,84,85,84,64,60,64,64,84,62,86,86,64,69,59,86,67,68,67,68,67,70,71,73,75,67,69,70,68,69,66,66,69,66,71,68,67,68,67,66,66,67,67,67,67,67,67,68,68,68,68,68,68,69,69,69,68,69,69,69,70,69,69,70,71,71,71,72,72,72,72,73,73,72,73,73,73,73,74,73,74,73,74,74,74,74,74,73,74,73,74,75,74,75,73,74,75,75,74,74,74,75,74,75,76,75,76,75,75,75,76,76,77,76,77,76,77,77,77,77,76,77,78,77,78,77,77,77,78,78,77,78,78,79,78,79,78,79,79,79,79,79,64,79,64,79,64,79,64,64,64,65,64,65,65,66,27,66,27,67,27,67,30,68,29,68,28,69,27,69,26,70,25,79,24,27,23,25,22,24,23,22,22,218,22,218,31,218,26,218,22,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,221,221,221,220,221,220,221,220,221,220,221,220,220,220,220,219,220,219,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,193,196,194,193,194,193,194,193,194,196,193,196,193,196,194,193,194,193,194,193,194,197,194,197,194 +,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,107,108,107,107,107,107,107,108,107,252,107,109,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,109,107,109,109,109,107,109,107,107,109,101,102,101,52,103,102,52,103,103,102,52,103,96,52,96,52,97,97,52,98,52,96,52,96,52,103,96,52,102,99,52,52,54,54,101,52,53,52,54,101,54,53,52,53,52,53,53,49,52,96,52,52,52,53,53,53,102,53,52,54,102,52,52,53,52,102,53,52,53,52,53,52,53,53,53,53,53,53,53,52,53,53,53,52,53,53,53,52,53,53,53,52,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,54,54,54,54,54,55,55,55,55,55,55,55,56,56,56,56,58,54,52,53,56,59,52,52,56,54,56,55,57,54,56,57,59,60,59,60,58,63,57,63,57,62,58,62,57,89,58,63,58,61,62,61,62,61,62,59,63,62,91,62,60,62,59,61,61,58,92,92,63,92,92,63,63,93,62,81,61,81,62,81,82,82,82,81,82,84,83,84,86,64,65,87,66,87,86,65,65,86,69,66,66,65,64,66,68,69,75,72,73,73,74,68,68,74,73,73,72,69,73,68,72,75,68,68,69,69,69,69,70,68,68,67,67,69,69,70,69,69,70,69,70,69,70,70,70,70,71,71,71,71,70,70,71,72,72,73,72,71,73,72,73,74,73,73,74,73,74,74,74,75,75,74,74,75,74,74,75,74,75,74,75,75,75,75,75,75,75,74,75,76,75,76,76,76,76,76,76,77,76,77,77,77,77,77,77,77,78,77,78,78,78,78,78,78,78,78,78,79,79,79,79,79,79,79,79,79,79,64,64,64,64,64,64,64,64,65,65,65,65,66,66,66,66,66,66,67,23,67,26,68,26,68,25,69,25,69,25,70,24,70,24,27,24,29,23,30,23,218,22,218,30,218,28,218,26,218,24,218,23,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,220,221,220,220,220,220,220,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,196,194,193,194,194,194,194,194,196,193,193,196,196,193,193,194,194,197,197,197,197,197,197,197,197 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,108,107,252,107,109,107,252,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,107,107,109,107,109,107,109,107,109,109,101,53,102,102,52,102,53,102,53,53,102,103,53,96,103,52,52,97,52,47,53,54,53,54,53,54,102,52,52,102,53,52,53,54,54,53,53,101,54,54,52,53,52,53,54,53,54,53,54,54,52,53,53,52,53,53,53,50,52,52,52,102,52,53,53,53,53,53,53,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,54,54,54,54,54,55,55,55,55,55,55,55,56,56,56,56,56,56,56,56,56,56,58,52,55,57,58,52,55,58,58,60,57,53,56,59,56,58,55,59,56,63,63,85,63,60,86,60,88,62,90,59,90,59,89,60,61,60,89,63,90,63,62,91,63,92,60,60,63,62,61,60,62,60,92,93,92,92,63,93,93,63,94,63,81,80,65,62,65,81,83,83,83,65,65,65,64,65,65,65,65,66,89,65,88,66,66,68,70,66,68,70,71,71,75,72,70,74,75,73,75,74,73,74,72,68,71,73,72,72,73,71,72,69,68,69,71,72,70,70,71,69,71,70,70,71,71,71,71,70,71,72,71,71,72,71,72,72,71,72,71,71,70,72,72,73,73,72,73,73,73,73,74,74,74,74,74,74,74,75,74,75,75,75,75,74,75,75,75,75,75,76,76,75,75,76,75,75,76,76,76,77,76,77,76,77,76,77,77,78,77,78,77,78,77,78,78,79,78,79,78,79,78,79,79,79,64,79,64,79,64,79,64,79,64,64,64,64,64,65,28,65,28,65,65,66,30,66,30,67,29,67,28,68,27,68,27,69,26,69,25,70,24,70,24,71,23,71,30,72,28,27,27,28,26,29,24,31,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,221,217,221,217,221,217,221,217,221,221,221,221,220,221,220,221,220,221,220,221,220,220,219,220,219,220,219,220,219,219,219,220,219,219,219,220,219,219,219,220,219,219,219,220,219,196,196,193,196,194,193,194,193,194,194,196,196,196,196,197,196,194,194,194,194,197,197,198,197,198,197,198,197,198 +,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,108,107,108,107,107,107,109,107,109,107,252,107,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,107,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,109,107,109,109,109,107,109,107,107,107,109,109,50,52,102,53,102,53,53,102,98,103,53,98,102,53,53,53,54,53,98,53,54,54,54,54,54,54,54,54,54,54,54,54,55,101,55,54,55,55,54,54,54,53,53,53,54,53,54,55,54,55,101,55,55,52,52,53,52,52,52,53,53,53,53,53,53,53,54,53,53,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,53,54,54,54,54,54,54,54,54,54,54,54,54,55,54,55,54,55,54,54,55,56,56,56,56,56,56,56,56,56,56,56,57,56,57,57,57,58,58,57,57,57,56,57,55,59,60,59,60,58,63,57,58,62,85,85,86,86,86,62,87,88,89,90,62,90,89,64,60,89,62,89,91,90,62,66,91,92,90,93,91,91,91,92,62,94,63,92,61,92,93,93,95,94,80,94,95,81,81,66,81,67,82,82,65,65,65,68,65,66,66,66,67,66,66,66,66,66,66,66,67,67,67,67,68,70,70,75,72,72,74,75,75,75,73,71,75,72,74,71,71,75,73,73,72,74,73,71,71,72,72,71,71,71,72,71,73,71,71,73,72,72,72,72,72,72,73,72,72,72,72,73,73,71,72,73,71,72,73,72,73,73,73,73,73,74,73,74,74,74,74,74,74,75,74,75,75,75,75,75,75,75,75,76,76,76,76,76,76,76,76,77,77,77,77,77,77,77,77,78,77,78,78,78,78,78,78,79,78,79,79,79,79,79,79,79,30,79,79,79,64,79,29,64,29,64,64,64,64,64,64,65,65,65,65,66,65,66,66,66,66,67,67,67,67,68,68,68,26,69,25,69,25,70,25,70,24,70,24,71,30,71,29,72,27,22,30,218,29,218,27,218,26,218,30,218,28,218,25,218,23,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,220,220,220,220,220,220,220,220,219,220,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,196,194,193,194,193,194,194,196,196,196,196,196,196,197,197,197,197,197,197,197,197,198,197,198,198,198,198 +,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,107,108,107,252,107,252,107,252,107,252,107,107,107,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,252,252,109,109,107,109,107,109,107,109,107,107,107,109,52,52,103,102,53,102,98,53,52,53,53,54,53,54,53,98,53,54,54,54,54,54,54,55,54,54,54,55,54,55,54,55,55,55,54,55,55,55,55,55,55,55,55,55,55,54,54,54,55,54,55,55,55,55,55,55,55,53,56,52,53,54,53,53,53,54,54,54,54,54,54,54,54,54,54,54,54,55,54,55,54,55,54,54,54,55,54,55,54,55,54,55,54,55,54,55,54,55,54,55,54,55,55,55,55,55,55,55,55,56,56,57,56,57,56,57,57,57,57,58,57,58,57,58,57,58,58,59,58,58,56,57,57,58,59,56,63,63,85,63,60,84,83,84,83,84,85,86,87,86,88,91,64,65,62,65,92,65,90,91,65,64,92,91,67,92,65,65,65,66,93,67,67,92,65,64,67,63,65,65,93,64,65,66,67,68,80,68,66,81,66,65,64,66,66,66,69,67,67,67,67,70,69,68,68,68,68,67,69,67,68,69,68,66,69,66,70,69,71,68,73,74,75,75,74,75,75,72,74,74,72,72,75,111,111,111,104,104,74,74,72,71,73,74,72,73,73,72,73,73,73,73,73,72,72,72,72,72,72,74,74,73,73,73,73,74,74,74,73,74,74,74,75,74,75,75,74,75,74,75,74,75,75,76,75,76,75,76,75,76,76,76,76,77,76,77,76,77,76,77,77,78,77,78,77,78,77,78,78,79,78,79,78,79,78,79,79,79,79,79,79,79,64,79,64,79,64,79,64,79,29,64,64,64,64,64,30,65,29,65,27,66,25,66,66,67,66,67,66,67,67,68,67,68,68,69,68,69,69,70,69,70,28,70,28,71,27,71,26,72,25,72,24,73,24,29,23,31,22,218,22,218,30,218,28,218,27,218,25,218,24,218,22,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,220,221,220,221,220,221,220,220,220,221,219,220,219,220,219,220,219,220,219,220,219,220,219,220,219,220,219,196,196,196,196,197,196,194,196,194,194,194,197,196,196,197,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,198 +,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,107,108,107,108,107,108,107,108,108,252,108,252,108,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,109,109,107,109,109,107,109,107,109,107,109,107,109,53,52,53,102,53,52,53,98,53,102,53,54,53,54,54,54,53,54,54,54,54,54,54,55,54,55,54,55,54,55,54,55,55,55,55,55,55,55,56,56,56,56,56,56,55,55,55,55,55,55,55,55,55,55,56,54,54,53,54,56,53,54,54,54,53,55,54,54,54,54,54,55,54,54,54,54,54,55,54,55,54,55,54,55,54,55,54,55,54,55,55,55,55,55,55,55,55,55,55,55,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,58,59,59,59,59,59,59,59,59,60,63,63,62,62,84,58,62,85,85,86,86,86,83,84,83,84,84,85,85,85,85,88,88,91,91,92,92,64,66,64,65,64,66,65,67,65,66,65,67,66,68,67,67,67,66,65,66,65,92,68,65,66,66,67,68,68,69,66,67,66,68,64,67,66,66,67,69,69,67,69,69,69,69,69,70,69,69,68,69,68,69,70,69,70,71,69,67,67,70,67,71,71,73,75,75,74,105,105,105,105,105,105,111,111,110,110,110,110,110,104,76,72,73,74,74,74,73,75,74,73,74,73,74,73,74,74,74,74,74,74,74,74,74,74,75,74,75,74,75,75,75,75,75,75,75,75,75,75,75,75,75,76,75,76,76,76,76,76,76,76,76,77,77,77,77,77,77,77,77,78,77,78,77,78,78,78,78,78,78,78,78,79,79,79,79,79,79,79,79,79,79,79,64,79,64,64,64,64,64,64,64,64,64,64,64,65,65,65,65,66,66,66,27,67,27,67,27,67,27,68,26,68,26,68,26,69,26,69,25,70,25,70,25,71,24,71,24,71,31,72,30,72,29,72,28,28,31,29,30,30,28,31,27,218,26,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,220,220,220,220,220,220,220,220,219,219,219,219,219,219,219,219,219,219,219,219,219,196,196,196,196,197,196,197,197,194,194,194,194,196,196,196,196,197,197,197,197,197,197,197,197,198,197,198,198,198,198,198,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,107,252,107,108,107,252,107,252,108,252,108,252,108,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,109,107,109,107,109,107,109,107,107,107,109,107,109,101,52,53,53,101,53,53,103,53,54,54,54,54,54,54,55,54,55,54,55,55,55,55,55,55,55,55,55,55,55,55,55,55,56,56,57,56,57,56,57,57,57,57,58,58,56,56,56,56,56,55,55,55,55,57,57,57,58,58,58,56,55,55,55,55,55,54,54,55,55,55,55,54,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,56,57,56,57,56,57,57,58,57,58,57,58,57,58,58,58,58,59,58,59,58,59,59,59,59,59,59,60,59,60,60,60,60,60,60,60,60,61,63,83,83,83,83,63,84,83,84,83,84,85,86,84,83,84,85,84,86,85,86,86,88,88,89,89,89,65,64,66,65,64,65,65,65,66,66,66,67,66,68,68,67,68,68,68,67,69,68,68,68,69,69,66,68,70,69,69,68,70,68,69,69,67,69,68,70,70,69,69,68,70,70,70,70,69,68,70,69,71,69,70,71,72,72,72,72,71,69,105,105,105,105,105,105,105,105,111,110,111,105,105,111,111,110,110,110,111,110,111,110,104,104,74,75,76,74,75,75,75,75,75,74,75,75,74,74,74,74,75,75,76,76,75,75,75,75,75,75,76,76,75,75,75,75,76,76,76,75,76,75,76,76,77,76,77,76,77,76,77,76,77,77,78,77,78,77,78,77,78,78,78,78,78,78,79,78,79,78,79,78,79,79,79,64,79,64,79,64,79,64,79,64,79,29,79,64,64,64,64,28,65,28,65,28,65,28,66,27,66,27,67,27,67,67,68,67,68,67,68,68,69,68,69,68,69,28,70,27,70,26,71,25,71,24,72,23,72,23,72,22,73,23,73,23,27,23,28,22,28,22,29,22,30,22,31,22,218,31,218,29,218,27,218,25,218,23,218,22,218,218,218,218,218,218,218,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,220,221,220,221,220,220,220,220,219,221,219,220,219,220,219,220,219,220,219,220,219,220,196,196,196,197,196,194,197,194,194,198,197,196,196,197,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,198,197,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,107,108,107,108,107,108,107,108,108,109,108,252,108,108,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,107,109,107,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,109,109,109,107,109,107,109,107,107,107,109,109,54,53,54,53,54,53,54,53,54,53,54,53,54,54,54,54,54,55,54,55,54,55,54,55,55,55,55,55,55,55,55,56,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,57,58,58,58,55,56,56,56,57,57,57,57,57,58,58,56,56,56,56,56,55,55,55,55,55,55,55,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,58,59,58,59,59,59,59,59,59,60,59,60,60,59,60,60,60,59,60,60,60,61,61,61,61,61,61,61,62,83,81,82,83,82,82,83,82,83,84,83,84,84,85,85,85,85,85,86,86,87,86,87,86,87,87,89,64,64,89,64,64,64,66,64,65,65,65,65,66,66,67,66,66,67,67,67,67,68,68,69,68,68,68,69,69,69,69,69,70,69,68,70,70,71,69,69,69,69,70,69,70,70,69,70,70,71,70,70,71,71,72,71,71,72,72,105,105,105,105,105,105,105,105,110,110,110,110,111,111,111,111,105,110,110,110,110,110,110,110,111,110,111,104,111,104,76,76,76,76,75,76,76,76,75,75,76,75,76,76,75,75,76,76,76,76,76,77,76,77,76,76,76,76,76,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,78,77,78,77,78,78,78,78,78,78,78,78,79,79,79,79,79,31,79,79,79,79,79,64,79,64,79,64,64,64,64,64,64,64,64,30,64,29,65,28,65,27,65,26,66,25,66,66,67,67,67,67,67,67,68,26,68,26,68,68,69,69,69,69,70,70,70,70,70,70,71,71,71,24,71,31,72,29,72,26,73,31,78,30,79,29,218,28,218,27,22,26,25,25,28,25,31,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,217,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,220,221,220,220,220,220,220,220,219,219,219,219,219,219,219,219,219,219,196,196,197,197,196,197,194,196,197,198,196,196,196,196,196,197,196,197,197,197,197,197,197,198,197,198,198,198,198,198,198,198,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,107,108,107,252,107,252,107,252,107,252,108,252,108,252,108,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,109,109,109,107,109,107,109,107,107,107,109,107,109,54,53,54,53,54,53,54,54,54,54,54,54,54,55,55,55,54,55,55,55,55,55,55,55,55,56,55,56,56,56,56,57,56,57,57,57,57,58,57,58,57,58,58,59,58,59,58,59,59,58,58,58,58,58,58,57,58,58,58,57,57,57,57,58,58,58,57,58,58,58,55,56,56,56,56,57,57,57,57,58,57,58,57,58,57,58,58,58,58,59,58,59,58,59,59,59,59,60,59,60,59,60,60,60,60,61,60,60,61,60,58,60,61,61,60,59,60,61,82,61,63,82,82,82,82,82,82,82,82,82,83,83,84,83,84,85,84,86,85,86,86,64,64,64,64,87,64,88,65,64,65,65,64,65,65,65,65,65,66,65,66,66,66,65,66,65,66,66,66,67,67,67,68,68,68,69,68,68,69,69,70,69,69,70,71,70,71,70,71,70,70,71,70,71,71,72,71,71,71,71,70,70,71,71,72,71,71,72,105,105,105,111,105,111,105,105,110,110,110,111,110,111,110,111,111,105,110,110,110,111,110,111,110,111,110,111,104,106,104,106,106,75,75,76,76,76,75,76,76,76,76,76,77,77,76,76,76,77,77,77,77,76,76,77,76,77,76,77,77,77,77,77,77,77,77,77,77,77,77,78,77,78,77,78,77,78,77,78,78,78,78,79,78,79,78,79,78,79,79,79,79,79,64,79,64,79,64,79,64,79,64,79,64,64,64,64,64,64,64,65,64,65,65,65,22,66,28,66,27,66,27,67,27,67,27,68,26,68,26,68,30,69,29,69,28,69,27,70,27,70,26,71,25,71,24,71,23,72,22,72,24,72,24,73,23,73,23,78,23,78,23,79,23,79,22,218,22,218,22,218,22,218,31,218,29,218,27,218,26,218,24,218,22,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,220,220,220,220,196,196,196,196,196,196,196,196,196,197,196,197,194,197,198,196,197,196,197,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,198,198,198,198,198 +,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,108,107,108,107,108,107,108,107,109,107,108,108,252,108,109,108,252,108,108,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,109,109,109,109,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,109,109,109,109,107,109,107,109,107,107,107,109,107,109,54,53,54,53,54,53,54,54,54,54,54,54,54,55,55,55,54,55,55,55,55,55,55,55,55,56,55,56,56,56,56,57,56,57,57,57,57,58,57,58,57,58,58,59,58,59,58,59,59,59,59,58,59,59,59,58,57,58,58,58,59,58,59,58,59,59,58,58,58,58,58,58,57,58,57,57,57,58,58,58,58,58,58,58,58,59,59,59,59,59,59,59,59,60,60,60,60,60,60,61,60,61,61,61,61,61,60,61,60,60,58,61,61,60,61,59,61,82,82,82,82,82,82,82,82,82,82,82,82,82,82,83,83,83,84,85,84,85,65,65,86,65,65,65,64,65,65,65,65,65,66,65,66,65,66,67,66,66,66,66,66,66,66,66,66,66,66,66,66,66,67,67,67,67,68,68,68,68,68,68,70,69,70,70,70,71,71,71,71,71,71,71,70,71,71,72,71,70,71,71,71,71,72,71,72,105,105,105,111,111,111,111,105,111,110,110,110,110,110,111,111,111,111,105,110,110,110,110,110,110,110,111,110,111,104,111,111,104,106,106,76,76,75,75,76,76,77,76,76,76,76,77,76,76,76,76,76,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,78,77,78,78,78,78,78,78,78,78,79,79,79,79,79,79,79,31,79,79,79,30,79,30,79,64,79,64,64,64,64,64,64,64,64,64,64,64,65,28,65,28,65,28,66,28,66,66,66,27,67,27,67,27,67,27,68,26,68,26,68,26,69,26,69,26,70,26,70,25,70,25,70,25,71,25,71,24,72,24,72,30,72,29,73,28,73,31,73,29,78,29,79,28,79,27,218,26,218,25,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,220,220,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,197,197,196,196,194,194,198,196,196,196,196,196,197,196,197,197,197,197,197,197,198,197,198,197,198,198,198,198,198,198,198,198 +,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,109,252,252,107,109,107,252,107,109,107,109,108,252,108,109,108,252,108,108,108,109,252,252,108,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,109,109,109,109,107,109,107,107,107,109,107,109,109,54,54,54,55,54,55,54,55,54,55,54,55,54,55,54,55,55,55,55,55,55,55,56,55,56,57,56,56,56,56,57,57,57,57,57,57,58,58,58,58,58,58,59,58,59,59,59,59,59,59,59,59,58,59,59,59,58,58,57,58,58,59,58,59,58,59,59,59,59,58,59,59,59,58,57,58,59,58,59,58,59,58,59,60,60,60,59,59,59,60,61,61,60,61,60,61,61,61,62,61,62,62,62,62,62,61,61,61,60,60,82,82,59,82,61,82,82,81,61,61,82,61,82,82,82,82,82,82,82,83,64,82,83,83,84,84,83,64,65,64,64,64,64,65,66,65,66,66,66,66,66,65,67,65,66,67,66,67,67,68,67,67,66,67,67,67,67,67,67,67,67,67,68,67,68,67,68,67,69,69,69,70,70,69,69,70,70,70,70,71,71,72,71,71,72,72,71,72,73,72,71,72,71,105,105,105,111,110,111,110,111,105,110,110,110,110,111,110,111,110,111,110,105,110,111,110,110,110,111,110,111,110,111,104,111,106,104,107,107,106,106,75,76,76,76,76,76,77,77,77,77,76,77,76,77,76,77,78,77,77,78,78,77,78,77,78,77,78,78,77,77,78,78,77,77,78,78,77,78,78,79,78,79,78,79,78,79,79,79,79,79,79,79,64,79,64,79,64,79,64,79,64,79,64,79,64,64,64,64,64,65,64,65,28,65,28,66,28,66,28,66,27,67,66,67,66,67,67,68,67,68,68,68,68,69,29,69,28,69,27,70,25,70,25,70,24,71,31,71,30,71,29,72,28,72,27,72,26,73,25,73,24,73,23,74,22,74,22,74,31,31,29,218,28,218,27,218,25,218,24,218,30,218,28,218,27,218,25,218,24,218,22,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,217,221,217,221,221,196,196,196,196,196,196,196,196,196,196,196,197,197,196,196,197,196,197,197,198,197,198,198,197,197,196,196,196,196,197,197,194,197,198,196,196,196,197,196,197,196,197,196,197,197,198,197,198,197,198,197,198,198,198,197,198,198,198,198,198 +,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,109,252,108,107,108,107,108,107,109,107,109,108,252,108,109,108,252,252,252,108,108,252,109,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,107,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,107,107,107,109,109,109,54,54,54,55,54,55,54,55,54,55,54,55,54,55,54,55,55,55,55,55,55,55,56,55,56,57,56,56,56,56,57,57,57,57,57,57,58,58,58,58,58,58,59,58,59,59,59,59,59,59,59,59,59,59,59,59,59,59,58,58,59,58,59,59,59,59,59,59,59,59,58,59,59,59,58,58,58,59,59,59,58,60,60,58,60,60,60,60,59,60,61,61,62,60,61,61,62,61,62,62,63,63,63,62,61,61,62,81,82,82,82,61,63,82,60,61,82,61,82,84,84,82,82,82,82,84,82,82,82,65,65,65,64,66,64,64,65,65,65,67,65,65,67,65,66,66,65,66,66,66,66,66,66,67,67,67,67,67,67,67,67,67,68,68,67,68,68,68,68,68,68,68,68,68,68,68,68,69,69,69,69,69,69,69,69,69,70,70,70,70,70,71,71,71,71,72,71,72,72,71,72,105,105,105,110,111,111,111,111,111,105,111,110,110,110,111,110,111,111,111,111,111,110,110,110,110,110,110,110,111,110,111,104,111,106,108,104,107,106,106,106,106,76,76,76,76,76,76,76,77,77,77,77,77,77,77,77,77,77,77,78,77,78,77,78,78,78,78,78,78,78,78,78,78,78,78,78,79,78,79,79,79,79,79,79,79,79,79,79,79,79,79,64,79,64,79,64,64,64,64,64,64,64,64,64,64,64,64,64,65,65,65,27,65,65,66,66,66,66,66,66,67,67,67,67,67,22,68,27,68,26,68,26,69,69,69,69,69,26,70,25,70,25,70,25,71,25,71,25,71,25,72,24,72,24,72,24,73,24,73,31,73,30,73,28,74,27,74,25,31,24,31,23,218,31,218,30,218,28,218,27,218,26,218,25,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,221,217,221,221,221,221,221,196,196,196,196,197,197,197,197,197,197,197,197,196,196,196,196,197,197,197,197,197,197,198,198,198,196,196,196,197,197,197,197,194,198,198,196,196,196,196,196,197,196,197,197,197,197,197,197,197,197,198,198,198,198,198,197,198,197,198,198,198,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,109,107,252,107,252,107,109,108,252,108,109,108,252,108,252,108,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,109,109,109,107,109,107,109,107,109,107,109,109,55,54,55,54,55,54,55,54,55,55,55,55,55,55,55,55,57,56,55,56,55,56,56,57,57,58,58,57,57,58,57,58,57,58,58,59,58,59,58,59,59,60,59,60,59,60,60,60,61,59,59,59,59,59,59,59,59,59,59,58,59,58,59,59,59,59,59,59,59,59,59,59,59,59,59,59,58,59,61,60,59,61,59,60,60,60,59,59,60,61,61,61,61,62,62,63,62,63,63,63,62,62,61,63,63,63,61,61,82,82,65,80,82,62,82,63,61,82,64,64,83,82,82,84,60,60,64,64,66,66,67,66,67,66,66,65,65,65,66,67,66,67,66,67,67,68,67,67,67,66,67,66,66,66,67,67,67,68,68,68,68,67,68,68,68,68,68,69,68,69,69,69,69,68,69,69,69,69,70,69,70,69,70,69,70,70,70,70,71,70,71,70,71,70,71,70,71,71,71,105,105,105,111,110,111,111,111,111,111,105,111,110,111,110,111,110,111,110,111,110,111,111,110,110,111,110,111,110,111,110,111,110,111,106,108,108,104,107,107,106,106,106,76,76,76,76,77,77,76,77,76,77,76,77,77,77,77,78,78,77,77,78,78,77,78,77,78,77,78,78,79,78,79,78,79,78,79,79,79,79,79,79,79,64,79,64,79,64,79,64,79,64,79,64,79,64,64,64,64,29,64,29,65,28,65,28,65,28,65,28,66,65,66,66,66,27,67,27,67,27,67,27,68,27,68,26,68,26,69,26,69,26,69,26,70,25,70,25,70,30,70,30,71,29,71,29,77,28,77,28,77,27,78,27,73,26,73,26,73,25,74,25,74,24,74,24,218,30,218,28,218,26,218,24,218,22,218,31,218,29,218,28,218,26,218,25,218,24,218,22,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,217,221,221,196,196,196,196,196,197,196,196,196,197,196,197,196,197,196,196,196,197,196,197,196,197,197,198,197,196,196,197,196,197,196,197,197,198,197,198,198,196,196,197,196,197,196,197,196,197,197,197,197,198,197,198,197,198,197,198,198,198,198,196,198,198,198,198 +,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,108,252,108,107,108,107,109,107,108,107,252,252,109,108,252,252,252,108,108,108,252,252,109,252,109,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,109,109,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,109,109,109,109,107,109,107,107,107,109,109,109,107,55,55,55,55,55,55,55,56,57,56,57,56,57,57,58,58,58,56,56,57,56,57,57,59,57,58,59,58,58,58,58,59,59,59,59,60,60,60,60,60,60,61,60,61,61,61,61,61,61,61,59,59,59,61,59,59,59,59,59,59,60,59,60,60,60,61,59,59,59,59,59,59,59,59,59,61,61,61,62,60,59,60,62,59,60,58,59,59,60,59,60,63,62,62,63,62,63,63,81,63,63,61,63,82,61,64,64,64,64,63,65,63,82,82,82,65,64,64,83,63,65,83,83,66,83,65,65,66,67,67,66,67,66,67,68,66,67,67,70,67,67,68,69,68,68,67,68,67,69,67,67,66,67,66,67,67,66,68,67,68,68,68,68,68,68,69,69,69,69,70,71,70,70,70,70,70,70,70,70,70,70,70,71,70,71,70,71,71,71,71,71,71,71,71,72,72,105,105,105,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,110,110,111,111,111,111,111,106,107,108,104,107,107,107,107,106,106,106,76,76,76,77,77,77,77,77,77,77,77,77,77,77,77,77,78,78,78,78,78,78,78,78,79,78,79,78,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,64,79,64,79,64,79,64,79,64,79,64,79,64,64,64,65,65,65,65,66,66,66,66,66,66,66,66,67,67,67,27,68,26,68,26,68,25,68,25,69,24,69,24,69,23,70,23,70,22,70,25,71,25,71,25,71,25,71,24,78,24,78,24,78,24,79,31,79,30,27,29,29,28,31,27,218,26,218,31,218,29,218,30,218,29,218,28,218,27,218,25,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,221,217,221,221,221,221,221,196,196,196,196,197,196,196,196,196,196,197,196,196,196,197,197,196,196,196,196,197,196,196,196,196,196,197,197,197,197,197,197,197,197,198,198,198,198,196,196,196,196,197,196,197,196,197,197,197,197,197,197,198,197,198,198,198,198,198,198,198,198,198,198,198,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,107,109,107,109,107,109,108,252,108,252,108,252,108,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,107,109,107,252,107,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,109,109,109,107,109,107,109,107,107,107,109,109,109,55,55,55,55,55,55,56,57,56,57,56,57,57,58,58,58,56,56,57,56,57,57,59,57,58,59,58,58,58,58,59,59,59,59,60,60,60,60,60,60,61,60,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,59,59,59,59,59,59,61,61,61,61,61,59,59,59,61,59,62,62,62,61,62,60,59,59,61,59,60,62,60,58,59,59,90,91,92,61,92,63,62,63,62,63,62,94,94,82,80,80,94,80,94,80,65,81,82,65,65,82,82,66,66,67,67,83,68,84,67,66,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,69,70,70,71,69,68,69,69,68,68,69,68,69,68,67,67,68,68,67,68,69,69,68,69,68,69,70,70,71,71,70,71,70,70,70,71,71,70,71,70,70,71,72,72,71,71,72,71,72,72,72,71,72,105,105,105,111,111,111,111,111,111,111,111,111,111,111,110,110,110,111,110,111,110,111,110,111,111,111,110,111,110,111,110,111,111,111,111,111,104,106,107,104,107,108,107,107,106,107,106,106,106,76,77,77,77,77,77,77,77,78,77,78,77,78,77,78,78,79,78,79,78,79,78,79,79,79,79,79,79,79,64,79,79,79,30,79,30,79,30,79,30,79,31,79,30,79,29,64,29,64,28,64,28,65,27,65,27,66,26,66,25,66,25,66,24,67,24,67,23,67,22,67,22,68,26,68,26,68,26,69,26,69,31,69,30,70,29,70,29,70,28,70,27,71,26,71,26,71,25,72,24,72,23,72,30,67,29,73,28,79,27,26,26,28,24,29,23,30,22,31,23,218,31,218,29,218,27,218,26,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,217,217,217,221,217,221,217,221,221,196,196,196,196,196,197,196,196,196,197,196,197,196,197,196,197,198,197,196,196,196,197,196,197,196,197,196,197,197,197,197,197,197,198,197,198,197,198,197,198,196,196,196,196,196,197,196,197,197,197,197,197,197,198,197,198,198,198,198,198,198,198,198,198,198,198,196,196 +,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,108,252,108,107,109,107,108,107,109,108,109,108,109,252,252,252,252,252,108,108,252,252,109,252,109,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,109,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,107,109,107,109,107,109,109,109,107,107,57,57,57,57,58,58,58,58,58,58,58,57,57,59,59,57,57,58,57,58,59,59,58,59,59,60,59,60,60,61,60,61,61,61,62,61,60,62,60,61,60,62,62,62,61,62,62,61,61,61,61,61,61,94,61,61,61,59,59,61,59,61,61,61,61,59,59,63,61,63,62,62,84,84,62,62,62,62,63,61,61,62,60,60,60,60,60,59,91,61,91,92,92,92,93,93,94,94,63,94,63,62,65,63,63,80,63,63,63,64,66,66,65,64,65,65,66,68,68,69,68,69,105,105,105,105,105,110,105,105,110,110,110,111,110,111,111,111,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,68,69,69,69,69,70,69,70,70,70,71,71,72,70,71,70,71,71,71,71,71,71,72,71,71,72,72,72,72,72,72,72,71,72,105,105,111,105,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,111,111,111,111,111,110,110,110,111,111,111,110,111,111,111,111,111,111,111,104,106,106,107,107,107,107,107,106,106,106,106,77,77,77,77,77,78,78,78,78,78,78,78,78,78,78,79,78,79,79,79,79,79,79,79,79,79,79,79,79,79,31,64,30,64,30,64,29,64,28,64,27,65,27,65,26,65,26,65,29,65,29,65,28,65,28,66,28,66,28,66,28,66,28,67,27,67,27,67,27,68,27,68,27,68,27,68,26,69,26,69,26,69,26,70,26,28,26,30,25,71,25,71,25,71,25,71,25,72,25,72,24,72,24,73,24,27,24,28,24,28,30,29,29,30,28,30,26,31,25,31,24,218,23,218,31,218,29,218,28,218,27,218,25,218,24,218,23,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,217,217,221,221,221,196,196,196,196,196,196,196,196,197,196,196,196,196,196,196,196,197,197,198,198,196,196,196,196,196,196,197,197,197,197,197,197,197,197,197,197,197,197,198,198,198,198,198,198,196,196,196,196,197,197,197,197,197,197,197,197,198,198,198,198,198,198,198,198,198,198,196,196,196,196,196,196 +,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,109,107,109,107,252,107,109,108,252,108,252,108,252,108,252,108,252,108,252,108,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,107,109,107,109,107,107,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,109,109,107,109,107,109,107,107,107,109,109,109,107,107,58,59,58,59,58,59,59,58,59,59,59,59,59,58,59,59,60,60,94,60,61,61,58,59,59,60,59,60,60,61,60,61,61,61,62,61,60,62,60,61,60,62,62,62,61,62,62,62,62,61,62,62,62,94,61,61,81,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,84,84,63,59,83,62,62,64,61,60,66,62,64,62,62,85,60,63,91,92,93,94,63,94,94,63,64,94,95,95,66,65,64,65,66,65,66,66,67,67,68,67,67,68,105,105,105,105,105,105,105,105,105,105,110,110,111,110,111,110,111,111,105,105,105,105,105,110,111,110,111,110,111,111,110,109,105,110,111,110,111,105,105,105,71,70,70,70,70,70,70,71,71,71,72,71,72,71,72,71,72,72,72,71,72,72,72,72,73,72,73,72,73,72,73,105,105,111,111,105,111,111,111,111,111,111,111,111,111,111,111,110,110,110,111,110,111,111,111,111,111,110,111,111,111,111,111,110,111,110,111,110,111,110,111,104,104,106,107,106,107,107,107,106,107,106,107,106,106,77,78,77,78,78,78,78,79,78,79,78,79,78,79,78,79,79,79,79,79,64,79,64,79,29,79,29,79,28,79,28,64,28,64,27,65,27,65,26,65,26,65,25,66,25,66,24,69,23,70,23,71,22,72,22,73,30,74,30,75,29,77,28,78,28,79,27,26,27,27,26,27,25,28,25,28,24,29,23,30,23,30,22,31,22,71,25,71,25,71,24,71,24,72,24,72,24,72,24,73,24,25,23,26,23,26,23,27,23,28,23,29,31,29,29,30,27,31,26,31,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,221,217,221,217,221,221,196,196,198,198,198,198,196,198,197,198,197,198,197,198,197,198,198,196,196,197,196,197,196,197,196,197,196,197,197,197,197,197,197,198,197,198,197,198,197,198,197,198,198,198,196,197,196,197,196,197,196,197,197,198,197,198,197,198,197,198,198,198,197,198,197,198,196,196,196,196,196,197,197,197 +,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,109,107,108,107,109,107,109,108,109,252,109,108,252,252,252,252,108,108,252,252,252,252,109,252,252,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,107,107,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,109,109,107,109,107,109,107,107,107,109,107,109,107,59,59,59,59,59,59,60,58,59,58,60,59,61,61,61,62,62,60,60,94,60,61,61,61,61,60,61,61,61,59,58,59,59,60,59,60,60,61,60,61,61,61,62,61,60,62,94,61,60,62,62,93,61,62,61,105,105,105,105,105,105,105,110,110,110,110,110,110,111,111,111,111,110,104,106,61,64,84,83,67,65,67,66,62,67,64,64,85,65,86,65,91,92,93,64,64,65,64,94,64,64,64,65,65,65,66,67,67,66,67,67,67,67,67,105,105,105,110,105,110,105,105,105,109,110,110,110,110,110,110,111,111,111,105,105,109,110,110,110,109,110,111,111,110,111,111,111,105,105,110,110,110,110,105,105,105,105,106,73,71,71,71,71,71,71,71,71,72,72,71,72,73,72,72,72,72,73,72,72,74,73,73,73,73,73,73,105,105,111,111,111,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,110,111,111,111,106,104,108,106,106,107,107,107,107,107,106,106,107,106,106,78,78,78,78,78,78,79,79,79,79,79,79,79,79,79,79,79,31,64,30,64,30,64,29,64,28,64,27,65,27,65,26,65,26,65,65,26,65,72,24,73,23,75,23,77,22,79,29,30,28,31,28,31,28,67,31,22,30,23,30,23,29,24,28,24,28,25,27,25,26,26,26,26,25,27,25,27,24,28,23,28,23,29,22,29,25,30,31,30,30,31,30,72,29,218,28,218,27,218,27,218,26,218,25,218,24,218,24,25,23,31,22,218,22,218,22,218,31,218,29,218,27,218,25,218,23,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,221,217,221,221,221,221,196,198,198,198,198,198,196,196,197,197,197,198,197,198,197,198,198,196,196,196,196,196,196,197,197,197,196,197,197,197,197,197,197,197,197,198,197,198,197,198,198,198,198,198,198,198,196,197,197,197,197,197,197,197,197,198,198,198,198,198,197,198,197,198,198,196,196,196,196,197,197,197,197,197,197 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,252,252,252,252,108,109,107,109,107,252,107,109,108,252,108,252,108,252,108,252,252,108,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,109,107,252,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,109,107,109,107,109,107,109,107,109,107,109,107,109,107,60,61,61,61,61,59,61,94,58,62,62,59,61,61,61,62,62,62,62,61,62,62,62,59,60,60,94,60,61,58,59,59,60,59,60,60,61,60,61,61,92,62,92,60,93,60,61,95,62,94,94,61,105,105,105,105,111,110,111,110,110,110,111,110,111,110,111,111,111,109,110,109,104,107,106,64,65,69,69,67,68,68,68,68,68,69,70,66,69,69,67,65,65,65,66,66,66,66,66,66,66,65,66,66,66,67,67,67,67,105,105,105,105,110,111,110,105,110,111,110,105,110,110,109,110,110,110,110,111,110,111,105,110,109,110,110,111,110,111,110,111,110,111,111,111,105,111,110,111,110,111,111,105,105,111,106,107,106,73,72,73,72,72,72,72,72,72,72,73,72,73,72,73,72,73,73,73,73,73,73,73,74,74,105,105,111,111,105,105,105,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,110,111,111,111,110,111,110,111,110,111,111,111,111,111,110,111,110,111,110,106,107,108,104,104,107,106,106,107,106,107,107,107,106,107,106,106,106,79,78,79,78,79,79,79,30,79,79,79,64,79,27,23,26,79,28,64,28,64,27,65,27,65,26,65,26,65,25,66,25,66,24,25,66,24,30,30,29,30,29,31,29,66,29,66,29,67,29,67,28,67,28,68,28,23,28,24,27,25,27,26,27,27,27,29,26,30,26,31,26,70,26,70,26,70,26,71,25,71,25,71,25,218,25,218,24,218,24,218,24,218,24,218,24,218,24,218,23,218,23,218,30,218,29,218,28,218,26,218,25,218,24,218,23,218,22,218,23,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,217,217,217,221,217,221,217,221,217,221,217,221,221,221,221,221,196,197,198,197,198,197,198,197,198,197,196,196,196,196,197,196,197,196,197,196,197,197,197,197,197,197,198,197,198,197,198,197,198,197,198,197,198,198,198,198,197,196,197,196,197,197,198,197,198,197,198,198,198,197,198,197,198,197,196,196,196,196,197,197,198,197,198,197,198 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,108,252,108,252,108,108,109,108,109,107,109,252,109,108,252,252,252,252,252,252,252,252,108,252,252,252,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,109,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,109,107,109,107,109,107,107,107,109,109,109,107,107,107,60,61,61,61,61,59,61,94,58,62,62,62,62,58,62,62,62,60,59,61,61,61,62,60,60,94,60,61,61,61,60,61,60,94,60,61,61,61,62,92,92,93,93,94,62,94,62,94,105,105,105,110,105,111,111,111,111,110,110,109,110,110,111,110,111,111,111,109,110,109,104,107,107,106,67,69,71,67,70,70,69,71,70,70,71,72,69,70,68,69,66,66,69,66,71,68,67,68,67,66,66,67,67,67,105,105,105,105,110,110,111,111,111,111,111,109,110,110,110,110,110,110,110,110,110,110,111,111,111,105,110,110,110,110,111,111,111,110,111,111,111,105,110,110,111,110,111,111,111,111,105,111,110,110,110,106,106,73,74,74,74,73,74,74,73,73,74,73,73,73,73,73,73,73,73,73,74,74,74,74,105,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,111,111,110,111,110,111,106,107,107,108,104,104,104,108,106,106,106,106,107,107,106,106,106,106,106,106,106,79,31,79,30,79,30,79,79,79,29,79,28,79,28,79,27,64,27,64,26,66,26,71,25,75,25,79,24,64,24,65,23,65,23,65,22,65,22,66,31,66,31,66,30,66,30,67,30,67,30,67,29,67,29,68,29,68,29,68,28,69,28,69,28,218,31,218,30,218,30,218,29,218,28,218,28,218,27,218,27,218,26,218,25,218,25,218,24,218,23,218,31,218,29,218,28,218,27,218,25,218,24,218,23,218,23,218,22,218,22,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,196,196,197,196,197,196,197,197,197,197,197,197,197,197,198,197,198,197,198,198,198,198,198,198,197,197,197,197,197,197,198,198,198,197,197,197,197,197,197,197,198,197,198,198,196,196,196,198,197,197,197,197,197,197,198,197 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,108,109,107,252,108,252,108,252,107,252,108,252,108,252,252,252,108,252,252,252,252,108,107,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,107,107,107,252,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,109,107,109,107,109,107,109,107,109,107,109,107,107,63,60,59,59,59,60,61,61,60,61,61,61,61,59,61,94,58,62,59,61,83,61,62,62,62,61,62,61,61,61,62,62,62,59,60,59,60,63,62,91,92,93,94,63,94,94,105,105,111,111,110,111,111,111,111,110,109,110,109,110,111,111,110,111,111,111,109,110,104,104,107,108,107,107,106,71,71,70,72,70,72,71,73,71,70,74,68,68,74,73,73,72,69,73,68,72,75,68,68,69,69,105,105,105,110,111,110,111,111,111,110,111,111,110,109,110,109,110,109,110,109,110,110,110,110,111,110,105,110,111,110,111,110,111,110,111,110,111,105,111,111,111,110,111,110,111,110,111,111,111,111,110,110,111,106,110,106,106,74,75,74,74,74,74,74,75,73,75,74,73,74,74,74,73,74,74,74,75,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,110,111,111,111,111,111,110,111,106,107,107,108,108,104,104,104,107,106,107,108,106,107,107,107,106,107,106,106,106,106,30,79,29,79,28,79,27,79,26,79,25,79,24,79,23,64,22,64,29,64,28,64,28,65,28,65,28,65,27,65,27,66,27,66,26,66,26,66,26,67,25,67,25,67,25,218,25,218,24,218,24,218,24,68,23,218,23,218,23,218,22,218,22,218,22,218,22,218,27,218,31,218,29,218,28,218,27,218,25,218,24,218,23,218,22,218,27,218,26,218,24,218,23,218,22,218,22,218,22,218,23,218,22,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,196,197,196,197,196,197,196,197,197,198,197,198,197,198,197,198,197,198,197,198,198,197,196,197,197,198,197,198,197,198,197,198,198,198,197,198,197,198,197,198,197,198,196,196,198,197,197,198,197,198,197,198,197,198 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,108,109,108,108,107,109,107,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,107,108,108,108,108,108,252,252,252,108,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,107,107,107,107,109,107,109,107,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,252,109,107,109,107,109,107,107,107,109,109,109,107,109,107,60,63,59,59,59,60,61,61,60,61,61,61,61,59,61,94,58,62,83,83,82,62,83,84,84,62,62,62,59,60,58,59,59,60,59,60,63,62,92,91,92,93,105,105,105,105,105,111,111,111,111,111,111,111,110,109,109,109,110,110,111,111,109,109,109,109,110,104,108,108,108,107,107,107,106,71,72,72,72,71,72,71,73,72,70,74,75,73,75,74,73,74,72,68,71,73,105,105,105,105,105,110,111,110,111,110,111,111,111,111,111,111,110,109,110,110,110,110,110,110,110,110,111,111,110,110,111,110,111,110,111,111,111,110,111,111,111,111,111,110,110,110,111,110,111,110,111,111,111,105,110,110,110,110,106,108,110,106,106,75,75,75,75,75,74,75,74,75,74,75,74,75,75,75,75,76,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,111,111,111,106,106,107,108,108,104,104,104,107,107,107,107,107,106,107,107,107,106,107,106,106,106,106,31,79,28,79,25,64,22,64,31,64,30,64,30,64,29,64,28,64,27,65,27,65,26,65,26,65,25,66,24,66,23,66,23,66,22,67,29,218,28,218,28,218,27,218,26,218,25,218,24,218,23,218,23,218,22,218,29,218,25,218,22,218,28,218,26,218,24,218,22,218,31,218,29,218,27,218,25,218,23,218,218,218,30,218,30,218,29,218,28,218,27,218,26,218,25,218,25,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,221,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,197,197,197,197,197,197,197,197,197,197,197,197,198,198,198,198,198,197,197,197,197,197,197,197,198,198,198,197,198,198,198,198,198,197,197,197,198,198,198,196,196,198,197,197,197,197,198,197,198,197,198,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,108,108,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,108,108,108,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,109,107,109,107,109,107,109,107,109,109,109,107,107,60,63,63,63,95,63,80,59,82,63,83,84,84,56,63,85,63,83,82,82,84,83,82,84,85,84,61,66,67,65,68,71,68,68,69,65,65,66,69,67,21,105,105,105,105,111,111,111,110,111,111,111,111,109,109,110,109,110,110,111,110,111,111,110,109,110,104,108,108,108,107,108,107,107,107,106,72,71,72,72,72,73,75,72,72,74,75,75,75,73,71,75,105,105,105,105,111,111,111,111,110,111,110,111,110,111,111,111,110,111,109,110,109,110,109,110,109,110,110,111,110,110,110,110,110,111,110,111,111,110,110,111,110,111,111,111,111,110,110,111,110,111,110,111,110,111,111,111,111,110,110,110,110,106,107,109,109,107,106,106,75,76,75,75,75,75,75,75,75,76,75,76,75,75,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,110,111,110,111,110,111,111,111,111,109,109,104,106,107,107,108,108,104,104,108,107,108,107,108,107,106,106,107,106,107,106,107,106,106,106,106,30,79,30,79,29,64,29,79,28,64,28,64,27,65,27,65,26,65,26,65,25,66,25,66,24,66,24,66,23,67,22,218,22,67,31,67,29,68,28,68,27,218,26,218,25,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,30,218,30,218,29,218,29,218,28,218,28,218,27,218,27,218,26,218,26,218,25,218,25,218,24,218,24,218,23,218,23,218,22,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,217,221,221,221,217,221,221,221,221,221,221,197,198,197,198,198,198,197,197,197,198,197,198,197,198,197,198,197,198,197,198,198,198,198,198,197,198,197,198,197,198,196,196,196,197,196,197,197,198,197,198,198,198,197,198 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,109,252,109,108,108,108,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,108,108,108,108,252,108,252,252,252,252,252,252,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,107,107,109,109,109,107,109,107,107,81,63,63,95,81,62,63,80,83,82,84,85,84,64,62,64,82,84,83,84,82,84,83,84,86,67,68,67,68,67,70,71,73,75,67,69,70,68,105,105,111,111,111,111,111,111,111,111,111,111,111,109,109,110,110,110,110,110,110,111,111,111,111,104,104,108,108,108,108,108,108,108,107,107,106,71,72,72,72,72,66,70,69,105,105,105,105,105,105,105,105,111,111,111,111,111,111,111,110,111,110,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,110,110,110,110,111,111,111,111,110,110,110,110,110,110,110,110,111,110,111,111,111,105,110,110,110,110,106,107,108,109,110,106,106,106,106,76,75,75,75,75,76,76,76,76,75,76,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,111,111,109,109,104,106,107,108,108,104,104,108,107,107,107,107,107,107,106,107,106,107,106,106,106,106,106,106,106,64,29,64,28,64,26,64,24,64,23,65,28,65,27,65,26,65,25,66,24,66,24,66,23,66,22,67,24,218,23,218,23,218,22,218,31,218,29,218,28,218,26,69,24,69,23,218,28,218,27,218,27,218,26,218,26,218,25,218,25,218,24,218,24,218,23,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,220,198,198,198,198,198,198,198,198,198,198,198,198,196,196,196,196,196,197,197,197,197,197,198,198,198,198,198,198 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,107,108,107,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,109,107,109,107,109,107,109,109,109,107,109,107,61,81,62,81,82,82,82,81,82,84,83,84,86,64,65,87,66,87,86,65,65,86,69,66,66,65,64,66,68,69,75,72,73,73,74,105,105,105,111,111,105,110,111,110,111,110,111,111,111,111,110,109,110,110,110,110,111,110,111,111,111,109,104,108,108,108,108,108,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,110,111,110,109,109,109,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,111,111,111,111,111,110,110,111,110,111,110,111,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,111,109,110,109,110,109,110,106,108,108,110,106,107,106,107,106,106,75,75,75,75,76,76,76,76,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,109,110,111,111,111,111,111,110,111,111,111,110,111,111,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,111,109,109,104,106,107,108,104,104,108,107,108,107,108,107,107,107,107,106,107,106,107,106,107,106,107,106,106,106,64,30,64,30,65,29,65,28,65,27,65,27,66,26,66,25,66,24,66,24,218,23,218,22,218,31,218,29,68,27,218,25,218,23,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,30,218,30,218,29,218,29,218,28,218,28,218,27,218,26,218,26,218,25,218,25,218,24,218,24,218,23,218,22,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,220,220,220,220,220,220,220,198,198,197,196,196,196,196,197,196,197,197,198,197,198,198,198,197,198,198,198 +,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,109,108,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,107,108,107,108,252,252,252,108,252,252,252,109,109,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,109,107,107,107,109,109,109,109,109,107,107,62,81,80,65,62,65,81,83,83,83,65,65,65,64,65,65,65,65,66,89,65,88,66,66,68,70,66,68,70,71,71,75,72,105,105,111,111,111,111,111,110,111,111,111,111,111,111,111,109,110,110,110,110,111,111,111,111,111,110,111,111,104,104,105,105,105,105,105,110,111,111,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,109,110,109,109,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,109,109,110,111,109,110,110,110,109,109,109,109,109,110,110,110,110,110,110,111,110,111,111,111,109,110,110,110,110,110,110,106,107,106,110,107,107,107,106,106,106,75,75,75,75,75,76,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,109,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,111,111,111,109,109,109,104,106,108,104,108,108,108,108,108,108,107,108,107,107,107,106,106,106,106,107,107,107,106,106,106,106,31,65,30,65,29,65,29,65,28,66,27,66,26,66,26,66,25,67,24,67,23,218,23,218,22,68,31,218,30,68,29,68,29,69,28,69,27,218,27,218,26,218,26,218,25,218,25,218,24,218,23,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,196,196,196,197,198,196,197,196,197,197,198,198,198,198,198,198,197,198 +,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,107,108,107,252,252,252,252,252,252,252,252,252,109,109,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,107,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,107,252,107,109,107,107,107,109,107,109,107,109,107,95,81,81,66,81,67,82,82,65,65,65,68,65,66,66,66,67,66,66,66,66,66,66,66,67,67,67,67,68,70,105,105,105,111,111,111,105,110,111,110,111,110,111,110,111,111,111,111,110,110,111,110,111,109,110,110,111,110,111,111,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,111,111,111,111,111,111,111,111,111,110,110,110,109,110,109,109,109,111,111,110,109,110,109,110,110,110,109,110,110,111,110,111,110,111,110,111,111,111,111,111,110,111,109,109,109,111,111,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,111,110,109,110,110,110,109,110,110,111,110,106,110,108,107,107,107,107,106,107,106,74,76,76,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,109,110,110,111,111,111,110,111,111,111,110,111,111,111,110,111,111,111,111,111,110,111,110,111,111,111,110,111,111,109,109,109,109,104,106,104,108,108,108,108,108,108,107,106,107,108,107,107,106,106,106,107,106,107,107,107,106,107,106,106,31,66,29,66,27,66,25,66,23,67,22,67,30,67,28,218,27,68,25,68,23,68,22,68,29,68,26,218,23,218,28,218,27,218,26,218,30,218,29,218,29,218,28,218,27,218,26,218,25,218,24,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,217,217,218,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,196,196,196,197,197,198,196,197,197,197,197,198,197,198,197,198,197,198,198,198 +,108,252,108,252,252,252,108,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,108,107,108,108,108,252,108,252,252,252,252,252,109,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,109,107,107,107,109,107,109,109,109,107,109,107,80,68,66,81,66,65,64,66,66,66,69,67,67,67,67,70,69,68,68,68,68,67,69,67,68,69,68,105,105,105,111,105,105,105,111,110,111,111,111,111,111,111,111,110,110,110,111,110,111,111,110,110,110,109,110,110,111,111,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,109,109,109,109,109,110,110,110,110,111,111,110,109,109,111,110,110,110,110,110,110,111,110,111,111,111,111,111,110,111,109,109,109,110,109,109,110,111,110,110,110,110,110,109,109,109,109,110,110,111,111,111,109,110,109,110,110,110,110,109,110,110,110,110,110,111,106,110,107,107,107,107,107,107,106,106,106,105,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,109,109,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,111,111,111,109,109,109,104,104,106,104,108,108,108,107,108,108,108,106,107,107,108,107,107,106,106,107,107,106,107,107,106,106,106,106,106,106,28,66,28,66,27,66,26,67,25,67,25,67,24,67,24,67,23,218,22,218,28,218,28,218,27,218,26,218,25,218,25,218,31,218,29,218,28,218,26,218,25,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,196,196,196,197,198,198,198,196,197,197,197,197,197,197,198,198,198,197,198,198,198,197 +,252,108,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,108,252,109,108,109,108,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,107,108,108,108,252,252,252,252,109,252,252,252,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,107,109,109,107,109,107,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,252,107,109,107,109,107,109,107,109,107,109,107,107,66,67,66,68,64,67,66,66,67,69,69,67,69,69,69,69,69,70,69,69,68,69,68,69,70,105,105,105,105,105,105,111,110,110,110,110,111,111,111,111,110,111,111,111,110,111,110,111,111,110,109,110,109,110,109,111,109,110,110,110,110,110,110,111,110,111,110,111,110,109,111,111,110,111,110,111,111,111,111,111,110,110,110,110,109,109,109,109,109,110,109,110,110,109,109,111,111,110,109,110,110,110,110,111,110,111,110,111,110,111,111,111,111,110,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,109,109,110,111,109,109,110,109,110,109,110,109,109,109,111,111,111,110,111,110,111,110,111,110,111,107,108,107,107,106,105,105,105,111,111,111,105,105,111,111,111,110,111,111,111,111,111,111,111,110,111,109,110,109,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,110,111,110,109,110,111,110,111,111,111,111,109,109,109,104,106,107,104,104,108,108,108,108,108,107,106,106,107,107,108,107,108,106,107,106,107,107,107,107,107,106,107,106,106,106,106,27,67,26,67,106,67,23,67,22,68,67,68,67,68,30,68,29,69,29,218,28,218,27,218,26,218,25,218,25,218,24,218,30,218,28,218,27,218,25,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,196,196,197,197,198,197,198,198,197,196,197,196,197,197,196,197,198,198,198,198,198,198,198 +,108,252,108,252,252,252,252,252,108,109,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,108,109,108,108,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,252,252,252,108,252,252,252,109,109,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,252,107,107,107,109,109,109,109,109,107,109,107,68,70,68,69,69,67,69,68,70,70,69,69,68,70,70,70,70,69,68,70,69,71,105,105,105,105,105,105,111,111,110,110,111,111,110,110,111,111,111,110,110,110,110,110,111,111,111,111,111,111,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,109,109,110,110,111,111,110,111,111,111,111,111,111,111,110,110,110,110,109,109,109,109,109,110,110,109,109,111,111,111,111,111,111,110,110,110,110,110,110,111,110,111,110,111,111,111,111,110,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,109,109,109,109,109,110,110,110,109,110,110,111,111,110,110,110,110,111,111,111,111,111,109,109,109,105,105,105,111,111,111,111,111,105,105,111,111,111,111,111,111,111,111,111,111,111,111,109,109,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,109,109,110,110,111,111,111,111,111,109,109,109,109,104,106,108,104,108,108,108,108,108,108,108,108,106,106,107,108,108,107,106,106,106,106,107,106,107,106,107,106,106,106,106,106,67,29,67,28,67,27,68,26,68,25,218,24,218,23,218,22,218,29,218,28,218,27,218,27,218,26,218,25,218,24,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,220,220,220,221,220,220,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,196,197,197,197,197,198,198,198,196,196,196,197,196,196,196,197,198,198,198,198,198,198,197 +,252,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,252,108,252,252,252,109,252,252,252,109,109,109,108,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,107,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,107,252,107,109,107,109,107,109,107,109,107,109,107,107,107,68,70,70,71,69,69,69,69,70,69,70,70,69,70,70,71,70,70,71,105,105,111,111,105,111,111,111,111,111,110,110,110,111,110,111,111,111,111,110,110,111,110,111,110,111,110,111,111,111,111,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,111,110,110,111,110,111,110,111,110,111,109,110,109,109,109,110,109,110,109,109,110,110,110,111,110,111,111,110,109,110,110,111,110,111,110,111,110,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,111,109,109,110,109,110,109,109,109,110,110,111,111,110,109,110,109,110,110,111,110,111,110,111,110,105,105,105,105,105,105,105,105,105,105,111,111,111,110,111,110,111,111,111,110,111,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,109,109,110,109,110,110,111,110,111,109,110,109,110,110,111,104,104,106,104,108,108,108,108,108,108,107,108,106,107,107,108,108,108,106,107,106,107,107,107,107,107,106,107,106,106,106,106,106,68,30,68,29,68,28,68,26,68,25,218,23,69,22,69,68,69,69,70,69,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,196,197,196,197,197,198,197,198,197,198,197,198,196,197,196,197,196,198,197,198,198,198,197,198 +,108,252,108,252,108,252,252,252,108,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,252,108,252,252,252,252,252,252,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,107,107,109,109,107,107,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,107,252,107,107,107,109,107,109,107,109,107,109,107,109,70,71,70,71,70,70,71,70,71,71,72,71,71,71,71,70,105,105,105,105,105,105,111,111,111,111,111,110,110,110,110,110,110,111,111,111,111,111,111,110,110,111,111,111,111,111,111,109,109,109,109,110,109,110,109,109,109,110,109,110,110,110,110,110,110,111,111,111,111,111,110,110,109,109,109,109,109,110,109,110,109,110,109,109,109,110,110,110,110,111,111,111,110,111,110,109,109,109,109,110,110,110,110,110,110,111,111,111,109,110,109,109,109,109,109,110,110,110,109,110,110,110,110,110,109,109,109,109,109,109,109,109,109,110,109,110,109,110,110,111,111,110,110,110,110,110,110,110,110,111,110,111,105,105,105,105,111,111,111,111,111,111,111,105,111,111,111,111,111,111,111,111,111,111,109,109,109,110,110,111,111,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,109,109,110,109,110,110,110,110,111,111,110,110,110,110,110,104,106,104,106,108,108,108,108,108,108,108,108,107,108,106,107,108,108,107,107,106,107,106,107,106,108,107,107,106,106,106,106,106,106,106,68,29,68,28,68,27,69,26,69,25,218,24,218,23,218,22,218,27,218,27,70,26,218,25,218,24,218,23,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,197,198,198,198,197,198,197,198,196,196,196,197,197,197,197,198,197,198,198,198,197 +,252,108,252,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,109,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,252,252,252,252,252,252,252,109,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,109,107,109,107,252,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,107,252,107,109,107,109,107,109,107,109,107,109,107,107,107,109,71,71,71,71,71,71,71,70,71,71,72,71,70,105,105,111,105,105,111,111,111,111,111,111,111,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,111,111,111,111,111,109,109,109,110,109,109,109,110,109,110,109,110,110,110,110,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,109,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,111,111,110,110,110,110,110,110,111,110,111,110,105,105,105,111,111,111,111,111,111,111,111,111,105,111,111,111,111,110,111,110,111,111,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,109,109,110,109,110,110,111,110,111,111,110,109,110,110,111,104,106,104,108,108,108,108,108,108,108,108,108,108,108,108,108,106,108,107,108,107,108,106,107,106,108,108,107,106,107,106,107,106,106,106,106,27,69,26,69,24,218,23,218,218,70,69,70,30,218,30,218,29,218,29,218,28,218,27,218,27,218,26,218,25,218,25,218,24,218,24,218,23,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,198,197,198,197,196,196,197,196,197,196,197,197,198,197,198,198,197 +,108,252,108,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,252,252,108,252,252,252,252,252,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,109,109,109,107,109,107,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,252,107,107,107,109,107,109,107,109,107,109,107,109,109,70,70,70,70,71,71,72,71,71,72,72,105,105,105,105,105,111,111,111,111,111,111,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,109,109,109,109,109,109,110,110,110,109,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,109,110,110,110,110,111,111,111,110,111,110,111,110,111,111,111,110,111,111,111,109,109,109,109,109,110,110,110,110,110,110,110,110,111,109,109,109,110,110,110,109,109,109,110,110,110,110,111,111,110,110,110,109,110,110,110,110,109,110,111,110,110,110,110,110,110,110,110,110,111,105,105,111,105,111,111,111,111,111,111,111,111,105,111,105,111,111,110,110,111,111,111,111,110,109,109,109,110,110,111,111,111,110,110,110,111,111,111,110,111,111,111,111,111,111,111,109,111,109,109,109,110,110,110,110,111,111,110,110,110,110,110,110,111,104,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,107,107,106,106,107,108,107,107,107,106,106,106,106,106,106,106,69,69,30,218,28,218,26,218,29,218,28,218,26,218,25,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,221,221,220,221,220,220,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,196,196,197,197,197,197,198,197,198,198,198,198 +,252,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,252,108,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,108,108,252,108,252,252,252,252,252,252,252,252,108,252,108,109,109,109,252,109,252,109,252,109,252,252,252,252,252,107,109,107,109,109,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,252,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,70,70,70,70,70,71,71,105,105,105,105,111,111,111,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,110,111,111,110,110,109,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,109,109,111,111,110,110,110,110,111,110,111,111,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,110,110,111,110,105,105,111,111,105,111,111,111,111,111,111,111,111,111,111,105,111,110,111,110,111,111,111,111,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,111,109,109,110,109,110,110,111,111,110,109,110,110,111,110,111,104,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,107,108,107,108,106,106,107,108,106,107,106,107,106,107,106,106,106,106,69,218,69,70,69,70,70,70,23,70,31,71,30,218,29,218,28,218,27,218,26,218,26,218,25,218,24,218,23,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,217,221,221,220,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,198,197,198,197,198,197,198 +,108,252,108,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,109,108,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,108,108,108,252,108,252,252,252,252,252,252,252,108,109,109,109,109,109,252,109,252,252,252,252,252,252,252,252,107,107,109,109,109,107,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,107,107,109,107,109,107,109,107,109,107,109,109,107,107,70,71,70,71,105,105,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,109,109,109,109,110,109,110,110,110,109,109,109,109,109,109,109,109,109,110,109,109,110,110,111,110,110,110,109,109,109,110,110,110,110,111,111,111,110,111,110,111,110,111,111,111,111,111,111,111,111,109,109,109,109,110,109,110,110,110,110,110,110,110,110,111,110,111,111,111,111,110,110,110,110,111,110,111,111,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,105,105,105,105,105,105,111,111,111,111,111,111,111,111,111,105,111,105,111,110,110,111,111,111,110,110,110,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,109,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,108,108,108,107,108,107,107,106,106,108,107,107,107,106,106,106,106,106,106,106,218,28,70,27,70,26,70,25,71,25,71,24,218,24,218,23,218,23,218,22,218,30,218,28,218,26,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220 +,252,108,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,108,108,109,108,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,108,108,108,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,109,107,109,107,109,107,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,107,252,107,252,107,109,107,109,107,109,107,109,107,107,107,109,109,107,107,105,105,105,105,111,111,111,111,111,111,111,111,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,110,110,110,110,110,110,109,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,109,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,111,110,109,110,109,110,109,110,109,110,110,111,111,111,111,111,110,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,110,110,105,105,105,111,111,111,105,111,111,111,111,111,111,111,111,111,105,111,105,111,110,110,109,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,109,109,109,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,109,108,108,108,108,108,108,108,108,108,108,105,105,105,105,111,105,104,104,104,104,104,104,104,108,107,108,106,108,106,107,106,107,106,107,106,107,106,106,106,70,29,218,29,218,28,218,27,218,26,218,26,218,25,218,24,218,23,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,108,108,108,108,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,108,108,252,108,252,108,252,252,252,252,252,252,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,107,252,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,107,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,111,110,110,110,111,111,111,111,111,111,111,111,111,111,111,110,109,110,111,109,109,109,110,109,109,109,109,109,110,109,110,109,110,110,110,110,109,109,109,109,110,109,110,110,110,110,110,110,110,110,111,110,111,111,111,111,110,110,110,110,111,110,111,110,111,111,111,110,109,109,109,109,110,110,110,110,110,110,111,110,111,111,111,110,110,111,111,111,111,111,110,109,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,109,110,110,110,110,110,110,110,110,110,105,105,105,105,111,111,105,105,111,111,111,111,111,111,111,111,111,111,111,105,111,111,111,109,109,110,110,111,110,110,110,110,110,110,110,111,110,110,110,111,110,111,110,111,111,111,110,111,111,111,111,109,111,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,105,109,105,105,105,105,105,105,105,105,105,105,109,109,109,109,109,109,104,104,104,104,104,104,104,104,108,107,107,106,108,107,107,106,107,106,106,106,106,106,106,106,218,24,218,23,218,23,218,22,218,25,218,24,218,23,218,31,218,30,218,29,218,28,218,27,218,27,218,26,218,25,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220,221,220,220,220 +,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,108,252,108,109,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,107,109,107,109,109,252,107,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,252,107,252,107,109,107,109,107,109,107,109,107,107,107,109,109,107,107,107,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,111,110,109,110,110,109,109,110,110,111,110,109,109,110,109,110,109,110,109,110,110,111,110,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,110,110,111,110,111,110,111,110,111,110,111,110,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,110,109,109,109,109,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,110,105,105,105,111,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,105,111,110,111,110,109,109,110,110,111,110,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,109,110,111,109,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,111,110,109,110,110,111,110,111,111,111,109,104,106,107,108,104,104,108,107,107,106,107,106,107,106,107,106,107,106,107,106,106,24,218,23,218,23,218,22,218,25,218,31,218,29,218,27,218,26,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,108,108,108,108,108,109,109,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,108,108,252,108,252,252,252,252,252,252,109,108,109,109,109,252,252,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,109,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,109,107,109,107,109,109,109,107,109,107,109,109,107,107,107,107,111,111,111,111,111,111,111,110,111,111,110,109,110,110,110,110,111,111,111,111,111,111,111,111,111,111,109,109,110,109,110,110,110,110,111,109,109,109,110,110,109,109,109,109,110,109,110,110,110,110,110,110,111,109,109,109,110,109,110,109,110,110,110,110,110,110,111,110,111,111,111,111,110,110,110,110,110,110,111,110,111,111,111,109,109,109,110,109,110,110,110,110,110,110,111,111,111,111,111,111,111,110,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,109,110,109,110,109,110,110,110,110,110,110,105,105,105,111,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,109,110,110,110,110,111,110,110,110,110,109,110,111,111,110,110,110,111,110,111,110,111,111,109,111,111,111,111,111,111,109,110,110,111,109,109,109,111,109,110,109,110,110,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,109,110,109,110,109,110,110,110,110,110,110,104,106,107,108,104,104,107,107,107,107,107,107,107,106,107,106,106,106,106,106,106,71,72,71,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220 +,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,108,108,109,108,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,107,107,107,109,107,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,107,252,107,109,107,107,107,109,107,109,107,107,107,109,107,107,107,107,107,111,111,111,111,111,110,111,110,111,110,111,111,110,110,110,110,111,110,111,111,111,110,111,111,109,109,110,110,111,111,110,109,110,110,109,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,111,110,109,109,110,109,110,110,111,110,111,110,111,111,110,110,111,110,111,111,109,109,109,109,110,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,105,105,105,111,111,105,110,111,111,111,105,111,111,105,105,111,105,111,111,111,109,111,111,111,105,111,110,109,109,110,110,111,111,111,110,111,109,110,109,111,110,111,110,111,110,111,110,111,110,109,110,111,110,111,110,111,111,109,109,110,109,111,110,111,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,111,111,109,110,109,110,109,110,109,110,110,110,110,111,110,104,106,107,107,104,104,104,107,107,107,107,106,107,106,107,106,107,106,106,106,106,29,218,28,218,26,218,25,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,217,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,108,109,109,108,108,109,108,109,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,107,107,109,109,109,107,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,107,252,107,109,107,109,107,107,109,109,107,109,107,107,109,107,107,107,107,107,107,111,110,110,110,111,110,110,110,111,111,111,111,111,111,111,110,111,111,111,111,109,109,109,109,110,110,110,110,111,111,110,110,109,109,109,109,109,109,109,109,109,109,110,109,110,110,110,110,111,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,111,110,110,110,111,110,110,110,111,111,111,110,109,109,109,109,110,110,110,110,111,109,110,110,110,110,111,111,109,109,109,109,109,109,109,109,109,109,109,110,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,105,105,105,105,111,111,105,105,111,111,105,111,105,110,111,111,111,111,111,111,111,111,109,111,111,111,111,111,111,109,109,110,110,111,111,111,110,109,109,109,109,110,110,110,110,111,111,111,110,111,111,109,109,110,110,109,109,110,110,110,110,110,110,111,111,111,109,109,109,110,110,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,109,110,111,110,109,110,110,110,110,110,110,110,110,111,104,106,107,108,108,104,104,107,107,107,107,107,107,107,106,106,106,106,106,106,106,218,29,218,28,72,27,218,26,218,25,218,31,218,29,218,28,218,26,218,25,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,221,221,220,221,220,221,220,221,220,221,220 +,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,108,108,252,108,252,108,109,109,108,108,252,108,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,109,109,109,252,109,252,109,108,109,252,252,252,252,252,107,252,107,109,107,252,107,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,252,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,110,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,109,109,109,110,109,109,109,110,109,110,110,110,110,111,109,110,109,110,110,111,111,110,110,110,110,111,110,111,110,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,109,109,109,110,109,110,110,111,110,109,111,110,110,111,110,111,109,109,109,110,109,109,109,110,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,105,105,105,105,111,110,105,105,111,111,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,109,109,110,110,111,110,109,109,110,109,110,110,110,110,111,110,111,110,111,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,110,111,110,111,111,111,109,110,110,111,109,110,109,110,109,109,110,111,110,110,110,104,106,107,107,104,104,104,104,106,107,107,107,107,106,107,106,107,106,106,106,106,106,218,26,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,109,109,108,108,108,109,108,109,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,109,109,252,252,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,252,107,109,107,109,107,109,107,109,107,109,107,107,109,109,109,109,107,107,107,111,109,109,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,109,109,109,110,110,110,110,110,110,111,111,111,111,111,109,109,109,109,109,110,109,109,109,110,110,110,110,109,109,110,110,110,110,110,110,111,111,110,110,110,110,111,110,111,111,111,111,111,110,110,110,110,110,111,110,111,110,111,109,109,109,110,110,110,110,111,111,109,111,110,110,111,111,109,109,109,109,109,109,109,109,109,109,110,109,109,109,109,109,109,109,109,109,109,109,109,109,110,109,105,105,105,105,105,111,105,105,105,111,111,111,111,111,111,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,105,111,111,111,109,110,110,111,110,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,110,110,110,110,110,110,110,110,111,111,111,111,111,109,109,109,109,109,110,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,109,110,110,111,110,110,110,104,106,107,108,104,104,104,106,108,106,107,107,107,107,107,107,106,107,106,106,106,106,106,218,25,218,24,218,31,218,30,218,28,218,27,218,26,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,217,221,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221 +,252,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,108,252,108,109,109,108,108,252,108,252,108,252,108,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,252,252,252,252,252,252,252,107,107,109,107,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,252,107,109,107,107,107,109,107,109,107,107,107,109,107,109,109,107,107,107,107,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,109,111,110,109,110,109,110,109,110,109,110,110,111,110,111,110,109,110,109,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,109,110,110,111,110,109,110,111,110,111,111,109,109,109,109,109,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,105,105,105,105,105,105,105,105,111,111,110,111,110,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,109,111,110,111,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,109,109,109,110,109,109,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,111,109,109,110,110,111,111,111,104,106,106,108,108,104,104,104,106,106,106,108,107,107,107,107,106,106,106,106,106,106,106,106,218,218,218,218,218,218,30,218,29,218,27,218,26,218,25,218,24,218,28,218,24,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,252,252,109,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,109,109,109,108,108,108,108,108,252,108,108,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,109,109,252,252,252,252,252,252,252,252,252,107,107,107,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,107,252,107,109,107,109,109,109,107,109,107,109,107,107,107,109,109,109,107,107,107,107,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,110,111,109,110,110,111,111,109,109,110,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,109,109,109,109,110,110,110,110,110,110,111,110,111,111,111,110,111,111,111,109,111,111,111,111,111,111,110,109,109,109,109,109,110,110,110,110,110,110,109,109,109,110,111,111,110,109,109,109,109,109,109,109,109,109,109,109,110,109,109,109,110,110,110,109,109,109,109,109,109,109,105,105,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,111,111,111,110,111,111,111,111,111,111,111,111,111,110,110,110,110,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,110,110,110,110,111,111,111,111,111,111,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,109,109,110,110,110,111,111,111,110,104,106,107,108,104,104,104,107,107,106,106,106,107,107,107,107,107,107,106,106,107,106,106,106,106,27,218,27,218,26,218,25,218,25,218,24,218,23,218,22,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220 +,252,252,252,109,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,109,109,108,108,252,108,252,108,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,109,107,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,107,109,107,107,107,109,109,109,107,109,107,107,109,109,107,109,109,109,107,107,107,110,109,110,110,111,110,110,110,111,110,111,110,111,110,111,110,111,110,109,109,111,111,111,111,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,109,109,110,109,110,109,110,110,110,110,111,110,111,111,111,111,111,110,111,109,111,110,111,110,111,109,110,109,110,109,110,109,110,110,111,110,111,110,109,109,109,110,111,111,110,109,109,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,109,105,105,105,105,105,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,110,110,109,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,111,111,111,110,111,110,111,111,111,111,111,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,110,111,111,111,110,111,110,106,108,104,107,107,106,107,106,107,106,106,107,107,106,107,106,106,106,106,106,106,106,218,31,218,29,218,28,218,27,218,25,218,24,218,23,218,22,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,108,109,108,109,108,109,108,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,107,109,109,109,107,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,109,107,109,107,107,109,109,107,109,107,107,107,109,107,109,109,109,109,107,107,107,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,109,110,111,111,111,111,111,110,109,110,110,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,109,111,111,110,110,110,110,110,110,111,111,111,111,111,110,111,111,111,111,111,111,110,110,110,109,109,109,109,109,110,109,110,110,110,110,110,109,109,109,109,110,111,111,111,109,109,109,109,109,109,109,110,109,110,109,109,109,109,109,110,109,110,109,110,110,109,109,105,105,105,105,105,111,111,111,111,111,111,105,111,111,111,110,111,111,111,111,111,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,109,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,111,110,111,110,111,111,111,111,111,109,109,109,109,109,110,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,109,109,109,110,110,110,110,111,111,110,110,110,110,111,110,106,107,107,106,107,106,106,106,106,107,106,108,107,107,107,106,107,107,106,106,106,106,218,218,218,31,218,30,218,29,218,28,218,27,218,26,218,24,218,23,218,22,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,109,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,252,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,109,252,109,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,107,109,107,107,107,109,107,109,107,109,107,107,109,109,107,109,109,109,107,107,107,110,110,110,110,109,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,111,111,109,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,109,110,110,111,109,110,110,111,110,111,110,111,111,111,110,111,110,111,110,111,111,111,111,110,109,109,109,110,109,110,109,110,109,110,110,110,110,111,110,111,109,109,111,110,110,111,110,111,111,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,105,105,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,111,109,109,109,109,109,110,109,110,110,111,110,111,110,110,110,111,110,111,110,111,110,111,110,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,109,109,110,110,111,110,110,110,111,110,111,110,111,104,111,109,108,107,107,106,107,106,106,106,106,107,106,108,107,106,106,106,107,106,107,106,106,106,218,25,218,23,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221,220,221 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,109,108,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,252,109,109,109,252,252,252,252,252,252,252,252,252,252,252,107,109,107,109,107,107,107,109,109,109,107,107,107,109,107,109,109,109,109,109,107,107,109,110,110,110,110,111,111,111,110,111,110,111,111,111,111,111,109,111,111,111,111,109,110,111,110,110,110,110,110,111,111,111,110,111,110,111,111,111,111,109,110,110,111,111,110,110,109,110,110,110,110,111,111,111,111,111,111,111,110,111,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,111,109,109,109,110,110,110,110,111,111,109,109,110,109,109,109,110,110,110,109,110,110,110,110,110,110,105,105,105,105,111,111,111,111,111,111,111,111,105,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,111,110,111,110,111,111,111,110,111,111,111,111,111,111,111,110,110,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,109,109,109,110,109,109,109,110,110,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,109,110,109,110,111,111,110,110,110,110,110,110,110,111,104,111,109,108,108,107,107,107,106,107,106,106,106,107,106,108,107,107,106,107,107,108,106,106,106,106,31,218,29,218,27,218,26,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,108,109,252,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,109,109,109,107,109,107,110,109,110,110,111,110,111,110,111,111,111,110,111,109,111,109,111,110,111,111,110,109,110,110,111,110,111,111,111,110,111,110,111,111,111,110,111,110,109,109,111,111,111,111,111,110,111,110,111,110,109,109,110,110,111,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,109,109,110,109,110,110,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,109,110,105,105,105,105,111,111,110,111,111,111,111,105,111,105,110,111,111,111,110,111,111,111,110,111,111,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,111,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,110,110,111,110,111,110,109,109,110,109,110,110,111,110,111,111,111,110,111,110,110,110,111,110,111,104,111,109,108,107,108,107,107,106,107,106,107,106,106,106,108,106,107,106,106,106,107,107,107,106,107,106,106,30,218,28,218,26,218,31,218,28,218,25,218,23,218,217,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221,221,221,220,221 +,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,109,109,109,109,109,107,107,107,110,110,110,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,111,110,111,111,111,111,111,110,111,111,111,111,109,109,109,110,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,109,109,109,110,110,111,111,111,110,110,110,110,110,110,110,111,111,111,111,111,111,109,109,110,109,110,110,110,110,110,110,105,105,111,111,111,111,110,110,111,111,111,105,105,111,111,110,111,111,111,111,111,105,111,110,111,111,111,111,111,111,111,110,110,110,110,109,111,110,111,110,111,111,111,111,111,111,111,111,109,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,109,110,110,110,110,110,110,111,109,109,109,110,110,110,110,110,110,111,111,111,111,110,110,110,110,110,110,104,104,111,106,108,108,108,107,107,107,107,106,106,106,107,107,106,106,106,107,107,106,106,107,107,106,106,106,106,106,106,26,218,24,218,22,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,108,109,252,109,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,107,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,111,111,110,109,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,109,110,109,110,109,110,110,111,110,111,111,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,111,110,109,110,105,105,105,105,105,105,110,111,110,111,110,111,105,111,110,111,110,111,111,111,111,111,111,111,110,111,110,111,110,111,111,111,109,110,109,111,110,111,110,111,110,111,110,111,110,111,111,111,111,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,109,111,110,111,110,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,111,110,111,110,111,110,111,109,110,109,110,109,110,110,111,110,111,110,111,111,111,110,111,110,111,110,104,106,108,104,109,108,108,107,108,107,107,106,107,106,107,106,107,107,106,107,106,107,106,106,107,107,106,106,107,106,106,106,218,25,218,31,218,28,218,25,218,22,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,220,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,252,252,108,252,108,252,108,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,252,109,109,109,252,252,252,109,252,252,252,252,252,252,252,107,107,109,109,107,109,107,109,107,109,107,107,107,107,107,109,107,109,109,109,107,107,107,107,110,111,111,111,110,111,109,111,111,111,111,111,111,111,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,110,110,111,109,109,109,109,109,109,109,110,109,109,109,110,110,110,109,110,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,110,110,110,110,110,110,111,111,111,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,105,105,105,111,111,110,110,110,110,111,111,111,111,111,111,110,110,111,111,111,111,105,111,111,110,111,111,111,111,111,111,111,110,110,110,111,111,111,110,111,110,111,111,111,111,111,111,111,111,109,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,109,110,111,110,111,111,111,111,111,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,109,110,111,110,110,110,110,110,111,109,109,109,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,106,107,109,104,109,107,108,108,108,107,107,107,107,107,106,106,106,107,107,106,106,107,107,107,106,107,106,107,106,107,106,106,106,106,218,218,218,218,218,218,218,218,218,218,218,218,218,217,218,218,218,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,108,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,109,107,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,109,109,109,109,109,107,107,107,110,109,110,110,110,110,111,110,111,111,111,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,110,110,111,110,111,110,111,109,109,109,105,105,105,105,105,105,105,105,110,109,110,109,110,109,110,110,111,109,109,109,110,109,109,109,110,109,109,109,110,110,111,111,110,109,110,110,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,105,105,111,111,111,111,110,110,111,110,111,110,111,110,111,110,111,109,110,110,111,111,111,110,111,111,111,110,111,110,111,111,111,111,110,109,110,111,111,110,111,110,111,111,111,110,111,111,111,110,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,109,110,111,109,111,111,111,111,111,109,110,109,110,109,110,109,110,109,110,109,109,111,110,109,109,109,111,111,110,110,109,110,111,110,109,109,110,109,110,110,111,110,111,111,111,111,111,111,111,110,111,110,106,107,108,106,104,104,108,107,108,108,108,107,108,107,107,106,106,106,108,107,106,106,106,107,107,106,106,106,107,107,107,106,106,106,106,106,218,218,218,222,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,109,108,252,108,252,108,252,108,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,109,109,109,252,109,252,109,252,252,252,252,252,252,252,109,109,107,109,109,109,107,109,107,109,107,109,107,107,107,107,107,109,109,109,109,109,107,107,107,107,107,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,109,109,109,110,110,110,110,111,111,109,109,110,110,110,110,110,110,110,110,111,110,111,105,105,105,105,109,107,107,106,106,106,106,106,105,105,105,105,105,105,105,105,105,105,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,105,105,111,111,111,111,110,110,110,110,110,111,110,111,111,111,110,111,111,110,110,110,110,105,111,111,110,110,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,109,109,109,109,109,109,109,110,109,110,110,110,109,110,110,110,110,110,110,109,110,110,109,110,110,111,111,111,109,109,109,110,109,110,109,110,110,110,110,109,110,111,109,110,110,111,111,109,111,110,110,111,110,111,110,109,109,110,110,111,111,111,111,111,111,111,111,111,110,110,110,106,107,108,104,104,104,106,104,108,107,108,108,108,107,107,107,108,107,107,106,107,106,106,106,107,107,107,106,107,107,107,106,107,106,106,106,106,218,218,218,218,218,218,218,218,218,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,109,109,107,107,107,107,109,110,110,111,110,111,110,111,110,111,110,111,110,111,111,110,110,111,110,111,110,109,109,110,109,109,109,110,110,111,110,111,110,105,105,105,105,109,109,110,105,105,111,104,107,106,106,106,106,106,106,106,106,107,107,107,107,107,105,105,105,105,108,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,110,110,111,110,105,105,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,105,111,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,110,111,111,111,111,110,109,110,110,110,110,110,110,110,110,110,109,109,109,110,109,110,109,110,109,110,109,109,109,110,110,111,110,111,110,111,109,109,109,110,110,111,110,111,111,110,109,110,109,110,109,110,109,110,109,110,109,111,109,110,110,111,109,111,110,111,110,111,110,111,110,111,110,111,109,111,110,111,110,111,111,111,110,111,110,111,110,106,107,104,104,110,110,104,106,107,107,108,108,104,104,108,107,108,107,107,106,106,106,107,106,106,106,108,107,107,106,107,107,106,106,107,106,107,106,106,104,104,104,104,104,218,218,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,218,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,222,222,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,252,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,109,109,252,109,109,109,252,252,252,252,252,252,252,109,109,107,107,107,109,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,109,109,109,109,109,107,107,107,110,110,110,110,111,110,111,110,111,111,111,111,111,111,110,110,110,110,109,109,110,109,110,110,110,110,110,110,111,105,105,105,105,109,109,109,110,105,105,105,111,111,111,104,107,106,107,106,107,106,107,106,107,106,107,106,107,106,107,107,108,108,109,108,109,109,109,109,110,109,110,109,110,110,110,109,110,110,110,110,110,110,110,110,110,110,110,105,105,111,111,111,111,110,110,110,110,110,110,110,111,111,111,109,110,105,111,110,111,111,110,110,111,111,111,110,110,110,110,110,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,109,109,110,110,110,109,109,110,110,110,111,111,111,110,111,109,109,109,110,110,110,110,111,110,111,111,111,109,110,109,110,110,110,110,110,109,109,109,110,110,110,111,111,110,110,110,111,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,110,109,109,110,110,104,104,110,111,111,109,104,106,106,107,107,108,108,104,104,104,108,108,107,107,106,106,106,107,107,106,106,107,107,107,106,108,106,108,106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,104,218,217,218,217,218,217,218,217,217,217,217,217,217,221,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,217,221,217,221,221,221,222,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,109,252,109,252,109,108,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,109,107,109,107,109,107,109,109,109,107,109,107,107,107,109,107,107,107,109,107,109,107,109,107,109,107,107,107,107,107,111,110,111,110,111,110,111,110,111,110,111,111,109,109,110,109,110,109,110,110,110,110,110,110,105,105,105,105,105,105,105,105,105,105,105,105,111,110,111,110,111,111,111,104,107,106,107,106,107,106,107,107,108,107,107,107,107,107,107,108,107,108,109,108,109,108,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,105,105,105,111,111,110,111,110,111,110,111,110,111,110,111,110,111,109,111,111,111,111,110,110,111,110,111,111,110,109,110,110,111,110,111,110,111,110,111,111,111,110,111,111,110,109,110,110,110,109,110,110,111,110,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,110,111,111,111,110,111,110,109,109,110,109,110,109,110,110,111,110,111,111,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,111,111,109,110,109,110,110,111,110,111,110,109,109,110,109,104,106,107,106,107,107,108,108,104,104,104,104,107,106,107,106,107,107,107,106,106,107,108,107,107,106,106,107,107,106,107,106,106,106,104,104,104,104,104,104,104,104,104,104,104,106,104,217,218,217,217,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,222,222,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,109,109,109,252,109,252,252,252,252,252,252,109,109,107,107,109,107,109,109,109,107,109,107,107,109,109,107,109,107,107,107,109,107,109,109,109,109,109,107,107,107,107,110,110,110,111,110,111,110,111,111,111,109,109,109,109,109,110,109,110,110,110,105,105,105,105,111,111,111,111,111,110,110,110,110,110,110,110,110,111,111,111,111,111,111,104,107,107,106,107,107,107,106,107,107,108,107,107,107,107,107,107,108,108,108,109,108,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,105,105,105,105,105,105,105,111,111,110,110,110,110,109,110,110,111,111,111,111,105,111,111,110,111,111,111,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,109,110,109,109,109,110,110,110,110,111,111,111,110,111,110,109,109,110,110,110,110,110,110,111,111,111,109,110,109,110,110,110,110,110,109,109,109,110,110,111,111,111,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,109,109,109,110,110,111,111,111,109,110,110,110,110,104,106,106,106,107,107,108,108,108,108,104,104,104,104,104,106,106,106,107,107,107,106,106,107,107,107,107,106,108,106,107,106,106,106,106,106,104,104,104,104,104,104,104,104,104,106,107,108,104,217,218,217,218,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,217,221,222,221,217,221,217,221,222,221,222,221,222,221,222,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,107,109,252,109,252,109,252,109,252,252,109,109,107,107,109,107,109,107,109,109,109,107,107,109,109,107,109,107,107,107,109,107,109,107,109,109,109,107,109,107,107,107,107,110,111,110,111,110,111,110,111,109,109,109,110,109,110,109,105,105,105,105,111,105,105,111,111,111,111,109,110,109,110,110,110,110,111,110,111,110,111,110,111,111,110,104,107,107,107,106,107,107,107,107,107,107,108,107,107,107,107,107,107,108,107,108,109,108,110,108,110,109,110,109,110,109,110,109,110,109,110,109,110,105,105,105,105,105,111,111,111,110,109,109,110,109,110,110,111,110,111,110,111,111,105,111,110,110,111,111,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,111,109,109,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,109,110,109,110,110,111,110,111,109,110,109,110,109,110,109,110,109,110,110,109,109,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,109,110,110,111,110,111,111,110,110,111,111,110,109,110,110,110,110,104,106,107,106,107,107,108,107,108,108,104,108,104,104,104,104,107,106,107,106,107,107,106,106,106,106,108,107,106,108,107,106,107,106,107,106,106,106,104,104,104,104,104,106,104,106,107,107,104,104,106,217,218,217,217,217,217,217,217,217,217,217,217,217,217,221,217,221,217,221,217,221,221,221,221,221,217,221,221,221,221,221,221,221,221,221,221,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,252,109,252,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,107,107,252,109,252,109,252,252,252,252,252,109,107,107,107,107,107,107,109,109,109,109,107,109,109,107,109,107,109,107,107,107,107,107,109,109,109,107,109,107,107,107,107,107,110,110,110,110,110,110,111,109,109,109,105,105,105,105,105,105,105,111,105,105,111,111,111,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,104,108,107,107,107,108,107,107,107,107,107,107,107,107,108,107,108,107,108,107,108,107,108,109,108,110,109,109,109,110,109,110,109,110,110,110,109,105,105,111,111,111,111,111,111,111,110,110,110,109,109,110,110,111,111,111,111,111,111,105,111,111,110,111,110,111,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,110,111,110,109,110,110,110,110,110,110,110,110,111,110,111,110,109,110,111,111,111,109,109,109,110,109,110,109,110,110,110,109,110,110,110,109,111,110,110,110,110,110,110,110,111,110,110,110,111,111,111,109,109,109,110,110,110,110,110,110,111,111,109,111,110,110,110,110,110,110,110,110,110,110,104,106,107,107,107,107,108,108,108,108,104,104,104,104,108,107,106,106,107,107,107,106,106,106,106,108,107,106,108,106,107,107,106,106,107,106,106,106,104,104,104,106,104,104,104,106,107,108,104,106,106,217,218,217,217,217,217,217,217,221,217,221,217,221,217,221,217,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,221,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,252,107,252,109,252,109,252,109,252,109,252,252,109,107,107,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,107,107,109,107,109,107,109,109,109,107,109,107,107,107,109,107,110,110,111,110,111,105,111,105,105,110,105,110,105,111,111,110,111,111,111,111,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,104,104,108,107,108,107,107,107,107,107,107,107,107,107,107,107,107,108,107,108,107,108,108,108,108,108,109,108,110,108,110,109,110,109,110,109,110,105,105,111,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,111,111,105,111,110,111,110,111,110,111,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,111,111,110,111,110,110,109,110,110,110,110,110,110,111,109,110,109,110,110,111,111,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,110,110,111,110,111,110,111,110,111,110,111,109,110,109,110,109,110,110,111,110,111,111,111,110,111,111,110,109,110,110,110,109,110,110,111,110,104,104,106,106,107,107,108,108,104,104,104,104,106,108,107,106,106,106,107,106,107,106,106,106,106,107,106,107,107,106,107,106,106,106,107,106,106,104,104,104,104,104,104,104,106,107,104,106,106,106,218,217,218,217,218,217,217,217,217,217,217,217,217,217,222,221,217,221,217,221,221,221,222,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,252,108,252,252,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,107,252,109,252,252,252,252,252,252,109,107,107,107,107,107,109,109,109,109,107,107,109,109,109,107,109,107,109,107,107,107,109,107,109,109,109,107,109,107,107,107,107,107,107,107,105,111,111,105,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,111,104,108,108,108,108,107,108,107,108,108,108,107,107,107,107,107,107,108,107,107,107,108,107,108,107,108,108,108,109,108,109,109,110,109,110,109,105,105,111,111,111,111,111,110,110,110,110,110,110,110,110,110,111,110,109,110,110,111,111,111,110,110,111,110,111,111,111,109,109,109,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,109,109,110,110,110,110,111,111,111,109,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,111,111,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,110,111,111,109,110,110,111,109,109,109,109,110,110,110,110,110,110,111,111,111,111,110,110,110,110,110,110,110,104,106,106,107,107,108,108,104,104,104,104,107,107,107,108,106,106,106,107,107,107,106,106,106,107,107,107,106,108,107,107,107,106,106,107,107,107,106,104,104,104,104,104,106,107,104,106,107,106,106,106,218,217,217,217,217,217,217,221,217,221,221,221,217,217,217,221,222,221,217,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,221,221,221,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221,221,221,222,221,221,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,252,107,252,109,252,109,252,252,109,109,107,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,109,109,107,109,107,107,107,107,107,107,107,111,110,111,110,111,111,111,110,111,111,111,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,104,108,108,108,108,107,108,107,108,108,108,108,108,107,108,107,107,107,107,107,107,108,107,108,107,108,108,108,107,108,109,108,110,109,110,105,105,105,105,111,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,109,111,111,111,111,110,111,110,111,110,111,111,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,111,111,110,111,111,111,110,110,110,110,110,110,110,109,109,110,109,110,110,111,110,111,109,110,110,110,110,111,110,111,110,111,110,111,111,111,110,111,111,111,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,109,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,110,110,111,110,111,110,111,104,104,104,104,106,107,107,104,104,104,107,108,107,107,108,107,106,107,107,107,106,106,106,106,107,108,106,108,107,107,106,107,106,106,106,107,106,106,104,104,104,104,106,104,106,107,107,107,106,106,106,218,217,217,217,217,217,217,217,217,217,217,222,217,222,221,221,222,221,221,221,221,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,108,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,108,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,107,107,107,252,252,252,109,252,252,252,109,107,107,107,107,109,107,109,107,109,109,107,107,109,109,109,107,109,107,109,107,107,107,107,107,109,109,109,107,109,107,109,107,107,107,107,107,107,111,111,110,111,111,111,111,111,111,111,109,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,104,104,108,108,108,108,108,108,108,108,107,108,108,108,108,108,108,108,107,107,107,107,107,107,107,107,108,107,108,107,108,107,108,109,108,109,105,105,105,105,111,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,109,111,110,111,110,111,111,111,111,111,111,111,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,109,109,110,110,110,110,111,110,111,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,109,109,109,110,109,110,109,110,110,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,110,110,111,111,111,110,111,111,111,111,111,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,110,110,110,110,111,110,110,110,111,111,111,110,104,106,108,104,104,108,107,107,107,107,108,106,106,106,107,106,106,106,106,106,106,107,106,108,107,107,107,106,106,107,106,107,107,106,104,106,107,108,104,106,106,106,107,107,106,106,106,106,218,217,221,221,217,217,217,221,217,217,217,221,217,222,217,221,222,221,222,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221,222,221,221,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,108,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,109,252,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,252,107,252,107,252,252,252,252,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,107,107,109,107,107,107,107,110,111,111,111,111,111,109,110,109,110,109,110,109,110,110,111,110,110,110,111,110,111,110,111,110,111,111,111,111,111,104,108,107,108,108,108,107,108,107,108,107,108,107,108,107,108,108,108,107,107,107,108,107,107,107,108,107,107,107,107,107,107,108,108,109,105,105,105,105,105,111,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,111,109,111,110,111,110,111,110,111,110,111,111,111,111,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,110,111,111,111,111,111,111,111,111,110,110,109,109,110,110,111,109,110,110,111,110,111,110,110,110,110,110,111,110,111,111,111,111,111,110,111,110,111,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,109,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,109,109,110,109,110,109,110,110,111,110,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,104,106,107,108,104,104,107,108,107,108,107,108,107,107,106,107,106,107,106,106,106,108,106,108,107,107,106,107,106,106,107,107,107,104,106,107,108,104,107,106,106,107,106,107,106,107,106,106,106,217,221,217,217,217,217,217,221,222,221,222,221,217,221,221,221,221,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,107,252,252,252,252,252,109,109,107,107,107,107,107,109,107,109,109,107,107,109,107,109,109,109,107,109,107,107,109,109,109,109,107,109,107,109,107,109,107,107,107,107,107,107,107,111,111,111,111,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,104,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,108,108,107,107,107,107,108,108,107,107,107,107,107,107,107,107,107,107,105,105,105,105,105,105,111,109,109,109,109,110,109,110,110,110,110,110,110,111,109,110,110,111,111,111,110,111,110,111,111,111,111,111,111,111,111,111,109,110,110,110,110,110,110,111,111,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,110,110,110,109,109,109,109,110,110,110,110,111,111,110,110,110,110,111,111,111,111,111,110,111,111,111,111,111,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,109,110,110,111,111,110,110,110,110,110,110,111,110,111,111,111,111,111,111,111,111,111,111,109,109,110,110,110,110,110,110,111,111,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,104,106,106,107,108,104,104,108,107,107,107,107,107,107,107,107,106,106,106,106,106,106,106,108,107,107,107,107,107,107,106,107,107,104,106,106,107,104,108,107,106,106,106,107,107,107,106,106,106,106,106,217,221,217,221,217,221,217,221,217,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,252,109,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,252,107,107,109,252,109,252,252,109,109,107,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,107,107,107,107,109,107,107,107,111,111,109,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,104,108,108,108,108,108,108,108,108,108,107,108,107,108,107,108,107,108,108,108,107,108,107,108,108,108,107,108,107,108,107,107,107,105,105,105,105,111,105,105,111,110,109,110,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,110,110,111,110,111,111,110,110,110,110,111,110,111,110,111,110,111,111,111,110,111,110,111,111,111,110,111,109,110,109,110,109,110,110,111,110,111,111,111,110,111,111,111,110,111,110,111,110,109,111,111,109,110,109,111,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,110,109,109,109,110,110,111,111,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,104,104,106,107,107,108,108,104,107,108,107,108,107,107,108,107,106,107,106,107,106,107,106,106,106,108,106,108,107,107,106,107,106,106,107,104,106,104,108,108,107,107,106,107,106,107,106,107,106,107,106,106,221,217,221,217,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,107,107,107,107,252,109,252,252,252,109,109,109,107,107,107,107,107,107,109,109,109,109,107,107,109,109,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,110,111,111,111,111,104,104,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,108,108,107,108,107,107,108,108,108,108,107,108,107,105,105,111,105,111,105,105,111,110,109,110,110,110,110,110,110,109,109,110,110,110,110,111,111,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,110,111,109,109,109,110,110,110,110,110,110,109,109,111,111,111,111,111,111,111,111,111,111,111,110,111,109,109,109,110,110,110,110,110,110,111,111,111,110,110,110,111,110,111,110,111,111,111,111,111,109,109,110,111,109,109,109,109,109,109,109,110,110,110,110,110,110,111,110,111,111,111,110,110,110,110,110,111,111,111,110,111,111,111,111,111,111,111,111,111,110,110,110,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,104,106,107,107,108,108,104,104,106,107,108,107,107,107,107,107,107,106,107,106,106,106,106,106,106,107,106,107,108,107,107,106,107,107,108,104,104,107,108,108,107,107,107,106,107,107,107,106,106,106,106,106,106,221,217,217,222,221,222,217,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,109,252,252,109,109,252,252,252,252,252,252,252,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,109,107,252,109,252,109,252,109,109,109,109,107,107,107,109,107,109,107,109,107,109,109,107,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,107,107,109,107,107,107,109,107,107,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,104,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,108,108,107,108,107,108,107,108,107,108,107,108,108,108,107,108,105,105,105,111,105,111,105,105,111,110,109,110,109,110,109,110,110,109,109,110,109,110,110,111,111,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,110,109,110,109,109,109,110,109,110,110,109,109,110,110,111,110,111,111,111,110,111,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,109,110,110,111,111,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,109,110,110,111,110,111,111,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,104,106,106,107,107,108,108,104,106,106,107,108,107,107,107,107,106,107,106,107,106,107,106,106,106,106,107,108,106,107,107,106,107,108,104,107,107,108,107,108,107,107,106,107,106,107,106,107,106,107,106,107,106,106,221,217,221,217,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,109,109,252,252,109,109,252,252,252,252,252,252,108,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,107,107,107,107,252,252,252,252,252,252,109,109,109,107,107,107,107,107,109,107,109,109,109,107,109,109,109,107,109,107,107,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,107,109,109,109,109,109,110,109,110,111,110,110,109,111,110,110,111,111,111,111,111,111,107,107,108,108,108,108,108,108,108,108,108,108,108,108,107,107,108,108,108,108,108,108,108,107,108,107,108,107,108,107,107,108,105,105,105,111,111,105,111,105,111,111,110,109,110,110,110,110,110,110,109,109,110,110,110,110,111,111,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,109,109,109,110,109,110,110,110,109,109,109,110,110,110,110,111,111,111,109,109,109,109,109,110,109,109,109,110,110,110,110,110,110,111,111,111,110,111,110,111,111,111,111,111,111,109,109,109,109,110,110,111,110,110,110,110,110,110,110,110,110,110,110,111,109,110,111,111,111,111,111,111,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,109,110,110,110,110,111,111,111,111,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,104,106,106,107,107,108,108,104,104,106,106,108,107,108,107,107,107,107,107,107,106,107,106,106,106,106,106,106,107,107,107,107,106,107,108,104,108,108,108,108,107,107,107,107,106,106,107,107,107,107,106,106,106,106,106,106,221,217,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,109,252,109,252,252,109,109,252,109,252,109,252,252,252,252,108,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,107,252,109,252,109,252,109,252,109,109,109,107,107,107,107,109,107,109,107,109,107,109,107,109,109,109,107,107,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,109,107,107,107,107,107,107,109,110,109,110,110,111,110,109,111,110,110,111,110,111,110,111,110,109,109,110,107,107,107,107,108,108,108,108,108,108,108,108,107,108,107,107,107,108,108,108,107,108,107,108,107,108,107,108,107,108,107,105,105,111,111,111,111,111,105,111,111,110,109,110,109,110,109,110,110,110,109,110,109,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,109,109,110,109,110,109,110,109,110,109,109,109,110,109,110,110,111,110,111,111,109,109,110,109,110,109,110,110,111,111,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,110,109,110,109,111,110,111,109,110,110,110,110,111,110,111,110,111,110,109,109,110,110,111,110,111,111,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,110,109,110,110,111,110,111,110,111,111,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,104,106,106,107,107,108,108,104,104,104,106,106,106,108,107,108,107,107,107,107,106,107,106,107,106,107,106,106,106,108,107,108,107,107,104,107,108,108,107,108,107,108,107,108,107,107,107,107,106,107,106,107,106,107,106,107,106,106,221,217,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,109,252,109,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,109,252,252,252,252,252,109,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,252,252,252,252,252,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,109,107,107,109,109,252,252,252,252,109,109,109,107,107,107,107,107,109,107,109,107,109,109,109,109,109,109,109,107,109,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,107,107,110,109,110,110,110,109,111,111,111,111,111,110,110,110,111,111,109,109,110,110,107,106,107,107,107,107,108,108,108,108,108,108,108,108,108,107,107,107,108,108,108,108,108,105,105,105,105,105,105,105,105,105,111,111,111,111,111,105,111,111,110,109,110,110,110,110,110,110,110,110,109,110,111,110,111,110,110,110,111,111,111,110,111,111,111,111,111,111,111,110,111,111,111,110,109,109,109,109,110,109,110,109,110,110,109,109,110,110,110,110,110,110,111,111,111,109,109,109,110,110,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,110,109,109,110,110,110,110,111,111,110,110,110,110,110,110,111,110,110,110,109,109,110,110,110,110,111,111,111,111,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,109,109,110,110,110,110,111,110,111,111,111,111,110,110,110,110,110,110,111,110,110,110,111,111,111,110,104,106,108,109,108,104,110,108,104,104,104,106,106,106,108,107,108,107,107,107,107,107,107,106,107,106,106,107,106,106,108,107,107,107,107,108,108,108,108,108,108,108,108,107,108,107,106,108,107,107,107,106,106,106,106,106,106,106,107,221,222,217,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,107,252,109,252,109,252,109,252,109,109,109,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,107,107,109,107,107,107,107,107,110,110,111,110,111,110,111,110,111,111,111,110,111,110,109,109,110,109,110,107,107,106,107,106,107,107,107,108,108,108,108,108,108,108,108,107,107,105,105,105,105,105,111,111,105,105,105,105,105,111,111,110,111,111,111,105,111,111,110,109,110,110,110,109,110,110,111,110,109,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,111,111,110,111,110,111,110,111,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,110,111,110,111,111,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,111,111,110,111,109,109,109,110,110,111,110,111,111,111,110,110,110,111,110,111,110,111,110,109,109,110,109,110,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,110,111,111,109,109,110,109,110,109,110,110,111,110,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,106,110,108,104,104,111,104,107,106,106,107,108,107,108,107,107,107,107,106,107,106,106,106,107,107,106,106,108,107,108,108,108,108,108,108,108,108,108,107,108,107,108,106,107,108,107,106,106,106,107,106,107,106,107,106,107,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,107,107,109,109,109,252,109,252,252,109,109,109,109,107,107,107,107,107,107,109,107,109,109,109,109,109,109,107,107,109,109,109,107,109,107,109,107,107,107,109,107,107,107,107,107,107,107,107,107,107,107,107,110,110,110,110,110,111,111,111,111,111,110,110,110,109,109,109,109,110,107,107,106,107,106,107,106,107,107,107,107,108,108,105,105,105,105,105,105,105,111,105,111,105,105,105,105,105,105,111,111,105,111,111,111,111,105,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,110,111,110,111,111,111,111,111,109,109,109,109,109,109,109,110,109,110,109,109,109,110,110,110,110,111,110,111,111,109,109,110,109,111,110,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,111,110,109,109,109,110,110,111,111,111,110,110,110,110,110,110,110,111,110,111,110,109,109,109,109,110,110,110,110,110,110,111,110,111,111,111,110,111,111,111,111,109,111,111,111,111,109,109,109,110,110,110,110,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,106,107,108,104,104,104,107,106,106,106,106,107,108,107,107,107,107,107,107,107,107,106,107,107,107,106,106,106,108,108,108,108,108,108,108,108,108,108,108,108,108,107,106,107,108,107,106,106,107,107,107,106,106,106,107,107,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,109,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,109,252,109,252,109,252,109,109,109,109,107,107,107,109,107,109,107,109,107,109,109,109,109,107,107,107,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,109,107,109,107,109,107,107,107,107,110,111,110,111,110,111,109,110,110,110,110,109,109,110,109,110,109,107,106,107,106,107,106,107,106,105,105,105,105,105,111,105,105,111,105,105,111,105,111,111,111,105,105,105,105,105,105,105,111,111,111,111,105,111,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,110,111,110,111,110,111,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,111,110,109,109,109,110,110,111,110,110,110,110,110,111,110,111,110,111,110,111,111,111,111,109,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,109,110,109,110,110,111,110,111,110,111,111,111,110,111,110,109,110,111,111,109,109,110,109,110,110,111,110,111,110,111,111,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,109,110,111,110,111,110,111,110,106,106,110,104,107,106,107,106,107,106,106,107,108,107,108,107,107,106,107,106,106,106,107,107,106,106,106,108,108,108,108,108,108,108,108,108,108,107,108,107,108,107,106,107,107,106,106,106,107,106,107,106,107,106,107,106,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,108,252,108,252,108,108,109,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,109,109,109,109,109,252,109,109,109,109,107,107,107,109,107,109,107,109,109,109,109,107,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,107,107,107,107,107,107,107,107,107,107,107,107,111,111,111,109,110,110,110,110,110,110,110,109,109,109,110,109,110,107,107,105,105,105,105,105,105,105,105,105,105,105,111,111,111,111,111,111,111,111,111,105,105,105,111,111,111,111,111,111,111,111,105,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,110,111,111,111,111,111,111,111,110,111,110,110,110,111,111,111,110,111,109,109,109,109,109,109,109,110,109,109,109,109,109,110,109,110,110,110,110,111,111,109,109,109,109,110,110,111,111,110,110,110,110,110,110,111,111,111,111,111,111,111,109,109,109,110,110,111,110,110,110,111,111,111,110,110,110,110,110,111,110,111,110,111,111,109,109,110,109,110,110,110,110,110,110,111,111,111,111,111,111,111,110,111,109,110,111,109,109,109,109,110,110,110,110,111,111,111,111,110,110,110,110,110,110,110,110,111,110,110,110,111,110,111,110,109,111,111,111,111,111,111,106,107,108,104,110,107,107,107,106,107,106,106,106,108,107,107,107,107,107,107,107,107,106,106,106,107,107,106,106,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,107,107,106,106,107,107,107,106,106,106,106,106,107,107,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,108,109,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,109,109,252,109,252,109,109,109,109,109,107,107,107,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,107,107,107,107,107,109,110,109,110,109,110,109,110,110,111,110,109,109,110,109,110,105,105,105,111,111,111,105,111,105,111,111,105,111,109,111,111,111,111,111,111,111,105,105,105,105,111,105,111,111,111,111,105,111,111,111,110,109,110,109,110,110,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,111,110,109,109,109,109,109,109,109,109,110,109,109,109,109,109,110,110,111,110,111,109,110,109,109,109,110,110,111,111,111,110,111,110,111,110,111,110,111,110,111,111,109,109,110,109,110,109,110,110,111,111,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,109,109,109,110,109,110,110,110,110,111,110,111,110,111,111,111,110,111,110,111,110,111,109,110,109,110,110,111,110,111,110,111,111,110,110,111,110,110,110,111,110,111,109,110,109,110,110,111,110,111,110,111,110,111,110,111,106,107,108,104,110,107,107,107,106,106,107,107,106,106,106,108,107,108,107,108,106,107,107,106,106,107,107,107,106,106,106,108,108,108,108,108,108,108,108,108,108,108,108,108,107,108,107,108,107,106,106,107,107,107,106,106,106,107,106,107,107,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222,222,222,221,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,108,108,108,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,109,109,109,109,252,252,109,109,109,107,107,107,107,107,109,109,109,109,109,107,107,107,109,109,109,109,109,107,109,107,109,107,107,109,109,107,107,107,107,107,107,107,107,107,107,107,107,107,109,109,109,109,109,109,110,109,110,109,110,110,109,109,110,110,110,111,111,110,111,105,105,111,111,105,111,111,111,111,111,111,111,111,111,105,105,111,105,111,111,111,111,111,111,105,111,111,105,111,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,111,111,110,110,110,111,111,111,110,111,110,111,110,111,110,111,111,111,111,111,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,110,111,109,109,109,109,110,109,110,110,111,111,110,110,110,110,110,110,109,110,111,111,111,109,109,109,110,109,109,109,110,110,110,110,111,111,111,110,110,110,110,110,110,110,111,110,111,110,111,110,109,109,109,109,110,110,110,110,110,110,111,111,111,110,111,110,111,111,111,111,111,111,109,109,110,110,110,110,111,111,111,111,111,110,110,110,110,110,110,110,109,109,110,110,110,110,110,110,111,111,111,111,111,111,111,111,106,107,108,104,110,107,107,107,106,106,107,107,107,106,106,106,108,107,107,107,106,106,107,106,106,106,107,107,106,106,106,106,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,107,106,106,106,107,107,107,106,106,106,107,107,107,106,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,252,109,109,252,109,252,109,109,109,107,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,109,107,109,107,107,109,109,109,110,109,110,109,110,109,111,109,110,109,110,109,110,110,111,110,111,111,111,111,111,111,111,110,111,110,111,111,111,111,105,105,105,105,105,105,111,105,111,111,111,105,111,111,111,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,109,109,109,109,109,109,109,109,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,111,110,110,110,111,109,110,109,110,110,111,110,111,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,109,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,109,110,109,110,110,111,110,111,111,111,111,110,110,110,110,111,110,109,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,106,107,108,104,110,107,108,107,107,106,107,106,107,107,107,106,106,107,108,107,108,107,107,106,107,106,107,106,107,106,106,107,106,108,108,108,108,108,108,108,108,108,108,108,108,107,108,107,108,107,106,107,106,106,107,106,106,106,107,107,107,107,106,106,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,108,108,108,108,252,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,109,109,109,252,252,252,252,109,107,107,107,109,109,109,109,109,107,109,107,107,107,107,107,109,109,109,107,109,107,109,107,107,109,109,107,109,107,107,107,107,107,107,107,107,107,107,107,107,109,109,109,110,110,110,110,111,110,110,109,110,110,110,110,110,110,110,110,111,111,111,110,111,111,111,111,111,111,111,111,105,111,111,111,105,111,111,111,111,111,105,105,111,111,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,110,110,110,111,110,111,111,111,111,110,110,111,111,111,110,111,111,111,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,110,110,109,109,110,110,110,110,110,110,111,110,111,111,109,109,110,109,109,109,110,110,110,110,111,111,111,111,110,110,110,110,111,110,110,110,111,110,111,110,111,111,111,110,111,111,111,111,111,111,111,111,111,110,111,110,111,111,111,111,111,111,111,111,111,109,109,110,110,111,111,110,111,111,111,110,110,110,110,110,109,109,109,109,110,110,110,110,111,111,111,110,111,111,111,111,111,106,107,108,109,110,108,107,107,107,106,106,107,107,107,106,106,106,106,107,108,107,107,107,107,107,107,106,107,107,106,106,107,107,106,108,108,108,104,104,104,104,108,108,108,108,108,108,108,108,108,107,106,106,106,106,107,107,106,106,107,107,106,106,106,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,107,252,252,252,109,109,109,252,109,252,252,107,107,109,107,109,107,109,109,109,107,107,107,109,107,109,109,109,109,109,107,109,107,109,107,107,107,109,107,109,107,107,107,109,107,107,107,109,107,107,107,110,109,110,110,111,111,110,109,110,109,110,110,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,105,105,111,111,105,105,111,111,105,111,105,105,111,111,111,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,111,111,110,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,111,111,109,109,109,110,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,109,109,110,109,110,109,110,110,109,109,110,109,110,109,110,110,111,110,111,110,111,111,110,109,110,109,110,110,111,110,111,111,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,110,111,110,111,110,111,111,111,111,111,109,110,109,110,110,111,110,111,110,111,110,110,110,111,110,109,109,110,109,110,110,109,110,111,110,111,110,111,110,111,110,111,111,109,109,109,108,108,107,108,107,108,107,107,106,106,106,107,107,107,106,108,107,108,107,107,107,107,106,107,106,106,106,107,106,104,104,104,104,104,104,104,104,104,104,104,108,108,108,108,108,108,107,108,107,108,106,107,106,107,106,107,106,107,107,107,106,106,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,223,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,108,108,108,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,252,252,107,107,107,107,109,109,109,107,107,107,107,107,109,109,109,109,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,107,107,107,110,110,111,111,109,110,109,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,105,105,111,105,105,105,105,111,111,111,111,111,111,111,111,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,111,110,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,110,109,109,109,109,110,110,110,110,110,110,111,110,111,111,111,111,110,110,110,110,111,110,111,111,111,110,110,110,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,111,110,111,111,111,111,111,111,111,111,111,110,110,109,109,109,110,110,110,110,111,111,110,110,110,110,110,109,110,110,110,111,109,110,111,111,111,111,111,111,111,111,111,111,109,109,109,109,108,108,108,107,107,107,107,107,106,106,107,107,107,106,106,106,107,107,107,107,107,106,106,106,106,104,104,104,104,104,109,109,109,109,109,109,109,109,109,104,104,104,104,108,108,108,108,107,108,107,107,107,107,107,107,107,106,106,107,106,106,106,106,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,109,108,252,108,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,109,107,109,107,107,109,109,107,109,109,107,109,107,107,107,107,107,109,107,109,107,109,107,109,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,105,105,105,105,105,111,110,111,111,111,111,111,111,110,111,111,111,109,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,111,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,109,110,111,110,111,109,109,109,109,109,109,109,110,109,109,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,110,111,110,111,110,111,111,111,110,111,110,111,110,111,111,110,109,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,109,110,111,110,111,111,111,111,111,111,110,110,109,109,110,109,110,110,111,111,111,110,111,110,111,110,111,110,111,110,109,111,111,110,111,110,111,110,111,110,111,110,109,109,110,109,108,107,108,107,108,107,108,107,107,106,107,106,107,106,107,106,106,106,107,106,106,104,104,104,104,104,109,109,110,109,110,109,110,110,111,110,111,109,110,109,110,109,110,110,109,109,109,107,108,107,108,107,108,107,107,107,107,106,107,106,107,106,107,106,106,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,108,108,108,252,252,108,108,108,108,108,108,252,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,109,109,109,107,107,107,109,107,109,107,109,109,109,109,107,107,107,107,109,107,107,107,109,107,109,107,107,107,107,107,107,107,107,107,107,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,105,105,111,105,105,111,111,111,111,111,111,111,111,111,110,110,111,110,110,110,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,110,111,110,110,110,109,109,110,110,110,110,111,111,109,111,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,111,110,111,111,111,111,110,109,111,110,110,110,110,110,110,110,111,110,110,110,111,111,111,110,111,111,111,111,111,111,111,111,111,111,111,111,109,109,110,110,111,111,111,111,111,111,110,110,110,110,109,109,110,111,111,110,110,110,110,110,111,110,110,110,111,110,109,111,111,111,111,110,111,111,111,111,111,109,109,109,110,109,108,108,108,108,108,107,108,107,107,107,106,106,106,106,107,107,106,104,104,104,104,104,104,109,109,109,110,110,110,110,110,110,110,110,111,110,111,109,109,109,110,110,110,110,110,110,111,111,104,104,106,108,108,107,107,107,107,107,107,107,106,106,107,106,106,106,106,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,108,252,108,252,108,252,108,252,108,252,108,252,108,252,107,252,107,252,252,252,107,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,109,109,107,107,107,107,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,109,107,109,107,109,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,105,105,105,105,105,111,111,111,110,111,111,111,110,111,111,110,110,111,110,111,111,110,110,109,109,110,109,110,109,110,110,111,110,111,111,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,109,110,109,110,110,111,110,111,111,111,110,109,109,109,109,110,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,110,109,109,109,110,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,111,111,110,111,111,109,109,111,111,111,110,110,110,111,110,111,110,109,110,111,110,111,110,111,110,111,110,111,111,111,110,111,111,111,111,109,109,110,110,111,111,111,110,111,111,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,109,109,111,110,111,110,111,110,111,110,111,109,110,108,108,108,108,108,108,108,108,107,108,107,108,107,106,106,107,110,110,110,110,110,109,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,109,109,109,110,109,110,110,111,110,111,110,111,111,104,104,106,107,108,107,108,107,107,107,107,106,107,107,107,106,106,106,106,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,108,108,108,252,252,252,108,108,108,108,108,108,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,109,107,107,107,107,107,109,109,109,109,109,109,107,107,109,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,109,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,105,105,105,105,111,111,111,111,111,111,111,111,111,105,111,111,111,110,110,110,111,111,110,110,110,110,109,109,110,110,111,111,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,109,109,109,110,110,110,110,111,111,111,111,111,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,109,110,110,110,110,110,109,110,111,111,110,111,111,111,111,111,109,110,110,110,111,111,110,110,110,110,110,110,109,110,110,111,111,111,110,111,111,111,111,111,111,111,111,111,111,111,111,109,110,110,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,109,111,110,111,110,111,110,111,111,111,111,109,109,109,108,108,108,108,108,108,108,108,108,108,108,108,110,110,110,110,110,109,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,110,109,110,110,110,110,111,110,111,111,111,111,104,106,106,107,108,107,107,107,107,107,107,106,107,106,107,106,106,106,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,252,252,252,252,252,252,252,108,108,108,252,108,252,108,252,108,252,107,252,107,252,107,252,107,252,252,252,107,252,252,252,252,252,252,252,252,252,252,252,252,107,107,109,107,107,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,109,107,109,107,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,105,105,105,111,105,111,110,111,110,111,111,111,111,111,111,111,111,111,109,110,110,111,111,110,109,110,109,110,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,111,111,109,110,110,111,109,109,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,109,109,109,109,110,109,110,109,110,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,109,109,110,109,111,110,111,111,110,110,111,110,111,109,110,109,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,110,111,110,111,110,111,111,111,110,111,110,110,110,110,110,110,110,111,110,111,110,111,110,109,109,110,110,111,110,111,110,111,110,111,110,111,110,109,109,108,108,108,108,108,108,108,108,108,108,111,111,110,110,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,104,111,104,107,106,106,107,108,107,108,107,107,107,107,106,107,106,107,106,107,106,223,222,223,222,223,222,104,104,104,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,108,108,107,107,107,252,107,107,107,252,107,252,107,252,252,252,107,252,252,252,252,252,252,252,252,252,107,252,107,109,107,107,107,109,107,109,107,109,109,109,109,107,107,107,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,109,109,110,109,110,110,110,110,110,110,111,111,111,111,105,105,105,111,111,111,111,111,111,111,111,111,111,105,111,105,111,111,110,109,110,110,111,111,110,110,110,109,110,110,110,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,109,109,110,110,111,111,110,109,110,110,111,111,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,110,110,110,111,110,111,111,111,111,110,110,111,111,111,109,109,109,110,110,110,110,111,111,110,110,110,110,110,110,109,109,110,110,111,110,111,111,111,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,109,111,109,111,111,110,110,110,110,110,110,110,110,110,110,111,110,109,110,111,110,110,110,111,111,111,110,111,111,111,110,109,108,108,108,108,108,108,108,108,111,111,111,111,110,111,109,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,104,106,106,106,106,107,107,107,107,107,107,107,107,107,107,106,106,106,106,106,223,222,104,104,104,104,104,104,104,104,104,104,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,252,107,252,107,107,107,109,107,109,107,109,109,109,109,109,107,109,107,109,109,109,107,107,107,109,107,109,107,109,107,107,107,109,107,107,107,109,107,109,109,110,109,110,110,111,110,111,110,111,111,105,105,105,105,105,105,111,105,111,111,111,110,105,105,111,111,111,111,109,109,111,111,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,111,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,111,109,109,110,109,110,110,111,111,109,109,110,109,109,109,110,109,109,109,110,109,109,109,110,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,111,109,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,109,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,109,109,109,110,109,110,110,111,110,111,111,111,110,111,111,110,110,110,110,111,110,110,110,111,110,109,109,111,110,111,110,111,110,111,110,109,110,111,110,111,110,109,108,108,108,108,108,108,108,111,110,110,110,111,110,109,109,109,109,110,109,110,109,110,109,109,111,110,109,110,109,110,109,110,110,110,109,110,110,111,110,110,110,109,109,109,111,110,109,110,109,110,109,110,110,111,110,111,110,111,110,106,108,104,106,106,106,106,107,108,107,108,107,107,107,107,106,107,106,107,106,106,106,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,108,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,107,107,107,107,107,107,107,107,107,252,107,252,107,252,107,252,107,252,252,252,252,252,252,252,252,252,107,252,107,107,107,107,107,109,109,109,109,109,107,107,107,109,109,109,109,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,109,109,109,110,110,110,110,111,111,111,105,105,105,111,111,111,111,111,111,111,111,111,111,111,111,109,110,111,111,109,111,110,109,110,109,110,110,110,109,110,110,110,110,110,109,109,109,109,109,110,109,110,110,111,110,110,110,110,110,110,110,111,110,111,111,111,109,109,109,110,110,110,110,111,111,109,109,110,110,110,110,111,111,111,109,109,109,109,109,110,110,110,109,109,109,109,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,111,110,111,110,109,109,109,109,110,110,110,110,111,110,111,111,111,110,109,111,110,110,110,110,111,110,111,110,111,110,111,110,111,111,111,111,111,111,111,109,109,109,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,109,110,110,111,110,111,110,110,110,111,109,110,111,111,111,111,110,109,109,108,108,108,108,108,108,110,110,110,110,110,110,109,109,109,109,109,109,109,109,109,109,110,110,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,109,110,111,111,109,109,110,110,110,110,110,110,110,110,110,110,111,110,106,107,104,104,106,106,106,106,106,107,107,107,107,107,107,107,106,107,107,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,109,109,107,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,107,107,107,107,109,107,109,107,252,109,110,109,110,110,111,111,105,105,105,110,111,110,111,109,111,110,111,111,111,111,109,109,110,109,110,110,111,111,110,109,110,109,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,109,109,110,110,111,110,111,110,111,110,111,110,109,109,110,109,110,110,111,110,111,110,111,111,109,109,110,109,110,110,111,110,111,110,109,109,110,109,110,109,110,110,110,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,111,111,109,110,111,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,110,110,111,110,111,111,111,111,111,111,110,110,110,110,110,110,110,110,109,109,110,110,111,111,111,110,111,110,109,109,110,110,109,109,111,111,109,109,110,108,108,108,108,108,108,110,110,110,111,110,109,109,109,109,110,109,110,109,109,109,110,110,111,110,111,109,110,109,110,109,110,109,110,110,110,110,109,109,110,110,111,111,110,109,110,109,110,109,110,110,110,110,111,110,111,110,106,107,109,104,107,106,107,106,106,106,106,107,108,107,108,107,106,106,107,106,107,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,106,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,252,108,252,252,252,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,107,107,107,107,107,107,252,107,107,107,252,107,107,107,252,252,252,107,252,252,252,252,252,252,109,107,109,107,107,107,109,107,109,107,109,109,109,109,107,107,107,107,109,109,109,107,107,107,109,107,109,107,109,107,107,107,107,107,107,107,107,252,109,109,110,110,111,105,105,105,111,111,109,109,110,110,111,111,111,105,111,109,109,109,110,109,110,110,110,110,111,111,111,111,110,110,110,109,110,110,110,110,110,110,110,109,109,109,109,109,110,109,110,110,111,111,109,109,110,109,110,110,110,110,110,110,111,110,111,110,111,111,111,110,109,109,109,109,110,110,110,110,111,111,109,109,110,109,110,110,109,109,109,109,110,110,109,109,109,109,109,109,110,110,110,110,110,110,110,110,111,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,109,109,110,110,111,110,110,110,111,110,110,110,111,110,111,110,111,111,111,109,110,110,111,111,109,109,110,110,111,111,111,110,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,109,111,110,110,110,111,110,110,110,109,109,110,109,110,110,110,110,111,111,109,109,108,108,108,108,110,110,110,110,110,110,109,111,109,109,109,109,109,109,109,109,110,110,110,110,111,110,110,109,110,110,110,110,110,110,110,109,110,110,110,110,111,111,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,106,108,104,107,107,106,106,106,106,106,106,106,107,107,107,107,107,106,106,107,107,107,106,107,107,106,106,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,106,106,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222,223,222,222,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,252,109,107,109,107,107,107,107,107,109,107,109,109,109,109,107,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,252,252,109,110,105,105,105,111,111,109,110,109,110,110,111,111,111,105,111,109,109,110,111,109,110,110,110,110,111,110,111,110,111,111,111,109,110,109,110,109,110,110,110,109,109,109,110,109,110,110,111,110,111,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,109,111,110,109,109,110,109,110,109,110,110,111,109,109,109,110,109,109,109,109,109,110,109,110,109,110,109,109,109,110,109,110,109,110,110,110,110,111,110,109,109,110,109,110,109,110,109,109,110,111,110,110,110,111,110,111,110,111,110,109,109,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,110,111,111,109,110,111,110,111,110,111,111,111,111,110,110,110,109,110,110,111,110,110,110,111,110,110,110,111,110,111,110,111,110,111,109,109,109,110,109,110,110,111,110,111,111,110,108,108,108,110,110,110,110,109,109,111,111,109,109,110,109,110,109,110,109,109,109,111,111,110,109,110,109,110,110,110,109,110,110,109,109,110,110,111,110,111,111,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,106,109,107,106,107,106,107,106,107,106,106,106,106,107,108,107,108,107,107,107,106,106,106,106,107,107,106,106,104,104,104,104,104,104,104,104,104,104,106,104,104,104,104,104,104,106,106,106,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,109,108,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,252,252,252,107,107,107,107,107,107,107,252,107,107,107,252,107,252,107,252,252,252,252,252,252,109,109,109,107,109,107,107,107,109,107,109,109,109,107,109,107,107,107,109,107,109,109,109,109,109,107,109,107,109,107,109,107,107,107,107,107,107,107,107,107,252,105,105,105,105,111,111,109,109,110,110,110,111,111,111,105,111,111,109,110,111,111,110,109,110,110,110,110,110,110,111,110,111,111,111,111,110,110,110,110,110,110,110,109,109,109,110,110,111,111,111,110,109,109,109,109,110,110,110,110,110,109,109,109,110,110,110,110,111,111,111,109,109,109,110,110,110,110,110,110,109,109,110,109,109,109,109,109,109,109,110,109,110,109,109,109,109,109,110,110,110,110,110,110,110,110,109,109,109,109,110,110,110,110,111,111,111,111,110,110,111,110,111,111,111,109,109,110,110,110,111,111,110,110,110,110,110,110,111,110,111,110,111,109,109,109,110,110,110,110,111,111,110,110,110,110,110,110,111,109,110,110,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,109,109,109,110,109,110,110,110,110,111,111,111,111,110,109,110,110,109,109,110,110,111,111,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,109,109,109,110,110,111,111,109,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,109,107,107,107,107,107,106,106,106,107,107,106,106,106,107,107,107,107,107,107,107,107,106,106,106,107,107,106,106,104,104,104,104,104,104,104,104,106,104,104,104,104,104,104,104,106,106,106,106,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,252,108,252,252,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,109,107,109,107,109,107,107,107,109,107,109,109,109,107,109,107,107,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,107,107,109,107,109,107,252,107,252,105,111,111,111,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,109,110,109,110,110,111,110,111,110,111,110,111,111,110,109,110,109,110,109,110,110,110,109,109,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,110,109,110,109,110,109,110,110,109,109,109,109,110,109,110,109,110,109,110,109,110,109,109,109,109,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,111,111,110,111,110,111,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,110,111,109,110,109,110,109,110,110,111,110,111,110,111,111,110,109,110,110,110,110,110,110,111,110,110,110,111,109,110,109,110,109,110,110,109,109,110,109,110,109,110,110,111,110,111,111,110,109,108,109,110,109,110,110,111,111,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,111,111,110,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,109,107,107,107,106,107,106,106,106,107,106,107,106,106,106,106,107,108,107,108,107,107,106,106,106,107,106,107,106,106,106,104,106,104,104,104,104,104,104,106,107,104,106,104,104,104,106,107,106,106,106,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,252,252,107,107,107,107,107,107,107,107,107,252,107,252,107,252,252,252,107,252,107,107,107,109,109,109,107,109,107,109,109,109,107,109,107,109,107,107,107,107,107,107,107,109,109,109,109,109,109,109,107,109,107,109,107,107,107,107,107,107,107,107,107,252,252,111,111,111,111,109,109,110,110,110,110,111,111,105,111,110,110,110,110,111,111,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,110,109,109,109,109,109,110,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,109,109,109,110,109,110,110,110,109,109,109,109,109,109,109,109,109,110,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,110,110,109,109,109,109,110,110,110,110,111,111,111,110,111,110,110,110,111,110,110,110,111,111,111,110,109,110,111,109,109,109,109,109,110,110,110,110,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,110,109,110,110,109,109,110,110,110,110,110,110,111,110,111,111,110,109,108,108,109,109,110,110,111,111,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,109,110,110,110,110,110,110,109,109,111,111,110,110,109,109,109,109,109,109,109,109,110,110,110,109,110,110,110,110,110,110,110,109,107,107,107,107,107,107,107,106,106,106,107,107,107,106,106,106,106,107,107,107,107,107,107,107,106,107,106,107,107,106,106,104,106,108,104,104,104,104,104,104,106,107,108,104,104,106,107,106,107,106,106,106,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,252,108,252,108,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,109,109,107,109,107,109,107,109,107,107,107,107,107,252,107,252,107,252,252,111,110,111,109,110,110,111,110,111,111,111,111,110,110,111,110,111,111,111,109,110,110,110,110,110,110,111,110,111,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,109,110,109,110,110,111,109,109,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,111,111,110,109,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,109,109,109,109,110,109,110,110,110,110,111,110,111,110,111,111,111,111,110,110,110,110,110,110,111,110,110,110,109,109,110,109,110,109,110,110,109,109,110,109,110,109,110,110,111,110,111,109,110,109,108,108,110,109,110,110,111,111,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,109,110,111,110,111,110,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,109,110,110,111,109,108,107,108,107,107,107,107,106,107,106,107,106,107,107,107,106,106,106,106,107,108,107,108,107,107,107,107,106,107,106,106,106,104,106,104,104,104,104,104,104,104,106,107,108,104,104,108,107,107,106,107,106,106,106,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,108,252,252,252,252,107,107,107,107,107,107,107,107,107,107,252,107,252,107,252,252,252,107,107,107,109,109,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,109,107,109,109,109,109,109,109,109,107,109,107,109,107,107,107,107,107,107,107,107,107,252,111,111,111,109,109,110,110,111,111,111,110,110,110,110,110,111,111,111,111,109,109,110,110,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,109,109,109,109,109,109,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,109,111,110,111,111,111,111,111,111,109,109,109,109,110,110,110,110,111,111,111,111,110,110,110,110,111,110,111,110,111,110,111,110,111,111,109,109,109,109,109,109,110,110,110,110,110,110,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,109,109,109,109,110,109,110,110,110,110,109,109,110,110,111,111,111,111,111,109,109,109,110,109,109,110,110,110,111,111,109,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,109,111,110,110,110,110,110,110,110,110,110,111,109,109,109,109,109,109,109,110,109,110,109,110,110,110,110,110,110,110,109,108,107,107,107,107,107,107,107,107,107,107,106,106,106,107,107,106,106,106,106,106,107,107,107,107,107,107,106,107,107,106,106,106,104,104,104,104,104,104,104,104,104,106,107,104,104,108,107,107,107,106,107,107,106,106,106,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,222,223,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,108,252,108,252,107,252,252,107,107,252,107,252,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,109,107,109,107,107,109,109,107,109,107,107,107,109,107,109,107,109,107,109,107,109,109,109,109,109,107,109,107,109,107,107,107,107,107,252,107,252,252,111,109,111,110,109,110,111,111,111,111,110,110,111,110,111,110,111,111,111,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,109,111,111,111,110,110,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,109,109,110,110,111,110,111,110,111,110,111,111,111,109,110,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,109,111,111,110,111,110,111,109,109,109,110,109,110,109,110,110,111,110,111,110,111,111,111,110,111,111,111,110,110,110,110,110,110,110,111,109,109,109,110,109,110,109,110,109,110,110,109,110,111,110,111,110,109,109,108,108,111,109,110,109,110,110,111,111,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,111,110,110,110,110,111,110,111,110,111,110,109,109,109,109,110,109,110,109,110,109,110,109,110,110,110,110,109,109,108,107,108,107,108,107,108,107,107,107,107,106,107,106,107,106,107,106,107,106,106,106,106,107,108,107,108,107,107,106,107,106,106,106,104,104,104,104,104,104,104,104,106,107,104,104,108,107,108,107,108,106,107,107,107,106,106,106,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,108,109,108,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,108,252,252,252,252,252,107,107,107,107,107,107,107,252,107,107,107,252,107,252,107,252,107,107,107,109,109,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,109,107,109,107,109,109,109,109,109,107,109,107,109,107,107,107,107,107,107,107,252,107,252,111,111,111,109,109,109,111,111,111,110,110,110,110,111,111,109,109,109,109,109,109,109,109,109,109,110,109,109,109,110,110,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,111,111,110,109,109,110,110,111,111,111,111,111,110,110,109,109,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,110,109,109,109,110,110,110,110,110,110,109,109,110,110,110,110,111,110,111,110,111,111,111,111,111,109,109,109,110,110,110,110,110,110,111,111,111,110,110,110,111,110,110,109,110,110,110,110,111,111,111,109,109,109,109,109,110,110,110,110,110,110,111,111,111,111,110,110,111,111,111,111,111,110,110,110,110,110,110,110,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,108,108,108,108,111,110,109,109,110,110,111,111,110,109,109,109,109,109,109,109,109,109,109,109,110,110,110,109,110,109,110,111,110,110,110,110,110,110,110,110,111,110,110,109,109,109,109,109,111,109,110,109,110,110,110,110,110,106,110,108,108,108,108,107,108,107,107,107,107,107,107,107,107,107,107,106,107,106,106,106,106,106,106,106,106,108,107,107,107,107,106,106,106,106,104,104,104,104,104,104,104,104,104,106,108,104,108,108,108,108,107,107,107,106,107,107,107,106,106,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,223,223,223,223,222,223,223,223,222,223,223,223,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,108,109,252,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,252,252,107,107,107,107,252,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,109,107,109,107,109,107,107,107,109,107,107,107,109,107,109,107,109,107,109,109,109,109,109,107,109,107,109,107,109,107,107,107,252,107,107,107,252,107,252,111,111,109,110,110,111,110,110,110,111,110,109,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,110,110,111,110,111,110,111,109,109,109,110,109,110,109,110,110,110,110,111,110,111,110,111,111,111,111,110,109,109,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,111,110,111,110,111,111,109,109,110,109,110,110,111,110,111,110,111,110,111,110,111,109,110,109,110,110,111,110,111,111,111,109,109,109,110,109,109,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,111,110,110,110,110,111,110,109,109,109,109,110,110,111,109,110,110,110,110,110,110,111,108,108,108,108,111,111,109,109,109,110,110,111,111,110,110,109,109,109,109,110,109,110,111,110,109,110,109,110,109,110,110,109,110,111,110,110,110,110,110,111,110,111,110,111,109,110,110,111,109,110,110,111,109,110,110,110,106,108,108,110,108,108,108,108,107,108,107,108,107,108,107,108,106,108,107,107,106,107,106,107,106,107,106,107,106,106,106,106,107,108,107,108,106,106,106,106,106,104,104,104,104,104,104,104,104,104,108,104,108,108,108,108,107,108,107,106,106,107,107,107,106,106,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,223,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,108,109,108,109,108,109,108,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,252,252,107,107,107,107,107,107,107,107,107,107,107,107,252,107,109,107,107,107,109,109,109,107,109,107,109,107,109,107,109,107,109,107,107,107,107,107,107,107,109,107,109,109,109,109,109,109,109,107,109,107,109,107,109,107,107,107,107,107,107,107,252,107,111,111,111,111,111,111,111,110,110,110,109,109,109,109,109,109,109,109,109,109,109,109,110,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,109,109,109,109,109,110,111,109,109,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,109,109,110,110,110,110,111,110,111,111,110,110,111,110,111,111,111,111,109,109,109,109,110,110,110,110,111,110,111,111,110,110,110,109,109,109,110,110,110,110,110,110,111,111,111,111,109,109,110,109,109,109,110,110,110,110,111,111,110,110,111,111,111,111,111,111,110,110,110,110,110,110,109,109,110,110,111,109,110,110,110,110,110,110,110,110,111,108,108,108,108,108,111,109,110,109,110,110,111,111,110,110,110,110,109,109,109,109,110,111,109,109,110,109,110,109,110,110,110,110,109,111,110,110,110,110,110,110,111,110,111,109,110,110,111,109,110,110,110,110,111,110,106,107,108,109,110,108,108,108,108,108,108,108,108,107,108,107,107,106,107,107,108,107,107,107,107,106,107,106,106,106,106,106,106,106,106,107,108,107,107,106,104,106,104,104,104,104,104,104,104,104,108,108,104,108,108,108,108,108,108,108,108,107,106,106,107,107,106,106,106,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,107,252,107,252,107,252,107,252,107,107,107,109,107,109,107,109,107,109,107,109,107,109,107,107,109,109,107,107,107,109,107,109,107,109,107,109,107,109,109,109,109,109,107,109,107,109,107,107,107,107,107,252,107,252,107,252,107,111,110,111,110,111,110,110,110,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,110,110,111,110,111,110,111,109,109,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,109,109,109,109,109,109,110,110,111,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,110,111,110,111,111,111,110,111,110,111,110,111,110,109,109,110,109,110,110,110,110,111,110,111,111,111,110,111,110,109,109,110,109,110,109,110,110,111,110,111,110,111,111,110,109,110,109,109,109,110,110,111,110,111,110,111,110,111,110,111,111,110,110,110,110,110,109,110,110,111,109,109,109,110,109,110,109,110,110,110,110,108,108,108,108,108,108,111,109,110,109,110,110,111,111,111,110,111,110,109,109,110,111,111,111,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,109,109,110,110,111,109,110,109,110,110,111,106,107,107,109,109,110,108,108,108,108,108,108,107,108,107,108,107,108,107,106,106,107,107,108,107,107,106,106,108,106,106,107,106,106,106,106,106,106,107,108,107,106,107,104,104,104,104,104,104,104,104,108,108,104,108,108,108,108,108,108,108,108,107,106,106,108,106,107,107,107,106,106,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,223,223,222,223,222,223,222,223,222,223,222,223,223,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,108,109,252,109,109,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,107,107,252,107,107,107,109,109,109,107,109,107,109,107,107,107,107,107,109,109,107,107,107,107,107,107,109,107,109,107,109,109,109,109,109,107,109,107,109,107,252,107,107,107,107,107,107,107,107,107,252,107,252,110,111,111,110,110,109,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,110,110,111,111,111,110,109,109,109,109,110,110,110,110,110,110,110,110,111,111,111,111,109,109,109,109,110,110,111,111,109,109,109,109,109,109,109,109,110,109,109,109,110,109,110,109,110,109,109,109,110,110,110,110,110,110,111,110,111,111,110,110,111,110,111,110,111,111,111,109,109,109,110,110,110,110,110,110,111,111,111,110,110,110,110,110,109,109,109,109,110,110,110,110,111,111,111,109,110,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,109,110,111,110,110,110,109,109,109,109,110,110,110,110,110,110,108,108,108,108,111,111,110,109,110,110,109,110,111,110,111,110,111,110,109,109,110,110,111,109,109,109,110,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,111,109,109,109,110,110,111,111,109,109,110,110,110,106,107,107,108,109,109,110,108,108,108,108,108,108,108,108,108,108,108,107,108,106,106,107,107,108,108,107,106,107,107,108,106,106,106,106,106,106,106,106,106,108,106,108,104,104,104,104,104,104,108,104,104,104,107,108,108,108,108,108,108,106,108,108,108,107,106,106,107,107,106,107,108,108,106,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,252,109,109,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,252,107,252,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,107,107,109,107,109,107,109,107,109,107,109,107,109,109,109,107,109,107,252,107,252,107,252,107,107,107,252,107,252,107,252,252,252,111,111,110,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,109,110,109,110,109,110,109,110,110,111,110,111,110,111,110,109,109,109,109,110,110,111,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,110,111,110,111,110,111,111,111,110,111,110,111,110,111,110,111,110,109,109,110,109,110,110,111,110,111,111,111,111,111,110,111,110,111,110,109,109,110,109,110,110,111,111,111,109,110,109,110,109,110,110,110,110,110,110,111,110,111,110,111,110,111,111,110,110,110,109,110,110,111,110,111,110,111,110,109,109,110,109,110,109,110,110,108,108,108,111,111,109,110,109,110,109,110,110,109,110,111,110,111,109,110,110,111,111,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,111,110,111,109,110,109,110,110,111,111,111,109,110,109,106,106,107,107,108,108,109,109,110,108,108,108,108,108,108,107,108,107,108,107,108,107,108,106,107,107,108,108,107,106,107,107,108,108,107,106,107,106,107,106,106,106,106,104,104,104,104,104,104,106,104,104,104,104,107,108,108,108,108,108,108,108,106,107,108,107,108,107,106,106,107,106,107,107,108,108,106,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223,223,223,222,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,109,108,109,108,109,109,109,109,109,109,109,108,109,108,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,107,107,107,107,107,107,109,107,109,109,109,107,109,107,107,107,109,109,109,109,107,107,107,107,107,107,109,107,109,109,109,109,109,109,109,107,109,107,252,107,252,107,107,107,107,107,107,107,107,107,252,107,252,252,252,111,110,109,109,109,109,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,110,111,110,111,110,111,111,111,111,111,111,111,111,111,109,109,109,110,109,110,110,110,110,111,110,111,111,111,109,109,109,110,110,111,109,109,109,109,109,110,109,109,109,109,109,109,109,109,109,110,109,110,109,110,109,110,110,110,110,110,110,111,111,111,111,110,110,110,110,111,110,111,111,111,111,111,109,109,109,110,110,110,110,111,111,111,111,111,110,110,110,111,110,111,110,109,109,110,110,110,110,111,111,109,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,109,110,111,110,110,110,110,110,110,110,109,109,110,110,110,110,108,108,111,111,109,109,109,109,110,110,110,110,110,110,111,111,109,109,110,110,111,109,109,109,109,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,109,109,110,110,111,111,111,111,109,109,106,106,107,107,108,108,109,109,110,110,108,108,108,108,108,108,108,108,108,108,108,108,108,107,106,106,107,107,108,108,106,106,107,107,108,108,107,106,106,106,106,106,106,106,106,104,104,104,104,108,104,104,104,104,107,108,108,108,108,108,108,108,108,108,106,108,108,108,108,106,106,106,107,107,108,108,108,106,106,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223 +,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,109,109,108,109,108,109,252,109,252,109,252,109,252,109,252,109,252,109,252,109,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,107,107,107,252,107,252,107,107,107,109,107,109,107,109,107,109,107,107,107,109,107,109,107,109,107,109,107,109,107,109,107,109,107,109,109,109,109,109,107,252,107,252,107,109,107,107,107,252,107,252,107,252,107,252,107,252,252,252,110,109,109,109,109,110,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,111,110,111,110,111,110,111,110,111,110,111,110,111,110,111,111,111,111,111,110,111,252,109,109,110,109,110,109,110,110,111,110,111,110,111,109,109,109,109,109,110,109,110,109,110,109,110,109,110,109,109,109,110,109,110,109,110,109,110,109,110,109,110,110,110,110,110,110,110,111,111,111,111,110,110,110,110,111,110,111,111,111,111,111,109,109,109,110,110,110,110,111,111,111,111,111,110,110,110,111,110,111,110,109,109,110,110,110,110,111,111,109,109,110,109,110,110,110,110,110,110,110,110,111,111,111,111,111,111,110,110,110,110,109,110,111,110,110,110,110,110,110,110,109,109,110,110,110,110,108,108,111,111,109,109,109,109,110,110,110,110,110,110,111,111,109,109,110,110,111,109,109,109,109,109,109,109,109,109,110,109,110,110,110,110,110,110,110,110,110,110,110,110,109,109,110,110,111,111,111,111,109,109,106,106,107,107,108,108,109,109,110,110,108,108,108,108,108,108,108,108,108,108,108,108,108,107,106,106,107,107,108,108,106,106,107,107,108,108,107,106,106,106,106,106,106,106,106,104,104,104,104,108,104,104,104,104,107,108,108,108,108,108,108,108,108,108,106,108,108,108,108,106,106,106,107,107,108,108,108,106,106,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223]} +); diff --git a/apps/animclk/animclk.pal b/apps/animclk/animclk.pal new file mode 100644 index 0000000000000000000000000000000000000000..d33bfcdb9524e027f6819cc62f6e853f28eb03bd GIT binary patch literal 512 zcmZQz*nfZi`S|tr^Z&Q~kJ}%&->zQIp6$Qre%^XnIo-WFF*d)gXFA7Ei%z}h9DH=^ zw%z;wZi`<(XWq@$l4+&Kf{$*C*%o6QveDV!TF?5N6rZ-g^+o54&Yyr#$VJ%2*vD#~ zzO*-!784g3YBQbX(wDwyEMybxvn8aw)^gc@ASiFWnqyWvqt|lT?tM`}EPLMe`ksCB zp4(oZ_dI&r&!s!&miL;qey!P3a<$}ZjaaQ&Yk2R?xzXG19;?4U)koN7qjrGwMr~o6 zsXpSVokbt6EDL;WkSL&D^ltU!rvb&mb3S#O@BP#rPzif=jThCtHBJqFPH<4$P?h0J( ZKf=3b&1QpakQszs>05:>%&)),0235699<=?ssstststssssstststtuuuuuœœœœ›—›œ›››—œÇÇÇÁœœ›œœœ›œœ›œœœ›œ›››œ››ÊÊÊËÊËËÌÊÇÀÁÀÁÀÁÀÁÁÁÁÀÀÀÁÂÁÂÀÀÀÁÀÁÁÂÂÂÁÀÀÁÀÁÀÁÀÂÂÂÂÀÀÁÀÁÀÁÁÁÁÂÂÂÂÃÃÃÃÃÂÂÀÀÁÀÀÀÁÀÁÁÁÁÂÃÂÃÂÀÀÃÁÃÂÃÁÄÀÅÀÅÁÅÀÅÁÅÁÅÂÆÂÆÀÅÁÅÁÅÁÅÁÅÁÅÂÁÂÂ"#%&'()*,-./ "#%'(*,-/ !!"##$%&&''()**+,,-.02478;=?œœ›œœœ————œ››—ÀÇÁÅÁÆœœ›œœ›œ›œ››œœœœœ›››œ›››ËÊËÊËËÌÊÇÀÄÀÁÀÄÀÁÀÁÁÀÀÀÁÂÁÁÁÁÀÁÁÁÀÁÂÂÂÀÀÁÀÁÀÁÁÄÁÂÂÅÀÁÀÁÀÁÁÅÁÂÁÂÂÃÃÃÃÅÂÁÀÀÁÀÁÀÀÀÁÁÁÁÂÆÂÃÂÀÀÁÁÁÁÃÂÅÄÁÁÁÁÀÁÁÁÁÁÁÂÂÁÂÀÀÁÁÁÁÁÁÁÁÁÂÂÁÂÆÂ$%( "#%&()+,./--.././œœœœœ›œ›œ››——››—ÇÁÄÁÁÆÆÆÆœœ›œ›››œœ››œ›œœ›œ›œ›››œ›ËÊËÊËËÌÊÇÀÄÀÄÁÁÄÄÁÂÁÂÀÁÁÂÀÁÀÁÀÁÀÁÁÁÁÂÂÃÀÀÀÁÀÁÁÂÂÂÂÂÀÀÀÀÁÁÁÁÁÁÁÂÂÂÃÃÃÆÂÁÀÀÁÀÁÀÀÀÁÀÁÁÂÆÂÃÂÀÀÁÀÁÁÃÂÃÃÄÁÅÀÅÁÄÀÅÁÅÂÆÂÆÁÆÀÅÁÅÁÅÁÅÁÅÁÆÂÆÂÂ)*+,-./++--./œœœœœœœ››œœ››œ›››››——››››ÇÄÁÄÁÁÆÆÆœœœœœ›››œ››œœ››œœœœœœ››››››ÊËÊËËÌÊÇÀÄÀÄÁÄÁÄÁÁÂÂÀÁÁÂÂÁÀÁÀÁÁÁÁÂÂÂÂÂÀÀÀÁÀÁÁÄÂÅÁÄÁÀÀÁÀÁÁÅÁÅÁÅÁÂÃÃÃÆÆÁÂÀÁÁÂÂÀÀÁÁÁÁÁÆÆÅÂÀÀÀÀÁÁÁÂÃÂÄÄÅÁÁÁÄÁÁÁÅÂÂÂÆÂÂÀÅÀÁÁÅÁÁÁÅÂÂÂÂÂÂÂ-../ &%&&'&'(œœœœœœœ›œ›œœœ›››››››››››———ÀÄÁÄÅÁÁÆÆÆÆœ›œ›œ›œ›œ›œ›œ›œœ›œ›œ›››››ËËËÊËËËÇÄÁÄÁÄÄÄÄÁÁÂÁÁÁÂÂÀÀÁÄÁÁÁÁÂÁÂÂÃÀÀÀÁÀÁÁÁÂÅÁÄÂÀÀÀÀÁÁÁÁÅÁÁÁÂÂÃÃÆÃÁÁÀÁÀÁÁÂÀÁÀÁÁÁÂÂÁÂÀÀÁÀÁÁÃÁÃÂÅÄÄÁÅÁÄÁÅÁÅÂÆÂÆÂÆÁÅÁÅÁÅÁÅÁÅÁÅÁÆÂÆÂÆ,- "$%()+- !"#%&'()//5689;<>?0134679:<=?024:<=?02467ÇÁÄÁÁÁÅÆÆÅÆÆ›››››››››››››œœœœ››››››››ÊËÊËËËÇÄÁÄÄÄÅÄÄÅÅÂÂÁÁÁÁÄÀÁÄÁÁÁÁÁÁÂÃÃÁÀÀÁÀÁÁÄÄÅÂÅÄÁÂÀÁÁÁÀÁÅÁÅÁÄÂÃÂÆÃÅÁÁÀÀÀÀÁÀÁÁÁÁÁÂÂÆÂÀÀÁÀÁÁÁÁÃÃÅÅÄÄÄÁÄÁÁÁÅÁÅÂÆÂÂÂÅÁÅÀÅÁÁÁÅÁÅÁÆÂÆÂÆÂ/ "#&'*+- #%(*-/>?014589<=?02367:;=?014589<=?ÇÄÁÄÁÅÅÆÅÆÅÆÆœ›››››œœœ›››œ››››››››››ËËËËËËÄÀÄÄÄÄÄÄÄÅÄÁÅÂÂÁÁÀÀÁÄÁÄÁÁÂÁÂÂÃÃÀÀÁÀÁÁÅÁÄÂÅÄÄÂÀÁÀÁÂÂÄÁÅÁÅÂÂÂÃÃÅÁÁÀÁÁÀÁÁÁÁÁÁÂÂÂÆÂÁÂÁÀÁÁÃÁÃÂÃÂÅÄÅÁÅÁÅÁÆÁÄÂÅÂÆÂÆÁÅÁÅÁÅÁÅÁÅÁÆÁÆÂÆÂÆ)*+,--// !"#$%& !"#$%&()*,-./::;;<<==>>??ÄÄÄÄÅÅÅÅÆÆÆÆÆÆKKLMNNO5556œœ›œ›››››››ËÊËËËÄÀÄÄÄÄÄÆÆÁÁÁÁÆÂÂÅÀÄÁÄÁÄÁÁÁÁÂÃÃÃÀÀÁÀÁÁÅÁÄÁÄÁÄÁÀÁÂÁÄÁÅÁÅÁÂÁÂÃÃÆÆÁÁÀÁÀÀÁÁÁÁÁÁÆÁÆÆÂÁÀÀÂÁÁÁÁÃÃÃÂÅÄÄÁÅÁÅÁÅÁÅÂÆÂÆÂÅÂÅÁÅÁÅÁÅÁÄÁÅÂÆÂÆÂÆÂ!"##%%&&''((**++,,--// !##%%'(**,,./?02367:;>>;ÇÄÄÄÄÅÅÆÅÆÅÆÆÆÆÆEGGHIJJLLNNO45465767ËËËËÄÇÄÄÄÄÄÄÅÆÆÅÁÆÅÂÂÄÄÁÄÁÄÁÄÂÁÂÁÃÃÄÀÁÁÁÁÅÁÄÄÄÂÄÄÅÁÅÁÄÁÅÅÅÁÅÂÂÂÂÃÆÅÁÀÁÁÁÁÁÁÁÁÁÆÂÆÆÂÁÂÄÂÁÄÁÅÃÁÃÂÅÄÄÁÅÁÅÁÅÁÆÁÆÂÆÂÆÂÅÁÅÁÅÁÅÁÅÁÅÁÆÁÆÂÆÂ "$&)*-/!!""##$$%%&&''(()**++,,-..// !#$%&()*+-./566ÄÄÄÄÅÅÅÅÆÆÆÆÆÆÆÆÆ>??@ACDEFHIJKMNO344ËËËËÇÄÄÄÄÄÅÁÁÁÆÆÁÅÃÆÂÄÄÄÄÄÁÄÁÅÂÃÃÃÃÀÁÄÁÄÁÁÅÁÆÂÅÄÅÁÅÁÄÁÅÂÅÁÂÁÂÂÃÃÆÅÁÄÁÁÁÁÁÁÁÁÁÆÂÆÆÆÆÁÁÄÀÄÁÅÁÁÃÃÄÄÄÁÅÁÅÁÅÁÅÁÆÁÆÂÆÂÅÂÅÁÅÁÅÁÄÁÅÁÅÁÆÂÆÂÆÂ !!""##$$%%&&''(())**++,,--..//001122ÄÄÄÄÅÄÅÅÆÅÆÆÆÆÆÆÆÆÆ<ÇÀÄ>?@AACCEEGÇÄHËËËËÇÄÄÄÄÄÁÁÆÅÆÅÆÅÃÅÆÂÄÄÄÄÁÄÂÅÂÅÃÃÃÀÁÄÁÁÁÁÅÅÄÂÆÄÄÁÅÅÄÁÅÂÅÁÅÅÂÂÃÃÆÆÂÅÄÅÁÅÁÅÁÅÁÆÂÆÆÂÆÆÁÂÁÄÁÅÁÅÃÅÃÄÅÁÅÁÅÁÅÁÅÁÆÁÆÂÆÂÆÁÅÁÅÁÅÁÅÁÅÁÆÁÆÁÆÂÆÆÆ . "%'*,/ !!""##$$%%&&''(())**++,,--../0111ÄÄÄÄÄÅÅÅÅÆÅÆÆÅÆÆÆÆÆÀÄÄÅÅ=>??@ABBÇÄÄÄÄÄÄÄÄÄÄÆÆÅÁÁÅÆÆÆÆÆÅÃÃÄÄÄÄÅÅÅÅÃÃÃÅÃÃÁÄÁÄÁÄÁÁÄÁÅÆÄÄÅÁÄÁÅÁÅÅÅÁÆÂÃÃÂÃÂÅÄÄÁÅÁÅÁÅÅÅÂÆÂÅÆÆÆÁÄÄÁÅÅÅÃÃÃÄÄÁÅÄÅÁÅÅÅÁÅÅÅÁÆÆÆÂÅÅÅÁÅÄÄÁÅÅÅÁÆÆÆÂÆÆÂÆ !"#$%&'()*+,-./ !!""##$$%%&&''(())**++,,--..//001ÄÄÄÄÄÅÅÅÄÅÅÆÅÆÅÆÆÆÄÄÄÅÅÆ<>=>>ÇÇÄÀÆÅÆÆÄÄÄÅÄÅÆÁÆÁÆÅÆÆÅÅÃÅÃÄÅÄÅÄÂÄÂÅÃÅÃÃÁÄÁÄÁÄÁÁÄÁÅÅÆÄÅÅÅÁÄÄÅÂÅÅÅÂÆÆÆÃÃÅÂÅÄÅÁÅÁÅÁÆÂÆÂÆÆÅÆÂÅÄÁÄÅÅÆÅÃÅÄÁÅÁÅÁÅÁÅÁÅÁÆÂÆÂÆÂÆÂÅÁÅÁÅÁÅÁÅÁÆÁÆÁÆÆÂÆÆ,,,,,,, $'+/ !"#$%&'()*+,-./ !!!"""##$$%%%&&'''(())**+++,,,--..//0011ÄÄÄÄÅÄÄÅÅÆÅÅÆÆÆÅÆÆÅÄÄÄÅÅÆ<==ÇÀÄÀÅÅÅÅÆÆÆÆÄÅÆÆÆÅÅÅÆÆÆÅÃÅÃÃÂÅÆÆÅÅÅÅÃÅÃÃÃÄÁÄÁÁÁÄÁÄÅÂÆÄÅÄÅÁÄÁÅÂÅÅÆÂÆÂÆÃÃÃÅÄÁÅÄÅÁÅÅÅÂÆÆÆÆÆÆÆÆÅÄÄÁÅÅÆÆÅÄÄÄÄÄÄÅÅÅÅÅÅÅÅÆÅÆÄÆÆÆÅÅÄÄÄÅÅÅÅÅÅÆÆÆÂÆÆÆÂ--------- #(+/ ! ! !!"!""##$#$$%%&%'&''(')())**+*++,,-,--.././0101122ÄÄÄÄÄÄÅÅÆÆÆÅÆÆÆÅÆÆÅÄÅÅÆÅÆ<ÀÀÄÀÅÄÅÅÆÅÆÆÆÄÅÅÆÆÆÅÆÅÆÅÆÅÃÃÃÄÆÅÆÄÅÅÃÅÃÃÃÁÁÄÁÅÁÅÁÄÅÅÆÆÄÄÆÅÆÄÄÄÅÅÅÅÆÆÆÆÃÃÂÄÂÅÁÅÁÅÅÆÅÆÂÆÆÅÆÅÆÆÅÄÁÄÅÅÆÆÅÄÄÁÅÁÅÁÅÁÅÁÆÂÆÂÆÁÆÂÆÆÅÁÄÁÅÁÅÁÅÁÆÁÆÂÆÆÆÆÆ !!!!!!! !!!!""""####$$$$%%&&&&''(((())))****++,,,,---...///0111122334ÄÄÄÅÄÄÄÅÅÆÅÆÆÅÅÆÅÆÁÅÅÅÅÆÆÆÀÄÀÄÄÅÅÅÅÆÆÆÄÅÅÆÆÆÅÅÅÃÃÅÅÄÅÅÅÆÆÆÆÅÅÅÅÃÅÃÅÄÄÄÁÅÅÄÄÅÂÆÅÆÄÄÅÆÁÅÂÅÄÅÅÆÅÆÃÆÆÆÅÄÄÄÅÄÅÅÅÅÆÅÆÆÅÆÅÆÆÆÅÁÄÁÅÆÆÅÄÄÄÄÄÅÅÅÅÅÅÅÅÅÅÅÅÄÆÆÆÆÅÄÄÅÄÅÅÅÅÅÅÆÆÆÂÆÂÆÆ"" ! !!"!#"##$#$$%$%%&%&&''('(())*)**+*++,+,,--.-.././deeff0011213233ÇÄ545ÄÄÄÅÄÅÅÆÆÆÆÅÄÅÅÆÅÆÅÆÄÅÅÆÆÅÁÀÄÅÄÅÄÅÅÆÅÆÄÅÅÆÃÃÅÃÃÅÅÅÅÆÅÆÅÆÅÆÅÆÅÆÃÅÃÅÄÄÄÅÅÄÄÅÅÅÅÆÄÄÆÆÆÄÄÅÅÅÅÅÅÆÆÆÃÃÃÆÄÄÅÁÅÄÅÅÆÂÆÂÅÆÅÆÆÆÆÅÅÄÄÅÅÆÄÄÄÅÁÅÄÅÁÅÅÅÂÅÅÆÂÄÅÆÅÄÆÅÁÄÄÅÁÅÅÅÁÆÅÆÁÆÂÆÅÅ""""#ÄÅÅ$$%%%%&&&&''(((())))**++++,,,,----..///abbccdde00111223334445ÀÄÄÄÆÄÄÅÄÄÄÅÅÆÆÅÅÆÆÄÆÅÅÅÅÆÆÆÆÆÆÀÄÀÄÄÄÄÅÆÅÅÅÆÅÆÃÃÅÃÃÅÅÅÅÅÅÅÅÆÆÆÆÆÆÆÄÄÄÅÄÄÄÄÄÄÄÅÄÆÅÆÆÅÄÆÆÄÄÅÄÅÄÅÅÆÅÆÆÆÆÆÆÅÄÄÅÅÅÅÅÅÆÅÅÅÅÆÅÆÆÆÆÅÄÅÅÆÄÄÄÄÄÅÄÅÅÅÅÅÅÅÅÅÅÆÄÅÅÆÄÆÅÄÄÄÄÅÅÅÅÅÅÆÅÆÂÆÆÆÅ%&%ÄÄÅÅÆÅÅÅÆ()())*)**+*++,+,,-,--.-.././/eeff``aa0011223343ÇÇÄÄÄÄÆÆ8ÇÄÄÅÅÆÄÅÄÅÄÅÅÆÆÅÅÆÆÆÁÇÇÅÄÅÅÆÅÆÆÆÄÄÄÄÄÄÅÆÅÅÅÆÅÆÅÃÃÃÅÅÅÅÅÆÅÆÅÆÅÆÆÆÅÆÄÄÄÅÅÆÅÆÅÆÄÄÅÅÅÆÆÄÄÄÆÆÅÄÄÄÄÅÅÅÅÆÆÆÆÆÅÆÅÄÄÅÄÅÅÅÄÅÅÆÅÆÅÆÅÆÆÆÅÄÄÆÆÄÄÅÁÅÄÅÁÅÄÅÁÅÅÆÂÆÄÅÂÆÆÄÆÅÄÅÁÅÄÅÁÅÅÆÁÆÅÆÅÆÅÅ(ÅÅÅÅÅÆÆÆÆÆÆÆÆÆ+,,,,----....////aabbccdde0011222334455667ÇÀÄÄÄÄÅÆÆÆÇÄÄÄÄÆÆÆÄÅÄÄÅÅÆÆÅÆÆÆÅÇÇÄÄÆÆÅÅÆÆÆÅÄÄÄÄÄÅÆÆÆÅÅÅÆÆÆÆÅÅÅÅÅÆÅÅÆÅÆÅÆÆÆÆÆÄÄÄÅÅÅÅÆÆÆÅÄÄÅÆÅÅÄÄÅÄÆÆÆÄÅÄÅÄÅÅÆÅÆÆÆÆÆÆÅÄÄÄÅÄÅÄÅÅÅÅÅÅÆÅÆÆÆÆÆÅÅÅÄÄÄÄÅÄÅÄÅÅÅÅÅÅÅÅÆÄÄÅÅÆÆÅÆÅÄÄÅÄÅÅÅÅÅÅÆÆÆÆÆÆÅÅÄÅÄÅÅÆÅÆÅÆÅÆÆÆÅÆ././//fg`abcdef``00112233445565778788:ÄÀÄÄÄÄÅÆÅÆÆÆÀÄÄÄÄÅÅÆÅÆÄÄÄÅÅÆÆÆÅÆÆÇÄÄÄÅÅÆÆÆÅÅÆÅÄÅÄÄÅÅÅÆÅÆÅÅÅÆÅÆÅÅÅÅÆÆÅÆÅÆÅÆÆÆÆÆÆÄÄÅÅÆÅÆÅÆÅÄÄÅÆÆÅÄÄÅÅÆÅÆÆÆÄÅÅÅÅÆÆÆÆÆÆÆÅÆÄÅÄÅÄÅÄÅÅÅÅÅÅÆÅÆÅÆÅÆÆÆÅÄÄÅÄÅÄÅÄÅÄÅÁÅÅÆÅÆÅÄÁÅÅÆÆÅÆÅÁÄÄÅÄÅÅÆÁÆÅÆÅÆÅÅÅÅÅÅÅÅÅÅÆÅÆÆÆÆÆÅÆÆÆeefffgg`01122334455566778899::;;;ÄÄÄÀÄÄÅÅÅÅÅÅÆÆÄÄÄÄÄÅÆÆÅÅÆÆÆÆÅÅÅÆÆÆÆÆÄÄÄÄÅÅÅÆÆÅÆÅÄÄÅÅÆÅÅÆÆÆÆÆÅÅÅÆÆÅÆÅÅÅÆÆÅÅÅÅÆÆÆÆÆÆÄÄÅÅÅÆÆÄÄÄÄÅÆÆÆÅÄÄÅÅÅÅÆÅÆÅÆÆÅÅÅÅÆÅÆÆÆÆÆÅÄÄÄÄÅÄÅÅÅÅÅÅÅÅÆÆÆÆÆÅÅÅÆÄÄÄÄÄÅÄÅÅÅÅÅÅÅÅÅÅÅÄÅÅÅÅÆÅÆÅÄÄÄÄÅÅÅÅÅÅÆÆÆÆÅÅÅÆÅÅÅÆÅÆÅÆÅÆÆÆÅÆÅÆÆÆ0112233445566778899::;;<<==>ÄÄÄÄÄÄÄÄÄÅÄÆÅÆÆÄÄÄÄÄÄÆÅÆÅÆÅÆÅÆÅÆÆÅÅÆÆÆÆÄÄÅÄÄÄÅÅÆÅÆÅÆÅÆÄÅÅÆÆÆÅÆÅÆÅÅÅÆÆÆÅÅÅÅÆÆÅÆÅÆÅÆÅÆÆÄÄÅÅÆÅÄÄÄÄÅÅÆÅÆÅÄÄÅÄÅÅÅÅÆÅÆÆÅÄÅÅÆÅÆÅÆÆÆÅÄÄÅÄÅÄÄÄÅÅÆÆÆÅÆÆÆÅÆÅÆÄÄÄÅÄÅÄÅÄÅÄÅÄÅÅÅÅÆÅÆÅÄÄÅÅÆÆÆÆÅÄÅÄÅÄÅÅÆÅÆÅÆÆÅÆÅÅÅÅÅÅÅÆÅÆÅÆÆÆÆÆÆÆÆÆÆÆ566778999:;;<===>??@@BBÄÄÄÄÄÄÄÄÄÅÆÄÅÅÆÆÅÅÄÄÄÄÅÄÅÅÆÅÆÆÆÅÅÅÆÆÆÆÆÆÆÆÆÄÄÄÅÅÅÅÆÅÆÆÆÆÆÆÆÄÅÆÆÅÅÅÇÄÅÅÆÅÅÅÆÆÆÆÆÅÅÅÆÆÆÆÆÆÆÄÄÅÅÅÄÄÅÄÅÅÆÆÆÅÅÄÄÄÅÅÅÅÅÅÆÆÆÅÅÅÅÅÆÆÆÆÆÆÄÄÅÅÅÅÅÅÆÅÆÆÆÅÆÅÅÄÄÄÄÄÄÆÄÄÄÄÄÄÅÅÅÅÅÅÅÅÅÅÅÅÆÄÄÅÅÆÆÅÆÅÄÄÅÄÅÅÅÅÅÅÆÆÆÆÄÅÆÅÅÆÅÆÅÆÅÆÆÆÆÆÅÆÅÆÆÆÆ;;<<==>>?YZYZZ[@BBEEÄÄÄÄÄÄÄÄÆÅÆÅÆÅÄÅÆÅÆÅÄÄÅÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÅÆÆÆÆÆÄÄÄÅÄÅÅÅÆÅÅÆÆÆÅÆÆÆÅÆÅÆÇÇÄÁÅÅÅÆÅÅÅÆÅÆÆÆÅÆÅÆÅÆÆÆÄÄÄÅÅÄÄÅÄÅÅÆÅÆÆÆÄÄÄÅÄÅÅÆÅÆÆÆÄÅÅÆÅÆÅÆÅÆÆÆÄÅÄÅÅÆÅÆÅÆÅÆÄÄÄÄÄÄÄÄÄÆÆÄÄÅÅÆÄÅÄÅÄÅÄÅÄÅÅÆÅÆÅÄÄÅÅÆÆÆÆÆÄÄÄÅÄÅÅÆÅÆÅÆÆÄÅÆÅÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆ€€‚‚XXYYYYYYZ@BDFHKMO2ÄÄÄÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÅÆÆÆÆÆÅÆÆÆÆÆÆÆÆÄÄÅÆÄÅÅÅÅÆÅÆÅÆÆÆÆÄÄÄÇÇÄÄÅÄÅÅÆÂÆÆÅÅÆÆÆÅÅÅÆÆÆÆÆÄÄÄÅÅÅÄÄÄÄÅÅÅÆÆÆÄÄÄÅÅÅÅÅÅÆÆÆÅÅÅÅÅÆÅÆÆÆÆÆÆÅÅÅÅÆÅÆÆÆÄÄÄÄÄÄÄÄÄÅÅÆÄÄÅÅÅÆÆÄÄÄÄÅÅÅÅÅÅÅÅÅÅÄÄÅÅÅÆÆÅÆÅÄÄÄÄÅÅÅÅÆÆÆÆÄÅÅÅÆÆÅÆÅÆÆÆÆ††ˆˆŠ‹Æ€‚@BDEHILMO@CEHJMOOÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÆÆÆÆÆÆÆÆÆÆÆÆÆÅÆÅÆÆÄÆÆÆÆÆÅÄÅÅÅÆÅÅÅÅÅÅÆÅÆÆÆÆÅÅÇÄÄÄÄÄÅÅÆÅÆÅÆÅÆÅÆÆÅÅÆÅÆÆÆÆÄÄÅÄÅÄÅÄÄÅÆÅÆÅÆÅÄÄÅÄÅÅÆÅÆÅÆÄÅÅÅÅÆÅÆÅÆÆÆÅÆÄÅÅÆÅÆÆÆÄÄÄÄÄÄÄÅÄÅÅÆÄÅÄÅÅÆÅÆÄÅÄÅÄÅÄÅÄÅÅÅÅÆÄÅÄÅÅÆÆÆÆÄÄÅÄÅÄÅÅÆÅÆÅÄÅÅÅÆÆÆŽ€‚ƒ„…‡‡‰Š‹ŒŽ€€@@AABBCCCDDEEEFFGGHHHIIJJJKKLLMMMNNOOÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÅÄÄÅÅÅÅÆÅÅÅÅÆÅÆÆÄÀÄÄÅÄÄÄÅÅÅÅÆÆÆÆÆÆÆÆÅÅÅÅÆÆÆÆÄÄÄÄÅÅÄÄÅÄÅÅÆÆÆÆÆÄÄÄÅÅÅÅÆÆÆÅÅÅÅÅÆÅÆÅÆÆÆÆÆÅÅÅÆÆÆÅÆÆÄÄÄÄÄÄÅÅÅÅÄÄÄÄÅÅÆÆÆÅÅÄÅÅÅÄÆÆÅÅÅÅÅÄÄÅÅÅÆÆÆÅÆÄÄÄÅÅÅÅÆÆÆÆÄÄÅÅÆÅÆÆ=??012244667899;;==>?@@@AABBBCCCDDDEEFFFFGGHHFEFFGFHGHHIHJIJJKJKKLKLLMLMMNNONOÛÛÛÄÄÄÄÄÄÄÄÄÅÅÆÆÅÆÆÆÆÄÆÅÄÅÄÄÄÅÄÅÅÆÆÆÅÆÆÆÅÆÆÅÅÆÅÆÅÆÄÄÄÅÅÆÄÄÄÅÄÅÅÆÅÆÄÅÄÅÅÅÅÆÅÆÆÅÅÅÅÅÅÆÅÆÆÆÆÆÆÅÄÅÅÆÆÆÅÄÄÄÄÅÄÅÅÆÅÆÄÅÄÅÅÆÅÆÆÆÅÆÅÆÅÄÅÆÅÆÄÅÆÄÄÅÅÆÅÆÆÆÆÄÄÅÄÅÅÆÅÆÆÄÄÅÅÆÅÆÆÆb7c89:::fd6778899:::>>>>??A@?B?AA@ABABCCDBDEFFGGHHFFFFGGHHHHIIJJJJKKLLLMMMNNNOOÄÄÄÄÄÅÅÅÅÅÅÆÆÆÆÆÅÆÄÄÄÄÄÄÄÅÄÅÄÅÅÆÅÆÅÆÆÆÆÛÛÛÛÛÛÛÛÛÄÄÄÅÅÅÄÄÄÄÅÅÅÅÅÆÆÄÄÅÅÅÅÅÅÆÆÅÅÅÅÅÅÆÅÆÆÆÆÆÆÆÅÅÅÆÆÆÆÄÄÄÄÅÅÅÅÆÆÆÄÄÄÅÅÅÅÆÆÆÅÅÅÅÅÄÅÅÆÅÄÅÅÅÆÆÅÅÅÆÆÆÆÆÄÄÄÅÅÅÅÆÆÄÄÅÅÆÅÆÆÆÆ2425556779fd6778899:::::=>==>>>>>@>?ABAABCCCDCDFFFFGGHHEEFFGGHHIIJJKKLLMMNNOOOÄÄÄÅÄÅÄÅÅÆÅÆÅÆÆÆÅÆÆÄÄÅÄÅÄÅÅÅÅÅÅÅÅÅÅÆÅÆÆÆÆÅÛÛÛÛÛÛÄÄÄÄÄÅÅÄÄÄÄÅÅÆÅÆÆÆÄÅÄÅÄÅÅÆÅÆÄÅÅÅÅÆÅÆÅÆÆÆÅÆÆÅÅÆÆÆÄÅÄÄÅÆÅÄÄÅÅÆÆÄÄÅÄÅÅÆÅÆÆÆÅÆÅÄÄÆÆÆÄÅÄÅÅÆÆÅÅÆÅÆÆÆÅÆÄÅÄÅÅÆÅÆÄÅÄÆÅÆÆÆÆÆ/deeeeeeefd67fd67787899:::::=====>>>??????@?A?ABDDEEF@FFGGHH@ABCDEFFHHIJKLMNOÄÄÄÅÅÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÄÄÄÅÅÅÅÅÆÅÆÆÆÆÆÆÆÆÆÆÆÄÄÄÄÛÛÛÛÆÆÆÄÄÄÄÅÅÅÅÆÆÆÆÄÄÄÄÅÅÅÅÆÆÅÅÅÅÅÅÆÆÆÆÆÆÆÄÅÅÆÆÆÆÄÄÄÄÆÅÄÄÅÅÆÆÆÄÄÄÅÅÅÅÆÆÆÅÅÅÄÅÆÅÆÅÄÄÅÅÅÅÆÅÅÅÆÆÆÅÆÆÄÄÅÅÅÆÆÄÄÄÅÅÆÅÆÅÆÆdde/ed/dddedfe/ffeecc6fc88f8f99=:::=======??????@=@=ACDCDEEFFFFGGHHKIHL@NLMÄÄÄÄÅÄÅÄÅÅÆÅÆÅÆÅÆÆÆÅÆÄÅÄÅÄÅÄÅÅÅÅÆÅÅÅÅÆÆÆÆÆÆÅÆÆÆÅÅÅÄÛÛÛÛÛÛÛÛÛÆÄÅÅÆÆÆÅÆÄÅÄÅÅÆÅÆÄÅÄÅÅÆÅÆÅÆÅÆÆÆÄÅÅÆÆÆÆÄÄÄÄÄÅÄÄÅÅÆÅÆÄÄÄÅÄÅÅÆÅÆÅÆÅÄÅÆÅÆÄÅÄÅÅÆÅÆÆÆÅÆÅÆÆÆÆÆÄÅÅÆÅÆÅÄÄÅÄÆÅÅÅÆÆÆd//e/ee/ed/dddedfe/ffeecc6fc88f889:9::<<<========>????=A=D=EEFFFFGGHHEJDFÄÄÄÄÄÅÅÅÅÅÅÆÅÆÆÆÆÆÆÆÆÄÄÄÄÅÄÅÅÅÅÅÅÅÅÆÅÆÆÅÅÅÅÄÆÆÆÆÅÆÅÅÅÄÄÄÄÄÄÛÛÛÛÛÛÛÛÛÛÛÛÛÛÅÅÆÆÆÆÄÄÅÄÅÅÅÅÆÆÆÆÆÆÆÄÅÆÆÆÆÄÄÄÄÅÆÄÄÅÅÅÆÆÆÄÄÄÅÅÅÅÆÆÆÅÄÅÆÅÄÄÅÄÅÅÅÅÆÆÆÅÆÅÆÆÆÅÆÆÄÅÅÅÆÆÆÄÄÄÅÅÅÅÆÆÆÆc/dddddde/ed/dddedfe/ffeecc6fc88ff888::9:9>99e:==>==>>>>?>??@@@^]@_B\AHÄÄÄÄÅÄÅÅÅÅÆÅÆÅÆÅÆÆÆÅÆ‚ÄÄÅÄÄÄÅÄÅÅÆÅÆÅÆÅÆÆÆÄÅÆÅÅÅÅÅÅÅÅÆÅÆÅÆÅÆÅÆÄÄÄÄÄÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÆÆÆÄÄÅÅÆÆÆÆÆÄÄÄÄÄÄÄÄÄÅÅÆÆÆÅÄÄÅÄÅÅÆÅÆÄÅÅÆÅÄÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÆÆÅÆÄÅÅÆÆÄÄÅÄÅÅÅÅÆÆÆÆÆcdddeeee/ed/dddedfe/ffeecc6fc88f778899:::<=:===>>>??>?=>>?>Z>^[Z^[^\]]ÄÄÄÄÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆ€ÄÄÄÄÅÅÅÅÅÅÅÅÆÆÆÆÆÄÄÅÅÅÅÅÅÄÄÅÅÆÆÅÆÅÆÅÆÆÆÆÆÆÆÆÆÅÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÄÅÅÆÆÆÄÅÅÆÆÆÆÆÄÄÅÅÅÆÆÆÄÅÅÆÆÄÄÄÄÅÅÅÅÆÆÆÆÆÅÆÅÆÆÆÅÆÆÆÄÆÆÆÄÄÄÅÄÅÅÆÅÆÆÆÆcccdde/ed/dddedfe/ffeecc6fc88f778897:9:=:<=>==>>??>>>>>?>[[\Z\\[\]]^€‚‚ƒ„††ˆˆŠŠŒŽ€Ž‡ŠŒˆÄÄÄÄÅÄÅÅÅÅÆÅÆÅÆÄÅÅÅÅÅÅÄÄÅÄÅÄÆÄÅÅÆÅÆÅÆÅÆÅÆÆÆÅÆÆÆÅÜÜÜÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÅÄÅÅÆÅÆÄÅÆÆÅÆÅÄÄÆÆÆÄÅÄÅÅÆÅÆÄÅÄÅÄÅÅÆÅÆÅÆÅÆÅÆÆÆÆÆÅÆÅÆÅÆÄÆÄÅÄÅÅÆÅÆÆÆÆÆd/dddedfe/ffeecc6fc88ffd6778899:::<<<=====>>>ÄÄÄÄÄ?<==>>\>\\]\^^^^€‚‚ƒ„…†‡‡ˆ‰Š‹ŒŽFGGHHIˆÄˆÅÄÅÅÅÅÅÅÆÅÆÆÅÅÅÄÅÅÅÅÄÄÄÄÄÄÅÅÅÅÆÆÆÆÆÅÆÅÆÆÆÆÆÆÆÆÆÆÆÞÝÝÝÝÝÝÜÜÜÜÜÜÜÜÜÜÜÜÜÛÛÛÛÛÛÛÛÄÄÄÅÅÅÅÅÅÆÆÆÅÆÅÆÅÆÆÆÅÆÅÆÄÅÅÅÅÆÄÄÄÅÅÅÅÅÅÆÆÆÅÅÅÆÆÆÆÆÅÆÆÆÅÆÅÄÆÄÄÅÅÅÅÆÅÆÆÆÆ787889899c9:9:9::;:;:;;;;<;<<=<=<===<==???ÄÄÄÄÄÄÅÆÆÆ=>>???]\]]^^]^^^__^_@AABBCCDDEEFFGGHˆˆˆÅÄˆÄÆÅÆÅÆÅÆÅÆÄÄÄÅÄÅÅÅÅÄÅÆÄÅÄÅÅÆÅÆÅÆÅÆÆÆÅÆÅÆÅÆÅÆÆÆÆÆÆÆÞÞÞÞÞÞÝÞÝÝÝÝÜÝÜÝÜÜÜÜÜÜÜÜÛÄÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÅÆÅÆÅÆÅÄÄÅÅÆÆÅÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÅÆÆÆÅÆÆÆÅÄÅÆÄÅÄÅÅÆÅÆÆÆÆÆ9999:9::::;d;;;;;;<<<<<<=<======>>>>>???ÄÄÄÅÅÆÅÅÆÆÆÆÆÆ\>?\]\]]^^^^@^A@BACBCCDDDDEEEFGGG‡ˆˆˆˆˆÆÅÆÆÆÆÆÆÄÄÄÄÄÄÄÅÅÅÅÅÅÆÆÆÅÅÅÆÅÆÆÆÆÆÅÆÅÆÅÆÆÆÅÆÆÆÆÆÆÆÆÆÆÆÞÞÞÞÞÞÞÞÝÝÝÝÝÝÝÝÜÝÜÜÜÄÄÄÄÅÅÅÅÆÆÆÆÆÆÆÅÆÆÆÅÆÆÆÅÆÆÄÄÅÅÆÄÅÅÅÅÅÅÅÅÆÆÆÅÆÅÆÅÆÆÆÅÆÆÆÅÆÄÅÆÄÄÅÅÅÅÆÆÆÆÆÆ:::;:;:;;<;<;<<<<=<=<=====>=>>>??>>????ÄÅÆÆÆÆÆÅÆÆÆÆÆÆÆ\]]\^^@BAB@BABCCCDDCCDDDDEEFFFGGG‡‰ŠŒŒŽŽ€ÄŒŒŒŽŽÆÅÆÆÆÅÆÆÆÅÆÅÆÅÆÆÆÆÅÅÆÅÆÅÆÅÆÆÆÅÆÅÆÅÆÆÆÅÆÆAABÙÞÞÞÞÞÝÝÝÝÜÝÜÝÜÄÄÅÄÅÄÅÄÅÅÆÅÆÆÆÅÆÅÆÅÆÅÆÅÆÅÆÄÅÅÆÄÅÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÆÆÆÆÅÆÆÆÅÄÅÆÄÅÄÅÅÆÅÆÆÆÆÆ;;;;<<<<<<<<========>>>>>=>>>>>>?0???5?Å€€ÆÆÆÆÆÆÆÆÆÆÆ„„]^^\]@A]DBBDCCDDDDFDDEEEFFFFGGHHIIIIŠŠŠŠ‹‹‹‹ŒŒŒŒŽŽŽÆÆÆÆÆÆÆÆÆÆÆÆÅÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆBBÙNÙÙÞÞÞÝÝÝÝÜÝÜÜÆÄÄÄÄÅÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÄÄÅÆÅÅÅÅÅÅÅÅÆÆÆÆÅÅÅÅÆÆÆÆÆÅÆÆÆÆÄÅÅÆÄÄÅÅÅÅÆÅÆÆÆÆ<=<=<====>=>=>=>>>>?>>>>>>?>?>=><=?X???€€€ƒƒ„„„„………\AA]B@B\@C@ECEFFFFFEFFEEFFGFHGHHIIJIJJKKLKLLMMNMNNOOO@O@@@A@BABBCCD„„„„……††‡‡ÆˆÆÆÆÆÅÆÆÆÆÆÆÆÆÆÆÆÆÆMÙMÙMÙÞÞÞÝÝÝÜÜÛÛÛÆÄÅÄÅÄÅÅÆÅÆÅÆÅÆÅÆÅÆÅÆÅÄÄÄÅÆÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÅÆÅÆÆÆÅÆÆÆÄÅÅÆÄÅÄÅÅÆÅÅÆÅÆÆ>=>>>>>>>>??????<<===?==>>>?>>>=>>;=XXXXY;>Y?YYC[AAB\D\ABDACBDCDADCDDDFFGFGFFGGFGGGGHHHHIIJJJJKKLLLLMMMMNNNNOOO@O@@@AAAABBCCDDDDEFFFGGHHIIIIJJKKLLLLLLLMMMÙMÙÙÙÞÞÝÝÝÝÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÆÆÆÆÆÆÆÆÄÄÄÄÄÄÆÅÅÅÅÅÅÆÆÆÆÆÆÅÅÆÅÆÅÆÆÆÅÆÆÆÆÄÅÅÆÄÄÅÅÆÆÆÆÆÆÆÆ>?>>?>>?>?>>>=?===?=>=?=??>>=>==>X??Y>Y=ZZA@ZBC@CCCBDCDEBDEECDFDEFEGGHHGHHGHGHHIHIIJIJKJJKKLKLLMLMMNNONOOOOO@O@@@AABBCBCCDDEEFEFFGGHHIHIIJJKKLLLÙÙÙÙÙÙÙÙÞÞÝÝÝÝÜÝÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÅÄÆÄÅÅÆÅÆÅÆÅÆÆÆÅÆÅÆÅÆÆÆÅÆÆÆÆÄÄÁÄÁÄÅÅÆÇÇÇÁÁÆÆÆ>?===??>>?>>>==<=====>=?==???>:>:=>YXW>VX@ZZ@BABCDDCBCDDDDEEFEDEFEFEEFFGIJHHJHIHIIIIIIJKKJKKKKLLLLMMMMNNNNOOOOOOO@@@@@AÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÝÝÝÝÝÝÝÜÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÅÅÅÅÅÅÅÅÆÆÆÆÆÆÅÅÅÅÅÅÆÆÆÆÅÅÆÆÇÇÇÇÇÁÇÄÁÇÁÁÁÁÇÇÇÇ>?SSR=>?R>???=STT>>>>>>>?>>>??>>>>>U>=>VWXYABCDCCEDEDEFEFEFFFGGFGGGGHHGIHIHJJJJJJJJKJKKJLKKKLLLMLMLMMNMNNONONOOO@O@AÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÙÙÙÝÙÝÙÝÙÝÝÝÝÜÝÜÝÜÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÅÄÅÅÆÅÆÆÆÆÆÅÆÆÄÄÅÄÅÅÆÅÆÆÆÆÆÆÇÇÁÄÁÁÁÁÁÁÂÁÇÇÇÁÁÁÁQQ@??RR>RR@>RSR<>S=>@>?B>@=>U>V?VUVWW@ACDCEDDEEEFFFHFGGGGHHIHIHIHIHJIJJIKKKKJKJJKJLLKLLKLLLLMMMMNNNNONOOOOO@O@AABÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÜÜÜÜÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÆÄÄÆÆÆÆÆÆÆÇÄÄÄÄÁÁÁÂÁÂÄÇÇÁÁÁÁÁÁÁ@Q@QARRAR@S?ASSBSSS>@TSCACB?C@@UAVAWAEVEBCEEFFFGFFFGGHGHIHJIJJIIIJIJIJKJJJKKJLKLKLKJKKLMKLLLLMLMMNMNNNNONONOOO@O@@@AABCCÚÚÚÚÚÚÚÚÚÙÚÙÚÙÙÙÙÝÙÝÙÝÝÝÝÝÝÜÝÜÝÜÝÜÜÜÜÛÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÆÇÄÄÁÄÁÄÁÂÁÂÇÇÄÄÁÁÁÁÂÁÂAAARAARRBBCCSDTCBATS@AEECDDDDDEFBECCGFGGGGGHHGGGGGGHIHJKJJJJJKJKJJJJJKKJKJKLKKLKKLKKLKLMLLMMMMMMNMNNNNONOOOOO@O@@@@@AAABCCDÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÜÜÜÜÜÛÜÜÜÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÇÄÄÄÄÁÁÁÁÂÂÇÄÄÄÁÁÂÁÂÁÂÁBA@BBA@AABDDEDEDDEDCCEGCFFEGFFGHGFEIFGHGHHHHHHHIIIIIJJJJKJJKJKKJKKKKKJKKKKKKKLLKLMLMLLLLLMLMMNMNMNNONONONOOO@OO@@ABBCCDEÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÝÝÝÝÝÜÝÜÝÜÜÜÜÛÜÛÜÛÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÇÄÄÄÄÁÄÁÂÂÂÇÄÄÄÁÄÂÁÂÁÂÂÂABABBCCDCCDEDDDEDEFGHGGFHFHGIGFGGGHHIHIHHHIHIIIJHIIIJKIJJKKKKKLKKLKKKKKKLLKLKLKLLLMLLMMLMMMMNNNNNNNNOOOOOO@O@@@AABCCDDÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÝÝÝÝÝÝÝÝÜÝÜÜÜÜÜÜÜÜÜÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÁÄÄÄÁÂÁÂÄÄÄÄÁÁÂÁÂÂÂÂÁÂCCBCCCCCCDDDEDEEFEEFHGHHHGHGIHGHHIIJIGJIIIIIIIJIJIJKJJJJJJJKKKKKLKKLLKKLKMLLKLMLLLLMMLMMMNMNNNNNNONOOOOO@O@O@@@AABBCDDEÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÝÙÝÙÝÝÝÝÜÝÜÝÜÝÜÝÜÜÜÜÛÜÛÜÛÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÁÄÂÄÂÂÁÂÂÇÄÄÁÄÂÁÂÁÂÁÂÂÂCCCCCCDCCDDDEEEEGEFGFGHGHHHIIHIIIHJHIHIJJJJIIIJJIKJJJJJJJJJKKKKKKKKLLLLLMMLMLLMLNMLMLMNMNNNNNNOOOOOOOOO@@@@@@@AABBCCDDEOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÝÝÝÝÝÝÝÝÝÝÜÜÜÜÜÜÜÜÜÜÛÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÁÄÂÄÂÁÂÂÂÄÁÄÄÄÂÁÂÂÂÂÂÅÂÂCCCDDDDDDEEEDEEEFEEFGGGHHHHIIHIIIIJIJIJJJJJIJIJKJKIJKKJJJKJKLKLKKKLLMLMLMMMMLMNMNMMMNNMNNONONOOOOO@O@O@O@@@A@AABBCCDDEEFOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÝÝÝÜÝÜÝÜÝÜÝÜÜÜÜÛÜÛÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÁÄÂÁÂÁÂÁÂÄÁÄÁÄÂÁÂÁÂÁÂÅÂÅÂDDCCEEFEEFEFEFFFFGGGGFFGHHIHGIHIJIIJIJJJKKJJKJJKJKJKKKKKKKJKLKLLLLLLMLMMMMMMMNMNNNNNNNNNOOOOOOOOOO@@@@@@@@AAAABBBBBBCCDDEEFFÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÜÝÜÜÜÜÜÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÄÂÁÂÂÂÂÂÄÁÁÄÄÁÁÂÂÅÅÅÅÅÅÅÅGHFFGEGFFGGGGFGHGGHGHHGHGGFHHIIHIIIIJJJJJJJKJKKKKJKKKKKLLKKLKKLLLMLMLMLMMNMNMNMNNONONONOOO@O@O@O@O@@@@@AAAABBCCDDEEFFGGHÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÝÙÝÙÝÙÝÙÝÝÝÝÜÝÜÝÜÝÜÝÜÜÛÜÛÜÛÜÛÛÛÜÛÛÛÜÛÛÛÜÛÛÛÜÛÄÄÁÄÂÁÂÁÂÂÄÄÄÄÅÄÂÂÂÂÅÅÆÅÆÅÆÅÆHHGGGHGIGGIHHHHHHIHHHHIIGHIGHIHIIIIIJIJJJJJJKJKKKKKKKKLLLLLLLLMMMMMMMMNMNNNNNNONOOOOOOOOOO@O@@@@@@@AAAABABBBBCCCCDDDEEFFFGGHÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÜÜÜÜÜÜÜÜÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÄÂÁÂÁÂÂÄÄÄÄÄÄÅÅÅÅÅÅÅÅÆÅÆÆÆÆJJHGIJHIIHIIIIIHHHHHHJJIIIIJJJIJJJKJKKJKJKJKKLKLKLKLLLLMLMLMLMMNMNMNMNNONONONOOOOOOO@O@O@O@O@@@@@AABBBCBCBCCDCDDEDEEFEFFGGHHIÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÜÝÜÝÜÝÜÜÜÝÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÜÛÄÄÄÄÅÄÂÄÂÂÂÅÄÄÅÄÅÄÅÄÅÅÆÅÆÅÆÅÆÅÆhLHIJJJIKJIJIJIJJJJJJJJJJKJKJKKKKKKKKKKKKKLKLLLLLLLLMMMMMMMMNMNMNNNNNNNNOOOOOOOOOOO@O@@@@@@@@@@@AAAABBBCCCDDDEEFFGGGHHHÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÜÜÜÜÜÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÄÄÄÄÅÄÅÅÂÂÂÂÄÄÄÄÅÅÅÅÅÅÅÅÆÅÆÆÆÆÆÆnhhJKLJKKKKKJKKJJJJKKLLKKKKKKLLKKKKLLLKLKLLMLMLMLMLMMNMNMNMNNNNNNONONONOOO@O@O@O@O@OO@@@@AAABBCCCDCDCDDEDEDEFFGGHHHIIÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÜÝÜÝÜÜÜÜÛÝÛÜÛÜÛÜÛÜÛÜÛÜÄÄÄÅÄÂÅÂÂÆÅÄÄÅÄÅÄÅÄÅÅÆÅÆÅÆÅÆÅÆÅÆohohLLLLKLLLKKLKLLKKLLLLLMLMLLLLLMMMMMMMMMMMMMMMMMNMNMNNNNNNNNOOOOOOOOOO@O@O@@@@@@@@@AAABBBCCCCCCDDDDEEEEFFFFFFGGGGHHINOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÙÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÜÝÜÜÜÜÜÜÛÛÛÛÛÛÛÛÛÛÄÄÅÅÄÅÂÄÅÆÄÄÄÄÄÅÄÅÅÅÅÅÅÆÅÆÆÆÆÆÆÆÆhjhjjKKLLLKLLLLLMMLLLMMMMLLMLMLMMMMMMMMMMMMNMNMNMNMNNNNONONONOOOOO@O@O@O@O@O@@@@@@@A@AAABBBCCDDDEEEFFGGGHHHIINNOOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÜÜÜÜÄÄÄÄÄÄÄÄÄÅÄÅÂÅÆÄÅÄÅÄÅÄÅÄÅÅÆÅÆÅÆÅÆÅÆÆÆÆÆoohjjLLKKLLMLLLLMLLLLLMMMMMMMMMMMMMMMMMMMMNMNNNNNNNNOOOOOOOOOOOO@O@@@@@@@@@@@AAABBBBCCCDDDEEFFFFGGHHHIIINOOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÜÜÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÅÄÄÂÂÆÄÄÄÄÄÅÄÅÅÅÅÅÅÆÅÆÅÆÆÆÆÆÆÆÆjhkkjjKLLLLLMMMMLMLMLMNMMNNMNMNMNNMMNNMMNNMNNONONONOOOOOOO@O@O@O@O@O@O@@@@@A@AABBBCBCBCCDCDDDDEEEFFFGGGHHHIIIJJJÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÙÝÙÝÝÄÄÄÄÄÄÄÄÄÄÄÅÅÄÄÅÄÅÅÆÅÆÆÅÅÄÄÄÄÅÅÂÅÆÄÄÄÅÄÅÄÅÄÅÅÆÅÆÅÆÅÆÆÆÅÆÆÆÆÆlhkjjjjLLLLLLLMMMMMMMMMMMNMNMNNNNNNNNNNNNNONOOOOOOOOOOOOO@O@O@@@@@@@@@@@@@AAAAABBBBBBCCCCCDDDEEEEEFFFGGGHHHIIIIJJÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÝÙÝÝÝÝÝÄÄÄÄÅÅÅÅÅÅÅÅÄÄÄÄÅÅÅÅÅÅÆÆÆÄÄÄÅÅÅÅÂÆÆÄÄÄÄÄÅÄÅÅÅÅÅÅÅÅÆÆÆÆÆÅÆÅÆÆÆÆlhkkjjjLLLLMMLMLMLMMMMNNMMNNMNMNMNNONONONOOOOOOO@O@O@O@O@O@O@@@@@AAAABABBBCCCDDDEEEFFFFGGMMMNIIIJJJÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÙÝÝÄÄÄÄÄÅÄÄÄÅÄÅÄÅÄÄÄÅÄÅÄÅÅÆÅÄÄÅÄÅÄÅÅÆÅÆÆÄÄÅÄÅÄÅÄÅÅÅÅÆÅÆÅÆÅÆÆÆÆÄÆÆÆÆhkkkkjjjLLLMMMMMMMMMMMMMNNNNNNNNONONOOOOOOOOOOOOOOOOO@O@O@O@O@O@O@@@AAAABBBBBBBBCCCDDDDEEEFFFGGGGNNNOOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÝÙÝÝÝÝÝÄÄÄÄÅÄÄÄÄÄÅÄÄÄÅÅÄÄÄÄÅÄÄÄÄÄÅÅÅÅÅÅÅÅÆÆÆÆÄÄÄÄÅÄÅÄÅÅÅÅÅÅÆÅÆÆÆÆÆÆÆÆÆÆÆÆklkkjkjjjLMMMMMMMNMNMNMNNONONONOOOOOOO@OOOOOOOOO@@@AABBBBCCCCDDDEEEFFFFGGGHHHCIOÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÙÙÙÝÙÝÙÝÝÄÄÄÄÄÅÄÄÄÅÄÅÄÅÄÅÆÅÄÄÄÅÄÅÄÅÄÅÅÅÅÅÅÆÅÆÅÆÅÆÄÄÄÄÄÅÄÅÅÅÅÅÅÆÅÆÆÆÆÆÆÆÆÆÆÆÄÄkkkkkjjjjMMMMMNNNNNNNNNNONOOOOOOOOOOOOO@@@@@AAAAAAABBBBCCCDDDDEEEFGGGGHHHIÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÙÙÝÝÝÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÅÆÆÄÄÄÄÄÄÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÆÆÆÄÄÄÄÅÅÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆÄÄÄÄÄÄjkkkjkjkjjMNMNNNNONONONONOOOOO@O@OOOO@@AAAABBEFGHIJKMNOGGGGHHHIÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÝÙÝÙÝÝÄÄÆÆÆÆÄÆÅÆÅÆÅÆÅÆÆÄÄÅÄÅÄÅÄÅÄÅÅÅÅÅÅÆÅÆÅÆÅÆÅÆÆÆÄÅÄÅÄÅÄÅÅÆÅÆÅÆÅÆÆÆÅÆÅÆÄÄÄÄÄÅÅÅkkkkkjjkjjNNNNNNOOOOOOOOOOO@@@@@AAAAAAHIKMOCHÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÝÙÝÝÝÝÄÆÆÆÆÆÄÄÅÅÅÆÅÆÅÆÆÄÄÄÄÄÄÅÅÅÄÅÅÅÅÅÅÅÅÆÅÆÅÆÆÆÆÆÆÆÄÅÅÅÅÅÅÅÅÆÆÆÆÆÅÆÅÆÆÄÄÄÄÅÅÅÅÅÅjkjkkkjkjjjONONOOOOOO@OO@@AAAABBBBBCCCDFFFGGGÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÙÙÙÝÙÝÙÝÙÝÙÝÝÝÝÝÄÅÆÅÆÅÆÅÆÅÄÄÄÄÅÄÅÄÅÄÅÅÅÅÅÅÆÅÆÅÆÅÆÅÆÅÆÆÆÆÅÄÅÄÅÅÆÅÆÅÆÆÆÅÆÅÆÅÄÄÄÄÅÅÆÅÆÅÆjjjkkjjjjjjjOOOOOOOOO@@BGKO@AAAABBBBCCCCDDDEEÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÄÄÅÄÅÄÅÅÅÅÅÅÅÅÆÅÆÅÆÆÆÆÆÆÅÅÅÅÅÅÆÆÆÅÅÅÅÅÅÅÆÅÆÆÄÄÄÆÅÅÅÅÅÅÆÅkljkkkjkjjjjOOOOOOO@@@@AAAABBBBCCCÚÚÚÚDÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÄÅÄÅÄÅÄÅÅÆÅÆÅÆÅÆÅÆÅÆÆÅÄÅÅÆÅÆÅÆÅÆÆÆÅÆÅÆÅÆÅÆÄÄÆÅÅÆÅÆÅÆÅÆkkkjkkkjkjjjjOO@@@@@@@AAAABBBBCÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÝÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÆÆÅÅÅÅÅÅÅÆÆÆÅÆÆÆÆÆÅÅÅÆÆÆÄÄÆÅÅÅÅÆÅÆÅÆÆklkjjkjkjkjjjjOO@O@@AAAABBBBCÚCCDDÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÙÝÝÝÙÝÝÝÝÝÝÅÆÅÆÆÆÅÅÅÆÅÆÅÆÅÆÅÆÅÆÆÆÆÆÅÆÅÆÅÆÄÄÄÅÄÅÅÆÅÆÆÆÅÆkkkjkjkjjjjjjj@@@@@AAAABBBBCÚÚÚÚÚÚÚEEÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÜÆÆÆÆÆÆÆÆÆÆÆÆÄÄÄÄÄÅÅÅÅÅÆÆÆÆÆÆkkkkjkjkjkjkjjj@@AAAABBBBÚÚÚÚDÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÜÜÜÜÜÜÜÆÆÅÄÄÄÄÅÄÅÅÆÅÆÆÆÅÆÆÆlkkkjjjjkkkjjjjAAAABBBBCCÚÚDÚDDEEÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÄÄÄÅÆÄÅÄÅÅÆÆÆÆÆÆÅÆklkkjjjkjkkkjkjjBBBBCCCÚDDDDDÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÙÙÚÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÄÄÄÅÅÆÄÅÅÅÅÆÅÆÅÆÅÆÆÆklkkjjkkjkkjjjjjjBBBCCCCCÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÄÄÄÅÆÆÆÄÅÅÅÅÅÅÆÆÆÅÆÆÆÅklkljkjkkkkkjkjjjjCCjCCDCDCDDEÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÄÄÅÅÆÅÆÆÅÄÅÄÅÅÄÅÆÆÆÆÆÆÆkllkjjjjkjkjkjjjjjCCCDDÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÜÜÜÝÜÜÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÄÅÅÅÅÆÆÆÄÄÄÅÄÄÄÅÆÆÆÆÆÆÅkllljkjkkkkkjkjjjjjDDDDDÚEEDEEFEÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÄÅÄÅÅÆÅÆÅÆÅÆÄÅÄÅÄÆÅÆÆÆÅÆkllkkjkjkjlkkjjjjjjjDDDEEÚÚÚÚÚFÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÅÆÆÆÅÆÅÆÄÄÄÅÅÅÅÆÅÆÆÆÅjlklkljkjllkjkjkjjjjEEÚÚÚFEFÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÆÅÆÅÄÄÅÄÅÄÅÅÆÅÆÆÅlllklkkjjklkkkjjjjjjjEEÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÝÝÜÝÜÜÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÄÄÅÅÅÅÆÅÆÆÆÆllklklkljjkljkjkjkjjjjEÚEFEFFFFGÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÙÝÝÜÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÆÅÆÅÆÅÆkllllklkkjjlkkkjjjjjjjÚFFFGGÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜhhhhhhhlkljljkjkjkjkjjjFÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝhhhhhhhhlkkjlkkjkjjjjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜÝÜÜÜoomhjklhhlkkjkjkjkjkjkjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝnnnnhjklhhkkkkkkkjkjjjjjjGHGÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜnnnonhjkkhhhkkkkjkjkjkjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÙÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝnnnnohjkllhhkkkkkkkjjjjjjjÚÚHÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÝÝÜÝÜÝÜÝÜÝÜnonnnhjkkhhhhjkkkkjkjkjjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝnonnnhjklhhhjljkkkkkkjkjjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÙÝÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝnooohjjllhhhjjjlkkkkjjjjjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝooonhjklhhhkkjjjkkkkkkjjkjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜnooononjlhkkjkjkjjkkjkjjjjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝoonnnnonjkkjkjjjjkjlkkkjkkjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝnononohomlkkjkjjjjkjlkjjjkjkjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝÜÝnnnnohomllkkkjkjjjkjlkkjkkljjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝnonohomlklkkjkjkjjjljkjjjkkkjkjjÚÚÚÚÚÚÚÙÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝÝÝÜÝnnhhojlllkkkkjjjkkjjjkkjjkkjjjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝnhjlhmllklkkjkjkjkkjkjkjjkkjjkjjjÚÚÚÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÜÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝjkmhmklllkkkkkjjjkkjjkkkjkjkjkjjjjÚÚÚÚÚÚÚÚÚÚÚÚÚÙÚÚÚÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝkljhhlklllklkkjjjlkjjjkkjjjkkkjjjjjÚÚÚÞÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝlhhhjhlklllkkklkkjkjjjkkkjkkkjkjjjjÚÚÚÚÚÚÚÚÚÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝhnnhjkkllhhlklkkjjjkjjjlkkjkkjjkjkjjhhhhhÚÚÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÚÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÞÞÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝoomhjjkkllhhhllkkjjjkkjjkkkjljljjjjjjhhhhhhhhhhhÚÙÚÙÚÙÚÙÙÙÙÙÙÝÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÙÝÙÝÝÝÞÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝmnmhjkjkkllhhhhkjkjkkkjjklkkjjkkjkjjjhhhhhhhhhhhjhÙÚÙÙÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÞÞÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝnnhjjjkkllllhhhhhjjjkkkjjkkkkjljkjjjjjhhhhhhhhhjklhÙÚÙÚÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÙÝÞÝÙÝÙÝÞÝÞÝÞÝÞÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝnhjkjkklkllhlhhhhkjkjkkjjjjlkjlkjkjkjjjhhhhhjhjkkhhjÙÚÙÙÙÙÙÙÙÙÙÙÙÙÝÙÝÙÝÙÝÝÝÝÝÙÝÝÝÝÝÝÝÝÝÝÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞnnhjkkkkllllhhhhlkjjkkkjjjjlkjljkkjjkjjjhhhjhhhjklhjjÙÚÙÙÙÙÙÙÝÙÝÙÝÙÝÙÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÝÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝnonhhjjkkllhhhhjlkjjjkjkjjjjkjkkjkjjjkjjhhhhhhhjkhjjjÚÙÚÙÚÙÙÙÙÙÙÙÙÙÞÝÙÝÙÝÝÝÞÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞnnnhjjkkllhhhhkkkljjjkkkjjjkkkjlkkkjjkkkjhhhhhjkhjkjjjÚÙÙÙÙÙÙÝÙÝÝÝÙÙÙÝÞÝÙÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÝÝÝÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝÝÝÞÝÝÝÝÝnonohhhhjkkhhhklkklkjkkkjjjjkljlkkjkjjjkjjhhhhjhjkkkjjjÚÙÙÙÙÙÙÙÙÙÙÞÙÞÝÝÞÝÝÝÝÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞonnnooonhjlhhlkkkkljjjkjjjjjjkjlkkkjjkjkkjhjklhjjjkkjjjjÚÙÝÝÙÙÙÝÙÙÙÝÙÞÙÝÞÝÞÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝÞÝÝÝnonononohjklhhklklklkkjkjkjjjljlkkjkjjkkkhjklhkjjkjkjkjjjÙÝÙÙÙÙÙÝÞÝÞÝÙÝÝÝÝÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞnnononohjjklhhlkkkkkkkkjjjjjjjlkkkkkkjkkhjjkhlkjjjkkkjjjjjÙÝÙÝÙÝÙÝÙÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝnononohhjkkllhklklkklkjkjkjkjjjljlkkjkjjkhjhllkkjkjkjkjkjjÝÙÝÙÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞononoohjkkllhhjklkkkkkkjkjjjjjjkjklkkjkklhhkllkkkjkkkjjjjjjÝÙÙÞÝÞÙÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝnononohjjkkllhjjklkkkkjkjkjkjjjjkljkkjklhkklklkkjkjkjkjkjkjjÝÙÝÙÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞonooohjjkkllhhjjlklkkkkkkjkjjjjjjkkkkjklhllllkkkkjjkkkkjjjjjjÝÙÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞnonohjjkkllhhhjjjlklkkkkjkjkjkjjjlklkkhkllklklklkkkkjkjkjkjkjjÝÙÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞooonhjlmlhnlhhhjjjlklkkkkkkjkjjkjjlkkkkllllllllklkjlkkkjjjjjjjkÝÞÙÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝnonononojnlhhohkjjklklkkkkjkjjjkkjjlklllllllllklkljklkjjjkjkjkjkÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞonoooooojklhhhkjjjjklkkkkkkkkjkkkjjjlllllllllllllkjklkjjkkkjjjkkÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞnmnonononjjnhkjkjkjjklklkkjkjjjkkjjjllllllllllklklkjkkjjjkjkjkjkjÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞÝÞmoooooojklhnkkkjkjjjlkkkkkkkkjjjkkjjlllllllllllllllkkkjjkkkjjjjjkkÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞnononojklhnkkkjjkkjjjlklkljkkjjkkkjjjlllllllllllllklklkjjkkkjjjkjkkÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞÞÞÝÞoooooojklhnkkkjjkkkjjjlkkkjjkjjjkkjjjjlllllllllllllllkkjjjkkkjjjkkkjÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞnononjklhnklkkjkjkkkjjklklkkjkjkjkjjkjllllllllllllklklkjkjjkjjjkkkkjjÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞooooojklmnlkkkjjkkkjjjjklkkkkkkjkkjjkkjlllhhhhlllllllllkjjjjkkjjkkjjjÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞnonoommmllklklkkjjjkkkjlklkkkkjkjjjkjhhhhhhhhhhhllllllklkljkjkjkjkkkjjÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞÞÞÞÞÞßÞÞoooommmmlllkkkkkjjkkkjjjkkkkkjjjjhhhhhmmmmmmmmmhhhhllllklkkkkkkkjjkjjjjÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞnonmmnmlklklklkkjkjkjkjjjkjjhhhhhmmnmnmnnonomnmnmnnmmmklklklkkkkjkjkjkjjÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞßÞÞÞß \ No newline at end of file diff --git a/apps/animclk/app-icon.js b/apps/animclk/app-icon.js new file mode 100644 index 000000000..f904072e3 --- /dev/null +++ b/apps/animclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+i4AFnYHGBBIAPDA0dAH4A/ABtBFtlk0uALlml0uBF1uAvQvtvQvroGAF4NWdteARwIvsXwNWq1BAFEdwK+CF9VBF4d6F9SOBR4OAF1OIF4KOB0opjwV6vd7rrtCFwIvlwN70q6BFQN6RwIEBsoAHrwJIACGBdINWvTtDAoIvINgIuYxAvBwAsCLwIjB0glGxKbCMDGCvYvBDwItBGYdWxIAExBpBp9dx4LFAAuPx+IxAQELoK9BE4S+CLgKQCC4IAD1gKBp9WBQoAFxOCE4WCAAIvB0uBWgIuCq2kAoIiBp962YAECIVPqFWBYoAEWQIAH0qNBLwYDBLwRfCF49Pp+BAIIuI1gnBvYADAoIBC0q9BAAWl0hiBp4nBDwoRBLwOzNwOtBgms1ouBq4mBAAQECRwICBGAJeCvQEEldeAAZxESIIzBBgeCq9dFwKKEqwuDvS/CMAQCCXgJiBp9dAAQFBFYUrAAgrBAAszmddq4ABJwI0CFANVXIjsCAIU5nMznNXLYIpBlksmUyq0yBgIBBroDBAwQKCJAMrJIIiBDYJNBAoILBqoJBHIIaDJYIABJgIsBAAIKBAAI7CAgIJBHgNVqsrkgCBPAgwBAAMkDARYBJ5AAFGgcrFQOIAALBFEQQwBbQQ3BAASGCqokDLAwACToKfDAYRyCwQzBFYaODfAOl0q/BR4I1BL4IcDAYIyDmUOhw4DN4IABr1eLQJkDxGsAAWBLAQxBA4L3BYQQoChEIFAIABFAuCKoWIAYYqE1oAB2ez6+sxGrLwOr6HW63XBQOrFYQxBFIRRBEgglBFogqEFYQtC2YODGAWl1nQGQXWU4geBAYNeE4YXD0mBFIoqBJ4RpG1YwEAQOBvQNBZYQHBwI1EBIQABcAOsFoaOCSw4XFeIkr0mlwACBBYYgBCooSBbwIrDwOIB4oAFMAITC6GrL4N60gCBAgSFBRAQCDvUkkgwBruIw+CQIYsHXQQAHwGAF4YTB5+kMwgABqp0Cp+BNgwsEFpQABD4JdDFQgxCAgOAAYIwCqzgEQwgsLAAWkEAIACGIQ2DNQmkYIUrOIRaEFx/QXA4oCY4g4CFwSRBB4SJOX4wiBMIYpDFwhfCGAtPSYJeCACC5FLoYEDNQYJBSAcqAQNWF6oeBXQgrCAoIzBAIKQFGAeAdwIAQDwNVqt6vLeDLQYzDFwVWfAYHCCIYAOwAaEEwJbCLQSTC0krHwV6CwOkqqWBYgVWF5whCRwr1BMgQ8ECAYCBp8kFwIwCAQIvN")) diff --git a/apps/animclk/app.js b/apps/animclk/app.js new file mode 100644 index 000000000..451003d62 --- /dev/null +++ b/apps/animclk/app.js @@ -0,0 +1,116 @@ +var pal = new Uint16Array(E.toArrayBuffer(E.toString(require("Storage").read("animclk.pal")))); +var img1 = require("Storage").read("animclk.pixels1"); +var img1height = img1.length/240; +var img2 = require("Storage").read("animclk.pixels2"); +var img2height = img2.length/240; +var cycle = [ + {reverse:0,rate:1,low:32,high:47}, + {reverse:0,rate:3,low:48,high:63}, + {reverse:0,rate:3,low:64,high:79}, + {reverse:0,rate:2,low:80,high:95}, + {reverse:0,rate:1,low:96,high:103}, + {reverse:0,rate:3,low:128,high:143}, + {reverse:0,rate:2,low:22,high:31} +]; +var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; +var IX = 80, IY = 10, IBPP = 1; +var IW = 174, IH = 45, OY = 24; +var inf = {align:0}; +var bgoptions; + +require("Font7x11Numeric7Seg").add(Graphics); +var cg = Graphics.createArrayBuffer(IW,IH,IBPP,{msb:true}); +var cgimg = {width:IW,height:IH,bpp:IBPP,transparent:0,buffer:cg.buffer}; +var locale = require("locale"); +var lastTime = ""; + +// store clock background image in bgimg (a file in flash memory) +var bgimg = require("Storage").read("imgclock.face.bg"); +// if it doesn't exist, make it +function createBgImg() { + cg.drawImage(img,-IX,-IY,bgoptions); + require("Storage").write("imgclock.face.bg", cg.buffer); + bgimg = require("Storage").read("imgclock.face.bg"); +} +if (!bgimg || !bgimg.length) createBgImg(); + +function drawClock() { + var t = new Date(); + var hours = t.getHours(); + var meridian = ""; + if (is12Hour) { + meridian = (hours < 12) ? "AM" : "PM"; + hours = ((hours + 11) % 12) + 1; + } + // draw time + cg.clear(1); + cg.setColor(1); + var x = 74 + 32 * inf.align; + cg.setFont("7x11Numeric7Seg",3); + cg.setFontAlign(1,-1); + cg.drawString(hours, x, 0); + x+=2; + if (t.getSeconds() & 1) + cg.fillRect(x, 10, x+2, 10+2).fillRect(x, 20, x+2, 20+2); + x+=6; + cg.setFontAlign(-1,-1); + cg.drawString(("0"+t.getMinutes()).substr(-2), x, 0); + x+=44; + cg.setFont("7x11Numeric7Seg",1); + cg.drawString(("0"+t.getSeconds()).substr(-2), x, 20); + cg.setFont("6x8",1); + cg.drawString(meridian, x+2, 0); + let date = locale.date(t); + if (cg.stringWidth(date) < IW-64) { + cg.setFontAlign(0, -1); + cg.drawString(date,IW/2+32*inf.align,IH-8); + } else { + cg.setFontAlign(inf.align, -1); + cg.drawString(date,IW*(inf.align+1)/2,IH-8); + } +} + +function draw() { + var t = (new Date()).toString(); + if (t!=lastTime) { + lastTime = t; + drawClock(); + } + // color cycling + cycle.forEach(c=>{ + var p = pal.slice(c.low,c.high); + pal[c.low] = pal[c.high]; + pal.set(p,c.low+1); + }); + // draw image + g.setColor(-1); + // draw just the clock part overlaid (to avoid flicker) + g.drawImages([{x:0,y:OY,image:{width:240,height:img1height,bpp:8,palette:pal,buffer:img1}}, + {image:cgimg,x:IX,y:IY+OY}], + {x:0,y:OY,width:239,height:img1height}); + // now draw the image on its own below - this is faster + g.drawImage({width:240,height:img2height,bpp:8,palette:pal,buffer:img2},0,OY+img1height); +} + +if (g.drawImages) { + // draw clock itself and do it every second + draw(); + var secondInterval = setInterval(draw,100); + // load widgets + Bangle.loadWidgets(); + Bangle.drawWidgets(); + // Stop when LCD goes off + Bangle.on('lcdPower',on=>{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw,100); + lastTime=""; + draw(); + } + }); +} else { + E.showMessage("Please update\nBangle.js firmware\nto use this clock","animclk"); +} +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); diff --git a/apps/animclk/app.png b/apps/animclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..63eac03e5ea382874275acb5595292d7ac4bac70 GIT binary patch literal 4797 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 XyIFCj-P>bJ00000NkvXXu0mjf37H@B literal 0 HcmV?d00001 diff --git a/apps/animclk/create_images.js b/apps/animclk/create_images.js new file mode 100644 index 000000000..8436d99b3 --- /dev/null +++ b/apps/animclk/create_images.js @@ -0,0 +1,57 @@ +/* Creates an image and palette based off of +an image from http://www.effectgames.com/demos/canvascycle/ + +You just need to open devtools and find the `CanvasCycle.processImage` +call, then create a file for it. eg. + +http://www.effectgames.com/demos/canvascycle/image.php?file=V29&callback=CanvasCycle.processImage + +Finally cycles just needs adding +*/ +var CanvasCycle = { + processImage : function(info) { + const IMG1_HEIGHT = 55; + const IMG2_HEIGHT = 240-(24+55); + var img1 = Buffer.alloc(240*IMG1_HEIGHT); + var img2 = Buffer.alloc(240*IMG2_HEIGHT); + var n=0; + /* img.writeUInt8(240, n++); + img.writeUInt8(240, n++); + img.writeUInt8(8, n++);*/ + var pal = Buffer.alloc(256*2); + + for (var i=0;i>3); + pal.writeUInt16LE(p, i*2); + } + + function getPixel(x,y) { + return info.pixels[(x+640-240)+((y+480-240)*640)]; + } + + n = 0; + for (var y=0;y Date: Thu, 28 May 2020 14:38:46 +0100 Subject: [PATCH 1018/1189] fix formatting using eslint --- apps/sleepphasealarm/app.js | 178 ++++++++++++++++++------------------ apps/verticalface/app.js | 40 ++++---- 2 files changed, 109 insertions(+), 109 deletions(-) diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index dbb91c23f..d54ae1307 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -2,7 +2,7 @@ const alarms = require("Storage").readJSON("alarm.json",1)||[]; const active = alarms.filter(a=>a.on); // Sleep/Wake detection with Estimation of Stationary Sleep-segments (ESS): -// Marko Borazio, Eugen Berlin, Nagihan Kücükyildiz, Philipp M. Scholl and Kristof Van Laerhoven, "Towards a Benchmark for Wearable Sleep Analysis with Inertial Wrist-worn Sensing Units", ICHI 2014, Verona, Italy, IEEE Press, 2014. +// Marko Borazio, Eugen Berlin, Nagihan K�c�kyildiz, Philipp M. Scholl and Kristof Van Laerhoven, "Towards a Benchmark for Wearable Sleep Analysis with Inertial Wrist-worn Sensing Units", ICHI 2014, Verona, Italy, IEEE Press, 2014. // https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en // // Function needs to be called for every measurement but returns a value at maximum once a second (see winwidth) @@ -13,124 +13,124 @@ const sleepthresh=600; var ess_values = []; var slsnds = 0; function calc_ess(val) { - ess_values.push(val); + ess_values.push(val); - if (ess_values.length == winwidth) { - // calculate standard deviation over ~1s - const mean = ess_values.reduce((prev,cur) => cur+prev) / ess_values.length; - const stddev = Math.sqrt(ess_values.map(val => Math.pow(val-mean,2)).reduce((prev,cur) => prev+cur)/ess_values.length); - ess_values = []; + if (ess_values.length == winwidth) { + // calculate standard deviation over ~1s + const mean = ess_values.reduce((prev,cur) => cur+prev) / ess_values.length; + const stddev = Math.sqrt(ess_values.map(val => Math.pow(val-mean,2)).reduce((prev,cur) => prev+cur)/ess_values.length); + ess_values = []; - // check for non-movement according to the threshold - const nonmot = stddev < nomothresh; + // check for non-movement according to the threshold + const nonmot = stddev < nomothresh; - // amount of seconds within non-movement sections - if (nonmot) { - slsnds+=1; - if (slsnds >= sleepthresh) { - return true; // awake - } - } else { - slsnds=0; - return false; // sleep - } - } + // amount of seconds within non-movement sections + if (nonmot) { + slsnds+=1; + if (slsnds >= sleepthresh) { + return true; // awake + } + } else { + slsnds=0; + return false; // sleep + } + } } // locate next alarm var nextAlarm; active.forEach(alarm => { - const now = new Date(); - const alarmHour = alarm.hr/1; - const alarmMinute = Math.round((alarm.hr%1)*60); - var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), alarmHour, alarmMinute); - if (dateAlarm < now) { // dateAlarm in the past, add 24h - dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000)); - } - if (nextAlarm === undefined || dateAlarm < nextAlarm) { - nextAlarm = dateAlarm; - } + const now = new Date(); + const alarmHour = alarm.hr/1; + const alarmMinute = Math.round((alarm.hr%1)*60); + var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), alarmHour, alarmMinute); + if (dateAlarm < now) { // dateAlarm in the past, add 24h + dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000)); + } + if (nextAlarm === undefined || dateAlarm < nextAlarm) { + nextAlarm = dateAlarm; + } }); function drawString(s, x, y) { - g.clearRect(0,y-15,239,y+15); - g.reset(); - g.setFont("Vector",20); - g.setFontAlign(0,0); // align right bottom - g.drawString(s, x, y); + g.clearRect(0,y-15,239,y+15); + g.reset(); + g.setFont("Vector",20); + g.setFontAlign(0,0); // align right bottom + g.drawString(s, x, y); } function drawApp() { - g.clearRect(0,24,239,215); - var alarmHour = nextAlarm.getHours(); - var alarmMinute = nextAlarm.getMinutes(); - if (alarmHour < 10) alarmHour = "0" + alarmHour; - if (alarmMinute < 10) alarmMinute = "0" + alarmMinute; - const s = alarmHour + ":" + alarmMinute + "\n\n"; - E.showMessage(s, "Sleep Phase Alarm"); + g.clearRect(0,24,239,215); + var alarmHour = nextAlarm.getHours(); + var alarmMinute = nextAlarm.getMinutes(); + if (alarmHour < 10) alarmHour = "0" + alarmHour; + if (alarmMinute < 10) alarmMinute = "0" + alarmMinute; + const s = alarmHour + ":" + alarmMinute + "\n\n"; + E.showMessage(s, "Sleep Phase Alarm"); - function drawTime() { - if (Bangle.isLCDOn()) { - const now = new Date(); - var nowHour = now.getHours(); - var nowMinute = now.getMinutes(); - var nowSecond = now.getSeconds(); - if (nowHour < 10) nowHour = "0" + nowHour; - if (nowMinute < 10) nowMinute = "0" + nowMinute; - if (nowSecond < 10) nowSecond = "0" + nowSecond; - const time = nowHour + ":" + nowMinute + ":" + nowSecond; - drawString(time, 120, 140); - } - } + function drawTime() { + if (Bangle.isLCDOn()) { + const now = new Date(); + var nowHour = now.getHours(); + var nowMinute = now.getMinutes(); + var nowSecond = now.getSeconds(); + if (nowHour < 10) nowHour = "0" + nowHour; + if (nowMinute < 10) nowMinute = "0" + nowMinute; + if (nowSecond < 10) nowSecond = "0" + nowSecond; + const time = nowHour + ":" + nowMinute + ":" + nowSecond; + drawString(time, 120, 140); + } + } - setInterval(drawTime, 500); // 2Hz + setInterval(drawTime, 500); // 2Hz } var buzzCount = 19; function buzz() { - Bangle.setLCDPower(1); - Bangle.buzz().then(()=>{ - if (buzzCount--) { - setTimeout(buzz, 500); - } else { - // back to main after finish - setTimeout(load, 1000); - } - }); + Bangle.setLCDPower(1); + Bangle.buzz().then(()=>{ + if (buzzCount--) { + setTimeout(buzz, 500); + } else { + // back to main after finish + setTimeout(load, 1000); + } + }); } // run var minAlarm = new Date(); var measure = true; if (nextAlarm !== undefined) { - Bangle.drawWidgets(); - Bangle.loadWidgets(); + Bangle.drawWidgets(); + Bangle.loadWidgets(); - // minimum alert 30 minutes early - minAlarm.setTime(nextAlarm.getTime() - (30*60*1000)); - setInterval(function() { - const now = new Date(); - const acc = Bangle.getAccel().mag; - const swest = calc_ess(acc); + // minimum alert 30 minutes early + minAlarm.setTime(nextAlarm.getTime() - (30*60*1000)); + setInterval(function() { + const now = new Date(); + const acc = Bangle.getAccel().mag; + const swest = calc_ess(acc); - if (swest !== undefined) { - if (Bangle.isLCDOn()) { - drawString(swest ? "Sleep" : "Awake", 120, 180); - } - } + if (swest !== undefined) { + if (Bangle.isLCDOn()) { + drawString(swest ? "Sleep" : "Awake", 120, 180); + } + } - if (now >= nextAlarm) { - // The alarm widget should handle this one - setTimeout(load, 1000); - } else if (measure && now >= minAlarm && swest === false) { - buzz(); - measure = false; - } - }, 80); // 12.5Hz - drawApp(); + if (now >= nextAlarm) { + // The alarm widget should handle this one + setTimeout(load, 1000); + } else if (measure && now >= minAlarm && swest === false) { + buzz(); + measure = false; + } + }, 80); // 12.5Hz + drawApp(); } else { - E.showMessage('No Alarm'); - setTimeout(load, 1000); + E.showMessage('No Alarm'); + setTimeout(load, 1000); } // BTN2 to menu, BTN3 to main setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); diff --git a/apps/verticalface/app.js b/apps/verticalface/app.js index 3e4650d18..aa6441e79 100644 --- a/apps/verticalface/app.js +++ b/apps/verticalface/app.js @@ -98,8 +98,8 @@ var secondInterval = setInterval(()=>{ Bangle.on('lcdPower',on=>{ if (on) { secondInterval = setInterval(()=>{ - drawTimeDate(); -}, 15000); + drawTimeDate(); + }, 15000); //Screen on drawBPM(HRMstate); drawTimeDate(); @@ -122,29 +122,29 @@ Bangle.on('touch', function(button) { //HRM Controller. setWatch(function(){ if(!HRMstate){ - console.log("Toggled HRM"); - //Turn on. - Bangle.buzz(); - Bangle.setHRMPower(1); - currentHRM = "CALC"; - HRMstate = true; - } else if(HRMstate){ - console.log("Toggled HRM"); - //Turn off. - Bangle.buzz(); - Bangle.setHRMPower(0); - HRMstate = false; - currentHRM = []; - } + console.log("Toggled HRM"); + //Turn on. + Bangle.buzz(); + Bangle.setHRMPower(1); + currentHRM = "CALC"; + HRMstate = true; + } else if(HRMstate){ + console.log("Toggled HRM"); + //Turn off. + Bangle.buzz(); + Bangle.setHRMPower(0); + HRMstate = false; + currentHRM = []; + } drawBPM(HRMstate); }, BTN1, { repeat: true, edge: "falling" }); Bangle.on('HRM', function(hrm) { if(hrm.confidence > 90){ - /*Do more research to determine effect algorithm for heartrate average.*/ - console.log(hrm.bpm); - currentHRM = hrm.bpm; - drawBPM(HRMstate); + /*Do more research to determine effect algorithm for heartrate average.*/ + console.log(hrm.bpm); + currentHRM = hrm.bpm; + drawBPM(HRMstate); } }); From 192ba32a5d9fa0d04daa6a2d017ce70770f7a367 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 28 May 2020 22:32:53 +0200 Subject: [PATCH 1019/1189] simpletimer: make BTN2 really return to launcher (only while countdown is not running) --- apps/simpletimer/README.md | 1 + apps/simpletimer/app.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/simpletimer/README.md b/apps/simpletimer/README.md index ebe54dbe5..426942034 100644 --- a/apps/simpletimer/README.md +++ b/apps/simpletimer/README.md @@ -15,4 +15,5 @@ Simple timer, useful when playing board games or cooking - Tap on seconds to increase them one by one - Press BTN3 to reset time to 0 - Press BTN1 to start the timer or reset to the original time +- Press BTN2 to return to the launcher (only while countdown is not running) - When the time is up use the [swipeleft](https://github.com/espruino/BangleApps/tree/master/apps/gesture) gesture to reset the timer diff --git a/apps/simpletimer/app.js b/apps/simpletimer/app.js index 0bd7992e2..8c8890af3 100644 --- a/apps/simpletimer/app.js +++ b/apps/simpletimer/app.js @@ -111,7 +111,6 @@ function reset(value) { state = value === 0 ? "unset" : "set"; } -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); function addWatch() { clearWatch(); setWatch(changeState, BTN1, { @@ -119,6 +118,16 @@ function addWatch() { repeat: true, edge: "falling" }); + setWatch(() => { + if (state !== "started") { + Bangle.showLauncher(); + }}, + BTN2, + { + repeat: false, + edge: "falling", + }, + ); setWatch( () => { reset(0); From 4ab68eb4112bd86fba7dd39e894208f6d18cdd90 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 28 May 2020 22:29:58 +0200 Subject: [PATCH 1020/1189] simpletimer: remember last set time --- apps.json | 7 ++++++- apps/simpletimer/ChangeLog | 1 + apps/simpletimer/app.js | 5 ++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 5eede9c05..9779ba5a2 100644 --- a/apps.json +++ b/apps.json @@ -1634,7 +1634,7 @@ "id": "simpletimer", "name": "Timer", "icon": "app.png", - "version": "0.03", + "version": "0.04", "description": "Simple timer, useful when playing board games or cooking", "tags": "timer", "readme": "README.md", @@ -1659,6 +1659,11 @@ "url": "app-icon.js", "evaluate": true } + ], + "data": [ + { + "name": "simpletimer.json" + } ] }, { diff --git a/apps/simpletimer/ChangeLog b/apps/simpletimer/ChangeLog index 3f8d98248..b9a839e7d 100644 --- a/apps/simpletimer/ChangeLog +++ b/apps/simpletimer/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial version 0.02: Reset with gesture 0.03: BTN2 to open launcher +0.04: Remember last set time \ No newline at end of file diff --git a/apps/simpletimer/app.js b/apps/simpletimer/app.js index 8c8890af3..041535998 100644 --- a/apps/simpletimer/app.js +++ b/apps/simpletimer/app.js @@ -2,6 +2,7 @@ let counter = 0; let setValue = 0; let counterInterval; let state; +let saved = require("Storage").readJSON("simpletimer.json",true) || {}; const DEBOUNCE = 50; @@ -61,6 +62,8 @@ function clearIntervals() { function set(delta) { if (state === "started") return; counter += delta; + saved.counter = counter; + require("Storage").write("simpletimer.json", saved); if (state === "unset") { state = "set"; } @@ -160,5 +163,5 @@ Bangle.on("aiGesture", gesture => { if (gesture === "swipeleft" && state === "stopped") reset(0); }); -reset(0); +reset(saved.counter || 0); addWatch(); From 631abb812e8acdce0cb15ee8947bff2c26acbbe4 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 28 May 2020 23:27:10 +0200 Subject: [PATCH 1021/1189] gbridge: Add setting to show/hide icon --- apps.json | 5 ++++- apps/gbridge/ChangeLog | 1 + apps/gbridge/settings.js | 20 +++++++++++++++++++- apps/gbridge/widget.js | 19 +++++++++++++++---- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 5eede9c05..8b950228c 100644 --- a/apps.json +++ b/apps.json @@ -95,7 +95,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.11", + "version":"0.12", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", @@ -103,6 +103,9 @@ {"name":"gbridge.settings.js","url":"settings.js"}, {"name":"gbridge.img","url":"app-icon.js","evaluate":true}, {"name":"gbridge.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"gbridge.json"} ] }, { "id": "mclock", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index f66040388..0676652c7 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -10,3 +10,4 @@ 0.09: Update Bluetooth connection state automatically 0.10: Make widget play well with other Gadgetbridge widgets/apps 0.11: Report battery status on connect and at regular intervals +0.12: Setting to show/hide icon \ No newline at end of file diff --git a/apps/gbridge/settings.js b/apps/gbridge/settings.js index 723c9cae9..1834aa052 100644 --- a/apps/gbridge/settings.js +++ b/apps/gbridge/settings.js @@ -2,10 +2,28 @@ function gb(j) { Bluetooth.println(JSON.stringify(j)); } - + const storage = require('Storage'); + let settings = storage.readJSON("gbridge.json", true) || {}; + if (!("showIcon" in settings)) { + settings.showIcon = true; + } + function updateSettings() { + storage.write('gbridge.json', settings); + } + function toggleIcon() { + settings.showIcon = !settings.showIcon; + updateSettings(); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + } var mainmenu = { "" : { "title" : "Gadgetbridge" }, "Connected" : { value : NRF.getSecurityStatus().connected?"Yes":"No" }, + "Show Icon" : { + value: settings.showIcon, + format: v => v?"Yes":"No", + onchange: toggleIcon + }, "Find Phone" : function() { E.showMenu(findPhone); }, "< Back" : back, }; diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index ae7d0f8fa..987426022 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -1,4 +1,5 @@ (() => { + const storage = require('Storage'); const state = { music: "stop", @@ -12,6 +13,11 @@ scrollPos: 0 }; + let settings = storage.readJSON('gbridge.json',1) || {}; + if (!("showIcon" in settings)) { + settings.showIcon = true; + } + function gbSend(message) { Bluetooth.println(""); Bluetooth.println(JSON.stringify(message)); @@ -192,10 +198,15 @@ g.flip(); // turns screen on } - NRF.on("connect", changedConnectionState); - NRF.on("disconnect", changedConnectionState); - - WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: draw }; + if (settings.showIcon) { + WIDGETS["gbridgew"] = {area: "tl", width: 24, draw: draw}; + NRF.on("connect", changedConnectionState); + NRF.on("disconnect", changedConnectionState); + } else { + NRF.removeListener("connect", changedConnectionState); + NRF.removeListener("disconnect", changedConnectionState); + delete WIDGETS["gbridgew"]; + } function sendBattery() { gbSend({ t: "status", bat: E.getBattery() }); From fa692c4d8e64bf22e399d92740ea3d3574290bea Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 29 May 2020 00:05:26 +0200 Subject: [PATCH 1022/1189] gbridge: Fix setting to show/hide icon Don't reload all widgets: just change this one and redraw --- apps/gbridge/settings.js | 6 ++++-- apps/gbridge/widget.js | 31 +++++++++++++++++++------------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/apps/gbridge/settings.js b/apps/gbridge/settings.js index 1834aa052..8df3f6ab4 100644 --- a/apps/gbridge/settings.js +++ b/apps/gbridge/settings.js @@ -13,7 +13,9 @@ function toggleIcon() { settings.showIcon = !settings.showIcon; updateSettings(); - Bangle.loadWidgets(); + // need to re-layout widgets + WIDGETS["gbridgew"].reload(); + g.clear(); Bangle.drawWidgets(); } var mainmenu = { @@ -35,5 +37,5 @@ "< Back" : function() { E.showMenu(mainmenu); }, }; - E.showMenu(mainmenu); + const menu = E.showMenu(mainmenu); }) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 987426022..db6963abb 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -1,5 +1,6 @@ (() => { const storage = require('Storage'); + let settings; const state = { music: "stop", @@ -13,10 +14,6 @@ scrollPos: 0 }; - let settings = storage.readJSON('gbridge.json',1) || {}; - if (!("showIcon" in settings)) { - settings.showIcon = true; - } function gbSend(message) { Bluetooth.println(""); @@ -186,6 +183,7 @@ }); function draw() { + if (!settings.showIcon) return; g.setColor(-1); if (NRF.getSecurityStatus().connected) g.drawImage(require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")), this.x + 1, this.y + 1); @@ -198,16 +196,25 @@ g.flip(); // turns screen on } - if (settings.showIcon) { - WIDGETS["gbridgew"] = {area: "tl", width: 24, draw: draw}; - NRF.on("connect", changedConnectionState); - NRF.on("disconnect", changedConnectionState); - } else { - NRF.removeListener("connect", changedConnectionState); - NRF.removeListener("disconnect", changedConnectionState); - delete WIDGETS["gbridgew"]; + function reload() { + settings = storage.readJSON('gbridge.json', 1) || {}; + if (!("showIcon" in settings)) { + settings.showIcon = true; + } + if (settings.showIcon) { + WIDGETS["gbridgew"].width = 24; + NRF.on("connect", changedConnectionState); + NRF.on("disconnect", changedConnectionState); + } else { + WIDGETS["gbridgew"].width = 0; + NRF.removeListener("connect", changedConnectionState); + NRF.removeListener("disconnect", changedConnectionState); + } } + WIDGETS["gbridgew"] = {area: "tl", width: 24, draw: draw, reload: reload}; + reload(); + function sendBattery() { gbSend({ t: "status", bat: E.getBattery() }); } From 855186f7c9289d4f3f53e0f053c38fb5f7b5de9e Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 29 May 2020 10:37:44 +0200 Subject: [PATCH 1023/1189] gbridge: improve settings handling No need to keep them in memory after reload() is done --- apps/gbridge/settings.js | 25 ++++++++++++++----------- apps/gbridge/widget.js | 23 ++++++++++++----------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/apps/gbridge/settings.js b/apps/gbridge/settings.js index 8df3f6ab4..9e2245e66 100644 --- a/apps/gbridge/settings.js +++ b/apps/gbridge/settings.js @@ -2,17 +2,20 @@ function gb(j) { Bluetooth.println(JSON.stringify(j)); } - const storage = require('Storage'); - let settings = storage.readJSON("gbridge.json", true) || {}; - if (!("showIcon" in settings)) { - settings.showIcon = true; + function settings() { + let settings = require('Storage').readJSON("gbridge.json", true) || {}; + if (!("showIcon" in settings)) { + settings.showIcon = true; + } + return settings } - function updateSettings() { - storage.write('gbridge.json', settings); + function updateSetting(setting, value) { + let settings = require('Storage').readJSON("gbridge.json", true) || {}; + settings[setting] = value + require('Storage').write('gbridge.json', settings); } - function toggleIcon() { - settings.showIcon = !settings.showIcon; - updateSettings(); + function setIcon(visible) { + updateSetting('showIcon', visible); // need to re-layout widgets WIDGETS["gbridgew"].reload(); g.clear(); @@ -22,9 +25,9 @@ "" : { "title" : "Gadgetbridge" }, "Connected" : { value : NRF.getSecurityStatus().connected?"Yes":"No" }, "Show Icon" : { - value: settings.showIcon, + value: settings().showIcon, format: v => v?"Yes":"No", - onchange: toggleIcon + onchange: setIcon }, "Find Phone" : function() { E.showMenu(findPhone); }, "< Back" : back, diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index db6963abb..622543d1b 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -1,7 +1,4 @@ (() => { - const storage = require('Storage'); - let settings; - const state = { music: "stop", @@ -14,6 +11,13 @@ scrollPos: 0 }; + function settings() { + let settings = require('Storage').readJSON("gbridge.json", true) || {}; + if (!("showIcon" in settings)) { + settings.showIcon = true; + } + return settings + } function gbSend(message) { Bluetooth.println(""); @@ -183,7 +187,6 @@ }); function draw() { - if (!settings.showIcon) return; g.setColor(-1); if (NRF.getSecurityStatus().connected) g.drawImage(require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")), this.x + 1, this.y + 1); @@ -197,18 +200,16 @@ } function reload() { - settings = storage.readJSON('gbridge.json', 1) || {}; - if (!("showIcon" in settings)) { - settings.showIcon = true; - } - if (settings.showIcon) { + NRF.removeListener("connect", changedConnectionState); + NRF.removeListener("disconnect", changedConnectionState); + if (settings().showIcon) { WIDGETS["gbridgew"].width = 24; + WIDGETS["gbridgew"].draw = draw; NRF.on("connect", changedConnectionState); NRF.on("disconnect", changedConnectionState); } else { WIDGETS["gbridgew"].width = 0; - NRF.removeListener("connect", changedConnectionState); - NRF.removeListener("disconnect", changedConnectionState); + WIDGETS["gbridgew"].draw = ()=>{}; } } From 03246fdc85fb209e9d23b061eba059b76fcb805e Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 29 May 2020 10:41:19 +0200 Subject: [PATCH 1024/1189] gbridge: minor fixes IDE kept complaining about unused constant & unsafe comparisons --- apps/gbridge/settings.js | 2 +- apps/gbridge/widget.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/gbridge/settings.js b/apps/gbridge/settings.js index 9e2245e66..d1ecb594b 100644 --- a/apps/gbridge/settings.js +++ b/apps/gbridge/settings.js @@ -40,5 +40,5 @@ "< Back" : function() { E.showMenu(mainmenu); }, }; - const menu = E.showMenu(mainmenu); + E.showMenu(mainmenu); }) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 622543d1b..9fe87be03 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -76,7 +76,7 @@ var p = MAXCHARS; while (p > MAXCHARS - 8 && !" \t-_".includes(l[p])) p--; - if (p == MAXCHARS - 8) p = MAXCHARS; + if (p === MAXCHARS - 8) p = MAXCHARS; txt[i] = l.substr(0, p); txt.splice(i + 1, 0, l.substr(p)); } @@ -109,7 +109,7 @@ const changed = state.music === event.state state.music = event.state - if (state.music == "play") { + if (state.music === "play") { showNotification(40, (y) => { g.setColor("#ffffff"); g.drawImage(require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")), 8, y + 8); @@ -126,14 +126,14 @@ }, changed); } - if (state.music == "pause") { + if (state.music === "pause") { hideNotification(); } } function handleCallEvent(event) { - if (event.cmd == "accept") { + if (event.cmd === "accept") { showNotification(40, (y) => { g.setColor("#ffffff"); g.drawImage(require("heatshrink").decompress(atob("jEYwIMJj4CCwACJh4CCCIMOAQMGAQMHAQMDAQMBCIMB4PwgHz/EAn4CBj4CBg4CBgACCAAw=")), 8, y + 8); @@ -180,7 +180,7 @@ }); Bangle.on("swipe", (dir) => { - if (state.music == "play") { + if (state.music === "play") { const command = dir > 0 ? "next" : "previous" gbSend({ t: "music", n: command }); } From 7e87bd0c03ba4b012ac22067d91170096178234e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 29 May 2020 13:23:20 +0100 Subject: [PATCH 1025/1189] add toast to log --- js/ui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/ui.js b/js/ui.js index 47016e86b..859954e7f 100644 --- a/js/ui.js +++ b/js/ui.js @@ -83,6 +83,7 @@ Puck.writeProgress = function(charsSent, charsTotal) { /// Show a 'toast' message for status function showToast(message, type) { // toast-primary, toast-success, toast-warning or toast-error + console.log("TOAST["+(type||"-")+"] "+message); let style = "toast-primary"; if (type=="success") style = "toast-success"; else if (type=="error") style = "toast-error"; From 49d504a034ac3f631db538cdc6307e4dcb9de276 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 29 May 2020 13:27:27 +0100 Subject: [PATCH 1026/1189] Only upload binary files where needed. Assume utf-8 otherwise (Fix #463) --- js/utils.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/js/utils.js b/js/utils.js index 69dcda93b..4716c3f46 100644 --- a/js/utils.js +++ b/js/utils.js @@ -29,11 +29,18 @@ function htmlElement(str) { return div.firstChild; } function httpGet(url) { + let isBinary = !(url.endsWith(".js") || url.endsWith(".json") || url.endsWith(".csv") || url.endsWith(".txt")); return new Promise((resolve,reject) => { let oReq = new XMLHttpRequest(); oReq.addEventListener("load", () => { - // ensure we actually load the data as a raw 8 bit string (not utf-8/etc) - if (oReq.status==200) { + if (oReq.status!=200) { + resolve(oReq.status+" - "+oReq.statusText) + return; + } + if (!isBinary) { + resolve(oReq.responseText) + } else { + // ensure we actually load the data as a raw 8 bit string (not utf-8/etc) let a = new FileReader(); a.onloadend = function() { let bytes = new Uint8Array(a.result); @@ -43,7 +50,7 @@ function httpGet(url) { resolve(str) }; a.readAsArrayBuffer(oReq.response); - } else reject(oReq.status+" - "+oReq.statusText); + } }); oReq.addEventListener("error", () => reject()); oReq.addEventListener("abort", () => reject()); @@ -51,7 +58,8 @@ function httpGet(url) { oReq.onerror = function () { reject("HTTP Request failed"); }; - oReq.responseType = 'blob'; + if (isBinary) + oReq.responseType = 'blob'; oReq.send(); }); } From 889ed82de2e86fb123a8fbcdc4b3b0d2304e65b0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 29 May 2020 16:18:12 +0100 Subject: [PATCH 1027/1189] ok so eslint didn't fix it --- apps/sleepphasealarm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index d54ae1307..1f8bf92ae 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -2,7 +2,7 @@ const alarms = require("Storage").readJSON("alarm.json",1)||[]; const active = alarms.filter(a=>a.on); // Sleep/Wake detection with Estimation of Stationary Sleep-segments (ESS): -// Marko Borazio, Eugen Berlin, Nagihan K�c�kyildiz, Philipp M. Scholl and Kristof Van Laerhoven, "Towards a Benchmark for Wearable Sleep Analysis with Inertial Wrist-worn Sensing Units", ICHI 2014, Verona, Italy, IEEE Press, 2014. +// Marko Borazio, Eugen Berlin, Nagihan Kücükyildiz, Philipp M. Scholl and Kristof Van Laerhoven, "Towards a Benchmark for Wearable Sleep Analysis with Inertial Wrist-worn Sensing Units", ICHI 2014, Verona, Italy, IEEE Press, 2014. // https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en // // Function needs to be called for every measurement but returns a value at maximum once a second (see winwidth) From c83ae5dc7ee86e3a151876ba9696fc9533bc3b97 Mon Sep 17 00:00:00 2001 From: Harrison Asmar <34726416+hasmar04@users.noreply.github.com> Date: Sat, 30 May 2020 20:05:47 +1000 Subject: [PATCH 1028/1189] Stops the face redrawing and using all memory Removes the clear screen and widget loading from each wake so it only runs the first time. Prevents the watch from running out of memory after approx. 3 wakes. --- apps/cliock/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/cliock/app.js b/apps/cliock/app.js index 20086464e..a94b7264d 100644 --- a/apps/cliock/app.js +++ b/apps/cliock/app.js @@ -5,9 +5,6 @@ var flag = false; var WeekDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; function drawAll(){ - g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); updateTime(); updateRest(new Date()); } @@ -42,6 +39,9 @@ function writeLine(str,line){ g.drawString(str,25,marginTop+line*30); } +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); drawAll(); Bangle.on('lcdPower',function(on) { if (on) From 48eea4cc578abd66dc5e7062ccbbd450f4587a28 Mon Sep 17 00:00:00 2001 From: Harrison Asmar <34726416+hasmar04@users.noreply.github.com> Date: Sat, 30 May 2020 20:20:12 +1000 Subject: [PATCH 1029/1189] Update ChangeLog --- apps/cliock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/cliock/ChangeLog b/apps/cliock/ChangeLog index 081a638f6..59f07c400 100644 --- a/apps/cliock/ChangeLog +++ b/apps/cliock/ChangeLog @@ -1 +1,2 @@ 0.07: Submitted to App Loader +0.08: Fixes issue where face would redraw on wake leading to all memory being used and watch crashing. From b08d8ce0f41789420e240cef46b449deffda7818 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Sun, 31 May 2020 15:06:31 +0100 Subject: [PATCH 1030/1189] gpsrec can now graph altitude & speed --- apps.json | 4 +- apps/gpsrec/ChangeLog | 1 + apps/gpsrec/app.js | 92 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 75f010fcd..e96b19d63 100644 --- a/apps.json +++ b/apps.json @@ -317,7 +317,7 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.09", + "version":"0.10", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", @@ -1826,7 +1826,7 @@ {"name":"animclk.img","url":"app-icon.js","evaluate":true} ] }, - { + { "id": "verticalface", "name": "Vertical watch face", "shortName":"Vertical Face", diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 469671b38..489e2d366 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -10,3 +10,4 @@ 0.09: Change default GPS period to 10 (1 is overkill for most uses and makes things slow) Added RAM keyword to functions & other tweaks to speed up rendering Going 'back' from track view now doesn't load again +0.10: Can now graph altitude & speed diff --git a/apps/gpsrec/app.js b/apps/gpsrec/app.js index aeea18bc2..10aa0ebbf 100644 --- a/apps/gpsrec/app.js +++ b/apps/gpsrec/app.js @@ -129,9 +129,15 @@ function viewTrack(n, info) { menu[info.time.toISOString().substr(0,16).replace("T"," ")] = function(){}; menu["Duration"] = { value : asTime(info.duration)}; menu["Records"] = { value : ""+info.records }; - menu['Plot'] = function() { + menu['Plot Map'] = function() { plotTrack(info); }; + menu['Plot Alt.'] = function() { + plotGraph(info, "altitude"); + }; + menu['Plot Speed'] = function() { + plotGraph(info, "speed"); + }; menu['Erase'] = function() { E.showPrompt("Delete Track?").then(function(v) { if (v) { @@ -215,6 +221,90 @@ function plotTrack(info) { setWatch(function() { viewTrack(info.fn, info); }, BTN3); + g.flip(); +} + +function plotGraph(info, style) { + "ram" + E.showMenu(); // remove menu + E.showMessage("Calculating...","GPS Track "+info.fn); + var filename = getFN(info.fn); + var infn = new Float32Array(200); + var infc = new Uint16Array(200); + var title; + var lt = 0; // last time + var tn = 0; // count for each time period + var strt, dur = info.duration; + var f = require("Storage").open(filename,"r"); + if (f===undefined) return; + var l = f.readLine(f); + var nl = 0, c, i; + if (l!==undefined) { + c = l.split(","); + strt = c[0]/1000; + } + if (style=="altitude") { + title = "Altitude (m)"; + while(l!==undefined) { + ++nl;c=l.split(","); + i = Math.round(200*(c[0]/1000 - strt)/dur); + infn[i]+=+c[3]; + infc[i]++; + l = f.readLine(f); + } + } else if (style=="speed") { + title = "Speed (m/s)"; + var p,lp = Bangle.project({lat:c[1],lon:c[2]}); + var t,dx,dy,d,lt = c[0]/1000; + while(l!==undefined) { + ++nl;c=l.split(","); + i = Math.round(200*(c[0]/1000 - strt)/dur); + t = c[0]/1000; + p = Bangle.project({lat:c[1],lon:c[2]}); + dx = p.x-lp.x; + dy = p.y-lp.y; + d = Math.sqrt(dx*dx+dy*dy); + if (t!=lt) { + infn[i]+=d / (t-lt); // speed + infc[i]++; + } + lp = p; + lt = t; + l = f.readLine(f); + } + } else throw new Error("Unknown type"); + var min=100000,max=-100000; + for (var i=0;i0) infn[i]/=infc[i]; + var n = infn[i]; + if (n>max) max=n; + if (n 8) { + grid*=2; + } + // draw + g.clear(1).setFont("6x8",1); + var r = require("graph").drawLine(g, infn, { + x:4,y:0, + width: g.getWidth()-24, + height: g.getHeight()-8, + axes : true, + gridy : grid, + gridx : 50, + title: title, + xlabel : x=>Math.round(x*dur/(60*infn.length))+" min" // minutes + }); + g.setFont("6x8",2); + g.setFontAlign(0,0,3); + g.drawString("Back",230,200); + setWatch(function() { + viewTrack(info.fn, info); + }, BTN3); + g.flip(); } showMainMenu(); From 42180a1770376ec1baeb37e433b902598b26784b Mon Sep 17 00:00:00 2001 From: Richard Hopkins Date: Mon, 1 Jun 2020 00:46:27 +0100 Subject: [PATCH 1031/1189] New screens, buttons and icons --- apps/BLEcontroller/README.md | 30 ++- apps/BLEcontroller/app.js | 369 +++++++++++++++++++++++++++++++++-- 2 files changed, 381 insertions(+), 18 deletions(-) diff --git a/apps/BLEcontroller/README.md b/apps/BLEcontroller/README.md index 049a5f824..237392e1e 100644 --- a/apps/BLEcontroller/README.md +++ b/apps/BLEcontroller/README.md @@ -2,25 +2,43 @@ A highly customisable state machine driven user interface that will communicate with another BLE device. The controller uses the three buttons and the left and right hand side of the watch to provide a flexible and attractive BLE interface. Amaze your friends by controlling your robot from your watch! -Commands are sent from the Controller to the BLE robot in a JSON format. +To keep the messages small, commands are sent from the Controller to the BLE robot in a text string. This is made up of a comma delimited string of the following elements: +* message number (3 characters) +* screen name (3 characters) +* object name (3 characters) +* value/status (3 characters) + +The combination of these variables will uniquely identify the status change requested from the watch to the robot that can then be programmed to respond appropriately. ## Usage -The application can be configured at will by chaning the definitions of the screens, events, icons and buttons. +The application can be configured at will by changing the definitions of the screens, events, icons and buttons. Most changes are possible via data, rather than code change. ## Features -In its default state, it has three screens that provide the ability to: -turn the robot on or off -turn on and off its voice and microphone -make the robot move by spinning left or right and moving forward and backwards +In its default state, it has nine screens that provide the ability to: +* select which robot to interact with (dog or dalek) + * for the dog the following functions are available: + * control movement via a joystick (forwards, backwards, spin left, spin right) + * turn on/off follow mode + * start a game of chess + * wake or sleep the robot + * wag its tail in two directions + * for the dalek, the user can: + * turn on or off face recognition + * make it say random phrases + * control the dalek's iris light and servo + * turn the dalek hover lights on or off + * turn the speaker on or off ## Controls The controls will vary by screen, but I suggest a convention of using BTN3 (the bottom button) for moving backwards up the menu stack. +I have used the convention of red/green for buttons that are switches and blue buttons that provide single function operation (such as navigating a menu or executing a on-off activity) + ## Requests In the first instance, please consult my blog post on this application here. diff --git a/apps/BLEcontroller/app.js b/apps/BLEcontroller/app.js index 3afae6b4b..6200600f1 100644 --- a/apps/BLEcontroller/app.js +++ b/apps/BLEcontroller/app.js @@ -80,11 +80,11 @@ const icons = [ }, { name: "left", - data: "gEBAP4B/AP4BKa9ojHAC5pfHJKDTUsYdZHb6ZfO+I9dABabdLbIBdHf473PP47NJdY7/ePIB/RJop5Ys7t/AP6PvD7o7fP8Y1zTZoHPf/4B/AP4B+A==" + data: "gEBAP4B/AP4BKa9ojHAC5pfHJKDTUsYdZHb6ZfO+I9dABabdLbIBdHf473PP47NJdY7/ePIB/RJop5Ys7t/AP6PvD7o7fP8Y1zTZoHPf/4B/AP4B+A==" }, { name: "right", - data: "gEBAP4B/AP4BKa+oAXDo45hCaqFbUbLBfbbo7bHMojTR7Y5LHa51ZALo75Ov47/FeY77AP4B5WdbF3dv4B/R94fdHb5/jGuabNA57//AP4B/APw=" + data: "gEBAP4B/AP4BKa+oAXDo45hCaqFbUbLBfbbo7bHMojTR7Y5LHa51ZALo75Ov47/FeY77AP4B5WdbF3dv4B/R94fdHb5/jGuabNA57//AP4B/APw=" }, { name: "forward", @@ -117,8 +117,60 @@ const icons = [ { name: "comms", data: "gEBAP4B+QvbF7ABo7/He49tACI7/Hf47zHtI7jJq47lRqoAVEqY7nHsoAZGJo71HrKxfQaY7bdKo7/Hdqz5B5Y7zHK47RD55FRHao3XHKo7JG7L1NHeJTbHboB/AP4BG" + }, + { + name: "dalek", + data: "gEBAP4B/AP4B/AJMQwQBBGucIoMAkADBhFhAoZBcAAQfJhEgB45BCHYMBjGiB4ZLCK5APDFpphBC5AbEJosY0YfCG4IAEJIYdGFYR5LHJYlEAI0Y4cY8YXMOpQBFlNFlMkOZA7MKII7JOAXkE4T1UERKtFHoxJBABY5QiGiD5kANYTnCiFiWIJVOgDZCOra3FoKxFDKI7hADQ7PkEIaoIHEaKYfJAoKPFAJcIGYIJHkI7UgMY8ZFHC5rVDKIZTCDIJhBA4ILBBoYFHC4QBEBogpBjHDdsJJEAoYAHKoTxWWb5tNWZOiHZRbBHbwtLF5ynBL7wtLjHjd6oAZkHkI5JJKAAZ3TkAjJhALBsJ5K0a/KkLvfkMEFpVhO8hrIU4QLGG4QAzkCdVAP4B/AP4Bb" + }, + { + name: "k9", + data: "gEBAP4B/AP4B/AP4B/AP4B/AKAADIf5N/IaIAJJv5LZLeIARffZNdD5JN/KLYATC65RbAGrHlJ/5P/JuYrRJfovNJf4BdAFJL/Jv5N/Jv5L1Jv5PvJv5L7Jv5PpAGpN/dv5HzAP4B/AP4B/AP4B/AP4B/ALg" + }, + { + name: "pawn", + data: "gEBAP4B/AP4B/AP4BEAA455HuY7/Hf47xAB47/PuI1xPZY7/Hf47/G9Y/zHfIATHPI9nHfYB/AOYAfHf4B/AP4B/APA=" + }, + { + name: "facerecog", + data: "gEBAP4BSLuozNH9YpTHsolXPsYfdDraZhELIZhHeLtJELY1VC4Y7HHqoXJABYdNHa5bJDrLvfHfbrPZJI7nGZpdVNJ4lRIpaznRqp1hCq55ZC6IRPd8oPjW8Y5jSr45dEJppNHcIjLHZY5ja6rrhFK45pVqI5rGI4AHHNpx3ANA=" + }, + { + name: "sleep", + data: "gEBAP4B/AP4B2ACY7/Quq95HP45/HP4APOdY7fACZfnHcaZZAL45/HP45/E7YAHCaZFZHfbh/HP45/HOoAHHf4B/AP4B/AP4BIA=" + }, + { + name: "awake", + data: "gEBAP4B/AKyb7HfIAFHPI77Ov451Hf453Hf453HdoAbHf45/Hf5HrHNY7NHNo7/HO47/HO47HHPJ1/Heo51HfoB/ALg=" + }, + { + name: "wag_h", + data: "gEBAP4B/AP4B/AP4B/AP4B/AMwADD+oAFHb4hTHMIlXHMopTHNItPAG47/WfY9tFKY9lEq49hELY7ja8YB/AP4B/AP4B/AP4B/AP4BCA" + }, + { + name: "wag_v", + data: "gEBAP4B/AP4BOafIAHHPI9xAB45vd449rFZIHLHsonJBKa7rGNo7/Hf47/Hf47/Hf47/Hf4xlBKY7hFIoHLQM4rHApK7rAB71xHOo9LHOI9HHOoB/AP4BYA=" + }, + { + name: "happy", + data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/HtInTCZrfZHa4vNABYlVKLI3PbLrzfD7qTXDLaphHMIpLAB45hIKY1pAP4B/AMA" + }, + { + name: "sad", + data: "gEBAP4B/AP4BKa+oAXHNITfHK4ZtD5JZfHOojZaMYlXHMYnXHfI5nFaYPLaaIRNHf47/d/47/CK4njCZ4APHcIVJBbbdTecYjZHr4fdSa4ZbEZ4lNCaY9dAB45hIKY1pAP4B/AMA" + }, + { + name: "hover", + data: "gEBAP4B/AP7NedL4fZK7ojNHeJ35DJI7vC5Y7tVMI7XHNYnNYro7hHKI7lAK47/HdoAhHPI7/Hf47/Hf4AtHPI7/Hf47/Hd45LAP4B/ANwA=" + }, + { + name: "light", + data: "gEBAP4B/APi/Na67lfACZ/nNaI9lE6o9jEbI9hD7Y7dDsJZ3D6YRJHdIJHHfaz7Hf5Z/Hf4hZHMIjFEqIVVHsY5hDpI7TEqL1jVsqlTdM55THOJvHOuY7/HfI9JHOI9HHOoBgA==" + }, + { + name: "speak", + data: "gEBAP4B/AP4BIbO4AXG+4/hAEY55HqoArHPI9PHfIAzHf47/Hf47/HeY9xHJI79Hto5NHtY5RHc45THco5VHcI3XHJpHRG7I7LEro5ZG+IB/AP4BwA==" } -]; + ]; /* finds icon data by name in the icon array and returns an image object*/ const drawIcon = (name) => { @@ -163,6 +215,114 @@ var turnRightBtn = { primary_icon: 'right', }; +var k9Btn = { + primary_colour: 0x653E, + primary_text: 'K9', + primary_icon: 'k9', + }; + +var dalekBtn = { + primary_colour: 0x33F9, + primary_text: 'Dalek', + primary_icon: 'dalek', + }; + +var tailHBtn = { + primary_colour: 0x653E, + primary_text: 'Wag Tail', + primary_icon: 'wag_h', + }; + +var tailVBtn = { + primary_colour: 0x33F9, + primary_text: 'Wag Tail', + primary_icon: 'wag_v', + }; + +var happyBtn = { + primary_colour: 0x653E, + primary_text: 'Speak', + primary_icon: 'happy', + }; + +var sadBtn = { + primary_colour: 0x33F9, + primary_text: 'Speak', + primary_icon: 'sad', + }; + +var speakBtn = { + primary_colour: 0x33F9, + primary_text: 'Speak', + primary_icon: 'speak', + }; + +var faceBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'facerecog', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'facerecog', + value: status_face + }; + +var chessBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'pawn', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'pawn', + value: status_chess + }; + +var irisLightBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'light', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'light', + value: status_iris_light + }; + +var irisBtn = { + primary_colour: 0xE9C7, + primary_text: 'Closed', + primary_icon: 'sleep', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'Open', + secondary_icon : 'awake', + value: status_iris + }; + +var wakeBtn = { + primary_colour: 0xE9C7, + primary_text: 'Sleeping', + primary_icon: 'sleep', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'Awake', + secondary_icon : 'awake', + value: status_wake + }; + +var hoverBtn = { + primary_colour: 0xE9C7, + primary_text: 'Off', + primary_icon: 'hover', + toggle: true, + secondary_colour: 0x3F48, + secondary_text: 'On', + secondary_icon : 'hover', + value: status_hover + }; + var autoBtn = { primary_colour: 0xE9C7, primary_text: 'Stop', @@ -207,9 +367,16 @@ are defined as btn1, bt2 and bt3. The values are names from the icon array. */ const menuScreen = { - left: autoBtn, + left: k9Btn, + right: dalekBtn, +}; + +const k9MenuScreen = { + left: wakeBtn, right: joystickBtn, - btn1: "comms" + btn1: "pawn", + btn2: "wag_h", + btn3: "back" }; const joystickScreen = { @@ -220,12 +387,50 @@ const joystickScreen = { btn3: "back" }; +const tailScreen = { + left: tailHBtn, + right: tailVBtn, + btn3: "back" +}; + const commsScreen = { left: micBtn, right: spkBtn, btn3: "back" }; +const dalekMenuScreen = { + left: faceBtn, + right: speakBtn, + btn1: "hover", + btn2: "light", + btn3: "back" +}; + +const speakScreen = { + left: happyBtn, + right: sadBtn, + btn3: "back" +}; + +const irisScreen = { + left: irisBtn, + right: irisBirisLightBtn, + btn3: "back" +}; + +const lightsScreen = { + left: hoverBtn, + right: spkBtn, + btn3: "back" +}; + +const chessScreen = { + left: chessBtn, + right: autoBtn, + btn3: "back" +}; + /* base state definition Each of the screens correspond to a state; this class provides a constuctor for each @@ -270,15 +475,32 @@ const Home = new State({ screen: menuScreen, events: (event) => { if ((event.object == "right") && (event.status == "end")) { - transmit("Joystick", "joystick", "on"); - return Joystick; - } - if ((event.object == "top") && (event.status == "end")) { - return Comms; + return DalekMenu; } if ((event.object == "left") && (event.status == "end")) { - status_auto.value = !status_auto.value; - transmit(this.state, "auto", onOff(status_auto.value)); + //status_auto.value = !status_auto.value; + //transmit(this.state, "auto", onOff(status_auto.value)); + //return this; + return K9Menu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const K9Menu = new State({ + state: "K9Menu", + screen: k9MenuScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return Home; + } + if ((event.object == "right") && (event.status == "end")) { + return Joystick; + } + if ((event.object == "left") && (event.status == "end")) { + status_wake.value = !status_wake.value; + transmit(this.state, "auto", onOff(status_wake.value)); return this; } transmit(this.state, event.object, event.status); @@ -286,6 +508,129 @@ const Home = new State({ } }); +const DalekMenu = new State({ + state: "DalekMenu", + screen: dalekMenuScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return Home; + } + if ((event.object == "right") && (event.status == "end")) { + return Speak; + } + if ((event.object == "left") && (event.status == "end")) { + status_face.value = !status_face.value; + transmit(this.state, "face", onOff(status_face.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Speak = new State({ + state: "Speak", + screen: speakScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Chess = new State({ + state: "Chess", + screen: chessScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return K9Menu; + } + if ((event.object == "right") && (event.status == "end")) { + status_auto.value = !status_auto.value; + transmit(this.state, "follow", onOff(status_auto.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_chess.value = !status_chess.value; + transmit(this.state, "chess", onOff(status_chess.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Tail = new State({ + state: "Tail", + screen: tailScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return K9Menu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Speak = new State({ + state: "Speak", + screen: speakScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Iris = new State({ + state: "Iris", + screen: irisScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + if ((event.object == "right") && (event.status == "end")) { + status_iris_light.value = !status_iris_light.value; + transmit(this.state, "iris_light", onOff(status_iris_light.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_iris.value = !status_iris.value; + transmit(this.state, "iris_servo", onOff(status_iris.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + +const Lights = new State({ + state: "Lights", + screen: lightsScreen, + events: (event) => { + if ((event.object == "bottom") && (event.status == "end")) { + return DalekMenu; + } + if ((event.object == "right") && (event.status == "end")) { + status_spk.value = !status_spk.value; + transmit(this.state, "iris_light", onOff(status_spk.value)); + return this; + } + if ((event.object == "left") && (event.status == "end")) { + status_hover.value = !status_hover.value; + transmit(this.state, "hover", onOff(status_hover.value)); + return this; + } + transmit(this.state, event.object, event.status); + return this; + } +}); + + /* Joystick page state */ const Joystick = new State({ state: "Joystick", From 207fabeb1d2222a047c1db6ac9838e8ad0b18446 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 1 Jun 2020 08:40:46 +0100 Subject: [PATCH 1032/1189] version bump --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e96b19d63..09c7f9390 100644 --- a/apps.json +++ b/apps.json @@ -1024,7 +1024,7 @@ "name": "Commandline-Clock", "shortName":"CLI-Clock", "icon": "app.png", - "version":"0.07", + "version":"0.08", "description": "Simple CLI-Styled Clock", "tags": "clock,cli,command,bash,shell", "type":"clock", From 46121e60a0aa71ffb7aec3d5a7ecb975a2077c9b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 1 Jun 2020 08:43:33 +0100 Subject: [PATCH 1033/1189] Fix `marked is not defined` error (and include in repo, just in case) --- CHANGELOG.md | 1 + index.html | 6 +++--- lib/marked.min.js | 6 ++++++ 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 lib/marked.min.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 48bfe74ec..66dc20b5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,3 +20,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * New 'espruinotools' which fixes pretokenise issue when ID follows ID (fix #416) * Improve upload of binary files * App description can now be markdown +* Fix `marked is not defined` error (and include in repo, just in case) diff --git a/index.html b/index.html index 480fdd2e1..f0f54c248 100644 --- a/index.html +++ b/index.html @@ -174,14 +174,14 @@ + + + - - - diff --git a/lib/marked.min.js b/lib/marked.min.js new file mode 100644 index 000000000..b9d0f20e6 --- /dev/null +++ b/lib/marked.min.js @@ -0,0 +1,6 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2020, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).marked=t()}(this,function(){"use strict";function s(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[t++]}};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(e){return c[e]}var e,t=(function(t){function e(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:null,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tokenizer:null,walkTokens:null,xhtml:!1}}t.exports={defaults:e(),getDefaults:e,changeDefaults:function(e){t.exports.defaults=e}}}(e={exports:{}}),e.exports),i=(t.defaults,t.getDefaults,t.changeDefaults,/[&<>"']/),a=/[&<>"']/g,l=/[<>"']|&(?!#?\w+;)/,o=/[<>"']|&(?!#?\w+;)/g,c={"&":"&","<":"<",">":">",'"':""","'":"'"};var h=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function u(e){return e.replace(h,function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""})}var p=/(^|[^\[])\^/g;var f=/[^\w:]/g,d=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;var k={},b=/^[^:]+:\/*[^/]*$/,m=/^([^:]+:)[\s\S]*$/,x=/^([^:]+:\/*[^/]*)[\s\S]*$/;function w(e,t){k[" "+e]||(b.test(e)?k[" "+e]=e+"/":k[" "+e]=v(e,"/",!0));var n=-1===(e=k[" "+e]).indexOf(":");return"//"===t.substring(0,2)?n?t:e.replace(m,"$1")+t:"/"===t.charAt(0)?n?t:e.replace(x,"$1")+t:e+t}function v(e,t,n){var r=e.length;if(0===r)return"";for(var i=0;it)n.splice(t);else for(;n.length=r.length?e.slice(r.length):e}).join("\n")}(n,t[3]||"");return{type:"code",raw:n,lang:t[2]?t[2].trim():t[2],text:r}}},t.heading=function(e){var t=this.rules.block.heading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[1].length,text:t[2]}},t.nptable=function(e){var t=this.rules.block.nptable.exec(e);if(t){var n={type:"table",header:O(t[1].replace(/^ *| *\| *$/g,"")),align:t[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:t[3]?t[3].replace(/\n$/,"").split("\n"):[],raw:t[0]};if(n.header.length===n.align.length){for(var r=n.align.length,i=0;i ?/gm,"");return{type:"blockquote",raw:t[0],text:n}}},t.list=function(e){var t=this.rules.block.list.exec(e);if(t){for(var n,r,i,s,a,l,o,c=t[0],h=t[2],u=1/i.test(r[0])&&(t=!1),!n&&/^<(pre|code|kbd|script)(\s|>)/i.test(r[0])?n=!0:n&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(r[0])&&(n=!1),{type:this.options.sanitize?"text":"html",raw:r[0],inLink:t,inRawBlock:n,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(r[0]):C(r[0]):r[0]}},t.link=function(e){var t=this.rules.inline.link.exec(e);if(t){var n,r=j(t[2],"()");-1$/,"$1"))?s.replace(this.rules.inline._escapes,"$1"):s,title:a?a.replace(this.rules.inline._escapes,"$1"):a},t[0])}},t.reflink=function(e,t){var n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){var r=(n[2]||n[1]).replace(/\s+/g," ");if((r=t[r.toLowerCase()])&&r.href)return E(n,r,n[0]);var i=n[0].charAt(0);return{type:"text",raw:i,text:i}}},t.strong=function(e){var t=this.rules.inline.strong.exec(e);if(t)return{type:"strong",raw:t[0],text:t[4]||t[3]||t[2]||t[1]}},t.em=function(e){var t=this.rules.inline.em.exec(e);if(t)return{type:"em",raw:t[0],text:t[6]||t[5]||t[4]||t[3]||t[2]||t[1]}},t.codespan=function(e){var t=this.rules.inline.code.exec(e);if(t){var n=t[2].replace(/\n/g," "),r=/[^ ]/.test(n),i=n.startsWith(" ")&&n.endsWith(" ");return r&&i&&(n=n.substring(1,n.length-1)),n=C(n,!0),{type:"codespan",raw:t[0],text:n}}},t.br=function(e){var t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}},t.del=function(e){var t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[1]}},t.autolink=function(e,t){var n=this.rules.inline.autolink.exec(e);if(n){var r,i="@"===n[2]?"mailto:"+(r=C(this.options.mangle?t(n[1]):n[1])):r=C(n[1]);return{type:"link",raw:n[0],text:r,href:i,tokens:[{type:"text",raw:r,text:r}]}}},t.url=function(e,t){var n,r,i,s;if(n=this.rules.inline.url.exec(e)){if("@"===n[2])i="mailto:"+(r=C(this.options.mangle?t(n[0]):n[0]));else{for(;s=n[0],n[0]=this.rules.inline._backpedal.exec(n[0])[0],s!==n[0];);r=C(n[0]),i="www."===n[1]?"http://"+r:r}return{type:"link",raw:n[0],text:r,href:i,tokens:[{type:"text",raw:r,text:r}]}}},t.inlineText=function(e,t,n){var r=this.rules.inline.text.exec(e);if(r){var i=t?this.options.sanitize?this.options.sanitizer?this.options.sanitizer(r[0]):C(r[0]):r[0]:C(this.options.smartypants?n(r[0]):r[0]);return{type:"text",raw:r[0],text:i}}},e}(),L=S,P=z,U=A,B={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:L,table:L,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,text:/^[^\n]+/,_label:/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,_title:/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/};B.def=P(B.def).replace("label",B._label).replace("title",B._title).getRegex(),B.bullet=/(?:[*+-]|\d{1,9}\.)/,B.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,B.item=P(B.item,"gm").replace(/bull/g,B.bullet).getRegex(),B.list=P(B.list).replace(/bull/g,B.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+B.def.source+")").getRegex(),B._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",B._comment=//,B.html=P(B.html,"i").replace("comment",B._comment).replace("tag",B._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),B.paragraph=P(B._paragraph).replace("hr",B.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",B._tag).getRegex(),B.blockquote=P(B.blockquote).replace("paragraph",B.paragraph).getRegex(),B.normal=U({},B),B.gfm=U({},B.normal,{nptable:"^ *([^|\\n ].*\\|.*)\\n *([-:]+ *\\|[-| :]*)(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)",table:"^ *\\|(.+)\\n *\\|?( *[-:]+[-| :]*)(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"}),B.gfm.nptable=P(B.gfm.nptable).replace("hr",B.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",B._tag).getRegex(),B.gfm.table=P(B.gfm.table).replace("hr",B.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",B._tag).getRegex(),B.pedantic=U({},B.normal,{html:P("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",B._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,fences:L,paragraph:P(B.normal._paragraph).replace("hr",B.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",B.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()});var F={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:L,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^_([^\s_<][\s\S]*?[^\s_])_(?!_|[^\s,punctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\s,punctuation])|^\*([^\s*<\[])\*(?!\*)|^\*([^\s<"][\s\S]*?[^\s\[\*])\*(?![\]`punctuation])|^\*([^\s*"<\[][\s\S]*[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:L,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~"};F.em=P(F.em).replace(/punctuation/g,F._punctuation).getRegex(),F._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,F._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,F._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,F.autolink=P(F.autolink).replace("scheme",F._scheme).replace("email",F._email).getRegex(),F._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,F.tag=P(F.tag).replace("comment",B._comment).replace("attribute",F._attribute).getRegex(),F._label=/(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,F._href=/<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/,F._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,F.link=P(F.link).replace("label",F._label).replace("href",F._href).replace("title",F._title).getRegex(),F.reflink=P(F.reflink).replace("label",F._label).getRegex(),F.normal=U({},F),F.pedantic=U({},F.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:P(/^!?\[(label)\]\((.*?)\)/).replace("label",F._label).getRegex(),reflink:P(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",F._label).getRegex()}),F.gfm=U({},F.normal,{escape:P(F.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\'+(n?e:Q(e,!0))+"\n":"
"+(n?e:Q(e,!0))+"
\n"},t.blockquote=function(e){return"
\n"+e+"
\n"},t.html=function(e){return e},t.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},t.hr=function(){return this.options.xhtml?"
\n":"
\n"},t.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},t.listitem=function(e){return"
  • "+e+"
  • \n"},t.checkbox=function(e){return" "},t.paragraph=function(e){return"

    "+e+"

    \n"},t.table=function(e,t){return"\n\n"+e+"\n"+(t=t&&""+t+"")+"
    \n"},t.tablerow=function(e){return"
    !_x=I99ZD`i||p|7HFJ6kK@F4mEvXeWDzAyOXn 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ℑ?XtfVueutE!$+x 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⋘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

    wSq-M09OLL?6?Toap5p%#6f{d6uY&c}77mgi;{w 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 z zL=;55MtYQ^9rm+dILaZ6UZ|oFr>W9F4oIfkE-pR;d0+&mxw4WW@-r$)0SujqKa&p} z$De1HZHBq8Va{A>?z=Yk-N>CZw{lI6Bxy5u(%eVV2r1G?CFHlcNkxY!)kuX@bgI;T z{(|Ruy`J;?`F=j{k5G0F{NUOS2|OA{Dyz-uQw$M|!4GxcSmmGZkd zR3dU>cy{Z9!q7;Bp);P0s?~8r%-0|tcwAgR>&MLm~E_T1o3G4x2Z~jzj+Zw;q#Xqv~z5tEk4e38IrRxJwuE^$2kN zmyA#m4YRV-Vp23f@a#BL#$6CNQE>R@m6vi05|Xiex_lE!ey&JSlKkfc5f(0oE~24= z7GvjqJ!fWPYiRI{kU$F2d0PR!@lrCVUe2fi2&|W5lipc_eNmtxbq_}&l;$QFBg0$H-H4UY= z=~+)tWvNX8cMcJ6wAU?4NFsWMg^a5F!H^%42WBK2q^Cg1aOe9*A#zrOsvBHMndzYj zTJw=wMBM|_ycBwvXb|b-HNkz{ptLTv7~^Ya$r_mc>DqUVTORcF{4XK84vC(=msP8{y zJf&_^DqBNe68yoPRio)~QH5O9*6`d2n6hw|gbLxgoM z78V9&`jcnX&>Q^aK}jwu`yFbdY3JwfNF*7P#v!NIdhDfJ_!Nxx$OYVy*w)x%qKs+y@xE4yIw_T^m1p-XozV*loc5ZD*(ocVhgmBgQ1F%N_oU{;%4*;PZ6mgy38C&Q&@(`dkU&eGh95OM;^uCFY8>Lp6w(gm>y5_a3WOAove%#~E5 zi?2HxD*_`afynH4=sFHsf+X5bl(2)`ks?X3=vXIBxoi#Pg)E6WPLBycdeokN`#DF9 z;9xRJAGivB$Bjq?(LIJ8uL1aGFE^>6qvnxi!f3z+CkCl|(fUa4T8gshw?Xqch84&5 zF9$j{$Y_(gV(f2gOqgt>z%^-u+U+)4PJ_baJm^-CSTf4$x7P%PC@dEVi66_G9g$oU zJNkUtpfR#_n1kFd9P)`ik`)uJy}REgI@%!UNU6q|ib#nC8%Fx$`dk2;O_J-P57dI^ zjx7J@F~N~)A2Cu^ZoC9l2ZcA}R(+UCvkOA`+V>mhh960Z$3iUE-A7Y(t-6QCiiE^52oLa!dh}R4sF2tfuP&u^Rc(^xl1sw*j zbK5CVhG=qNq2sYsMan zmZ$D8{T(}H+|G7ITTaeTs+YupveHX51%Jk??KsP1UEbhTp5l>ffeCZtNQNWv;qfJD*(H1wCQLw=av#aV(bgU7{h7g05fH~LF7pT$8S`o3KZmKuw6rN+k zzwu1My3(Y*SU^HygN*bfQObY)Rrk=(fBfB+MbL4FAzoz8ulmp0PJ=4zz#Ve{F;^8M4W>^2t+Q()O(+mK@x`?;V8G6K zgF1lx?as?wJ!KB$lL=Rx`6~8XwxYYD+-Rh#b(dEcVb2#XchK8p9c$)@MA5a2hF%R1{S?!;;9MQo*8ddk*m1z>P9?rR?0rYJ*q|aO zr2EI~BQ>OJK~t)xkNBN@g3`v4DpJDe8YbBsJI^Di2u&;mUVquk5itbu-cYMK=$M#3 zZ}h0KroO3Ko)3$q_Khn_qn(YOEOrCG(9l)}w9V+I=MX~~XfsW?RsVb^a6Mc9hCa** z5M*=EL|}hrlA-_+c+=@FKy!besK8G!6#-0NZ^DiP`(3zN(Sy=PpqJ~1U)}|>{Ti6t zUmHWGR2N27=eXQg&rb%eUR!iT_h_nISjzcrNQ_FrUSwDeGkz*=rV8uXCdg~1W~u3h z%mz5ZDPv;1I$>RDp)?LWyi7W(wXxcNZ0~zN;x<6(`)q%Dx8QnNNHvJa1+c#~|pZv!F-!t8D+^_jZBIC8IlDmVg)j2~_&#-? zaT8l(Bir#~P|V&$IkLb`=R)*Wsa*L}p>X8+IAdLxGKJhk**zAK@4vxpE%xVfKpNko zY(Km2^sT=4-F*iQ6@Ml`%d>@+FG?(AJ-zx{@})~Z=f9;Sch=)dLuM>n4gX2OXj%%A!#hc1eJ#Scty;ay?t(1(*km3p z{SD#|+O%-X-thlS|GeMvUL=K={p)+t88ODensKqquY0~gK11vzj5Cl@ zM&s{iTHLS7m?ZZUh*YXOYiKCj*yRaJ3!@2?=^5~>mVr|*RX^0OpiDD@pq#~UuGQaL z3~1ksF6oSaXYk#b6*3HmA+8gs_Y6>7RpIKArbZ=yCFF7=&ydmIjDeFfRKJRDww9 zv;hxweO-Na`|$0Lr?yiC>|_i!|I?`5f(Y4QlEXzv>;7b>4X!=5;hx-NY|YVufYD;z zmTDE$x>XYhoFn$~8pX&K6Lzv>Id0DLbPiq6S!z{v7yorp=O|7=W@p;N6xrTy5~|6H zN2-{y^t43`ABEhy%Kjp3wJC*vX!T7ZAFl_@F(~k@Z-2z5`q#=5_VsK-sRj7jR)~<1 z-W_{!M~U!ht_{ANt$e@k*E?LiiD%f5dQ-2H0L(-F0jN^#U*ahlaBRlJFaM6SS6F^$ zBu?qXFso;YKwU&!uD_?8ryH%g*!-bn{u0b(000I>T#OEj@ zDmSJMKkU|YH=fThd|ZQ5V3d8WWRk-A?7)74Dc|zN$x_ZhZ8$ zky)>!eu%bsv&O2hbWm+qSo~D?fuxgm@!5R&CuzbK3bkd*D4f+){Dkj?bzxtv2|=PS z_kl$S94f(aoh#0<=FJ|qUTIKCtWak%BjL)eT$`q|RGWaS%}n{YXII{d>a&@eor<|> zE;PaI6k@JPxF)!on&4!EurFhy^Q41jqz|7ud1bUVNdYSd#prEO%#CxKLXgILIrRLT z!$DpGd3PA4z6H|buKnEUB?Gi5^?P-~UlpJcRqW_7rE>A2%*GjOy(5(oM|PhlS4@R} zvX_bKL0wij{$Mpnguvls*{X~-lYr&z5#k}K1Q~k1?iRJVhRQyn7Kd{ie^!xkQolv+ z+Rc9)xB_RqapZl=_!9Ky`S2HU{Ps|%hS`SEgS0mQ;)NsxkPWkYV>Dtev;mtnY3acW+EGc**^kw5gaV(AUhdaM zzqZ1^lj%|VG+5e-PA~S}Nu`r#wpu#R^wsSV5VV~VtHBwio^~_^M1Ybev(5W5p-iL>v4HbSI zGo+U=K@`qxfnHJD@y${gcuY7;z+ETO|B2h%M*7(V+9ic8j=*h;101#dGe{-POUNSt z!iOWOnAk+ItPH8hp6AMa+%Yo-f#*)FgelS`!ol$Xnjn%@qsjuElkvH@6HsH8 zHrhGg74PJcK?{gXCwYbF4$02VAxtw@9Zs|l$)3mKS9D8dq}Rs}E6I@Lz4f^%?Uxib zwjA~>^SS3DrU3zGN|wU6O_5A0L;e?U%zFeie$0ZnQ^Ptm_b3ILHn42(-uS+E>1}^T zVMP4j0OBE@0qs!Y7Z|+a9*I7pFOf~hiP&>TAE^%D!(o@?-fAj)fV*tW8nHjiatJan z=E^gnU5iKovsq9${@b8%J@f)tMU-1kgF%(ZLmIP-!cnb_a=-i$N&`El*XZc9bK`jj z?u4Apa57d}dU6d9$6Lu_-30tuT)($kvz?VsPe>Ahk>B%DebEJeVk?p%7#F|4`K!QT ze4Ygw+-bEz!HHXK!c5t0_1JO|t+Ll4f?THXr>@ST3kb6n`Qn7wH}a3Mx!Q`{JU)2T zglxg%M7clXAb(_`?o#9A*_-F6-3U{MWdhbxo>FrWm07rAxS&+CdiJ^YsxtiKT=ax*+3 zn@51*5i8zB8$V6DovoO`BaeBins~op1TVkA#YKwt1%bWF#9diU1ZcU34JbN-!V$bnAy24YHzSw7HBaYlLt>3RrXA2zv z7ACUq!M#ISxa?i|I;ysW&tl=LNa&%^#DWXt44vCTzXNAwyH*ky;URab|M7n&9gwjp z+@FL~*-)0-=8Q_D_ZFLI_T1NVk|~k`^HpU)?93-dJ#>Pmg;gGQKd|@^c_`ZUApsuq z))n?e9QZ~_2sMmIwW{C`_WQ!8K^9a;a>_ ziy~zqAEEGi1wzgY<{3OIupv*y`C;Bm!-WXtpMk4gI#4%OdT4-YANafScpn4Tm%k!9 zVx%sy?HJVbW&X5Dt(m)>r+6ba=cd%Xqfut6au2W$^D}$TQhT6E{15q~8tbfFzDEO0 zR$9*DbN;y`H?Ht|rhskJ)xujfM5u$)kZ3TQp^763dNWU$pBRSmih0j1Ki?`i{i&bz zH6p%S+XCi6&N)2Myw5f2H&$WsTqXvJRCfCLO7j*VK@JZJlzxU~QB_5Uraf^qJX{-=kKt0Ipk;3@+IkWR7ZHi28fR4Y+B;E z7{%*3`pISw8=sQm0u6KIr}36q#Z9+Ye<}Q0frC?7*FAW!z;(T)!IQ)Sz28~o*%ayD z4N5H_(gaZk3)_M6AyOl4ALaJXjbY~S6F7$Sl4GRG*cRVwjhEX{wQ^5E`$LtBpwiZk zw(5#aMqq|%M~ZEuku)HhCX&uo*jf}V1#rtDhIa9?-fAF`_11}lIt8F_0{;N#e@DYE ztc&nr?))FuzxJrY&3ODTgQF|EcVk#1>k#moPMI(f84p4xLPU^5p`Vr@Njx+gFKDC| zH=I)tt~HScVi&WwyhEgOxw5s&AFKB(yvkSHne#R7o!zOkP=6qtioiJ72;9#BLWx4* z%1YZL$rcvZna`EZ&NG*FRnlXm^M-_9#ZKP@oZ4AnkBSOLxtldNfgP8WE6{s z3EqT0CrbTomx8-n{@5dZykt+hr|X6dh@9S&v00YuS-ugLUrUiIoe{NR$^04AmBK@< z@W^2fX8nQT)&`30DYQhxs(`!ZU7u!$$PI)jtZ)^wN)@xOoLNv#S_YMxT&i34O95~} z4pG2h6N2PHhbiKmMV#WIkJu4=HyXr=BEZ6;D~N&*c)}8;%Gbzh^^A}nYW?UW+^cBM zT4)F13oM(Zx*68N&(f@Lx`N78mURdBTxhCuFL*3&K(_B)1b zDv{gM=~UgS{}h1T-jqUeBcvJ)UUGM?IU>gZQQ%emB?Ms@g}BgwNFbod2cn~iLhQ2$ zwr5CkhJKdnBZyEvEuo`&?8D1jT89U{LHV*R&4v&0K= zxlmKSq>K3V42=7!g}84I5dn;-1r8g#shK!(V8f4g^4O%$fJksBsbun@N_hw_*Jez6 zBwu~ziw)S@#M)35vR}15FOD1_%HgNKk1yKoes^;HqmC6#{c!ia;bsBtHB=W5O?^V_ zPqfJ;DQqY^{Q`H6D;7bnp7z|i0H1D6Ie$N3+`>_F8MH%qBhXJwL?uKv@DE3?)H$&B zJu5KjI4ji_YV+`$GnVG2JE3R8aW{W=ac7ayaRW+YdF&S7|CEkJJkFSmTi|5b^JjJy zr8?La7l>4G9LlC7+(_%=#k&|(>&t6rc}a#ZNt2ugT#gnl9aJfG-Y0$RUnn#-SzFVA z<$b%`#M9UZbbd%+302cfLVa?!CF|p7oM~U(R8RBnX3 zHjcX}{-0!24ob6mz3Rcu<*Rft5-u=*Ji3WfCMGqe{YcjW4@~-6{|S-zAR&oHcJsIPjH@)%rKrEX z6+goHq&65{$vQ=SBH^(ZaeQ^XQ8_Ei+euJbb5$pCG5%`)Dx!BZ#;iFyh!gFp61U4RxBN0iW$iVNG*s7bZ=n+hu!@dduG1$zlS#}^AA z1tZ1e@(+}A=5L&d|KatFj+?rP%ky&jZ*f_V2DP~tlg!IaO3OPwo#&3% ztuo2a>yevPR`?Qvt86$J7-bx%RviaWGrN8bKS( zqwInKAc7T8`_KcoLzf9&aD7&W&#@@z-|0)836I!m9OOj_;<^Ilo%O z8=o&#jl?~w{GLCm((tJf+ON`Ykxp7?k@!nIbQWH}iHP>nNZ)_7_EL!4tq}Ry#dEHD zK`|DZIbuen$IAu)v{z+EmxtyGT;^7l>@Nc{vtTTyfbb)~gIup1Ugy+$MitUV`E?mG9Yhs$OpBVLluKR(&{!cy}W(8Z1H z(yc{TzsXF$u_ zAO`sAiujjPp%4usY#+?;RP*a(0VjkIqWJOx4W|)%AaL7I@*K3oKZGVEuxFEhm-znhsqbPZl0aDo5^(-2~S@!BAix*f0%V5OEs z=kV9h6GbI{UYGP$p-mXTsZ?}K?h>=xhP9Y=)8Y)i0@_Cm!P_THVdmN%+~ihL~j_9 z4AW)l)C1x&XGEy-a56`yuEICVRPR_>v={(H#^2DwgPI(n9=wpjB0OJpj}--3TqM$X zO&PX`zRE&NfKn8af#8hnsJ!T(@hT4JRkdJU<<;_(j&o7OH7W}fRc7S8e6D=k(Wpcb znrSjt*Lp7~8ssW|X^?wP1opBV^Lfwf!mlQVnL#rf|t)Ef2EfMCF@G^`i zptOiSCQrT*+|}0zYIE*ja#Z#HKGLEIiqY!+T|l?uc}hHRtq3SoU3^<9gv&e6m-{3* z2a^Ik4GI>bI(-B25-Ohxs3mnobmqAv-L$WSH6lv&L3PKDIn*0H8QG~MgfyFem8wbpV>@njZ*es!y0g3fsbR%m?RT+zn zkqLhJ8RSExH5vdC5&2kUC_fJ)Zs%mKJeZXyCS?%5 z#iWCXI$2$#Xo{h2mUNJ!)m*5Au$Roi+QDjWPNAfXNUPP3LOLmk0TIbUZ2YK%aiXHN zSI(_zMJ>q1k72 z-OxcjJisvy(?ULp*9Wm+p0^O*f8+YTLI32H56g ziOQ+=Dax?%ImNoMQ&+WfW)(f{Y>;w@PYo`6?&~VQ^z;tcE%a<{m{E+*$m8GPj3hm zCz+>K3ejbjx=XnMq;i7*Vgz|U@%Dw|ubZRlPpqcs2SZR;CI=cs)rZ1EO^9B8Pz;Zr z>HqDxRA5)M&A2)uQ#22MUUQDeIG*@b$ZTuljmW;tL)8tI`RccdEnhEV-{nR0Usaq#G_eI0_ifN4`}KCUoybmoSRF8=J`v-rsEj402x$Uf zvWgoEs4$M8DO3jRrND8ot*7DD`prUruIZ+Psfv8lKL;40;)~e@ztu&!Tho_{xg|?CoH0sG90DRPd}c#}GR}jDip>zR5TQ2ifn%3T zJD1Wb}*ZZO8jL%{DbZ&$Nw!wDF&dn17G5s$S2XGpnB*BJl*jcbKvHONMo+aif zAW+eGD7^G!s;q!g5W(!JyGhiA8^|itfVqr~h($i`u(Fmpvb9Ma&a4v+EX@`)qk$eQ8|C!}kibjI57Qim(5zvLE8VEF z>h23GV2=6IB;luI!p#nS0|95`dCkCx*-z@29^*@Ap0Y;|t!OCQi;gO! zzmS(xN@R@LMV_V*JkgQ95S8#nsA+yR%7LiS-pV>x6~mHmB{1~4EkJ!D5k%9RRK_u? zhK%r28qTFEEsshy1BmL*bCRLXG`{r7nfxDf(;3);Po z5ddjkEi1D%UHD1pjYJ}n;d+thwRgwAxf+w}KL67#Hs7;W3Nl5>)c!9ap9{y)FhlDA zLhc&{-5ygX9L3wh&Lu7Bk?z zkjqT^sB^y}9yV4>t8y+lgut5&_y?9iW$>QEfi$S-){5h){NP>IT4q6ex#&V#?!o9# zk*Il?5}Q1=%PQ>Q|bmH`bs86_fR{`g{A1Z@a7jI-_)~ZPFg&Qt4_&D@ikm9uK5- zWVFyw?-ThynrDb7wI^#EO>{`-oTnP3`fOhQ6G3gDlZfD)haTEj9hs zSBT#E6p^WqV6go>^!(_jzMF&=ap}q8~lD8J6FCGNEe<@s%Hb=+SWk7rybp^bz z5NJDItbe*pqBS~?)kebDQkuR`DwsTtx8X~LziIT4{`)CS39ZD#+G3E7W^x%6blf;b zW}UTPe}M+tPWNJ}by^q~5pC6fhIbjv^BXQH-yLH9?DZ0`Qw$L{ZAl~{=6OP3HCSQ-JQK?_;&BlJEiZyi=| z`XRcy_prfF$>RU+9vt4L<`IgW%q~^3gxt1vA8`c`x;+$>$c$SXkye4z;TpBLq`e5( zL^+e`Fzm&skbN|ZGtVsED3NIQU!l|PWcKIlJ*fpT?6fUyTF!e%K4`(27(0A_pkc7q zJq;r9J{u3i=G&gKW!#m672 zAM@%aOpD`N0gH&1%AB8x@wud+sc%%|cx+d4CMhWs&GZYr0bH>=-B1cRCW#BbQA>%8 zDxsph@DP=a6GWQcs!BYGoNP`_3BGaAHQWB^2CdyMB+pm#%;i8_c5vs^J1gAh8IB-V-lwiP^sycdsmpUV@l=I!^rxC=A2#b#JEnWs+SK$U4 zb&wRbx|u|0Gk)64kn@kkG|gc@F}5F;kn_`X2i4GxThy5n43Rf|#d;NBA?r z+L8P@5-e_mXi0!hIxwC|oG2$vGyIHpH^ehbS1nITb=c4^AJ|7K`s0@yVMg0Uz(-@%Rd~3H(V}3ep(%?d z7#;6Qj(?I57a14GU?Ik`-I7Y&7N-R<)hG3-K>;)nGhM8QM}%&8Tj2A}X`llytcJ-) zlx_w6nv-y!ITt@hbtHn8{>O8_gEvgn_$Ih&wcxHxg+ddBbkj@|dgO}`OEeA8$S#qS zRWFPJf)R(?mcc)!G~r%qp}v$B2({V7w#yvp8N{pl=;j0A7ZRfXr<_}~=|=Rywea-p-3g;;nY4IzI7 z|L68;Ihw4cvdZMK)A7R&G&9QVkkb*d5dn(Js2P^Gtv=S`Z4Cmv9tSzv=DDgDj>L zPHF*D^L0*UncfFZ_;`ssmV>rQnLTNl;?zt%QT3t%h&dax0?_{bJRL_rlWCs=od$#7 z0;VCxQ)0Lc)WzQLP?d;y65Gzl2&T!i^$sH|+8Iy1q3aQ$q2xl_4J3&PArauxc(tgS z9YPTN{l&A2nJj`*tjq?qI!R7k3qW4w_$^4m3HtmT?^b6)o@{@#v1vAFwd`O>GAn|e zHRt52BGY^9jJ?0=bQ$X5@Ul!&gEi~O_ZrX@j|49t!BKq8m~dtq<|{?`CJSaomYcpA zc1WxBuDs55W`Qq- z_+ep^SSX2|(w+o9n?*zo!fANa&1r#qQ8z4qTyq!g__q>v1b~FgCQ|I{qDP#pi7+J= zv+FUb7XtJegbT|?@hh(Xc2WQHn}3+=Vr(ga!(er9eIN!lc)LS0)RhJ(5nx%YHhvAPy#^Navx~;| z@g~Ae`ZCO3WE=$0RVVM<)v7d^^}l#bAM%5-GpWC6VU168t27k$YhEgDxPI+J?{#^< zW5(oEpDW7Yez)6jXC(dKr^w#DSKsl$fmzaKPVuJn0*Ol&nJc2F{x~pIv*xPcMgTE` z1ufe|&OIZT@vUjE9k zbr5$x%ZI6gc&GeD#g3MCi8Js| z=G5ECLKQCy@HlkdF~0Q;WWPy?3^m66eBtkA@nfjIBy-Oz%fsE4*Zng3qGvhZzjLtL zcf{Se8^12fQu`G*d=>v(!~oQlxq}8|9hFAt91NIy4+Ky>G+1}{0IIZUfm0a*$C+|F z_tm?$^9Pyeyt<(!i$lkv{HJVL(!4V&S-t}yq76>aYhOk8Tpd=?zy41?GwFnpB9)nZq^ zs_MQF>)ae`6peW3-S7W3X!3heUqy27pI2qT+qes9>9bM0>GDT zhhV6z8F30X4W$tO%V3oU;GuXbjK&!|2p{0ZARlB1#L&ziXAHcJxqpR-W=)@KW1~Bm zCXKmVaIY zJCgYQek*xL*Qa;3EUqa#&#J5527!~K_1XY&@a;?~FSU*}n~QyPnkGQS-q(m5(7G_B z`x4d0K`&TAOD`S1D1SR)Szf%vX@{)qbiUgycEr!Btk_j~`-`9ME<>G6o4w1AS(zhr175;^w82 z^=lMx=(RH~MW7a04ExkrkpocET7*N?oSATQGUO;$jbjf4U|&#b3iQsR|C~i1wdSLG z&I-)*znCo=GT%m9xpk;vtMTg`rMvsj4qc-0;t9}y3r{S$wm*OHF8RkBu|;F9h)WI3J-D_g|7jTaK(xwtNiBFu z0?9 zMX{D$JI3P)kKHfGsuOKx2sIXQ-O=j3V*kKbRZQ*;|B3nTx}YnOivGAxzWAJEcbf+_ z>fc=D$KmxW!+UD8_;+sZC^G`-7EYG=wZ0IM^vbVy18)-7=^pE2#p_v$D?-N+@odD| z`k_l~bj>(2h~?PPAUoe+1)7Rxzich`zN^?>hm&3_JA`Xid}6T(yoyo_8Cm-ry!7JG zL!mp9WqQT9hQgm3*=?s15a}!#iL9QzL1u*XW$(MHEcDzoW|V>%FJ2!8Hbp-R4p1?Y zr!hD2s8@g1VZl7t0W|U-Bwa!;%H-9`IMDoy5&71@(enEKBJi!^%PU2Fr3z0z3xD43 ze`)?u_G{+S+>90zd~nmn%tDPKvGzIiTFSKL#wQCy4jj487Jg6R3%{EddPx;}MiIJC z*_6EaeU|tA8R7dos*ur(u}-XD{=#O;*@B{ta|E+5H6;N!Kb8@@KSbV0ugO~Yj5o1(vW=d%fl^i z^xCOAEq@RnSDoCyRv77BU9mtCw%UT{b5C!X@rRVA2}InIbB5Lf`ClxvhB;|b*f}#( zrrCYY&T``4>cxMo>;FFf_wUNSAEneE*I#dT?nAfp9+_67Xn4NH+ovu7oz8^|>jh0u zH-wEdv+Zze6g+V!gfDB5w#93JK#BpYOc>r1aD)L)z7!f@3s&wvG@#2NzH>te$G#e_ zIk3z9f()T(i%NP2Z$t_!HYwX)@lr5wz#d`Pa*!Gxi3Hh1?o;!V>$CGQ(k8lAT@m*O z&s0ghvb^QGXJ%cq4qO-?zG3h5`U9vAm2oM=#vh6^itWe{sX`yw1F}eu>hZN}Ju!?LAAo>@h1GJ-ee*lE8W4(9_g7@f-V}8S6{*D-Vqb z;S8`Icksk9iM{G|Ra;bsvlw`FuwZ2GkM-0~F^l}Om*n?W9O_TE{9chfoQ)8u(NE`O z=#OpV%+h)6{c6r4(m1D2KaRA_>=pcISmNNao6Gl&xn^9Ges6WhWldd#)?}1^Tv2wZrCQYS=z$~wZ2-L3+uXT)ey{mbzu(@1luh;hpJt9u_4{0uU zdy>S<0*?1-!X>=&7jwr{l3E26ta@TKFjywJrGS8RZiEb}tr86noV>=Z3qIpc`w^YQ zV~99VCyiezHj#6A<YBzVR?~3f6aY&k?=XLm}yS?>t zJGJmZ($_apU0ikUhO_ZcgB@q72*$$5fIp6Fq$31<&KE$14aAYIrK6Z6HN(@!A8*#g zUv>6J1RX5{7c_9)gQ!Ht2J}tn?)Yqm@Lv{S|FOCeFyDs{ExelU-=g3c)uitwpR(+E z;JB%KM7d{hKtx5Lf50*v{rrYj=UJqyG7lGYsv=)8e$GH0^ty^?M48$E%}f{cN53-< zt)}N{DCt_x5r?S6T*2jj{DdHyePsDaS?I4^(R!88Wk$=m3JT#{Zc-3AThghJ8a?ds zGC5&5vE%r;O4r~M1?|n1_RQG*tbEiP8hG%4OuS28DWMvft@_2y7-q0V^S$qImF9PI z&)#YETC+%JR{@9U{khB=OSf0W?&8z#1oA4k;^#|)HEH*{&gW|2+3y6d8q8>1CACD69z|O0W zc@YX}tw3I+C#Stbr$E%Q&TN$gUMX=kZk!|m=e zc(x$*;B|%0x4^vt;RvA}Rlil;=MA31Sif|v>+jYOO_1$PKRp4n&~~QRq?@+9c3xJ; z3^GZOv@X%%VdGx$;>2X0=^Nb+7=}p~)^572Mx!HTG(piILd{VlZ3k;XrKa)A3f(*X zHMK{d^*y=0_xSzhBRBbGj|6cuxb>ny9;6^GyUmINZ-K0FI>E>a9yNm?r9YQi0c2EaSpoYJQI{%r|4NpAL*O=G%q zxyYkr#^zqOU3z2=g2J;kR`GjOHd~=y;jTiTlKR|V*lk{vR?@vJ z%rf5yVjQk4IMG1rDaBhGTP<0fYiv8Tzt;TQo$~9&+bw#b4T9enA?yw+V_^E1?&CEh zbLWfz)QXz5hDL}*sX9amaSZyD?yjL;;52L^fBv+EaU68b=X&P%TGW+%gjc%4L7lbd zmz|mcH^5fPiowvLH6)7llB75+#NKa9Q5?zmY@MeaOBM#DJnwkZzkz~&R=Wv%lIS}N zdFAK0x27{kp0;VIKGc#~OZn>@OPVy1gMmP(QHQ=Xx0QTeH#Yp3!T2c!@yS6^?#-a8b{3O(9CzUieI(Q{}&>PkT6Uodsf+ESUzu6Tp|D zUJ!o!Cxk7P^hSmZxn+@!8r^%Vv|`Fw3VvSm#-9sSxi%8!iIiK2&8Bk2GVFM^WU-5u zN9hi~MpTU?^h7yTifv#ftm}`7zB!~Co~Tz^8FNW4 zV+1|a(oum73Bkw^!kjYdU;8ns*;&{(b2cr#ZD&^1YZAo5R+yRrFEMBv>8Zv z-tJ7;C)AG#{WVnT_FF@Fe~08gXY$VvDi1)q<>CGRm~ql$ z^G`D8@2vy5tOeFPgNx||TUr3S*1V2nc@HacfL#wW@J^N~3CHp6(i3X*CNFxA( z#k_@TImsle4AO~DMTT=vzDurmPMy6WgSmct_nEN$H*|+zp1xAmH*qcdA`h_FTyYb- zKpo0{-b>M@RKK^Ql25(}?G-x5Mp%6z9UX0J-YkASbFMp~sz3g5Gk^42#_s%1q!^i! z`EjQCg0`A?k&|YQrBZ6A-@{P;wVvoMF8BmtuKq0Ww54amD`kRdT6BpG}Hn79Lx1%Q-@V%0;rCN#!mzbNE z$*BOVAmvEF9*{UAu&p+5g>Ep1wqQJzvc99kw-5Bd4@|X{GBc-Rt}+y-A3BEgFacw- ziK?@zgD8Q9!6^n<4ng?<9dN5;%B^SG!TV#eirc?s^DeH5L8l0cV?jb&|B4&oX^FYP zfdaUIZ zkQSg20H|mR;mEHgG6Eyuf<-U}ESwZd5yetGI(x7oF=R(l0EJLUwe$g}^l_qE5I8vD%ZxdxnnkmaIf0G~$O1K(t>;ikY-7k4c^MAC0jek=Fn9!2ut-&SgqXpJ z2a$!pn!G#Jj4oDP*R7hrg4q>!|UVxmi zkOz4%mwaG{HmIPHxe2&w2?t^crJxh5=#bXJfgL!4F_45(aD^WthGVb>a;(0aOpBbf zhfvr_b|g%~^aLT{J{=OuM*5~pDN6TYg-?)#KA?gf*t}dz5)}aoYipbf@T6R%kZ-}t zt<)*gOcWVtgK$`fa0mx$Xoh95$Y$V%Y5;_6k&v|H7?EfRbkZZI7!;QIsvX#YF#rTf zxXV%~g;ijMS~!MdkV%^CGQhMU!Fa5P36cSL-J{Gl$ zyhuz>@J{d?L!cZ_9C`(LS%vfH3r3KHKj?$?d;#~&HKpKyH)}z!VYmZ3O|0zCC&d6Y zkcWI|hi?dnb1;{%%m=b;gZi6O8P^`D~n_OecrMS=?FoL?ggFi3?LzsjPMFkKg z5>_AvXqZX1h=-FxQJhrK71fJC<<1zL(VYyzOR)=;{~`sY;R_z^ghqH%AWZ|nAksE8 zpb%56`b?4fD$S33QjjZ%WjKdXU59hvhGyu6Ucd%NSq4e0M&Lmi2hgs!{G>K~&-cWS zZ>&o(a0jz-{%#aY3aF&mA(x>cCjT@OZScYCu1x#zPEZBr`Rv3lW zko`^?{SigwK2$6ZY~9gM*w$@*)E||EMVQoE|1|*`z_tl#jLkS#{(RSOu@%y+5EoDd z899e#hz4#rhkO7~vH*mCWeJn{3BD1zf_+a6$TbsaiiACaG#CShy@QASRZ0-sIi=WH zuvlWS25ZpR4Wv$a=vZbwkC2sH8Lb3JfYy>lR52WdXAM+nJ&#K0R&V{*%DhYzJlOYK z3TC{@SIRIi1s0m<3|B*krhdES!hCYKLU?)3=S=xsB1f-PVy!OrEq0d3n~v z)QcGX+rVXnZw*p6xXc-l0h-O;>}AF$|BYAuthNv60Xx`)M=)PIP=hHTFC4&1Pb%2# zrPH^xvnj^kFwUoD{HS@u;QCR<##SYLPsXdvPQR@Ma;=D&4fL@;J$hGHrf zRPN-?Nl=4_@Pp-bZd8XR4bYjpjU6egRfK0v|Yn zlWyhvo#S`D1K6eI*~Md2|0vsfeg^2|U42$yK^A6&{%3$jWMxKZ!x8+efLU>NO?-RaR%>Jn63XYFBP&caG&VcwN|i(^{U`inZ8h zK--L+hdo7NL9PTsHr_@+guC|XCl+WbCSH)W1fzxoyFP?NXlOW?W;Zy4F<|Oz_Tr>8 z0g--ek(TVqo@|TW>aD(EuRa3SRRXY{V<-S^vL@@6=3$7HXPKtwv$g4Wus)+JMPQz5 zCN^HYzUxGAV(%2{XeH>m_3OW$?ZHm!KbYnWZf9^Xrk_IOK91< z9_)rzYHCjGF_`FUc5XOkZsxx1R@UqS*Mk0@?gUqG>b7nj?po08xh7<8MFc+palAI>frjspmG8dAZTe1c;Kpym9`60_Z~q=}=#K7_Rst%x@fe@z zuI2F__wgR50tTOME9h|uZ)vkO?U*jxTz<}Ocn2IoM_^uHqh8`|y=yTNzmgeE!VjiDpB`9eck8U2|f$Bc+82|A)w{sqMXE{G`ABXS=x8q-> z-3qVgy%cXK|2JJEm|!FIHqd9< zN8j>DhlKA$UJ`fSO5e_q<<>^{RY`8>*!=@MsOJ6dS}jQF>h^XeumUY0@>xFvOWxvg zFZUx?_ag^#Es%3rC-+*PaPLlQv(0t4j&fgL)^6o#CmwcU*Yfs`bY&;hkrnFe40CAD zbV`_nGRN=O#e+K_Zf(~Bub$&?rvfV&_XpqaJ{RpRUiXk^_icaoh5d0_Z)sbn_j$H= zwCziH|IqMW*LT4T+?sC$NI(Q)2l%^2_HC^M+@5r3t@LMA@$}C5Mt}I&oo2G;ac_6` zmDc#Ehj22W`ZcKfPp9UP57MpQ`a1xG#Kv*!w(~wG1JZtJK<9){2v(UUvjJ9yYv=}; z$C0_m5oVoxDYyBWKYE=v_PmbtpU>_0j#0t{5@@Y!`$l^FcIb(3`d3EqiPrcc7wxOZ zdTKW8b?5rbZ|TH#_c(XwllS7(a`@3IO*B9ix58S=qd7kh2 zWEbibe{aGkk3lVZg=Pe#R{Yr2Zy3jM$cOjro_xy3dN{E5md^a>-+Inh0?)5=k3R#^ z|L1Nvg=w|_Zeo4TeD*@O6-?MqV%d*mhUWXezkS{JPTU9j!7ofp_k=@MXyH%#i6?6v zk9r;_dw?J#a1FtNaQ+}f*k>Wbh7S9T8KY#P5-JfdMm(c&;~6q{?%?@j$k3!ooKAj1 zr4rSwmb!cqJ9f?7yLdKl#*=4nr@eVTc>)c}h*6`WMjIW{lSdCzrhfb&LIi0l)vAyz zVa-}KtEaA>LWLqF7OYoGRf{q@q;_N;gm>0#9Ajl76)ScxZWO4OOu;p9;Dk&lSn$J- zcOp{Mf)OLfydXo4EP0Ys%9So(#++Fbr%jzaea;Ii+TPHkMw8N!)6{8HtFB*f|Fz`x zYuK@%%APH%_7GcycnAuVOR?@apkxf!w zX?fO5U&oGh+sxVXPSB%;5;cufj~vyj^+1&hyAo`wSZ9Mp3R$z6Mb&9*8N!@zz@1^& zL{Qje9C8EwRiR+aDd^lE4c#$aL|Ryf-F72(^w@WkP;!!ZDqRMXOy+Rb8GG)%$5VW! zA#z9_^)0npe)|;&8&_U|1=ek|@n@iJ2x9mL9&iwp-CSDOWkp`dK}k@Be=Ub$bIw8M z;fG2nMk0wG;ep4ADRQzROXTUIOJ*>}D36`({Z!*lrOB66eRA~3ntoMP|DsiY|8*4# zZABj0RgjPvmE&$+I+-S1b14C#l^W@_rKc5onW1xr-I3izT9j#+nU1A75=r2>$)ZcX z&Jq>S%6_NU9c7<^FLgw@_@cMMnaKTj8H{kSqrs7*o1nlu)4B@))GP zyPZI3s`(w8^|nMFt!7vtl%1#bKCJ20&V`6 z=boqemp~h7!2{`vo&J%8Xs&KEy|2#_OPsM=bL%~}-_GmMLk%^_q`sF?MtyS#iul6D zHw<}Gn+oKXXR+0^#c~_tSQn^=w68(%dV_mX<;cJhD0r`Q|94mj%-p6rd6}x0N+t}=$(+nD#DFiGVY#*!bo|DwD!DMGsC?32WJ#x;C4O8Mn( zH)ovGU)ZQWV!;v-MVX~lYS}nkPK;uDY~JAf2*{0fA%7w(W)hM4Cpaimfl%auGap06 zvK?od)U??q(FZ$U00WfAu$4De2+qItkesXpp2^-=!*#NADz)TKC2k2%}Sb}SxzWr^fctcJ{GN`0nF*0M@Bf7rDy60ut$ z?J~2wJov6p#e2oplBB$pz~)iC2+_dS_O`h_tbA{j7GWJNe+n+x$zG{n$o7{|SXmfx zVVRWG%%Q;fBWnwQnP3HDcfo(cu8MKm{{`rkRs||h0-6#c-h{NaB#9;JH9Ohi^+hzI zgN24RXz~vDKJ`8HL(8O6tl~mm^~H#bF(i=nRpIUCK6=Qpjt}hPA_F+gI)u+!fRKNMEMYkel4T>Dy#Iy39wqO zt!C~~=`g=X*l6r6r_Bjmq%p_EYKHMvZ)g=$N5v1Ro&%l#)M}ST7uK>~cad+6WGJct z23zcA)V!C|2zX4VXSmc!imaM8qJTIs~(Hfyc^=GbJVW^H>y`t z2XfCLHRkTZfq9T_b;mHzA-A==bt-7O(%Y^WKDhnzZC+!eVib-pp)Mi~41l{Ag{9;P zDkbO3g>MPep@z6|B|eozn7ZOkQ8mVsSZB?`nz}`z(hZiQ(aa zDa^scp5z?Ay7zdXcqjL||Ld=EJh5NClF0YF?8|2A<(*yWzs;97t(|J8DnzbqXB4YP zfej^;W%sP2TGdR^JNGZH=W`=?jp3U5;P*27js2kZPyozG#Orn5_r4Rx9tH4&Px*jD zqp5yVVGGlOVde|OmOLMGM4#yKmsM0BY+N7qiJSK2UH38F90VEox!&N7T)XK7prN1o zv7aHZ*84f0zP;T1Ioe;v$^Ah?{#BG=^`G*&N&*F-^La`1sl`W`h8!UsxII?()xq{b zUjC{{`H^#B}jt&K?OPA z0OkP=Zd=4H4#b7q|LHm459(cx5z^nK-w-Wa$X%dY-I@k&p!b}CnpoJqg&>=7g8cp7 z6vD{~njQX$Qat3&d~snOcp(`6MVfdC==Bg9){uEs#R8t%Q*fdWI-tdIADtd&-hA-(U0;u;<-Q~V2EMdRiY&d zk9le0CURoMabK!+-;m`GDe?fv#h#II+;%NcX|2qg309#l2HZ?I)fNJyJjNhBh6*LVk=(f$GVY*0p56m~B7QXE0~*sP zN*F;Bp(P=tHY%hbH6$Lq!9$V^hRNdBG1^H;AtB;oL?Hu4Vqw}{8hjwg|9xQq7NfO{ zqz?_)Q&=KOqNESrMJX{;oW=+XL067OR}VW-iLCM6>~c0 z13+iIZKlUTSAhajGx4TS9TNy@QeB4UT@vNw86|8gg9_4SjjX2&CP?Lkix^H0eS#?7 z*{4;eVR15}oDmEZz`%2ACRw_ui`HI@$|wisfr2jR?tQ0&p5u5HqVORDg(hVwWvKG$ z2pAS)e1>R}HbpZ+++&_3imp-@2pWJ2=!;tET+L{fuHPT*BwT7|PvYpJ>8N<(rE5mo z|4|NBg=!?OsON32#bQCF1OLC%55``(11)`(Q9L<%TUjD+Q=3k}mOPl(nTAY|}ZVr6Tsi%r4o@UiDA_9p< zg(e24QdEc)$Q72>URi0%wgl5ny51J}MNEAf$%O0I2-}pIS0h9rMMh{9+T5;QAusZu zo(yKS46F8R4%jROk|Jw;ifRoptFxA#4pz(_S>_g0tBkr{m269OZlkw~i@1)f|6Hb~ zzSXKNmLSd9T%_&lmh}v7T`ErmYY(+W<=ktz>??gLtG^2DsV%F(RtttGr@>mQbPkbS zNRQ2~r8Z8FxIEY!oQ!w6T*Zdx6k=?~X4x;et1`gr$L<7qMc>F?TOxVR$vQ>93Jz0e_{vhlU7uII&avhL;-7d}k zK-hXFLVo7%o+Y@f+o!3;k`x6c7zHiX;yH2=@+$AH{^*Y~Z(uQ%&p@xH?#79&g@O>y z?|KgQLZJ3O7WZzi_wtfuf+ZAnYsZ+c`J%7%sIRQ?<{>Nz2cxS|$X^KmUgY7b=-zGq zA_Mb=E;span;rrq3NUX>)zJX1^(xZWAh6zjs_brW4kiL6s1pyVRE1cMbao~MbDZI+ z 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�N5@m? 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≷u5Lh61asc(Y{4YQWsW4{}-EjB(x3&G9Uom1#^Hf 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 KZ8xES0028mq+Zkj literal 0 HcmV?d00001 From 98bfe26ccc65280b16622c2cbada937350b182a9 Mon Sep 17 00:00:00 2001 From: Bastian Greshake Tzovaras Date: Wed, 17 Jun 2020 14:11:13 +0200 Subject: [PATCH 1160/1189] don't trigger on brief presses --- apps/1button/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/1button/widget.js b/apps/1button/widget.js index 0967d802e..cce099309 100644 --- a/apps/1button/widget.js +++ b/apps/1button/widget.js @@ -15,7 +15,7 @@ digitalWrite(LED2,1); press_time = new Date(); Bangle.buzz(); - }, BTN1, { repeat: true, edge: 'rising', debounce: 50 }); + }, BTN1, { repeat: true, edge: 'rising', debounce: 130 }); // listen to button go to get end time & write data setWatch(function(e) { From dcf2e064fb5df3a9cc90ca0033e13edb7f70009f Mon Sep 17 00:00:00 2001 From: Bastian Greshake Tzovaras Date: Wed, 17 Jun 2020 14:14:22 +0200 Subject: [PATCH 1161/1189] update readme --- apps/1button/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/1button/README.md b/apps/1button/README.md index 13c716f97..13a2724c0 100644 --- a/apps/1button/README.md +++ b/apps/1button/README.md @@ -1,6 +1,6 @@ # The One Button tracker -A simple widget that turns the `BTN1` of your Bangle.js into a one-button-tracker that can be used right from the clock face. Record when you're sneezing, yawning, eating, or whatever you think the button should track for you. +A simple widget that turns the `BTN1` of your Bangle.js into a one-button-tracker that can be used right from the clock face and everywhere else. Record when you're sneezing, yawning, eating, or whatever you think the button should track for you. ![](one-button.GIF) @@ -10,6 +10,8 @@ Every time you press & release the `BTN1` from the clockface this widget will re Once you release `BTN1` both the start & end time of your button press will be saved in 2-column `one_button_presses.csv` CSV file on your _Bangle.js_. The CSV file can [be downloaded from the _My Apps_ tab on the Bangle.js app store](https://banglejs.com/apps/). +To not interfere with alternative usages of `BTN1` (eg when using it for menu navigation) you need to keep the button pressed for at least 130 milliseconds before it triggers a recording (the vibration & LED will inform you about having triggered it). + ## Features - Track whatever events you want with a simple button press on your wrist From 2f06eeb9f96f5e6dc99e07b9ca96e2aa45ce3578 Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Thu, 18 Jun 2020 22:56:27 +0200 Subject: [PATCH 1162/1189] Numerals clock: Add date on touch and some improvements --- apps.json | 2 +- apps/numerals/ChangeLog | 1 + apps/numerals/README.md | 5 +++- apps/numerals/numerals.app.js | 48 +++++++++++++++++++----------- apps/numerals/numerals.settings.js | 9 +++++- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/apps.json b/apps.json index 94c13ef9e..7ebf3cfd8 100644 --- a/apps.json +++ b/apps.json @@ -1332,7 +1332,7 @@ "name": "Numerals Clock", "shortName": "Numerals Clock", "icon": "numerals.png", - "version":"0.06", + "version":"0.07", "description": "A simple big numerals clock", "tags": "numerals,clock", "type":"clock", diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index 9e6abb393..b4dbae3e6 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -4,3 +4,4 @@ 0.04: Don't overwrite existing settings on app update 0.05: Fix settings issue 0.06: Improve rendering of Numeral 1, fix issue with alarms not showing up +0.07: Add date on touch and some improvements (see settings and readme) \ No newline at end of file diff --git a/apps/numerals/README.md b/apps/numerals/README.md index 52e84c76d..ebf4c10fe 100644 --- a/apps/numerals/README.md +++ b/apps/numerals/README.md @@ -17,4 +17,7 @@ Settings can be accessed through the app/widget settings menu of the Bangle.js * frame - only shows outline of numerals ### Menu button -* choose button to start launcher menu with \ No newline at end of file +* choose button to start launcher menu with + +### Date on touch +* shows the current date as DD MM on touch and reverts back to time after 5 seconds \ No newline at end of file diff --git a/apps/numerals/numerals.app.js b/apps/numerals/numerals.app.js index 37f8219c4..123825853 100644 --- a/apps/numerals/numerals.app.js +++ b/apps/numerals/numerals.app.js @@ -42,7 +42,8 @@ if (!settings) { settings = { color:0, drawMode:"fill", - menuButton:24 + menuButton:24, + showDate:0 }; } @@ -56,35 +57,46 @@ function drawNum(num,col,x,y,func){ } } -function draw(drawMode){ +function draw(date){ let d = new Date(); - let h1 = Math.floor((_12hour?d.getHours()%12:d.getHours())/10); - let h2 = (_12hour?d.getHours()%12:d.getHours())%10; - let m1 = Math.floor(d.getMinutes()/10); - let m2 = d.getMinutes()%10; + let l1, l2; + if (date) { + setUpdateInt(0); + l1 = ("0"+(new Date()).getDate()).substr(-2); + l2 = ("0"+(new Date()).getMonth()).substr(-2); + setTimeout(()=>{ draw(); setUpdateInt(1); }, 5000); + } else { + l1 = ("0"+(_12hour?d.getHours()%12:d.getHours())).substr(-2); + l2 = ("0"+d.getMinutes()).substr(-2); + } g.clearRect(0,24,240,240); - drawNum(h1,_hCol[_rCol],0,0,eval(drawMode)); - drawNum(h2,_hCol[_rCol],1,0,eval(drawMode)); - drawNum(m1,_mCol[_rCol],0,1,eval(drawMode)); - drawNum(m2,_mCol[_rCol],1,1,eval(drawMode)); + drawNum(l1[0],_hCol[_rCol],0,0,eval(settings.drawMode)); + drawNum(l1[1],_hCol[_rCol],1,0,eval(settings.drawMode)); + drawNum(l2[0],_mCol[_rCol],0,1,eval(settings.drawMode)); + drawNum(l2[1],_mCol[_rCol],1,1,eval(settings.drawMode)); +} + +function setUpdateInt(set){ + if (interval) clearInterval(interval); + if (set) interval=setInterval(draw, REFRESH_RATE); } Bangle.setLCDMode(); g.reset().clear(); setWatch(Bangle.showLauncher, settings.menuButton, {repeat:false,edge:"falling"}); if (settings.color>0) _rCol=settings.color-1; -interval=setInterval(draw, REFRESH_RATE, settings.drawMode); -draw(settings.drawMode); +setUpdateInt(1); +draw(); +if (settings.showDate) { + Bangle.on('touch', () => draw(1)); +} Bangle.on('lcdPower', function(on){ if (on){ if (settings.color==0) _rCol = Math.floor(Math.random()*_hCol.length); - draw(settings.drawMode); - interval=setInterval(draw, REFRESH_RATE, settings.drawMode); - }else - { - clearInterval(interval); - } + draw(); + setUpdateInt(1); + } else setUpdateInt(0); }); Bangle.loadWidgets(); diff --git a/apps/numerals/numerals.settings.js b/apps/numerals/numerals.settings.js index fbd721146..278d7edc7 100644 --- a/apps/numerals/numerals.settings.js +++ b/apps/numerals/numerals.settings.js @@ -6,7 +6,8 @@ numeralsSettings = { color:0, drawMode:"fill", - menuButton:22 + menuButton:22, + showDate:0 }; updateSettings(); } @@ -36,6 +37,12 @@ format: v=>btn[v][1], onchange: v=> { numeralsSettings.menuButton=btn[v][0]; updateSettings();} }, + "Date on touch": { + value: 0|numeralsSettings.showDate, + min:0,max:1, + format: v=>v?"On":"Off", + onchange: v=> { numeralsSettings.showDate=v; updateSettings();} + }, "< back": back }; E.showMenu(menu); From b78e483874622d16f300da135ed64b36d6295198 Mon Sep 17 00:00:00 2001 From: ps-igel <60899838+ps-igel@users.noreply.github.com> Date: Sun, 21 Jun 2020 10:59:19 +0200 Subject: [PATCH 1163/1189] fix wrong month --- apps/numerals/numerals.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numerals/numerals.app.js b/apps/numerals/numerals.app.js index 123825853..e84793536 100644 --- a/apps/numerals/numerals.app.js +++ b/apps/numerals/numerals.app.js @@ -63,7 +63,7 @@ function draw(date){ if (date) { setUpdateInt(0); l1 = ("0"+(new Date()).getDate()).substr(-2); - l2 = ("0"+(new Date()).getMonth()).substr(-2); + l2 = ("0"+((new Date()).getMonth()+1)).substr(-2); setTimeout(()=>{ draw(); setUpdateInt(1); }, 5000); } else { l1 = ("0"+(_12hour?d.getHours()%12:d.getHours())).substr(-2); From a8f52da8030a4d6214c3223464ef414e1ac25d6c Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Mon, 22 Jun 2020 20:48:08 +0200 Subject: [PATCH 1164/1189] Added gpsautotime widget --- apps.json | 12 ++++++++++++ apps/gpsautotime/widget.js | 33 +++++++++++++++++++++++++++++++++ apps/gpsautotime/widget.png | Bin 0 -> 1826 bytes 3 files changed, 45 insertions(+) create mode 100644 apps/gpsautotime/widget.js create mode 100644 apps/gpsautotime/widget.png diff --git a/apps.json b/apps.json index d447aa18c..8b428092d 100644 --- a/apps.json +++ b/apps.json @@ -1974,5 +1974,17 @@ "data": [ {"name":"one_button_presses.csv","storageFile": true} ] + }, + { "id": "gpsautotime", + "name": "GPS auto time", + "shortName":"GPS auto time", + "icon": "widget.png", + "version":"0.01", + "description": "A widget that automatically updates the Bangle.js time to the GPS time whenever there is a valid GPS fix.", + "tags": "widget,gps", + "type": "widget", + "storage": [ + {"name":"gps_auto_time.wid.js","url":"widget.js"} + ] } ] diff --git a/apps/gpsautotime/widget.js b/apps/gpsautotime/widget.js new file mode 100644 index 000000000..a1d1b2b08 --- /dev/null +++ b/apps/gpsautotime/widget.js @@ -0,0 +1,33 @@ +(() => { + var lastTimeSet = 0; + + Bangle.on('GPS',function(fix) { + if (fix.fix) { + var curTime = fix.time.getTime()/1000; + setTime(curTime); + lastTimeSet = curTime; + + WIDGETS["gpsAutoTime"].draw(WIDGETS["gpsAutoTime"]); + } + }); + + // add your widget + WIDGETS["gpsAutoTime"]={ + area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right) + width: 28, // width of the widget + draw: function() { + g.reset(); // reset the graphics context to defaults (color/font/etc) + g.setFont("6x8"); + if ((getTime() - lastTimeSet) <= 60) { + // time is uptodate + g.setColor('#00ff00'); // green + } + g.drawString("auto", this.x, this.y); + g.drawString("time", this.x, this.y+10); + } + }; + + setInterval(function() { + WIDGETS["gpsAutoTime"].draw(WIDGETS["gpsAutoTime"]); + }, 1*60000); // update every minute +})() diff --git a/apps/gpsautotime/widget.png b/apps/gpsautotime/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..6f6e23f2f6d22c2854f6c436c45cef5292dbd6e4 GIT binary patch literal 1826 zcmV+-2i^FIP)bMK~!jg?U!FrRM#EHKj+@vds&c05F-#ptr0}4i9{tqOpUaY05zj& z)6CSFJ|xp*ATvg1`X_xV5B-yw{vjGAO*_*UC(XoZNlgqIjTjpW0{#oprs`N@6j!&4t+61_4RF^W;sUs%Y$EjezlXSVrWYYVPg3s+M9hDo zNb~p1PiC;kzzA5Rq&e{og#cJtd=GQ)O{VG44gA9<67i`cWNrE?{!Wf~&1Wx6VfChL zyaNV}?{?rF95KJ5D3jb}Zp@IxmEyoZY$A|zZKop>@EmAp%$JDLn{NG2&#ze%nl3=p zCG^x&`&C=zEg(~OsXVZ89*P28*SuJ!J=V{2&5Pl;XgktLpCU0+|XPZuDj5~_OWV1cEo4M?)G7R|z)?&Q+heuRL$!a00?X%PRgiRw_W zOdA2+!s45+wUo8jooFslEUN)TnmC&FrN^JxS~WP#H`s)N}k9CpzUZUyn~Prtu(VNT_W#S1M}Rh(0eC7@d%kHzC-+G#XgPC}wi zv0*1N&@EL_y5$?ipTskNLgI8~(VxkQ>>{RaN~V(|R0e2aw=yzj&qCZv-17`w8go z^?56Ne&aJ~@ip7j4+5EUvPa^0aoKz{S8ORZApiis`_c0~eFFne2ZN!&D1_2}>B>se zvJQmJOI4IUx25cT<6K7N(BUkX?Nc&TheF|_SvZ`6?hYTJfHevm9Yn$a0Q&p-YHxIP zBn5*(KY)~^oxOPZf|OKQwp|k5u)a&KeYRIkM+hv_=1hZ!|C}G-lcrlp2}@SaCN)Ek z3Sz=I{YtAb1f&{4&Hd97F%0ng(}DXGOI!x7>{zGYH~t$5=cQ%a-l5(~Ei?N~;6c-r zdj>D z$N??_INbVmyFX|FxwRk3^r{V_Kk}Qu?*7&G@bk}h|G7-s_6Gu){{{0|F4lf42ZvLT zo1ezTQ@sG_E|o>g)39y0@XuS3iFW5iJ|`?8DMZI8$dd58?MsCr1;+qqNH-?UF2COX zOgCC^qePqp5W)%}Fad-jP*mu+a+`~%`v6cK3WndJxxSOr4PA6y^WG81V+XM1KSmyu z^2qlBxfei6@$*+t8OtVvc)6;o-{mx(fIG8OPp6NjgB_eZ;Q=YhE6ku|^S$UvD#LvS zH={H^;%5TYv<4p#$g{wW0k5{W`cYwq+g@ok>VU1lbw!HJ+l#c1Cz~Wvg&fd#gZ&AZx+U(}rPW=8`M zxe@?_JqDI3Idj|-vw4`}B;M6xY?XpKpevwg1uv};gWX-eU zzD$uTp}SNJzZJ82nBp9Gu}FU#DI0<8BrEur{rjaFZu{~5!uw*8{;Xn)hk?HV0U|d1 zREk`Qc+F1<03cMk4a6-3%j9Da$n)`-hbY5b zOo2Sjx4#0P6DqFzKuwFWMF@Tg zEFa&tW1XJxTi#@v)?~X|g7-^BZjn+v0x}25{2fJlYNE`|Xht)d(f_~x3oe;pX=9M7 QJpcdz07*qoM6N<$g291%?EnA( literal 0 HcmV?d00001 From 7ec8f1f90c58b0103455d7930276d20721fab1a5 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Mon, 22 Jun 2020 22:44:04 +0200 Subject: [PATCH 1165/1189] gpsautotime: renamed gps_auto_time to gpsautotime to fix sanitycheck --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 8b428092d..d0df625bc 100644 --- a/apps.json +++ b/apps.json @@ -1984,7 +1984,7 @@ "tags": "widget,gps", "type": "widget", "storage": [ - {"name":"gps_auto_time.wid.js","url":"widget.js"} + {"name":"gpsautotime.wid.js","url":"widget.js"} ] } ] From 56ce4c30e16f0e6513ca552ee8347591993a04c0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 23 Jun 2020 08:08:59 +0100 Subject: [PATCH 1166/1189] boldclk: Tweak for more efficient rendering, and firmware 2v06 --- apps.json | 2 +- apps/boldclk/ChangeLog | 1 + apps/boldclk/bold_clock.js | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index d447aa18c..3b24e720b 100644 --- a/apps.json +++ b/apps.json @@ -882,7 +882,7 @@ { "id": "boldclk", "name": "Bold Clock", "icon": "bold_clock.png", - "version":"0.02", + "version":"0.03", "description": "Simple, readable and practical clock", "tags": "clock", "type":"clock", diff --git a/apps/boldclk/ChangeLog b/apps/boldclk/ChangeLog index 7819dbe2a..0d02bf644 100644 --- a/apps/boldclk/ChangeLog +++ b/apps/boldclk/ChangeLog @@ -1 +1,2 @@ 0.02: Modified for use with new bootloader and firmware +0.03: Tweak for more efficient rendering, and firmware 2v06 diff --git a/apps/boldclk/bold_clock.js b/apps/boldclk/bold_clock.js index 4a082a45b..b7eaa8968 100644 --- a/apps/boldclk/bold_clock.js +++ b/apps/boldclk/bold_clock.js @@ -16,11 +16,11 @@ const clock_center = {x:Math.floor((240-1)/2), y:24+Math.floor((239-24)/2)}; // ={ x: 119, y: 131 } const radius = Math.floor((239-24+1)/2); // =108 -let tick0 = Graphics.createArrayBuffer(30,8,1); +let tick0 = Graphics.createArrayBuffer(30,8,1,{msb:true}); tick0.fillRect(0,0,tick0.getWidth()-1, tick0.getHeight()-1); -let tick5 = Graphics.createArrayBuffer(20,6,1); +let tick5 = Graphics.createArrayBuffer(20,6,1,{msb:true}); tick5.fillRect(0,0,tick5.getWidth()-1, tick5.getHeight()-1); -let tick1 = Graphics.createArrayBuffer(8,4,1); +let tick1 = Graphics.createArrayBuffer(8,4,1,{msb:true}); tick1.fillRect(0,0,tick1.getWidth()-1, tick1.getHeight()-1); function big_wheel_x(angle){ From 830980498593769403bcefa9eb4069d4db7ae6f7 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 23 Jun 2020 08:17:52 +0100 Subject: [PATCH 1167/1189] 0.10: Fix auto-snooze option (this stopped new alarms being added) (fix #506) --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 5f6f004f4..23b8ee562 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -7,3 +7,4 @@ 0.07: Don't overwrite existing settings on app update 0.08: Make alarm scheduling more reliable 0.09: Add per alarm auto-snooze option +0.10: Fix auto-snooze option (this stopped new alarms being added) (fix #506) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 74482bb1f..b6019ca08 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -8,7 +8,7 @@ var alarms = require("Storage").readJSON("alarm.json",1)||[]; msg : "Eat chocolate", last : 0, // last day of the month we alarmed on - so we don't alarm twice in one day! rp : true, // repeat - as : true, // auto snooze + as : false, // auto snooze } ];*/ @@ -45,6 +45,7 @@ function editAlarm(alarmIndex) { var mins = 0; var en = true; var repeat = true; + var as = false; if (!newAlarm) { var a = alarms[alarmIndex]; hrs = 0|a.hr; @@ -74,7 +75,7 @@ function editAlarm(alarmIndex) { onchange: v=>repeat=v }, 'Auto snooze': { - value: en, + value: as, format: v=>v?"Yes":"No", onchange: v=>as=v } From 682f2ad9d38c7d72792a861a3bc72de54f27c171 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 23 Jun 2020 09:26:25 +0100 Subject: [PATCH 1168/1189] Create README.md --- apps/multiclock/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/multiclock/README.md diff --git a/apps/multiclock/README.md b/apps/multiclock/README.md new file mode 100644 index 000000000..7f835950b --- /dev/null +++ b/apps/multiclock/README.md @@ -0,0 +1 @@ +Temporary From 13ab4f19933e418ef7b4f77af68ba8b178849064 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 23 Jun 2020 09:27:36 +0100 Subject: [PATCH 1169/1189] Add files via upload --- apps/multiclock/ChangeLog | 8 ++++ apps/multiclock/README.md | 50 +++++++++++++++++++- apps/multiclock/ana.js | 72 +++++++++++++++++++++++++++++ apps/multiclock/ana.min.js | 2 + apps/multiclock/anaface.jpg | Bin 0 -> 44568 bytes apps/multiclock/apps_entry.json | 18 ++++++++ apps/multiclock/big.js | 32 +++++++++++++ apps/multiclock/big.min.js | 1 + apps/multiclock/bigface.jpg | Bin 0 -> 40453 bytes apps/multiclock/clock.js | 60 ++++++++++++++++++++++++ apps/multiclock/clock.min.js | 3 ++ apps/multiclock/digi.js | 31 +++++++++++++ apps/multiclock/digi.min.js | 1 + apps/multiclock/digiface.jpg | Bin 0 -> 48073 bytes apps/multiclock/multiclock-icon.js | 1 + apps/multiclock/multiclock.png | Bin 0 -> 1737 bytes apps/multiclock/txt.js | 42 +++++++++++++++++ apps/multiclock/txt.min.js | 2 + apps/multiclock/txtface.jpg | Bin 0 -> 51801 bytes 19 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 apps/multiclock/ChangeLog create mode 100644 apps/multiclock/ana.js create mode 100644 apps/multiclock/ana.min.js create mode 100644 apps/multiclock/anaface.jpg create mode 100644 apps/multiclock/apps_entry.json create mode 100644 apps/multiclock/big.js create mode 100644 apps/multiclock/big.min.js create mode 100644 apps/multiclock/bigface.jpg create mode 100644 apps/multiclock/clock.js create mode 100644 apps/multiclock/clock.min.js create mode 100644 apps/multiclock/digi.js create mode 100644 apps/multiclock/digi.min.js create mode 100644 apps/multiclock/digiface.jpg create mode 100644 apps/multiclock/multiclock-icon.js create mode 100644 apps/multiclock/multiclock.png create mode 100644 apps/multiclock/txt.js create mode 100644 apps/multiclock/txt.min.js create mode 100644 apps/multiclock/txtface.jpg diff --git a/apps/multiclock/ChangeLog b/apps/multiclock/ChangeLog new file mode 100644 index 000000000..2f1d08cc0 --- /dev/null +++ b/apps/multiclock/ChangeLog @@ -0,0 +1,8 @@ +0.01: New App! +0.02: Separate *.face.js files for faces +0.03: Renaming +0.04: Bug Fixes +0.05: Add README +0.06: Add txt clock + + diff --git a/apps/multiclock/README.md b/apps/multiclock/README.md index 7f835950b..c59f27137 100644 --- a/apps/multiclock/README.md +++ b/apps/multiclock/README.md @@ -1 +1,49 @@ -Temporary +# Multiclock + +This is a clock app that supports multiple clock faces. The user can switch between faces while retaining widget state which makes the switch fast and preserves state such as bluetooth connections. Currently there are four clock faces as shown below: + +### Analog Clock Face +![](anaface.jpg) + +### Digital Clock Face +![](digiface.jpg) + +### Big Digit Clock Face +![](bigface.jpg) + +### Text Clock Face +![](txtface.jpg) + +## Controls +Clock faces are kept in a circular list. + +*BTN1* - switches to the next clock face. + +*BTN2* - switches to the app launcher. + +*BTN3* - switches to the previous clock face. + +## Adding a new face +Clock faces are described in javascript storage files named `name.face.js`. For example, the Analog Clock Face is described in `ana.face.js`. These files have the following structure: + +``` +(() => { + function getFace(){ + function onSecond(){ + //draw digits, hands etc + } + function drawAll(){ + //draw background + initial state of digits, hands etc + } + return {init:drawAll, tick:onSecond}; + } + return getFace; +})(); +``` +For those familiar with the structure of widgets, this is similar, however, there is an additional level of function nesting. This means that although faces are loaded when the clock app starts running they are not instantiated until their `getFace` function is called, i.e. memory is not allocated to structures such as image buffer arrays declared in `getFace` until the face is selected. Consequently, adding a face does not require a lot of extra memory. + +The app at start up loads all files `*.face.js`. The simplest way of adding a face is thus to load it into Storage using the WebIDE. + +## Support + +Please report bugs etc. by raising an issue [here](https://github.com/jeffmer/JeffsBangleAppsDev). \ No newline at end of file diff --git a/apps/multiclock/ana.js b/apps/multiclock/ana.js new file mode 100644 index 000000000..4fd5a7251 --- /dev/null +++ b/apps/multiclock/ana.js @@ -0,0 +1,72 @@ +(() => { + + function getFace(){ + + const p = Math.PI/2; + const PRad = Math.PI/180; + + function seconds(angle, r) { + const a = angle*PRad; + const x = 120+Math.sin(a)*r; + const y = 134-Math.cos(a)*r; + if (angle % 90 == 0) { + g.setColor(0,1,1); + g.fillRect(x-6,y-6,x+6,y+6); + } else if (angle % 30 == 0){ + g.setColor(0,1,1); + g.fillRect(x-4,y-4,x+4,y+4); + } else { + g.setColor(1,1,1); + g.fillRect(x-1,y-1,x+1,y+1); + } + } + + function hand(angle, r1,r2, r3) { + const a = angle*PRad; + g.fillPoly([ + 120+Math.sin(a)*r1, + 134-Math.cos(a)*r1, + 120+Math.sin(a+p)*r3, + 134-Math.cos(a+p)*r3, + 120+Math.sin(a)*r2, + 134-Math.cos(a)*r2, + 120+Math.sin(a-p)*r3, + 134-Math.cos(a-p)*r3]); + } + + var minuteDate; + var secondDate; + + function onSecond() { + g.setColor(0,0,0); + hand(360*secondDate.getSeconds()/60, -5, 90, 3); + if (secondDate.getSeconds() === 0) { + hand(360*(minuteDate.getHours() + (minuteDate.getMinutes()/60))/12, -16, 60, 7); + hand(360*minuteDate.getMinutes()/60, -16, 86, 7); + minuteDate = new Date(); + } + g.setColor(1,1,1); + hand(360*(minuteDate.getHours() + (minuteDate.getMinutes()/60))/12, -16, 60, 7); + hand(360*minuteDate.getMinutes()/60, -16, 86, 7); + g.setColor(0,1,1); + secondDate = new Date(); + hand(360*secondDate.getSeconds()/60, -5, 90, 3); + g.setColor(0,0,0); + g.fillCircle(120,134,2); + } + + function drawAll() { + secondDate = minuteDate = new Date(); + // draw seconds + g.setColor(1,1,1); + for (let i=0;i<60;i++) + seconds(360*i/60, 100); + onSecond(); + } + + return {init:drawAll, tick:onSecond}; + } + +return getFace; + +})(); diff --git a/apps/multiclock/ana.min.js b/apps/multiclock/ana.min.js new file mode 100644 index 000000000..f0c671e97 --- /dev/null +++ b/apps/multiclock/ana.min.js @@ -0,0 +1,2 @@ +(function(){return function(){function e(a,d,b,c){a*=k;g.fillPoly([120+Math.sin(a)*d,134-Math.cos(a)*d,120+Math.sin(a+h)*c,134-Math.cos(a+h)*c,120+Math.sin(a)*b,134-Math.cos(a)*b,120+Math.sin(a-h)*c,134-Math.cos(a-h)*c])}function l(){g.setColor(0,0,0);e(360*f.getSeconds()/60,-5,90,3);0===f.getSeconds()&&(e(360*(d.getHours()+d.getMinutes()/60)/12,-16,60,7),e(360*d.getMinutes()/60,-16,86,7),d=new Date);g.setColor(1,1,1);e(360*(d.getHours()+d.getMinutes()/60)/12,-16,60,7);e(360*d.getMinutes()/60,-16, + 86,7);g.setColor(0,1,1);f=new Date;e(360*f.getSeconds()/60,-5,90,3);g.setColor(0,0,0);g.fillCircle(120,134,2)}var h=Math.PI/2,k=Math.PI/180,d,f;return{init:function(){f=d=new Date;g.setColor(1,1,1);for(var a=0;60>a;a++){var e=360*a/60,b=e*k,c=120+100*Math.sin(b);b=134-100*Math.cos(b);0==e%90?(g.setColor(0,1,1),g.fillRect(c-6,b-6,c+6,b+6)):0==e%30?(g.setColor(0,1,1),g.fillRect(c-4,b-4,c+4,b+4)):(g.setColor(1,1,1),g.fillRect(c-1,b-1,c+1,b+1))}l()},tick:l}}})(); \ No newline at end of file diff --git a/apps/multiclock/anaface.jpg b/apps/multiclock/anaface.jpg new file mode 100644 index 0000000000000000000000000000000000000000..86aaccd5496cbd435baa8bc522eec38b71e768ea GIT binary patch literal 44568 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 GfB)IuGe&O! literal 0 HcmV?d00001 diff --git a/apps/multiclock/apps_entry.json b/apps/multiclock/apps_entry.json new file mode 100644 index 000000000..91ed12d6c --- /dev/null +++ b/apps/multiclock/apps_entry.json @@ -0,0 +1,18 @@ +{ "id": "multiclock", + "name": "Multi Clock", + "icon": "multiclock.png", + "version":"0.06", + "description": "Clock with multiple faces - Big, Analogue, Digital, Text.\n Switch between faces with BT1 & BTN3", + "readme": "README.md", + "tags": "clock", + "type":"clock", + "allow_emulator":false, + "storage": [ + {"name":"multiclock.app.js","url":"clock.min.js"}, + {"name":"big.face.js","url":"big.min.js"}, + {"name":"ana.face.js","url":"ana.min.js"}, + {"name":"digi.face.js","url":"digi.min.js"}, + {"name":"txt.face.js","url":"txt.min.js"}, + {"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true} + ] + }, diff --git a/apps/multiclock/big.js b/apps/multiclock/big.js new file mode 100644 index 000000000..7580c2427 --- /dev/null +++ b/apps/multiclock/big.js @@ -0,0 +1,32 @@ +(() => { + + function getFace(){ + + function drawTime(d) { + g.reset(); + var da = d.toString().split(" "); + var time = da[4].substr(0, 5).split(":"); + var hours = time[0], + minutes = time[1]; + g.clearRect(0,24,239,239); + g.setColor(1,1,1); + g.setFont("Vector",100); + g.drawString(hours,50,24,true); + g.drawString(minutes,50,135,true); + } + + function onSecond(){ + var t = new Date(); + if (t.getSeconds() === 0) drawTime(t); + } + + function drawAll(){ + drawTime(new Date()); + } + + return {init:drawAll, tick:onSecond}; + } + + return getFace; + +})(); \ No newline at end of file diff --git a/apps/multiclock/big.min.js b/apps/multiclock/big.min.js new file mode 100644 index 000000000..97359511f --- /dev/null +++ b/apps/multiclock/big.min.js @@ -0,0 +1 @@ +(function(){return function(){function c(a){g.reset();var b=a.toString().split(" ")[4].substr(0,5).split(":");a=b[0];b=b[1];g.clearRect(0,24,239,239);g.setColor(1,1,1);g.setFont("Vector",100);g.drawString(a,50,24,!0);g.drawString(b,50,135,!0)}return{init:function(){c(new Date)},tick:function(){var a=new Date;0===a.getSeconds()&&c(a)}}}})(); \ No newline at end of file diff --git a/apps/multiclock/bigface.jpg b/apps/multiclock/bigface.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6857268644e9f09aca81bdd2b8ef32c9633b2f66 GIT binary patch literal 40453 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 literal 0 HcmV?d00001 diff --git a/apps/multiclock/clock.js b/apps/multiclock/clock.js new file mode 100644 index 000000000..ed2383b8d --- /dev/null +++ b/apps/multiclock/clock.js @@ -0,0 +1,60 @@ +var FACES = []; +var iface = 0; +require("Storage").list(/\.face\.js$/).forEach(face=>FACES.push(eval(require("Storage").read(face)))); +var face = FACES[iface](); +var intervalRefSec; + +function stopdraw() { + if(intervalRefSec) {intervalRefSec=clearInterval(intervalRefSec);} +} + +function startdraw() { + g.clear(); + g.reset(); + Bangle.drawWidgets(); + face.init(); + intervalRefSec = setInterval(face.tick,1000); +} + +function setButtons(){ + function newFace(inc){ + var n = FACES.length-1; + iface+=inc; + iface = iface>n?0:iface<0?n:iface; + stopdraw(); + face = FACES[iface](); + startdraw(); + } + setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + setWatch(newFace.bind(null,1), BTN1, {repeat:true,edge:"rising"}); + setWatch(newFace.bind(null,-1), BTN3, {repeat:true,edge:"rising"}); +} + +var SCREENACCESS = { + withApp:true, + request:function(){ + this.withApp=false; + stopdraw(); + clearWatch(); + }, + release:function(){ + this.withApp=true; + startdraw(); + setButtons(); + } +}; + +Bangle.on('lcdPower',function(on) { + if (!SCREENACCESS.withApp) return; + if (on) { + startdraw(); + } else { + stopdraw(); + } +}); + +g.clear(); +Bangle.loadWidgets(); +startdraw(); +setButtons(); + diff --git a/apps/multiclock/clock.min.js b/apps/multiclock/clock.min.js new file mode 100644 index 000000000..1eec2b1f5 --- /dev/null +++ b/apps/multiclock/clock.min.js @@ -0,0 +1,3 @@ +var FACES=[],iface=0;require("Storage").list(/\.face\.js$/).forEach(function(a){return FACES.push(eval(require("Storage").read(a)))});var face=FACES[iface](),intervalRefSec;function stopdraw(){intervalRefSec&&(intervalRefSec=clearInterval(intervalRefSec))}function startdraw(){g.clear();g.reset();Bangle.drawWidgets();face.init();intervalRefSec=setInterval(face.tick,1E3)} +function setButtons(){function a(a){var b=FACES.length-1;iface+=a;iface=iface>b?0:0>iface?b:iface;stopdraw();face=FACES[iface]();startdraw()}setWatch(Bangle.showLauncher,BTN2,{repeat:!1,edge:"falling"});setWatch(a.bind(null,1),BTN1,{repeat:!0,edge:"rising"});setWatch(a.bind(null,-1),BTN3,{repeat:!0,edge:"rising"})}var SCREENACCESS={withApp:!0,request:function(){this.withApp=!1;stopdraw();clearWatch()},release:function(){this.withApp=!0;startdraw();setButtons()}}; +Bangle.on("lcdPower",function(a){SCREENACCESS.withApp&&(a?startdraw():stopdraw())});g.clear();Bangle.loadWidgets();startdraw();setButtons(); \ No newline at end of file diff --git a/apps/multiclock/digi.js b/apps/multiclock/digi.js new file mode 100644 index 000000000..f4250bd31 --- /dev/null +++ b/apps/multiclock/digi.js @@ -0,0 +1,31 @@ +(() => { + +function getFace(){ + + var buf = Graphics.createArrayBuffer(240,92,1,{msb:true}); + function flip() { + g.setColor(1,1,1); + g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},0,85); + } + + function drawTime() { + buf.clear(); + buf.setColor(1); + var d = new Date(); + var da = d.toString().split(" "); + var time = da[4]; + buf.setFont("Vector",42); + buf.setFontAlign(0,-1); + buf.drawString(time,buf.getWidth()/2,0); + buf.setFont("6x8",2); + buf.setFontAlign(0,-1); + var date = d.toString().substr(0,15); + buf.drawString(date, buf.getWidth()/2, 70); + flip(); + } + return {init:drawTime, tick:drawTime}; +} + +return getFace; + +})(); \ No newline at end of file diff --git a/apps/multiclock/digi.min.js b/apps/multiclock/digi.min.js new file mode 100644 index 000000000..1bad4da9e --- /dev/null +++ b/apps/multiclock/digi.min.js @@ -0,0 +1 @@ +(function(){return function(){function b(){a.clear();a.setColor(1);var c=new Date,b=c.toString().split(" ")[4];a.setFont("Vector",42);a.setFontAlign(0,-1);a.drawString(b,a.getWidth()/2,0);a.setFont("6x8",2);a.setFontAlign(0,-1);c=c.toString().substr(0,15);a.drawString(c,a.getWidth()/2,70);g.setColor(1,1,1);g.drawImage({width:a.getWidth(),height:a.getHeight(),buffer:a.buffer},0,85)}var a=Graphics.createArrayBuffer(240,92,1,{msb:!0});return{init:b,tick:b}}})(); \ No newline at end of file diff --git a/apps/multiclock/digiface.jpg b/apps/multiclock/digiface.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b0323bd55d1e9947e5573171b77d851445c5b8f9 GIT binary patch literal 48073 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:" ",bot:a[c]}:20>c?{top:" ",bot:b[c-10]}:60>c?{top:d[Math.floor(c/10)-2],bot:a[c%10]}:"error"}g.reset();g.clearRect(0,40,239,210);g.setColor(1,1,1);g.setFontAlign(0,0);g.setFont("Vector",32);var d=a(b.getHours());g.drawString(d.top, +120,60);g.drawString(d.bot,120,100);d=a(b.getMinutes());g.drawString(d.top,120,140);g.drawString(d.bot,120,180)}return{init:function(){a(new Date)},tick:function(){var b=new Date;0===b.getSeconds()&&a(b)}}}})(); \ No newline at end of file diff --git a/apps/multiclock/txtface.jpg b/apps/multiclock/txtface.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e3834125780c16c697d9fb22d5d3eead3cee2d30 GIT binary patch literal 51801 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 literal 0 HcmV?d00001 From 9af674aa30de97a9f5ce140b0e285cdec064a5c7 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 23 Jun 2020 09:30:38 +0100 Subject: [PATCH 1170/1189] Update apps.json --- apps.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps.json b/apps.json index 0097bc483..53c8d128f 100644 --- a/apps.json +++ b/apps.json @@ -1986,5 +1986,23 @@ "storage": [ {"name":"gpsautotime.wid.js","url":"widget.js"} ] + }, + { "id": "multiclock", + "name": "Multi Clock", + "icon": "multiclock.png", + "version":"0.06", + "description": "Clock with multiple faces - Big, Analogue, Digital, Text.\n Switch between faces with BT1 & BTN3", + "readme": "README.md", + "tags": "clock", + "type":"clock", + "allow_emulator":false, + "storage": [ + {"name":"multiclock.app.js","url":"clock.min.js"}, + {"name":"big.face.js","url":"big.min.js"}, + {"name":"ana.face.js","url":"ana.min.js"}, + {"name":"digi.face.js","url":"digi.min.js"}, + {"name":"txt.face.js","url":"txt.min.js"}, + {"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true} + ] } ] From c67d76612b4957e745fcf6b9007f4dfea1aceae0 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 23 Jun 2020 10:27:03 +0100 Subject: [PATCH 1171/1189] BugFix: Marioclock drawPoly (used to draw pyramids) update to stop pyramids appearing to float above ground --- apps/marioclock/ChangeLog | 3 ++- apps/marioclock/marioclock-app.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index 69a3ccc7b..582f21436 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -9,4 +9,5 @@ 0.09: Add GadgetBridge functionality. Mario shows message type in speach bubble, while message scrolls in info panel 0.10: Swiping left to enable night-mode now also reduces LCD brightness through 3 levels before returning to day-mode. 0.11: User settings persisted and read to file. -0.12: Add info banner message when phone (dis)connects. Display low-battery warning (<=10%) \ No newline at end of file +0.12: Add info banner message when phone (dis)connects. Display low-battery warning (<=10%) +0.13: Fix drawPyramid function so pyramids are drawn in correct Y position \ No newline at end of file diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index 886e53dc0..d4ab7bca6 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -225,7 +225,7 @@ function drawFloor() { } function drawPyramid() { - const pPol = [pyramidSprite.x + 10, H - 6, pyramidSprite.x + 50, pyramidSprite.height, pyramidSprite.x + 90, H - 6]; // Pyramid poly + const pPol = [pyramidSprite.x + 10, H - 5, pyramidSprite.x + 50, pyramidSprite.height, pyramidSprite.x + 90, H - 5]; // Pyramid poly const color = (nightMode) ? DARK : LIGHT; g.setColor(color); From 7a054bc79434a4dd720debd474c6bf804ff1d74e Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Tue, 23 Jun 2020 10:28:59 +0100 Subject: [PATCH 1172/1189] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 0097bc483..306cea50d 100644 --- a/apps.json +++ b/apps.json @@ -1036,11 +1036,11 @@ { "id": "marioclock", "name": "Mario Clock", "icon": "marioclock.png", - "version":"0.12", + "version":"0.13", "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", "tags": "clock,mario,retro", "type": "clock", - "allow_emulator":true, + "allow_emulator":false, "readme": "README.md", "storage": [ {"name":"marioclock.app.js","url":"marioclock-app.js"}, From a345ca2316fc51a4b8b1aae06c438e13f12b215a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 23 Jun 2020 13:13:14 +0100 Subject: [PATCH 1173/1189] Add flag raiser docs --- apps.json | 1 + apps/flagrse/README.md | 76 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 apps/flagrse/README.md diff --git a/apps.json b/apps.json index 0097bc483..030134ea5 100644 --- a/apps.json +++ b/apps.json @@ -959,6 +959,7 @@ "name": "Espruino Flag Raiser", "icon": "app.png", "version":"0.01", + "readme": "README.md", "description": "App to send a command to another Espruino to cause it to raise a flag", "tags": "", "storage": [ diff --git a/apps/flagrse/README.md b/apps/flagrse/README.md new file mode 100644 index 000000000..819ebde36 --- /dev/null +++ b/apps/flagrse/README.md @@ -0,0 +1,76 @@ +# Espruino Flag Raiser + +An app to send a command to another Espruino to cause it to raise a flag. + +For this to work, you need to upload the following code to another +bluetooth Espruino device (the one with the flag attached) : + +``` +var FLAG_PIN = D14; + +var s = require("servo").connect(FLAG_PIN); +s.move(1,3000); // move to position 1 over 3 seconds + +var timeout; +function flag() { + if (timeout) clearTimeout(); + s.move(0.2,2000); + timeout = setTimeout(function() { + timeout = undefined; + s.move(1,2000); + },2000); +} + +setWatch(flag, BTN, {repeat:true}); + +NRF.setServices({ + "3e440001-f5bb-357d-719d-179272e4d4d9": { + "3e440002-f5bb-357d-719d-179272e4d4d9": { + value : [0], + maxLen : 1, + writable : true, + onWrite : function(evt) { + flag(); + } + } + } +}, { uart : false }); +NRF.setAdvertising({}, {name:"Flag"}); +``` + +## Wiring + +This is designed for an [MDBT42Q Breakout board](http://www.espruino.com/MDBT42Q) +but should work on any Bluetooth LE Espruino device - you just need to change `FLAG_PIN` +to the name of the pin that's connected to the servo motor. + +However, as designed: + +* Get an [MDBT42Q Breakout board](http://www.espruino.com/MDBT42Q) +* Connect `GND` to GND (black) of a 3.7v LiPo battery +* Connect `Vin` to positive (red) of the battery +* Take a servo motor and: + * Connect the Black wire to `GND` (LiPo GND) + * Connect the Red wire to `Vin` (LiPo 3.7v) + * Connect the White wire to `D14` on the MDBT42Q + +## How does it work? + +The code above changes the advertised name of the Espruino device to be +`Flag` (which the app then searches for). + +Then, it adds a service UUID `3e440001-f5bb-357d-719d-179272e4d4d9` (this +is just a random number we made up) with characteristic `3e440002-f5bb-357d-719d-179272e4d4d9` +(the same UUID with the second 16 bits incremented). When the characteristic +is written (with any data), `flag()` is called, which raises the flag. + +`flag()` itself uses the [servo module](http://www.espruino.com/Servo+Motors) +to allow the servo motor to be controlled easily. + +You might find the [Espruino About Bluetooth LE page](http://www.espruino.com/About+Bluetooth+LE) +is useful as an introduction to services and characteristics. + +### Don't want to use a servo motor? + +No problem, just replace `flag()` with a function that controls whatever you need +it to. From f40e3a25491491af67b158b89d0d53033a797c5f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 23 Jun 2020 13:54:28 +0100 Subject: [PATCH 1174/1189] bump version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 030134ea5..14feabe80 100644 --- a/apps.json +++ b/apps.json @@ -167,7 +167,7 @@ "name": "Default Alarm", "shortName":"Alarms", "icon": "app.png", - "version":"0.09", + "version":"0.10", "description": "Set and respond to alarms", "tags": "tool,alarm,widget", "storage": [ From 27082439790408d039abf9af992dc683686cb978 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Tue, 23 Jun 2020 14:24:01 +0100 Subject: [PATCH 1175/1189] Add files via upload --- apps/multiclock/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/multiclock/README.md b/apps/multiclock/README.md index c59f27137..5bf6856e5 100644 --- a/apps/multiclock/README.md +++ b/apps/multiclock/README.md @@ -1,6 +1,6 @@ # Multiclock -This is a clock app that supports multiple clock faces. The user can switch between faces while retaining widget state which makes the switch fast and preserves state such as bluetooth connections. Currently there are four clock faces as shown below: +This is a clock app that supports multiple clock faces. The user can switch between faces while retaining widget state which makes the switch fast and preserves state such as bluetooth connections. Currently there are four clock faces as shown below. To my eye, these faces look better when widgets are hidden using **widviz**. ### Analog Clock Face ![](anaface.jpg) @@ -42,7 +42,7 @@ Clock faces are described in javascript storage files named `name.face.js`. For ``` For those familiar with the structure of widgets, this is similar, however, there is an additional level of function nesting. This means that although faces are loaded when the clock app starts running they are not instantiated until their `getFace` function is called, i.e. memory is not allocated to structures such as image buffer arrays declared in `getFace` until the face is selected. Consequently, adding a face does not require a lot of extra memory. -The app at start up loads all files `*.face.js`. The simplest way of adding a face is thus to load it into Storage using the WebIDE. +The app at start up loads all files `*.face.js`. The simplest way of adding a face is thus to load it into `Storage` using the WebIDE. Similarly, to remove an unwanted face, simply delete it from `Storage` using the WebIDE. ## Support From c449a258f1de107f2f80ec36ec14947b07f222bf Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 24 Jun 2020 09:55:28 +0100 Subject: [PATCH 1176/1189] Added Espruino control (fix #417) --- apps.json | 14 ++ apps/espruinoctrl/ChangeLog | 1 + apps/espruinoctrl/README.md | 28 ++++ apps/espruinoctrl/app-icon.js | 1 + apps/espruinoctrl/app.png | Bin 0 -> 1302 bytes apps/espruinoctrl/custom.html | 275 ++++++++++++++++++++++++++++++++++ 6 files changed, 319 insertions(+) create mode 100644 apps/espruinoctrl/ChangeLog create mode 100644 apps/espruinoctrl/README.md create mode 100644 apps/espruinoctrl/app-icon.js create mode 100644 apps/espruinoctrl/app.png create mode 100644 apps/espruinoctrl/custom.html diff --git a/apps.json b/apps.json index 14feabe80..eb9b7b6a3 100644 --- a/apps.json +++ b/apps.json @@ -1987,5 +1987,19 @@ "storage": [ {"name":"gpsautotime.wid.js","url":"widget.js"} ] + }, + { "id": "espruinoctrl", + "name": "Espruino Control", + "shortName":"Espruino Ctrl", + "icon": "app.png", + "version":"0.01", + "description": "Send commands to other Espruino devices via the Bluetooth UART interface. Customisable commands!", + "tags": "", + "readme": "README.md", + "custom": "custom.html", + "storage": [ + {"name":"espruinoctrl.app.js"}, + {"name":"espruinoctrl.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/espruinoctrl/ChangeLog b/apps/espruinoctrl/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/espruinoctrl/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/espruinoctrl/README.md b/apps/espruinoctrl/README.md new file mode 100644 index 000000000..a7bca662c --- /dev/null +++ b/apps/espruinoctrl/README.md @@ -0,0 +1,28 @@ +# Espruino Control + +Send commands to other Espruino devices via the Bluetooth UART interface. + +## Customising + +Click the customise button and you can customise your commands +with 4 options: + + +* **Title** - The title of the menu item that will be displayed +* **Command** - The JS command to execute, eg. `LED.toggle()` +* **MAC Address** - If specified, of the form `aa:bb:cc:dd:ee:ff`. The device +with this address will be connected to directly. If not specified a menu +showing available Espruino devices is popped up. +* **RX** - If checked, the app will display any data received from the +device being connected to. Use this if you want to print data - eg: `print(E.getBattery())` + +When done, click 'Upload'. Your changes will be saved to local storage +so they'll be remembered next time you upload from the same device.s + +## Usage + +Simply load the app and you'll see a menu with the menu items +you defined. Select one and you'll be able to connect to the device +and send the command. + +If a command should wait for a response then diff --git a/apps/espruinoctrl/app-icon.js b/apps/espruinoctrl/app-icon.js new file mode 100644 index 000000000..70d2dd062 --- /dev/null +++ b/apps/espruinoctrl/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwhH+AH4A/AH4A/AH4AFwIuuAAIllAAYIGF041IF34AKqwuuAANXF9QuCAANdGHqQgGBwvdGCIud5mjGB4udAAIwPFz3MSR61VFxQwNci4vGeh4uXGAguHGBK3WGA4AIegtXc69dGBxoBGAouWO4IwNe4gwZa4YwLFwikEFzAwLFwwwCFzQwKFw68YGB4AdF5AwmF5IwlF5QwkF5Yw/F8IwEL9WBB4IuuADwuzGxAugFAgliGBYutAH4A/AH4A/ADA=")) diff --git a/apps/espruinoctrl/app.png b/apps/espruinoctrl/app.png new file mode 100644 index 0000000000000000000000000000000000000000..900861e43729a5385ffe8352888915c2d4653c50 GIT binary patch literal 1302 zcmV+x1?l>UP)?ZmN^iIB{MNu%(l4E0-}r2scX4p zZrw1(#6MHOm~3N<^2fPpB5Z!d9|jg#m#vI$ktK7+tYJWmOVlMQo7Rn@K(&-XbOZWz zk3XQ@rK7#~;ss3X^N;f$&ig#?Ip@BoFOWnMNhGn9U`tIP9-3_q9)vC9%XK>&%gaOY z{Qi>yX2>50pk=_RvE{lK;)&2MCb1)SyIu%rod8zfu}C;nx5K>Wu+6cR2yGE=1XSq; z$NT`SbH!XV0Zpx^vxESBfw{;70K@L4V-5omo{r%a7C4-X7k42`hyfq~IB2)ulO9a@ z3Pg`8j1eY=n)>Z#TcS-=M`L3n_v4LV3j?`I*KYhkz~q+zTctTIPPKDAq#BiqGYI#%2kDC|EL>uR?`e=qc0AO@{e6y?H zeL-m)Mld(GISxwssV+bWQyYN4#kN03d=hXuHC43@pO|a+8O8Rw$b(SD%KV-28{1c!AQOE=RH>=}p64}`x2gq%S2&_` z=GPj^Z?A@HMCAP-JkQGfosm^VUngSUhqx3|{SJ#qO#w_;R@@4Poil%DazJM^6UM;X z01jjN+-sZ-umAm4zERUv*RP**NUwOky84D(Qi@8bbnS*u^*K2mG3HDTI2#ecHU@r* z_y2S;Z4(G*N^*x%8#Z(x_MY&KjX&FcspnNCoMa1VYCWALVCwusMTM4SdVOr;MMX%F z2apZ`2L14WK|j0=z^z$+gkmU|l4S|_*mhROrOj9vsaHUC!h**eKQ!MMw)^ z*rPOPQQ=Bco<28rRL0dR#PBMxPngM%+`4 zLp}_!gin18_(2;+Wz0ytAmo7r0+@j3Fq?dcF<9%YTec=>?4Py4(387r%%iHZOn|s0 zWVhQj!vXD4Oux%Zz7j7L681o&)2Y=BjvXaNol>vFNhFa(68}&91AovF7oUbDTL1t6 M07*qoM6N<$g0ps59{>OV literal 0 HcmV?d00001 diff --git a/apps/espruinoctrl/custom.html b/apps/espruinoctrl/custom.html new file mode 100644 index 000000000..e6297cf2e --- /dev/null +++ b/apps/espruinoctrl/custom.html @@ -0,0 +1,275 @@ + + + + + + + + +

    Enter the menu items you'd like to see appear in the app below. MAC Address is the MAC address + of the device to use. If it isn't specified then a menu will be presented showing available devices.

    +
    + + + + + + + + + + + + +
    TitleCommandMAC AddressRX
    +
    +

    + + + + + + From 7647a7a92135e44bc28f9e8a2cfc98903d452a17 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 24 Jun 2020 10:13:00 +0100 Subject: [PATCH 1177/1189] Add new draw styles, tidy up draw functionality --- apps.json | 2 +- apps/numerals/ChangeLog | 3 +- apps/numerals/numerals.app.js | 51 ++++++++++++++++++++---------- apps/numerals/numerals.settings.js | 16 +++++----- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/apps.json b/apps.json index eb9b7b6a3..793dad65f 100644 --- a/apps.json +++ b/apps.json @@ -1333,7 +1333,7 @@ "name": "Numerals Clock", "shortName": "Numerals Clock", "icon": "numerals.png", - "version":"0.07", + "version":"0.08", "description": "A simple big numerals clock", "tags": "numerals,clock", "type":"clock", diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index b4dbae3e6..2869074a6 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -4,4 +4,5 @@ 0.04: Don't overwrite existing settings on app update 0.05: Fix settings issue 0.06: Improve rendering of Numeral 1, fix issue with alarms not showing up -0.07: Add date on touch and some improvements (see settings and readme) \ No newline at end of file +0.07: Add date on touch and some improvements (see settings and readme) +0.08: Add new draw styles, tidy up draw functionality diff --git a/apps/numerals/numerals.app.js b/apps/numerals/numerals.app.js index e84793536..49a41732e 100644 --- a/apps/numerals/numerals.app.js +++ b/apps/numerals/numerals.app.js @@ -8,7 +8,7 @@ var numerals = { 0:[[9,1,82,1,90,9,90,92,82,100,9,100,1,92,1,9],[30,25,61,25,69,33,69,67,61,75,30,75,22,67,22,33]], - 1:[[50,1,82,1,90,9,90,92,82,100,73,100,65,92,65,27,50,27,42,19,42,9]], + 1:[[50,1,82,1,90,9,90,92,82,100,73,100,65,92,65,27,50,27,42,19,42,9]], 2:[[9,1,82,1,90,9,90,53,82,61,21,61,21,74,82,74,90,82,90,92,82,100,9,100,1,92,1,48,9,40,70,40,70,27,9,27,1,19,1,9]], 3:[[9,1,82,1,90,9,90,92,82,100,9,100,1,92,1,82,9,74,70,74,70,61,9,61,1,53,1,48,9,40,70,40,70,27,9,27,1,19,1,9]], 4:[[9,1,14,1,22,9,22,36,69,36,69,9,77,1,82,1,90,9,90,92,82,100,78,100,70,92,70,61,9,61,1,53,1,9]], @@ -24,18 +24,33 @@ var _mCol = ["#55ff55","#ffffff","#00EFEF","#FFBF00"]; var _rCol = 0; var interval = 0; const REFRESH_RATE = 10E3; +var drawFuncs = { + fill : function(poly,isHole){ + if (isHole) g.setColor(0); + g.fillPoly(poly,true); + }, + framefill : function(poly,isHole){ + var c = g.getColor(); + g.setColor(isHole ? 0 : ((c&0b1111011111011110)>>1)); // 16 bit half bright + g.fillPoly(poly,true); + g.setColor(c); + g.drawPoly(poly,true); + }, + frame : function(poly,isHole){ + g.drawPoly(poly,true); + }, + thickframe : function(poly,isHole){ + g.drawPoly(poly,true); + g.drawPoly(translate(1,0,poly),true); + g.drawPoly(translate(1,1,poly),true); + g.drawPoly(translate(0,1,poly),true); + } +}; function translate(tx, ty, p){ - return p.map((x, i)=> x+((i%2)?ty:tx)); + return p.map((x, i)=> x+((i&1)?ty:tx)); } -function fill(poly){ - return g.fillPoly(poly,true); -} - -function frame(poly){ - return g.drawPoly(poly,true); -} let settings = require('Storage').readJSON('numerals.json',1); if (!settings) { @@ -47,13 +62,13 @@ if (!settings) { }; } -function drawNum(num,col,x,y,func){ +function drawNum(num,col,x,y,func,funcName){ g.setColor(col); let tx = x*100+25; let ty = y*104+32; for (let i=0;i0) g.setColor((func==fill)?"#000000":col); - func(translate(tx,ty,numerals[num][i])); + g.setColor(col); + func(translate(tx,ty,numerals[num][i]), i>0); } } @@ -69,11 +84,13 @@ function draw(date){ l1 = ("0"+(_12hour?d.getHours()%12:d.getHours())).substr(-2); l2 = ("0"+d.getMinutes()).substr(-2); } + var drawFunc = drawFuncs[settings.drawMode]; + if (drawFunc==undefined) drawFunc=drawFuncs.fill; g.clearRect(0,24,240,240); - drawNum(l1[0],_hCol[_rCol],0,0,eval(settings.drawMode)); - drawNum(l1[1],_hCol[_rCol],1,0,eval(settings.drawMode)); - drawNum(l2[0],_mCol[_rCol],0,1,eval(settings.drawMode)); - drawNum(l2[1],_mCol[_rCol],1,1,eval(settings.drawMode)); + drawNum(l1[0],_hCol[_rCol],0,0,drawFunc); + drawNum(l1[1],_hCol[_rCol],1,0,drawFunc); + drawNum(l2[0],_mCol[_rCol],0,1,drawFunc); + drawNum(l2[1],_mCol[_rCol],1,1,drawFunc); } function setUpdateInt(set){ @@ -100,4 +117,4 @@ Bangle.on('lcdPower', function(on){ }); Bangle.loadWidgets(); -Bangle.drawWidgets(); \ No newline at end of file +Bangle.drawWidgets(); diff --git a/apps/numerals/numerals.settings.js b/apps/numerals/numerals.settings.js index 278d7edc7..991abc888 100644 --- a/apps/numerals/numerals.settings.js +++ b/apps/numerals/numerals.settings.js @@ -1,5 +1,5 @@ -(function(back) { - function updateSettings() { +(function(back) { + function updateSettings() { storage.write('numerals.json', numeralsSettings); } function resetSettings() { @@ -14,26 +14,26 @@ let numeralsSettings = storage.readJSON('numerals.json',1); if (!numeralsSettings) resetSettings(); if (numeralsSettings.menuButton===undefined) numeralsSettings.menuButton=22; - let dm = ["fill","frame"]; + let dm = ["fill","frame","framefill","thickframe"]; let col = ["rnd","r/g","y/w","o/c","b/y"]; let btn = [[24,"BTN1"],[22,"BTN2"],[23,"BTN3"],[11,"BTN4"],[16,"BTN5"]]; var menu={ "" : { "title":"Numerals"}, "Colors": { value: 0|numeralsSettings.color, - min:0,max:4, + min:0,max:col.length-1, format: v=>col[v], onchange: v=> { numeralsSettings.color=v; updateSettings();} }, - "Draw mode": { + "Draw": { value: 0|dm.indexOf(numeralsSettings.drawMode), - min:0,max:1, + min:0,max:dm.length-1, format: v=>dm[v], onchange: v=> { numeralsSettings.drawMode=dm[v]; updateSettings();} }, "Menu button": { value: btn.findIndex(e=>e[0]==numeralsSettings.menuButton), - min:0,max:4, + min:0,max:btn.length-1, format: v=>btn[v][1], onchange: v=> { numeralsSettings.menuButton=btn[v][0]; updateSettings();} }, @@ -46,4 +46,4 @@ "< back": back }; E.showMenu(menu); -}) \ No newline at end of file +}) From ab30d2dd6bf9f2c424d4cd90f1cb18c9de2d60b9 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 24 Jun 2020 10:20:39 +0100 Subject: [PATCH 1178/1189] launcher 0.04: Now displays widgets --- apps.json | 2 +- apps/launch/ChangeLog | 1 + apps/launch/app.js | 15 ++++++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 793dad65f..d55450d57 100644 --- a/apps.json +++ b/apps.json @@ -41,7 +41,7 @@ "name": "Launcher (Default)", "shortName":"Launcher", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", "tags": "tool,system,launcher", "type":"launch", diff --git a/apps/launch/ChangeLog b/apps/launch/ChangeLog index fe5aa9d0e..7e7ea65ab 100644 --- a/apps/launch/ChangeLog +++ b/apps/launch/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Only store relevant app data (saves RAM when many apps) 0.03: Allow scrolling to wrap around (fix #382) +0.04: Now displays widgets diff --git a/apps/launch/app.js b/apps/launch/app.js index b20c808a1..9795d8901 100644 --- a/apps/launch/app.js +++ b/apps/launch/app.js @@ -1,5 +1,5 @@ var s = require("Storage"); -var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src}}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)); +var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)); apps.sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first @@ -17,10 +17,13 @@ function drawMenu() { var n = 3; if (selected>=n+menuScroll) menuScroll = 1+selected-n; if (selectedn+menuScroll) g.fillPoly([120,239,100,219,140,219]); - else g.clearRect(100,219,140,239); + // arrows + g.setColor(menuScroll ? -1 : 0); + g.fillPoly([120,6,106,20,134,20]); + g.setColor((apps.length>n+menuScroll) ? -1 : 0); + g.fillPoly([120,233,106,219,134,219]); + // draw + g.setColor(-1); for (var i=0;i Date: Thu, 25 Jun 2020 07:55:44 +0100 Subject: [PATCH 1179/1189] gpsrec: Ensure we don't turn GPS off if it was previously on (eg from another app/widget) --- apps.json | 2 +- apps/gpsrec/ChangeLog | 3 ++- apps/gpsrec/widget.js | 11 ++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 9ee115218..7a12e551c 100644 --- a/apps.json +++ b/apps.json @@ -344,7 +344,7 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.10", + "version":"0.11", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 489e2d366..8e4a8931c 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -10,4 +10,5 @@ 0.09: Change default GPS period to 10 (1 is overkill for most uses and makes things slow) Added RAM keyword to functions & other tweaks to speed up rendering Going 'back' from track view now doesn't load again -0.10: Can now graph altitude & speed +0.10: Can now graph altitude & speed +0.11: Ensure we don't turn GPS off if it was previously on (eg from another app/widget) diff --git a/apps/gpsrec/widget.js b/apps/gpsrec/widget.js index dae613cd2..3281ebbf9 100644 --- a/apps/gpsrec/widget.js +++ b/apps/gpsrec/widget.js @@ -4,6 +4,7 @@ var fixToggle = false; // toggles once for each reading var gpsTrack; // file for GPS track var periodCtr = 0; + var gpsOn = false; // draw your widget function draw() { @@ -45,17 +46,21 @@ settings.file |= 0; Bangle.removeListener('GPS',onGPS); + var gOn = false; if (settings.recording) { WIDGETS["gpsrec"].width = 24; - Bangle.on('GPS',onGPS); - Bangle.setGPSPower(1); + Bangle.on('GPS', onGPS); var n = settings.file.toString(36); gpsTrack = require("Storage").open(".gpsrc"+n,"a"); + gOn = true; } else { WIDGETS["gpsrec"].width = 0; - Bangle.setGPSPower(0); gpsTrack = undefined; } + if (gOn != gpsOn) { + Bangle.setGPSPower(gOn); + gpsOn = gOn; + } } // add the widget WIDGETS["gpsrec"]={area:"tl",width:24,draw:draw,reload:function() { From 25bd4fb752f7b216ae8ef87c5c971a26080b5727 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Thu, 25 Jun 2020 18:35:56 +0100 Subject: [PATCH 1180/1189] Create README.md --- apps/widancs/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/widancs/README.md diff --git a/apps/widancs/README.md b/apps/widancs/README.md new file mode 100644 index 000000000..ed041f1ea --- /dev/null +++ b/apps/widancs/README.md @@ -0,0 +1 @@ +temporary From d69d6098a4394d856cb1cd95da38029fed950ecd Mon Sep 17 00:00:00 2001 From: jeffmer Date: Thu, 25 Jun 2020 18:39:00 +0100 Subject: [PATCH 1181/1189] Add files via upload --- apps/widancs/ChangeLog | 8 ++ apps/widancs/README.md | 71 +++++++++- apps/widancs/ancs.js | 264 +++++++++++++++++++++++++++++++++++ apps/widancs/ancs.min.js | 10 ++ apps/widancs/call_pic.jpg | Bin 0 -> 38261 bytes apps/widancs/message_pic.jpg | Bin 0 -> 48987 bytes apps/widancs/missed_pic.jpg | Bin 0 -> 36388 bytes apps/widancs/settings.js | 61 ++++++++ apps/widancs/widget.png | Bin 0 -> 1944 bytes apps/widancs/widget_pic.jpg | Bin 0 -> 50792 bytes 10 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 apps/widancs/ChangeLog create mode 100644 apps/widancs/ancs.js create mode 100644 apps/widancs/ancs.min.js create mode 100644 apps/widancs/call_pic.jpg create mode 100644 apps/widancs/message_pic.jpg create mode 100644 apps/widancs/missed_pic.jpg create mode 100644 apps/widancs/settings.js create mode 100644 apps/widancs/widget.png create mode 100644 apps/widancs/widget_pic.jpg diff --git a/apps/widancs/ChangeLog b/apps/widancs/ChangeLog new file mode 100644 index 000000000..7844830d1 --- /dev/null +++ b/apps/widancs/ChangeLog @@ -0,0 +1,8 @@ +0.01: New Widget! +0.02: Version using connect back +0.03: Version using modified firmware +0.04: Works on both standard and modified firmware +0.05: Bug fixes w.r.t. reconnection +0.06: Update README - Release version + + diff --git a/apps/widancs/README.md b/apps/widancs/README.md index ed041f1ea..d3ee0bdc4 100644 --- a/apps/widancs/README.md +++ b/apps/widancs/README.md @@ -1 +1,70 @@ -temporary +## ANCS - iPhone notifications for Bangle.js + +The ANCS widget allows you to answer or cancel iPhone incoming calls and also displays messages and notifications. It connects to the Apple Notification Center Service which is already on all iPhones, so you do not need to install any additional iPhone apps to use this widget. + +## Firmware +The widget will run on the standard firmware, however, installation of a slightly modified version - the zip file is available from [this directory](https://github.com/jeffmer/JeffsBangleAppsDev/tree/master/apps/widancs) - will increase the performance of the app by an order of magnitude in terms of the time to connect or reconnect to the iPhone. In addition, the Bangle will stay connected to the iPhone over a greater separation distance than with the standard firmware. + + +![](widget_pic.jpg) + +## Installation + +After the widget is uploaded to the Bangle, it needs to be enabled in the Bangle Settings app:- `ANCS Widget` will appear in `APP/Widget settings`. There is also a menu in these settings to let you configure the categories of notifications that you want to be displayed. You must disconnect from the App Loader before enabling the widget. + +## Compatible Apps + +The widget will only run with a compatible app - for the reason for this see Issue 1 below. The apps that are compatible with the ANCS widget are:- **Multi Clock**, **Navigation Compass** and **GPS Navigation**. When you switch to an app that is not compatible, the ANCS phone icon will not appear. + +## iPhone Pairing +Once enabled, the widget icon should be displayed coloured grey (its green in the photo). Go to the phone's Bluetooth settings menu and your Bangle should appear under Other devices. If this is the first time you have connected with the Bangle from your iPhone, it may be named Accessory. Click on the name and the iPhone should connect and start pairing. The widget icon will turn red and the iPhone will ask you to enter a pairing code - the traditional 123456. You have 10 seconds to enter this after which you will need to start pairing again. After that, the iPhone may also ask to allow the device access to ANCS. Once pairing is complete, the widget icon should go blue and eventually green. The range of colours is: + +* **Grey** - not connected - advertising +* **Red** - connected - not paired. +* **Blue** - paired and connected - getting services +* **Yellow** - got Services. +* **Green** - waiting for new notifications. + +After pairing the first time, the Bangle should connect automatically when the widget is running. Sometimes you may need you to click on the Bangle name in `Settings:Bluetooth:My devices` on the iPhone or disable and then enable Bluetooth to start connection. If you need to load other apps from the iPhone, it will be necessary to ask the iPhone to forget the pairing and you will also need to disable the widget in Settings and restart the Bangle by turning it off in Settings and then pressing BTN1 to restart. If you are loading apps from a different device, you simply need to turn off the iPhone bluetooth which will retain the pairing. You still need to disable the widget and restart the Bangle. + +![](message_pic.jpg) + +## Messages & Calls +Messages are displayed as shown above until BTN2 is pressed to dismiss it. I strongly advise disabling the BTN2 LCD wake function in the Settings App as otherwise when the screen times out and you press BTN2 to wake the LCD, the screen will turn on and the Message Alert will be dismissed!. Calls can be answered or dropped. + +![](call_pic.jpg) ![](missed_pic.jpg) + + +## Issues +1. With GadgetBridge, the Android phone has a Central-Client role with the Bangle as Peripheral-Server. With the ANCS widget there is the fairly unusual situation in which the Bangle is Peripheral-Client to the iPhone's Central-Server role. Since Espruino does not deal explicitly with Bangle as Peripheral-Client an additional function has been added in the modified firmware: `var gatt = NRF.getGattforCentralServer(addr);`. This returns a bluetooth remote GATT server given the address of the iPhone which has just connected to the Bangle. With the standard firmware, the widget reconnects to the iPhone as a Client - however this has greatly degraded performance. See [Issue 1800.](https://github.com/espruino/Espruino/issues/1800) for more details. + +2. When the Bangle switches apps, all state - including widget state - is lost unless explicitly stored. The consequence of this is that when the Bangle switches apps, the connection to iPhone has to be re-established to restore the remote GATT server and characteristics state. This is quite slow. To minimise reconnection, the widget needs to grab the screen from the running app to signal messages and calls. To allow this to work, the app needs to implement the `SCREENACCESS` interface. In essence, the widget only connects when running with compatible apps that implement this interface. An example implementation is: + +``` +var SCREENACCESS = { + withApp:true, + request:function(){ + this.withApp=false; + stopdraw(); //clears redraw timers etc + clearWatch(); //clears button handlers + }, + release:function(){ + this.withApp=true; + startdraw(); //redraw app screen, restart timers etc + setButtons(); //install button event handlers + } +} + +Bangle.on('lcdPower',function(on) { + if (!SCREENACCESS.withApp) return; + if (on) { + startdraw(); + } else { + stopdraw(); + } +}); +``` + +## Support + +Please report bugs etc. by raising an issue [here](https://github.com/jeffmer/JeffsBangleAppsDev). \ No newline at end of file diff --git a/apps/widancs/ancs.js b/apps/widancs/ancs.js new file mode 100644 index 000000000..84a79fbf9 --- /dev/null +++ b/apps/widancs/ancs.js @@ -0,0 +1,264 @@ +(() => { + + var s = require("Storage").readJSON("widancs.json",1)||{settings:{enabled:false, category:[1,2,4]}}; + var ENABLED = s.settings.enabled; + var CATEGORY = s.settings.category; + + function advert(){ + NRF.setAdvertising([ + 0x02, //length + 0x01, //flags + 0x06, // + 0x11, //length + 0x15, //solicited Service UUID + 0xD0,0x00,0x2D,0x12,0x1E,0x4B, + 0x0F,0xA4, + 0x99,0x4E, + 0xCE,0xB5, + 0x31,0xF4,0x05,0x79],{connectable:true,discoverable:true,interval:375}); + } + + var state = { + gatt:null, + ancs:null, + current:{cat:0,uid:0}, + notqueue:[], + msgTO:undefined, + com:new Uint8Array([0,0,0,0,0,1,20,0,3,100,0]), + buf:new Uint8Array(132), + inp:0, + store:function(b){ + var i = this.inp; + if (i+b.length<=132){ + this.buf.set(b,i); + this.inp+=b.length; + } + }, + gotmsg:function(){ + var n = this.inp; + var vw = DataView(this.buf.buffer); + if (n<8) return null; + var tn=vw.getUint16(6,true); + if (n<(tn+8)) return null; + var mn=vw.getUint16(9+tn,true); + if (n<(mn+tn+11)) return null; + return {tlen:tn, mlen:mn}; + } + }; + + //stop advertising when peripheral link disconnected + if (!NRF.getGattforCentralServer && ENABLED && typeof SCREENACCESS!='undefined') + NRF.on('disconnect',function(reason){ + NRF.sleep(); + }); + + if (ENABLED && typeof SCREENACCESS!='undefined') + NRF.on('connect',function(addr){ + if(NRF.getGattforCentralServer) + do_bond(NRF.getGattforCentralServer(addr)); + else + NRF.connect(addr).then(do_bond); + }); + + function do_bond(g) { + var tval, ival; + state.gatt = g; + function cleanup(){ + drawIcon(0); //disconnect from iPhone + delete state.gatt; + delete state.ancs; + if(!NRF.getGattforCentralServer) NRF.disconnect(); + setTimeout(()=>{NRF.wake();},500); + } + drawIcon(1); //connect from iPhone + state.gatt.device.on('gattserverdisconnected', function(reason) { + if (ival) clearInterval(ival); + if (tval) clearInterval(tval); + cleanup(); + }); + E.on("kill",function(){ + state.gatt.disconnect().then(function(){NRF.sleep();}); + }); + NRF.setSecurity({passkey:"123456",mitm:1,display:1}); + tval = setTimeout(function(){ + if (ival) clearInterval(ival); + state.gatt.disconnect().then(cleanup); + },10000); + state.gatt.startBonding().then(function(){ + ival = setInterval(function(){ + var sec = state.gatt.getSecurityStatus(); + if (!sec.connected) {clearInterval(ival); clearTimeout(tval); return;} + if (sec.connected && sec.encrypted){ + clearInterval(ival); + clearTimeout(tval); + drawIcon(2); //bonded to iPhone + do_ancs(); + return; + } + },1000); + }).catch(function(e){ + Terminal.println("ERROR "+e); + }); + } + + function do_ancs() { + state.ancs = {primary:null, notify:null, control:null, data:null}; + state.gatt.getPrimaryService("7905F431-B5CE-4E99-A40F-4B1E122D00D0").then(function(s) { + state.ancs.primary=s; + return s.getCharacteristic("9FBF120D-6301-42D9-8C58-25E699A21DBD"); + }).then(function(c) { + state.ancs.notify=c; + return state.ancs.primary.getCharacteristic("69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9"); + }).then(function(c) { + state.ancs.control=c; + return state.ancs.primary.getCharacteristic("22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB"); + }).then(function(c) { + state.ancs.data =c; + drawIcon(3);//got remote services + state.ancs.notify.on('characteristicvaluechanged', function(ev) { + getnotify(ev.target.value); + }); + state.ancs.data.on('characteristicvaluechanged', function(e) { + state.store(e.target.value.buffer); + var inds = state.gotmsg(); + if (inds) printmsg(state.buf,inds); + }); + state.ancs.notify.startNotifications().then(function(){ + state.ancs.data.startNotifications().then(function(){ + drawIcon(4); //ready for messages + }); + }); + }).catch(function(e){ + Terminal.println("ERROR "+e); + }); + } + + function wordwrap(s){ + var txt = s.split("\n"); + var MAXCHARS = 18; + for (var i = 0; i < txt.length; i++) { + txt[i] = txt[i].trim(); + var l = txt[i]; + if (l.length > MAXCHARS) { + var p = MAXCHARS; + while (p > MAXCHARS - 8 && !" \t-_".includes(l[p])) + p--; + if (p == MAXCHARS - 8) p = MAXCHARS; + txt[i] = l.substr(0, p); + txt.splice(i + 1, 0, l.substr(p)); + } + } + return txt.join("\n"); + } + + + var buzzing =false; + var screentimeout = undefined; + var inalert = false; + + function release_screen(){ + screentimeout= setTimeout(() => { + SCREENACCESS.release(); + screentimeout = undefined; + inalert=false; + next_notify(); + }, 500); + } + + function printmsg(buf,inds){ + + function send_action(tf){ + var bb = new Uint8Array(6); + var v = DataView(bb.buffer); + v.setUint8(0,2); + v.setUint32(1,state.current.uid,true); + v.setUint8(5,tf?0:1 ); + state.ancs.control.writeValue(bb).then(release_screen); + } + + if (state.msgTO) clearTimeout(state.msgTO); + var title=""; + for (var i=8;i<8+inds.tlen; ++i) title+=String.fromCharCode(buf[i]); + var message = ""; + for (var j=11+inds.tlen;j<11+inds.tlen+inds.mlen;++j) { + message+=String.fromCharCode(buf[j]); + } + message = wordwrap(message); + //we may already be displaying a prompt, so clear it + E.showPrompt(); + if (screentimeout) clearTimeout(screentimeout); + Bangle.setLCDPower(true); + SCREENACCESS.request(); + if (!buzzing){ + buzzing=true; + Bangle.buzz(500).then(()=>{buzzing=false;}); + } + if (state.current.cat!=1){ + E.showAlert(message,title).then(send_action.bind(null,false)); + } else { + E.showPrompt(message,{title:title,buttons:{"Accept":true,"Cancel":false}}).then(send_action); + } + } + + var notifyTO; + function getnotify(d){ + var eid = d.getUint8(0); + var ct = d.getUint8(2); + var id = d.getUint32(4,true); + if (eid>1) return; + if (notifyTO) clearTimeout(notifyTO); + if(!CATEGORY.includes(ct)) return; + var len = state.notqueue.length; + if (ct == 1) { // it's a call so pre-empt + if (inalert) {state.notqueue.push(state.current); inalert=false;} + state.notqueue.push({cat:ct, uid:id}); + } else if (len<16) + state.notqueue[len] = {cat:ct, uid:id}; + notifyTO = setTimeout(next_notify,1000); + } + + function next_notify(){ + if(state.notqueue.length==0 || inalert) return; + inalert=true; + state.current = state.notqueue.pop(); + var v = DataView(state.com.buffer); + if (state.current.cat==6) v.setUint8(8,2); else v.setUint8(8,3);//get email title + v.setUint32(1,state.current.uid,true); + state.inp=0; + state.ancs.control.writeValue(state.com).then(function(){ + state.msgTO=setTimeout(()=>{ + inalert=false; + state.msgTO=undefined; + next_notify(); + },1000); + }); + } + + var stage = 5; + //grey, pink, lightblue, yellow, green + function draw(){ + var colors = new Uint16Array([0xc618,0xf818,0x3ff,0xffe0,0x07e0,0x0000]); + var img = E.toArrayBuffer(atob("GBgBAAAABAAADgAAHwAAPwAAf4AAP4AAP4AAP4AAHwAAH4AAD8AAB+AAA/AAAfgAAf3gAH/4AD/8AB/+AA/8AAf4AAHwAAAgAAAA")); + g.setColor(colors[stage]); + g.drawImage(img,this.x,this.y); + } + + WIDGETS["ancs"] ={area:"tl", width:24,draw:draw}; + + function drawIcon(id){ + stage = id; + WIDGETS["ancs"].draw(); + } + + if (ENABLED && typeof SCREENACCESS!='undefined') { + stage = 0; + NRF.setServices(undefined,{uart:false}); + NRF.sleep(); + NRF.wake(); + advert(); + } + + })(); + + + \ No newline at end of file diff --git a/apps/widancs/ancs.min.js b/apps/widancs/ancs.min.js new file mode 100644 index 000000000..8ccf58e61 --- /dev/null +++ b/apps/widancs/ancs.min.js @@ -0,0 +1,10 @@ +(function(){function t(a){function e(){k(0);delete b.gatt;delete b.ancs;NRF.getGattforCentralServer||NRF.disconnect();setTimeout(function(){NRF.wake()},500)}var d;b.gatt=a;k(1);b.gatt.device.on("gattserverdisconnected",function(a){d&&clearInterval(d);c&&clearInterval(c);e()});E.on("kill",function(){b.gatt.disconnect().then(function(){NRF.sleep()})});NRF.setSecurity({passkey:"123456",mitm:1,display:1});var c=setTimeout(function(){d&&clearInterval(d);b.gatt.disconnect().then(e)},1E4);b.gatt.startBonding().then(function(){d= + setInterval(function(){var a=b.gatt.getSecurityStatus();a.connected?a.connected&&a.encrypted&&(clearInterval(d),clearTimeout(c),k(2),v()):(clearInterval(d),clearTimeout(c))},1E3)})["catch"](function(a){Terminal.println("ERROR "+a)})}function v(){b.ancs={primary:null,notify:null,control:null,data:null};b.gatt.getPrimaryService("7905F431-B5CE-4E99-A40F-4B1E122D00D0").then(function(a){b.ancs.primary=a;return a.getCharacteristic("9FBF120D-6301-42D9-8C58-25E699A21DBD")}).then(function(a){b.ancs.notify= + a;return b.ancs.primary.getCharacteristic("69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9")}).then(function(a){b.ancs.control=a;return b.ancs.primary.getCharacteristic("22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB")}).then(function(a){b.ancs.data=a;k(3);b.ancs.notify.on("characteristicvaluechanged",function(a){var e=a.target.value,c=e.getUint8(0);a=e.getUint8(2);e=e.getUint32(4,!0);1c&&(b.notqueue[c]={cat:a,uid:e}),m=setTimeout(n,1E3)))});b.ancs.data.on("characteristicvaluechanged",function(a){b.store(a.target.value.buffer);(a=b.gotmsg())&&x(b.buf,a)});b.ancs.notify.startNotifications().then(function(){b.ancs.data.startNotifications().then(function(){k(4)})})})["catch"](function(a){Terminal.println("ERROR "+a)})}function y(a){a=a.split("\n");for(var b=0;b=b+a.length&&(this.buf.set(a,b),this.inp+=a.length)},gotmsg:function(){var a=this.inp,b= + DataView(this.buf.buffer);if(8>a)return null;var d=b.getUint16(6,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
    02>j;{(SMl!lEw5#*1akQbA7`+x|ZP!v_#hS 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 F|JkZ80w@3g literal 0 HcmV?d00001 diff --git a/apps/widancs/missed_pic.jpg b/apps/widancs/missed_pic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c9d958ec662deffeb4d17b701e49252c386c270a GIT binary patch literal 36388 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 BI+6eY literal 0 HcmV?d00001 diff --git a/apps/widancs/settings.js b/apps/widancs/settings.js new file mode 100644 index 000000000..8964d560c --- /dev/null +++ b/apps/widancs/settings.js @@ -0,0 +1,61 @@ +(function(back) { + const ANCSFILE = "widancs.json"; + + // initialize with default settings... + let s = { + 'enabled': false, + 'category':[1,2,4] + }; + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage'); + const d = storage.readJSON(ANCSFILE, 1) || {}; + const saved = d.settings || {}; + for (const key in saved) { + s[key] = saved[key]; + } + + function save() { + d.settings = s; + storage.write(ANCSFILE, d); + } + + function setcategory(){ + const names = ["Other","Call ","Missed Call","Voicemail","Messages ","Calendar","Email","News ","Fitness ","Busniness","Location ","Entertainment"]; + function hascat(n){return s.category.includes(n);} + function setcat(n,v){ + if (v) + s.category.push(n); + else + s.category = s.category.filter((v,i,a)=>{return v!=n;}); + } + const menu = { + '': { 'title': 'Set Categories' } + }; + for (var i=0; iv?'Yes':'No', + onchange:setcat.bind(null,i) + }; + menu['< Back'] = ()=>{save(); showMain();}; + return E.showMenu(menu); + } + + function showMain(){ + return E.showMenu({ + 'Enable ANCS': { + value: s.enabled, + format: () => (s.enabled ? 'Yes' : 'No'), + onchange: () => { + s.enabled = !s.enabled; + save(); + }, + }, + 'Set Category':setcategory, + '< Back': back, + }); + } + + showMain(); +}); \ No newline at end of file diff --git a/apps/widancs/widget.png b/apps/widancs/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f57cc1eb635beca19aaea029907faf39cf5eca GIT binary patch literal 1944 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 GIb_Foo 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Μ{XY7F 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 literal 0 HcmV?d00001 From f1fcc6ff5a509df62bb16521f59f3ee444dded77 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Thu, 25 Jun 2020 18:44:21 +0100 Subject: [PATCH 1182/1189] Update apps.json --- apps.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps.json b/apps.json index 7a12e551c..7c705bc6d 100644 --- a/apps.json +++ b/apps.json @@ -2019,5 +2019,19 @@ {"name":"txt.face.js","url":"txt.min.js"}, {"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true} ] + }, + { "id": "widancs", + "name": "Apple Notification Widget", + "shortName":"ANCS Widget", + "icon": "widget.png", + "version":"0.06", + "description": "Displays call, message etc notifications from a paired iPhone. Read README before installation as it only works with compatible apps", + "readme": "README.md", + "tags": "widget", + "type": "widget", + "storage": [ + {"name":"widancs.wid.js","url":"ancs.min.js"}, + {"name":"widancs.settings.js","url":"settings.js"} + ] } ] From dcf8c6c1f3df14d116bb6ee4ff8f14b32bf69b87 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 26 Jun 2020 09:26:41 +0100 Subject: [PATCH 1183/1189] Add workaround for https://github.com/espruino/Espruino/issues/1868 since 2v06 firmware has the issue --- lib/espruinotools.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/espruinotools.js b/lib/espruinotools.js index 0e8df02cb..245035ce7 100644 --- a/lib/espruinotools.js +++ b/lib/espruinotools.js @@ -6605,6 +6605,8 @@ To add a new serial device, you must add an object to var tokenString = code.substring(tok.startIdx, tok.endIdx); var tokenId = LEX_OPERATOR_START + TOKENS.indexOf(tokenString); if (tokenId Date: Fri, 26 Jun 2020 22:56:54 +0200 Subject: [PATCH 1184/1189] Added first version of CRP Assist app --- apps.json | 25 ++++++++++ apps/cprassist/ChangeLog | 1 + apps/cprassist/README.md | 24 +++++++++ apps/cprassist/cprassist-icon.js | 1 + apps/cprassist/cprassist-icon.png | Bin 0 -> 4037 bytes apps/cprassist/cprassist.js | 79 ++++++++++++++++++++++++++++++ apps/cprassist/settings.js | 64 ++++++++++++++++++++++++ 7 files changed, 194 insertions(+) create mode 100644 apps/cprassist/ChangeLog create mode 100644 apps/cprassist/README.md create mode 100644 apps/cprassist/cprassist-icon.js create mode 100644 apps/cprassist/cprassist-icon.png create mode 100644 apps/cprassist/cprassist.js create mode 100644 apps/cprassist/settings.js diff --git a/apps.json b/apps.json index 7c705bc6d..bd8731ff5 100644 --- a/apps.json +++ b/apps.json @@ -2033,5 +2033,30 @@ {"name":"widancs.wid.js","url":"ancs.min.js"}, {"name":"widancs.settings.js","url":"settings.js"} ] + }, + { + "id": "cprassist", + "name":"CPR Assist", + "icon":"cprassist-icon.png", + "version": "0.01", + "readme": "README.md", + "description": "Provides assistance while performing a CPR", + "tags": "tool,firstaid", + "allow_emulator": true, + "storage": [ + { + "name": "cprassist.app.js", + "url": "cprassist.js" + }, + { + "name": "cprassist.img", + "url": "cprassist-icon.js", + "evaluate": true + }, + { + "name": "cprassist.settings.js", + "url": "settings.js" + } + ] } ] diff --git a/apps/cprassist/ChangeLog b/apps/cprassist/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/cprassist/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/cprassist/README.md b/apps/cprassist/README.md new file mode 100644 index 000000000..569f61149 --- /dev/null +++ b/apps/cprassist/README.md @@ -0,0 +1,24 @@ +# CPR Assist + +Provides assistance while performing a CPR + +## Usage + +The app alternates between the phases for +chest compression and rescue breaths in an in an endless loop. +In the chest compression phase the the watch will provide a +buzz at a rate of 100 rpm for 30 repetitions. +A longer buzz introduces an interval of 4 seconds to perform +2 rescue breaths. +A ratio of chest compressions to rescue breaths is also +displayed in the bottom of the screen. + +The number of repetitions for chest compression and +rescue breaths, the rpm rate and the duration of the +rescue breath phase can be adjusted in the settings. +See e.g. [CPR on Wikipedia](https://en.wikipedia.org/wiki/Cardiopulmonary_resuscitation) +for futher information and updates on the recommendations. + +## Attributions + +Icon source: https://commons.wikimedia.org/wiki/File:ISO_7010_E003_-_First_aid_sign.svg diff --git a/apps/cprassist/cprassist-icon.js b/apps/cprassist/cprassist-icon.js new file mode 100644 index 000000000..ec4667a8c --- /dev/null +++ b/apps/cprassist/cprassist-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4Arg93AB1wC/dxkQACi4XRuf/AAU3C/4X/C+sTmYABn4XD+YICmIXJl4TDAA/yC/4X/C+LXXAAdzC4c3BQgX/C/4X0uMiAAUXC6IAKC+wA/AH4AkA==")) diff --git a/apps/cprassist/cprassist-icon.png b/apps/cprassist/cprassist-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c39962aaaf641c1e3d907d9d1855330fbb74c45b GIT binary patch literal 4037 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 rGobwpFvIe`e@6ZeGc1n)06 0 + ? SHORT_BUZZ_PERIOD + : LONG_BUZZ_PERIOD; + try { + Bangle.buzz(period, 1.0); + } catch(err) { + } +} + +function drawHeart() { + g.fillCircle(40, 92, 12); + g.fillCircle(60, 92, 12); + g.fillPoly([29, 98, 50, 120, 71, 98]); +} + +function updateScreen() { + const colors = [0xFFFF, 0x9492]; + g.reset().clearRect(0, 50, 250, 150); + if (counter > 0) { + g.setFont("Vector", 40).setFontAlign(0, 0); + g.setColor(colors[counter%2]); + drawHeart(); + g.drawString(counter + "", g.getWidth()/2, 100); + } else { + g.setFont("Vector", 20).setFontAlign(0, 0); + g.drawString("RESCUE", g.getWidth()/2, 70); + g.drawString("BREATHS", g.getWidth()/2, 120); + } +} + +function tick() { + provideFeedback(); + updateScreen(); + if (counter == 0) { + var reset = function() { + counter = setting('compression_count'); + clearInterval(interval); + interval = setInterval(tick, 60000/setting('compression_rpm')); + }; + clearInterval(interval); + interval = setInterval(reset, setting('breath_period_sec')*1000); + } + counter -= 1; +} + +interval = setInterval(tick, 60000/setting('compression_rpm')); + +g.clear(1).setFont("6x8"); +g.drawString(setting('compression_count') + ' / ' + setting('breath_count'), 30, 200); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); diff --git a/apps/cprassist/settings.js b/apps/cprassist/settings.js new file mode 100644 index 000000000..5776baa0b --- /dev/null +++ b/apps/cprassist/settings.js @@ -0,0 +1,64 @@ +// This file should contain exactly one function, which shows the app's settings +/** + * @param {function} back Use back() to return to settings menu + */ +(function(back) { + const SETTINGS_FILE = 'cprassist.settings.json'; + + // initialize with default settings... + let s = { + 'compression_count': 30, + 'breath_count': 2, + 'compression_rpm': 100, + 'breath_period_sec': 4 + }; + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage'); + const saved = storage.readJSON(SETTINGS_FILE, 1) || {}; + for (const key in saved) { + s[key] = saved[key]; + } + + // creates a function to safe a specific setting + function save(key) { + return function(value) { + s[key] = value; + storage.write(SETTINGS_FILE, s); + }; + } + + const menu = { + '': { 'title': 'CPR Assist' }, + '< Back': back, + 'chest compr.': { + value: s.compression_count, + min: 1, + max: 200, + step: 1, + onchange: save('compression_count'), + }, + 'rescue breaths': { + value: s.breath_count, + min: 0, + max: 100, + step: 1, + onchange: save('breath_count'), + }, + 'rpm': { + value: s.compression_rpm, + min: 1, + max: 200, + step: 10, + onchange: save('compression_rpm'), + }, + 'breaths period': { + value: s.breath_period_sec, + min: 1, + max: 60, + step: 1, + onchange: save('breath_period_sec'), + } + }; + E.showMenu(menu); +}); From f319cff2bcd68845827c8dd686d35232b0cd6e25 Mon Sep 17 00:00:00 2001 From: tebarius Date: Sun, 28 Jun 2020 21:03:05 +0200 Subject: [PATCH 1185/1189] Modification of SimpleClock to use Vectorfont --- apps.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps.json b/apps.json index 7c705bc6d..9672a657b 100644 --- a/apps.json +++ b/apps.json @@ -674,6 +674,19 @@ {"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true} ] }, + { "id": "svclock", + "name": "Simple V-Clock", + "icon": "vclock-simple.png", + "version":"0.01", + "description": "Modification of Simple Clock 0.04 to use Vectorfont", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"svclock.app.js","url":"vclock-simple.js"}, + {"name":"svclock.img","url":"vclock-simple-icon.js","evaluate":true} + ] + }, { "id": "dclock", "name": "Dev Clock", "icon": "clock-dev.png", From 65cb9b46ba94d7704287313d50b1a566a7e8d081 Mon Sep 17 00:00:00 2001 From: tebarius Date: Sun, 28 Jun 2020 21:04:16 +0200 Subject: [PATCH 1186/1189] Modification of SimpleClock to use Vectorfont --- apps/svclock/ChangeLog | 1 + apps/svclock/vclock-simple-icon.js | 1 + apps/svclock/vclock-simple.js | 84 +++++++++++++++++++++++++++++ apps/svclock/vclock-simple.png | Bin 0 -> 590 bytes 4 files changed, 86 insertions(+) create mode 100644 apps/svclock/ChangeLog create mode 100644 apps/svclock/vclock-simple-icon.js create mode 100644 apps/svclock/vclock-simple.js create mode 100644 apps/svclock/vclock-simple.png diff --git a/apps/svclock/ChangeLog b/apps/svclock/ChangeLog new file mode 100644 index 000000000..b585cb6ed --- /dev/null +++ b/apps/svclock/ChangeLog @@ -0,0 +1 @@ +0.01: Modification aof SimpleClock 0.04 to use Vectorfont diff --git a/apps/svclock/vclock-simple-icon.js b/apps/svclock/vclock-simple-icon.js new file mode 100644 index 000000000..b41bd6fcc --- /dev/null +++ b/apps/svclock/vclock-simple-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATiwAGFdYzlFp4xeFyYwZD49kxGt2fX6+z1uIsgxcDQtAxArCAA+zxFAGDAYFxAsJAAuIGCxcF1ouPAAOsGCouERRSUKSYguoGARgRCIiMSAAutGCDqUABNkF5yNEFzKRQLzwABxAvRdgYFBDgYFFBphgEF5lkEJwNOYIaORF7KQMBYetEJoDHAo+sF56+DF7TAMBYaBQBpwv/R97vvxCPdxAvLGAdkF7tkFxbAIF7C+MSBQAXRxovEoAvboAvNMD69DFxYvEi2sFy+sDwgvLGAryDACTsEFxrCGGCmzXh5gJSSaMFF6AwGshiPdQguSGA8WxAxK2eIRYguUGBBjBxGsGYWz1mILYwuWGJQANFq4wWFzQxSFrozNFcYA/AH4Av")) diff --git a/apps/svclock/vclock-simple.js b/apps/svclock/vclock-simple.js new file mode 100644 index 000000000..2af8b74a4 --- /dev/null +++ b/apps/svclock/vclock-simple.js @@ -0,0 +1,84 @@ +/* jshint esversion: 6 */ +const timeFontSize = 65; +const dateFontSize = 20; +const gmtFontSize = 10; +const font = "Vector"; + +const xyCenter = g.getWidth() / 2; +const yposTime = 75; +const yposDate = 130; +const yposYear = 175; +const yposGMT = 220; + +// Check settings for what type our clock should be +var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; + +function drawSimpleClock() { + g.clear(); + Bangle.drawWidgets(); + + // get date + var d = new Date(); + var da = d.toString().split(" "); + + g.reset(); // default draw styles + // drawSting centered + g.setFontAlign(0, 0); + + // draw time + var time = da[4].substr(0, 5).split(":"); + var hours = time[0], + minutes = time[1]; + var meridian = ""; + if (is12Hour) { + hours = parseInt(hours,10); + meridian = "AM"; + if (hours == 0) { + hours = 12; + meridian = "AM"; + } else if (hours >= 12) { + meridian = "PM"; + if (hours>12) hours -= 12; + } + hours = (" "+hours).substr(-2); + } + + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, true); + g.setFont(font, gmtFontSize); + g.drawString(meridian, xyCenter + 102, yposTime + 10, true); + + // draw Day, name of month, Date + var date = [da[0], da[1], da[2]].join(" "); + g.setFont(font, dateFontSize); + + g.drawString(date, xyCenter, yposDate, true); + + // draw year + g.setFont(font, dateFontSize); + g.drawString(d.getFullYear(), xyCenter, yposYear, true); + + // draw gmt + var gmt = da[5]; + g.setFont(font, gmtFontSize); + g.drawString(gmt, xyCenter, yposGMT, true); +} + +// handle switch display on by pressing BTN1 +Bangle.on('lcdPower', function(on) { + if (on) drawSimpleClock(); +}); + +// clean app screen +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// refesh every 15 sec +setInterval(drawSimpleClock, 15E3); + +// draw now +drawSimpleClock(); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); diff --git a/apps/svclock/vclock-simple.png b/apps/svclock/vclock-simple.png new file mode 100644 index 0000000000000000000000000000000000000000..824062aedaded6605ecab000d555a519557ddd50 GIT binary patch literal 590 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s`2jv5u0Wb$%|V8>2N~8JVpx5U zVcj8yHTxJ=?PXYX48#RWtv&!EAqdC@i9l^T=394*!|0D^)Q|n3+{bZ=Ml6vn$cx?FmfJu z=|nYGZBG7NyFkWYu9|`GKL@vI-P>F}efgxFEK8y>zXwnKEyp^E(ahAYZiIW>)3mr6OV%r$25F}!S;>jsvYc^>)ZPo1~z znD6MiRJZ4K82{t2){WNhq8oRJukHH%<#y|%xX8>Waa|v8ZV YS?g0SGc5aa6O=GKUHx3vIVCg!0Fhi2)Bpeg literal 0 HcmV?d00001 From a9f691cfea8374e834f9790d409d4b2f0ba9928b Mon Sep 17 00:00:00 2001 From: tebarius Date: Sun, 28 Jun 2020 21:16:25 +0200 Subject: [PATCH 1187/1189] misspelling --- apps/svclock/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/svclock/ChangeLog b/apps/svclock/ChangeLog index b585cb6ed..a9e0036a3 100644 --- a/apps/svclock/ChangeLog +++ b/apps/svclock/ChangeLog @@ -1 +1 @@ -0.01: Modification aof SimpleClock 0.04 to use Vectorfont +0.01: Modification of SimpleClock 0.04 to use Vectorfont From 3f74e96bc5e00c47ab0bac4f4bdd9888d627f0da Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 29 Jun 2020 08:39:11 +0100 Subject: [PATCH 1188/1189] verticalclock 0.05: Stop hours being displayed wrong if moving from 2 digits to 1 (fix #516) --- apps.json | 2 +- apps/verticalface/ChangeLog | 1 + apps/verticalface/app.js | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 59869c68e..040fa2088 100644 --- a/apps.json +++ b/apps.json @@ -1900,7 +1900,7 @@ "name": "Vertical watch face", "shortName":"Vertical Face", "icon": "app.png", - "version":"0.04", + "version":"0.05", "description": "A simple vertical watch face with the date.", "tags": "clock", "type":"clock", diff --git a/apps/verticalface/ChangeLog b/apps/verticalface/ChangeLog index 19d763698..c30b02411 100644 --- a/apps/verticalface/ChangeLog +++ b/apps/verticalface/ChangeLog @@ -1 +1,2 @@ 0.04: Fixed day being displayed +0.05: Stop hours being displayed wrong if moving from 2 digits to 1 (fix #516) diff --git a/apps/verticalface/app.js b/apps/verticalface/app.js index aa6441e79..52c8e47a7 100644 --- a/apps/verticalface/app.js +++ b/apps/verticalface/app.js @@ -8,7 +8,7 @@ function drawTimeDate() { var h = d.getHours(), m = d.getMinutes(), day = d.getDate(), month = d.getMonth(), weekDay = d.getDay(); var daysOfWeek = ["SUN", "MON", "TUE","WED","THU","FRI","SAT"]; - var hours = h; + var hours = (" "+h).substr(-2); var mins= ("0"+m).substr(-2); var date = `${daysOfWeek[weekDay]}|${day}|${("0"+(month+1)).substr(-2)}`; @@ -151,4 +151,4 @@ Bangle.on('HRM', function(hrm) { //Bangle.on('step', function(up) { // console.log("Step"); -//}); \ No newline at end of file +//}); From b172017f2e07d99cffa0beb99c77e19234031513 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 30 Jun 2020 22:48:00 +0200 Subject: [PATCH 1189/1189] gbridge: Don't keep LCD on while playing music Looks like this fell through during the 'notify' upgrade. Some apps can keep the LCD pretty much awake all the time with "position" updates. --- apps.json | 2 +- apps/gbridge/ChangeLog | 1 + apps/gbridge/widget.js | 21 ++++++++++++++------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index 040fa2088..da3b04799 100644 --- a/apps.json +++ b/apps.json @@ -121,7 +121,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.14", + "version":"0.15", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index 124f2f001..8277b3479 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -13,3 +13,4 @@ 0.12: Setting to show/hide icon 0.13: Modified to use the 'notify' library 0.14: Added 'find' event handling +0.15: Don't keep LCD on while playing music \ No newline at end of file diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 0741fcb58..b2f169985 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -29,25 +29,32 @@ Bangle.buzz(); } - function handleMusicStateUpdate(event) { - const changed = state.music === event.state - state.music = event.state - + function updateMusic(options){ if (state.music === "play") { - require("notify").show({size:40, render:y => { + require("notify").show(Object.assign({size:40, render:y => { g.setColor(-1); g.drawImage(require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")), 8, y + 8); g.setFontAlign(-1, -1); var x = 40; g.setFont("4x6", 2).drawString(state.musicInfo.artist, x, y + 8); g.setFont("6x8", 1).drawString(state.musicInfo.track, x, y + 22); - }}); + }}, options)); } if (state.music === "pause") { require("notify").hide(); } } + function handleMusicStateUpdate(event) { + if (state.music !== event.state) { + state.music = event.state + updateMusic({on: true}); + } + } + function handleMusicInfoUpdate(event) { + state.musicInfo = event; + updateMusic({on: false}); + } function handleCallEvent(event) { if (event.cmd === "accept") { @@ -77,7 +84,7 @@ handleNotificationEvent(event); break; case "musicinfo": - state.musicInfo = event; + handleMusicInfoUpdate(event); break; case "musicstate": handleMusicStateUpdate(event);