MotoRun - Offline-first Verseny Adminisztrációs Rendszer MotoRun - Offline-first Verseny Adminisztrációs Rendszer

MotoRun - Offline-first Verseny Adminisztrációs Rendszer


Áttekintés

A MotoRun egy modern Android alkalmazás Silkolene motoRun motoros navigációs versenyekhez, amely egyszerűsíti a verseny szervezői és résztvevői számára a pontőröknél történő adatnaplózást. Az alkalmazás offline-first megközelítéssel készült, ahol az elsődleges cél a megbízható, másodperc-pontos digitális naplózás volt még internetkapcsolat nélkül is.

A projekt során különös figyelmet fordítottam a Clean Architecture elvekre, MVVM mintára és az offline-first adatkezelésre, biztosítva hogy a kritikus versenyinformációk soha ne vesszenek el kapcsolódási problémák miatt.

A rendszer azóta tovább nőtt:

  • 2024-2025: Android alkalmazás Firebase backenddel. Az oldal nagy része ezt a verziót mutatja be.
  • 2026 tavasz: saját Spring Boot backend a Firebase helyett, az Önálló laboratórium keretében.
  • 2026 ősz: auditálható versenyértékelés és webes adminisztráció a szakdolgozatomban.

Architektúra és tervezési minták

Clean Architecture implementáció

  • Presentation Layer: @HiltViewModel annotált ViewModel-ek unidirectional data flow-val (StateFlow)
  • Domain Layer: Repository interface-ek és use-case-ek a business logic elkülönítésére
  • Data Layer: Room database + Firestore hibrid megoldás offline-first prioritással
  • UI Layer: Jetpack Compose-zal felépített stateless Composable-ök

State Management és reaktív programozás

data class CheckpointUiState(
    val sorter: Sorter = Sorter.TimeDESC,
    val filter: Filter = Filter.Arrived,
    val selectedEntry: Entry? = null,
    val sortedEntries: List<Entry> = emptyList(),
    val isFilterHidingEntries: Boolean = false
)
  • Sealed classes típusbiztos state/error modeling-hez (AuthState, AuthError)
  • Flow operators (combine, distinctUntilChanged) reaktív adatáramláshoz

Dependency Injection és modularitás

  • Hilt használata teljes DI coverage-dzsel
  • Moduláris felépítés: AuthRepository, EntryRepository, NetworkManager
  • Interface segregation a tesztelhetőség javítására

Kulcs funkciók és implementációk

NFC-alapú csapat regisztráció

@Singleton
class NFCHandler @Inject constructor(
    private val authRepository: AuthRepository,
    private val entryRepository: EntryRepository
) {
    sealed class NFCState {
        object Disabled : NFCState()
        data class Enabled(val checkpointId: Int) : NFCState()
    }
    
    fun handleNfcIntent(intent: Intent) {
        // Role-based authorization and automatic entry creation
    }
}

Offline-first adatszinkronizáció

  • Room database helyi perzisztenciával
  • Firestore cloud backup és multi-device sync
  • Conflict resolution version-based update strategiával
  • Network state monitoring automatikus reconnection és retry logikával

Role-based hozzáférés-vezérlés

enum class Role {
    UNKNOWN, TEAM, CHECKPOINT, ORGANIZER, ADMIN
}

sealed class AuthState {
    data object Idle : AuthState()
    data object Loading : AuthState() 
    data class LoggedIn(val role: Role, val isOnline: Boolean) : AuthState()
    data class Error(val error: AuthError) : AuthState()
}

Robusztus hálózatkezelés

  • NetworkManager lifecycle-aware hálózatkezelés
  • Exponential backoff újra csatlakozási stratégia
  • Rate limiting Firestore API túlterhelés ellen (free tier :))
  • Health checks és automatikus helyreállás

Technikai megvalósítás

Offline képességek

  • AndroidKeyStore belépési adatok és kulcsok biztonságos tárolásához
  • Room komplex relációs lekérdezésekkel és indexeléssel
  • DataStore konfigurációk kezeléséhez

UI/UX tervezés

  • Material 3 design system
  • Compose UI deklaratív kezelőfelület leírás
  • State hoisting clean separation of concerns-ért
  • Dialog management centralizált UI state handling-gel

Adatexport és jelentések

  • Apache POI Excel export funkcióhoz
  • Google Apps Script Google Sheets export funkcióhoz
  • FileProvider offline file sharing-hez
  • Progress tracking callbacks hosszú műveleteknél

Hardware integráció

  • NFC card reading NDEF message parsing-gal
  • Device identification unique device tracking-hez
  • Hardware sensor access készülék-specifikus adatokhoz

