Soglie dei badge ricalibrate su ~71 eventi a stagione; obiettivo pagelle a 1000
Presenza fissa 15/35/55, Sempre in palestra 5/10/20, Sherpa dei palloni 3/5/8; obiettivo o13 da 200 a 1000 voti. Test di integrazione ora derivano le soglie dalle definizioni; documenti e CHANGELOG aggiornati. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
50930ac142
commit
cfbba613dc
11 files changed
+109
-88
No files matched your search
@@ -106,7 +106,7 @@ if (!locale) {
|
||||
// m1-m3: turno confermato esplicitamente a pv1 (3 turni -> soglia bronzo).
|
||||
// m4: NESSUN turno confermato -> non deve contare per nessuno, anche se un algoritmo
|
||||
// di rotazione (usato altrove per la UI) proporrebbe qualcuno in automatico.
|
||||
// m5-m7: confermati di nuovo a pv1 (6 turni totali -> soglia argento).
|
||||
// m5-m6: confermati di nuovo a pv1 (5 turni totali -> soglia argento).
|
||||
const eventi = [
|
||||
[`${PREFISSO}-m1`, "2020-01-01", "pv1"],
|
||||
[`${PREFISSO}-m2`, "2020-01-02", "pv1"],
|
||||
@@ -114,7 +114,6 @@ if (!locale) {
|
||||
[`${PREFISSO}-m4`, "2020-01-04", null],
|
||||
[`${PREFISSO}-m5`, "2020-01-05", "pv1"],
|
||||
[`${PREFISSO}-m6`, "2020-01-06", "pv1"],
|
||||
[`${PREFISSO}-m7`, "2020-01-07", "pv1"],
|
||||
] as const;
|
||||
|
||||
for (const [id, data] of eventi.slice(0, 3)) await creaEvento(id, data);
|
||||
@@ -128,7 +127,7 @@ if (!locale) {
|
||||
assert.equal(
|
||||
statoBadge(palloniDef, giocatoreAzzerato(conteggioA3["pv1"]!)).grado,
|
||||
"bronzo",
|
||||
"3 turni: bronzo, non oltre (soglia argento è 6)",
|
||||
"3 turni: bronzo, non oltre (soglia argento è 5)",
|
||||
);
|
||||
|
||||
for (const [id, data] of eventi.slice(3)) await creaEvento(id, data);
|
||||
@@ -136,13 +135,13 @@ if (!locale) {
|
||||
if (giocatore) await confermaTurno(id, giocatore);
|
||||
|
||||
const eventiLetti = await leggiEventi();
|
||||
assert.equal(eventiLetti.length, 7, "tutti gli eventi scritti si rileggono");
|
||||
assert.equal(eventiLetti.length, 6, "tutti gli eventi scritti si rileggono");
|
||||
|
||||
const salvati = await leggiTurniSalvati();
|
||||
assert.equal(Object.keys(salvati).length, 6, "6 turni confermati esplicitamente, m4 no");
|
||||
assert.equal(Object.keys(salvati).length, 5, "5 turni confermati esplicitamente, m4 no");
|
||||
|
||||
const conteggio = conteggioTurni(salvati, eventiLetti, OGGI);
|
||||
assert.equal(conteggio["pv1"], 6, "6 turni confermati per pv1");
|
||||
assert.equal(conteggio["pv1"], 5, "5 turni confermati per pv1");
|
||||
assert.equal(
|
||||
conteggio["pv2"] ?? 0,
|
||||
0,
|
||||
@@ -150,7 +149,7 @@ if (!locale) {
|
||||
);
|
||||
|
||||
const badgePv1 = statoBadge(palloniDef, giocatoreAzzerato(conteggio["pv1"]!));
|
||||
assert.equal(badgePv1.grado, "argento", "6 turni: soglia argento raggiunta");
|
||||
assert.equal(badgePv1.grado, "argento", "5 turni: soglia argento raggiunta");
|
||||
|
||||
const badgePv2 = statoBadge(palloniDef, giocatoreAzzerato(conteggio["pv2"] ?? 0));
|
||||
assert.equal(badgePv2.grado, null, "zero turni confermati: nessun badge");
|
||||
|
||||
@@ -122,54 +122,63 @@ if (!locale) {
|
||||
await prova(
|
||||
"il badge presenze passa da bronzo a oro con presenze vere lette dal database",
|
||||
async () => {
|
||||
// 30 allenamenti passati. "pp1" risponde a tutti e 30 (i primi 5 "presente", un
|
||||
// "ritardo" nel mezzo per verificare che conti come presenza, il resto "presente"),
|
||||
// così una sola scrittura basta a verificare le tre soglie 5/15/30.
|
||||
for (let i = 1; i <= 30; i += 1) {
|
||||
// Tanti allenamenti passati quanti ne chiede l'oro. "pp1" risponde a tutti (un "ritardo"
|
||||
// nel mezzo per verificare che conti come presenza), così una sola scrittura basta a
|
||||
// verificare le tre soglie.
|
||||
const { bronzo, argento, oro } = presenzeDef.soglie;
|
||||
for (let i = 1; i <= oro; i += 1) {
|
||||
await creaEvento(`${PREFISSO}-a${String(i).padStart(2, "0")}`, i);
|
||||
}
|
||||
for (let i = 1; i <= 30; i += 1) {
|
||||
for (let i = 1; i <= oro; i += 1) {
|
||||
const stato = i === 10 ? "ritardo" : "presente";
|
||||
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "pp1", stato);
|
||||
}
|
||||
// "pp2" risponde solo ai primi 5: resta a bronzo, non oltre.
|
||||
for (let i = 1; i <= 5; i += 1) {
|
||||
// "pp2" risponde solo ai primi `bronzo`: resta a bronzo, non oltre.
|
||||
for (let i = 1; i <= bronzo; i += 1) {
|
||||
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "pp2", "presente");
|
||||
}
|
||||
// "pp2" risponde anche "assente" a un evento: non deve contare.
|
||||
await rispondi(`${PREFISSO}-a06`, "pp2", "assente");
|
||||
await rispondi(`${PREFISSO}-a${String(bronzo + 1).padStart(2, "0")}`, "pp2", "assente");
|
||||
|
||||
const eventi = await leggiEventi();
|
||||
assert.equal(eventi.length, 30, "tutti gli eventi scritti si rileggono");
|
||||
assert.equal(eventi.length, oro, "tutti gli eventi scritti si rileggono");
|
||||
const presenze = await leggiPresenze();
|
||||
|
||||
const contoPp1 = contaPresenzeGiocatore("pp1", eventi, presenze, OGGI);
|
||||
assert.equal(contoPp1, 30, "30 risposte, incluso un ritardo contato come presenza");
|
||||
assert.equal(
|
||||
contoPp1,
|
||||
oro,
|
||||
"una risposta per evento, incluso un ritardo contato come presenza",
|
||||
);
|
||||
assert.equal(
|
||||
statoBadge(presenzeDef, giocatoreAzzerato(contoPp1)).grado,
|
||||
"oro",
|
||||
"30 presenze: soglia oro raggiunta",
|
||||
`${oro} presenze: soglia oro raggiunta`,
|
||||
);
|
||||
|
||||
const contoPp2 = contaPresenzeGiocatore("pp2", eventi, presenze, OGGI);
|
||||
assert.equal(contoPp2, 5, "5 presenti, l'assente su a06 non conta");
|
||||
assert.equal(contoPp2, bronzo, "solo i presenti contano, l'assente su a-extra no");
|
||||
const badgePp2 = statoBadge(presenzeDef, giocatoreAzzerato(contoPp2));
|
||||
assert.equal(badgePp2.grado, "bronzo", "5 presenze: soglia bronzo raggiunta, non oltre");
|
||||
assert.equal(
|
||||
badgePp2.grado,
|
||||
"bronzo",
|
||||
`${bronzo} presenze: soglia bronzo raggiunta, non oltre`,
|
||||
);
|
||||
assert.equal(badgePp2.prossimo, "argento");
|
||||
assert.equal(badgePp2.prossimaSoglia, 15);
|
||||
assert.equal(badgePp2.prossimaSoglia, argento);
|
||||
|
||||
// Un pp2 a metà strada (15 presenze) sblocca l'argento.
|
||||
for (let i = 7; i <= 16; i += 1) {
|
||||
// Un pp2 a metà strada (`argento` presenze) sblocca l'argento.
|
||||
for (let i = bronzo + 2; i <= argento + 1; i += 1) {
|
||||
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "pp2", "presente");
|
||||
}
|
||||
const eventiDopo = await leggiEventi();
|
||||
const presenzeDopo = await leggiPresenze();
|
||||
const contoPp2Dopo = contaPresenzeGiocatore("pp2", eventiDopo, presenzeDopo, OGGI);
|
||||
assert.equal(contoPp2Dopo, 15, "5 + 10 nuove presenze");
|
||||
assert.equal(contoPp2Dopo, argento, "bronzo + nuove presenze fino all'argento");
|
||||
assert.equal(
|
||||
statoBadge(presenzeDef, giocatoreAzzerato(contoPp2Dopo)).grado,
|
||||
"argento",
|
||||
"15 presenze: soglia argento raggiunta",
|
||||
`${argento} presenze: soglia argento raggiunta`,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -125,39 +125,40 @@ if (!locale) {
|
||||
await prova(
|
||||
"il badge passa da bronzo a oro con presenze consecutive vere, e un buco lo azzera",
|
||||
async () => {
|
||||
// 10 allenamenti passati, tutti presenti per "sa1": bronzo (3), poi argento (6), poi
|
||||
// oro (10) man mano che si rileggono i dati.
|
||||
for (let i = 1; i <= 10; i += 1) {
|
||||
// Tanti allenamenti passati quanti ne chiede l'oro, tutti presenti per "sa1": le prime
|
||||
// `bronzo` presenze valgono bronzo, tutte e `oro` valgono oro.
|
||||
const { bronzo, oro } = serieDef.soglie;
|
||||
for (let i = 1; i <= oro; i += 1) {
|
||||
await creaAllenamento(`${PREFISSO}-a${String(i).padStart(2, "0")}`, i);
|
||||
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "sa1", "presente");
|
||||
}
|
||||
const eventi10 = await leggiEventi();
|
||||
const presenze10 = await leggiPresenze();
|
||||
const serieA3 = serieConsecutiva(
|
||||
const eventiOro = await leggiEventi();
|
||||
const presenzeOro = await leggiPresenze();
|
||||
const serieBronzo = serieConsecutiva(
|
||||
"sa1",
|
||||
eventi10.slice(0, 3),
|
||||
presenze10,
|
||||
eventiOro.slice(0, bronzo),
|
||||
presenzeOro,
|
||||
"allenamento",
|
||||
OGGI,
|
||||
);
|
||||
assert.equal(serieA3, 3);
|
||||
assert.equal(serieBronzo, bronzo);
|
||||
assert.equal(
|
||||
statoBadge(serieDef, giocatoreAzzerato(serieA3)).grado,
|
||||
statoBadge(serieDef, giocatoreAzzerato(serieBronzo)).grado,
|
||||
"bronzo",
|
||||
"3 allenamenti di fila: soglia bronzo",
|
||||
`${bronzo} allenamenti di fila: soglia bronzo`,
|
||||
);
|
||||
|
||||
const serieCompleta = serieConsecutiva("sa1", eventi10, presenze10, "allenamento", OGGI);
|
||||
assert.equal(serieCompleta, 10, "presente a tutti e 10, nessun buco");
|
||||
const serieCompleta = serieConsecutiva("sa1", eventiOro, presenzeOro, "allenamento", OGGI);
|
||||
assert.equal(serieCompleta, oro, `presente a tutti e ${oro}, nessun buco`);
|
||||
assert.equal(
|
||||
statoBadge(serieDef, giocatoreAzzerato(serieCompleta)).grado,
|
||||
"oro",
|
||||
"10 allenamenti di fila: soglia oro",
|
||||
`${oro} allenamenti di fila: soglia oro`,
|
||||
);
|
||||
|
||||
// Un undicesimo allenamento con un buco (assente) azzera la serie.
|
||||
await creaAllenamento(`${PREFISSO}-a11`, 11);
|
||||
await rispondi(`${PREFISSO}-a11`, "sa1", "assente");
|
||||
// Un allenamento in più con un buco (assente) azzera la serie.
|
||||
await creaAllenamento(`${PREFISSO}-a${oro + 1}`, oro + 1);
|
||||
await rispondi(`${PREFISSO}-a${oro + 1}`, "sa1", "assente");
|
||||
const eventiConBuco = await leggiEventi();
|
||||
const presenzeConBuco = await leggiPresenze();
|
||||
const serieDopoBuco = serieConsecutiva(
|
||||
@@ -167,7 +168,7 @@ if (!locale) {
|
||||
"allenamento",
|
||||
OGGI,
|
||||
);
|
||||
assert.equal(serieDopoBuco, 0, "un'assenza azzera la serie, anche dopo 10 di fila");
|
||||
assert.equal(serieDopoBuco, 0, `un'assenza azzera la serie, anche dopo ${oro} di fila`);
|
||||
assert.equal(
|
||||
statoBadge(serieDef, giocatoreAzzerato(serieDopoBuco)).grado,
|
||||
null,
|
||||
@@ -182,7 +183,7 @@ if (!locale) {
|
||||
// ripartire da 1.
|
||||
const eventi = [`${PREFISSO}-b01`, `${PREFISSO}-b02`, `${PREFISSO}-b03`, `${PREFISSO}-b04`];
|
||||
for (let i = 0; i < eventi.length; i += 1) {
|
||||
await creaAllenamento(eventi[i]!, 20 + i);
|
||||
await creaAllenamento(eventi[i]!, serieDef.soglie.oro + 10 + i);
|
||||
}
|
||||
await rispondi(eventi[0]!, "sa2", "presente");
|
||||
await rispondi(eventi[1]!, "sa2", "presente");
|
||||
@@ -195,8 +196,8 @@ if (!locale) {
|
||||
assert.equal(serie, 3, "l'infortunio è saltato: 3 presenze restano consecutive");
|
||||
assert.equal(
|
||||
statoBadge(serieDef, giocatoreAzzerato(serie)).grado,
|
||||
"bronzo",
|
||||
"3 di fila (infortunio escluso dal conteggio): soglia bronzo",
|
||||
null,
|
||||
"3 di fila: ancora sotto la soglia bronzo, ma la serie non si è azzerata",
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
|
||||
Reference in new issue
Block a user