Initial commit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
47
backend/internal/model/exercise.go
Executable file
47
backend/internal/model/exercise.go
Executable file
@@ -0,0 +1,47 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Exercise repräsentiert eine Kraftübung.
|
||||
type Exercise struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
MuscleGroup string `json:"muscle_group"`
|
||||
WeightStepKg float64 `json:"weight_step_kg"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty"`
|
||||
}
|
||||
|
||||
// CreateExerciseRequest enthält die Felder zum Anlegen einer Übung.
|
||||
type CreateExerciseRequest struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
MuscleGroup string `json:"muscle_group"`
|
||||
WeightStepKg *float64 `json:"weight_step_kg"`
|
||||
}
|
||||
|
||||
// Validate prüft und normalisiert den Request. Setzt Default für WeightStepKg.
|
||||
func (r *CreateExerciseRequest) Validate() error {
|
||||
r.Name = strings.TrimSpace(r.Name)
|
||||
if len(r.Name) == 0 || len(r.Name) > 100 {
|
||||
return errors.New("Name muss 1–100 Zeichen lang sein")
|
||||
}
|
||||
if !ValidMuscleGroup(r.MuscleGroup) {
|
||||
return errors.New("Ungültige Muskelgruppe")
|
||||
}
|
||||
if r.WeightStepKg != nil {
|
||||
if *r.WeightStepKg <= 0 {
|
||||
return errors.New("Gewichtsschritt muss > 0 sein")
|
||||
}
|
||||
} else {
|
||||
def := 2.5
|
||||
r.WeightStepKg = &def
|
||||
}
|
||||
return nil
|
||||
}
|
||||
19
backend/internal/model/session.go
Executable file
19
backend/internal/model/session.go
Executable file
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// Session repräsentiert eine Trainingseinheit.
|
||||
type Session struct {
|
||||
ID int64 `json:"id"`
|
||||
SetID int64 `json:"set_id"`
|
||||
SetName string `json:"set_name"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
EndedAt *time.Time `json:"ended_at,omitempty"`
|
||||
Note string `json:"note"`
|
||||
Logs []SessionLog `json:"logs,omitempty"`
|
||||
}
|
||||
|
||||
// CreateSessionRequest enthält die Felder zum Starten einer Session.
|
||||
type CreateSessionRequest struct {
|
||||
SetID int64 `json:"set_id"`
|
||||
}
|
||||
76
backend/internal/model/session_log.go
Executable file
76
backend/internal/model/session_log.go
Executable file
@@ -0,0 +1,76 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SessionLog repräsentiert einen einzelnen Satz innerhalb einer Session.
|
||||
type SessionLog struct {
|
||||
ID int64 `json:"id"`
|
||||
SessionID int64 `json:"session_id"`
|
||||
ExerciseID int64 `json:"exercise_id"`
|
||||
ExerciseName string `json:"exercise_name"`
|
||||
SetNumber int `json:"set_number"`
|
||||
WeightKg float64 `json:"weight_kg"`
|
||||
Reps int `json:"reps"`
|
||||
Note string `json:"note"`
|
||||
LoggedAt time.Time `json:"logged_at"`
|
||||
}
|
||||
|
||||
// CreateLogRequest enthält die Felder zum Loggen eines Satzes.
|
||||
type CreateLogRequest struct {
|
||||
ExerciseID int64 `json:"exercise_id"`
|
||||
SetNumber int `json:"set_number"`
|
||||
WeightKg float64 `json:"weight_kg"`
|
||||
Reps int `json:"reps"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
|
||||
// Validate prüft den Request.
|
||||
func (r *CreateLogRequest) Validate() error {
|
||||
if r.SetNumber < 1 {
|
||||
return errors.New("Satznummer muss ≥ 1 sein")
|
||||
}
|
||||
if r.WeightKg < 0 || r.WeightKg > 999 {
|
||||
return errors.New("Gewicht muss zwischen 0 und 999 kg liegen")
|
||||
}
|
||||
if r.Reps < 0 || r.Reps > 999 {
|
||||
return errors.New("Wiederholungen müssen zwischen 0 und 999 liegen")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateLogRequest enthält die Felder zum Korrigieren eines Satzes.
|
||||
type UpdateLogRequest struct {
|
||||
WeightKg *float64 `json:"weight_kg"`
|
||||
Reps *int `json:"reps"`
|
||||
Note *string `json:"note"`
|
||||
}
|
||||
|
||||
// Validate prüft den Request.
|
||||
func (r *UpdateLogRequest) Validate() error {
|
||||
if r.WeightKg != nil && (*r.WeightKg < 0 || *r.WeightKg > 999) {
|
||||
return errors.New("Gewicht muss zwischen 0 und 999 kg liegen")
|
||||
}
|
||||
if r.Reps != nil && (*r.Reps < 0 || *r.Reps > 999) {
|
||||
return errors.New("Wiederholungen müssen zwischen 0 und 999 liegen")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LastLogResponse enthält die letzten Werte einer Übung.
|
||||
type LastLogResponse struct {
|
||||
WeightKg float64 `json:"weight_kg"`
|
||||
Reps int `json:"reps"`
|
||||
}
|
||||
|
||||
// ExerciseStats enthält aggregierte Statistiken einer Übung.
|
||||
type ExerciseStats struct {
|
||||
ExerciseID int64 `json:"exercise_id"`
|
||||
ExerciseName string `json:"exercise_name"`
|
||||
MaxWeightKg float64 `json:"max_weight_kg"`
|
||||
TotalVolumeKg float64 `json:"total_volume_kg"`
|
||||
TotalSets int `json:"total_sets"`
|
||||
LastTrained string `json:"last_trained"`
|
||||
}
|
||||
52
backend/internal/model/training_set.go
Executable file
52
backend/internal/model/training_set.go
Executable file
@@ -0,0 +1,52 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TrainingSet ist eine benannte Zusammenstellung von Übungen.
|
||||
type TrainingSet struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Exercises []Exercise `json:"exercises"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty"`
|
||||
}
|
||||
|
||||
// CreateSetRequest enthält die Felder zum Anlegen eines Sets.
|
||||
type CreateSetRequest struct {
|
||||
Name string `json:"name"`
|
||||
ExerciseIDs []int64 `json:"exercise_ids"`
|
||||
}
|
||||
|
||||
// Validate prüft und normalisiert den Request.
|
||||
func (r *CreateSetRequest) Validate() error {
|
||||
r.Name = strings.TrimSpace(r.Name)
|
||||
if len(r.Name) == 0 || len(r.Name) > 100 {
|
||||
return errors.New("Name muss 1–100 Zeichen lang sein")
|
||||
}
|
||||
if len(r.ExerciseIDs) == 0 {
|
||||
return errors.New("Mindestens eine Übung erforderlich")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSetRequest enthält die Felder zum Aktualisieren eines Sets.
|
||||
type UpdateSetRequest struct {
|
||||
Name string `json:"name"`
|
||||
ExerciseIDs []int64 `json:"exercise_ids"`
|
||||
}
|
||||
|
||||
// Validate prüft und normalisiert den Request.
|
||||
func (r *UpdateSetRequest) Validate() error {
|
||||
r.Name = strings.TrimSpace(r.Name)
|
||||
if len(r.Name) == 0 || len(r.Name) > 100 {
|
||||
return errors.New("Name muss 1–100 Zeichen lang sein")
|
||||
}
|
||||
if len(r.ExerciseIDs) == 0 {
|
||||
return errors.New("Mindestens eine Übung erforderlich")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
28
backend/internal/model/validation.go
Executable file
28
backend/internal/model/validation.go
Executable file
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
// Gültige Muskelgruppen für Übungen.
|
||||
var muscleGroups = map[string]bool{
|
||||
"brust": true,
|
||||
"ruecken": true,
|
||||
"schultern": true,
|
||||
"bizeps": true,
|
||||
"trizeps": true,
|
||||
"beine": true,
|
||||
"bauch": true,
|
||||
"ganzkoerper": true,
|
||||
"sonstiges": true,
|
||||
}
|
||||
|
||||
// ValidMuscleGroup prüft ob die übergebene Muskelgruppe gültig ist.
|
||||
func ValidMuscleGroup(mg string) bool {
|
||||
return muscleGroups[mg]
|
||||
}
|
||||
|
||||
// MuscleGroups gibt alle gültigen Muskelgruppen zurück.
|
||||
func MuscleGroups() []string {
|
||||
groups := make([]string, 0, len(muscleGroups))
|
||||
for g := range muscleGroups {
|
||||
groups = append(groups, g)
|
||||
}
|
||||
return groups
|
||||
}
|
||||
Reference in New Issue
Block a user