274 lines
16 KiB
Markdown
274 lines
16 KiB
Markdown
# Changelog — HormoneTrack
|
||
|
||
Format : [Keep a Changelog](https://keepachangelog.com/fr-FR/1.1.0/).
|
||
Versionnage : [SemVer](https://semver.org/). Releases taguées dans git (`v1.2.10`, …).
|
||
|
||
## [1.2.10] — 2026-09-05 (versionCode 13)
|
||
|
||
### Corrigé
|
||
- **Sens des boutons de zoom inversé** (retour utilisateur) : convention
|
||
carte — « **+** » = zoom **avant** (fenêtre plus courte, plus de détail) et
|
||
« **−** » = zoom **arrière** (fenêtre plus longue, plus de temps). Avant,
|
||
le « + » dézoomait (montrait plus de temps) — pas intuitif. Le pinch
|
||
(écarter = zoom avant) était déjà correct.
|
||
|
||
## [1.2.9] — 2026-09-05 (versionCode 12)
|
||
|
||
### Ajouté
|
||
- **Zoom du graphique de simulation** : pinch à 2 doigts **et** boutons − / +
|
||
(accessibilité), plage bornée **6 h → 300 j** ; le point focal du pinch reste
|
||
fixe dans le temps ; échantillonnage adaptatif (15 min ≤ 12 h, 30 min ≤
|
||
24 h, sinon 1 h — courbes lisses à fort zoom) ; labels X adaptatifs
|
||
(1 h / 3 h). Un seul gestionnaire de gestes gère pan + zoom (pas de
|
||
conflit de consommation).
|
||
- **README : disclaimer IA** en en-tête — projet développé avec l'IA,
|
||
contribution humaine essentielle (feedback, retours utilisateur, suggestions) ;
|
||
mention factuelle reprise en §1/§2 de la doc de développement.
|
||
- 3 tests `stepForRange` (67 au total).
|
||
|
||
## [1.2.8] — 2026-09-05 (versionCode 11)
|
||
|
||
### Modifié
|
||
- **« Fréquence d'injection » renommé « Posologie »** (section Traitements) :
|
||
le terme « fréquence d'injection » n'avait pas de sens pour les prises
|
||
d'hormones non injectables (gel, patch, oral). L'astuce d'intervalle est
|
||
inchangée ; les textes d'aide disent désormais « dernière **prise**
|
||
enregistrée » au lieu de « dernière injection » (EN : « Dosage »).
|
||
|
||
## [1.2.7] — 2026-09-05 (versionCode 10)
|
||
|
||
### Corrigé
|
||
- **Prévision cassée après un oubli d'injection** : le premier créneau projeté
|
||
tombait dans le PASSÉ (dernière prise + intervalle = jour de l'injection
|
||
manquée) → la courbe peignait un **faux pic dans l'historique** et tout le
|
||
rythme projeté était décalé. Désormais les créneaux déjà passés ne sont
|
||
jamais simulés : la prévision avance au premier créneau **strictement
|
||
futur** au rythme configuré. Un simple **retard**, lui, décale naturellement
|
||
toute la prévision (elle part de la dernière prise réelle — comportement
|
||
voulu, désormais testé).
|
||
- 2 nouveaux tests (64 au total) : oubli (créneaux passés sautés, espacement
|
||
conservé) et retard (décalage complet de la prévision).
|
||
|
||
## [1.2.6] — 2026-09-05 (versionCode 9)
|
||
|
||
### Ajouté
|
||
- **Valeurs estimées sur les pics/creux** : chaque triangle ▲▼ du graphique est
|
||
accompagné de la valeur simulée de l'extremum (au-dessus d'un pic, en dessous
|
||
d'un creux), dans la couleur de la courbe.
|
||
|
||
### Corrigé
|
||
- **Import JSON en mode ÉCRASEMENT** : l'import échouait dès que l'app
|
||
contenait déjà des données (conflit d'IDs du backup avec les IDs existants).
|
||
Désormais l'import efface d'abord les données actuelles (ordre enfants →
|
||
parents), restaure le backup (IDs conservés → FK valides), restaure le
|
||
réglage T du backup et **reprogramme les rappels**. Le dialog d'import
|
||
prévient clairement : « Effacer & restaurer ».
|
||
|
||
## [1.2.5] — 2026-09-05 (versionCode 8)
|
||
|
||
### Corrigé
|
||
- **Espace vide en haut de l'écran** (contenu trop bas) : double consommation des
|
||
insets — la fenêtre poussait déjà le contenu sous la barre de statut (thème
|
||
AppCompat) ET les `TopAppBar` Material 3 rajoutaient leur padding de barre de
|
||
statut interne. Passage en **edge-to-edge propre** (`enableEdgeToEdge()`) :
|
||
- les `TopAppBar` consomment la barre de statut (une seule fois) ;
|
||
- les `Scaffold` (racine + imbriqués Doses/Analyses) ont
|
||
`contentWindowInsets = 0` pour ne pas cumuler ;
|
||
- la `NavigationBar` consomme la barre de navigation système.
|
||
Le contenu remonte, les listes défilent visuellement sous la barre de statut
|
||
(comportement Material You standard).
|
||
- **Builds release optimisés** (R8 + shrink des ressources, signés avec la clé
|
||
debug → installables par-dessus sans perte de données) : l'APK passe de
|
||
**20 Mo à 2,4 Mo** et gagne en fluidité. Depuis cette release, chaque version
|
||
est publiée en deux fichiers :
|
||
- `HormoneTrack-vX.Y.Z-release.apk` ← **recommandé** (optimisé R8) ;
|
||
- `HormoneTrack-vX.Y.Z-debug.apk` (comme avant, plus lourd, pour diagnostic).
|
||
|
||
## [1.2.4] — 2026-09-05 (versionCode 7)
|
||
|
||
### Corrigé
|
||
- **Traitement inactif = drapeau administratif, pas filtre de données** (bug
|
||
remonté) : passer un traitement à inactif faisait disparaître sa simulation du
|
||
graphique **et** sa contribution à la calibration, tout en permettant encore
|
||
d'y loger des doses (incohérence). Désormais :
|
||
- Home et Graphiques simulent avec **TOUS les traitements** (actifs + inactifs)
|
||
→ l'historique EV d'un traitement passé à inactif reste simulé et calibré ;
|
||
- l'inactivation retire uniquement : les chips « Log rapide », le traitement
|
||
dans le dropdown des **nouvelles** doses (l'édition d'une dose existante
|
||
garde son traitement même inactif), et les **rappels** (alarme annulée au
|
||
save, au boot et dans le calcul de la prochaine dose) ;
|
||
- la suppression d'une dose reste possible depuis l'historique.
|
||
|
||
### Ajouté
|
||
- **Régression n°3** épinglée sur le 3ᵉ export réel (HORS dépôt, gitignoré) :
|
||
le scénario complet de transition — 1 traitement **EV inactif** (29 doses,
|
||
2–8 mg, janvier→juillet) + 1 traitement **EEn actif** (9 doses), 22 labs
|
||
couvrant les deux périodes. Vérifie : simulation de l'inactif, calibration
|
||
par période sur les DEUX esters (EV **et** EEN), k T par ester, continuité
|
||
de la courbe pendant la transition, niveau actuel. 6 nouveaux tests (62 au
|
||
total, tous verts).
|
||
|
||
## [1.2.3] — 2026-09-05 (versionCode 6)
|
||
|
||
### Ajouté
|
||
- **Pics et creux estimés sur le graphique** : chip « Pics / creux » (désactivé par
|
||
défaut) qui affiche des triangles ▲▼ aux extrema locaux de CHAQUE courbe
|
||
(E2 et T, pour les deux modèles), colorés comme leur série. Détection dans le
|
||
moteur (`detectExtrema`) : extrema locaux stricts, plateaux fusionnés,
|
||
alternance pic/creux imposée, oscillations d'amplitude < seuil ignorées
|
||
(2 pg/mL pour l'E2, 0,02 ng/mL pour la T — sémantique zigzag : une oscillation
|
||
sous le seuil produit un seul pivot).
|
||
- **Calibration T PAR PÉRIODE D'ESTER** : la suppression de la testostérone n'est
|
||
pas la même selon l'ester (valerate = pics hauts et courts, enanthate = plateau
|
||
doux) → le k du modèle T est désormais calibré **par période** comme le facteur
|
||
d'échelle E2 (`computeTKPerEster`) : labs T valerate → k des doses valerate,
|
||
labs T enanthate → k des doses enanthate. La courbe T utilise à chaque instant
|
||
le k de l'ester **actif** (dernière dose ≤ t, `activeEsterAt`), fallback = k stocké.
|
||
Le k T est calibré contre l'E2 **déjà calibrée** (scalePerEster appliqué).
|
||
- **Données de test hors dépôt (vie privée)** : les tests de régression épinglés
|
||
sur les exports réels chargent désormais leurs données depuis `local-test-data/`
|
||
(**gitignoré**) et s'ignorent proprement si le fichier est absent — **aucune
|
||
donnée de santé personnelle dans le dépôt ni dans son historique** (réécriture
|
||
d'historique effectuée avant le premier push).
|
||
- 14 nouveaux tests (56 au total) : détection d'extrema (6) + attribution du k T
|
||
par période et courbe T utilisant le k de l'ester actif (2), regroupement des
|
||
prises de sang (4), régression n°2 en version data-driven (6).
|
||
|
||
### Corrigé
|
||
- La calibration automatique de la T utilisait l'E2 **non calibrée** → les k
|
||
étaient faussés ; elle utilise maintenant l'E2 calibrée par période d'ester.
|
||
|
||
## [1.2.2] — 2026-09-05 (versionCode 5)
|
||
|
||
### Ajouté
|
||
- **Prise de sang E2 + T en UNE entrée** : le dialog d'ajout propose les deux
|
||
marqueurs (chacun **optionnel** — on peut ne saisir que E2 ou que T), avec
|
||
date/heure et notes partagées ; les entrées sont insérées au même timestamp et
|
||
s'affichent **côte à côte** dans l'écran Analyses (« E2 306 pg/mL · T 44 ng/dL »).
|
||
- **Tap sur une paire → sélecteur** (« Quelle entrée veux-tu modifier ? » E2 / T)
|
||
puis édition pré-remplie de l'entrée choisie.
|
||
- **Suppression par prise de sang** : la corbeille supprime la prise entière
|
||
(confirmation listant les valeurs).
|
||
- **Toggle T du graphique** : masque désormais aussi les **labs T** (avant : seule
|
||
la courbe T disparaissait, les points restaient).
|
||
- 4 tests de regroupement (48 au total).
|
||
|
||
## [1.2.1] — 2026-09-05 (versionCode 4)
|
||
|
||
### Corrigé
|
||
- **Calibration par PÉRIODE D'ESTER** (le fond du problème « courbes à 250–375 ») :
|
||
la calibration automatique calculait UN facteur par traitement, mélangeant les labs
|
||
de toutes les périodes — un lab valerate comparé à une prédiction enanthate donne un
|
||
ratio aberrant qui gonfle la courbe. Désormais chaque lab est **attribué à la période
|
||
d'injection dans laquelle il tombe** (dernière dose E2 ≤ lab → son ester) et le
|
||
facteur est la médiane des ratios de CETTE période : labs valerate → doses
|
||
valerate, labs enanthate → doses enanthate (`computeEsterScaleFactors` +
|
||
paramètre `scalePerEster` dans `e2At`/`computeCurve`).
|
||
Vérifié sur les données réelles : l'état d'équilibre EEn (t½ ≈ 6,7 j, doses tous
|
||
les 6–7 j → accumulation ×2) donne ~270 pg/mL calibré — cohérent avec les labs
|
||
300/250 ; les « 375 » rapportés = le même calcul **non calibré** (268/0,72 ≈ 367).
|
||
- **Lab T saisi en "pg/mL"** (38 "pg/mL" — faute de frappe) : renvoyé brut, il
|
||
écrasait l'axe T (~40) et **rendait la courbe T invisible** (écrasée en bas).
|
||
Conversion défensive ajoutée (`pg` → ÷1000, `µg/L` → ÷1000).
|
||
|
||
### Ajouté
|
||
- **Édition des résultats de labo** (comme les doses) : appuyer sur une ligne de
|
||
l'écran Analyses ouvre le dialog pré-rempli (marqueur, valeur, unité, date/heure,
|
||
notes). Nouveau formateur `formatLabValue` (préserve les décimales : 0,44 reste
|
||
0,44, contrairement à formatDose).
|
||
- **Tap sur le graphique de l'accueil → écran Graphiques** + mini-légende (E2 bleu /
|
||
T rose) + indication.
|
||
- **Calibration automatique fusionnée** : UNE seule option dans Paramètres qui couvre
|
||
**E2 (par période d'ester) ET T** — plus de réglage T isolé ; le bouton manuel
|
||
« Calibrer avec les analyses » (T) reste comme action ponctuelle.
|
||
- **8 nouveaux tests** (44 au total) dont `RegressionUserCase2Test` épinglé sur le
|
||
2ᵉ export réel (9 doses EEn/TFS, 8 labs, fréquence 6 j) — inclut la vérification
|
||
de l'état d'équilibre et du lab T en unité aberrante.
|
||
|
||
### Modifié
|
||
- `AutoCalibrated` : `treatments` inchangés (plus de copies avec SF modifié), nouveau
|
||
champ `esterScales: Map<String, Double>` + `calibratedEsters`.
|
||
|
||
## [1.2.0] — 2026-09-05 (versionCode 3)
|
||
|
||
### Ajouté
|
||
- **Panoramique du graphique** : fais glisser le graphique vers la droite pour
|
||
remonter dans le passé (fenêtre glissante sur tout l'historique) ; bouton
|
||
« Revenir à maintenant ».
|
||
- **Les deux modèles PK superposables** : Estrannaise (bleu) et Transfem Science
|
||
(turquoise) tracées simultanément sur le même graphique, avec toggles
|
||
indépendants (override de modèle dans le moteur, indépendant du modèle stocké
|
||
par traitement).
|
||
- **Simulation prévisionnelle** : nouvelle section « Fréquence d'injection » dans
|
||
l'éditeur de traitement (intervalle en jours) → chip « Prévision » du graphique
|
||
qui projette les doses à venir (2× l'intervalle, borné 7–30 j) à partir de la
|
||
dernière injection réelle ; les doses projetées ne sont jamais sauvegardées et
|
||
conservent l'ester override de la dernière injection.
|
||
- **Calibration automatique (optionnelle)** : dans les Paramètres, option
|
||
« Calibration automatique » — ajuste à la volée (affichage seul) les facteurs
|
||
d'échelle et le modèle T depuis les labs ; désactivée par défaut, les valeurs
|
||
stockées ne sont jamais modifiées.
|
||
- **Intervalle entre dosages** : l'écran Doses affiche Δ (jours) entre chaque dose
|
||
et la précédente du même traitement (colonne « Interval (d) » du `.ods`).
|
||
- 6 nouveaux tests (`V120FeaturesTest`) → **36 tests**.
|
||
|
||
### Modifié
|
||
- **Montée des toolchains** : Gradle 9.7.1, **AGP 9.4.0** (Kotlin intégré — plus de
|
||
plugin `org.jetbrains.kotlin.android`, `kotlinOptions` supprimé), Kotlin 2.3.21,
|
||
KSP 2.3.11, **Compose BOM 2026.08.00** (Compose 1.12), Room 2.8.4,
|
||
Navigation 2.10.0, Activity 1.13.0, AppCompat 1.8.0, DataStore 1.2.1, Gson 2.14.0,
|
||
compileSdk/targetSdk **37**.
|
||
- Note Material You / Expressive : la BOM récente apporte composants et comportements
|
||
Material You ; `MaterialExpressiveTheme` reste **internal** dans la ligne material3
|
||
pinnée (vérifié par compilation) → `MaterialTheme` standard conservé, à basculer
|
||
dès que l'API devient publique (commenté dans `ui/theme/Theme.kt`).
|
||
|
||
### Corrigé
|
||
- **Horloge du TimePicker décentrée** (partait vers la gauche dans les dialogs de
|
||
saisie) : centrage explicite (Box + Center) dans `DateTimeField` et l'éditeur de
|
||
traitement.
|
||
- Migration Room **v1 → v2** propre (colonne `forecastIntervalDays`) avec
|
||
suppression du `fallbackToDestructiveMigration()` — les données réelles sont
|
||
protégées : une migration manquante plante bruyamment au lieu d'effacer.
|
||
|
||
## [1.1.0] — 2026-09-05 (versionCode 2)
|
||
|
||
### Corrigé
|
||
- **Courbes EEn plates à zéro** (le bug rapporté : « les graphiques ne se génèrent pas »).
|
||
Cause : casse des clés de profils — l'asset JSON (verbatim du `.ods`) contient
|
||
`"EEn_ese"`/`"EEn_tfs"` (n minuscule) alors que la constante `Esters.EEN = "EEN"` ;
|
||
le lookup exact échouait silencieusement → `sample() = 0` pour **tous** les traitements
|
||
EEn (EV et EU marchaient, ce qui masquait le bug). Fix : lookup **insensible à la casse**
|
||
dans `PKProfileStore` (`lookup()`), test de régression épinglé sur les données réelles
|
||
de l'utilisatrice (`RegressionUserCaseTest`, export v1.0.0 fourni).
|
||
- **Unités de testostérone** : les labs T pouvaient être saisis en ng/dL (cas réel :
|
||
33 et 44 ng/dL). L'axe T du chart mélangeait alors des ng/dL avec des estimations en
|
||
ng/mL (erreur ×100, courbe T invisible) et la calibration T aurait été faussée d'un
|
||
facteur 100. Fix : `PharmacokineticEngine.convertTToNgMl()` (ng/dL → ×0,01 ;
|
||
ng/L → ×0,001 ; nmol/L → ×0,2884 ; ng/mL inchangé), appliqué à la calibration **et
|
||
au rendu du chart**.
|
||
|
||
### Ajouté
|
||
- **Édition des doses** (le bug rapporté : « on ne peut pas modifier les entrées
|
||
d'injection ») : appuyer sur une ligne de l'écran Doses ouvre le dialog en mode
|
||
édition (traitement, dose, date/heure, notes) → enregistre sans recréer.
|
||
- **Choix de l'ester par injection** dans le dialog de dose (comme dans le `.ods`) :
|
||
« Défaut (EEn) », EV, EU, EEn — override stocké par dose, utilisé par le moteur PK.
|
||
- 6 tests de régression sur les données réelles de l'utilisatrice (30 tests au total).
|
||
|
||
### Technique
|
||
- `versionCode 2`, `versionName 1.1.0` ; APK debug régénérée.
|
||
|
||
## [1.0.0] — 2026-09-05 (versionCode 1)
|
||
|
||
Première version fonctionnelle :
|
||
- Courbes estimées E2/T heure par heure (24 h / 7 j / 30 j), modèles **Estrannaise** et
|
||
**Transfem Science** (tables horaires extraites de `Estrogen.ods` : EV/EU/EEn)
|
||
- Modèle Bateman paramétrable (gel/patch/oral)
|
||
- Log des doses, analyses de sang, calibration (facteur d'échelle médian lab÷prédiction)
|
||
- Estimation T empirique calibrable
|
||
- Rappels quotidiens (alarmes exactes) avec actions « Pris » / « Reporter 1 h »,
|
||
notifications remontant sur Huawei Watch GT 3 (Gadgetbridge ou Huawei Health)
|
||
- Sauvegarde/Restauration JSON (SAF), FR/EN (langue par app), 100 % local
|
||
- 24 tests unitaires (moteur PK, profils ODS, round-trip backup)
|