from django.contrib.auth.models import User from django.test import TestCase from exercise.models import Exercise from generator.models import UserPreference from generator.services.exercise_selector import ExerciseSelector from registered_user.models import RegisteredUser class TestWarmupSelector(TestCase): def setUp(self): django_user = User.objects.create_user( username='warmup_selector_user', password='testpass123', ) registered_user = RegisteredUser.objects.create( user=django_user, first_name='Warmup', last_name='Tester', ) self.preference = UserPreference.objects.create( registered_user=registered_user, days_per_week=4, fitness_level=2, ) def test_warmup_excludes_working_set_movements(self): dynamic_1 = Exercise.objects.create( name='Dynamic Warmup A', movement_patterns='dynamic stretch, mobility - dynamic, activation, warm up', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=2, complexity_rating=2, difficulty_level='beginner', ) dynamic_2 = Exercise.objects.create( name='Dynamic Warmup B', movement_patterns='mobility - dynamic, cardio/locomotion, balance', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=3, complexity_rating=2, difficulty_level='beginner', ) weighted_press = Exercise.objects.create( name='Lying Dumbbell Tricep Extension', movement_patterns='upper push - horizontal, upper push, arms', is_duration=True, is_reps=False, is_weight=True, is_compound=False, exercise_tier='secondary', hr_elevation_rating=2, complexity_rating=2, difficulty_level='intermediate', ) duration_push = Exercise.objects.create( name='Floor Press Hold', movement_patterns='upper push - horizontal, upper push', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='secondary', hr_elevation_rating=2, complexity_rating=2, difficulty_level='intermediate', ) selector = ExerciseSelector(self.preference) selected = selector.select_warmup_exercises(target_muscles=[], count=4) selected_ids = {ex.pk for ex in selected} self.assertIn(dynamic_1.pk, selected_ids) self.assertIn(dynamic_2.pk, selected_ids) self.assertNotIn(weighted_press.pk, selected_ids) self.assertNotIn(duration_push.pk, selected_ids) def test_warmup_keeps_side_specific_variants_adjacent(self): left_variant_a = Exercise.objects.create( name='Side Lying T Stretch', side='left_arm', movement_patterns='dynamic stretch, mobility - dynamic, warm up', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=2, complexity_rating=1, difficulty_level='beginner', ) right_variant_a = Exercise.objects.create( name='Side Lying T Stretch', side='right_arm', movement_patterns='dynamic stretch, mobility - dynamic, warm up', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=2, complexity_rating=1, difficulty_level='beginner', ) left_variant_b = Exercise.objects.create( name='Quadruped Adductor Stretch with Thoracic Rotation', side='left_side', movement_patterns='dynamic stretch, mobility - dynamic, warm up', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=2, complexity_rating=1, difficulty_level='beginner', ) right_variant_b = Exercise.objects.create( name='Quadruped Adductor Stretch with Thoracic Rotation', side='right_side', movement_patterns='dynamic stretch, mobility - dynamic, warm up', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=2, complexity_rating=1, difficulty_level='beginner', ) selector = ExerciseSelector(self.preference) selected = selector.select_warmup_exercises(target_muscles=[], count=4) selected_ids = [ex.pk for ex in selected] self.assertEqual( set(selected_ids), {left_variant_a.pk, right_variant_a.pk, left_variant_b.pk, right_variant_b.pk}, ) side_pairs = {} for idx, ex in enumerate(selected): key = selector._strip_side_tokens(ex.name) side_pairs.setdefault(key, []).append(idx) self.assertEqual(len(side_pairs['side lying t stretch']), 2) self.assertEqual(len(side_pairs['quadruped adductor stretch with thoracic rotation']), 2) self.assertEqual( side_pairs['side lying t stretch'][1], side_pairs['side lying t stretch'][0] + 1, ) self.assertEqual( side_pairs['quadruped adductor stretch with thoracic rotation'][1], side_pairs['quadruped adductor stretch with thoracic rotation'][0] + 1, ) def test_cooldown_keeps_side_specific_variants_adjacent(self): left_variant_a = Exercise.objects.create( name="Matsyendra's Pose", side='left_side', movement_patterns='static stretch, cool down', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=1, complexity_rating=1, difficulty_level='beginner', ) right_variant_a = Exercise.objects.create( name="Matsyendra's Pose", side='right_side', movement_patterns='static stretch, cool down', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=1, complexity_rating=1, difficulty_level='beginner', ) left_variant_b = Exercise.objects.create( name='Miniband Reverse Clamshell', side='left_leg', movement_patterns='mobility - static, cooldown', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=1, complexity_rating=1, difficulty_level='beginner', ) right_variant_b = Exercise.objects.create( name='Miniband Reverse Clamshell', side='right_leg', movement_patterns='mobility - static, cooldown', is_duration=True, is_reps=False, is_weight=False, is_compound=False, exercise_tier='accessory', hr_elevation_rating=1, complexity_rating=1, difficulty_level='beginner', ) selector = ExerciseSelector(self.preference) selected = selector.select_cooldown_exercises(target_muscles=[], count=4) selected_ids = [ex.pk for ex in selected] self.assertEqual( set(selected_ids), {left_variant_a.pk, right_variant_a.pk, left_variant_b.pk, right_variant_b.pk}, ) side_pairs = {} for idx, ex in enumerate(selected): key = selector._strip_side_tokens(ex.name) side_pairs.setdefault(key, []).append(idx) self.assertEqual(len(side_pairs["matsyendra's pose"]), 2) self.assertEqual(len(side_pairs['miniband reverse clamshell']), 2) self.assertEqual( side_pairs["matsyendra's pose"][1], side_pairs["matsyendra's pose"][0] + 1, ) self.assertEqual( side_pairs['miniband reverse clamshell'][1], side_pairs['miniband reverse clamshell'][0] + 1, )