fix(stats): use accumulated elevation gain for Most Climbing record

The Most Climbing record was incorrectly using net climb (endElevation - startElevation)
instead of accumulated elevation gain. This caused two problems:
1. Net climb doesn't capture drives that go up and down (e.g., +500m up, -400m down = +100m net vs +500m accumulated)
2. Many drives have null endElevation, causing them to be excluded from the query

Fixed by:
- Updated AggregateDao queries to ORDER BY elevationGain (accumulated) instead of (endElevation - startElevation)
- Updated queries to filter by elevationGain IS NOT NULL instead of requiring both start/end elevations
- Simplified StatsRepository to use elevationGain directly instead of recalculating net climb
This commit is contained in:
Davide Ferrari
2026-01-05 14:26:08 +01:00
parent 9261f78239
commit 4c4111561a
2 changed files with 7 additions and 16 deletions
@@ -81,13 +81,12 @@ interface AggregateDao {
""")
suspend fun driveWithMinElevation(carId: Int): DriveDetailAggregate?
// Drive with most net elevation gain (end - start altitude)
// Drive with most accumulated elevation gain (total meters climbed)
@Query("""
SELECT a.* FROM drive_detail_aggregates a
WHERE a.carId = :carId
AND a.startElevation IS NOT NULL
AND a.endElevation IS NOT NULL
ORDER BY (a.endElevation - a.startElevation) DESC LIMIT 1
AND a.elevationGain IS NOT NULL
ORDER BY a.elevationGain DESC LIMIT 1
""")
suspend fun driveWithMostElevationGain(carId: Int): DriveDetailAggregate?
@@ -95,10 +94,9 @@ interface AggregateDao {
SELECT a.* FROM drive_detail_aggregates a
JOIN drives_summary d ON a.driveId = d.driveId
WHERE a.carId = :carId
AND a.startElevation IS NOT NULL
AND a.endElevation IS NOT NULL
AND a.elevationGain IS NOT NULL
AND d.startDate >= :startDate AND d.startDate < :endDate
ORDER BY (a.endElevation - a.startElevation) DESC LIMIT 1
ORDER BY a.elevationGain DESC LIMIT 1
""")
suspend fun driveWithMostElevationGainInRange(carId: Int, startDate: String, endDate: String): DriveDetailAggregate?
@@ -176,14 +176,10 @@ class StatsRepository @Inject constructor(
},
driveWithMostClimbing = driveWithMostGain?.let { agg ->
val drive = driveSummaryDao.get(agg.driveId)
// Net elevation gain = end elevation - start elevation
val netElevationGain = if (agg.startElevation != null && agg.endElevation != null) {
agg.endElevation - agg.startElevation
} else null
DriveElevationRecord(
driveId = agg.driveId,
elevationM = agg.maxElevation ?: 0,
elevationGainM = netElevationGain,
elevationGainM = agg.elevationGain,
date = drive?.startDate
)
},
@@ -283,13 +279,10 @@ class StatsRepository @Inject constructor(
driveWithMinElevation = null, // Not shown in UI
driveWithMostClimbing = driveWithMostGain?.let { agg ->
val drive = driveSummaryDao.get(agg.driveId)
val netElevationGain = if (agg.startElevation != null && agg.endElevation != null) {
agg.endElevation - agg.startElevation
} else null
DriveElevationRecord(
driveId = agg.driveId,
elevationM = agg.maxElevation ?: 0,
elevationGainM = netElevationGain,
elevationGainM = agg.elevationGain,
date = drive?.startDate
)
},