Il badge Pagellone si sblocca ora solo con almeno 5 pagelle ricevute (VOTI_MINIMI_PAGELLA): un voto solo poteva sbloccarlo o farlo sparire senza significatività statistica. Aggiunto Giocatore.votiPagella per farlo funzionare. La migration m13 (DD-027) estende le policy RLS di M11 su pagelle_voti, mvp_voti e badge_social_voti: votante e votato devono essere convocati all'evento (prima solo un filtro applicativo), e per le pagelle anche pagelle_chiuse=false. Le policy admin restano permissive di proposito. Applicata anche al progetto cloud. Copertura test completa: unit sulla soglia minima, integration sulle nuove policy RLS (permessi.test.ts) e un end-to-end reale (pagella-badge.test.ts) sul modello di mvp-badge.test.ts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
Modulo — Votazione MVP
Stato: implementato (v1.0)
File principali: src/lib/mvp-voti.ts, src/components/crapp/VotazioneMvp.tsx
Obiettivo
Eleggere il MVP di una partita tramite voto tra compagni, un voto a testa, con vincitore calcolato a runtime.
Dati
Tabella mvp_voti, vincolo UNIQUE (match_id, votante_id) — un solo voto per giocatore per
partita, sovrascrivibile.
match_id è l'id dell'evento CrAPP, non quello del referto CSI né dello Scout: la
votazione non dipende più da nessuna delle due fonti (i voti scritti prima con l'id scout/CSI
restano nel database ma non vengono più letti da nessuna schermata).
Implementazione
- Il pannello sta in
partita.$id.tsxin una sezione sua, sempre presente:votoMvpAperto()lo apreORE_ATTESA_MVP(2) ore dopodata+oradell'evento, prima di allora mostra solo quando aprirà. Nessun legame con il risultato caricato. - Votano e sono votabili solo i presenti di quell'evento (
presenteoritardoinusePresenzeEvento): chi non c'era ha il bottone disabilitato e non compare nell'elenco. useVotaMvp()fa upsertonConflict: match_id, votante_id: il voto è modificabile senza limiti, senza storico.- Nessuno vota sé stesso:
VotazioneMvp.tsxtoglie il votante dall'elenco e il vincolomvp_no_autovoto(migrationm12_niente_autovoto) rifiuta la riga anche a chi scrive direttamente su PostgREST, come già facevapagelle_no_autovotoper le pagelle. conteggioPartita()/vincitoriMvp()richiedono un margine netto: in caso di parità, nessun vincitore viene assegnato per quella partita finché non arrivano altri voti.mvpVintiPerGiocatore()conta una vittoria per ogni partita "vinta" con margine netto; il risultato alimenta il campomvpdelGiocatoreinuseRosa(), mostrato come StatTile nel profilo e in home.
Limiti noti
- Nessuna scadenza o chiusura della votazione: una volta aperta resta aperta indefinitamente.
- Il voto è legato a chi lo scrive: da
m11_scritture_per_ruolola policy impone chevotante_idsia lo slot collegato all'account (DD-023). Su chi viene votato l'unico vincolo diretto è che non sia il votante stesso (mvp_no_autovoto). Dam13_convocati_e_pagelle_chiusela stessa policy verifica anche che sia il votante sia il votato siano tra i convocati dell'evento (evento_permette_voto(), convocati vuoto = tutta la rosa): prima era un filtro solo applicativo, ora un giocatore non convocato non può più votare né essere votato scrivendo direttamente su PostgREST. Restano invece solo applicativi, non controllati da nessuna policy: che votante e votato fossero presenti (non solo convocati:presente/ritardoinusePresenzeEvento, un controllo più stretto della sola convocazione) a quella partita, e le due ore d'attesa dall'inizio evento (votoMvpAperto()) — un amministratore, o chiunque scriva su PostgREST, passa comunque. - In caso di parità, nessun MVP viene assegnato per quella partita.
Evoluzioni possibili
- Introdurre una scadenza (es. la votazione si chiude N giorni dopo la partita).