HormoneTrack/README.md
Siphonight ae14cee07b v1.13.0 : reco prédictive — valeur E2 au creux, régime poolé entre traitements identiques, cible de creux personnelle
- predictedE2 : valeur brute au creux × facteur du ester actif — fournie
  par Home/Labs quand l'auto-calibration est ON (sinon null : la carte
  n'affiche rien, une valeur brute serait trompeuse). Miroir web.
- Régime POOLÉ (pooledRegimeDoses) : les doses de tous les traitements
  partageant (ester effectif, mg) forment UNE séquence — le re-parenting
  d'historique (« 6d-old », v1.12.0) ne fait plus redémarrer la
  stabilisation. Garde-fous : ester ≠ jamais poolé (régression n°3) ;
  dose ≠ exclue (le 8 mg casse via le trou). Régression n°7 data-driven
  sur le nouvel export (backup-v1.12.0.json).
- Cible de creux E2 (opt-in) : DataStore + carte settings (hint croisé
  « distinct des seuils d'alerte — jamais de notification ») + coloration
  carte reco (primaire/hors cible tertiary) + backup rétrocompatible (un
  backup ancien n'efface pas la cible locale). Système à 3 niveaux
  documenté §7.11. Miroir web complet.

284 tests JVM (250 sans données locales) + 14 UI + lint verts ; web 199
tests + E2E verts (check.sh). Validé émulateur sur données réelles :
« Expected at this trough: ≈ 208 pg/mL — outside your target », régime
poolé = stable depuis le 12 août, 0 crash.
2026-10-07 09:59:19 +02:00

297 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HormoneTrack
> **Langue** : Français (ce fichier) · [English](README.en.md)
> **🤖 Développé avec l'IA** : ce projet a été conçu et codé avec un assistant IA.
> La contribution humaine a été **essentielle** : feedback continu, retours
> utilisateur (tests sur vrai téléphone, rapports de bugs accompagnés d'exports
> réels), suggestions d'améliorations et validation de chaque release. Le
> détail session par session est documenté dans
> [docs/DEVELOPPEMENT.md §2](docs/DEVELOPPEMENT.md).
Suivi de thérapie hormonale (THS) sur Android, avec courbes estimées **heure par heure**
d'estradiol (E2) et de testostérone (T), calibration sur les prises de sang, rappels
affichés sur smartwatch (Huawei Watch GT 3 via Gadgetbridge ou Huawei Health) et
sauvegarde JSON. **100 % local, aucun compte, aucun serveur.**
> **⚠️ Avertissement médical** : les courbes sont des **estimations pharmacocinétiques**
> à titre informatif — ce ne sont pas des mesures. Fie-toi toujours à tes analyses de
> sang et aux consignes de ton endocrinologue.
- **Statut** : v1.13.0 — build Android ✅, **lint vert** ✅, **284 tests unitaires** ✅ (250 sans les données de test locales ; 7 régressions épinglées sur données réelles **non versionnées**), **14 tests UI Compose** ✅ (émulateur), intégration montre = notifications ✅, **dépôt Gitea privé + releases avec APK** ✅
- **Journal des versions** : [docs/CHANGELOG.md](docs/CHANGELOG.md)
- **Guide utilisateur** : [docs/GUIDE_INSTALLATION.md](docs/GUIDE_INSTALLATION.md)
- **Doc de développement** (architecture, maths, décisions, bugs) : [docs/DEVELOPPEMENT.md](docs/DEVELOPPEMENT.md)
- **Montre / Gadgetbridge** : [docs/MONTRE-GADGETBRIDGE.md](docs/MONTRE-GADGETBRIDGE.md)
- **README anglais** : [README.en.md](README.en.md)
## Fonctionnalités
- **Courbes estimées heure par heure** : E2 (pg/mL) et T (ng/mL), vue 24 h / 7 j / 30 j,
**doses marquées** (prévisionnelles et réelles), **fuseau horaire du graphique
configurable** (v1.4.5),
**panoramique** (glisser pour remonter dans le passé), **zoom** (pinch ou boutons
− / +, 6 h → 300 j, échantillonnage adaptatif), **pics & creux** affichables avec
leurs **valeurs estimées** (triangles ▲▼ aux extrema locaux, toggle)
- **Deux modèles PK au choix, superposables** : **Estrannaise (EstraNase)** (tables
horaires du `.ods`) et **Transfem Science** — depuis v1.4.0, le modèle TFS est la
**méta-analyse officielle à 3 compartiments** (forme close exacte, params du
[simulateur TFS](https://transfemscience.org/misc/injectable-e2-simulator/),
[article](https://transfemscience.org/articles/injectable-e2-meta-analysis/)),
avec les **7 esters** (EV, EU, EEn, EB, EC huile, EC suspension, PEP) — et WHSAH
en couvre 6 (sans PEP). Affichés côte à côte avec toggles indépendants (3 couleurs) — **pré-cochés
selon les modèles de tes traitements** (v1.4.7) et **chaque modèle calibré
séparément** par tes labs (v1.4.8 — les facteurs s'adaptent à chaque profil)
- **« Tracé labs » (v1.5.0, prolongé en v1.6.0)** : la courbe ancrée sur tes
prises de sang (chip `Tracé labs`, off par défaut) — la forme du modèle PK
entre les labs, mais l'amplitude recalée pour passer EXACTEMENT sur chaque
lab E2 ; transition log-linéaire d'un lab au suivant, garde des labs hors
fenêtre d'action (#61) ; **chip `Prolonger` (v1.6.0)** : la courbe se
prolonge au-delà du dernier lab (modèle × ratio du dernier lab, horizon =
extinction du modèle, partie estimée dessinée atténuée + légende dédiée) —
la courbe est une référence de COMPARAISON, jamais une estimation d'action
(elle n'entre jamais dans l'accueil/les alertes)
- **Modèle Estrannaise ANALYTIQUE (v1.9.0)** : le modèle ESE utilise désormais
la forme close 3C publiée par estrannaise.js (fidélité aux anciennes tables
épinglée RMS 0) — **nuage d'incertitude MCMC** (chip `Nuage`, exclusif ESE :
32 courbes du posterior montrant la plage d'imprécision, comme sur le site
estrannaise) ; **6 esters injectables** (dont EUCS, exclusif) ; l'ODS
historique n'est plus utilisé au runtime (fidélité = tests uniquement) ;
t½ terminale analytique (recommandation de prise de sang)
- **Modèle Bateman** paramétrable (temps au pic, demi-vie, biodisponibilité) pour gel,
patch et voie orale
- **Simulation prévisionnelle** : configurer la **posologie** (intervalle en jours) sur un
traitement → projection des doses à venir sur le graphique (jamais sauvegardées) ;
**l'activation ne déplace pas le début du graphique** mais ÉTEND la fenêtre
jusqu'à la prochaine dose (v1.4.4) et la projection se parcourt en tirant
vers la gauche, jusqu'à **1 an**
- **Log des doses** avec date/heure exacte, dose en mg, **ester par injection**
(switch EV↔EU↔EEn comme dans le tableur), **éditable** (tap sur une ligne dans Doses),
**intervalle en jours entre dosages** affiché ; **icône de forme de prise**
(oral / injection IM-SC / gel / patch, v1.12.0) et **encart « prise de sang
le même jour »** (🧪↑ avant la dose, 🧪↓ après)
- **Traitements inactifs** : un traitement archivé n'apparaît plus dans la saisie
ni dans les rappels, mais **tout son historique reste simulé et calibré** —
utile pour une transition valerate → enanthate ; **regroupés tout en bas** de la
page Traitements sous un en-tête dédié, cartes atténuées (v1.11.0)
- **Analyses de sang** : **E2 + T en une seule entrée** (chacune optionnelle), affichées
**côte à côte** quand elles partagent la même date/heure, éditables (tap → choix de
l'entrée) ; unités T : ng/mL, ng/dL, ng/L, nmol/L
- **Prochaine prise de sang suggérée (v1.8.0, étendu v1.8.1 aux pages Analyses et Accueil)** : la page Analyses recommande le
**creux estimé juste avant l'injection suivante** (moment le plus comparable),
**au premier creux où ton régime est stabilisé** (~5 demi-vies après ton dernier
changement — dose, ester ou intervalle) — déduit des courbes et de la Posologie ; requiert un
injectable E2 actif à Posologie (une invite propose de la renseigner sinon) ;
estimations, jamais un avis médical ;
**v1.13.0** : la carte affiche la **valeur E2 attendue au creux** (si l'auto-calibration
est ON) et la compare à ta **cible de creux** personnelle (opt-in — distinct des
seuils d'alerte, jamais de notification)
- **Calibration** : facteur d'échelle par traitement = médiane(lab ÷ prédiction du modèle),
calculé automatiquement (« Scale factor » du `.ods`, automatisé) — ou **calibration
automatique permanente** (option, désactivée par défaut) qui calibre **chaque ester
avec les labs de sa période** (labs valerate → doses valerate, labs enanthate → doses
enanthate) et recalibre le modèle T
- **Estimation T** empirique `T = plancher + (base − plancher) ÷ (1 + k·E2)`, avec
**k calibré par période d'ester** (la suppression T diffère valerate vs enanthate),
contre l'E2 déjà calibrée — unités T acceptées : ng/mL, ng/dL, ng/L, nmol/L
- **Rappels quotidiens** avec actions **« Pris » / « Reporter 1 h »** dans la notification ;
les notifications remontent sur la Watch GT 3 (Gadgetbridge ou Huawei Health) ;
**les rappels suivent la Posologie** (v1.4.0) : un traitement injecté tous les
7 jours ne sonne que le jour d'injection, pas tous les jours ; **une dose déjà
loguée dans la journée saute la notification** (v1.10.0 — le rappel suivant
repart au créneau suivant)
- **Seuils d'alerte configurables** (v1.4.2) : limites hautes/basses E2 (pg/mL)
et T (ng/mL) dans Paramètres → carte d'avertissement sur l'accueil +
**notification toutes les 15 min même app fermée** (WorkManager, anti-spam,
canal dédié) — évaluées sur le taux **estimé**, opt-in
- **Sauvegarde JSON complète** : traitements + doses + analyses + réglages T
**+ paramètres (langue, auto-calibration, seuils d'alerte)** (v1.4.2)
- **Sauvegarde automatique quotidienne (v1.7.0, opt-in)** : en PLUS de
l'export manuel — chaque jour, un backup JSON complet (même format,
importable tel quel) est écrit dans le **dossier que tu choisis** (ex.
dossier Owncloud synchronisé). Aucune permission de stockage (SAF, dossier
choisi une fois, permission persistante révocable), rétention configurable
(1–30 copies, défaut 7 — fichier horodaté par run, jamais d'écrasement ;
exports manuels et fichiers étrangers **jamais touchés**), statut du
dernier run dans Paramètres, premier backup immédiat à l'activation
- **Nouveautés à chaque mise à jour** : dialog de changelog automatique
(fermé = ne réapparaît pas avant la prochaine version)
- **Temps sous THS** affiché en haut de la page Doses (depuis la 1re prise) ;
**prochaine dose en jours** sur l'accueil quand elle est à plus de 24 h (v1.4.1)
- **Logs de diagnostic** exportables (Paramètres) — utile pour le support
- **Événements d'agenda** : les rappels de prises peuvent créer un événement
récurrent (posologie) dans un calendrier « HormoneTrack » de ton téléphone
- **Sauvegarde/Restauration JSON** complète (traitements + doses + analyses + réglages T + paramètres, v1.4.2)
- **FR + EN** (langue par app, indépendante du système)
- UI Jetpack Compose récente (BOM 2026.08, Material You) ; 100 % local, aucun compte
## Démarrage rapide (build depuis les sources)
Prérequis : JDK 17+ (Java 21 OK), Android SDK (la plateforme 37 sera auto-téléchargée
par AGP si les licences sont signées). Le wrapper télécharge Gradle 9.7.1.
```bash
git clone <repo> && cd HormoneTrack
echo "sdk.dir=/chemin/vers/android-sdk" > local.properties # ou ANDROID_HOME
./gradlew assembleDebug # APK : app/build/outputs/apk/debug/app-debug.apk
./gradlew testDebugUnitTest # 284 tests (250 sans les données locales)
./gradlew connectedDebugAndroidTest # 14 tests UI (émulateur/appareil requis)
./gradlew lint # lint vert obligatoire avant release
```
Installation sur un téléphone : mode développeur + Débogage USB, puis Android Studio
(**Run ▶️**) ou `adb install -r app/build/outputs/apk/debug/app-debug.apk`.
Pas de Play Store : l'app est sideloadée. Détails pas-à-pas : [docs/GUIDE_INSTALLATION.md](docs/GUIDE_INSTALLATION.md).
## Git
Dépôts : **gitea.cloudyfy.fr** et **gitea.farewell.dev** (miroir) —
`Siphonight/HormoneTrack` sur les deux (privé), avec
**releases taguées** (`v1.1.0` → `v1.10.0`) et **deux APK par release** (depuis v1.2.5)
(téléchargeables sans compiler, cf [docs/DEVELOPPEMENT.md §16.bis](docs/DEVELOPPEMENT.md)) :
`-release.apk` (**recommandé**, optimisé R8, 2,7 Mo) et `-debug.apk` (20 Mo) :
```bash
git tag # lister les releases
git log --oneline # historique par couches (toolchain / moteur / UI / docs)
git push -u origin main --tags
```
**Portage web** : depuis v1.4.10, la version navigateur vit dans son propre
dépôt `Siphonight/HormoneTrack-web` (mêmes instances) — versions **alignées**
(web v1.4.10 = portage de l'Android v1.4.10), releases sync (checklist
§16 étape 4.bis), changelogs séparés.
Chaque commit de release passe `./gradlew testDebugUnitTest` (vert obligatoire) et est
taggué annoté. Voir [docs/DEVELOPPEMENT.md §16](docs/DEVELOPPEMENT.md).
**Signature release** : l'APK release est signé avec la clé debug tant qu'aucun
`keystore.properties` n'existe à la racine ; dès sa création via
`scripts/make-release-keystore.sh` (fichiers gitignorés), `assembleRelease`
signe avec ce keystore — migration téléphone documentée dans
[docs/DEVELOPPEMENT.md §16.quater](docs/DEVELOPPEMENT.md).
## Les modèles en bref
Chaque injection contribue `dose_mg × profil(dt)` où `profil` est la réponse normalisée
(pg/mL par mg) ; les contributions se superposent. **Trois modèles superposables** :
- **Estrannaise** = tables horaires du `.ods` (8001 h), EV/EU/EEn
- **Transfem Science** = méta-analyse à 3 compartiments (V3C, forme close,
[article](https://transfemscience.org/articles/injectable-e2-meta-analysis/)),
7 esters (EV, EU, EEn, EB, EC, EC suspension, PEP)
- **WHSAH** (v1.4.6) = fit « license-free » du [WHSAH Collective via
Mona](https://github.com/mona-hrt/mona) — même famille mathématique mais
paramètres indépendants avec biodisponibilité explicite F < 1 : montée
plus rapide à J+1 (EEn ~70 pg/mL à J+1 pour 5 mg vs ~22 chez TFS) et
décroissance plus longue (t½ EEn 7,3 j vs 4,5 j). 6 esters (sans PEP)
Pics de référence (pg/mL par mg) :
| Profil | Modèle | Pic (pg/mL/mg) | Tmax | t½ term. |
|----------|------------------|----------------|--------|----------|
| EV | Estrannaise | 61,1 | ~45 h | — |
| EU | Estrannaise | 3,4 | ~55 h (plateau long) | — |
| EEn | Estrannaise | 31,4 | ~152 h | — |
| EV | Transfem Science | 59,0 | ~51 h | 3,0 j |
| EU | Transfem Science | 10,1 | ~198 h | — |
| EEn | Transfem Science | 32,0 | ~156 h | 4,5 j |
| EB | Transfem Science | 194,2 | ~16 h | 1,2 j |
| EC (huile) | Transfem Science | 31,1 | ~103 h | 6,7 j |
| EC (susp.) | Transfem Science | 48,2 | ~29 h | 5,1 j |
| PEP | Transfem Science | 1,03 (dose ~6,5×) | ~18 j | 28,4 j |
| EV | WHSAH | 73,5 | ~41 h | 3,1 j |
| EEn | WHSAH | 37,6 | ~120 h | 7,3 j |
| EB | WHSAH | 260,1 | ~12 h | 1,3 j |
| EC (huile) | WHSAH | 25,0 | ~81 h | 7,9 j |
| EC (susp.) | WHSAH | 53,5 | ~16 h | 7,1 j |
| EU | WHSAH | 4,9 | ~67 h | 31,7 j |
**Calibration (v1.4.8)** : le facteur d'échelle s'applique par ESTER et par
PÉRIODE d'injection (médiane des ratios lab ÷ prédiction, comme la colonne
« Scale factor » de la feuille d'origine) — et **par MODÈLE** : chaque courbe
affichée (Estrannaise / Transfem Science / WHSAH) est calibrée avec la
prédiction de SON modèle → toutes collent à tes labs, quelle que soit leur
forme. L'auto-calibration est optionnelle (désactivée par défaut).
## Vie privée
- **L'app est 100 % locale** : base de données Room sur le téléphone, aucun serveur,
aucune télémétrie ; compat **Gadgetbridge** (FOSS) sans dépendance à Huawei Health
- **Le dépôt ne contient aucune donnée de santé** : le code et la doc sont génériques ;
les tests de régression qui utilisent des exports réels chargent leurs données
depuis `local-test-data/` (**gitignoré**, hors dépôt — et l'historique a été
nettoyé avant le premier push, cf [docs/DEVELOPPEMENT.md §8.bis](docs/DEVELOPPEMENT.md))
- Sauvegarde = fichier JSON que tu stockes où tu veux (Owncloud, etc.)
- **L'auto-backup quotidien (v1.7.0) n'écrit QUE dans le dossier que tu as
toi-même choisi** (sélecteur système SAF, permission révocable) — rien
ne part ailleurs, aucun serveur
- `allowBackup=false` (données sensibles) ; verrou biométrique prévu en Phase 2
- Le dépôt est **privé** : les releases APK se téléchargent en étant connecté ;
passer le dépôt en public rend les APK téléchargeables sans compte (sans risque
de données, cf ci-dessus)
## Structure du dépôt
```
HormoneTrack/
├── README.md ← ce fichier (README.en.md = version anglaise)
├── docs/
│ ├── GUIDE_INSTALLATION.md guide utilisateur (téléphone + montre)
│ ├── DEVELOPPEMENT.md doc de dev complète (architecture, maths, bugs, tests)
│ ├── CHANGELOG.md journal détaillé des versions
│ └── MONTRE-GADGETBRIDGE.md montre Huawei GT 3 : options + limites
├── scripts/
│ ├── gitea-release.py publie le corps d'une release (CHANGELOG + APK)
│ ├── publish-release.py publie les 2 APK d'un tag (vérification par téléchargement)
│ ├── seed-emulator.py injecte un backup JSON dans la DB d'un émulateur (cf §16.ter)
│ └── make-release-keystore.sh génère le keystore de signature release (v1.9.8, §16.quater)
├── local-test-data/ ← gitignoré : backups réels pour les tests
│ de régression (JAMAIS dans le dépôt, cf §8.bis)
├── keystore.properties ← gitignoré : signature release (optionnel, §16.quater)
├── build.gradle.kts config Gradle racine (AGP/Kotlin/KSP épinglés)
├── settings.gradle.kts
├── gradle.properties
├── gradle/wrapper/ wrapper Gradle 9.7.1 (jar + properties)
├── gradlew / gradlew.bat
└── app/
├── build.gradle.kts dépendances (Compose, Room, DataStore, Gson…)
├── proguard-rules.pro
└── src/
├── main/
│ ├── AndroidManifest.xml
│ ├── assets/pk_profiles.json ← tables horaires (Estrannaise/TFS)
│ ├── java/com/hormonetrack/
│ │ ├── data/ (Room : models, DAOs, repository, backup)
│ │ ├── pk/ (moteur PK + profils : Estrannaise/TFS/WHSAH, alertes, export)
│ │ ├── reminder/ (alarmes exactes, notifs + actions, boot, worker alertes)
│ │ ├── settings/ (DataStore : TConfig, langue)
│ │ ├── ui/ (Compose : screens, components, theme)
│ │ │ └── screens/settings/ ← cartes des Paramètres (découpage v1.9.8)
│ │ ├── HormoneTrackApp.kt
│ │ └── MainActivity.kt
│ └── res/ (strings FR/EN, thème, icônes)
├── test/java/com/hormonetrack/ ← tests unitaires JVM
│ ├── pk/ (moteur, profils ESE/TFS/WHSAH, calibration
│ │ par modèle, rappels, régressions data-driven)
│ ├── data/backup/ (round-trip Gson + paramètres)
│ ├── ui/ (fenêtre graphique, garde de source)
│ ├── util/ (noms de fichiers d'export, durées)
│ └── reminder/ + settings/ (RRULE agenda, changelog)
└── androidTest/java/com/hormonetrack/ ← tests UI Compose (v1.9.8)
└── uitest/ (navigation, dialog changelog, Paramètres)
```
## Feuille de route
- [x] v1 : courbes E2/T, log doses, labs + calibration, rappels, backup JSON, FR/EN
- [x] Tests UI Compose (13) + infrastructure de compilation release signée (v1.9.8)
- [ ] Verrou biométrique, widget, export CSV
- [ ] Phase 2 montre : watchface personnalisée et/ou mini-app Lite Wearable (voir [docs/MONTRE-GADGETBRIDGE.md](docs/MONTRE-GADGETBRIDGE.md))
## Licence
**GPL-3.0** — voir [LICENSE](LICENSE). Cohérent avec l'écosystème Gadgetbridge.
Les modèles PK appartiennent à leurs autrices respectives
([Estrannaise](https://estrannaise.github.io/), [Transfem Science](https://transfemscience.org)).