// package services // // import ( // // "log" // "time" // // "git.patanix.de/git/kettlebell-app/internal/data" // // ) // // // TrainingState hält den aktuellen Zustand einer laufenden Trainingseinheit. // // type TrainingState struct { // IsTrainingRunning bool // RemainingSeconds int // InitialDurationSeconds int // SetsDone int // GoalSets int // RepsPerSet int // SetTimes []time.Time // Progress float64 // SecondsSinceLastSet int // LastSetTimestamp *time.Time // CurrentProgram string // CurrentBlockDay int // CurrentReps int // TotalTrainingDays int // } // // func NewTrainingState() *TrainingState { // return &TrainingState{ // IsTrainingRunning: false, // RemainingSeconds: 0, // InitialDurationSeconds: 0, // SetsDone: 0, // GoalSets: 5, // RepsPerSet: 5, // Progress: 0.0, // SecondsSinceLastSet: 0, // LastSetTimestamp: nil, // CurrentProgram: "giant_1.0", // CurrentBlockDay: 1, // CurrentReps: 5, // TotalTrainingDays: 0, // SetTimes: []time.Time{}, // } // } // // type TrainingService struct { // State *TrainingState // dbService *data.DatabaseService // settingsService *SettingsService // } // // func NewTrainingService(db *data.DatabaseService, settings *SettingsService) *TrainingService { // initialState := NewTrainingState() // trainingCount, err := db.GetTrainingCount() // if err != nil { // log.Printf("Fehler beim Abrufen der Trainingsanzahl, setze auf 0: %v", err) // initialState.TotalTrainingDays = 0 // } else { // initialState.TotalTrainingDays = trainingCount // } // return &TrainingService{ // State: initialState, // dbService: db, // settingsService: settings, // } // } // // func (s *TrainingService) updateProgram() { // st := s.State // newTotalDays := st.TotalTrainingDays + 1 // newProgram := st.CurrentProgram // newDay := (st.CurrentBlockDay % 3) + 1 // newReps := st.CurrentReps // // if newTotalDays > 0 && newTotalDays%12 == 0 { // switch st.CurrentProgram { // case "giant_1.0": // newProgram = "ksk_1.0" // case "giant_1.1": // newProgram = "ksk_1.1" // case "giant_1.2": // newProgram = "ksk_1.2" // case "ksk_1.0": // newProgram = "giant_1.1" // case "ksk_1.1": // newProgram = "giant_1.2" // case "ksk_1.2": // newProgram = "giant_1.0" // default: // newProgram = "giant_1.0" // } // newDay = 1 // } // // repsMap := map[string][]int{ // "giant_1.0": {5, 6, 4}, // "giant_1.1": {6, 8, 7}, // "giant_1.2": {7, 9, 8}, // "ksk_1.0": {5, 6, 4}, // "ksk_1.1": {6, 8, 7}, // "ksk_1.2": {7, 9, 8}, // } // // if reps, ok := repsMap[newProgram]; ok && len(reps) >= newDay { // newReps = reps[newDay-1] // } else { // newReps = 5 // } // // st.CurrentProgram = newProgram // st.CurrentBlockDay = newDay // st.CurrentReps = newReps // st.TotalTrainingDays = newTotalDays // } // // func (s *TrainingService) StartTraining(minutes, goal int) { // s.updateProgram() // duration := minutes * 60 // s.State = &TrainingState{ // IsTrainingRunning: true, // InitialDurationSeconds: duration, // RemainingSeconds: duration, // GoalSets: goal, // RepsPerSet: s.State.CurrentReps, // CurrentProgram: s.State.CurrentProgram, // CurrentBlockDay: s.State.CurrentBlockDay, // TotalTrainingDays: s.State.TotalTrainingDays, // SetTimes: []time.Time{}, // } // } // // func (s *TrainingService) Tick() { // if s.State.RemainingSeconds > 0 { // s.State.RemainingSeconds-- // } // } // // func (s *TrainingService) TickLastSetTimer() { // if s.State.IsTrainingRunning && s.State.LastSetTimestamp != nil { // s.State.SecondsSinceLastSet = int(time.Since(*s.State.LastSetTimestamp).Seconds()) // } // } // // func (s *TrainingService) CompleteSet() { // st := s.State // st.SetsDone++ // now := time.Now() // st.SetTimes = append(st.SetTimes, now) // if st.GoalSets > 0 { // st.Progress = min(float64(st.SetsDone)/float64(st.GoalSets), 1.0) // } // st.LastSetTimestamp = &now // st.SecondsSinceLastSet = 0 // } // // func (s *TrainingService) FinishTraining(session *data.TrainingSession) error { // session.Program = s.State.CurrentProgram // session.BlockDay = int64(s.State.CurrentBlockDay) // // err := s.dbService.SaveTraining(session) // if err != nil { // return err // } // // // Platzhalter für den API-Aufruf (aus api_service.dart) // s.sendToBackend(session) // // s.ResetTraining() // return nil // } // // func (s *TrainingService) ResetTraining() { // // Diesen Teil nochmals pruefen // s.State = NewTrainingState() // trainingCount, err := s.dbService.GetTrainingCount() // if err != nil { // log.Print("Unable to get training count") // } // s.State.CurrentBlockDay = trainingCount // // Hier müsste man TotalTrainingDays wieder korrekt laden. // } // // // sendToBackend ist ein Platzhalter für deinen API-Aufruf. // // func (s *TrainingService) sendToBackend(session *data.TrainingSession) { // // Hier würde die Logik aus deinem `api_service.dart` hinkommen. // // z.B. ein HTTP POST Request mit den Trainingsdaten. // // Da der Service nicht existiert, loggen wir es nur. // log.Println("Sende Trainingsdaten an das Backend (Platzhalter)...") // // rest := float64(session.Duration) / float64(session.Sets) // // log.Printf("Reps: %d, Rest: %.2f, Sets: %d", session.RepsPerSet, rest, session.Sets) // } package services import ( "log" "time" "git.patanix.de/git/kettlebell-app/internal/data" ) type TrainingState struct { IsTrainingRunning bool RemainingSeconds int InitialDurationSeconds int SetsDone int GoalSets int RepsPerSet int SetTimes []time.Time Progress float64 SecondsSinceLastSet int LastSetTimestamp *time.Time CurrentProgram string CurrentBlockDay int CurrentReps int TotalTrainingDays int } func calculateStateByDayCount(totalDays int) (program string, blockDay, reps int) { program = "clean_1.0" blockDay = 1 reps = 5 if totalDays > 0 { cycleIndex := (totalDays / 12) % 6 programs := []string{"clean_1.0", "snatch_1.0", "clean_1.1", "snatch_1.1", "clean_1.2", "snatch_1.2"} program = programs[cycleIndex] blockDay = (totalDays % 3) + 1 } repsMap := map[string][]int{ "clean_1.0": {5, 6, 4}, "clean_1.1": {6, 8, 7}, "clean_1.2": {7, 9, 8}, "snatch_1.0": {5, 6, 4}, "snatch_1.1": {6, 8, 7}, "snatch_1.2": {7, 9, 8}, } if r, ok := repsMap[program]; ok && len(r) >= blockDay { reps = r[blockDay-1] } return } func NewTrainingState(db *data.DatabaseService) *TrainingState { trainingCount, err := db.GetTrainingCount() if err != nil { log.Printf("Fehler beim Abrufen der Trainingsanzahl, setze auf 0: %v", err) trainingCount = 0 } program, blockDay, reps := calculateStateByDayCount(trainingCount) return &TrainingState{ IsTrainingRunning: false, TotalTrainingDays: trainingCount, CurrentProgram: program, CurrentBlockDay: blockDay, CurrentReps: reps, SetTimes: []time.Time{}, GoalSets: 5, RepsPerSet: reps, } } type TrainingService struct { State *TrainingState dbService *data.DatabaseService settingsService *SettingsService apiService *ApiService } func NewTrainingService(db *data.DatabaseService, settings *SettingsService, api *ApiService) *TrainingService { return &TrainingService{ State: NewTrainingState(db), dbService: db, settingsService: settings, apiService: api, } } func (s *TrainingService) StartTraining(minutes, goal int) { program, blockDay, reps := calculateStateByDayCount(s.State.TotalTrainingDays) st := s.State st.IsTrainingRunning = true st.InitialDurationSeconds = minutes * 60 st.RemainingSeconds = st.InitialDurationSeconds st.GoalSets = goal st.CurrentProgram = program st.CurrentBlockDay = blockDay st.CurrentReps = reps st.RepsPerSet = reps st.SetsDone = 0 st.Progress = 0.0 st.SetTimes = []time.Time{} st.LastSetTimestamp = nil } func (s *TrainingService) Tick() { if s.State.RemainingSeconds > 0 { s.State.RemainingSeconds-- } } func (s *TrainingService) TickLastSetTimer() { if s.State.IsTrainingRunning && s.State.LastSetTimestamp != nil { s.State.SecondsSinceLastSet = int(time.Since(*s.State.LastSetTimestamp).Seconds()) } } func (s *TrainingService) CompleteSet() { st := s.State st.SetsDone++ now := time.Now() st.SetTimes = append(st.SetTimes, now) if st.GoalSets > 0 { st.Progress = min(float64(st.SetsDone)/float64(st.GoalSets), 1.0) } st.LastSetTimestamp = &now st.SecondsSinceLastSet = 0 } func (s *TrainingService) FinishTraining(session *data.TrainingSession) error { session.Program = s.State.CurrentProgram session.BlockDay = int64(s.State.CurrentBlockDay) err := s.dbService.SaveTraining(session) if err != nil { return err } go s.apiService.SendTrainingData(session) s.ResetTraining() return nil } func (s *TrainingService) ResetTraining() { s.State = NewTrainingState(s.dbService) } // sendToBackend ist ein Platzhalter für deinen API-Aufruf. func (s *TrainingService) sendToBackend(session *data.TrainingSession) { log.Println("Sende Trainingsdaten an das Backend (Platzhalter)...") }