Replace demo stats with real data
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+8
-37
@@ -82,40 +82,6 @@ function inizialiDa(nome: string) {
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
type StatsDemo = Pick<Giocatore, "presenze" | "streak" | "mvp" | "mediaVoto">;
|
||||
|
||||
/** Statistiche demo: mix di badge bronzo / argento / oro già sbloccati. */
|
||||
const statsDemo: Record<string, StatsDemo> = {
|
||||
"Ivan Cacciari": { presenze: 31, streak: 8, mvp: 5, mediaVoto: 8.7 },
|
||||
"Davide Grilli": { presenze: 27, streak: 5, mvp: 3, mediaVoto: 8.4 },
|
||||
"Nicola Pezzoli": { presenze: 24, streak: 4, mvp: 2, mediaVoto: 8.2 },
|
||||
"Laura Passabì": { presenze: 22, streak: 6, mvp: 3, mediaVoto: 8.1 },
|
||||
"Francesca Tucci": { presenze: 19, streak: 3, mvp: 1, mediaVoto: 7.9 },
|
||||
"Iacopo Ricci": { presenze: 21, streak: 2, mvp: 3, mediaVoto: 7.8 },
|
||||
"Alessandra Brunacci": { presenze: 14, streak: 3, mvp: 1, mediaVoto: 7.5 },
|
||||
"Mattias Bologna": { presenze: 12, streak: 2, mvp: 1, mediaVoto: 7.4 },
|
||||
"Giada Valbonesi": { presenze: 13, streak: 4, mvp: 1, mediaVoto: 7.6 },
|
||||
"Alessio Cocco": { presenze: 11, streak: 1, mvp: 0, mediaVoto: 7.2 },
|
||||
"Mattia Catalano": { presenze: 9, streak: 2, mvp: 0, mediaVoto: 7.0 },
|
||||
"Antonella Loverre": { presenze: 8, streak: 1, mvp: 0, mediaVoto: 6.9 },
|
||||
"Carlo Di Castelnuovo": { presenze: 7, streak: 1, mvp: 0, mediaVoto: 6.8 },
|
||||
"Camilla Esposito": { presenze: 6, streak: 2, mvp: 0, mediaVoto: 6.7 },
|
||||
"Salvador Battistella": { presenze: 20, streak: 5, mvp: 1, mediaVoto: 7.7 },
|
||||
"Silvia Chilese": { presenze: 16, streak: 3, mvp: 0, mediaVoto: 7.3 },
|
||||
"Cristina Titone": { presenze: 15, streak: 2, mvp: 0, mediaVoto: 7.1 },
|
||||
};
|
||||
|
||||
/** Serie demo derivate dalle statistiche: ogni tipo ha il suo contatore. */
|
||||
function serieDa(s?: StatsDemo) {
|
||||
const streak = s?.streak ?? 0;
|
||||
const presenze = s?.presenze ?? 0;
|
||||
return {
|
||||
serieAllenamenti: streak,
|
||||
seriePartite: Math.ceil(streak / 2),
|
||||
serieConferme: presenze >= 20 ? 12 : presenze >= 14 ? 8 : presenze >= 8 ? 4 : 1,
|
||||
};
|
||||
}
|
||||
|
||||
export const giocatori: Giocatore[] = rosaCSI.map((r, i) => ({
|
||||
id: `g${i + 1}`,
|
||||
nome: r.nome,
|
||||
@@ -123,14 +89,19 @@ export const giocatori: Giocatore[] = rosaCSI.map((r, i) => ({
|
||||
ruolo: r.ruolo,
|
||||
nascita: r.nascita,
|
||||
iniziali: inizialiDa(r.nome),
|
||||
totaliEventi: 32,
|
||||
presenze: 0,
|
||||
totaliEventi: 0,
|
||||
streak: 0,
|
||||
serieAllenamenti: 0,
|
||||
seriePartite: 0,
|
||||
serieConferme: 0,
|
||||
mvp: 0,
|
||||
mediaVoto: 0,
|
||||
infortuni: 0,
|
||||
ritardi: 0,
|
||||
palloni: 0,
|
||||
cacche: 0,
|
||||
cacchePartita: 0,
|
||||
...(statsDemo[r.nome] ?? { presenze: 0, streak: 0, mvp: 0, mediaVoto: 0 }),
|
||||
...serieDa(statsDemo[r.nome]),
|
||||
}));
|
||||
|
||||
export type RigaClassifica = {
|
||||
|
||||
@@ -84,3 +84,17 @@ export function vincitoriMvp(voti: VotoMvp[]): Record<string, string> {
|
||||
export function mioVoto(voti: VotoMvp[], matchId: string, votanteId: string) {
|
||||
return voti.find((v) => v.match_id === matchId && v.votante_id === votanteId) ?? null;
|
||||
}
|
||||
|
||||
/** MVP vinti per giocatore, contando una vittoria per partita votata. */
|
||||
export function mvpVintiPerGiocatore(voti: VotoMvp[]): Record<string, number> {
|
||||
const out: Record<string, number> = {};
|
||||
const matchIds = new Set(voti.map((v) => v.match_id));
|
||||
for (const matchId of matchIds) {
|
||||
const top = conteggioPartita(voti, matchId);
|
||||
if (top.length > 0 && (top.length === 1 || top[0]!.voti > top[1]!.voti)) {
|
||||
const id = top[0]!.id;
|
||||
out[id] = (out[id] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,41 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { supabase } from "@/integrations/supabase/client";
|
||||
import type { Stato } from "./crapp-data";
|
||||
import type { Evento } from "./eventi";
|
||||
|
||||
export const PRESENZE_KEY = ["risposte-presenze"] as const;
|
||||
|
||||
/** eventoId -> giocatoreId -> stato */
|
||||
export type MappaPresenze = Record<string, Record<string, Stato>>;
|
||||
|
||||
/** Allenamenti e partite CrAPP che contano per le statistiche di presenza. */
|
||||
function eventiContanoPresenze(eventi: Evento[], giocatoreId?: string) {
|
||||
return eventi.filter(
|
||||
(e) =>
|
||||
(e.tipo === "partita" || e.tipo === "allenamento") &&
|
||||
(giocatoreId === undefined ||
|
||||
e.convocati.length === 0 ||
|
||||
e.convocati.includes(giocatoreId)),
|
||||
);
|
||||
}
|
||||
|
||||
/** Presenze effettive (presente o in ritardo) su eventi CrAPP. */
|
||||
export function contaPresenzeGiocatore(
|
||||
giocatoreId: string,
|
||||
eventi: Evento[],
|
||||
presenze: MappaPresenze,
|
||||
): number {
|
||||
return eventiContanoPresenze(eventi, giocatoreId).filter((e) => {
|
||||
const stato = presenze[e.id]?.[giocatoreId];
|
||||
return stato === "presente" || stato === "ritardo";
|
||||
}).length;
|
||||
}
|
||||
|
||||
/** Eventi CrAPP rilevanti per il denominatore presenze di un giocatore. */
|
||||
export function totaliEventiGiocatore(giocatoreId: string, eventi: Evento[]): number {
|
||||
return eventiContanoPresenze(eventi, giocatoreId).length;
|
||||
}
|
||||
|
||||
async function fetchPresenze(): Promise<MappaPresenze> {
|
||||
const { data, error } = await supabase
|
||||
.from("risposte_presenze")
|
||||
|
||||
+11
-7
@@ -1,6 +1,6 @@
|
||||
import { useSyncExternalStore } from "react";
|
||||
import { giocatori, type Giocatore } from "./crapp-data";
|
||||
import { conInfortuni, useInfortuniERitardi } from "./infortuni";
|
||||
import { useIo } from "./rosa";
|
||||
|
||||
const KEY = "crapp-user-v1";
|
||||
const listeners = new Set<() => void>();
|
||||
@@ -36,9 +36,9 @@ export function resetGiocatore() {
|
||||
write(null);
|
||||
}
|
||||
|
||||
/** Solo lettura locale: nessuna dipendenza da React Query (usabile fuori dal provider). */
|
||||
export function useGiocatoreBase(): Giocatore | null {
|
||||
const id = useSyncExternalStore(
|
||||
/** Id del giocatore collegato al dispositivo (localStorage). */
|
||||
export function useGiocatoreId(): string | null {
|
||||
return useSyncExternalStore(
|
||||
(cb) => {
|
||||
listeners.add(cb);
|
||||
return () => listeners.delete(cb);
|
||||
@@ -46,11 +46,15 @@ export function useGiocatoreBase(): Giocatore | null {
|
||||
() => read(),
|
||||
() => null,
|
||||
);
|
||||
}
|
||||
|
||||
/** Anagrafica base dal localStorage: le statistiche restano a zero finché non passa da `useIo`. */
|
||||
export function useGiocatoreBase(): Giocatore | null {
|
||||
const id = useGiocatoreId();
|
||||
return id ? (giocatori.find((x) => x.id === id) ?? null) : null;
|
||||
}
|
||||
|
||||
/** Giocatore corrente con statistiche calcolate da dati reali (presenze, MVP, badge, …). */
|
||||
export function useGiocatoreCorrente(): Giocatore | null {
|
||||
const g = useGiocatoreBase();
|
||||
const { infortuni, ritardi } = useInfortuniERitardi();
|
||||
return g ? conInfortuni(g, infortuni, ritardi) : null;
|
||||
return useIo();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user