CoOp:Anything
๊ฒ์์ ๊ฒ์ํด ํ๋ ํ๋ ์ด ๊ฐ๋ฅํ ๋ชจ๋ยท๋จ๊ณยทํ์งยท์ปค๋ฎค๋ํฐ ํ์ ์ ํ์ธํฉ๋๋ค
Waffle kloon
๊ฒ์HTML ยท JavaScriptGitHub @iTim-Technology์ต๊ทผ ์ ์ ํ์ธ ์คํจ์ด์์ ๋ฏธํ์ธ
์จ ๋ณด์ จ์ด์? ํ ๋ฒ๋ง ๋๋ฌ ์ฃผ์ธ์. ๋ก๊ทธ์ธ์ ํ์ ์์ด์.
์์ง ๊ฐ์ง๋ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๋ค. GitHub ๋ฆด๋ฆฌ์ค๊ฐ ๋์ค๋ฉด ์ฌ๊ธฐ์ ๋ณด์ ๋๋ค.
๋ก๊ทธ์ธ ์ํ๋ฅผ ํ์ธํ๋ ์ค์ ๋๋ค.
๋๊ธ์ ๋ถ๋ฌ์ค๋ ์ค์ ๋๋ค.
๊ฐ์ธ ๊ณ์ ์ ๊ณต๊ฐ ์ ์ฅ์ ์์ ์๋ GitHub๋ก ๋ก๊ทธ์ธํด ์ด์์๋ฅผ ํ์ธํ๊ณ ์๊ฐ๋ฅผ ์ง์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ๊ด๋ฆฌ์ ์น์ธ์ ํ์ํ์ง ์์ต๋๋ค.
๋ก๊ทธ์ธํ ๋ค ํ์ธ ํ์ผ์ ๋ง๋ค์ด ์ด ์ ์ฅ์์ ๊ธฐ๋ณธ ๋ธ๋์น์ 30๋ถ ์์ ์ปค๋ฐํด ์ฃผ์ธ์. ๋ค๋ฅธ ๋ธ๋์น๋ ํฌํฌ์ ํ์ผ์ ์ธ์ ํ์ง ์์ต๋๋ค. ํ์ผ์ ์ฌ๋ฆฐ ๋ค ์๋์์ ํ์ธํ๋ฉด ๊ด๋ฆฌ์ ์น์ธ ์์ด ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ์๊ฒฉ์ ์ ์งํ๋ ค๋ฉด ํ์ผ์ ๋จ๊ฒจ ๋์ธ์.
๋ก๊ทธ์ธ์ด ํ์ํ๋ฉด ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ์ด๋ํฉ๋๋ค. ๋ก๊ทธ์ธ ํ ์ด๊ณณ์ผ๋ก ๋์์ ์ํ๋ ํ์ธ ๋ฒํผ์ ๋ค์ ๋๋ฌ ์ฃผ์ธ์.
ํ๋ก์ ํธ ํด๋์์ /nomorevibe verify๋ฅผ ์คํํ๋ฉด ์์ ๊ถ์ ํ์ธํ๊ณ ์๊ฐ๋ฅผ ์ง์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
1๋ถ ๋ง์ ํ์ธํ๊ธฐ๋ฉ์ด์ปค๊ฐ ์ด ์๊ฐ๋ ์์ ํ ์ค์ด ์ ๋ถ์ ๋๋ค. ๋ ์์ธํ ๋ด์ฉ์ ์ ์ฅ์ README์์ ์ฝ์ ์ ์์ต๋๋ค. ์ ์ฅ์ README โ
README ์ ์ฒด๋ฅผ ๋ถ๋ฌ์ค๋ ์ค์ ๋๋ค.
README ์ ๋ฌธ ๋ณด๊ธฐ โEen kleine verzameling spellen en speel-tools voor in de browser. De site wordt geserveerd door een minimale Node-server (zonder dependencies) die ook de scores van de kaartspellen bijhoudt; de overige spellen werken gewoon offline als losse pagina's.
| Spel | Map | Wat |
|---|---|---|
| ๐งฉ Kubus Solver | games/cube-solver/ | Kleur je Rubik's kubus in en los hem in ยฑ20 zetten op (Kociemba two-phase), stap voor stap. |
| ๐ง Wafelwoorden | games/wafelwoorden/ | Sleep de letters op hun plek en los de woordwafel op. |
| ๐ Boerenbridge | games/boerenbridge/ | Score bijhouden met twee apparaten: invoer op je telefoon, live scorebord op een tweede scherm. Met klassement over alle potjes. |
| ๐ก Klaverjas | games/klaverjas/ | Een boompje van 16 rondes met twee teams: troef, punten, roem, nat en pit. Met live scorebord op een tweede scherm en klassement. |
| ๐ Tafeltennis | games/tafeltennis/ | Toernooitracker (4T): poule, poule + eindronde of knock-out, uitslagen per game met deuce-controle, live scorebord met stand, kruistabel en schema, en een klassement over toernooien heen. |
| ๐ฒ Yahtzee | games/yahtzee/ | Digitaal scoreblok: 1โ8 spelers, 1โ6 rijtjes tegelijk, op รฉรฉn telefoon of op meerdere tegelijk, highscores per rijtje โ en optioneel de camera die de stenen telt. |
Elk spel is een zelfstandige pagina onder games/<naam>/index.html met een
link terug naar de homepage.
node server/server.js
De server (Node โฅ 18, geen npm-dependencies) serveert de hele site op
http://localhost:3000 en biedt de spel-API's onder /api/boerenbridge/,
/api/klaverjas/, /api/tafeltennis/ en /api/yahtzee/, elk met een eigen
SSE-kanaal voor het scorebord (bij yahtzee luisteren de invoerpagina's zelf mee). Configuratie via omgevingsvariabelen:
PORT โ poort (standaard 3000)DATA_DIR โ map voor de databestanden boerenbridge.json,
klaverjas.json, tafeltennis.json en yahtzee.json (standaard ./data)games/boerenbridge/ op de telefoon van de scorebijhouder โ hier
start of hervat je een spel en voer je voorspellingen en slagen in.
Aantallen tik je aan op knoppen (0 t/m het aantal kaarten). Bij de
werkelijke slagen grijst de pagina onmogelijke aantallen uit: samen nooit
meer dan het aantal kaarten, en de laatste speler kan alleen nog het
exacte restant kiezen. Nogmaals tikken wist een keuze weer. Onder de
slagen-invoer staat de tussenstand zoals die wordt als de ingetikte
slagen kloppen; het scoreblok eronder toont per ronde de punten van die
ronde รฉn de stand op dat moment, met de plek in de stand onder het totaal.games/boerenbridge/display/ op een tweede apparaat (bijv. een iPad
op tafel) โ dit scorebord volgt het spel live via Server-Sent Events.
Zonder actief spel toont het scherm het klassement. Tijdens een potje
schakelt het vanzelf tussen vier weergaven: zodra de eerste voorspelling
wordt aangetikt zie je live wie hoeveel vraagt en groot het totaal
("samen gevraagd"); tijdens het kaarten blijven ieders voorspelling en dat
totaal groot in beeld (mรฉt of er te veel of te weinig gevraagd is); na de
telling komt de tussenstand met het scoreblok; en na de laatste ronde de
eindstand. De tussenstand loopt door alle weergaven mee: elke spelerkaart
toont zijn plek in de stand en zijn puntentotaal, tijdens het invoeren van
de slagen met een pijl naar waar dat totaal op uitkomt. Naast het
"samen gevraagd"-blok en naast het scoreblok staat een verloopgrafiek met
รฉรฉn lijn per speler; loopt er slagen-invoer, dan wordt die lijn gestippeld
doorgetrokken naar de verwachte stand. Op smalle schermen (< 900 px)
vervalt de grafiek en blijven de cijfers. Tussen de rondes staat er een
weetje over het potje ("Anne zit al 4 rondes op rij precies goed",
"Tim is niet meer in te halen", "Halverwege!"); dat blijft de hele ronde
staan. Zijn er al eerdere potjes gespeeld, dan komen daar weetjes uit de
historie bij ("Piet vraagt bij 5 kaarten meestal 1", "het record aan deze
tafel is 87"); nieuws uit dit potje en achtergrond wisselen elkaar af. De
weetjes praten mee met de klok: wie 's middags kaart leest "vanmiddag".
Terwijl er voorspeld wordt, reageert het scherm op de zojuist aangetikte
keuze ("Anne vraagt nul; dat lukte 30 van de 42 keer") โ diezelfde regel
staat ook onder de invoer op de telefoon. Op de eindstand staan de
hoogtepunten van het potje: comeback, het kantelpunt, wie het langst aan kop
stond, wie het vaakst goed zat, de beste ronde, de zwaarste klap en de
nulletjes-koning.
Staat er geen potje op het scherm, dan wisselt onder het klassement elke
negen seconden een weetje over de tafel (records, het lastigste ronde-type).Er is bewust geen authenticatie of koppelcode: dit is bedoeld voor een vertrouwd thuisnetwerk. Zet het niet zonder extra maatregelen (reverse proxy met auth) open naar internet.
Tip voor het display: tik โ rechtsboven aan, dan blijft het scherm aan (zie
"Op de telefoon of tablet"). Lukt dat niet โ bijvoorbeeld op een oud iPad of
via een http://-adres โ zet dan automatische schermvergrendeling uit op het
apparaat.
games/klaverjas/ op de telefoon van de scorebijhouder en vul vier
namen in op zitvolgorde: speler 1 & 3 vormen samen een team, 2 & 4 ook.games/klaverjas/display/ op een tweede scherm โ dat toont live de
troef, wie er speelt, de standen en het scoreblok. Zonder actief potje
staat daar het klassement.Elke ronde gaat in twee stappen:
De server rekent de ronde uit:
server/klaverjas.js.Na 16 rondes (elke speler heeft dan vier keer gedeeld) sluit het potje zichzelf af en telt het mee voor het klassement. Een ronde verkeerd ingevoerd? Met โ Terug ga je stap voor stap terug โ eerst de telling, dan de troefkeuze โ ook nadat het potje al is afgelopen. Net als bij boerenbridge kun je onder ๐ Klassement spelers aantikken om potjes waarin zij meededen weg te laten.
games/tafeltennis/ op de telefoon van de toernooileider. Vul de
spelers in (3โ16; bekende namen staan als tikbare suggesties klaar) en kies
de toernooivorm:
games/tafeltennis/display/ op een tweede scherm. Dat toont wie er nu
aan welke tafel speelt en wie hierna komt, de poulestand met kruistabel
(of de laatste uitslagen bij meer dan acht spelers), in de eindronde het
schema, en na afloop het podium. Zonder toernooi staat er het klassement.De poule is met de cirkelmethode ingedeeld, dus per ronde speelt iedereen hooguit รฉรฉn keer. Uitslagen mag je in elke volgorde invoeren: tik een wedstrijd aan onder Nu aan tafel of in de lijst. Bij invoer per game verschijnt de volgende game vanzelf; met de knop 11 โฒ geef je een kant de game (de andere kant vul je dan met de verliezende score aan). Terwijl je typt gaat de tussenstand live naar het scorebord.
De server bewaakt de regels: een game win je met minstens 11 (of 21) punten en twee verschil (boven de 11 dus precies twee, 12โ10, 13โ11, โฆ), de wedstrijd is uit zodra iemand de helft-plus-รฉรฉn van de best-of heeft, en daarna volgen geen games meer. In de stand telt eerst het aantal gewonnen wedstrijden; wie gelijk staat wordt onderling vergeleken (winst, dan game- en puntensaldo in die onderlinge duels), daarna op game- en puntensaldo over de hele poule. Wat dan nog gelijk is, deelt de plek (gemarkeerd met *); voor de seeding van de eindronde geldt dan de invoervolgorde.
Met โ Laatste uitslag terugnemen loop je de invoer stap voor stap terug, ook over de fasegrens heen: neem je de laatste poulewedstrijd terug, dan verdwijnt de (nog ongespeelde) eindronde en wordt die opnieuw ingedeeld zodra de poule weer uit is. Het klassement telt per speler toernooien, titels, podiumplaatsen en het winstpercentage over alle wedstrijden; ook hier kun je spelers uitsluiten.
games/yahtzee/, vul de spelers in op volgorde van gooien (1โ8) en
kies het aantal rijtjes per speler (1โ6). Met meer rijtjes kies je elke
beurt zelf in welk rijtje je worp komt; elk rijtje heeft zijn eigen bonus.http://-adres in huis staat de browser hem niet toe.De regels zijn de officiรซle: 35 bonus bij 63 of meer in het bovenste deel (onder de bovenste vakjes staat hoeveel je voor of achter ligt op "drie van elk"), +100 per extra Yahtzee als het Yahtzee-vakje van dat rijtje 50 heeft, en de jokerregel (vijf gelijk telt als full house of straat zodra het Yahtzee-vakje vol is). Vul je in met de stenen, dan rekent de server dat allemaal zelf uit; met de hand vink je een extra Yahtzee aan in het keuzevenster. โถ Ongedaan neemt de laatste zet terug, ook na afloop โ en kwam die zet uit een worp, dan liggen die stenen weer op tafel.
De highscores zijn de tien beste rijtjes ooit (dus eerlijk tussen potjes met รฉรฉn of meer rijtjes); het klassement telt per speler potjes, winst (alleen met tegenstanders), het gemiddelde per rijtje, de beste, het aantal Yahtzees en hoe vaak de bonus binnenkwam.
Alles gaat op voornaam, en het klassement houdt spelers uit elkaar op naam. Heten twee mensen hetzelfde, zet ze dan op de pagina Spelers (onderaan de homepage) onder รฉรฉn voornaam met elk een eigen volledige naam, bijvoorbeeld Ilse โ Ilse B. en Ilse de V.. Dat geldt voor alle spellen tegelijk.
Geen zoom. Knijpen en dubbeltikken zoomen niet meer; teksten en knoppen blijven staan waar je ze verwacht. Scrollen en slepen (wafelwoorden) werken gewoon.
Scherm wakker. Tik โ rechtsboven aan en het scherm gaat niet meer op slot zolang de pagina openstaat. Dat onthoudt het toestel, voor alle spellen; nog een tik zet het weer uit. Het knopje verdwijnt na een paar tellen โ tik ergens op het scherm en het is er weer. Werkt alleen via het https-adres.
Zet je de site op je beginscherm (Deel โ Zet op beginscherm), dan start hij zonder Safari-balken, als een app. Stond hij er al vรณรณr deze wijziging op? Haal hem er dan รฉรฉn keer af en zet hem er opnieuw op โ iOS onthoudt de oude instelling.
De Spellenhoek thuis wordt uitgerold vanuit de manor-repo
(stacks/spellenhoek/NOTES.md); daar staat hoe. Zelf draaien kan zo:
docker build -t spellenhoek .
docker run -p 3000:3000 -v ./spellenhoek-data:/app/data spellenhoek
Voorbeeld voor een docker-compose homelab:
spellenhoek:
build: ./gamehoekje # pad naar een checkout van deze repo
container_name: spellenhoek
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- ./appdata/spellenhoek:/app/data
Achter een reverse proxy: zet response-buffering uit voor
/api/boerenbridge/events, /api/klaverjas/events,
/api/tafeltennis/events en /api/yahtzee/events (SSE); de server stuurt
daarvoor zelf al X-Accel-Buffering: no en een heartbeat elke 25 s.
node test/api.test.js
node test/klaverjas.test.js
node test/tafeltennis.test.js
node test/yahtzee.test.js
node test/yahtzee-vision.test.js
node test/spelers.test.js
node test/solver.test.js
api.test.js start de server op een vrije poort met een tijdelijke datamap
en test het volledige spelverloop, de scoreformule (tegen een onafhankelijke
herimplementatie), validatie en 409-guards, undo, het klassement, SSE,
path-traversal-bescherming en persistentie over een herstart.
klaverjas.test.js doet hetzelfde voor het klaverjas-API: de telling van
nat, roem en pit (opnieuw tegen een onafhankelijke herimplementatie), de twee
fasen per ronde, validatie, undo, het klassement per speler, SSE en de
gescheiden opslag naast boerenbridge.
tafeltennis.test.js speelt poules van 3โ7 spelers uit in willekeurige
volgorde en vergelijkt stand en eindstand met een onafhankelijke
herimplementatie van de tiebreak-regels, en test verder de game-validatie
(deuce, best-of), seeding en doorschuiven in de eindronde, vrije rondes,
undo over de fasegrens, de live tussenstand, het klassement, SSE en
persistentie.
yahtzee.test.js speelt een heel potje (3 spelers ร 2 rijtjes) met
willekeurige worpen en vergelijkt elke tussenstand met een onafhankelijke
herimplementatie van de telling (bonus, Yahtzee-bonus, jokerregel), en test
verder de invoer per waarde, de 409-guards, undo, het klassement en de
highscores, SSE en persistentie.
yahtzee-vision.test.js haalt de dobbelsteenherkenning uit de pagina en
laat hem synthetische camerabeelden tellen: onscherp, schaduw, glimlicht,
stenen tegen elkaar, een lamp aan รฉรฉn kant, enzovoort (aantal per scenario
via N_VISION). Dat test het rekenwerk, niet een echte camera.
spelers.test.js test de dubbele voornamen: de vraag bij de start, de
voornaam aan tafel, de suggesties en het toewijzen van oude potjes, voor alle
vier de spellen.
solver.test.js lost honderden willekeurige scrambles op met beide
oplossers en verifieert elke oplossing (aantallen instelbaar via
N_KOCIEMBA / N_LBL).
index.html # homepage / spellenoverzicht
spelers/index.html # beheer: twee spelers met dezelfde voornaam
server/
server.js # statische site + spel-API's + SSE
shared.js # gedeelde helpers (klassement, foutobjecten)
spelers.js # dubbele voornamen (voor alle spellen)
logic.js # autoritatieve boerenbridge-logica
klaverjas.js # autoritatieve klaverjas-logica
tafeltennis.js # autoritatieve toernooilogica (tafeltennis)
yahtzee.js # autoritatieve yahtzee-telling
games/
boerenbridge/index.html # invoerpagina (telefoon)
boerenbridge/display/ # live scorebord (tweede scherm)
klaverjas/index.html # klaverjas-invoerpagina (telefoon)
klaverjas/display/ # live scorebord (tweede scherm)
tafeltennis/index.html # toernooi-invoerpagina (telefoon)
tafeltennis/display/ # live scorebord: tafels, stand, schema
yahtzee/index.html # scoreblok + stenen + camera (telefoon)
cube-solver/index.html # zelfstandige (gebouwde) solver-pagina
wafelwoorden/index.html # woordspel
src/
cube-solver/ # bron van de solver-pagina
template.html solver.js kociemba.js app.js
build.js # bouwt de cube-solver naar games/cube-solver/
test/api.test.js # end-to-end API-test (boerenbridge)
test/klaverjas.test.js # end-to-end API-test (klaverjas)
test/tafeltennis.test.js # end-to-end API-test (tafeltennis)
test/yahtzee.test.js # end-to-end API-test (yahtzee)
test/yahtzee-vision.test.js # dobbelsteenherkenning op synthetische beelden
test/spelers.test.js # dubbele voornamen (alle spellen)
data/ # spelgegevens (niet in git; Docker-volume)
games/<naam>/index.html (zelfstandige pagina; voeg bovenin een
โ Alle spellen link toe naar ../../index.html).index.html (kopieer een bestaand <a class="game">).De solver-pagina is รฉรฉn zelfstandig bestand, samengesteld uit losse bronnen:
node build.js # src/cube-solver/* -> games/cube-solver/index.html
solver.js โ kubusmodel, facelet-conversie + laag-voor-laag fallbackkociemba.js โ Kociemba two-phase oplosser (ยฑ20 zetten, ~0,8 s tabel-build)app.js โ de mobiele UI (draait de solver in een Web Worker)template.html โ HTML + stylingDe oplosser is getest op duizenden willekeurige scrambles: 0 fouten, gemiddeld ~20 zetten. Elke oplossing wordt geverifieerd voor hij getoond wordt.
games/boerenbridge/stats/)
gaat dieper. Iedereen staat op รฉรฉn regel met het aantal potjes en een balkje
precies / te weinig gevraagd / te veel gevraagd; tik een naam aan voor het
volledige profiel met durf, wisselvalligheid, eerste tegen tweede helft en
trefzekerheid per kaartaantal. Tik er meer aan om ze naast elkaar te
vergelijken; die keuze blijft op dat toestel bewaard. Daarnaast records, welk ronde-type
het lastigst is, per troef, de onderlinge standen en wat opvalt aan de tafel
(bijvoorbeeld hoe vaak de koploper na de 1-kaartronde uiteindelijk wint).
Hetzelfde filter als bij het klassement, en die keuze wordt gedeeld.