No description
  • Kotlin 93.5%
  • Python 6.5%
Find a file
Cyril Leblanc 61ff08c303 feat(app): display SNCF trains like the rest of the network
Data v3 adds 19 SNCF lines (TGV, TER, RE coaches) with stop-chained
substitute geometry; their stoptimes already flow through the existing
ETA pipeline untouched.

- EtaGrouper: badge names now come from the line shortName (K6, C1, P24)
  instead of the raw route id, and train lines sort as their own tier
  ahead of the urban hierarchy so SNC:C1 and SEM:C1 never interleave
- C1 disambiguation: SNCF badges are squared (train family) instead of
  circular, everywhere a line id is known — stop sheet, search results,
  search peek, disruption chips and rows
- search: lines match on longName too ("Grenoble Chambery" finds the
  TER C1) and the row shows the full route name under the badge; match
  ranking considers the subtitle
- map: synthetic geometries render dashed via the existing dashed
  property expression, so a station-resolution polyline never reads as
  the real track; SNCF lines stay out of ALWAYS_VISIBLE_IDS (too long a
  range for a wide viewport)
- vehicle cursors: trains interpolate at rail speed (70 km/h) instead of
  bus speed
- Room v6: lines gains longName and syntheticGeometry, migrated in place
  with absent-value defaults so existing installs keep working

PublishedGeometry.synthetic and both new LineEntity columns are optional
with defaults, so a v2 payload still parses and imports cleanly.
2026-08-23 23:09:11 +02:00
.forgejo feat(data): replace bundled asset with Forgejo registry download source 2026-08-23 21:53:10 +02:00
app feat(app): display SNCF trains like the rest of the network 2026-08-23 23:09:11 +02:00
docs/superpowers docs: add address-numero display fix to Task 3 2026-06-19 19:54:51 +02:00
gradle feat: migrate from OSMDroid to MapLibre GL Native with offline vector tiles 2026-06-07 00:57:13 +02:00
scripts feat(data): include SNCF lines (v3) with synthetic geometry 2026-08-23 23:09:00 +02:00
.gitignore feat(data): replace bundled asset with Forgejo registry download source 2026-08-23 21:53:10 +02:00
build.gradle.kts initial commit 2026-06-01 23:51:55 +02:00
CLAUDE.md feat(bootstrap): gate first launch behind a blocking download screen 2026-08-23 21:53:16 +02:00
gradle.properties initial commit 2026-06-01 23:51:55 +02:00
gradlew Performance and architecture improvements 2026-06-04 21:02:49 +02:00
LICENSE Add README and MIT license for open-source release 2026-06-04 22:33:37 +02:00
README.md refactor(map): use openfreemap tiles + cache, drop bundled MBTiles 2026-06-27 22:40:11 +02:00
settings-gradle.lockfile feat(build): enable Gradle dependency locking, commit lockfile 2026-08-23 20:33:52 +02:00
settings.gradle.kts feat: rename to Gresit, fix text colors, edge-to-edge, app icon 2026-06-07 23:19:03 +02:00

Gresit

Application Android non officielle pour les transports en commun de l'agglomération grenobloise (M réso).

Carte · Horaires temps réel · Position des véhicules · Perturbations · Itinéraires

License: MIT Android Kotlin API


Présentation

Application avec carte openfreemap (tuiles vectorielles en ligne + cache disque) et données temps réel via l'API M réso. Interface 100 % Jetpack Compose, thème sombre inspiré de l'identité visuelle M réso.

Fonctionnalités

Carte interactive

  • Carte plein écran, tuiles vectorielles openfreemap + cache disque (MapLibre GL), style sombre M réso fondé sur OpenStreetMap
  • Rotation à deux doigts, boussole, zoom fluide, animations caméra par coroutines (~60 fps)
  • Tous les réseau : trams (AE), Chrono, Flexo et bus
  • Curseur croix central ; l'arrêt le plus proche est mis en surbrillance (logique de distance en pixels)
  • Dispersion force-directed des quais : à fort zoom, les quais co-localisés d'un pôle (plusieurs lignes, même position GPS) s'écartent en amas compact piloté par une simulation physique (ressorts vers la position réelle + répulsion, type d3-force), chaque quai à la couleur de sa ligne
  • Géolocalisation GPS avec recentrage automatique au fix

Horaires temps réel

  • Prochains passages par arrêt, rafraîchis toutes les 15 s (cache TTL 15 s)
  • Groupement par ligne / direction / destination ; convention de nommage M réso (tram → Chrono → Flexo → bus)
  • Code couleur : vert = temps réel, orange/rouge = retard, gris = théorique
  • Flèches de direction calculées depuis les séquences GTFS
  • Position estimée des véhicules : curseurs sur la carte indiquant la position approchée des véhicules sur chaque ligne, déduite des horaires temps réel et des géométries (badge couleur de ligne + direction)
  • Perturbations & signalisations : alertes par ligne (API dyn M réso), indicateur sur la carte, popup dédié ; plans PDF (page 1) affichés dans le détail, mis en cache app-wide, badge sur les lignes concernées

