Rilettura completa della documentazione confrontata con il codice. Dove la doc diceva il falso l'ho corretta; dove aveva ragione lei ho corretto il codice. Autovoto (la doc aveva ragione) - migration m12_niente_autovoto: vincoli mvp_no_autovoto e badge_social_no_autovoto, gli stessi che pagelle_voti ha dalla v1.0. Le righe che li violano vengono cancellate prima dell'ALTER, altrimenti fallisce; in locale non ce n'erano. M11 garantisce solo che il voto sia firmato con il proprio votante_id, non che il votato sia un altro: eleggersi MVP restava a un POST di distanza. - VotazioneMvp non mostra più il votante nell'elenco, come già faceva VotoSocial. Test che guardavano la colonna sbagliata - scritture.test.ts verificava che aggiornato_il si muovesse, chiamandolo "quello che alimenta la serie di conferme". È l'opposto: la serie usa risposto_il, che il trigger di M9 deve tenere fermo. Ora il test prova a riscriverlo e controlla che il database abbia tenuto la prima risposta; prima passava anche senza trigger. - destinatariSollecito() esce dalla route sollecita-presenze e diventa una funzione pura in presenze.ts, con i suoi test — stesso trattamento di avvisiPalloniEvento. Tre riletture in meno - giocatori-squadra, scout-store e avatar-store usavano invalidateQueries dove il dato scritto era già noto: ora setQueryData, come il resto dell'app. Resta scout-live, dove il lock può averlo vinto un altro dispositivo. Documentazione riallineata - presenze.md, badge.md, mvp.md: i limiti su RLS aperta e route non autenticata erano superati da M11 e DD-024; - serie-presenze.md: il filtro è e.data < oggi, non <=, e l'evento di oggi non conta (conterebbe come assenza per tutti); aggiunta la tabella risposto_il/aggiornato_il; - ARCHITECTURE.md ed EFFICIENZA_CLOUD.md: una sola eccezione a setQueryData; - DATABASE.md: i vincoli delle tre tabelle di voto; - PROJECT_STATE.md: fermo a M9, ora arriva a M12. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.6 KiB
3.6 KiB
Modulo — Badge
Stato: implementato (v1.0), coerente con DD-007 e DD-008
File principali: src/lib/badges.ts, src/lib/badge-social.ts,
src/components/crapp/CollezioneBadge.tsx, src/components/crapp/BadgeDrawer.tsx,
src/components/crapp/CelebrazioneBadge.tsx, src/components/crapp/VotoSocial.tsx
Obiettivo
Gamification: sbloccare badge (gradi bronzo/argento/oro, più badge "segreti") in base a statistiche personali reali del giocatore, per motivare la partecipazione senza penalizzare i ruoli con meno statistiche "spettacolari" (DD-008).
Dati
Nessuna tabella dedicata ai badge sbloccati: calcolati interamente a runtime
dall'oggetto Giocatore (DD-007). L'unica tabella coinvolta è badge_social_voti, per i
badge assegnati per voto dai compagni.
Implementazione
badgeDefs/badgeSegreti(badges.ts) definiscono ogni badge con una funzionevalore(g)e soglie bronzo/argento/oro. Le fonti dato sono solo statistiche indipendenti dal ruolo in campo: MVP, media pagelle, turni palloni, presenze, serie, infortuni, ritardi, cacche — mai punti/ace/muri dello Scout Live, coerentemente con DD-008.- I badge segreti restano nascosti (icona lucchetto) finché non sbloccati.
- Badge social (
badge-social.ts, tabellabadge_social_voti): 5 categorie fisse per partita ("Compagno affidabile", "Miglior spirito di squadra", "Fair play", "Meme della partita", "Cuore del gruppo"), votabili una volta a testa per categoria/partita (modificabile), con auto-voto escluso in interfaccia (VotoSocial.tsx) e rifiutato dal database (vincolobadge_social_no_autovoto, migrationm12_niente_autovoto). A differenza delle Pagelle, qui non c'è alcun tentativo di anonimato:votante_id/votato_idsono entrambi visibili. CollezioneBadge.tsxmostra sbloccati, in progresso, badge social vinti e un contatore di badge segreti ancora da scoprire;BadgeDrawer.tsxil dettaglio di un singolo badge;CelebrazioneBadge.tsxl'overlay celebrativo alla prima visualizzazione di un badge nuovo.- Il rilevamento "nuovo" (
notifiche-smart.ts) confronta id deterministici con quelli già visti, salvati inlocalStorage— quindi locale al dispositivo, non sincronizzato tra dispositivi dello stesso giocatore.
Regole rispettate
- DD-007: nessuna tabella
badge_sbloccati, tutto calcolato a runtime dai dati esistenti. - DD-008: nessun
BadgeDefusa dati di reparto (punti/ace/muri); solo statistiche raggiungibili da qualunque ruolo.
Limiti noti
- Dipendenza dal modulo Serie: i badge "Sempre in palestra",
"Risposta lampo" e il segreto "Mai un forfait" si muovono solo se cambiano le serie. Le
serie sono calcolate sui dati reali dalla migration
m9in avanti, ma "Risposta lampo" e "Mai un forfait" dipendono daserieConferme, erisposto_ilnon è ricostruibile per le risposte precedenti am9: su quelle righe la serie è un'approssimazione. - Nessuno storico dei badge sbloccati: se cambiano le soglie o i dati sorgente, un badge già "ottenuto" può sparire o apparire retroattivamente.
- La policy di M11 garantisce che il voto sia firmato con il proprio
votante_id, ma non che il votato sia un giocatore convocato per quella partita: quello resta un filtro solo applicativo. - Notifiche "nuovo badge" solo locali al dispositivo (localStorage), si ripetono cambiando browser o dispositivo.
Evoluzioni possibili
- Sincronizzare lo stato "visto" su Supabase invece che solo in localStorage.
- Verificare sui dati di stagione che i tre badge legati alle serie si sblocchino davvero, ora che le serie sono calcolate.