From c63bb1fe807c5ec9a09d188675f7d9e1d5408b56 Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Sat, 22 Aug 2026 09:02:20 +0200 Subject: [PATCH] =?UTF-8?q?longevity:=20chiude=20i=20tre=20buchi=20nei=20t?= =?UTF-8?q?est=20delle=20curve=20=E2=80=94=20ramo=20crescente=20di=20curva?= =?UTF-8?q?Gradini=20mai=20esercitato,=20test=20zeroVal=20non=20discrimina?= =?UTF-8?q?nte,=20cardinalita=20mancante=20su=20due=20confronti=20con=20l?= =?UTF-8?q?=20oracolo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/longevity/motore-curve.test.ts | 59 +++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/tests/longevity/motore-curve.test.ts b/tests/longevity/motore-curve.test.ts index 1395c16..32ef3d1 100644 --- a/tests/longevity/motore-curve.test.ts +++ b/tests/longevity/motore-curve.test.ts @@ -32,14 +32,18 @@ describe('curve del questionario, confrontate con l oracolo', () => { }); it('la crescente con plateau combacia', () => { - for (const c of casiDi('score_increasing_plateau')) { + const casi = casiDi('score_increasing_plateau'); + expect(casi.length).toBeGreaterThan(20); + for (const c of casi) { const [v, worst, plateau] = c.args as number[]; expect(curvaCrescenteConPlateau(v, worst, plateau)).toBeCloseTo(c.atteso, 1); } }); it('la diretta per dieci combacia', () => { - for (const c of casiDi('score_direct_x10')) { + const casi = casiDi('score_direct_x10'); + expect(casi.length).toBeGreaterThan(10); + for (const c of casi) { expect(curvaDirettaX10((c.args as number[])[0])).toBeCloseTo(c.atteso, 1); } }); @@ -63,10 +67,53 @@ describe('curve del questionario, confrontate con l oracolo', () => { expect(curvaGradini(40, steps, undefined, true)).toBeLessThan(20); }); - it('zeroVal ha la precedenza sui gradini: q_schermi a zero vale 100', () => { - const steps: [number, number][] = [[15, 85], [30, 70], [60, 40], [999, 10]]; - expect(curvaGradini(0, steps, 100, true)).toBe(100); - expect(curvaGradini(15, steps, 100, true)).toBe(85); + // Il ramo crescente non era esercitato da nessun test: l'ancoraggio (0, 20) + // — invece di (0, 100) — poteva essere invertito o sbagliato senza che + // niente diventasse rosso. Parametri veri da src/lib/longevity/registro.ts. + it('i gradini crescenti riproducono il prototipo: q_attivita e q_luce', () => { + // q_attivita: nessun zeroVal, i gradini partono già da (0, 20). + const stepsAttivita: [number, number][] = [[0, 20], [2, 50], [4, 80], [999, 100]]; + expect(curvaGradini(0, stepsAttivita, undefined, false)).toBe(20); + expect(curvaGradini(2, stepsAttivita, undefined, false)).toBe(50); + expect(curvaGradini(4, stepsAttivita, undefined, false)).toBe(80); + expect(curvaGradini(999, stepsAttivita, undefined, false)).toBe(100); + expect(curvaGradini(1, stepsAttivita, undefined, false)).toBe(35); // interpolato fra (0,20) e (2,50) + expect(curvaGradini(3, stepsAttivita, undefined, false)).toBe(65); // interpolato fra (2,50) e (4,80) + + // q_luce: zeroVal 20, gradini che partono da 0.5 — l'ancoraggio (0, 20) + // serve davvero per interpolare fra 0 (escluso, coperto da zeroVal) e 0.5. + const stepsLuce: [number, number][] = [[0.5, 60], [1, 90], [999, 100]]; + expect(curvaGradini(0.5, stepsLuce, 20, false)).toBe(60); + expect(curvaGradini(1, stepsLuce, 20, false)).toBe(90); + expect(curvaGradini(999, stepsLuce, 20, false)).toBe(100); + expect(curvaGradini(0.75, stepsLuce, 20, false)).toBe(75); // interpolato fra (0.5,60) e (1,90) + expect(curvaGradini(0.25, stepsLuce, 20, false)).toBe(40); // interpolato fra l'ancoraggio (0,20) e (0.5,60) + }); + + // Non basta controllare che a zero il risultato sia il valore atteso: se + // zeroVal COINCIDE con l'ancoraggio di default (100 per il decrescente, + // 20 per il crescente, come in q_schermi e q_luce) il test passa anche + // cancellando dal codice la riga che gestisce lo zero. Qui zeroVal è + // deliberatamente diverso dall'ancoraggio, in entrambe le direzioni: se + // la riga sparisse, l'interpolazione a v=0 darebbe l'ancoraggio (100 o 20), + // non questi valori, e il test diventerebbe rosso. + it('zeroVal vince sui gradini anche quando NON coincide con l ancoraggio', () => { + // q_schermi, il caso reale: qui zeroVal (100) coincide con l'ancoraggio + // decrescente (100), quindi da solo NON è discriminante — resta utile + // come controllo del valore vero, non come prova dello zero speciale. + const stepsSchermi: [number, number][] = [[15, 85], [30, 70], [60, 40], [999, 10]]; + expect(curvaGradini(0, stepsSchermi, 100, true)).toBe(100); + expect(curvaGradini(15, stepsSchermi, 100, true)).toBe(85); + + // Discriminante, decrescente: ancoraggio di default sarebbe 100, + // zeroVal è 42. Senza la riga dello zero speciale risulterebbe 100. + const stepsDecrescenteDiscriminante: [number, number][] = [[10, 80], [30, 50], [999, 10]]; + expect(curvaGradini(0, stepsDecrescenteDiscriminante, 42, true)).toBe(42); + + // Discriminante, crescente: ancoraggio di default sarebbe 20, + // zeroVal è 55. Senza la riga dello zero speciale risulterebbe 20. + const stepsCrescenteDiscriminante: [number, number][] = [[5, 40], [20, 70], [999, 100]]; + expect(curvaGradini(0, stepsCrescenteDiscriminante, 55, false)).toBe(55); }); it('clamp e lerp si comportano come nell oracolo', () => {