Remontée : le rappel quotidien (CPA) masquait le rappel hebdomadaire (EEn) — « je ne le vois quasiment pas ». - NextDoseCard : UNE ligne par traitement, TRIÉES par prochaine prise ; 1ʳᵉ ligne (la plus proche) en avant, suivantes en style secondaire ; titre pluriel « Prochaines doses » dès 2 lignes (next_doses FR/EN) - Helper PUR nextDoseLine (locale/zone paramétrables, template jours localisé next_dose_days) + 3 tests NextDoseLineTest - Notifications inchangées (une alarme par traitement) - versionCode 43 / 1.9.6 + CHANGELOG/§2/README/GUIDE
274 lines
17 KiB
Markdown
274 lines
17 KiB
Markdown
# HormoneTrack
|
||
|
||
> **🤖 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.9.6 — build Android ✅, **lint vert** ✅, **247 tests unitaires** ✅ (217 sans les données de test locales ; régressions épinglées sur données réelles **non versionnées**), 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)
|
||
|
||
## 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é
|
||
- **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
|
||
- **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
|
||
- **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
|
||
- **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 # 247 tests (217 sans les données locales)
|
||
./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.8.1`) 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,4 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).
|
||
|
||
## 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
|
||
├── 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)
|
||
├── local-test-data/ ← gitignoré : backups réels pour les tests
|
||
│ de régression (JAMAIS dans le dépôt, cf §8.bis)
|
||
├── 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)
|
||
│ │ ├── 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)
|
||
```
|
||
|
||
## Feuille de route
|
||
|
||
- [x] v1 : courbes E2/T, log doses, labs + calibration, rappels, backup JSON, FR/EN
|
||
- [ ] Tests UI Compose + compilation release signée
|
||
- [ ] 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)).
|