diff --git a/src/lib/rosa.ts b/src/lib/rosa.ts index 8482a49..d772104 100644 --- a/src/lib/rosa.ts +++ b/src/lib/rosa.ts @@ -1,15 +1,18 @@ import { useMemo } from "react"; import { giocatori, type Giocatore } from "./crapp-data"; -import { giocatoriConScout, useScoutMatches } from "./scout-store"; -import { useVotiMvp, vincitoriMvp } from "./mvp-voti"; +import { mvpVintiPerGiocatore, useVotiMvp } from "./mvp-voti"; import { mediePagelle, usePagelle } from "./pagelle"; import { statisticheCacche, useCacche } from "./cacche"; import { conteggioTurni } from "./palloni-core"; import { useTurniPalloni } from "./palloni"; import { useInfortuniERitardi } from "./infortuni"; -import { useGiocatoreBase } from "./user-store"; +import { useGiocatoreId } from "./user-store"; import { useEventi } from "./eventi"; -import { useRispostePresenze } from "./presenze"; +import { + contaPresenzeGiocatore, + totaliEventiGiocatore, + useRispostePresenze, +} from "./presenze"; import { obiettiviOrdinati } from "./obiettivi"; import { useCsi } from "./csi"; import { partiteGiocate } from "./csi-core"; @@ -20,12 +23,13 @@ import { partiteGiocate } from "./csi-core"; * nessuna query aggiuntiva rispetto a quelle che l'app fa comunque. */ export function useRosa(): Giocatore[] { - const scoutMatches = useScoutMatches(); const voti = useVotiMvp(); const { voti: pagelle } = usePagelle(); const { righe: cacche } = useCacche(); const { turni } = useTurniPalloni(); const { infortuni, ritardi } = useInfortuniERitardi(); + const { eventi } = useEventi(); + const { presenze: mappaPresenze } = useRispostePresenze(); const votiMvp = voti.data ?? []; @@ -33,24 +37,38 @@ export function useRosa(): Giocatore[] { const medie = mediePagelle(pagelle); const statCacche = statisticheCacche(cacche); const palloni = conteggioTurni(turni); - return giocatoriConScout(scoutMatches, vincitoriMvp(votiMvp)).map((g) => ({ + const mvpVinti = mvpVintiPerGiocatore(votiMvp); + + return giocatori.map((g) => ({ ...g, - mediaVoto: medie[g.id]?.media ?? g.mediaVoto, + presenze: contaPresenzeGiocatore(g.id, eventi, mappaPresenze), + totaliEventi: totaliEventiGiocatore(g.id, eventi), + mvp: mvpVinti[g.id] ?? 0, + mediaVoto: medie[g.id]?.media ?? 0, palloni: palloni[g.id] ?? 0, cacche: statCacche[g.id]?.giornateTop ?? 0, cacchePartita: statCacche[g.id]?.media ?? 0, infortuni: infortuni[g.id] ?? 0, ritardi: ritardi[g.id] ?? 0, })); - }, [scoutMatches, votiMvp, pagelle, cacche, turni, infortuni, ritardi]); + }, [ + votiMvp, + pagelle, + cacche, + turni, + infortuni, + ritardi, + eventi, + mappaPresenze, + ]); } /** Il giocatore selezionato sul dispositivo, con le statistiche complete. */ export function useIo(): Giocatore | null { - const base = useGiocatoreBase(); + const id = useGiocatoreId(); const rosa = useRosa(); - if (!base) return null; - return rosa.find((g) => g.id === base.id) ?? base; + if (!id) return null; + return rosa.find((g) => g.id === id) ?? null; } /** Obiettivi collaborativi calcolati sui dati reali già in cache. */ diff --git a/src/lib/scout-store.ts b/src/lib/scout-store.ts index d6b499b..e1fa149 100644 --- a/src/lib/scout-store.ts +++ b/src/lib/scout-store.ts @@ -186,24 +186,22 @@ export function totaliSquadra(matches: ScoutMatch[]) { return out; } -/** Presenze e MVP ricavati dalle partite scoutate: nessuna statistica individuale offensiva. - * `mvpPerMatch` mappa idPartita -> nome dell'MVP eletto dalla squadra. */ +/** + * MVP ricavati dalle partite scoutate (mappa matchId → nome vincitore). + * Le presenze personali restano su `risposte_presenze`, non sullo scout. + */ export function giocatoriConScout( matches: ScoutMatch[], mvpPerMatch: Record = {}, ): Giocatore[] { return giocatori.map((g) => { - let presenze = 0; let mvp = 0; for (const m of matches) { - if (totaliPerGiocatore(m.azioni).has(g.id)) presenze += 1; if (mvpPerMatch[m.id] === g.nome) mvp += 1; } return { ...g, - mvp: g.mvp + mvp, - presenze: g.presenze + presenze, - totaliEventi: g.totaliEventi + matches.length, + mvp, }; }); } diff --git a/test/unit/scout-store.test.ts b/test/unit/scout-store.test.ts index c8bcb61..186aae2 100644 --- a/test/unit/scout-store.test.ts +++ b/test/unit/scout-store.test.ts @@ -59,20 +59,24 @@ assert.deepEqual(totaliSquadra([match("m1", 3, 0, azioni), match("m2", 3, 1, azi }); assert.deepEqual(totaliSquadra([]), { punti: 0, ace: 0, muri: 0, errori: 0 }); -// --- giocatoriConScout: presenze e MVP, nessuna statistica offensiva --------- +// --- giocatoriConScout: solo MVP da scout, presenze separate ----------------- const base = giocatori.find((g) => g.id === "g1")!; const conScout = giocatoriConScout([match("m1", 3, 0, azioni)], { m1: base.nome }); const dopo = conScout.find((g) => g.id === "g1")!; -assert.equal(dopo.presenze, base.presenze + 1, "chi ha azioni risulta presente"); -assert.equal(dopo.mvp, base.mvp + 1, "l'MVP eletto viene sommato"); -assert.equal(dopo.totaliEventi, base.totaliEventi + 1); +assert.equal(dopo.presenze, 0, "le azioni scout non alimentano le presenze personali"); +assert.equal(dopo.mvp, 1, "l'MVP eletto viene contato"); +assert.equal(dopo.totaliEventi, 0, "totaliEventi arriva dagli eventi CrAPP, non dallo scout"); const assente = conScout.find((g) => g.id === "g3")!; -const baseAssente = giocatori.find((g) => g.id === "g3")!; -assert.equal(assente.presenze, baseAssente.presenze, "chi non ha azioni non guadagna presenze"); -assert.equal(assente.totaliEventi, baseAssente.totaliEventi + 1, "l'evento conta per tutti"); +assert.equal(assente.presenze, 0, "senza risposte presenze resta a zero"); +assert.equal(assente.mvp, 0); +assert.equal(assente.totaliEventi, 0); -assert.deepEqual(giocatoriConScout([]), giocatori, "senza partite la rosa resta invariata"); +const senzaPartite = giocatoriConScout([]); +assert.ok( + senzaPartite.every((g) => g.presenze === 0 && g.mvp === 0 && g.totaliEventi === 0), + "senza partite scout le statistiche restano a zero", +); // --- metadati azioni --------------------------------------------------------- for (const [tipo, meta] of Object.entries(azioniMeta)) {