lots of stuff, don't truly remember
This commit is contained in:
@@ -43,6 +43,21 @@ type PeriodStats struct {
|
||||
AvgHR float64 `json:"avg_hr"`
|
||||
}
|
||||
|
||||
// DailyTSS holds the computed TSS for a single day.
|
||||
type DailyTSS struct {
|
||||
Date string `json:"date"`
|
||||
TSS float64 `json:"tss"`
|
||||
}
|
||||
|
||||
// PowerPoint holds power data for a single completed workout.
|
||||
type PowerPoint struct {
|
||||
Date string `json:"date"`
|
||||
AvgPower int `json:"avg_power"`
|
||||
MaxPower int `json:"max_power"`
|
||||
Duration int `json:"duration"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// GetSummary returns overall ride statistics for completed workouts.
|
||||
func (r *Repository) GetSummary(userID uint) (*Summary, error) {
|
||||
var summary Summary
|
||||
@@ -120,6 +135,65 @@ func (r *Repository) GetMonthlyStats(userID uint, months int) ([]PeriodStats, er
|
||||
return stats, err
|
||||
}
|
||||
|
||||
// GetDailyTSS returns daily TSS values for the last N days.
|
||||
// TSS = (duration_seconds * (avg_power / FTP)^2 / 3600) * 100
|
||||
// Simplified: (duration * avg_power^2) / (FTP^2 * 36)
|
||||
func (r *Repository) GetDailyTSS(userID uint, ftp int, days int) ([]DailyTSS, error) {
|
||||
if ftp <= 0 {
|
||||
return []DailyTSS{}, nil
|
||||
}
|
||||
|
||||
cutoff := time.Now().AddDate(0, 0, -days)
|
||||
ftpFloat := float64(ftp)
|
||||
|
||||
var results []DailyTSS
|
||||
err := database.DB.Model(&workout.Workout{}).
|
||||
Select(`
|
||||
TO_CHAR(scheduled_date, 'YYYY-MM-DD') as date,
|
||||
COALESCE(SUM(
|
||||
CASE WHEN avg_power > 0 AND duration > 0
|
||||
THEN (duration::float8 * avg_power::float8 * avg_power::float8) / (? * ? * 36.0)
|
||||
ELSE 0
|
||||
END
|
||||
), 0) as tss
|
||||
`, ftpFloat, ftpFloat).
|
||||
Where("user_id = ? AND status = ? AND scheduled_date >= ?", userID, "completed", cutoff).
|
||||
Group("date").
|
||||
Order("date ASC").
|
||||
Scan(&results).Error
|
||||
|
||||
if results == nil {
|
||||
results = []DailyTSS{}
|
||||
}
|
||||
|
||||
return results, err
|
||||
}
|
||||
|
||||
// GetPowerHistory returns power data points for completed workouts in the last N days.
|
||||
func (r *Repository) GetPowerHistory(userID uint, days int) ([]PowerPoint, error) {
|
||||
cutoff := time.Now().AddDate(0, 0, -days)
|
||||
|
||||
var results []PowerPoint
|
||||
err := database.DB.Model(&workout.Workout{}).
|
||||
Select(`
|
||||
TO_CHAR(scheduled_date, 'YYYY-MM-DD') as date,
|
||||
avg_power,
|
||||
max_power,
|
||||
duration,
|
||||
title
|
||||
`).
|
||||
Where("user_id = ? AND status = ? AND avg_power > 0 AND scheduled_date >= ?",
|
||||
userID, "completed", cutoff).
|
||||
Order("scheduled_date ASC").
|
||||
Scan(&results).Error
|
||||
|
||||
if results == nil {
|
||||
results = []PowerPoint{}
|
||||
}
|
||||
|
||||
return results, err
|
||||
}
|
||||
|
||||
// PersonalBest holds a single personal best record.
|
||||
type PersonalBest struct {
|
||||
Category string `json:"category"`
|
||||
|
||||
Reference in New Issue
Block a user