Scout live: valutazioni − / + per fondamentale e per set
Per ogni convocato un − o un + su battuta, ricezione, attacco e muro, separato per set e fuori dal punteggio (DD-053, migration m39: colonna scout_partite.valutazioni). Lo stato in corso le salva in scout_live.stato; il CSV admin ha la tabella per set. Nella pagina dello scout tolti il blocco avversario/campo, i tasti delle azioni e il tabellone del punteggio; il titolo della sezione mostra cognome e numero del giocatore. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
09dba1890d
commit
51b7a10c99
16 files changed
+367
-120
No files matched your search
@@ -32,6 +32,7 @@ if (!locale) {
|
||||
"turni_palloni",
|
||||
"risposte_presenze",
|
||||
"scout_live",
|
||||
"scout_partite",
|
||||
] as const;
|
||||
|
||||
const rest = (percorso: string, init?: RequestInit) =>
|
||||
@@ -312,6 +313,32 @@ if (!locale) {
|
||||
"il jsonb viene rimpiazzato: i campi del set precedente non restano appesi",
|
||||
);
|
||||
});
|
||||
|
||||
// --- scout: le valutazioni − / + stanno accanto alle azioni (m39) ----------------
|
||||
await prova(
|
||||
"la partita scoutata conserva le valutazioni; senza, l'elenco è vuoto",
|
||||
async () => {
|
||||
const evento = `${PREFISSO}-e5`;
|
||||
const base = {
|
||||
evento_id: evento,
|
||||
data: "2026-11-02",
|
||||
avversario: "X",
|
||||
set_nostri: 3,
|
||||
set_loro: 0,
|
||||
};
|
||||
await upsert("scout_partite", "id", { ...base, id: `${PREFISSO}-s1` });
|
||||
const valutazioni = [
|
||||
{ id: "v1", giocatoreId: "g1", fondamentale: "battuta", segno: "+", set: 1, ts: 0 },
|
||||
];
|
||||
await upsert("scout_partite", "id", { ...base, id: `${PREFISSO}-s2`, valutazioni });
|
||||
const righe = await leggi(
|
||||
"scout_partite",
|
||||
`evento_id=eq.${evento}&select=id,valutazioni&order=id`,
|
||||
);
|
||||
assert.deepEqual(righe[0]?.["valutazioni"], [], "le partite senza valutazioni hanno []");
|
||||
assert.deepEqual(righe[1]?.["valutazioni"], valutazioni);
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
for (const tabella of TABELLE) {
|
||||
const colonna = tabella.endsWith("_voti") ? "match_id" : "evento_id";
|
||||
|
||||
@@ -29,6 +29,7 @@ const match: ScoutMatch = {
|
||||
[25, 18],
|
||||
],
|
||||
azioni: [a("attacco", g1.id), a("ace", g1.id, 2), a("errore", g2.id, 2), a("punto_avv")],
|
||||
valutazioni: [],
|
||||
};
|
||||
|
||||
const csv = csvScoutMatch(match, giocatori);
|
||||
@@ -78,3 +79,42 @@ const conVirgolette = csvScoutMatch({ ...match, avversario: 'Team "X"' }, giocat
|
||||
assert.ok(conVirgolette.includes('"Team ""X"""'));
|
||||
|
||||
console.log("scout-export: ok");
|
||||
|
||||
// --- valutazioni − / + per set -------------------------------------------------
|
||||
assert.ok(!csv.includes("Battuta +"), "senza valutazioni la sezione non c'è");
|
||||
const val = (
|
||||
giocatoreId: string,
|
||||
fondamentale: "battuta" | "muro",
|
||||
segno: "+" | "-",
|
||||
set: number,
|
||||
) => ({
|
||||
id: `${giocatoreId}-${fondamentale}-${segno}-${set}-${Math.random()}`,
|
||||
giocatoreId,
|
||||
fondamentale,
|
||||
segno,
|
||||
set,
|
||||
ts: 0,
|
||||
});
|
||||
const conVal = csvScoutMatch(
|
||||
{
|
||||
...match,
|
||||
valutazioni: [
|
||||
val(g1.id, "battuta", "+", 1),
|
||||
val(g1.id, "battuta", "+", 1),
|
||||
val(g1.id, "battuta", "-", 1),
|
||||
val(g1.id, "muro", "-", 2),
|
||||
],
|
||||
},
|
||||
giocatori,
|
||||
);
|
||||
assert.ok(
|
||||
conVal.includes(
|
||||
"Set;Numero;Giocatore;Battuta +;Battuta -;Ricezione +;Ricezione -;Attacco +;Attacco -;Muro +;Muro -",
|
||||
),
|
||||
);
|
||||
assert.ok(
|
||||
conVal.includes(`1;${g1.numero};${g1.nome};2;1;0;0;0;0;0;0`),
|
||||
"set 1: 2 più e 1 meno in battuta",
|
||||
);
|
||||
assert.ok(conVal.includes(`2;${g1.numero};${g1.nome};0;0;0;0;0;0;0;1`), "set 2: 1 meno a muro");
|
||||
assert.ok(!conVal.includes(`;${g2.nome};0;0;0;0;0;0;0;0`), "chi non ha valutazioni non ha riga");
|
||||
@@ -5,7 +5,10 @@ import { SCOUT_STATO_KEY, statoIniziale } from "@/lib/scout-stato";
|
||||
// --- statoIniziale: parte vuoto, con avversario e campo memorizzati -----------
|
||||
const stato = statoIniziale("Avversari", true);
|
||||
// Confronta una copia: deepEqual restringerebbe `stato` al letterale, con `azioni: never[]`.
|
||||
assert.deepEqual({ ...stato }, { azioni: [], setChiusi: [], avversario: "Avversari", casa: true });
|
||||
assert.deepEqual(
|
||||
{ ...stato },
|
||||
{ azioni: [], valutazioni: [], setChiusi: [], avversario: "Avversari", casa: true },
|
||||
);
|
||||
|
||||
const trasferta = statoIniziale("Altra Squadra", false);
|
||||
assert.equal(trasferta.casa, false);
|
||||
@@ -14,6 +17,7 @@ assert.deepEqual(trasferta.azioni, [], "ogni chiamata parte da una lista vuota i
|
||||
// Le liste non devono essere condivise tra due stati distinti.
|
||||
stato.azioni.push({ id: "a1", tipo: "attacco", set: 1, ts: 0 });
|
||||
assert.deepEqual(trasferta.azioni, [], "modificare uno stato non tocca l'altro");
|
||||
assert.notEqual(stato.valutazioni, trasferta.valutazioni, "anche le valutazioni sono indipendenti");
|
||||
|
||||
// --- SCOUT_STATO_KEY: chiave stabile per React Query --------------------------
|
||||
assert.deepEqual(SCOUT_STATO_KEY("evt-1"), ["scout-stato", "evt-1"]);
|
||||
|
||||
@@ -3,10 +3,13 @@ import assert from "node:assert/strict";
|
||||
import { giocatori } from "@/lib/crapp-data";
|
||||
import {
|
||||
azioniMeta,
|
||||
contaValutazioni,
|
||||
fondamentali,
|
||||
giocatoriConScout,
|
||||
totaliPerGiocatore,
|
||||
totaliSquadra,
|
||||
type Azione,
|
||||
type Valutazione,
|
||||
type ScoutMatch,
|
||||
} from "@/lib/scout-store";
|
||||
|
||||
@@ -32,6 +35,7 @@ const match = (
|
||||
setLoro,
|
||||
parziali: [],
|
||||
azioni,
|
||||
valutazioni: [],
|
||||
});
|
||||
|
||||
// --- totaliPerGiocatore: ace e muri valgono anche come punto ------------------
|
||||
@@ -84,3 +88,54 @@ for (const [tipo, meta] of Object.entries(azioniMeta)) {
|
||||
}
|
||||
|
||||
console.log("scout-store: ok");
|
||||
|
||||
// --- valutazioni − / +: per giocatore, fondamentale e set; fuori dal punteggio -------
|
||||
const v = (
|
||||
giocatoreId: string,
|
||||
fondamentale: Valutazione["fondamentale"],
|
||||
segno: Valutazione["segno"],
|
||||
set = 1,
|
||||
): Valutazione => ({
|
||||
id: `${giocatoreId}-${fondamentale}-${segno}-${set}-${Math.random()}`,
|
||||
giocatoreId,
|
||||
fondamentale,
|
||||
segno,
|
||||
set,
|
||||
ts: 0,
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
fondamentali.map((f) => f.id),
|
||||
["battuta", "ricezione", "attacco", "muro"],
|
||||
);
|
||||
const val = [
|
||||
v("g1", "battuta", "+"),
|
||||
v("g1", "battuta", "+"),
|
||||
v("g1", "battuta", "-"),
|
||||
v("g1", "ricezione", "-", 2),
|
||||
v("g1", "muro", "+", 2),
|
||||
v("g2", "attacco", "+"),
|
||||
];
|
||||
assert.deepEqual(contaValutazioni(val, "g1", 1), {
|
||||
battuta: { piu: 2, meno: 1 },
|
||||
ricezione: { piu: 0, meno: 0 },
|
||||
attacco: { piu: 0, meno: 0 },
|
||||
muro: { piu: 0, meno: 0 },
|
||||
});
|
||||
assert.deepEqual(
|
||||
contaValutazioni(val, "g1", 2).ricezione,
|
||||
{ piu: 0, meno: 1 },
|
||||
"il set 2 è separato",
|
||||
);
|
||||
assert.deepEqual(
|
||||
contaValutazioni(val, "g1").battuta,
|
||||
{ piu: 2, meno: 1 },
|
||||
"senza set: tutta la partita",
|
||||
);
|
||||
assert.deepEqual(contaValutazioni(val, "g1").ricezione, { piu: 0, meno: 1 });
|
||||
assert.deepEqual(
|
||||
contaValutazioni(val, "g3", 1).battuta,
|
||||
{ piu: 0, meno: 0 },
|
||||
"giocatore senza valutazioni",
|
||||
);
|
||||
assert.equal(totaliPerGiocatore([]).size, 0, "le valutazioni non sono azioni: nessun punto");
|
||||
Reference in new issue
Block a user