Dedup Garmin data storage, configurable chart colors, taxonomy fixes, sync/progression fixes
- Remove duplicated Garmin fields from storage; decode display-only fields (activity name/type, lap duration/HR, structured workout raw JSON) from RawJSON at API-response time instead of storing redundant columns - Add a fully configurable chart color system (pace/HR main-line colors, 4 effort-kind colors, tint/darken/brighten intensity knobs) under Profile > Chart colors - Rename training types and fix their display order (Easy, Long, 60'/30' Threshold, Tempo, Intervals, MAS Test, Race) everywhere they're listed - Add an Efficiency Factor progression metric; fix Progression chart axes to use tight non-zero-based domains, m:ss/km pace formatting, and rounded ticks instead of raw floating-point labels - Expose the raw get_workout_by_id() payload in the raw-data viewer alongside activity/lap/detail JSON; enlarge the modal and shrink array indentation for readability - Fix "last sync" reporting a meaningless activity count: record one combined sync run per manual "Sync now" and count genuinely new activities instead of re-listing whatever Garmin returned for the queried window - Let a Review Queue activity be manually cleared back to Unclassified, and make "Reset all" available even while disconnected from Garmin Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,31 +22,18 @@ func isRunningActivityType(typeKey string) bool {
|
||||
func toActivityRow(a garmin.Activity) store.Activity {
|
||||
return store.Activity{
|
||||
GarminActivityID: a.ActivityID,
|
||||
ActivityName: a.ActivityName,
|
||||
ActivityType: a.ActivityType.TypeKey,
|
||||
EventTypeKey: a.EventType.TypeKey,
|
||||
WorkoutID: a.WorkoutID,
|
||||
StartTimeUTC: a.StartTimeGMT,
|
||||
BeginTimestampMs: a.BeginTimestamp,
|
||||
DurationSeconds: a.Duration,
|
||||
DistanceMeters: a.Distance,
|
||||
AvgHR: nonZero(a.AverageHR),
|
||||
MaxHR: nonZero(a.MaxHR),
|
||||
AvgSpeedMps: nonZero(a.AverageSpeed),
|
||||
MaxSpeedMps: nonZero(a.MaxSpeed),
|
||||
ElevationGainM: a.ElevationGain,
|
||||
ElevationLossM: a.ElevationLoss,
|
||||
Calories: nonZero(a.Calories),
|
||||
LapCount: a.LapCount,
|
||||
AerobicTrainingEffect: nonZero(a.AerobicTrainingEffect),
|
||||
AnaerobicTrainingEffect: nonZero(a.AnaerobicTrainingEffect),
|
||||
TrainingEffectLabel: a.TrainingEffectLabel,
|
||||
VO2MaxValue: a.VO2MaxValue,
|
||||
HrTimeInZone1: nonZero(a.HrTimeInZone1),
|
||||
HrTimeInZone2: nonZero(a.HrTimeInZone2),
|
||||
HrTimeInZone3: nonZero(a.HrTimeInZone3),
|
||||
HrTimeInZone4: nonZero(a.HrTimeInZone4),
|
||||
HrTimeInZone5: nonZero(a.HrTimeInZone5),
|
||||
RawJSON: string(a.Raw),
|
||||
}
|
||||
}
|
||||
@@ -90,18 +77,9 @@ func toLapRows(laps []garmin.Lap, samples []garmin.Sample, targets []*garmin.Wor
|
||||
hrLow, hrHigh = targetHRRange(*targets[i], profile)
|
||||
}
|
||||
|
||||
raw, _ := json.Marshal(l)
|
||||
rows = append(rows, store.Lap{
|
||||
LapIndex: l.LapIndex,
|
||||
StartTimeUTC: l.StartTimeGMT,
|
||||
DurationSeconds: l.Duration,
|
||||
DistanceMeters: l.Distance,
|
||||
AvgHR: nonZero(l.AverageHR),
|
||||
MaxHR: nonZero(l.MaxHR),
|
||||
AvgSpeedMps: nonZero(l.AverageSpeed),
|
||||
MaxSpeedMps: nonZero(l.MaxSpeed),
|
||||
ElevationGainM: nonZero(l.ElevationGain),
|
||||
ElevationLossM: nonZero(l.ElevationLoss),
|
||||
IntensityType: l.IntensityType,
|
||||
HRDriftBpmPerMin: driftPtr,
|
||||
HRRecoveryBpmPerMin: recoveryPtr,
|
||||
@@ -109,7 +87,7 @@ func toLapRows(laps []garmin.Lap, samples []garmin.Sample, targets []*garmin.Wor
|
||||
TargetPaceHighMps: paceHigh,
|
||||
TargetHRLowBpm: hrLow,
|
||||
TargetHRHighBpm: hrHigh,
|
||||
RawJSON: string(raw),
|
||||
RawJSON: string(l.Raw),
|
||||
})
|
||||
elapsedStart = elapsedEnd
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user