import uuid from datetime import datetime from pydantic import BaseModel, ConfigDict, Field, model_validator class EquipmentCreate(BaseModel): name: str = Field(min_length=1, max_length=160) description: str | None = None image_s3_url: str | None = None image_s3_key: str | None = None class EquipmentRead(EquipmentCreate): id: uuid.UUID owner_user_id: uuid.UUID | None is_builtin: bool created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class ExerciseCreate(BaseModel): name: str = Field(min_length=1, max_length=160) description: str | None = None equipment_id: uuid.UUID | None = None image_s3_url: str | None = None image_s3_key: str | None = None default_calories_per_minute: float | None = None class ExerciseRead(ExerciseCreate): id: uuid.UUID owner_user_id: uuid.UUID | None is_builtin: bool created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class WorkoutCreate(BaseModel): started_at: datetime | None = None notes: str | None = None class WorkoutUpdate(BaseModel): finished_at: datetime | None = None notes: str | None = None class WorkoutSetCreate(BaseModel): weight: float = 0 reps: int = 0 duration_seconds: int | None = None calories: float | None = None completed_at: datetime | None = None class WorkoutSetRead(WorkoutSetCreate): id: uuid.UUID workout_item_id: uuid.UUID set_index: int completed_at: datetime model_config = ConfigDict(from_attributes=True) class WorkoutItemCreate(BaseModel): exercise_id: uuid.UUID | None = None equipment_id: uuid.UUID | None = None order_index: int | None = None planned_working_weight: float | None = None @model_validator(mode="after") def exactly_one_entity(self) -> WorkoutItemCreate: if bool(self.exercise_id) == bool(self.equipment_id): raise ValueError("Provide exactly one of exercise_id or equipment_id") return self class WorkoutItemRead(WorkoutItemCreate): id: uuid.UUID workout_id: uuid.UUID order_index: int created_at: datetime sets: list[WorkoutSetRead] = [] model_config = ConfigDict(from_attributes=True) class WorkoutRead(BaseModel): id: uuid.UUID user_id: uuid.UUID started_at: datetime finished_at: datetime | None notes: str | None estimated_calories: float created_at: datetime updated_at: datetime items: list[WorkoutItemRead] = [] model_config = ConfigDict(from_attributes=True) class ProgressionPoint(BaseModel): date: str max_weight: float volume: float class ProgressionRead(BaseModel): last_weight: float | None max_weight: float | None previous_delta: float | None points: list[ProgressionPoint] class CaloriesRead(BaseModel): total_calories: float workouts: list[dict[str, str | float]]