Files
WerkoutAPI/workout/models.py
Trey t 1c61b80731 workout generator audit: rules engine, structure rules, split patterns, injury UX, metadata cleanup
- Add rules_engine.py with quantitative rules for all 8 workout types
- Add quality gate retry loop in generate_single_workout()
- Expand calibrate_structure_rules to all 120 combinations (8 types × 5 goals × 3 sections)
- Wire WeeklySplitPattern DB records into _pick_weekly_split()
- Enforce movement patterns from WorkoutStructureRule in exercise selection
- Add straight-set strength support (single main lift, 4-6 rounds)
- Add modality consistency check for duration-dominant workout types
- Add InjuryStep component to onboarding and preferences
- Add sibling exercise exclusion in regenerate and preview_day endpoints
- Display generator warnings on dashboard
- Expand fix_rep_durations, fix_exercise_flags, fix_movement_pattern_typo
- Add audit_exercise_data and check_rules_drift management commands
- Add Next.js frontend with dashboard, onboarding, preferences, history pages
- Add generator app with ML-powered workout generation pipeline
- 96 new tests across 7 test modules

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:07:40 -06:00

94 lines
3.3 KiB
Python

from django.db import models
from exercise.models import *
from registered_user.models import RegisteredUser
WORKOUT_LEVEL = (
(0, "na"),
(1, "easy"),
(2, "moderate"),
(3, "average"),
(4, "hard"),
(5, "death"),
)
# Create your models here.
class Workout(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=255)
description = models.CharField(null=True, blank=True, max_length=255)
registered_user = models.ForeignKey(
RegisteredUser,
on_delete=models.CASCADE
)
estimated_time = models.FloatField(max_length=255, blank=True, null=True)
def __str__(self):
return str(self.id) + ": " + self.name + " - " + (self.description or "") + " - by: " + str(self.registered_user.first_name) + " - on: " + str(self.created_at)
class WorkoutExercise(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
workout = models.ForeignKey(
Workout,
on_delete=models.CASCADE,
related_name='workout_exercise_workout'
)
exercise = models.ForeignKey(
Exercise,
on_delete=models.CASCADE,
related_name='workout_exercise_exercise'
)
weight = models.IntegerField(null=True, blank=True, max_length=4)
reps = models.IntegerField(null=True, blank=True, max_length=4)
duration = models.IntegerField(null=True, blank=True, max_length=4)
def __str__(self):
return self.workout.name + " : " + self.exercise.name
def duration_audio(self):
if self.duration is not None:
return str(settings.MEDIA_URL) + "quantities_audio/" + "for_"+str(self.duration)+"_seconds.m4a"
def weight_audio(self):
if self.weight is not None:
return str(settings.MEDIA_URL) + "quantities_audio/" + "for_"+str(self.weight)+"_pounds.m4a"
class CompletedWorkout(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
registered_user = models.ForeignKey(
RegisteredUser,
on_delete=models.CASCADE,
related_name='completed_workout_user'
)
workout = models.ForeignKey(
Workout,
on_delete=models.CASCADE,
related_name='completed_workout_workout'
)
difficulty = models.PositiveSmallIntegerField(
choices=WORKOUT_LEVEL
)
total_time = models.IntegerField(null=True, blank=True)
workout_start_time = models.DateTimeField(null=False, blank=False)
notes = models.TextField(null=True, blank=True)
health_kit_workout_uuid = models.CharField(max_length=1000, blank=True, null=True)
def __str__(self):
return self.registered_user.first_name + " : " + self.registered_user.last_name + " : " + self.workout.name + " : " + str(self.difficulty)
class PlannedWorkout(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
on_date = models.DateField(auto_now=False,null=False, blank=False)
workout = models.ForeignKey(
Workout,
on_delete=models.CASCADE,
related_name='planned_workout_workout'
)
registered_user = models.ForeignKey(
RegisteredUser,
on_delete=models.CASCADE,
related_name='planned_workout_registered_user'
)