Files
Stride/app/stats_sources.py

73 lines
2.9 KiB
Python

"""Expand persisted compact laps or moving segments without reading raw recordings."""
from copy import copy
from .stats_analysis import evaluate, expression_tree, valid
from .stats_dsl import QueryError
def expand(history, q, catalog):
rows = []
trees = [
(spec["name"], expression_tree(spec["expression"], catalog)[0]) for spec in q["derived"]
]
for activity in history:
source = q["source"]
units = (activity.analysis_summary or {}).get(source, [])
if source == "efforts":
units = [{"distance": e["distance"], "duration": e["seconds"],
"effort_time": e["seconds"]} for e in activity.best_efforts or []]
for index, unit in enumerate(units):
if (
not isinstance(unit, dict)
or not valid(unit.get("distance"))
or not valid(unit.get("duration"))
or unit["duration"] <= 0
or unit["distance"] <= 0
):
continue
row = copy(activity)
row.activity_id = activity.id
row.parent_title = activity.title
row.recording = unit
row.id = activity.id * 1000000 + index
row.title = (
f"{activity.title} · {'lap' if q['source'] == 'laps' else 'segment'} {index + 1}"
)
row.distance_m, row.duration_s = unit["distance"], unit["duration"]
row.elevation_m = unit.get("elevation")
row.avg_hr = (
unit.get("heart_rate")
if valid(unit.get("heart_rate")) and unit["heart_rate"] > 0
else None
)
row.values = {key: None for key in catalog}
row.values.update(
count=1,
distance=row.distance_m / 1000,
duration=row.duration_s / 3600,
pace=row.duration_s * 1000 / row.distance_m,
speed=row.distance_m / row.duration_s * 3.6,
heart_rate=row.avg_hr,
matched_minutes=row.duration_s / 60,
matched_windows=1,
elevation=row.elevation_m,
elevation_per_km=row.elevation_m / (row.distance_m / 1000)
if valid(row.elevation_m)
else None,
)
for key in catalog:
if key in {"distance", "duration", "pace", "count", "speed", "heart_rate", "elevation", "elevation_per_km", "matched_minutes", "matched_windows"}:
continue
row.values[key] = unit.get(key)
row.analysis_summary = row.values
row.previous = None
for name, tree in trees:
row.values[name] = evaluate(tree, row.values)
rows.append(row)
if len(rows) > 100000:
raise QueryError(
"This expands over 100,000 recording units. Use a shorter date range."
)
return rows