mirror of
https://github.com/sstent/aicyclingcoach-go.git
synced 2026-04-04 20:13:01 +00:00
sync
This commit is contained in:
98
internal/tui/models/activity.go
Normal file
98
internal/tui/models/activity.go
Normal file
@@ -0,0 +1,98 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user