longevity: test fisici nel registro e nel calcolo (prerequisito del gestionale) #1
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
COSA: il registro contiene solo le 20 domande del questionario; le 20 curve fisiche di apps/platforms/src/lib/longevity/motore/test-fisici.ts sono verificate contro l'oracolo ma non collegate a calcolaSessione (motore/index.ts). Senza questo, 6 assi su 7 restano 'insufficiente' qualunque cosa inserisca il trainer.
PERCHÉ: il gestionale trainer (issue seguente) inserisce misure fisiche; devono entrare nel punteggio.
FATTO QUANDO: registro con le misure grezze fisiche; sotto-domini fisici calcolati con età e sesso; la sessione di check-up e quella di questionario si combinano nel punteggio; caso demo dell'oracolo riprodotto in un test; test verdi.
🤖 goldrake — preso in carico 2026-09-26T12:23:39Z
ramo:
lavoro/goldrake· capacità: docker, pubblica, sempre-accesa, systemdESITO: richiesta
RIF: gitea:Adriano/InsanityLab-web#1
COSA: analisi (passo 1). Misure fisiche grezze nel registro, sotto-domini fisici calcolati con età e sesso, sessioni combinate nel punteggio.
RAMO: lavoro/goldrake — clone di lavoro goldrake:~/lavoro/InsanityLab-web (NON /opt/docker/insanitylab/src, che è la produzione)
BASE:
13d8cdd, apps/platforms: 27 file di test, 202 verdiStato verificato
apps/platforms/src/lib/longevity/registro.ts: il registro semina soloQUESTIONARIO(20 vociq_*).PESI_ASSEcita 17 sotto-domini fisici che nessun test alimenta.motore/test-fisici.ts: 20 funzioni verificate contro l'oracolo (tests/longevity/motore-fisici.test.ts), nessun chiamante insrc/.motore/index.tscalcolaSessione: legge solo le misure della sessione stessa (WHERE sessione_id = ?). Un check-up e un questionario sono due sessioni: il check-up da solo lascerebbe vuoti gli assi del questionario, e viceversa.vista.tssottoDominiPresenti(usata permancanonel referto) guarda il join registro/misure della sola sessione.vista.tscampiDelQuestionariofiltratest_idcon prefissoq_: i test fisici con prefissof_non entrano nel modulo del cliente.Modifiche
registro.ts: nuovo arrayFISICI: VoceRegistro[], seminato insieme aQUESTIONARIOdaseedRegistro. Voci = misure grezze, prefissof_,tipo_valore:'num',curvaeparamsassenti,assevalorizzato (per l'interfaccia),sotto_dominioassente (il calcolo non passa daapplicaCurva).range_min/range_max= limiti di plausibilità fisiologica larghi (commento: non soglie cliniche, servono a marcare errori di battitura). Elenco:f_peso_kg, f_handgrip_kg, f_pushup_rip, f_row_carico_kg, f_row_rip, f_squat_carico_kg, f_squat_rip, f_plank_sec, f_grasso_pct, f_muscolo_pct, f_whr, f_vo2max (ml/kg/min, diretto), f_mutt_vam (m/min), f_step_hr_recovery (bpm), f_spo2_pct, f_hrv_score (0-100, da Stress Index), f_pa_sistolica, f_pa_diastolica, f_hrr_1min_bpm, f_flamingo_cadute, f_sit_reach_cm, f_back_scratch_cm, f_spalla_outreach_deg, f_spalla_buckling_deg.
motore/fisici.ts:sottoDominiFisici(m: Map<string,number>, eta: number|null, sesso: Sesso): Record<string, number>. Mappa, identica ademo()dell'oracolo (tests/longevity/riferimento/isl_scoring_engine.py):Regola: un sotto-dominio che manca di un ingresso (anche età null dove serve) non compare nel risultato. Mai un valore di ripiego.
Fuori dal perimetro, e lo dichiara il commento: spirometria (calcolatore GLI assente), milfit, 2 km walk, sit-to-stand, trazione isometrica.
motore/index.ts:a. Nuova
misureValideAlla(db, sessioneId): Map<test_id, number>= per ogni test_id, il valore più recente dello stesso cliente fra le sessioni con(data < S.data) OR (data = S.data AND id <= S.id),fuori_range = 0,valore_num IS NOT NULL. Più recente = data DESC, id DESC. Costante esportataFINESTRA_GIORNI: number | null = null(null = nessun limite di età della misura), applicata se non null. Commento: decisione aperta per Nicola.b. Nuova
sottoDominiDellaSessione(db, sessioneId): Record<string, number>= sotto-domini da curva (questionario, logica attuale del livello 1 ma sulle misure di 3a) +sottoDominiFisiciconeta_alla_datadella sessione esessodasoggetti. Chiave in conflitto: vince il fisico (non ce ne sono oggi).c.
calcolaSessioneusa 3b per il livello 1. Livelli 2-4 invariati.vista.ts:sottoDominiPresentidiventanew Set(Object.keys(sottoDominiDellaSessione(db, sessioneId))). Eliminare la query attuale. Aggiornare il commento diETICHETTE_SOTTO_DOMINIO.test-fisici.ts(⚠️ NON COLLEGATE), testa discripts/seed-demo.ts(registro solo questionario).TEST (vitest,
apps/platforms/tests/longevity/)motore-fisici-sessione.test.ts: casodemo()dell'oracolo (M, 38 anni, peso 90.3, handgrip 48, push-up 24, row 80x5, squat 140x5, plank 110, grasso 12.8, muscolo 48.8, whr 0.71, MUTT 230, SpO2 98, PA 114/81, HRR 15, flamingo 5, sit&reach 20, back scratch -5, spalla 180/180, hrv 68). Attesi: gli assi Forza & Struttura, Composizione Corporea, Stabilità & Mobilità Funzionale uguali all'oracolo. Valori attesi ricavati lanciando l'oracolo (python3), non a mano, con il comando scritto nel test. Cardio, Recupero ed Energia diversi per costruzione: l'oracolo usa segnaposto (spirometria 75, questionari 72/60/70, hrv 65 su Energia): scriverlo nel test.campiDelQuestionarionon restituisce nessunf_*.npx tsc --noEmit -p .senza errori nuovi.NON TOCCARE
test-fisici.tsecurve.ts(porting verificato dell'oracolo).anagrafica.ts,auth.ts,db.ts(schema invariato: nessuna colonna nuova).apps/sito/.Soluzione
ESITO: fatto (sul ramo lavoro/goldrake, NON in main e non in produzione)
COMMIT:
48910d8registro FISICI + motore/fisici.ts ·4968b75misureValideAlla, sottoDominiDellaSessione, calcolaSessione e vista agganciati ·af8afebspareggio m.id DESC e nota sulla conferma dei fuori range (#7)FILE: apps/platforms/src/lib/longevity/registro.ts (24 voci f_*), motore/fisici.ts (nuovo, sottoDominiFisici), motore/index.ts, vista.ts, scripts/seed-demo.ts (commento), tests/longevity/motore-fisici-sessione.test.ts (10 test)
REGOLA NUOVA: il punteggio di una sessione usa per ogni test la misura valida più recente del cliente fino a quella data (FINESTRA_GIORNI = null, nessun limite: decisione aperta per Nicola).
PROVA: npx vitest run → 212 passed (202 prima); tsc --noEmit → 0 errori. Caso demo() dell'oracolo: Forza, Composizione, Stabilità identici.
FUORI PERIMETRO: spirometria (manca il calcolatore GLI), milfit, 2 km walk, sit-to-stand, trazione isometrica.
MANCA: merge in main e deploy, insieme al gestionale (#2).
ESITO: fatto
COSA: in produzione su piattaforme.tielogic.xyz, 2026-09-26 13:17 UTC. main
12b2e91.PROVA: docker compose up -d --build → container Up; migra() → colonne verifica/verificata_da/verificata_at presenti; registro_test f_ = 24; misure 20 prima e dopo.
BACKUP: /opt/docker/insanitylab-platforms/backup/*-pre-gestionale (sqlite3 .backup, integrity ok).