Recherche

  • Recherche répartie sur trois sources : lignes en mémoire (Room, hors-ligne), arrêts via find/json (clusters), adresses via find/json (rue/lieux) — l'agglomération M réso (LaMetro)
  • Tolérante aux accents, correspondance par ville
  • Hors-ligne : seules les lignes sont recherchées ; un message signale que les arrêts et adresses sont indisponibles
  • Historique des recherches récentes (persistant)
  • Exploration d'une ligne : tous ses arrêts, suivi de l'arrêt le plus proche, terminus mis en avant

Calcul d'itinéraires

  • Origine / destination : arrêt, adresse, position GPS ou point sur carte
  • Choix de l'heure et de la date, en mode « Départ » (partir à) ou « Arrivée » (arriver avant)
  • Plusieurs propositions ; tri selon le mode : « Départ » = arrivée la plus tôt, « Arrivée » = arrivée la plus proche de l'heure voulue
  • Recalcul automatique à chaque changement d'entrée (heure, date, mode)
  • Visualisation carte : segments piétons en pointillé, transports en couleur
  • Inversion origine/destination en un tap ; message explicite si aucun itinéraire trouvé

Interface

  • Bottom sheet (masqué / aperçu / étendu) avec gestes fluides
  • Material Design 3, mode sombre
  • UI 100 % Jetpack Compose, single-activity

Architecture

Module unique :app, injection de dépendances manuelle via TransitContainer. Trois couches :

┌──────────────────────────────────────────────────┐
│                    UI Layer                       │
│  Jetpack Compose · ViewModels · TransitEventBus  │
└──────────────────────────┬───────────────────────┘
                           │
┌──────────────────────────▼───────────────────────┐
│                  Domain Layer                     │
│  Pure Kotlin · State Machines · Spatial Index    │
└──────────────────────────┬───────────────────────┘
                           │
┌──────────────────────────▼───────────────────────┐
│                   Data Layer                      │
│  Room · Retrofit · Repository · Bundled Assets   │
└──────────────────────────────────────────────────┘
  • Domain (domain/) — Kotlin pur, aucune dépendance UI. Machine à états TransitionMachine<S>, index spatial ClusterIndex / StopIndex, calculs (distance, bearing, regroupement des passages, interpolation de position des véhicules, dispersion force-directed des quais, simplification Douglas-Peucker, décodage polyline).
  • Data (data/) — Room (5 tables en lecture), Retrofit vers l'API OTP M réso, repository avec cache TTL, import des assets embarqués.
  • UI (ui/) — 4 ViewModels (Transit / Eta / Search / Plan) découplés par TransitEventBus (SharedFlow). Trois modes : EXPLORE, SEARCH, PLAN.

Points notables :

  • TransitionMachine<S> — machine à états générique avec transitions validées et effets de bord
  • TransitEventBus — SharedFlow qui découple les ViewModels
  • Couches carte MapLibre : sources GeoJSON + style data-driven (arrêts, lignes, itinéraires, marqueurs)
  • Recherche : lignes en mémoire + find/json M réso (arrêts clusters, adresses rue/lieux), fusionnée avec debounce
  • Animations caméra par coroutines avec throttling

Tech Stack

Composant Technologie
Langage Kotlin 2.1
UI Jetpack Compose, Material 3
Carte MapLibre GL Native (tuiles vectorielles openfreemap + cache)
Base de données Room (KSP)
Réseau Retrofit + kotlinx.serialization
Asynchrone Coroutines, StateFlow, SharedFlow
Build Gradle (Kotlin DSL), version catalog
Cible Android 8.0+ (API 26), compileSdk 35

Données embarquées & génération

L'asset suivant est gitignoré et (re)généré par un script Python reproductible :

Asset Script Source
transit-data.json (arrêts, lignes, géométries, séquences) generate_transit_data.py API M réso

La recherche d'arrêts et d'adresses ne dépend pas d'un asset : elle interroge en direct l'API M réso find/json. Les lignes (~60) sont lues en mémoire depuis Room (hors-ligne).

python3 scripts/generate_transit_data.py   # données transit → transit-data.json

Les tuiles vectorielles, glyphes et sprite proviennent d'openfreemap (tiles.openfreemap.org) sur HTTPS et sont mis en cache sur disque par MapLibre (aucun MBTiles ni police à embarquer ; réseau requis au premier affichage d'une zone non encore visitée). Au premier lancement, l'app importe les données transit dans Room.

Construction

./gradlew assembleDebug      # APK debug
./gradlew assembleRelease    # APK release (minifié + réduit, signé)
./gradlew installDebug       # Build & installation sur appareil

Prérequis : Android Studio 2024+, Java 17.

Données temps réel

Via l'API OpenTripPlanner de data.mobilites-m.fr :

  • getStoptimes — prochains passages temps réel par cluster
  • plan — calcul d'itinéraires multimodaux
  • dyn — perturbations et signalisations par ligne

Roadmap

  • Recherche de points d'intérêt — POI (Overpass / OSM) en plus des arrêts, lignes et adresses
  • Thème clair — variante claire du style carte MapLibre

Contribuer

Les contributions sont les bienvenues ! Pour proposer des changements :

  1. Fork le projet
  2. Créer une branche feature (git checkout -b feature/nom-de-la-feature)
  3. Commit les changements (git commit -m 'Add une feature')
  4. Push la branche (git push origin feature/nom-de-la-feature)
  5. Ouvrir une Pull Request

Licence

Ce projet est sous licence MIT.

Copyright (c) 2026 Cyril Leblanc