From a1d46f5e32d6c4dc979f6562b3560a191890918e Mon Sep 17 00:00:00 2001 From: Hans de Zwart Date: Tue, 11 Aug 2026 10:52:35 +0200 Subject: [PATCH] First commit --- public_html/README.md | 67 +++ public_html/icon-192.png | Bin 0 -> 1050 bytes public_html/icon-512.png | Bin 0 -> 3339 bytes public_html/icon-maskable-512.png | Bin 0 -> 2358 bytes public_html/index.html | 683 ++++++++++++++++++++++++++++++ public_html/manifest.webmanifest | 19 + public_html/sw.js | 33 ++ 7 files changed, 802 insertions(+) create mode 100644 public_html/README.md create mode 100644 public_html/icon-192.png create mode 100644 public_html/icon-512.png create mode 100644 public_html/icon-maskable-512.png create mode 100644 public_html/index.html create mode 100644 public_html/manifest.webmanifest create mode 100644 public_html/sw.js diff --git a/public_html/README.md b/public_html/README.md new file mode 100644 index 0000000..1c075e6 --- /dev/null +++ b/public_html/README.md @@ -0,0 +1,67 @@ +# Backgammon Clock + +A two-player match clock with **simple delay you can actually see**. Reserve time +plus a fixed number of free seconds each turn that never carry over — the +Backgammon Galaxy control. Defaults to 3:00 + 15s. + +Plain HTML, CSS and JavaScript. No frameworks, no fonts, no images, no network. + +## Getting it onto your phone + +Chrome will only offer a real install over HTTPS, so the file needs a host. +GitHub Pages is free and takes about two minutes: + +1. Create a new public repository, e.g. `bgclock`. +2. Upload all six files to the root: `index.html`, `manifest.webmanifest`, + `sw.js`, `icon-192.png`, `icon-512.png`, `icon-maskable-512.png`. +3. **Settings → Pages → Source: Deploy from a branch → `main` / `(root)` → Save.** +4. Wait a minute, then open `https://.github.io/bgclock/` in Chrome on Android. +5. Chrome menu (⋮) → **Add to Home screen** → **Install**. + +Open it from the home-screen icon and it runs fullscreen with no browser +chrome, offline, with the screen kept awake while a game is on. + +If you're using a different path than `/bgclock/`, edit the `"id"` field in +`manifest.webmanifest` to match, or just delete that line. + +To try it before hosting, open `index.html` in any browser — everything works +except installation and the service worker. + +## Using it + +- **Tap your own half** to end your turn and start your opponent's clock. + At the start, whoever taps first sets the *other* player going. +- The waiting player's taps are ignored, so a stray hand won't stop the clock. +- The bar under the big time is the delay draining. When it empties you get a + soft tick and your reserve starts moving. That's the moment worth hearing. +- **Reset** returns to the starting position. **Pause** freezes mid-turn and + resumes exactly where it stopped, delay included. + +Backgammon clocks pause between games, and after a cocked die the delay is +normally restarted — use pause and reset for those. + +## Settings + +| Setting | Range | Default | +| --- | --- | --- | +| Time | 0:15 – 99:00 | 3:00 | +| Delay | 0 – 60 s | 15 s | +| Colour | Sage, Brass, Slate, Teal, Plum | Sage | +| Sound | on / off | on | + +Brass is the colour in the chess.com app, if you want the exact original look. +Changing time or delay resets the clock. Settings are remembered on the device. + +## Sounds + +All three are generated with the Web Audio API, so there are no audio files to +download and nothing to attribute. + +- **Turn change** — a soft rising fifth with an octave partial, marimba-like. +- **Delay expiry** — a single quiet 300 Hz tick, deliberately easy to miss unless + you're listening for it. +- **Time out** — a falling triad, loud and unambiguous. + +## Licence + +Do whatever you like with it. diff --git a/public_html/icon-192.png b/public_html/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..6b0478abb876b47923d3819272e1307726803f24 GIT binary patch literal 1050 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zf+;V1DT7;uumf=j~nJBB^u+*NbjT z?=I1ryhgKo1G``9B-aN=wUl#ol&_flWv)FR*>I<+{5SKGN&NTw;@j9iZ~Mx+Va4HV z;sx(YAJ^Z%QLShDe75UGR|dE9)z4=~n6{ZR8`K=Lc$+d+;2Ot)4>Oad3QXex(uWr* z>IgPG+}z^oR59~&H}A3YpVIE$h*1X$ExYO0Z0X1FI9x9RT&;X54^kQY&0`a;;ygsUXVa!&%IYSfI8BRvoe$lHRPa4LUoY<#r^BtK40rzCTz!ArTNZ`4 zwG8k6y}7F|UCuP2Ob)0|)PCDL76o61C3BfRd}^PyJ+XjEK%LMf72pxnGLq^EbnjZr^t;zf_UWjT78dBn z;0`rHD&yJ`EploFH%x36hDXCKO@{oIm6kj}Aqz%OoKANP`Ez5JaKo1Gj25gncE_6m zjRMleY-oK($yO{D$2sm->3>?CNmXq zeOP06_uUO)2Ns*zfwT8MRh__5A+~sX)$3{o!4EI;ZoQadeo*NFD2=Y1&(zuAZk##! zdkv2k6DS$q`(4Z+xMAyVGmGQ=hg=SXy}NhswM@9-pFI<{&)g>$V|?4U{9Sx&fz*aA zk>+OCISbBZ9uN}Sxl>Q@K&QZr!;98yP2+js!r`;=)ajR|OcsJn$!mVu6`f`9JGbA_ u(11s}u40ob!*jjb$BS-kZ~wLAL%qnnND;Ho&TYUv&*16m=d#Wzp$Pz!T&D&A literal 0 HcmV?d00001 diff --git a/public_html/icon-512.png b/public_html/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..50974f2d5d57e0b7cd3ee376ccf1adc5897691c0 GIT binary patch literal 3339 zcmeHKYgAKL7XEG$l0Xs?>F|gkiaIW9K|w1IA4GhiGfH(FwUmINS*S}zGJuE*;ffBl ziqP7TN{IuuGlyz#ro^FPc_I>l>sg zYx66wtXw}Wc%4J5P;-0gVb!b+Qs2&_k-vK=o~hd3rm-*Bx~^L%jvlBi>fYp-*IP0m zz`OsfY@S87B;FskIw+0LeRwfvH!GaSQaD$*8WQW(%MT@&b0{b7M1!B!kT~j zG(u^ee9W4>DNQ6tOGl;dT-QnHQuY#0r!bcPmR=%#iLh}6N~?R=F8U{J#ggL17`fBV z)?}Qa>{$k$PF!P{(Ua5%&k?L1l;m^CR-PjGn%f!ybYg1mSCV`V?J+oHNsP*F#{%M! zm?{g>PS|o48k1N|o(xJ9`6}V0MqTV}iLZVNXu$MS4~}1yBd9NxMO_Mt5&7z@C?mVz zvM#E+mTl-s0$l1&`n2a~z;-l`ts0-2I8}9BK)&QDyi@ggUszGC%?ix6y}UMX4@Z^n zV^5ydEwJ;w#*nDqz86*BNqCMr^U-~LuWqv~dAh|H#pRbmytiZ3a0)@4$ZNbLWh-v` z*x;|8O@&nsxK|c{f}^Lscjn>vvm*pa3D03^bTG2sF( zJ1%7HGtXHB1uuj{Mwy|?Y1RA9Lz)Z=Hn*pw3z>!0(!#&1c|h`VD+W@K?v_1oG6Olg zy)QC!K4Ybwe^xOx0pPzk2MNPG^85zzTW;4U{TFQ z!l0L-^U-OMdK$yf`MlMmpHByI6`{pMC~U=%7X$!jp&hP{vMG62^JYhyzr@GF@7Hv> zb|xT+eFw&VF=DRlITK0;X|J;cNpH=oiX%WyB7lG*4*5z3m&#N67xYUA$g%7}wQAzd zVus$D<{X+1jhQesG&e;vA?#@0-Z1!@*_5BWDR#^i>tR93)%v(G*Hk8CJ$gna;%>*O zBfG~!(s7cTxnvt%&Yek-Wn*y|V#^Xcs0j(ihkbg(3OLI7E{(CDSJ3782q1H14rURM zzh~DEd4CFR*(($H7Z2FfuO?zg+j7iJ!@s4vOrveuezo<|vV>t%->z=QfYjR5fe(qo z$K#OgW$N+D8CUq2MXA*J<)d=8Q0pFE!5}N01f6Za;4KfJ)SjK`8F9dG(wx%#EYdi=8Js95nrX%iq zq7b%)C?(rl&*ai&jg7!@eN~7>EeE*dTfm);b4M6G%?)Hx_Q2EV0dEW47Z$ph_^qE< z#5W5nE0Bo`OK((%VJR%)ZjtmlK1142cTfMENp`yxL%KtGtSa;sYZ42Jv;QuvV;bUn z^C2goNL%j{cin0c2UN+1mb$eW4A)uZtvt(sFiJgn+6k&-tsH-S_}7-hZkuuAfC5qRsG6S2w=e zM9|)6ar$dzW@#=Tx!dYRjq{PYjDwns!~InfRL(AUCg7Y!Phr+%MAl;wLGGugvn-Y( zc-mei6cOtp8+Q-|?w>FtTyjTYWCh;Mv~HP>_?o|D(-WV2<=>*5&=~%}Bij#|5f6QA z;qTR#QsqiB57IN@##P!-Mjd@hNwu|O8?7*sUuIs;35MEI62iK?k(D}rrJJWy^E)cewh_=b(H)+qS1PHes* zor$OuPsLoaL$ghJH=2mAoC|X9iEYMNcb(w47~~dBG;R0u4WF$u6D-f`9Yv4sIFdzj zHi~a_q?$jsv!J%m)+MbKkODVQ7dW(cJmbxMbN+~9ABrU`hz47=63F%qJ1!AIbD&nc zn4as`)Av(o=5eStxfRlN?JX6iq9CW*bWOl9xC=)Pnt0Bdhro=CLHbV)RxS%#dTy~I`9CIQ Bx_$rv literal 0 HcmV?d00001 diff --git a/public_html/icon-maskable-512.png b/public_html/icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce1939305bf0d420f2b41b2ca3b83f0b818a848 GIT binary patch literal 2358 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4YzZe)e{(8DNhE&XXdv{}@h@*f* z;ItsKkcR@ojxxsrEm$_P>~?7g@wjY#tX{vVuEDB9pop5-i2V)}$_*p#V>{37V_DW+ZNl@Wq{mb)M?` zB(~j5GDW2S(~+TvqSCrJnHmK3bRrJx7`j3%>WSC;V3^k7$$iT87jWqbO-4LX0kz-h88@&eO>?hJ7)%l z@0%D$^FPtW+=9n8=d-^nGBi}*#GR@JUv!U_@1ynH@T<-j>_4#9Yx7(kyC=Z*5QC?y KpUXO@geCwiz(^qg literal 0 HcmV?d00001 diff --git a/public_html/index.html b/public_html/index.html new file mode 100644 index 0000000..bd20375 --- /dev/null +++ b/public_html/index.html @@ -0,0 +1,683 @@ + + + + + +Backgammon Clock + + + + + + + + + + + +
+
+
+
Moves: 0
+
+
3:00
+
+ + 15 +
+
+
+
+ +
+ + + + + +
+ +
+
+
Moves: 0
+
+
3:00
+
+ + 15 +
+
+
+
+
+ +
+ + + + + + diff --git a/public_html/manifest.webmanifest b/public_html/manifest.webmanifest new file mode 100644 index 0000000..7402d4a --- /dev/null +++ b/public_html/manifest.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "Backgammon Clock", + "short_name": "BG Clock", + "description": "Two-player match clock with a visible simple delay.", + "start_url": "./index.html", + "scope": "./", + "id": "/bgclock/", + "display": "fullscreen", + "display_override": ["fullscreen", "standalone"], + "orientation": "portrait", + "background_color": "#332E2B", + "theme_color": "#332E2B", + "categories": ["games", "utilities"], + "icons": [ + { "src": "icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, + { "src": "icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, + { "src": "icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } + ] +} diff --git a/public_html/sw.js b/public_html/sw.js new file mode 100644 index 0000000..d427f59 --- /dev/null +++ b/public_html/sw.js @@ -0,0 +1,33 @@ +/* Cache-first: once installed the clock never touches the network again. */ +const CACHE = "bgclock-v1"; +const FILES = [ + "./", + "./index.html", + "./manifest.webmanifest", + "./icon-192.png", + "./icon-512.png", + "./icon-maskable-512.png" +]; + +self.addEventListener("install", (e) => { + e.waitUntil(caches.open(CACHE).then((c) => c.addAll(FILES)).then(() => self.skipWaiting())); +}); + +self.addEventListener("activate", (e) => { + e.waitUntil( + caches.keys() + .then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))) + .then(() => self.clients.claim()) + ); +}); + +self.addEventListener("fetch", (e) => { + if (e.request.method !== "GET") return; + e.respondWith( + caches.match(e.request).then((hit) => hit || fetch(e.request).then((res) => { + const copy = res.clone(); + caches.open(CACHE).then((c) => c.put(e.request, copy)).catch(() => {}); + return res; + }).catch(() => caches.match("./index.html"))) + ); +});