package api import ( "net/http" "geniusrun/backend/internal/store" ) // handleReclassifyAll re-runs the rule engine for every activity except // those that are locked: // - a manual assignment is the user's definitive word and is never // overwritten by the rule engine again; // - an activity already assigned to Race is locked too, since that // classification comes from a hard Garmin fact (eventType.typeKey == // "race"), not a rule the user might retune -- there's nothing to // re-derive. // // It's a synchronous, bounded operation (unlike sync), so it runs inline // rather than in the background. func (s *Server) handleReclassifyAll(w http.ResponseWriter, r *http.Request) { raceKind, hasRaceKind, err := s.DB.GetWorkoutKindByName(r.Context(), "Race") if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } assignments, err := s.DB.AllCurrentAssignments(r.Context()) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } var activityIDs []int64 for _, a := range assignments { if a.AssignmentSource == store.AssignmentSourceManual { continue } if hasRaceKind && a.WorkoutKindID != nil && *a.WorkoutKindID == raceKind.ID { continue } activityIDs = append(activityIDs, a.ActivityID) } for _, activityID := range activityIDs { if err := s.Sync.ClassifyActivity(r.Context(), activityID); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } } writeJSON(w, http.StatusOK, map[string]int{"reclassified": len(activityIDs)}) }