Infortuni/ritardi: non contano più gli eventi futuri nei badge

contaInfortuni()/contaRitardi() leggevano tutta la mappa presenze senza
guardare la data dell'evento: un giocatore può segnarsi infortunato o in
ritardo anche su un evento non ancora avvenuto (l'UI lo permette finché
l'evento non è passato), e quel conteggio arrivava subito ai badge segreti
"Infermeria" e "Ritardi". Ora filtrano su data < oggi, come già fa
eventiContanoPresenze() per le statistiche di presenza: con l'avanzare
della data reale l'evento prima futuro entra da solo nel conteggio.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 16:59:50 +02:00
co-authored by Claude Sonnet 5
parent e7b5082398
commit 9cc63b7854
3 changed files with 126 additions and 19 deletions
+45 -13
View File
@@ -1,13 +1,31 @@
import { useMemo } from "react";
import type { Giocatore } from "./crapp-data";
import type { Evento } from "./eventi";
import { useEventi } from "./eventi";
import { dataOggi } from "./scout-live";
import { useRispostePresenze, type MappaPresenze } from "./presenze";
/** giocatoreId -> numero di eventi (allenamenti + partite) con stato "infortunato". */
export type ContoInfortuni = Record<string, number>;
function contaStato(presenze: MappaPresenze, stato: string): ContoInfortuni {
/**
* Un giocatore può segnarsi infortunato o in ritardo anche su un evento futuro
* (l'UI lo permette finché l'evento non è passato): finché quell'evento non è
* avvenuto davvero non deve contare per i badge, altrimenti si sbloccherebbero
* in anticipo. Un evento non più in `eventi` (es. cancellato) non viene contato:
* non potendo verificarne la data, si esclude per prudenza.
*/
function contaStato(
presenze: MappaPresenze,
stato: string,
eventi: Evento[],
oggi: string = dataOggi(),
): ContoInfortuni {
const dataPerEvento = new Map(eventi.map((e) => [e.id, e.data]));
const out: ContoInfortuni = {};
for (const eventoId of Object.keys(presenze)) {
const dataEvento = dataPerEvento.get(eventoId);
if (dataEvento === undefined || dataEvento >= oggi) continue;
const evento = presenze[eventoId] ?? {};
for (const giocatoreId of Object.keys(evento)) {
if (evento[giocatoreId] === stato) out[giocatoreId] = (out[giocatoreId] ?? 0) + 1;
@@ -16,14 +34,22 @@ function contaStato(presenze: MappaPresenze, stato: string): ContoInfortuni {
return out;
}
/** Conta gli infortuni dalla mappa presenze già in cache: ogni evento vale una volta sola. */
export function contaInfortuni(presenze: MappaPresenze): ContoInfortuni {
return contaStato(presenze, "infortunato");
/** Conta gli infortuni dalla mappa presenze già in cache: ogni evento passato vale una volta sola. */
export function contaInfortuni(
presenze: MappaPresenze,
eventi: Evento[],
oggi: string = dataOggi(),
): ContoInfortuni {
return contaStato(presenze, "infortunato", eventi, oggi);
}
/** Conta i ritardi dalla stessa mappa presenze: ogni evento vale una volta sola. */
export function contaRitardi(presenze: MappaPresenze): ContoInfortuni {
return contaStato(presenze, "ritardo");
/** Conta i ritardi dalla stessa mappa presenze: ogni evento passato vale una volta sola. */
export function contaRitardi(
presenze: MappaPresenze,
eventi: Evento[],
oggi: string = dataOggi(),
): ContoInfortuni {
return contaStato(presenze, "ritardo", eventi, oggi);
}
export function conInfortuni<T extends Giocatore>(
@@ -38,23 +64,29 @@ export function conInfortuni<T extends Giocatore>(
};
}
/** Nessuna query aggiuntiva: riusa la cache delle risposte presenze. */
/** Nessuna query aggiuntiva: riusa le cache di risposte presenze ed eventi. */
export function useInfortuni(): ContoInfortuni {
const { presenze } = useRispostePresenze();
return useMemo(() => contaInfortuni(presenze), [presenze]);
const { eventi } = useEventi();
return useMemo(() => contaInfortuni(presenze, eventi), [presenze, eventi]);
}
/** Nessuna query aggiuntiva: riusa la cache delle risposte presenze. */
/** Nessuna query aggiuntiva: riusa le cache di risposte presenze ed eventi. */
export function useRitardi(): ContoInfortuni {
const { presenze } = useRispostePresenze();
return useMemo(() => contaRitardi(presenze), [presenze]);
const { eventi } = useEventi();
return useMemo(() => contaRitardi(presenze, eventi), [presenze, eventi]);
}
/** Un solo hook per entrambi i conteggi: evita hook extra nei componenti. */
export function useInfortuniERitardi(): { infortuni: ContoInfortuni; ritardi: ContoInfortuni } {
const { presenze } = useRispostePresenze();
const { eventi } = useEventi();
return useMemo(
() => ({ infortuni: contaInfortuni(presenze), ritardi: contaRitardi(presenze) }),
[presenze],
() => ({
infortuni: contaInfortuni(presenze, eventi),
ritardi: contaRitardi(presenze, eventi),
}),
[presenze, eventi],
);
}