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:
@@ -29,39 +29,49 @@ func main() {
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Easy 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.
|
||||
easyID, err := db.CreateWorkoutKind(ctx, store.WorkoutKind{
|
||||
Name: "Easy", Description: "Easy conversational runs", Color: "#22c55e",
|
||||
// Set a max heart rate on the profile so avg_hr_pct_max is computed
|
||||
// during classification below (it's nil/unset by default).
|
||||
profile, err := db.GetProfile(ctx)
|
||||
must(err)
|
||||
maxHR := 190.0
|
||||
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":[
|
||||
{"metric":"avg_pace_sec_per_km","op":"between","value":[330,420]},
|
||||
{"metric":"avg_hr_pct_max","op":"<=","value":0.85}
|
||||
]}`,
|
||||
IsActive: true,
|
||||
})
|
||||
must(err)
|
||||
}))
|
||||
|
||||
tempoID, err := db.CreateWorkoutKind(ctx, store.WorkoutKind{
|
||||
Name: "Tempo", Description: "Comfortably hard sustained effort", Color: "#f59e0b",
|
||||
tempoID := mustFindKindID(ctx, db, "Tempo")
|
||||
must(db.UpdateWorkoutKind(ctx, store.WorkoutKind{
|
||||
ID: tempoID, Name: "Tempo", Description: "Comfortably hard sustained effort", Color: "#f59e0b",
|
||||
RuleJSON: `{"match":"all","conditions":[
|
||||
{"metric":"avg_pace_sec_per_km","op":"between","value":[300,340]},
|
||||
{"metric":"avg_hr_pct_max","op":">=","value":0.70}
|
||||
]}`,
|
||||
IsActive: true,
|
||||
})
|
||||
must(err)
|
||||
}))
|
||||
|
||||
_, err = db.CreateWorkoutKind(ctx, store.WorkoutKind{
|
||||
Name: "Interval", Description: "Structured work/rest intervals", Color: "#ef4444",
|
||||
intervalID := mustFindKindID(ctx, db, "Interval")
|
||||
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}]}`,
|
||||
IsActive: true,
|
||||
})
|
||||
must(err)
|
||||
}))
|
||||
|
||||
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()
|
||||
activityIDs := []int64{}
|
||||
@@ -219,3 +229,15 @@ func must(err error) {
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user