Files
bincio-activity/bincio/extract/models.py
T
2026-03-28 13:59:36 +01:00

59 lines
1.7 KiB
Python

"""Core data models for the extract stage.
ParsedActivity is the internal representation produced by parsers.
It gets fed into metrics computation and the BAS JSON writer.
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
@dataclass
class DataPoint:
"""One measurement sample from a GPS/sensor recording."""
timestamp: datetime
lat: Optional[float] = None
lon: Optional[float] = None
elevation_m: Optional[float] = None
hr_bpm: Optional[int] = None
cadence_rpm: Optional[int] = None
# Speed from device (km/h). May be absent; we compute it from GPS if so.
speed_kmh: Optional[float] = None
power_w: Optional[int] = None
temperature_c: Optional[float] = None
# Cumulative distance from device (metres), if recorded.
distance_m: Optional[float] = None
@dataclass
class LapData:
index: int
started_at: datetime
duration_s: Optional[int] = None
distance_m: Optional[float] = None
elevation_gain_m: Optional[float] = None
avg_speed_kmh: Optional[float] = None
avg_hr_bpm: Optional[int] = None
avg_power_w: Optional[int] = None
@dataclass
class ParsedActivity:
"""Raw activity data as produced by a parser, before metric computation."""
points: list[DataPoint]
sport: str # normalised to BAS sport enum
started_at: datetime
source_file: str # basename of original file
source_hash: str # "sha256:{hex}"
sub_sport: Optional[str] = None
device: Optional[str] = None
title: Optional[str] = None
description: Optional[str] = None
gear: Optional[str] = None
strava_id: Optional[str] = None
laps: list[LapData] = field(default_factory=list)