Alkalmazott technológiák

Android fejlesztés:

  • Kotlin 2.0 modern nyelvi elemek használata
  • Jetpack Compose declarative UI
  • Navigation Compose type-safe navigáció
  • Hilt dependency injection
  • Room + DataStore data persistence

Backend és szinkronizáció (első verzió):

  • Firebase Auth role-based authentication
  • Firebase Firestore szinkronizációs adatbázis, verziókezeléssel
  • Firebase Crashlytics crash reporting

Architektúra és patterns:

  • MVVM + Clean Architecture
  • Repository pattern adat absztakciós réteg
  • Observer pattern reactive programming-hoz
  • Singleton pattern system services-hez

Fejlesztői tooling:

  • Gradle KTS build configuration
  • ProGuard code obfuscation and minifying
  • BuildConfig environment-specific settings

Eredmények és teljesítmény

  • Offline működés: 100% funkcionalitás internet nélkül
  • Adatbiztonság: Zero data loss konfliktus-feloldó szinkronizációval
  • NFC response idő: < 200ms card-tól entry creation-ig
  • Multi-role support: 4 különböző felhasználói szerepkör
  • Excel export: Teljes verseny eredmények batch export-ja
  • Network resilience: Automatikus reconnection és retry logika

A projekt demonstrálja a modern Android fejlesztés best practice-eit, különös tekintettel a reliability, scalability és maintainability szempontjaira kritikus alkalmazási környezetben.


2026: saját backend (Önálló laboratórium)

A Firebase induláskor jól szolgált, de az alkalmazás kinőtte: a Firestore árazása miatt kliensoldali rate limitinget kellett bevezetnem, ami perces szinkronizációs késéseket okozott, az üzleti logika kizárólag a klienseken futott, és nem volt szerveroldali source of truth. A 2026-os tavaszi félévben ezért a teljes Firebase backendet saját fejlesztésű, Spring Boot alapú moduláris monolitra cseréltem. A Room alapú offline-first működés érintetlen maradt, csak a távoli szinkronizációs réteg változott.

  • Spring Boot 4 + Spring Modulith (Java 25): auth és entry modul, PostgreSQL 18, Liquibase sémakezelés.
  • JWT alapú autentikáció és RBAC: access és refresh tokenek, TEAM, CHECKPOINT, ORGANIZER és ADMIN szerepkörök Spring Security-vel.
  • Determinisztikus, szerveroldali konfliktusfeloldás: kombinált push/pull szinkronizáció az órákig offline pontőri eszközökhöz, ahol a szerver dönt autoritatívan.
  • Valós idejű adatszórás: STOMP over WebSocket, így a szervező késleltetés nélkül látja az ellenőrzőpontok adatait.
  • Android kliens: a Firebase SDK-k helyett OkHttp és Retrofit alapú távoli szinkronizációs réteg.
  • Infrastruktúra: Docker Compose, GitHub Actions CI/CD, Cloudflare, Prometheus és Grafana monitoring.

A backendet OpenRouter + OpenCode alapú agentic fejlesztéssel építettem. A tervet és az ütemezést az Önálló laboratórium tervben írtam le.


Szakdolgozat: auditálható versenyértékelés (2026 ősz, folyamatban)

A verseny végeredménye ma még egy manuális bizalmi határon halad át: a szervezők Google Sheetsből egy több munkalapos Excel fájlba másolják az adatokat, ahol egy elcsúszott hivatkozás vagy hibás copy-paste úgy módosíthatja az eredményt, hogy azt csak hosszú kézi ellenőrzéssel lehet megtalálni. A szakdolgozatomban ezt a folyamatot váltom ki:

  • Determinisztikus pontszámítás verziózott szabályok alapján, részletes számítási naplóval: minden összesített érték visszakövethető a nyers pontőri bejegyzésekig.
  • Compose Multiplatform Web adminisztrációs felület: versenykonfiguráció, csapat-szakasz hőtérkép, hibapont-főkönyv, javítások és egyedi elbírálások.
  • Megváltoztathatatlan, verziózott publikáció: a csapatok egy hozzájuk kötött linken (QR kóddal) látják a saját eredményük teljes levezetését.
  • Bizonyítható működés: visszaellenőrzés a 2026-os verseny teljes adathalmazán, Playwright E2E tesztek, automatizált mentés és helyreállítás.
  • AI mint másodvélemény: az LLM a determinisztikusan megjelölt gyanús értékekhez ad második véleményt, a résztvevőknek pedig a saját publikált eredményük alapján magyaráz, de a pontszámításba nem szól bele.

A részletes terv és ütemezés a Szakdolgozat tervben olvasható.


Vissza a projektekhez