From e4866595255020ee823893da47190c61ad9de021 Mon Sep 17 00:00:00 2001 From: Erovia Date: Wed, 21 Feb 2024 20:45:50 +0000 Subject: [PATCH] First version of the C25K app --- apps/c25k/ChangeLog | 1 + apps/c25k/README.md | 70 +++++++++++++ apps/c25k/app-icon.js | 1 + apps/c25k/app.js | 216 +++++++++++++++++++++++++++++++++++++++ apps/c25k/app.png | Bin 0 -> 376 bytes apps/c25k/c25k-scrn1.png | Bin 0 -> 2792 bytes apps/c25k/c25k-scrn2.png | Bin 0 -> 2766 bytes apps/c25k/c25k-scrn3.png | Bin 0 -> 2404 bytes apps/c25k/c25k-scrn4.png | Bin 0 -> 3055 bytes apps/c25k/c25k-scrn5.png | Bin 0 -> 3042 bytes apps/c25k/c25k-scrn6.png | Bin 0 -> 5865 bytes apps/c25k/c25k-scrn7.png | Bin 0 -> 3397 bytes apps/c25k/metadata.json | 28 +++++ 13 files changed, 316 insertions(+) create mode 100644 apps/c25k/ChangeLog create mode 100644 apps/c25k/README.md create mode 100644 apps/c25k/app-icon.js create mode 100644 apps/c25k/app.js create mode 100644 apps/c25k/app.png create mode 100644 apps/c25k/c25k-scrn1.png create mode 100644 apps/c25k/c25k-scrn2.png create mode 100644 apps/c25k/c25k-scrn3.png create mode 100644 apps/c25k/c25k-scrn4.png create mode 100644 apps/c25k/c25k-scrn5.png create mode 100644 apps/c25k/c25k-scrn6.png create mode 100644 apps/c25k/c25k-scrn7.png create mode 100644 apps/c25k/metadata.json diff --git a/apps/c25k/ChangeLog b/apps/c25k/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/c25k/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/c25k/README.md b/apps/c25k/README.md new file mode 100644 index 000000000..8be8c2e15 --- /dev/null +++ b/apps/c25k/README.md @@ -0,0 +1,70 @@ +# C25K + +Unofficial app for the Couch to 5k training plan. +From being a couch-potato to running 5k in 8 weeks! + +Each week has 3 training days, ideally with rest days between them. + +Each day's programme consists of running for a certain time with occasional walking/resting phases. +When walking is part of the programme, the (run+walk) stages are repeated a number of times. + +![](c25k-scrn1.png) +![](c25k-scrn2.png) +![](c25k-scrn3.png) + +## Features + +- Show remaining time in seconds for each phase +- Vibrates on phase changes +- Keeps screen on to allow quickly glancing at the time while running +- Shows time on button press + +## Usage + +If you know the week and day of the programme you'd like to start, set `Week` and `Day` to the appropriate values in the main menu and press `Start`. + +**Example**: +To start the programme of the **second day** of **week 4**: +![](c25k-scrn4.png) + +--- + +Alternatively, you can go to the `View plan` menu to look at all the programmes and select the one you'd like to start. + +**Example**: +Go to the `View plan` menu: +![](c25k-scrn5.png) + +Select the programme to start it: +![](c25k-scrn6.png) + +--- + +The format of the `View menu` is `w{week}d{day}(r:{run mins}|w:{walk mins}|x{number of reps})`. + +For example `w6d1(r:6|w:3|x2)` means: +`it's the programme of day 1 on week 6`, +`it consists of running for 6 minutes`, +`followed by walking for 3`, +`done 2 times back to back`. + +--- + +### Show the time: + +If you ever need to peek at the time, just press the middle (or only) physical button on the watch: +![](c25k-scrn7.png) + +--- + +## Disclaimer + +This app was hacked together in a day with no JS knowledge. +It's probably inefficient and buggy, but it does what I needed it to do: allow me to follow the C25K programme without a phone. + +The app was designed with a Bangle.js 1 in mind, as that's the one I have. +It *should* work fine on the Bangle.js 2, but I couldn't test it on real hardware. + +--- + +Made with <3 by [Erovia](https://github.com/Erovia) diff --git a/apps/c25k/app-icon.js b/apps/c25k/app-icon.js new file mode 100644 index 000000000..6b85dbf29 --- /dev/null +++ b/apps/c25k/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AoPk9G9gsj14lZhWq0AEBgtVqALmhQJBAQMFBIICCBc4ADBQYLnAQQKEBcibETQIABHggLiAEQqEh/wgACCBcpXDBAIKDBcqJDh//BQYLkHwg7GBcY7FU5ALgAEQA=")) diff --git a/apps/c25k/app.js b/apps/c25k/app.js new file mode 100644 index 000000000..bbc0c606e --- /dev/null +++ b/apps/c25k/app.js @@ -0,0 +1,216 @@ +var week = 1; +var day = 1; +var time; + +var loop; // To store how many times we will have to do a countdown +var counter = 0; // To keep count of how many iterations we have in the current countdown +var currentMode; // Either "run" or "walk" +var mainInterval; // Ticks every second, checking if a new countdown is needed +var activityInterval; // Ticks every second, doing the countdown +var buttonWatch; // Watch for button presses + +function outOfTime() { + // Buzz 3 times on state transitions + Bangle.buzz(500) + .then(() => new Promise(resolve => setTimeout(resolve, 200))) + .then(() => Bangle.buzz(500)) + .then(() => new Promise(resolve => setTimeout(resolve, 200))) + .then(() => Bangle.buzz(500)); + + // Once we're done + if (loop == 0) { + clearWatch(buttonWatch); // Don't watch for button presses anymore + g.setBgColor("#75C0E0"); // Blue background for the "Done" text + g.clear(); + g.drawString("Done", g.getWidth()/2, g.getHeight()/2); // Write "Done" to screen + g.reset(); + setTimeout(E.showMenu, 5000, mainmenu); // Show the main menu again after 5secs + clearInterval(mainInterval); // Stop the main interval from starting a new activity + mainInterval = undefined; + } +} + +function countDown() { + text = (currentMode === "run") ? "Run\n" + counter : "Walk\n" + counter; // Switches output text + if (time) text += "\n" + time; + g.clear(); + g.setFontAlign(0,0); // center font + if (process.env.HWVERSION == 2) { // To accomodate the Bangle.js 2 screen + if (time) { + g.setFont("6x8",5); // when time is shown + } + else { + g.setFont("6x8",7); // when time is not shown + } + } + else { + g.setFont("6x8",8); // bitmap font, 8x magnified + } + g.drawString(text, g.getWidth() / 2, g.getHeight() / 2); // draw the current mode and seconds + Bangle.setLCDPower(1); // keep the watch LCD lit up + + counter--; // Reduce the seconds + + // If the current activity is done + if (counter < 0) { + clearInterval(activityInterval); + activityInterval = undefined; + outOfTime(); + return; + } +} + +function startTimer(w, d) { + // If something is already running, do nothing + if (activityInterval) { + return; + } + + // Switches between the two modes + if (!currentMode || currentMode === "walk") { + currentMode = "run"; + counter = PLAN[w][d].run * 60; + g.setBgColor("#ff5733"); + } + else { + currentMode = "walk"; + counter = PLAN[w][d].walk * 60; + g.setBgColor("#4da80a"); + } + + countDown(); + if (!activityInterval) { + loop--; // Reduce the number of iterations + activityInterval = setInterval(countDown, 1000); // Start a new activity + } +} + +function showTime() { + if (time) return; // If clock is already shown, don't do anything even if the button was pressed again + // Get the time and format it with a leading 0 if necessary + var d = new Date(); + var h = d.getHours(); + var m = d.getMinutes(); + time = h + ":" + m.toString().padStart(2, 0); + setTimeout(function() { time = undefined; }, 5000); // Hide clock after 5secs +} + +// Populate the PLAN menu +function populatePlan() { + for (var i = 0; i < PLAN.length; i++) { + for (var j = 0; j < PLAN[i].length; j++) { + // Ever line will have the following format: + // w{week}d{day}(r:{run mins}|w:{walk mins}|x{number of reps}) + var name = "w" + (i + 1) + "d" + (j + 1); + if (process.env.HWVERSION == 2) { + name += "\n"; // Print in 2 lines to accomodate the Bangle.js 2 screen + } + name += "(r:" + PLAN[i][j].run; + if ("walk" in PLAN[i][j]) name += "|w:" + PLAN[i][j].walk; + if ("repetition" in PLAN[i][j]) name += "|x" + PLAN[i][j].repetition; + name += ")"; + // Each menu item will have a function that start the program at the selected day + planmenu[name] = getFunc(i, j); + } + } +} + +// Helper function to generate functions for the PLAN menu +function getFunc(i, j) { + return function() { + week = i + 1; + day = j + 1; + startActivity(); + }; +} + +function startActivity() { + var w = week - 1; + var d = day - 1; + + if ("walk" in PLAN[w][d]) { + loop = PLAN[w][d].repetition * 2; + } + else { + loop = 1; + } + E.showMenu(); // Hide the main menu + buttonWatch = setWatch(showTime, (process.env.HWVERSION == 2) ? BTN1 : BTN2, {repeat: true}); // Show the clock on button press + mainInterval = setInterval(function() {startTimer(w, d);}, 1000); // Check every second if we need to do something +} + +const PLAN = [ + [ + {"run": 1, "walk": 1.5, "repetition": 8}, + {"run": 1, "walk": 1.5, "repetition": 8}, + {"run": 1, "walk": 1.5, "repetition": 8}, + ], + [ + {"run": 1.5, "walk": 2, "repetition": 6}, + {"run": 1.5, "walk": 2, "repetition": 6}, + {"run": 1.5, "walk": 2, "repetition": 6}, + ], + [ + {"run": 2, "walk": 2, "repetition": 5}, + {"run": 2.5, "walk": 2.5, "repetition": 4}, + {"run": 2.5, "walk": 2.5, "repetition": 4}, + ], + [ + {"run": 3, "walk": 2, "repetition": 5}, + {"run": 3, "walk": 2, "repetition": 5}, + {"run": 4, "walk": 2.5, "repetition": 3}, + ], + [ + {"run": 5, "walk": 2, "repetition": 3}, + {"run": 8, "walk": 5, "repetition": 2}, + {"run": 20}, + ], + [ + {"run": 6, "walk": 3, "repetition": 2}, + {"run": 10, "walk": 3, "repetition": 2}, + {"run": 25}, + ], + [ + {"run": 25}, + {"run": 25}, + {"run": 25}, + ], + [ + {"run": 30}, + {"run": 30}, + {"run": 30}, + ], +]; + +// Main menu +var mainmenu = { + "" : { + "title" : "-- C25K --" + }, + "Week" : { + value : week, + min:1,max:PLAN.length,step:1, + onchange : v => { week = v; } + }, + "Day" : { + value : day, + min:1,max:3,step:1, + onchange : v => { day = v; } + }, + "View plan" : function() { E.showMenu(planmenu); }, + "Start" : function() { startActivity(); }, + "Exit" : function() { load(); }, +}; + +// Plan view +var planmenu = { + "" : { + title : "-- Plan --", + back : function() { E.showMenu(mainmenu);}, + } +}; + +// Populate the PLAN menu view +populatePlan(); +// Actually display the menu +E.showMenu(mainmenu); diff --git a/apps/c25k/app.png b/apps/c25k/app.png new file mode 100644 index 0000000000000000000000000000000000000000..6b3a9ba95ad9dd9e8d87d1df39cc4bf2d18b58bc GIT binary patch literal 376 zcmV-;0f+vHP)Px$GD$>1RA@u(Sj!E`AScVN4kquae8;Bd~2<1X6)hKz-B$Sjst~Q4E zvE!r(A#`EJpJq7#&TU$!!^)-OW4ll0uWuKs9oLiQIk z*J-qUqG{$o$OOQ*|4RYHK&^59PFyL1{{>Kb?49nrk%q_3HK{3^A5}mA%)=DRXfF$! zzZ?b7GYA?|h*1=e)u$B@05FB50NU4)$C1S>!?qqe7qWXm089@^0eB}yo-uLs%7CT} zio1Kj`Tv6eIJecF;9~cI>J;#<)82Cc&3(2f=v@f)ga8H8|H|QM?3*lv-L7>d-XOaLEN&a&t-h;)^pr*coT~uzTj5 zJ>S`HzVrY8=Bvxg-OFM`F#rHyWoGQor^cm?hwe|kxi6SMpa!rqfA21!=a;Q!0ARFb z?tZ$Uy3}&!n}gAXoBTTK#p2l1r*_x2HHc4UGtjeLPu90Q>s&uNa>2jInR(n}{bObt zi}A#Pfd!#!ZN#a{C;I*5VR^#Hr=bzQ@UNy|1l6w zd_Xnvu$ovv{f-B+4=gX$CxY;yfNgm>eC3JSed0iN-_BU&D-feNE$wVJUwI7-3=hjQ zUZ1_c1Y+C@%1}3>P-L*~W@w(Uihu7{|E_>;$ZL~T9anh2m@zEifox8+77`q}M1vTc zjPAr2gjwSfK3@r@!5vGV;(p=Hp>|eIU{Nrg%|T6DnlFB?qN<)Xp2B&!JUv!T04kA? zp_618-4LREP_JthD2k92bOmuFmvtdhfsFhb(t{mvE_2U3rowJyJL*JTNxVW~Dt||8 zw?ZO6oivrOG>z3woYff;3Hy7Pc8t566aqGSJZ!+GOz}xNesmTgK8r?$e(5gs}I<7A)>9KdKYGGAp{i--c7^ zMl=VZL&|au>5lqatUKy*uX5IZ0`72dxE}gd6=r?8XZ4}vXrM$`B$D%X>7!rjE(DHY z*0YXBG%>AiIxFSvL{4|@vYY-KxNyn2`Lq?gkCTqwKpbY%&3H;IZasO(+bCKqR>m96 zaFz}y1+q}iT(+ZAk!o1LtSl^n1E*>DW-?jPg+LwBPObwn&A0_avz2fMibt}2r)3h2 zNmIDTEIqFnOOf^v;Y)VtoJsHMQxe`{D0y{z?&=p)-F2CZPb1>4u(E)jd!6`8N*cv z?*O`SA6J5V3yrnG8A^<+z9wZ{_>otIi#SDCnA{V$ft}l*zfW1x2lRi0D62@*f}OQz zzH*m=Xx#j9p%7S9#GivEC6XU3o@DRve8k!;&H9l2_UglOYC3@vEj$lcNV98f13`Ty z=!#1$r|vK(;Bq3rMxLs*N+@l=9;r^}wUiy!Kuy8pYXgDoB@0>Oe3NP%xcom1RM#6=Qp5KSgp!b6RF9jpC-;IaYZxSCIqgq!W N^V!_pJ-dWQ{sN33V2%I) literal 0 HcmV?d00001 diff --git a/apps/c25k/c25k-scrn2.png b/apps/c25k/c25k-scrn2.png new file mode 100644 index 0000000000000000000000000000000000000000..ba064200e28f4350e0c001fff4b4f3911d63b464 GIT binary patch literal 2766 zcmeHJZBQH66_u7%twn@2{Uo0G(bmgMG;7=5CTFL2n&6)+OGJ~PW!X{ z*YwBkn>X*gd*_^c-L0&1ndSV~@YxH0EJ?AZYVb+%B=Q8@H z_Bk1h__qu5a>`Vd?)h)u>dsF(>-ZJ_cGZO+3>2h3^;~gwVp3x3>iyQesiEJxCXTF5 z|Ebnn_xyK~u`SXdrGgF-o2R^m3qWC8drwkOzyw|g!JS;5$Ke^g!9d&$;3||DRI1MB zYw>ypG6AyHS!W)kiDlVZ`~m<9_jUd?i8rucOdMqb2X{(b?8MofJY_2b*>zQa5oEu) zBQdK;i(j2Ep9a98IQG7DF)`t&-p>TA%&%S=;$Z_}r?$opd0Jrd!3dhEkM_9q(V=N* z^e+B$^67#%6z97h+3U#Tl>ZcB;C{ak1qUIEO!{u~ddI4fQrPS> zZ&{Z?TZ!!Vn&hWHK6&Kas$xX*9vtbwtm@BdsyEki!Bnb0_Cc*k)?3q%}2ID zaWCc!S4Z8ofPz0zE`n~&weR_s?_`DOGptFN>8WQ}eTKLim%?l9vp;D!NeBm=c;Phe zTvu=gE8zDOktTo}oZLUR=O;!@#_T4&YsJlX5;Q0drhB?%W;FdM0-cfnjR-(RGGJHy z39|a1kZ#;5DYQNwqH>y#+w0(dizM=*3}{3!-T)bQ1$R(CyVsOciXYb2+59>aI%QUy z$+1e&(jv=GqsDN!gfLQIv9}xTa;n44FZ=!-P)Tgwe)8jKy>$4I#U&v8TZaz{22y4@ zk6E3Kh!xek$xW^@tTs~Xm2jh}9u`JfHB3X`b=*z5qgW&94$YA~WhkR=uXqF-liA0j ze)VChu0#fiNDP7YY4QfOL+g4}YhHG5$>HsDxv)}3Ckb)@EBuZQd+X1}W1iP47s%`D>Y318W#{dsmCBN$yEfodK zZ$&JG+Dk{N?3LE0Az?npXm zj&iq)$rrlS*VY^Qu@|JDqf=uzP1TbE_Q2xw9P_CdQ9zG!VNIu|ITR95>pzNckNYed z(Pw&-s5$yZ{%GvNKuXqFnur4QDQjlwhbZ4`sYw^Y?hFws32Ur&{jzmR7wq=7zzDZX zvMY-<(@AFyaP6Dq5LSkfnpN1SS#80uoeO2uheE2RM B$YCoWw@B1b2Rmu_P#zI4 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 F`ybNL9sU3S literal 0 HcmV?d00001 diff --git a/apps/c25k/c25k-scrn5.png b/apps/c25k/c25k-scrn5.png new file mode 100644 index 0000000000000000000000000000000000000000..ca32abdfa9f9e3911d3a1bd48752f491af1aa2d8 GIT binary patch literal 3042 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 literal 0 HcmV?d00001 diff --git a/apps/c25k/c25k-scrn6.png b/apps/c25k/c25k-scrn6.png new file mode 100644 index 0000000000000000000000000000000000000000..53f5221d70b4c7ebd9b7346923008b1e05328f5d GIT binary patch literal 5865 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 literal 0 HcmV?d00001 diff --git a/apps/c25k/c25k-scrn7.png b/apps/c25k/c25k-scrn7.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc8ebd3c157555d1bb3f83dcedd0a32191b1b0f GIT binary patch literal 3397 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 fIX{h17}yc;*5#MqzfjKp7Xcf7k(S)F4lVyH(h