Non conta i turni palloni finché l'evento non è passato.
conteggioTurni() contava ogni turno presente nella mappa, incluse le assegnazioni anticipate per eventi futuri: un allenamento di lunedì con turno già assegnato oggi (venerdì) veniva già sommato al badge "Sherpa dei palloni" prima ancora di essersi svolto. Ora filtra su e.data < oggi, lo stesso criterio già usato per presenze e serie — il turno resta assegnabile/ modificabile in anticipo, semplicemente non conta finché il giorno non arriva. oggiISO() (palloni-core.ts) diventa un alias di dataOggi(): stessa correzione di fuso della commit precedente, qui serviva anche per admin.tsx (scadenza documenti/certificati) e cacche.ts (statistiche giornaliere), che la usano. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,10 @@ compaiono.
|
||||
upsert su `evento_id`.
|
||||
- Il conteggio "quante volte hai portato i palloni" mostrato nel profilo e nei badge è
|
||||
ricalcolato a runtime da `conteggioTurni()` su turni salvati **più proposte non ancora
|
||||
confermate** (partite/eventi) — non è uno storico in tabella dedicata.
|
||||
confermate** (partite/eventi) — non è uno storico in tabella dedicata. Conta solo gli
|
||||
eventi già passati (`e.data < oggi`, stesso criterio delle presenze): un turno assegnato
|
||||
in anticipo per un allenamento futuro non è ancora "portato", quindi non sale finché quel
|
||||
giorno non arriva.
|
||||
- `TurnoPalloni.tsx` mostra/assegna il turno sulla card di un evento; `PromemoriaPalloni.tsx`
|
||||
è il banner in Home per il giocatore di turno.
|
||||
|
||||
|
||||
+19
-6
@@ -1,5 +1,6 @@
|
||||
import { formatData } from "./crapp-data";
|
||||
import type { Evento } from "./eventi";
|
||||
import { dataOggi } from "./scout-live";
|
||||
|
||||
export type Turno = { evento_id: string; giocatore_id: string; aggiornato_da: string | null };
|
||||
|
||||
@@ -60,10 +61,23 @@ export function completaTurni(
|
||||
return risultato;
|
||||
}
|
||||
|
||||
/** Quante volte ciascun giocatore è incaricato dei palloni. */
|
||||
export function conteggioTurni(turni: Record<string, string>): Record<string, number> {
|
||||
/**
|
||||
* Quante volte ciascun giocatore è incaricato dei palloni, solo per eventi già passati:
|
||||
* un turno assegnato in anticipo per un allenamento futuro non è ancora "portato", quindi
|
||||
* non deve contare finché quell'allenamento non è terminato (stesso criterio `e.data < oggi`
|
||||
* usato per le presenze, così la conta non cambia da sola col passare della giornata).
|
||||
*/
|
||||
export function conteggioTurni(
|
||||
turni: Record<string, string>,
|
||||
eventi: Evento[],
|
||||
oggi: string = dataOggi(),
|
||||
): Record<string, number> {
|
||||
const passati = new Set(eventi.filter((e) => e.data < oggi).map((e) => e.id));
|
||||
const out: Record<string, number> = {};
|
||||
for (const id of Object.values(turni)) out[id] = (out[id] ?? 0) + 1;
|
||||
for (const [eventoId, giocatoreId] of Object.entries(turni)) {
|
||||
if (!passati.has(eventoId)) continue;
|
||||
out[giocatoreId] = (out[giocatoreId] ?? 0) + 1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -84,10 +98,9 @@ export function eventoSuccessivo(eventi: Evento[], eventoId: string): Evento | u
|
||||
return i >= 0 ? lista[i + 1] : undefined;
|
||||
}
|
||||
|
||||
/** Alias di `dataOggi()`, nel fuso di Roma: qui per non toccare gli import esistenti. */
|
||||
export function oggiISO(d = new Date()): string {
|
||||
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const dd = String(d.getDate()).padStart(2, "0");
|
||||
return `${d.getFullYear()}-${mm}-${dd}`;
|
||||
return dataOggi(d);
|
||||
}
|
||||
|
||||
/** Chi deve ricevere l'avviso push, oggi: chi porta i palloni e chi li riprende. */
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ export function useRosa(): Giocatore[] {
|
||||
return useMemo(() => {
|
||||
const medie = mediePagelle(pagelle);
|
||||
const statCacche = statisticheCacche(cacche);
|
||||
const palloni = conteggioTurni(turni);
|
||||
const palloni = conteggioTurni(turni, eventi);
|
||||
const mvpVinti = mvpVintiPerGiocatore(votiMvp);
|
||||
|
||||
return squadra
|
||||
|
||||
@@ -74,7 +74,8 @@ assert.equal(conAllenamentoSalvato["e2"], "g5");
|
||||
const molti = Array.from({ length: giocatori.length + 2 }, (_, i) =>
|
||||
evento(`x${i}`, `2026-10-${String(i + 1).padStart(2, "0")}`, "partita"),
|
||||
);
|
||||
const rotazione = conteggioTurni(completaTurni({}, molti, rosa));
|
||||
// Tutte "passate" rispetto a questa data, altrimenti conteggioTurni le scarterebbe.
|
||||
const rotazione = conteggioTurni(completaTurni({}, molti, rosa), molti, "2026-11-01");
|
||||
const carichi = Object.values(rotazione);
|
||||
assert.equal(
|
||||
Math.max(...carichi) - Math.min(...carichi),
|
||||
@@ -102,13 +103,38 @@ assert.equal(conFantasma["e1"], "gXX", "il turno storico resta com'è");
|
||||
assert.ok(conFantasma["e2"], "la partita riceve comunque una proposta");
|
||||
assert.equal(conFantasma["e3"], undefined, "l'allenamento senza salvataggio resta vuoto");
|
||||
|
||||
// --- conteggioTurni ----------------------------------------------------------
|
||||
assert.deepEqual(conteggioTurni({ a: "g1", b: "g1", c: "g2" }), { g1: 2, g2: 1 });
|
||||
assert.deepEqual(conteggioTurni({}), {});
|
||||
// --- conteggioTurni: solo eventi già passati ----------------------------------
|
||||
const eventiConteggio: Evento[] = [
|
||||
evento("c1", "2026-09-01", "partita"),
|
||||
evento("c2", "2026-09-05", "partita"),
|
||||
evento("c3", "2026-09-10", "allenamento"), // futuro rispetto a OGGI_CONTEGGIO
|
||||
];
|
||||
const OGGI_CONTEGGIO = "2026-09-08";
|
||||
assert.deepEqual(
|
||||
conteggioTurni({ c1: "g1", c2: "g1", c3: "g2" }, eventiConteggio, OGGI_CONTEGGIO),
|
||||
{ g1: 2 },
|
||||
"il turno di un evento futuro non è ancora contato, anche se già assegnato",
|
||||
);
|
||||
assert.deepEqual(
|
||||
conteggioTurni({}, eventiConteggio, OGGI_CONTEGGIO),
|
||||
{},
|
||||
"nessun turno assegnato: conteggio vuoto",
|
||||
);
|
||||
|
||||
// --- oggiISO -----------------------------------------------------------------
|
||||
// --- oggiISO -------------------------------------------------------------------
|
||||
assert.match(oggiISO(), /^\d{4}-\d{2}-\d{2}$/);
|
||||
assert.equal(oggiISO(), new Date().toLocaleDateString("sv-SE"), "data locale, non UTC");
|
||||
// Stesso controllo di dataOggi() in scout-live.test.ts: oggiISO() ne è un alias, il fuso
|
||||
// deve restare Europe/Rome anche passando da qui.
|
||||
assert.equal(
|
||||
oggiISO(new Date("2026-01-15T23:30:00Z")),
|
||||
"2026-01-16",
|
||||
"CET: mezzanotte italiana precede quella UTC di un'ora",
|
||||
);
|
||||
assert.equal(
|
||||
oggiISO(new Date("2026-07-15T22:30:00Z")),
|
||||
"2026-07-16",
|
||||
"CEST: il cambio ora legale porta lo scarto a due ore, non resta fisso a uno",
|
||||
);
|
||||
|
||||
// --- destinatariPromemoriaPalloni --------------------------------------------
|
||||
const eventiPush: Evento[] = [
|
||||
|
||||
Reference in New Issue
Block a user