HormoneTrack/docs/CHANGELOG.md
Siphonight 5f5244d8eb v1.2.3 : pics/creux estimés sur le graphique (toggle) + calibration T par période d'ester
- detectExtrema : extrema locaux stricts (plateaux fusionnés), alternance
  pic/creux imposée, filtre d'amplitude (2 pg/mL E2, 0,02 ng/mL T) — sémantique
  zigzag documentée (oscillation sous le seuil = un seul pivot)
- CurveChart : triangles ▲▼ aux extrema de chaque série (couleur de la série),
  chip « Pics / creux » + légende (désactivé par défaut)
- computeTKPerEster : le k du modèle T est calibré PAR PÉRIODE D'ESTER (labs T
  attribués à la période de la dernière dose ≤ lab, médiane) — la suppression T
  diffère valerate vs enanthate ; la courbe T utilise le k de l'ester ACTIF à
  chaque instant (activeEsterAt + curseur de doses triées dans computeCurve)
- Fix : la calibration T automatique utilise désormais l'E2 CALIBRÉE
  (scalePerEster) — calibrer contre l'E2 brute faussait les k
- levelAt/currentLevel : paramètre tKPerEster (fallback = tConfig.k stocké)
- ExtremaTest : 6 tests (alternance, monotone, plat, court, filtre d'amplitude,
  anti-corrélation E2/T) — 56 tests verts
- versionCode 6, versionName 1.2.3 ; docs mises à jour (§7.5/§7.6, §11, README, guide)
2026-09-05 18:58:10 +02:00

9.6 KiB
Raw Blame History

Changelog — HormoneTrack

Format : Keep a Changelog. Versionnage : SemVer. Releases taguées dans git (v1.2.3, …).

[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é).
  • 8 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).

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)