尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Pitalica je multiplayer platforma za kvizove uživo, za društvene večeri, obiteljska okupljanja, razrede i timove. Domaćin složi kviz i pokrene igru, a igrači ulaze s mobitela preko 6-znamenkastog PIN-a ili QR koda, samo s nadimkom i bez računa. Pitanja se svima pojavljuju istovremeno, bodove računa server, a igra završava ljestvicom i postoljem pobjednika.
Sučelje je na hrvatskom jeziku, a kod i komentari na engleskom.
Detaljna arhitektura (stanja igre, realtime događaji, baza): docs/ARHITEKTURA.md.
Domaćin (potreban račun)
Igrač (bez računa)
Vrste pitanja
| Vrsta | Igrač | Bodovanje |
|---|---|---|
| Jedan točan odgovor | dodir na karticu | točno / netočno |
| Više točnih odgovora | označi pa pošalji | cijeli skup ili djelomično |
| Točno / netočno | dva velika gumba | točno / netočno |
| Klizač procjene | klizač, +/– | tolerancija, s bodovima prema blizini |
| Kratki odgovor | upis teksta | točno podudaranje uz normalizaciju, opcionalno ručni pregled |
| Brojčani odgovor | numerička tipkovnica | tolerancija, cijeli ili decimalni broj |
| Pribadača na slici | dodir na sliku | radijus, prema udaljenosti |
| Poredaj redom | povlačenje ili strelice | točan redoslijed ili djelomično |
| Spoji parove | dodir lijevo pa desno | svi parovi ili djelomično |
| Slike kao odgovori | dodir na sliku | točno / netočno |
| Anketa | dodir | bez bodova, rezultati uživo |
| Rangiranje | povlačenje ili strelice | bez bodova, poredak grupe (Borda) |
| Sloj | Tehnologija |
|---|---|
| Okvir | Next.js 16 (App Router, Turbopack), React 19, TypeScript (strict) |
| Stil | Tailwind CSS 4 (dizajnerski tokeni u src/app/globals.css), vlastite komponente na Radix UI primitivima u stilu shadcn/ui |
| Forme i validacija | React Hook Form, Zod 4 (iste sheme na klijentu i serveru) |
| Animacije | Motion (motion/react), canvas-confetti |
| Ikone i fontovi | Lucide, Bricolage Grotesque i Plus Jakarta Sans (lokalno preko @fontsource) |
| Povlačenje | dnd-kit |
| Backend | Supabase: Postgres, Auth, Realtime (Broadcast i Presence), Storage |
| Testovi | Vitest (unit i integracija), Playwright (E2E) |
| Deploy | Vercel (uz dnevni cron za čišćenje) |
Zvukovi se sintetiziraju u pregledniku (Web Audio API), pa nema audio datoteka i nema pitanja licence.
Preduvjeti: Node.js ≥ 20.9 (preporuka 22), Docker (za lokalni Supabase).
npm install # .npmrc postavlja legacy-peer-deps
npx supabase start # lokalni Postgres, Auth, Realtime, Storage, Mailpit
cp .env.example .env.local # zatim upišite vrijednosti koje je ispisao `supabase start`
npm run dev # http://localhost:3000
npx supabase start primjenjuje migracije iz supabase/migrations/. U .env.local upišite ove vrijednosti iz ispisa naredbe:
Ispis supabase start | Varijabla |
|---|---|
API_URL | NEXT_PUBLIC_SUPABASE_URL |
PUBLISHABLE_KEY (ili ANON_KEY) | NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
SECRET_KEY (ili SERVICE_ROLE_KEY) | SUPABASE_SECRET_KEY |
Lokalni e-mailovi (potvrde, reset lozinke) stižu u Mailpit na http://127.0.0.1:54324.
Prvi kviz za 30 sekundi: registrirajte se, na nadzornoj ploči kliknite Uvezi JSON i odaberite examples/primjer-kviz.pitalica.json. Zatim pokrenite igru i otvorite /join u drugom pregledniku ili na mobitelu u istoj mreži.
Korisne naredbe:
npm run db:reset # ponovno stvara lokalnu bazu iz migracija
npm run db:types # regenerira src/lib/supabase/database.types.ts
npm run lint && npm run typecheck && npm test
Ako
supabase startne može preuzeti slike spublic.ecr.aws, pokrenite ga saSUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io npx supabase start.
npx supabase login
npx supabase link --project-ref <project-ref>
npx supabase db push
Migracija stvara tablice, indekse, RLS politike, funkcije i Storage bucket quiz-media (javno čitanje, najviše 5 MB, samo PNG, JPEG, WebP i GIF).https://pitalica.vercel.apphttps://pitalica.vercel.app/** (po potrebi i adrese preview deployova)/auth/callback (PKCE). Ako koristite predloške s token_hash, usmjerite ih na /auth/confirm?token_hash={{ .TokenHash }}&type=recovery.game:<uuid>. Poruke sadrže samo „stanje se promijenilo, verzija N”, nikad odgovore ni bodove, a UUID sesije znaju samo sudionici. Ako je javni pristup isključen, igra i dalje radi, ali se osvježava periodično (svakih 2,5 s) umjesto trenutno.publishable ide u NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, a secret u SUPABASE_SECRET_KEY. Legacy anon i service_role ključevi također rade.| Varijabla | Gdje | Opis |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | klijent i server | URL Supabase projekta |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | klijent i server | publishable (ili legacy anon) ključ; zaštitu podataka osigurava RLS |
SUPABASE_SECRET_KEY | samo server | secret (ili service_role) ključ za autoritativne operacije igre. Nikad s prefiksom NEXT_PUBLIC_. |
NEXT_PUBLIC_SITE_URL | klijent i server | javni URL aplikacije (metapodaci, apsolutne poveznice) |
CRON_SECRET | samo server | štiti /api/cron/cleanup; Vercel Cron ga šalje automatski |
Primjer je u .env.example. Prave tajne se ne commitaju (.env*.local je u .gitignore).
vercel.json postavlja npm ci i cron./api/cron/cleanup pokreće se jednom dnevno (03:17 UTC). On:
Nije potreban zaseban server za igru. Rokovi se provjeravaju „lijeno”: svako čitanje stanja zatvara pitanje kojem je istekao rok, a promjene se zapisuju atomarno (compare-and-swap).
| Naredba | Što pokreće | Preduvjet |
|---|---|---|
npm test | unit testovi (Vitest, ~100): bodovanje svih tipova, djelomično bodovanje, tolerancije, udaljenost pribadače, redoslijed i parovi, javni prikaz bez odgovora, stanja igre, rokovi, izjednačenja, timovi, nadimci, validacija | ništa |
npm run test:integration | integracijski testovi na pravoj bazi: spremanje kviza, RLS, autorizacija domaćina, PIN, ulazak, odgovori, zatvaranje pitanja, poredak, cijela igra sa svih 12 tipova, 20 istovremenih igrača, timovi, vježba, ručni pregled, Storage politike, čišćenje, ograničenje PIN-a | npx supabase start i .env.local |
npm run test:e2e | Playwright: domaćin gradi kviz u uređivaču i igra s dva igrača; svaki tip pitanja kroz sučelje igrača; ponovno spajanje; zabranjene radnje; ručni pregled; timovi; vježba; alati uređivača (upload, dupliciranje, brisanje, presloži, pregled, izvoz i uvoz); pretraga na ploči; odjava i reset lozinke e-mailom | kao gore. Test sam napravi produkcijski build i pokrene ga na portu 3100. |
npm run test:all
E2E_BASE_URL=http://localhost:3000 npm run test:e2e # koristi već pokrenut dev server
QA=1 npx playwright test visual.qa # snimke zaslona za dizajnerski pregled
Playwright je prikvačen na 1.63.0 zbog preglednika instaliranog u razvojnom okruženju. Na drugim računalima pokrenite npx playwright install chromium.
src/
app/ # Next.js rute (stranice + /api route handleri)
(auth)/ # prijava, registracija, reset lozinke
(app)/ # nadzorna ploča, povijest igara, račun
quizzes/[id]/ # uređivač, pregled, postavljanje igre
host/[id]/ # ekran domaćina (projektor)
play/[id]/ join/ practice/[quizId]/
api/ # quizzes, media, games, join, practice, cron
components/
ui/ brand/ site/ home/ app/ auth/
editor/ # uređivač kviza i uređivači po tipu pitanja
game/ # dijeljeno: unos odgovora, rezultati, odbrojavanje, ljestvica, realtime hook
host/ player/
lib/
domain/ # čista logika bez I/O: sheme, bodovanje, javni prikaz, stanja, poredak
server/ # samo server: auth, HTTP, rate limit, kvizovi, games/ (servis igre)
client/ # samo klijent: API, upload, zvuk, sesija igrača, izvoz
supabase/ # klijenti + generirani tipovi baze
game/types.ts # ugovor GameView / GameEvent između servera i klijenta
supabase/migrations/ # SQL shema, RLS, funkcije, Storage
tests/unit | integration | e2e | support
examples/ # primjer kviza za uvoz
docs/ARHITEKTURA.md
host_idanon nema nikakva prava nad tablicama igre, a funkcije igre (submit_answer, finalize_question…) može izvršiti samo service_role.(igrač, pitanje) sprječava dvostruke bodove.state_version (compare-and-swap), pa dvostruki klik ne preskače pitanje.<user-id>/<uuid>.<ext>. Bucket provjerava MIME tip i veličinu, a RLS na storage.objects dopušta pisanje samo u vlastitu mapu.?next=)Sve bodove računa src/lib/domain/scoring.ts na serveru. Svako pitanje daje udio f između 0 i 1:
| Tip | Pravilo |
|---|---|
| Jedan točan, slike, točno/netočno | f = 1 za točan odgovor, inače 0 |
| Više točnih | 1 samo za točan skup; s djelomičnim bodovanjem max(0, (točno označeni − pogrešno označeni) / broj točnih) |
| Klizač | samo točno: 1 ili 0; inače unutar ±tolerancije točno, a s „bodovima prema blizini” 100 % na cilju i 50 % na rubu |
| Brojčani | ` |
| Kratki odgovor | podudaranje nakon odabrane normalizacije (razmaci, velika/mala slova, dijakritici). Bez približnog (fuzzy) podudaranja. Uz ručni pregled nepodudarni odgovori čekaju odluku domaćina. |
| Pribadača | udaljenost u jedinicama širine slike, uz poštivanje omjera stranica (koordinate su normalizirane 0–1); unutar radijusa točno, s ocjenom prema blizini 100 %–50 % |
| Poredaj | 1 za točan redoslijed; djelomično = stavke na točnom mjestu / ukupno |
| Spoji parove | 1 za sve parove; djelomično = točni parovi / ukupno |
| Anketa, rangiranje | nikad ne boduju |
Bodovi = osnovica × množitelj (0/1/2) × f. S bonusom za brzinu polovica je zajamčena, a druga polovica linearno pada s vremenom odgovora (kao u Kahootu). Bodovi nikad nisu negativni.
Izjednačenja: igrači s istim bodovima dijele mjesto (1, 1, 3). Redoslijed prikaza unutar istog mjesta određuje broj točnih odgovora, zatim ukupno vrijeme odgovora, pa vrijeme ulaska.
Timovi: bodovi tima su prosjek bodova članova, pa veći tim nema prednost.
src/lib/media.ts.| Problem | Rješenje |
|---|---|
| „Aplikacija nije konfigurirana” | Nedostaju NEXT_PUBLIC_SUPABASE_* ili SUPABASE_SECRET_KEY. Provjerite .env.local ili varijable na Vercelu. |
| Igrači ne vide promjene odmah | Provjerite je li u Supabase Realtime postavkama uključen javni pristup. Bez njega aplikacija se osvježava svakih 2,5 s. |
| Poveznica za reset lozinke vodi na login s greškom | URL aplikacije mora biti u Redirect URLs, a link se mora otvoriti u istom pregledniku u kojem je zatražen (PKCE). |
| Upload slike ne uspijeva | Datoteka mora biti PNG, JPEG, WebP ili GIF do 5 MB. Bucket quiz-media stvara migracija; provjerite je li supabase db push izvršen. |
| „Previše pokušaja” | Ograničenje po IP-u traje minutu. Kod PIN-a se broje samo promašaji. |
npm install javlja grešku s peer ovisnostima | Repozitorij ima .npmrc s legacy-peer-deps=true; koristite npm ci. |
Lokalni supabase start ne može preuzeti slike | SUPABASE_INTERNAL_IMAGE_REGISTRY=docker.io npx supabase start |
| Playwright ne pronalazi preglednik | npx playwright install chromium |