longevity: la prova sul congelamento ora discrimina davvero il ricalcolo

Il peso mutato prima era l'unico sotto-dominio del suo asse (questionario_lifestyle,
1.00 in Stile di Vita & Sonno): in una media pesata a un solo elemento disponibile
il peso si semplifica sia al numeratore sia al denominatore, quindi il test restava
verde anche se refertoDi avesse ricalcolato invece di leggere gli score congelati.
Sostituita con il peso di un sotto-dominio ASSENTE in un asse a piu' elementi con
copertura parziale non nulla (hrv in Recupero & Sistema Nervoso): li' un ricalcolo
sposta davvero la copertura oltre soglia. Verificato rosso col ricalcolo forzato,
verde ripristinato.
This commit is contained in:
2026-08-22 14:32:43 +02:00
parent 7f01ee0b45
commit 6630be7a02
+44 -3
View File
@@ -20,6 +20,27 @@ function conCompilazione() {
return { db, s }; return { db, s };
} }
/**
* Come conCompilazione, con IN PIU' una risposta di questionario_sonno (q_riposato).
* Serve solo alla prova sul congelamento, che ha bisogno di un asse con PIU' sotto-domini
* pesati e copertura parziale non nulla — vedi il commento sopra la mutazione qui sotto per
* il perche' conCompilazione da sola non basta.
*/
function conCoperturaParziale() {
const db = createLongevityDb(':memory:');
seedRegistro(db); seedPesi(db, MODEL_VERSION);
db.prepare(`INSERT INTO soggetti (client_code, sesso) VALUES ('ISL-0001','F')`).run();
const s = salvaCompilazione(db, {
client_code: 'ISL-0001', data: '2026-08-22', eta: 35,
risposte: {
q_attivita: 5, q_alimentazione: 8, q_sigarette: 0, q_alcol_life: 2, q_luce: 2, q_schermi: 10,
q_riposato: 8,
},
});
salvaScore(db, s, calcolaSessione(db, s));
return { db, s };
}
describe('il referto del cliente', () => { describe('il referto del cliente', () => {
it('restituisce i sette assi', () => { it('restituisce i sette assi', () => {
const { db, s } = conCompilazione(); const { db, s } = conCompilazione();
@@ -46,10 +67,30 @@ describe('il referto del cliente', () => {
}); });
it('legge i punteggi congelati, non li ricalcola al volo', () => { it('legge i punteggi congelati, non li ricalcola al volo', () => {
const { db, s } = conCompilazione(); const { db, s } = conCoperturaParziale();
// se rileggesse le misure invece degli score salvati, cambiare i pesi cambierebbe il referto
const prima = JSON.stringify(refertoDi(db, s)); const prima = JSON.stringify(refertoDi(db, s));
db.prepare(`UPDATE pesi SET peso = 0.99 WHERE model_version = ? AND elemento = 'questionario_lifestyle'`).run(MODEL_VERSION); // ATTENZIONE alla scelta della mutazione: non una qualunque, una che DISCRIMINA
// davvero un ricalcolo da una lettura congelata.
//
// 'Recupero & Sistema Nervoso' pesa QUATTRO sotto-domini (hrv 0.50, pressione 0.15,
// hrr 0.15, questionario_sonno 0.20); questa sessione ne misura UNO solo
// (questionario_sonno, via q_riposato in conCoperturaParziale) — copertura vera
// 0.20/1.00=0.20, sotto COPERTURA_MINIMA (0.4): l'asse e' 'insufficiente', ma con
// disponibili.length===1, non 0 — la formula del peso viene davvero eseguita, non
// bypassata dalla scorciatoia "nessun dato disponibile" di aggrega() in cascata.ts.
// Azzerando il peso di 'hrv' (un sotto-dominio ASSENTE) il totale scende a 0.50 e la
// copertura vera diventa 0.20/0.50=0.40: attraversa la soglia, l'asse passerebbe da
// insufficiente a ok SE il referto ricalcolasse (provato: vedi task-3-report.md).
//
// Una mutazione come questa NON discrimina, ed e' un errore da non ripetere:
// il peso dell'UNICO sotto-dominio di un asse a un solo elemento (es.
// 'questionario_lifestyle', 1.00 in 'Stile di Vita & Sonno') si semplifica sempre,
// sia al numeratore sia al denominatore della media pesata — cambiarlo non altera
// ne' il valore ne' la copertura, quindi il test resterebbe verde anche se
// refertoDi ricalcolasse davvero (era il bug di questo stesso test, corretto qui).
db.prepare(
`UPDATE pesi SET peso = 0 WHERE model_version = ? AND livello='asse' AND contenitore='Recupero & Sistema Nervoso' AND elemento='hrv'`
).run(MODEL_VERSION);
expect(JSON.stringify(refertoDi(db, s))).toBe(prima); expect(JSON.stringify(refertoDi(db, s))).toBe(prima);
}); });