From 46494ebf7b96eaf5618f9e4eb5e8e2fff9951575 Mon Sep 17 00:00:00 2001 From: Keith Irwin Date: Wed, 6 Nov 2024 10:02:16 -0700 Subject: [PATCH] Bug fixes and upgrades to pokertimer --- apps/pokertimer/ChangeLog | 7 ++++- apps/pokertimer/README.md | 27 ++++++++++++++++-- apps/pokertimer/ROADMAP.md | 17 ----------- apps/pokertimer/app.img | Bin 714 -> 0 bytes apps/pokertimer/app.js | 26 ++++++++++++++--- apps/pokertimer/metadata.json | 6 ++-- .../screenshots/01_paused-start.png | Bin 0 -> 2820 bytes .../screenshots/02_counting-down.png | Bin 0 -> 3322 bytes apps/pokertimer/screenshots/03_blinds-up.png | Bin 0 -> 3551 bytes 9 files changed, 56 insertions(+), 27 deletions(-) delete mode 100644 apps/pokertimer/ROADMAP.md delete mode 100644 apps/pokertimer/app.img create mode 100644 apps/pokertimer/screenshots/01_paused-start.png create mode 100644 apps/pokertimer/screenshots/02_counting-down.png create mode 100644 apps/pokertimer/screenshots/03_blinds-up.png diff --git a/apps/pokertimer/ChangeLog b/apps/pokertimer/ChangeLog index 642dbcc7e..ff87a1708 100644 --- a/apps/pokertimer/ChangeLog +++ b/apps/pokertimer/ChangeLog @@ -1 +1,6 @@ -0.0.1: Packaged app +0.06: Fix bug when play/pause during alert +0.05: Added screenshots +0.04: Added 20-second warning buzz +0.03: Start app with paused timer +0.02: Fix alert buzz time, Indicate when paused +0.01: Packaged app diff --git a/apps/pokertimer/README.md b/apps/pokertimer/README.md index 09aa2d6a1..ce8316def 100644 --- a/apps/pokertimer/README.md +++ b/apps/pokertimer/README.md @@ -1,7 +1,12 @@ # Poker Timer +*v.0.06* A blinds timer for poker. Don't know what that means? See [Wikipedia: Blind (poker)](https://en.wikipedia.org/wiki/Blind_(poker)) and [Wikipedia: Texas hold 'em](https://en.wikipedia.org/wiki/Texas_hold_%27em). +![Screenshot showing countdown paused on start](screenshots/01_paused-start.png) +![Screenshot showing active countdown](screenshots/02_counting-down.png) +![Screenshot showing blinds up alert](screenshots/03_blinds-up.png) + The blinds are hardcoded and go up every ten minutes: - 1, 2 @@ -14,14 +19,32 @@ The blinds are hardcoded and go up every ten minutes: ... and so on, doubling each round. +## Features + +- Starts paused +- Button to pause/resume +- 20-second warning buzz +- Auto-exit after round 25 + ## Usage -The timer will start as soon as you open the app. Time left in the round is on the top of the screen, currnt small and big blinds are shown below. After ten minutes, it will vibrate and flash and show the new blind. Then it starts over. +The timer will start as soon as you open the app. Time left in the round is on the top of the screen, currnt small and big blinds are shown below. After ten minutes, it will vibrate and flash and show the new blind. Then it starts over. + +### Auto-exit + +The program will automatically exit after the 25 round. This is not a bug. If the blinds double again, it will perform some kind of overflow and convert the blind values to floats. + +The blinds in round 25 are `20971520 / 41943040`. You probably aren't still playing poker at that point and just forgot to exit the program. ## Controls - **Pause/Resume:** Press the button - - **Exit:** hold down the button. + - **Exit:** hold down the button + +## Roadmap + +- Set settings +- Better graphics ## Requests diff --git a/apps/pokertimer/ROADMAP.md b/apps/pokertimer/ROADMAP.md deleted file mode 100644 index b182c5b38..000000000 --- a/apps/pokertimer/ROADMAP.md +++ /dev/null @@ -1,17 +0,0 @@ -# Roadmap - -## Bugs - -- Unlock before vibrate/flash - -## Improvements - -- Screenshots in README -- Start app paused -- Indicate when paused -- 20-second warning - -## Long-term projects - -- Set settings -- Better graphics diff --git a/apps/pokertimer/app.img b/apps/pokertimer/app.img deleted file mode 100644 index e2e05ea17aef14d8efd6130ffe6d010ade2347b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 714 zcmb7?KTE?<6va;(trRIj1qG`RC4*9QYmwrRL7`C*ovo0;L7@TNT5xy;LEK7Eadhwl zbgBg%3WDI`Bt;2GR~`KV_1<^WKda&8a?kDWop+KnlX*76w{G`hK6|~C_dciF!MPo{ z|6B$1u4rRVA|+OlK2`|5Ib zY$f(P7@A_V9*EEOeN!QM<57#qa^*3)IT>r2U8A0Q33{Xdtb5 zH+I?)KB?H>uD%yV$6K0r5_h6akNsV1VpX(J*L=;~7EPak{RaU`nja3p{=7oJLF-HN ddcra+3onfJ?D5R-Alfb_bdWUtN`C;?`UC5bn?C>m diff --git a/apps/pokertimer/app.js b/apps/pokertimer/app.js index 26b72c481..9d584b3b2 100644 --- a/apps/pokertimer/app.js +++ b/apps/pokertimer/app.js @@ -1,5 +1,5 @@ -const BLIND_INTERVAL = 600; // 10 minutes -const BLINDSUP_ALERT_DURATION = 5000; // 30 seconds +const BLIND_INTERVAL = 600; // 10 minutes in seconds +const BLINDSUP_ALERT_DURATION = 10000; // 10 seconds in ms // Convert seconds to mm:ss const secondsToMinutes = (s) => { @@ -32,7 +32,13 @@ const stopTimer = () => { timer_running = false; }; const pauseResume = () => { - if (timer_running) stopTimer(); + if (is_alerting) return; + if (timer_running) { + stopTimer(); + g.setFont('Vector',15); + g.drawString('(PAUSED)', + g.getWidth()/2, g.getHeight()*7/8); + } else startTimer(); }; @@ -48,6 +54,7 @@ const getBlinds = (i) => { // Sound the alarm const blindsUp = () => { + is_alerting = true; // Display message const showMessage = () => { g.clear(); @@ -66,7 +73,7 @@ const blindsUp = () => { console.log(`Blinds for round ${b} are ${blinds[0]} / ${blinds[1]}`); // Buzz and light up every second const buzzInterval = setInterval(() => { - Bangle.buzz(); + Bangle.buzz(500); Bangle.setLCDPower(1); }, 1000); // Invert colors every second @@ -82,6 +89,7 @@ const blindsUp = () => { }, 500); // Restart timer setTimeout(() => { + is_alerting = false; fmtDark(); tick(); clearInterval(buzzInterval); clearInterval(flashInterval); @@ -94,6 +102,13 @@ const blindsUp = () => { const tick = () => { if (!timer_running) return; time_left--; + // 20-second warning buzz + if (time_left==20) { + const buzzInterval = setInterval(Bangle.buzz, 500); + setTimeout(() => { + clearInterval(buzzInterval); + }, 5000); + } if (time_left<=0) blindsUp(); else { g.clear(); @@ -120,5 +135,8 @@ let time_left = BLIND_INTERVAL + 1; let b = 0; let blinds = getBlinds(b); let timer_running = true; +let is_alerting = false; let timer = setInterval(tick, 1000); tick(); +// Start paused +pauseResume(); diff --git a/apps/pokertimer/metadata.json b/apps/pokertimer/metadata.json index abdc6e81f..a22229e4f 100644 --- a/apps/pokertimer/metadata.json +++ b/apps/pokertimer/metadata.json @@ -4,12 +4,12 @@ "shortName":"Poker Timer", "readme":"README.md", "icon": "app.png", - "version":"0.0.1", + "version":"0.06", "description": "A blinds timer for use with Texas Hold 'Em", "tags": "poker", "supports": ["BANGLEJS2"], "storage": [ - {"name":"timer.app.js","url":"app.js"}, - {"name":"timer.img","url":"app-icon.js","evaluate":true} + {"name":"pokertimer.app.js","url":"app.js"}, + {"name":"pokertimer.img","url":"app-icon.js","evaluate":true} ] } diff --git a/apps/pokertimer/screenshots/01_paused-start.png b/apps/pokertimer/screenshots/01_paused-start.png new file mode 100644 index 0000000000000000000000000000000000000000..929bd473eb3314b795962c227087d047ca66b673 GIT binary patch literal 2820 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