fix: update seedsample for the fixed workout taxonomy and profile-based max HR

Update workout kinds by fixed name (via ListWorkoutKinds/UpdateWorkoutKind)
instead of creating new ones, since the taxonomy migration now seeds
Easy Run/Tempo/Interval by unique name. Set profile.MaxHeartRate so
avg_hr_pct_max is computed during classification, and drop the removed
appsync.Config.MaxHR field.
This commit is contained in:
2026-07-17 19:29:02 +02:00
parent 17ebe3c665
commit 91b901ba60

View File

@@ -29,39 +29,49 @@ func main() {
} }
defer db.Close() defer db.Close()
// Easy and Tempo's pace/HR ranges deliberately overlap a little (330-340 // Set a max heart rate on the profile so avg_hr_pct_max is computed
// sec/km, 0.70-0.85 HR%max) so a run that lands in that overlap zone // during classification below (it's nil/unset by default).
// demonstrates the ambiguous-multi-match review path, not just a gap profile, err := db.GetProfile(ctx)
// between disjoint ranges. must(err)
easyID, err := db.CreateWorkoutKind(ctx, store.WorkoutKind{ maxHR := 190.0
Name: "Easy", Description: "Easy conversational runs", Color: "#22c55e", profile.MaxHeartRate = &maxHR
must(db.UpdateProfile(ctx, profile))
// Easy Run and Tempo's pace/HR ranges deliberately overlap a little
// (330-340 sec/km, 0.70-0.85 HR%max) so a run that lands in that overlap
// zone demonstrates the ambiguous-multi-match review path, not just a
// gap between disjoint ranges. The taxonomy migration already seeded
// these rows (by fixed name) -- update their rules in place rather than
// creating new ones, since names are unique.
easyID := mustFindKindID(ctx, db, "Easy Run")
must(db.UpdateWorkoutKind(ctx, store.WorkoutKind{
ID: easyID, Name: "Easy Run", Description: "Easy conversational runs", Color: "#22c55e",
RuleJSON: `{"match":"all","conditions":[ RuleJSON: `{"match":"all","conditions":[
{"metric":"avg_pace_sec_per_km","op":"between","value":[330,420]}, {"metric":"avg_pace_sec_per_km","op":"between","value":[330,420]},
{"metric":"avg_hr_pct_max","op":"<=","value":0.85} {"metric":"avg_hr_pct_max","op":"<=","value":0.85}
]}`, ]}`,
IsActive: true, IsActive: true,
}) }))
must(err)
tempoID, err := db.CreateWorkoutKind(ctx, store.WorkoutKind{ tempoID := mustFindKindID(ctx, db, "Tempo")
Name: "Tempo", Description: "Comfortably hard sustained effort", Color: "#f59e0b", must(db.UpdateWorkoutKind(ctx, store.WorkoutKind{
ID: tempoID, Name: "Tempo", Description: "Comfortably hard sustained effort", Color: "#f59e0b",
RuleJSON: `{"match":"all","conditions":[ RuleJSON: `{"match":"all","conditions":[
{"metric":"avg_pace_sec_per_km","op":"between","value":[300,340]}, {"metric":"avg_pace_sec_per_km","op":"between","value":[300,340]},
{"metric":"avg_hr_pct_max","op":">=","value":0.70} {"metric":"avg_hr_pct_max","op":">=","value":0.70}
]}`, ]}`,
IsActive: true, IsActive: true,
}) }))
must(err)
_, err = db.CreateWorkoutKind(ctx, store.WorkoutKind{ intervalID := mustFindKindID(ctx, db, "Interval")
Name: "Interval", Description: "Structured work/rest intervals", Color: "#ef4444", must(db.UpdateWorkoutKind(ctx, store.WorkoutKind{
ID: intervalID, Name: "Interval", Description: "Structured work/rest intervals", Color: "#ef4444",
RuleJSON: `{"match":"all","conditions":[{"metric":"lap_interval_pattern","op":"==","value":true}]}`, RuleJSON: `{"match":"all","conditions":[{"metric":"lap_interval_pattern","op":"==","value":true}]}`,
IsActive: true, IsActive: true,
}) }))
must(err)
m := &mock.Client{} m := &mock.Client{}
svc := appsync.NewService(m, db, appsync.Config{MinConfidence: 0.6, MaxHR: 190}, nil) svc := appsync.NewService(m, db, appsync.Config{MinConfidence: 0.6}, nil)
today := time.Now() today := time.Now()
activityIDs := []int64{} activityIDs := []int64{}
@@ -219,3 +229,15 @@ func must(err error) {
log.Fatal(err) log.Fatal(err)
} }
} }
func mustFindKindID(ctx context.Context, db *store.DB, name string) int64 {
kinds, err := db.ListWorkoutKinds(ctx, false)
must(err)
for _, k := range kinds {
if k.Name == name {
return k.ID
}
}
log.Fatalf("seedsample: no workout kind named %q found (did migration 0004 run?)", name)
return 0
}