fix: route leaderboards rank by moving time not elapsed — top-10 route times and route completions list now use COALESCE(moving_time_s, duration_s) so mid-activity pauses don't inflate times (consistent with moving-time avg pace)
This commit is contained in:
@@ -423,17 +423,21 @@ async def get_route_leaderboard(
|
|||||||
if not act.named_route_id:
|
if not act.named_route_id:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Rank by moving time (pauses excluded), falling back to elapsed for
|
||||||
|
# activities without it — consistent with avg pace being moving-time based.
|
||||||
|
effort_s = func.coalesce(Activity.moving_time_s, Activity.duration_s)
|
||||||
rows = (await db.execute(
|
rows = (await db.execute(
|
||||||
select(
|
select(
|
||||||
Activity.id, Activity.name, Activity.start_time,
|
Activity.id, Activity.name, Activity.start_time,
|
||||||
Activity.duration_s, Activity.distance_m, Activity.avg_heart_rate,
|
effort_s.label("duration_s"),
|
||||||
|
Activity.distance_m, Activity.avg_heart_rate,
|
||||||
)
|
)
|
||||||
.where(
|
.where(
|
||||||
Activity.named_route_id == act.named_route_id,
|
Activity.named_route_id == act.named_route_id,
|
||||||
Activity.user_id == current_user.id,
|
Activity.user_id == current_user.id,
|
||||||
Activity.duration_s.isnot(None),
|
Activity.duration_s.isnot(None),
|
||||||
)
|
)
|
||||||
.order_by(Activity.duration_s)
|
.order_by(effort_s)
|
||||||
)).all()
|
)).all()
|
||||||
if not rows:
|
if not rows:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -195,11 +195,13 @@ async def route_activities(
|
|||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
):
|
):
|
||||||
|
# Rank by moving time (pauses excluded), falling back to elapsed for
|
||||||
|
# activities without it — consistent with avg pace being moving-time based.
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(Activity).where(
|
select(Activity).where(
|
||||||
Activity.named_route_id == route_id,
|
Activity.named_route_id == route_id,
|
||||||
Activity.user_id == current_user.id,
|
Activity.user_id == current_user.id,
|
||||||
).order_by(Activity.duration_s)
|
).order_by(func.coalesce(Activity.moving_time_s, Activity.duration_s))
|
||||||
)
|
)
|
||||||
activities = result.scalars().all()
|
activities = result.scalars().all()
|
||||||
return [
|
return [
|
||||||
@@ -207,7 +209,7 @@ async def route_activities(
|
|||||||
"id": a.id,
|
"id": a.id,
|
||||||
"name": a.name,
|
"name": a.name,
|
||||||
"start_time": a.start_time,
|
"start_time": a.start_time,
|
||||||
"duration_s": a.duration_s,
|
"duration_s": a.moving_time_s or a.duration_s,
|
||||||
"distance_m": a.distance_m,
|
"distance_m": a.distance_m,
|
||||||
"avg_heart_rate": a.avg_heart_rate,
|
"avg_heart_rate": a.avg_heart_rate,
|
||||||
"avg_speed_ms": a.avg_speed_ms,
|
"avg_speed_ms": a.avg_speed_ms,
|
||||||
|
|||||||
Reference in New Issue
Block a user