mirror of
https://github.com/sstent/aicyclingcoach-go.git
synced 2026-01-28 18:11:37 +00:00
99 lines
3.3 KiB
Go
99 lines
3.3 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/sstent/fitness-tui/internal/types"
|
|
)
|
|
|
|
type Activity struct {
|
|
ID string
|
|
Name string
|
|
Description string
|
|
Type string // Garmin activity type (e.g., "running", "cycling")
|
|
ActivityType string // Activity type for AI analysis prompts (e.g., "running", "cycling", "hiking")
|
|
Date time.Time
|
|
Duration time.Duration
|
|
Distance float64 // meters
|
|
Elevation float64
|
|
Calories int // in kilocalories
|
|
Metrics ActivityMetrics
|
|
FilePath string // Path to original activity file (e.g., GPX/FIT)
|
|
}
|
|
|
|
type ActivityMetrics struct {
|
|
// Core metrics
|
|
AvgHeartRate int
|
|
MaxHeartRate int
|
|
AvgPace float64 // seconds per km
|
|
AvgSpeed float64 // km/h
|
|
ElevationGain float64 // meters
|
|
ElevationLoss float64 // meters
|
|
RecoveryTime int // hours
|
|
IntensityFactor float64
|
|
|
|
// Raw data streams
|
|
HeartRateData []float64 `json:"heart_rate_data"`
|
|
ElevationData []float64 `json:"elevation_data"`
|
|
PowerData []float64 `json:"power_data,omitempty"`
|
|
CadenceData []float64 `json:"cadence_data,omitempty"`
|
|
SpeedData []float64 `json:"speed_data,omitempty"`
|
|
TemperatureData []float64 `json:"temperature_data,omitempty"`
|
|
|
|
// Downsampled metrics (for AI analysis)
|
|
DownsampledHR []types.DownsampledPoint `json:"downsampled_hr,omitempty"`
|
|
DownsampledPower []types.DownsampledPoint `json:"downsampled_power,omitempty"`
|
|
DownsampledCadence []types.DownsampledPoint `json:"downsampled_cadence,omitempty"`
|
|
DownsampledSpeed []types.DownsampledPoint `json:"downsampled_speed,omitempty"`
|
|
|
|
// Power metrics
|
|
AvgPower float64 `json:"avg_power"`
|
|
MaxPower float64 `json:"max_power"`
|
|
NormalizedPower float64 `json:"normalized_power"`
|
|
FTP float64 `json:"ftp"` // Functional Threshold Power
|
|
|
|
// Cadence metrics
|
|
AvgCadence float64 `json:"avg_cadence"`
|
|
MaxCadence float64 `json:"max_cadence"`
|
|
|
|
// Running metrics
|
|
GroundContactTime int `json:"ground_contact_time"` // milliseconds
|
|
VerticalOscillation int `json:"vertical_oscillation"` // millimeters
|
|
|
|
// Hiking metrics
|
|
AscentRate float64 `json:"ascent_rate"` // meters/hour
|
|
DescentRate float64 `json:"descent_rate"` // meters/hour
|
|
AvgTemperature float64 `json:"avg_temperature"` // Celsius
|
|
|
|
// Analysis-specific fields
|
|
TargetZones string `json:"target_zones"` // e.g., "Z2: 115-140bpm"
|
|
TrainingLoad float64 `json:"training_load"` // Training load score
|
|
TrainingStressScore float64 `json:"training_stress_score"` // TSS score
|
|
ElevationProfile string `json:"elevation_profile"` // e.g., "Hilly with 3 major climbs"
|
|
FatigueLevel string `json:"fatigue_level"` // e.g., "Moderate"
|
|
}
|
|
|
|
func (a *Activity) FormattedDuration() string {
|
|
hours := int(a.Duration.Hours())
|
|
minutes := int(a.Duration.Minutes()) % 60
|
|
seconds := int(a.Duration.Seconds()) % 60
|
|
if hours > 0 {
|
|
return fmt.Sprintf("%d:%02d:%02d", hours, minutes, seconds)
|
|
}
|
|
return fmt.Sprintf("%02d:%02d", minutes, seconds)
|
|
}
|
|
|
|
func (a *Activity) FormattedDistance() string {
|
|
return fmt.Sprintf("%.2fkm", a.Distance/1000)
|
|
}
|
|
|
|
func (a *Activity) FormattedPace() string {
|
|
if a.Metrics.AvgPace <= 0 {
|
|
return "--:--"
|
|
}
|
|
minutes := int(a.Metrics.AvgPace) / 60
|
|
seconds := int(a.Metrics.AvgPace) % 60
|
|
return fmt.Sprintf("%d:%02d/km", minutes, seconds)
|
|
}
|